/* ==========================================================
   Studio Name — Architectural Bureau
   Reference viewport: 1512px. Display type is fluid (vw).
   ========================================================== */

@font-face{
  font-family:"Nimbus Sans L";
  src:url("../fonts/nimbus-sans-l-regular.otf") format("opentype");
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"Nimbus Sans L";
  src:url("../fonts/nimbus-sans-l-regular-italic.otf") format("opentype");
  font-weight:400; font-style:italic; font-display:swap;
}
@font-face{
  font-family:"Nimbus Sans L";
  src:url("../fonts/nimbus-sans-l-bold.otf") format("opentype");
  font-weight:700; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"Nimbus Sans L";
  src:url("../fonts/nimbus-sans-l-bold-italic.otf") format("opentype");
  font-weight:700; font-style:italic; font-display:swap;
}

*,*::before,*::after{ box-sizing:border-box }

/* Visually hidden, still read aloud. */
.u-hidden{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap;
}

:root{
  --pad: 28px;

  --paper:#ffffff;
  --ink:#0d0d0d;
  /* All three uses of --muted are caption text at --micro (11-13px), where
     #8c8c8c measured 3.36:1 on white — under AA. #767676 is 4.54:1 and still
     reads as a grey, not a second black. */
  --muted:#767676;

  --void:#000000;
  --ink-i:#ffffff;
  --muted-i:#6e6e6e;

  --ph:#8f8f8f;
  --ph-dark:#333333;

  --sans:"Nimbus Sans L","Helvetica Neue",Helvetica,Arial,sans-serif;
  /* Source Serif 4 is the current release of Source Serif Pro — same design,
     plus a variable optical-size axis, which matters here because the serif
     runs from 19px (ledes) up to 242px (display). Pro is named next in the
     stack so a locally installed copy still resolves. */
  --serif:"Source Serif 4","Source Serif Pro","Times New Roman",Georgia,serif;

  --d-sans: clamp(40px, 9.1vw, 182px);
  --d-serif: clamp(42px, 12.1vw, 242px);
  --hero: 64px;
  --micro: max(11px, 0.76vw);
  --nav: max(11px, 0.79vw);

  --ease:cubic-bezier(.22,1,.36,1);
}

@media (max-width:820px){ :root{ --pad:18px; --d-sans:clamp(34px,10vw,64px); --d-serif:clamp(34px,9.6vw,64px) } }

html{ -webkit-text-size-adjust:100% }

body{
  margin:0; background:var(--paper); color:var(--ink);
  font-family:var(--sans); font-weight:400;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
h1,h2,h3,p,figure,blockquote{ margin:0 }
a{ color:inherit; text-decoration:none }
::selection{ background:#0d0d0d; color:#fff }

.serif{ font-family:var(--serif); font-weight:400 }

/* ── display type ───────────────────────────────────────── */
.d-sans{
  font-family:var(--sans); font-weight:400;
  font-size:var(--d-sans); line-height:.98;
  letter-spacing:-.035em;
}
.d-serif{
  font-family:var(--serif); font-weight:400;
  font-size:var(--d-serif); line-height:.99;
  letter-spacing:-.012em;
}

/* masked line/word reveal primitives.
   The overflow box needs room on BOTH edges — line-height is below 1 on the
   display faces (.98/.99), so cap-height (S, T...) clips at the top and
   descenders (g, y, Q...) clip at the bottom without this. Padding opens the
   box on each side and the matching negative margin keeps the flowed
   height/position unchanged. */
.ln,.msk{
  display:block; overflow:hidden;
  padding:.16em 0 .18em; margin:-.16em 0 -.18em;
}
.msk{ display:inline-block; vertical-align:top }
.ln__i,.msk__i{ display:inline-block; will-change:transform }

/* ── placeholders ───────────────────────────────────────── */
.ph{ position:relative; display:block; overflow:hidden; background:var(--ph) }
.ph__fill{
  position:absolute; inset:-8% 0; display:block;
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255,255,255,.13), rgba(255,255,255,0) 60%),
    repeating-linear-gradient(135deg, rgba(0,0,0,.016) 0 34px, rgba(0,0,0,0) 34px 68px),
    var(--ph);
  will-change:transform;
}
.ph::after{
  content:attr(data-ph);
  position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
  font-size:var(--micro); letter-spacing:.16em; text-transform:uppercase;
  color:rgba(255,255,255,.5); z-index:2; pointer-events:none;
}
.ph__fill--img{
  background:var(--ph) url("../img/team-photo.jpg") center/cover no-repeat;
}
.ph--shade::before{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(to top, rgba(0,0,0,.42), rgba(0,0,0,0) 42%),
             linear-gradient(to bottom, rgba(0,0,0,.28), rgba(0,0,0,0) 26%);
}

/* ── loader ─────────────────────────────────────────────── */
.loader{ display:none }
.js .loader{
  position:fixed; inset:0; z-index:90; background:var(--paper);
  display:flex; align-items:center; justify-content:center; pointer-events:none;
}
.loader__bar{
  width:min(30vw,360px); height:2px; background:var(--ink);
  transform-origin:left center; transform:scaleX(0);
}

/* ── header ─────────────────────────────────────────────── */
.hdr{
  position:fixed; inset:0 0 auto 0; z-index:40;
  display:flex; align-items:flex-start; justify-content:space-between;
  padding:var(--pad);
  /* Always white + mix-blend-mode:difference (kononenkogroup.com's header
     trick): the browser inverts per-pixel against whatever is directly
     behind it — difference(white, black bg) = white, difference(white,
     white bg) = black — so the logo/nav stay legible over any background
     (photo, video, gradient, light or dark section) with no JS section
     tracking needed. Replaces the old per-section .is-light toggle, which
     only ever knew a section's nominal light/dark flag, not what was
     actually painted behind the header at that scroll position. */
  color:#fff; mix-blend-mode:difference;
  transition:opacity .45s var(--ease);
}
/* Always visible now — the header no longer hides near the footer or while
   scrolling down. JS still toggles .is-gone/.is-away at the same triggers as
   before; these are kept as harmless no-ops rather than ripping out that
   logic, so re-enabling the old behaviour later is a one-line revert. */
.hdr.is-gone,
.hdr.is-away{ opacity:1; pointer-events:auto }
.mark{
  display:block; line-height:0; color:inherit;
}
.mark__svg{
  display:block; width:auto; height:clamp(20px,2.3vw,30px);
  color:currentColor;
}
.nav{ font-size:var(--nav); display:flex; gap:.28em; align-items:baseline }
.nav__a{ position:relative }
.nav__a.is-on{ text-decoration:underline; text-underline-offset:.22em }
.nav__a::after{
  content:""; position:absolute; left:0; right:0; bottom:-.2em; height:1px;
  background:currentColor; transform:scaleX(0); transform-origin:left;
  transition:transform .4s var(--ease);
}
.nav__a:hover::after{ transform:scaleX(1) }

/* ══════════════════════════ 1 · hero ══════════════════════
   Scroll pulls back from one frame to the whole wall, then the wall washes
   out to white and hands off to the statement below. The section is tall and
   the pin is what you actually see. */
/* 560, not 320: the section now runs two acts — pull back to the wall and wash
   white, then return, travel one tile diagonally and land on it. 320/560 is
   HERO_SPLIT in main.js, which keeps the opening act's on-screen scroll
   distance exactly what it was before the return was added. */
.hero{ position:relative; height:150svh }
.hero__pin{
  position:sticky; top:0; height:100svh; overflow:hidden;
  background:var(--paper);
}
.hero__grid{
  position:absolute; top:50%; left:50%;
  transform:translate(-50%,-50%);
  transform-origin:50% 50%;
  display:grid;
  /* the gutters ARE this background — white, not the pin showing through */
  background:var(--paper);
  will-change:transform;
  /* columns/rows and the gap are written by main.js so the cell aspect stays
     put across viewports */
}
.hero__cell{
  position:relative; overflow:hidden;
  background:var(--ph);              /* grey placeholder until artwork lands */
  will-change:opacity;
}
.hero__cell video,
.hero__cell img{
  position:absolute; left:0; top:-11%;
  width:100%; height:122%; object-fit:cover; display:block;
}
/* The source film is letterboxed: measured 28px of pure black top and bottom on
   a 360px frame, 7.8% a side, identical in every clip. object-fit:cover on an
   exactly-fitting box still shows them — the element fills, the PICTURE does
   not — so the video has to overscan past its box to crop them. 122%/-11%
   clears it with room to spare. */

.hero__title{
  position:absolute; left:var(--pad); bottom:calc(var(--pad) + .4vw); z-index:7;
  color:#fff; font-size:64px; line-height:1.03; letter-spacing:-.022em;
  will-change:opacity;
}
.hero__title .ln__i.serif{ font-size:48px }

/* reduced motion: no pin, no zoom — just the first frame */
.no-motion .hero{ height:100svh }
.no-motion .hero__pin{ position:relative }

/* ══════════════════════ 2 · statement ═════════════════════ */
.stmt__head{ padding-inline:var(--pad) }
.stmt__notes{
  display:grid;
  grid-template-columns:26% 18% 8.5% 18% 1fr;
  margin-top:clamp(22px,2.4vw,44px);
  margin-bottom:clamp(60px,8vw,150px);
}

.stmt__notes p:nth-of-type(1),
.fact__notes p:nth-of-type(1){ grid-column:2 }
.stmt__notes p:nth-of-type(2),
.fact__notes p:nth-of-type(2){ grid-column:4 }

.stmt__notes p{
  font-size:var(--micro); line-height:1.42; color:var(--muted);
}


/* ══════════════════════ 2b · about ═══════════════════════ */
/* ═════════════════════ 2b · statement ═════════════════════
   Opens the page below the hero, running the full measure flush to both
   margins — same width the figures below occupy. */
.statement{
  background:var(--paper);
  padding:clamp(80px,9vw,170px) var(--pad) clamp(70px,8vw,150px);
}
.statement__t{
  font-family:var(--serif); font-weight:400;
  font-size:clamp(19px,2.1vw,42px); line-height:1.12; letter-spacing:-.006em;
}

/* ═══════════════════════ 2b2 · stats ══════════════════════
   Figures run the full measure, flush left with the statement above. Four
   across at desktop — with no label rail taking a third of the row, two
   columns would leave each figure stranded in half a viewport. */
.stats{
  background:var(--paper);
  padding:0 var(--pad) clamp(80px,9vw,170px);
}
.stats__grid{
  display:grid; grid-template-columns:repeat(4,1fr);
  column-gap:clamp(20px,2.4vw,48px);
}
/* Four across needs roughly 240px a column before the figures start colliding
   with their own captions; below that, drop to two and let the rows stack. */
@media (max-width:1100px){
  .stats__grid{ grid-template-columns:repeat(2,1fr) }
}
/* Hairline over each cell, matching .office's rules — the figures read as a
   table of record rather than as four floating cards. */
.stat{
  display:block;
  padding:clamp(14px,1.35vw,28px) 0;
  border-top:1px solid #e6e6e6;
}
.stat__n{
  display:block;
  font-family:var(--sans); font-weight:400;
  font-size:clamp(26px,2.9vw,58px); line-height:1.04; letter-spacing:-.035em;
}
.stat__l{
  display:block; margin-top:.55em;
  font-size:max(11px,.85vw); line-height:1.45; color:#9a9a9a;
}

/* ══════════════════════ offices table ═════════════════════
   The index no longer carries an offices section; these rules now serve only
   the list embedded in about.html's philosophy section, which supplies its
   own container, label, and dark treatment via .offices__list--dark. */
.offices__list{
  position:relative; flex:0 0 47.04%; margin-left:4.1%;
  isolation:isolate;
}
.offices__rows{ display:block }
.office{
  display:grid;
  grid-template-columns:28.7% 29.4% 40.8% 1.1%;
  align-items:baseline;
  padding:clamp(9px,.85vw,18px) 0;
  border-top:1px solid #e6e6e6;
  font-size:max(12px,.85vw); line-height:1.3;
  color:var(--ink);
}
.office:last-child{ border-bottom:1px solid #e6e6e6 }
.office__c,.office__a{ color:#9a9a9a }
.office__x{ justify-self:end; font-size:.92em; opacity:.55 }

/* the sliding card: a black plate that carries its own copy of the rows,
   so the type inverts exactly where the plate covers it */
.offices__mask{
  position:absolute; inset:0 0 auto 0; z-index:2;
  overflow:hidden; background:var(--ink);
  opacity:0; pointer-events:none;
  will-change:transform;
}
.offices__mask .office{
  border-top-color:transparent; color:#fff;
}
.offices__mask .office:last-child{ border-bottom-color:transparent }
.offices__mask .office__c,
.offices__mask .office__a{ color:#c9c9c9 }
.offices__mask .office__x{ opacity:1 }
.offices__rows--inv{ will-change:transform }

/* ═══════════════════ 3 · radial / inversion ═══════════════ */
.radial{ height:300vh; position:relative; background:var(--paper) }
.radial__pin{
  position:sticky; top:0; height:100svh; overflow:hidden;
  display:grid; place-items:center;
}
/* A centred SQUARE, not a stretched fill — the reference sizes its fan box to
   ~80% of the viewport height and lets the page breathe around it. The
   numbers ride at 1.06x the tip radius, outside the viewBox, so overflow has
   to stay visible. Rotation happens in the path data now, never as a CSS
   transform, so there is nothing to promote. */
.radial__svg{
  position:absolute; left:50%; top:50%;
  width:min(78svh,84vw); height:min(78svh,84vw);
  transform:translate(-50%,-50%);
  overflow:visible;
}
/* Soft haze behind the centre — the spokes converge and read as a hard knot
   without it. backdrop-filter so it blurs whatever the section currently is,
   which matters because this section inverts white -> black mid-scroll. */
.radial__haze{
  position:absolute; left:50%; top:50%;
  width:min(46vw,620px); aspect-ratio:1;
  transform:translate(-50%,-50%);
  border-radius:50%;
  backdrop-filter:blur(26px);
  -webkit-backdrop-filter:blur(26px);
  -webkit-mask-image:radial-gradient(circle at center, #000 0%, #000 34%, transparent 72%);
  mask-image:radial-gradient(circle at center, #000 0%, #000 34%, transparent 72%);
  pointer-events:none; z-index:1;
}
.radial__type{ z-index:2 }
/* stroke width and group opacity match the reference (0.94 / 0.5 on the
   masked group — the group carries the opacity now, not each path).
   Tick font-size is in SVG USER UNITS, so it scales with the box: 13 units in
   a ~1050px box is ~15px on screen. On a phone the box drops to ~345px and the
   same 13 units render at 4.5px — illegible — so the unit size climbs as the
   box shrinks. */
.radial__svg .spoke{ fill:none; stroke:currentColor; stroke-width:.94 }
.radial__svg .tick{ font-family:var(--sans); font-size:13px; letter-spacing:.06em; fill:currentColor }
@media (max-width:820px){
  .radial__svg{ width:min(64svh,84vw); height:min(64svh,84vw) }
  .radial__svg .spoke{ stroke-width:1.6 }
  .radial__svg .tick{ font-size:27px }
  .radial__haze{ width:min(72vw,620px) }
}
.radial__pin{ color:var(--ink) }
/* The two headlines swap by sliding through this window rather than
   cross-fading. Stacked in one grid cell, a fade left both readable at once
   over the mid-grey of the inversion — a double exposure. Clipping instead
   means only one is ever in view. Padding keeps descenders off the clip edge,
   the negative margin cancels it from layout. */
.radial__type{
  position:relative; z-index:2; display:grid; place-items:center;
  overflow:hidden; padding-block:.16em; margin-block:-.16em;
}
.radial__t{
  grid-area:1/1; text-align:center;
  font-size:clamp(30px,4.2vw,80px); line-height:1.06; letter-spacing:-.028em;
  will-change:transform;
}
/* parked below the window until the swap; travel exceeds 100% so the padded
   band is cleared too */
.radial__t--b{ color:#fff; transform:translateY(112%) }

/* ═══════════════════ 3a · TAP (pinned reveal) ═══════════════════
   Each word is CAP + REST; REST sits clipped to width:0 at rest so the row
   reads as the bare acronym "TAP", then main.js scrubs each REST open to
   its measured natural width as the section scrolls. */
.tap{ background:var(--paper); color:var(--ink); height:250vh; position:relative }
.tap__pin{
  position:sticky; top:0; height:100svh; overflow:hidden;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:clamp(40px,6vw,90px);
}
/* Visible only while the row still reads as the bare acronym — main.js
   fades this out the instant the letters start pulling apart into words. */
.tap__eyebrow{
  display:block; font-family:var(--sans); font-weight:400;
  font-size:clamp(26px,3.2vw,48px); color:var(--muted); text-align:center;
}
/* two nested layers so the one-off entrance zoom (main.js, on .tap__stage)
   and the continuous scroll-scrubbed "shrink to keep fitting" (main.js, on
   .tap__row, as the letters grow into full words) never fight over the
   same transform */
.tap__stage{ display:flex; align-items:center; justify-content:center; width:100% }
.tap__row{
  display:flex; align-items:baseline; justify-content:center;
  padding:0 var(--pad); gap:clamp(22px,5vw,84px);
  transform-origin:50% 50%;
}
.tap__word{ display:inline-flex; align-items:baseline }
.tap__cap,.tap__rest{
  font-family:var(--sans); font-weight:500;
  font-size:clamp(120px,28vw,460px); line-height:1; letter-spacing:-.02em;
  white-space:nowrap;
}
.tap__rest{ display:inline-block; overflow:hidden; width:0; will-change:width }

@media (max-width:820px){
  .tap{ height:auto }
  .tap__pin{ position:relative; height:auto; padding:22vh 0 }
  .tap__row{ flex-direction:column; gap:.1em }
  .tap__cap,.tap__rest{ font-size:clamp(34px,11vw,64px); white-space:normal }
  .tap__rest{ width:auto }
}
.no-motion .tap{ height:auto }
.no-motion .tap__pin{ position:relative; height:auto; padding:22vh 0 }
.no-motion .tap__rest{ width:auto }

/* ═════════════════════════ 3b · values (pinned) ═══════════════════════
   main.js crossfades .value__media/.value__copy pairs and replays the
   incoming headline's mask reveal at each of the two transitions.

   400vh, not 300: the pin eats one viewport, so the scroll-through distance
   is height - 100vh. At 300vh that left only 200vh for three stages, and the
   third one's turn began exactly as the pin released — Productivity was still
   arriving while the section scrolled away, so it never sat centred the way
   the first two do. 400vh gives a full 100vh hold per stage, third included. */
.value{ position:relative; height:220vh; color:var(--ink-i) }
.value__pin{ position:sticky; top:0; height:100svh; overflow:hidden }
.value__media{ position:absolute; inset:0 }
.value__media img{ width:100%; height:100%; object-fit:cover; display:block }
.value__scrim{
  position:absolute; inset:0; z-index:1;
  background:linear-gradient(180deg, rgba(0,0,0,.15), rgba(0,0,0,.5) 60%, rgba(0,0,0,.65));
}
.value__copy{
  position:absolute; inset:0; z-index:2; text-align:center;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:clamp(20px,2.6vw,35px);
  width:min(84vw,1148px); margin-inline:auto; padding:0 var(--pad);
}
.value__t{
  font-family:var(--sans); font-weight:500; color:#fff;
  font-size:clamp(48px,10.6vw,182px); line-height:1.05; letter-spacing:-.02em;
  margin:0;
}
.value__d{
  font-family:var(--sans); font-weight:400; color:#fff;
  font-size:clamp(17px,1.75vw,30px); line-height:1.27;
  max-width:52ch; margin:0;
}

/* ═════════════════ 4 · people &amp; process ════════════════ */
.eyebrow{
  display:block; font-size:var(--micro); line-height:1.3; color:var(--ink-i);
  margin-bottom:clamp(18px,2.4vw,44px);
}
.fact.fact--statement{
  /* top-aligned instead of the base .fact's centered content: the card trail
     below tracks this text's own position (see anchorY in main.js), so
     lifting the text off vertical-center is what keeps the trail fully
     inside the pinned viewport instead of running off the bottom edge. */
  justify-content:flex-start;
  padding:clamp(14vh,18vh,220px) var(--pad) clamp(26px,3.2vw,58px);
}
.fact--statement .d-serif{
  max-width:68%; transform-origin:left top;
  /* Measured directly off the live reference's own computed style: 85.67px
     at a 1394px viewport = 6.15vw, not 10.1vw. The old value ran the text at
     1.64x the reference's actual size — max-width was already right (68vw at
     6.15vw font reflows into the same four lines the reference hard-breaks
     into: "A studio shaped by" / "clarity, trust, and a" / "collective
     pursuit of" / "thoughtful design."), so only the size needed correcting. */
  font-size:clamp(38px,6.15vw,124px);
}
.fact--statement .eyebrow{ margin-bottom:clamp(14px,1.8vw,32px) }

/* ═══════════════ 5 · wheel + facts (pinned) ══════════════ */
.facts{ background:var(--void); color:var(--ink-i); height:260vh; position:relative }
.facts__pin{ position:sticky; top:0; height:100svh; overflow:hidden }

.wheel{
  position:absolute; inset:0;   /* just a stage — cards are placed per frame */
}
.wheel__i{
  position:absolute; top:50%; left:50%;
  top:0; left:0;
  width:18%; aspect-ratio:var(--ar,4/3);
  transform-origin:50% 50%;
  background:#4f4f4f;
  border-radius:clamp(10px,1.15vw,22px);
  overflow:hidden;
  /* promoted to its own layer so the per-frame transform is composited, not
     repainted — without this the ring judders once ~18 cards are moving */
  will-change:transform;
  transform:translateZ(0);
  backface-visibility:hidden;
}
.wheel__i img{
  display:block; width:100%; height:100%; object-fit:cover;
  border-radius:inherit;
}
.wheel__i::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  border-radius:inherit;
  background:linear-gradient(160deg, rgba(0,0,0,.06), rgba(0,0,0,.22));
}

.facts__list{
  position:absolute; left:0; top:50%; width:100%;
  will-change:transform;
}
/* Each stat owns a full viewport. That spacing is what lets a stat actually
   LEAVE the screen before the next one arrives — the rearrangement fires when
   a stat's bottom clears the top of the viewport, and at the old ~430px
   spacing it never got there, so there was no such moment to fire on. */
.fact{
  min-height:100svh;
  display:flex; flex-direction:column; justify-content:center;
  padding:clamp(26px,3.2vw,58px) var(--pad) clamp(26px,3.2vw,58px) 52%;
  will-change:opacity,transform;
}
.fact__n{
  /* measured off the reference at vw 1639: 149.388px / 9.115vw, line-height
     104.572px = .700em, letter-spacing -4.482px = -.030em. The tight .700
     is what pulls the label up under the number instead of leaving the gap
     we had at .96. */
  display:block; font-size:clamp(34px,9.1vw,182px); line-height:.700;
  letter-spacing:-.030em;
}
.fact__l{
  /* Reference: 100.73px at vw 1639 = 6.146vw, line-height 90.657px = .900em,
     letter-spacing -3.022px = -.030em. Capped at the same 2000px viewport the
     number caps at, so the pair stays in proportion: 6.146vw * 2000 = 123px. */
  display:block; font-family:var(--serif); font-weight:400;
  font-size:clamp(20px,6.15vw,123px); line-height:.900; letter-spacing:-.030em;
  color:#cfcfcf; margin-top:.02em;
  /* NOT padding-left: that pushed every line in, so "covered" sat under
     "Total area". Theirs offsets only the first line (margin-inline-start
     110.974px = 1.10em) and lets the rest return to the number's left edge. */
  padding-left:0; text-indent:1.10em;
}
.fact--lead{
  padding:clamp(26px,3.2vw,58px) var(--pad);
  text-align:center;
}
.fact--lead p{ max-width:92vw; margin-inline:auto }
.fact--lead .fact__n{ margin-right:.22em }
.fact--lead .fact__n,
.fact--lead .fact__l{
  display:inline; font-family:var(--sans); color:inherit;
  /* capped lower than the original 158px: that max was tuned for a short
     "2016 / Year of Foundation" pair, and the longer replacement sentence
     overran the viewport width at the same size */
  font-size:clamp(26px,5.2vw,100px); line-height:1.1;
  /* text-indent:0 so the stat rule above cannot shift this one. The lead sets
     the wheel's morph timing off its own rect, so its metrics must not move. */
  letter-spacing:-.035em; padding:0; margin:0; text-indent:0;
}

.fact__notes{
  display:grid;
  grid-template-columns:26% 18% 8.5% 18% 1fr;
  margin-top:clamp(18px,2.4vw,44px);
}
.fact__notes p{
  font-size:var(--micro); line-height:1.42; color:var(--muted-i);
}
/* single-note case (one continuous sentence instead of the original two
   short, separately-placed notes): drop the multi-column grid tuned for
   two side-by-side notes and constrain this to a tidy, centred measure
   instead of letting it stretch edge to edge. */
.fact__notes:has(p:only-child){
  display:block; max-width:min(640px,72%); margin-inline:auto; text-align:center;
}

/* ═════════════════════ 6b · case studies ═════════════════════ */
.cases{
  background:var(--paper); color:var(--ink);
  padding:clamp(70px,8vw,150px) var(--pad) clamp(90px,10vw,170px);
  border-top:1px solid #e6e6e6;
}
.cases__head{
  display:flex; align-items:flex-start; justify-content:space-between;
  gap:24px; margin-bottom:clamp(36px,4.5vw,64px);
}
.cases__headline{ text-align:left; max-width:640px }
.cases__eyebrow{
  display:block; font-size:var(--micro); letter-spacing:.08em;
  text-transform:uppercase; color:var(--muted);
  margin-bottom:clamp(10px,1.2vw,20px);
}
.cases__t{
  text-align:left; letter-spacing:-.02em; margin:0;
  font-family:var(--sans); font-weight:400;
  font-size:clamp(26px,3.2vw,48px); line-height:1.15;
}
.cases__nav{ display:flex; gap:10px; flex-shrink:0 }
.cases__arrow{
  width:44px; height:44px; border-radius:50%; border:1px solid #d8d8d8;
  background:none; display:grid; place-items:center; color:var(--ink);
  cursor:pointer; transition:background .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
.cases__arrow:hover{ background:var(--ink); color:var(--paper); border-color:var(--ink) }
.cases__arrow svg{ display:block }

.cases__track{
  display:flex; gap:clamp(14px,1.6vw,28px);
  overflow-x:auto; scrollbar-width:none; scroll-behavior:smooth;
}
.cases__track::-webkit-scrollbar{ display:none }

.case{
  flex:1 1 0%; min-width:220px; max-width:640px;
  display:flex; flex-direction:column; cursor:pointer;
  transition:flex-grow .6s var(--ease);
}
.case:hover, .case:focus-within{ flex-grow:2.6 }

.case__media{
  position:relative; aspect-ratio:4/3; overflow:hidden;
  background:#ececec; border-radius:2px;
}
.case__media img{
  width:100%; height:100%; object-fit:cover; display:block;
  transform:scale(1.001); transition:transform .6s var(--ease);
}
.case:hover .case__media img{ transform:scale(1.045) }
/* Optional per-card hover video (e.g. Prakash's card): sits over the photo,
   invisible until hovered, main.js plays/pauses it in sync with the fade. */
.case__video{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  opacity:0; transition:opacity .4s var(--ease); pointer-events:none;
}
.case:hover .case__video, .case:focus-within .case__video{ opacity:1 }

/* ── video popup ─────────────────────────────────────────── */
.video-modal{
  position:fixed; inset:0; z-index:100;
  display:flex; align-items:center; justify-content:center;
  padding:clamp(24px,6vw,80px) var(--pad);
  opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity .35s var(--ease), visibility 0s linear .35s;
}
.video-modal.is-open{
  opacity:1; visibility:visible; pointer-events:auto;
  transition:opacity .35s var(--ease), visibility 0s linear 0s;
}
.video-modal__backdrop{ position:absolute; inset:0; background:rgba(0,0,0,.86) }
.video-modal__box{ position:relative; z-index:1; width:min(90vw,1100px) }
.video-modal__video{
  display:block; width:100%; max-height:86vh; border-radius:4px; background:#000;
}
.video-modal__close{
  position:absolute; top:-48px; right:0; z-index:2;
  width:36px; height:36px; border-radius:50%;
  border:1px solid rgba(255,255,255,.4); background:none; color:#fff;
  font-size:22px; line-height:1; cursor:pointer;
  display:grid; place-items:center;
  transition:background .25s var(--ease), color .25s var(--ease);
}
.video-modal__close:hover{ background:#fff; color:#000 }
.case__bar{ display:block; height:4px; background:var(--accent,#8f7cf0); transition:height .3s var(--ease) }
.case:hover .case__bar{ height:6px }

.case__name{
  font-family:var(--sans); font-weight:400; font-size:clamp(18px,1.5vw,24px);
  letter-spacing:-.02em; margin:clamp(14px,1.6vw,22px) 0 .3em;
}
.case__role{ font-size:var(--micro); color:var(--muted); line-height:1.4; max-width:46ch }
.case__more{
  font-size:var(--micro); color:var(--ink); line-height:1.5; max-width:50ch;
  max-height:0; opacity:0; overflow:hidden; margin-top:0;
  transition:max-height .5s var(--ease), opacity .4s var(--ease), margin-top .5s var(--ease);
}
.case:hover .case__more, .case:focus-within .case__more{
  max-height:6em; opacity:1; margin-top:.6em;
}
/* ═════════════════ 6c · office / amenities ═════════════════
   A horizontal filmstrip driven by vertical scroll, over a static intro
   screen. The intro (.aslide-intro) fills the pinned viewport and never
   moves: black copy panel left, full-bleed photo right — that is the first
   screen, before any scrolling. The strip (.aslider__track) is ONE flex row
   parked just off the right edge, which JS translates leftwards; because it
   carries its own white background it slides in across the intro photo,
   covering it from the right, and then keeps going. No per-slide show/hide
   and no crossfade anywhere: the strip just moves, and the viewport is a
   window onto it.

   Per slide the three pieces are separate track columns in reading order
   (heading, image, caption) rather than a copy block beside the image. That
   is what gives the reference its rhythm — a heading arriving top-left, its
   image filling the middle, its caption trailing along the bottom while the
   NEXT heading is already entering from the right. */
.amenities{ position:relative; background:var(--void) }

/* Height is overwritten by JS to (viewport + one viewport of lead-in +
   horizontal distance) so the strip travels 1:1 with the wheel; the calc is
   the pre-JS fallback and keeps the page from jumping if the script never
   runs. */
.aslider{ position:relative; height:calc(8 * 100vh) }
.aslider__pin{ position:sticky; top:0; height:100svh; overflow:hidden; background:var(--paper) }

/* The static first screen. Sits under the strip, so the strip's white
   background is what wipes it away — the intro itself never moves. */
.aslide-intro{ position:absolute; inset:0; z-index:1; display:flex; align-items:stretch }
.aslide-intro__copy{
  flex:0 0 auto; width:min(49vw,760px);
  background:var(--void); color:var(--ink-i);
  display:flex; flex-direction:column; justify-content:center;
  gap:clamp(18px,2.4vw,32px);
  padding:0 var(--pad);
}
/* Takes whatever the copy panel leaves, and bleeds to the top, bottom and
   right edges of the viewport. */
.aslide-intro__media{ position:relative; flex:1 1 auto; min-width:0; overflow:hidden; background:#111 }
.aslide-intro__media img{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; display:block;
}

/* z-index above the intro, and its own opaque background: together those are
   what make the strip read as sliding in over the intro photo rather than
   appearing beside it. The left padding keeps the first heading off the
   white's leading edge as it arrives. */
.aslider__track{
  position:absolute; inset:0 auto 0 0; z-index:2; height:100%;
  display:flex; align-items:stretch; gap:clamp(40px,5vw,96px);
  padding-left:clamp(28px,3vw,60px);
  /* Matches main.js's trailing gutter (A_TAIL) — as PADDING, not just extra
     scroll travel, so the track's own white background still covers that
     gutter. It used to be travel-only: the strip's box (background included)
     is only as wide as its content, so scrolling A_TAIL px further than that
     ran the box itself off-screen before the scroll-through finished,
     exposing the never-moving .aslide-intro layer underneath — its black
     panel/photo flashing back in right at the end, reading as the slider
     "getting cut off". */
  padding-right:clamp(60px,8vw,120px);
  background:var(--paper);
  will-change:transform;
}
.amenities__t{
  text-align:left; letter-spacing:-.02em; margin:0; max-width:18ch;
  font-family:var(--sans); font-weight:400;
  font-size:clamp(28px,3.6vw,52px); line-height:1.12;
}
.amenities__d{
  font-size:clamp(15px,1.35vw,20px); line-height:1.5; color:var(--muted-i);
  max-width:40ch; margin:0; text-align:left;
}

/* Symmetric vertical padding: it is the slide's own inset that puts the
   image's top and bottom edges where they are, and the same box is what
   flex-start/flex-end align the heading and caption against — so heading
   top, image top, caption bottom and image bottom all line up. */
.aslide{
  flex:0 0 auto; color:var(--ink);
  display:flex; align-items:stretch; gap:clamp(40px,5vw,96px);
  padding:clamp(48px,7.6vh,110px) 0;
}
/* Deliberately narrow measure: the reference wraps even a short heading to
   two or more lines, which is what keeps the heading reading as a column of
   the strip rather than a banner running into the image. The top margin
   drops it below the image's top edge (and clear of the fixed header). */
.aslide__t{
  flex:0 0 auto; align-self:flex-start; width:min(24vw,340px);
  margin:clamp(10px,4.4vh,60px) 0 0;
  font-family:var(--sans); font-weight:400; color:var(--ink);
  font-size:clamp(28px,3.6vw,54px); line-height:1.14; letter-spacing:-.015em;
}
/* Full body size, ink, sentence case — in the reference the caption is a
   paragraph you are meant to read at the bottom of the frame, not the
   tracked-out micro label the card sections use. */
.aslide__d{
  flex:0 0 auto; align-self:flex-end; width:min(30vw,420px);
  margin:0; color:var(--ink);
  font-size:clamp(15px,1.5vw,24px); line-height:1.42;
}
.aslide__media{
  position:relative; flex:0 0 auto; align-self:stretch;
  width:min(55vw,860px);
  overflow:hidden; border-radius:2px;
  background:#ececec;
}
/* Oversized inside its frame so the internal pan (see main.js) has room to
   move the picture without ever exposing an edge: 12% of the frame's width
   of slack on each side against a pan that reaches 10.5%, so there is ~1.5%
   of margin left over for subpixel rounding at the extremes. */
.aslide__media img{
  position:absolute; left:-12%; top:-6%; width:124%; height:112%;
  object-fit:cover; display:block; will-change:transform;
  /* Which part of the photo survives the crop. The frames go portrait on a
     tall viewport while these photos are landscape, so cover throws away a
     lot of width — and dead centre is not always where the subject is. Per
     slide override with --focus on .aslide__media. Percentages, so the
     shift scales with however much overflow there actually is. */
  object-position:var(--focus,50%) var(--focus-y,50%);
}
@media (max-width:820px){
  .aslider{ height:auto }
  .aslider__pin{ position:relative; height:auto; overflow:visible }
  .aslider__track{
    position:relative; inset:auto; height:auto;
    flex-direction:column; gap:0; padding-left:0;
  }
  /* Stacked: copy panel, then the photo as a band under it, then the slides
     in a column — the horizontal wipe has nothing to wipe on one column. */
  .aslide-intro{ position:relative; inset:auto; flex-direction:column }
  .aslide-intro__copy{
    width:auto;
    padding:clamp(70px,18vw,110px) var(--pad) clamp(40px,10vw,64px);
  }
  .aslide-intro__media{ height:52vh; flex:0 0 auto }
  .amenities__t{ max-width:none }
  .aslide{
    flex-direction:column; align-items:flex-start;
    padding:clamp(40px,10vw,64px) var(--pad); gap:20px;
  }
  .aslide__t, .aslide__d{ width:auto; align-self:auto; max-width:44ch; margin:0 }
  .aslide__media{ width:100%; height:60vh; align-self:auto }
}

/* ═════════════════ 6d · scroll-activated text ═════════════════
   Adapted from Codegrid's "scroll-activated text blocks": three short
   statements sit in fixed columns; as the pinned section scrolls, each
   column's words mask out while the next column's words mask in — so the
   three ideas play in sequence rather than all at once. A velocity-reactive
   image marquee rides along the bottom of the same pin. */
.scrolltext{ background:var(--void); color:var(--ink-i); height:400vh; position:relative }
.scrolltext__pin{ position:sticky; top:0; height:100svh; overflow:hidden }

.scrolltext__title{
  position:absolute; left:var(--pad); top:clamp(28px,4vw,56px); z-index:1;
  max-width:min(70vw,780px); margin:0;
  font-family:var(--sans); font-weight:400;
  font-size:clamp(28px,3.8vw,56px); line-height:1.1; letter-spacing:-.01em;
}
.scrolltext__indicator{
  position:absolute; width:min(160px,14vw); height:1px; z-index:1;
  top:clamp(30px,4.3vw,58px); right:var(--pad);
  background:#2f2f2f;
}
.scrolltext__indicator::after{
  content:''; position:absolute; inset:0;
  background:#fff; transform-origin:left; transform:scaleX(var(--progress,0));
  will-change:transform;
}

.scrolltext__copy{
  position:absolute; left:0; top:50%; transform:translateY(-50%);
  width:100%; padding:0 var(--pad);
  display:flex; gap:clamp(18px,2.6vw,40px);
}
.scrolltext__block{ flex:1 }
.scrolltext__block p{
  font-family:var(--serif); font-weight:400;
  font-size:clamp(17px,1.7vw,26px); line-height:1.34; letter-spacing:-.006em;
  margin:0;
}
.scrolltext__block p .word{ will-change:transform }

.scrolltext__marquee{
  position:absolute; left:0; bottom:clamp(20px,2.8vw,36px); width:100%;
  height:clamp(130px,16vw,230px); overflow:hidden;
  display:flex; align-items:center;
}
.scrolltext__track{ display:flex; gap:14px; will-change:transform }
.scrolltext__item{
  flex:none; width:clamp(200px,22vw,320px); height:100%;
  border-radius:2px; overflow:hidden; background:var(--ph-dark);
}
.scrolltext__item img{ width:100%; height:100%; object-fit:cover; display:block }

/* static fallback (phone width, or reduced-motion): JS skips the pin and
   the word-mask entirely, so the track never gets a transform — let it
   scroll natively instead of clipping the later images away */
@media (max-width:820px){
  .scrolltext{ height:auto }
  .scrolltext__pin{ position:relative; height:auto; padding:100px 0 40px; overflow:visible }
  .scrolltext__copy{ position:relative; top:auto; transform:none; flex-direction:column; gap:28px }
  .scrolltext__marquee{ position:relative; bottom:auto; margin-top:36px; overflow-x:auto; scrollbar-width:none }
  .scrolltext__marquee::-webkit-scrollbar{ display:none }
}
.no-motion .scrolltext{ height:auto }
.no-motion .scrolltext__pin{ position:relative; height:auto; padding:100px 0 40px; overflow:visible }
.no-motion .scrolltext__copy{ position:relative; top:auto; transform:none; flex-direction:column; gap:28px }
.no-motion .scrolltext__marquee{ position:relative; bottom:auto; margin-top:36px; overflow-x:auto; scrollbar-width:none }
.no-motion .scrolltext__marquee::-webkit-scrollbar{ display:none }

/* ═══════════════════════ 6 · brands ══════════════════════ */
.brands{ background:var(--void); color:var(--ink-i); height:200vh; position:relative }
.brands__pin{
  position:sticky; top:0; height:100svh; overflow:hidden;
  display:grid; place-items:center;
}
.brands__ring{
  position:absolute; inset:0;            /* fills the pin, so its LAYOUT box
                                            gives JS a resolvable size to read.
                                            No transform of its own — GSAP owns
                                            the scroll scale on this element. */
  will-change:transform;
}
/* The ring is an ELLIPSE, not a circle, and it is taller than it is wide.
   Measured off the reference: horizontal semi-axis 508px, vertical 563.5px in
   a 1394px viewport — B/A = 1.1085, A = 0.3646vw. That ratio is what reads as
   a ring lying back in 3D rather than a flat hoop. The vh term keeps it from
   running off a short window. */

.chip{
  position:absolute; left:50%; top:50%;
  will-change:transform,opacity;
  /* JS writes width/height/transform/opacity/z-index every frame */
}
.chip__i{
  display:block; width:100%; height:100%;
  border-radius:50%; overflow:hidden;
  background:#f8f8f8;                    /* the reference chip is a near-white disc */
  transform:translateZ(0);
  backface-visibility:hidden;
}
.chip__i img{ display:block; width:100%; height:100%; object-fit:cover }

/* Reference heading: 127px at a 1394px viewport (0.0911vw), leading 0.8167,
   block 804px wide = 0.577vw. The block has to stay narrower than the ring's
   1016px horizontal span or the words collide with the chips instead of
   sitting in the hole. z-index 2 puts it between the back and front chips. */
.brands__t{
  position:relative; z-index:2; text-align:center;
  width:min(57.7vw, 900px); max-width:none;
  margin-inline:auto; padding-inline:0;
  /* Reference sets 127px in an 804px block — but that block is 0.79 of the
     ring's 1016px span, and THAT proportion is what keeps the words inside the
     hole. Source Serif is wider than the reference face, so holding 0.577vw
     and trimming the type 6.7% (0.0911 -> 0.085vw) lands the same four lines
     inside the same proportion, rather than widening into the chips. */
  /* width and font-size are written by layoutBrands() from the ring's own A,
     so the words always sit inside the hole; these are the pre-JS fallback */
  font-size:clamp(28px, 8.5vw, 170px);
  line-height:.8167; letter-spacing:-.018em;
}

/* ═══════════════════════ 7 · footer ══════════════════════ */
.foot{ background:var(--void); color:var(--ink-i); height:170vh; position:relative }
.foot__inner{
  position:sticky; top:0; height:100svh;
  display:flex; flex-direction:column;
  /* Links at the TOP again — the header hides itself when the footer arrives,
     so there is nothing left to clear. The wordmark takes margin-top:auto, so
     the spare height sits between the links and the mark, the way the
     reference composes it (their columns sit 137px into a 1354px frame ≈ 10vh). */
  padding:clamp(44px,10vh,140px) var(--pad) clamp(12px,1.6vh,22px);
  overflow:hidden;
}
.foot__cols{
  display:flex; align-items:flex-start; gap:2.4%;
  font-size:var(--nav);
}
.foot__col{ flex:1 1 0; display:flex }
/* The label column is a FIXED width, not a share of the column: the reference
   starts every value exactly 107px right of its label at vw 1639 (6.53vw),
   which is what makes the four pairs read as aligned. The old 44% reservation
   scaled with the column and left each value stranded far from its label. */
.foot__k{ flex:0 0 clamp(84px,6.53vw,110px); color:var(--muted-i) }
.foot__v{ flex:1 1 0; display:flex; flex-direction:column; line-height:1.3 }
.foot__v a{ position:relative; width:fit-content }
.foot__v a.is-on{ text-decoration:underline; text-underline-offset:.22em }
.foot__v a:hover{ color:#b9b9b9 }
.foot__v p{ margin-top:1.5em }

/* flex:0 0 auto so the wrap hugs the wordmark rather than absorbing the spare
   height — space-between owns that gap now, so no margin is needed here. */
.foot__markwrap{
  flex:0 0 auto; display:flex; align-items:flex-end; justify-content:center;
  min-height:0;
  /* margin-top:auto is what pushes the mark (and the rights line after it) to
     the bottom and pools all the spare height above, between links and mark. */
  margin-top:auto;
  /* edge to edge: cancel .foot__inner's horizontal padding so the mark is not
     inset by --pad the way the columns are. */
  margin-inline:calc(var(--pad) * -1);
}
.foot__mark{
  display:flex; justify-content:center;
}
/* Full-bleed width at the bottom of the frame, in currentColor — the same
   white mark the header wears, as inline SVG so it takes the footer's ink. */
.foot__mark__svg{
  display:block; width:100%; height:auto; color:currentColor;
}

/* Below the mark, like the reference's bottom row: muted, --nav size, a
   small breath under the wordmark (theirs sits 17px below it). */
.foot__rights{
  flex:0 0 auto; font-size:var(--nav); color:var(--muted-i);
  padding-top:clamp(10px,1.6vh,20px);
}


/* ══════════════════════ ABOUT PAGE ══════════════════════ */
.is-about{ background:var(--void); color:var(--ink-i) }

/* 1 · hero */
.ahero{ position:relative; height:100svh; overflow:hidden }
.ahero__media{ position:absolute; inset:0; background:#4a4a4a }
/* The photo pans vertically inside this frame as the section scrolls — the
   internal parallax is driven by data-parallax on the fill (see "6 ·
   parallax" in main.js), and .ph clips it.

   The shared .ph__fill bleeds 8% a side, which is all the default drift
   needs; this one travels further than that, so without a deeper bleed the
   frame's own edge would swing into view at the extremes. 16% of slack
   against a pan that reaches 13.5% of the frame leaves ~2.5% spare for
   subpixel rounding. */
.ahero .ph__fill{ inset:-16% 0 }
.ahero__t{
  position:absolute; left:var(--pad); bottom:calc(var(--pad) + .4vw); z-index:3;
  max-width:min(78vw,900px);
  font-family:var(--sans); font-weight:400; color:#fff;
  font-size:64px; line-height:1.03; letter-spacing:-.022em;
}

/* 2 · philosophy + offices */
.phil{
  background:var(--void);
  display:flex; align-items:flex-start;
  padding:clamp(80px,11vw,200px) var(--pad) clamp(90px,12vw,220px);
}
.phil__k{
  flex:0 0 45%;
  font-family:var(--serif); font-size:max(12px,1.15vw); line-height:1.35;
  padding-top:clamp(50px,7vw,130px);
}
.phil__body{ flex:1 1 0; min-width:0 }
.phil__lede{
  font-family:var(--serif); font-weight:400;
  font-size:clamp(19px,2.1vw,42px); line-height:1.16; letter-spacing:-.006em;
  margin:0 0 1.1em;
}
.phil__lede:last-of-type{ margin-bottom:clamp(70px,9vw,170px) }

.offices__list--dark{ flex:none; margin-left:0; width:90% }
.offices__list--dark .office{ border-top-color:#2a2a2a; color:var(--ink-i) }
.offices__list--dark .office:last-child{ border-bottom-color:#2a2a2a }
.offices__list--dark .office__c,
.offices__list--dark .office__a{ color:#7d7d7d }
/* the plate inverts the other way on a dark page */
.offices__list--dark .offices__mask{ background:#fff }
.offices__list--dark .offices__mask .office{ color:var(--ink) }
.offices__list--dark .offices__mask .office__c,
.offices__list--dark .offices__mask .office__a{ color:#5e5e5e }

/* 3 · the team */
.mates{ background:var(--void); padding-bottom:clamp(80px,10vw,190px) }
.mates__head{ padding:clamp(70px,9vw,170px) var(--pad) clamp(46px,5.5vw,105px) }
.mates__t{
  text-align:center;
  font-size:clamp(44px,7.4vw,148px); line-height:.98; letter-spacing:-.035em;
}
.mates__notes{
  display:grid; grid-template-columns:28% 19% 5% 19% 1fr;
  margin-top:clamp(26px,3vw,56px);
}
.mates__notes p:nth-of-type(1){ grid-column:2 }
.mates__notes p:nth-of-type(2){ grid-column:4 }
.mates__notes p{
  font-size:var(--micro); line-height:1.42; color:var(--muted-i); text-align:center;
}
.mates__grid{
  display:grid; grid-template-columns:repeat(4,1fr);
  gap:clamp(40px,4.4vw,84px) clamp(8px,.9vw,18px);
  padding-inline:var(--pad);
}
.mate{ display:block }
/* the row is staggered, as in the reference */
.mate--0{ margin-top:0 }
.mate--1{ margin-top:calc(3.2vw) }
.mate--2{ margin-top:calc(6.4vw) }
.mate--3{ margin-top:calc(1.6vw) }
.mate__ph{
  display:block; position:relative; overflow:hidden;
  aspect-ratio:4/5; background:#4a4a4a;
}
.mate__ph img{ display:block; width:100%; height:100%; object-fit:cover }
.mate__cap{
  display:flex; justify-content:space-between; gap:8px;
  margin-top:calc(10px + .5vw);
  font-size:var(--micro); line-height:1.3;
}
.mate__cap span:last-child{ color:var(--muted-i) }

/* 4 · founder */
.founder{
  background:var(--void); color:var(--ink-i);
  display:flex; align-items:flex-start;
  padding:clamp(70px,9vw,170px) var(--pad) clamp(80px,10vw,190px);
}
.founder__ph{
  flex:0 0 23.5%; margin:0;
  overflow:hidden; background:#4a4a4a; aspect-ratio:1/1;
}
.founder__ph img{ display:block; width:100%; height:100%; object-fit:cover }
.founder__q{ flex:1; margin:0 0 0 8.9%; padding-top:.2em }
.founder__quote{
  font-family:var(--serif); font-weight:400;
  font-size:clamp(19px,2.1vw,42px); line-height:1.12; letter-spacing:-.006em;
}
.founder__cite{
  display:block; margin-top:clamp(18px,2vw,34px);
  font-style:normal; font-size:var(--micro); color:var(--muted-i);
}

@media (max-width:820px){
  .ahero__t{ font-size:clamp(24px,7vw,40px) }
  .phil{ flex-direction:column; gap:clamp(30px,6vw,60px) }
  .phil__k{ flex:0 0 auto; padding-top:0 }
  .mates__notes{ display:flex; flex-direction:column; gap:18px }
  .mates__notes p{ text-align:left }
  .mates__grid{ grid-template-columns:repeat(2,1fr) }
  .mate--1,.mate--2,.mate--3{ margin-top:0 }
  .founder{ flex-direction:column; gap:26px }
  .founder__ph{ flex:0 0 auto; width:62%; max-width:300px }
  .founder__q{ margin-left:0 }
}

/* ══════════════════════ responsive ══════════════════════ */
@media (max-width:820px){

  .stats__grid{ grid-template-columns:1fr }

  /* the pinned crossfade is STATIC on mobile — one screen, holding on
     Transparency — same convention as .facts; main.js skips building the
     stage scrollTriggers under this width. */
  .value{ height:100svh }

  .offices__list{ flex:1 1 auto; width:100%; margin-left:0 }
  .office{ grid-template-columns:1fr auto; row-gap:3px; padding-block:14px }
  .office__n{ grid-area:1 / 1 }
  .office__x{ grid-area:1 / 2 }
  .office__c{ grid-area:2 / 1 }
  .office__a{ grid-area:3 / 1 }
  .offices__mask{ display:none }

  .stmt__notes,
  .fact__notes{ display:flex; flex-direction:column; gap:22px }
  .stmt__notes p,
  .fact__notes p{ grid-column:auto }

  .radial{ height:230vh }
  .radial__t{ font-size:clamp(24px,7.4vw,44px) }

  /* ── the roll section is STATIC on mobile, like the reference's ──
     Their phone layout (measured at 375): no pin, no choreography — the
     statement, then the ring already FORMED around "2011 Year of Foundation"
     (9 cards, radius 140px = 37.3vw, evenly spaced from the top), the notes
     under the ring, then the four stats as a plain list (number 40px, label
     36px, ~60px between stats). JS skips the whole choreography under 820px
     and lays the ring out once; everything here is ordinary flow. */
  .fact--statement .d-serif{ max-width:100% }
  .facts{ height:auto }
  .facts__pin{ position:relative; height:auto; overflow:hidden }
  .facts__list{ position:relative; left:auto; top:auto; width:100% }
  .fact{ min-height:0; padding:clamp(24px,7vw,40px) var(--pad) }
  .fact.fact--statement{ padding:clamp(70px,18vw,110px) var(--pad) clamp(8px,2vw,16px) }
  .fact__n{ font-size:clamp(38px,10.7vw,48px) }
  .fact__l{ font-size:clamp(34px,9.6vw,44px) }
  .fact--lead{ padding:0 var(--pad) }
  /* the lead line reserves the ring's vertical band around itself:
     radius 37.3vw + half a card 8.7vw + a breath. Direct child only —
     the notes' paragraphs live inside .fact__notes and must NOT inherit
     this band (each once picked up 405px of padding from it). */
  .fact--lead > p{ display:block; padding-block:clamp(190px,54vw,240px) }
  .fact--lead .fact__notes p{ padding-block:0 }
  .fact--lead .fact__n,
  .fact--lead .fact__l{ font-size:clamp(36px,10.7vw,44px) }
  .fact__notes{ padding-left:0; margin-top:0;
    padding-bottom:clamp(40px,10vw,70px) }
  .fact__notes p{ text-align:center; margin-inline:auto; max-width:88% }
  .facts .wheel__i{ border-radius:10px }

  .brands__t{ max-width:100% }

  /* no hover on touch: cards stay equal width and snap-scroll instead,
     with the "more" note always visible since it can never be hovered in */
  .cases__head{ flex-direction:column; align-items:flex-start; gap:16px }
  .cases__t{ max-width:100% }
  .cases__track{ scroll-snap-type:x mandatory }
  .case{ flex:0 0 78%; scroll-snap-align:start }
  .case:hover{ flex-grow:0 }
  .case__more{ max-height:6em; opacity:1; margin-top:.6em }

  .foot{ height:150vh }
  /* the reference's phone footer: two columns, values BELOW their labels */
  .foot__cols{ display:grid; grid-template-columns:1fr 1fr;
    gap:clamp(28px,7vw,44px) 6% }
  .foot__col{ display:block }
  .foot__k{ display:block; margin-bottom:.7em }
  .foot__mark__svg{ width:100% }
}

.no-motion .radial__t--b{ display:none }
.no-motion .radial{ height:auto }
.no-motion .radial__pin{ position:relative; height:auto; padding-block:26vh }
.no-motion .facts{ height:auto }
.no-motion .facts__pin{ position:relative; height:auto; padding-block:12vh }
.no-motion .wheel{ display:none }
.no-motion .facts__list{ position:relative; left:auto; top:auto; width:100% }
.no-motion .brands{ height:auto }
.no-motion .brands__pin{ position:relative; height:auto; padding-block:20vh }
.no-motion .foot{ height:auto }
.no-motion .foot__inner{ position:relative; height:auto }

/* ═══════════════════════ 13 · contact page ═══════════════════════ */
/* The statement runs at display size so the page opens on the sentence
   itself rather than on a form. Centred, matching the reference. No fixed
   100svh: the block is as tall as the words need, and what follows starts
   right under them. */
.cintro{
  background:var(--paper); text-align:center;
  padding:clamp(110px,15vh,210px) var(--pad) clamp(50px,7vw,110px);
}
.cintro__t{
  max-width:22ch; margin:0 auto clamp(22px,2.8vw,38px);
  font-family:var(--serif); font-weight:400;
  font-size:clamp(34px,6.6vw,112px); line-height:1.05; letter-spacing:-.014em;
}
.cintro__d{
  max-width:54ch; margin:0 auto;
  font-family:var(--sans); font-weight:400; color:var(--muted);
  font-size:clamp(16px,1.4vw,21px); line-height:1.5;
}

/* ── how to reach us ──────────────────────────────────────────────
   Three columns, but only the middle one holds content: the value is
   centred on the page and the label is pushed to the inside edge of the
   left column, which is what hangs it in the gutter beside the value
   instead of indenting the value to make room for it. align-items:baseline
   sets the label on the value's FIRST baseline, so a value that wraps still
   has its label level with its opening line. */
.creach{
  background:var(--paper);
  padding:clamp(20px,3vw,44px) var(--pad) clamp(70px,9vw,150px);
}
.creach__row{
  display:grid; grid-template-columns:1fr auto 1fr;
  column-gap:clamp(18px,3vw,56px); align-items:baseline;
  padding:clamp(12px,1.8vw,26px) 0;
}
.creach__k{
  grid-column:1; justify-self:end; text-align:right;
  font-family:var(--sans); font-weight:400; color:var(--muted);
  font-size:var(--micro); line-height:1.3; letter-spacing:.03em;
}
.creach__v{
  grid-column:2; margin:0; text-align:center;
  font-family:var(--serif); font-weight:400; color:var(--ink);
  font-size:clamp(26px,4.6vw,76px); line-height:1.14; letter-spacing:-.012em;
}
/* Underline on hover only: at this size a permanent rule under every value
   would read as three heavy bars down the middle of the page. */
.creach__v a{
  color:inherit; text-decoration:none;
  transition:opacity .25s var(--ease);
}
.creach__v a:hover{ text-decoration:underline; text-underline-offset:.12em }

.cband{ background:var(--paper) }
.cband img{
  display:block; width:100%;
  height:clamp(280px,52vw,780px); object-fit:cover;
}

/* Same idiom as .creach__row, except the label is justified to the START of
   the left column — hard against the page edge, the way the reference sets
   it — rather than to the value. */
.caddr{
  background:var(--paper);
  display:grid; grid-template-columns:1fr auto 1fr;
  column-gap:clamp(18px,3vw,56px); align-items:baseline;
  padding:clamp(60px,8vw,130px) var(--pad) clamp(80px,10vw,170px);
}
.caddr__k{
  grid-column:1; justify-self:start;
  font-family:var(--sans); font-weight:400; color:var(--muted);
  font-size:var(--micro); line-height:1.3; letter-spacing:.03em;
}
.caddr__v{
  grid-column:2; margin:0; text-align:center;
  font-family:var(--serif); font-weight:400; color:var(--ink);
  font-size:clamp(24px,3.6vw,58px); line-height:1.18; letter-spacing:-.012em;
}

@media (max-width:820px){
  /* One column: the hanging label has nowhere to hang, so it sits above its
     value as a plain caption and everything aligns left. */
  .creach__row, .caddr{
    grid-template-columns:1fr; row-gap:.35em;
  }
  .creach__k, .caddr__k{
    grid-column:1; justify-self:start; text-align:left;
  }
  .creach__v, .caddr__v{ grid-column:1; text-align:left }
}

.connect{
  background:var(--void); color:var(--ink-i);
  padding:clamp(80px,10vw,170px) var(--pad);
}
.connect__head{ max-width:640px; margin-bottom:clamp(40px,5vw,64px) }
.connect__t{
  font-family:var(--serif); font-weight:400; margin:0 0 .5em;
  font-size:clamp(30px,4.2vw,60px); line-height:1.08; letter-spacing:-.012em;
}
.connect__d{
  font-family:var(--sans); font-size:clamp(15px,1.2vw,18px); color:var(--muted-i);
  line-height:1.5; margin:0;
}
.connect__list{ display:flex; flex-direction:column }
.connect__a{
  display:flex; align-items:center; justify-content:space-between;
  padding:clamp(18px,2.4vw,30px) 0; border-top:1px solid #2a2a2a;
  font-family:var(--serif); font-size:clamp(22px,3vw,44px); letter-spacing:-.01em;
  transition:opacity .25s var(--ease);
}
.connect__list .connect__a:last-child{ border-bottom:1px solid #2a2a2a }
.connect__a:hover{ opacity:.6 }
.connect__x{
  font-family:var(--sans); font-size:max(14px,1.1vw); flex-shrink:0; margin-left:1em;
}

.no-motion .radial__t--b{ display:none }
.no-motion .radial{ height:auto }
.no-motion .radial__pin{ position:relative; height:auto; padding-block:26vh }
.no-motion .facts{ height:auto }
.no-motion .facts__pin{ position:relative; height:auto; padding-block:12vh }
.no-motion .wheel{ display:none }
.no-motion .facts__list{ position:relative; left:auto; top:auto; width:100% }
.no-motion .brands{ height:auto }
.no-motion .brands__pin{ position:relative; height:auto; padding-block:20vh }
.no-motion .foot{ height:auto }
.no-motion .foot__inner{ position:relative; height:auto }

@media (prefers-reduced-motion:reduce){
  *{ animation-duration:.001s !important; transition-duration:.001s !important }
}

/* ═══════════════════════ 14 · careers page ═══════════════════════
   Layout follows figma.com/careers — hero, why-us, values, life, benefits,
   location, then the grouped openings — but every part is built out of this
   site's own pieces: the About page's .ahero and .phil, the contact page's
   hanging label/value pairing, and the .connect row for the listings. */
.is-careers{ background:var(--void); color:var(--ink-i) }

/* Its own crop of the office rather than the About page's team photo, so
   the two heroes are not the same picture twice. */
.ph__fill--careers{
  background:var(--ph) url("../img/services.png") center/cover no-repeat;
}
.ahero .ph__fill--careers{ inset:-16% 0 }

/* ── values and culture ───────────────────────────────────
   figma.com/careers' arrangement — heading, narrow intro, image-topped
   cards three to a row — in this site's colours and type.

   The row is TOP-aligned and every photo keeps its own aspect ratio, so the
   headings sit at different heights down the row. That stagger is the whole
   point of the layout: five equal cards on a shared baseline would read as
   a table of contents rather than a wall of moments. */
.vals{
  background:var(--void); color:var(--ink-i);
  padding:0 var(--pad) clamp(90px,12vw,200px);
}
.vals__head{ max-width:60ch; margin-bottom:clamp(44px,6vw,96px) }
.vals__t{
  font-family:var(--serif); font-weight:400; margin:0 0 .5em;
  font-size:clamp(30px,4.2vw,60px); line-height:1.08; letter-spacing:-.012em;
}
.vals__lede{
  margin:0; max-width:52ch;
  font-family:var(--sans); font-weight:400; color:var(--muted-i);
  font-size:clamp(15px,1.25vw,19px); line-height:1.5;
}
.vals__grid{
  display:grid; grid-template-columns:repeat(3,1fr);
  align-items:start;                      /* the stagger depends on this */
  gap:clamp(40px,5vw,88px) clamp(24px,3.4vw,60px);
}
.vals__img{
  display:block; width:100%; height:auto;  /* natural aspect, hence the stagger */
  margin-bottom:clamp(16px,1.8vw,28px);
  background:var(--ph-dark);
}
.vals__k{
  margin:0 0 .6em;
  font-family:var(--sans); font-weight:400; color:var(--ink-i);
  font-size:clamp(19px,1.9vw,28px); line-height:1.2; letter-spacing:-.012em;
}
.vals__d{
  margin:0; font-family:var(--sans); color:var(--muted-i);
  font-size:clamp(14px,1.15vw,17px); line-height:1.5;
}

/* ── life here: photo left, copy right ───────────────────── */
.clife{
  background:var(--void); color:var(--ink-i);
  display:flex; align-items:stretch; gap:clamp(24px,4vw,72px);
  padding:0 var(--pad) clamp(90px,12vw,200px);
}
.clife__media{
  flex:0 0 52%; position:relative; overflow:hidden;
  min-height:clamp(320px,44vw,620px); background:var(--ph-dark);
}
.ph__fill--life{
  background:var(--ph) url("../img/podcast.png") center/cover no-repeat;
}
.clife__copy{
  flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; justify-content:flex-end;
  padding-bottom:clamp(6px,1vw,18px);
}
.clife__t{
  font-family:var(--serif); font-weight:400; margin:0 0 .5em;
  font-size:clamp(28px,3.6vw,52px); line-height:1.08; letter-spacing:-.012em;
}
.clife__d{
  margin:0; max-width:38ch;
  font-family:var(--sans); font-size:clamp(15px,1.2vw,18px);
  line-height:1.5; color:var(--muted-i);
}

/* ── benefits ─────────────────────────────────────────────── */
.perks{
  background:var(--paper); color:var(--ink);
  padding:clamp(80px,11vw,180px) var(--pad) clamp(70px,9vw,150px);
}
.perks__t{
  font-family:var(--serif); font-weight:400; margin:0 0 clamp(36px,5vw,80px);
  font-size:clamp(30px,4.2vw,60px); line-height:1.08; letter-spacing:-.012em;
}
.perks__grid{
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:clamp(28px,3.4vw,60px) clamp(24px,3.4vw,60px);
}
.perks__i{ border-top:1px solid #e6e6e6; padding-top:clamp(14px,1.6vw,24px) }
.perks__k{
  display:block; margin-bottom:.8em;
  font-family:var(--sans); font-size:var(--micro); letter-spacing:.03em;
  text-transform:uppercase; color:var(--muted);
}
.perks__d{
  margin:0; font-family:var(--sans);
  font-size:clamp(15px,1.25vw,19px); line-height:1.45; color:var(--ink);
}

/* ── location: the contact page's hanging label/value ─────── */
.cloc{
  background:var(--paper); color:var(--ink);
  display:grid; grid-template-columns:1fr auto 1fr;
  column-gap:clamp(18px,3vw,56px); align-items:baseline;
  padding:0 var(--pad) clamp(90px,11vw,180px);
}
.cloc__k{
  grid-column:1; justify-self:start;
  font-family:var(--sans); color:var(--muted);
  font-size:var(--micro); line-height:1.3; letter-spacing:.03em;
}
.cloc__v{
  grid-column:2; margin:0; text-align:center;
  font-family:var(--serif); font-weight:400; color:var(--ink);
  font-size:clamp(22px,3vw,48px); line-height:1.18; letter-spacing:-.012em;
}

/* ── the openings ─────────────────────────────────────────── */
.jobs{
  background:var(--paper); color:var(--ink);
  padding:0 var(--pad) clamp(60px,8vw,120px);
  /* the header is fixed, so an anchor jump has to clear it */
  scroll-margin-top:clamp(56px,7vw,92px);
}
.jobs__head{ max-width:640px; margin-bottom:clamp(40px,5vw,72px) }
.jobs__t{
  font-family:var(--serif); font-weight:400; margin:0 0 .5em;
  font-size:clamp(34px,5.4vw,88px); line-height:1.04; letter-spacing:-.014em;
}
.jobs__d{
  margin:0; font-family:var(--sans); color:var(--muted);
  font-size:clamp(15px,1.2vw,18px); line-height:1.5;
}
/* ── search + team filters ────────────────────────────────
   Only rendered under .js: without the script they would be dead furniture
   in front of a list that reads perfectly well on its own. */
.jobf{ display:none }
.js .jobf{
  display:flex; flex-wrap:wrap; align-items:center;
  gap:clamp(14px,1.6vw,22px) clamp(16px,2vw,28px);
  margin-bottom:clamp(30px,4vw,64px);
}
/* A ruled field rather than a boxed one — the same hairline the job rows
   and the old form inputs use, so it belongs to this page. */
.jobf__search{ flex:1 1 240px; max-width:340px; display:block }
.jobf__input{
  width:100%; border:0; border-bottom:1px solid var(--ink); border-radius:0;
  background:none; padding:.55em 0; outline:none;
  font-family:var(--sans); font-size:clamp(14px,1.05vw,16px); color:var(--ink);
  -webkit-appearance:none; appearance:none;
}
.jobf__input::placeholder{ color:var(--muted) }
.jobf__input:focus-visible{ border-bottom-width:2px; padding-bottom:calc(.55em - 1px) }

.jobf__chips{ display:flex; flex-wrap:wrap; gap:8px }
/* Same pill as the values sound toggle, inverted for light ground. */
.jobf__chip{
  display:inline-flex; align-items:flex-end; gap:.5em;
  padding:.55em 1em; border:1px solid #dcdcdc; border-radius:999px;
  background:none; color:var(--ink); cursor:pointer;
  font-family:var(--sans); font-size:var(--micro); letter-spacing:.03em;
  text-transform:uppercase; line-height:1.3; white-space:nowrap;
  transition:background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.jobf__chip:hover{ border-color:var(--ink) }
.jobf__chip.is-on{ background:var(--ink); border-color:var(--ink); color:var(--paper) }
.jobf__n{ font-size:.86em; opacity:.5 }
/* A team with nothing left after a search is still worth showing as a
   disabled option — hiding chips would make the row jump on every keystroke. */
.jobf__chip[disabled]{ opacity:.32; cursor:default }
.jobf__chip[disabled]:hover{ border-color:#dcdcdc }

.jobf__count{
  margin:0 0 0 auto; flex-shrink:0;
  font-family:var(--sans); font-size:var(--micro); letter-spacing:.03em;
  text-transform:uppercase; color:var(--muted);
}

.jobs__none{
  margin:0; padding:clamp(24px,3vw,44px) 0; border-top:1px solid #e6e6e6;
  font-family:var(--sans); font-size:clamp(15px,1.2vw,18px); color:var(--muted);
}
.jobs__none a{ color:var(--ink) }

.jobs__group + .jobs__group{ margin-top:clamp(44px,5.5vw,88px) }
.jobs__k{
  margin:0 0 clamp(8px,1vw,16px);
  font-family:var(--sans); font-weight:400; color:var(--ink);
  font-size:clamp(20px,2.2vw,32px); line-height:1.2; letter-spacing:-.012em;
}
.jobs__list{ display:flex; flex-direction:column }
/* The .connect row, inverted for light ground: title left, meta right, rule
   above, and the whole row is the target rather than just the words. */
.job{
  display:flex; align-items:baseline; justify-content:space-between; gap:1.5em;
  padding:clamp(15px,1.9vw,26px) 0; border-top:1px solid #e6e6e6;
  color:var(--ink); text-decoration:none;
  transition:opacity .25s var(--ease);
}
.jobs__list .job:last-child{ border-bottom:1px solid #e6e6e6 }
.job:hover{ opacity:.55 }
/* main.js hides non-matching rows via the hidden attribute; without this,
   the unconditional display:flex above outranks the UA's [hidden] rule and
   the row stays on screen regardless of what the filter/search decided. */
.job[hidden]{ display:none }
.job__t{
  font-family:var(--serif); font-weight:400;
  font-size:clamp(18px,1.9vw,30px); line-height:1.2; letter-spacing:-.008em;
}
.job__meta{
  flex-shrink:0; display:flex; align-items:baseline; gap:clamp(10px,1.4vw,26px);
  font-family:var(--sans); font-size:var(--micro); color:var(--muted);
  letter-spacing:.03em; text-transform:uppercase;
}
.job__x{ font-size:max(13px,1vw); color:var(--ink) }

/* ── job detail + apply (careers.js) ─────────────────────────
   Toggled in place of .jobs via [hidden] when the URL carries a ?job= id.
   Neither this nor .applyf sets its own `display` override, so the [hidden]
   attribute's default display:none is left free to actually hide it —
   see the .job[hidden] rule above for why that matters. */
.jobdetail{
  background:var(--paper); color:var(--ink);
  padding:clamp(60px,8vw,120px) var(--pad) clamp(90px,11vw,180px);
  scroll-margin-top:clamp(56px,7vw,92px);
}
.jobdetail__back{
  display:inline-block; margin-bottom:clamp(30px,4vw,56px);
  font-family:var(--sans); font-size:var(--micro); letter-spacing:.03em;
  text-transform:uppercase; color:var(--muted);
  transition:color .2s var(--ease);
}
.jobdetail__back:hover{ color:var(--ink) }

.jobdetail__head{ max-width:760px; margin-bottom:clamp(36px,4.5vw,64px) }
.jobdetail__t{
  font-family:var(--serif); font-weight:400; margin:0 0 .4em;
  font-size:clamp(30px,4.6vw,72px); line-height:1.06; letter-spacing:-.014em;
}
.jobdetail__meta{
  display:flex; flex-wrap:wrap; gap:clamp(10px,1.4vw,26px);
  margin:0; font-family:var(--sans); font-size:var(--micro); color:var(--muted);
  letter-spacing:.03em; text-transform:uppercase;
}
.jobdetail__meta span:empty{ display:none }

.jobdetail__body{
  display:grid; grid-template-columns:1fr 1fr; gap:clamp(28px,4vw,56px);
  max-width:960px; padding-top:clamp(28px,3.4vw,48px);
  border-top:1px solid #e6e6e6; margin-bottom:clamp(48px,6vw,88px);
}
.jobdetail__desc{
  grid-column:1 / -1; margin:0 0 clamp(8px,1vw,16px);
  font-family:var(--serif); font-size:clamp(17px,1.4vw,22px); line-height:1.45;
  max-width:70ch;
}
.jobdetail__desc:empty{ display:none }
.jobdetail__k{
  margin:0 0 .6em; font-family:var(--sans); font-weight:400;
  font-size:clamp(14px,1.05vw,17px); letter-spacing:.01em;
}
.jobdetail__list{
  margin:0; padding:0; list-style:none;
  font-family:var(--sans); color:var(--muted);
  font-size:clamp(14px,1.05vw,16px); line-height:1.55;
}
.jobdetail__list li{ padding-left:1.1em; position:relative; margin-bottom:.5em }
.jobdetail__list li::before{ content:"\2013"; position:absolute; left:0; color:var(--ink) }
.jobdetail__col:has(.jobdetail__list:empty){ display:none }

/* ── apply form ───────────────────────────────────────────── */
.applyf{
  max-width:640px; display:grid; grid-template-columns:1fr 1fr;
  gap:clamp(20px,2.4vw,32px);
}
.applyf__t{
  grid-column:1 / -1; margin:0 0 .2em;
  font-family:var(--serif); font-weight:400;
  font-size:clamp(22px,2.4vw,32px); letter-spacing:-.012em;
}
.applyf__field{ display:flex; flex-direction:column; gap:.5em }
.applyf__field--wide{ grid-column:1 / -1 }
.applyf__label{
  font-family:var(--sans); font-size:var(--micro); color:var(--muted);
  letter-spacing:.03em; text-transform:uppercase;
}
.applyf__input{
  width:100%; border:0; border-bottom:1px solid var(--ink); border-radius:0;
  background:none; padding:.55em 0; outline:none; resize:none;
  font-family:var(--sans); font-size:clamp(14px,1.05vw,16px); color:var(--ink);
  -webkit-appearance:none; appearance:none;
}
.applyf__input::placeholder{ color:var(--muted) }
.applyf__input:focus-visible{ border-bottom-width:2px; padding-bottom:calc(.55em - 1px) }
.applyf__textarea{ resize:vertical; min-height:4.4em }

.applyf__submit{
  grid-column:1 / -1; justify-self:start; margin-top:.4em;
  padding:.85em 1.8em; border:1px solid var(--ink); border-radius:999px;
  background:var(--ink); color:var(--paper); cursor:pointer;
  font-family:var(--sans); font-size:var(--micro); letter-spacing:.03em;
  text-transform:uppercase;
  transition:background .2s var(--ease), color .2s var(--ease);
}
.applyf__submit:hover{ background:none; color:var(--ink) }
.applyf__submit[disabled]{ opacity:.5; cursor:default; pointer-events:none }

.applyf__status{
  grid-column:1 / -1; margin:0; min-height:1.4em;
  font-family:var(--sans); font-size:var(--micro); color:var(--muted);
}
.applyf__status.is-error{ color:#b3261e }

/* ── open application ─────────────────────────────────────── */
.capply{
  background:var(--paper); color:var(--ink);
  padding:clamp(50px,7vw,110px) var(--pad) clamp(90px,11vw,180px);
}
.capply__row{
  display:grid; grid-template-columns:1fr auto 1fr;
  column-gap:clamp(18px,3vw,56px); align-items:baseline;
}
.capply__k{
  grid-column:1; justify-self:end; text-align:right;
  font-family:var(--sans); color:var(--muted);
  font-size:var(--micro); line-height:1.3; letter-spacing:.03em;
}
.capply__v{
  grid-column:2; margin:0; text-align:center;
  font-family:var(--serif); font-weight:400;
  font-size:clamp(26px,4.6vw,76px); line-height:1.14; letter-spacing:-.012em;
}
.capply__v a{ color:inherit; text-decoration:none }
.capply__v a:hover{ text-decoration:underline; text-underline-offset:.12em }

@media (max-width:820px){
  /* Two up on tablet, one on phone — the stagger still reads at two. */
  .vals__grid{ grid-template-columns:repeat(2,1fr) }
  .perks__grid{ grid-template-columns:1fr }
  .clife{ flex-direction:column }
  .clife__media{ flex:0 0 auto; min-height:58vw }
  .cloc, .capply__row{ grid-template-columns:1fr; row-gap:.35em }
  .cloc__k, .capply__k{ grid-column:1; justify-self:start; text-align:left }
  .cloc__v, .capply__v{ grid-column:1; text-align:left }
  /* The meta drops under the title rather than squeezing it to nothing. */
  .job{ flex-direction:column; align-items:flex-start; gap:.5em }
  .jobf__search{ max-width:none; flex-basis:100% }
  .jobf__count{ margin-left:0 }
  .jobdetail__body{ grid-template-columns:1fr }
  .applyf{ grid-template-columns:1fr }
}
@media (max-width:560px){
  .vals__grid{ grid-template-columns:1fr }
}
