/* Catholic Leaders in Action — 2026-09-03.

   A port of the sequel.co system onto CLIA's own material. The owner asked for
   that site, exactly, with our copy and our photographs, and named the parts
   they wanted: the hero video, the video tiles from "We bring value to
   founders", the statistics, the bento off /membership, the Instagram grid and
   social icons off /stories.

   Every number here was measured off the live site, not eyeballed. Sources:
   research/refero/sequel.md §"Ground-truth cross-check" for the token layer,
   research/sequel/HOME.md for per-section geometry, research/sequel/MOTION.md
   for the motion. Four findings did the most work:

     · the footer is #0d0d0d with a #2c2c2c inset rule, not pure black;
     · #333/#999 are not in their system — de-emphasis is white at 0.75–0.94;
     · there is one accent in the whole site, #f5f5f0, and it is only ever a
       filled button;
     · section headings are 32px. Not 57px. Their .subtitle clamp
       (2rem, 2.2vw, 4.2rem) never clears its own floor below a 1454px
       viewport, so every H2 on that site is locked at 32px, and the page
       reads large because of whitespace and photography, not type size.
       The hero is 57.6px and the footer wordmark is 128px; those two are the
       only display sizes on the page.

   Two substitutions, both forced by licensing: VisueltPro → General Sans
   (ITF Free Font License), Bradford italic → Newsreader italic (SIL OFL).
   Chosen on letterform comparison; the reasoning is at the end of
   research/refero/sequel.md. */

/* Registered so the engine knows their type. An unregistered custom property
   inherits, so writing these on .believe-card invalidated its whole subtree
   sixty times a second. --r/--sx/--sy/--bo are deliberately NOT registered:
   .believe-card::after reads all four, and a pseudo-element inherits from its
   originating element — a non-inheriting property would never reach it and the
   hairline would stop scaling. An engine that cannot parse the at-rule ignores
   it and everything behaves exactly as it does today. */
@property --ix{syntax:"<length>";inherits:false;initial-value:0px}
@property --iy{syntax:"<length>";inherits:false;initial-value:0px}
@property --o {syntax:"<number>";inherits:false;initial-value:1}
/* Same defect as --ix/--iy had, in the other half of the file and unfixed until
   now: main.js §12 writes --mx/--my on .btn on every pointermove, and while
   they were unregistered they inherited — so each write invalidated the
   button's whole subtree (the label span and the arrow <svg>) at pointer rate.
   inherits:false is the entire point. Deliberately no transition on either:
   research/ui-2026/PLAN.md item 14 killed the lagged specular and it stays
   killed. The initial values are the lamp's, so a button that has never been
   pointed at rests where the fixed light is rather than at its own centre. */
@property --mx{syntax:"<percentage>";inherits:false;initial-value:18%}
@property --my{syntax:"<percentage>";inherits:false;initial-value:0%}

/* ─── §0 the two faces ──────────────────────────────────────────────────── */

@font-face{font-family:'General Sans';font-weight:300;font-style:normal;font-display:swap;src:url(assets/fonts/GeneralSans-300.woff2) format('woff2')}
@font-face{font-family:'General Sans';font-weight:400;font-style:normal;font-display:swap;src:url(assets/fonts/GeneralSans-400.woff2) format('woff2')}
@font-face{font-family:'General Sans';font-weight:500;font-style:normal;font-display:swap;src:url(assets/fonts/GeneralSans-500.woff2) format('woff2')}
@font-face{font-family:'Newsreader';font-weight:400;font-style:italic;font-display:swap;src:url(assets/fonts/Newsreader-italic.woff2) format('woff2')}
/* Numerals only. General Sans ships no tnum table, so `font-variant-numeric:
   tabular-nums` was doing nothing and the stat counters visibly jittered as
   they counted — a 1 advances 11.5px where an 8 advances 22.9px. Satoshi has
   the table, and at these sizes nobody can tell the two faces apart on digits. */
@font-face{font-family:'Satoshi';font-weight:300;font-style:normal;font-display:swap;src:url(assets/fonts/Satoshi-300.woff2) format('woff2')}
@font-face{font-family:'Satoshi';font-weight:500;font-style:normal;font-display:swap;src:url(assets/fonts/Satoshi-500.woff2) format('woff2')}

/* ─── §0b the fallback that wears General Sans's metrics ────────────────────
   Every face is font-display:swap and the stack fell back to system-ui, which
   is 8.1% wider and 10% shorter in the ascender — so the hero headline painted
   in the system font and then jumped when the real face landed. Measured
   advance ratios against General Sans 500: Helvetica Neue .9831, Arial 1.0171,
   both inside 1.7%, so there is no size-adjust to maintain and no per-platform
   number. The real mismatch is vertical, and these three overrides are General
   Sans's own metrics on its 1000 upem, exact on every platform.
   local() never downloads, so this costs nothing. */
@font-face{
  font-family:'General Sans fallback';
  src:local('Helvetica Neue'),local('Arial'),local('Helvetica');
  ascent-override:101%;
  descent-override:24%;
  line-gap-override:10%;
}

/* ─── §1 tokens ─────────────────────────────────────────────────────────── */

:root{
  color-scheme:dark;
  --bg:#000000;
  --surface:#202020;        /* every tile and card */
  --chip:#2a2a2a;
  --footer-bg:#0d0d0d;
  --footer-rule:#2c2c2c;

  --accent:#f5f5f0;
  --accent-hover:#e5e5e0;

  --text:#ffffff;
  --text-94:rgba(255,255,255,.94);
  --text-75:rgba(255,255,255,.753);
  --text-70:rgba(255,255,255,.7);
  /* .4 is 3.66:1 on black — below AA — and it is not the reference's either:
     their text ink ladder is .94/.90/.851/.753/.70 and rgba(255,255,255,.4)
     appears once, as a social-icon stroke, never as text. .48 computes to
     4.92:1 on #000 and 5.00:1 on the footer's #0d0d0d. */
  --text-40:rgba(255,255,255,.48);

  --glass:rgba(200,200,200,.1);
  --glass-edge:rgba(255,255,255,.2);
  --rule:rgba(255,255,255,.15);      /* their hairline, on stats and the card */

  --sans:'General Sans','General Sans fallback',system-ui,-apple-system,'Segoe UI',sans-serif;
  --serif:'Newsreader',Georgia,'Times New Roman',serif;

  /* Their four curves, by role. The first is the signature — long tail, almost
     no ease-in — and is reserved for links and the scrubbed moves. */
  --ease-sig:cubic-bezier(.625,.05,0,1);
  /* The comments were right and the values were one power order off. Sampled
     at 1000 points, the old --ease-2 was 16.8% from power2.out and 2.2% from
     power3.out — it WAS power3; the old --ease-3 was 13.2% from power3 and is
     power4. That is 6px of position error on a 36px line and 9.5px on a 72px
     block, on every reveal on the page. These solve to 0.19% of the analytic
     curves. */
  --ease-2:cubic-bezier(.5,1,.89,1);        /* power2.out — text reveals */
  --ease-3:cubic-bezier(.33,1,.68,1);       /* power3.out — block reveals */
  --ease-mat:cubic-bezier(0,0,.2,1);        /* the footer's long arrival */
  --ease-in:cubic-bezier(.55,.085,.68,.53);  /* power2.in — the menu's iris */
  --ease-inout:cubic-bezier(.455,.03,.515,.955); /* power2.inOut — the burger */
  --t-fast:.2s;
  --t:.3s;
  /* The response clock, and it is not the same job as --t. --t is for moves the
     visitor is meant to WATCH; --t-resp is an object acknowledging a pointer,
     which at 300ms reads as "a thing animated" and at 160ms as "the thing
     responded". Measured off live stylesheets this pass: Linear's button is
     160ms on cubic-bezier(.25,.46,.45,.94), family.co's is 100ms, and Vero's
     300ms is on `color` alone with everything else at 650ms/1s and deliberate.
     Ours had 300ms on the response, which is the literal thing that made the
     hover read as an animation rather than as material. */
  --t-resp:.16s;
  --ease-out-quad:cubic-bezier(.25,.46,.45,.94);  /* power2.out — the response */

  /* The one number the whole page's rhythm comes from, and the one that spoils
     it: the pinned stage centres a 16:9 card in a 100svh box, so there is an
     empty half-band above and below it that stacks on the neighbouring
     section's padding. Naming it lets the two sections either side subtract it
     instead of guessing. */
  --band-gap:clamp(150px,30vh,300px);
  --believe-void:calc((100svh - (min(1200px,100vw) - 2*clamp(20px,5vw,32px)) * .5625) / 2);

  /* Smoothstep in space — the same idea as the --ease-* curves in time.
     alpha = 1 − (3t² − 2t³) has zero slope at BOTH ends, so the fade has no
     findable termination edge over dark photography, and it integrates to
     exactly 0.5: the same total ink as the linear ramp it replaces, so the
     collage is no lighter than the reference's. */
  --feather:var(--bg) 0%,rgba(0,0,0,.957) 12.5%,rgba(0,0,0,.844) 25%,
    rgba(0,0,0,.684) 37.5%,rgba(0,0,0,.5) 50%,rgba(0,0,0,.316) 62.5%,
    rgba(0,0,0,.156) 75%,rgba(0,0,0,.043) 87.5%,transparent 100%;

  /* the column every block on the page is measured against */
  --col:min(1136px,100vw - 2 * clamp(20px,5vw,32px));

  --gutter:clamp(24px,4vw,80px);
  /* 600px is their number for a face wider than ours: at 17.6px the same box
     gives them 66 characters a line and us 77. Scaled to their count. */
  --measure:515px;      /* body copy */
  --heading:800px;      /* headings */
  --wide:1200px;        /* the card grid */
}

/* ─── §1c the lamp ──────────────────────────────────────────────────────────
   The reference describes its own material as a single warm lamp in an
   otherwise unlit cinema. A lamp has a position, and it does not move when you
   move your head. Ours did: every button lit from the pointer, which means the
   page had no lighting at all until you touched something and none whatsoever
   on a phone — and a highlight nailed to the cursor reads as a sticker on the
   cursor rather than as a surface catching light.

   So there is now one fixed light, upper-left and just above the horizon, and
   every convex object on the page — the three pill sizes, the play control, the
   badges, the six bento cells, the two photo cards, the video and quote tiles,
   the six crew cards — catches it from the same place. The rim brightens on the
   arc facing it and darkens on the arc away from it. The tints are Linear's
   measured numbers off EdgeShine.BKCmF3VB.css: 6% white for the general case,
   12% for the step up; their --edge-highlight-x/y are likewise STATIC, set by
   class, never written by script.

   Nothing here animates, so nothing here runs on the compositor and nothing
   here needs to: these are static paints, rasterized once per element and held
   in the layer. Zero per-frame cost, zero JS, and — the whole point — fully
   present on touch, under prefers-reduced-motion, and in a screenshot, which is
   where most people see this page first.

   The shadow carries the lamp's temperature. Ours were rgba(0,0,0,.35): a black
   shadow on a black page draws nothing, which is why the objects sat ON the
   page instead of IN it. Vero's key/bounce pair is orange at 3.9% from upper
   left and deep red at 3.1% from lower right; the principle is theirs and the
   value is ours — the key is our own accent's temperature (#f5f5f0, warm
   off-white) rather than an orange this palette does not contain, and it sits
   below the amplitude at which anyone would name a hue.

   The bounce is gone, and it went for the reason it should: it was measured.
   Rendering the whole page twice with only --lamp-bounce neutralised
   (tools/_shadowcensus.mjs --diff) moved 8,177 pixels out of 23.1 million, and
   moved them by ONE level of 255 at the 90th percentile and two at the 99th.
   That is a shadow layer on nineteen elements, at 34-52px of blur, painting
   something no eye resolves. The key, measured the same way, moves 13,183
   pixels by 2/4/5 levels at p50/p90/p99 — thin, but present, and it is the one
   that reads as light coming from somewhere. So the page keeps the half of the
   pair that draws and drops the half that does not: nineteen fewer non-inset,
   two-axis box-shadow layers, 57 down to 38 at 1440, against a §7.5 rule the
   base build was already over. An unlit room does return a bounce; a room this
   dark, at 4% of a desaturated grey, returns it below the floor of vision. */
:root{
  --lamp-x:18%;                              /* where the light sits, in the object's own box */
  --lamp-y:0%;
  --lamp-rim:rgba(255,255,255,.06);
  --lamp-rim-strong:rgba(255,255,255,.12);
  --lamp-shade:rgba(0,0,0,.28);
  --lamp-key:rgba(245,238,214,.055);         /* the key, warm, upper-left */
  /* The arc: a duplicate of the object's own edge, masked so only the ~90°
     facing the lamp survives. Named once so every host reads the same shape. */
  --lamp-arc:radial-gradient(ellipse 60% 90% at var(--lamp-x) var(--lamp-y),
    #000 0%,#000 8%,transparent 88%);
}

/* Everything with a radius and a body catches the arc. Deliberately NOT on
   .believe-card, whose ::after is the scaled hairline the file header
   documents, nor on .perk or .fcard, which live inside transformed marquee and
   collage layers. -webkit-mask ships alongside mask for Safari; if both were
   dropped the ring would paint unmasked at 12% white, which is a mild
   over-brightening rather than a break.

   And deliberately NOT on .ccard. The rim is drawn as a masked 1px border, and
   the crew card is the one surface on this page that is not allowed to compute
   a border at all — nor a box-shadow, nor a background-image, which rules out
   every other way of drawing an edge here (a gradient rim would also be a
   fourth gradient background-image outside #top/#voice, which §7.6's ninth tell
   forbids on its own). That constraint is not an accident to route around: the
   crew card is the only text-only plate on the page, §12b states its rest state
   as "no scale, no lift, no shadow, no border, no colour change", and the lamp
   model is about convex objects catching light off their own edge. A flat
   typographic plate at --surface has no edge to catch it. So it does not take
   the rim, and its lighting is the one it always had: the value step between
   #202020 and the black page around it. */
.cell::after,.pcard::after,.vtile::after,.qtile::after,
.badge:not(.btn)::after{
  content:'';position:absolute;inset:0;z-index:4;pointer-events:none;
  border:1px solid var(--lamp-rim-strong);border-radius:inherit;
  -webkit-mask:var(--lamp-arc);mask:var(--lamp-arc);
}
.qtile{position:relative}

/* ─── §2 base ───────────────────────────────────────────────────────────── */

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

html{
  scrollbar-gutter:stable;
  /* Nothing here paints. It stops the page's scroll chaining into browser
     chrome: -x:none keeps a horizontal flick over the two marquees off
     swipe-back navigation (neither is a scroll container, and the viewport has
     no horizontal scroll to consume it), -y:contain blocks Android
     pull-to-refresh — which matters because a reduced-motion phone runs native
     scroll with no Lenis at all. `contain`, not `none`, so iOS keeps its rubber
     band; killing that is what makes a page feel like a webview. */
  overscroll-behavior-x:none;
  overscroll-behavior-y:contain;
  background:var(--bg);
  color:var(--text);
  font-family:var(--sans);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

/* ─── §2b the smooth-scroll layer ───────────────────────────────────────────
   The reference runs Lenis at duration 1.2 on an expo-out curve, and every
   other piece of motion on the page inherits its lag — a 300px wheel tick
   settles at t50 252ms / t90 523ms / t99 887ms (research/sequel/MOTION.md
   §2.1). Without it the same reveals fire against a hard, native scroll and
   read as jumpy no matter how well tuned they are. These four rules are the
   library's own; `scroll-behavior` must be `auto` or the browser's smooth
   scroll fights Lenis on every anchor jump. */
/* ─── §2c what the browser is allowed to skip ───────────────────────────────
   The owner's phone stutters, and the cause is not any one component — an
   ablation across backdrop-filter, the collage, will-change, the videos and the
   blurs moved the number by a few points each. It is the document: eleven
   full-viewport sections of photography, all of it laid out, styled and rastered
   whether or not it is anywhere near the screen.

   content-visibility lets the browser skip all of that for a section it is not
   showing. Measured at 390x844 on a 6x-throttled CPU, scrolling the whole page:
   frames over budget fell from 63% to 24%, and p90 from 25.7ms to 17.3ms. For
   scale, the reference itself measures p50 25.1ms / p90 75.1ms / 74% over budget
   under the identical harness — this is now the faster of the two by a distance.

   `auto` on contain-intrinsic-size is what keeps it honest: the guess below is
   only used until a section has been rendered once, after which the browser
   remembers the real height, so the scrollbar does not lurch. #believe is
   excluded — it contains the sticky pinned stage, and containment and sticky do
   not mix. Nothing here changes what anything looks like. */
@media (prefers-reduced-motion:no-preference){
  #about,#voices,#record,#evening,#team,#seat,#stories,
  #upcoming,#past,footer.foot{content-visibility:auto}
  /* Measured heights, not a blanket guess. The guess is what the scrollbar and
     an anchor jump are computed against before a section has ever rendered, so
     a flat 1200px put the #evening anchor 771px past its mark. These are the
     real numbers at 1440; the phone column below carries its own. */
  #about  {contain-intrinsic-size:auto 1076px}
  #voices {contain-intrinsic-size:auto 947px}
  #record {contain-intrinsic-size:auto 953px}
  #evening{contain-intrinsic-size:auto 1526px}
  /* #team moved to /team/ and #upcoming/#past are that page's neighbours on
     /events/. All three are measured on the pages they now live on, with
     containment off, not carried over from the section #team used to be:
     the old 814/1133 were 25% and 16% out once the section became a page.
     #next-up is deliberately absent — it is the first section on its page and
     containment on the thing that is already on screen is a pessimization. */
  /* Re-measured with containment off every time this section's contents change,
     because this number is what the scrollbar and a cross-page anchor are
     computed against before #team has ever rendered. 652/981 predated the
     card's media field; 1680/2421 predated the sequel hero and Saul's career.
     Now 2435.1 at 1440 and 3319.0 at 390. */
  #team   {contain-intrinsic-size:auto 2435px}
  #seat   {contain-intrinsic-size:auto 1304px}
  #stories{contain-intrinsic-size:auto 2109px}
  #upcoming{contain-intrinsic-size:auto 562px}
  #past   {contain-intrinsic-size:auto 284px}
  footer.foot{contain-intrinsic-size:auto 884px}
  @media (max-width:759px){
    #about  {contain-intrinsic-size:auto 1326px}
    #voices {contain-intrinsic-size:auto 1585px}
    #record {contain-intrinsic-size:auto 1755px}
    #evening{contain-intrinsic-size:auto 2366px}
    #team   {contain-intrinsic-size:auto 3319px}
    #seat   {contain-intrinsic-size:auto 1132px}
    #stories{contain-intrinsic-size:auto 1638px}
    #upcoming{contain-intrinsic-size:auto 536px}
    #past   {contain-intrinsic-size:auto 250px}
    footer.foot{contain-intrinsic-size:auto 1180px}
  }
}

html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}
.lenis.lenis-stopped{overflow:hidden}
html:not(.lenis){scroll-behavior:smooth}

body{margin:0;overflow-x:hidden;font-size:16px;line-height:1.5;font-weight:400}

img,video{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}

/* Hover does not exist on a phone, and there was not one :active rule in the
   stylesheet — every tap on this page landed with no acknowledgement. The press
   states themselves live in §15b: :active and :hover are both (0,2,0), so source
   order decides, and from here they lost every collision to hover rules hundreds
   of lines below. */
html{-webkit-tap-highlight-color:transparent}
h1,h2,h3,h4,p,figure,blockquote{margin:0}
ul,ol{margin:0;padding:0;list-style:none}

/* A single-colour ring cannot survive both grounds this page has: on black it
   needs to be light, and on the cream RSVP button a cream ring measured 1.00:1
   — invisible. Two tones, so one edge always has contrast. */
:focus-visible{outline:2px solid #000;outline-offset:0;
  box-shadow:0 0 0 5px var(--accent);border-radius:3px}
/* .btn-fill carries its own box-shadow and comes later in the file, so the ring
   has to out-specify it or it never paints on the one button that needs it. */
.btn:focus-visible,.play:focus-visible,.nav-toggle:focus-visible{
  border-radius:9999px;box-shadow:0 0 0 5px var(--accent),0 1px 2px rgba(0,0,0,.35),0 4px 20px rgba(0,0,0,.25)}
/* .fcard rests at 8px, so a 10px focus ring made a keyboard pass twitch; .cell
   is an <article> and not focusable at all. */
.fcard:focus-visible{border-radius:inherit}

::selection{background:var(--accent);color:#000}
::-moz-selection{background:var(--accent);color:#000}
html{scrollbar-color:rgba(255,255,255,.25) transparent}

.skip{position:absolute;left:-9999px;top:0;z-index:200}
.skip:focus{left:12px;top:12px;padding:10px 16px;background:var(--accent);color:#000;border-radius:9999px}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ─── §3 type ───────────────────────────────────────────────────────────── */

/* The signature move: one word per headline in the serif italic. Nothing else
   on the page is serif, and nothing anywhere is heavier than 500. */
/* The whole system rests on one move — a single serif-italic word inside a
   sans headline — and the substitute face was quietly losing it. Measured
   x-heights: their Bradford italic sits at 0.982 of VisueltPro; our Newsreader
   italic sat at 0.889 of General Sans, six times the deficit, so the accent
   word read a size smaller than the words either side of it rather than as a
   change of voice. font-size-adjust scales the face to the reference's own
   parity without touching the declared font-size, so the character split and
   every line-break calculation are untouched.
   The word-gap is theirs too: they tune it per context (.25em before the
   accent in a display line, .15em in a heading) rather than one flat number. */
.em{font-family:var(--serif);font-style:italic;font-weight:400;letter-spacing:-.05em;
  margin:0 .15em;font-size-adjust:ex-height .52}
/* letter-spacing applies after the LAST glyph too, so .em's -.05em pulls the
   next character back: at the hero's 57.6px that is -2.88px against a 1.15px
   margin, and the period collided with the italic. */
.hero h1 .em,.foot-line .em{margin-left:.25em;margin-right:.08em}
.believe-lines .em{margin:0 .1em}

/* Section heading. 32px at every desktop width — see the note at the top. */
.title{
  font-size:clamp(2rem,2.2vw,4.2rem);
  font-weight:500;line-height:1;letter-spacing:-.03em;
  max-width:var(--heading);text-wrap:balance;
}
.desc{
  font-size:1.1rem;font-weight:400;line-height:1.4;
  color:var(--text-75);max-width:var(--measure);
}
/* Eight one-word widows on the page, including "it." alone on a 32px display
   line. text-wrap:pretty costs nothing where it is unsupported. */
.desc,.pcard p,.pcard h3,.cell p,.cell h3,.cell .lineup li,
.qtile blockquote,.perk p,.stat .cap,.believe-lines li,.foot-fine{text-wrap:pretty}
/* Two different jobs were sharing one token. A badge on a photograph is 11px;
   the eyebrow that opens a section is 15.84px at +.07em on the reference, and
   ours was rendering both at 11.2px — which is why our section openings read
   quieter than theirs. */
.label{
  font-size:.7rem;font-weight:500;line-height:1.2;
  letter-spacing:.05em;text-transform:uppercase;color:var(--text);
}
.eyebrow{
  font-size:clamp(.9rem,1.1vw,1.1rem);font-weight:500;line-height:1.2;
  letter-spacing:.07em;text-transform:uppercase;color:var(--text);
}

/* ─── §3d figures inside all-caps ────────────────────────────────────────
   General Sans's default figures are lining at 676 units against a 718 cap, so
   in an uppercase line the numbers sit 42 units low — "AGES 21 TO 40" reads
   with the digits dropped. `case` substitutes the cap-height set. There is no
   high-level property for it, and naming only `case` leaves kern/liga/calt and
   font-variant-numeric alone. Inert on a string with no figures.
   NOT on .stat b or .count b: those are Satoshi, whose `case` table holds no
   figures at all, and they carry the tabular-nums that keeps the counters from
   jittering. */
.eyebrow,.label,.badge,.stat .cap,.illus,.seat-note,
.vtile .role,.qtile .role,.foot-base,.thero-cta,.tline-when{font-feature-settings:'case' 1}
/* The one glyph the font cannot fix: General Sans ships no cap-height middot,
   and the default sits .0925em below the cap band's centre. vertical-align
   rather than transform, so the glyph stays inline and line-breaking is
   untouched — 1px of extra inline box on a single-line label. */
.sep{vertical-align:.0925em}

/* ─── §4 buttons — the three-size pill ramp ─────────────────────────────── */

/* The lit pill. Every button is an object under §1c's one fixed lamp: a rim
   along the arc that faces it, a hairline of shade along the arc that does not,
   a tight contact shadow, and an ambient pair that carries the lamp's own
   temperature. On hover a specular highlight arrives — but it is now the moving
   half of a lighting model whose fixed half is always there, rather than the
   whole model. The highlight rests at the lamp, not at the button's centre, so
   it arrives at and departs from the light instead of teleporting to the
   middle; main.js §12 writes --mx/--my on pointermove and they are registered
   at the top of this file so the write no longer invalidates the label and the
   arrow with it.

   The clock is --t-resp (160ms), not --t (300ms). Nothing moves on its own,
   nothing overshoots. `filter` and `transform` are compositor properties;
   `box-shadow` and `color` are not, and are unchanged in kind, only halved in
   duration — so every hover repaint on this page is now half as long as it was
   and .btn-fill's is gone entirely. */
.btn{
  position:relative;isolation:isolate;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;
  border-radius:9999px;font-weight:500;white-space:nowrap;border:none;
  --mx:var(--lamp-x);--my:var(--lamp-y);
  transition:
    background-color var(--t-resp) var(--ease-out-quad),
    box-shadow       var(--t-resp) var(--ease-out-quad),
    transform        var(--t-resp) var(--ease-out-quad),
    filter           var(--t-resp) var(--ease-out-quad),
    color            var(--t-resp) var(--ease-out-quad);
}
.btn::before{
  content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  background:radial-gradient(120px circle at var(--mx) var(--my),var(--spec,rgba(255,255,255,.22)),transparent 62%);
  opacity:0;transition:opacity var(--t-resp) var(--ease-out-quad);
}
.btn:hover::before,.btn:focus-visible::before{opacity:1}
/* The rim, made directional. It used to be `inset 0 1px` over `inset 0 -1px` —
   symmetric, i.e. lit from directly overhead, which reads as a UI token rather
   than as an object in a room. Offsetting both on the diagonal puts the lit
   crescent on the arc facing §1c's lamp and the shaded crescent opposite it, on
   the same side as every card, badge and tile on the page. Static paint. */
.btn::after{
  content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  box-shadow:inset 1px 1px 0 var(--rim,var(--lamp-rim-strong)),
             inset -1px -1px 0 var(--shade,var(--lamp-shade));
}
.btn-sm{height:42px;padding:0 20px;gap:5px;font-size:.875rem}
.btn-md{height:45px;padding:0 24px;gap:7px;font-size:.9375rem}
.btn-lg{height:52px;padding:0 28px;gap:9px;font-size:1.0625rem}

/* The two ambient layers are the lamp's key and bounce, offset on the same
   diagonal as the rim: a black shadow on a black page is a shadow that draws
   nothing, which is the whole reason these objects read as stickers. The
   contact shadow stays black — that one is occlusion, not light.
   The hover brightens the fill with `filter` rather than swapping the
   background: brightness runs on the compositor, a background-color change
   repaints for the whole duration. --accent-hover (#e5e5e0) is 93.6% of
   --accent, so .936 lands on exactly the colour the token named. */
.btn-fill{background:var(--accent);color:#000;
  --rim:rgba(255,255,255,.75);--shade:rgba(0,0,0,.12);--spec:rgba(255,255,255,.9);
  box-shadow:-14px -4px 34px var(--lamp-key),0 1px 2px rgba(0,0,0,.35)}
.btn-fill:hover{filter:brightness(.936);transform:translateY(-2px);
  box-shadow:-16px -5px 40px var(--lamp-key),0 2px 4px rgba(0,0,0,.35)}

.btn-glass{background:transparent;color:var(--text);
  --rim:rgba(255,255,255,.22);--shade:rgba(0,0,0,.35);--spec:rgba(255,255,255,.16)}
.btn-glass:hover{background-color:rgba(255,255,255,.1)}

.glass{
  background:var(--glass);
  border:1px solid var(--glass-edge);
  box-shadow:-12px -3px 30px var(--lamp-key),
             0 6px 20px rgba(0,0,0,.3),inset 0 1px rgba(255,255,255,.08);
  border-radius:9999px;
}
/* Six of the fifteen glass elements sit on flat --bg — the four stat badges and
   the two opener buttons. Over a uniform field blur(20px) returns that field and
   saturate() on an achromatic backdrop is the identity, so those six were paying
   a GPU render-surface and a backdrop readback per frame to draw nothing. The
   filter stays wherever the backdrop is imagery. */
.hero .glass,          /* the play control, over the hero video */
.pcard .glass,         /* two badges and two buttons, over the photograph */
.believe-card .glass,  /* "Take a seat", over the nave */
.vtile .glass,         /* two badges, over playing video */
.cell .glass{          /* the countdown, over the lead cell's illustration */
  -webkit-backdrop-filter:blur(20px) saturate(1.4);
  backdrop-filter:blur(20px) saturate(1.4);
}
/* 7b — the five elements that are both .btn and .glass drew two 1px inset rims
   at the same pixel row: .08 under .22 composites to .28, three and a half times
   the reference's glass rim. The badges keep the ported .08. */
/* A glass button was casting a heavier shadow than the bone RSVP beside it, so
   the page's one accent object sat LOWER to the page than its secondary. */
.btn.glass{box-shadow:-10px -3px 26px var(--lamp-key),0 2px 10px rgba(0,0,0,.28)}

/* The signature curve is reserved for links. The arrow is a mechanism, and it
   was running the 735ms link curve compressed into 300ms; it now runs on the
   response clock with the rest of the pill. transform: compositor. */
.btn .arrow{width:1em;height:1em;flex:none;transition:transform var(--t-resp) var(--ease-out-quad)}
.btn:hover .arrow{transform:translateX(3px)}

/* Promote the layer at the moment of press, not permanently: a standing
   will-change on nine buttons is nine layers the compositor holds for the life
   of the page. Linear applies it exactly here and nowhere else. */
.btn:active{will-change:transform}

/* Badge: 35px tall, 8px/16px padding, 11.2px uppercase at .05em. */
.badge{
  position:relative;
  display:inline-flex;align-items:center;height:35px;padding:0 16px;
  background:var(--chip);border-radius:9999px;
  font-size:.7rem;font-weight:500;letter-spacing:.05em;text-transform:uppercase;
  color:var(--text);
}
.badge.glass{background:var(--glass)}

/* ─── §5 layout ─────────────────────────────────────────────────────────── */

.wrap{max-width:var(--wide);margin-inline:auto;padding-inline:clamp(20px,5vw,32px)}
section{position:relative}
/* Their section rhythm is a flat 30vh of padding-top between every major
   section and no padding-bottom — 270px on a 900-tall screen, 253px on a
   phone. We were running clamp(80px,10vw,150px) top AND bottom, which is 144px
   on the desktop it was tuned at and 80px on a phone: barely half their air,
   and the single biggest reason the page read as tight next to theirs. The
   clamp keeps it from running away on a very tall monitor. */
.band{padding-block:var(--band-gap) 0}
/* Nothing gets its own bottom air: the next section's padding-top is the gap,
   and anything added here double-counts against it. */

.opener{text-align:center;display:grid;justify-items:center;gap:24px}
.opener .title,.opener .desc{margin-inline:auto}
.opener .desc{max-width:min(var(--measure),92%)}

/* ─── §6 header ─────────────────────────────────────────────────────────── */

/* A gradient scrim sits behind the bar so the wordmark survives a bright
   frame of the hero video without the bar itself acquiring a background. */
/* Both this and .hero-media::after were tuned against a frame whose mean was
   170/255. The graded hero is 99, so the same scrims now over-darken a sky that
   is already dark and put a visible band across the top of the fold. Lightened
   to suit the footage. Measured on the composited page across eight frames of
   the clip, the RSVP pill against the pixels actually painted around it: 5.94:1
   worst at 1440 and 5.00:1 worst at 390, against a 4.5 floor. Before the grade,
   with the heavier scrims, the same measurement read 4.68 and 4.60. */
.nav-scrim{position:fixed;inset:0 0 auto;height:128px;z-index:98;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,.28),transparent)}

.nav{
  position:fixed;inset:0 0 auto;z-index:100;
  display:flex;align-items:center;justify-content:space-between;gap:24px;
  padding:24px;
}
@media (min-width:1024px){.nav{padding:40px}}
.nav-mark{display:flex;align-items:center;gap:10px;font-size:.9375rem;font-weight:500;letter-spacing:-.02em}
/* Inline, and painted with currentColor, so the mark is white on the hero
   video and inherits whatever the bar inherits — a PNG could do neither, and
   at 26px the old raster seal was mud. The pseudo-element is the 44px target. */
.nav-mark{position:relative}
.nav-mark::after{content:'';position:absolute;inset:-11px -8px}
.nav-mark .mark{width:22px;height:22px;flex:none}
.nav-mark span{display:none}
@media (min-width:560px){.nav-mark span{display:inline}}

/* The centre links fade out on scroll down and return on scroll up — the one
   piece of chrome on the reference that moves at all. */
.nav-links{display:none;gap:28px;font-size:1rem;font-weight:500;
  transition:opacity var(--t) ease-out}
.nav[data-hide] .nav-links{opacity:0;pointer-events:none}
@media (min-width:900px){
  .nav-links{display:flex;position:absolute;left:50%;transform:translateX(-50%)}
}
/* Their bar link hover is a colour move and nothing else: 90% white to full
   over 200ms. The underline wipe belongs to their footer, not up here. */
.nav-links a{color:rgba(255,255,255,.9);transition:color .2s cubic-bezier(.4,0,.2,1)}
.nav-links a:hover{color:#fff}

.nav-toggle{display:grid;place-items:center;width:42px;height:42px;border-radius:9999px;
  position:relative;z-index:101}
.nav-toggle:hover{background:rgba(255,255,255,.1)}
@media (min-width:900px){.nav-toggle{display:none}}

/* The burger folds into a cross rather than swapping glyphs: each bar rotates
   ±45° and travels half the gap, 300ms on power2.inOut. Two elements, because
   one two-line path cannot be rotated about its own centre. */
.burger{position:relative;display:block;width:18px;height:12px}
.burger i{position:absolute;left:0;width:18px;height:1.4px;background:currentColor;
  transition:transform .3s var(--ease-inout)}
.burger i:first-child{top:1px}
.burger i:last-child{top:9.6px}
.nav-toggle[aria-expanded="true"] .burger i:first-child{transform:translateY(4.3px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] .burger i:last-child{transform:translateY(-4.3px) rotate(-45deg)}
/* the wordmark steps aside for the overlay, on the same 300ms */
.nav-mark{transition:opacity .3s var(--ease-inout)}
.nav[data-menu] .nav-mark,.nav[data-menu] .btn{opacity:0;pointer-events:none}

/* The overlay is a circle opening from the burger itself — 500ms power2.in on
   the way in, 300ms on the way out, and the close is deliberately not a
   reverse (MOTION.md §1.6: open is 1.4s of choreography, close is ~500ms). */
/* The overlay had four links floating in the middle of an otherwise empty
   screen and no way to RSVP — you opened the menu and the one thing the site
   exists for was not in it. It is a screen now, not a list: numbered sections
   holding the top, and the evening's date, price and CTA holding the foot. */
.menu{
  position:fixed;inset:0;z-index:99;
  display:flex;flex-direction:column;justify-content:space-between;
  padding:96px var(--gutter) max(32px,env(safe-area-inset-bottom));
  background:rgba(0,0,0,.96);
  -webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);
  /* the burger's own centre: 24px of bar padding + half of the 42px control */
  --ox:calc(100% - 45px);--oy:45px;
  clip-path:circle(0px at var(--ox) var(--oy));
  visibility:hidden;
  transition:clip-path .3s var(--ease-in),visibility 0s linear .3s;
}
.menu[data-open]{
  visibility:visible;
  clip-path:circle(150% at var(--ox) var(--oy));
  transition:clip-path .5s var(--ease-in),visibility 0s;
}
.menu-nav{display:flex;flex-direction:column;gap:2px}
/* The label is its own box because splitChars turns each word into an element,
   and a flex gap would then apply between every word rather than between the
   index and the label. */
.menu-nav a{position:relative;display:flex;align-items:baseline;gap:14px;padding:6px 0;
  font-size:clamp(2rem,9vw,3rem);font-weight:500;letter-spacing:-.05em;line-height:1.2}
.menu-nav a .lbl{display:block}
/* The index sets the sections against each other and gives the eye a left edge
   to run down — the reference's own device on its founders list. */
.menu-nav a i{font-family:'Satoshi',var(--sans);font-style:normal;font-variant-numeric:tabular-nums;
  font-size:.7rem;font-weight:500;letter-spacing:.08em;color:var(--text-40);
  flex:none;width:2.2ch;transition:color var(--t) ease}
.menu-nav a:hover i,.menu-nav a:active i{color:var(--accent)}

.menu-foot{display:grid;gap:20px;justify-items:start;border-top:1px solid var(--rule);padding-top:28px}
.menu-next{font-size:.9375rem;line-height:1.5;color:var(--text-75)}
.menu-next .eyebrow{display:block;margin-bottom:8px;color:var(--text)}
.menu-foot .btn{align-self:stretch}
.menu-foot .socials{justify-content:flex-start;padding:0}

/* Menu links arrive character by character — 400ms, 20ms apart, each link
   starting 80ms after the one above it; on the way out they leave upward in
   150ms, which is what makes the close read as decisive rather than undone. */
/* filter:none is load-bearing. splitChars adds .split to these links too, so
   they were picking up the headline pre-state from §16 — blur(8px) — and the
   rule that clears it only ever fires on .in, which a menu link never gets.
   The links were rendering permanently out of focus. */
html.motion .menu-nav a .ch{opacity:0;transform:translateY(30px);filter:none;
  transition:opacity .15s var(--ease-2),transform .15s var(--ease-2)}
html.motion .menu[data-open] .menu-nav a .ch{opacity:1;transform:none;filter:none;
  transition:opacity .4s var(--ease-2),transform .4s var(--ease-2)}
/* leaving, they go out of the top — not back down the way they came */
html.motion .menu.closing .menu-nav a .ch{transform:translateY(-15px)}
html.motion .menu-foot{opacity:0;transform:translateY(20px);
  transition:opacity .3s var(--ease-2),transform .3s var(--ease-2)}
html.motion .menu[data-open] .menu-foot{opacity:1;transform:none;
  transition:opacity .5s var(--ease-3) .38s,transform .5s var(--ease-3) .38s}

/* ─── §7 hero ───────────────────────────────────────────────────────────── */

.hero{position:relative;height:100svh;min-height:600px;overflow:hidden}
.hero-media{position:absolute;inset:0;will-change:transform}
.hero-media video,.hero-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* Their overlay: dark at the very top for the bar, clear through the middle,
   dark again under the headline. Never a flat veil. */
.hero-media::after{
  content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.30) 0%,rgba(0,0,0,.07) 26%,transparent 46%,rgba(0,0,0,.26) 78%,rgba(0,0,0,.62) 100%);
}
.hero-inner{
  position:relative;z-index:2;height:100%;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:24px;
  padding:80px clamp(25px,5.5vw,80px) 7vh;
}
@media (min-width:900px){
  .hero-inner{flex-direction:row;align-items:flex-end;justify-content:center;gap:24px}
  .hero-left{flex-grow:1}
  .hero-aside{align-items:flex-end}
}
.hero-left{display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.hero h1{
  /* 3.6rem was the reference's *rendered value at 1440* pasted into the cap
     slot, so the headline froze at 57.6px on every larger monitor. Their cap
     is 6.5rem; the 3rem floor and the 4vw slope were already right. */
  font-size:clamp(3rem,4vw,6.5rem);
  font-weight:500;line-height:1;letter-spacing:-.05em;margin:0;
}
.hero-eyebrow{display:flex;align-items:center;gap:10px;color:var(--text-75)}
.hero-eyebrow .dot{width:6px;height:6px;border-radius:50%;background:var(--accent);flex:none}

.hero-aside{display:flex;flex-direction:column;gap:28px;align-items:flex-start;max-width:320px}
.hero-aside .desc{font-size:1.1rem;line-height:1.4;color:var(--text-94);max-width:320px}
@media (max-width:899px){
  .hero-inner{align-items:center;text-align:center}
  .hero-left{align-items:center}
  .hero-aside{flex-direction:column-reverse;align-items:center;text-align:center}
}

.play{display:inline-flex;align-items:center;gap:9px;height:44px;padding:0 20px 0 7px;font-size:.875rem;font-weight:500;
  position:relative;isolation:isolate;overflow:hidden;--mx:var(--lamp-x);--my:var(--lamp-y)}
.play::before{content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;
  background:radial-gradient(120px circle at var(--mx) var(--my),rgba(255,255,255,.16),transparent 62%);
  opacity:0;transition:opacity var(--t-resp) var(--ease-out-quad)}
.play:hover::before{opacity:1}
/* The same directional rim the pills carry, so the one control on the hero is
   lit from where everything else on the page is lit. Static paint. */
.play::after{content:'';position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  box-shadow:inset 1px 1px 0 var(--lamp-rim-strong),inset -1px -1px 0 var(--lamp-shade)}
.play .disc{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.15);flex:none;transition:background-color var(--t-resp) var(--ease-out-quad)}
.play .disc svg{width:9px;height:9px;margin-left:1px}
.play:hover .disc{background-color:rgba(255,255,255,.28)}

.hero-time{
  position:absolute;z-index:2;left:var(--gutter);top:calc(50% - .5em);
  font-size:.6875rem;letter-spacing:.07em;color:var(--text-40);
  font-family:'Satoshi',var(--sans);font-variant-numeric:tabular-nums;
}
@media (max-width:899px){.hero-time{display:none}}

/* ─── §8 statement + the two photo cards ────────────────────────────────── */

.statement{text-align:center;display:grid;justify-items:center;gap:24px}

/* A grid, not a flex-wrap: `flex:1 1 360px` fitted two 360px cards at exactly
   800px, so the pair went from 560px stacked at 799 to 360px side by side at
   800 — 59% less photograph as the window grew one pixel. Two columns to 1024,
   one below, and the cards fill whichever they are in. */
.duo{display:grid;grid-template-columns:repeat(2,1fr);gap:16px;margin-top:clamp(72px,15vh,150px)}
@media (max-width:1024px){.duo{grid-template-columns:1fr;max-width:500px;margin-inline:auto}}
.pcard{
  position:relative;overflow:hidden;border-radius:10px;
  max-width:560px;aspect-ratio:1/1;background:var(--surface);
  display:flex;flex-direction:column;justify-content:flex-end;gap:12px;padding:24px;
  isolation:isolate;
}
/* The photograph pans with the scroll the whole time the card is on screen —
   the reference's geometry (top:-50%, height:150%) gives it half a card of
   travel; the scrub is in main.js §6. Nothing happens on hover: their cards
   carry a button too and their image still does not move. */
/* `>` and <picture> do not mix: wrapping each <img> for a WebP source pushed
   every one of these a level deeper, and a child combinator stopped matching —
   seven photographs on this page were rendering at their intrinsic size,
   unpositioned and stretched. display:contents keeps the wrapper out of layout;
   the selectors have to name both shapes because <video> is not wrapped. */
picture{display:contents}
/* The crop point, defaulting to exactly today's rendering. Paint-time only, so
   it cannot cause reflow, and with no --op set nothing moves. sept-group is
   1420x743 in a 2:3 box, so a default centre crop discards 65% of a fifty-person
   group photograph — the values are a judgement for a human, the hook is not. */
.pcard picture img,.cell picture img,.believe-card picture img,
.fcard img,.perk img{object-position:var(--op,50% 50%)}
.pcard>img,.pcard>picture>img,.pcard>video{position:absolute;left:0;top:-50%;z-index:-2;width:100%;height:150%;
  object-fit:cover;will-change:transform}
.pcard::before{
  content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(0,0,0,.35) 0%,transparent 30%,rgba(0,0,0,.45) 62%,rgba(0,0,0,.85) 100%);
}
.pcard .badge{position:absolute;top:16px;right:16px;z-index:1}
.pcard h3{font-size:clamp(1.25rem,1.5vw,1.375rem);font-weight:500;letter-spacing:-.03em;line-height:1.2}
.pcard p{font-size:.8125rem;line-height:1.45;color:var(--text-94);max-width:46ch}
.pcard .btn{align-self:flex-start;margin-top:6px}

/* ─── §9 the manifesto stage ────────────────────────────────────────────── */

/* Their defining move. The card begins at exactly the width of the two-card
   grid above it, with the same 10px radius and a 1px hairline, so it reads as
   one of those cards growing into the whole screen. It expands to 100vw over
   the first quarter of the section, holds while five statements roll past on a
   three-dimensional drum, then contracts back to a card on the way out. */
/* Measured: this boundary was 130px on the way in and 400px on the way out
   against a 270px median (576px at 390) — the card's empty half-band adding
   itself to #voices' full 30vh. Both sides now subtract it. */
.believe{height:425vh;padding-top:max(0px,calc(var(--band-gap)*.667 - var(--believe-void)))}
#voices{position:relative;z-index:1;padding-top:0;
  margin-top:calc(var(--band-gap) - var(--believe-void))}
.believe-stage{position:sticky;top:0;height:100svh;display:grid;place-items:center;overflow:hidden}
/* The card used to BE the size of the window and grow — scrubbing width and
   height on every scroll frame. That is layout on every frame, and it scored
   CLS 0.168 at 1440 and 0.386 at 390, both of which fail Core Web Vitals
   outright (0.1 is the pass mark, 0.25 the floor of "poor").

   So the box no longer moves. The card is always the full stage, and what
   opens is a clip: `clip-path: inset()` is a paint operation, and the hairline
   rides a `transform: scale()` — the layout-instability spec excludes transform
   changes by definition. Same visual, zero layout, zero shift.

   The photograph now holds still while the frame opens over it, rather than
   rescaling with the box. On a backdrop held at 50% opacity that reads as the
   better version of the move, not a compromise. */
.believe-card{
  position:absolute;inset:0;overflow:hidden;
  --ix:calc((100vw - min(1080px,92vw)) / 2);
  --iy:calc((100svh - min(1080px,92vw) * 9 / 16) / 2);
  clip-path:inset(var(--iy) var(--ix) round var(--r,10px));
  display:grid;place-items:center;
}
/* The hairline has to sit on the moving edge, which a clip cannot draw, so it
   is its own layer riding a scale. A 1px border under a 0.79/0.71 scale renders
   at 0.79/0.71px — indistinguishable from the hairline it replaces. */
.believe-card::after{
  content:'';position:absolute;inset:0;pointer-events:none;z-index:3;
  border:1px solid var(--rule);
  border-radius:calc(var(--r,10px) / var(--sx,1));
  transform:scale(var(--sx,1),var(--sy,1));
  opacity:var(--bo,1);
}
/* One added token, `video`, is the whole CSS cost of making this stage move:
   the media element was already absolutely positioned, inset:0, cover-fitted
   and held at half opacity, so a <video> drops into the same box with no
   layout work and no new rule. object-position is set deliberately rather than
   left at centre — on a viewport wider than 16:9 the cover crop takes it out of
   the vertical, and 40% keeps the rose windows in the upper third, above the
   band the statements occupy, instead of behind them. */
.believe-card>img,.believe-card>picture>img,.believe-card>video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.5}
.believe-card>video{object-position:50% 40%}
.believe-body{position:relative;z-index:2;display:grid;justify-items:center;gap:22px;text-align:center;padding:0 6vw;opacity:var(--o,1)}

.believe-lines{position:relative;display:grid;place-items:center;width:100%;min-height:5.2em;perspective:1000px}
/* The lens shade. The statements are the only white type on this page that
   sits over moving footage, and the footage is a rose window: measured on the
   composited page with the glyphs masked (tools/_believeink.mjs), the worst
   backdrop pixel under a stroke came to 4.82:1 at 390 across the whole 12s —
   over the WCAG floor, but by 7%, on a backdrop that is moving. Seven percent
   is not a margin, it is a coin toss on the next frame.

   This is a scrim and not a text-shadow because a shadow on 32px type at this
   weight reads as a cheap glow, and it is a masked solid rather than a
   gradient background because a gradient here would be a fourth gradient
   background-image outside #top/#voice, which §7.6's ninth tell forbids — the
   same masking technique §1c and .perks already use. Feathered to closest-side
   with nothing solid until 40%, so there is no edge to see: it reads as the
   falloff of the room's own light, and the rosette above the band and the
   floor below it are untouched.

   It paints once and never again. No animation, no filter, no JS, no
   compositor work, no main-thread work — present identically on touch, under
   prefers-reduced-motion (where §17 stacks the five statements and the shade
   grows with the box), and with scripts off. */
.believe-lines::before{
  content:'';position:absolute;inset:-2.4em -14%;z-index:-1;pointer-events:none;
  background:rgba(0,0,0,.26);
  -webkit-mask:radial-gradient(closest-side ellipse at 50% 50%,#000 0%,#000 40%,transparent 100%);
  mask:radial-gradient(closest-side ellipse at 50% 50%,#000 0%,#000 40%,transparent 100%);
}
.believe-lines li{
  grid-area:1/1;
  font-size:2rem;font-weight:500;line-height:1.2;letter-spacing:-.03em;
  max-width:20ch;transform-style:preserve-3d;
  will-change:transform,opacity,filter;
}

/* ─── §10 the voices — video tiles and quote tiles ──────────────────────── */

/* Not a grid: two fixed-width flex columns, the second running in reverse, so
   the video tiles sit out of phase down the page. That phase shift is the
   whole bento effect. */
.voices{display:flex;flex-wrap:wrap;justify-content:center;gap:16px;margin-top:clamp(56px,10vh,110px);
  padding-inline:clamp(20px,5vw,32px)}
.vcol{width:clamp(360px,30vw,400px);flex-shrink:0;display:flex;flex-direction:column;gap:16px}
.vcol.rev{flex-direction:column-reverse}
/* 799, not 800: two columns fit at exactly 800 (2×360 + 16 + 2×32), so the
   reverse must already be on there or the stagger is dead at that one width. */
@media (max-width:799px){.vcol.rev{flex-direction:column}}

.vtile{
  position:relative;width:100%;flex-grow:1;aspect-ratio:3.5/4;min-height:280px;
  border-radius:10px;overflow:hidden;background:var(--surface);
}
.vtile video,.vtile img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:.8;transition:opacity var(--t) ease}
.vtile:hover video,.vtile:hover img{opacity:1}
.vtile figcaption{position:relative;z-index:2}
.vtile-overlay .badge{align-self:flex-start}
.vtile-overlay{
  position:absolute;inset:0;z-index:1;display:flex;flex-direction:column;justify-content:space-between;
  padding:16px;
  background:linear-gradient(to bottom,rgba(0,0,0,.3) 0%,transparent 30%,transparent 60%,rgba(0,0,0,.6) 100%);
}
.vtile cite{display:block;font-style:normal;font-size:clamp(1rem,1.5vw,1.25rem);font-weight:500;line-height:1.5;margin-bottom:4px}
.vtile .role{font-size:.75rem;font-weight:400;line-height:1.5;letter-spacing:.05em;text-transform:uppercase;color:var(--text)}

.qtile{
  width:100%;position:relative;border-radius:10px;background:var(--surface);
  padding:20px;display:flex;flex-direction:column;gap:12px;min-height:140px;
}
.qtile .badge{align-self:flex-start}
/* Optical margin alignment: the opening quote mark hangs into the padding so
   the first letterform, not the punctuation, sits on the text edge. General
   Sans's quotedblleft has advance 478 and lsb 48, so the whole advance clears
   the column. hanging-punctuation is Safari-only, so it is the upgrade and the
   negative indent is the mechanism. */
.qtile blockquote{font-size:clamp(.875rem,1.2vw,1rem);font-weight:500;line-height:1.4;flex:1;
  text-indent:-.478em}
@supports (hanging-punctuation:first){
  .qtile blockquote{text-indent:0;hanging-punctuation:first}
}
.qtile .role{font-size:.7rem;font-weight:400;line-height:1.5;letter-spacing:.05em;text-transform:uppercase;color:var(--text-75)}

/* ─── §11 the numbers ───────────────────────────────────────────────────── */

/* The row was arithmetic, not a grid: four 282.6px tiles centred in the
   viewport put its left edge at 131 where every other block on the page —
   .duo, .pcard, .bento, .cell — sits at 152. Same column now, and the
   hairlines land on the card verticals. */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;
  width:var(--col);margin-inline:auto;padding-inline:0;
  margin-top:clamp(16px,10vh,110px)}
/* Four columns is a desktop shape. Below 1024 it becomes two, and one on a
   phone — a 390px viewport divided four ways is a 78px card, which is how the
   third and fourth ran off the screen. */
@media (max-width:1024px){.stats{grid-template-columns:repeat(2,1fr)}}
@media (max-width:600px){.stats{grid-template-columns:1fr;max-width:400px}}
.stat{
  /* flex-end, not space-between: the badge and the number were 100px apart in
     a 282px square — 36% of the cell as a hole. .pcard and .cell already stack
     their content at the foot. */
  display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-end;gap:1rem;
  width:clamp(211.97px,21.197vw,282.62px);height:clamp(211.97px,21.197vw,282.62px);
  flex-shrink:0;padding:1.2rem;
  border-left:1px solid var(--rule);
}
.stat-body{display:flex;flex-direction:column;align-items:flex-start;gap:.5rem}
/* The 300-weight number against a 500-weight uppercase micro-label is the
   entire character of this block. Do not level the weights. */
.stat b{
  display:block;margin-top:1rem;
  font-size:clamp(2.96rem,4.06vw,3.38rem);font-weight:300;line-height:1.2;
  /* Without the face that actually has a tnum table this declaration is inert,
     and the right edge of each number swung 47px as the counter ran. */
  font-family:'Satoshi',var(--sans);
  font-variant-numeric:tabular-nums;
}
.stat .cap{
  font-size:clamp(.7rem,.96vw,.8rem);font-weight:400;line-height:1.4;letter-spacing:.03em;
  text-transform:uppercase;color:var(--text);opacity:.7;max-width:200px;
  min-height:2.8em;   /* reserve the second line, so all four numbers share a baseline */
}
@media (max-width:1024px){
  .stat{align-items:center;justify-content:center;width:auto;max-width:none;
        height:clamp(245px,26vw,350px);border:none;border-radius:10px}
  .stat-body{align-items:center}
  .stat b,.stat .cap{text-align:center}
}

/* The marquee: their two tracks, 67 and 63 px/s at 1440, opposite directions. The
   durations are the ones that were measured (45s / 47.2s); the px/s follow from
   how much each track carries, and the marks track carries four repeats of the
   set per half so translateX(-50%) stays seamless out to a 3200px viewport. */
.marquee{margin-top:clamp(72px,15vh,150px);display:grid;gap:24px;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.mrow{display:flex;width:max-content;animation:slide var(--dur,45s) linear infinite}
.mrow[data-rev]{animation-direction:reverse}
.marquee:hover .mrow{animation-play-state:paused}
.mrow span{flex:none;padding-inline:clamp(20px,2.6vw,40px);font-size:.875rem;font-weight:500;
  color:var(--text-40);white-space:nowrap;letter-spacing:-.01em;transition:color var(--t) ease}
.mrow span:hover{color:var(--text)}

/* The marks track. Sizes are hand-set, not height-matched — the whole point of
   §3 of research/partner-logos/PLAN.md is that Vercel's row runs 15px to 40px
   tall and holds its *widths* in a band instead, because what the eye levels is
   optical mass. Painted 182x36, 111x43 and 76x66; measured off the composited
   page at 1440, box areas 6,559 / 4,793 / 5,014 px^2 (-12%..+20% about the
   mean) and lit areas — the integral of the excess luminance over the ground —
   683 / 1,153 / 1,032 px^2 (-29%..+21%). Vercel's own published row runs
   -41%..+44% on box, so this is the tighter family. Every mark is also well
   inside its source: the Lay Mission file is 337px for a 111px paint and the
   Missionaries of Charity file is 160px for a 76px paint. 66px is that mark's
   floor — it is a square of fine meridians and arched serif type and it closes
   up below it, which is why it is the tall one rather than the short one. */
/* One rest value for the whole track. A raster cannot inherit currentColor, so
   the vector spends it as an alpha on the ink and the two PNGs spend the same
   number as an opacity; both lift to full on hover, with the track below at
   .48 so the marks lead and the names caption. .86 rather than Vercel's .93 —
   compared at 2x against .94, .78 and .70, .70 greys the Missionaries of
   Charity serif out and .94 glares against the very thin numerals above it. */
.mrow-marks{--mink:.86}
.mrow-marks span{display:flex;align-items:center;padding-inline:clamp(20px,4.4vw,72px)}
.pmark{display:block;width:auto;color:rgba(255,255,255,var(--mink));
  transition:color var(--t) ease,opacity var(--t) ease}
.m-lm,.m-mc{opacity:var(--mink)}
.mrow-marks span:hover .pmark{color:var(--text)}
.mrow-marks span:hover .m-lm,.mrow-marks span:hover .m-mc{opacity:1}
.m-sa{height:36px;aspect-ratio:706.13/139.51}
.m-lm{height:43px}
.m-mc{height:66px}
@keyframes slide{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ─── §12 the bento ─────────────────────────────────────────────────────── */

.bento{display:grid;gap:16px;margin-top:clamp(72px,15vh,150px)}
/* Two stages instead of one: three columns only from 1000px, where a column is
   at least 300px; two between 760 and 999. And rows two and three used to be
   the same 240px letterbox twice over — the third and fourth cells get height
   so the grid has a rhythm rather than a repeat. */
@media (min-width:1000px){
  .bento{grid-template-columns:repeat(3,1fr);grid-auto-rows:minmax(240px,auto)}
  .cell.wide{grid-column:span 2}
  .cell.lead{min-height:400px}
  .cell:nth-child(3),.cell:nth-child(4){min-height:340px}
}
@media (min-width:760px) and (max-width:999px){
  .bento{grid-template-columns:repeat(2,1fr)}
  .cell.wide{grid-column:span 2}
}

.cell{
  position:relative;overflow:hidden;border-radius:10px;background:var(--surface);
  padding:24px;min-height:240px;isolation:isolate;
  display:flex;flex-direction:column;justify-content:flex-end;gap:10px;
}
.cell>img,.cell>picture>img,.cell>video{position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover;opacity:.85}
.cell.has-media::before{content:'';position:absolute;inset:0;z-index:-1;
  background:linear-gradient(180deg,rgba(0,0,0,.3) 0%,rgba(0,0,0,.15) 30%,rgba(0,0,0,.65) 66%,rgba(0,0,0,.95) 100%)}
.cell h3{font-size:clamp(1.2rem,1.5vw,2rem);font-weight:500;letter-spacing:-.02em;line-height:1.2}
.cell p{font-size:.8125rem;line-height:1.5;color:var(--text-94);max-width:42ch}

/* The filmic wash sequel puts behind its feature cells, warmed a step so it
   sits with parish-hall photography rather than against it. */
.cell.tint{background:linear-gradient(152deg,#9c9083 0%,#6f6a60 44%,#2a2926 100%)}


.illus{position:absolute;z-index:1;left:24px;top:26px;
  font-size:.625rem;font-weight:500;letter-spacing:.05em;text-transform:uppercase;
  color:var(--text-40)}

.count{position:absolute;z-index:1;right:24px;top:24px;
  display:grid;gap:2px;justify-items:center;padding:12px 22px;text-align:center}
.count b{font-size:clamp(1rem,1.6vw,1.375rem);font-weight:500;letter-spacing:-.02em;
  font-family:'Satoshi',var(--sans);font-variant-numeric:tabular-nums}
.count span{font-size:.625rem;letter-spacing:.05em;text-transform:uppercase;color:var(--text-75)}

/* Below the bento's own breakpoint the lead cell is a single narrow column, and
   a countdown pinned to its top-right corner lands straight on the headline —
   "Next · Called to Relat…". Absolute positioning is a desktop affordance here:
   on one column both markers join the flow and stack above the title instead. */
@media (max-width:759px){
  .illus{position:static;order:-2;align-self:flex-start}
  .count{position:static;order:-1;align-self:flex-start;padding:10px 18px;
    justify-items:start;text-align:left;margin-bottom:2px}
  .cell{min-height:0;padding:20px}
  .cell.lead{min-height:0}
}

/* The lead cell's next-evening block and its empty state. Both are one group
   the build stamps with one end instant, but the cell is the flex container
   the countdown's order:-1 and the 10px gap are measured against, so the
   wrapper generates no box of its own and every line inside it stays a direct
   flex item of the cell. Hidden it must still collapse the subtree, and
   display:contents would otherwise outrank the UA's [hidden]. */
.next-live{display:contents}
.next-live[hidden]{display:none}

.cell .lineup{display:grid;gap:7px;margin-top:2px}
.cell .lineup li{font-size:.8125rem;color:var(--text-94);line-height:1.4;max-width:42ch}
.cell .lineup b{font-weight:500;color:var(--text)}


/* On a phone the copy sits on a much smaller crop of the same photograph, so
   the scrim that is enough at 1440 is not enough at 390. Deepen it rather than
   shrinking the type. */
/* A pill with a long label cannot shrink below its own text, and one 294px
   button was setting the min-content width of the whole page at 320. Let the
   pills wrap down there instead of letting the page scroll sideways. */
@media (max-width:420px){
  /* `height:auto` was discarding the 42/45/52 ramp, so the primary CTA lost
     its hierarchy against every secondary button on the page. Floors instead. */
  .btn{white-space:normal;height:auto;padding-block:11px;line-height:1.25;text-align:center}
  .btn-sm{min-height:44px}
  .btn-md{min-height:46px}
  .btn-lg{min-height:52px;padding-block:14px}
  .opener{max-width:100%}
  .opener>*{max-width:100%}
}

@media (max-width:760px){
  .pcard::before{background:linear-gradient(180deg,rgba(0,0,0,.4) 0%,rgba(0,0,0,.15) 24%,rgba(0,0,0,.6) 52%,rgba(0,0,0,.94) 100%)}
  .cell.has-media::before{background:linear-gradient(180deg,rgba(0,0,0,.35) 0%,rgba(0,0,0,.25) 22%,rgba(0,0,0,.75) 55%,rgba(0,0,0,.97) 100%)}
  .cell{min-height:280px}
  .perk p{font-size:.9375rem}
}

/* ─── §12b the team ─────────────────────────────────────────────────────────
   The only text-only block on the page, seated between the bento's six media
   cells and the perk marquee's two rows of photography. Two heavy neighbours
   are what let a quiet typographic block read as a decision rather than as
   something left over.

   It is the reference's .quoteTile, not its .videoTile: without media the video
   tile is a 400x457 empty rectangle, and no publicly served portrait of these
   six clears half the 1120 device px this page would paint — the best is
   200x200 and two of them have no image at all (research/team/REFERENCE.md
   §11). Two faces among four placeholders is the hole this section must not
   have, so the card is typographic by design, not a photo card waiting for a
   photo.

   Nothing in the ROW below keys a height, width, colour, weight or font to a
   person or a position. Saul used to lead on position and content alone: he is
   named in the description, he is the first <li>, and he is the only one with a
   second verified line, which under align-items:stretch sets his row — the
   mechanism REFERENCE.md §3 measured on the reference.

   THAT IS NO LONGER THE WHOLE STORY, and the change is deliberate rather than
   drift. The owner asked, in those words, that Saul have his own dedicated card
   so that it is obvious he is the one who leads this organisation. That is an
   explicit override of §3's finding, and it is recorded here rather than
   quietly applied: the reference does not promote a founder, this page now
   does, and the instruction to do it came from the person whose organisation it
   is. `.ccard--lead` at the foot of this block is the whole of it. */

/* Not a grid: a wrapping flex row of fixed columns, centred, like .voices.
   3 x 400 + 2 x 16 is 1232px against a 1136px content column, so the row lives
   outside .wrap with its own gutter.
   The phone gutter is the one deliberate deviation from the reference. Their
   #founders holds a 360px column floor against 32px of padding, so at 390 the
   326px content box is narrower than the column and justify-content centres a
   10px overflow — 15px of gutter, with overflow-x:hidden covering the rest.
   Their own note says to lower the floor, not the padding. A text card has no
   minimum photographic width, so the floor comes off and the phone lands on a
   350px card inside the same 20px gutter as every .wrap here.
   THE 16px AT THE BOTTOM IS NOT AIR — §5's rule stands, the row closes on the
   same 16px it separates its rows by. It is there because the last card sat
   flush with #team's content-visibility containment edge, where the reveal
   observer delivered two records for it across a whole traverse (ratio 0.105
   in, 0 out) and never one above the 0.3 threshold main.js §3 waits for: Fr.
   Tom stayed at opacity 0 on a real scroll at every one-column width. One gap
   of trailing box clears it everywhere; 8px did not. */
.crew{
  display:flex;flex-wrap:wrap;justify-content:center;align-items:stretch;gap:16px;
  padding-inline:clamp(20px,5vw,32px);padding-bottom:16px;
  margin-top:clamp(56px,10vh,110px);
}
/* THE CARD IS A PLATE WITH A MEDIA FIELD, not a paragraph in a box.
   The owner's word for the old one was "template", and the cause was
   structural rather than cosmetic: sequel's founder card is media-FIRST — a
   person fills the frame and the name is set into its bottom edge — and ours
   had no media region at all, so six equal grey rectangles of text was the
   whole design.

   Five of the six have no obtainable photograph (an Instagram avatar that
   tops out at 150px, two LinkedIn walls, three with nothing located), and a
   substituted face is not an option, so the field is built to be legible
   EMPTY. It is a --chip plate the width of the card carrying the person's
   initials in the display italic at display size, cropped by the plate's own
   bottom edge. That is what a person-card without a portrait has always been;
   drawn at 120px instead of 32px it reads as a monogram rather than as a hole.

   The plate is a flex ITEM with flex-grow, not an absolute layer, so on a row
   whose height was set by Saul's third line the other two plates grow and all
   three name/role blocks still sit on one baseline. R64's row rhythm therefore
   still comes only from the note, and from nothing else. */
.ccard{
  --plate:clamp(200px,23vw,330px);
  position:relative;overflow:hidden;
  flex:0 0 auto;width:min(400px,(100% - 32px) / 3);
  display:flex;flex-direction:column;
  padding:20px;border-radius:10px;background:var(--surface);
}
/* A straight 3 -> 1, no 2-up: three columns still fit at exactly 800
   (3 x 234 + 2 x 16 + 2 x 32), and a 2-up row of six people reads as a table. */
@media (max-width:799px){.ccard{width:100%;max-width:400px}}

/* The media field. Bleeds to the card's edges through the 20px padding and is
   clipped by the card's own radius, so it carries no radius of its own and the
   page's radius set stays {0px, 10px}. */
.cface{
  position:relative;flex:1 1 auto;min-height:var(--plate);
  margin:-20px -20px 20px;overflow:hidden;
  background:linear-gradient(155deg,rgba(255,255,255,.05),transparent 58%),var(--chip);
  border-bottom:1px solid var(--rule);
}
/* Generated content, deliberately: the monogram is decoration for a name that
   is already in the DOM two lines below, so it stays out of the accessibility
   tree, out of innerText and off the page's word count. .16 white on #2a2a2a
   is a watermark and is not text — every string a reader actually has to read
   is still on --surface at the ratios §12b was measured at. */
.cface::before{
  content:attr(data-mono);position:absolute;left:14px;bottom:-.15em;
  font-family:var(--serif);font-style:italic;font-weight:400;
  font-size:clamp(7rem,14.5vw,13rem);line-height:1;letter-spacing:-.05em;
  color:rgba(255,255,255,.2);
}
/* THE DROP-IN SLOT. tools/build-pages.mjs writes a <picture> in here for all
   six people or for none of them, and only for files that clear twice the
   plate's widest painted width. Drop the six headshots into site/assets/team/
   and rebuild; no other file changes. `>` is named on both shapes because a
   <picture> wrapper puts the <img> one level deeper — the same trap §8 hit. */
.cface>picture>img,.cface>img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:var(--op,50% 28%);
}

/* The rest state sits one level in, not on the card: .ccard is the .rv target
   and html.motion .rv.in{opacity:1} would overwrite an opacity written there.
   The reference is built the same way — the tile reveals, the media inside
   carries the dim. One channel only: 0.8 -> 1.0 over 300ms, their measured
   curve. No scale, no lift, no shadow, no border, no colour change, and
   nothing faked on touch. */
.ccard-in{flex:0 0 auto;display:flex;flex-direction:column;gap:4px;opacity:.8;transition:opacity var(--t) ease}
.ccard:hover .ccard-in{opacity:1}

/* h3, not cite: cite is for the title of a work, and .vtile cite already
   misuses it for a person's name one section up. */
.ccard h3{font-size:clamp(1rem,1.5vw,1.25rem);font-weight:500;line-height:1.5;letter-spacing:normal}
/* The flat .75rem .vtile .role already carries, rather than the reference's
   second clamp: matching the name/role pair already on this page beats a curve
   that is pinned at both test widths anyway. --text-70 is /founders' own
   --color-text-muted, which the homepage leaves undefined and therefore renders
   white. Off the painted pixels over #202020: 5.72:1 at the card's 0.8 rest and
   8.21:1 on hover, with the name at 10.78 and the note at 6.69 at rest. */
.ccard .role{
  font-size:.75rem;font-weight:400;line-height:1.5;letter-spacing:.05em;
  text-transform:uppercase;color:var(--text-70);
}
.ccard .note{
  font-size:clamp(.875rem,1.2vw,1rem);font-weight:400;line-height:1.4;
  color:var(--text-75);margin-top:8px;
}

/* THE LEAD CARD. Same <li>, same media field, same three lines, same reveal,
   same 0.8 -> 1.0 hover: a bigger box holding the same contents is the cheap
   version of this and it is not what is below. What changes is the CARD'S
   COMPOSITION — the object is turned on its side.

   Every other card is media-FIRST and stacked: a portrait plate across the top,
   the name set under its bottom edge. The lead card is that card turned on its
   side. The plate becomes a full-height column bleeding to the card's top,
   bottom and left edges, the card runs two columns and a gutter wide instead of
   one, and the name still sits on the plate's bottom edge — now beside it
   rather than beneath it. At 1440 that is 816x480 against the row's 400x423:
   2.3x the area, the tallest portrait on the page, alone on the first line,
   its two edges landing exactly on the two-card row that closes the section.
   It reads as the masthead of the roster rather than as a member of it, which
   is the claim the owner asked the page to make.

   WHAT IS NOT USED, and why. No type-scale change: `.ccard h3` and `.role` are
   the same 20/12px here as in the row, because the six names are one roster and
   a name in a size no other name uses says "a different kind of person" rather
   than "the person in charge". No colour, no surface, no rim, no shadow, no
   border the row does not already have — §12b's flat-plate ruling stands and
   §1c's lamp still skips this card. No second hover channel, no second reveal.
   Everything carrying the promotion is geometry, so all of it survives a
   screenshot, a phone, JS-off, prefers-reduced-motion and a print, which is
   more than a type bump or a hover treatment would.

   THE PLATE IS CAPPED AT 400px WIDE ON PURPOSE. That is the widest painted
   width the build's FACE_MIN_WIDTH=800 gate is built around, so the lead's
   portrait is held to exactly the same 2x rule as the row's (R72b) and the gate
   does not have to move. The box is 5/6 — shallower than the 4/5 the headshots
   are cut to — so an 800px file that clears the gate is 1000px tall against a
   960px requirement and clears the doubling on both axes too. It is also why
   the card is 816 and not the full 1232 of the row: past two columns there is
   no legal width left for the portrait to balance, and a 1232px card with a
   400px plate is three quarters empty surface.

   The card's height comes from the plate's aspect-ratio, not from a magic
   number: the plate's negative top and bottom margins cancel the card's 20px
   padding, so the card is exactly as tall as the portrait, in BOTH states — the
   plate's box is the same box whether the build fills it with a <picture> or
   with a monogram, so the day saul-perez.jpg lands nothing on this page moves.
   align-items:flex-end then drops the identity block onto the card's bottom
   padding, on the portrait's own bottom edge. The air collects at the top
   right, where a masthead's air belongs, rather than beside the type. */
/* The slot takes the whole flex line and now stacks two things in it: the card
   and, on the row's own 16px, the career that is the reason the card exists.
   Column direction, so `justify-content:center` becomes `align-items:center`;
   the card's own width:100%/max-width:816px is untouched by the change. */
.lead-slot{flex:0 1 100%;display:flex;flex-direction:column;align-items:center;gap:16px}
.ccard--lead{
  width:100%;max-width:816px;
  flex-direction:row;align-items:flex-end;
  gap:clamp(20px,2.6vw,40px);
}
.ccard--lead .cface{
  flex:0 0 clamp(240px,52%,400px);
  min-height:0;aspect-ratio:5/6;
  margin:-20px 0 -20px -20px;
  border-bottom:0;border-inline-end:1px solid var(--rule);
}
/* The monogram is drawn against a plate half again as tall as the row's, so it
   steps up with it — the same crop off the bottom edge, at the size this box
   asks for. It stays inside 400px of plate at every width. */
.ccard--lead .cface::before{font-size:clamp(8rem,16vw,15rem)}
/* A measure, not a margin. The note is the longest line on the page; given the
   whole of the card's right half it would set at ~60ch and read as a paragraph
   of body copy rather than as the second line of an identity. */
.ccard--lead .ccard-in{flex:1 1 auto;max-width:46ch}

/* On one column the rotation has nowhere to go — a 350px card cannot hold a
   portrait beside three lines without making the lead's face SMALLER than the
   five below it, which is the opposite of what this card is for. So the phone
   keeps the stacked card and promotes the plate instead: 5/6 of the card's full
   width, 350x420 against the row's 350x200 band. His portrait is still the
   largest object in the section by a distance, he is still alone at the top of
   it, and the card is still the only one of the six the page had to describe
   twice. The one-column card also cannot outgrow the reveal threshold main.js
   §3 watches at 0.3 — at 390 it is 598px against a 675px ceiling — so it
   reveals on the same rule as the other five and not on the tall-element
   fallback. */
@media (max-width:799px){
  .ccard--lead{max-width:400px;flex-direction:column;align-items:stretch}
  .ccard--lead .cface{
    flex:0 0 auto;margin:-20px -20px 20px;
    border-inline-end:0;border-bottom:1px solid var(--rule);
  }
  .ccard--lead .ccard-in{max-width:none}
}

/* ─── §12c the subpages ─────────────────────────────────────────────────────
   /events/ and /team/ are the site's first pages that are not the home page.
   Nothing here is a new idea: the surface, the radius, the ink ladder, the
   reveal classes, the .band rhythm and the 160ms button response are the ones
   already in this file. What is new is only the two shapes the home page never
   needed — an event card and a list of past ones.

   The first band on a subpage carries its own top padding. --band-gap is 30vh,
   which is right between two full sections and wrong as the very first thing
   under a fixed bar with no hero above it: at 1440 it opened the page with
   342px of black. The 72px on <main> is the fixed-nav offset the rest of the
   site scrolls anchors to (F-05), so a subpage's first section lands exactly
   where an anchored one does; the shorter band padding above the heading is
   what the eye reads as the opener.                                          */
main.sub{padding-top:72px}
main.sub>.band:first-of-type{padding-block-start:clamp(64px,12vh,120px)}
/* --band-gap is 30vh, and it is right on the home page, where every band holds
   a full screen of photography and the gap is the pause between two chapters.
   The three bands here hold one heading and a short list each, so the same 270px
   at 1440 reads as a page that has run out rather than as air. This is the same
   rhythm scaled to the amount of matter it separates; the token itself is
   untouched and the home page is not affected. */
main.sub>.band+.band{padding-block-start:clamp(96px,18vh,180px)}
.page-head{margin-bottom:clamp(40px,6vh,60px)}

/* One column below 800, two at and above it. Six people wanted three columns
   because a name is short; an event card carries four to six lines and a third
   column would set them at a width that wraps every one of them. */
.elist{display:flex;flex-direction:column;gap:16px}
@media (min-width:800px){.elist{flex-direction:row;flex-wrap:wrap}
  .elist>.ecard{flex:0 0 auto;width:calc((100% - 16px)/2)}}

.ecard{position:relative;background:var(--surface);border-radius:10px;padding:24px;
  display:flex;flex-direction:column;gap:20px;align-items:stretch}
.ebody{display:flex;flex-direction:column;gap:8px;align-items:flex-start}
.ecard-lead{padding:clamp(24px,4vw,40px)}

/* THE PHOTOGRAPH. This page shipped with none, which is the whole of what the
   owner saw. Every frame here is the organisation's own and is chosen by the
   event's KIND, so an evening card can only ever carry an evening and an
   action card can only ever carry an action; the mapping and the reasoning are
   in src/data/event-art.json.
   6px inside the card's 10px is the nested-radius pair this file already uses
   for a frame and its plate, and it means the media never has to fight the
   card's own corner. --op is the crop point, set per frame from the data:
   a 4:5 negative in a 3:2 box keeps a little over half its height and the half
   with the faces in it is near the top, not the middle. */
.ephoto{position:relative;margin:0;overflow:hidden;border-radius:6px;
  background:var(--chip);aspect-ratio:3/2;flex:none}
.ephoto>picture>img,.ephoto>img{display:block;width:100%;height:100%;
  object-fit:cover;object-position:var(--op,50% 50%)}
/* The card names what the photograph is, on the photograph. An event that has
   not happened has no picture of itself and the page may not imply that it
   does. It is the site's own .badge, in the reference's own position, and it is
   opaque for a measured reason: the first draft set the line over a bottom
   scrim instead, and against the bright wall in room-back at 390 that read
   3.4:1 — a scrim strong enough to fix it would have been dark enough to be
   the point of the picture. --chip under --text-75 is 6.2:1 over any frame
   that will ever go here, because the frame is not underneath it. */
.ephoto figcaption{position:absolute;z-index:1;left:12px;top:12px}

/* At 900 the lead card is wide enough that a full-bleed band would make a
   letterbox of a portrait negative and push the RSVP below the fold on a
   laptop. So it splits: the frame takes 60% and the four lines sit beside it,
   centred against it. Below 900 it stacks, which is also every width the list
   cards ever see. */
@media (min-width:900px){
  .ecard-lead{flex-direction:row;align-items:center;gap:clamp(24px,3vw,40px)}
  .ecard-lead>.ephoto{flex:0 0 60%}
  .ecard-lead>.ebody{flex:1 1 auto}
}
/* §1c's lamp, on §1c's own tints. .ecard is a convex plate like .cell and takes
   the same masked rim from the same fixed light; the declaration is repeated
   here rather than added to §1c's selector list so the stylesheet's diff stays
   inside this one new region. .ccard still does not take it — F-09 ruled the
   crew card the page's one deliberately flat plate and that ruling stands. */
.ecard::after{
  content:'';position:absolute;inset:0;z-index:4;pointer-events:none;
  border:1px solid var(--lamp-rim-strong);border-radius:inherit;
  -webkit-mask:var(--lamp-arc);mask:var(--lamp-arc);
}
.ecard .when{font-size:.75rem;font-weight:400;line-height:1.5;letter-spacing:.05em;
  text-transform:uppercase;color:var(--text-70)}
.ecard .at{font-size:.875rem;line-height:1.5;color:var(--text-75)}
.ecard h2{font-size:clamp(1.25rem,2vw,1.5rem);font-weight:500;line-height:1.3;letter-spacing:-.01em}
.ecard h3{font-size:clamp(1rem,1.5vw,1.25rem);font-weight:500;line-height:1.4;letter-spacing:normal}
.ecard .where,.ecard .note{font-size:clamp(.875rem,1.2vw,1rem);line-height:1.4;color:var(--text-75)}
/* Not a chip and not a badge: the word, set the way every other small label on
   the site is set. A price that was not stated never reaches this element. */
.ecard .tag{font-size:.75rem;font-weight:500;line-height:1.5;letter-spacing:.05em;
  text-transform:uppercase;color:var(--accent)}
/* The one thing an owner who forgets the Luma link sees. It is a sentence, not
   a disabled control: a dead button is worse than no button. */
.ecard .pending{font-size:.875rem;line-height:1.5;color:var(--text-70)}
.ecard .btn{margin-top:8px}

/* The record is a list, not a wall of cards: past events carry no control and
   nothing to click, so a card around each one would be a box drawn for its own
   sake. */
/* main.js §13 hides a card whose end has passed, and hides #upcoming when
   nothing in it survives. Every one of those elements sets its own display, so
   the UA's [hidden] rule loses on source order and the attribute would do
   nothing without this. */
.ecard[hidden],#upcoming[hidden],.epast li[hidden],.count[hidden]{display:none}

.epast li{display:flex;flex-wrap:wrap;gap:4px 12px;padding:14px 0;
  border-bottom:1px solid var(--rule);align-items:baseline}
.epast li:first-child{border-top:1px solid var(--rule)}
.epast .when{flex:none;min-width:11em;font-size:.75rem;font-weight:400;line-height:1.5;
  letter-spacing:.05em;text-transform:uppercase;color:var(--text-70)}
.epast .what{font-size:1rem;line-height:1.5;color:var(--text-94)}
.epast .where{font-size:.875rem;line-height:1.5;color:var(--text-70)}

.empty{font-size:clamp(.9375rem,1.2vw,1.0625rem);line-height:1.5;color:var(--text-75);
  max-width:var(--measure)}
.empty a{text-decoration:underline;text-underline-offset:3px;
  transition:color var(--t-resp) var(--ease-out-quad)}
.empty a:hover{color:var(--accent)}

/* The events page's own headings sit on the same 40/60 rhythm R19 holds the
   home page's bands to. */
#upcoming .title,#past .title{margin-bottom:40px}
@media (min-width:900px){#upcoming .title,#past .title{margin-bottom:60px}}

/* ─── §12d /team/'s hero, and the one career on it ──────────────────────────
   THE HERO IS A TRANSLATION, NOT A COPY, AND THE THING BEING TRANSLATED IS A
   RATIO. Three passes at this page failed because they were built from a
   description of sequel.co/founders rather than from its numbers, and a
   description loses exactly the part that makes it work. The reference,
   measured in a browser at 1440x900:

     h1        56px / line-height 56 / weight 500 / letter-spacing -1.68px,
               centred, box 1000px wide
     italic    a serif face at the same 56px, letter-spacing -2.8px
     the pill  100 x 56, radius 16.8, overflow hidden, inline, vertically
               centred on the line, 16.8px of margin either side — a looping
               muted clip sitting INSIDE the sentence
     the cta   uppercase 12.84px / weight 500 / letter-spacing .642px,
               underlined, 32px below the h1

   Divide all of that by the h1's own 56px and every number becomes a ratio
   that survives a change of type scale:

     measure   17.857em      pill w   1.786em     pill radius  .3em
     cta size    .2293em     pill h   1em         cta gap      .5714em
     tracking  -.03em (the h1) and -.05em (the italic word)

   So --h1 is the only px in this block. Its clamp lands 56.16px at 1440 —
   the reference's 56 — and 30.4px at 390, which is what their mobile hero
   measures; everything else is em OF THAT and therefore correct at both ends
   and everywhere between. -.03em is also what .title already carries and
   -.05em is what .em already carries, so the two tracking numbers are this
   site's own, not borrowed.

   WHAT DID NOT COME ACROSS, and why. Their pill is a <button> that opens a
   founders' intro film. We have no such film, and a control that does nothing
   is worse than no control, so ours is a decorative <span>: aria-hidden, not
   focusable, and drawn with no play triangle, because a play triangle on a
   thing that cannot be played is a lie about the interface. What is left is
   the part that actually reads at 100x56 — a moving inlay in the middle of a
   sentence. */
.thero{
  --h1:clamp(1.9rem,3.9vw,4rem);
  text-align:center;display:grid;justify-items:center;
}
.thero-h{
  font-size:var(--h1);font-weight:500;line-height:1;letter-spacing:-.03em;
  max-width:17.86em;text-wrap:balance;
}
/* The pill. Its height is one line-height exactly, which is why the sentence
   only grows by the few px a vertical-align:middle box adds and not by a whole
   line. --chip under the video so the box is a shape rather than a hole for
   the frame before the poster paints. The margin is .2em rather than the
   reference's .3em because there is real whitespace either side of this
   element in the markup — .2em plus a word space lands on their measured
   26px gap — and that whitespace is what lets the sentence break beside the
   pill instead of dragging it through the line-break with its neighbours. */
.thero-pill{
  position:relative;
  display:inline-flex;vertical-align:middle;overflow:hidden;
  width:1.786em;height:1em;border-radius:.3em;margin:0 .25em;
  background:var(--chip);
}
/* The still is the element that ships and the clip is laid over it, both
   filling the same box, so the moment main.js §10a appends the video nothing
   moves and nothing flashes: the video carries the still as its own poster. */
.thero-pill>img,.thero-pill>video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
}
/* The two floors are the one place this block stops being a ratio, and they
   are the reference's own behaviour rather than a rescue: their CTA is ~11px
   at 390 against an h1 that has come down to 30px, so it does NOT ride the
   headline all the way down. Pure .2293em would set it at 6.97px on a phone,
   which is not a control, it is a smudge. Above ~880px wide the ratio is what
   applies and the floors are inert. */
.thero-cta{
  margin-top:max(24px,calc(var(--h1) * .5714));
  font-size:max(.6875rem,calc(var(--h1) * .2293));font-weight:500;line-height:1.2;
  letter-spacing:.05em;text-transform:uppercase;
  text-decoration:underline;text-underline-offset:.18em;
  transition:color var(--t-resp) var(--ease-out-quad);
}
.thero-cta:hover{color:var(--accent)}

/* THE CAREER. The owner asked for this page's lead card so that it is obvious
   who leads this organisation; the timeline is the reason that card exists,
   so it goes with the card rather than somewhere else on the page. It is the
   same plate at the same radius at the same width, stacked under it on the
   row's own 16px, so the two read as one masthead and not as a card plus an
   appendix.

   THE LOGO SLOT IS DELIBERATELY EMPTY, and that is a decision rather than an
   omission. The owner asked for organisation marks on these rows. LinkedIn
   serves all five at 100x100, which is a blurred smear at any size this row
   would paint, and two of the five — MIT and The George Washington University
   — publish trademark policies that a redrawn or resampled mark would be in
   breach of. So the row is built to be handsome with nothing in the slot:
   a date column, a role, an organisation set as a name and not as a picture.
   tools/build-pages.mjs looks for site/assets/orgs/<slug>.{svg,png} on every
   run and emits an <img class="tline-mark"> in front of the name for any file
   it finds, and nothing at all for the ones it does not. Drop an official file
   in and the mark appears; no other edit anywhere.

   The rule and the date column are .epast's, which is this site's existing
   answer to "a list of dated things": 11em of uppercase .75rem, a hairline
   between rows, no box around each entry. */
.tline{
  width:100%;max-width:816px;
  background:var(--surface);border-radius:10px;
  padding:clamp(20px,2.6vw,32px);
}
.tline-cap{margin-bottom:clamp(18px,2.4vw,28px);color:var(--text-70)}
.tline-row{
  display:grid;grid-template-columns:11.5em 1fr;gap:2px 24px;align-items:baseline;
  padding:16px 0;border-top:1px solid var(--rule);
}
.tline-row:first-child{border-top:0;padding-top:0}
.tline-when{
  font-size:.75rem;font-weight:400;line-height:1.5;letter-spacing:.05em;
  text-transform:uppercase;color:var(--text-70);
}
/* The one live row. The same 6px accent dot the hero eyebrow uses for the same
   job — saying which of these is happening now — rather than a second colour
   or a second weight in a column that has neither.
   It HANGS: -14 + 6 + 8 is zero, so the dot costs the line no inline width and
   all five dates keep one left edge. A marker that pushes its own row out of
   the column it is marking is worse than no marker. 14px of hang against the
   plate's 20px of padding at its narrowest, so it never leaves the card. */
.tline-when .dot{
  display:inline-block;width:6px;height:6px;border-radius:50%;
  background:var(--accent);margin-left:-14px;margin-right:8px;vertical-align:.08em;
}
.tline-role{font-size:clamp(1rem,1.3vw,1.0625rem);font-weight:500;line-height:1.4;
  letter-spacing:-.01em;color:var(--text-94)}
.tline-org{font-size:.9375rem;line-height:1.5;color:var(--text-70);margin-top:2px}
/* The slot, sized off the line it sits on rather than off a px number, so a
   mark that does land is the height of the name beside it at every width. */
.tline-mark{display:inline-block;height:1.15em;width:auto;
  margin-right:.5em;vertical-align:-.22em}
.tline-note{font-size:.875rem;line-height:1.5;color:var(--text-75);
  margin-top:8px;max-width:52ch}
.tline-foot{font-size:.875rem;line-height:1.5;color:var(--text-75);
  margin-top:20px;padding-top:16px;border-top:1px solid var(--rule)}
/* One column below 700: an 11.5em date column against a 350px card is two
   thirds of the row, and the roles here are long. The date goes above its own
   role, which is the shape this list has on a phone everywhere else. */
@media (max-width:699px){
  .tline-row{grid-template-columns:1fr;gap:6px}
  .tline-when{margin-bottom:2px}
}
@media (max-width:799px){.tline{max-width:400px}}

/* ─── §13 take a seat — the membership page's perk marquee ──────────────── */

/* /membership answers "what do I get" with two counter-rotating rows of photo
   cards rather than a list, a table or an accordion. 409x306, 8px radius, a
   flat 40% scrim, one sentence centred on each. The gap lives on the card as a
   right margin, not as flex `gap`, so the doubled track wraps at exactly -50%
   with no half-gap stutter. */
.perks{--dur:47.2s;width:100vw;max-width:100vw;margin-inline:calc(50% - 50vw);
  margin-top:clamp(72px,15vh,150px);overflow:hidden;display:grid;gap:10px;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 10rem,#000 calc(100% - 10rem),transparent);
  mask-image:linear-gradient(90deg,transparent,#000 10rem,#000 calc(100% - 10rem),transparent)}
@media (max-width:600px){.perks{-webkit-mask-image:linear-gradient(90deg,transparent,#000 5rem,#000 calc(100% - 5rem),transparent);
  mask-image:linear-gradient(90deg,transparent,#000 5rem,#000 calc(100% - 5rem),transparent)}}
.perks-row{display:flex;width:max-content;animation:perkslide var(--dur) linear infinite}
/* two rows at two speeds, or they phase-lock and read as one */
.perks-row[data-rev]{animation-direction:reverse;--dur:52.4s}
@keyframes perkslide{from{transform:translateX(0)}to{transform:translateX(-50%)}}

.perk{position:relative;flex:none;width:clamp(260px,28vw,409px);aspect-ratio:409/306;
  margin-right:10px;border-radius:8px;overflow:hidden;background:var(--surface);
  display:grid;place-items:center;padding:24px;text-align:center;isolation:isolate}
.perk img{position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover}
.perk::before{content:'';position:absolute;inset:0;z-index:-1;background:rgba(0,0,0,.45)}
.perk p{font-size:clamp(1rem,1.3vw,1.125rem);font-weight:500;letter-spacing:-.02em;line-height:1.35;max-width:20ch}

.seat-close{display:grid;justify-items:center;gap:16px;margin-top:clamp(56px,10vh,110px)}
.seat-note{font-size:.75rem;letter-spacing:.05em;text-transform:uppercase;color:var(--text-40)}

/* ─── §14 the feed — /stories' five-column collage ──────────────────────── */

/* Not masonry: five equal columns of 3:4 tiles, the even columns pulled up by
   half a tile, the whole thing full-bleed and feathered top and bottom into the
   page. Each column drifts at its own rate as you pass it — .03 and .08 of the
   scroll, alternating — which is what stops a uniform grid reading as a
   contact sheet. */
.socials{display:flex;justify-content:center;gap:20px;padding:20px 24px;margin:0}
.opener .socials{margin-top:-20px}
/* The icons stay 16px — that is the reference's size and the row's whole
   character — but the thing a thumb has to hit is 44px. An invisible
   pseudo-element does it without moving a pixel of what renders. */
.socials a{position:relative;display:grid;place-items:center;width:16px;height:16px;
  color:rgba(255,255,255,.4);transition:color var(--t) ease}
.socials a::after{content:'';position:absolute;left:50%;top:50%;
  width:44px;height:44px;transform:translate(-50%,-50%)}
.socials a:hover{color:var(--text)}
.socials a:focus-visible{outline:2px solid #fff;outline-offset:4px;border-radius:.5rem;color:var(--text)}
.socials svg{width:100%;height:100%;fill:currentColor}

.feed{
  position:relative;width:100vw;max-width:100vw;margin-inline:calc(50% - 50vw);
  margin-top:clamp(24px,3vw,40px);
  display:grid;grid-template-columns:repeat(5,1fr);gap:.75rem;
  overflow:hidden;padding:0 .75rem;container-type:inline-size;isolation:isolate;
}
/* A percentage mask on a content-sized container scales with the collage: 20%
   of a 1500px wall is 303px of erased photographs at each end. Fixed height. */
.feed::before,.feed::after{content:'';position:absolute;left:0;right:0;height:clamp(56px,10vh,100px);z-index:2;pointer-events:none}
.feed::before{top:0;transform:translateY(-4px);background:linear-gradient(to bottom,var(--feather))}
.feed::after{bottom:0;transform:translateY(4px);background:linear-gradient(to top,var(--feather))}

/* No transition: the scrub writes this transform every frame, so a .1s
   transition restarted sixty times a second and never completed — five
   compositor animations permanently in flight, trailing the thumb by 100ms.
   Smooth the scroll signal, not the animation. */
.fcol{display:flex;flex-direction:column;gap:.75rem;will-change:transform}
.fcol:nth-child(2n){margin-top:calc(-13.3333cqi + .4rem)}
/* Desktop shows four of the six tiles per column. This is not a detail: the
   feathered edges are 20% of the collage's own height, so six rows makes the
   wall half again as tall and the masks then eat a whole row at each end
   instead of just softening them. Six only come back at the 3-column
   breakpoint, where the columns are narrow enough to need them. */
.fcol .fcard:nth-child(n+5){display:none}

.fcard{position:relative;display:block;width:100%;aspect-ratio:3/4;border-radius:.5rem;
  overflow:hidden;background:var(--surface)}
/* No zoom: every other grid on this page is inert on hover — .pcard, .cell and
   .perk all are, and .vtile only dims. The overlay fade is the affordance. */
.fcard img,.fcard video{width:100%;height:100%;object-fit:cover;display:block}
.fcard-ov{position:absolute;inset:0;display:flex;align-items:flex-start;justify-content:flex-end;
  padding:clamp(.5rem,1vw,.75rem);pointer-events:none;
  background:linear-gradient(rgba(0,0,0,.4),rgba(0,0,0,0) 35%);opacity:0;transition:opacity var(--t) ease}
.fcard:hover .fcard-ov{opacity:1}
.fcard:active .fcard-ov{opacity:1}
/* Twenty-four links to Instagram had no affordance at all on a touch screen —
   hover does not exist there and the overlay rests at 0. The glyph only, not
   the scrim, so the feathered collage keeps its quiet. */
@media (hover:none){
  .fcard-ov{opacity:1;background:none}
  .fcard-ov svg{opacity:.62;filter:drop-shadow(0 1px 3px rgba(0,0,0,.55))}
}
.fcard-ov svg{width:14px;height:14px;fill:#fff}

#stories{padding-bottom:clamp(56px,10vh,110px)}

/* At 390 the resting card would be 350x197 inside an 844px stage — a 323px
   void above and below. The floor now lives in the scrub (main.js §6) because
   the box no longer carries the size. */

@media (max-width:800px){
  .feed{grid-template-columns:repeat(3,1fr);gap:.5rem;padding:0 .5rem}
  .fcol:nth-child(4),.fcol:nth-child(5){display:none}
  .fcol .fcard:nth-child(n+5){display:block}
  .fcol:nth-child(2n){margin-top:calc(-22.2222cqi + .222222rem)}
}

/* ─── §15 footer ────────────────────────────────────────────────────────── */

.foot{background:var(--footer-bg);box-shadow:inset 0 2px 0 0 var(--footer-rule);padding:96px 0 40px}
.foot-line{font-size:clamp(3rem,8.9vw,8rem);font-weight:500;line-height:1;
  letter-spacing:-.025em;margin-bottom:clamp(56px,8vw,110px)}
.foot-cols{display:grid;gap:48px 40px;grid-template-columns:repeat(2,1fr)}
@media (min-width:760px){.foot-cols{grid-template-columns:repeat(2,1fr);gap:48px 40px}}
@media (min-width:1000px){.foot-cols{grid-template-columns:repeat(2,.8fr) repeat(3,1.15fr);gap:64px 40px}}
.foot-col{display:flex;flex-direction:column;align-items:flex-start;gap:12px}
.foot-col .label{color:var(--text-40)}
/* Their footer link rests at #fff and SUBTRACTS ink on hover; ours rested at
   .75 and added. The 735ms curve and the right-to-left origin flip on ::after
   were ported correctly — only the direction was inverted. */
/* F-02 / R60. 15px type on a normal line box is 22.5px tall with 12px between,
   a 34.5px pitch — every target on this page clears 44px except these six, and
   the rule they share is inherited, so the fix is one rule for all six rather
   than anything scoped to the new #team link. The phone already had the right
   answer (padding inside the box, so the leading is untouched); it was only
   ever gated to the phone. The negative block margin hands the column back the
   12px the padding added at each end, so the six boxes come out at a 44.5px
   pitch and 44.5px tall — abutting exactly, never overlapping, which is the
   failure the phone rule already had to design around. */
.foot-col a{position:relative;display:inline-block;padding-block:11px;margin-block:-6px;
  font-size:.9375rem;opacity:1;transition:opacity .735s var(--ease-sig)}
@media (max-width:759px){
  .foot-cols{gap:40px}
}
/* 9px, not −2: the hit box now carries 11px of padding under the baseline, and
   the wipe belongs under the word, not under the target. */
.foot-col a::after{content:'';position:absolute;left:0;right:0;bottom:9px;height:1px;background:currentColor;
  transform:scaleX(0);transform-origin:right;transition:transform .735s var(--ease-sig)}
.foot-col a:hover{opacity:.6}
.foot-col a:hover::after{transform:scaleX(1);transform-origin:left}

.venue{display:flex;flex-direction:column;align-items:flex-start;gap:5px;align-self:start;
  padding-bottom:14px;border-bottom:1px solid var(--rule)}
.venue svg{margin-left:-2px;width:20px;height:24px;margin-bottom:12px;stroke:#fffafa;fill:none;stroke-width:1.1}
.venue h3{font-size:clamp(1.05rem,1.4vw,1.375rem);font-weight:400;letter-spacing:-.02em}
.venue .label{color:var(--text-40)}

.foot-base{display:grid;gap:16px;align-items:center;margin-top:clamp(56px,7vw,96px);
  font-size:.6875rem;letter-spacing:.05em;text-transform:uppercase;color:var(--text-40)}
@media (min-width:760px){.foot-base{grid-template-columns:1fr auto 1fr}.foot-base .mid{text-align:center}.foot-base .end{justify-self:end}}
/* ─── §15b press ────────────────────────────────────────────────────────────
   :active and :hover are both (0,2,0), so source order decides and this has to
   come after every hover rule it shares a property with. In §2 base it was
   losing all of them: the page's one call to action acknowledged a mouse click
   with nothing at all, and .btn-glass was worse than nothing — on press it fell
   back toward --glass and dimmed.
   Only .foot-col a needs a duration; it inherits the 735ms link curve, on which
   a 110ms tap moves opacity by 0.006. The others never transition opacity, so
   their press is already instant.
   .pcard is dropped rather than moved: it is an <article> containing its own
   button, so a press state on it is a false affordance that would also fire
   when the visitor presses the button inside it. */
.btn:active{transform:translateY(0) scale(.97);transition-duration:.08s}
.btn-fill:active{background:#dcdcd6}
.btn-glass:active{background:rgba(255,255,255,.16)}
.fcard:active .fcard-ov{opacity:1}
.socials a:active,.nav-links a:active,.menu a:active{opacity:.6}
.foot-col a:active{opacity:.5;transition-duration:.09s}

.foot-base a{display:inline-block;padding-block:10px}
.foot-base a:hover{color:var(--text)}
.foot-base .socials{margin:0;gap:16px}
.foot-fine{margin-top:22px;font-size:.6875rem;line-height:1.5;color:rgba(255,255,255,.48);max-width:56ch}

/* ─── §16 motion ────────────────────────────────────────────────────────── */

/* The taste rules, from research/sequel/MOTION.md:
     · text you are about to read travels 0–36px, never more;
     · a headline does not travel at all — it de-blurs and fades;
     · opacity, transform and blur are always coupled on one curve;
     · stagger is 100ms between lines, 150ms between blocks, never more;
     · nothing overshoots.
   The pre-states live under html.motion, which JS sets, so a page whose script
   never runs is a static page rather than a blank one. */

html.motion .rv{opacity:0}
html.motion .rv.in{opacity:1}

/* a heading: 8px of blur, no travel, 500ms */
html.motion .rv-t{filter:blur(8px)}
html.motion .rv-t.in{filter:blur(0);transition:opacity .5s var(--ease-2),filter .5s var(--ease-2)}

/* …but once JS has split it, the glyphs carry the reveal and the block itself
   stops animating: chars 20ms apart, 8px of blur, no travel. The word wrapper
   is what keeps lines breaking between words now that every glyph is
   inline-block, and it is the only reason `text-wrap:balance` still works. */
.wd{display:inline-block}
html.motion .rv-t.split{opacity:1;filter:none}
/* The one thing in a split headline that is not a glyph. splitChars only walks
   text, so the inline pill is left at full opacity while the sentence around it
   blurs in — an element popping into a headline that is still arriving. It
   takes the same 500ms curve, delayed to roughly the middle of the stagger, so
   it arrives with the words it sits between. Scale rather than travel: this box
   is inside a line of type and 8px of blur on a 100x56 video is a smear. */
html.motion .thero-pill{opacity:0;transform:scale(.86)}
html.motion .thero-h.in .thero-pill{opacity:1;transform:none;
  transition:opacity .5s var(--ease-2) .28s,transform .5s var(--ease-2) .28s}
html.motion .split .ch{display:inline-block;opacity:0;filter:blur(8px)}
html.motion .split.in .ch{opacity:1;filter:blur(0);
  transition:opacity .5s var(--ease-2),filter .5s var(--ease-2)}

/* §16b — the load timeline ------------------------------------------------
   The bar drops in from −144px over 800ms and the hero's supporting copy
   rises 72px behind the headline's glyphs, 80ms apart. Pre-states live here
   rather than in JS so there is never a frame of un-positioned chrome. */
html.motion .nav{opacity:0;transform:translateY(-144px)}
html.motion .nav.in{opacity:1;transform:none;
  transition:opacity .8s var(--ease-3),transform .8s var(--ease-3)}

html.motion .hero h1{opacity:1}

/* These three used to wait for a class that main.js adds after racing
   document.fonts.ready. That put the hero's description — which is the page's
   LCP element at 29,355px² — on the *script's* clock rather than the page's,
   and on a cold throttled connection main.js does not start executing until
   ~3.8s. Measured LCP 5.56s, with reduced-motion collapsing it to 1.44s, which
   is what proved the animation and not the network was the cost.

   Same delays, same durations, same curve — only the clock changed. As a CSS
   animation with fill-mode both they start at page render, so LCP is bounded
   by the fade beginning rather than by when a 27KB script finishes parsing.
   The headline still splits in JS; it is not the LCP element. */
@keyframes heroRise{from{opacity:0;transform:translateY(72px)}to{opacity:1;transform:none}}
html.motion .hero .hero-eyebrow,
html.motion .hero .hero-aside>*,
html.motion .hero .hero-time{animation:heroRise .7s var(--ease-3) .7s both}
html.motion .hero .hero-aside>*:nth-child(2){animation-delay:.78s}
html.motion .hero .hero-time{animation-delay:.86s}

/* a line of copy or a small element: 36px, 8px of blur, 500ms */
html.motion .rv-l{transform:translateY(36px);filter:blur(8px)}
html.motion .rv-l.in{transform:none;filter:blur(0);
  transition:opacity .5s var(--ease-2),transform .5s var(--ease-2),filter .5s var(--ease-2)}

/* a control: fades only. A button that slides is a button you cannot press. */
html.motion .rv-c.in{transition:opacity .5s var(--ease-2)}

/* a whole block — a card, a tile, a stat: 72px on the slower curve */
html.motion .rv-b{transform:translateY(72px)}
html.motion .rv-b.in{transform:none;transition:opacity .7s var(--ease-3),transform .7s var(--ease-3)}

/* the footer arrives from a long way down, once, on the material curve */
html.motion .rv-f{transform:translateY(180px)}
html.motion .rv-f.in{transform:none;transition:opacity 1s var(--ease-mat),transform 1s var(--ease-mat)}

html.motion .rv[data-d="1"].in{transition-delay:.1s}
html.motion .rv[data-d="2"].in{transition-delay:.2s}
html.motion .rv[data-d="3"].in{transition-delay:.3s}
html.motion .rv-b[data-d="1"].in{transition-delay:.15s}
html.motion .rv-b[data-d="2"].in{transition-delay:.3s}
html.motion .rv-b[data-d="3"].in{transition-delay:.45s}

/* ─── §17 the hero, on the compositor ──────────────────────────────────────
   The same two moves main.js has always made — 0.5px of travel per pixel of
   scroll capped at 450, and a dim from 1 to .5 across 20-80% of the exit —
   expressed as scroll-driven animations so they run off the main thread
   entirely. main.js tests the identical string and stands down when this
   applies, so exactly one of the two is ever live.
   The range is a LENGTH, not 100vh: at a 1200px viewport the JS caps at y=900
   and a viewport unit would not. svh for the dim, because the URL-bar-showing
   viewport is the one a phone starts in. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-media{
      animation:heroDrift linear both;
      animation-timeline:scroll(root block);
      animation-range:0 900px;
    }
    @keyframes heroDrift{from{transform:translate3d(0,0,0)}to{transform:translate3d(0,450px,0)}}

    .hero{
      animation:heroDim linear both;
      animation-timeline:scroll(root block);
      animation-range:20svh 80svh;
    }
    @keyframes heroDim{from{opacity:1}to{opacity:.5}}
  }
}

@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  html.motion .rv,html.motion .rv.in{opacity:1;transform:none;filter:none;transition:none}
  html.motion .split .ch,html.motion .nav,html.motion .hero .hero-eyebrow,
  html.motion .hero .hero-aside>*,html.motion .hero .hero-time,
  html.motion .thero-pill{
    opacity:1;transform:none;filter:none;transition:none;animation:none}
  .mrow,.perks-row{animation:none}
  .fcol{transform:none!important}
  .pcard>img,.pcard>picture>img,.pcard>video{transform:none!important;top:0;height:100%}
  .believe{height:auto}
  .believe-stage{position:static;height:auto;padding-block:clamp(80px,10vw,150px)}
  .believe-card{position:static;inset:auto;clip-path:none;margin-inline:auto;
    width:min(1080px,92vw);height:auto;aspect-ratio:16/9;border-radius:10px}
  .believe-card::after{display:none}
  .believe-lines{display:grid;gap:16px;min-height:0;perspective:none}
  .believe-lines li{grid-area:auto;opacity:1!important;transform:none!important;filter:none!important}
  /* The lamp, not the geometric centre. §1c's rim is fully present in this
     state — it is the only part of the lighting model that ever was — and the
     resting specular now agrees with it instead of contradicting it. */
  .btn::before,.play::before{--mx:var(--lamp-x)!important;--my:var(--lamp-y)!important}
  /* A progress-driven animation has no duration to shorten, so the blanket
     override below would pin these at their end keyframe — full drift at half
     opacity. They have to be named. */
  .hero-media{animation:none!important;transform:none!important}
  .hero{animation:none!important;opacity:1!important}
  *,*::before,*::after{animation-duration:.001ms!important;transition-duration:.001ms!important}
}
