/* ============================================================================
   ara-data.com — Fable showcase redesign · styles.css
   Spec: design/fable-redesign/DESIGN-DIRECTION.md §§0–9 + §10 PwC addendum
   Round 7: design/fable-redesign/CASE-STUDY-TREATMENT.md (Parts A + C)
   Canon: team/brand/ara-logo/ARA_design_philosophy.md (brand v1.2 in force)
   Ground arc: dark hero → Paper middle → Navy DK close (§10.2)
   ============================================================================ */

/* ---- Fonts (§4) ------------------------------------------------------------
   DEPLOY: swap font paths to /fonts/... when merged into the live repo —
   same four files ship there. */
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("/fonts/IBMPlexSans-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---- Tokens (§3.1, §4.1, §5, §7.1) ---------------------------------------- */
:root {
  /* palette — canon, no new colors (the hero canvas's far interpolation stop
     #2F3E5C lives in JS only — round-3 value) */
  --navy: #10243F;
  --navy-dk: #0B1A30;
  --ink: #0A1526;
  --orange: #E2641B;
  --orange-hi: #F47B25;
  --orange-ink: #B04708;
  --grey: #8A929E;
  --grey-lt: #C9CED6;
  --pale: #EEF0F3;
  --paper: #F6F4EF;
  --graphite: #54607A;
  --hair-dark: rgba(201, 206, 214, 0.18);
  --hair-light: #C9CED6;

  /* motion (§3.1) */
  --ease-settle: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-draw: cubic-bezier(0.65, 0, 0.35, 1);
  --t-reveal: 560ms;
  --t-draw: 700ms;
  --t-counter: 900ms;
  --t-hover: 140ms;
  --d-stagger: 70ms;
  --reveal-shift: 16px;
  --hover-lift: 2px;

  /* display-XL (§10.1 + §11 F3/R5, gate F-3): ONE continuous expression for
     >720px — width-fluid at 8vw (8.5vw wraps H1 line two near 1200px), and
     height-governed on short viewports by (100vh − nav 104 − strap 72 −
     stack padding 160 − fixed stack content ≈ 360px) / 2.08 line-heights.
     The 360px re-derivation (was ≈304) accounts for the owner-ordered
     3-line A/R/A stack: kicker 41 + H1 margin 32 + sub 133 + annotations
     3×17 + 2×12 + 32 = 107 + CTAs 48. Anna's hard bounds: floor 40px /
     ceiling 104px. No tiers, no jumps. */
  --fs-display-xl: clamp(40px, min(8vw, (100vh - 696px) / 2.08), 104px);
  --fs-display: 76px;
  --fs-h2: 44px;
  --fs-h3: 24px;
  --fs-stat: 96px;
  --fs-body-l: 20px;
  --fs-body: 17px;
  --fs-nav: 14px;
  --fs-label: 12px;
  --fs-micro: 11px;
  /* round 7 (Part C.2): the ONE amendment to the type scale — long-form
     leading, scoped to field-note body copy only. §4.1's 1.6 was set for card
     bodies and short section prose. */
  --lh-longform: 1.7;

  /* grid (§7.1) — nav is 104px, not the spec'd 72px: the lockup at its canon
     minimum of 160px wide stands 101px tall incl. its built-in 1.5×D
     exclusion padding; 104px (13 × 8px) is the smallest bar that holds it. */
  --u: 8px;
  --nav-h: 104px;
  --max-w: 1200px;
  --margin: clamp(24px, 6vw, 96px);
}
@media (max-width: 720px) {
  :root {
    --fs-display-xl: clamp(40px, 10.5vw, 64px);
    --fs-display: clamp(40px, 9vw, 76px);
    --fs-h2: clamp(30px, 6vw, 44px);
    --fs-stat: clamp(64px, 14vw, 96px);
  }
}
/* §11 R5 compression order, remaining step: the annotations→CTAs gap eases
   to its 32px floor on short viewports. (The H1's height governance now
   lives in the base display-XL token — continuous, no tier boundary.) */
@media (min-width: 721px) and (max-height: 860px) {
  .hero-ara { margin-bottom: 32px; } /* the R5 floor */
}

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

/* D1: at anchor stops the band's own 120px padding tucks partially under the
   sticky chrome, leaving a 64px visible gap between chrome bottom and the FIG
   rule. Band padding and normal scroll rhythm untouched. (≤720px override
   below.) 48 → 88 with the second register: the stack is 104 + 40 = 144px at
   the five indexed anchors, and 120 − (144 − 88) = 64px, unchanged.
   #contact sits OUTSIDE the indexed range, so it meets a 104px chrome and
   lands at 104px of visible gap rather than 64. That asymmetry is derived, not
   drift, and it stays: tuning for Contact needs spt = 48, which drops all five
   indexed anchors to 24px. Nothing is hidden in either case — only the band's
   own empty padding tucks under, 56px at the five and 16px at Contact. */
html { scroll-padding-top: 88px; }

body {
  margin: 0;
  background: var(--navy-dk);
  color: var(--paper);
  font: 400 var(--fs-body)/1.6 "IBM Plex Sans", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
ul[role="list"], ol[role="list"] { list-style: none; padding: 0; }
img { max-width: 100%; height: auto; }
a { color: inherit; }

h2 {
  font-size: var(--fs-h2);
  line-height: 1.08;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-wrap: balance;
  margin-bottom: 24px;
}
h3 {
  font-size: var(--fs-h3);
  line-height: 1.25;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

.wrap {
  max-width: calc(var(--max-w) + 2 * var(--margin));
  margin-inline: auto;
  padding-inline: var(--margin);
}

/* the spec-sheet split: left rail 3 cols / content 9 cols (§7.1) */
.row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
  column-gap: 24px;
}

.mono-label {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  line-height: 1.4;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}
.micro {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-micro);
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}
.body-l {
  font-size: var(--fs-body-l);
  line-height: 1.55;
  max-width: 62ch;
  text-wrap: pretty;
}

/* meta segments: text + trailing separator wrap as ONE unit, so line breaks
   only fall between segments and a "·" never orphans at a line start */
.ms { white-space: nowrap; }
/* gate F-2: the kicker triad NEVER breaks internally, at any width — the only
   permitted kicker break is after the em dash */
.kicker-triad { white-space: nowrap; }

/* band grounds */
.band-light { --band-bg: var(--paper); background: var(--band-bg); color: var(--ink); }
.band-dark  { --band-bg: var(--navy-dk); background: var(--band-bg); color: var(--paper); }
.band { padding: 120px 0; }

.band-light .mono-label,
.band-light .micro { color: var(--graphite); }
.band-dark .mono-label,
.band-dark .micro { color: var(--grey); }

/* ---- Accessibility chrome --------------------------------------------------- */
.skip-link {
  position: absolute;
  left: 24px;
  top: -64px;
  z-index: 100;
  padding: 12px 24px;
  background: var(--paper);
  color: var(--ink);
  font: 500 var(--fs-nav)/1.4 "IBM Plex Sans", sans-serif;
  text-decoration: none;
}
.skip-link:focus { top: 24px; }

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

:focus-visible {
  outline: 2px solid var(--orange-hi);
  outline-offset: 2px;
}
/* --orange-hi is 2.48:1 on --paper and fails SC 1.4.11, so every light ground
   the site owns steps the ring down to --orange-ink at 5.09:1. The section
   index is a THIRD light ground: it is a sibling of the bands and it is not
   inside .site-nav, so it matches neither of the first two selectors and would
   silently take the base ring. Same pattern as its colour and its stacking —
   what .site-nav does for itself, this row has to do for itself. */
.band-light :focus-visible,
html.js-on .site-nav.nav-light :focus-visible,
.section-index :focus-visible {
  outline-color: var(--orange-ink);
}

/* ============================================================================
   NAV (§1.7) — Navy DK over the hero; instant ground-swap to Paper at hero
   exit (§10.3 — a hard cut, deliberately no transition).
   ============================================================================ */
.site-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  height: var(--nav-h);
  background: var(--navy-dk);
  border-bottom: 1px solid var(--hair-dark);
}
.nav-inner {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}
.nav-brand { display: block; flex: none; }
.lockup { display: block; width: 160px; height: auto; } /* canon minimum — never smaller */
.lockup-ink { display: none; }

.nav-links {
  display: flex;
  align-items: center;
  gap: 32px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-links a {
  position: relative;
  display: inline-block;
  padding: 4px 0;
  color: var(--paper);
  font-size: var(--fs-nav);
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.4;
  text-decoration: none;
}
/* hover underline draw (§3.2.5) — transform only */
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-hover) ease-out;
}
.nav-links a:hover::after,
.nav-links a:focus-visible::after { transform: scaleX(1); }
/* Contact — the single static nav accent; its underline never moves */
.nav-links a.nav-contact::after {
  background: var(--orange-hi);
  transform: scaleX(1);
  transition: none;
}

/* The current route: not a link, so it inherits none of .nav-links a above.
   Its underline ships DRAWN in currentColor — the site's existing idiom for
   "this state is permanent", the same mechanism .nav-contact uses. Two static
   underlines coexist because they say different things and there is at most
   one of each: orange is signal, currentColor is state. Nothing here spends
   orange, and the distinction is never colour-alone — aria-current carries it
   semantically, the drawn rule carries it visually. */
.nav-links .nav-current {
  position: relative;
  display: inline-block;
  padding: 4px 0;
  color: var(--paper);
  font-size: var(--fs-nav);
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.4;
}
.nav-links .nav-current::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: currentColor;
}

/* light nav state (post-hero) */
html.js-on .site-nav.nav-light { background: var(--paper); border-bottom-color: var(--hair-light); }
html.js-on .site-nav.nav-light .nav-links a { color: var(--ink); }
html.js-on .site-nav.nav-light .nav-links .nav-current { color: var(--ink); }
html.js-on .site-nav.nav-light .lockup-white { display: none; }
html.js-on .site-nav.nav-light .lockup-ink { display: block; }
html.js-on .site-nav.nav-light .nav-links a.nav-contact::after { background: var(--orange); }

/* ============================================================================
   SECTION INDEX (direction §3.8) — the PAGE register: the figure list the
   drawing has implied since launch, collected and hoisted to the top of the
   page. Site chrome sticks from the top of the WINDOW; the page's index sticks
   from where the PAGE begins, at top: var(--nav-h), so the hero keeps its
   104px constant and --fs-display-xl's height governance is untouched.

   EVERY DECLARATION HERE IS ONE THE ROW CARRIES ITSELF, and none of them is
   optional. The row is a SIBLING of the bands, so .band-light .mono-label — a
   descendant selector — never matches it, and base .mono-label declares no
   colour: undeclared, it inherits body { color: var(--paper) } onto the paper
   ground below. 1:1. Invisible. The bar's hairline, its --ink text and its
   z-index are all scoped inside html.js-on .site-nav.nav-light, which this row
   is not inside either. Whatever .site-nav does for itself, this row does for
   itself — colour, stacking, and its focus ring (see :focus-visible above).
   Graded by check 26, because an unasserted declaration is one "add nothing
   unasked" edit away from shipping text nobody can see.
   ============================================================================ */

/* The row's sticky containing block, so the row unsticks where its index ends
   — a figure index that outlives the last figure is indexing nothing. THREE
   CONSTRAINTS, each of which fails SILENTLY: nothing errors, it quietly stops
   being right.
     1. No `overflow` other than visible. hidden / auto / scroll / clip each
        make this the sticky element's scroll container, and the row then
        sticks to the wrapper, i.e. reads as never sticking at all.
     2. No containment or transform context — no transform, filter,
        perspective, backdrop-filter, no will-change naming any of those, and
        no contain: layout | paint | strict. Each establishes a containing
        block or containment scope that changes or breaks position: sticky.
     3. Full-bleed. The bands paint their own full-bleed backgrounds and take
        their horizontal margin from the .wrap INSIDE them, so any inline
        constraint here insets every band background AND narrows the index
        row's own track, moving the +104.00px this design is measured on.
   Constraint 3 is declared rather than left to the initial values so that
   check 25a can grade it: the harness computes the index track as the .wrap
   track, which is true only while this stays full-bleed. This element also
   carries no class participating in the mono-label colour cascade — it
   contains #act-2, a band-dark, and .band-dark .mono-label at (0,2,0) would
   overrule the row's own colour into 2.86:1 grey-on-paper: a WCAG failure that
   looks deliberate rather than broken, which is why the link selector below is
   (0,2,1). */
.index-scope {
  max-width: none;
  margin-inline: 0;
  padding-inline: 0;
}

.section-index {
  position: sticky;
  top: var(--nav-h);
  /* under the bar's 10, over band content. position: sticky makes this a
     positioned element at z-index auto, painting in tree order — and every
     band inside the wrapper comes LATER in tree order, so a .card lifting on
     hover (a transform, i.e. a stacking context) paints over the row. */
  z-index: 9;
  /* opaque: no alpha, no backdrop-filter. A transparent sticky row has page
     content scrolling through its type, and would run 2.77:1 over the dark
     bands. Opacity is what holds the text at 5.74:1 at every scroll position. */
  background: var(--paper);
  border-bottom: 1px solid var(--hair-light);
}
.section-index ul {
  display: flex;
  align-items: center;
  gap: 32px;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* The 11px padding is on the <a>, deliberately: there it makes a 38.8px target
   and clears SC 2.5.8, where on the row or the <ul> it would be 16.8px and
   fail. THESIS, the narrowest label, is 56.16px wide. */
.section-index a.index-link {
  display: inline-block;
  padding: 11px 0;
  color: var(--graphite);   /* 5.74:1 on paper */
  text-decoration: none;
}
.section-index a.index-link:hover,
.section-index a.index-link:focus-visible {
  color: var(--ink);        /* 16.64:1 — the same step .footer-link takes */
}

/* ============================================================================
   HERO — THE DATUM FRAME (§1, §10.1)
   ============================================================================ */
.hero {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  min-height: clamp(640px, calc(100vh - var(--nav-h)), 960px);
  background: var(--navy-dk);
}

.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: none;
}
html.js-on .hero-canvas { display: block; }

.hero-fallback {
  position: absolute;
  left: 64%;
  top: 46%;
  transform: translate(-50%, -50%);
}
.hero-fallback svg { display: block; height: min(76vh, 860px); width: auto; }
html.js-on .hero-fallback { display: none; }

/* Three-layer scrim (§10.1 + round-3): flat veil, left-weighted plateau,
   bottom-up gradient. These hero-scrim layers are the ONLY gradients
   anywhere on the page (v1.1 hero-only material). */
.hero-scrim { position: absolute; inset: 0; pointer-events: none; }
.hero-scrim::before {
  content: "";
  position: absolute;
  inset: 0;
  /* veil 0.35 (§10.1) + round-3 LEFT-WEIGHTED layer, Anna's geometry: a 0.5
     plateau to 38% viewport width covering the text footprint, fading out by
     56% — complete before the tower's left face. Stacked as background-image
     over the veil color (::before/::after slots are otherwise taken). */
  background-color: rgba(11, 26, 48, 0.35);
  background-image: linear-gradient(
    to right,
    rgba(11, 26, 48, 0.5) 0%,
    rgba(11, 26, 48, 0.5) 38%,
    rgba(11, 26, 48, 0) 56%
  );
}
.hero-scrim::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 55%;
  background: linear-gradient(to top, rgba(11, 26, 48, 0.72), rgba(11, 26, 48, 0));
}

.hero-body {
  position: relative;
  z-index: 2;
  width: 100%;
  flex: 1;
  display: flex;
  align-items: flex-end;
}
.hero-stack {
  max-width: 72%;              /* §10.1 — headline lower-left and WIDE */
  padding: 96px 0 64px;        /* §11 R5: ≥96px dead space below the nav;
                                  CTAs sit 64px above the mission strap */
}
.hero-kicker {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 24px;
}
.hero-h1 {
  font-size: var(--fs-display-xl);
  line-height: 1.04;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--paper);
  margin-bottom: 32px;
}
.hero-sub {
  font-size: var(--fs-body-l);
  line-height: 1.55;
  color: var(--grey-lt);
  max-width: 52ch;
  margin-bottom: 40px;
  text-wrap: pretty;
}

/* A/R/A annotations — THREE stacked lines at every width (owner order,
   2026-07-26 — overrides §10.1's "single row of three"; recorded with Anna).
   Matches the former mobile treatment; leaders stay. */
.hero-ara {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 48px;
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
}
.hero-ara li { display: flex; align-items: center; }
.hero-ara .leader {
  display: inline-block;
  width: 24px;
  height: 1px;
  background: var(--hair-dark);
  margin-right: 12px;
  flex: none;
}

.hero-ctas { display: flex; align-items: center; gap: 32px; }

/* the page's single orange-filled control (§10.1, §8.6) */
.cta-primary {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: 48px;
  padding: 0 32px;
  background: var(--orange-hi);
  color: var(--ink);              /* canon on-orange rule */
  font-size: var(--fs-nav);
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  border-radius: 0;
}
.cta-primary:hover { background: var(--orange); } /* pre-set solid swap — instant, no gradient */

.cta-secondary {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 48px;
  color: var(--paper);
  font-size: var(--fs-nav);
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
}
.cta-secondary::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 8px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-hover) ease-out;
}
.cta-secondary:hover::after,
.cta-secondary:focus-visible::after { transform: scaleX(1); }

.mission-strap {
  position: relative;
  z-index: 2;
  border-top: 1px solid var(--hair-dark);
  border-bottom: 1px solid var(--hair-dark);
}
.mission-strap p {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
  padding: 24px 0;
}

/* ============================================================================
   FIG SECTION HEADS (§7.2, §7.3) — the label sits ON the rule; the rule is an
   SVG line so it can draw; the origin tick is the section's one orange stamp.
   ============================================================================ */
.fig-head {
  position: relative;
  height: 17px;
  margin-bottom: 64px;
}
.fig-rule { position: absolute; inset: 0; }
.rule-svg {
  position: absolute;
  left: 0;
  top: 50%;
  margin-top: -1px;
  width: 100%;
  height: 2px;
  display: block;
}
.rule-svg line {
  stroke-width: 1;
  stroke-dasharray: 1;
  stroke-dashoffset: 0; /* final state in markup+CSS; motion only under html.anim */
}
.band-light .rule-svg line { stroke: var(--hair-light); }
.band-dark .rule-svg line { stroke: var(--hair-dark); }

.fig-tick {
  position: absolute;
  left: 0;
  top: 50%;
  margin-top: -1.5px;
  width: 12px;
  height: 3px;
  transform-origin: left;
  z-index: 1; /* stays above the label's rule-knockout background */
}
.band-light .fig-tick { background: var(--orange); }
.band-dark .fig-tick { background: var(--orange-hi); }

.fig-label {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  background: var(--band-bg); /* knocks the rule out behind the text */
  padding: 0 12px 0 24px;     /* text clears the 12px origin tick */
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.band-light .fig-label { color: var(--graphite); }
.band-dark .fig-label { color: var(--grey); }

/* ============================================================================
   BAND 2 — THESIS (Paper, §10.2)
   ============================================================================ */
.lead-in { max-width: 24ch; }

.card-grid {
  display: grid;
  gap: 24px;
  margin-top: 48px;
}
.three-up { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* D2: stories run 3-up on desktop, single column ≤1024px (no 2+1 tablet row);
   grid margin 24 per Anna's final slack call (closed the anchor-landing fit) */
.stories-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 24px;
}
@media (max-width: 1024px) {
  .stories-grid { grid-template-columns: minmax(0, 1fr); }
  /* Part A.12's `.story-dossier { order: 0 }` override lives WITH the dossier
     block below, not here — see the note there. */
}

.card {
  background: var(--pale);
  border: 1px solid var(--hair-light);
  padding: 32px;
  transition: transform var(--t-hover) ease-out; /* transform only — border-color swaps instantly */
}
.card:hover {
  transform: translateY(calc(-1 * var(--hover-lift)));
  border-color: var(--graphite);
}
.card-body { font-size: var(--fs-body); line-height: 1.6; text-wrap: pretty; }
.t-index { margin-bottom: 16px; }
/* service panels: mono index + rule (§2 Band 4) */
.svc-index {
  padding-bottom: 16px;
  border-bottom: 1px solid var(--hair-light);
  margin-bottom: 16px;
}

.thesis-close { margin-top: 96px; }
.close-line {
  font-size: var(--fs-h2);
  line-height: 1.08;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin-bottom: 8px;
}
.close-support {
  font-size: var(--fs-body-l);
  line-height: 1.55;
  color: var(--graphite);
}

/* ============================================================================
   BAND 3 — TRACK RECORD
   ============================================================================ */
.stat-block { max-width: 260px; }
.stat-row { display: flex; align-items: baseline; gap: 8px; }
.stat-num {
  font-size: var(--fs-stat);
  line-height: 1;
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.stat-unit {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  letter-spacing: 0.18em;
  color: var(--graphite);
}
.stat-rule {
  display: block;
  width: 60px;
  height: 2px;
  background: var(--orange);
  margin: 16px 0 24px;
  transform-origin: left;
}
.stat-caption { font-size: var(--fs-body); line-height: 1.6; color: var(--graphite); text-wrap: pretty; }

.timeline { margin: 64px 0; }
.tl-line { width: 100%; height: 2px; display: block; }
.tl-line line { stroke: var(--hair-light); stroke-width: 1; stroke-dasharray: 1; stroke-dashoffset: 0; }
.tl-items {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  margin-top: 16px;
}
.tl-item {
  position: relative;
  flex: 1;
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-micro);
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--graphite);
  font-variant-numeric: tabular-nums;
}
.tl-tick {
  position: absolute;
  top: -18px;
  left: 0;
  width: 2px;
  height: 10px;
  background: var(--graphite);
}
.tl-item:nth-child(2) { text-align: center; }
.tl-item:nth-child(2) .tl-tick { left: 50%; }
.tl-item:last-child { text-align: right; }
.tl-item:last-child .tl-tick { left: auto; right: 0; }
.tl-today .tl-tick { background: var(--orange); } /* graphical orange — clears 3:1 on Paper */

.proof-lines { margin: 64px 0 48px; }
.proof-lines li {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  gap: 24px;
  padding: 24px 0;
  border-top: 1px solid var(--hair-light);
}
.proof-lines li:last-child { border-bottom: 1px solid var(--hair-light); }
.proof-index { padding-top: 3px; }
.proof-lines p { font-size: var(--fs-body); line-height: 1.6; }

.mission-close {
  font-size: var(--fs-body-l);
  line-height: 1.55;
  max-width: 62ch;
  text-wrap: pretty;
}

/* ============================================================================
   BAND 5 — SUCCESS STORIES (§6 story SVG voice)
   ============================================================================ */
/* D2 card anatomy — internal rhythm meta→16→SVG→16→stat→8→title→8→body→12→
   link; the action link pins to the card bottom so links baseline-align
   across the 3-up row. */
.card.story {
  padding: 24px;
  display: flex;
  flex-direction: column;
}
/* give-back round (this section only): fig-head 40, H2 gap 16 */
#stories .fig-head { margin-bottom: 40px; }
#stories h2 { margin-bottom: 16px; }
.story-svg {
  display: block;
  height: 144px;            /* D2 as amended (give-back round): cap 144,   */
  width: auto;              /* native 320:200 ratio, left-aligned, never   */
  max-width: 100%;          /* stretched or cropped                        */
  aspect-ratio: 320 / 200;
  margin: 0 0 16px;
}
/* §6 common spec: 1.5px strokes, square caps, flat — no depth on light bands */
.s-ink { stroke: var(--ink); stroke-width: 1.5; stroke-linecap: square; fill: none; }
.s-graphite { stroke: var(--graphite); stroke-width: 1.5; stroke-linecap: square; fill: none; }
.s-hair { stroke: var(--hair-light); stroke-width: 1; }
.s-strike { stroke: var(--graphite); stroke-width: 1; }
/* §11 R2: bidder bars = 1px Graphite hairline outline + 45% Graphite fill
   (55% ceiling if render still shy; never solid — lighter than the Ink caps) */
.s-bar { fill: var(--graphite); fill-opacity: 0.45; stroke: var(--graphite); stroke-width: 1; }
.s-text, .s-stamp {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  fill: var(--graphite);
  letter-spacing: 0.05em;
}
.s-text { font-size: 10px; }
.s-stamp { font-size: 14px; }

.story-meta { margin-bottom: 16px; }
.story-stat {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  line-height: 1.4;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--graphite);
  font-variant-numeric: tabular-nums;
  padding-top: 16px;
  border-top: 1px solid var(--hair-light);
  margin-bottom: 8px;
}
.story h3 { margin-bottom: 8px; }
/* No clamp (Anna's final ruling on the flagged conflict): owner copy is never
   truncation-liable. Cards may grow; grid stretch absorbs it and the pinned
   links hold the bottom line. */
.story .card-body { margin-bottom: 12px; }

/* varied action links (§10.4) — Ink, never orange; hover = Graphite underline draw */
.story-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;      /* D2: pinned to the card bottom */
  align-self: flex-start;
  color: var(--ink);
  font-size: var(--fs-nav);
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
}
.story-link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 1px;
  background: var(--graphite);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-hover) ease-out;
}
.story-link:hover::after,
.story-link:focus-visible::after { transform: scaleX(1); }

/* ============================================================================
   ROUND 7 — DISCLOSURE CHROME (shared by FIG. 04 dossiers + FIG. 05 notes)
   CASE-STUDY-TREATMENT A.9 / C.6. The trigger keeps .story-link styling
   exactly; only the button reset is added, because main.js swaps the shipped
   anchor for a <button> to get real disclosure semantics.
   ============================================================================ */
button.story-link {
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  line-height: 1.4;
  cursor: pointer;
  text-align: left;
}
/* the glyph is a CHARACTER swap (↓ → ↑), never a rotation — state, not
   motion (§10.3 precedent). No transform, no transition. */
.link-glyph { flex: none; }

/* the foot is a <div>, not a <p>, so the field note's `p + p { margin-top:
   24px }` rule (0,1,2) can never out-specify this 48px. */
.disclosure-foot {
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--hair-light);
}

/* ============================================================================
   BAND 5 — FIG. 04.1–04.3 · STORY DOSSIERS (CASE-STUDY-TREATMENT Part A)
   A full-width detail callout drawn on the same sheet, below the three-up
   row. Paper ground (NOT Pale — it is the sheet, not a fourth card),
   delimited by hairlines. Zero orange anywhere in here (A.4, A.11).
   ============================================================================ */
.story-dossier {
  grid-column: 1 / -1;   /* A.3: cards hold row 1; the dossier lands full-width */
  order: 1;              /*      in row 2, whichever card it belongs to        */
  /* No margin-top: the grid's own 24px row gap IS the single rhythm unit A.3
     asks for. A margin here would add to it, not match it (Anna, round 7). */
  scroll-margin-top: 72px; /* 48px global scroll-padding + 72 = the y=120
                              landing — Floyd's D-1 precedent, shared with
                              .insight-row and .insight-body-full */
}
/* A.10.7: declared explicitly — any display rule on the element would
   otherwise beat the `hidden` attribute. */
.story-dossier[hidden] { display: none; }

/* A.4 — head: label seated ON a STATIC CSS rule (never draws; §7.2 reserves
   SVG lines for animating rules). No origin tick: a sub-figure does not
   stamp the section's orange scale mark. */
.dossier-head {
  position: relative;
  height: 17px;
  margin-bottom: 40px;
}
.dossier-head::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: var(--hair-light);
}
.dossier-label {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  background: var(--band-bg); /* knocks the rule out behind the text */
  padding-right: 12px;        /* no left pad — there is no tick to clear */
}

/* A.5 — the meta block (rail, 3 cols). A specimen block: no rules inside,
   and deliberately NOT sticky. */
.dossier-meta + .dossier-meta { margin-top: 24px; }
.dossier-meta-label { margin-bottom: 8px; }
.dossier-meta-value {
  font-size: var(--fs-body);
  line-height: 1.6;
  text-wrap: pretty;
}
/* text-transform: none is LOAD-BEARING — uppercasing would destroy
   `iOS`, `SwiftUI`, `M365 Copilot`, `Power BI`. */
.dossier-meta-code {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-label);
  line-height: 1.6;
  letter-spacing: 0.06em;
  text-transform: none;
  font-variant-numeric: tabular-nums;
  color: var(--graphite);
}

/* A.6 — the four sections (content column, 9 cols). Rule ABOVE the label,
   not through it: label-on-the-rule is reserved for FIG heads. */
.dossier-section {
  margin-top: 40px;
  padding-top: 16px;
  border-top: 1px solid var(--hair-light);
}
.dossier-section:first-child { margin-top: 0; }
.dossier-section h4 { margin: 0 0 16px; }
.dossier-section p {
  font-size: var(--fs-body);
  line-height: 1.6;
  max-width: 66ch;
  text-wrap: pretty;
}
.dossier-section p + p { margin-top: 16px; }

/* A.7 — pull quote: regular weight at heading size is the whole trick.
   Spans the full content width (rail + column), which is what makes it read
   as a pull quote with no change of colour or weight. No italic, no orange,
   no oversized quote glyph, no left bar. */
.dossier-quote {
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--hair-light);
}
.dossier-quote blockquote { margin: 0; }
.dossier-quote p {
  font-size: var(--fs-h3);
  line-height: 1.4;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ink);
  max-width: 44ch;
  text-wrap: pretty;
}
.dossier-attrib { margin-top: 16px; } /* no leading dash — a spec annotation */

/* A.8 — capabilities: an index line, not chips/tags/pills. */
.dossier-caps { margin-top: 40px; }
.dossier-caps-label { margin-bottom: 8px; }
.dossier-caps-list {
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: var(--fs-micro);
  line-height: 1.8;
  letter-spacing: 0.08em;
  text-transform: none;
  color: var(--graphite);
  max-width: 72ch;
}

/* A.9 — card active state: the tether between the card and the detail below
   it. Instant, no transition, no lift, no fill. */
.card.story.is-open { border-color: var(--ink); }

/* A.12 — ≤1024px the stories grid is already single-column, so the dossier
   returns to its source position, directly under its own card.
   This block MUST sit AFTER `.story-dossier { order: 1 }` above: both are
   (0,1,0) and a media query contributes no specificity, so source order is
   the only thing deciding the winner. */
@media (max-width: 1024px) {
  .story-dossier { order: 0; }
}

/* ============================================================================
   BAND 6 — INSIGHTS
   ============================================================================ */
.insight-index { margin-top: 48px; }
.insight-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
  column-gap: 24px;
  padding: 32px 0;
  border-top: 1px solid var(--hair-light);
}
/* no border-bottom on the last row — the subscribe block's top rule is the
   list's closing hairline (a doubled rule read as an empty stray row) */
.insight-row h3 { margin-bottom: 8px; } /* title→dek gap (§11 R1) */
.insight-dek { font-size: var(--fs-body); line-height: 1.6; color: var(--graphite); max-width: 60ch; text-wrap: pretty; }
/* rail: two hard-broken mono lines — mono never wraps (§11 R1) */
.insight-meta { padding-top: 5px; white-space: nowrap; }
/* D-1: story-link landings on #note-00X — rows carry only 32px padding, so
   without this the FIELD NOTE meta hides under the 104px sticky nav.
   72px is Anna-ratified: row top lands at 120, meta 16px clear.
   Round 7 (C.8b): KEPT UNCHANGED. Scroll alignment uses the row's TOP edge,
   which does not move when the row grows downward. */
.insight-row { scroll-margin-top: 72px; }

/* below ~1000px the whole row stacks (rail-as-top-rail) before a rail line
   could ever be forced to wrap (§11 R1) */
@media (max-width: 1000px) {
  .insight-row { grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .insight-meta { padding-top: 0; }
}

/* ---- FIG. 05 field notes (CASE-STUDY-TREATMENT Part C) ----------------------
   The note opens IN PLACE, inside its own row's content column, under the
   dek. No FIG. 05.x sub-figure label — it never leaves its index row, and
   the rail is already its masthead (C.0, C.1). Zero orange (C.7.8). */
.insight-link { margin-top: 16px; } /* C.4: trigger sits 16px below the dek */

.insight-body-full {
  margin-top: 24px;
  padding-top: 24px;
  border-top: 1px solid var(--hair-light); /* one rule, marking where the piece starts */
  scroll-margin-top: 72px; /* 48 + 72 = y=120, agreeing with .insight-row */
}
/* C.7.7: declared explicitly, same reason as the dossier. */
.insight-body-full[hidden] { display: none; }

/* C.2 — the reading measure. 1,150–1,600 words is not case-study prose:
   17/1.7 at 62ch with a 24px paragraph gap. */
.insight-body-full p {
  font-size: var(--fs-body);
  line-height: var(--lh-longform);
  max-width: 62ch;
  text-wrap: pretty;
}
.insight-body-full p + p { margin-top: 24px; }
/* the lede — the site's existing lead-paragraph grammar (.body-l, .hero-sub,
   .close-lead). Body resumes at 17/1.7 from paragraph two.
   Selector is deliberately two-class: `.insight-body-full p` above is
   (0,1,1) and would otherwise win on all three properties. */
.insight-body-full .note-lede {
  font-size: var(--fs-body-l);
  line-height: 1.55;
  max-width: 52ch;
}
/* C.3 — section marks: SPACE, not rules. 48px above, 16px below, no
   hairlines. A dossier is a structured record (ruled); a field note is
   continuous argument (space only). Marks are not capped at the 62ch body
   measure — they run to the column width and wrap if they must. */
.insight-body-full h4 {
  margin: 48px 0 16px;
  text-wrap: balance;
}
.subscribe {
  margin-top: 64px;
  padding-top: 48px;
  border-top: 1px solid var(--hair-light);
}
.subscribe-label { display: block; margin-bottom: 16px; }
.subscribe-controls { display: flex; flex-wrap: wrap; gap: 16px; }
.subscribe input[type="email"] {
  flex: 1 1 280px;
  max-width: 420px;
  height: 48px;
  padding: 0 16px;
  border: 1px solid var(--hair-light);
  border-radius: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--fs-body)/1.4 "IBM Plex Sans", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
}
.subscribe input[type="email"]::placeholder { color: var(--graphite); opacity: 1; }
.subscribe button {
  height: 48px;
  padding: 0 32px;
  border: 1px solid var(--ink);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font: 500 var(--fs-nav)/1.4 "IBM Plex Sans", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  letter-spacing: 0.01em;
  cursor: pointer;
}
.subscribe button:hover { background: var(--ink); color: var(--paper); } /* instant swap */
.subscribe .micro { margin-top: 12px; }

/* ============================================================================
   BAND 7 — CLOSE (Navy DK bookend, §10.6)
   ============================================================================ */
.close-statement {
  font-size: var(--fs-display);
  line-height: 1.02;
  letter-spacing: -0.015em;
  margin-bottom: 32px;
}
.close-lead {
  font-size: var(--fs-body-l);
  line-height: 1.55;
  color: var(--grey-lt);
  max-width: 52ch;
  margin-bottom: 64px;
  text-wrap: pretty;
}
.close-email a {
  position: relative;
  font-family: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(22px, 3vw, 32px);
  letter-spacing: 0.02em;
  color: var(--paper);
  text-decoration: none;
}
/* the page's final orange event — hover-only, user-initiated, one element */
.close-email a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 2px;
  background: var(--orange-hi);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-hover) ease-out;
}
.close-email a:hover::after,
.close-email a:focus-visible::after { transform: scaleX(1); }

.site-footer {
  margin-top: 120px;
  padding-top: 48px;
  border-top: 1px solid var(--hair-dark);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 24px 48px;
}
.footer-lockup { width: 176px; height: auto; flex: none; }
.footer-name { color: var(--grey); }
.footer-year { color: var(--grey); margin-left: auto; }
/* Footer route link (Anna, 2026-08-06; rev. gate F-2). Two layers, one
   mechanism: ::before is a static track that makes the link legible as a link
   at rest; ::after is the site's existing underline draw, which now travels
   ALONG the track instead of arriving from nowhere. Both share --rule-y so
   they cannot disagree about where the line sits at any width. On its own page
   it ships as a non-link carrying aria-current — no anchor, so no track. */
.footer-link a {
  position: relative;
  display: inline-block;
  padding-bottom: 2px;
  color: var(--grey);
  text-decoration: none;
  transition: color var(--t-hover) ease-out;
  --rule-y: 0px;
}
.footer-link a::before,
.footer-link a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--rule-y);
  height: 1px;
}
.footer-link a::before { background: var(--grey); }
.footer-link a::after {
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-hover) ease-out;
}
.footer-link a:hover,
.footer-link a:focus-visible { color: var(--paper); }
.footer-link a:hover::after,
.footer-link a:focus-visible::after { transform: scaleX(1); }
.footer-link[aria-current="page"] { color: var(--paper); }

/* ============================================================================
   MOTION LAYER (§3) — every rule below is scoped to html.anim, which main.js
   only grants when it is running AND prefers-reduced-motion is not set.
   Without it the page is its own complete static end-state.
   ============================================================================ */

/* one-shot reveals — non-orange elements only; JS staggers group children.
   Reveals run as keyframe ANIMATIONS (not transitions) so they can never
   collide with the cards' 140ms hover-lift transition on `transform`. */
@keyframes reveal-in {
  from { opacity: 0; transform: translateY(var(--reveal-shift)); }
}
@keyframes fade-in {
  from { opacity: 0; }
}
html.anim [data-reveal]:not(.in),
html.anim [data-reveal-group] > *:not(.in) { opacity: 0; }
html.anim [data-reveal].in,
html.anim [data-reveal-group] > *.in {
  animation: reveal-in var(--t-reveal) var(--ease-settle);
}
/* story cards fade without translate — their SVGs each hold one orange
   element, and orange never takes transform motion outside the hero (§8.4) */
html.anim [data-fade-only] > *.in { animation-name: fade-in; }

/* ROUND 7 — disclosure panels (A.11 / C.7.3). The panel's HEIGHT never
   animates: height/max-height repaint layout and are outside the v1.2
   whitelist. The expand is an INSTANT layout state change with the content
   fading in on top of it — the same hard-cut logic as the nav ground-swap.
   `.in` is added by the toggle on every open, so the fade retriggers each
   time and a panel can never be stranded at opacity 0 by the reveal-group
   rule above. Higher specificity than the [data-fade-only] rule by design. */
html.anim .stories-grid > .story-dossier.in {
  animation: fade-in 240ms var(--ease-settle);
}
html.anim .insight-body-full.in {
  animation: fade-in 240ms var(--ease-settle);
}

/* rule draws (§3.2.2) + origin tick stamp (§3.2.4) */
html.anim .fig-head .rule-svg line {
  transition: stroke-dashoffset var(--t-draw) var(--ease-draw);
}
html.anim .fig-head:not(.in) .rule-svg line { stroke-dashoffset: 1; }
html.anim .fig-tick {
  transition: transform 240ms ease-out var(--t-draw); /* stamps as its rule completes */
}
html.anim .fig-head:not(.in) .fig-tick { transform: scaleX(0); }

/* timeline draw + LABEL reveal, 200ms stagger after the line completes.
   Gate C1(a): only the .tl-text labels animate — the ticks (including the
   orange TODAY tick) appear as an INSTANT state change with the .in flip
   (nav-swap precedent: state, not motion), so no orange ever fades here. */
html.anim .timeline .tl-line line {
  transition: stroke-dashoffset var(--t-draw) var(--ease-draw);
}
html.anim .timeline:not(.in) .tl-line line { stroke-dashoffset: 1; }
html.anim .timeline .tl-text { transition: opacity var(--t-reveal) var(--ease-settle); }
html.anim .timeline .tl-item:nth-child(1) .tl-text { transition-delay: 700ms; }
html.anim .timeline .tl-item:nth-child(2) .tl-text { transition-delay: 900ms; }
html.anim .timeline .tl-item:nth-child(3) .tl-text { transition-delay: 1100ms; }
html.anim .timeline:not(.in) .tl-text { opacity: 0; }
html.anim .timeline:not(.in) .tl-tick { opacity: 0; } /* no transition — instant */

/* the counter's 60px orange underline draws only after the count completes (§3.2.3) */
html.anim .stat-rule { transition: transform 400ms var(--ease-draw); }
html.anim #stat-block:not(.count-done) .stat-rule { transform: scaleX(0); }

/* ---- Reduced motion: belt and braces on top of the missing .anim class ---- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }
}

/* ============================================================================
   RESPONSIVE
   ============================================================================ */
@media (max-width: 960px) {
  .three-up { grid-template-columns: minmax(0, 1fr); }
}

/* The nav-fit gap taper at (721px, 860px) was RETIRED here with the two-register
   split (direction §3.6): it existed only because six section anchors plus the
   160px lockup did not clear a 32px gap below 808.42px, and those anchors now
   live in the section index. It is a costed reserve, not lost knowledge —
   re-opening it is worth 16 × n px of label budget (§7.2), and check 25's gap
   assertions fail loudly if it returns without the sweep being taught about the
   second minimum it reintroduces just above 860px (§3.11, C-11). */

@media (max-width: 720px) {
  .band { padding: 72px 0; }
  .fig-head { margin-bottom: 48px; }

  .row { grid-template-columns: minmax(0, 1fr); }
  .rail { margin-bottom: 32px; }
  .rail:empty { margin-bottom: 0; } /* spacer rails only exist on the desktop grid */

  .card { padding: 24px; }
  html { scroll-padding-top: calc(var(--nav-h) + 16px); } /* D1 mobile */

  /* A.12 / C.6: disclosure triggers take the F2 tap target */
  .story-link { min-height: 44px; }

  /* the second register does not render below 720px, so the existing mobile
     collapse is untouched — out of scope, per Derick */
  .section-index { display: none; }

  /* nav: lockup + Contact only; F2 — the Contact link keeps its Orange HI
     underline and gets a ≥44px tap target (underline re-seated near text) */
  .nav-links li:not(:last-child) { display: none; }
  .nav-links a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 12px 0;
  }
  .nav-links a::after { bottom: 8px; }

  /* hero (§1.8.3): full-width scrim at 0.9 alpha; structure recenters via JS;
     text stack goes full width */
  .hero-scrim::before { background: rgba(11, 26, 48, 0.9); }
  .hero-fallback { left: 50%; top: 38%; }
  .hero-fallback svg { height: min(52vh, 620px); }
  .hero-stack { max-width: 100%; padding: 72px 0 64px; }
  /* (.hero-ara already stacks at all widths — owner order) */
  .hero-ctas { flex-wrap: wrap; gap: 24px; }

  .thesis-close { margin-top: 64px; }
  .timeline { margin: 48px 0; }
  .tl-items { flex-direction: column; gap: 12px; margin-top: 16px; }
  .tl-item, .tl-item:nth-child(2), .tl-item:last-child { text-align: left; }
  .tl-tick,
  .tl-item:nth-child(2) .tl-tick,
  .tl-item:last-child .tl-tick {
    position: static;
    display: inline-block;
    width: 10px;
    height: 2px;
    margin-right: 8px;
    vertical-align: middle;
  }
  .proof-lines { margin: 48px 0 40px; }

  .site-footer { margin-top: 72px; }
  .footer-year { margin-left: 0; }
  /* F2 tap target, the same treatment the nav links take at this width */
  .footer-link a { display: inline-flex; align-items: center; min-height: 44px; }
  /* …which centres the text in a 44px box, so bottom:0 would strand the rule
     ~13.6px below it. Re-seat both layers to 2px under the text: every term
     traces to a declaration above — 44px min-height, 2px padding-bottom, and
     .mono-label's declared 1.4 line-height (declared, not inherited, so this
     holds on the fallback face too). */
  .footer-link a { --rule-y: calc((44px - 2px - 1.4em) / 2); } /* = 12.6px */
}

/* Kicker at small widths (Anna's F1 ratification): drop to the micro register
   and break ONLY after the em dash — `ARA —` / the triad, which never breaks
   internally and never strands a separator at a line end. */
@media (max-width: 400px) {
  .hero-kicker {
    font-size: var(--fs-micro);
    letter-spacing: 0.14em;
  }
  /* (triad nowrap is unconditional — see .kicker-triad, gate F-2) */
}
/* 320px-class edge: the triad line alone eases to 10px rather than wrap */
@media (max-width: 360px) {
  .hero-kicker .kicker-triad { font-size: 10px; }
}
