/* ==========================================================================
   Valor Resourcing Group
   Static, typographic single page: thesis, standard, process, ambassador, routes.
   Palette per BRAND.md §11 as amended 10 Aug 2026 (navy / sand / gold / ice).
   ========================================================================== */

/* -- 0. Fonts (self-hosted latin subsets; no third-party requests) --------- */

@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("assets/fonts/manrope-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("assets/fonts/dm-mono-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("assets/fonts/dm-mono-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -- 1. Tokens ------------------------------------------------------------ */

:root {
  /* Brand */
  --navy: #002949;
  --navy-deep: #001d33;
  --navy-grad-light: #093c64;  /* background gradient range only — never the emblem */
  --navy-grad-deep: #001a2f;
  --gold: #c6a15b;             /* rules, marks and accent text on dark — 6.1:1 on navy */
  --gold-hover: #d3b273;
  --gold-text: #7d6029;        /* gold text on light — 5.9:1 on white, 4.8:1 on sand */

  /* Surfaces */
  --sand: #f2e7d8;
  --panel: #fff;
  --panel-tint: #f8f3ea;

  /* Text */
  --ink: #102d3d;
  --muted: #4e6068;            /* body copy on light — 5.4:1 on sand */
  --muted-strong: #3f545c;     /* small labels on light — 6.5:1 on sand */
  --on-navy: #fff;             /* headings on navy */
  --ice: #d7e5f3;              /* body copy on navy — 11.6:1 */
  --ice-soft: #b9cfe2;         /* secondary text on navy */
  --ice-faint: #9db4c9;        /* tertiary text on deep navy */

  /* Lines */
  --line: rgba(16, 45, 61, .16);
  --line-strong: rgba(16, 45, 61, .32);
  --line-on-navy: rgba(215, 229, 243, .22);
  --line-on-navy-strong: rgba(215, 229, 243, .44);
  --field-line: #5f6f76;       /* form-field boundaries — ≥3:1 on white and panel-tint */
  --focus-ring: #997634;       /* ≥3:1 against navy, sand and white alike */

  /* Type */
  --display: "Manrope", "Helvetica Neue", Arial, sans-serif;
  --mono: "DM Mono", "SFMono-Regular", Consolas, monospace;
  --h1: clamp(42px, 5.2vw, 78px);
  --h2: clamp(32px, 3.8vw, 52px);
  --h3: clamp(24px, 2.3vw, 29px);
  --lede: 18px;
  --text: 16px;
  --text-sm: 14px;
  --label: 11px;
  --label-sm: 10px;
  --track: .06em;

  /* Rhythm */
  --shell: min(1180px, calc(100vw - 72px));
  /* The header height is held in one token because the sticky offsets derive
     from it. The 160px wordmark renders ~64px tall, leaving a calm 12px above
     and below without letting the utility bar dominate the opening screen. */
  --header-h: 88px;
  --section-y: clamp(78px, 9vw, 130px);
  --radius: 4px;
  --panel-pad: 28px;
  /* How far a row travels as it arrives (§14 · D1). One token, because the
     scroll-driven branch and the JavaScript fallback must move by the same
     amount or the two branches are two different designs. */
  --arrive-y: 14px;
}

/* -- 2. Base -------------------------------------------------------------- */

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

html { scroll-behavior: smooth; }

body {
  min-width: 320px;
  margin: 0;
  color: var(--ink);
  background: var(--sand);
  font-family: var(--display);
  /* `clip`, not `hidden`: `overflow-x: hidden` forces the used `overflow-y` to
     `auto`, which would make <body> a scroll container and capture every
     `view()` timeline in §14 before it could reach the viewport. `clip` sheds
     the same horizontal overflow without creating a scrollport. */
  overflow-x: clip;
}

/* Author-level `display` on a component would otherwise beat the UA stylesheet's
   `[hidden] { display: none }`, leaving hidden elements on screen. */
[hidden] { display: none !important; }

a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; }
button { cursor: pointer; }
img { max-width: 100%; }
h1, h2, h3, h4, p { margin-top: 0; }

h1 { margin-bottom: 25px; font-size: var(--h1); line-height: .96; letter-spacing: -.075em; }
h2 { margin-bottom: 22px; font-size: var(--h2); line-height: 1.02; letter-spacing: -.06em; }
h3 { font-size: var(--h3); line-height: 1.06; letter-spacing: -.05em; }

/* Gold display italics: dark-legible gold on light grounds by default; the two
   navy sections re-lighten it below. Serif italics want near-zero tracking. */
h1 em,
h2 em {
  color: var(--gold-text);
  font-family: Georgia, "Times New Roman", serif;
  font-weight: 400;
  letter-spacing: -.01em;
}

/* One focus language across every control: the mid gold clears 3:1 on navy,
   sand and white, so no per-section overrides are needed. */
:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: 2px;
}

main:focus { outline: none; }

[id] { scroll-margin-top: 24px; }

/* -- 3. Primitives -------------------------------------------------------- */

.shell { width: var(--shell); margin-inline: auto; }
.section-space { padding-block: var(--section-y); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: fixed;
  z-index: 100;
  top: -60px;
  left: 20px;
  padding: 10px 14px;
  color: var(--navy-deep);
  background: var(--gold);
  border-radius: 5px;
  font-weight: 700;
}
.skip-link:focus { top: 20px; }

/* A23: the eyebrow speaks the demo's register — gold dash, then "01 · Label"
   in one mono voice. The pill numeral is retired. */
.eyebrow {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 0 0 19px;
  font: 500 var(--label) / 1.35 var(--mono);
  letter-spacing: .075em;
  text-transform: uppercase;
}
.eyebrow::before {
  flex: none;
  width: 34px;
  height: 2px;
  background: var(--gold);
  content: "";
}
.eyebrow span::after {
  content: "·";
  content: "·" / "";
  margin-left: 12px;
}

.button {
  display: inline-flex;
  gap: 11px;
  min-height: 48px;
  padding: 0 18px;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 12px;
  font-weight: 800;
  text-align: center;
  transition: transform .2s ease, background .2s ease, border-color .2s ease;
}
.button:hover { transform: translateY(-2px); }
.button span { font-size: 17px; }
.button--gold { color: var(--navy-deep); background: var(--gold); }
.button--gold:hover { background: var(--gold-hover); }
.button--line { border-color: var(--line-on-navy-strong); color: var(--on-navy); }
.button--line:hover { border-color: var(--gold); }
.button--navy { color: #fff; background: var(--navy); }
.button--navy:hover { background: var(--navy-grad-light); }
/* `[aria-disabled="true"]`, not `[disabled]`. app.js never sets `disabled` — it
   uses aria-disabled plus a re-entry guard so keyboard focus is not dropped
   mid-form — so the old attribute selector matched nothing and the in-flight
   button had no state at all: it read "Sending…" while still lifting under the
   cursor. The hover is restated here so the lift is suppressed for the one
   moment the button is refusing input. */
.button[aria-disabled="true"],
.button[aria-disabled="true"]:hover { cursor: progress; opacity: .65; transform: none; }

/* Shared split heading: title left, lede right. Light sections by default;
   dark sections recolour it in their own blocks. */
/* `column-gap`, and an explicit zero row gap — never the `gap` shorthand. A
   percentage row gap resolves against the container's own block size, which is
   indefinite here: the auto height is computed with the gap at zero and the gap
   is then resolved against that height and applied when the rows are placed. On
   desktop the two items share one row so nothing shows, but from 800px down —
   where the heading stacks — the lede was pushed 11% of the heading's height
   below its own container, squeezing the 38px above the block that follows to
   between 16px and −6px depending on how tall that heading happened to be. The
   stacked row spacing is the lede's own margin in §16. */
.section-heading {
  display: grid;
  grid-template-columns: 1fr .64fr;
  column-gap: 11%;
  row-gap: 0;
  align-items: end;
}
.section-heading .eyebrow { color: var(--gold-text); }
.section-heading h2 { max-width: 16ch; margin-bottom: 0; }
.section-heading > p {
  max-width: 44ch;
  margin: 0;
  color: var(--muted);
  font-size: var(--lede);
  line-height: 1.65;
}

/* -- 4. Header ------------------------------------------------------------ */

.site-header-band {
  position: relative;
  z-index: 10;
  background: var(--navy);
}

.site-header {
  display: flex;
  min-height: var(--header-h);
  align-items: center;
  gap: 24px;
  /* Faint on purpose: the band and the hero top share the same navy, so this
     reads as a drafting rule under the nav, not a seam between two surfaces. */
  border-bottom: 1px solid rgba(215, 229, 243, .16);
  color: var(--on-navy);
}

/* BRAND.md as amended: the full logo never renders below 120 px. */
.brand-lockup { display: block; flex: 0 0 auto; width: 160px; min-width: 160px; }
.brand-lockup img { display: block; width: 100%; height: auto; object-fit: contain; }

/* A39: the header carries the two universal destinations. The service and
   audience routes remain in the hero/body, where they have enough context. */
.header-actions {
  display: flex;
  flex: 0 0 auto;
  gap: 0;
  align-items: center;
  margin-left: auto;
  padding: 5px;
  border: 1px solid rgba(215, 229, 243, .18);
  border-radius: 6px;
  background: rgba(0, 29, 51, .26);
  box-shadow: 0 12px 30px rgba(0, 18, 32, .12);
  transform: translateY(3px);
}

/* About stays quieter than the direct-contact action, with one fine divider
   giving the compact pair a clear reading order. */
.header-link {
  display: inline-flex;
  gap: 8px;
  min-height: 44px;
  padding: 0 15px;
  align-items: center;
  border-right: 1px solid var(--line-on-navy);
  color: var(--ice);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .01em;
  white-space: nowrap;
  transition: color .2s ease;
}
.header-link::after {
  color: var(--gold);
  font-size: 15px;
  line-height: 1;
  content: "\2192";
  transition: transform .2s ease;
}
.header-link:hover { color: #fff; }
.header-link:hover::after { transform: translateX(2px); }

.header-cta {
  display: inline-flex;
  gap: 9px;
  min-height: 44px;
  padding: 0 15px;
  align-items: center;
  border: 1px solid var(--gold);
  border-radius: var(--radius);
  color: var(--on-navy);
  background: rgba(198, 161, 91, .08);
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
  transition: border-color .2s ease, background .2s ease, color .2s ease;
}
/* The header echoes the hero's button family in outline, so the hero retains
   the opening screen's single gold fill. */
.header-cta:hover { background: var(--gold); color: var(--navy-deep); }
.header-cta__label { font-size: 11px; }
.header-cta__arrow { font-size: 16px; color: var(--gold); transition: color .2s ease; }
.header-cta:hover .header-cta__arrow { color: var(--navy-deep); }

/* -- 5. Hero -------------------------------------------------------------- */

/* A42 · Handover. The hero is not a box that ends, it is a navy panel that
   retracts. The section's own surface is the sand section 01 stands on, so the
   seam has something true to uncover rather than a colour it has to imitate;
   the navy is a layer above it, because a seam can only clip a layer, not a
   colour. Isolated because five layers now share this box and none of them
   should be able to argue with the header band above it. */
.site-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  isolation: isolate;
  overflow: hidden;
  color: var(--on-navy);
  background: var(--sand);
}

/* The navy panel. Its top edge is the same navy as the header band, so header
   and hero read as one surface — the light no longer sits in a band under the
   logo, it blooms from the open right-hand side of the type.
   rgb(9, 60, 100) is --navy-grad-light with alpha — the glow stays inside the
   A1 gradient range. */
.hero-ground {
  position: absolute;
  z-index: 1;
  inset: 0;
  background:
    radial-gradient(64% 78% at 82% 42%, rgba(9, 60, 100, .78) 0%, rgba(9, 60, 100, 0) 68%),
    linear-gradient(180deg, var(--navy) 0%, var(--navy-grad-deep) 100%);
}
/* The drafting grid rides inside the panel — it has to retract with the navy,
   not hang over the sand. */
.hero-ground::before {
  position: absolute;
  inset: 0;
  content: "";
  opacity: .55;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(215, 229, 243, .09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(215, 229, 243, .08) 1px, transparent 1px);
  background-size: 72px 72px;
  mask-image: linear-gradient(115deg, transparent 36%, black 84%);
  -webkit-mask-image: linear-gradient(115deg, transparent 36%, black 84%);
}

/* Single copy column (A12). A23: the fork band is gone — the hero carries two
   simple actions and a mono microcopy line instead, so the band breathes again.
   Hierarchy per A19: the H1 states the service; the locked strapline runs on
   from "search." in the gold serif italic as the supporting voice. */
.hero-inner {
  position: relative;
  z-index: 3;
  padding: clamp(34px, 3.8vw, 54px) 0 clamp(36px, 4.4vw, 62px);
}
.hero-copy { max-width: none; }

/* A41: ordinary-height viewports get a complete first screen again. The copy is
   centred in the space above the scope band; wide displays add an upward bias
   so the header rule and title stay connected. Short screens keep natural
   height rather than squeezing the content. */
@media (min-height: 620px) {
  .site-hero { min-height: calc(100vh - var(--header-h)); min-height: calc(100svh - var(--header-h)); }
  .hero-inner {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    justify-content: center;
  }
  .hero-band { flex: 0 0 auto; }
}
@media (min-width: 801px) and (min-height: 620px) {
  .hero-copy { transform: translateY(clamp(-56px, -6vh, -24px)); }
}

/* Geography cue + the hero's one small gold accent above the headline. */
.hero-inner .eyebrow {
  margin-bottom: 18px;
  color: var(--ice);
  font-size: clamp(11px, 1vw, 13px);
  font-weight: 500;
  letter-spacing: .11em;
}
.hero-inner .eyebrow::before {
  flex: none;
  width: clamp(24px, 3vw, 40px);
  height: 2px;
  background: var(--gold);
  content: "";
}

/* A26: the strapline has left the hero for the footer sign-off, so the H1 is
   the whole headline — one voice, set at full display size. */
.hero-headline { margin-bottom: clamp(18px, 2vw, 26px); }
.hero-headline h1 {
  display: block;
  margin: 0;
  color: var(--on-navy);
  font-size: clamp(40px, 6.5vw, 86px);
  font-weight: 800;
  line-height: .98;
  letter-spacing: -.05em;
}
@media (min-width: 1001px) {
  .hero-headline h1 span { display: block; }
}

/* Greg's gloss, set as his own words. */
.hero-gloss {
  max-width: 58ch;
  margin: 0;
  padding-left: 20px;
  border-left: 2px solid var(--gold);
  color: var(--ice);
  font-size: clamp(16px, 1.35vw, 18px);
  line-height: 1.62;
}

/* A23: the two hero actions — one gold fill (the only one on screen, A21's
   rule kept) and one underlined text route for candidates — with the offer
   microcopy beneath them in the strip's mono voice. */
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 22px;
  align-items: center;
  margin-top: clamp(26px, 3vw, 36px);
}
.hero-actions .button {
  min-height: 50px;
  min-width: 200px;
  padding: 0 20px;
  justify-content: space-between;
  font-size: 13px;
}
.hero-role-link {
  display: inline-flex;
  gap: 10px;
  min-height: 50px;
  padding: 0 2px;
  align-items: center;
  border-bottom: 1px solid var(--line-on-navy-strong);
  color: var(--ice);
  font-size: 13px;
  font-weight: 800;
  transition: border-color .2s ease, color .2s ease;
}
.hero-role-link span { color: var(--gold); font-size: 16px; line-height: 1; transition: transform .2s ease; }
.hero-role-link:hover { border-color: var(--gold); color: #fff; }
.hero-role-link:hover span { transform: translateX(3px); }
.hero-microcopy {
  margin: 18px 0 0;
  color: var(--ice-soft);
  font: 500 var(--label) / 1.6 var(--mono);
  letter-spacing: .09em;
  text-transform: uppercase;
}

/* One band, drawn twice. The sand copy sits under the navy panel and carries
   the words; the navy copy sits over it and is clipped by the same seam. While
   the edge is inside the band the cells read half navy and half sand, which is
   the hand-off stated in one component. */
.hero-band--sand { position: relative; z-index: 0; }
.hero-band--navy {
  position: absolute;
  z-index: 2;
  right: 0;
  bottom: 0;
  left: 0;
}

/* At rest the seam is simply the rule that closes the hero. Its lower edge is
   the seam, so the rule always reads as the last 3px of navy — which is what
   makes it legible as the same device the ledger opens with. */
.hero-seam {
  position: absolute;
  z-index: 4;
  right: 0;
  bottom: 0;
  left: 0;
  height: 3px;
  background: var(--gold);
}

/* Definition band at the hero's foot: the slot the sector fills with statistics,
   filled with facts of definition instead (no numbers — BRAND §10 row 1). It
   replaces the retired what-we-do paragraph as the scope statement (A15). */
.hero-foot {
  position: relative;
  z-index: 1;
  margin-top: 0;
  padding-block: 20px 24px;
  border-top: 1px solid var(--line-on-navy-strong);
  background: rgba(0, 29, 51, .28);
  box-shadow: 0 0 0 100vmax rgba(0, 29, 51, .28);
  clip-path: inset(0 -100vmax);
}
/* Three compact definition cells keep the scope facts attached to the hero
   message instead of leaving them as loose labels at the bottom of a viewport. */
.hero-foot dl {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  margin: 0;
}
.hero-foot dl > div { display: grid; gap: 7px; align-content: start; }
.hero-foot dl > div + div {
  padding-left: clamp(22px, 3vw, 42px);
  border-left: 1px solid var(--line-on-navy);
}
.hero-foot dt {
  margin: 0;
  color: var(--ice-faint);
  font: 500 var(--label) var(--mono);
  letter-spacing: .07em;
  text-transform: uppercase;
  line-height: 1;
}
.hero-foot dd {
  margin: 0;
  color: var(--on-navy);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -.015em;
  line-height: 1.2;
}

/* Sand dress for the lower copy, stated after the navy one it re-specifies at
   equal weight: the label greys and hairlines section 01 uses, on the tint that
   keeps the band reading as a shelf rather than as loose text dropped on the
   page. */
.hero-band--sand .hero-foot {
  border-top-color: var(--line);
  background: var(--panel-tint);
  box-shadow: 0 0 0 100vmax var(--panel-tint);
}
.hero-band--sand dt { color: var(--muted-strong); }
.hero-band--sand dd { color: var(--ink); }
.hero-band--sand dl > div + div { border-left-color: var(--line); }

/* -- 6. Why commissioning ------------------------------------------------- */

/* No gap to cross. Section 01 hangs off the hero's closing rule instead of
   opening a section's worth of air beneath a hard colour change. */
/* The class, not the id. `.why-section` was a hook that styled nothing while an
   id selector did its job — the only id selector in the file, and the reason
   this one rule sat at a specificity nothing else on the page could answer. It
   still wins over `.section-space`'s padding-block on source order alone. */
.why-section { padding-top: clamp(34px, 3.6vw, 50px); }

.why-layout {
  display: grid;
  grid-template-columns: .78fr 1.22fr;
  gap: clamp(48px, 9vw, 130px);
  align-items: start;
}
/* The heading column used to be sticky. It could only ever hold for about
   100px before its own grid area ran out beneath it, which read as a stall
   rather than a hold — and the rows opposite now arrive one at a time, which is
   the movement that section was asking for. */
.why-intro .eyebrow { color: var(--gold-text); }
/* The eyebrow's gold dash is the section's opening mark now — no second rule
   above the H2 (A23). */
.why-intro h2 {
  max-width: 15ch;
  margin-bottom: 0;
}
/* A23: the heading column carries the section's one paragraph (demo layout);
   the ledger opposite stays scannable on its own. */
.why-intro > p:not(.eyebrow) {
  max-width: 40ch;
  margin: 24px 0 0;
  color: var(--muted);
  font-size: var(--lede);
  line-height: 1.65;
}
.why-copy { padding-top: 6px; }

/* The thesis is a ledger (A22, rows re-copied A23): three ruled rows the eye
   can take in without reading a paragraph. Gold rules open and total the
   account; the row markers are the site's own DM Mono numeral device. */
.ledger {
  margin: 0;
  padding: 0;
  border-top: 3px solid var(--gold);
  list-style: none;
}
.ledger-row {
  display: grid;
  grid-template-columns: 128px minmax(0, 1fr);
  gap: 10px 24px;
  align-items: baseline;
  padding: clamp(20px, 2.2vw, 26px) 0;
  border-bottom: 1px solid var(--line);
}
/* The account closes on a gold rule, as a total line does. */
.ledger-row--close { border-bottom: 3px solid var(--gold); }
.ledger-row__key {
  display: flex;
  gap: 11px;
  align-items: baseline;
  margin: 0;
  font: 500 var(--label) / 1.2 var(--mono);
  letter-spacing: .105em;
  text-transform: uppercase;
  white-space: nowrap;
}
.ledger-row__num { color: var(--gold-text); }
.ledger-row__tag { color: var(--muted-strong); }
.ledger-row__val {
  max-width: 43ch;
  margin: 0;
  color: var(--muted);
  font-size: clamp(15.5px, 1.5vw, 17.5px);
  line-height: 1.6;
  letter-spacing: -.008em;
  text-wrap: balance;
}
.ledger-row__val strong {
  display: block;
  margin-bottom: 8px;
  color: var(--ink);
  font-size: clamp(18px, 1.9vw, 22px);
  font-weight: 800;
  line-height: 1.24;
  letter-spacing: -.035em;
}
.ledger-row__val strong:last-child { margin-bottom: 0; }

/* -- 6b. What's changing (A26) --------------------------------------------- */

/* The reported shift, set on the white panel ground so it separates from the
   thesis above without another navy block before "The standard". The grid
   opens on the ledger's gold rule, so section 01 and 02 read as one argument
   continued, and the cells are divided by hairlines only. */
.shift-section { background: var(--panel); }
/* Equal columns with the dividers drawn in the gaps, not as card padding: a
   padded-cell grid would make the middle column narrower than its flush-edge
   neighbours, and the three labels would then wrap at different widths and lose
   their shared top edge. */
.shift-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: clamp(40px, 4.6vw, 60px);
  margin-top: clamp(38px, 4.2vw, 52px);
  border-top: 3px solid var(--gold);
}
.shift-card {
  position: relative;
  padding: clamp(24px, 2.4vw, 30px) 0 4px;
}
.shift-card + .shift-card::before {
  position: absolute;
  top: 0;
  bottom: 0;
  left: clamp(-30px, -2.3vw, -20px);
  width: 1px;
  background: var(--line);
  content: "";
}
/* Set as one text flow rather than a flex row: as flex items the numeral and
   the label are sized independently and a long label collapses word by word,
   so the three labels take different line counts at the same column width. */
.shift-card__tag {
  display: block;
  margin: 0 0 16px;
  color: var(--muted-strong);
  font: 500 var(--label) / 1.2 var(--mono);
  letter-spacing: .105em;
  text-transform: uppercase;
}
.shift-card__tag span { color: var(--gold-text); }
.shift-card__tag span::after {
  content: "·";
  content: "·" / "";
  margin: 0 11px;
}
/* Label, heading and body share three rows across the whole grid, so a label
   that takes a second line at one width cannot drop its own heading below its
   neighbours'. Without subgrid the cards fall back to ordinary block flow —
   the same layout, minus the guarantee. */
@media (min-width: 801px) {
  @supports (grid-template-rows: subgrid) {
    .shift-grid { grid-template-rows: auto auto auto; }
    .shift-card {
      display: grid;
      grid-row: span 3;
      grid-template-rows: subgrid;
    }
  }
}
.shift-card h3 {
  margin: 0 0 12px;
  color: var(--ink);
  font-size: clamp(19px, 1.75vw, 23px);
  font-weight: 800;
  line-height: 1.18;
  letter-spacing: -.04em;
}
.shift-card p {
  margin: 0;
  color: var(--muted);
  font-size: var(--text);
  line-height: 1.65;
}

/* The section pays itself off: what the shift asks of a search, in the
   strapline's serif-italic voice. */
.shift-close {
  margin-top: clamp(32px, 3.6vw, 46px);
  padding-top: clamp(20px, 2.2vw, 26px);
  border-top: 1px solid var(--line);
}
.shift-close p {
  max-width: 74ch;
  margin: 0;
  color: var(--muted-strong);
  font-size: var(--lede);
  line-height: 1.6;
}
.shift-close em {
  color: var(--gold-text);
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  letter-spacing: -.01em;
}

/* -- 6c. When it's already late (A32) -------------------------------------- */

/* Section 03 changes texture deliberately. 01 argues in ruled rows and 02 in
   three equal cells, so a third grid would read as the same slide again: this
   one argues in prose on the left and lifts the testable part into a single
   white card on the right. It opens on the same 3px gold rule as the ledger and
   the shift grid, which is what keeps it inside the same system. */
.recovery-layout {
  display: grid;
  grid-template-columns: 1.06fr .94fr;
  gap: clamp(40px, 5vw, 74px);
  align-items: stretch;
  margin-top: clamp(38px, 4.2vw, 52px);
  padding-top: clamp(26px, 2.8vw, 36px);
  border-top: 3px solid var(--gold);
}
/* The prose runs shorter than the panel beside it, so the closing assertion is
   pushed to the column's foot on its own rule — the two columns then close on
   roughly the same line instead of leaving a void under the paragraphs. */
.recovery-account { display: flex; flex-direction: column; }
.recovery-account p {
  max-width: 52ch;
  margin: 0 0 18px;
  color: var(--muted);
  font-size: var(--text);
  line-height: 1.7;
}
/* The section's one assertion about VRG, so it leaves the body-copy colour. */
.recovery-account .recovery-account__close {
  margin: clamp(28px, 3vw, 40px) 0 0;
  padding-top: clamp(18px, 2vw, 24px);
  border-top: 1px solid var(--line);
  color: var(--ink);
  font-size: var(--lede);
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: -.025em;
}
@media (min-width: 861px) {
  .recovery-account .recovery-account__close { margin-top: auto; }
}

.recovery-panel {
  padding: clamp(24px, 2.5vw, 32px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
}
.recovery-panel__label {
  margin: 0 0 18px;
  color: var(--muted-strong);
  font: 500 var(--label) / 1.2 var(--mono);
  letter-spacing: .105em;
  text-transform: uppercase;
}
.recovery-checks { margin: 0; }
.recovery-checks > div {
  padding: 15px 0;
  border-top: 1px solid var(--line);
}
.recovery-checks > div:first-of-type { padding-top: 0; border-top: 0; }
.recovery-checks > div:last-of-type { padding-bottom: 0; }
.recovery-checks dt {
  margin-bottom: 5px;
  color: var(--ink);
  font-size: 16.5px;
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -.032em;
}
.recovery-checks dd {
  margin: 0;
  color: var(--muted);
  font-size: var(--text-sm);
  line-height: 1.6;
}
.recovery-panel__close {
  margin: clamp(20px, 2vw, 26px) 0 0;
  padding-top: clamp(16px, 1.8vw, 22px);
  border-top: 1px solid var(--line);
  color: var(--muted-strong);
  font-size: var(--text-sm);
  line-height: 1.65;
}
/* Padded rather than min-height'd: a 44px flex box would float the rule well
   below the words. This way the tap target and the underline are the same box. */
.recovery-panel__cta {
  display: inline-flex;
  gap: 9px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--line-strong);
  color: var(--navy);
  font-size: 12px;
  font-weight: 800;
  transition: border-color .2s ease;
}
.recovery-panel__cta:hover { border-color: var(--gold); }
.recovery-panel__cta span { font-size: 16px; }

/* -- 7. The standard — three rules, costs included (A24) ------------------- */

.standards-section {
  color: var(--ice);
  background: linear-gradient(180deg, var(--navy) 0%, var(--navy-grad-deep) 100%);
}
.standards-section .section-heading .eyebrow { color: var(--gold); }
.standards-section .section-heading h2 { color: var(--on-navy); }
.standards-section h2 em,
.creed-band p em { color: var(--gold); }
.standards-section .section-heading > p { color: var(--ice-soft); }

/* Three hairline-ruled cells, nothing folded (supersedes A17's disclosures):
   number top, title on air, body, and the cost line held to the cell's foot
   in the strapline's serif-italic voice — still not fine print (BRAND.md §2). */
.standards-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 44px;
  border-top: 1px solid var(--line-on-navy);
  border-left: 1px solid var(--line-on-navy);
}
.standard-card {
  display: flex;
  min-height: 320px;
  flex-direction: column;
  padding: 26px 28px;
  border-right: 1px solid var(--line-on-navy);
  border-bottom: 1px solid var(--line-on-navy);
  transition: background-color .2s ease;
}
.standard-card:hover { background: rgba(215, 229, 243, .035); }
.standard-card__number {
  color: var(--gold);
  font: 500 var(--label-sm) var(--mono);
  letter-spacing: .12em;
}
.standard-card h3 {
  margin: clamp(30px, 3.6vw, 52px) 0 12px;
  color: var(--on-navy);
  font-size: clamp(21px, 1.85vw, 25px);
}
.standard-card > p:not(.standard-card__cost) {
  margin: 0 0 22px;
  color: var(--ice-soft);
  font-size: var(--text-sm);
  line-height: 1.65;
}
.standard-card__cost {
  margin: auto 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--line-on-navy);
  color: var(--ice);
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-size: 15px;
  line-height: 1.6;
}

/* -- 8. Inside the search — six visible stages ---------------------------- */

.process-section {
  color: var(--ink);
  padding-bottom: clamp(52px, 6vw, 80px);
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}
/* Each stage is a native <details> (A17): number, name and lede stay scannable
   in a slim row; the full We check / You receive content opens on demand. */
.process-list {
  display: grid;
  padding: 0;
  margin: clamp(28px, 3.4vw, 44px) 0 0;
  list-style: none;
}
.process-stage { border-top: 1px solid var(--line); }
.process-stage:last-child { border-bottom: 1px solid var(--line); }

.process-fold summary {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr) auto;
  gap: clamp(22px, 3.4vw, 52px);
  align-items: baseline;
  padding: clamp(18px, 2.2vw, 24px) 0;
  cursor: pointer;
  list-style: none;
}
.process-fold summary::-webkit-details-marker { display: none; }
.process-fold summary h3 {
  display: flex;
  gap: 12px;
  align-items: baseline;
  margin: 0;
  font-size: clamp(19px, 1.8vw, 23px);
  font-weight: 800;
  letter-spacing: -.045em;
}
.process-fold summary h3 span {
  color: var(--gold-text);
  font: 500 var(--label) var(--mono);
  letter-spacing: .075em;
}
.process-stage__lede {
  color: var(--ink);
  font-size: clamp(16px, 1.6vw, 19px);
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: 1.35;
}
.process-fold summary::after {
  content: "+";
  content: "+" / "";
  align-self: center;
  color: var(--gold-text);
  font: 400 19px/1 var(--mono);
}
.process-fold[open] summary::after {
  content: "−";
  content: "−" / "";
}

/* Open state: body aligns under the lede column. */
.process-stage__body {
  margin: 0 0 clamp(26px, 3vw, 36px) calc(168px + clamp(22px, 3.4vw, 52px));
}
.process-stage__body > p {
  max-width: 58ch;
  margin: 0;
  color: var(--muted);
  font-size: var(--text);
  line-height: 1.65;
}
.process-stage__detail {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(240px, .85fr);
  gap: 14px;
  margin-top: 20px;
  align-items: stretch;
}
.process-checks h4 {
  margin: 0 0 10px;
  color: var(--gold-text);
  font: 500 var(--label) var(--mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.process-checks ul {
  display: grid;
  gap: 7px;
  padding: 0;
  margin: 0;
  list-style: none;
  color: var(--muted-strong);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.process-checks li { position: relative; padding-left: 22px; }
.process-checks li::before {
  position: absolute;
  left: 0;
  content: "✓";
  content: "✓" / "";
  color: var(--gold-text);
}
.process-output {
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-top: 3px solid var(--gold);
  border-radius: var(--radius);
  background: var(--panel-tint);
}
.process-output span {
  display: block;
  margin-bottom: 9px;
  color: var(--gold-text);
  font: 500 var(--label) var(--mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.process-output strong {
  color: var(--ink);
  font-size: 17px;
  line-height: 1.4;
  letter-spacing: -.03em;
}

/* -- 9. Creed slot -------------------------------------------------------- */

/* Reserved treatment for the three-beat line (BRAND.md §4). The band is not
   rendered anywhere until Greg approves the wording; the page reads complete
   without it. When approved, replace the `creed-slot` comment in index.html with:
   <aside class="creed-band" aria-label="Valor creed"><div class="shell"><p>[approved line]</p></div></aside> */
.creed-band {
  padding-block: clamp(54px, 6vw, 88px);
  color: var(--on-navy);
  text-align: center;
  background: var(--navy);
}
.creed-band p {
  max-width: 26ch;
  margin: 0 auto;
  padding-block: 26px;
  border-top: 2px solid var(--gold);
  border-bottom: 2px solid var(--gold);
  font-size: clamp(24px, 3.4vw, 40px);
  font-weight: 800;
  letter-spacing: -.05em;
  line-height: 1.15;
}

/* -- 10. Who you're dealing with + two paths ------------------------------ */

.who-layout {
  display: grid;
  grid-template-columns: minmax(240px, .58fr) minmax(0, 1.42fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: start;
}

.who-portrait { margin: 6px 0 0; }
/* Light panel behind a cut-out portrait — the suit is close to brand navy, so a
   navy ground would swallow the figure. Gold hairline at the foot ties it in. */
.who-portrait__frame {
  display: grid;
  aspect-ratio: 4 / 5;
  place-items: center;
  overflow: hidden;
  border: 1px solid var(--line);
  border-bottom: 2px solid var(--gold);
  border-radius: var(--radius);
  background: linear-gradient(168deg, var(--panel-tint) 0%, var(--panel-tint) 48%, #ece0d0 100%);
}
.who-portrait__frame > img { display: block; }
.who-portrait__frame .who-portrait__photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 8%;  /* keep the head, crop reads as a waist crop */
}
.who-portrait figcaption {
  margin-top: 12px;
  color: var(--muted-strong);
  font: 500 var(--label) / 1.5 var(--mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
/* Personal profile sits under the caption, not in the body copy — an identity
   detail, not a call to action. */
.who-portrait figcaption a {
  display: flex;
  width: fit-content;
  min-height: 44px;
  align-items: center;
  color: var(--gold-text);
  text-decoration: underline;
  text-decoration-color: rgba(125, 96, 41, .45);
  text-underline-offset: 4px;
  transition: text-decoration-color .2s ease;
}
.who-portrait figcaption a:hover { text-decoration-color: var(--gold-text); }

.who-copy .eyebrow { color: var(--gold-text); }
.who-copy h2 { max-width: 15ch; }
/* The eyebrow is also a <p> here — keep it out of the body-copy cascade. */
.who-copy > p:not(.eyebrow) {
  max-width: 58ch;
  margin: 0 0 18px;
  font-size: var(--text);
  line-height: 1.72;
}
.who-copy > p:nth-of-type(2) { font-size: clamp(17px, 1.8vw, 20px); letter-spacing: -.012em; }
.who-copy > p:last-of-type { margin-bottom: 0; }

/* -- 11. The two routes — full-bleed split band (A25) ---------------------- */

/* The audience fork, moved out of the hero and set as the demo's split band:
   client door on brand navy, candidate door on gold, each padded so its copy
   opens on the shell's type axis. The section ids stay (#candidates), so
   every nav link and the hero's candidate route still land here.

   The white chooser strip that used to open the band is gone: it asked "are you
   hiring or looking for a role?" and then answered it with the same two links
   the cards below already are, so the fork was put to the reader twice. The
   `.route-card__label` mono line is what states each door's audience now. */
/* `clip` rather than `hidden` for the same reason as <body>: the two route
   cards animate on a `view()` timeline and must measure against the viewport,
   not against a scrollport this band would otherwise open. */
.routes-band {
  overflow: clip;
  /* Two different gutters, and the band is the only place on the page that
     needs both: the outer one is the shell's own margin, so the client door
     opens on the page's left axis and the candidate door closes on its right;
     the inner one is the seam where the two doors meet, and belongs to the
     band alone. */
  --band-gutter: calc((100vw - var(--shell)) / 2);
  --band-seam: clamp(30px, 3.4vw, 64px);
}
.routes-grid { display: grid; grid-template-columns: 1fr 1fr; }
.route-card {
  display: flex;
  min-height: 420px;
  flex-direction: column;
  align-items: flex-start;
  padding-block: clamp(64px, 7.5vw, 110px);
}
/* A54: the outer gutter is charged to the outer edge only. Set on both edges of
   both doors — as it was from A25 — it was paid twice out of a column that is
   half the viewport, so the measure narrowed as the window widened: 554px of
   copy at 1252px, 220px at 1920px, and nothing at all past ~2200px, where two
   gutters are wider than the door that has to hold them. That is why the copy
   read as a squeezed ribbon on a wide screen and the CTA label wrapped mid-
   phrase. Each door now pays the gutter once, on the side that actually meets
   the page's margin, and the seam on the side that meets the other door. */
.route-card--client {
  padding-inline: var(--band-gutter) var(--band-seam);
  color: var(--on-navy);
  background: linear-gradient(180deg, var(--navy) 0%, var(--navy-grad-deep) 100%);
}
.route-card--candidate {
  padding-inline: var(--band-seam) var(--band-gutter);
  color: var(--navy-deep);
  background: var(--gold);
}
/* The doors speak the section eyebrow's device — dash + mono label — so the
   band reads at section level, not sub-label level (judge graft, A25). */
.route-card__label {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 0 0 clamp(30px, 4.4vw, 54px);
  font: 500 var(--label) / 1.4 var(--mono);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.route-card__label::before { flex: none; width: 34px; height: 2px; content: ""; }
.route-card--client .route-card__label { color: var(--gold); }
.route-card--client .route-card__label::before { background: var(--gold); }
.route-card--candidate .route-card__label { color: rgba(0, 29, 51, .74); }
.route-card--candidate .route-card__label::before { background: rgba(0, 29, 51, .74); }
/* A26: the door headings run to the card's own column rather than a 13ch
   measure, so the two doors carry similar heading depth and the CTA block below
   them is not left stranded under a short one. */
.route-card h2 {
  max-width: 17ch;
  margin: 0 0 14px;
  font-size: clamp(34px, 3.9vw, 56px);
  letter-spacing: -.055em;
  line-height: 1;
}
.route-card--client h2 { color: var(--on-navy); }
.route-card--candidate h2 { color: var(--navy-deep); }
.route-card > p:not(.route-card__label) {
  max-width: 46ch;
  margin: 0 0 32px;
  font-size: var(--text);
  line-height: 1.65;
}
.route-card--client > p:not(.route-card__label) { color: var(--ice); }
.route-card--candidate > p:not(.route-card__label) { color: rgba(0, 29, 51, .82); }
/* A26: both doors close on the same block — button, then one mono line — held
   to the foot of the card, so the two calls to action sit on one line across
   the split however long the copy above them runs. */
.route-card__cta {
  display: flex;
  margin-top: auto;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.route-card--candidate .button--navy { background: var(--navy-deep); }
.route-card--candidate .button--navy:hover { background: var(--navy); }
/* The candidate CTA leaves the page and says so (mailto transparency); the
   client note carries the same offer terms as the hero. */
.route-card__note {
  margin: 0;
  font: 400 12px / 1.5 var(--mono);
  letter-spacing: .01em;
}
.route-card--client .route-card__note { color: var(--ice-faint); }
.route-card--candidate .route-card__note { color: rgba(0, 29, 51, .68); }

/* -- 11b. The enquiry form ------------------------------------------------- */

/* The client enquiry form is the only form on the site — the candidate CV form
   was retired in A25, and its confirmation page was parked in A52. Until A53
   these rules were split across a generic "forms" layer here and a contact
   layer in §12, and the split had stopped paying: six declarations were set in
   one and immediately overridden by the other (the heading's border colour, the
   h3's whole font, the <b> colour, the label colour, the field background, the
   footer border). One block now, carrying the value that actually applied. If a
   second form returns, lift the shared part back out then — because two forms
   need it, not in anticipation of one. */

.client-form {
  padding: 29px;
  color: var(--ink);
  border: 1px solid var(--line);
  border-top: 3px solid var(--gold);
  background: var(--panel);
  box-shadow: 0 24px 60px rgba(10, 43, 57, .08);
}

.form-heading {
  display: flex;
  gap: 12px;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
  color: var(--muted-strong);
  font: 500 10px/1.4 var(--mono);
  letter-spacing: .05em;
  text-transform: uppercase;
}
.form-heading h3 {
  margin: 0;
  color: var(--ink);
  font: 800 clamp(20px, 2.2vw, 27px) / 1.08 var(--display);
  letter-spacing: -.045em;
  text-transform: none;
}
/* "20 minutes" is a duration, not a sentence: below 400px the heading beside it
   takes two lines and the flex row squeezed this to "20 / MINUTES", which reads
   as two labels. It is 64px wide held on one line, and the narrowest card it has
   to sit in leaves ~248px. */
.form-heading b { color: var(--gold-text); font-weight: 500; white-space: nowrap; }

.client-form__intro { margin: 13px 0 2px; color: var(--muted); font-size: 13px; line-height: 1.5; }

/* The response promise is part of the offer, not fine print. */
.form-promise {
  margin: 15px 0 0;
  padding: 13px 16px;
  border-left: 3px solid var(--gold);
  background: var(--panel-tint);
  color: var(--ink);
  font-size: var(--text);
  font-weight: 600;
  line-height: 1.55;
}
.form-promise b { font-weight: 800; white-space: nowrap; }

.honeypot { display: none; }
.form-row { display: grid; gap: 13px; }
.form-row--split { grid-template-columns: 1fr 1fr; }

.client-form label { display: grid; gap: 7px; color: var(--muted-strong); font-size: 12px; font-weight: 800; }
.client-form .form-row,
.client-form > label { margin-top: 15px; }

.field-hint { color: var(--muted); font-size: 12px; font-weight: 500; letter-spacing: .01em; }

.client-form input,
.client-form textarea {
  width: 100%;
  min-height: 46px;
  padding: 0 10px;
  border: 1px solid var(--field-line);
  border-radius: 3px;
  color: var(--ink);
  background: var(--panel-tint);
  /* 16px also stops iOS Safari zooming the page on field focus, at any width. */
  font-size: 16px;
}
.client-form textarea { min-height: 118px; padding-block: 10px; resize: vertical; }
.client-form input:focus,
.client-form textarea:focus { border-color: var(--gold-text); }

.form-error:empty { margin: 0; padding: 0; border: 0; }
.form-error {
  margin: 16px 0 0;
  padding: 12px 14px;
  border-left: 3px solid #b4472f;
  background: rgba(180, 71, 47, .09);
  color: #7d2f1d;
  font-size: 13px;
  line-height: 1.5;
}
.form-error a { text-decoration: underline; }

.client-form__footer {
  display: flex;
  gap: 15px;
  justify-content: space-between;
  align-items: center;
  margin-top: 19px;
  padding-top: 17px;
  border-top: 1px solid var(--line);
}
.client-form__footer p { max-width: 40ch; margin: 0; color: var(--muted); font-size: 13px; line-height: 1.5; }
.client-form__footer a { text-decoration: underline; }

/* -- 12. Contact ---------------------------------------------------------- */

.contact-layout { display: grid; grid-template-columns: 1.42fr .58fr; gap: 30px; margin-top: 52px; align-items: start; }

/* Direct routes carry equal weight with the form — nobody is pushed through it. */
.contact-aside {
  padding: 26px;
  border: 1px solid var(--line);
  border-top: 3px solid var(--gold);
  border-radius: var(--radius);
  background: var(--panel);
}
.contact-aside h3 { margin: 0 0 10px; font-size: 24px; }
.contact-aside__note { margin: 0 0 20px; color: var(--muted); font-size: var(--text-sm); line-height: 1.6; }
.contact-details { display: grid; gap: 16px; margin: 0; }
.contact-details div { padding-top: 13px; border-top: 1px solid var(--line); }
.contact-details dt { margin-bottom: 5px; color: var(--gold-text); font: 500 10px var(--mono); letter-spacing: var(--track); text-transform: uppercase; }
.contact-details dd { margin: 0; color: var(--ink); font-size: var(--text-sm); line-height: 1.55; }
.contact-details a {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  text-decoration: underline;
  text-decoration-color: rgba(16, 45, 61, .35);
  text-underline-offset: 4px;
  overflow-wrap: anywhere;
  transition: text-decoration-color .2s ease;
}
.contact-details a:hover { text-decoration-color: var(--gold-text); }
.contact-details--primary dd { font-size: 17px; font-weight: 800; letter-spacing: -.02em; }
.contact-details--primary a { color: var(--navy); }

/* A25: the aside answers "what happens next" (three steps, no new promises)
   and carries the candidate route now that the CV form is retired — email a
   short note, with what to include. */
.contact-aside__next { margin: 0 0 16px; padding-top: 13px; border-top: 1px solid var(--line); }
.aside-label {
  display: block;
  margin-bottom: 10px;
  color: var(--gold-text);
  font: 500 10px var(--mono);
  letter-spacing: var(--track);
  text-transform: uppercase;
}
.aside-steps { display: grid; gap: 9px; margin: 0; padding: 0; list-style: none; }
.aside-steps li {
  position: relative;
  padding-left: 24px;
  color: var(--ink);
  font-size: var(--text-sm);
  line-height: 1.55;
}
.aside-steps li::before {
  position: absolute;
  left: 0;
  content: "→";
  content: "→" / "";
  color: var(--gold-text);
  font: 500 13px/1.6 var(--mono);
}
.contact-aside__candidate {
  margin: 20px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.6;
}
.contact-aside__candidate strong { color: var(--ink); }
/* The privacy notice inside this paragraph computed to the same colour as the
   copy around it with no underline, so nothing but position marked it as a link.
   The form's own footer already states it this way. */
.contact-aside__candidate a {
  color: var(--gold-text);
  text-decoration: underline;
  text-decoration-color: rgba(125, 96, 41, .45);
  text-underline-offset: 3px;
  transition: text-decoration-color .2s ease;
}
.contact-aside__candidate a:hover { text-decoration-color: var(--gold-text); }
.contact-aside__verify { margin: 12px 0 0; color: var(--muted); font-size: 12px; line-height: 1.5; }

/* -- 13. Footer ----------------------------------------------------------- */

.site-footer { color: var(--ice-soft); background: linear-gradient(180deg, var(--navy) 0%, var(--navy-grad-deep) 100%); }
/* The index column's track is .68fr, not the .58fr it was before it carried
   numbers. A number and its gap cost each row ~22px, and at .58fr the explore
   track resolves to 189px between 961px and 1039px — two pixels short of "06
   Who you're dealing with", which wrapped to a second line in that ~80px
   window and nowhere else. Widening the track costs nothing above 1180px,
   where .site-footer__nav's own 220px max-width is what governs. */
.site-footer__main {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .68fr) minmax(0, .76fr);
  gap: clamp(32px, 3.8vw, 56px);
  padding-block: 46px 40px;
  align-items: stretch;
  border-top: 1px solid var(--line-on-navy);
}
.site-footer__brand,
.site-footer__explore,
.site-footer__action { min-width: 0; }
/* Each column opens on the same optical line, so the lockup reads as a
   heading beside the two labels rather than floating above them. */
.site-footer__brand { display: flex; flex-direction: column; padding-top: 2px; }
.site-footer .brand-lockup { width: 150px; min-width: 150px; }
.site-footer__brand p {
  max-width: 52ch;
  margin: 15px 0 0;
  color: var(--ice-faint);
  font: var(--label-sm) var(--mono);
  letter-spacing: .04em;
  text-transform: uppercase;
}
/* A33: the roles line sits directly under the descriptor as its second half —
   the one place on the page that names the three titles in full, for the reader
   who does not know that "Cx" and "commissioning" are the same word. */
.site-footer__brand .site-footer__roles { margin-top: 10px; color: var(--ice-faint); opacity: .78; }

/* A26: the strapline leaves the hero and signs the page off here — the one
   place it is not competing with the service statement for the same glance. */
.site-footer__brand .site-footer__strap {
  max-width: none;
  margin: 20px 0 2px;
  color: var(--gold);
  font: italic 400 clamp(23px, 2.1vw, 29px) / 1.1 Georgia, "Times New Roman", serif;
  letter-spacing: -.01em;
  text-transform: none;
}
.site-footer__direct {
  display: grid;
  gap: 0;
  width: max-content;
  max-width: 100%;
  margin-top: 26px;
  padding-top: 4px;
  border-top: 1px solid var(--line-on-navy);
}
.site-footer__direct a {
  display: flex;
  width: max-content;
  max-width: 100%;
  min-height: 36px;
  align-items: center;
  color: var(--ice);
  font-size: 13px;
  font-weight: 700;
  overflow-wrap: anywhere;
  transition: color .2s ease;
}
.site-footer__direct a:hover { color: #fff; }
.site-footer__label {
  margin: 0 0 16px;
  color: var(--gold);
  font: var(--label-sm) var(--mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.site-footer__explore,
.site-footer__action {
  padding-left: clamp(24px, 2.6vw, 38px);
  border-left: 1px solid var(--line-on-navy);
}
/* A tight index block: the arrow rides beside its label on hover rather than
   stranding at the far edge of the grid track. */
.site-footer__nav {
  display: grid;
  grid-template-columns: 1fr;
  max-width: 220px;
  font-size: 13px;
  font-weight: 700;
}
.site-footer__nav a {
  display: flex;
  min-height: 34px;
  gap: 9px;
  align-items: center;
  color: var(--ice);
  border-bottom: 1px solid rgba(215, 229, 243, .1);
  transition: border-color .2s ease, color .2s ease;
}
.site-footer__nav a:last-child { border-bottom: 0; }
/* The section's own number, in the eyebrow's device, so the column reads as an
   index of the page rather than a pile of links — and so a reader who has
   scrolled past "03" can see what they skipped. Two mono digits at every entry,
   so the labels share one axis without a track being declared for them.

   No opacity on it. These numbers carry the page's ordering, so they are text
   under 1.4.3 rather than decoration, and `aria-hidden` does not exempt them —
   that exemption is for text nobody is meant to read. --gold is 6.1:1 on this
   ground at full strength; at the .72 it was first drafted with, it composites
   to rgb(143,127,85) and measures 3.9:1, which fails at 10px. It would also have
   been the permanent state on any touch device, where the hover that restored it
   never fires. */
.site-footer__nav a > span {
  flex: none;
  color: var(--gold);
  font: 500 10px / 1 var(--mono);
  letter-spacing: .06em;
}
.site-footer__nav a::after {
  color: var(--gold);
  content: "→";
  content: "→" / "";
  font: 12px var(--mono);
  opacity: 0;
  transform: translateX(-5px);
  transition: opacity .2s ease, transform .2s ease;
}
.site-footer__nav a:hover { border-color: var(--gold); color: #fff; }
.site-footer__nav a:hover::after { opacity: 1; transform: none; }
.site-footer__action {
  display: flex;
  min-height: 0;
  flex-direction: column;
  align-items: flex-start;
}
.site-footer__action strong {
  display: block;
  max-width: 15ch;
  color: #fff;
  font-size: 22px;
  line-height: 1.1;
  letter-spacing: -.045em;
}
.site-footer__cta {
  display: inline-flex;
  width: 100%;
  min-height: 46px;
  gap: 18px;
  margin-top: 22px;
  padding: 0 16px;
  align-items: center;
  justify-content: space-between;
  border: 1px solid var(--gold);
  border-radius: var(--radius);
  color: var(--navy-deep);
  background: var(--gold);
  font-size: 12px;
  font-weight: 800;
  transition: border-color .2s ease, background .2s ease, transform .2s ease;
}
.site-footer__cta:hover { border-color: var(--gold-hover); background: var(--gold-hover); transform: translateY(-1px); }
.site-footer__cta span { font-size: 15px; }

/* The candidate door, kept out of the section index because it is not a section
   — it is the other half of the same question the gold CTA above it asks. Set
   quieter than the button and opening on the contact aside's own words. */
.site-footer__candidate {
  max-width: 32ch;
  margin: 18px 0 0;
  font-size: 13px;
  line-height: 1.6;
}
.site-footer__candidate a {
  /* inline-flex so the ≤960px block can give it the same 44px touch box every
     other action in this footer has — it is a route for a whole audience, at
     the foot of the page a phone reader ends on. The underline is drawn with
     text-decoration rather than a border so the box can grow without the rule
     leaving the words. */
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--ice);
  font-weight: 700;
  white-space: nowrap;
  text-decoration: underline;
  text-decoration-color: rgba(215, 229, 243, .4);
  text-underline-offset: 4px;
  transition: color .2s ease, text-decoration-color .2s ease;
}
.site-footer__candidate a:hover { color: #fff; text-decoration-color: var(--gold); }
.site-footer__candidate a span { color: var(--gold); font-size: 14px; }
/* The mailto says so, as the route card's button does — leaving the page without
   warning is the one thing this site does not do to a reader. */
.site-footer__candidate-note {
  display: block;
  color: var(--ice-faint);
  font: 400 11px / 1.5 var(--mono);
  letter-spacing: .01em;
  overflow-wrap: anywhere;
}

.site-footer .site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  justify-content: space-between;
  align-items: baseline;
  min-height: 0;
  padding: 18px 0 28px;
  border-top: 1px solid rgba(215, 229, 243, .13);
  color: var(--ice-faint);
  font-size: 12px;
  line-height: 1.6;
}
.site-footer__legal p { margin: 0; }
.site-footer__legal p:nth-child(2) { white-space: nowrap; }
/* Full-width so the build credit always takes its own line under the notices
   rather than competing with them for the row. */
.site-footer__credit { width: 100%; text-align: right; }
/* One link treatment for the legal bar, so the privacy notice that closes the
   registration line and the build credit that closes the row below it read as
   the same kind of thing. */
.site-footer__legal a {
  color: var(--ice-soft);
  border-bottom: 1px solid rgba(215, 229, 243, .3);
  font-weight: 700;
  transition: color .2s ease, border-color .2s ease;
}
.site-footer__legal a:hover { color: #fff; border-color: var(--gold); }

/* -- 14. Motion ----------------------------------------------------------- */

/* The policy the whole page is held to:
     scroll-linked motion carries the page;
     time-based motion is only for what the reader triggers.
   Anything that happens because the reader scrolled is welded to scroll
   position, so it cannot run off-screen, finish early or lag behind the hand
   moving it. Anything that happens because the reader acted — hover, focus,
   <details>, form states — stays a `transition` and lives with its component.

   Two branches, and never both on the same element. A browser with
   scroll-driven animation runs everything below; a browser without it keeps the
   IntersectionObserver fade, which app.js only starts when the feature is
   absent. `.reveal` is the marker for that fallback branch and nothing else —
   the two lists match, except that the route band, which had no entry before,
   gains one only in the scroll-driven branch.

   A44: both branches used to stop at 621px, on the reasoning that a phone
   screen is one row high and an entry animation is therefore only a delay. That
   is measurable, and it is not what happens: on a 390×844 screen a ledger row's
   `cover 3% → 24%` range settles it while its top edge is still about 610px down
   the screen — three quarters of the way down, long before it is the line being
   read. Nothing on the page is inside the first viewport either, because the
   hero is exactly one screen tall at every height that has a fold. So the floor
   is gone and the phone gets the same page the desktop does, with a shorter
   travel. The hero's own gesture (D3) does not follow it down — see below. */

.motion-ready .reveal { opacity: 0; transform: translateY(var(--arrive-y)); transition: opacity .5s cubic-bezier(.16, 1, .3, 1), transform .5s cubic-bezier(.16, 1, .3, 1); }
.motion-ready .reveal.is-visible { opacity: 1; transform: none; }

/* D1 · The row arrives. The site's own 14px fade-up, moved off the slab and on
   to the row, because a 448px block is not a unit of reading: one fade for a
   whole grid leaves its lower rows already settled by the time they are looked
   at. The stagger is the layout — every row carries its own timeline, so rows
   arrive in order at the speed of the hand scrolling them and there is not one
   delay to tune. */
@keyframes row-arrive {
  from { opacity: 0; transform: translateY(var(--arrive-y)); }
  to   { opacity: 1; transform: none; }
}

/* D2 · The block opens. The 3px gold rule that tells this site a structural
   block starts here draws in from the left, finishing before the first row
   inside it has arrived: the block opens, then fills. It has to be a
   pseudo-element because a border cannot be transformed. */
@keyframes rule-draw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* D3 · The hero hands over. One clock drives all of it, so nothing can drift
   out of register: the panel's clip, the duplicate band's clip, the rule's
   travel and the title's journey all run over the same scroll range.

   The range starts at 12vh rather than 0 so the first flick of the wheel does
   not fire the whole gesture, and ends at 100vh — the scroll at which the
   hero's foot leaves the screen. 26vh of retraction is deliberately less than
   the clearance between the copy and the band: the edge crosses the band, then
   keeps travelling through empty ground, and never reaches anything that has to
   stay readable. */
@keyframes hero-retract {
  from { clip-path: inset(0 0 0 0); }
  to   { clip-path: inset(0 0 26vh 0); }
}
@keyframes hero-seam-lift {
  from { transform: translateY(0); }
  to   { transform: translateY(-26vh); }
}

/* A guard, not a gesture. The copy column's box stops one band-height short of
   the hero's foot, so subtracting 72px — a little less than the band's 81px —
   puts this cut just above the true seam. If a short viewport ever let the edge
   reach the microcopy, the line would leave cleanly instead of turning into
   white text on sand. On every viewport that fits, nothing here ever clips. */
@keyframes hero-guard {
  from { clip-path: inset(-100vmax -100vmax -72px -100vmax); }
  to   { clip-path: inset(-100vmax -100vmax calc(26vh - 72px) -100vmax); }
}

/* Greg's ask, literally: the title moves down with the scroll. The keyframes
   restate the -6vh resting offset because animating this transform replaces
   it. */
@keyframes hero-drift {
  from { transform: translateY(clamp(-56px, -6vh, -24px)); }
  to   { transform: translateY(calc(clamp(-56px, -6vh, -24px) + 6vh)); }
}

/* And shrinks toward the size the rest of the page speaks in: .59 takes the
   hero's clamp(40px, 6.5vw, 86px) to within a point of --h2 at every width from
   801px up. scale(), never font-size, so no line ever rewraps; origin left, so
   the title lands on the same axis as #why-commissioning's heading column. */
@keyframes hero-title {
  from { transform: scale(1); }
  to   { transform: scale(.59); }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* No width floor (A44). Every row on the page arrives the same way at every
       width, which is the point of having one system rather than a desktop one. */
    .why-intro,
    .ledger-row,
    .section-heading,
    .shift-card,
    .shift-close,
    .recovery-account,
    .recovery-panel,
    .standard-card,
    .process-stage,
    .who-portrait,
    .who-copy,
    /* The two doors carry the band's own grounds, so it is what stands on
       them that arrives. Fading the card itself would fade the navy and the
       gold to sand for the length of the entry, and a ground that flickers
       reads as a fault rather than as an arrival. */
    .route-card > * {
      animation: row-arrive linear both;
      /* Declared after the shorthand on purpose — `animation` resets both of
         these, so setting them first would silently drop the timeline. */
      animation-timeline: view();
      /* Settled by the time the row is roughly a fifth of the way up the
         screen, so the arrival always happens where the reader is looking. */
      animation-range: cover 3% cover 24%;
    }

    /* The contact form is deliberately absent from that list. The reader has
       arrived there to type, and fields that move while being aimed at are a
       defect, not a flourish. */

    .ledger,
    .shift-grid,
    .recovery-layout {
      position: relative;
      /* The real border keeps the box's geometry; the pseudo-element below
         draws the visible rule. Both, and the rule would be 6px in Firefox. */
      border-top-color: transparent;
    }
    .ledger::before,
    .shift-grid::before,
    .recovery-layout::before {
      position: absolute;
      top: -3px;
      right: 0;
      left: 0;
      height: 3px;
      content: "";
      background: var(--gold);
      transform-origin: left center;
      animation: rule-draw linear both;
      animation-timeline: view();
      animation-range: cover 2% cover 20%;
    }
  }
}

/* D4 · The stage opens. The other half of the policy, and the only thing on the
   page the reader actually triggers: the six process folds. Opening one used to
   snap the page down by up to 400px with no account of where the content came
   from, which on a phone is most of a screen arriving at once. It is a
   transition, not an animation on a timeline, because it is answering a tap.

   Both features are tested because both are load-bearing: `::details-content`
   is what keeps the closed content in the box at all (without it the UA simply
   does not render it, and there is no height to animate from), and
   `interpolate-size` is what makes `auto` an interpolable height. Scoped to the
   fold rather than :root so nothing else on the page gains keyword
   interpolation. Where either is missing the fold opens instantly, exactly as
   it does today. */
@supports (interpolate-size: allow-keywords) and selector(::details-content) {
  @media (prefers-reduced-motion: no-preference) {
    .process-fold { interpolate-size: allow-keywords; }
    .process-fold::details-content {
      block-size: 0;
      opacity: 0;
      /* Also what stops .process-stage__body's bottom margin collapsing out of
         the pseudo-element and leaving a gap under a closed fold. */
      overflow: clip;
      transition:
        block-size .34s cubic-bezier(.32, .72, 0, 1),
        opacity .22s ease,
        content-visibility .34s;
      transition-behavior: allow-discrete;
    }
    .process-fold[open]::details-content { block-size: auto; opacity: 1; }
  }
}

/* The hero's own clock, tested for the timeline function it actually uses.
   `scroll()` and `view()` ship together, but an engine with only `view()` would
   drop `animation-timeline: scroll(root block)` as invalid, fall back to the
   document timeline at a 0s duration, and land the hero permanently in its
   end state — a navy panel already retracted at rest. Gated where the hero's
   desktop layout starts, and off short viewports, where 26vh of retraction has
   nowhere to go.

   A44 deliberately did not bring this below 801px with the rest of the system.
   The retraction is 26vh, and on a 390×844 screen the hero's copy column clears
   the scope band by only 94px: the guard below would cut 147px up from the foot
   of .hero-inner and take the microcopy line with it. The mobile hero is also one
   screen exactly — the gesture would be over before the reader had finished the
   first flick — and its gold closing rule already performs the hand-off standing
   still. Retuning the retraction for phones would be a second hero, not this one. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    @media (min-width: 801px) and (min-height: 620px) {
      .hero-ground,
      .hero-band--navy { animation: hero-retract linear both; }
      .hero-seam { animation: hero-seam-lift linear both; }
      .hero-inner { animation: hero-guard linear both; }
      .hero-copy { animation: hero-drift linear both; }
      .hero-headline h1 {
        transform-origin: 0 50%;
        animation: hero-title linear both;
      }

      .hero-ground,
      .hero-band--navy,
      .hero-seam,
      .hero-inner,
      .hero-copy,
      .hero-headline h1 {
        /* `scroll(root block)`, not `view()`: the hero is what the root scroll
           is being measured from, and its own `overflow: hidden` would capture
           a view timeline anyway. */
        animation-timeline: scroll(root block);
        animation-range: 12vh 100vh;
      }
    }
  }
}

/* -- 15. Sub-pages --------------------------------------------------------
   (The .policy-* rules left with privacy-policy.html — the notice is a hosted
   document now.) */

.submission-page {
  display: grid;
  min-height: 100vh;
  padding: 24px;
  place-items: center;
  color: var(--on-navy);
  background: linear-gradient(180deg, var(--navy) 0%, var(--navy-grad-deep) 100%);
}
.submission-card {
  width: min(570px, 100%);
  padding: clamp(30px, 5vw, 46px);
  border: 1px solid var(--line-on-navy);
  border-radius: 5px;
  background: rgba(0, 30, 50, .76);
  box-shadow: 0 25px 70px rgba(0, 6, 18, .3);
}
.submission-card > img { display: block; width: 186px; max-width: 100%; height: auto; margin-bottom: clamp(32px, 6vw, 52px); }
.submission-card .eyebrow { margin-bottom: 21px; color: var(--ice-soft); }
.submission-card h1 { max-width: 480px; margin-bottom: 20px; font-size: clamp(38px, 6vw, 58px); }
.submission-card > p:not(.eyebrow) { max-width: 470px; margin-bottom: 0; color: var(--ice); font-size: 16px; line-height: 1.7; }
.submission-card .button { margin-top: 30px; }
.submission-card a:not(.button) { color: var(--gold); text-decoration: underline; }
.submission-card__links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }
.submission-card__links .button { margin-top: 0; }

/* -- 16. Responsive ------------------------------------------------------- */

@media (max-width: 1000px) {
  :root { --shell: min(100vw - 56px, 1180px); }
  .why-layout { gap: 60px; }
  .contact-layout { grid-template-columns: 1fr; }
}

@media (max-width: 960px) {
  /* Single column: the heading and the opening line lead; the portrait follows,
     so "There's nobody to hide behind." arrives before the photograph. */
  .who-layout { display: flex; flex-direction: column; }
  .who-portrait { max-width: 300px; order: 2; margin: 10px 0 0; }

  .site-footer__main { grid-template-columns: 1fr; gap: 0; padding-block: 40px 30px; }
  .site-footer__direct { margin-top: 22px; }
  .site-footer__direct a { min-height: 44px; }
  .site-footer__explore,
  .site-footer__action { margin-top: 27px; padding: 27px 0 0; border-top: 1px solid var(--line-on-navy); border-left: 0; }
  .site-footer__nav { max-width: 430px; }
  .site-footer__nav a { min-height: 44px; }
  .site-footer__action strong { max-width: 22ch; }
  .site-footer__cta { width: min(100%, 360px); margin-top: 22px; }
  /* The candidate route and the legal links join the footer's 44px standard;
     without this the CV link is 19px and the privacy notice 18px, the only
     targets in the file that opt out of it. */
  .site-footer__candidate a { min-height: 44px; }
  .site-footer__legal a { display: inline-block; padding-block: 12px; }
  .site-footer .site-footer__legal { align-items: flex-start; flex-direction: column; padding: 18px 0 30px; }
  .site-footer__legal p:nth-child(2) { white-space: normal; }
  .site-footer__credit { text-align: left; }
}

/* Below the desktop shell the band sticks, so About and Contact stay one tap
   away on a long page. There is nothing to collapse, but the sticky band still
   has to be cleared by anything anchored or sticky beneath it. */
@media (max-width: 1279px) {
  .site-header-band {
    position: sticky;
    top: 0;
    /* Chrome that floats needs an edge. Two of the surfaces this band travels
       over are its own navy — the hero, and the client route card, which opens
       on `var(--navy)` exactly — so without a boundary the bar dissolves into
       them. Over the routes band that is visible as a fault rather than a
       merge: the gold half of the split still gives the header a hard edge, so
       it appears to have an edge across only half its width. This became
       reachable when the white chooser strip stopped standing between the two
       (A49). Above 1280px the band is part of the page rather than over it, and
       stays seamless with the hero, which is the design.

       An inset shadow, not a border: a border would add a pixel to the band,
       and --header-h is what the hero's `100svh - var(--header-h)` fold and
       every anchor offset are measured from. */
    box-shadow: inset 0 -1px 0 var(--line-on-navy);
  }
  [id] { scroll-margin-top: calc(var(--header-h) + 14px); }
}

@media (max-width: 860px) {
  /* The ledger's key column folds above its rows before the layout stacks. */
  .ledger-row { grid-template-columns: minmax(0, 1fr); gap: 9px; }
  .ledger-row__val { max-width: 52ch; }

  /* The recovery panel loses too much of its measure before the prose does, so
     it stacks under the account rather than being squeezed beside it. */
  .recovery-layout { grid-template-columns: 1fr; gap: clamp(30px, 4vw, 40px); }
  .recovery-account p { max-width: none; }
}

@media (max-width: 800px) {
  :root { --shell: min(100vw - 44px, 1180px); --panel-pad: 24px; }

  /* Ease the desktop header geometry down with the tablet shell. */
  .site-header { gap: 16px; }
  .brand-lockup { width: 148px; min-width: 148px; }
  .header-actions { padding: 4px; }
  .header-link { padding-inline: 12px; }
  .header-cta { padding-inline: 12px; }

  .section-heading,
  .why-layout,
  .contact-layout { grid-template-columns: 1fr; }

  .section-heading h2 { max-width: 20ch; }
  .section-heading > p { max-width: none; margin-top: 18px; }

  /* The three shifts stack; the dividers turn with them. */
  .shift-grid { grid-template-columns: 1fr; }
  .shift-card { padding: 24px 0; border-bottom: 1px solid var(--line); }
  .shift-card + .shift-card::before { display: none; }
  .shift-card:last-child { padding-bottom: 4px; border-bottom: 0; }
  .shift-card h3,
  .shift-card p { max-width: 52ch; }

  /* Stacked, the frame stops being a table and its side rails only serve to
     push §04's copy 29px in from the shell, while every other section on the
     page stays flush to it. The rails go and the cell padding with them, so the
     three rules read as ruled rows on the page's one left axis — the same thing
     the shift grid does when it stacks. The top edge and the row rules stay:
     they are what still says "three of one thing, closed at the end". */
  .standards-grid { grid-template-columns: 1fr; border-left: 0; }
  .standard-card { min-height: 0; padding-inline: 0; border-right: 0; }
  .standard-card h3 { margin-top: 20px; }
  .standard-card > p:not(.standard-card__cost) { max-width: 52ch; }
  /* The cost line is the one piece of copy in the cell that carries a rule, and
     with the side rails gone that rule has to run the same width as the row
     separator under it or the block reads ragged — 52ch stopped it two thirds of
     the way across at tablet widths. The line is short enough that the full
     measure costs it nothing. */
  .standard-card__cost { max-width: none; }

  .routes-grid { grid-template-columns: 1fr; }
  .route-card { min-height: 0; }
  /* Stacked, each door is the full width of the page and has no seam to hold,
     so both its edges are the shell's margin again. */
  .route-card--client,
  .route-card--candidate { padding-inline: var(--band-gutter); }

  /* The specification cells become compact ruled rows. */
  .hero-headline h1 { letter-spacing: -.045em; }
  .hero-foot dl { grid-template-columns: 1fr; }
  .hero-foot dl > div {
    grid-template-columns: 104px minmax(0, 1fr);
    gap: 12px;
    padding: 13px 0;
    align-items: baseline;
  }
  .hero-foot dl > div + div { padding-left: 0; border-top: 1px solid var(--line-on-navy); border-left: 0; }
  .hero-foot dl > div:first-child { padding-top: 0; }
  .hero-foot dl > div:last-child { padding-bottom: 0; }

  .why-copy { padding-top: 0; }
  .why-layout { gap: 34px; }

  .standards-grid { margin-top: 36px; }
  .contact-layout { gap: 30px; margin-top: 36px; }

  .process-fold summary { grid-template-columns: minmax(0, 1fr) auto; gap: 6px 14px; }
  .process-fold summary::after { grid-row: 1; grid-column: 2; }
  .process-stage__lede { grid-column: 1 / -1; }
  .process-stage__body { margin-left: 0; }
  .process-stage__detail { grid-template-columns: 1fr; }
}

@media (max-width: 620px) {
  /* 10px, not 14px: the same fraction of a phone's line height that 14px is of a
     desktop's, so the arrival reads as the same gesture rather than a bigger one
     on a smaller screen. */
  :root { --shell: min(100vw - 32px, 1180px); --panel-pad: 22px; --header-h: 76px; --arrive-y: 10px; }

  .site-header { gap: 12px; }
  .brand-lockup { width: 132px; min-width: 132px; }
  .site-footer .brand-lockup { width: 138px; min-width: 138px; }
  .header-actions { transform: translateY(2px); }
  .header-link { padding-inline: 12px; }
  .header-cta { padding-inline: 12px; }

  .eyebrow { align-items: start; }
  .eyebrow::before { margin-top: 6px; }
  .hero-inner .eyebrow::before { margin-top: 8px; }

  .hero-inner { padding: 36px 0 44px; }
  .hero-gloss { padding-left: 16px; }

  /* Stacked actions: the gold door and the candidate route become full-width
     rows sharing one right-hand arrow axis. */
  .hero-actions { align-items: stretch; flex-direction: column; }
  .hero-actions .button { width: 100%; }
  /* Same inline padding as the button, so the stacked rows share one axis. */
  .hero-role-link { width: 100%; justify-content: space-between; padding: 0 20px; }
  .who-portrait { max-width: 260px; }

  .route-card__label { align-items: start; }
  .route-card__label::before { margin-top: 5px; }

  .client-form { padding: 19px; }
  .form-row--split { grid-template-columns: 1fr; }
  .client-form__footer { align-items: stretch; flex-direction: column; }
  .client-form__footer .button { width: 100%; }

  .submission-page { padding: 16px; }
  .submission-card { padding: 28px 22px; }
  .submission-card .button { width: 100%; }
}

@media (max-width: 480px) {
  .hero-foot dd { font-size: 14px; }
  .site-footer__nav { max-width: none; }
  .site-footer__cta { width: 100%; }
}

@media (max-width: 400px) {
  .site-header { gap: 8px; }
  /* Still clears the 120 px logo minimum. */
  .brand-lockup { width: 120px; min-width: 120px; }
  .header-link,
  .header-cta { padding-inline: 9px; }
  .header-link::after,
  .header-cta__arrow { display: none; }
}

/* -- 17. Forced colors ----------------------------------------------------- */

@media (forced-colors: active) {
  /* Filled buttons keep a boundary when their gold/navy fills are replaced. */
  .button,
  .header-cta,
  .site-footer__cta { border: 1px solid ButtonBorder; }
  /* The split band's two grounds collapse to Canvas; a hairline keeps the two
     doors legible as separate routes. */
  .route-card { border: 1px solid CanvasText; }
}

/* -- 18. Reduced motion --------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  .button:hover,
  .header-cta:hover,
  .site-footer__cta:hover { transform: none; }
}

/* -- 19. Touch ------------------------------------------------------------- */

/* A44. Two things a hover-built page gets wrong on a phone.

   First, iOS applies :hover on tap and holds it until something else is tapped,
   so every hover that moves something leaves it displaced and reading as stuck.
   The colour hovers are harmless — they land as tap feedback — and stay. */
@media (hover: none) {
  .button:hover,
  .header-cta:hover,
  .site-footer__cta:hover { transform: none; }
  .hero-role-link:hover span { transform: none; }
  .header-link:hover::after { transform: none; }
  .site-footer__nav a:hover::after { opacity: 0; transform: translateX(-5px); }
}

/* Second, nothing acknowledged a press. One shared, instantaneous state, stated
   after the block above so a genuine press still wins over a stranded hover. */
.button:active,
.site-footer__cta:active { transform: translateY(1px); }
.header-cta:active,
.hero-role-link:active,
.recovery-panel__cta:active,
.contact-details a:active,
.site-footer__nav a:active,
.site-footer__candidate a:active,
.site-footer__direct a:active { opacity: .7; }
.process-fold summary:active { background: rgba(16, 45, 61, .04); }
