@import url("fonts.css");

/* ==========================================================================
   Tucker : design system
   Palette and type per the 2026 Tucker brand guideline (screen values settled
   2026-08-07). Navy #152A48 primary, gold #ECAC1E accent. ONE pair, everywhere.

   Gold is for rules, seams, bars and chip fills. Gold TEXT only ever sits on
   navy -- gold on white is 2.0:1 and fails contrast. (An earlier version of this
   note said "never gold fills", which the pressed filter chip below already
   contradicted; the real rule is the text rule.)

   Every other navy in this file is the SAME hue and saturation (H215 S55) at a
   different lightness. Do not paste in a navy or gold from anywhere else. Six
   older values are retired -- the two print-guideline values, the two softer
   "document" values, and the two Pantone conversions. They are listed by hex in
   the brand memo, deliberately NOT here: a find-and-replace sweep would rewrite
   the literals in this comment and leave it saying the opposite of what it means.

   The one sanctioned exception is #204A87 for very large navy fills. It is not
   used in this file.
   ========================================================================== */

:root {
  --navy:        #152A48;
  --gold:        #ECAC1E;
  --ink:         #333333;
  --muted:       #6E6E6E;
  --rule:        #E0E0E0;
  --panel:       #F2F2F2;
  --white:       #FFFFFF;

  --navy-scrim:  rgba(21, 42, 72, .62);
  --navy-soft:   rgba(21, 42, 72, .08);
  --navy-deep:   #0B1524;
  --navy-lift:   #1B365C;

  /* Deck ground: deep navy with an off-centre glow rather than a flat fill.
     Every stop is the brand navy's own hue AND saturation (H215 S55) at a
     different lightness. The earlier stops were H215 at S85-100, which is the
     retired royal blue -- correct token, wrong family underneath it. */
  --ground: radial-gradient(110% 80% at 76% 6%, #172E4E 0%, #102138 42%, #0A1321 100%);
  --ground-alt: radial-gradient(105% 80% at 16% 96%, #172E4E 0%, #102138 46%, #0A1321 100%);

  --font-display: 'Montserrat', 'Helvetica Neue', Arial, sans-serif;
  --font-body:    'Open Sans', Arial, sans-serif;

  /* Fluid type scale */
  --t-hero:   clamp(2.75rem, 1.6rem + 5.1vw, 6rem);
  --t-h1:     clamp(2.25rem, 1.5rem + 3.2vw, 4rem);
  --t-h2:     clamp(1.65rem, 1.25rem + 1.7vw, 2.5rem);
  --t-h3:     clamp(1.15rem, 1rem + .6vw, 1.4rem);
  --t-stat:   clamp(2.5rem, 1.6rem + 4vw, 4.75rem);
  --t-body:   clamp(1rem, .96rem + .18vw, 1.075rem);
  --t-lead:   clamp(1.1rem, 1rem + .5vw, 1.35rem);
  --t-label:  .72rem;

  --gutter:   clamp(1.25rem, .6rem + 3vw, 4.5rem);
  --measure:  68ch;
  --band:     clamp(4.5rem, 3rem + 7vw, 9rem);

  --shell:    1440px;
  --ease:     cubic-bezier(.22, .61, .36, 1);
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--navy);
  margin: 0;
  line-height: 1.16;
  letter-spacing: -.02em;
  text-wrap: balance;
}
/* brand.json: H1 = Montserrat Bold, H2 = Montserrat SemiBold. The variable font
   defaults to 700, so H2/H3 must set their weight explicitly. */
h1 { font-weight: 700; line-height: 1.06; }
h2, h3, h4 { font-weight: 600; }
h3, h4 { line-height: 1.25; }

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

::selection { background: var(--navy); color: var(--white); }

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--navy); color: var(--white);
  padding: .85rem 1.4rem; font-family: var(--font-display); font-weight: 600;
}
.skip:focus { left: 0; }
#main { scroll-margin-top: 5rem; }
#main:focus { outline: none; }

/* ---------- layout primitives ---------- */
.shell {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.band { padding-block: var(--band); }
.band--panel { background: var(--panel); }
.band--navy  {
  background: var(--ground);
  color: rgba(255,255,255,.82);
  position: relative;
  /* clip, not hidden. Both crop the gradient the same way, but `hidden` makes
     this element a scroll container, which silently kills position:sticky on
     anything inside it -- and the portfolio filter bar lives in here. */
  overflow: clip;
}
.band--navy--alt { background: var(--ground-alt); }
/* Hairline gold seam at the top of every dark chapter. */
.band--navy::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(236,172,30,.55) 22%, rgba(236,172,30,.55) 78%, transparent);
}
.band--navy h1, .band--navy h2, .band--navy h3 { color: var(--white); }

.measure { max-width: var(--measure); }

/* Editorial two-column: label rail + content */
.rail {
  display: grid;
  grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
  gap: clamp(1.5rem, .5rem + 3vw, 5rem);
  align-items: start;
}
@media (max-width: 860px) { .rail { grid-template-columns: 1fr; gap: 1.5rem; } }

/* A section heading sits directly above a hard photographic edge. That junction
   needs far more air than the gap between two cards, and it must not depend on
   an inline style in one template. */
.rail + .grid,
.rail + .stats,
.rail + .divisions,
.rail + .people,
.rail + .news,
.rail + .gallery { margin-top: clamp(3.5rem, 2rem + 5vw, 6rem); }

/* ---------- section label: small caps + gold rule ---------- */
.label {
  font-family: var(--font-display);
  font-size: var(--t-label);
  font-weight: 700;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--navy);
  margin: 0 0 1rem;
  display: block;
}
.label::before {
  content: "";
  display: block;
  width: 2.5rem;
  height: 2px;
  background: var(--gold);
  margin-bottom: .85rem;
}
.band--navy .label { color: var(--gold); }
.band--navy .label::before { background: var(--gold); }
.label--plain::before { display: none; }

/* gold rule used as a standalone divider */
.rule-gold { height: 2px; width: 3.5rem; background: var(--gold); border: 0; margin: 0 0 1.75rem; }

/* ---------- chevron mark motif (from the Tucker logo) ---------- */
.chev {
  display: inline-block;
  width: .62em; height: .62em;
  border-top: 2px solid var(--gold);
  border-right: 2px solid var(--gold);
  transform: rotate(45deg);
  transition: transform .35s var(--ease);
  flex: none;
}

/* ---------- header ---------- */
.hdr {
  position: fixed; inset: 0 0 auto 0; z-index: 100;
  transition: background .4s var(--ease), box-shadow .4s var(--ease);
}
.hdr__in {
  max-width: var(--shell); margin-inline: auto;
  padding: 1.1rem var(--gutter);
  display: flex; align-items: center; justify-content: space-between;
  gap: 2rem;
}
.hdr__logo img { height: 30px; width: auto; transition: opacity .3s var(--ease); }
.hdr__logo .lg-white { display: block; }
.hdr__logo .lg-navy  { display: none; }

/* Floating dark bar rather than a white slab, so it reads against both grounds. */
.hdr.is-solid {
  background: rgba(11, 21, 36, .97);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  backdrop-filter: saturate(160%) blur(14px);
  box-shadow: 0 1px 0 rgba(236,172,30,.28), 0 10px 30px -18px rgba(0,0,0,.6);
}
.hdr.is-solid .lg-white { display: block; }
.hdr.is-solid .lg-navy  { display: none; }
@supports not (backdrop-filter: blur(1px)) {
  .hdr.is-solid { background: rgba(11, 21, 36, 1); }
}

.nav { display: flex; align-items: center; gap: clamp(1rem, .2rem + 1.5vw, 2.15rem); }
.nav a {
  font-family: var(--font-display);
  font-size: .82rem; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; text-decoration: none;
  color: var(--white); padding: .3rem 0;
  position: relative; white-space: nowrap;
}
.hdr.is-solid .nav a { color: var(--white); }
.nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px;
  height: 2px; background: var(--gold);
  transform: scaleX(0); transform-origin: left;
  transition: transform .32s var(--ease);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }

.nav__cta {
  border: 1px solid rgba(255,255,255,.45);
  padding: .55rem 1.1rem !important;
}
.hdr.is-solid .nav__cta { border-color: rgba(255,255,255,.45); }
.nav__cta::after { display: none; }
.nav__cta:hover { background: var(--gold); border-color: var(--gold); color: var(--navy) !important; }

.burger {
  display: none; background: none; border: 0; cursor: pointer;
  padding: .5rem; width: 44px; height: 44px;
}
.burger span {
  display: block; height: 2px; width: 24px; background: var(--white);
  margin: 5px 0; transition: transform .3s var(--ease), opacity .2s;
}
.hdr.is-solid .burger span { background: var(--white); }
.hdr.is-open .burger span { background: var(--white); }
.hdr.is-open .burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hdr.is-open .burger span:nth-child(2) { opacity: 0; }
.hdr.is-open .burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 1080px) {
  .burger { display: block; }
  .nav {
    position: fixed; inset: 0; background: var(--navy);
    flex-direction: column; justify-content: center; align-items: flex-start;
    gap: .35rem; padding: 5rem var(--gutter) 3rem;
    transform: translateY(-100%); transition: transform .5s var(--ease);
    overflow-y: auto;
  }
  .hdr.is-open .nav { transform: translateY(0); }
  .nav a, .hdr.is-solid .nav a { color: var(--white); font-size: 1.5rem; padding: .5rem 0; letter-spacing: .03em; }
  .nav__cta, .hdr.is-solid .nav__cta { border: 0; padding: .5rem 0 !important; color: var(--gold) !important; }
  .hdr.is-open { background: transparent; backdrop-filter: none; box-shadow: none; }

  /* The nav overlay is fixed and full-bleed, so the close control and the logo
     have to sit above it or the menu cannot be dismissed by tapping. */
  .hdr.is-open .burger,
  .hdr.is-open .hdr__logo { position: relative; z-index: 2; }
  .hdr.is-open .hdr__logo .lg-white,
  .hdr.is-solid.is-open .hdr__logo .lg-white { display: block; }
  .hdr.is-open .hdr__logo .lg-navy,
  .hdr.is-solid.is-open .hdr__logo .lg-navy { display: none; }
}

/* Touch targets: chips and controls need a 44px hit area on touch devices. */
@media (pointer: coarse) {
  .filter { min-height: 44px; padding-block: .8rem; }
  .btn { min-height: 46px; }
  .nav a { min-height: 44px; display: flex; align-items: center; }
  .lb__btn { width: 56px; height: 56px; }
}

/* Reading progress, mirroring the deck's footer bar */
.progress {
  position: fixed; top: 0; left: 0; z-index: 120;
  height: 2px; width: 100%; transform-origin: 0 50%; transform: scaleX(0);
  background: linear-gradient(90deg, var(--gold), #F1C45F);
  pointer-events: none;
}

/* Pages with no hero open on white, so the white lockup and white nav would
   disappear. These pages get the navy treatment from the first paint. */
.no-hero .hdr,
.no-hero .hdr.is-solid {
  background: var(--white);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: 0 1px 0 var(--rule);
}
.no-hero .hdr .lg-white,
.no-hero .hdr.is-solid .lg-white { display: none; }
.no-hero .hdr .lg-navy,
.no-hero .hdr.is-solid .lg-navy { display: block; }
.no-hero .nav a,
.no-hero .hdr.is-solid .nav a { color: var(--navy); }
.no-hero .nav__cta,
.no-hero .hdr.is-solid .nav__cta { border-color: var(--navy); }
.no-hero .nav__cta:hover,
.no-hero .hdr.is-solid .nav__cta:hover { border-color: var(--gold); color: var(--navy) !important; }
.no-hero .burger span,
.no-hero .hdr.is-solid .burger span { background: var(--navy); }

@media (max-width: 1080px) {
  /* the open mobile panel is navy, so its contents flip back to white */
  .no-hero .hdr.is-open,
  .no-hero .hdr.is-solid.is-open { background: transparent; box-shadow: none; }
  .no-hero .hdr.is-open .nav a,
  .no-hero .hdr.is-solid.is-open .nav a { color: var(--white); }
  .no-hero .hdr.is-open .burger span,
  .no-hero .hdr.is-solid.is-open .burger span { background: var(--white); }
  .no-hero .hdr.is-open .nav__cta,
  .no-hero .hdr.is-solid.is-open .nav__cta { color: var(--gold) !important; }
}

/* ---------- hero ---------- */
.hero {
  position: relative;
  min-height: min(92vh, 900px);
  display: flex; align-items: flex-end;
  color: var(--white);
  overflow: hidden;
}
.hero--short { min-height: min(64vh, 620px); }
/* Short heroes carry only an eyebrow, a headline and one line of sub, so the
   bottom-aligned block ended up glued to the bottom edge of the photograph on
   Contact and Media. */
.hero--short .hero__in { padding-bottom: clamp(4rem, 2.5rem + 4vw, 6rem); }
.hero { background: var(--ground); }
.hero__bg { position: absolute; inset: 0; }

/* Rotating hero: frames stack and cross-fade, each holding a slow push.

   The push used to jolt. Two reasons, both fixed here:

   1. `.hero__bg--rotate img { animation: none }` sat ABOVE `.hero__bg img
      { animation: heroPush 18s }` at equal specificity, so source order handed
      the 18s push to every frame including the ones waiting their turn. The
      static-hero rule is now scoped with :not(), so it cannot reach the frames.
   2. The frames rested at scale(1.06) and the keyframe drove them to 1. When a
      frame lost .is-on its animation vanished and it SNAPPED back to 1.06 --
      roughly a hundred pixels on a large screen -- while still fading out.
      The rest state is now scale(1), the end of the travel, so losing .is-on
      leaves the frame exactly where the animation had already carried it.

   The duration deliberately equals the 6500ms rotation interval in site.js, so
   a frame finishes its travel at the very moment it hands over and there is
   nothing left to snap. Change one and change the other.

   linear, not ease-out: ease-out spent most of its movement in the first three
   seconds and then sat still, which read as a quick zoom. A constant drift
   reads as film. */
.hero__bg--rotate img {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.6s var(--ease);
}
.hero__bg--rotate img.is-on {
  opacity: 1;
  animation: heroPush 6.5s linear forwards;
}
@media (prefers-reduced-motion: reduce) {
  .hero__bg--rotate img { transition: none; animation: none; transform: none; }
  .hero__bg--rotate img.is-on { opacity: 1; }
}
.hero__bg img {
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(1);
}
/* Single-frame heroes have nothing to hand over to, so they keep the long push. */
.hero__bg:not(.hero__bg--rotate) img {
  transform: scale(1.06);
  animation: heroPush 18s linear forwards;
}
@keyframes heroPush { from { transform: scale(1.06); } to { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
  .hero__bg img,
  .hero__bg:not(.hero__bg--rotate) img { animation: none; transform: none; }
}
.hero__bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(90% 70% at 75% 12%, rgba(31,61,104,.30) 0%, transparent 60%),
    linear-gradient(180deg, rgba(11,21,36,.78) 0%, rgba(21,42,72,.30) 45%, rgba(11,21,36,.92) 100%);
}
.hero__in {
  position: relative; z-index: 2;
  text-shadow: 0 1px 18px rgba(11, 22, 37, .45);
  max-width: var(--shell); margin-inline: auto; width: 100%;
  padding: clamp(6rem, 4rem + 4vw, 8rem) var(--gutter) clamp(3rem, 1.5rem + 5vw, 6.5rem);
}
.hero__eyebrow {
  font-family: var(--font-display); font-size: var(--t-label); font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase; color: var(--gold);
  margin: 0 0 1.1rem;
}
.hero h1 {
  color: var(--white);
  font-size: var(--t-hero);
  font-weight: 700;
  letter-spacing: -.03em;
  max-width: 18ch;
}
.hero--short h1 { font-size: var(--t-h1); }
.hero__sub {
  margin-top: 1.5rem; max-width: 56ch;
  font-size: var(--t-lead); line-height: 1.6;
  color: rgba(255,255,255,.9);
}
.hero__rule { width: 4.5rem; height: 3px; background: var(--gold); margin-top: 2rem; }

/* No photography yet: fall back to the navy brand ground. */
.hero--plain { background: var(--navy); min-height: min(48vh, 460px); }

/* Headline reveals line by line rather than as one block. */
.hero h1 .ln {
  display: block; overflow: hidden;
  padding-bottom: .16em; margin-bottom: -.16em;
}
.hero h1 .ln > span {
  display: block;
  transform: translateY(105%);
  animation: lineUp .95s cubic-bezier(.16,.84,.34,1) forwards;
}
.hero h1 .ln:nth-child(2) > span { animation-delay: .12s; }
.hero h1 .ln:nth-child(3) > span { animation-delay: .24s; }
@keyframes lineUp { to { transform: translateY(0); } }

.hero__eyebrow, .hero__sub, .hero__rule {
  opacity: 0; animation: fadeUp .9s cubic-bezier(.16,.84,.34,1) forwards;
}
.hero__eyebrow { animation-delay: .05s; }
.hero__sub { animation-delay: .42s; }
.hero__rule { animation-delay: .55s; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .hero h1 .ln > span, .hero__eyebrow, .hero__sub, .hero__rule {
    animation: none; opacity: 1; transform: none;
  }
}

/* scroll hint */
.hero__scroll {
  position: absolute; z-index: 2; bottom: 1.5rem; right: var(--gutter);
  writing-mode: vertical-rl;
  font-family: var(--font-display); font-size: .68rem; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: rgba(255,255,255,.7);
  display: flex; align-items: center; gap: .8rem;
}
.hero__scroll::after {
  content: ""; width: 1px; height: 3rem; background: rgba(255,255,255,.45);
}
@media (max-width: 860px) { .hero__scroll { display: none; } }

@media (max-width: 520px) {
  :root { --t-hero: 2.15rem; --t-h1: 1.95rem; }
  .hero h1 { max-width: none; }
}

/* ---------- stats: typographic, not boxed ---------- */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0;
  border-top: 1px solid rgba(255,255,255,.16);
  border-bottom: 1px solid rgba(255,255,255,.16);
}
.stat {
  padding: clamp(1.5rem, 1rem + 1.5vw, 2.5rem) clamp(1rem, .5rem + 1.5vw, 2rem);
  border-left: 1px solid rgba(255,255,255,.16);
}
.stat:first-child { border-left: 0; padding-left: 0; }
@media (max-width: 720px) {
  .stat { border-left: 0; border-top: 1px solid rgba(255,255,255,.16); padding-left: 0; }
  .stat:first-child { border-top: 0; }
}
/* Laptop and iPad widths. auto-fit was still fitting four columns here, which
   gives each figure about 180px. "1996" is wider than that at --t-stat, so it
   sat hard against the divider and at some widths crossed it. Two columns. */
@media (min-width: 721px) and (max-width: 1080px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat { border-left: 1px solid rgba(255,255,255,.16); border-top: 0; }
  .stat:nth-child(odd) { border-left: 0; padding-left: 0; }
  .stat:nth-child(n + 3) { border-top: 1px solid rgba(255,255,255,.16); }
}
/* Numerals set light against the display weight, gold on the units only. */
.stat__v {
  font-family: var(--font-display); font-weight: 400;
  font-size: var(--t-stat); line-height: .95; letter-spacing: -.045em;
  color: var(--white);
  font-variant-numeric: tabular-nums;
}
.stat__v .g { color: var(--gold); }

.stat__l {
  font-family: var(--font-display); font-size: .72rem; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  margin-top: 1rem; color: rgba(255,255,255,.9);
}
.stat__n { font-size: .84rem; color: rgba(255,255,255,.52); margin-top: .35rem; line-height: 1.5; }

/* ---------- lead / prose ---------- */
.lead { font-size: var(--t-lead); line-height: 1.62; color: var(--ink); max-width: 52ch; }
.band--navy .lead { color: rgba(255,255,255,.88); }

.prose { max-width: var(--measure); }
.prose h2 { font-size: var(--t-h2); margin-bottom: 1rem; }
.prose h3 { font-size: var(--t-h3); font-weight: 600; margin: 2.5rem 0 .75rem; }
.prose ul { margin: 0 0 1.15em; padding-left: 0; list-style: none; }
.prose li {
  position: relative; padding-left: 1.65rem; margin-bottom: .7rem;
}
.prose li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: .5rem; height: .5rem;
  border-top: 2px solid var(--gold); border-right: 2px solid var(--gold);
  transform: rotate(45deg);
}

.pullquote {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(1.4rem, 1rem + 1.7vw, 2.35rem);
  line-height: 1.24; letter-spacing: -.02em; color: var(--navy);
  border-left: 3px solid var(--gold);
  padding-left: clamp(1.25rem, .5rem + 2vw, 2.5rem);
  max-width: 24ch;
}
.band--navy .pullquote { color: var(--white); }

/* ---------- division cards ---------- */
.divisions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--rule); }
@media (max-width: 900px) { .divisions { grid-template-columns: 1fr; } }
.division {
  background: var(--white);
  padding: clamp(1.75rem, 1rem + 2vw, 3rem);
  display: flex; flex-direction: column;
  text-decoration: none;
  transition: background .35s var(--ease);
  min-height: 100%;
}
.division:hover { background: var(--panel); }
.division:hover .chev { transform: rotate(45deg) translate(3px, -3px); }
.division__n {
  font-family: var(--font-display); font-size: .72rem; font-weight: 700;
  /* was .45, which made 01 / 02 / 03 too faint to actually read */
  letter-spacing: .19em; color: var(--navy); opacity: .8; margin-bottom: 1.75rem;
}
.division h3 { font-size: var(--t-h3); font-weight: 700; margin-bottom: .5rem; }

/* Business-line lockups replace the typeset name. All three are normalised to
   the same box, so fixing the width keeps the TUCKER wordmark aligned across
   the row regardless of descender length. */
.division__logo {
  margin: 0 0 1.25rem;
  line-height: 0;
}
.division__logo img {
  width: clamp(150px, 52%, 205px);
  height: auto;
  transition: transform .45s var(--ease);
}
.division:hover .division__logo img { transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) {
  .division:hover .division__logo img { transform: none; }
}
.division__t { font-family: var(--font-display); font-size: .95rem; font-weight: 500; color: var(--navy); opacity: .75; margin-bottom: 1rem; }
.division p { font-size: .96rem; color: var(--ink); flex: 1; }
.division__go {
  margin-top: 1.75rem; display: flex; align-items: center; gap: .6rem;
  font-family: var(--font-display); font-size: .76rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--navy);
}

/* ---------- project grid ---------- */
.filters {
  display: flex; flex-wrap: wrap; gap: .5rem;
  border-bottom: 1px solid var(--rule); padding-bottom: 1.5rem; margin-bottom: 3.5rem;
}

/* The portfolio filter sticks while you scroll. 39 tiles is three screens, and
   today changing filter means scrolling all the way back up.

   top clears the fixed header (1.1rem padding either side of a 30px logo). The
   negative inline margin lets the bar's own background reach the edge of the
   shell so tiles do not show through beside it; the shell is also what bounds
   the tiles, so nothing can pass outside it. */
.band--navy .filters {
  position: sticky;
  top: 4rem;
  z-index: 60;
  background: rgba(11, 21, 36, .96);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  backdrop-filter: saturate(160%) blur(12px);
  margin-inline: calc(var(--gutter) * -1);
  padding: 1.1rem var(--gutter);
  border-bottom: 1px solid rgba(236, 172, 30, .3);
}
@supports not (backdrop-filter: blur(1px)) {
  .band--navy .filters { background: rgb(11, 21, 36); }
}
.filter {
  font-family: var(--font-display); font-size: .74rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  background: none; border: 1px solid var(--rule); color: var(--navy);
  padding: .6rem 1.1rem; cursor: pointer;
  transition: all .28s var(--ease);
}
.filter:hover { border-color: var(--navy); }
.filter[aria-pressed="true"] { background: var(--navy); border-color: var(--navy); color: var(--white); }

/* Row gap is deliberately much larger than the gap from a photo down to its own
   caption. They used to be nearly equal, so a caption floated midway between two
   pictures and the eye could not tell which one it belonged to -- the whole grid
   read as one undifferentiated field rather than as discrete projects. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: clamp(3.5rem, 2rem + 4.5vw, 5.5rem) clamp(1.25rem, .5rem + 2vw, 2.25rem);
}
.card { display: flex; flex-direction: column; height: 100%; text-decoration: none; }
.card__body { display: flex; flex-direction: column; flex: 1 1 auto; }
.card__fig {
  position: relative; overflow: hidden; background: var(--panel);
  aspect-ratio: 3 / 2;
}
.card__fig img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .8s var(--ease);
}
.card:hover .card__fig img { transform: scale(1.045); }
.card__fig::after {
  content: ""; position: absolute; inset: 0;
  background: var(--navy); opacity: 0;
  transition: opacity .4s var(--ease);
}
.card:hover .card__fig::after { opacity: .12; }
.card__tag {
  position: absolute; z-index: 2; left: 0; top: 0;
  background: var(--navy); color: var(--white);
  font-family: var(--font-display); font-size: .64rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  line-height: 1; padding: .55rem .85rem;
}
/* tightened from 1.25rem: the caption belongs to the photo above it */
.card__body { padding-top: 1.15rem; border-top: 2px solid var(--gold); margin-top: .85rem; }
.card h3 { font-size: 1.12rem; font-weight: 700; line-height: 1.28; }
.card__meta {
  font-size: .86rem; color: var(--muted); margin-top: .6rem; line-height: 1.5;
}
.card__status {
  font-family: var(--font-display); font-size: .72rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--navy);
  margin-top: auto; padding-top: .85rem; opacity: .75;
}
/* The role line is a second half of the status, not a separate grey note.
   Same treatment as .card__status so the two read as one statement. */
.card__role {
  font-family: var(--font-display); font-size: .72rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--navy);
  margin-top: .35rem; opacity: .75;
}
/* .card.is-hidden lives with the filter rules further down; it was declared
   twice, identically, in two different sections. */

/* Cards sitting on the dark ground */
.band--navy .card__body { border-top-color: rgba(236,172,30,.85); }
.band--navy .card h3 { color: var(--white); }
.band--navy .card__meta { color: rgba(255,255,255,.55); }
.band--navy .card__status { color: rgba(236,172,30,.9); opacity: 1; }
.band--navy .card__role { color: rgba(236,172,30,.9); opacity: 1; }
.band--navy .card__fig { background: rgba(255,255,255,.05); }
.band--navy .card__ph { box-shadow: inset 0 0 0 1px rgba(236,172,30,.45); }
.band--navy .card { transition: transform .5s var(--ease); }
.band--navy .card:hover { transform: translateY(-6px); }
.band--navy .card:hover .card__fig::after { opacity: 0; }
.band--navy .card__fig { box-shadow: 0 0 0 0 rgba(236,172,30,0); transition: box-shadow .45s var(--ease); }
.band--navy .card:hover .card__fig { box-shadow: 0 18px 50px -18px rgba(0,0,0,.7), 0 0 0 1px rgba(236,172,30,.5); }

/* Cards without a detail page are not links, so they must not behave like one. */
.card:not(a) { cursor: default; }
.card:not(a):hover .card__fig img { transform: none; }
.card:not(a):hover .card__fig::after { opacity: 0; }
.band--navy .card:not(a):hover { transform: none; }
.band--navy .card:not(a):hover .card__fig { box-shadow: 0 0 0 0 rgba(236,172,30,0); }

/* the sticky bar above sets its own gold hairline; this rule used to reset it
   to white and, sitting later in the file, silently won */
.band--navy .filter { border-color: rgba(255,255,255,.38); color: rgba(255,255,255,.85); }
.band--navy .filter:hover { border-color: var(--gold); color: var(--white); }
.band--navy .filter[aria-pressed="true"] { background: var(--gold); border-color: var(--gold); color: var(--navy); }

/* Cards animate in on a stagger, and out/in when filtered */
.grid .card { transition: opacity .45s var(--ease), transform .45s var(--ease); }
.filters__count {
  font-family: var(--font-display); font-size: .72rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase;
}

/* The filter fade-out.

   `.card.is-out` is two classes. The reveal rules that set opacity:1 on a
   revealed tile are three (`.js .rv-items > *.in`), so the plain .is-out rule
   was simply outranked and the instruction to fade was written but never obeyed:
   tiles vanished the instant JS added .is-hidden and the survivors snapped back
   at full strength. These selectors are deliberately heavier than the reveal
   rules so the fade wins.

   The duration is restated here because the reveal transition is .6s, and the
   is-hidden timeout in site.js is 460ms -- without this the card would be
   display:none'd a third of the way through its own fade. Keep .45s here and
   460ms there in step. Delay is zeroed so a filtered-out row leaves together
   rather than inheriting its arrival stagger. */
.js .grid.rv-items > .card.is-out,
.js .rv-stagger.in > .card.is-out,
.card.is-out {
  opacity: 0;
  transform: scale(.97);
  transition: opacity .45s var(--ease), transform .45s var(--ease);
  transition-delay: 0s;
}
.card.is-hidden { display: none; }

/* ---------- project detail ---------- */
.pstats {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
  gap: clamp(1.25rem, .5rem + 2vw, 2.5rem);
}
.pstat { border-top: 1px solid var(--rule); padding-top: 1.05rem; }
.pstat__v {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.35rem, 1rem + 1.1vw, 1.9rem);
  color: var(--navy); line-height: 1.1; letter-spacing: -.02em;
}
.pstat__l {
  font-size: .78rem; color: var(--muted); margin-top: .55rem; line-height: 1.35;
  letter-spacing: .06em; text-transform: uppercase;
}

.meta-list { border-top: 2px solid var(--gold); padding-top: 1.25rem; }
.meta-list dt {
  font-family: var(--font-display); font-size: .7rem; font-weight: 700;
  letter-spacing: .17em; text-transform: uppercase; color: var(--muted);
  margin-top: 1.25rem;
}
.meta-list dt:first-child { margin-top: 0; }
.meta-list dd { margin: .3rem 0 0; font-size: .95rem; color: var(--navy); font-weight: 600; }

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 380px), 1fr)); gap: clamp(1rem, .5rem + 1.1vw, 1.75rem); }
.gallery figure { margin: 0; background: var(--panel); }
.gallery img { width: 100%; aspect-ratio: 3/2; object-fit: cover; }
.gallery--wide > *:first-child { grid-column: 1 / -1; }
.gallery--wide > *:first-child img { aspect-ratio: 16/7; }

.contacts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: 1.75rem; }
.contact-card { border-top: 2px solid var(--gold); padding-top: 1.1rem; }
.contact-card__r {
  font-family: var(--font-display); font-size: .7rem; font-weight: 700;
  letter-spacing: .17em; text-transform: uppercase; color: var(--muted);
}
.contact-card__c { font-family: var(--font-display); font-weight: 700; color: var(--navy); margin-top: .55rem; font-size: 1.02rem; }
.contact-card__o { font-size: .9rem; color: var(--ink); margin-top: .15rem; }
.contact-card a { color: var(--navy); text-decoration: none; border-bottom: 1px solid var(--rule); }
.contact-card a:hover { border-color: var(--gold); }

/* ---------- managed property list ---------- */
.managed { margin-top: clamp(2rem, 1rem + 2vw, 3rem); }
.managed__hd {
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem;
  align-items: baseline; justify-content: space-between;
  border-top: 2px solid var(--gold); padding-top: 1rem;
}
.managed__hd h3 { font-size: 1.1rem; font-weight: 700; }
.managed__hd span {
  font-family: var(--font-display); font-size: .74rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.managed__list {
  list-style: none; margin: 1.25rem 0 0; padding: 0;
  columns: 2; column-gap: clamp(1.5rem, .5rem + 2vw, 3rem);
}
@media (max-width: 640px) { .managed__list { columns: 1; } }
.managed__list li {
  break-inside: avoid;
  padding: .55rem 0 .55rem 1.5rem; position: relative;
  border-bottom: 1px solid var(--rule); font-size: .95rem;
}
.managed__list li::before {
  content: ""; position: absolute; left: 0; top: 1.05em;
  width: .42rem; height: .42rem;
  border-top: 2px solid var(--gold); border-right: 2px solid var(--gold);
  transform: rotate(45deg);
}

/* ---------- card placeholder (project awaiting photography) ---------- */
.card__ph {
  position: absolute; inset: 0;
  background: linear-gradient(150deg, #1F3D68 0%, #132743 55%, #0B1524 100%);
  box-shadow: inset 0 0 0 1px rgba(236,172,30,.28);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1rem; padding: 1.5rem; text-align: center;
}
.card__ph span {
  font-family: var(--font-display); font-size: .82rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: rgba(255,255,255,.75);
}
/* The actual Tucker mark: gold chevron with the white diamond, per the
   dark-background variant in the 2026 guideline. Never redrawn in CSS. */
.card__ph .mark {
  width: 44px; height: 44px; flex: none;
  opacity: .95;
}

/* ---------- team ---------- */
.people { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: clamp(2.5rem, 1.5rem + 3vw, 4rem) clamp(1.5rem, .5rem + 2vw, 2.5rem); }
.person { text-decoration: none; display: block; }
.person__fig { aspect-ratio: 1; overflow: hidden; background: var(--panel); position: relative; }
/* transform-origin matters here. The photos are square in a square frame, so
   nothing is cropped at rest -- but the hover zoom grows the image inside a
   clipped box, and from the default centre origin that takes ~2% off EVERY
   edge, about 18px off the top of a 900px headshot. Teresa's portrait is framed
   far tighter than the others (her hair almost touches the top of the file), so
   hovering her tile clipped the top of her head.

   Anchoring to the top means the zoom pushes downward into the jacket, which is
   where there is room to lose. Protects every headshot, not just this one. */
.person__fig img {
  width: 100%; height: 100%; object-fit: cover;
  transform-origin: top center;
  transition: transform .7s var(--ease);
}
.person:hover .person__fig img { transform: scale(1.04); }
.person__ph {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: linear-gradient(150deg, #1F3D68 0%, #132743 55%, #0B1524 100%);
  box-shadow: inset 0 0 0 1px rgba(236,172,30,.28);
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.5rem, 1rem + 4vw, 3.75rem);
  color: var(--gold); letter-spacing: .05em;
}
.person__n { font-family: var(--font-display); font-weight: 700; color: var(--navy); font-size: 1.08rem; line-height: 1.25; margin-top: 1.1rem; padding-top: 1.1rem; border-top: 2px solid var(--gold); }
.person__t { font-size: .88rem; color: var(--muted); margin-top: .4rem; line-height: 1.5; }

.bio-hd { display: grid; grid-template-columns: minmax(0, 18rem) minmax(0, 1fr); gap: clamp(1.5rem, .5rem + 3vw, 4rem); align-items: start; }
@media (max-width: 760px) { .bio-hd { grid-template-columns: 1fr; } }

/* ---------- news ---------- */
.news { border-top: 1px solid var(--rule); }
.news__item {
  display: grid; grid-template-columns: minmax(0, 11rem) minmax(0, 1fr);
  gap: clamp(1rem, .3rem + 2vw, 3rem);
  padding: clamp(1.5rem, .8rem + 1.5vw, 2.25rem) 0;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  transition: background .3s var(--ease);
}
a.news__item:hover { background: var(--panel); }
@media (max-width: 700px) { .news__item { grid-template-columns: 1fr; gap: .5rem; } }
.news__meta {
  font-family: var(--font-display); font-size: .72rem; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase; color: var(--navy);
}
.news__date { color: var(--muted); font-weight: 600; letter-spacing: .1em; display: block; margin-top: .35rem; }
.news__t { font-family: var(--font-display); font-weight: 600; font-size: clamp(1.05rem, .95rem + .5vw, 1.35rem); color: var(--navy); line-height: 1.3; }

/* ---------- contact ---------- */
.contact-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: clamp(2rem, 1rem + 3vw, 4rem); }
.contact-block a { color: var(--navy); text-decoration: none; border-bottom: 1px solid var(--gold); }
.contact-block a:hover { background: var(--panel); }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: .7rem;
  font-family: var(--font-display); font-size: .78rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; text-decoration: none;
  padding: .95rem 1.75rem;
  border: 1px solid var(--navy); color: var(--navy); background: none;
  transition: all .32s var(--ease); cursor: pointer;
}
.btn:hover { background: var(--navy); color: var(--white); }
.btn:hover .chev { transform: rotate(45deg) translate(3px, -3px); }
.btn--solid { background: var(--navy); color: var(--white); }
.btn--solid:hover { background: var(--gold); border-color: var(--gold); color: var(--navy); }
.btn--light { border-color: rgba(255,255,255,.5); color: var(--white); }

/* Long email addresses in buttons overflow narrow viewports. */
@media (max-width: 520px) {
  .btn {
    max-width: 100%;
    letter-spacing: .1em;
    padding: .9rem 1.15rem;
    word-break: break-word;
  }
}
.btn--light:hover { background: var(--gold); border-color: var(--gold); color: var(--navy); }

.backlink {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--font-display); font-size: .74rem; font-weight: 700;
  letter-spacing: .15em; text-transform: uppercase; text-decoration: none;
  color: var(--muted); margin-bottom: 2rem;
}
.backlink:hover { color: var(--navy); }
.backlink .chev { transform: rotate(-135deg); border-color: currentColor; }
.backlink:hover .chev { border-color: var(--gold); transform: rotate(-135deg) translate(3px, -3px); }

/* ---------- footer ---------- */
/* --navy-deep, not --navy. Every dark band bottoms out at #0A1321, so a #152A48
   footer directly beneath one was visibly LIGHTER than the section above it and
   left a hard seam across the foot of every project page. */
.ftr { background: var(--navy-deep); color: rgba(255,255,255,.72); padding-block: clamp(3rem, 2rem + 4vw, 5.5rem) 2rem; }
.ftr__top { display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)); gap: clamp(1.75rem, .5rem + 3vw, 3.5rem); }
@media (max-width: 900px) { .ftr__top { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .ftr__top { grid-template-columns: 1fr; } }
.ftr__logo img { height: 30px; margin-bottom: 1.5rem; }
.ftr h4 {
  font-size: .72rem; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gold); margin-bottom: 1.1rem;
}
.ftr ul { list-style: none; margin: 0; padding: 0; }
.ftr li { margin-bottom: .6rem; }
.ftr a { color: rgba(255,255,255,.72); text-decoration: none; font-size: .92rem; transition: color .25s; }
.ftr a:hover { color: var(--gold); }
.ftr address { font-style: normal; font-size: .92rem; line-height: 1.75; }
.ftr__bar {
  margin-top: clamp(2.5rem, 1.5rem + 3vw, 4rem);
  padding-top: 1.6rem; border-top: 1px solid rgba(236,172,30,.32);
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-size: .8rem; color: rgba(255,255,255,.6);
}
.ftr__social { display: flex; gap: 1.5rem; }
.ftr__social a { font-family: var(--font-display); font-size: .74rem; font-weight: 600; letter-spacing: .13em; text-transform: uppercase; }
.ftr__disc { max-width: 62ch; font-size: .78rem; line-height: 1.65; color: rgba(255,255,255,.55); margin-top: 1.25rem; }

/* ---------- lightbox ---------- */
.lb {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(8,16,28,.985);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  display: none; align-items: center; justify-content: center;
  padding: clamp(1rem, .5rem + 3vw, 4rem);
}
.lb[open], .lb.is-open { display: flex; }
.lb__img {
  max-width: min(1400px, 100%); max-height: 100%;
  object-fit: contain;
  opacity: 0; transform: scale(.985);
  transition: opacity .35s var(--ease), transform .45s var(--ease);
}
.lb.is-ready .lb__img { opacity: 1; transform: none; }
.lb__bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1.25rem clamp(1rem, .5rem + 3vw, 4rem);
  font-family: var(--font-display); font-size: .74rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: rgba(255,255,255,.65);
}
.lb__btn {
  position: absolute; top: 50%; transform: translateY(-50%);
  background: none; border: 1px solid rgba(255,255,255,.28); color: #fff;
  width: 52px; height: 52px; cursor: pointer;
  display: grid; place-items: center;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.lb__btn:hover { border-color: var(--gold); background: rgba(236,172,30,.14); }
.lb__prev { left: clamp(.5rem, .2rem + 1.5vw, 2rem); }
.lb__next { right: clamp(.5rem, .2rem + 1.5vw, 2rem); }
.lb__close { top: clamp(1rem, .5rem + 2vw, 2.5rem); right: clamp(1rem, .5rem + 2vw, 2.5rem); transform: none; }
.lb__btn i { width: .62em; height: .62em; border-top: 2px solid currentColor; border-right: 2px solid currentColor; font-size: 1.5rem; display: block; }
.lb__prev i { transform: rotate(-135deg) translate(-2px,-2px); }
.lb__next i { transform: rotate(45deg) translate(-2px,-2px); }
.lb__close i { transform: rotate(45deg); border: 0; position: relative; }
.lb__close i::before, .lb__close i::after {
  content: ""; position: absolute; left: 50%; top: 0; width: 2px; height: 1.4em;
  background: currentColor; transform: translateX(-50%);
}
.lb__close i::after { transform: translateX(-50%) rotate(90deg); }
body.lb-open { overflow: hidden; }

.gallery figure { cursor: zoom-in; position: relative; overflow: hidden; }
.gallery figure img { transition: transform .7s var(--ease); }
.gallery figure:hover img { transform: scale(1.035); }

/* ---------- reveal ---------- */
/* Only hide when JS is running, so content is never lost if the script fails. */
.js .rv { opacity: 0; transform: translateY(14px); transition: opacity .8s var(--ease), transform .8s var(--ease); }
.js .rv.in { opacity: 1; transform: none; }
/* children stagger within a revealed block */
.js .rv-stagger > * { opacity: 0; transform: translateY(20px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.js .rv-stagger.in > * { opacity: 1; transform: none; }
.js .rv-stagger.in > *:nth-child(1) { transition-delay: .04s; }
.js .rv-stagger.in > *:nth-child(2) { transition-delay: .10s; }
.js .rv-stagger.in > *:nth-child(3) { transition-delay: .16s; }
.js .rv-stagger.in > *:nth-child(4) { transition-delay: .22s; }
.js .rv-stagger.in > *:nth-child(5) { transition-delay: .28s; }
.js .rv-stagger.in > *:nth-child(6) { transition-delay: .34s; }

/* Per-item reveal for long grids.

   rv-stagger reveals a whole block the moment 8% of it is visible and defines
   only six delays, which is fine for a five-tile row and wrong for the 39-tile
   portfolio: everything past tile six finished animating before you scrolled to
   it. rv-items has no nth-child delays at all -- site.js observes each tile and
   sets the delay from its position within its own row, so the grid ripples row
   by row at any column count. */
.js .rv-items > * {
  opacity: 0; transform: translateY(22px);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
.js .rv-items > *.in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js .rv, .js .rv-stagger > *, .js .rv-items > * {
    opacity: 1; transform: none; transition: none; transition-delay: 0s !important;
  }
  .progress { display: none; }
  .card__fig img, .person__fig img { transition: none; }
}

/* ---------- stat roll (departure board) ----------
   The figure is real text in the HTML; site.js swaps it for these strips only
   when the row scrolls into view. Each strip is 0-9 twice over plus the target
   digit, and parks on the last one, so every digit makes one full visible
   revolution before it settles. Nothing here runs without JS, and without JS
   the plain number is simply left alone. */
.roll { display: inline-flex; align-items: flex-start; }
.roll__d {
  display: inline-block; overflow: hidden;
  height: 1em; line-height: 1;
}
.roll__c {
  display: block;
  transform: translateY(-20em);   /* parked on the real digit before JS starts */
  transition: transform 0s cubic-bezier(.16, .78, .3, 1);
  will-change: transform;
}
.roll__c > span { display: block; height: 1em; line-height: 1; }
@media (prefers-reduced-motion: reduce) {
  .roll__c { transition: none; }
}

/* ---------- utilities ---------- */
.mt-s { margin-top: 1rem; }
.mt-m { margin-top: 2rem; }
.mt-l { margin-top: clamp(2.5rem, 1.5rem + 3vw, 4.5rem); }
.stack > * + * { margin-top: clamp(2.5rem, 1.5rem + 3vw, 4.5rem); }
.center { text-align: center; }
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
