/* ═══════════════════════════════════════════════════════════
   Studio Zero/In — landing (v4 · antimatter redesign)
   Light-grey ground, near-black rooms, one acid accent.
   ═══════════════════════════════════════════════════════════ */

/* ── tokens ────────────────────────────────────────────── */
:root{
  /* ground scale — legacy names kept so every component and the
     subpages keep resolving; only the values changed */
  --bone:      #E8E8E8;   /* main ground */
  --bone-2:    #F0F0EF;   /* lifted band */
  --sand:      #DCDCDB;   /* recessed band / media placeholder */
  --sand-warm: #E2E2E1;   /* between the two */
  --ink:       #171717;
  --ink-2:     #55554F;
  --ink-3:     #676762;
  --dark:      #171717;   /* dark rooms: services, footer, menu */
  --dark-2:    #171717;
  --paper:     #F5F5F5;   /* light type on dark */

  --accent:      #D7FF2E; /* the acid — fills, chips, dark rooms only */
  --accent-lt:   #D7FF2E; /* legacy alias — on-dark accent */
  --accent-deep: #55650A; /* the acid darkened to read as ink on light (≥4.5:1) */

  --line:      color-mix(in srgb, var(--ink) 14%, transparent);
  --line-d:    color-mix(in srgb, var(--paper) 14%, transparent);
  --gridline:  color-mix(in srgb, var(--ink) 6%, transparent);
  --gridmark:  color-mix(in srgb, var(--ink) 22%, transparent);

  /* legacy gradient tokens — collapsed to flats so every old
     consumer (underlines, fills, dark surfaces) lands on-palette */
  --gradient:       linear-gradient(var(--accent), var(--accent));
  --gradient-vivid: linear-gradient(var(--accent), var(--accent));
  --gradient-mesh:  linear-gradient(180deg, #171717 0%, #171717 100%);
  --mesh-scrim:     linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0));

  --sans:  'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --serif: 'Manrope', Georgia, serif;   /* the serif retired with v3 */
  /* The micro-label voice. Manrope rather than a monospace, so the whole
     site sits in one typeface; the labels keep their identity from the
     uppercase and the tracking instead of from fixed-width letterforms.
     --logo-font below is a separate matter: that one has to stay JetBrains
     Mono because the wordmark is drawn in it. */
  --mono:  'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* the wordmark's own face; --cap is JetBrains Mono's capHeight (730/1000),
     so a logo set to calc(<font-size> * var(--cap)) matches the cap height
     of type at that size exactly */
  --logo-font: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;
  --cap: .73;

  --label: .62rem;                      /* every mono micro-label */
  --body:  clamp(.92rem,1.05vw,1rem);   /* every run of body copy */

  --pad:  clamp(1.15rem, 4.2vw, 4.5rem);
  --col:  calc((100vw - 2 * var(--pad)) / 4);  /* one grid column */
  --gap:  clamp(1rem, 2.2vw, 2rem);
  --seam: 2px;

  --e-out: cubic-bezier(.16, 1, .3, 1);
  --e-io:  cubic-bezier(.65, .05, .2, 1);
}

/* ── reset ─────────────────────────────────────────────── */
*,*::before,*::after{ box-sizing:border-box; margin:0; padding:0 }
html{ -webkit-text-size-adjust:100%; scroll-behavior:auto }
body{
  background:var(--bone);
  color:var(--ink);
  font-family:var(--sans);
  font-size:16px;
  line-height:1.5;
  overflow-x:clip;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  font-synthesis:none;
}
img,canvas,svg{ display:block; max-width:100% }
a{ color:inherit; text-decoration:none }
button{ font:inherit; color:inherit; background:none; border:0; cursor:pointer }
ul,ol{ list-style:none }
h1,h2,h3,h4{ font-weight:600; line-height:1 }
::selection{ background:var(--accent); color:var(--ink) }
:focus-visible{ outline:2px solid var(--ink); outline-offset:4px; border-radius:2px }
/* ink vanishes on the dark rooms — the acid takes over there */
.services :focus-visible, .foot :focus-visible,
.menu :focus-visible, .reel :focus-visible{ outline-color:var(--accent) }

.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ── shared type ───────────────────────────────────────── */
.eyebrow{
  font-family:var(--mono);
  font-size:var(--label);
  letter-spacing:.18em;
  color:var(--ink-3);
}
/* The accent word inside display heads. It is set in caps like the rest
   of its line — the acid chip alone carries the accent. The hero opts
   out of the chip below and uses acid type instead. */
.hero__h i, .feature__h i, .cta__h i, .pj-title i, .grad-text{
  font-style:normal; color:var(--ink);
  background:var(--accent);
  padding:0 .08em;
  -webkit-box-decoration-break:clone; box-decoration-break:clone;
}
/* Project names opt out of the caps and set as written, so the name reads
   as a name against the capped line it sits on. Same rule on the project
   page, so a title is lettered the same in both places. */
.feature__h i, .pj-title i{ text-transform:none;
  /* pull the acid chip left by its own padding so the WORD lines up
     with the client name above; the highlight itself runs out. */
  margin-left:-.08em }

/* ── section header strip — "01 / LABEL …… +" ──────────── */
.shead{
  display:flex; align-items:center; gap:.7rem;
  padding-bottom:.85rem; margin-bottom:clamp(1.6rem,3.5vw,2.6rem);
  border-bottom:1px solid var(--line);
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.18em; color:var(--ink-2);
}
.shead__idx{ color:var(--ink); font-weight:500 }
.shead__slash{ color:var(--ink-3) }
.shead__t{ color:var(--ink) }
.shead__n{ color:var(--ink-3); margin-left:.4rem }
/* dark-room variant */
.shead--dark{ border-bottom-color:var(--line-d); color:var(--paper) }
.shead--dark .shead__idx, .shead--dark .shead__t{ color:var(--paper) }
.shead--dark .shead__idx{ color:var(--accent) }
.shead--dark .shead__slash, .shead--dark .shead__n{ color:color-mix(in srgb, var(--paper) 55%, transparent) }

/* line-mask reveal wrapper (JS fills in the inner spans) */
[data-lines] .l{ display:block; overflow:hidden;
                 padding-bottom:.22em; margin-bottom:-.22em;
                 padding-right:.08em;  margin-right:-.08em }
[data-lines] .w{ display:inline-block; overflow:hidden; vertical-align:top;
                 padding-bottom:.22em; margin-bottom:-.22em;
                 padding-right:.08em;  margin-right:-.08em }
[data-lines] .w > .wi{ display:inline-block; will-change:transform }

/* ── page column grid ────────────────────────────────────
   Drawn per section rather than as one fixed overlay. Two reasons: a
   z-index:-1 pseudo paints above its section's own background but below
   every child, so images and video cover the rules instead of being
   crossed by them; and each section owns its --gridline, so the dark
   rooms invert to light rules instead of disappearing into the black. */
main > section, .foot{ position:relative; isolation:isolate }
main > section::before, .foot::before{
  content:''; position:absolute; inset:0 var(--pad); z-index:-1;
  pointer-events:none;
  border-inline:1px solid var(--gridline);
  background:
    linear-gradient(90deg, var(--gridline), var(--gridline)) 25% 0 / 1px 100% no-repeat,
    linear-gradient(90deg, var(--gridline), var(--gridline)) 50% 0 / 1px 100% no-repeat,
    linear-gradient(90deg, var(--gridline), var(--gridline)) 75% 0 / 1px 100% no-repeat;
}
/* Registration marks: a small + where each section's top edge crosses the
   left and right rules, so every new segment announces itself. Its own
   layer because it has to sit 5px proud of the rule box on both sides —
   centred on the rule, the arms would be clipped by the box that draws
   it. The hero is excluded: its ::after already carries the over-video
   grid, and its top is under the nav anyway. */
main > section:not(.hero)::after, .foot::after{
  content:''; position:absolute; z-index:-1; pointer-events:none;
  left:calc(var(--pad) - 5px); right:calc(var(--pad) - 5px);
  top:25px; height:11px;
  background:
    linear-gradient(var(--gridmark), var(--gridmark)) left 0    top 5px / 11px 1px no-repeat,
    linear-gradient(var(--gridmark), var(--gridmark)) left 5px  top 0   / 1px 11px no-repeat,
    linear-gradient(var(--gridmark), var(--gridmark)) right 0   top 5px / 11px 1px no-repeat,
    linear-gradient(var(--gridmark), var(--gridmark)) right 5px top 0   / 1px 11px no-repeat;
}
/* dark rooms: the ink rule and mark are invisible on near-black, so both flip */
.hero, .services, .foot{
  --gridline:color-mix(in srgb, var(--paper) 11%, transparent);
  --gridmark:color-mix(in srgb, var(--paper) 30%, transparent);
}

/* ── foot glass ──────────────────────────────────────────
   A shallow pane of frosted glass along the bottom edge, the quiet
   counterpart to the frosted chips at the top. Masked so only the last
   few pixels are fully blurred and it dissolves upward into the page.
   It stands down over the footer — blurring the contact details you have
   just scrolled to would be the effect working against the content.
   (body.at-foot is set by footGlass() in app.js.) */
.footglass{
  position:fixed; inset:auto 0 0 0; z-index:49;
  height:clamp(40px, 5.5vh, 68px);
  pointer-events:none;
  -webkit-backdrop-filter:blur(7px); backdrop-filter:blur(7px);
  -webkit-mask-image:linear-gradient(180deg, transparent 0%, #000 88%);
          mask-image:linear-gradient(180deg, transparent 0%, #000 88%);
  opacity:1; transition:opacity .45s var(--e-out);
}
body.at-foot .footglass{ opacity:0 }
body.reel-open .footglass{ opacity:0 }

/* ── film grain ────────────────────────────────────────── */
.grain{
  position:fixed; inset:-120px; z-index:9998; pointer-events:none;
  opacity:.3; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.34'/%3E%3C/svg%3E");
  animation:grain 700ms steps(2,end) infinite;
}
@keyframes grain{
  0%  { transform:translate(0,0) }
  50% { transform:translate(-14px,9px) }
  100%{ transform:translate(8px,-11px) }
}

/* ── nav — v3's floating chip bar, in frosted glass ─────
   The bar itself is inert: it is only a positioning frame, so the
   footage stays clickable between the chips. Each chip carries its own
   material, which is why nothing has to change when the bar crosses
   from the dark hero onto the light page. */
.nav{
  position:fixed; z-index:100; top:0; left:0; right:0;
  padding:var(--pad);
  display:flex; align-items:flex-start; justify-content:space-between;
  pointer-events:none;
  --chip:2.35rem;              /* one height for every chip in the bar */
  transition:transform .6s var(--e-out);
}
.nav > *{ pointer-events:auto }
.nav.is-hidden{ transform:translateY(-115%) }
body.menu-open .nav{ transform:none }   /* the close button must stay reachable */

/* shared chip material: frosted glass, hairline, ink type */
.brand, .nav__link, .plus{
  background:color-mix(in srgb, #fff 72%, transparent);
  -webkit-backdrop-filter:blur(22px) saturate(1.2);
  backdrop-filter:blur(22px) saturate(1.2);
  border:1px solid color-mix(in srgb, #fff 34%, transparent);
  box-shadow:0 18px 48px -30px rgba(10,10,10,.55);
  color:var(--ink); border-radius:2px;
  transition:background-color .3s var(--e-out), border-color .3s var(--e-out),
             transform .5s var(--e-out);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .brand, .nav__link, .plus{ background:rgba(255,255,255,.9) }
}

/* The mark always sits straight on the page — no chip, in any state. It
   is drawn twice, in the two inks, and cross-faded as the nav passes from
   one room to the next, so the change lands on the section boundary. */
.brand{
  display:inline-flex; align-items:center;
  font-family:var(--logo-font); font-size:var(--label);
  white-space:nowrap;
  background:none; border:0; box-shadow:none; padding:0;
  -webkit-backdrop-filter:none; backdrop-filter:none;
  transition:none;
}
/* --mark is one cap height; the stacked lockup is 3.409x that because it
   carries three lines. The two inks share a viewBox trimmed to the same
   ink box, so they register exactly and the fade shows no drift. */
.brand{ --mark:calc(var(--chip) * .4); position:relative }
.brand__logo{
  width:auto; max-width:none; display:block;
  height:calc(var(--mark) * 3.409);
  transition:opacity .1s linear;    /* near-instant: it follows the page */
}
.brand__logo--dark{ position:absolute; inset:0; opacity:0 }
/* the ink flips with .is-ink, set by navInk() in app.js (see v2.css) */

/* One height for both chips, declared once: the label chip sizes to it
   and the plus takes it as a square, so the two always agree instead of
   each arriving at a height of its own. */
.nav__tools{ display:flex; align-items:center; gap:.4rem }
/* The acid rule under the label is the showreel's call to action — it
   carries the underline the hero row used to. */
.nav__link{
  display:inline-flex; align-items:center;
  height:var(--chip); padding-inline:.8rem;
  font-family:var(--sans); font-size:var(--label); letter-spacing:.14em;
  border-bottom:2px solid var(--accent);
}
.nav__link:hover{
  background:var(--accent); border-color:var(--accent);
  border-bottom-color:var(--ink);
}

/* the plus — the menu trigger, and the site's recurring mark */
.plus{
  width:var(--chip); height:var(--chip); flex:none; position:relative;
}
.plus::before,.plus::after{
  content:''; position:absolute; inset:50% 28%; translate:0 -50%;
  height:1px; background:var(--ink);
}
.plus::after{ rotate:90deg }
.plus:hover{ background:var(--accent); border-color:var(--accent) }
body.menu-open .plus{ transform:rotate(45deg) }

/* ── showreel lightbox ─────────────────────────────────── */
.reel{
  position:fixed; inset:0; z-index:200;
  display:grid; place-items:center;
  padding:clamp(1rem,4vw,3rem);
  opacity:0; transition:opacity .4s var(--e-out);
}
.reel[hidden]{ display:none }
.reel.is-open{ opacity:1 }
.reel__bg{
  position:absolute; inset:0;
  background:rgba(10,10,10,.86);
  -webkit-backdrop-filter:blur(18px); backdrop-filter:blur(18px);
}
.reel__frame{
  position:relative;
  width:min(100%, calc((100vh - 6rem) * 16 / 9));
  aspect-ratio:16/9;
  border-radius:4px; overflow:hidden;
  background:#000;
  box-shadow:0 40px 120px -40px rgba(0,0,0,.8);
  transform:scale(.97); transition:transform .45s var(--e-out);
}
.reel.is-open .reel__frame{ transform:scale(1) }
.reel__player, .reel__player iframe, .reel__player video{
  position:absolute; inset:0; width:100%; height:100%; border:0;
}
.reel__close{
  position:absolute; z-index:2; top:.6rem; right:.6rem;
  width:40px; height:40px; border-radius:2px;
  display:grid; place-items:center;
  background:rgba(255,255,255,.14); color:#fff;
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  transition:background-color .3s var(--e-out), color .3s var(--e-out);
}
.reel__close:hover{ background:var(--accent); color:var(--ink) }
.reel__close svg{ width:18px; height:18px }
body.reel-open{ overflow:hidden }
/* film grain over a fullscreen player reads as a dirty screen */
body.reel-open .grain{ opacity:0 }

/* ── dropdown menu ──────────────────────────────────────
   A panel hung under the + button rather than a fullscreen takeover, so
   the page stays visible behind it. The markup is unchanged from the
   overlay it replaces — the reveal is still the background's clip-path,
   which now reads as a panel unrolling instead of a curtain dropping. */
.menu{
  position:fixed; z-index:99;
  top:calc(var(--pad) + 3rem); right:var(--pad); left:auto; bottom:auto;
  width:min(19rem, calc(100vw - 2 * var(--pad)));
  padding:0;
  pointer-events:none;
}
.menu[inert]{ visibility:hidden }
.menu__bg{
  position:absolute; inset:0;
  /* dark glass: translucent enough for the page to move underneath, opaque
     enough that paper type still clears AA against whatever it lands on */
  background:color-mix(in srgb, var(--dark) 62%, transparent);
  /* the panel itself is thinner now, so the glass darkens what it samples
     rather than relying on its own fill — the page still reads through it
     but paper type keeps its contrast over a light section */
  -webkit-backdrop-filter:blur(22px) saturate(1.15) brightness(.72);
          backdrop-filter:blur(22px) saturate(1.15) brightness(.72);
  border:1px solid color-mix(in srgb, var(--paper) 16%, transparent);
  border-radius:4px;
  box-shadow:0 28px 64px -28px rgba(0,0,0,.65);
  clip-path:inset(0 0 100% 0);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .menu__bg{ background:var(--dark) }
}
.menu__inner{
  position:relative; color:var(--paper); width:100%; opacity:0;
  padding:.35rem 1rem .6rem;
}
.menu__list a{
  position:relative; display:flex; align-items:center; gap:.85rem;
  padding:.62rem 0;
  border-bottom:1px solid var(--line-d);
  overflow:hidden;
}
.menu__list a:last-child{ border-bottom:0 }
.menu__list em{
  font-family:var(--mono); font-style:normal;
  font-size:var(--label); letter-spacing:.14em; color:var(--accent);
  transform:none;
}
.menu__t{
  display:block;
  font-size:1rem;
  line-height:1.1; letter-spacing:-.01em; font-weight:500;
  transition:transform .45s var(--e-out), color .45s var(--e-out);
}
.menu__list a:hover .menu__t{ transform:translateX(.35rem); color:var(--accent) }
/* the acid plus that rides each row's right edge */
.menu__list a::after{
  content:'+'; content:'+' / ''; position:absolute; right:.1rem; top:50%;
  translate:0 -50%; rotate:-90deg;
  font-family:var(--mono); font-size:.85rem; line-height:1; color:var(--accent);
  opacity:0;
  transition:opacity .35s var(--e-out), rotate .35s var(--e-out);
}
.menu__list a:hover::after{ opacity:1; rotate:0deg }

/* the address block belongs to the fullscreen layout — hidden rather than
   deleted so the markup stays shared with the subpages */
.menu__aside{ display:none }
.menu__col h4{
  font-family:var(--mono); font-size:var(--label); letter-spacing:.2em; color:var(--accent); margin-bottom:.7rem;
  font-weight:400;
}
.menu__col h4::before{ content:'/ '; content:'/ ' / '' }
.menu__col p{ font-size:var(--body); line-height:1.6; color:color-mix(in srgb, var(--paper) 78%, transparent) }
.menu__col a:hover{ color:var(--accent) }
body.menu-open .menu{ pointer-events:auto }

/* ═══════════  hero  ═══════════
   v3's stage: a full-height dark room with the footage graded down, the
   copy set hard against the bottom-right corner. The frosted panel and
   its dot screen sit on that same right-hand side, behind the type. */
.hero{
  position:relative;
  height:100svh; min-height:34rem;
  overflow:hidden;
  background:var(--dark);
  color:var(--paper);
}
.hero__media{
  position:absolute; inset:0; z-index:1;
  overflow:hidden;
}
/* Footage runs ungraded, at full brightness. Legibility is carried
   entirely by the scrims and the frosted panel, which sit under the copy
   rather than over the whole frame. */
.hero__img,
.hero__vid{
  position:absolute; inset:0; width:100%; height:100%;
  max-width:none; object-fit:cover; object-position:50% 50%;
}
.hero__vid{
  opacity:0; transition:opacity .8s var(--e-out);
  pointer-events:none;
}
.hero__vid.is-playing{ opacity:1 }

/* Two scrims, not one: the linear pass sets the overall key, the radial
   sits under the copy's own corner. A single ramp left the type sitting
   on whatever the footage happened to be doing there. */
.hero__scrim{
  position:absolute; inset:0; z-index:2; pointer-events:none;
  background:
    radial-gradient(120% 90% at 12% 92%, rgba(8,8,8,.86) 0%, rgba(8,8,8,.35) 42%, transparent 72%),
    /* the studio line and coordinates sit outside the frosted panel, so
       their corner gets a scrim of its own */
    radial-gradient(58% 40% at 94% 96%, rgba(8,8,8,.72) 0%, rgba(8,8,8,.3) 55%, transparent 78%),
    linear-gradient(180deg, rgba(8,8,8,.55) 0%, rgba(8,8,8,.12) 34%, rgba(8,8,8,.78) 100%);
}

/* The page rules again, but over the footage this time: the hero's own
   ::before sits behind the video like every other section, so this second
   layer rides above it and is masked to the lower scrim, fading out as it
   climbs into the bright part of the frame. */
.hero::after{
  content:''; position:absolute; inset:0 var(--pad); z-index:2;
  pointer-events:none;
  border-inline:1px solid var(--gridline);
  background:
    linear-gradient(90deg, var(--gridline), var(--gridline)) 25% 0 / 1px 100% no-repeat,
    linear-gradient(90deg, var(--gridline), var(--gridline)) 50% 0 / 1px 100% no-repeat,
    linear-gradient(90deg, var(--gridline), var(--gridline)) 75% 0 / 1px 100% no-repeat;
  -webkit-mask-image:linear-gradient(180deg, transparent 52%, #000 100%);
          mask-image:linear-gradient(180deg, transparent 52%, #000 100%);
}

/* Frosted panel + dot screen — the copy's ground, so it sits on the same
   side as the headline. backdrop-filter cannot take a gradient, so the
   whole layer (blur, tint and dots together) is faded out with a mask:
   solid behind the type at the left edge, gone by the middle of the frame. */
.hero__frost{
  position:absolute; z-index:2; inset:0 auto 0 0;
  width:min(64%, 48rem);
  backdrop-filter:blur(20px) saturate(1.05) brightness(.94);
  -webkit-backdrop-filter:blur(20px) saturate(1.05) brightness(.94);
  background:
    radial-gradient(circle at center,
      color-mix(in srgb, var(--paper) 17%, transparent) 0 .75px,
      transparent 1px) 0 0 / 9.75px 9.75px,
    linear-gradient(90deg,
      rgba(23,23,23,.52) 0%,
      rgba(23,23,23,.22) 55%,
      transparent 100%);
  /* Two masks intersected: the horizontal one fades the panel out to the
     right, the vertical one fades it out above the copy so the glass ends
     where the type does instead of running the full height. */
  -webkit-mask-image:
    linear-gradient(90deg, #000 0%, #000 55%, rgba(0,0,0,.28) 80%, transparent 100%),
    linear-gradient(180deg, transparent 23%, #000 73%);
  mask-image:
    linear-gradient(90deg, #000 0%, #000 55%, rgba(0,0,0,.28) 80%, transparent 100%),
    linear-gradient(180deg, transparent 23%, #000 73%);
  -webkit-mask-composite:source-in;
          mask-composite:intersect;
  pointer-events:none;
}

/* Three rows: an empty 1fr that pushes everything to the floor, the tag,
   then the bottom band. The headline and the studio line share that last
   row, so they sit on one baseline at the lowest part of the frame. */
.hero__inner{
  position:absolute; inset:0; z-index:3;
  padding:calc(var(--pad) + 3rem) var(--pad) var(--pad);
  display:grid;
  grid-template-columns:minmax(0,auto) minmax(0,1fr);
  grid-template-rows:1fr auto auto;
  column-gap:clamp(1.5rem,4vw,3rem);
  align-items:end;
}
/* The line under the headline, on the same left edge and the same bottom
   line as the studio copy opposite it. It used to be a three-word tag and
   wore the mono/uppercase/tracked micro-label treatment; it carries a
   sentence now, which at .62rem and .2em of tracking was a 670px strip of
   shouting. Same opt-out .hero__sub makes one column over, for the same
   reason — the two read as the pair of descriptive lines they are. The
   acid square stays: it is what marks this as the hero's own line. */
.hero__tag{
  grid-column:1; grid-row:3;
  display:flex; align-items:flex-start; justify-content:flex-start; gap:.6rem;
  margin-top:clamp(.8rem,1.6vw,1.2rem);
  max-width:46ch;
  font-family:var(--sans); font-size:var(--body);
  letter-spacing:normal; text-transform:none; line-height:1.7;
  color:color-mix(in srgb, var(--paper) 72%, transparent);
}
.hero__tag i{
  font-style:normal; width:8px; height:8px; background:var(--accent);
  display:inline-block; flex:none;
  /* on the first line's optical centre, so a wrap does not drag it down */
  margin-top:.6em;
}
.hero__h{
  grid-column:1; grid-row:2;
  text-align:left; color:var(--paper);
  text-shadow:0 1px 40px rgba(0,0,0,.45);
  font-size:clamp(1.47rem, 4.48vw, 4.48rem); font-weight:500;
  letter-spacing:-.035em; line-height:.94;
  max-width:14ch;
}
/* The hero's last word carries no accent at all: no chip, no colour. It
   inherits the headline's own paper and shadow, so it reads as part of
   the line. The padding goes with the background it was spacing. */
.hero__h i{
  color:inherit; background:none; padding:0;
}

.hero__foot{
  grid-column:2; grid-row:3; justify-self:end;
  display:flex; justify-content:flex-end; align-items:flex-end;
  gap:1.5rem;
  color:color-mix(in srgb, var(--paper) 82%, transparent);
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.14em;
}
/* the action row leads on the left; the studio line answers it on the
   right, with the coordinates sitting under that text */
.hero__col{
  display:flex; flex-direction:column; align-items:flex-end; gap:.7rem;
  text-align:right;
}
.hero__meta{ display:flex; align-items:center; gap:.55rem }
.hero__meta em{ font-style:normal; color:var(--paper) }
.hero__meta b{ font-weight:400; color:var(--accent) }
.hero__sub{
  max-width:34ch; line-height:1.7;
  font-size:var(--body);
  /* sits inside .hero__foot, which is mono/uppercase/tracked — opt out so
     this reads as body copy like every other paragraph. */
  font-family:var(--sans); letter-spacing:normal; text-transform:none;
  color:color-mix(in srgb, var(--paper) 72%, transparent);
}

/* acid-underlined action row — v3's one repeated call to action. It sits
   under the studio line, so it takes that column's right edge and caps
   its own width rather than stretching the column. */
.act{
  display:flex; align-items:center; justify-content:space-between;
  gap:1.5rem; margin-top:.5rem; padding:.85rem 0 .7rem;
  width:min(100%, 20rem); flex:none;
  border-bottom:2px solid var(--accent);
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.14em; color:inherit;
  text-align:left;
  transition:color .35s var(--e-out);
}
.act svg{ width:1.1rem; height:1.1rem; flex:none; transition:translate .45s var(--e-out) }
/* the acid only reads as ink on the dark rooms; on the light page the
   deepened accent stands in */
.act:hover{ color:var(--accent-deep) }
.hero .act:hover{ color:var(--accent) }
/* on the featured projects the acid rule fought the acid title chip,
   so the line there is ink and the chip keeps the colour to itself */
.feature .act{ border-bottom-color:var(--ink) }
.act:hover svg{ translate:.35rem 0 }

/* ── button — square chip, acid sweep on hover ─────────── */
/* The old acid slide-up pill retired with this layout — its markup
   (.pill__t / .pill__ico) appears on no page here. The name is reused by
   v2.css for a plain round button; leaving this block in place would have
   leaked its border, shadow and backdrop-blur onto that one. */

/* ═══════════  ticker  ═══════════ */
/* Hidden rather than deleted, so the markup and its content stay in
   place and this is a one-line revert — same idiom as .pj-specs below.
   marquee() in app.js measures a zero width here and bails, so nothing
   animates and no error is thrown. */
.ticker{
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  padding:clamp(.9rem,1.6vw,1.3rem) 0; overflow:hidden;
  background:var(--bone);
  display:none;        /* ← the hide. Delete this line to bring the bar back. */
}
.ticker__track{ display:flex; width:max-content; will-change:transform }
.ticker__set{ display:flex; align-items:center; gap:clamp(1.4rem,3vw,3rem); padding-right:clamp(1.4rem,3vw,3rem) }
.ticker__set span{
  font-size:clamp(1.05rem,2vw,1.7rem); letter-spacing:-.01em;
  font-weight:600; white-space:nowrap;
}
.ticker__set b{ width:.637em; height:.591em; color:var(--accent-deep) }
@supports ((-webkit-mask-image:url(a)) or (mask-image:url(a))){
  .ticker__set b{
    --star:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2032%2032'%3E%3Crect%20x='15.05'%20width='1.9'%20height='32'%20fill='black'/%3E%3Crect%20x='15.05'%20width='1.9'%20height='32'%20fill='black'%20transform='rotate(45%2016%2016)'/%3E%3Crect%20x='15.05'%20width='1.9'%20height='32'%20fill='black'%20transform='rotate(90%2016%2016)'/%3E%3Crect%20x='15.05'%20width='1.9'%20height='32'%20fill='black'%20transform='rotate(135%2016%2016)'/%3E%3C/svg%3E");
    background-color:currentColor;
    -webkit-mask:var(--star) center/contain no-repeat;
            mask:var(--star) center/contain no-repeat;
  }
}

/* ═══════════  services — dark room, lead + card grid  ═══════════
   Copy on the left, a 2-up card grid on the right. The grid holds three
   services in four cells: the empty cell is deliberate breathing room,
   and the acid + sits on the crossing where the two rules meet. */
.services{
  padding:clamp(4rem,9vw,7.5rem) var(--pad) clamp(4rem,8vw,6.5rem);
  background:var(--dark);
  color:var(--paper);
}
.svcs{
  --svcs-gap:clamp(2rem,5vw,4rem);
  display:grid;
  /* The card grid takes the right half of the band (3rd rule -> 5th rule),
     which puts its centre exactly on the 4th rule. Equal columns would sit
     it at r4 + gap/4 instead. The lead column absorbs the gap. */
  grid-template-columns:calc(50% - var(--svcs-gap)) 50%;
  gap:var(--svcs-gap);
  align-items:stretch;
}
/* the lead stretches the row so its action row can sit on the floor,
   level with the bottom of the card grid */
.svcs__lead{ display:flex; flex-direction:column }
.services__h{
  font-size:clamp(2rem,4.6vw,3.4rem); letter-spacing:-.02em; font-weight:500;
  line-height:.98;
  margin:0 0 clamp(1.1rem,2.2vw,1.6rem);
  max-width:11ch;
}
.services__h i{
  font-style:normal; color:var(--dark);
  background:var(--accent); padding:0 .08em;
  -webkit-box-decoration-break:clone; box-decoration-break:clone;
}
.services__p{
  font-size:var(--body); line-height:1.65;
  color:color-mix(in srgb, var(--paper) 62%, transparent);
  max-width:var(--col);   /* wraps just before the 2nd rule */
}
.svcs__lead .act{ margin-top:auto; padding-top:clamp(2rem,5vw,3.5rem) }

.svcs__grid{
  display:grid; grid-template-columns:repeat(2, minmax(0,1fr));
  align-self:start;
}
.svc{
  position:relative;
  display:flex; flex-direction:column;
  padding:clamp(1.1rem,2vw,1.6rem);
  transition:background-color .45s var(--e-out);
}
/* internal rules only — the outer edges stay open to the room */
/* no internal vertical rule — the section's own 4th gridline now falls
   exactly on this edge, and drawing both showed a double line. */
.svc:nth-child(-n+2){ border-bottom:1px solid var(--line-d) }
.svc:hover{ background:color-mix(in srgb, var(--paper) 5%, transparent) }

.svc__no{
  font-family:var(--mono); font-size:var(--label); letter-spacing:.14em;
  color:var(--accent);
}
/* the dotted grip in the corner — a 2 × 3 dot field, drawn not typed */
.svc__grip{
  position:absolute; top:clamp(1.2rem,2vw,1.7rem); right:clamp(1.1rem,2vw,1.6rem);
  width:7px; height:11px;
  color:color-mix(in srgb, var(--paper) 34%, transparent);
  background-image:radial-gradient(circle at center, currentColor 0 1px, transparent 1.2px);
  background-size:4px 4px;
}
/* the crossing of the two rules gets the site's + */
.svc:first-child::after{
  content:'+'; content:'+' / ''; position:absolute; right:0; bottom:0;
  translate:50% 50%; z-index:2;
  font-family:var(--mono); font-size:.8rem; line-height:1;
  color:var(--accent);
}
.svc h3{
  font-size:1rem; font-weight:500; letter-spacing:-.01em;
  margin:clamp(1.6rem,3vw,2.4rem) 0 .55rem;
}
.svc p{
  font-size:var(--body); line-height:1.6;
  color:color-mix(in srgb, var(--paper) 58%, transparent);
  max-width:34ch;
}
.svc__tags{
  display:flex; flex-wrap:wrap; gap:.35rem .8rem;
  margin-top:.9rem;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.13em;
  color:color-mix(in srgb, var(--paper) 42%, transparent);
}
.svc__tags li::before{ content:'/ '; content:'/ ' / ''; color:var(--accent) }

/* ═══════════  work grid — 2 × 3  ═══════════ */
.work{ background:var(--bone-2); padding-bottom:var(--seam) }
.work__head{ padding:clamp(2.6rem,6vw,4.5rem) var(--pad) 0 }
.work__head .shead{ margin-bottom:clamp(1.4rem,3vw,2.2rem) }
/* The two rows drift in opposite directions as the section scrolls (see
   tiles() in app.js). --drift is the travel distance, written by the JS
   so there is one source of truth; the grid is grown by that much on each
   side and pulled back out with a negative margin, so a drifting row can
   never expose a gap at the page edge. Falls back to 0 with no JS. */
.work__grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);   /* 3 across, 2 down */
  gap:var(--seam);
  background:var(--bone-2);
  width:calc(100% + var(--drift, 0px) * 2);
  margin-inline:calc(var(--drift, 0px) * -1);
}
.tile{
  position:relative; overflow:hidden; display:block;
  aspect-ratio:16/9;
  background:var(--sand);
  isolation:isolate;
}
.tile__media{
  position:absolute; inset:-7%; width:114%; height:114%;
  will-change:transform;
}
.tile__img,
.tile__vid{
  position:absolute; inset:0; width:100%; height:100%;
  max-width:none;
  object-fit:cover;
}
.tile__vid{
  opacity:0; transition:opacity .45s var(--e-out);
  pointer-events:none;
}
.tile__vid.is-playing{ opacity:1 }
.tile::after{
  content:''; position:absolute; inset:0; z-index:1;
  background:linear-gradient(180deg, transparent 45%, rgba(10,10,10,.6));
  opacity:0; transition:opacity .6s var(--e-out);
}
.tile:hover::after,
.tile:focus-visible::after{ opacity:1 }
/* the ring draws inside the frame — outside it would vanish under the seams */
.tile:focus-visible{ outline-offset:-6px }
/* mono index chip, top-left of every tile */
.tile__no{
  position:absolute; z-index:2; top:.85rem;
  left:calc(.9rem + var(--edge-shift, 0px));
  font-family:var(--mono); font-size:var(--label); letter-spacing:.14em;
  color:#fff; mix-blend-mode:difference;
}
/* acid plus, top-right, arrives on hover — on an ink chip so it reads
   over any footage */
.tile__plus{
  position:absolute; z-index:2; top:.7rem; right:.8rem;
  font-family:var(--mono); font-size:.95rem; line-height:1;
  color:var(--accent); background:var(--ink); padding:.12em .38em;
  opacity:0; transform:rotate(-90deg);
  transition:opacity .5s var(--e-out), transform .5s var(--e-out);
}
.tile:hover .tile__plus,
.tile:focus-visible .tile__plus{ opacity:1; transform:rotate(0deg) }

.tile__meta{
  position:absolute; z-index:2; inset:auto 0 0 0;
  /* --edge-shift is written by tiles() while a row is drifting: it is the
     amount this tile currently hangs off the left of the viewport, so the
     caption stays inside the frame instead of sliding out with the tile.
     It lands on padding, not a transform — the reveal below owns that. */
  padding:1.1rem 1.2rem 1.1rem calc(1.2rem + var(--edge-shift, 0px));
  color:#fff;
  display:flex; flex-direction:column; gap:.3rem;
  transform:translateY(115%);
  transition:transform .6s var(--e-out);
}
.tile:hover .tile__meta,
.tile:focus-visible .tile__meta{ transform:translateY(0) }
.tile__meta h3{
  font-size:1rem; font-weight:500; letter-spacing:-.01em;
}
.tile__meta span{
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em; color:var(--accent);
}

/* ═══════════  featured  ═══════════ */
/* Two equal halves with no gap and no padding on the grid itself, so the
   visual's inner edge lands exactly on 50% — the page's centre column
   rule — while its outer edge still bleeds off the page. The gutter the
   copy needs is carried by .feature__text, not by the grid. */
.feature{
  display:grid; grid-template-columns:1fr 1fr;
  align-items:center; gap:0;
  padding-block:clamp(4rem,9vw,8rem); padding-inline:0;
  background:var(--bone-2);
}
.feature__text{ padding-left:var(--pad); padding-right:clamp(2rem,5vw,4rem) }
.feature--flip .feature__text{ padding-left:clamp(2rem,5vw,4rem); padding-right:var(--pad) }
.feature--flip .feature__vis{ order:1 }
.feature--flip .feature__text{ order:2 }
.feature--flip .feature__play{ left:auto; right:5% }
.feature--flip{ background:var(--bone) }
.feature__kicker{
  display:flex; align-items:center; gap:.6rem;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.18em; color:var(--ink-2);
}
/* the same acid square the hero tag carries, in place of a numbered chip */
.feature__kicker i{
  font-style:normal; width:8px; height:8px; flex:none;
  background:var(--accent); display:inline-block;
}
/* Client name (1st line) at half size; the rest of the title unchanged. */
.feature__h .l:first-child,
.pj-title   .l:first-child{ font-size:.5em }
.feature__h{
  font-size:clamp(2rem,4.8vw,4.2rem); letter-spacing:-.02em;
  font-weight:500; line-height:.96;
  margin:.9rem 0 1.4rem;
}
.feature__p{
  font-size:var(--body); line-height:1.68;
  color:var(--ink-2); max-width:42ch; margin-bottom:1.9rem;
}
.feature__facts{
  display:grid; gap:.1rem; margin-bottom:2.2rem;
  border-top:1px solid var(--line); padding-top:.4rem;
}
/* Values are set in the label's mono too, so each row reads as one
   typed line rather than a label and a caption in two voices. They keep
   their own case and tracking so the labels still lead. */
.feature__facts li{
  display:grid; grid-template-columns:7.5rem 1fr;
  padding:.55rem 0; border-bottom:1px solid var(--line);
  font-family:var(--mono); font-size:var(--label); letter-spacing:.16em;
  line-height:1.5; color:var(--ink);
  /* the value runs to the right edge, the label holds the left */ text-align:right;
}
.feature__facts em{
  font-family:var(--mono); font-style:normal; font-size:var(--label);
  letter-spacing:.16em; color:var(--ink);
  align-self:center; text-align:left;
}

.feature__vis{
  position:relative; overflow:hidden;
  aspect-ratio:16/9; background:var(--dark);
}
.feature__media{
  position:absolute; inset:-7%; width:114%; height:114%;
  will-change:transform;
}
.feature__c,
.feature__vid{
  position:absolute; inset:0; width:100%; height:100%;
  max-width:none;
  object-fit:cover;
}
.feature__vid{
  opacity:0; transition:opacity .6s var(--e-out);
  pointer-events:none;
}
.feature__vid.is-playing{ opacity:1 }
.feature__vis:has(.feature__vid.is-playing) .feature__play{
  opacity:0; transform:scale(.9);
  transition:opacity .5s var(--e-out), transform .5s var(--e-out);
}
.feature__play{
  position:absolute; z-index:2; left:5%; bottom:6%;
  width:clamp(48px,5.5vw,66px); aspect-ratio:1; border-radius:2px;
  display:grid; place-items:center;
  background:var(--accent); color:var(--ink);
  transition:transform .55s var(--e-out), background-color .4s;
}
.feature__play svg{ width:20px; height:20px; margin-left:2px }
.feature__vis:hover .feature__play{ transform:scale(1.1) rotate(90deg) }

/* ═══════════  blog  ═══════════ */
.blog{
  background:var(--sand-warm);
  padding:clamp(4rem,9vw,7rem) var(--pad);
}
/* No max-width cap: every other section runs to the padded edge, so capping
   this one pushed the whole block off the 1st rule on wide screens. */
.blog__inner{ width:100% }
.blog__head{
  display:flex; justify-content:space-between; align-items:baseline;
  gap:clamp(1rem,4vw,3rem); flex-wrap:wrap;
  margin-bottom:clamp(2rem,4.5vw,3.2rem);
}
.blog__h{
  font-size:clamp(2rem,5vw,3.6rem); letter-spacing:-.02em; font-weight:500;
}
.blog__sub{
  font-size:var(--body); line-height:1.6;
  color:var(--ink-2); max-width:42ch;
}
.blog__grid{
  --blog-gap:clamp(1.6rem,4vw,3rem);
  display:grid;
  /* Post 1 runs from the 1st rule (left edge); post 2 starts exactly on the
     3rd rule (centre). The gap is taken out of post 1's width rather than
     straddling the centre line, so post 2's edge lands on the rule. */
  grid-template-columns:repeat(2, calc(50% - var(--blog-gap)));
  gap:var(--blog-gap);
}

.post{ display:block }
.post__media{
  position:relative; overflow:hidden;
  aspect-ratio:16/9; background:var(--sand);
  border-radius:2px; margin-bottom:clamp(1rem,2vw,1.4rem);
}
.post__media img{
  position:absolute; inset:0; width:100%; height:100%;
  max-width:none; object-fit:cover;
  transition:transform 1s var(--e-out), filter 1s var(--e-out);
}
.post:hover .post__media img{ transform:scale(1.04) }
/* index chip on the plate */
.post__media::after{
  content:'+'; content:'+' / ''; position:absolute; top:.7rem; right:.8rem;
  font-family:var(--mono); font-size:.95rem;
  color:var(--accent); background:var(--ink); padding:.12em .38em;
  opacity:0; transform:rotate(-90deg);
  transition:opacity .5s var(--e-out), transform .5s var(--e-out);
}
.post:hover .post__media::after{ opacity:1; transform:rotate(0) }

.post__meta{
  display:flex; align-items:center; gap:.7rem; margin-bottom:.7rem;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em;
}
.post__meta span{ color:var(--ink); background:var(--accent); padding:.15em .5em }
.post__meta em{ font-style:normal; color:var(--ink-3) }

.post__title{
  font-size:clamp(1.15rem,1.9vw,1.6rem); line-height:1.15;
  letter-spacing:-.02em; font-weight:500; margin-bottom:.6rem;
  max-width:26ch;
}
.post__excerpt{
  font-size:var(--body); line-height:1.65;
  color:var(--ink-2); max-width:44ch; margin-bottom:1rem;
}
.post__more{
  display:inline-flex; align-items:center; gap:.5rem;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em;
  border-bottom:1px solid var(--ink);
  padding-bottom:.2rem;
}
.post__more svg{ width:13px; height:13px; transition:transform .5s var(--e-out) }
.post:hover .post__more svg{ transform:translateX(4px) }

/* ═══════════  article  ═══════════ */
.art{ max-width:46rem; margin-inline:auto; padding:0 var(--pad) }
.art__hero{ padding:clamp(7rem,14vw,10rem) 0 clamp(1.6rem,3vw,2.4rem) }
.art__meta{
  display:flex; align-items:center; gap:.7rem; margin-bottom:1.2rem;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em;
}
.art__meta span{ color:var(--ink); background:var(--accent); padding:.15em .5em }
.art__meta em{ font-style:normal; color:var(--ink-3) }
.art__title{
  font-size:clamp(2rem,4.6vw,3.4rem); line-height:1.02;
  letter-spacing:-.02em; font-weight:500; margin-bottom:1rem;
}
.art__lead{
  font-size:var(--body); line-height:1.6;
  color:var(--ink-2);
}
.art__plate{
  position:relative; overflow:hidden; aspect-ratio:16/9;
  background:var(--sand); margin:clamp(1.6rem,3.5vw,2.6rem) 0;
}
.art__plate img{
  position:absolute; inset:0; width:100%; height:100%;
  max-width:none; object-fit:cover;
}
.art__body > *{ margin-bottom:clamp(1rem,2vw,1.4rem) }
.art__body p{
  font-size:var(--body); line-height:1.75; color:var(--ink-2);
}
.art__body h2{
  font-size:clamp(1.3rem,2.2vw,1.7rem); letter-spacing:-.02em;
  font-weight:500; color:var(--ink);
  margin-top:clamp(2rem,4vw,2.8rem);
}
.art__body ul{ padding-left:1.1rem }
.art__body li{
  font-size:var(--body); line-height:1.75; color:var(--ink-2);
  list-style:disc; margin-bottom:.5rem;
}
.art__body strong{ color:var(--ink); font-weight:600 }
.art__foot{
  display:flex; justify-content:space-between; gap:1rem; flex-wrap:wrap;
  margin:clamp(2.5rem,6vw,4rem) 0 clamp(4rem,9vw,7rem);
  padding-top:clamp(1.2rem,2.5vw,1.8rem);
  border-top:1px solid var(--line);
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em; color:var(--ink-3);
}
.art__foot a:hover{ color:var(--ink) }

/* ═══════════  clients  ═══════════ */
.clients{
  overflow:hidden; padding:clamp(1.3rem,2.6vw,2rem) 0;
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  background:var(--bone);
}
.clients__track{ display:flex; width:max-content; will-change:transform }
.clients__set{ display:flex; align-items:center; gap:clamp(1.8rem,4.5vw,4rem); padding-right:clamp(1.8rem,4.5vw,4rem) }
/* Logo strip. The marks are pre-trimmed to their ink and flattened to
   alpha silhouettes, so they are greyscale by construction and share one
   optical weight instead of ten different brand colours and paddings.
   --logo is the shared cap height; --s corrects for shape, since a 16:1
   wordmark and a 3:1 stacked lockup do not read as the same size at the
   same height. Factors are (6/aspect)^0.35 — a reference wordmark is 1. */
.clients__set{ --logo:clamp(15px, 1.75vw, 24px) }
.clients__set img{
  height:calc(var(--logo) * var(--s, 1));
  width:auto; max-width:none; flex:none;
  opacity:.42;
  transition:opacity .4s var(--e-out);
}
.clients__set img:hover{ opacity:.9 }
.c-komori{ --s:0.89 }
.c-philips{ --s:1.04 }
.c-bommel-wonen{ --s:1.26 }
.c-videoland{ --s:0.95 }
.c-revitalize{ --s:1.00 }
.c-endemolshine{ --s:1.14 }
.c-prime-video{ --s:1.25 }
.c-wisemonkeys{ --s:1.02 }
.c-monks{ --s:1.02 }
.c-tommy-hilfiger{ --s:0.70 }

/* ═══════════  cta  ═══════════ */
.cta{
  display:grid;
  /* the ask starts on the page's centre rule rather than floating in a
     centred max-width box, so it lines up with the section rules */
  grid-template-columns:50% minmax(0,1fr);
  gap:0;
  align-items:start;
  padding:clamp(4.5rem,11vw,9rem) var(--pad);
  text-align:left;
  background:var(--bone);
}
.cta__who-h{
  font-size:clamp(1.5rem,3.2vw,2.4rem);
  letter-spacing:-.02em; font-weight:500; line-height:1;
}
.cta__who{ padding-right:clamp(2rem,6vw,5rem) }
.cta__intro{ max-width:52ch; margin-top:clamp(1.1rem,2.2vw,1.7rem) }
.cta__intro p{
  font-size:var(--body);
  line-height:1.7; color:var(--ink-2);
  margin-bottom:clamp(.98rem,2.1vw,1.54rem);
}
.cta__intro p:last-child{ margin-bottom:0 }

.cta__ask{ align-self:center }
.cta__h{
  font-size:clamp(2.1rem,5vw,4.4rem); letter-spacing:-.02em;
  font-weight:500; line-height:.96;
  margin:0 0 clamp(1.6rem,3vw,2.4rem);
}
.cta__mail{
  position:relative; display:inline-block;
  font-family:var(--sans);
  font-size:clamp(.9rem,1.4vw,1.15rem); letter-spacing:.04em;
  padding-bottom:.35rem;
}
.cta__mail::before{ content:'→ '; content:'→ ' / ''; color:var(--accent-deep) }
.cta__mail::after{
  content:''; position:absolute; inset:auto 0 0 0; height:1px;
  background:var(--ink); transform-origin:0 50%;
  transition:transform .55s var(--e-out), background-color .4s;
}
.cta__mail:hover::after{ transform:scaleX(0); transform-origin:100% 50% }

/* ═══════════  zero in on band  ═══════════
   Stands where the film wall used to, between the second featured project
   and the journal, and the one strip on the page that ignores --pad
   entirely: the artwork runs edge to edge, square-cornered, and butts
   straight onto the journal below.

   The section's own rules and registration mark stay off — the frame
   covers the outer pair and the inner three at every size, so they would
   only be dead pseudo-elements. */
.band{ padding:0 }
.band::before, .band::after{ content:none }

/* Height is the clip's own 1820×680 ratio rather than a fixed value, so
   the readout is never cropped — at any width you see the whole frame.
   The clip is still needed: the media inside is overscanned for parallax
   and has to be cut back to the frame. */
.band__frame{
  position:relative;
  aspect-ratio:1820 / 680;
  overflow:hidden;
  background:var(--dark);
}

/* Overscanned like a featured visual so parallax() has headroom to travel
   in — 7% a side, which is what the 6% travel below needs. What it crops
   off the sides is pure ribbon: the glass starts a quarter of the way in,
   so the overscan never reaches it. */
.band__media{
  position:absolute; inset:-7%; width:114%; height:114%;
  will-change:transform;
}
.band__img,
.band__vid{
  position:absolute; inset:0; width:100%; height:100%;
  max-width:none; object-fit:cover;
}
.band__vid{
  opacity:0; transition:opacity .6s var(--e-out);
  pointer-events:none;
}
.band__vid.is-playing{ opacity:1 }

/* ── the readout ─────────────────────────────────────────
   Rebuilt from the baked-in bar, on the fractions measured off it: the
   glass spans the middle half of the frame (25%–75%, dead centre), stands
   82/680 of the frame tall, and the type sits 113/910 in from its left
   edge at 48/680 of the frame. Everything is in cqw against the frame
   rather than vw, so the bar keeps those proportions whether the band
   runs full-bleed or inset — it has been both.

   Below 700px the frame is too short for a faithfully-scaled bar to stay
   readable (the type would land near 9px), so there the glass widens and
   the type takes a floor. */
.band__frame{ container-type:inline-size }

.band__bar{
  --pill-h:  4.505cqw;      /*  82 / 1820 */
  --pill-fs: 2.637cqw;      /*  48 / 1820 */
  --pill-px: 6.209cqw;      /* 113 / 1820 */
  position:absolute; z-index:2; left:25%; right:25%; top:50%;
  height:var(--pill-h); margin:0;
  transform:translateY(-50%);
  display:flex; align-items:center;
  pointer-events:none;
  /* Words travel in and out vertically. Clipped to the capsule they arrive
     from under its own edge, the way the rendered bar did; unclipped they
     simply appear on the plate above and below it. */
  border-radius:calc(var(--pill-h) / 2);
  overflow:hidden;
}
/* An author display beats the UA's [hidden] rule, so the attribute needs
   saying again here — same as .reel does above. */
.band__bar[hidden]{ display:none }

/* The glass is its own element so the entrance can scale it open without
   squashing the type riding on top. */
.band__glass{
  position:absolute; inset:0;
  border-radius:calc(var(--pill-h) / 2);
  background:rgba(12,12,12,.52);
  border:1px solid rgba(255,255,255,.27);
  backdrop-filter:blur(7px) saturate(.9);
  -webkit-backdrop-filter:blur(7px) saturate(.9);
  transform-origin:50% 50%;
}

.band__line{
  position:relative; z-index:1;
  display:flex; align-items:baseline;
  gap:0;
  padding-left:var(--pill-px);
  font-family:var(--logo-font);
  font-size:var(--pill-fs);
  font-weight:400; line-height:1;
  letter-spacing:0;
  white-space:nowrap;
  /* the slashed zero the baked-in bar used; JetBrains Mono ships it as an
     opt-in feature, and the dotted default stands in where it is missing */
  font-feature-settings:'zero' 1;
  font-variant-numeric:slashed-zero;
}
.band__lede{ color:var(--accent) }
.band__on{ color:var(--paper) }
.band__lede::after,
.band__on::after{ content:'\00a0' }

/* The rotating word. All five are stacked in the slot so the slot holds
   the widest one's box and nothing reflows as they swap; only the one
   carrying .is-on is visible. */
.band__slot{
  display:inline-grid;          /* every word in cell 1/1 … */
  color:var(--paper);
}
.band__word{
  grid-area:1 / 1;              /* … so the slot is as wide as the longest
                                   one and the glass never has to resize */
  opacity:0;
}
.band__word.is-on{ opacity:1 }

@container (max-width: 700px){
  .band__bar{
    --pill-h:34px; --pill-fs:13px; --pill-px:15px;
    left:4%; right:4%;
  }
}

/* Reduced motion keeps the bar, drops the movement: the first word stands
   and the glass is simply there. */
@media (prefers-reduced-motion: reduce){
  .band__glass, .band__line{ transform:none !important; opacity:1 !important }
}

/* ═══════════  footer  ═══════════ */
.foot{
  background:var(--dark); color:var(--paper);
  padding:clamp(3rem,6vw,5rem) var(--pad) clamp(1.2rem,2vw,1.8rem);
  overflow:hidden;
}
/* Columns start on the page's first three rules — the left edge, 25%
   and 50% — so the gap is the rule spacing itself, not a gutter. */
.foot__top{
  display:grid; grid-template-columns:25% 25% minmax(0,1fr);
  gap:0; padding-bottom:clamp(2.5rem,6vw,4.5rem);
}
.foot__col{ padding-right:var(--gap) }
.foot__col h4{
  font-family:var(--mono); font-size:var(--label); letter-spacing:.2em; color:var(--accent); margin-bottom:.85rem;
  font-weight:400;
}
.foot__col p{ font-size:var(--body); line-height:1.65; color:color-mix(in srgb, var(--paper) 74%, transparent) }
.foot__col a{ transition:color .35s }
.foot__col a:hover{ color:var(--accent) }

/* The mark rides beside the year on the closing line. Its height is the
   bar's own cap height, so it sets on the same line as the type; inverted
   because the artwork is dark-on-transparent and the room is near-black. */
.foot__c{ display:inline-flex; align-items:center; gap:.5rem }
.foot__logo{
  height:calc(var(--label) * var(--cap));
  width:auto; max-width:none; display:block;
}

.foot__bar{
  display:flex; justify-content:space-between; gap:1rem; flex-wrap:wrap;
  padding-top:1.4rem; border-top:1px solid var(--line-d);
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em;
  color:color-mix(in srgb, var(--paper) 66%, transparent);
}
.foot__back:hover{ color:var(--accent) }

/* ═══════════  project page  ═══════════ */
.pj-hero{
  padding:calc(var(--pad) + 7rem) var(--pad) clamp(2.5rem,5vw,4rem);
  background:var(--bone);
}
.pj-crumb{
  display:inline-flex; align-items:center; gap:.55rem;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.18em; color:var(--ink-3);
  margin-bottom:clamp(1.6rem,4vw,2.6rem);
}
.pj-crumb svg{ width:13px; height:13px }
.pj-crumb a{ transition:color .35s var(--e-out) }
.pj-crumb a:hover{ color:var(--ink) }
.pj-crumb b{ color:var(--ink); font-weight:400 }

.pj-title{
  font-size:clamp(2.6rem,7.4vw,6.8rem);
  line-height:.92; letter-spacing:-.025em; font-weight:500;
  max-width:16ch;
}
.pj-lead{
  margin-top:clamp(1.4rem,3vw,2.2rem);
  font-size:var(--body);
  line-height:1.5; letter-spacing:-.015em;
  color:var(--ink); max-width:46ch;
}

.pj-meta{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--gap);
  margin-top:clamp(2.4rem,5vw,3.6rem);
  border-top:1px solid var(--line); padding-top:1.5rem;
}
.pj-meta dt{
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.18em;
  color:var(--ink-3); margin-bottom:.5rem;
}
.pj-meta dt::before{ content:'/ '; content:'/ ' / ''; color:var(--accent-deep) }
.pj-meta dd{ font-size:var(--body); line-height:1.5; letter-spacing:-.01em }

.pj-plate{
  position:relative; overflow:hidden;
  aspect-ratio:16/9; background:var(--sand);
}
.pj-plate img{
  position:absolute; inset:-7%; width:114%; height:114%;
  max-width:none; object-fit:cover; will-change:transform;
}
.pj-plate figcaption{
  position:absolute; z-index:2; inset:auto 0 0 0;
  padding:1.4rem var(--pad);
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em; color:#fff;
  background:linear-gradient(180deg, transparent, rgba(10,10,10,.5));
}

.pj-shots{
  display:grid; grid-template-columns:repeat(2,1fr);
  gap:clamp(.5rem,1vw,.9rem);
  padding:0 var(--pad) clamp(.5rem,1vw,.9rem);
}
.pj-shots--full{ grid-template-columns:1fr }
.pj-shots--3{ grid-template-columns:repeat(3,1fr) }

.pj-section{
  font-size:clamp(1.6rem,3.6vw,2.8rem); letter-spacing:-.02em; font-weight:500;
  padding:clamp(3rem,7vw,5.5rem) var(--pad) clamp(1.2rem,2.5vw,1.8rem);
  max-width:96rem; margin-inline:auto;
  text-align:center;
}
.pj-shots--4{ grid-template-columns:repeat(4,1fr) }

.pj-film{
  position:relative; margin:0 var(--pad) clamp(.5rem,1vw,.9rem);
  aspect-ratio:16/9; overflow:hidden; background:#000;
}
.pj-film iframe{
  position:absolute; inset:0; width:100%; height:100%; border:0;
}
.pj-shots--bleed{ padding-left:0; padding-right:0 }

.pj-shot{
  position:relative; overflow:hidden; display:block;
  aspect-ratio:16/9; background:var(--sand);
}
.pj-shot__media{
  position:absolute; inset:-8%; width:116%; height:116%;
  will-change:transform;
}
.pj-shot--exact{ aspect-ratio:var(--ratio) }
.pj-shot--exact .pj-shot__media{ inset:0; width:100%; height:100% }

.pj-shot img,
.pj-shot video{
  position:absolute; inset:0; width:100%; height:100%;
  max-width:none; object-fit:cover;
}
.pj-shot video{ opacity:0; transition:opacity .5s var(--e-out); pointer-events:none }
.pj-shot--auto{ aspect-ratio:auto }
.pj-shot--auto .pj-shot__media{ position:relative; inset:auto; width:100%; height:auto }
.pj-shot--auto img{ position:relative; inset:auto; height:auto; object-fit:contain }

.pj-shot video.is-playing{ opacity:1 }

.pj-shot.pj-shot--board{ aspect-ratio:auto; background:none }
.pj-shot.pj-shot--board .pj-shot__media{
  position:static; inset:auto; width:100%; height:auto; transform:none;
}
.pj-shot.pj-shot--board .pj-shot__media img{
  position:static; inset:auto; width:100%; height:auto; object-fit:contain;
}
.pj-shot figcaption{
  position:absolute; z-index:2; inset:auto 0 0 0;
  padding:.9rem 1.1rem;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.16em; color:#fff;
  background:linear-gradient(180deg, transparent, rgba(10,10,10,.55));
}

.pj-chapter{
  display:flex; align-items:baseline; gap:clamp(1rem,3vw,2.5rem);
  padding:clamp(2.6rem,6vw,4.5rem) var(--pad) clamp(1.2rem,2.5vw,1.8rem);
}
.pj-chapter em{
  font-family:var(--mono); font-style:normal; font-size:var(--label);
  letter-spacing:.18em; color:var(--ink-3);
  flex:none;
}
.pj-chapter em::before{ content:'/ '; content:'/ ' / ''; color:var(--accent-deep) }
.pj-chapter h2{
  font-size:clamp(1.5rem,3.2vw,2.4rem);
  letter-spacing:-.02em; font-weight:500;
}
.pj-chapter p{
  font-size:var(--body); line-height:1.65; color:var(--ink-2); max-width:38ch;
  margin-left:auto;
}

.pj-body{
  display:grid; grid-template-columns:minmax(0,15rem) minmax(0,1fr);
  gap:clamp(2rem,6vw,6rem);
  padding:clamp(3.5rem,8vw,7rem) var(--pad);
  background:var(--bone);
  max-width:96rem; margin-inline:auto;
}
.pj-body__label{
  position:sticky; top:calc(var(--pad) + 4.5rem); align-self:start;
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.18em; color:var(--ink-3);
}
.pj-body__label::before{ content:'/ '; content:'/ ' / ''; color:var(--accent-deep) }
.pj-body--center{
  grid-template-columns:minmax(0,1fr);
  max-width:74rem;
  padding-top:0;
}
.pj-body--center .pj-body__label{
  position:static; text-align:center; margin-bottom:clamp(1.6rem,3vw,2.4rem);
}
.pj-body--center .pj-block{ text-align:left }
.pj-body--center .pj-block p{ max-width:none; margin-inline:0 }
.pj-body--center .pj-body__cols > .pj-block:last-child:nth-child(odd){
  grid-column:1 / -1; justify-self:center;
}

.pj-body__cols{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(1.8rem,4vw,3rem) clamp(2rem,5vw,3.5rem);
  align-items:start;
}
.pj-body__cols .pj-block + .pj-block{ margin-top:0 }
.pj-body__cols .pj-block p{ max-width:48ch }

.pj-block + .pj-block{ margin-top:clamp(2.2rem,5vw,3.4rem) }
.pj-block h3{
  font-size:clamp(1.3rem,2.4vw,2rem); letter-spacing:-.02em;
  font-weight:500; margin-bottom:.9rem;
}
.pj-block p{
  font-size:var(--body); line-height:1.7;
  color:var(--ink-2); max-width:62ch;
}
.pj-block p + p{ margin-top:1rem }

.pj-specs{
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:var(--gap) clamp(2rem,5vw,4rem);
  padding:clamp(3rem,6vw,5rem) var(--pad);
  border-top:1px solid var(--line);
  background:var(--bone-2);
  display:none;
}
.pj-specs h4{
  font-family:var(--mono); font-size:var(--label);
  letter-spacing:.18em;
  color:var(--ink); margin-bottom:1rem;
}
.pj-specs li{
  display:flex; justify-content:space-between; gap:1rem;
  padding:.6rem 0; border-bottom:1px solid var(--line);
  font-size:.88rem; letter-spacing:-.01em;
}
.pj-specs li span{ color:var(--ink-3); text-align:right }

.pj-quote{
  padding:clamp(4rem,10vw,8rem) var(--pad);
  text-align:center; background:var(--dark); color:var(--paper);
}
.pj-quote blockquote{
  font-family:var(--sans); font-style:normal; font-weight:500;
  font-size:clamp(1.5rem,4vw,3rem); line-height:1.1;
  letter-spacing:-.02em;
  max-width:24ch; margin-inline:auto;
}
.pj-quote blockquote::before{ content:'“'; content:'“' / ''; color:var(--accent) }
.pj-quote blockquote::after{ content:'”'; content:'”' / ''; color:var(--accent) }
.pj-quote cite{
  display:block; margin-top:clamp(1.4rem,3vw,2.2rem);
  font-family:var(--mono); font-style:normal; font-size:var(--label);
  letter-spacing:.18em;
  color:color-mix(in srgb, var(--paper) 55%, transparent);
}

.pj-next{ background:var(--bone-2); padding-top:clamp(2rem,5vw,3.5rem) }
.pj-next__head{
  display:flex; justify-content:space-between; align-items:baseline;
  gap:1rem; flex-wrap:wrap;
  padding:0 var(--pad) clamp(1.4rem,3vw,2rem);
}
.pj-next__head h2{
  font-size:clamp(1.6rem,3.4vw,2.6rem);
  letter-spacing:-.02em; font-weight:500;
}
.work__grid--3{ grid-template-columns:repeat(3,1fr) }

/* ═══════════  responsive  ═══════════ */
@media (max-width:1080px){
  .work__grid,
  .work__grid--3{ grid-template-columns:repeat(2,1fr) }
  .pj-shots--3,
  .pj-shots--4{ grid-template-columns:repeat(2,1fr) }
  .svcs{ grid-template-columns:minmax(0,1fr); gap:clamp(2rem,5vw,3rem) }
  .svcs__lead .act{ padding-top:clamp(1.4rem,3vw,2rem) }
  /* --col is a quarter of the content width — a desktop measure that
     collapses to ~85px on a phone. Stacked, the copy takes the column. */
  .services__p{ max-width:none }
  .blog__grid{ grid-template-columns:1fr; gap:clamp(2.2rem,6vw,3rem) }

  .pj-body{ grid-template-columns:1fr; gap:1.4rem }
  .pj-body__cols{ grid-template-columns:1fr }
  .pj-body__label{ position:static }
  .pj-meta{ grid-template-columns:repeat(2,minmax(0,1fr)); row-gap:1.6rem }
  .pj-specs{ grid-template-columns:1fr; row-gap:2.2rem }
  /* Stacked: the visual goes full bleed, the copy keeps both gutters. The
     grid runs gap:0 side by side, which leaves the two blocks flush once
     they sit on top of each other — so the stack gets its own row gap,
     giving the action row and the film room to breathe. */
  .feature{ grid-template-columns:1fr; row-gap:clamp(2rem,7vw,3.2rem) }
  .feature__text,
  .feature--flip .feature__text{ padding-inline:var(--pad) }
  .feature--flip .feature__vis,
  .feature--flip .feature__text{ order:0 }
  .feature__vis{ aspect-ratio:16/10 }
  .foot__top{ grid-template-columns:repeat(2,minmax(0,1fr)); row-gap:2rem }
}

@media (max-width:760px){
  /* one column: the studio line drops under the headline again */
  .hero__inner{ grid-template-columns:minmax(0,1fr); grid-template-rows:1fr auto auto auto }
  .hero__h{ grid-row:2 }
  .hero__tag{ grid-row:3 }
  .hero__foot{ grid-column:1; grid-row:4; justify-self:start; margin-top:1.4rem }
  .hero__col{ align-items:flex-start; text-align:left }
  .act{ width:100% }
  /* the panel covers the frame once there is no room for a second column */
  .hero__frost{ width:100% }
  .hero__h{ max-width:none }

  .work__grid,
  .work__grid--3{ grid-template-columns:1fr }
  .tile__meta{ transform:translateY(0) }
  .tile::after{ opacity:1 }
  .tile__plus{ opacity:1; transform:none }

  /* one card per row: every divider becomes a horizontal rule */
  .svcs__grid{ grid-template-columns:minmax(0,1fr) }
  .svc:nth-child(odd){ border-right:0 }
  .svc:nth-child(-n+2),
  .svc:not(:last-child){ border-bottom:1px solid var(--line-d) }
  .svc:last-child{ border-bottom:0 }
  .svc:first-child::after{ display:none }

  .pj-meta{ grid-template-columns:1fr; row-gap:1.2rem }
  .pj-plate figcaption{ font-size:var(--label); padding:1rem var(--pad) }

  .feature__facts li{ grid-template-columns:6rem 1fr; font-size:var(--label)}
  .cta{ grid-template-columns:1fr; gap:clamp(2.4rem,8vw,3.4rem) }
  .cta__who{ padding-right:0 }
  .cta__ask{ align-self:start }
  .pj-shots,
  .pj-shots--3,
  .pj-shots--4{ grid-template-columns:1fr }
  .pj-chapter{ flex-direction:column; gap:.6rem }
  .pj-chapter p{ margin-left:0 }
  /* The mark rides beside the year on the closing line. Its height is the
   bar's own cap height, so it sets on the same line as the type; inverted
   because the artwork is dark-on-transparent and the room is near-black. */
.foot__c{ display:inline-flex; align-items:center; gap:.5rem }
.foot__logo{
  height:calc(var(--label) * var(--cap));
  width:auto; max-width:none; display:block;
}

.foot__bar{ justify-content:flex-start; flex-direction:column; gap:.5rem }
  main > section::before, .foot::before{ background:
    linear-gradient(90deg, var(--gridline), var(--gridline)) 50% 0 / 1px 100% no-repeat }
}

@media (max-width:480px){
  .foot__top{ grid-template-columns:1fr; row-gap:2rem }
}

/* pointer-coarse: no hover-only reveals */
@media (hover:none),(pointer:coarse){
  .tile__meta{ transform:translateY(0) }
  .tile::after{ opacity:1 }
  .tile__plus{ opacity:1; transform:none }
}

/* ── reduced motion ────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important; animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .grain{ animation:none }
  .ticker__track,.clients__track{ transform:none !important }
}
