/* ============================================================
   Steer Media — built to the Mōno™ layout system
   Light base, alternating black sections, Inter, red accent.
   ============================================================ */

:root{
  --white:#FFFFFF;
  --grey:#F5F5F5;
  --black:#000000;
  --ink:#000000;
  /* .55, not .52 — at .52 this lands on 4.27:1 against white and 4.19:1
     against --grey, both short of the 4.5:1 WCAG AA floor, and it carries
     every section label (.top-text) and every intro paragraph (.lead). .55
     is the first value that clears AA on both grounds, and it happens to be
     the same alpha as --d-muted, so the light and dark halves of the palette
     are now mirror images instead of one being quietly weaker. */
  --muted:rgba(0,0,0,.55);
  --line:rgba(0,0,0,.12);
  --red:#E81E25;

  /* inverted tokens for .drk sections */
  --d-text:#FFFFFF;
  --d-muted:rgba(255,255,255,.55);
  --d-line:rgba(255,255,255,.16);

  --pad:clamp(20px,3.6vw,56px);
  --font:'Inter',-apple-system,BlinkMacSystemFont,sans-serif;
  --ease:cubic-bezier(.22,1,.36,1);
}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-font-smoothing:antialiased}
body{
  font-family:var(--font);
  background:var(--white);
  color:var(--ink);
  overflow-x:hidden;
  font-feature-settings:"ss01","cv01";
}
img{display:block;width:100%;height:100%;object-fit:cover}
a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit;background:none;border:none;outline:none}
ul{list-style:none}

.container{max-width:1368px;margin:0 auto;width:100%}
section{padding:clamp(70px,9vw,120px) var(--pad);position:relative}

/* ---------- dark sections ---------- */
.drk{background:var(--black);color:var(--d-text)}
.drk .top-text{color:var(--d-muted)}
.drk .lead{color:var(--d-muted)}
.grey{background:var(--grey)}

/* ---------- Mōno signature: parenthesised labels ---------- */
.top-text{
  font-size:13px;font-weight:400;letter-spacing:-.01em;color:var(--muted);
  display:flex;align-items:center;gap:10px;
}
.top-text.gry{color:var(--muted)}
.label-row{
  display:flex;justify-content:space-between;align-items:center;
  gap:16px;border-bottom:1px solid var(--line);padding-bottom:16px;margin-bottom:clamp(32px,4vw,64px);
}
.drk .label-row{border-color:var(--d-line)}
.circle-divider{width:5px;height:5px;border-radius:50%;background:var(--red);flex:none}

/* ---------- type ---------- */
.h1{
  font-size:clamp(64px,12.2vw,176px);font-weight:600;line-height:.92;letter-spacing:-.05em;
}
.h2{
  font-size:clamp(30px,4.4vw,64px);font-weight:600;line-height:1.02;letter-spacing:-.04em;
  max-width:16ch;
}
.h3{font-size:clamp(20px,2.2vw,32px);font-weight:600;letter-spacing:-.032em}
.lead{font-size:clamp(15px,1.25vw,18px);line-height:1.5;color:var(--muted);max-width:46ch}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;gap:10px;
  font-size:14px;font-weight:500;letter-spacing:-.01em;
  padding:14px 24px;border-radius:100px;
  position:relative;overflow:hidden;isolation:isolate;
  transition:color .45s var(--ease);
  border:1px solid var(--line);
}
.btn svg{width:13px;height:13px;flex:none;transition:transform .16s var(--ease)}
.btn::before{content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;
  transform:translateY(101%);transition:transform .16s var(--ease)}
.btn--dark{background:var(--black);color:#fff;border-color:var(--black)}
.btn--dark::before{background:var(--red)}
.btn--light{background:#fff;color:var(--black);border-color:#fff}
.btn--light::before{background:var(--red)}
.btn--light:hover{color:#fff}
.btn--ghost::before{background:var(--black)}
.btn--ghost:hover{color:#fff}

/* Lift on light backgrounds only. A dark drop shadow reads as dirt on a
   black section, so anything inside .drk or a black card opts out. */
.btn--dark,.btn--ghost,.nav__cta{
  box-shadow:0 14px 30px rgba(0,0,0,.20), 0 3px 8px rgba(0,0,0,.10);
  /* transform is deliberately absent: initMagnetic() drives these with GSAP,
     and a CSS transition on transform would re-animate every frame it writes,
     making the magnetic pull lag behind the cursor. */
  transition:color .45s var(--ease),box-shadow .45s var(--ease);
}
.btn--dark:hover,.btn--ghost:hover,.nav__cta:hover{
  box-shadow:0 20px 42px rgba(0,0,0,.26), 0 5px 12px rgba(0,0,0,.13);
}
.drk .btn,.panel--dark .btn,.reel .btn{box-shadow:none}
.drk .btn:hover{box-shadow:none}
.drk .btn--ghost{border-color:var(--d-line)}
.drk .btn--ghost::before{background:#fff}
.drk .btn--ghost:hover{color:var(--black)}
.btn:hover::before{transform:translateY(0)}
.btn:hover svg{transform:translate(3px,-3px)}
.btn--wide{width:100%;justify-content:center}

/* ============================================================
   PRELOADER
   ============================================================ */
.loader{position:fixed;inset:0;z-index:9999;background:var(--black);
  display:flex;align-items:center;justify-content:center;flex-direction:column;gap:26px}
.loader__logo{width:clamp(160px,22vw,300px);height:auto}
.loader__bar{width:min(280px,52vw);height:1px;background:rgba(255,255,255,.2)}
.loader__bar span{display:block;height:100%;width:0;background:var(--red)}
.loader__count{
  position:absolute;bottom:var(--pad);right:var(--pad);
  font-size:13px;color:rgba(255,255,255,.5);
}

/* ============================================================
   CURSOR
   ============================================================ */
/* The red dot IS the pointer, so the system arrow is hidden and the dot has to
   carry the job on its own. At 8px flat red it disappeared against the red
   accent and against busy photography — 13px plus a white ring and a soft
   drop keeps it findable on white, on black and over an image. */
/* Hidden until initCursor() says otherwise. `body.has-dot-cursor` is the ONE
   switch for the whole swap — showing the dot and hiding the system pointer
   are the same decision, so they must never be able to disagree. Duplicating
   the test as a media query here is what lets that happen: initCursor() gates
   on width at load and does not re-check, so a window resized past the
   breakpoint would hide the system pointer with no dot to replace it. */
.cursor{position:fixed;top:0;left:0;z-index:9000;pointer-events:none;
  width:13px;height:13px;border-radius:100px;background:var(--red);
  display:none;align-items:center;justify-content:center;
  transform:translate(-50%,-50%);
  /* The red dot IS the pointer now, so it has to carry the job alone. At 8px
     flat red it vanished against the red accent and against busy photography;
     13px plus a white ring and a soft drop keeps it findable on white, on
     black and over an image. */
  box-shadow:0 0 0 2px rgba(255,255,255,.92), 0 2px 10px rgba(0,0,0,.4);
  transition:width .4s var(--ease),height .4s var(--ease),box-shadow .4s var(--ease)}
body.has-dot-cursor .cursor{display:flex}
.cursor__label{font-size:11px;font-weight:500;color:#fff;opacity:0;white-space:nowrap;transition:opacity .25s}
/* expanded into a label chip the ring reads as an outline, so it goes and the
   depth shadow does the separating instead */
.cursor.is-active{width:72px;height:72px;box-shadow:0 6px 22px rgba(0,0,0,.3)}
.cursor.is-active .cursor__label{opacity:1}

/* `!important` because ~17 components set their own `cursor:pointer`, each of
   which outranks a bare `*`. Text fields keep the native I-beam — there the
   system cursor still carries information the dot cannot. */
/* body itself as well as its descendants — `*` does not match its own root, so
   without the first selector the system pointer reappears over bare ground. */
body.has-dot-cursor,
body.has-dot-cursor *{cursor:none !important}
body.has-dot-cursor input,
body.has-dot-cursor textarea,
body.has-dot-cursor select,
body.has-dot-cursor [contenteditable]{cursor:auto !important}

/* ============================================================
   NAV
   ============================================================ */
/* Opacity is owned by CSS here, never by GSAP — that keeps the intro reveal
   and the scroll fade on one transition instead of fighting each other. */
.nav{position:fixed;top:0;left:0;right:0;z-index:800;
  display:flex;align-items:center;justify-content:space-between;
  padding:18px var(--pad);opacity:0;
  transition:opacity .3s var(--ease),transform .55s var(--ease),background .4s,backdrop-filter .4s}
.nav.is-ready{opacity:1}
.nav.is-stuck{background:rgba(255,255,255,.82);backdrop-filter:blur(14px)}
.nav.is-hidden{transform:translateY(-105%)}
.nav.is-over-wall{opacity:0;pointer-events:none}
.nav__logo img{width:clamp(92px,8vw,112px);height:auto;transition:opacity .4s}
.nav__logo:hover img{opacity:.6}
.nav__links{display:flex;gap:2px}
.nav__link{position:relative;overflow:hidden;height:18px;display:flex;flex-direction:column;
  font-size:14px;font-weight:400;padding:0 14px}
.nav__link span{line-height:18px;transition:transform .2s var(--ease)}
.nav__link:hover span{transform:translateY(-18px)}
.nav__link span:last-child{color:var(--red)}
.nav__cta{display:inline-flex;align-items:center;gap:9px;font-size:13.5px;font-weight:500;
  border:1px solid var(--line);border-radius:100px;padding:10px 18px;
  transition:background .4s,color .4s,border-color .4s}
.nav__cta-dot{width:5px;height:5px;border-radius:50%;background:var(--red)}
.nav__cta:hover{background:var(--black);color:#fff;border-color:var(--black)}
.nav__burger{display:none;width:32px;height:18px;position:relative;cursor:pointer}
.nav__burger span{position:absolute;left:0;right:0;height:1.5px;background:var(--ink);
  transition:transform .45s var(--ease)}
.nav__burger span:first-child{top:4px}
.nav__burger span:last-child{bottom:4px}
body.menu-open .nav__burger span{background:#fff}
body.menu-open .nav__burger span:first-child{transform:translateY(4px) rotate(45deg)}
body.menu-open .nav__burger span:last-child{transform:translateY(-4px) rotate(-45deg)}

/* ============================================================
   DOCK — floating bottom pill nav, used past the hero.
   Hidden by default; slides up when the scroll goes idle.
   ============================================================ */
.dock{
  position:fixed;left:50%;bottom:clamp(16px,2.4vw,30px);z-index:690;
  display:flex;align-items:center;gap:clamp(8px,1.6vw,26px);
  padding:10px clamp(14px,1.6vw,22px);
  /* frosted glass: translucent dark tint + strong gaussian blur */
  background:rgba(36,36,40,.44);
  -webkit-backdrop-filter:blur(22px) saturate(150%);
  backdrop-filter:blur(22px) saturate(150%);
  border:1px solid rgba(255,255,255,.14);
  border-radius:100px;box-shadow:0 18px 48px rgba(0,0,0,.32),0 4px 14px rgba(0,0,0,.16);
  /* start hidden below the fold, centred; .is-up brings it into view */
  transform:translate(-50%,150%);opacity:0;pointer-events:none;
  transition:transform .6s var(--ease),opacity .5s var(--ease);
}
.dock.is-up{transform:translate(-50%,0);opacity:1;pointer-events:auto}

.dock__link{
  position:relative;overflow:hidden;height:18px;display:flex;flex-direction:column;
  font-size:14px;font-weight:500;color:#fff;padding:0 clamp(6px,1vw,14px);
}
/* dark glass → recolour the near-black wordmark to white (keep the red dot) */
.dock__logo svg [fill="#0B0B0C"]{fill:#fff}
.dock__link span{line-height:18px;transition:transform .2s var(--ease)}
.dock__link:hover span{transform:translateY(-18px)}
.dock__link span:last-child{color:var(--red)}

.dock__logo{display:flex;align-items:center;justify-content:center;padding:0 clamp(4px,.6vw,10px)}
/* the injected SVG has no width of its own — size it here (also covers the
   <img> fallback via .dock-logo) */
.dock__logo svg,.dock__logo .dock-logo{width:clamp(84px,7vw,104px);height:auto;display:block}
/* the red dot in the wordmark pulses */
.dock__logo .dock-dot{
  transform-box:fill-box;transform-origin:center;
  animation:dockDot 2.2s var(--ease) infinite;
}
@keyframes dockDot{
  0%,100%{transform:scale(1);opacity:1}
  45%{transform:scale(1.55);opacity:.7}
}

@media(max-width:560px){
  .dock{gap:4px;padding:8px 12px}
  .dock__link{font-size:12.5px;padding:0 6px}
}

/* Thumb-sized hit areas for the two primary mobile controls. Must stay BELOW
   the 560px block above, which also sets .dock padding — otherwise that rule
   wins on a phone and the dock grows by the padding instead of absorbing it.

   .dock__link cannot simply take padding: its `overflow:hidden` + `height:18px`
   IS the mask that hides the second span until hover, so padding would reveal
   both labels at once. Transparent borders work because overflow clips to the
   PADDING box — the 18px mask is untouched while the border box grows to 44.
   Dock padding drops to compensate, so the pill only gains 6px overall. */
@media (pointer:coarse){
  .dock{padding-block:0}
  .dock__link{height:44px;border-block:13px solid transparent}
  .nav__burger::after{content:"";position:absolute;inset:-13px -6px}
  .nav__logo{position:relative}
  .nav__logo::after{content:"";position:absolute;inset:-6px -4px}
}

.menu{position:fixed;inset:0;z-index:700;background:var(--black);color:#fff;
  padding:100px var(--pad) var(--pad);
  display:flex;flex-direction:column;justify-content:space-between;
  clip-path:inset(0 0 100% 0);transition:clip-path .4s var(--ease);pointer-events:none}
body.menu-open .menu{clip-path:inset(0 0 0 0);pointer-events:auto}
.menu__item{display:flex;align-items:baseline;gap:16px;
  font-size:clamp(32px,8.5vw,58px);font-weight:600;letter-spacing:-.04em;
  padding:12px 0;border-bottom:1px solid var(--d-line);
  transition:color .35s,padding-left .45s var(--ease)}
.menu__item em{font-size:12px;font-style:normal;color:var(--d-muted)}
.menu__item:hover{color:var(--red);padding-left:14px}
.menu__foot{display:flex;justify-content:space-between;font-size:13px;color:var(--d-muted);padding-top:24px}

/* ============================================================
   HERO — white panel scales down to reveal the image wall
   ============================================================ */
.hero{height:320vh;padding:0;background:var(--black);position:relative}
.hero__pin{
  position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
}

/* full-bleed wall sitting behind the panel */
/* Ratio-aware wall. Twelve columns of short rows gives a fine enough lattice
   that each tile can take a span matching its own aspect ratio — portrait
   images get tall cells, landscape wide ones — instead of every picture being
   centre-cropped into the same box. `dense` back-fills the gaps that leaves. */
/* Ratio-aware wall. `--u` is set from JS to the measured column width so the
   grid units are SQUARE — only then does a span of N columns × M rows
   actually render at ratio N/M, letting each tile match its own image. */
.hero__wall{
  position:absolute;inset:0;z-index:0;
  display:grid;
  grid-template-columns:repeat(12,1fr);
  grid-auto-rows:var(--u,56px);
  grid-auto-flow:dense;
  gap:8px;padding:8px;
  overflow:hidden;
}
.hero__wall figure{
  overflow:hidden;border-radius:4px;background:#111;
  grid-column:span 4;grid-row:span 4;   /* default until the ratio is measured */
}
.hero__wall img{width:100%;height:100%;object-fit:cover;object-position:center}

/* the panel that shrinks */
.hero__panel{
  /* 90%, not 80%. Measured against a black patch of the wall showing through:
     body text is 16.7:1 at 90% and 13.1:1 at 80% — both far past the 4.5:1
     minimum — but the muted copyright line drops to 3.80:1 at 80%, under the
     threshold. 90% keeps every element legible. */
  position:relative;z-index:2;background:rgba(255,255,255,.9);
  width:100%;height:100%;
  display:flex;flex-direction:column;justify-content:space-between;
  padding:clamp(80px,9vw,120px) var(--pad) clamp(24px,3vw,44px);
  /* The panel is scaled down on scroll, and scale multiplies the radius —
     so this is sized to read correctly once shrunk, not at full bleed. */
  border-radius:clamp(18px,2vw,30px);
  overflow:hidden;
  will-change:transform;
}

/* the 4-column rule grid + dot markers */
.hero__rules{position:absolute;inset:0;pointer-events:none}
.hero__rules span{position:absolute;top:0;bottom:0;width:1px;background:var(--line)}
.hero__dots{position:absolute;top:50%;left:0;right:0;height:0;pointer-events:none}
.hero__dots i{position:absolute;width:5px;height:5px;border-radius:50%;background:var(--ink);top:-2.5px}
.hero__mid{position:absolute;left:0;right:0;top:50%;height:1px;background:var(--line)}

.hero__top{display:grid;grid-template-columns:1fr 1fr;gap:30px;position:relative;z-index:2}
.hero__services li{
  font-size:clamp(11px,.95vw,13.5px);font-weight:600;letter-spacing:-.01em;
  line-height:1.65;
}
/* The list reads as a plain stack until you approach it — the rule wipes in
   from the left on hover, so the affordance appears on intent rather than
   dressing seven links in permanent underlines. */
.hero__services a{
  display:inline-block;position:relative;
  transition:color .35s var(--ease);
}
.hero__services a::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--red);transform:scaleX(0);transform-origin:left;
  transition:transform .45s var(--ease);
}
.hero__services a:hover{color:var(--red)}
.hero__services a:hover::after{transform:scaleX(1)}
/* the category line — small by design; the seven service names above it do
   the loud work, this just names the business and the two markets.
   Overrides .top-text's flex row: as a flex container the label and the city
   pair become two separate blocks that wrap independently, which at narrow
   widths reads as two stray fragments. Block + inline dot lets the whole
   thing wrap as one sentence. */
.hero__what{
  display:block;
  font-size:clamp(11px,.95vw,13px);font-weight:500;line-height:1.45;
  margin-bottom:14px;text-wrap:balance;
}
.hero__what .circle-divider{
  display:inline-block;margin:0 7px;vertical-align:middle;
}
/* Now that the service names are links they are tap targets, and an 18px row
   is not one. Opening the leading to 38px puts seven comfortable rows in the
   ~406px above the hero's midline, so nothing collides with it. */
@media (pointer:coarse){
  /* 38px measured out at 36px of real target. 44 is what a thumb wants,
     and the list has room for it. */
  .hero__services li{line-height:44px}
}
.hero__pitch{justify-self:end;max-width:330px}
.hero__pitch p{
  font-size:clamp(11px,.95vw,13.5px);font-weight:600;line-height:1.45;
  margin-bottom:18px;
}

/* The "Scroll Down" pill is centred at the foot of the hero. That used to
   land in the empty column gap between "Steer" and "Media"; the headline is
   one continuous line now, so the pill would sit on top of it. Reserve a band
   at the bottom of the panel and the wordmark lifts clear of it. */
.hero__bottom{position:relative;z-index:2;padding-bottom:clamp(48px,6.4vh,66px)}
.hero__copyright{
  /* a shade darker than --muted: at 12px over a now-translucent card the
     default .52 alpha measured 4.06:1, just under the 4.5:1 minimum */
  display:block;text-align:right;font-size:12px;color:rgba(0,0,0,.6);
  margin-bottom:clamp(20px,4vw,60px);
}
/* Was a two-column grid holding "Steer | Media" side by side. The headline is
   now a sentence, so the two blocks stack instead — and the type steps down,
   because "Advertising Agency" is three times the width of "Media" and would
   run off the panel at the old 168px ceiling. */
.hero__wordmark{
  display:block;
  font-size:clamp(28px,8.4vw,130px);font-weight:600;letter-spacing:-.05em;line-height:.92;
}
.hero__word{display:block;overflow:hidden;padding-bottom:.22em;margin-bottom:-.22em}
.hero__word > span{display:block}
.hero__wordmark sup{font-size:.34em;vertical-align:super}

.hero__scrolltag{
  position:absolute;left:50%;bottom:22px;transform:translateX(-50%);z-index:3;
  background:var(--black);color:#fff;font-size:11px;border-radius:100px;padding:6px 14px;
}

/* ============================================================
   PARTNERS — rises over the wall with a curved top edge
   ============================================================ */
/* Pulled up over the last stretch of the hero so the panel rises across the
   still-pinned image wall, rather than over the hero's spent tail. */
/* Partners and Work read as one continuous grey panel, so the join between
   them gets a single modest gap rather than three stacked ones. */
.partners{
  background:var(--grey);position:relative;z-index:5;
  margin-top:-90vh;padding-top:clamp(60px,7vw,100px);
  padding-bottom:clamp(26px,3vw,44px);
}
/* ---------- animated arc cap ----------
   An SVG quadratic curve rather than a border-radius ellipse. A radius cap
   curls down hard at the ends (the "too rounded" corners) and its curvature
   can't be animated; a Bézier lets the control point travel from flat to
   arched on scroll, and meets the side edges at a shallow tangent. */
.arc{
  /* Pulled 1px INTO the section rather than sitting flush at bottom:100%.
     Two exact edges meeting leaves a hairline of background showing through
     at fractional scroll positions, which is what the seam was. */
  position:absolute;left:0;right:0;bottom:calc(100% - 1px);
  height:clamp(44px,5.5vw,96px);
  pointer-events:none;line-height:0;
}
/* overflow visible so the path can over-draw past the viewBox bottom */
.arc svg{display:block;width:100%;height:100%;overflow:visible}
.partner-grid{
  display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(10px,1.2vw,18px);
  perspective:1200px;
}
/* Black cards: the supplied logos are mostly white artwork, so a dark card is
   what lets them show in their own colours with no filtering at all. */
.partner-card{
  display:flex;align-items:center;justify-content:center;
  height:clamp(92px,10vw,140px);
  background:var(--black);border-radius:10px;
  font-size:clamp(13px,1.2vw,17px);font-weight:600;letter-spacing:-.025em;color:#fff;
  text-align:center;padding:clamp(16px,2vw,28px);
  /* No transform transition here: GSAP drives the tilt, and a CSS transition
     on the same property re-animates every value GSAP writes, which smears
     the scrub and lags the animation by its own duration. */
  transition:background .4s,color .4s;
  transform-style:preserve-3d;
}
/* hover lifts the card a shade — the logo itself is never recoloured */
.partner-card:hover{background:#1c1c20}

/* Logos are shown exactly as supplied — no greyscale, no inversion, no
   opacity knock-back. Contained so odd aspect ratios don't distort. */
.partner-logo{
  width:auto;height:auto;max-width:100%;max-height:100%;
  object-fit:contain;
}

/* the name is only shown if the logo file is missing */
.partner-name{display:none}
.partner-card.is-text .partner-name{display:block}

/* work sits on the grey too, so the section reads as one panel */
.work-section{background:var(--grey);padding-top:clamp(26px,3vw,44px)}

/* work: sticky left column + sticky-stacking cards */
.grid-work{display:grid;grid-template-columns:334px 1fr;gap:clamp(24px,4vw,56px);margin-top:0}
.sticky-lft{position:sticky;top:130px;align-self:start;padding-bottom:40px}
.sticky-lft .h2{
  font-size:clamp(40px,5.6vw,86px);font-weight:600;letter-spacing:-.045em;
  margin-bottom:clamp(120px,18vw,260px);display:flex;align-items:flex-start;gap:6px;
}
.sticky-lft .h2 em{font-style:normal;font-size:.28em;color:var(--muted);font-weight:500;margin-top:.35em}

/* each card pins, and the next one rides up over it */
.work-main{display:flex;flex-direction:column;gap:0}
/* All cards pin at the same offset. A staggered top would leave each
   outgoing card peeking above the incoming one — visible precisely
   because it is meant to have faded out by then. */
.work-item{
  display:block;text-decoration:none;color:inherit;
  position:sticky;top:120px;
  cursor:pointer;margin-bottom:clamp(40px,6vw,90px);
  will-change:transform,opacity;
}
.work-item:last-child{margin-bottom:0}
.work-item__media{
  position:relative;overflow:hidden;border-radius:clamp(14px,1.6vw,22px);aspect-ratio:16/11;
  box-shadow:0 26px 70px rgba(0,0,0,.22), 0 4px 14px rgba(0,0,0,.10);
  background:#0d0d0f;
}
.work-item__media img,
.work-item__media video{transition:transform 1.2s var(--ease)}
.work-item:hover .work-item__media img,
.work-item:hover .work-item__media video{transform:scale(1.04)}
/* A cover video sits ON TOP of the still, which stays as the poster layer.
   The still is what shows before the clip has decoded, if autoplay is refused,
   and whenever reduced motion is on — so the tile is never empty. */
.work-item__media video{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;opacity:0;transition:opacity .5s var(--ease),transform 1.2s var(--ease)}
.work-item__media video.is-live{opacity:1}

/* caption rides inside the card so stacked cards stay clean */
.work-item__foot{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  display:flex;justify-content:space-between;align-items:flex-end;gap:16px;
  padding:clamp(18px,2.4vw,32px);color:#fff;
  background:linear-gradient(to top,rgba(0,0,0,.72),rgba(0,0,0,.28) 46%,transparent);
}
.work-item__foot h3{font-size:clamp(18px,2.1vw,30px);font-weight:600;letter-spacing:-.03em}
.work-item__foot span{font-size:13px;color:rgba(255,255,255,.7);white-space:nowrap}

/* ============================================================
   STUDIO / WHO WE ARE  (white)
   ============================================================ */
.studio__top{display:grid;grid-template-columns:1fr 1fr;gap:clamp(24px,4vw,60px);align-items:end;margin-bottom:clamp(40px,5vw,72px)}
.studio__tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:20px}
.studio__tags li{
  font-size:12.5px;font-weight:500;letter-spacing:-.01em;color:var(--muted);
  border:1px solid var(--line);border-radius:100px;padding:7px 14px;
}
.studio__grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2vw,28px)}

/* ============================================================
   STUDIO PAGE (studio.html) — modeled on Mōno /studio
   ============================================================ */
/* hero — centered */
.studio-hero{text-align:center;padding:clamp(120px,15vw,190px) var(--pad) clamp(30px,5vw,70px)}
.studio-hero__eyebrow{display:block;margin-bottom:clamp(44px,8vw,110px)}
.studio-hero__title{font-size:clamp(52px,12vw,184px);font-weight:600;letter-spacing:-.045em;line-height:.9}
.studio-hero__title sup{font-size:.28em;vertical-align:super;font-weight:500}
.studio-hero__lead{font-size:clamp(15px,1.35vw,19px);line-height:1.55;color:var(--muted);
  max-width:56ch;margin:clamp(30px,4vw,48px) auto 0}
.studio-hero__dot{width:9px;height:9px;border-radius:50%;background:var(--ink);margin:clamp(36px,5vw,72px) auto 0}

/* evolution — full-bleed images that slide LEFT on scroll (pinned filmstrip) */
.evo{padding:0;background:var(--black);position:relative}
.evo__stage{overflow:hidden}
/* animated arc: a wide white ellipse whose bottom edge bulges down into the dark
   (like the reference's .circle-animation). It lives in an overflow-hidden strip
   at the evolution's top so it never bleeds up over the hero. Depth deepens on scroll. */
.evo__arc{position:absolute;top:0;left:0;width:100%;height:clamp(100px,14vw,200px);
  overflow:hidden;z-index:6;pointer-events:none;--arc:40px}
.evo__arc::before{content:'';position:absolute;top:0;left:50%;width:220%;height:78vw;
  background:var(--white);border-radius:50%;transform:translate(-50%,calc(-100% + var(--arc)))}
.evo__track{display:flex;flex-direction:column}
.evo__panel{position:relative;width:100%;height:100vh;height:100svh;min-height:600px;overflow:hidden;display:flex;align-items:flex-end;background:var(--black)}
.evo__panel img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.evo__panel::after{content:'';position:absolute;inset:0;background:linear-gradient(transparent 44%,rgba(0,0,0,.82))}
.evo__body{position:relative;z-index:1;color:#fff;padding:clamp(30px,5vw,84px);max-width:640px}
.evo__body p{font-size:clamp(16px,1.6vw,22px);line-height:1.5;color:#fff;font-weight:500;letter-spacing:-.01em;max-width:46ch}
/* pinned horizontal filmstrip (added by initStudioEvo) */
.evo.is-pinned .evo__stage{position:sticky;top:0;height:100vh;height:100svh}
.evo.is-pinned .evo__track{flex-direction:row;height:100%;width:max-content;will-change:transform}
.evo.is-pinned .evo__panel{flex:none;width:100vw;height:100%;min-height:0}

/* intro statement + partners */
.studio-intro{padding-top:clamp(80px,10vw,150px)}
.studio-intro__statement{font-size:clamp(24px,3.3vw,48px);font-weight:500;letter-spacing:-.03em;
  line-height:1.16;max-width:24ch;margin-bottom:clamp(50px,7vw,96px)}

/* partner logo wall — all partners from the deck */
.logo-wall{display:grid;gap:10px;margin-top:clamp(20px,2.4vw,32px);
  grid-template-columns:repeat(auto-fill,minmax(clamp(116px,13vw,168px),1fr))}
.logo-wall__item{background:var(--black);border-radius:12px;aspect-ratio:16/10;
  display:flex;align-items:center;justify-content:center;padding:clamp(14px,1.8vw,24px);
  transition:transform .4s var(--ease)}
.logo-wall__item:hover{transform:translateY(-3px)}
.logo-wall__item img{width:auto;height:auto;max-width:80%;max-height:58%;object-fit:contain}

/* approach — bold statement lines + image */
.approach2{padding-top:clamp(30px,4vw,60px)}
.approach2__grid{display:grid;grid-template-columns:1fr .82fr;gap:clamp(34px,5vw,80px);align-items:center}
.approach2__lines{margin:clamp(22px,3vw,44px) 0}
.approach2__line{font-size:clamp(30px,4.6vw,68px);font-weight:600;letter-spacing:-.035em;line-height:1.06}
.approach2__media{border-radius:14px;overflow:hidden;aspect-ratio:4/5;background:var(--grey)}
.approach2__media img{width:100%;height:100%;object-fit:cover;transition:transform 1s var(--ease)}
.approach2__media:hover img{transform:scale(1.05)}

/* figures — big numbers + image */
.figures__grid{display:grid;grid-template-columns:1fr .78fr;gap:clamp(34px,5vw,80px);
  align-items:center;margin-top:clamp(28px,3.5vw,52px)}
.fig{display:grid;grid-template-columns:minmax(0,auto) 1fr;gap:clamp(20px,3vw,48px);align-items:center;
  padding:clamp(22px,3vw,40px) 0;border-bottom:1px solid var(--line)}
.fig:first-child{border-top:1px solid var(--line)}
.fig__num{font-size:clamp(56px,8vw,124px);font-weight:300;letter-spacing:-.04em;line-height:.85}
.fig p{font-size:14px;line-height:1.5;color:var(--muted);max-width:32ch}
.figures__media{border-radius:14px;overflow:hidden;aspect-ratio:3/4;background:var(--grey)}
.figures__media img{width:100%;height:100%;object-fit:cover}

/* pull-quote */
.studio-quote{background:var(--grey)}
.bigquote{font-size:clamp(24px,3.4vw,52px);font-weight:500;letter-spacing:-.03em;line-height:1.14;
  max-width:20ch;margin:clamp(22px,3vw,40px) 0 clamp(20px,2.4vw,32px)}
.bigquote__by{display:flex;flex-direction:column;gap:2px}
.bigquote__by strong{font-size:15px;font-weight:600}
.bigquote__by span{font-size:13px;color:var(--muted)}

/* contact */
.studio-contact__statement{font-size:clamp(22px,2.9vw,42px);font-weight:500;letter-spacing:-.03em;
  line-height:1.2;max-width:22ch;margin-top:18px}
.studio-contact__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(34px,5vw,80px);
  align-items:start;margin-top:clamp(34px,4vw,60px)}
.studio-contact .btn{margin-top:26px}

/* capabilities — detailed services */
.caps{padding-top:clamp(30px,4vw,60px)}
.caps__head{font-size:clamp(26px,3.4vw,52px);font-weight:600;letter-spacing:-.03em;line-height:1.04;
  max-width:20ch;margin:clamp(20px,2.6vw,36px) 0 clamp(30px,4vw,54px)}
.caps__grid{display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(30px,5vw,72px)}
.cap{padding:clamp(22px,2.6vw,34px) 0;border-top:1px solid var(--line)}
.cap em{font-style:normal;font-size:12.5px;color:var(--red);font-weight:500}
.cap h3{font-size:clamp(19px,1.9vw,27px);font-weight:500;letter-spacing:-.02em;margin:8px 0 10px}
.cap p{font-size:14px;line-height:1.55;color:var(--muted);max-width:42ch}

/* case studies (dark) */
.cases__list{border-top:1px solid var(--d-line);margin-top:clamp(28px,3.5vw,48px)}
.case{display:grid;grid-template-columns:1fr auto;gap:clamp(18px,4vw,60px);align-items:start;
  padding:clamp(28px,4vw,54px) 0;border-bottom:1px solid var(--d-line);
  transition:padding-left .45s var(--ease)}
.case:hover{padding-left:clamp(6px,1vw,18px)}
.case__cl{display:block;font-size:12.5px;color:var(--d-muted);margin-bottom:16px}
.case h3{font-size:clamp(24px,3vw,46px);font-weight:500;letter-spacing:-.03em;line-height:1.06;margin-bottom:16px}
.case h3 span{color:var(--d-muted)}
.case p{font-size:14.5px;line-height:1.6;color:var(--d-muted);max-width:62ch}
.case__view{display:inline-flex;align-items:center;gap:8px;margin-top:24px;
  font-size:13px;font-weight:600;letter-spacing:-.01em;color:#fff;
  padding:11px 20px;border-radius:100px;background:var(--red);
  transition:background .4s var(--ease),transform .4s var(--ease),box-shadow .4s var(--ease);
  box-shadow:0 6px 22px rgba(232,30,37,.28)}
.case:hover .case__view{transform:translateX(4px);box-shadow:0 10px 30px rgba(232,30,37,.42)}
.case__result{font-size:12.5px;color:#fff;font-weight:500;text-align:right;white-space:nowrap;line-height:1.7}
.case__result b{display:block;font-size:clamp(22px,2.4vw,34px);font-weight:700;letter-spacing:-.03em;
  color:var(--red);transition:text-shadow .4s var(--ease)}
.case:hover .case__result b{text-shadow:0 0 30px rgba(232,30,37,.45)}

/* big section heading + light variant (used on the Work page so the
   case studies read as their own block, not part of the black footer) */
.cases__head{font-size:clamp(34px,6vw,84px);font-weight:600;letter-spacing:-.04em;line-height:.98;
  max-width:14ch;margin-top:clamp(16px,2vw,26px)}
.cases__intro{margin:clamp(18px,2.4vw,30px) 0 clamp(30px,4vw,56px);max-width:50ch}
.cases--light .cases__list{border-top-color:var(--line)}
.cases--light .case{border-bottom-color:var(--line)}
.cases--light .case__cl{color:var(--muted)}
.cases--light .case h3{color:var(--ink)}
.cases--light .case h3 span{color:var(--muted)}
.cases--light .case p{color:var(--muted)}
.cases--light .case__result{color:var(--ink)}

/* Optional preview image on a case row. Additive: it keys off :has(), so a
   card without a .case__media keeps the original text-only two columns and
   any page that has not opted in is untouched. The placeholder is a light
   veil rather than --grey, because these rows sit on black by default. */
.case:has(.case__media){grid-template-columns:clamp(180px,22vw,300px) 1fr auto}
.case__media{border-radius:12px;overflow:hidden;background:rgba(255,255,255,.06);
  aspect-ratio:4/3;align-self:center}
.cases--light .case__media{background:var(--grey)}
.case__media img{transition:transform 1.2s var(--ease)}
.case:hover .case__media img{transform:scale(1.06)}
@media(max-width:980px){
  /* three columns get cramped — the image takes its own full-width row above
     the copy, which also lets it run wider and more cinematic */
  .case:has(.case__media){grid-template-columns:1fr auto}
  .case__media{grid-column:1/-1;aspect-ratio:16/9;margin-bottom:clamp(14px,2vw,22px)}
}
@media(max-width:700px){
  .case:has(.case__media){grid-template-columns:1fr}
}

/* ============================================================
   CASE STUDY PREVIEW — the index format used on a service page
   ------------------------------------------------------------
   A preview, not a miniature of the case page. An earlier version led with a
   full-bleed 16:9 cover and ran to ~1400px for a single entry, which reads as
   a landing page rather than an index. The image sits BESIDE the copy at just
   under half the measure — big enough to carry the work, short enough that
   several entries stack without the page turning into a scroll.
   ============================================================ */
.csfeat{display:grid;grid-template-columns:minmax(0,46%) 1fr;
  gap:clamp(22px,3.4vw,52px);align-items:center;
  border-top:1px solid var(--line);padding:clamp(24px,3.4vw,46px) 0;
  transition:padding-left .45s var(--ease)}
.csfeat:hover{padding-left:clamp(4px,.8vw,14px)}
.csfeat:last-of-type{border-bottom:1px solid var(--line)}

.csfeat__cover{border-radius:14px;overflow:hidden;background:var(--grey);aspect-ratio:4/3}
.csfeat__cover img{transition:transform 1.3s var(--ease)}
.csfeat:hover .csfeat__cover img{transform:scale(1.05)}

.csfeat__cl{display:block;font-size:12.5px;color:var(--muted);margin-bottom:12px}
.csfeat__h{font-size:clamp(23px,2.7vw,40px);font-weight:500;letter-spacing:-.03em;
  line-height:1.06;color:var(--ink);margin-bottom:14px}
.csfeat__h span{color:var(--muted)}
.csfeat__p{font-size:14.5px;line-height:1.6;color:var(--muted);max-width:52ch}

/* facts run as one quiet line rather than three big numerals — at preview
   scale the headline should be the loudest thing in the block */
.csfeat__facts{display:flex;flex-wrap:wrap;gap:8px 18px;margin-top:18px;
  font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted)}
.csfeat__facts b{color:var(--red);font-weight:700;letter-spacing:-.01em;margin-right:5px}
.csfeat .case__view{margin-top:22px}

@media(max-width:900px){
  .csfeat{grid-template-columns:1fr;gap:clamp(16px,2.4vw,24px);align-items:start}
  .csfeat__cover{aspect-ratio:16/9}
}
@media(max-width:700px){
  .caps__grid{grid-template-columns:1fr}
  .case{grid-template-columns:1fr;gap:14px}
  .case__result{text-align:left}
}

@media(max-width:900px){
  .approach2__grid,.figures__grid,.studio-contact__grid{grid-template-columns:1fr;gap:36px}
  .approach2__media,.figures__media{order:-1;max-width:480px}
}
@media(max-width:640px){
  .fig{grid-template-columns:1fr;gap:8px}
  .evo:not(.is-pinned) .evo__panel{height:auto;min-height:0;aspect-ratio:3/4}
}
.panel{
  background:var(--grey);border-radius:12px;padding:clamp(22px,2.6vw,36px);
  display:flex;flex-direction:column;justify-content:space-between;gap:24px;min-height:280px;
}
.panel--dark{background:var(--black);color:#fff}
.panel__num{font-size:clamp(38px,4.6vw,64px);font-weight:600;letter-spacing:-.05em;line-height:1}
.panel__lbl{font-size:13px;color:var(--muted)}
.panel--dark .panel__lbl{color:var(--d-muted)}
.panel h3{font-size:15px;font-weight:600;letter-spacing:-.02em;line-height:1.35}

/* chat mock */
.chat{display:flex;flex-direction:column;gap:8px}
.chat__time{font-size:11px;color:var(--muted);text-align:center;margin:4px 0}
.bubble{
  font-size:13.5px;line-height:1.35;padding:10px 14px;border-radius:14px;width:fit-content;max-width:88%;
  background:#fff;border:1px solid var(--line);
}
.bubble--me{background:var(--black);color:#fff;margin-left:auto;border-color:var(--black)}

/* ============================================================
   BUILT DIFFERENT — pinned phrase sequence  (black)
   ============================================================ */
.anim-section{background:var(--black);color:#fff;height:500vh;padding:0;position:relative}
.anim-sticky{position:sticky;top:0;height:100vh;height:100svh;display:flex;align-items:center;justify-content:center;overflow:hidden}
.anim-phrase{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  font-size:clamp(34px,7.4vw,96px);font-weight:600;letter-spacing:-.045em;line-height:1;
  white-space:nowrap;text-align:center;
}
.anim-phrase em{font-style:normal;color:var(--red)}
/* carries the type over the film without darkening the film itself */
.anim-phrase{text-shadow:0 2px 18px rgba(0,0,0,.85),0 0 46px rgba(0,0,0,.6)}
/* The phrases are nowrap so they read as one line on a wide screen, but the
   longest — "Craft without compromise" — is wider than the viewport well
   before phone sizes (880px of text in a 768px window), and .anim-sticky
   clips it. Below that, let it wrap; the explicit width is needed because an
   absolutely positioned box has nothing to wrap against. */
@media(max-width:900px){
  .anim-phrase{white-space:normal;width:min(90vw,760px);line-height:1.04}
}

/* Background film behind the vision phrases.
   The clip plays at full strength; a single flat black tint fades it back so
   the phrases stay legible. Flat, not a radial vignette — the vignette hid
   the orb exactly where it is the whole point of the shot.

   The tint is kept light enough that the film actually reads — most of this
   clip is genuinely dark, so a heavy tint left it looking like a black
   rectangle. Legibility is bought back on the type instead, with a soft
   shadow: that protects the words without hiding the shot behind them. */
.vision-bg{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.vision-bg video{width:100%;height:100%;object-fit:cover;display:block}
.vision-bg::after{content:'';position:absolute;inset:0;background:rgba(0,0,0,.62)}
/* the copy sits above both */
.anim-top,.anim-btm,.anim-phrase{z-index:1}
/* Portrait crops this ultra-wide clip (2.03:1) to its middle ~23%, so the
   bright core fills the frame behind the type instead of being a centre spot.
   Same flat treatment, carried a little deeper. */
@media(max-width:760px){
  .vision-bg::after{background:rgba(0,0,0,.72)}
}

/* ============================================================
   SCATTER — tilted work cards drift around a centred CTA
   ============================================================ */
.scatter{
  position:relative;overflow:hidden;isolation:isolate;
  min-height:min(104vh,940px);display:flex;align-items:center;justify-content:center;
  padding:clamp(90px,12vw,150px) var(--pad);
  background:var(--red);color:#fff;text-align:center;
}
/* soft vignette keeps the centre type legible over the cards */
.scatter::after{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(52% 46% at 50% 50%,rgba(170,10,15,.80) 0%,rgba(170,10,15,.52) 42%,rgba(170,10,15,.12) 66%,transparent 78%);
}
/* the 3D card field — Three.js renders into this, behind the centre type */
.scatter__gl{
  position:absolute;inset:0;z-index:0;width:100%;height:100%;display:block;
  opacity:0;transition:opacity 1s var(--ease);
}
.scatter__gl.is-ready{opacity:1}

/* ---- fallback: plain DOM cards when WebGL can't run --------------
   Chrome refuses to texture WebGL from file:// images, and some
   devices have no WebGL at all — initScatter() then builds these
   instead so the section is never empty. */
.scatter__field{position:absolute;inset:0;z-index:0}
.scard{
  position:absolute;left:var(--x);top:var(--y);
  width:clamp(210px,25vw,400px);
  border-radius:12px;overflow:hidden;background:#0d0d0f;
  box-shadow:0 26px 60px rgba(0,0,0,.34),0 6px 16px rgba(0,0,0,.2);
  transform:translate3d(var(--tx,0px),var(--ty,0px),0) rotate(var(--r,0deg));
  transition:transform .6s cubic-bezier(.22,.61,.36,1);
  will-change:transform;
}
.scard__in{display:block;will-change:transform;
  animation:scardFloat var(--dur,10s) ease-in-out var(--dly,0s) infinite alternate}
@keyframes scardFloat{
  from{transform:translate(-9px,-7px) rotate(-1.1deg)}
  to  {transform:translate(9px,8px) rotate(1.2deg)}
}
.scard--sm{width:clamp(160px,19vw,310px)}
.scard img{width:100%;height:100%;object-fit:cover;aspect-ratio:4/3;display:block}
@media(max-width:900px){
  .scard--sm{display:none}
  .scard{width:clamp(104px,26vw,150px)}
}
@media(prefers-reduced-motion:reduce){
  .work-item__media video,.wcard__media video{display:none}
  /* keep the float — it's a slow, low-amplitude drift — but calm it down
     rather than freezing the whole wall */
  /* !important so it actually applies: the universal animation kill lower
     down carries !important too, and without it here that rule wins and
     this considered 'calm it, do not freeze it' decision never ran. */
  .scard__in{animation-duration:22s!important}
}

.scatter__inner{position:relative;z-index:2;max-width:min(90vw,760px)}
.scatter__eyebrow{
  display:inline-block;font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(255,255,255,.82);margin-bottom:clamp(14px,2vw,22px);
}
.scatter__eyebrow sup{font-size:.6em;vertical-align:super}
.scatter__title{
  font-size:clamp(42px,8.4vw,110px);line-height:.93;font-weight:600;letter-spacing:-.045em;
}
.scatter__title em{font-style:normal;color:var(--black)}
.scatter__sub{
  margin:clamp(18px,2.4vw,26px) auto 0;max-width:44ch;
  font-size:clamp(14px,1.5vw,17px);line-height:1.55;color:rgba(255,255,255,.9);
}
.scatter__cta{
  display:inline-flex;align-items:center;gap:10px;margin-top:clamp(24px,3.4vw,38px);
  padding:15px 34px;border-radius:100px;background:#fff;color:var(--black);
  font-size:14px;font-weight:600;white-space:nowrap;
  box-shadow:0 14px 36px rgba(0,0,0,.24);
  transition:transform .45s var(--ease),box-shadow .45s var(--ease),background .3s;
}
.scatter__cta:hover{transform:translateY(-2px) scale(1.03);box-shadow:0 20px 46px rgba(0,0,0,.3)}

@media(max-width:900px){
  .scatter{min-height:min(88vh,720px);padding:clamp(80px,16vw,110px) var(--pad)}
}

/* certifications strip (studio page) */
.certs{
  margin-top:clamp(38px,5vw,64px);padding-top:clamp(26px,3vw,38px);
  border-top:1px solid var(--line);
  display:flex;flex-direction:column;gap:18px;align-items:flex-start;
}
.certs img{width:100%;max-width:760px;height:auto;display:block}

/* ============================================================
   OFFICES — map cards on the contact page
   ============================================================ */
.offices{padding:clamp(20px,3vw,40px) 0 clamp(70px,9vw,120px)}
.offices__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(20px,3vw,40px)}
.office-card{
  border:1px solid var(--line);border-radius:clamp(14px,1.6vw,22px);overflow:hidden;
  background:var(--white);transition:box-shadow .5s var(--ease),transform .5s var(--ease);
}
.office-card:hover{box-shadow:0 26px 60px rgba(0,0,0,.12);transform:translateY(-3px)}
.office-card__map{position:relative;aspect-ratio:16/10;background:var(--grey)}
.office-card__map iframe{
  position:absolute;inset:0;width:100%;height:100%;border:0;display:block;
  /* the default map is loud — calm it down to sit with the palette */
  filter:grayscale(.9) contrast(1.02);transition:filter .6s var(--ease);
}
.office-card:hover .office-card__map iframe{filter:grayscale(0) contrast(1)}
.office-card__body{padding:clamp(20px,2.6vw,34px)}
.office-card__city{font-size:12px;color:var(--muted);display:block;margin-bottom:8px}
.office-card__name{font-size:clamp(24px,3vw,38px);font-weight:600;letter-spacing:-.03em;margin-bottom:12px}
.office-card__addr{font-size:14.5px;line-height:1.6;color:var(--muted);max-width:34ch}
.office-card__lines{display:flex;flex-direction:column;gap:4px;margin-top:16px}
.office-card__lines a{font-size:15px;width:fit-content;transition:color .3s,transform .4s var(--ease)}
.office-card__lines a:hover{color:var(--red);transform:translateX(4px)}
.office-card__dir{
  display:inline-flex;align-items:center;gap:8px;margin-top:22px;
  font-size:13px;font-weight:600;color:var(--red);
}
.office-card__dir svg{width:13px;height:13px;transition:transform .4s var(--ease)}
.office-card__dir:hover svg{transform:translate(3px,-3px)}

@media(max-width:860px){
  .offices__grid{grid-template-columns:1fr}
}

.anim-top,.anim-btm{position:absolute;left:var(--pad);right:var(--pad);display:flex;justify-content:space-between}
.anim-top{top:calc(var(--pad) + 60px)}
.anim-btm{bottom:var(--pad)}
.anim-section .top-text{color:var(--d-muted)}

/* ============================================================
   SERVICES  (white)
   ============================================================ */
/* Pinned so the list holds still while it steps. 380vh across seven services
   is ~54vh of scroll each — long enough to read the name and the blurb,
   short enough not to feel stuck.

   The pin is exactly 100vh with overflow:hidden, so everything inside has to
   fit the viewport HEIGHT — not just its width. Each measurement below is
   therefore capped in vh as well as vw; sizing on vw alone overflowed a
   1440x900 laptop by 86px and silently cut the label row off the top and the
   last service off the bottom. */
.services{height:380vh;padding:0;position:relative}
.services-pin{
  position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(28px,min(6vw,5vh),90px) var(--pad);
}
.services-pin > .container{width:100%}
.services-pin .label-row{margin-bottom:clamp(16px,min(4vw,3.4vh),64px)}

.svc-layout{display:grid;grid-template-columns:1.25fr .75fr;gap:clamp(24px,4vw,64px);align-items:start}

.svc-item{
  display:flex;align-items:baseline;gap:clamp(10px,1.4vw,22px);
  cursor:pointer;padding:clamp(2px,.4vw,8px) 0;
}
.svc-item em{
  font-style:normal;font-size:12px;color:var(--muted);flex:none;
  transition:color .45s var(--ease);
}
.svc-item span{
  /* seven names have to stack inside one viewport, so the vh cap is what
     actually governs on short screens */
  font-size:clamp(26px,min(5.4vw,7.1vh),80px);font-weight:600;letter-spacing:-.045em;line-height:1.12;
  color:rgba(0,0,0,.13);
  transition:color .45s var(--ease);
}
.svc-item.is-active span{color:var(--ink)}
.svc-item.is-active em{color:var(--ink)}
.svc-item:hover span{color:rgba(0,0,0,.35)}
.svc-item.is-active:hover span{color:var(--ink)}

/* static, not sticky — the whole section is pinned now, so a second sticky
   layer inside it would fight the pin */
.svc-panel{position:relative}
.svc-media{position:relative;aspect-ratio:4/3;border-radius:10px;overflow:hidden;background:var(--grey)}
.svc-shot{position:absolute;inset:0;opacity:0;transition:opacity .5s var(--ease)}
.svc-shot.is-active{opacity:1}
/* The descriptions are stacked absolutely so they cross-fade in place; the
   wrapper reserves the height of the tallest one. That reserve is capped in
   vh for the same reason the list is — it all has to fit one pinned screen. */
.svc-copy{position:relative;margin-top:clamp(10px,1.6vh,16px);min-height:min(15em,24vh)}
.svc-desc{
  position:absolute;inset:0;opacity:0;transition:opacity .5s var(--ease);
}
.svc-desc p{
  font-size:clamp(12px,1.5vh,13.5px);font-weight:600;line-height:1.45;max-width:38ch;
}
.svc-desc.is-active{opacity:1}

/* capability chips — the sub-services under each discipline */
.svc-tags{
  display:flex;flex-wrap:wrap;gap:5px;list-style:none;
  margin-top:clamp(8px,1.4vh,14px);max-width:40ch;
}
.svc-tags li{
  font-size:clamp(9.5px,1.15vh,11px);font-weight:500;letter-spacing:.01em;
  color:var(--muted);border:1px solid var(--line);border-radius:999px;
  padding:3px 9px;white-space:nowrap;
}

/* ============================================================
   SHOWREEL — pinned scaling grid  (black)
   ============================================================ */
.reel{background:var(--black);color:#fff;height:400vh;padding:0;position:relative}
.reel-sticky{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;display:flex;align-items:center;justify-content:center}
/* 3×3 grid; the middle cell is the showreel and starts filling the viewport,
   then the grid scales back to reveal the tiles around it. */
.reel-grid{
  display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);
  gap:14px;width:100vw;height:100vh;height:100svh;flex:none;
  will-change:transform;transform-origin:center center;
}
.reel-cell{border-radius:10px;overflow:hidden;position:relative;background:#111}
.reel-cell img,.reel-cell video{width:100%;height:100%;object-fit:cover;display:block}

.reel-feature{
  grid-column:2;grid-row:2;position:relative;
  border-radius:10px;overflow:hidden;background:#111;
  display:flex;align-items:center;justify-content:center;
}
.reel-feature img,.reel-feature video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.reel-title{
  position:relative;z-index:2;color:#fff;text-align:center;
  font-size:clamp(13px,1.5vw,20px);font-weight:600;letter-spacing:-.03em;
  text-shadow:0 2px 20px rgba(0,0,0,.5);
}
/* the scrim dims the reel while it is still full-bleed, then lifts */
.reel-scrim{position:absolute;inset:0;background:rgba(0,0,0,.55);pointer-events:none;z-index:3}
.reel-play{
  position:absolute;top:50%;left:50%;margin:-32px 0 0 -32px;z-index:4;
  width:64px;height:64px;border-radius:50%;background:rgba(255,255,255,.92);color:var(--black);
  display:flex;align-items:center;justify-content:center;pointer-events:auto;cursor:pointer;
  /* same reason as .btn — GSAP owns this element's transform */
  transition:background .4s,color .4s;
}
.reel-play svg{width:18px;height:18px;transition:transform .4s var(--ease)}
.reel-play:hover{background:var(--red);color:#fff}
.reel-play:hover svg{transform:scale(1.18)}

/* ============================================================
   REELS — pinned, track slides right→left with scroll
   Class names are deliberately .reels-* / .reel-card to avoid colliding
   with the Showreel section's .reel-* rules further up.
   ============================================================ */
.reels{background:var(--white);height:300vh;padding:0;position:relative}
.reels-pin{
  position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;
  display:flex;flex-direction:column;justify-content:center;gap:clamp(20px,3vw,40px);
}
/* content rides above the kinetic-grid canvas, which sits at z-index 0 */
.reels-head{
  display:flex;justify-content:space-between;align-items:center;gap:20px;
  padding:0 var(--pad);flex:none;position:relative;z-index:1;
}
.reels-track{
  display:flex;gap:clamp(12px,1.4vw,20px);
  padding:0 var(--pad);width:max-content;flex:none;will-change:transform;
  position:relative;z-index:1;
}

.reel-card{
  position:relative;flex:none;
  width:clamp(190px,17vw,260px);aspect-ratio:9/16;
  border-radius:14px;overflow:hidden;background:#111;
  box-shadow:0 18px 44px rgba(0,0,0,.16);
}
.reel-vid{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  display:block;background:#111;
}
/* controls sit hidden until the card is hovered */
.reel-ctrls{
  position:absolute;top:10px;right:10px;z-index:3;
  display:flex;gap:6px;opacity:0;transform:translateY(-6px);
  transition:opacity .35s var(--ease),transform .35s var(--ease);
}
.reel-card:hover .reel-ctrls{opacity:1;transform:translateY(0)}
.reel-card:focus-within .reel-ctrls{opacity:1;transform:translateY(0)}
.reel-btn{
  width:32px;height:32px;border-radius:50%;cursor:pointer;
  background:rgba(0,0,0,.55);backdrop-filter:blur(6px);color:#fff;
  display:flex;align-items:center;justify-content:center;
  transition:background .3s;
}
.reel-btn:hover{background:var(--red)}
.reel-btn svg{width:13px;height:13px;pointer-events:none}
.reel-btn .ico-off{display:none}
.reel-btn.is-off .ico-on{display:none}
.reel-btn.is-off .ico-off{display:block}

.reel-meta{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:14px;color:#fff;
  background:linear-gradient(to top,rgba(0,0,0,.78),transparent);
  display:flex;flex-direction:column;gap:2px;
}
.reel-meta strong{font-size:13px;font-weight:600;letter-spacing:-.02em}
.reel-meta span{font-size:11.5px;color:rgba(255,255,255,.68)}

@media(max-width:900px){
  .reels{height:240vh}
  .reel-card{width:clamp(150px,44vw,200px)}
}

/* ============================================================
   TESTIMONIALS — pinned  (grey)
   ============================================================ */
.testi{background:var(--grey);height:440vh;padding:0;position:relative}
.testi-sticky{position:sticky;top:0;height:100vh;height:100svh;overflow:hidden;display:flex;align-items:center;justify-content:center}

/* Two halves of ONE image. Each is 50% of the viewport and shows its own half
   of the picture, so together they read as a single uncut photo — then they
   slide apart to uncover the deck. Sit above the card, which is why the card
   appears to emerge from the gap. */
.photo-half{position:absolute;top:0;bottom:0;width:50.2%;overflow:hidden;z-index:4;will-change:transform}
.photo-half._01{left:0}
.photo-half._02{right:0}
.photo-half img{position:absolute;top:0;height:100%;width:200%;max-width:none;object-fit:cover}
.photo-half._01 img{left:0}
.photo-half._02 img{right:0}

.testi-label{position:absolute;left:var(--pad);top:50%;transform:translateY(-50%);z-index:3}
.testi-count{position:absolute;right:var(--pad);top:50%;transform:translateY(-50%);font-size:13px;color:var(--muted);z-index:3}
.testi-count em{font-style:normal;color:var(--ink)}
.testi-scroll{position:absolute;left:50%;bottom:34px;transform:translateX(-50%);z-index:3}

/* a single narrow card, with the rest of the deck stacked behind it */
.testi-deck{position:relative;z-index:2;width:min(360px,80vw);aspect-ratio:10/11}
.tcard{
  position:absolute;inset:0;background:var(--white);border-radius:16px;
  padding:clamp(20px,1.9vw,28px);
  display:flex;flex-direction:column;
  box-shadow:0 24px 60px rgba(0,0,0,.14);
  overflow:hidden;will-change:transform,opacity;
}
.tcard--photo{color:#fff}
.tcard--photo img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
.tcard--photo::after{content:'';position:absolute;inset:0;background:linear-gradient(to top,rgba(0,0,0,.75),rgba(0,0,0,.15));z-index:1}
.tcard > *{position:relative;z-index:2}

/* only the progress dots live up here now — the brand mark sits in the footer
   beside the attribution */
.tcard header{display:flex;justify-content:flex-end;align-items:center;margin-bottom:auto}

/* Brand mark on a disc, in the footer where the avatar placeholder used to be.
   The supplied partner logos are white artwork (same files the partner wall
   uses on black cards), so the disc has to be dark for them to read at all —
   on the photo cards it also takes a hairline and a blur so it separates from
   whatever is behind it. */
.tcard__logo{
  width:40px;height:40px;flex:none;
  border-radius:50%;background:var(--black);overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  padding:8px;
}
.tcard__logo img{width:100%;height:100%;object-fit:contain;display:block}
.tcard--photo .tcard__logo{
  background:rgba(12,12,14,.55);backdrop-filter:blur(8px);
  border:1px solid rgba(255,255,255,.28);
}
.tcard__dots{display:flex;gap:4px}
.tcard__dots i{width:5px;height:5px;border-radius:50%;background:rgba(0,0,0,.18)}
.tcard__dots i.on{background:var(--ink)}
.tcard--photo .tcard__dots i{background:rgba(255,255,255,.35)}
.tcard--photo .tcard__dots i.on{background:#fff}

.tcard p{font-size:15px;font-weight:600;line-height:1.38;letter-spacing:-.015em;margin-bottom:16px}
.tcard footer{display:flex;align-items:center;gap:10px}
.tcard footer > span:last-child{display:flex;flex-direction:column;gap:1px}
/* brand name leads in bold, role sits under it in grey */
.tcard strong{font-size:13.5px;font-weight:700;letter-spacing:-.01em}
.tcard em{font-style:normal;font-size:12.5px;color:var(--muted)}
.tcard--photo em{color:rgba(255,255,255,.7)}

/* ============================================================
   STATS  (black)
   ============================================================ */
/* No overflow:hidden here — the arc cap sits outside the section's box and
   would be clipped away. The kinetic-grid canvas is inset:0 so it cannot
   escape on its own. */
.stats{position:relative}
.kgrid{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:0}
.stats > .container{position:relative;z-index:1}
/* the cards sit on the mesh, so they need their own ground */
.stats .stat-card{background:rgba(17,17,20,.82);backdrop-filter:blur(6px)}

.stats__head{
  text-align:center;max-width:660px;margin:0 auto clamp(50px,7vw,110px);
  display:flex;flex-direction:column;align-items:center;gap:20px;
}
.stats__head .h2{max-width:none;display:inline}
.stats__head .lead{color:var(--d-muted);max-width:52ch}

.stats-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(12px,1.5vw,20px);align-items:start}
.stat-card{
  background:rgba(20,20,23,.82);backdrop-filter:blur(6px);
  border:1px solid var(--d-line);border-radius:12px;
  padding:clamp(18px,2vw,26px);min-height:clamp(200px,20vw,250px);
  display:flex;flex-direction:column;justify-content:space-between;gap:26px;
  will-change:transform;
}
.stat-card header{display:flex;justify-content:space-between;align-items:center;gap:10px}
.stat-card__lbl{font-size:12.5px;color:var(--d-muted)}
.stat-card__dots{display:flex;gap:4px;flex:none}
.stat-card__dots i{width:5px;height:5px;border-radius:50%;background:rgba(255,255,255,.22)}
.stat-card__dots i.on{background:var(--red)}
.stat-card__num{font-size:clamp(30px,3.6vw,52px);font-weight:700;letter-spacing:-.05em;line-height:1;margin-bottom:10px;color:var(--red)}
.stat-card p{font-size:12.5px;line-height:1.45;color:var(--d-muted);max-width:26ch}

/* ============================================================
   JOURNAL  (white)
   ============================================================ */
.post{display:grid;grid-template-columns:150px 1fr auto;gap:clamp(16px,3vw,40px);align-items:center;
  padding:clamp(20px,2.4vw,30px) 0;border-top:1px solid var(--line);
  transition:padding-left .5s var(--ease),color .4s}
.post:last-child{border-bottom:1px solid var(--line)}
.post:hover{padding-left:14px;color:var(--red)}
.post__date{font-size:13px;color:var(--muted)}
.post h3{font-size:clamp(16px,1.9vw,26px);font-weight:600;letter-spacing:-.03em}
.post__tag{font-size:11.5px;border:1px solid var(--line);border-radius:100px;padding:5px 12px;color:var(--muted)}

/* ============================================================
   CONTACT  (black)
   ============================================================ */
.contact{background:var(--black);color:#fff}
.contact__grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,80px);align-items:start}
.contact__title{font-size:clamp(48px,9vw,130px);font-weight:600;line-height:.94;letter-spacing:-.05em;margin-bottom:26px}
.contact__offices{display:grid;grid-template-columns:1fr 1fr;gap:26px;margin-top:34px}
.office__city{display:block;font-size:12.5px;color:var(--red);margin-bottom:10px}
.office p{font-size:13.5px;line-height:1.55;color:var(--d-muted);margin-bottom:10px}
.office a{display:block;font-size:14.5px;font-weight:500;width:fit-content;
  border-bottom:1px solid var(--d-line);padding-bottom:2px;margin-bottom:6px;transition:color .35s,border-color .35s}
.office a:hover{color:var(--red);border-color:var(--red)}

.contact__form{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.field{display:flex;flex-direction:column;gap:7px}
.field--full{grid-column:1/-1}
.field label{font-size:12px;color:var(--d-muted)}
.field input,.field select,.field textarea{
  border-bottom:1px solid var(--d-line);padding:11px 0;font-size:15px;color:#fff;resize:none;
  transition:border-color .35s}
.field input::placeholder,.field textarea::placeholder{color:rgba(255,255,255,.3)}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--red)}
.field select option{background:#111;color:#fff}
.contact__form .cf-turnstile,.contact__form .h-captcha{min-height:65px}
.contact__form .btn{grid-column:1/-1;margin-top:8px}
.form__note{grid-column:1/-1;font-size:12.5px;color:var(--red);min-height:16px}
.form__legal{grid-column:1/-1;font-size:12px;color:var(--d-muted)}
/* the two links have to be visibly clickable — this is the consent line */
.form__legal a{
  color:#fff;text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;text-decoration-color:rgba(255,255,255,.4);
  transition:color .3s,text-decoration-color .3s;
}
.form__legal a:hover{color:var(--red);text-decoration-color:var(--red)}

/* ============================================================
   FOOTER
   ============================================================ */
.footer{background:var(--black);color:#fff;padding:clamp(50px,6vw,80px) var(--pad) 22px;border-top:1px solid var(--d-line)}
/* Four columns, not four equal columns: the lead column carries the pitch,
   the email and the socials, so it gets the width; the link lists only need
   enough for their longest label. */
.footer__top{
  display:grid;grid-template-columns:1.7fr 1fr 1.25fr 1.35fr;
  gap:clamp(24px,3.4vw,60px);padding-bottom:clamp(44px,6vw,80px);
}
.footer__col{display:flex;flex-direction:column;gap:10px}
.footer__label{font-size:12.5px;color:var(--d-muted);margin-bottom:6px}
.footer__col a{font-size:14px;width:fit-content;transition:color .3s,transform .4s var(--ease)}
.footer__col a:hover{color:var(--red);transform:translateX(4px)}

/* lead column */
.footer__brand{display:flex;flex-direction:column;gap:15px;max-width:40ch}
.footer__pitch{font-size:13.5px;line-height:1.55;color:var(--d-muted)}
.footer__mail{
  font-size:clamp(16px,1.6vw,20px);font-weight:600;letter-spacing:-.02em;width:fit-content;
  border-bottom:1px solid rgba(255,255,255,.24);padding-bottom:4px;
  transition:color .3s,border-color .3s;
}
.footer__mail:hover{color:var(--red);border-color:var(--red)}
.footer__social{display:flex;flex-wrap:wrap;gap:8px;list-style:none;margin-top:2px}
.footer__social a{
  display:block;font-size:12.5px;padding:7px 15px;border-radius:100px;
  border:1px solid var(--d-line);color:var(--d-muted);
  transition:color .3s,border-color .3s,background .3s;
}
.footer__social a:hover{color:#fff;border-color:#fff;background:rgba(255,255,255,.06)}

/* offices */
.footer__office{display:flex;flex-direction:column;gap:3px}
.footer__office + .footer__office{margin-top:16px}
.footer__office strong{font-size:13.5px;font-weight:600}
.footer__office span{font-size:12.5px;line-height:1.5;color:var(--d-muted)}
.footer__office a{font-size:13px;margin-top:4px;width:fit-content;transition:color .3s}
.footer__office a:hover{color:var(--red)}
.footer__mark{display:flex;justify-content:center;padding-bottom:30px}
.footer__mark img{width:min(88%,880px);height:auto}
.footer__bar{display:flex;justify-content:space-between;align-items:center;gap:14px;flex-wrap:wrap;
  border-top:1px solid var(--d-line);padding-top:18px;font-size:12.5px;color:var(--d-muted)}
.footer__legal{display:flex;gap:clamp(14px,2vw,26px)}
.footer__legal a{color:var(--d-muted);transition:color .3s}
.footer__legal a:hover{color:#fff}
/* ---------- touch targets ----------
   The footer link stacks are set tight on purpose — dense columns are how the
   whole information architecture stays visible at a glance. But `width:fit-content`
   plus a ~17px line box leaves a target far under the 44px minimum, which is
   fine for a cursor and poor for a thumb. Scoped to `pointer:coarse` so only
   touch devices pay for it and the desktop footer keeps its density. */
@media (pointer:coarse){
  .footer__col a,
  .footer__legal a,
  .footer__office a,
  .footer__mail,
  .office a,          /* the contact section's phone links */
  .form__legal a{
    min-height:44px;
    display:flex;
    align-items:center;
  }
  /* the back-to-top pill and the social chips already clear 44 via padding */
  .footer__bar{row-gap:4px}
}

/* once the floating dock retires at the footer, this becomes the way up */
.footer__bar a[href="#top"]{
  color:#fff;padding:8px 18px;border-radius:100px;border:1px solid var(--d-line);
  transition:background .45s var(--ease),border-color .45s var(--ease),
             box-shadow .45s var(--ease),transform .5s var(--ease),color .3s;
}
body.at-footer .footer__bar a[href="#top"]{
  background:var(--red);border-color:var(--red);color:#fff;
  transform:translateY(-1px) scale(1.05);
  box-shadow:0 10px 30px rgba(232,30,37,.34);
}
.footer__bar a[href="#top"]:hover{color:#fff;opacity:.92}
.footer__bar a:not([href="#top"]):hover{color:var(--red)}

/* ============================================================
   REVEAL BASE STATES
   ============================================================ */
.reveal-up{opacity:0}
.reveal-media{overflow:hidden}
/* The mask that each line rises out of is exactly one line-box tall, and these
   headings run at line-height .98–1. Descenders (g, p, y, j, Q, comma) sit
   below the line box, so the mask was shaving them off — "Campaigns",
   "Packaging", "Photography" all lost the bottom of their tails.
   Grow the mask downwards and pull the next line back up by the same amount,
   so glyphs get room while the visual line spacing is untouched. Keep the two
   values identical or the heading rhythm shifts. */
.split-lines .sl-line{display:block;overflow:hidden;padding-bottom:.22em;margin-bottom:-.22em}
.split-lines .sl-inner{display:block}

/* ============================================================
   WORK INDEX PAGE  (work.html)
   ============================================================ */
.work-hero{padding-top:clamp(130px,16vw,210px);padding-bottom:clamp(30px,4vw,56px)}
.work-hero__title{
  font-size:clamp(40px,8.5vw,124px);line-height:.98;font-weight:600;
  letter-spacing:-.03em;max-width:16ch;margin:clamp(28px,4vw,60px) 0 clamp(26px,3.5vw,50px)}
.work-hero__meta{
  display:flex;justify-content:space-between;align-items:flex-end;gap:24px;
  border-top:1px solid var(--line);padding-top:22px}
.work-hero__count{font-size:14px;color:var(--muted);white-space:nowrap}
.work-hero__count em{color:var(--red);font-style:normal;font-weight:500}

.work-index{padding-top:clamp(30px,4vw,50px)}
.wgrid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(30px,3vw,52px) clamp(24px,3vw,44px)}
.wcard{display:block;color:inherit}
.wcard:nth-child(even){margin-top:clamp(46px,8vw,130px)}
.wcard__media{
  position:relative;border-radius:14px;overflow:hidden;aspect-ratio:4/3;
  background:var(--grey)}
.wcard__media img,
.wcard__media video{transition:transform .9s var(--ease)}
.wcard:hover .wcard__media img,
.wcard:hover .wcard__media video{transform:scale(1.05)}
.wcard__media video{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;opacity:0;transition:opacity .5s var(--ease),transform .9s var(--ease)}
.wcard__media video.is-live{opacity:1}
.wcard__foot{
  display:flex;justify-content:space-between;align-items:baseline;gap:18px;
  margin-top:18px;padding-bottom:4px;
  border-bottom:1px solid var(--line);
  transition:border-color .4s var(--ease)}
.wcard:hover .wcard__foot{border-color:var(--ink)}
.wcard__foot h2{font-size:clamp(19px,1.7vw,26px);font-weight:500;letter-spacing:-.02em}
.wcard__meta{display:flex;gap:16px;align-items:baseline;flex:none;
  font-size:12.5px;color:var(--muted);text-align:right}
.wcard__meta i{font-style:normal}

.work-cta{text-align:center}
.work-cta .container{display:flex;flex-direction:column;align-items:center;gap:22px}
.work-cta__title{font-size:clamp(34px,6vw,80px);line-height:1;font-weight:600;
  letter-spacing:-.03em;max-width:16ch}
.work-cta .lead{color:var(--d-muted);max-width:44ch;text-align:center}
.work-cta .btn{margin-top:8px}

@media(max-width:820px){
  .wgrid{grid-template-columns:1fr;gap:clamp(30px,7vw,50px)}
  .wcard:nth-child(even){margin-top:0}
  .work-hero__meta{flex-direction:column;align-items:flex-start;gap:14px}
}

/* ============================================================
   SOCIAL MEDIA CREATIVES — filter + gallery  (work-social.html)
   ============================================================ */
.social{padding-top:clamp(20px,3vw,40px)}

/* --- filter bar (sticks under the nav) --- */
/* Deliberately not sticky: the chips scroll away with the rest of the page.
   No sticky means no need for the white gradient that used to mask content
   passing underneath, and no stacking context to fight either. */
.filters{
  display:flex;flex-wrap:wrap;align-items:center;gap:9px;
  padding:14px 0;margin-bottom:clamp(24px,3vw,44px);
}
/* Standing label, written by the render functions so every gallery gets it.
   A bare row of pills reads as decoration above a long wall; one word in
   front of them says they are controls. */
.filters__label{
  font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);margin-right:4px;white-space:nowrap}
/* Chips carry a fill rather than a hairline outline. An outline-only pill on
   white is the same weight as the body copy around it and gets skipped; a
   filled one reads as a control at a glance. */
.filter{
  font-size:13.5px;font-weight:500;letter-spacing:-.01em;color:var(--ink);
  background:var(--grey);border:1px solid transparent;border-radius:100px;
  padding:9px 17px;cursor:pointer;white-space:nowrap;
  transition:color .18s var(--ease),background .18s var(--ease),border-color .18s var(--ease)}
.filter:hover{border-color:var(--ink)}
/* The live chip takes the brand red. Only one is ever on, so the accent stays
   as scarce here as everywhere else — and white on #E81E25 measures 4.52:1,
   clear of the 4.5:1 AA floor for this size. */
.filter.is-on{background:var(--red);color:#fff;border-color:var(--red)}
.filter.is-on:hover{border-color:var(--red)}
.filter em{font-style:normal;opacity:.5;margin-left:6px;font-size:12px;
  font-variant-numeric:tabular-nums}
.filter.is-on em{opacity:.8}

/* --- one block per category --- */
.social-group{margin-bottom:clamp(46px,6vw,86px);scroll-margin-top:130px}
.social-group.is-hidden{display:none}
.social-group.is-plain{margin-bottom:0}
.social.is-single .filters{display:none}
.social-group__head{
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  border-bottom:1px solid var(--line);padding-bottom:14px;margin-bottom:clamp(20px,2.4vw,34px)}
.social-group__head h2{font-size:clamp(20px,2vw,30px);font-weight:500;letter-spacing:-.02em}
.social-group__head span{font-size:13px;color:var(--muted);white-space:nowrap}

/* --- masonry columns of square-ish creatives --- */
/* CSS `columns` fills column 1 top-to-bottom BEFORE starting column 2, so the
   first N items land down the left edge rather than across the top — which
   makes any deliberate ordering invisible. These are real columns filled in
   reading order by layoutColumns(); item 1 goes top-left, item 2 top-next,
   and so on, so the leading category actually leads the wall. */
/* One knob for the wall's breathing room. Pages with few, detailed tiles
   (work-web) raise it; a dense wall of social posts leaves it alone. The
   gutter between columns and the gap below a tile stay equal either way. */
.social{--gal-gap:clamp(12px,1.4vw,20px)}
.social--roomy{--gal-gap:clamp(20px,2.6vw,44px)}
.social-grid{display:flex;align-items:flex-start;gap:var(--gal-gap)}
.social-col{flex:1 1 0;min-width:0}
/* fallback if the script never runs: the old column flow is better than one
   very long single column */
.social-grid:not(:has(.social-col)){display:block;columns:4 240px;column-gap:var(--gal-gap)}
.social--roomy .social-grid:not(:has(.social-col)){columns:3 420px}
.creative{
  position:relative;display:block;width:100%;margin:0 0 var(--gal-gap);
  break-inside:avoid;border-radius:12px;overflow:hidden;background:var(--grey);
  cursor:pointer;color:#fff}
.creative img{width:100%;height:auto;transition:transform .8s var(--ease)}
.creative:hover img{transform:scale(1.05)}
.creative__cap{
  position:absolute;left:0;right:0;bottom:0;
  display:flex;flex-direction:column;gap:2px;
  padding:34px 14px 13px;
  background:linear-gradient(transparent,rgba(0,0,0,.78));
  opacity:0;transform:translateY(8px);
  transition:opacity .4s var(--ease),transform .4s var(--ease)}
.creative:hover .creative__cap{opacity:1;transform:translateY(0)}
.creative__client{font-size:13.5px;font-weight:600;letter-spacing:-.01em}
.creative__title{font-size:12px;color:rgba(255,255,255,.75)}

/* --- carousel posts -------------------------------------------------
   Frames are stacked absolutely on top of the first one, which alone
   holds the height. That keeps the tile a fixed size while it cycles,
   so a masonry column never reflows and the wall never jumps. */
.creative--carousel .carousel__frames{display:block;position:relative}
.creative--carousel .carousel__frames>*{
  display:block;width:100%;height:auto;opacity:0;
  transition:opacity .7s var(--ease),transform .8s var(--ease)}
.creative--carousel .carousel__frames>img:first-child{position:relative}
/* A <video> measures 0 high until its metadata arrives, so it can never be the
   element that holds the box open — it is always absolute, and the container's
   inline aspect-ratio (written by sync-media.py from the first frame) carries
   the height instead. */
.creative--carousel .carousel__frames>video,
.creative--carousel .carousel__frames>:not(:first-child){
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.creative--carousel .carousel__frames>.is-on{opacity:1}
.creative--carousel:hover .carousel__frames>.is-on{transform:scale(1.05)}

.carousel__badge{
  position:absolute;top:10px;right:10px;z-index:3;display:flex;align-items:center;gap:5px;
  padding:5px 9px;border-radius:100px;font-size:11px;font-weight:600;line-height:1;
  color:#fff;background:rgba(0,0,0,.45);backdrop-filter:blur(4px);
  border:1px solid rgba(255,255,255,.28);pointer-events:none}
.carousel__badge svg{width:12px;height:12px}

/* prev / next — small, out of the way, only while the pointer is on the tile */
.carousel__nav{
  position:absolute;top:50%;transform:translateY(-50%);z-index:4;
  width:26px;height:26px;border-radius:100px;display:flex;align-items:center;justify-content:center;
  cursor:pointer;color:#fff;background:rgba(0,0,0,.42);backdrop-filter:blur(4px);
  border:1px solid rgba(255,255,255,.3);opacity:0;
  transition:opacity .3s var(--ease),background .25s,border-color .25s}
.carousel__prev{left:8px}
.carousel__next{right:8px}
.carousel__nav svg{width:13px;height:13px}
.creative--carousel:hover .carousel__nav{opacity:1}
.carousel__nav:hover{background:var(--red);border-color:var(--red)}
.carousel__nav:focus-visible{opacity:1;outline:2px solid #fff;outline-offset:2px}

.carousel__dots{
  position:absolute;left:0;right:0;bottom:10px;z-index:3;
  display:flex;justify-content:center;gap:6px;opacity:0;
  transition:opacity .35s var(--ease)}
.creative--carousel:hover .carousel__dots{opacity:1}
.carousel__dots i{
  width:6px;height:6px;border-radius:100px;cursor:pointer;
  background:rgba(255,255,255,.45);transition:background .3s,width .3s var(--ease)}
.carousel__dots i.is-on{background:#fff;width:16px}

/* the lightbox caption gains a frame counter on carousels */
#lightboxCap i{font-style:normal;opacity:.6;margin-left:8px}

@media(hover:none){
  /* no hover on touch — keep the controls visible so they stay reachable */
  .carousel__dots,
  .carousel__nav{opacity:1}
}

/* --- empty category state --- */
.social-empty{
  border:1px dashed var(--line);border-radius:14px;
  padding:clamp(34px,5vw,60px);text-align:center;color:var(--muted);font-size:14px}

/* --- whole-page coming-soon (gallery with no items yet) --- */
.gal-soon{
  border:1px dashed var(--line);border-radius:clamp(14px,1.6vw,22px);
  padding:clamp(48px,8vw,110px) clamp(24px,5vw,64px);
  display:flex;flex-direction:column;align-items:center;text-align:center;gap:18px}
.gal-soon h2{
  font-size:clamp(30px,5vw,58px);line-height:1.04;font-weight:600;letter-spacing:-.03em;
  padding-bottom:.08em}
.gal-soon p{max-width:52ch;color:var(--muted);font-size:15px;line-height:1.6}
.gal-soon .btn{margin-top:10px}

@media(max-width:560px){
  .social-grid:not(:has(.social-col)){columns:2 140px}
  .social-group__head h2{font-size:19px}
}

/* ============================================================
   VIDEO PRODUCTION WALL  (work-video.html)
   ============================================================ */
.videowall{padding-top:clamp(20px,3vw,40px)}
.vp-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(16px,2vw,30px)}
.vp-cell{position:relative;border-radius:14px;overflow:hidden;background:#000;
  aspect-ratio:16/9;isolation:isolate}
.vp-frame,.vp-frame div,.vp-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.vp-frame iframe{pointer-events:none}                 /* all interaction goes through our guard */

/* YouTube paints the film's title and the channel name across the top of the
   player. `modestbranding` was retired in 2023 and `showinfo` in 2018, so
   neither parameter suppresses it any more and there is no flag left that does.

   So give the iframe a viewport TALLER than the cell. YouTube fits the 16:9
   film inside that taller box, which letterboxes it — and it draws the title
   onto the black bar, not onto the picture. The cell's overflow:hidden then
   crops the bar away.

   The numbers are exact rather than eyeballed: at 150% height the bar above the
   film is (150% − 100%) / 2 = 25% of the cell, which is precisely the offset.
   The film still meets all four edges of the cell with nothing cropped.
   Only YouTube needs this — Vimeo takes title=0&byline=0 and Cloudflare Stream
   has no branding to hide — so it is scoped to the class set in onReady. */
.vp-frame iframe.is-yt{top:-25%;height:150%}
/* transparent layer over the player: catches every click so nothing reaches YouTube */
.vp-guard{position:absolute;inset:0;z-index:2;cursor:pointer}
/* poster hides the player (and its title flash) until the film is started */
.vp-poster{position:absolute;inset:0;z-index:3;width:100%;height:100%;object-fit:cover;
  transition:opacity .5s var(--ease)}
.vp-cell.is-playing .vp-poster{opacity:0;pointer-events:none}
/* big centre play button on the poster */
.vp-big{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:4;
  width:clamp(52px,5vw,68px);height:clamp(52px,5vw,68px);border-radius:100px;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:#fff;
  background:rgba(0,0,0,.45);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);
  transition:opacity .4s var(--ease),transform .4s var(--ease),background .3s}
.vp-big svg{width:44%;height:44%;margin-left:2px}
.vp-big:hover{background:var(--red);border-color:var(--red);transform:translate(-50%,-50%) scale(1.06)}
.vp-cell.is-playing .vp-big{opacity:0;pointer-events:none}
/* our only controls: play/pause + sound */
.vp-controls{position:absolute;left:12px;bottom:12px;z-index:4;display:flex;gap:8px;
  opacity:0;transform:translateY(6px);transition:opacity .35s var(--ease),transform .35s var(--ease)}
.vp-cell:hover .vp-controls,.vp-cell.is-playing .vp-controls{opacity:1;transform:none}
.vp-btn{width:38px;height:38px;border-radius:100px;display:flex;align-items:center;justify-content:center;
  cursor:pointer;color:#fff;background:rgba(0,0,0,.55);backdrop-filter:blur(6px);
  border:1px solid rgba(255,255,255,.22);transition:background .3s,border-color .3s}
.vp-btn svg{width:19px;height:19px}
.vp-btn:hover{background:var(--red);border-color:var(--red)}
/* The 38px pill is the right visual weight over a still, but a thumb wants 44.
   Same trick as the burger: an invisible ::after grows the hit box while the
   painted button stays exactly where it was. Coarse pointers only. */
@media (pointer:coarse){
  .vp-btn{position:relative}
  /* -4px vertical clears 44 with margin; horizontal is held to -3px because
     the play and sound pills sit only 8px apart and overlapping hit boxes
     would let one swallow the other's taps. */
  .vp-btn::after{content:"";position:absolute;inset:-4px -3px}
}
.vp-cap{position:absolute;right:14px;bottom:16px;z-index:4;color:#fff;
  font-size:13px;font-weight:600;letter-spacing:-.01em;
  text-shadow:0 1px 10px rgba(0,0,0,.55);
  opacity:0;transform:translateY(6px);transition:opacity .35s var(--ease),transform .35s var(--ease)}
.vp-cell:hover .vp-cap,.vp-cell.is-playing .vp-cap{opacity:1;transform:none}
@media(max-width:720px){ .vp-grid{grid-template-columns:1fr} }
.vp-notice{border:1px dashed var(--line);border-radius:14px;padding:clamp(30px,5vw,56px);
  max-width:640px;color:var(--muted)}
.vp-notice h2{font-size:clamp(19px,2vw,26px);font-weight:500;letter-spacing:-.02em;color:var(--ink);margin-bottom:12px}
.vp-notice p{font-size:14.5px;line-height:1.6}
.vp-notice code{background:var(--grey);border-radius:5px;padding:2px 7px;font-size:13px}
/* compact variant that sits above the grid in file:// preview mode */
.vp-notice--inline{padding:clamp(14px,1.6vw,20px) clamp(16px,2vw,24px);margin-bottom:clamp(18px,2.4vw,28px);text-align:left}
.vp-notice--inline p{margin:0}

/* ============================================================
   REELS WALL  (work-reels.html) — vertical clips, sectioned
   ============================================================ */
.reelwall{padding-top:clamp(10px,2vw,26px)}
.reels-note{display:inline-flex;align-items:center;gap:8px;margin-top:clamp(16px,2vw,22px);
  font-size:13px;color:var(--muted);background:var(--grey);border-radius:100px;
  padding:9px 16px}
.reels-note svg{width:15px;height:15px;color:var(--red);flex:none}
.reelwall__body{display:flex;flex-direction:column;gap:clamp(42px,6vw,88px);margin-top:clamp(24px,3vw,42px)}
.rgroup.is-hidden{display:none}
.rgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(12px,1.5vw,20px);margin-top:clamp(16px,2vw,26px)}
.rcard{display:block}
.rcard__media{position:relative;aspect-ratio:9/16;border-radius:14px;overflow:hidden;
  background:var(--grey);cursor:pointer;isolation:isolate}
/* masonry variant — each clip keeps its native ratio (aspect set inline per card) */
.reelwall--masonry .rgrid{display:block;columns:4 230px;column-gap:clamp(10px,1.4vw,18px)}
.reelwall--masonry .rcard{break-inside:avoid;margin:0 0 clamp(10px,1.4vw,18px)}
.reelwall--masonry .rcard__media{aspect-ratio:auto}
.rcard__vid{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.rcard__play{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:3;
  width:clamp(46px,4vw,60px);height:clamp(46px,4vw,60px);border-radius:100px;opacity:0;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:#fff;
  background:rgba(0,0,0,.42);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.35);
  transition:opacity .4s var(--ease),transform .3s var(--ease),background .3s,border-color .3s}
.rcard__play svg{width:42%;height:42%}
.rcard__play:hover{background:var(--red);border-color:var(--red);transform:translate(-50%,-50%) scale(1.07)}
/* These clips autoplay, so a play control laid over a running video is just
   clutter — and tying it to hover meant it appeared whenever the pointer
   entered the card, including while reaching for the sound button. It is now
   bound to playback state instead: visible only while the clip is stopped,
   where it is the affordance for starting it again.
   Stated positively (.is-playing hides it) rather than as :not(), so the
   winning declaration is the more specific one and cannot be lost to
   ordering. */
.rcard__play{opacity:1}
.rcard.is-playing .rcard__play{opacity:0;pointer-events:none}
/* the sound button doubles as the "this is muted — tap to listen" cue, so it
   stays visible; it brightens on hover */
.rcard__sound{position:absolute;right:10px;top:10px;z-index:4;
  width:36px;height:36px;border-radius:100px;display:flex;align-items:center;justify-content:center;
  cursor:pointer;color:#fff;background:rgba(0,0,0,.5);backdrop-filter:blur(6px);
  border:1px solid rgba(255,255,255,.22);opacity:.9;
  transition:opacity .35s var(--ease),background .3s,border-color .3s}
.rcard__media:hover .rcard__sound{opacity:1}
.rcard__sound.is-off{border-color:rgba(255,255,255,.4)}
.rcard__sound svg{width:18px;height:18px}
.rcard__sound:hover{background:var(--red);border-color:var(--red)}
/* icon toggles */
.rcard__play .ico-on,.rcard__sound .ico-on,
.rcard__play .ico-off,.rcard__sound .ico-off{align-items:center;justify-content:center}
.rcard__play .ico-on{display:none}
.rcard__play .ico-off{display:flex;margin-left:2px}
.rcard.is-playing .rcard__play .ico-on{display:flex}
.rcard.is-playing .rcard__play .ico-off{display:none}
.rcard__sound .ico-on{display:none}
.rcard__sound .ico-off{display:flex}
.rcard__sound:not(.is-off) .ico-on{display:flex}
.rcard__sound:not(.is-off) .ico-off{display:none}
@media(max-width:900px){ .rgrid{grid-template-columns:repeat(3,1fr)} }
@media(max-width:560px){ .rgrid{grid-template-columns:repeat(2,1fr);gap:12px} }
/* square variant — Social Films on the video page */
.reelwall--square .rgrid{grid-template-columns:repeat(3,1fr)}
.reelwall--square .rcard__media{aspect-ratio:1/1}
@media(max-width:640px){ .reelwall--square .rgrid{grid-template-columns:repeat(2,1fr)} }

/* ============================================================
   LIGHTBOX
   ============================================================ */
.lightbox{
  position:fixed;inset:0;z-index:900;
  display:flex;align-items:center;justify-content:center;
  padding:clamp(16px,4vw,60px);
  background:rgba(8,8,9,.94);backdrop-filter:blur(6px);
  opacity:0;visibility:hidden;transition:opacity .4s var(--ease),visibility .4s}
.lightbox.is-open{opacity:1;visibility:visible}
.lightbox__stage{display:flex;flex-direction:column;align-items:center;gap:14px;max-width:min(92vw,720px)}
.lightbox__stage img,.lightbox__video{
  width:auto;max-width:100%;max-height:78vh;object-fit:contain;
  border-radius:8px;box-shadow:0 30px 80px rgba(0,0,0,.5)}
.lightbox__video[hidden],.lightbox__stage img[hidden]{display:none}
.lightbox__stage figcaption{color:rgba(255,255,255,.7);font-size:13.5px;text-align:center}
.lightbox__stage figcaption b{color:#fff;font-weight:600}
.lightbox__close,.lightbox__nav{
  position:absolute;color:#fff;font-size:34px;line-height:1;
  width:52px;height:52px;display:flex;align-items:center;justify-content:center;
  border-radius:100px;cursor:pointer;
  background:rgba(255,255,255,.08);transition:background .3s}
.lightbox__close:hover,.lightbox__nav:hover{background:rgba(255,255,255,.2)}
.lightbox__close{top:clamp(14px,3vw,28px);right:clamp(14px,3vw,28px);font-size:30px}
.lightbox__nav{top:50%;transform:translateY(-50%)}
.lightbox__prev{left:clamp(10px,2vw,26px)}
.lightbox__next{right:clamp(10px,2vw,26px)}
@media(max-width:600px){
  .lightbox__nav{top:auto;bottom:18px;transform:none}
  .lightbox__prev{left:calc(50% - 66px)}
  .lightbox__next{right:calc(50% - 66px)}
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media(max-width:1080px){
  .studio__grid{grid-template-columns:1fr 1fr}
  .stats-grid{grid-template-columns:repeat(2,1fr)}
  .reel-grid{width:260vw}
  /* four columns get cramped before the 900px break — drop the lead column
     onto its own row rather than squeezing the link lists */
  .footer__top{grid-template-columns:repeat(3,1fr)}
  .footer__brand{grid-column:1 / -1;max-width:56ch}
}

/* Services keeps its two columns down to 700px. Stacking the media panel
   under the list puts ~400px of extra content into a pin that is only 100vh
   tall, which the overflow:hidden then eats — narrowing the media column is
   the change that actually fits. */
@media(max-width:700px){
  .svc-layout{grid-template-columns:1fr}
  .svc-panel{position:relative;top:auto;max-width:420px}
  /* stacked, it cannot fit one viewport at any type size — so stop pinning
     and let the section scroll normally instead of clipping it */
  .services{height:auto}
  .services-pin{position:static;height:auto;overflow:visible;padding:90px var(--pad)}
  .svc-item span{color:var(--ink)}      /* nothing steps here, so nothing stays greyed out */
}
@media(max-width:900px){
  .nav__links,.nav__cta{display:none}
  .nav__burger{display:block}
  .grid-work{grid-template-columns:1fr}
  .sticky-lft{position:relative;top:auto}
  .partner-grid{grid-template-columns:repeat(2,1fr)}
  .hero__sub{flex-direction:column;align-items:flex-start}
  .studio__top,.stats__head{grid-template-columns:1fr}
  .contact__grid,.contact__form{grid-template-columns:1fr}
  /* the pitch column needs the full width once there are only two */
  .footer__top{grid-template-columns:1fr 1fr}
  .footer__brand{grid-column:1 / -1;max-width:52ch}
  .anim-section{height:500vh}
  .reel{height:320vh}
  .testi{height:300vh}
}
@media(max-width:600px){
  .studio__grid{grid-template-columns:1fr}
  .stats-grid{grid-template-columns:1fr}
  .footer__top{grid-template-columns:1fr}
  .post{grid-template-columns:1fr;gap:8px;align-items:start}
  .post__tag{justify-self:start}
  .contact__offices{grid-template-columns:1fr}
  .reel-grid{width:340vw;grid-template-columns:repeat(3,1fr)}
}
/* ============================================================
   CASE STUDY DETAIL PAGES  (case-*.html)
   ============================================================ */
.cs-hero{padding:clamp(116px,15vw,188px) var(--pad) clamp(28px,4vw,50px)}
.cs-back{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;color:var(--muted);
  margin-bottom:clamp(34px,6vw,72px);transition:color .3s var(--ease)}
.cs-back:hover{color:var(--red)}
.cs-hero__cl{display:block;font-size:13px;color:var(--red);font-weight:500;margin-bottom:clamp(18px,2.4vw,30px)}
.cs-hero__title{font-size:clamp(38px,7vw,104px);font-weight:600;letter-spacing:-.042em;line-height:.96;max-width:15ch}
.cs-hero__title span{color:var(--muted)}
.cs-hero__lead{font-size:clamp(17px,1.85vw,26px);font-weight:500;line-height:1.34;letter-spacing:-.02em;
  max-width:44ch;margin-top:clamp(26px,3.4vw,46px)}
.cs-meta{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(18px,3vw,44px);
  margin-top:clamp(40px,5vw,74px);border-top:1px solid var(--line);padding-top:clamp(22px,3vw,36px)}
.cs-meta__k{font-size:11.5px;letter-spacing:.02em;text-transform:uppercase;color:var(--red);font-weight:600;display:block;margin-bottom:12px}
.cs-meta__v{font-size:14px;line-height:1.5;color:var(--muted)}

.cs-cover{padding:clamp(6px,1vw,14px) var(--pad) 0}
.cs-cover figure{border-radius:16px;overflow:hidden;aspect-ratio:16/9;background:var(--grey)}

.cs-block{padding:clamp(58px,8vw,112px) var(--pad)}
.cs-block__grid{display:grid;grid-template-columns:.44fr 1fr;gap:clamp(26px,5vw,80px);align-items:start}
.cs-block__h{font-size:clamp(23px,2.9vw,40px);font-weight:600;letter-spacing:-.03em;line-height:1.05}
.cs-block__h em{font-style:normal;color:var(--muted)}
.cs-prose p{font-size:clamp(15px,1.3vw,18px);line-height:1.62;color:var(--muted);max-width:62ch;margin-bottom:1.05em}
.cs-prose p:last-child{margin-bottom:0}
.cs-prose strong{color:var(--ink);font-weight:600}
.drk .cs-prose p{color:var(--d-muted)}
.drk .cs-prose strong{color:#fff}
.drk .cs-block__h em{color:var(--d-muted)}

.cs-steps{display:grid;gap:0;margin-top:clamp(28px,3.5vw,46px)}
.cs-step{display:grid;grid-template-columns:auto 1fr;gap:clamp(16px,3vw,40px);
  border-top:1px solid var(--line);padding:clamp(20px,2.6vw,32px) 0}
.cs-step em{font-style:normal;font-size:13px;color:var(--red);font-weight:600}
.cs-step h3{font-size:clamp(18px,1.9vw,25px);font-weight:500;letter-spacing:-.02em;margin-bottom:10px}
.cs-step p{font-size:14.5px;line-height:1.6;color:var(--muted);max-width:60ch}
.drk .cs-step{border-color:var(--d-line)}
.drk .cs-step p{color:var(--d-muted)}

.cs-gallery{padding:clamp(4px,1vw,12px) var(--pad)}
.cs-grid{display:grid;gap:clamp(10px,1.3vw,18px)}
.cs-grid--2{grid-template-columns:1fr 1fr}
.cs-grid--3{grid-template-columns:1fr 1fr 1fr}
.cs-grid figure{border-radius:12px;overflow:hidden;background:var(--grey)}
.cs-grid--2 figure{aspect-ratio:4/3}
.cs-grid--3 figure{aspect-ratio:3/4}
.cs-grid figure img{transition:transform 1.1s var(--ease)}
.cs-grid figure:hover img{transform:scale(1.045)}
/* ---- deck spreads -------------------------------------------------
   A guidelines page is a document, not a photograph: crop it and you lose
   the content. These figures take the spread's own ratio instead of a fixed
   one, and the image is never cover-fitted. Used by the case studies that
   show a brand book. */
.cs-deck{padding:0 var(--pad)}
.cs-deck__grid{display:grid;gap:clamp(14px,1.8vw,26px);grid-template-columns:1fr 1fr}
.cs-deck__grid--1{grid-template-columns:1fr;max-width:1180px;margin-inline:auto}
.cs-deck figure{border-radius:12px;overflow:hidden;background:var(--grey);
  border:1px solid var(--line);aspect-ratio:auto}
.cs-deck figure img{width:100%;height:auto;object-fit:contain}

/* ---- palette row --------------------------------------------------
   The client's own colours, shown as data. Values come from the book, so
   they are set inline per swatch rather than tokenised here. */
.cs-swatches{display:grid;grid-template-columns:repeat(5,1fr);gap:clamp(10px,1.2vw,16px);
  margin-top:clamp(26px,3.4vw,48px)}
.cs-swatch{border-radius:12px;overflow:hidden;border:1px solid var(--line)}
.cs-swatch__chip{aspect-ratio:4/5}
.cs-swatch__meta{padding:14px 14px 16px}
.cs-swatch__meta b{display:block;font-size:14px;font-weight:600;letter-spacing:-.01em}
.cs-swatch__meta span{display:block;margin-top:5px;color:var(--muted);
  font-size:11.5px;letter-spacing:.06em;text-transform:uppercase}
@media(max-width:900px){
  .cs-deck__grid{grid-template-columns:1fr}
  .cs-swatches{grid-template-columns:repeat(2,1fr)}
}

/* ---- product photography -------------------------------------------
   A photograph placed where the thing it shows is being discussed, not
   collected into a grid at the end. Two forms: a full-width band, and a
   split where the shot sits beside a short note about it. Photographs
   keep their own ratio — these are compositions, and a fixed crop would
   cut the frame the photographer set. */
.cs-shot{padding:clamp(6px,1.2vw,16px) var(--pad)}
.cs-shot__frame{border-radius:16px;overflow:hidden;background:var(--grey);
  max-width:1180px;margin-inline:auto}
.cs-shot__frame img{width:100%;height:auto;object-fit:contain}
.cs-shot__cap{display:block;max-width:1180px;margin:14px auto 0;
  font-size:13px;line-height:1.6;color:var(--muted)}

.cs-shot--split .container{display:grid;grid-template-columns:minmax(0,42%) 1fr;
  gap:clamp(22px,4vw,64px);align-items:center}
.cs-shot--split .cs-shot__frame{max-width:none;margin:0}
.cs-shot--split .cs-shot__cap{max-width:46ch;margin:0}
/* Flipping needs the TEMPLATE reversed, not just the order: `order` moves the
   figure into the second column but leaves that column its 1fr width, so the
   photograph came out wider than its unflipped twin. */
.cs-shot--split.is-flipped .container{grid-template-columns:1fr minmax(0,42%)}
.cs-shot--split.is-flipped .cs-shot__frame{order:2}
.cs-shot--split .cs-shot__note p{font-size:15px;line-height:1.65;color:var(--muted);
  max-width:46ch;margin-top:14px}
.cs-shot--split .cs-shot__note h3{font-size:clamp(20px,2.2vw,30px);font-weight:500;
  letter-spacing:-.025em;line-height:1.1;margin-top:12px;color:var(--ink)}

@media(max-width:860px){
  .cs-shot--split .container,
  .cs-shot--split.is-flipped .container{grid-template-columns:1fr;gap:clamp(16px,3vw,26px)}
  .cs-shot--split.is-flipped .cs-shot__frame{order:0}
}

.cs-wide{padding:clamp(4px,1vw,12px) var(--pad)}
.cs-wide figure{border-radius:14px;overflow:hidden;aspect-ratio:21/9;background:var(--grey)}

.cs-results .cs-figs{display:grid;grid-template-columns:repeat(3,1fr);gap:0 clamp(30px,5vw,72px);
  margin-top:clamp(28px,3.5vw,48px)}
.cs-fig{padding:clamp(26px,3vw,42px) 0;border-top:1px solid var(--d-line)}
.cs-fig__num{font-size:clamp(46px,6.4vw,104px);font-weight:700;letter-spacing:-.045em;line-height:.86;
  color:var(--red);display:inline-block;transform-origin:left center;cursor:default;
  transition:text-shadow .45s var(--ease),filter .45s var(--ease)}
.cs-fig__num small{font-size:.4em;font-weight:600;letter-spacing:-.02em}
.cs-fig:hover .cs-fig__num{text-shadow:0 0 46px rgba(232,30,37,.5);filter:brightness(1.12)}
.cs-fig p{font-size:13.5px;line-height:1.5;color:var(--d-muted);max-width:30ch;margin-top:16px}

.cs-quote{padding:clamp(58px,8vw,112px) var(--pad)}

.cs-next{border-top:1px solid var(--line)}
.cs-next__row{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--line)}
.cs-next__cell{background:var(--white);padding:clamp(34px,5vw,72px) var(--pad);transition:background .4s var(--ease)}
.cs-next__cell:hover{background:var(--grey)}
.cs-next__cell--all{text-align:right}
.cs-next__k{font-size:12px;color:var(--red);font-weight:500;display:block;margin-bottom:14px}
.cs-next__t{font-size:clamp(22px,2.6vw,38px);font-weight:600;letter-spacing:-.03em;line-height:1.06}
.cs-next__t span{display:inline-block;transition:transform .4s var(--ease)}
.cs-next__cell:hover .cs-next__t span{transform:translateX(6px)}
.cs-next__cell--all:hover .cs-next__t span{transform:translateX(-6px)}

@media(max-width:820px){
  .cs-block__grid{grid-template-columns:1fr;gap:clamp(18px,4vw,30px)}
  .cs-results .cs-figs{grid-template-columns:1fr 1fr}
}
@media(max-width:640px){
  .cs-meta{grid-template-columns:1fr 1fr;gap:24px}
  .cs-grid--3{grid-template-columns:1fr 1fr}
  .cs-results .cs-figs{grid-template-columns:1fr}
  .cs-next__row{grid-template-columns:1fr}
  .cs-next__cell--all{text-align:left}
  .cs-step{grid-template-columns:1fr;gap:8px}
}

/* ============================================================
   JOURNAL — listing page + article pages (journal*.html)
   ============================================================ */
/* --- listing --- */
.journal-index{padding-top:clamp(10px,2vw,26px)}
.jpost{display:grid;grid-template-columns:.9fr 1.4fr;gap:clamp(20px,3vw,48px);align-items:center;
  padding:clamp(24px,3vw,40px) 0;border-top:1px solid var(--line);transition:padding-left .45s var(--ease)}
.jpost:last-child{border-bottom:1px solid var(--line)}
.jpost:hover{padding-left:clamp(6px,1vw,16px)}
.jpost__media{border-radius:14px;overflow:hidden;aspect-ratio:16/10;background:var(--grey)}
.jpost__media img{width:100%;height:100%;object-fit:cover;transition:transform 1s var(--ease)}
.jpost:hover .jpost__media img{transform:scale(1.05)}
.jpost__meta{display:flex;align-items:center;gap:12px;margin-bottom:16px}
.jpost__tag{font-size:11.5px;border:1px solid var(--line);border-radius:100px;padding:5px 12px;color:var(--red)}
.jpost__date{font-size:12.5px;color:var(--muted)}
.jpost h2{font-size:clamp(22px,2.8vw,40px);font-weight:600;letter-spacing:-.03em;line-height:1.08;margin-bottom:14px}
.jpost__ex{font-size:14.5px;line-height:1.6;color:var(--muted);max-width:52ch}
.jpost__more{display:inline-block;margin-top:20px;font-size:13px;font-weight:600;color:var(--ink);
  border-bottom:1px solid var(--line);padding-bottom:2px;transition:color .3s var(--ease),border-color .3s var(--ease)}
.jpost:hover .jpost__more{color:var(--red);border-color:var(--red)}
@media(max-width:720px){
  .jpost{grid-template-columns:1fr;gap:16px}
  .jpost__media{order:-1;aspect-ratio:16/9}
}

/* --- article --- */
.article-hero{padding:clamp(116px,15vw,184px) var(--pad) clamp(22px,3vw,40px);text-align:center}
.article-hero__meta{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:14px;
  margin-bottom:clamp(24px,3vw,34px)}
.article-hero__tag{font-size:12px;font-weight:600;color:#fff;background:var(--red);border-radius:100px;padding:6px 14px}
.article-hero__dot{font-size:12.5px;color:var(--muted)}
.article-hero__title{font-size:clamp(30px,5vw,68px);font-weight:600;letter-spacing:-.035em;line-height:1.04;
  max-width:20ch;margin:0 auto}
.article-hero__lead{font-size:clamp(16px,1.7vw,22px);line-height:1.5;color:var(--muted);
  max-width:56ch;margin:clamp(22px,3vw,34px) auto 0}
.article-cover{padding:clamp(8px,1.4vw,18px) var(--pad) 0}
.article-cover figure{max-width:1100px;margin:0 auto;border-radius:16px;overflow:hidden;aspect-ratio:16/9;background:var(--grey)}
.article-back{display:inline-flex;align-items:center;gap:8px;font-size:12.5px;color:var(--muted);
  transition:color .3s var(--ease)}
.article-back:hover{color:var(--red)}

.article-body{max-width:720px;margin:0 auto;padding:clamp(46px,6vw,88px) var(--pad)}
.article-body>*{max-width:640px;margin-left:auto;margin-right:auto}
.article-body p{font-size:clamp(16px,1.25vw,18px);line-height:1.72;color:#1a1a1c;margin-bottom:1.35em}
.article-body p.article-lead{font-size:clamp(19px,1.7vw,23px);line-height:1.55;color:var(--ink);font-weight:500;
  margin-bottom:1.5em}
.article-body h2{font-size:clamp(22px,2.4vw,32px);font-weight:600;letter-spacing:-.03em;line-height:1.12;
  margin:1.9em 0 .6em}
.article-body h3{font-size:clamp(18px,1.8vw,23px);font-weight:600;letter-spacing:-.02em;margin:1.5em 0 .5em}
.article-body a{color:var(--red);border-bottom:1px solid rgba(232,30,37,.35);transition:border-color .3s}
.article-body a:hover{border-color:var(--red)}
.article-body strong{font-weight:600;color:var(--ink)}
.article-body ul,.article-body ol{margin:0 auto 1.35em;padding-left:1.25em}
.article-body li{font-size:clamp(15px,1.2vw,17.5px);line-height:1.66;color:#1a1a1c;margin-bottom:.5em}
.article-body ul li{list-style:disc}
.article-body ol li{list-style:decimal}
.article-body blockquote{max-width:680px;margin:1.8em auto;padding:6px 0 6px clamp(20px,3vw,34px);
  border-left:2px solid var(--red);
  font-size:clamp(20px,2.2vw,28px);font-weight:500;line-height:1.32;letter-spacing:-.02em;color:var(--ink)}
.article-body hr{max-width:640px;border:0;border-top:1px solid var(--line);margin:2.4em auto}
.article-body figure{max-width:900px;margin:2em auto}
.article-body figure img{width:100%;border-radius:14px}
.article-body figcaption{font-size:12.5px;color:var(--muted);text-align:center;margin-top:10px}
.article-foot{max-width:720px;margin:0 auto;padding:0 var(--pad) clamp(20px,3vw,40px)}
.article-foot__by{display:flex;align-items:center;gap:14px;border-top:1px solid var(--line);padding-top:clamp(24px,3vw,34px)}
.article-foot__dot{width:40px;height:40px;border-radius:100px;background:var(--ink);flex:none;
  display:flex;align-items:center;justify-content:center;color:#fff;font-weight:600;font-size:14px}
.article-foot__by strong{display:block;font-size:14px;font-weight:600}
.article-foot__by span{font-size:12.5px;color:var(--muted)}

@media(prefers-reduced-motion:reduce){
  /* Animations here are decorative loops — stop them. Transitions are NOT
     zeroed: opacity and colour changes aid comprehension and the standard
     asks for gentler, not none. They just get short. Movement is removed
     by the transform resets below. */
  *{animation-duration:.01ms!important}
  *{transition-duration:.15s!important}
  .reveal-up{opacity:1!important;transform:none!important}
  .anim-section{height:auto}
  .anim-sticky{height:auto;flex-direction:column;gap:30px;padding:90px 0}
  .anim-phrase{position:relative;left:auto;top:auto;transform:none;opacity:1!important;white-space:normal}
  .reel,.testi{height:auto}
  .reel-sticky,.testi-sticky{height:auto;padding:80px 0}
}

/* ============================================================
   LEGAL PAGES  (privacy.html, terms.html)
   ------------------------------------------------------------
   Long-form text, so: a measured column (~68ch) with a sticky
   contents rail beside it. Legal copy is only useful if it can
   actually be read, hence the larger body size and open leading.
   ============================================================ */
.legal{padding-bottom:clamp(70px,9vw,140px)}
.legal__grid{
  display:grid;grid-template-columns:minmax(180px,240px) minmax(0,1fr);
  gap:clamp(28px,5vw,90px);align-items:start;
}
.legal__toc{
  position:sticky;top:110px;display:flex;flex-direction:column;gap:9px;
  padding-right:10px;
}
.legal__toc a{
  font-size:13px;color:var(--muted);line-height:1.35;
  transition:color .3s var(--ease),transform .4s var(--ease);
}
.legal__toc a:hover{color:var(--ink);transform:translateX(3px)}

.legal__body{max-width:68ch}
.legal__intro{
  font-size:clamp(16px,1.7vw,20px);line-height:1.5;font-weight:500;
  letter-spacing:-.015em;padding-bottom:clamp(18px,2.4vw,30px);
  border-bottom:1px solid var(--line);margin-bottom:clamp(24px,3vw,40px);
}
.legal__body h2{
  font-size:clamp(19px,2vw,26px);font-weight:600;letter-spacing:-.03em;
  margin-top:clamp(34px,4.4vw,58px);margin-bottom:12px;scroll-margin-top:110px;
}
.legal__body h2:first-of-type{margin-top:0}
.legal__body p{font-size:15.5px;line-height:1.62;color:var(--ink);margin-bottom:14px}
.legal__body ul{margin:0 0 16px;padding-left:20px;list-style:disc}
.legal__body li{font-size:15.5px;line-height:1.62;margin-bottom:8px}
.legal__body strong{font-weight:600}
.legal__body a{
  color:var(--red);text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:1px;transition:opacity .3s;
}
.legal__body a:hover{opacity:.7}

@media(max-width:860px){
  .legal__grid{grid-template-columns:1fr}
  /* a sticky rail on a phone just eats the screen — let it scroll away */
  .legal__toc{
    position:static;flex-direction:row;flex-wrap:wrap;gap:8px 16px;
    padding-bottom:22px;margin-bottom:8px;border-bottom:1px solid var(--line);
  }
  .legal__toc a:hover{transform:none}
}

/* ============================================================
   WHY STEER  (studio.html)
   ------------------------------------------------------------
   Three across, so the five items break 3 + 2 and the last row
   stays deliberately open rather than padded out with filler.
   ============================================================ */
.whys{padding-top:clamp(30px,4vw,60px)}
.whys__head{
  font-size:clamp(26px,3.4vw,52px);font-weight:600;letter-spacing:-.03em;line-height:1.04;
  max-width:22ch;margin:clamp(18px,2.4vw,32px) 0 clamp(30px,4vw,54px);
}
.whys__grid{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:clamp(24px,3vw,44px) clamp(30px,4vw,64px);list-style:none;
}
.why{padding-top:clamp(18px,2.2vw,28px);border-top:1px solid var(--line)}
.why em{font-style:normal;font-size:12.5px;color:var(--red);font-weight:500}
.why h3{font-size:clamp(17px,1.6vw,22px);font-weight:600;letter-spacing:-.025em;margin:9px 0 10px}
.why p{font-size:14px;line-height:1.55;color:var(--muted)}

@media(max-width:900px){ .whys__grid{grid-template-columns:1fr 1fr} }
@media(max-width:600px){ .whys__grid{grid-template-columns:1fr} }

/* ============================================================
   FLUID-INTERFACE PASS — press feedback, focus, material fallbacks
   Added against Apple's fluid-interface guidance. Three gaps the
   audit found, in the order they matter.
   ============================================================ */

/* §1 RESPONSE — the site had NO :active state anywhere, so every control
   only acknowledged a click once it had already happened. Feedback belongs
   on pointer-DOWN: the press is the moment the user is asking "did that
   land?". 100ms out so it reads as instant, slower back so the release
   feels like a settle rather than a snap. */
.filter,.svc-item,.nav__link,.dock__link,.menu__item,.footer__col a,
.footer__legal a,.footer__social a,.hero__services a,.work-item,
.case,.creative,.reel-card,.jcard,.partner-grid img{
  /* 160ms, the top of STANDARDS.md's 100-160ms press-feedback budget. The
     first pass used 280ms for the release, which overshot it. */
  transition:transform .16s var(--ease);
}
.filter:active,.svc-item:active,.nav__link:active,.dock__link:active,
.menu__item:active,.footer__col a:active,.footer__legal a:active,
.footer__social a:active,.hero__services a:active,.work-item:active,
.case:active,.creative:active,.reel-card:active,.jcard:active{
  transform:scale(.97);
  transition-duration:.1s;
}
/* .btn, .nav__cta, .testi-nav button and .reel-play carry an INLINE transform
   from initMagnetic(), which outranks any class rule — so a scale here would
   simply never apply. Brightness is the press signal for those instead, and
   it reads on both the dark and light button variants. */
.btn:active,.nav__cta:active,.testi-nav button:active,.reel-play:active,
.carousel__nav:active,.lightbox__nav:active,.lightbox__close:active{
  filter:brightness(.86);
  transition:filter .1s var(--ease);
}

/* §16 CRAFT / keyboard — the stylesheet carried three focus rules in total,
   so tabbing through the site was very nearly invisible. One ring, brand
   red, offset so it never crowds the glyph. :focus-visible keeps it off
   mouse users. */
a:focus-visible,button:focus-visible,[role="tab"]:focus-visible,
.svc-item:focus-visible,input:focus-visible,select:focus-visible,
textarea:focus-visible{
  outline:2px solid var(--red);
  outline-offset:3px;
  border-radius:4px;
}
.drk a:focus-visible,.drk button:focus-visible,.footer a:focus-visible{
  outline-color:#fff;
}

/* §14 MATERIALS — 14 surfaces use backdrop-filter and none of them answered
   the transparency or contrast preferences. Reduced transparency wants the
   material solid, not merely frostier; increased contrast additionally wants
   a defined edge to sit against. */
@media (prefers-reduced-transparency:reduce){
  .nav.is-stuck{background:var(--white);backdrop-filter:none}
  .dock{background:rgb(28,28,31);backdrop-filter:none}
  .stats .stat-card,.testi-card,.lightbox,.reels-more,
  .carousel__nav,.vp-btn,.reel-btn,.rcard__btn{backdrop-filter:none}
}
@media (prefers-contrast:more){
  .nav.is-stuck{background:var(--white);backdrop-filter:none;border-bottom:1px solid var(--ink)}
  .dock{background:#000;backdrop-filter:none;border:1px solid #fff}
  .btn{border-color:currentColor}
  :root{--muted:rgba(0,0,0,.72);--d-muted:rgba(255,255,255,.8);--line:rgba(0,0,0,.32)}
}

/* ============================================================
   §Accessibility — hover gating for touch
   On a touch device :hover latches after a tap and stays until the next tap
   lands elsewhere, so a card you poked keeps its zoom. 32 rules move on
   hover; these are the ones where the stuck state is visible.

   Deliberately NOT reset here: .vp-cell, .reel-card, .creative--carousel,
   .rcard__play, .reel-play. Each pairs :hover with an .is-playing / .is-on
   selector to reveal media controls — neutralising the hover half would
   strand those controls hidden on the very devices that need tapping.
   ============================================================ */
@media (hover:none),(pointer:coarse){
  .work-item:hover .work-item__media img,
  .approach2__media:hover img,
  .case:hover .case__media img,
  .csfeat:hover .csfeat__cover img,
  .wcard:hover .wcard__media img,
  .creative:hover img,
  .cs-grid figure:hover img,
  .jpost:hover .jpost__media img,
  .logo-wall__item:hover,
  .scatter__cta:hover,
  .office-card:hover,
  .footer__col a:hover,
  .legal__toc a:hover,
  .case:hover .case__view,
  .btn:hover svg{
    transform:none;
  }
  /* the two-line label swaps would otherwise sit stuck on their red duplicate */
  .nav__link:hover span,.dock__link:hover span{transform:none}
  /* and the underline wipe would stay drawn under whichever link was tapped */
  .hero__services a:hover::after{transform:scaleX(0)}
}

/* ============================================================
   §CASE STUDY 2.0 — the visual language of the printed deck
   The three narrative case studies (LWK, Jazaa, Apollo) were walls
   of prose. The source deck argues visually instead: full-bleed
   client photography, huge red figures, numbered phase bars and
   flat red bands carrying reversed type. These components port
   that language to the page so the reading is looking, not
   reading.

   Everything here animates on transform/opacity/clip-path only.
   Durations: interface responses stay under 300ms, scroll-driven
   narrative reveals are allowed to run longer (they are
   explanatory, not interactive).
   ============================================================ */

/* ---------- full-bleed cover plate, the deck's title page ---------- */
.cs-plate{padding:clamp(6px,1vw,14px) var(--pad) 0}
.cs-plate__in{position:relative;border-radius:18px;overflow:hidden;background:var(--black);
  aspect-ratio:16/7.2;display:grid;place-items:center;isolation:isolate}
.cs-plate__bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  /* scaled a touch so the parallax drift never exposes an edge */
  transform:scale(1.12);will-change:transform}
.cs-plate__in::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.34),rgba(0,0,0,.16) 42%,rgba(0,0,0,.62));z-index:1}
.cs-plate__mark{position:relative;z-index:2;text-align:center;padding:0 6vw}
.cs-plate__name{display:block;color:#fff;font-weight:700;letter-spacing:-.045em;line-height:.94;
  font-size:clamp(30px,6.2vw,88px)}
.cs-plate__sub{display:block;margin-top:clamp(12px,1.6vw,20px);color:rgba(255,255,255,.72);
  font-size:clamp(11px,1.05vw,14px);letter-spacing:.14em;text-transform:uppercase;font-weight:500}
@media(max-width:760px){.cs-plate__in{aspect-ratio:4/5}}

/* ---------- flat colour bands ---------- */
.cs-band{background:var(--red);color:#fff;padding:clamp(52px,7vw,104px) var(--pad)}
.cs-band .top-text,.cs-band .cs-prose p{color:rgba(255,255,255,.84)}
.cs-band .cs-prose strong,.cs-band h2{color:#fff}
.cs-band__h{font-size:clamp(26px,4vw,62px);font-weight:700;letter-spacing:-.04em;line-height:1.02;
  max-width:18ch}
.cs-band__lead{margin-top:clamp(18px,2.4vw,32px);max-width:62ch;
  font-size:clamp(16px,1.5vw,21px);line-height:1.5;color:rgba(255,255,255,.86)}

/* ---------- the deck's stat cards: bordered box, huge red figure ---------- */
.cs-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(190px, 100%), 1fr));
  gap:clamp(10px,1.2vw,16px);margin-top:clamp(28px,3.6vw,48px)}
.cs-stat{border:1.5px solid var(--line);border-radius:14px;background:var(--white);
  padding:clamp(20px,2.4vw,32px) clamp(16px,2vw,26px);text-align:center;
  transition:transform .18s var(--ease),border-color .18s var(--ease),box-shadow .18s var(--ease)}
.cs-stat__n{display:block;font-size:clamp(34px,4.6vw,70px);font-weight:700;color:var(--red);
  letter-spacing:-.045em;line-height:.92;font-variant-numeric:tabular-nums}
.cs-stat__l{display:block;margin-top:10px;font-size:clamp(13px,1.15vw,17px);font-style:italic;
  font-weight:500;color:var(--ink);letter-spacing:-.01em}
.cs-stat__note{display:block;margin-top:8px;font-size:12px;line-height:1.45;color:var(--muted)}
.cs-band .cs-stat{background:transparent;border-color:rgba(255,255,255,.34)}
.cs-band .cs-stat__n{color:#fff}
.cs-band .cs-stat__l{color:#fff}
.cs-band .cs-stat__note{color:rgba(255,255,255,.7)}
.drk .cs-stat{background:transparent;border-color:var(--d-line)}
.drk .cs-stat__l{color:#fff}
.drk .cs-stat__note{color:var(--d-muted)}

/* ---------- numbered phase bars ---------- */
.cs-phases{margin-top:clamp(26px,3.4vw,44px);display:grid;gap:clamp(14px,1.8vw,24px)}
.cs-phase__bar{display:flex;align-items:center;gap:clamp(12px,1.6vw,22px);
  border:1.5px solid var(--line);border-radius:999px;
  padding:clamp(12px,1.5vw,20px) clamp(18px,2.2vw,30px)}
.cs-phase__n{font-size:clamp(24px,3vw,44px);font-weight:700;color:var(--red);
  letter-spacing:-.04em;line-height:1;flex:none}
.cs-phase__t{flex:1;font-size:clamp(13px,1.45vw,21px);font-weight:600;color:var(--red);
  text-transform:uppercase;letter-spacing:.005em;line-height:1.15}
.cs-phase__arw{flex:none;width:clamp(26px,2.6vw,34px);height:clamp(26px,2.6vw,34px);
  border-radius:50%;display:grid;place-items:center;color:var(--red);
  transition:transform .18s var(--ease),background .18s var(--ease),color .18s var(--ease)}
.cs-phase__arw svg{width:52%;height:52%}
.cs-phase__body{padding:clamp(14px,1.8vw,22px) clamp(18px,2.4vw,34px) 0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(250px, 100%), 1fr));
  gap:clamp(14px,2vw,32px)}
.cs-phase__body p{font-size:clamp(14px,1.2vw,16.5px);line-height:1.6;color:var(--muted);max-width:52ch}
.cs-phase__body strong{color:var(--ink);font-weight:600}
.cs-phase:hover .cs-phase__arw{background:var(--red);color:#fff;transform:translateX(3px)}
.cs-band .cs-phase__bar{border-color:rgba(255,255,255,.4)}
.cs-band .cs-phase__n,.cs-band .cs-phase__t,.cs-band .cs-phase__arw{color:#fff}
.cs-band .cs-phase__body p{color:rgba(255,255,255,.82)}
.cs-band .cs-phase__body strong{color:#fff}
.cs-band .cs-phase:hover .cs-phase__arw{background:#fff;color:var(--red)}
.drk .cs-phase__bar{border-color:var(--d-line)}
.drk .cs-phase__body p{color:var(--d-muted)}
.drk .cs-phase__body strong{color:#fff}
@media(max-width:640px){
  .cs-phase__t{font-size:13px}
  .cs-phase__body{padding-left:6px;padding-right:6px}
}

/* ---------- chapter rail: the film's seven movements ---------- */
/* The section is the scroll spacer; its height is set by JS to whatever the
   pan needs. The stage inside it sticks, so the six cards hold still on
   screen while they travel sideways — panning them without pinning meant the
   section scrolled away underneath and the first cards were never readable. */
.cs-chapters{background:var(--red);color:#fff}
.cs-chapters__stage{padding:clamp(52px,7vw,104px) 0;overflow:hidden}
.cs-chapters.is-pinned .cs-chapters__stage{position:sticky;top:0;
  height:100vh;height:100svh;display:flex;flex-direction:column;justify-content:center}
.cs-chapters__head{width:100%;padding:0 var(--pad);max-width:1368px;
  margin:0 auto clamp(28px,3.6vw,46px)}
.cs-chapters__h{font-size:clamp(26px,4vw,58px);font-weight:700;letter-spacing:-.04em;line-height:1.02}
.cs-chapters__sub{margin-top:14px;max-width:56ch;font-size:clamp(15px,1.35vw,18px);
  line-height:1.55;color:rgba(255,255,255,.84)}
.cs-rail{overflow:hidden}
/* the cards ride on their own track so the page's scroll can pan them with a
   transform. Panning scrollLeft instead would fight Lenis and cannot be
   composited. */
.cs-rail__track{display:flex;gap:clamp(12px,1.4vw,20px);padding:0 var(--pad);
  width:max-content;will-change:transform}
.cs-chap{flex:0 0 clamp(232px,25vw,320px);
  border:1.5px solid rgba(255,255,255,.34);border-radius:14px;
  padding:clamp(18px,2vw,26px);display:flex;flex-direction:column;gap:12px;
  transition:transform .2s var(--ease),background .2s var(--ease)}
.cs-chap:hover{background:rgba(0,0,0,.16)}
.cs-chap__n{display:inline-block;align-self:flex-start;background:var(--black);color:#fff;
  font-size:11.5px;font-weight:600;letter-spacing:.1em;padding:5px 11px;border-radius:4px}
.cs-chap__t{font-size:clamp(17px,1.7vw,23px);font-weight:600;letter-spacing:-.02em;line-height:1.15}
.cs-chap__p{font-size:14px;line-height:1.55;color:rgba(255,255,255,.8)}
/* progress line — reads as the arc being traversed, not as a scrollbar */
.cs-rail__prog{width:100%;max-width:1368px;margin:clamp(22px,2.8vw,36px) auto 0;
  padding:0 var(--pad)}
.cs-rail__prog i{display:block;height:2px;background:rgba(255,255,255,.28);
  position:relative;overflow:hidden}
.cs-rail__prog i::after{content:'';position:absolute;inset:0;background:#fff;
  transform:scaleX(var(--p,0));transform-origin:left center}

/* ---------- deliverables triple ---------- */
.cs-deliver{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(210px, 100%), 1fr));
  gap:clamp(1px,.1vw,2px);background:var(--d-line);margin-top:clamp(28px,3.6vw,48px)}
.cs-deliver__cell{background:var(--black);padding:clamp(24px,3vw,44px) clamp(18px,2.2vw,32px)}
.cs-deliver__k{display:block;font-size:clamp(28px,3.4vw,52px);font-weight:700;color:#fff;
  letter-spacing:-.04em;line-height:1}
.cs-deliver__k em{font-style:normal;color:var(--red)}
.cs-deliver__t{display:block;margin-top:14px;font-size:15px;font-weight:600;color:#fff}
.cs-deliver__p{display:block;margin-top:6px;font-size:13.5px;line-height:1.5;color:var(--d-muted)}

/* ---------- browser frame with a self-scrolling screenshot ---------- */
/* Same pin as the chapter rail: the section is the scroll spacer, the stage
   inside it sticks. Without it the screenshot began travelling the moment the
   frame edged into view, and the whole site flew past at ~3px of image per
   pixel scrolled. */
.cs-browser{padding:clamp(40px,5.5vw,80px) var(--pad)}
.cs-browser.is-pinned{padding-top:0;padding-bottom:0}
.cs-browser.is-pinned .cs-browser__stage{position:sticky;top:0;
  height:100vh;height:100svh;display:flex;flex-direction:column;justify-content:center}
/* an explicit window height, so frame + bar + caption always clear the
   locked viewport instead of relying on the 16/10 ratio to happen to fit */
.cs-browser.is-pinned .cs-browser__view{aspect-ratio:auto;height:min(62svh,640px)}
/* width:100% matters once the stage is a flex column — a flex item with
   `margin:0 auto` shrinks to fit its content, and the only in-flow content
   here is the URL text, so the frame collapsed to ~185px. */
.cs-browser__frame{width:100%;max-width:1080px;margin:0 auto;border-radius:14px;overflow:hidden;
  background:#fff;border:1px solid var(--line);box-shadow:0 30px 80px rgba(0,0,0,.16)}
.cs-browser__bar{display:flex;align-items:center;gap:7px;padding:12px 16px;
  background:var(--grey);border-bottom:1px solid var(--line)}
.cs-browser__bar i{width:10px;height:10px;border-radius:50%;background:rgba(0,0,0,.16);flex:none}
.cs-browser__url{margin-left:12px;font-size:12px;color:var(--muted);letter-spacing:.01em}
.cs-browser__view{position:relative;overflow:hidden;aspect-ratio:16/10;background:var(--grey)}
.cs-browser__view img{position:absolute;top:0;left:0;width:100%;height:auto;
  will-change:transform;display:block}
.cs-browser__cap{display:block;width:100%;max-width:1080px;margin:16px auto 0;font-size:13px;
  line-height:1.55;color:var(--muted)}

/* ---------- asymmetric image mosaic ---------- */
.cs-mosaic{padding:clamp(6px,1vw,14px) var(--pad);display:grid;
  grid-template-columns:repeat(6,1fr);gap:clamp(8px,1vw,14px)}
.cs-mosaic figure{border-radius:12px;overflow:hidden;background:var(--grey);margin:0}
.cs-mosaic figure img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .8s var(--ease)}
.cs-mosaic figure:hover img{transform:scale(1.04)}
.cs-mosaic .m-wide{grid-column:span 4;aspect-ratio:16/9}
.cs-mosaic .m-tall{grid-column:span 2;aspect-ratio:3/4}
.cs-mosaic .m-half{grid-column:span 3;aspect-ratio:4/3}
.cs-mosaic .m-third{grid-column:span 2;aspect-ratio:1/1}
.cs-mosaic .m-full{grid-column:span 6;aspect-ratio:21/9}
@media(max-width:760px){
  .cs-mosaic{grid-template-columns:repeat(2,1fr)}
  .cs-mosaic .m-wide,.cs-mosaic .m-half,.cs-mosaic .m-full{grid-column:span 2}
  .cs-mosaic .m-tall,.cs-mosaic .m-third{grid-column:span 1}
}

/* ---------- funnel: three narrowing stages ---------- */
.cs-funnel{margin-top:clamp(28px,3.6vw,48px);display:grid;gap:clamp(10px,1.2vw,16px)}
.cs-funnel__row{display:flex;align-items:center;gap:clamp(14px,2vw,28px)}
.cs-funnel__track{flex:1;height:clamp(58px,7vw,96px);position:relative}
.cs-funnel__fill{position:absolute;top:0;bottom:0;left:0;width:var(--w,100%);
  background:var(--red);border-radius:10px;display:flex;align-items:center;
  padding:0 clamp(16px,2vw,28px);gap:clamp(12px,1.6vw,20px);will-change:transform}
.cs-funnel__row:nth-child(2) .cs-funnel__fill{background:#c4171d}
.cs-funnel__row:nth-child(3) .cs-funnel__fill{background:#8d1116}
.cs-funnel__in{display:flex;align-items:baseline;gap:clamp(10px,1.4vw,18px);
  color:#fff;white-space:nowrap;overflow:hidden}
.cs-funnel__n{font-size:clamp(20px,2.4vw,36px);font-weight:700;letter-spacing:-.04em;flex:none}
.cs-funnel__t{font-size:clamp(12px,1.25vw,18px);font-weight:600;text-transform:uppercase;
  letter-spacing:.02em;overflow:hidden;text-overflow:ellipsis}
.cs-funnel__side{flex:0 0 clamp(150px,22%,280px);font-size:13.5px;line-height:1.5;
  color:var(--muted)}
.drk .cs-funnel__side{color:var(--d-muted)}
@media(max-width:760px){
  .cs-funnel__row{flex-direction:column;align-items:stretch;gap:8px}
  .cs-funnel__side{flex:none}
  /* flex:1 resolves to flex-basis:0 against the main axis. Once the row turns
     into a column that main axis is the height, so the track collapsed to
     nothing and took the bar with it. Opt the track out of flexing here and
     let its own height stand. */
  .cs-funnel__track{flex:none}
  /* the narrowing shape is the desktop story; on a stacked column it would
     just truncate the stage labels, so every bar goes full width */
  .cs-funnel__fill{width:100%!important}
}

/* ---------- pull statement, big and short ---------- */
.cs-pull{padding:clamp(50px,7vw,100px) var(--pad)}
.cs-pull__t{max-width:22ch;font-size:clamp(28px,4.6vw,74px);font-weight:600;
  letter-spacing:-.042em;line-height:1.04}
.cs-pull__t em{font-style:normal;color:var(--red)}

/* ---------- range ticker: proof of breadth, in motion ---------- */
.cs-ticker{overflow:hidden;border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:clamp(16px,2vw,26px) 0;background:var(--white)}
.drk .cs-ticker,.cs-ticker.drk{background:var(--black);border-color:var(--d-line)}
.cs-ticker__row{display:flex;width:max-content;gap:clamp(22px,3vw,48px);
  animation:cs-ticker-run 44s linear infinite}
.cs-ticker span{font-size:clamp(15px,1.7vw,24px);font-weight:500;letter-spacing:-.02em;
  color:var(--muted);white-space:nowrap;display:flex;align-items:center;gap:clamp(22px,3vw,48px)}
.cs-ticker span::after{content:'';width:6px;height:6px;border-radius:50%;background:var(--red);flex:none}
.cs-ticker.drk span{color:var(--d-muted)}
@keyframes cs-ticker-run{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
.cs-ticker:hover .cs-ticker__row{animation-play-state:paused}

/* ---------- reduced motion: keep the meaning, drop the movement ---------- */
@media (prefers-reduced-motion: reduce){
  /* the ticker is the one loop worth keeping — it carries content that
     scrolls out of view — so slow it rather than freezing it mid-word */
  .cs-ticker__row{animation-duration:200s!important}
  .cs-plate__bg{transform:scale(1)!important}
  .cs-browser__view img{transform:none!important}
  /* the chapters are only reachable by the scroll-driven pan, which is off
     here — hand the rail back its own scrollbar so all six stay readable */
  .cs-rail{overflow-x:auto}
  .cs-rail__track{transform:none!important}
  /* no pan means no reason to hold the section on screen */
  .cs-chapters.is-pinned .cs-chapters__stage{position:static;height:auto}
  .cs-browser.is-pinned .cs-browser__stage{position:static;height:auto}
  .cs-browser.is-pinned .cs-browser__view{aspect-ratio:16/10;height:auto}
}

/* ---------- touch: no latched hover states ---------- */
@media (hover:none),(pointer:coarse){
  .cs-mosaic figure:hover img{transform:none}
  .cs-phase:hover .cs-phase__arw{background:none;color:var(--red);transform:none}
  .cs-band .cs-phase:hover .cs-phase__arw{background:none;color:#fff}
  .cs-chap:hover{background:none}
}

/* ============================================================
   §CASE STUDY GRID — the full index, on the Work page
   The Work page listed three case studies as text rows with no
   imagery at all, while three more (the brand identities) lived
   only on the Branding page. This is the whole set in one grid,
   led by the pictures.
   ============================================================ */
.csgrid{display:grid;grid-template-columns:repeat(2,1fr);
  gap:clamp(20px,2.6vw,40px);margin-top:clamp(28px,3.6vw,48px)}
@media(max-width:860px){.csgrid{grid-template-columns:1fr;gap:clamp(22px,4vw,34px)}}

.cscard{display:flex;flex-direction:column}
/* The lift lives on the cover, not the card. .cscard carries .reveal-up, and
   that entrance leaves a GSAP *inline* transform behind — an inline style
   outranks any class rule, so a :hover transform on the card itself is simply
   never applied. The figure has no inline transform, so it can be moved. */
.cscard__cover{position:relative;border-radius:14px;overflow:hidden;
  background:var(--grey);aspect-ratio:16/10;margin:0;
  transition:transform .2s var(--ease),box-shadow .2s var(--ease)}
.cscard__cover img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .55s var(--ease)}
.cscard__tag{position:absolute;top:14px;left:14px;z-index:2;
  background:var(--red);color:#fff;font-size:11px;font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;padding:6px 11px;border-radius:999px}
.cscard__cl{display:block;margin-top:clamp(16px,1.8vw,22px);
  font-size:12.5px;color:var(--muted);font-weight:500}
.cscard__h{margin-top:10px;font-size:clamp(21px,2.2vw,32px);font-weight:600;
  letter-spacing:-.03em;line-height:1.08}
.cscard__h span{color:var(--muted);font-weight:500}
.cscard__p{margin-top:12px;font-size:14.5px;line-height:1.6;color:var(--muted);max-width:52ch}
.cscard__facts{display:flex;flex-wrap:wrap;gap:6px 20px;margin-top:auto;
  padding-top:clamp(16px,2vw,22px);font-size:12.5px;color:var(--muted)}
.cscard__facts span{display:inline-flex;align-items:baseline;gap:6px}
.cscard__facts b{color:var(--red);font-size:clamp(17px,1.7vw,22px);font-weight:700;
  letter-spacing:-.02em}
.cscard__go{display:inline-flex;align-items:center;gap:9px;margin-top:clamp(16px,1.8vw,22px);
  font-size:13px;font-weight:600;color:var(--ink)}
.cscard__go i{width:26px;height:26px;border-radius:50%;border:1.5px solid var(--line);
  display:grid;place-items:center;font-style:normal;font-size:11px;
  transition:transform .18s var(--ease),background .18s var(--ease),
             color .18s var(--ease),border-color .18s var(--ease)}

.cscard:hover .cscard__cover{transform:translateY(-5px);
  box-shadow:0 18px 42px rgba(0,0,0,.14)}
.cscard:hover .cscard__cover img{transform:scale(1.05)}
.cscard:hover .cscard__go i{background:var(--red);border-color:var(--red);
  color:#fff;transform:translate(2px,-2px)}

/* dark variant, for the studio page should it ever reuse this */
.drk .cscard__h,.drk .cscard__go{color:var(--d-text)}
.drk .cscard__cl,.drk .cscard__p,.drk .cscard__facts{color:var(--d-muted)}
.drk .cscard__go i{border-color:var(--d-line)}
.drk .cscard__cover{background:rgba(255,255,255,.06)}

/* touch: the lift and zoom latch after a tap, so drop them there */
@media (hover:none),(pointer:coarse){
  .cscard:hover .cscard__cover{transform:none;box-shadow:none}
  .cscard:hover .cscard__cover img{transform:none}
  .cscard:hover .cscard__go i{background:none;border-color:var(--line);
    color:inherit;transform:none}
}

/* ============================================================
   §FAQ — answer-engine blocks
   Question-phrased headings with a direct answer underneath, so
   search and AI engines can lift a clean 40–60 word response.
   Built on <details> so the answer text ships in the HTML and is
   readable with JavaScript disabled — collapsing is presentation
   only, never a content gate.
   ============================================================ */
.faq{padding:clamp(58px,8vw,112px) var(--pad)}
.faq__grid{display:grid;grid-template-columns:.44fr 1fr;gap:clamp(26px,5vw,80px);align-items:start}
.faq__h{font-size:clamp(23px,2.9vw,40px);font-weight:600;letter-spacing:-.03em;line-height:1.05}
.faq__h em{font-style:normal;color:var(--muted)}
.faq__list{display:flex;flex-direction:column;border-top:1px solid var(--line)}
.faq__item{border-bottom:1px solid var(--line)}
.faq__item summary{list-style:none;cursor:pointer;padding:clamp(18px,2.2vw,26px) 0;
  display:flex;align-items:flex-start;gap:18px;
  font-size:clamp(16px,1.7vw,21px);font-weight:500;letter-spacing:-.02em;line-height:1.3;
  transition:color .18s var(--ease)}
.faq__item summary::-webkit-details-marker{display:none}
.faq__item summary:hover{color:var(--red)}
.faq__item summary::after{content:'';flex:none;width:12px;height:12px;margin-left:auto;
  margin-top:.34em;border-right:1.6px solid currentColor;border-bottom:1.6px solid currentColor;
  transform:rotate(45deg);transition:transform .2s var(--ease)}
.faq__item[open] summary::after{transform:rotate(-135deg)}
.faq__a{padding:0 0 clamp(20px,2.4vw,28px);max-width:68ch}
.faq__a p{font-size:clamp(14.5px,1.2vw,16.5px);line-height:1.62;color:var(--muted)}
.faq__a p + p{margin-top:.9em}
.faq__a strong{color:var(--ink);font-weight:600}
.drk .faq__a p{color:var(--d-muted)}
.drk .faq__a strong{color:#fff}
.drk .faq__list,.drk .faq__item{border-color:var(--d-line)}
@media(max-width:860px){.faq__grid{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){.faq__item summary::after{transition:none}}

/* ============================================================
   §CONSENT BAR — written by js/tracking.js, and only when there is
   actually a tag to consent to. Decline is the same size and weight
   as Accept: an EEA-valid banner cannot make refusing harder than
   agreeing, and a greyed-out "Decline" is the usual way sites fail
   that test.
   ============================================================ */
.cbar{
  position:fixed;left:var(--pad);right:var(--pad);bottom:var(--pad);z-index:900;
  display:flex;align-items:center;gap:clamp(14px,2.4vw,32px);flex-wrap:wrap;
  max-width:760px;margin-inline:auto;
  padding:clamp(16px,1.8vw,22px) clamp(18px,2vw,26px);
  background:var(--black);color:#fff;border-radius:14px;
  box-shadow:0 18px 50px rgba(0,0,0,.32);
  opacity:0;transform:translateY(14px);
  transition:opacity .32s var(--ease),transform .32s var(--ease);
}
.cbar.is-in{opacity:1;transform:translateY(0)}
.cbar.is-out{opacity:0;transform:translateY(14px)}
.cbar__t{flex:1 1 320px;min-width:0;font-size:13.5px;line-height:1.55;color:rgba(255,255,255,.8)}
.cbar__t a{color:#fff;text-decoration:underline;text-underline-offset:2px}
.cbar__b{display:flex;gap:9px;flex:0 0 auto}
.cbar__btn{
  font:inherit;font-size:13.5px;font-weight:500;letter-spacing:-.01em;
  padding:11px 20px;border-radius:100px;cursor:pointer;white-space:nowrap;
  min-height:44px;
  background:transparent;color:#fff;border:1px solid rgba(255,255,255,.34);
  transition:background .18s var(--ease),border-color .18s var(--ease),color .18s var(--ease)}
.cbar__btn:hover{border-color:#fff}
.cbar__btn--y{background:#fff;color:var(--ink);border-color:#fff}
.cbar__btn--y:hover{background:var(--red);border-color:var(--red);color:#fff}
@media(max-width:600px){
  .cbar{flex-direction:column;align-items:stretch;gap:12px}
  .cbar__b{display:grid;grid-template-columns:1fr 1fr}
  .cbar__btn{width:100%}
}
@media(prefers-reduced-motion:reduce){
  .cbar{transition:opacity .2s linear;transform:none}
  .cbar.is-in,.cbar.is-out{transform:none}
}

/* ============================================================
   §SITEMAP — the human-readable index at /sitemap.html
   Grouped by intent rather than alphabetically, so the page is
   useful to a reader as well as a crawler.
   ============================================================ */
.smap{padding:clamp(30px,4vw,56px) var(--pad) clamp(58px,8vw,112px)}
.smap__group{padding-top:clamp(30px,4vw,52px);border-top:1px solid var(--line)}
.smap__group + .smap__group{margin-top:clamp(30px,4vw,52px)}
.smap__head{margin-bottom:clamp(18px,2.2vw,28px)}
.smap__head h2{font-size:clamp(21px,2.5vw,34px);font-weight:600;letter-spacing:-.03em;line-height:1.05}
.smap__head p{margin-top:8px;font-size:14.5px;line-height:1.55;color:var(--muted)}
.smap__list{list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(min(290px, 100%), 1fr));gap:0 clamp(20px,3vw,48px)}
.smap__row{border-top:1px solid var(--line)}
.smap__row a{display:flex;flex-direction:column;gap:4px;padding:clamp(13px,1.5vw,17px) 0;
  transition:padding-left .18s var(--ease)}
.smap__row a:hover{padding-left:8px}
.smap__t{font-size:clamp(15px,1.5vw,18px);font-weight:500;letter-spacing:-.02em;line-height:1.25}
.smap__row a:hover .smap__t{color:var(--red)}
.smap__d{font-size:13px;line-height:1.45;color:var(--muted)}
@media (hover:none),(pointer:coarse){
  .smap__row a:hover{padding-left:0}
  .smap__row a:hover .smap__t{color:inherit}
}

/* ============================================================
   §PRERENDER — static first rows of each gallery
   These exist so the portfolio is present in the HTML for clients
   that never run the JS. buildGallery() replaces them on load, so
   they are only ever seen without JavaScript or during a slow
   first paint — styled to resemble what replaces them, so the
   handover does not flash.
   ============================================================ */
.prerender-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(220px, 100%), 1fr));
  gap:clamp(10px,1.3vw,18px)}
.prerender-tile{margin:0;border-radius:12px;overflow:hidden;background:var(--grey);position:relative}
.prerender-tile img{width:100%;height:100%;object-fit:cover;display:block;aspect-ratio:9/16}
.prerender-tile figcaption{position:absolute;left:12px;right:12px;bottom:12px;color:#fff;
  font-size:12.5px;font-weight:500;text-shadow:0 1px 8px rgba(0,0,0,.8)}
.prerender-list{list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(min(240px, 100%), 1fr));gap:0 clamp(18px,2.4vw,36px)}
.prerender-list li{padding:11px 0;border-top:1px solid var(--line);
  font-size:14.5px;letter-spacing:-.01em;color:var(--ink)}
.drk .prerender-list li,.videowall .prerender-list li{border-color:var(--d-line);color:var(--d-text)}
.reelwall__body .prerender-tile figcaption{font-size:12px}

/* ============================================================
   §SERVICE BODY — the readable half of a service page
   The galleries carry the proof; this carries the argument, the
   process and the sector coverage. Sits between the work and the
   FAQ so the page still opens on the pictures.
   ============================================================ */
.svc{padding:clamp(52px,7vw,100px) var(--pad)}
.svc + .faq{padding-top:0}
.svc__grid{display:grid;grid-template-columns:.44fr 1fr;gap:clamp(26px,5vw,80px);align-items:start}
.svc__h{font-size:clamp(23px,2.9vw,40px);font-weight:600;letter-spacing:-.03em;line-height:1.05}
.svc__h em{font-style:normal;color:var(--muted)}
/* min-width:0 matters: a grid item defaults to min-width:auto, which refuses
   to shrink below its widest content. With a min-width table inside, that
   forces the whole column wider than the screen and the PAGE scrolls
   sideways instead of the table. Zero lets the column shrink so the
   table's own overflow-x actually takes over. */
.svc__body{max-width:70ch;min-width:0}
.svc__grid > *{min-width:0}
.svc__body > p{font-size:clamp(15px,1.3vw,17.5px);line-height:1.65;color:var(--muted)}
.svc__body > p + p{margin-top:1.05em}
.svc__body strong{color:var(--ink);font-weight:600}
.svc__body h3{font-size:clamp(17px,1.7vw,22px);font-weight:600;letter-spacing:-.02em;
  line-height:1.2;color:var(--ink);margin:clamp(28px,3.2vw,42px) 0 .55em}
.svc__body ul{margin:.4em 0 0;padding:0;list-style:none;
  display:grid;gap:0;border-top:1px solid var(--line)}
.svc__body ul li{padding:11px 0 11px 26px;border-bottom:1px solid var(--line);position:relative;
  font-size:clamp(14px,1.2vw,16px);line-height:1.55;color:var(--muted)}
.svc__body ul li::before{content:'';position:absolute;left:2px;top:1.02em;
  width:9px;height:1.5px;background:var(--red)}
.svc__body ul li b{color:var(--ink);font-weight:600}
/* Numbered process steps. Same hairline rows as the ul above, but the marker
   is the step number — the order is the information here, so it is shown
   rather than implied by a bullet. Counter, not <ol> markers, so the digit can
   take the accent and sit on the text's first baseline. */
.svc__body ol{margin:.4em 0 0;padding:0;list-style:none;counter-reset:svcstep;
  display:grid;gap:0;border-top:1px solid var(--line)}
.svc__body ol li{counter-increment:svcstep;position:relative;
  padding:12px 0 12px 34px;border-bottom:1px solid var(--line);
  font-size:clamp(14px,1.2vw,16px);line-height:1.55;color:var(--muted)}
.svc__body ol li::before{content:counter(svcstep,decimal-leading-zero);
  position:absolute;left:0;top:12px;font-size:12px;font-weight:600;
  color:var(--red);font-variant-numeric:tabular-nums;letter-spacing:.02em}
.svc__body ol li b{color:var(--ink);font-weight:600}

/* Spec tables. Wide content scrolls inside its own box so the page body never
   scrolls sideways on a phone. */
.svc__table{margin:.9em 0 0;overflow-x:auto;-webkit-overflow-scrolling:touch}
.svc__table table{border-collapse:collapse;width:100%;min-width:460px;
  font-size:clamp(13.5px,1.15vw,15.5px);line-height:1.5}
.svc__table th,.svc__table td{text-align:left;padding:11px 16px 11px 0;
  border-bottom:1px solid var(--line);vertical-align:top;color:var(--muted)}
.svc__table th{color:var(--ink);font-weight:600;font-size:12px;
  letter-spacing:.06em;text-transform:uppercase;border-bottom-color:var(--ink)}
.svc__table td:first-child{color:var(--ink);font-weight:500;white-space:nowrap}
.svc__table td{font-variant-numeric:tabular-nums}

.svc__note{margin-top:clamp(26px,3vw,38px);padding-left:16px;border-left:2px solid var(--red);
  font-size:clamp(14.5px,1.25vw,16.5px);line-height:1.6;color:var(--ink-2,var(--muted))}
.svc__note b{color:var(--ink);font-weight:600}
@media(max-width:860px){.svc__grid{grid-template-columns:1fr}}

/* ============================================================
   §LEADERSHIP — a named person on the About page
   E-E-A-T rests on identifiable people. One line, set as a byline
   rather than a team grid, so it reads as attribution instead of
   a staff directory.
   ============================================================ */
.lead-by{display:flex;align-items:center;gap:clamp(14px,1.6vw,20px);
  margin-top:clamp(34px,4.5vw,56px);padding-top:clamp(22px,2.8vw,32px);
  border-top:1px solid var(--line);max-width:56ch}
.drk .lead-by{border-color:var(--d-line)}
.lead-by__mark{width:46px;height:46px;border-radius:100px;flex:none;display:grid;place-items:center;
  background:var(--red);color:#fff;font-weight:700;font-size:16px;letter-spacing:-.02em}
.lead-by__t strong{display:block;font-size:clamp(15px,1.35vw,17px);font-weight:600;letter-spacing:-.02em}
.lead-by__t span{display:block;margin-top:3px;font-size:13px;color:var(--muted);line-height:1.45}
.drk .lead-by__t span{color:var(--d-muted)}


/* ============================================================
   VIDEO BAND - a full-width cinematic strip between sections
   ------------------------------------------------------------
   The clips are 1280x400, i.e. 3.2:1. The frame is held very
   slightly FLATTER than that, and that difference is the only
   room the parallax has to move in.

   The media element is sized so its box aspect equals the clip's
   own aspect exactly. That is what stops the sides being cropped:
   the element is always precisely the frame's width, so cover has
   nothing to trim horizontally and only ever gives up a sliver of
   height - which is the headroom the drift travels through.

   The still stays underneath as the poster layer, so the band is
   never an empty box.
   ============================================================ */
.vband{margin:clamp(40px,5.5vw,84px) 0}
/* This band sits in its own <section>, and section{} already carries
   70-120px of padding top and bottom. Without this it stacks with the
   margin above and the strip floats in a sea of white. */
.vband-sec{padding-top:0;padding-bottom:0}

.vband__frame{
  --clip-ar:3.2;              /* the source: 1280x400 */
  --band-ar:3.5556;           /* the frame: flatter, to create headroom */
  --media-h:calc(var(--band-ar) / var(--clip-ar) * 100%);
  position:relative;overflow:hidden;
  border-radius:clamp(14px,1.6vw,22px);
  aspect-ratio:var(--band-ar);
  background:#0d0d0f;
  box-shadow:0 26px 70px rgba(0,0,0,.18), 0 4px 14px rgba(0,0,0,.08);
}
.vband__frame > img,
.vband__frame > video{
  position:absolute;left:0;width:100%;
  height:var(--media-h);
  top:calc((100% - var(--media-h)) / 2);
  object-fit:cover;
}
.vband__frame > video{opacity:0;transition:opacity .6s var(--ease)}
.vband__frame > video.is-live{opacity:1}

/* Sound toggle. The clips are muted so they can autoplay at all; this is
   the only way back to the audio, so it stays visible rather than
   appearing on hover - a control nobody can find is not a control. */
.vband__sound{
  position:absolute;right:clamp(12px,1.4vw,20px);bottom:clamp(12px,1.4vw,20px);
  z-index:2;display:grid;place-items:center;
  width:clamp(38px,3.4vw,46px);height:clamp(38px,3.4vw,46px);
  border:0;border-radius:50%;cursor:pointer;padding:0;
  color:#fff;background:rgba(12,12,14,.55);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  box-shadow:0 2px 12px rgba(0,0,0,.35);
  transition:background .25s var(--ease),transform .25s var(--ease);
}
.vband__sound:hover{background:rgba(12,12,14,.78);transform:scale(1.06)}
/* The visible circle is ~38px on a phone, under the 44px a finger wants.
   The band is only ~105px tall there, so grow the HIT area rather than the
   button - the inset stays within the frame, so nothing gets clipped. */
.vband__sound::after{content:'';position:absolute;inset:-6px;border-radius:50%}
.vband__sound:focus-visible{outline:2px solid #fff;outline-offset:3px}
.vband__sound svg{width:50%;height:50%;display:block;fill:none;
  stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* one icon at a time: the slash shows while muted, the waves once audible */
.vband__sound .i-on{display:none}
.vband__sound[aria-pressed="true"] .i-on{display:block}
.vband__sound[aria-pressed="true"] .i-off{display:none}

@media (max-width:760px){
  /* On a phone the frame drops to the clip's own shape. A flatter frame
     would have to crop the sides to fill, and full width matters more here
     than the parallax - which the script then skips, since there is no
     longer any headroom to move through. */
  .vband__frame{--band-ar:var(--clip-ar)}
}

/* Motion off: no parallax, no fade-in, no audio control to chase.
   The poster still carries the band, so nothing is lost but the movement. */
@media (prefers-reduced-motion:reduce){
  .vband__frame > video,
  .vband__sound{display:none}
}
