/* ==========================================================================
   Quantum Ed — a Whiteshield product
   Built from the Claude Design export "Quantum Ed.html" (v2).

   The page alternates dark and light sections. Every section carries a
   data-theme attribute; the tokens below flip on it, and main.js / particles.js
   read the same attribute to re-colour the nav, the travelling line and the
   particle field.

   Stacking, from the back:
     0  section backgrounds        (position:relative, z-index auto)
     1  #particle-field            (fixed canvas)
     2  section content, footer    (.container / .site-footer)
     3  travelling line
     4  pinned journey stage       (the film runs over the line, not under it)
    50  header dock
    60  audience switcher
   ========================================================================== */

:root{
  /* Section grounds */
  --bg:#EDEFF0;               /* default light */
  --bg-tint:#F4F6F7;          /* tinted light (02, 07) */
  --bg-dark:#0A1B2E;          /* dark (03, 06, 08) */
  --hero-grad:linear-gradient(168deg,#0B2138 0%,#12335A 44%,#08182A 100%);
  --footer-bg:#0C1F2C;

  /* Brand */
  --navy:#0E3D73;
  --navy-deep:#0A2A50;
  --blue:#2F6BD8;
  --sky:#8FBEF0;

  /* Ink — light ground */
  --ink:#121C26;
  --ink-card:#101C28;
  --prose-l:#3D4854;
  --prose-soft-l:#5A6673;
  --prose-muted-l:#7A8791;
  --prose-card-l:#41505E;
  --rule-l:#D8DCDF;
  --error:#B3261E;            /* invalid form field */

  /* Ink — dark ground */
  --ink-d:#EAF1F8;
  --prose-d:#A9BED2;
  --prose-soft-d:#8397AB;
  --rule-d:rgba(255,255,255,.16);

  /* Footer band height — the last section on the page is sized around it. */
  --footer-h:88px;

  /* Metallic display text */
  /* One pass of light across the whole phrase: dim at the first letter, peak a
     little past the middle, settling again at the last. The stops must never
     double back — a second peak reads as the gradient restarting mid-phrase. */
  --metal-light:linear-gradient(96deg,#0A2A50 0%,#16457F 26%,#4C82C8 56%,#2E68AE 76%,#0C3160 100%);
  --metal-dark:linear-gradient(96deg,#AECCEE 0%,#DCEAFA 26%,#FFFFFF 56%,#E8F1FC 76%,#A6C5E9 100%);

  /* Layout — content occupies the middle 80% of the viewport */
  --content-w:80%;
  --journey-bleed:10vw;       /* the left gutter at --content-w:80% */
  --journey-gap:clamp(32px,5vw,88px);
  /* How far the film runs under the card. The card opens its glass by exactly
     this much and holds its text clear of it, so the two always agree. */
  --film-under:clamp(36px,3.8vw,78px);
  /* How far the film reaches past its own column: across the gap, and then
     under the card by --film-under. */
  --film-over:calc(var(--journey-gap) + var(--film-under));
  --film-r:18px;              /* the film's soft corner */
  --rail:44px;

  /* How many viewport-heights the pinned journey scrolls through */
  --journey-steps:6;

  --serif:"Palatino Linotype",Palatino,"Book Antiqua",Georgia,serif;
  --sans:Archivo,system-ui,-apple-system,"Segoe UI",sans-serif;

  /* Defaults, overridden per theme below. Anything that appears on both a blue
     and a white screen reads one of these rather than a -l/-d token directly, so
     a section can change ground without its contents being rewritten. */
  --eyebrow:var(--navy);
  --prose:var(--prose-l);
  --prose-soft:var(--prose-soft-l);
  --prose-muted:var(--prose-muted-l);
  --heading:var(--ink);
  --accent:var(--navy);
  --rule:var(--rule-l);
  --metal:var(--metal-light);
  --svg-hub:var(--ink);
  --svg-label:#4E6479;
  --line-dot:var(--navy);
  --link:var(--navy);
  /* Glass keeps its light interior on either ground - only the shadow beneath
     it changes, because a white card needs a deeper one to lift off navy. */
  --glass-border:rgba(18,28,38,.12);
  --glass-shadow:0 18px 46px rgba(16,28,38,.14);
  --glass-shadow-lift:0 28px 60px rgba(16,28,38,.20);
  --glass-shadow-on:0 30px 64px rgba(16,28,38,.24);
}

/* Theme flips ------------------------------------------------------------ */

[data-theme="light"]{
  --eyebrow:var(--navy);
  --prose:var(--prose-l);
  --prose-soft:var(--prose-soft-l);
  --prose-muted:var(--prose-muted-l);
  --heading:var(--ink);
  --accent:var(--navy);
  --rule:var(--rule-l);
  --metal:var(--metal-light);
  --svg-hub:var(--ink);
  --svg-label:#4E6479;
  --line-dot:var(--navy);
  --link:var(--navy);
  --glass-border:rgba(18,28,38,.12);
  --glass-shadow:0 18px 46px rgba(16,28,38,.14);
  --glass-shadow-lift:0 28px 60px rgba(16,28,38,.20);
  --glass-shadow-on:0 30px 64px rgba(16,28,38,.24);
}

[data-theme="dark"]{
  --eyebrow:var(--sky);
  --prose:var(--prose-d);
  --prose-soft:var(--prose-soft-d);
  --prose-muted:var(--prose-soft-d);
  --heading:var(--ink-d);
  --accent:var(--sky);
  --rule:var(--rule-d);
  --metal:var(--metal-dark);
  --svg-hub:var(--ink-d);
  --svg-label:#8FB4D6;
  /* LINE_DARK in main.js — the terminus and the line it ends are one colour. */
  --line-dot:#FFFFFF;
  --link:var(--sky);
  --glass-border:rgba(255,255,255,.80);
  --glass-shadow:0 16px 42px rgba(4,14,28,.34);
  --glass-shadow-lift:0 28px 60px rgba(4,14,28,.45);
  --glass-shadow-on:0 30px 64px rgba(4,14,28,.50);
  color:var(--ink-d);
}

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

[hidden]{display:none !important}

html{scroll-behavior:smooth}

body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--sans);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

a{color:var(--link)}
a:hover{color:var(--blue)}

img,svg,video{max-width:100%}

:focus-visible{outline:2px solid var(--blue);outline-offset:3px;border-radius:4px}
[data-theme="dark"] :focus-visible{outline-color:var(--sky)}

.skip-link{
  position:absolute;left:-9999px;top:0;z-index:100;
  background:var(--navy);color:#fff;padding:12px 20px;border-radius:0 0 10px 0;
  font-size:14px;font-weight:600;text-decoration:none;
}
.skip-link:focus{left:0;color:#fff}

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

@keyframes fadeUp{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}

/* --------------------------------------------------------------------------
   Layout primitives
   -------------------------------------------------------------------------- */

.page{position:relative;overflow-x:clip}

/* Middle 80% of the viewport, 10% clear on each side. */
.container{
  width:var(--content-w);
  margin:0 auto;
  position:relative;
  z-index:2;
}

.rail{margin-left:var(--rail)}
/* Section 02 runs the full content width instead of a 24ch/62ch column. Scoped
   under .rail--wide so these beat the .h-section / .lede caps wherever the base
   rules happen to sit in the file. */
.rail--wide{margin-right:var(--rail)}
.rail--wide .h-section--wide{max-width:38ch}
.rail--wide .lede--wide{max-width:none}
@media (max-width:1240px){ .rail--wide .h-section--wide{max-width:24ch} }

/* The particle field sits above the section grounds, below the content. */
#particle-field{
  position:fixed;inset:0;
  width:100%;height:100%;
  z-index:1;
  pointer-events:none;
  display:block;
}

/* Travelling line */
.line-track,
.line-fill{
  /* Fixed, not absolute: the line is placed against the viewport so it holds
     still by construction while the page scrolls, rather than being re-measured
     against the document on every frame. */
  position:fixed;
  width:2px;height:0;
  z-index:3;
  pointer-events:none;
}
.line-track{background:rgba(130,142,156,.40);transition:opacity .35s ease}
.line-fill{background:var(--navy)}   /* main.js swaps in a gradient */

/* Parked: while a journey stage is held, the line stops at a terminus instead
   of running on into the track ahead of it, and picks up again on the way out.
   The dot is the same mark the line ends on at the close. */
.line-fill::after{
  content:"";position:absolute;left:-4px;bottom:-5px;
  width:10px;height:10px;border-radius:50%;
  background:var(--line-dot);
  opacity:0;transform:scale(.4);
  transition:opacity .35s ease,transform .35s ease;
}
.line-fill.is-parked::after{opacity:1;transform:none}
.line-track.is-parked{opacity:0}

/* Out of the way while the use-case tiles hold the screen. */
.line-fill.is-away,
.line-track.is-away{opacity:0;transition:opacity .35s ease}
.line-fill{transition:opacity .35s ease}

/* No z-index here — the section background must paint UNDER the particle canvas. */
section{position:relative}

/* Section grounds --------------------------------------------------------- */

.sec--hero{background:var(--hero-grad);color:var(--ink-d)}
.sec--tint{background:var(--bg-tint)}
.sec--dark{background:var(--bg-dark);color:var(--ink-d)}

/* Every screen is one colour edge to edge: sections fill the viewport and
   centre their content, so you are never looking at two grounds at once. */
.section,
.section--tight,
.section--rule{
  min-height:100vh;
  display:flex;
  align-items:center;
  padding:clamp(44px,5vh,80px) 0;
}

/* This screen runs past one viewport, so its content sits at the padding edge
   rather than being centred — which puts the eyebrow under the floating dock.
   Give it a top padding that clears the dock instead. */
.section--roomy{padding-top:clamp(104px,12vh,160px)}

/* The journey and governments tracks are taller than a screen by nature. */
.section--tight{align-items:flex-start;display:block}

/* --------------------------------------------------------------------------
   Type
   -------------------------------------------------------------------------- */

.eyebrow{
  font-size:15px;
  letter-spacing:.20em;
  text-transform:uppercase;
  color:var(--eyebrow);
  font-weight:600;
  margin:0 0 20px;
}

em{font-style:italic}

.metal{
  font-style:italic;
  font-weight:700;
  padding-right:.09em;
  background:var(--metal);
  -webkit-background-clip:text;
  background-clip:text;
  -webkit-text-fill-color:transparent;
  color:transparent;
  /* The sweep is one pass over one box, so the phrase must not break. The hero's
     "future self" used to split over two lines and each half restarted the
     gradient, which is what made it flicker on and off (client, 2026-08-25).
     Every metal phrase on the site is short enough to hold a line unbroken. */
  white-space:nowrap;
  /* Belt and braces: if a phrase ever does wrap, each fragment gets the whole
     sweep rather than an arbitrary slice of it. */
  -webkit-box-decoration-break:clone;
  box-decoration-break:clone;
}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .metal{background:none;color:var(--navy);-webkit-text-fill-color:currentColor}
  [data-theme="dark"] .metal{color:#FFFFFF}
}

.h-hero{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(48px,6.4vw,92px);
  line-height:1.05;margin:0 0 30px;max-width:16ch;text-wrap:pretty;
}

.h-section{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(32px,3.8vw,52px);
  line-height:1.12;margin:0 0 26px;max-width:24ch;text-wrap:pretty;
}

.h-step{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(24px,2.4vw,32px);margin:0;
}

.h-minor{font-family:var(--serif);font-weight:400;font-size:26px;margin:0 0 14px}

.lede{font-size:18px;line-height:1.65;color:var(--prose);max-width:62ch;margin:0 0 40px}

.body-text{font-size:16px;line-height:1.65;color:var(--prose);margin:0}
.body-text--roomy{line-height:1.7}

.pull-quote{
  font-family:var(--serif);
  font-size:clamp(22px,2.2vw,28px);
  line-height:1.4;max-width:66ch;text-wrap:pretty;
}

.card-label{font-family:var(--serif);font-size:23px;margin:0 0 14px}

.footnote{font-size:13px;color:var(--prose-muted-l);margin:22px 0 0;max-width:70ch}
[data-theme="dark"] .footnote{color:var(--prose-soft-d)}

/* --------------------------------------------------------------------------
   Placeholders left in the design for art still to come
   -------------------------------------------------------------------------- */



/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn{
  display:inline-flex;align-items:center;gap:10px;
  font-family:var(--sans);font-size:15px;font-weight:600;
  padding:15px 26px;border-radius:999px;
  text-decoration:none;cursor:pointer;
  border:1px solid transparent;
  transition:background .25s ease,box-shadow .25s ease,transform .25s ease,border-color .25s ease,color .25s ease;
}
.btn .btn-arrow{font-size:13px}
.btn--sm{padding:14px 24px}

.btn--glass{
  background:linear-gradient(150deg,rgba(255,255,255,.92) 0%,rgba(224,236,250,.78) 100%);
  color:var(--navy);
  border-color:rgba(255,255,255,.75);
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  backdrop-filter:blur(20px) saturate(180%);
  box-shadow:0 12px 32px rgba(4,14,28,.38),inset 0 1px 0 rgba(255,255,255,.95);
}
.btn--glass:hover{
  background:linear-gradient(150deg,#FFFFFF 0%,#E8F1FC 100%);
  color:var(--navy);transform:translateY(-3px);
  box-shadow:0 20px 46px rgba(4,14,28,.45),inset 0 1px 0 rgba(255,255,255,1);
}

.btn--glass-blue{
  background:linear-gradient(150deg,rgba(47,107,216,.55) 0%,rgba(21,62,132,.42) 100%);
  color:#EAF3FF;
  border-color:rgba(143,190,240,.55);
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  backdrop-filter:blur(20px) saturate(180%);
  box-shadow:0 12px 32px rgba(4,14,28,.38),inset 0 1px 0 rgba(255,255,255,.35);
}
.btn--glass-blue:hover{
  background:linear-gradient(150deg,rgba(74,136,238,.70) 0%,rgba(29,80,164,.55) 100%);
  color:#EAF3FF;transform:translateY(-3px);
  box-shadow:0 20px 46px rgba(4,14,28,.45),inset 0 1px 0 rgba(255,255,255,.45);
}

.btn--solid{
  background:var(--navy);color:#FFFFFF;border-color:var(--navy);
  box-shadow:0 10px 26px rgba(14,61,115,.26);
}
.btn--solid:hover{color:#FFFFFF;transform:translateY(-3px);box-shadow:0 18px 40px rgba(14,61,115,.28)}

.btn--outline{background:transparent;color:var(--navy);border-color:rgba(14,61,115,.38)}
.btn--outline:hover{border-color:var(--ink);color:var(--navy)}

/* On a blue ground the flat pills sink into it — navy on #0A1B2E is barely
   readable, which is what made "Talk to us about a deployment" hard to see on
   the close screen, and the same is true of the two pills in each journey now
   that those screens are blue. Give them the hero's treatment there: the
   primary in light glass, the secondary in blue. Light grounds keep the flat
   pills (client, 2026-08-25). */
[data-theme="dark"] .btn--solid{
  background:linear-gradient(150deg,rgba(255,255,255,.92) 0%,rgba(224,236,250,.78) 100%);
  color:var(--navy);
  border-color:rgba(255,255,255,.75);
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  backdrop-filter:blur(20px) saturate(180%);
  box-shadow:0 12px 32px rgba(4,14,28,.38),inset 0 1px 0 rgba(255,255,255,.95);
}
[data-theme="dark"] .btn--solid:hover{
  background:linear-gradient(150deg,#FFFFFF 0%,#E8F1FC 100%);
  color:var(--navy);transform:translateY(-3px);
  box-shadow:0 20px 46px rgba(4,14,28,.45),inset 0 1px 0 rgba(255,255,255,1);
}
[data-theme="dark"] .btn--outline{
  background:linear-gradient(150deg,rgba(47,107,216,.55) 0%,rgba(21,62,132,.42) 100%);
  color:#EAF3FF;
  border-color:rgba(143,190,240,.55);
  -webkit-backdrop-filter:blur(20px) saturate(180%);
  backdrop-filter:blur(20px) saturate(180%);
  box-shadow:0 12px 32px rgba(4,14,28,.38),inset 0 1px 0 rgba(255,255,255,.35);
}
[data-theme="dark"] .btn--outline:hover{
  background:linear-gradient(150deg,rgba(74,136,238,.70) 0%,rgba(29,80,164,.55) 100%);
  color:#EAF3FF;transform:translateY(-3px);
  box-shadow:0 20px 46px rgba(4,14,28,.45),inset 0 1px 0 rgba(255,255,255,.45);
}

.btn-row{display:flex;gap:14px;flex-wrap:wrap}

/* --------------------------------------------------------------------------
   Header dock: removed

   The bespoke dock was replaced by the shared site nav (site-nav.css). Its
   rules did not just go dead, they collided: .nav-group, .nav-caret and
   .nav-dropdown are class names the site nav uses too, so the old rules kept
   applying to the new markup.

   Two visible faults came from that. .nav-caret drew a CSS-border chevron
   while the site nav expects a text glyph, so both rendered at once and read
   as a broken arrow. .nav-dropdown set margin-top:14px where the site rule
   uses padding-top, so the margin survived and left a dead 14px gap between
   the trigger and the dropdown: the pointer crossed unhoverable space and the
   menu closed before it could be clicked.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   01 Hero
   -------------------------------------------------------------------------- */

.hero{
  min-height:100vh;
  display:flex;flex-direction:column;justify-content:center;
  padding:140px 0 90px;
}
.hero .eyebrow{margin-bottom:26px}
.hero .lede{color:var(--prose-d)}

.line-start{display:block;width:0;height:0;margin-top:64px}

.scroll-hint{
  position:absolute;bottom:28px;left:50%;transform:translateX(-50%);
  display:flex;flex-direction:column;align-items:center;gap:10px;
  z-index:2;transition:opacity .3s;
}
.scroll-hint__word{font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:#8FB4D6}
.scroll-hint__rule{display:block;width:1px;height:36px;background:#8397AB}

/* --------------------------------------------------------------------------
   02 What Quantum Ed is
   -------------------------------------------------------------------------- */

.triad{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
  gap:clamp(32px,4vw,72px);
}

/* --------------------------------------------------------------------------
   Route selector — used to be a screen of its own. It is a strip at the foot
   of "What Quantum Ed is" now, so picking a route costs no scroll.
   -------------------------------------------------------------------------- */

.route{
  /* The screen is allowed to run past one viewport here: the reading above has
     to settle before the route question is put, so the selector sits below a
     clear run of space rather than crowding the pull quote (client, 2026-08-25). */
  margin-top:clamp(140px,20vh,260px);
  padding-top:clamp(24px,3vh,40px);
  border-top:1px solid var(--rule);
  display:flex;align-items:center;
  gap:clamp(18px,3vw,48px);flex-wrap:wrap;
}
.route__head{flex:0 0 auto;min-width:0}
.route__eyebrow{margin:0}

.route__tiles{display:flex;gap:12px;flex-wrap:wrap;flex:1 1 400px}

.route__tile{
  flex:1 1 190px;
  display:flex;align-items:center;gap:12px;
  padding:14px 18px;border-radius:14px;
  text-align:left;cursor:pointer;
  font-family:var(--sans);font-size:15px;font-weight:600;
  color:var(--ink-card);
  background:linear-gradient(150deg,rgba(255,255,255,.92),rgba(238,244,251,.82));
  border:1px solid rgba(18,28,38,.10);
  box-shadow:0 10px 26px rgba(16,28,38,.10),inset 0 1px 0 rgba(255,255,255,.92);
  transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease,background .25s ease,opacity .25s ease;
}
.route__tile:hover{transform:translateY(-3px);box-shadow:0 16px 34px rgba(16,28,38,.14)}
.route__tile[data-state="selected"]{
  border-color:rgba(14,61,115,.55);
  background:linear-gradient(150deg,#FFFFFF,#DCE9FA);
  box-shadow:0 16px 38px rgba(16,28,38,.16),inset 0 1px 0 rgba(255,255,255,1);
}
.route__tile[data-state="muted"]{opacity:.6}

.route__icon{flex:0 0 auto;width:22px;height:22px;color:var(--navy)}
.route__icon svg{width:100%;height:100%;display:block}
.route__label{line-height:1.25}
.triad__col{position:relative}
/* One mark per column. The particles draw the figure inside this box; the only
   thing in the markup is the single solid element that anchors it — the star you
   steer by, the two ends of the measure, the point on the globe. Both are
   measured from the same box, so they always line up. */
.col-mark{
  display:block;width:120px;height:120px;
  margin:0 0 14px;color:var(--navy);pointer-events:none;
  opacity:0;transition:opacity .5s ease;
}
/* The constellation and the measure run wide; the globe stays square so it
   draws as a circle. Same height on all three, so the headings line up. */
.col-mark--wide{width:172px}
.col-mark.is-on{opacity:1}
.col-mark svg{width:100%;height:100%;display:block;overflow:visible}
.dist-label{
  font-family:var(--sans);font-size:15px;font-weight:600;
  letter-spacing:.06em;fill:var(--navy);
}
@media (max-width:900px){ .col-mark{display:none} }

/* --------------------------------------------------------------------------
   03 Who are you
   -------------------------------------------------------------------------- */

[data-sec3] .container{z-index:0}
.audience{display:flex;gap:clamp(20px,2.5vw,36px);flex-wrap:wrap;align-items:stretch}

.audience__card{
  position:relative;overflow:hidden;
  flex:1 1 380px;min-width:280px;
  /* Taller than the copy needs, with the text pushed to the foot, so the
     drawing on the canvas behind has the top half of the tile to itself
     (client, 2026-08-24). */
  min-height:clamp(360px,44vh,500px);
  display:flex;flex-direction:column;justify-content:flex-end;
  text-align:left;padding:clamp(32px,3vw,48px) clamp(28px,2.6vw,44px);
  background:linear-gradient(150deg,rgba(255,255,255,.94) 0%,rgba(238,244,251,.86) 100%);
  -webkit-backdrop-filter:blur(24px) saturate(160%);
  backdrop-filter:blur(24px) saturate(160%);
  border:1px solid rgba(255,255,255,.55);
  border-radius:20px;
  box-shadow:0 16px 40px rgba(4,14,28,.32),inset 0 1px 0 rgba(255,255,255,.85);
  opacity:1;cursor:pointer;font-family:var(--sans);
  transition:background .3s ease,border-color .3s ease,box-shadow .3s ease,opacity .3s ease,transform .25s ease;
}
.audience__card:hover{transform:translateY(-4px)}

.audience__card[data-state="selected"]{
  background:linear-gradient(150deg,#FFFFFF 0%,#DCE9FA 100%);
  border-color:rgba(14,61,115,.55);
  box-shadow:0 26px 60px rgba(4,14,28,.50),inset 0 1px 0 rgba(255,255,255,.95);
  opacity:1;
}
.audience__card[data-state="muted"]{opacity:.55}

.audience__sheen{
  position:absolute;inset:0;border-radius:20px;pointer-events:none;
  background:radial-gradient(120% 80% at 10% -15%,rgba(255,255,255,.9) 0%,rgba(255,255,255,.25) 40%,rgba(255,255,255,0) 68%);
}

.audience__card > :not(.audience__sheen){position:relative}

.audience__card .ph-icon{border-color:rgba(14,61,115,.32);margin-bottom:26px}

.audience__title{
  display:block;font-family:var(--serif);
  font-size:clamp(26px,2.6vw,38px);line-height:1.15;
  color:var(--ink-card);margin-bottom:14px;text-wrap:pretty;
  /* One tile's heading wraps to two lines and the other does not, so with the
     copy bottom-aligned the two headings sat at different heights. Reserving
     two lines in both lines them up (client, 2026-08-24). */
  min-height:2.3em;
}
.audience__blurb{
  display:block;font-size:16px;line-height:1.65;
  color:var(--prose-card-l);max-width:46ch;
}

.sentinel{height:1px}

/* --------------------------------------------------------------------------
   04 The journey — pinned scroll stage
   -------------------------------------------------------------------------- */

.journey__intro{padding-top:clamp(96px,14vh,180px)}

.journey__hook{
  font-family:var(--serif);
  font-size:clamp(26px,3vw,44px);
  line-height:1.2;margin:0 0 40px;max-width:30ch;text-wrap:pretty;
}
/* The individual-track hook is the long one — at 30ch it broke over three
   lines. Widen it and balance so it lands on two even lines (client,
   2026-08-25). */
.journey__hook--long{max-width:64ch;text-wrap:balance}

/* The scroller is tall; the stage inside it sticks for the whole run, so the
   screen holds still and only the step content changes. */
.journey__scroller{
  position:relative;
  height:calc(var(--journey-steps) * 100vh);
}
.journey__pinned{
  position:sticky;top:0;
  height:100vh;
  display:flex;align-items:center;
  /* Above the line (3): the film reaches past the left gutter, where the line
     runs, and it should read as passing in front of it rather than being cut
     by it. overflow:hidden keeps that reach from opening a sideways scroll. */
  z-index:4;
  overflow:hidden;
}

.journey__layout{
  display:flex;gap:var(--journey-gap);
  align-items:center;width:100%;
}
.journey__steps{flex:1 1 52%;min-width:0}
/* Over the film, which reaches under this column's left edge. */
.journey__panel-col{flex:1 1 40%;min-width:0;position:relative;z-index:1}

/* Learner run: the film holds the left, the step copy rides in the card. */
.journey__media{flex:1 1 50%;min-width:0}

/* The film overflows its column to the left rather than being given a negative
   margin of its own: overflow does not feed back into the flex sizing, so the
   card on the right keeps exactly the width it had. max-width is undone
   because the global img/svg/video rule would otherwise clamp the reach. */
.journey__video{
  display:none;
  width:calc(100% + var(--journey-bleed) + var(--film-over));
  max-width:none;
  margin-left:calc(-1 * var(--journey-bleed));
  /* Taller than the film's own 16/9: the frame stands proud of the card top
     and bottom, and cover takes the difference off the top and bottom edges
     rather than squeezing the picture. */
  aspect-ratio:16/10;
  object-fit:cover;
  /* Flush to the screen on the left, soft on the two corners that show. */
  border-radius:0 var(--film-r) var(--film-r) 0;
  background:var(--bg-dark);
  /* Read outwards: the soft white edge, then the film's own spill onto the
     section, then the shadow it casts. All three in one property so they
     composite in that order and none of them costs any layout. The left of
     each is off the screen, which is where the frame is flush. */
  box-shadow:
    0 0 0 1px rgba(255,255,255,.20),
    0 0 100px -14px rgba(116,166,228,.22),
    0 40px 92px -34px rgba(2,10,20,.80);
}
/* Shown as soon as a film is wired in, so the poster holds the frame until
   main.js has metadata to scrub against. */
.journey__video[src]{display:block}
.journey__media-stage{
  position:relative;aspect-ratio:16/9;
  border:1px solid rgba(255,255,255,.13);
  border-radius:var(--film-r);
  background:rgba(255,255,255,.03);
}
/* Once a film is dropped in, the empty slot steps aside. */
.journey__media:has(video[src]) .journey__media-stage{display:none}

/* Steps are stacked and cross-faded in place */
.journey__stage{position:relative;min-width:0;min-height:clamp(300px,46vh,440px)}

.step{
  position:absolute;inset:0;
  display:flex;flex-direction:column;justify-content:center;
  opacity:0;visibility:hidden;
  transform:translateY(14px);
  transition:opacity .45s ease,transform .45s ease,visibility 0s linear .45s;
}
.step.is-active{opacity:1;visibility:visible;transform:none;transition:opacity .45s ease,transform .45s ease,visibility 0s}

.step__num{
  font-size:15px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--accent);font-weight:600;margin:0 0 10px;
}

/* The government stage ends on a card whose items arrive one per screen of
   scroll rather than all at once — main.js adds .is-shown in turn. */
/* --------------------------------------------------------------------------
   Use-case carousel — the tail of the government run

   The tiles sit on one long track that is translated right to left as the stage
   scrolls, so the examples read as their own movement rather than as a list
   inside a step. They overlap slightly and the middle one is brought forward.
   -------------------------------------------------------------------------- */

/* Three boxes, because the arrows must be outside whatever clips the tiles:
     .usecarousel        full-bleed frame, holds the band and the dots
     .usecarousel__band  the band and the arrows — its height is the tiles', so
                         the arrows centre on them and not on the dots below
     .usecarousel__view  the clip, inset from the screen so there is a clear
                         gutter for the arrows to sit in
   --car-edge is that gutter; --car-fade is how far the tiles dissolve inside
   the clip, so the run of tiles ends softly instead of being sliced off. */
.usecarousel{
  position:relative;
  margin:clamp(18px,3vh,34px) 0 0;
  --car-edge:clamp(58px,5.2vw,104px);
  --car-fade:clamp(34px,3.4vw,68px);
  width:100vw;
  margin-left:50%;transform:translateX(-50%);
}
.usecarousel__band{position:relative}
.usecarousel__view{
  position:relative;
  width:calc(100% - 2 * var(--car-edge));
  margin:0 auto;
  overflow:hidden;
  /* room for the centre tile to grow past the track without clipping */
  padding:34px 0 14px;
}
/* Gradient rather than a mask: a mask on this box would make it a backdrop root
   and the tiles' own backdrop-filter would have nothing left to sample. These
   sit over the tiles and under the arrows. */
.usecarousel__view::before,
.usecarousel__view::after{
  content:"";position:absolute;top:0;bottom:0;
  width:var(--car-fade);z-index:3;pointer-events:none;
}
.usecarousel__view::before{
  left:0;
  background:linear-gradient(to right,var(--bg-dark) 0%,rgba(10,27,46,0) 100%);
}
.usecarousel__view::after{
  right:0;
  background:linear-gradient(to left,var(--bg-dark) 0%,rgba(10,27,46,0) 100%);
}
.usecarousel__track{
  list-style:none;margin:0;padding:0;
  display:flex;align-items:stretch;
  will-change:transform;
  transition:transform .55s cubic-bezier(.22,.7,.2,1);
}

.usecase-card{
  flex:0 0 auto;
  /* wider and close to square: these carry a whole scenario, not a bullet */
  width:clamp(300px,27vw,400px);
  min-height:clamp(250px,20vw,310px);
  display:flex;flex-direction:column;
  /* the overlap */
  margin-right:clamp(-26px,-1.6vw,-14px);
  padding:clamp(18px,1.6vw,26px);
  border-radius:20px;
  background:linear-gradient(150deg,rgba(255,255,255,.90) 0%,rgba(232,240,250,.74) 100%);
  -webkit-backdrop-filter:blur(22px) saturate(170%);
  backdrop-filter:blur(22px) saturate(170%);
  border:1px solid var(--glass-border);
  box-shadow:var(--glass-shadow);
  color:var(--ink-card);
  /* the tile carries one scenario, centred in its own space */
  justify-content:center;
  text-align:center;
  /* Quieter than the centre tile, not darker than it: at .38 the dark ground
     showed straight through and the neighbours read as shadows. Closer in scale
     too, so the row reads as one band of cards. */
  transform:scale(.86);
  opacity:.72;
  transition:transform .55s cubic-bezier(.22,.7,.2,1),opacity .55s ease,box-shadow .55s ease;
}
/* the one under the reader's eye comes forward and clears its neighbours */
.usecase-card.is-current{
  transform:scale(1.08);
  opacity:1;
  z-index:2;
  box-shadow:var(--glass-shadow-lift);
}
/* The glyph is masked rather than drawn, so one rule tints every icon with the
   card's own ink and the source files need no editing. */
.usecase-card__icon{
  width:clamp(30px,2.6vw,38px);
  height:clamp(30px,2.6vw,38px);
  margin:0 auto clamp(14px,1.2vw,18px);
  background:var(--navy);
  opacity:.85;
  -webkit-mask-position:center;mask-position:center;
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
}
.usecase-card__icon--authority{-webkit-mask-image:url(../img/icons/authority.svg);mask-image:url(../img/icons/authority.svg)}
.usecase-card__icon--training{-webkit-mask-image:url(../img/icons/training.svg);mask-image:url(../img/icons/training.svg)}
.usecase-card__icon--entity{-webkit-mask-image:url(../img/icons/entity.svg);mask-image:url(../img/icons/entity.svg)}
.usecase-card__icon--job-offer{-webkit-mask-image:url(../img/icons/job-offer.svg);mask-image:url(../img/icons/job-offer.svg)}
.usecase-card__who{
  font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--navy);font-weight:600;margin:0 0 14px;
}
.usecase-card__text{
  font-size:clamp(15px,1.2vw,19px);line-height:1.55;
  color:var(--prose-card-l);margin:0;
}

.usecarousel__dots{
  display:flex;justify-content:center;gap:9px;
  margin-top:clamp(16px,2vh,26px);
}
.usecarousel__dot{
  width:7px;height:7px;border-radius:50%;
  background:var(--rule);
  transition:background .3s ease,transform .3s ease;
}
.usecarousel__dot.is-on{background:var(--accent);transform:scale(1.5)}

/* While the tiles are running the panel steps aside and the stage gives the
   carousel its full width. display:none, not just opacity — a faded column
   keeps its share of the flex row, and the track is then centred on the left
   column rather than on the screen. */
/* The carousel owns the whole stage for the last slices of the run: the film
   column and the card both step aside. It sits last in the markup because
   main.js reads [data-step] in document order, and first on screen because the
   others are gone by then. */
.journey__tail{display:none;flex:1 1 100%}
.journey__pinned.is-tail .journey__tail{display:block}
.journey__pinned.is-tail .journey__panel-col,
.journey__pinned.is-tail .journey__media{display:none}
/* The stage is sized for a step card; the carousel and its controls need more,
   and the pinned box clips whatever overflows. */
.journey__pinned.is-tail .journey__stage{min-height:min(600px,74vh)}

/* Dots only now — the arrows have moved out to the edges. */
.usecarousel__nav{
  display:flex;align-items:center;justify-content:center;
  margin-top:clamp(18px,2.4vh,30px);
}
.usecarousel__dots{
  display:flex;justify-content:center;align-items:center;gap:10px;
  margin:0;
}
.usecarousel__dot{
  width:8px;height:8px;border-radius:50%;padding:0;
  border:none;cursor:pointer;
  background:var(--rule);
  transition:background .3s ease,transform .3s ease;
}
.usecarousel__dot:hover{background:var(--accent);transform:scale(1.3)}
.usecarousel__dot.is-on{background:var(--accent);transform:scale(1.6)}

/* A mark, not a button. The glass discs sat in the middle of the row and read
   as the loudest thing on the screen; these are two bare chevrons against the
   edges, on the same line as the cards.
   The carousel's padding is 34px over the track and 14px under it, so the box
   centre is 10px above the cards' own — hence the offset rather than a plain
   50%. */
.usecarousel__arrow{
  position:absolute;top:calc(50% + 10px);
  transform:translateY(-50%);
  width:clamp(38px,3.2vw,48px);height:clamp(38px,3.2vw,48px);
  border-radius:50%;
  /* A white ring over a hint of the ground, so it reads on the dark section and
     on a dimmed tile equally. The bare chevron it replaces was --sky at .42,
     which disappeared against both. */
  background:rgba(10,27,46,.34);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  border:1.5px solid rgba(255,255,255,.72);
  padding:0;cursor:pointer;z-index:3;
  transition:background .25s ease,border-color .25s ease,transform .25s ease;
}
/* In the gutter, clear of the tiles entirely. */
.usecarousel__arrow--prev{left:clamp(6px,0.9vw,18px)}
.usecarousel__arrow--next{right:clamp(6px,0.9vw,18px)}
/* Two strokes meeting at a point, drawn with a rotated corner. */
.usecarousel__arrow::before{
  content:"";position:absolute;top:50%;left:50%;
  width:clamp(9px,0.8vw,12px);height:clamp(9px,0.8vw,12px);
  border-right:2px solid #FFFFFF;border-bottom:2px solid #FFFFFF;
  border-radius:1px;
}
.usecarousel__arrow--prev::before{transform:translate(-40%,-50%) rotate(135deg)}
.usecarousel__arrow--next::before{transform:translate(-60%,-50%) rotate(-45deg)}
.usecarousel__arrow:hover,
.usecarousel__arrow:focus-visible{
  background:rgba(255,255,255,.18);
  border-color:#FFFFFF;
  transform:translateY(-50%) scale(1.06);
}
/* the arrows wrap, so they are never dead */
.usecarousel__arrow:disabled{cursor:pointer}

/* no persona strip on this card, so it sits a little higher in the stage */
.step--tail{justify-content:center}
.step--tail .h-step{margin-bottom:2px}

/* Step copy. One voice per step now that the persona selector is gone. */
.step__lede{
  margin:12px 0 0;
  font-size:clamp(16px,1.2vw,18px);line-height:1.65;color:var(--prose);
  max-width:52ch;
}

/* On the card the step copy reads against glass, not against the dark ground. */
.panel .journey__stage{flex:1;min-height:clamp(230px,34vh,330px)}
.panel .step__num{color:var(--navy)}
.step__num--figure{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(40px,4.2vw,64px);
  letter-spacing:0;text-transform:none;
  line-height:1;margin:0 0 14px;
}
.panel .h-step{color:var(--ink-card)}
.panel .step__lede{color:var(--prose-card-l);max-width:none}

/* Scroll-scrubbed panel */
/* Liquid glass. It sits above the particle canvas, so backdrop-filter picks up
   the field drifting behind it rather than a flat ground. */
.panel{
  position:relative;overflow:hidden;
  /* Liquid glass. The card reaches over the film, so it is thin enough that
     what is behind it comes through as soft shape and colour rather than
     detail. brightness in the backdrop filter is what makes that safe: it
     lifts whatever the card is sitting on — the dark section as much as a dark
     frame of film — so the ink keeps its contrast wherever the card lands
     instead of going grey over the darker shots. */
  /* Open evenly across the overlap — the same value from the card's left edge
     to where the film ends, then a short feather into the body. Held even on
     purpose: ramping it across the overlap read as a smear rather than a pane.
     The padding below keeps every word off it, so the opening is free to cover
     the whole overlap without costing the ink any contrast. */
  background:linear-gradient(90deg,
    rgba(250,252,255,.66) 0,
    rgba(250,252,255,.66) var(--film-under),
    rgba(233,240,249,.84) calc(var(--film-under) + 24px));
  /* Barely any brightness lift. It is tempting to lift the backdrop hard so the
     glass reads light, but that blows out the film in the band where the film
     is the whole point — the light comes from the tint above instead, and the
     blur keeps it to shape and colour rather than legible detail. */
  -webkit-backdrop-filter:blur(30px) saturate(180%) brightness(1.18);
  backdrop-filter:blur(30px) saturate(180%) brightness(1.18);
  border:1px solid var(--glass-border);
  border-radius:20px;
  /* Floating over the film rather than resting on the section, so it takes the
     heavier of the two shadows, and catches light on both edges. */
  box-shadow:
    var(--glass-shadow-lift),
    inset 0 1px 0 rgba(255,255,255,.95),
    inset 0 -1px 0 rgba(255,255,255,.28);
  color:var(--ink-card);
  /* Left inset clears the overlap, so no line begins on the glass band. */
  padding:clamp(22px,2vw,32px) clamp(24px,2.2vw,34px) clamp(22px,2vw,32px)
          calc(var(--film-under) + clamp(14px,1.1vw,20px));
  min-height:clamp(360px,52vh,480px);
  display:flex;flex-direction:column;
}
.panel::before{
  content:"";position:absolute;inset:0;border-radius:20px;pointer-events:none;
  background:radial-gradient(110% 78% at 42% -20%,rgba(255,255,255,.46) 0%,rgba(255,255,255,.12) 44%,rgba(255,255,255,0) 72%);
}
.panel > *{position:relative}
.panel__head{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap}
.panel__kicker{
  font-size:14px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--navy);font-weight:600;
}
.panel__video{display:none;width:100%;border-radius:8px;margin-top:20px}
.panel__stage{position:relative;flex:1;min-height:240px;margin-top:8px}
.panel__state{
  position:absolute;inset:0;
  display:flex;flex-direction:column;justify-content:center;
  opacity:0;transition:opacity .25s ease;
}
.panel__state.is-active{opacity:1}
.panel__state-num{font-family:var(--serif);font-size:clamp(48px,5vw,72px);color:var(--navy)}
.panel__state-title{font-family:var(--serif);font-size:clamp(20px,1.8vw,26px);margin-top:8px}
.panel__foot{margin-top:18px}
.panel__bar{height:2px;background:#E2E6E9;border-radius:1px;overflow:hidden}
.panel__bar-fill{height:100%;width:0%;background:var(--navy)}

.access{
  margin-left:var(--rail);
  border-top:1px solid var(--rule);
  padding:44px 0 clamp(96px,12vh,160px);max-width:72ch;
}
.access p{font-size:16px;line-height:1.65;color:var(--prose);margin:0 0 28px}

/* --------------------------------------------------------------------------
   05 For governments
   -------------------------------------------------------------------------- */

.gov-block{padding:clamp(120px,16vh,200px) 0 clamp(96px,12vh,160px)}

.gov-list{max-width:88ch}
.gov-list p{
  border-top:1px solid var(--rule);
  padding:30px 0 0;margin:0 0 30px;
  font-size:16.5px;line-height:1.7;color:var(--prose);
}
.gov-list p:last-child{margin-bottom:0}
.gov-list strong{color:var(--heading);font-weight:600}

.usecases{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
  gap:36px clamp(32px,4vw,64px);
}
.usecases p{margin:0;font-size:15px;line-height:1.7;color:var(--prose-soft)}

.block-80{margin-top:72px}
.block-80--narrow{max-width:88ch}
.block-80 p{font-size:16px;line-height:1.65;color:var(--prose);margin:0 0 28px}

/* --------------------------------------------------------------------------
   06 Champions
   -------------------------------------------------------------------------- */

/* Copy, diagram and roster share one screen, so everything here is sized off
   the viewport rather than fixed: the figure shrinks before the text does. */
.champions{display:flex;gap:clamp(28px,3.6vw,64px);flex-wrap:wrap;align-items:center}
.champions__copy{flex:1 1 460px;min-width:300px}
.champions__copy .h-section{margin-bottom:clamp(14px,1.8vh,24px)}
/* :not(.eyebrow) because the eyebrow is a <p> in here too, and this rule
   outranks .eyebrow on specificity — it was overriding its size and colour
   (client, 2026-08-25). */
.champions__copy p:not(.eyebrow){
  font-size:clamp(14.5px,1.05vw,16px);line-height:1.62;
  color:var(--prose);margin:0 0 clamp(9px,1.2vh,14px);max-width:62ch;
}
.champions__copy p:not(.eyebrow):last-child{margin-bottom:0}
.champions__figure{flex:0 1 clamp(260px,26vw,360px);min-width:240px}
.champions__figure svg{width:100%;height:auto;display:block;max-height:34vh}

.champ-node{transition:opacity .5s;opacity:.45}
.champ-node.is-active{opacity:1}
.champ-line{transition:stroke .5s,stroke-width .5s}

.svg-hub{font-family:var(--sans);font-size:11px;letter-spacing:.16em;fill:var(--svg-hub)}
.svg-label{font-family:var(--sans);font-size:11px;letter-spacing:.14em;fill:var(--svg-label)}

/* Meet the champions */
.champ-roster{margin-left:var(--rail);margin-top:clamp(12px,1.6vh,26px)}
.champ-roster .eyebrow{margin-bottom:clamp(12px,1.6vh,22px)}
/* a square portrait made the row too tall to share the screen with the diagram */
/* The portraits are 2:3, the card slot is wider than that, and the faces sit
   high in the frame — so cover and bias the crop upward rather than letting it
   centre on a torso. */
.champ-card__portrait{
  display:block;width:100%;
  /* height:auto or the width/height attributes act as a used height and
     aspect-ratio is ignored, because both dimensions would then be given. */
  height:auto;
  aspect-ratio:5/4;
  /* Each source is pre-framed to 5:4 with the heads at a common size and eye
     line, so nothing is cropped here — cover is only a guard against a
     replacement file arriving at a different ratio. */
  object-fit:cover;object-position:50% 50%;
  border-radius:12px;
  background:#DCE6F2;
  margin-bottom:clamp(9px,1.2vh,14px);
}
.champ-grid{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:clamp(16px,1.6vw,28px);align-items:stretch;
}
.champ-card{
  /* flex column, because a <button> vertically centres its content: a card
     whose quote runs to one line instead of two had its whole block pushed
     down and the portrait then sat lower than its neighbours. */
  display:flex;flex-direction:column;align-items:stretch;justify-content:flex-start;
  width:100%;text-align:left;
  font-family:var(--sans);cursor:pointer;
  background:linear-gradient(150deg,rgba(255,255,255,.95) 0%,rgba(226,237,250,.86) 100%);
  -webkit-backdrop-filter:blur(24px) saturate(170%);
  backdrop-filter:blur(24px) saturate(170%);
  border:1px solid var(--glass-border);
  border-radius:18px;padding:clamp(12px,1.1vw,18px);
  box-shadow:var(--glass-shadow),inset 0 1px 0 rgba(255,255,255,.95);
  color:var(--ink-card);
  transition:transform .25s ease,box-shadow .25s ease,background .25s ease,border-color .25s ease;
}
.champ-card:hover{
  transform:translateY(-8px);
  border-color:rgba(14,61,115,.42);
  background:linear-gradient(150deg,#FFFFFF 0%,#E4EFFC 100%);
  box-shadow:var(--glass-shadow-lift),inset 0 1px 0 rgba(255,255,255,1);
}
.champ-card:active{transform:translateY(-2px)}
.champ-card[aria-pressed="true"]{
  background:linear-gradient(150deg,#FFFFFF 0%,#DCE9FA 100%);
  border-color:rgba(14,61,115,.55);
  box-shadow:var(--glass-shadow-on),inset 0 1px 0 rgba(255,255,255,1);
  transform:translateY(-6px);
}
.champ-card[aria-pressed="true"] .champ-card__portrait{box-shadow:0 0 0 2px rgba(14,61,115,.45)}
.champ-card__field{
  font-size:11px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--navy);font-weight:600;margin:0 0 8px;
}
.champ-card__role{font-family:var(--serif);font-size:22px;line-height:1.2;color:var(--ink-card);margin:0 0 6px}
.champ-card__name{font-size:13px;font-weight:600;letter-spacing:.01em;color:var(--navy);margin:0 0 12px}
.champ-card__line{font-size:14px;line-height:1.6;color:var(--prose-card-l);margin:0;font-style:italic}

/* Sheen — a highlight that sweeps the card under the cursor. Same treatment as
   the route cards in section 03. */
.champ-card{position:relative;overflow:hidden}
.champ-card__sheen{
  position:absolute;inset:0;pointer-events:none;border-radius:inherit;
  background:linear-gradient(115deg,transparent 30%,rgba(255,255,255,.85) 48%,transparent 66%);
  transform:translateX(-120%);transition:transform .75s cubic-bezier(.2,.7,.2,1);
}
.champ-card:hover .champ-card__sheen,
.champ-card:focus-visible .champ-card__sheen{transform:translateX(120%)}
.champ-card>*:not(.champ-card__sheen){position:relative;z-index:1}

/* The orb paints nothing itself — it is a measuring box for the particle
   field, which draws the sphere on its own fixed canvas. */
.sovereign__orb,
.close__orb{
  position:absolute;right:4%;top:50%;transform:translateY(-50%);
  width:min(38%,420px);aspect-ratio:1/1;pointer-events:none;
}
@media (max-width:900px){ .sovereign__orb,.close__orb{display:none} }

/* --------------------------------------------------------------------------
   07 What it unlocks
   -------------------------------------------------------------------------- */

.outputs{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));
  gap:clamp(36px,4.5vw,80px);
}

.closer-line{
  font-family:var(--serif);
  font-size:clamp(24px,2.6vw,36px);
  line-height:1.35;text-align:center;max-width:70ch;
  margin:clamp(56px,7vh,96px) auto 0;text-wrap:pretty;
}

/* --------------------------------------------------------------------------
   08 Deployment and data
   -------------------------------------------------------------------------- */

.sovereign{
  margin-left:var(--rail);
  border-top:1px solid var(--rule);
  border-bottom:1px solid var(--rule);
  padding:40px 0;max-width:72ch;
}
.sovereign h2{
  font-family:var(--serif);font-weight:400;font-size:clamp(22px,2vw,28px);
  color:var(--prose);margin:0 0 10px;
}
.sovereign p{font-size:14.5px;line-height:1.7;color:var(--prose-soft);margin:0}

/* --------------------------------------------------------------------------
   09 Close
   -------------------------------------------------------------------------- */

/* The footer takes the bottom of the last screen, so a full-viewport close can
   never be read whole: scrolled to the end, its top slides under the dock. It
   is sized to the screen minus the footer, and the top padding keeps the
   statement clear of the dock at every height. */
/* Not the last section any more, so it hands the footer allowance on and takes
   a whole screen again. The top padding stays — that is what keeps the
   statement out from under the dock. */
.close{
  min-height:100vh;
  min-height:100svh;
  display:flex;align-items:center;
  padding:clamp(88px,11vh,124px) 0 clamp(32px,4vh,56px);
}
/* The terminus. Absolute inside the rail so it lands against the statement and
   takes no part in the layout: -81px is the rail's own indent plus the 37px the
   line was pulled clear of the copy, which puts it back on the line's x. The
   offset is in em of the statement's own size, so it holds the same place
   against the second line at every viewport. */
.line-end{
  position:absolute;
  left:-81px;
  top:1.75em;
  font-size:clamp(28px,3.4vw,50px);
  line-height:1;
  width:10px;height:10px;border-radius:50%;
  background:var(--line-dot);
}
.close .rail{position:relative}
.close__statement{
  font-family:var(--serif);
  font-size:clamp(28px,3.4vw,50px);
  line-height:1.25;max-width:30ch;margin:0 0 clamp(36px,5vh,64px);text-wrap:pretty;
}
.close__product{font-family:var(--serif);font-size:28px;margin:0 0 8px}
.close__byline{margin:0 0 clamp(28px,4vh,40px);font-size:14px;letter-spacing:.1em;color:var(--prose-soft)}

/* --------------------------------------------------------------------------
   Footer — sits above the particle canvas
   -------------------------------------------------------------------------- */

/* Shorter than it was: the last screen reserves this height in its top padding,
   so every pixel here is a pixel the team row and the form do not get
   (client, 2026-08-27). Keep --footer-h in step with this padding. */
.site-footer{
  position:relative;z-index:2;
  background:var(--footer-bg);color:#B9C7D1;padding:34px 0;
}
.site-footer .container{
  display:flex;justify-content:space-between;align-items:center;gap:24px;flex-wrap:wrap;
}
.site-footer__logo{height:20px;width:auto;display:block;filter:brightness(0) invert(1)}
.footer-links{display:flex;align-items:center;gap:24px;flex-wrap:wrap}
.footer-links a{font-size:13px;color:#B9C7D1;text-decoration:none}
.footer-links a:hover{color:#FFFFFF}
.footer-links .copyright{font-size:13px;color:#7A8B97}

/* --------------------------------------------------------------------------
   Audience switch (floating)
   -------------------------------------------------------------------------- */

.switcher{
  position:fixed;bottom:20px;right:20px;z-index:60;
  opacity:0;pointer-events:none;transition:opacity .3s;
}
.switcher.is-visible{opacity:1;pointer-events:auto}
.switcher button{
  background:rgba(255,255,255,.96);
  border:1px solid var(--rule-l);border-radius:999px;
  padding:11px 18px;
  font-family:var(--sans);font-size:13px;font-weight:600;color:var(--navy);
  cursor:pointer;box-shadow:0 6px 20px rgba(16,28,38,.1);
}

/* --------------------------------------------------------------------------
   Reveal-on-scroll
   -------------------------------------------------------------------------- */

.reveal-ready[data-reveal]{
  opacity:0;transform:translateY(26px);
  transition:opacity .6s ease,transform .6s ease;
}
.reveal-ready[data-reveal="left"]{transform:translateX(48px)}
.reveal-ready[data-reveal="right"]{transform:translateX(-48px)}
.reveal-ready[data-reveal].is-in{opacity:1;transform:none}

[data-anim]{animation:fadeUp .7s cubic-bezier(.2,.6,.2,1) both}
[data-anim="1"]{animation-duration:.6s;animation-delay:.05s}
[data-anim="2"]{animation-delay:.15s}
[data-anim="3"]{animation-delay:.3s}
[data-anim="4"]{animation-delay:.45s}

/* --------------------------------------------------------------------------
   Example page
   -------------------------------------------------------------------------- */

.example-page{
  min-height:100vh;display:flex;flex-direction:column;justify-content:center;
  padding:80px 0;
}
.example-page h1{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(36px,4.5vw,64px);line-height:1.1;
  margin:0 0 24px;max-width:20ch;text-wrap:pretty;
}
.example-page .lede{font-size:17px;max-width:56ch}


/* --------------------------------------------------------------------------
   10 The team
   -------------------------------------------------------------------------- */

/* Flex rather than a fixed column count: at five people a four-column grid
   leaves the fifth stranded at the left of its own row, and any orphan row here
   centres itself instead. The basis decides how many fit; the cap stops three
   of them stretching into billboards on a wide screen. */
/* Three to a row with the remainder centred underneath. The basis is an exact
   third of the row rather than a rough one with a width cap on top, so the two
   on the second row come out the same width as the three above them — a card
   left alone on a last row used to grow to fill it. max-width lives on the row
   instead, or three cards would each be 480px wide on a large screen. */
.team-grid{
  --team-gap:clamp(13px,1.3vw,22px);
  display:flex;flex-wrap:wrap;justify-content:center;
  align-items:stretch;
  gap:var(--team-gap);
  max-width:1056px;
  /* Centred rather than left-aligned at the rail: the heading keeps the rail
     indent, the row of people sits in the middle of the page. */
  margin-left:auto;margin-right:auto;
  margin-top:clamp(12px,1.6vh,24px);
}
.team-card{flex:0 1 calc((100% - 2 * var(--team-gap)) / 3)}
.team-card{
  display:flex;flex-direction:column;align-items:center;text-align:center;
  background:linear-gradient(150deg,rgba(255,255,255,.95) 0%,rgba(226,237,250,.86) 100%);
  -webkit-backdrop-filter:blur(24px) saturate(170%);
  backdrop-filter:blur(24px) saturate(170%);
  border:1px solid var(--glass-border);
  border-radius:18px;
  padding:clamp(17px,1.45vw,22px) clamp(15px,1.3vw,20px) clamp(19px,1.65vw,24px);
  box-shadow:var(--glass-shadow),inset 0 1px 0 rgba(255,255,255,.95);
  color:var(--ink-card);
  transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease;
}
.team-card:hover{
  transform:translateY(-6px);
  border-color:rgba(14,61,115,.34);
  box-shadow:var(--glass-shadow-lift),inset 0 1px 0 rgba(255,255,255,1);
}

/* The frame is a circle and the initial sits under the photograph, so a portrait
   that has not been supplied yet reads as a monogram rather than a hole. */
.team-card__portrait{
  position:relative;display:grid;place-items:center;
  width:clamp(70px,5.5vw,88px);aspect-ratio:1;
  border-radius:50%;overflow:hidden;
  background:linear-gradient(160deg,#E4EDF8 0%,#CFDDEE 100%);
  box-shadow:0 0 0 1px rgba(14,61,115,.10),0 8px 18px -10px rgba(16,28,38,.35);
  margin-bottom:clamp(9px,0.9vw,13px);
}
.team-card__initial{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(22px,2.1vw,30px);line-height:1;
  color:var(--navy);opacity:.55;
}
.team-card__portrait img{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;object-position:50% 30%;
  /* The reference set is black and white, and mixed sources would not sit
     together in colour. */
  filter:grayscale(1) contrast(1.04);
}
.team-card__name{
  font-family:var(--serif);font-size:clamp(17.5px,1.38vw,21px);line-height:1.2;
  color:var(--ink-card);margin:0 0 4px;
}
.team-card__role{
  font-size:12.5px;font-weight:600;letter-spacing:.02em;
  color:var(--navy);margin:0 0 8px;
}
.team-card__bio{
  font-size:13.75px;line-height:1.5;color:var(--prose-card-l);
  margin:0;max-width:34ch;
}

/* --------------------------------------------------------------------------
   11 Start here
   -------------------------------------------------------------------------- */

/* Last section on the page: the footer takes the bottom of the final screen, so
   size to what is left of it or the heading rides under the dock. */
.cta{
  min-height:calc(100vh - var(--footer-h));
  min-height:calc(100svh - var(--footer-h));
  padding:clamp(88px,10vh,124px) 0 clamp(32px,4vh,56px);
}
/* The ask reads as a column of its own beside the form rather than a banner
   over it, so it is left-aligned and keeps its own measure. */
.cta__head{flex:1 1 42%;min-width:0;margin:0}
.cta__head .h-section{max-width:20ch;margin:0 0 20px}
.cta__sub{
  font-size:clamp(16px,1.25vw,19px);line-height:1.6;
  color:var(--prose-soft-l);margin:0;max-width:38ch;
}
/* align-items:center is what puts the two halves on the same line: the form is
   taller than the words beside it, so without it the copy would sit against the
   top of the panel instead of level with its middle. */
.cta__body{
  display:flex;align-items:center;justify-content:center;
  gap:clamp(30px,4.5vw,76px);
  max-width:1120px;margin:0 auto;
}
.cta__panel{flex:1 1 52%;min-width:0;max-width:620px}


.cta-form,
.cta-form__ok{
  background:linear-gradient(150deg,rgba(255,255,255,.96) 0%,rgba(235,243,252,.90) 100%);
  -webkit-backdrop-filter:blur(24px) saturate(170%);
  backdrop-filter:blur(24px) saturate(170%);
  border:1px solid var(--glass-border);
  border-radius:20px;
  box-shadow:var(--glass-shadow),inset 0 1px 0 rgba(255,255,255,.95);
  padding:clamp(24px,2.2vw,36px);
  color:var(--ink-card);
}
/* Underlined fields rather than boxes: three boxes in a row read as a database
   form, and this is the only input on the page. */
.cta-form__brief,
.cta-form input{
  width:100%;font-family:var(--sans);font-size:16px;color:var(--ink-card);
  background:transparent;border:0;border-bottom:1px solid var(--rule-l);
  padding:10px 2px;border-radius:0;
  transition:border-color .2s ease;
}
.cta-form__brief{resize:vertical;min-height:104px;line-height:1.6;margin-bottom:clamp(18px,2vh,26px)}
.cta-form__brief::placeholder,
.cta-form input::placeholder{color:var(--prose-muted-l)}
.cta-form__brief:focus,
.cta-form input:focus{outline:0;border-bottom-color:var(--navy)}
.cta-form__row{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(14px,1.4vw,22px);margin-bottom:clamp(22px,2.6vh,32px);
}
.cta-form__field{min-width:0}
.cta-form__send{margin:0}

/* Carries the form's status line: the validation prompt, "Sending", and the
   fallback message if the send fails. */
.cta-form__notice{
  margin:16px 0 0;font-size:14.5px;line-height:1.55;
  color:var(--navy);font-weight:600;
}
.cta-form__notice[hidden]{display:none}

.cta-form__reply{
  display:flex;align-items:center;gap:12px;
  margin:clamp(20px,2.4vh,30px) 0 0;
  font-size:14px;line-height:1.55;color:var(--prose-card-l);
}
.cta-form__reply strong{color:var(--ink-card)}
.cta-form__reply-face{
  position:relative;flex:0 0 auto;display:grid;place-items:center;
  width:40px;height:40px;border-radius:50%;overflow:hidden;
  background:linear-gradient(160deg,#E4EDF8 0%,#CFDDEE 100%);
}
.cta-form__reply-face .team-card__initial{font-size:17px;opacity:.6}
.cta-form__reply-face img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:50% 30%;filter:grayscale(1);
}

/* --------------------------------------------------------------------------
   The team and the enquiry, on one screen
   -------------------------------------------------------------------------- */

/* Both halves have to land inside a single viewport, so this screen runs
   tighter than the rest of the page: display:block because .section centres a
   single child and there are two here, and the type comes down a step so the
   row of people and the form can both be full size in their own terms
   (client, 2026-08-27). */
.contact{
  /* A column rather than .section's centred single child: two containers ride
     in here, the top padding clears the floating dock, and what is left over
     splits above and below so the pair sits in the middle of the screen
     instead of leaving a band of empty tint above the footer. */
  display:flex;flex-direction:column;justify-content:center;align-items:stretch;
  /* Taller than the .cta screen it inherits from: that one was sized to leave
     the footer on the same screen, and this one carries two blocks, so it takes
     the whole viewport and lets the footer follow (client, 2026-08-27).
     The top padding carries the footer height on top of the dock clearance for
     that reason: the page comes to rest with the footer at the bottom, which
     puts this screen scrolled a footer past its own top, and without the
     allowance the eyebrow would come to rest underneath the dock. */
  min-height:100vh;
  min-height:100svh;
  padding:calc(var(--footer-h) + clamp(88px,10vh,120px)) 0 clamp(34px,4vh,56px);
}
/* The row of people and the enquiry are two separate asks, so they get a gap
   that reads as one rather than a hairline between them. */
.contact .container + .container{margin-top:clamp(72px,10vh,128px)}
.contact .h-section{font-size:clamp(27px,2.5vw,37px);margin-bottom:clamp(10px,1.4vh,18px)}
.contact .eyebrow{margin-bottom:clamp(9px,1.1vh,15px)}
/* The enquiry heading is the ask on this screen, so it carries weight instead of
   size: same size as the team heading beside it, set bold. The serif is a system
   Palatino/Georgia stack, so 700 is a real cut rather than a synthesised one. */
/* The enquiry rides in the same bounds as the team row above it rather than in
   the 1120px box .cta__body centres by default: that box left the heading about
   460px whatever the screen, which is what was folding it onto two lines. With
   the head a share of the row instead, its width tracks the viewport, so one
   size in vw holds the heading on one line at every width (client, 2026-08-27). */
.contact .cta__body{max-width:none;margin-left:var(--rail);margin-right:var(--rail)}
.contact .cta__head{flex:1 1 46%}
.contact .cta__panel{flex:1 1 54%;max-width:none}
.contact .cta__head .h-section{max-width:none;font-weight:400;font-size:clamp(27px,2.75vw,52px)}

/* Five across on one line. The basis is an exact fifth of the row, as the
   three-up basis was, so no card is left to grow into a row of its own.
   The row is bounded by the rail on BOTH sides rather than centred inside a
   left-railed box: centred, it came out 44px clear of the dock on the left and
   flush against it on the right, which read as the row breaking the alignment
   the dock sets (client, 2026-08-27). A tighter gap than the three-up row, so
   five cards still get their width back. */
.contact .rail{margin-right:var(--rail)}
.team-grid--row{
  --team-gap:clamp(10px,0.95vw,17px);
  max-width:none;margin-top:clamp(6px,0.9vh,14px);
}
.team-grid--row .team-card{
  flex:0 1 calc((100% - 4 * var(--team-gap)) / 5);
  padding:clamp(13px,1.05vw,17px) clamp(10px,0.85vw,14px) clamp(14px,1.15vw,18px);
}
.team-grid--row .team-card__portrait{
  width:clamp(50px,3.8vw,60px);
  margin-bottom:clamp(6px,0.65vw,9px);
}
.team-grid--row .team-card__name{font-size:clamp(14.5px,1.05vw,16.5px);margin-bottom:2px}
.team-grid--row .team-card__role{font-size:11px;line-height:1.35;margin-bottom:0}

/* The panel gives up the height it does not need: the brief is the one field
   that can lose it without the form reading as cramped. */
.contact .cta-form{padding:clamp(18px,1.6vw,26px)}
.contact .cta-form__brief{min-height:clamp(52px,6.5vh,72px);margin-bottom:clamp(10px,1.3vh,16px)}
.contact .cta-form__row{margin-bottom:clamp(14px,1.7vh,20px)}

/* The send button and the reassurance beside it, rather than stacked. */
.cta-form__foot{
  display:flex;align-items:center;
  gap:clamp(12px,1.2vw,18px);flex-wrap:wrap;
}
/* No <strong> around it any more, so the ink it used to inherit from that comes
   from here instead: normal weight, but not the lighter prose grey. */
.cta-form__foot .cta-form__reply{margin:0;color:var(--ink-card)}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width:1200px){
  :root{--content-w:86%;--journey-bleed:7vw}
}

@media (max-width:1000px){
  .champ-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cta__body{flex-direction:column;align-items:stretch;gap:clamp(26px,3.4vh,40px);max-width:none}
  .cta__head,.cta__panel{flex:1 1 auto;max-width:none}
  .cta__head .h-section,.cta__sub{max-width:none}
  .journey__layout{flex-direction:column;align-items:stretch;gap:28px}
  .journey__panel-col{flex:1 1 auto}
  .journey__media{flex:1 1 auto}
  /* Stacked: the film is the full width of its own column, so there is no
     gutter to reach into and every corner is on show. Set on the element rather
     than the token, which a narrower breakpoint below would re-set. */
  .journey__video{
    width:100%;margin-left:0;
    aspect-ratio:16/9;
    border-radius:var(--film-r);
  }
  /* Nothing runs under the card here, so the band and the inset it was making
     room for both come off. */
  .panel{
    background:linear-gradient(150deg,rgba(250,252,255,.86) 0%,rgba(233,240,249,.80) 100%);
    padding-left:clamp(24px,2.2vw,34px);
  }
  .panel{min-height:0}
}

@media (max-width:900px){
  :root{--content-w:92%;--journey-bleed:4vw}
  /* The dock rules that lived here went with the dock. */
  .champions{gap:40px}
  /* Pinning a full stage on a short screen traps the reader — unpin it. */
  .journey__scroller{height:auto}
  .journey__pinned{position:static;height:auto;display:block;overflow:visible}
  .journey__stage{min-height:0}
  .step{
    position:static;opacity:1;visibility:visible;transform:none;
    margin-bottom:56px;
  }
  .step:last-child{margin-bottom:0}
}

@media (max-width:640px){
  :root{--rail:26px}
  .cta,.contact{min-height:0}
  .cta-form__row{grid-template-columns:1fr}
  .section,.section--tight,.section--rule{min-height:0;padding:clamp(72px,10vh,110px) 0}
  .hero{padding:120px 0 72px}
  .close{min-height:0}
  .audience__blurb{max-width:none}
  .champ-grid{grid-template-columns:1fr}
  .site-footer .container{align-items:flex-start}
}

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .reveal-ready[data-reveal]{opacity:1;transform:none}
  [data-anim]{animation:none;opacity:1;transform:none}
  .audience__card:hover,.champ-card:hover,.btn:hover,.site-header__bar:hover{transform:none}
  /* Unpin the journey and let all six steps read as a normal list. */
  .journey__scroller{height:auto}
  .journey__pinned{position:static;height:auto;display:block;overflow:visible}
  .journey__stage{min-height:0}
  .step{position:static;opacity:1;visibility:visible;transform:none;margin-bottom:56px}
  .step:last-child{margin-bottom:0}
  /* Nothing is scrubbing the track here, so the tiles read as a plain column. */
  .usecarousel{width:auto;margin-left:0;transform:none}
  .usecarousel__view{width:auto;overflow:visible;padding:0}
  .usecarousel__view::before,.usecarousel__view::after{display:none}
  .usecarousel__track{flex-direction:column;gap:16px;transform:none !important}
  .usecase-card{width:auto;margin-right:0;transform:none;opacity:1}
  .usecarousel__dots,
  .usecarousel__arrow{display:none}
}

/* The champion field labels are set wide; below this the longest one wraps and
   drops that card's role and quote out of line with its neighbours. Tighten the
   tracking rather than let it break. */
@media (max-width:1400px){
  .champ-card__field{letter-spacing:.12em;font-size:10.5px}
}

/* --------------------------------------------------------------------------
   02 held: the three inputs arrive one per screen of scroll
   -------------------------------------------------------------------------- */

.stage__scroller{
  position:relative;
  height:calc(var(--stage-beats) * 100vh);
}
.stage__pinned{
  position:sticky;top:0;
  height:100vh;
  display:flex;align-items:center;
  overflow:hidden;
}

/* Anything marked as a beat holds its space from the start, so nothing reflows
   as it arrives — only its own contents fade up. */
[data-beat]{
  opacity:0;transform:translateY(22px);
  transition:opacity .55s ease,transform .55s ease;
}
[data-beat].is-shown{opacity:1;transform:none}

/* It is a proof point now, not a footnote: wider and a size up again, since the
   deployment and data sentences moved onto the end of it and a 96ch column at
   footnote size turned that into a stack (client, 2026-08-27). */
.what__proof{
  max-width:114ch;
  font-size:clamp(15px,1.2vw,17.5px);
  line-height:1.62;
  margin-top:22px;
}

@media (prefers-reduced-motion: reduce){
  /* Unpinned: the whole reading is simply there. */
  .stage__scroller{height:auto}
  .stage__pinned{position:static;height:auto;display:block;overflow:visible}
  [data-beat]{opacity:1;transform:none}
  .what__proof{max-width:none}
}

/* --------------------------------------------------------------------------
   Route switch — rides at the top of the journey, above the hook.
   -------------------------------------------------------------------------- */

.journey__intro .route,
[data-sec4] > .container > .route,
[data-sec5] > .container > .route{margin-top:0}

/* At the head of a blue screen the strip needs air above it for the dock, and a
   rule underneath rather than over it. */
[data-sec4] .route,
[data-sec5] .route{
  margin:clamp(96px,13vh,170px) 0 0;
  padding:0 0 clamp(18px,2.4vh,30px);
  border-top:none;
  border-bottom:1px solid var(--rule);
}

/* --------------------------------------------------------------------------
   Short viewports — the journey cards
   -------------------------------------------------------------------------- */

/* A laptop screen gives the step card around 360px to work with. A heading that
   runs to four lines then needs more room than the stage has, and because the
   step is centred in that stage it overflowed upwards into the kicker as well as
   down onto the progress bar. The numeral is the cheapest thing to give back, so
   it goes first, and the heading follows it down a step. Height, not width: a
   wide-but-short window has exactly this problem and a width query misses it. */
@media (max-height:780px){
  .step__num--figure{
    font-size:clamp(30px,3.2vw,44px);
    margin-bottom:8px;
  }
  .panel .h-step{font-size:clamp(22px,2.1vw,28px)}
}

/* The step is absolutely placed and centred in its stage, so a heading longer
   than the stage can hold overflowed BOTH ways — upward into the kicker as much
   as down onto the bar. Auto margins centre it while there is room to spare and
   collapse to nothing when there is not, so a long heading grows downward only
   and never crosses the kicker. */
.panel .step{justify-content:flex-start}
.panel .step > :first-child{margin-top:auto}
.panel .step > :last-child{margin-bottom:auto}

/* The pull-quote that used to open this beat carried its top spacing (38px).
   With the quote gone the proof line leads the beat on its own, so it takes
   that spacing over rather than crowding the row above it. */
[data-beat] > .what__proof:first-child{margin-top:38px}

/* --------------------------------------------------------------------------
   The team row — how many to a row
   -------------------------------------------------------------------------- */

/* Stepping the count down explicitly, rather than leaving it to the basis and
   letting the browser decide — that gave four across with the fifth stranded on
   its own row at some widths. justify-content:center does the rest: whatever is
   left over centres itself instead of hugging the left edge. */
@media (max-width:820px){
  .team-card,
  .team-grid--row .team-card{flex:0 1 calc((100% - var(--team-gap)) / 2)}   /* two to a row */
}
@media (max-width:560px){
  .team-card,
  .team-grid--row .team-card{flex:0 1 100%}
}

/* --------------------------------------------------------------------------
   Metal card labels on small screens
   -------------------------------------------------------------------------- */

/* .metal sets white-space:nowrap so the gradient sweeps one unbroken box. That
   holds for every short phrase, but "For the person: direction towards your
   goal." needs 450px and the mobile rail is 333px, so it was clipped at the
   screen edge. Let the card labels wrap below 700px. The gradient stays correct
   because .metal already sets box-decoration-break:clone, so each wrapped line
   gets the whole sweep instead of a slice of it. The hero and every other
   metal phrase keep nowrap and are untouched. */
@media (max-width:700px){
  .card-label.metal{white-space:normal}
}

/* --------------------------------------------------------------------------
   Contact form states
   -------------------------------------------------------------------------- */

/* Off-screen rather than display:none, so a bot that skips hidden fields still
   fills it. Never focusable, never announced. */
.cta-form__hp{
  position:absolute;left:-9999px;width:1px;height:1px;
  opacity:0;pointer-events:none;
}

.cta-form input.is-bad,
.cta-form__brief.is-bad{border-bottom-color:var(--error)}

/* Replaces the form once the send succeeds, keeping the card above. */
.cta-form__ok b{
  display:block;font-family:var(--serif);font-size:clamp(24px,2.4vw,32px);
  font-weight:400;color:var(--ink-card);margin-bottom:10px;
}
.cta-form__ok p{
  margin:0;font-size:15px;line-height:1.6;color:var(--prose-card-l);
}
