/* ==========================================================================
   AQTHEVISION — Design System
   One stylesheet. Every page. Dark premium, gold as signal, restraint as luxury.
   Tokens are canonical: .claude/skills/design/data/colors.csv + typography.csv
   Bismillah.
   ========================================================================== */

/* ── 0. AQ NOOR ───────────────────────────────────────────────────────────
   The company's own variable serif, self-hosted. One file, wght 300-700 -
   the five filenames in public/fonts are byte-identical copies of the same
   variable font, so it is declared once and the axis does the work.

   Verified before the site was moved onto it: genuinely variable, 966 mapped
   codepoints, complete French and Kreyol accents including o-grave, and real
   em dashes and curly quotes. It can carry KOZE, not only English.

   Why this and not Syne: Syne is a free Google font any competitor installs
   in thirty seconds, so it can never be an identity. This face is owned.
   Three registers - AQ Noor speaks for humans, Inter carries body copy
   because a serif goes thin at 16px on near-black, and mono speaks for
   machines.
   ------------------------------------------------------------------------ */
@font-face {
  font-family: 'AQ Noor';
  src: url('/fonts/AQNoor-Regular.woff2?v=2026-08-05b') format('woff2-variations'),
       url('/fonts/AQNoor-Regular.woff2?v=2026-08-05b') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}


/* Inter and JetBrains Mono are now self-hosted. They used to come from Google
   Fonts on 30 pages, which cost two extra DNS + TLS handshakes on the critical
   path before a single glyph could be requested, and told a third party about
   every visitor. Both are SIL Open Font License, so self-hosting is permitted.

   Each is a variable font, instanced to only the weight range we actually
   render and subset to Latin-1 plus punctuation and currency. Latin-1 already
   carries every accent French and Kreyol need (e, e, a, o, c all live below
   U+00FF); the Latin Extended block was 85KB of Eastern European coverage we
   never set, so it is not shipped. */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/inter.woff2?v=2026-08-05b') format('woff2-variations'),
       url('/fonts/inter.woff2?v=2026-08-05b') format('woff2');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('/fonts/jetbrains-mono.woff2?v=2026-08-05b') format('woff2-variations'),
       url('/fonts/jetbrains-mono.woff2?v=2026-08-05b') format('woff2');
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}

/* ── 1. TOKENS ───────────────────────────────────────────────────────────── */
:root {
  /* Surfaces */
  /* Warm charcoal, not blue-black. anthropic.com and apple.com both get their
     calm from a WARM surface (#FAF9F5, #F5F5F7); the same trick inverted is a
     warm ink rather than a cold one. Measured against #ECE8E0: 15.44:1, still
     far above the 4.5 body-text bar. */
  --bg:            #12110F;
  --bg-2:          #1A1815;
  --bg-3:          #241F1A;
  --bg-grad:       linear-gradient(180deg, #12110F 0%, #1A1714 100%);
  --overlay:       rgba(18, 17, 15, 0.82);

  /* Gold — signal, never decoration */
  --gold:          #C9A84C;
  --gold-2:        #A8923F;
  --gold-3:        #7A6B2E;
  --gold-hover:    #D4B65E;
  --gold-active:   #B8973E;
  --gold-04:       rgba(201, 168, 76, 0.04);
  --gold-08:       rgba(201, 168, 76, 0.08);
  --gold-12:       rgba(201, 168, 76, 0.12);
  --gold-20:       rgba(201, 168, 76, 0.20);
  --gold-25:       rgba(201, 168, 76, 0.25);

  /* Text */
  /* Warm, not blue-white. Cool white on near-black blooms and haloes under
     greyscale antialiasing; a warm off-white settles onto the black and
     leaves the gold as the only temperature event on the page. 15.4:1 on the
     warm charcoal above, measured rather than remembered - the previous note
     said 14.9:1 against a background that actually gave 16.2:1. */
  --text:          #ECE8E0;
  --text-2:        #8A8A9A;
  --text-3:        #5A5A6A;

  /* State */
  --ok:            #34D399;
  --err:           #E8566D;
  --warn:          #E8A830;

  /* Structure */
  --line:          #322D26;
  --line-hover:    #453E33;
  --line-soft:     rgba(255, 255, 255, 0.05);

  /* Type */
  --font-display:  'AQ Noor', 'Cormorant Garamond', Georgia, serif;
  --font-body:     'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono:     'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Rhythm — 8pt scale */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px; --s5: 24px;
  --s6: 32px; --s7: 48px; --s8: 64px; --s9: 96px; --s10: 128px;

  /* Radius — a ladder, not a mood. Anthropic runs exactly four rungs
     (4/8/16 + pill) and Apple's two odd numbers are 28 (modals) and 980
     (pills — absurd on purpose, so the pill never flattens on a tall
     button). Every rectangle on the site sits on one of these five rungs;
     an off-ladder radius is drift. --r-tile is an alias kept for /pricing. */
  --r-xs: 4px; --r-sm: 8px; --r-md: 16px; --r-lg: 28px;
  --r-tile: var(--r-lg); --r-full: 980px;

  /* Elevation — whispers, not statements. Both reference sites are FLAT:
     Apple shadows nothing but focus rings; Anthropic's card shadow is three
     layers at 1-4% alpha, felt rather than seen. On dark ground the borders
     do the work (--line → --line-hover) and shadows only confirm. --lift-3
     keeps its weight for the two true overlays: palette and drawer. */
  --lift-1: 0 2px 2px rgba(0,0,0,0.06), 0 4px 4px rgba(0,0,0,0.08), 0 16px 24px rgba(0,0,0,0.12);
  --lift-2: 0 2px 2px rgba(0,0,0,0.08), 0 8px 12px rgba(0,0,0,0.12), 0 24px 40px rgba(0,0,0,0.16);
  --lift-3: 0 24px 80px rgba(0,0,0,0.55), 0 4px 12px rgba(0,0,0,0.35);

  /* Motion — three verbs and no more. State changes (color, border, bg)
     always ride --t-fast: Anthropic ships sixty-seven flat .2s transitions
     and nothing else, and that uniformity is most of the calm. Anything
     that physically MOVES takes Apple's house curve (they ship it 78
     times); entrances keep the expo settle. */
  --ease-move: cubic-bezier(0.4, 0, 0.6, 1);
  --t-fast: 0.2s ease;
  --t-card: 0.3s var(--ease-move);
  --t-slow: 0.6s cubic-bezier(0.16, 1, 0.3, 1);

  /* Section rhythm — Anthropic's quantized scale (4/6/10/14rem, 12rem page
     top) instead of one fluid guess. Sections sit on rungs, like radii. */
  --sec-sm: 4rem; --sec-md: 6rem; --sec-lg: 10rem; --sec-xl: 14rem;
  --sec-top: 12rem;

  /* Shell */
  --rail: 248px;
  --topbar: 64px;
}

/* ── 1b. DATA-SURFACE ACCENTS — scoped, never global ─────────────────────
   Anthropic's pattern (verified 2026-08-07): beyond its two brand colors it
   declares eight muted accents — clay, fig, cactus, sky — that surface ONLY
   on dashboards, research and news pages. The homepage stays two-color
   forever; the data layer gets a quiet palette that never bleeds upward.

   Same law here. These exist for portal, finance and report surfaces —
   chart series, status chips, category marks — and are declared on
   .surface-data, NOT on :root, so a brand page cannot reach them even by
   accident. Brand surfaces remain one black and one gold. If a marketing
   page ever needs one of these, the answer is no. */
.surface-data {
  --d-clay:    #C08A6C;   /* warm terracotta — series 1 / neutral emphasis */
  --d-sage:    #8FA98B;   /* muted green    — series 2 / steady, healthy  */
  --d-sky:     #7FA3B8;   /* dusty blue     — series 3 / informational    */
  --d-heather: #A08BB0;   /* muted violet   — series 4 / secondary dim.   */
  --d-sand:    #C4B292;   /* quiet sand     — series 5 / totals, baselines */
}

/* ── 2. RESET + BASE ─────────────────────────────────────────────────────── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  /* No scroll-behavior here. Lenis owns scrolling now, and native smooth
     fights its lerp — in Safari 15.4+ it can block programmatic scroll
     outright. Lenis 1.3.25 dropped the reset from its own stylesheet, so
     it lives below instead. */
  -webkit-text-size-adjust: 100%;
}
html.lenis, html.lenis body { scroll-behavior: auto !important; }
html.lenis { height: auto; }
.lenis.lenis-stopped { overflow: clip; }

body {
  background: var(--bg);
  color: var(--text);
  /* Body copy is the serif now. anthropic.com sets its body in a SERIF at
     24px/33.6 and that single choice does more for the editorial feel than any
     amount of layout. We already own AQ Noor, a variable serif, so this costs
     no new bytes. Inter stays for UI chrome - nav, buttons, labels, tables -
     because a serif goes thin and blurry at 13-15px on a dark surface. */
  font-family: var(--font-display);
  font-size: 19px;
  line-height: 1.68;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  min-height: 100vh;
  font-feature-settings: 'kern' 1, 'liga' 1, 'cv11' 1;
}

/* ── UI CHROME KEEPS INTER ────────────────────────────────────────────────
   The serif is for prose. Everything a person operates rather than reads
   stays on Inter: at 13-15px on a dark surface a serif's thin strokes go
   grey and lose their edge, and controls need to look like controls.
   Anthropic does the same split - serif body, sans navigation and buttons. */
.nav, .nav-links, .nav-logo, .drawer, .rail, .topbar,
.btn, button, input, select, textarea, label,
.label, .caption, .eyebrow, .badge, .chip, .telem,
table, th, td, .body-sm, .skel, .field > label, .field-error,
.agent-name, .agent-role, .agent-metric, .agent-last, .pick, .pick-name {
  font-family: var(--font-body);
}

/* Prose keeps the serif, and gets the measure that makes a serif readable. */
p, .lede, li, blockquote, .qa p, .legal p, .legal li {
  font-family: var(--font-display);
}
p, li { max-width: 74ch; }


/* Ambient depth — felt, not seen */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background: radial-gradient(ellipse 90% 55% at 50% -12%, rgba(201,168,76,0.045), transparent 62%);
  pointer-events: none;
  z-index: 0;
}
body > * { position: relative; z-index: 1; }

img, svg, video { max-width: 100%; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }

::selection { background: var(--gold-25); color: var(--text); }

/* Scrollbar — part of the surface, not an OS artifact */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: var(--r-full); border: 3px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: var(--line-hover); }

/* ── 3. ACCESSIBILITY (A11Y-002, A11Y-006, ANIM-005, FORM-005) ───────────── */
:focus { outline: none; }
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.30);
  border-radius: inherit;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 9999;
}
.skip-link:focus {
  left: var(--s4);
  top: var(--s4);
  background: var(--gold);
  color: var(--bg);
  padding: var(--s3) var(--s5);
  border-radius: var(--r-sm);
  font-weight: 600;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px #121219 inset !important;
  -webkit-text-fill-color: var(--text) !important;
  caret-color: var(--text);
  transition: background-color 5000s ease-in-out 0s;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── 4. TYPOGRAPHY ───────────────────────────────────────────────────────── */
/* A serif needs the opposite weight curve to the geometric sans that was here
   before. Display sizes want the light end of the axis and tight tracking, or
   the letterforms bloat; small sizes want weight, or the thin strokes vanish
   into the dark. And a high-contrast serif on near-black loses its hairlines
   to greyscale antialiasing, so smoothing is left alone on headings only -
   body copy stays antialiased because Inter wants it. */
h1, h2, h3, h4, .h1, .h2, .h3, .h4 {
  font-family: var(--font-display);
  color: var(--text);
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
  font-optical-sizing: auto;
}
/* Two things separate expensive type from template type, and neither costs a
   byte. First, TRACKING TIGHTENS AS SIZE RISES - spacing that reads correctly
   at 16px is gappy at 88px. Second, DISPLAY LEADING GOES BELOW 1 - tight
   display leading is the strongest single premium signal and the most common
   thing amateur sites get wrong.

   The third is scale CONTRAST: the ratio between the smallest and largest
   type is what reads as luxury. A uniform 1.2 ratio all the way up reads as a
   bootstrap template, so the hero jumps hard away from body copy. */
/* SEVEN sizes for the whole site, and no more. anthropic.com uses exactly
   seven (61/24/20/18/16/14/12) and that restraint is most of why it reads
   expensive; we were using twelve. Every ad-hoc clamp() elsewhere in this file
   now resolves to one of these steps instead of inventing an eighth.
   Display tracking stays at -0.034em, tighter than Apple's -0.015em, because
   that is ours and it is more distinctive. */
h1, .h1 { font-weight: 400; font-size: clamp(40px, 6.6vw, 88px); line-height: 0.98; letter-spacing: -0.034em; }
h2, .h2 { font-weight: 450; font-size: clamp(30px, 4.2vw, 56px); line-height: 1.04; letter-spacing: -0.026em; }
h3, .h3 { font-weight: 500; font-size: clamp(22px, 2.0vw, 32px); line-height: 1.16; letter-spacing: -0.014em; }
h4, .h4 { font-weight: 500; font-size: 20px; line-height: 1.30; letter-spacing: -0.006em; }

.lede    { font-size: clamp(17px, 1.5vw, 20px); line-height: 1.62; color: var(--text-2); }
.body-sm { font-size: 14px; line-height: 1.60; }
.mono    { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

.label {
  font-size: 14px; font-weight: 500; line-height: 1.2;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-2);
}
.caption {
  font-size: 12px; font-weight: 400; line-height: 1.4;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--text-3);
}
/* Wide-tracked uppercase at 12px is instrument text, not a voice. A serif has
   nothing to say at that size and loses its strokes; mono is crisp and carries
   the machine register the rest of the system already uses. */
.eyebrow {
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 500;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold);
}

.gold  { color: var(--gold); }
.dim   { color: var(--text-2); }
.faint { color: var(--text-3); }
.prose { max-width: 680px; }   /* TYPO-001 */

/* Leading-trim, for real. Anthropic fakes this with per-family em margins
   (.44em top-trim on their serif) because they shipped before text-box
   landed; every evergreen browser has had it since 2025, so we get the
   genuine article: the half-leading above cap height and below baseline is
   cut, type sits flush against edges, and button labels centre on their
   glyphs instead of their line boxes. Headings carry no default margins in
   this system, so nothing needs re-tuning underneath. */
@supports (text-box: trim-both cap alphabetic) {
  h1, h2, h3, h4, .h1, .h2, .h3, .h4,
  .lede, .eyebrow, .btn, .badge, .pull { text-box: trim-both cap alphabetic; }
}

/* ── 5. LAYOUT ───────────────────────────────────────────────────────────── */
.wrap { width: 100%; max-width: 1120px; margin: 0 auto; padding: 0 var(--s5); }
.wrap-wide { max-width: 1400px; }
/* Default section = Anthropic's --section-space--main (10rem) at the top of
   the clamp instead of an arbitrary 120px. The variants are rungs, so a page
   composes rhythm from the same scale everywhere. */
.section { padding: clamp(var(--sec-sm), 9vw, var(--sec-lg)) 0; }
.section-sm  { padding: clamp(2rem, 5vw, var(--sec-sm)) 0; }
.section-md  { padding: clamp(var(--sec-sm), 7vw, var(--sec-md)) 0; }
.section-lg  { padding: clamp(var(--sec-md), 12vw, var(--sec-xl)) 0; }
.section-top { padding-top: clamp(var(--sec-md), 14vw, var(--sec-top)); }

.stack   { display: flex; flex-direction: column; }
.row     { display: flex; align-items: center; }
.between { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); }
.gap-1 { gap: var(--s1); } .gap-2 { gap: var(--s2); } .gap-3 { gap: var(--s3); }
.gap-4 { gap: var(--s4); } .gap-5 { gap: var(--s5); } .gap-6 { gap: var(--s6); }
.grow  { flex: 1; }
.wrap-flex { flex-wrap: wrap; }

.grid { display: grid; gap: var(--s4); }
.g-2 { grid-template-columns: repeat(2, minmax(0,1fr)); }
.g-3 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.g-4 { grid-template-columns: repeat(4, minmax(0,1fr)); }
.g-auto { grid-template-columns: repeat(auto-fill, minmax(248px, 1fr)); }

.divider {
  height: 1px; border: 0; max-width: 200px; margin: 0 auto;
  background: linear-gradient(90deg, transparent, var(--gold-20), transparent);
}
.rule { height: 1px; background: var(--line); border: 0; }

/* ── 6. APP SHELL (portal + command) ─────────────────────────────────────── */
.app {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  min-height: 100vh;
}

.rail {
  position: sticky; top: 0;
  height: 100vh;
  display: flex; flex-direction: column;
  background: rgba(18, 18, 25, 0.6);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-right: 1px solid var(--line-soft);
  padding: var(--s5) var(--s3) var(--s4);
  overflow-y: auto;
  z-index: 40;
}
.rail-brand {
  display: flex; align-items: center; gap: var(--s3);
  padding: 0 var(--s3) var(--s5);
  font-family: var(--font-mono);
  font-weight: 600; font-size: 12px; letter-spacing: 0.25em;
  color: var(--gold);
}
.rail-brand svg { width: 26px; height: 26px; flex: none; }
.rail-group { margin-bottom: var(--s5); }
.rail-group > .caption { padding: 0 var(--s3) var(--s2); }

.rail-link {
  display: flex; align-items: center; gap: var(--s3);
  padding: 10px var(--s3);
  min-height: 44px;
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: 14px; font-weight: 500;
  transition: color var(--t-fast), background var(--t-fast);
  position: relative;
}
.rail-link:hover { color: var(--text); background: rgba(255,255,255,0.03); }
.rail-link[aria-current="page"] { color: var(--gold); background: var(--gold-08); }
.rail-link[aria-current="page"]::before {
  content: ''; position: absolute; left: 0; top: 50%;
  transform: translateY(-50%);
  width: 2px; height: 18px; border-radius: 0 2px 2px 0;
  background: var(--gold);
}
.rail-link .tag {
  margin-left: auto;
  font-family: var(--font-mono); font-size: 11px;
  color: var(--text-3);
}
.rail-foot { margin-top: auto; padding-top: var(--s4); border-top: 1px solid var(--line-soft); }

.main { min-width: 0; display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 30;
  min-height: var(--topbar);
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s3) clamp(16px, 3vw, 40px);
  background: rgba(10, 10, 15, 0.72);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--line-soft);
}
.topbar h1 { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; }

.canvas { padding: clamp(24px, 3vw, 40px) clamp(16px, 3vw, 40px) var(--s9); }
.canvas > * + * { margin-top: var(--s6); }

.rail-toggle { display: none; }

/* ── 7. CARDS + PANELS ───────────────────────────────────────────────────── */
.card {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--s5);
}
/* Neither parent moves a card. Apple's store tiles and Anthropic's article
   cards both answer hover with colour alone — the edge catches light, the
   surface breathes, nothing travels. */
.card-lift { transition: border-color var(--t-fast), background-color var(--t-fast), box-shadow var(--t-fast); }
.card-lift:hover {
  border-color: var(--gold-20);
  box-shadow: var(--lift-1);
}
.card-glass {
  background: rgba(18, 18, 25, 0.7);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--gold-12);
  border-radius: var(--r-lg);
}
.card-gold { border-color: var(--gold-20); background: linear-gradient(180deg, var(--gold-04), transparent 60%), var(--bg-2); }

.panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s4); margin-bottom: var(--s4);
}
.panel-head h2, .panel-head h3 { font-size: 16px; font-weight: 600; letter-spacing: 0.02em; }

/* Stat tile */
.stat { display: flex; flex-direction: column; gap: var(--s2); }
.stat-label { font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-3); font-weight: 500; }
/* Unlike .readout, .stat-value carries live portal telemetry - counts that
   move, refresh and get compared down a column. That is machine output, so it
   takes the machine register and gets tabular alignment for free. */
.stat-value {
  font-family: var(--font-mono); font-weight: 500;
  font-size: clamp(22px, 2.0vw, 32px); line-height: 1.1;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}
.stat-value.is-gold { color: var(--gold); }
.stat-foot { font-size: 14px; color: var(--text-2); }

/* ── 8. BUTTONS ──────────────────────────────────────────────────────────
   Anthropic's architecture, Apple's manners, mixed inheritance on the shape.

   Architecture: the base class renders ONLY from six custom properties and
   variants do nothing but reassign them — one component, N skins, exactly
   how anthropic.com ships primary/secondary/tertiary as pure var swaps.

   Manners: hover changes colour and nothing else. Apple's flagship button
   moves from #0071e3 to #0076DF on hover — about 2% — with no transform,
   no shadow, no sheen; ours moves gold → gold-hover the same way. The
   restraint IS the luxury; everything that used to translate, glow, sweep
   or scale here was deleted on 2026-08-06, not lost.

   Shape: the primary is Apple's pill (980px). Secondaries are Anthropic's
   bordered 8px rectangle. Apple pairs pills with text links, Anthropic
   pairs filled rects with bordered rects — the child pairs pill-primary
   with rect-secondary, one filled shape and one drawn one.
   ────────────────────────────────────────────────────────────────────── */
.btn {
  --btn-bg: transparent;
  --btn-text: var(--text);
  --btn-border: transparent;
  --btn-bg-hover: var(--btn-bg);
  --btn-text-hover: var(--btn-text);
  --btn-border-hover: var(--btn-border);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 44px; padding: 12px var(--s5);
  border: 1px solid var(--btn-border); border-radius: var(--r-sm);
  background: var(--btn-bg); color: var(--btn-text);
  font-family: var(--font-body); font-size: 16px; font-weight: 500;
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.btn:hover:not(:disabled) {
  background: var(--btn-bg-hover);
  color: var(--btn-text-hover);
  border-color: var(--btn-border-hover);
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-gold {
  --btn-bg: var(--gold);
  --btn-text: var(--bg);
  --btn-bg-hover: var(--gold-hover);
  --btn-text-hover: var(--bg);
  border-radius: var(--r-full);
  padding-inline: 28px;
  font-weight: 600; letter-spacing: 0.04em;
}
.btn-gold:active:not(:disabled) { background: var(--gold-active); }

.btn-ghost {
  --btn-text: var(--gold);
  --btn-border: var(--gold-25);
  --btn-bg-hover: var(--gold-08);
  --btn-text-hover: var(--gold);
  --btn-border-hover: var(--gold);
  letter-spacing: 0.03em;
}

.btn-dark {
  --btn-bg: var(--bg-3);
  --btn-border: var(--line);
  --btn-bg-hover: #242430;
  --btn-border-hover: var(--line-hover);
}

.btn-sm { min-height: 36px; padding: 8px var(--s4); font-size: 14px; }
.btn-block { width: 100%; }

.btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: none;
  border-radius: var(--r-sm);
  background: transparent; border: 1px solid var(--line);
  color: var(--text-2); cursor: pointer;
  transition: color var(--t-fast), border-color var(--t-fast), background var(--t-fast);
}
.btn-icon:hover { color: var(--text); border-color: var(--line-hover); background: rgba(255,255,255,0.03); }

.link-gold {
  color: var(--gold); font-weight: 500;
  border-bottom: 1px solid var(--gold-25);
  padding-bottom: 1px;
  transition: border-color var(--t-fast);
}
.link-gold:hover { border-color: var(--gold); }

/* ── 9. FORMS ────────────────────────────────────────────────────────────── */
.field { display: flex; flex-direction: column; gap: var(--s2); margin-bottom: var(--s5); }
.field > label { font-size: 14px; font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-2); }

.input, input[type="text"], input[type="email"], input[type="password"], input[type="search"], textarea, select {
  width: 100%;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 13px var(--s4);
  color: var(--text);
  font-size: 16px;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.input::placeholder, input::placeholder, textarea::placeholder { color: var(--text-3); }
.input:focus, input:focus, textarea:focus, select:focus {
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-08);
  background: rgba(255, 255, 255, 0.045);
}
.input[aria-invalid="true"], input[aria-invalid="true"] { border-color: var(--err); }

.field-error {
  display: flex; align-items: center; gap: 6px;
  color: var(--err); font-size: 14px;
}
.field-error::before { content: '!'; display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; border: 1px solid currentColor; border-radius: 50%; font-size: 11px; font-weight: 700; flex: none; }

/* ── 10. BADGES + STATUS (A11Y-007 — never colour alone) ─────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--r-full);
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  background: rgba(138,138,154,0.12); color: var(--text-2);
  border: 1px solid transparent;
}
.badge-gold { background: var(--gold-12); color: var(--gold); border-color: var(--gold-20); }
.badge-ok   { background: rgba(52,211,153,0.12);  color: var(--ok); }
.badge-warn { background: rgba(232,168,48,0.12);  color: var(--warn); }
.badge-err  { background: rgba(232,86,109,0.12);  color: var(--err); }

.dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: currentColor; }
.dot-live { background: var(--ok); animation: breathe 2.4s ease-in-out infinite; }
@keyframes breathe { 0%, 100% { opacity: 0.45; } 50% { opacity: 1; } }

/* ── 11. TABLES + LISTS ──────────────────────────────────────────────────── */
.table-scroll { overflow-x: auto; margin: 0 calc(var(--s5) * -1); padding: 0 var(--s5); }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th {
  text-align: left; padding: var(--s2) var(--s3) var(--s3);
  font-size: 11px; font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-3); border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
td { padding: var(--s3); border-bottom: 1px solid var(--line-soft); color: var(--text-2); vertical-align: middle; }
td.strong { color: var(--text); font-weight: 500; }
tbody tr { transition: background var(--t-fast); }
tbody tr:hover { background: rgba(255,255,255,0.02); }
tbody tr:last-child td { border-bottom: none; }

.feed-item {
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--line-soft);
}
.feed-item:last-child { border-bottom: none; }
.feed-mark {
  width: 34px; height: 34px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-sm);
  background: var(--gold-08); border: 1px solid var(--gold-12);
  color: var(--gold);
  font-family: var(--font-mono); font-weight: 600; font-size: 11px; letter-spacing: 0.04em;
}
.feed-body { flex: 1; min-width: 0; font-size: 14px; color: var(--text-2); }
.feed-body strong { color: var(--text); font-weight: 500; }
.feed-time { font-family: var(--font-mono); font-size: 12px; color: var(--text-3); white-space: nowrap; }

/* ── 12. LOADING, EMPTY, ERROR (ANIM-004, PERF-003) ──────────────────────── */
.skel {
  background: var(--bg-2);
  border-radius: var(--r-sm);
  animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.75; } }
.skel-line { height: 12px; }
.skel-line + .skel-line { margin-top: var(--s2); }
.skel-w70 { width: 70%; } .skel-w50 { width: 50%; } .skel-w40 { width: 40%; }

.loading-note { color: var(--gold); font-size: 14px; animation: pulse 2s ease-in-out infinite; }

.empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--s3);
  text-align: center; padding: var(--s7) var(--s5);
}
.empty-mark {
  width: 44px; height: 44px;
  color: var(--gold-3);
  animation: hover-breathe 5s ease-in-out infinite;
}
@keyframes hover-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.03); } }
.empty h4 { font-size: 18px; font-weight: 500; }
.empty p { color: var(--text-2); max-width: 380px; font-size: 16px; }

.notice {
  display: flex; gap: var(--s4); align-items: flex-start;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-left: 2px solid var(--text-3);
  border-radius: var(--r-sm);
  padding: var(--s4) var(--s5);
}
.notice-err  { border-left-color: var(--err); }
.notice-warn { border-left-color: var(--warn); }
.notice-gold { border-left-color: var(--gold); }
.notice h4 { font-size: 16px; font-weight: 500; margin-bottom: 4px; }
.notice p { color: var(--text-2); font-size: 14px; }

/* Connection banner — the honest answer to "is the site up?" */
.conn {
  position: fixed; left: 50%; bottom: var(--s5);
  transform: translate(-50%, 140%);
  z-index: 300;
  display: flex; align-items: center; gap: var(--s3);
  max-width: calc(100vw - 32px);
  padding: 10px var(--s4);
  border-radius: var(--r-full);
  background: rgba(28, 28, 39, 0.94);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--line);
  box-shadow: var(--lift-2);
  font-size: 14px; color: var(--text-2);
  transition: transform var(--t-card);
}
.conn.show { transform: translate(-50%, 0); }
.conn-warn { border-color: rgba(232,168,48,0.35); }

/* Toasts */
.toasts {
  position: fixed; right: var(--s5); bottom: var(--s5);
  z-index: 320; display: flex; flex-direction: column; gap: var(--s2);
  max-width: min(360px, calc(100vw - 32px));
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: var(--s3);
  background: var(--bg-3); border: 1px solid var(--line);
  border-left: 2px solid var(--gold);
  border-radius: var(--r-sm);
  padding: var(--s3) var(--s4);
  font-size: 14px; color: var(--text);
  box-shadow: var(--lift-2);
  animation: toast-in 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.toast-ok  { border-left-color: var(--ok); }
.toast-err { border-left-color: var(--err); }
.toast.out { animation: toast-out 0.25s ease forwards; }
@keyframes toast-in  { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to { opacity: 0; transform: translateY(8px); } }

/* ── 13. COMMAND PALETTE ─────────────────────────────────────────────────── */
.scrim {
  position: fixed; inset: 0; z-index: 200;
  background: var(--overlay);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: none;
}
.scrim.show { display: block; }

.palette {
  position: fixed; z-index: 210;
  top: 14vh; left: 50%; transform: translateX(-50%);
  width: min(560px, calc(100vw - 32px));
  background: var(--bg-3);
  border: 1px solid var(--gold-12);
  border-radius: var(--r-lg);
  box-shadow: var(--lift-3);
  overflow: hidden;
  display: none;
}
.palette.show { display: block; animation: toast-in 0.22s ease-out; }
.palette input {
  border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  background: transparent; padding: var(--s4) var(--s5); font-size: 16px;
}
.palette input:focus { box-shadow: none; border-color: var(--line); background: transparent; }
.palette-list { max-height: 320px; overflow-y: auto; padding: var(--s2); }
.palette-item {
  display: flex; align-items: center; gap: var(--s3);
  padding: 10px var(--s3); border-radius: var(--r-sm);
  font-size: 14px; color: var(--text-2); cursor: pointer;
}
.palette-item[aria-selected="true"] { background: var(--gold-08); color: var(--text); }
.palette-item .who { font-family: var(--font-mono); font-weight: 600; font-size: 12px; letter-spacing: 0.06em; color: var(--gold); min-width: 84px; }
.palette-empty { padding: var(--s5); text-align: center; color: var(--text-3); font-size: 14px; }

kbd {
  font-family: var(--font-mono); font-size: 11px;
  padding: 2px 6px; border-radius: var(--r-xs);
  background: rgba(255,255,255,0.05);
  border: 1px solid var(--line);
  color: var(--text-3);
}

/* ── 14. REVEAL (ANIM-001, ANIM-003) ─────────────────────────────────────── */
/* Content is visible by default. The hidden state is opt-in, set by an inline
   head script only when IntersectionObserver exists, so a failed observer or a
   blocked script can never leave a page permanently blank. */
.js-reveal .reveal { opacity: 0; transform: translateY(20px); transition: opacity var(--t-slow), transform var(--t-slow); }
.js-reveal .reveal.in { opacity: 1; transform: none; }
.d1 { transition-delay: 0.06s; } .d2 { transition-delay: 0.12s; }
.d3 { transition-delay: 0.18s; } .d4 { transition-delay: 0.24s; }

.scroll-progress {
  position: fixed; top: 0; left: 0; z-index: 120;
  height: 3px; width: 0;
  background: linear-gradient(90deg, var(--gold-3), var(--gold) 60%, var(--gold-hover));
  box-shadow: 0 0 12px rgba(201,168,76,0.55);
  transition: width 0.1s linear;
}

/* ── 15. MARKETING NAV ───────────────────────────────────────────────────── */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--s5) clamp(20px, 4vw, 40px);
  transition: background var(--t-card), padding var(--t-card), border-color var(--t-card);
  border-bottom: 1px solid transparent;
}
/* Apple's one indulgence, at Apple's exact recipe: glass lives on the nav
   and NOWHERE else on the page — saturate(180%) blur(20px), the values
   their global header has shipped for years. Saturation is what separates
   glass from fog: colour passing under the bar comes through slightly
   richer, not greyer. Base tint is the warm charcoal, not the old cool
   navy. Where backdrop-filter is unsupported the tint runs nearly solid. */
.nav.stuck {
  background: rgba(18, 17, 15, 0.92);
  border-bottom-color: var(--gold-08);
  padding-top: var(--s3); padding-bottom: var(--s3);
}
@supports (backdrop-filter: blur(20px)) or (-webkit-backdrop-filter: blur(20px)) {
  .nav.stuck {
    background: rgba(18, 17, 15, 0.72);
    backdrop-filter: saturate(180%) blur(20px);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
  }
}
/* The wordmark stays in the machine register. Small uppercase caps at 0.25em
   tracking is where a serif is weakest and mono is strongest, and it keeps the
   logo's technical edge instead of turning it editorial. */
.nav-logo {
  font-family: var(--font-mono); font-weight: 600;
  font-size: 14px; letter-spacing: 0.25em; color: var(--gold);
}
.nav-links { display: flex; align-items: center; gap: var(--s6); }
.nav-links a {
  font-size: 14px; font-weight: 500; letter-spacing: 0.02em;
  color: var(--text-2); transition: color var(--t-fast);
  padding: 6px 0;
}
.nav-links a:hover { color: var(--text); }
.nav-links a[aria-current="page"] { color: var(--gold); border-bottom: 2px solid var(--gold); }

.ham { display: none; width: 44px; height: 44px; background: none; border: 0; cursor: pointer; flex-direction: column; align-items: center; justify-content: center; gap: 5px; }
.ham span { display: block; width: 22px; height: 2px; border-radius: var(--r-xs); background: var(--text); transition: transform var(--t-card), opacity var(--t-card); }
.ham.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.ham.open span:nth-child(2) { opacity: 0; }
.ham.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.drawer {
  position: fixed; inset: 0 0 0 auto; z-index: 95;
  width: min(320px, 84vw);
  background: rgba(10, 10, 15, 0.98);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-left: 1px solid var(--line-soft);
  padding: calc(var(--topbar) + var(--s6)) var(--s6) var(--s6);
  display: flex; flex-direction: column; gap: var(--s2);
  transform: translateX(100%);
  /* visibility is delayed on the way out so the slide still plays, and is
     immediate on the way in. Without it the drawer is merely off-screen:
     still focusable, still read by screen readers. Above 860px .ham is
     hidden, so tabbing past the nav used to walk into five links nobody
     can see. Off-screen is not closed. */
  transition: transform var(--t-card), visibility 0s linear 0.3s;
  visibility: hidden;
}
.drawer.open {
  transform: none;
  visibility: visible;
  transition: transform var(--t-card);
}
.drawer a {
  font-family: var(--font-display); font-weight: 600; font-size: 18px;
  padding: var(--s3) 0; min-height: 56px;
  display: flex; align-items: center;
  border-bottom: 1px solid var(--line-soft);
}

/* ── 16. RESPONSIVE ──────────────────────────────────────────────────────── */
@media (max-width: 1024px) {
  .g-4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .g-3 { grid-template-columns: repeat(2, minmax(0,1fr)); }
}

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }
  .rail {
    position: fixed; inset: 0 auto 0 0;
    width: min(280px, 84vw);
    transform: translateX(-100%);
    transition: transform var(--t-card);
    background: rgba(14, 14, 20, 0.98);
  }
  .rail.open { transform: none; box-shadow: var(--lift-3); }
  .rail-toggle { display: inline-flex; }
  .nav-links { display: none; }
  .ham { display: flex; }
}

@media (max-width: 620px) {
  .topbar { gap: var(--s3); }
  .topbar h1 { white-space: nowrap; font-size: 18px; }
  .topbar .caption { display: none; }   /* the date is not worth two lines on a phone */

  .g-2, .g-3, .g-4 { grid-template-columns: 1fr; }
  .g-auto { grid-template-columns: 1fr; }
  body { font-size: 16px; }
  .card { padding: var(--s4); }
  .canvas > * + * { margin-top: var(--s5); }
  .toasts { left: var(--s4); right: var(--s4); max-width: none; }
  .card-lift:hover { box-shadow: none; }
}

/* Print — briefings get printed by real owners */
@media print {
  body { background: #fff; color: #000; }
  .rail, .topbar, .conn, .toasts, .nav, .drawer { display: none !important; }
  .card { border-color: #ccc; break-inside: avoid; }
}

/* ==========================================================================
   17. THE TRAJECTORY
   Opt-in layer for the public site. A page in this mode is not a document
   being scrolled - it is a distance being travelled. Everything here is
   transform/opacity only, and every bit of it dies under reduced-motion.
   Scoped to .cosmos so the portal stays calm and functional.
   ========================================================================== */

.cosmos { --vel: 0; --travel: 0px; }

/* Film grain. What separates a cinematic dark surface from a dark div. */
.cosmos::after {
  content: '';
  position: fixed; inset: -50%;
  z-index: 2;
  pointer-events: none;
  /* Same de-blend as body::after (§PAPER): a fixed blended layer re-blends
     the full viewport every scrolled frame. Plain alpha at a lower opacity
     reads the same and composites for almost nothing. */
  opacity: 0.10;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* The light source descends with you. The page is lit from wherever you are. */
.cosmos .lamp {
  position: fixed; inset: -30vh 0 auto 0;
  height: 120vh;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 45% at 50% 30%, rgba(201,168,76,0.075), transparent 65%);
  transform: translate3d(0, var(--travel), 0);
  will-change: transform;
}
/* Lift only the flow content above the lamp. A blanket rule here would
   overwrite position:fixed on the nav, the drawer and the spine. */
.cosmos > main, .cosmos > footer { position: relative; z-index: 1; }

/* ── The spine: a flight path, not a progress bar ───────────────────────── */
.spine {
  position: fixed; left: clamp(20px, 3.2vw, 46px); top: 0; bottom: 0;
  width: 1px; z-index: 60; pointer-events: none;
}
.spine-track {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent, var(--line) 10%, var(--line) 90%, transparent);
}
.spine-fill {
  position: absolute; top: 0; left: 0; width: 1px;
  height: var(--progress, 0%);
  background: linear-gradient(180deg, transparent, rgba(201,168,76,0.35) 30%, var(--gold));
}
.spine-head {
  position: absolute; left: -2px; top: var(--progress, 0%);
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 10px rgba(201,168,76,0.7), 0 0 26px rgba(201,168,76,0.25);
  /* Scroll fast and the marker streaks. Stop and it settles. */
  transform: translateY(-50%) scaleY(calc(1 + var(--vel) * 7));
  transform-origin: center;
}
.waypoint {
  position: absolute; left: 0; top: 0;
  transform: translate(-3px, -50%);
  pointer-events: auto;
}
.waypoint i {
  display: block; width: 7px; height: 7px;
  border: 1px solid var(--line-hover); border-radius: 50%;
  background: var(--bg);
  transition: background var(--t-fast), border-color var(--t-fast), box-shadow var(--t-fast);
}
.waypoint b {
  position: absolute; left: 18px; top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-mono); font-size: 11px; font-weight: 400;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-3); white-space: nowrap;
  opacity: 0; transition: opacity var(--t-fast), color var(--t-fast);
}
.waypoint.lit i { background: var(--gold); border-color: var(--gold); box-shadow: 0 0 10px rgba(201,168,76,0.5); }
.waypoint.lit b { opacity: 1; }
.waypoint.here b { color: var(--gold); }
@media (max-width: 1180px) { .spine { display: none; } }

/* ── Arrival: elements do not fade in, they come through ────────────────── */
/* No clip-path on an observed element. Chrome computes IntersectionObserver
   ratios against the clipped box, so a clipped element reports ratio 0,
   never intersects, and never un-hides. Opacity and transform do not have
   that problem. The hard masked edge lives on .wordmask, whose wrapper is
   clipped while the observed heading is not. */
.js-reveal .arrive {
  opacity: 0;
  transform: translate3d(0, 34px, 0);
  transition: opacity var(--t-slow), transform var(--t-slow);
}
.js-reveal .arrive.in { opacity: 1; transform: none; }

/* Headline words come through one at a time, from behind a hard edge. */
.wordmask { display: inline-block; overflow: hidden; vertical-align: bottom; }
.wordmask > i {
  display: inline-block; font-style: inherit;
  transform: translateY(110%);
  transition: transform var(--t-slow);
}
.wordmask.in > i { transform: none; }

/* ── Bands: the three enemies are not a card grid, they are a sequence ──── */
.band {
  position: relative;
  border-top: 1px solid var(--line-soft);
  padding: clamp(36px, 5vw, 64px) 0;
  display: grid;
  grid-template-columns: clamp(64px, 9vw, 128px) minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(16px, 3vw, 40px);
  align-items: start;
  transition: background var(--t-fast);
}
.band:last-child { border-bottom: 1px solid var(--line-soft); }
.band:hover { background: linear-gradient(90deg, var(--gold-04), transparent 55%); }
.band-n {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.16em;
  color: var(--gold-3); padding-top: 8px;
}
.band h3 {
  font-size: clamp(22px, 2.0vw, 32px); font-weight: 600;
  letter-spacing: -0.01em; line-height: 1.15;
}
.band p { color: var(--text-2); font-size: 16px; line-height: 1.75; }
@media (max-width: 780px) {
  .band { grid-template-columns: 1fr; gap: var(--s3); }
  .band-n { padding-top: 0; }
}

/* ── Instrument readout ─────────────────────────────────────────────────── */
.readout {
  display: flex; flex-wrap: wrap; gap: clamp(20px, 4vw, 52px);
  padding-top: var(--s5);
  border-top: 1px solid var(--line-soft);
}
.readout > div { min-width: 96px; }
.readout dt {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--text-3); margin-bottom: 6px;
}
/* Stays in the serif. A marketing readout - twenty-one agents, zero setup steps,
   no contract, ten percent - is a claim made to a human, not telemetry, and
   AQ Noor's figures are lining and cap-height (verified by canvas measurement
   against the fallbacks, not by eye). Tabular so the columns still align. */
.readout dd {
  font-family: var(--font-display); font-weight: 450;
  font-size: clamp(22px, 2.0vw, 32px); line-height: 1.05;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.readout dd em { font-style: normal; color: var(--gold); }

/* ── Composition cursor for the briefing ────────────────────────────────── */
.compose > * { opacity: 0; transition: opacity var(--t-slow); }
.compose > *.on { opacity: 1; }
.caret {
  display: inline-block; width: 7px; height: 1.05em;
  margin-left: 3px; vertical-align: text-bottom;
  background: var(--gold);
  animation: blink 1.1s steps(2, start) infinite;
}
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* ── Momentum: the card that argues for moving, moves ───────────────────── */
.drift { position: relative; overflow: hidden; }
.drift::before {
  content: '';
  position: absolute; left: -40%; top: 0; bottom: 0; width: 40%;
  background: linear-gradient(90deg, transparent, rgba(201,168,76,0.07), transparent);
  animation: sweep 6.5s cubic-bezier(0.45, 0, 0.55, 1) infinite;
  pointer-events: none;
}
@keyframes sweep { 0% { left: -45%; } 60%, 100% { left: 120%; } }

/* Reduced motion removes the universe and leaves the content. */
@media (prefers-reduced-motion: reduce) {
  .cosmos::after, .cosmos .lamp, .drift::before, .caret { display: none; }
  .js-reveal .arrive { opacity: 1; transform: none; }
  .wordmask > i { transform: none; }
  .compose > * { opacity: 1; }
  .spine-head { transform: translateY(-50%); }
}

/* ── The watcher ────────────────────────────────────────────────────────────
   The Aqthevision eye as atmosphere, per styles.csv floating_element: a sacred
   geometry motif that registers in peripheral vision only. Opacity stays under
   0.08, the drift runs slower than 15s, and it is never interactive. If a
   visitor notices one directly, it is too prominent.
   ------------------------------------------------------------------------- */
.watcher {
  position: absolute;
  pointer-events: none;
  color: var(--gold);
  opacity: 0.05;
  z-index: 0;
  animation: drift 22s ease-in-out infinite alternate;
}
.watcher svg { width: 100%; height: 100%; display: block; }
.watcher-lg { width: clamp(320px, 42vw, 620px); aspect-ratio: 2 / 1; }
.watcher-md { width: clamp(220px, 26vw, 380px); aspect-ratio: 2 / 1; }
.watcher-sm { width: clamp(160px, 18vw, 260px); aspect-ratio: 2 / 1; opacity: 0.04; }

@keyframes drift {
  from { transform: translate3d(0, 0, 0) rotate(0deg); }
  to   { transform: translate3d(0, -22px, 0) rotate(1.2deg); }
}

/* The pupil holds a slow contraction, so the eye reads as alive rather than
   as a logo someone parked in the background. */
.watcher .pupil { transform-origin: 100px 100px; animation: iris 13s ease-in-out infinite; }
@keyframes iris {
  0%, 100% { transform: scale(1); }
  45%      { transform: scale(0.82); }
  55%      { transform: scale(0.82); }
}

/* Anything hosting a watcher needs a positioning context, and must clip it:
   an eye placed off-canvas would otherwise widen the document. Clipping also
   reads better - the eye emerges from beyond the frame rather than sitting in it. */
.watched { position: relative; overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .watcher { animation: none; }
  .watcher .pupil { animation: none; }
}
@media (max-width: 620px) {
  .watcher-md, .watcher-sm { display: none; }  /* one per viewport on a phone */
}

/* Command Deck nervous system - legibility pass */
.node circle { fill: #14141F; stroke: rgba(201,168,76,0.30); stroke-width: 1.25; }
.node text { fill: var(--text-2); font-weight: 700; }
.edge { stroke: rgba(201,168,76,0.26); stroke-width: 1.25; }
.node:hover circle, .node.lit circle { filter: drop-shadow(0 0 8px rgba(201,168,76,0.55)); }
/* ==========================================================================
   18. LEGAL + LONG-FORM PROSE
   Terms, privacy, and the story page. These drifted because each one carried
   its own stylesheet; the system owns the pattern now so the next one cannot.
   Measure is capped for reading, not for layout - a policy nobody can read is
   a policy nobody consented to.
   ========================================================================== */
.legal { max-width: 760px; margin: 0 auto; padding: calc(var(--topbar) + var(--s8)) var(--s5) var(--s9); }
.legal-narrow { max-width: 660px; }

.legal h1 { margin-bottom: var(--s3); }
.legal h2 {
  font-size: clamp(22px, 2.0vw, 32px); font-weight: 500;
  line-height: 1.2; letter-spacing: -0.014em;
  margin-bottom: var(--s4);
}
.legal h3 {
  font-family: var(--font-body);
  font-size: 16px; font-weight: 600; letter-spacing: 0.02em;
  color: var(--text); margin: var(--s5) 0 var(--s3);
}

.legal p { color: var(--text-2); margin-bottom: var(--s4); font-size: 16px; line-height: 1.75; }
.legal p:last-child { margin-bottom: 0; }
.legal strong { color: var(--text); font-weight: 500; }
.legal em { font-style: italic; }

.legal ul { margin: 0 0 var(--s4); }
.legal li {
  position: relative; padding: 0 0 var(--s3) var(--s5);
  color: var(--text-2); font-size: 16px; line-height: 1.7;
}
.legal li::before {
  content: ''; position: absolute; left: var(--s2); top: 12px;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--gold); opacity: 0.4;
}
.legal li:last-child { padding-bottom: 0; }

.legal a:not(.btn) { color: var(--gold); border-bottom: 1px solid var(--gold-25); }
.legal a:not(.btn):hover { border-bottom-color: var(--gold); }

/* .table-scroll bleeds -24px to cancel a card's padding. Legal prose has no
   card and a 16px gutter on a phone, so the bleed becomes 8px of horizontal
   overflow on each side. A document's table scrolls inside the measure. */
.legal .table-scroll { margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0; }

/* The section marker is a document coordinate, not a voice - instrument text. */
.legal-num {
  display: block;
  font-family: var(--font-mono); font-size: 11px; font-weight: 500;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--gold); opacity: 0.7;
  margin-bottom: var(--s2);
}
.legal-sec { padding-top: var(--s8); }
.legal-sec + .legal-sec { border-top: 1px solid var(--line-soft); }
.legal-date {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.08em;
  color: var(--text-3); margin-bottom: var(--s7);
}
.legal-intro { font-size: 18px; line-height: 1.8; color: var(--text-2); }

.back-link {
  display: inline-flex; align-items: center; gap: var(--s2);
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-3); margin-bottom: var(--s7);
  transition: color var(--t-fast);
}
.back-link:hover { color: var(--gold); }
.back-link svg { width: 13px; height: 13px; flex: none; }

/* Long-form story: wider leading, gold pull quotes in the brand's own face. */
.story p { font-size: 18px; line-height: 1.8; }
.pull {
  font-family: var(--font-display);
  font-weight: 450; font-size: clamp(22px, 2.0vw, 32px);
  line-height: 1.35; letter-spacing: -0.014em;
  color: var(--gold);
  margin: var(--s7) 0;
  padding-left: var(--s5);
  border-left: 2px solid var(--gold-25);
}
.breath { height: var(--s7); }

@media (max-width: 620px) {
  .legal { padding: calc(var(--topbar) + var(--s6)) var(--s4) var(--s8); }
  .legal p, .legal li { font-size: 16px; }
  .story p { font-size: 16px; }
  .legal-sec { padding-top: var(--s7); }
}

/* ==========================================================================
   19. AUTH
   Sign in, forgot password, reset password, welcome. These four are one
   surface a customer walks through in sequence, so they share one shape.
   Lifted verbatim out of portal-login.html, which was the only page that had
   it - a pattern living inside one page is how the last drift started.
   ========================================================================== */
.auth { width: 100%; max-width: 420px; }
.auth-page { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: var(--s5); }
.auth-mark { width: 44px; height: 44px; margin: 0 auto 28px; display: block; }
/* The mark is the only way back to the site from a checkout page, so it is a
   link. The anchor carries the layout; the svg inside stops carrying it. */
.auth-mark-link { display: block; width: 44px; margin: 0 auto 28px; }
.auth-mark-link .auth-mark { margin: 0; transition: opacity var(--t-fast); }
.auth-mark-link:hover .auth-mark { opacity: 0.82; }
.auth h1 { font-size: clamp(22px, 2.0vw, 32px); font-weight: 600; text-align: center; letter-spacing: -0.01em; margin-bottom: var(--s2); }
.auth-sub { text-align: center; color: var(--text-2); font-size: 16px; margin-bottom: 36px; }
.auth-card {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 32px 28px 28px;
  box-shadow: var(--lift-2);
}
.auth-card h2 { font-size: 20px; font-weight: 500; margin-bottom: var(--s2); }
.auth-foot { text-align: center; margin-top: var(--s5); font-size: 14px; color: var(--text-3); }
.auth-foot a { color: var(--text-2); }
.auth-foot a:hover { color: var(--gold); }
.auth-legal { text-align: center; margin-top: var(--s6); font-size: 12px; color: var(--text-3); line-height: 1.7; }
.hint { font-size: 12px; line-height: 1.5; color: var(--text-3); margin-top: 6px; }

.shake { animation: shake 0.3s ease; }
@keyframes shake { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-2px); } 75% { transform: translateX(2px); } }

/* The success half of the notice family. .notice already had err/warn/gold;
   a form that can only report failure is not a finished form. */
.notice-ok { border-left-color: var(--ok); }

/* ── 20. SCROLL-DRIVEN MOTION ─────────────────────────────────────────────
   §14 and §17 stay the baseline and the fallback. Where the browser has
   view() timelines, the same classes are driven by scroll position rather
   than by a class flip: smoother, no observer, and correct when the browser
   restores a scroll position on back-navigation.

   The base state here is VISIBLE. The hidden state lives only inside the
   keyframe, reached through animation-fill-mode: both. This matters more
   than it looks. A view() timeline resolves against the nearest scroll
   container, and overflow:hidden makes an element one — .watched (:969)
   and .khero both are, and they wrap the index hero. Their timelines are
   inert. Had the base state been opacity:0, that hero would be blank
   forever. Content is never hidden by a feature that failed to run.
   ────────────────────────────────────────────────────────────────────── */

/* The native view() timeline path that lived here has been RETIRED.

   Lenis writes the scroll position once per rAF on the main thread. A
   view() timeline reading that value is main-thread-gated, one frame late,
   and desynced from every GSAP tween on the page — the two mechanisms do
   not compose, you pick one. We picked GSAP + Lenis, because pinning,
   scrubbing and SplitText's auto-resplit are worth more than compositor
   reveals, and because it is what the sites we are measuring against ship.

   Nothing is orphaned by this: .reveal/.arrive fall back to the
   IntersectionObserver path in aq.js (AQ.reveal :307, AQ.arrive :791),
   which is what already runs on every page today. Where AQ.split() runs,
   ScrollTrigger supersedes it.

   @keyframes aq-rise is kept below — AQ.deck() and the hero timeline use it. */

@keyframes aq-rise {
  from { opacity: 0; transform: translate3d(0, 26px, 0); }
  to   { opacity: 1; transform: none; }
}

/* The progress bar animated `width` on every scroll event: layout and paint
   once per frame, on the main thread. scaleX composites, and where scroll()
   exists it needs no listener at all. AQ.scrollProgress() feature-detects
   and skips attaching the listener when this branch is live. */
.scroll-progress {
  width: 100%;
  transform: scaleX(var(--p, 0));
  transform-origin: 0 50%;
  transition: none;
  will-change: transform;
}
@supports (animation-timeline: scroll()) {
  .scroll-progress {
    animation: aq-progress linear both;
    animation-timeline: scroll(root);
  }
}
@keyframes aq-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }


/* ── 21. VIEW TRANSITIONS ─────────────────────────────────────────────────
   Moving between pages should read as one surface changing, not as a
   sequence of separate documents. This is a multi-page site, so it is the
   cross-document form: no router, no JS, one at-rule.

   view-transition-name must be UNIQUE per document. .nav-logo appears
   twice on every marketing page — once in the nav, once in the footer — so
   it is scoped to .nav here. An unscoped name would silently abort every
   transition on the site, with no error anywhere.

   Chrome/Edge 126+, Safari 18.2+. Firefox navigates exactly as it does
   today; there is no fallback to write.
   ────────────────────────────────────────────────────────────────────── */

@view-transition { navigation: auto; }

.nav .nav-logo { view-transition-name: aq-mark; }
.nav           { view-transition-name: aq-nav; }

/* The nav is fixed and identical across pages. Naming it keeps it out of
   the root snapshot so it holds still while the page beneath it changes. */
::view-transition-old(aq-nav),
::view-transition-new(aq-nav) { animation: none; mix-blend-mode: normal; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 260ms;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  animation-fill-mode: both;
}
::view-transition-old(root) { animation-name: aq-vt-out; }
::view-transition-new(root) { animation-name: aq-vt-in; }

@keyframes aq-vt-out { to   { opacity: 0; transform: translate3d(0, -10px, 0); } }
@keyframes aq-vt-in  { from { opacity: 0; transform: translate3d(0,  12px, 0); } }


/* ── 22. SURFACES ─────────────────────────────────────────────────────────
   Depth on a dark surface comes from edges catching light, not from blur.
   Nothing here uses filter: blur() — it is the most expensive thing you can
   paint across a full viewport, and it is also what makes a page look like
   every other page shipped this year. Gradients are already soft.

   Composition with what exists: body::before (:118) owns the fixed ambient
   halo, and .cosmos adds .lamp and .cosmos::after. That is already three
   full-viewport fixed layers. Nothing below adds a fourth — each is a
   section-local ::before at z-index -1 inside an isolation context, so it
   stacks above its own section's background and below its content.

   Named .bg-* deliberately: .field is already the form-row class in §9.
   ────────────────────────────────────────────────────────────────────── */

:root {
  /* Sized explicitly so it rasterises once at 120x120 and tiles. An unsized
     SVG background rasterises the turbulence filter at the size of its box
     and re-runs on every resize. */
  --noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

.bg-layer { position: relative; isolation: isolate; }
.bg-layer::before {
  content: '';
  position: absolute; inset: 0;
  z-index: -1;
  pointer-events: none;
}

/* A grid that runs edge to edge is a wireframe. A grid that dissolves is a
   room. The mask is the whole point. */
.bg-grid::before {
  background-image:
    linear-gradient(to right,  rgba(201,168,76,0.10) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(201,168,76,0.10) 1px, transparent 1px);
  background-size: 68px 68px;
  -webkit-mask-image: radial-gradient(ellipse 78% 72% at 50% 0%, #000 0%, rgba(0,0,0,0.55) 48%, transparent 84%);
          mask-image: radial-gradient(ellipse 78% 72% at 50% 0%, #000 0%, rgba(0,0,0,0.55) 48%, transparent 84%);
}

.bg-dots::before {
  background-image: radial-gradient(circle at 1px 1px, rgba(201,168,76,0.28) 1px, transparent 0);
  background-size: 24px 24px;
  -webkit-mask-image: radial-gradient(ellipse 70% 76% at 50% 28%, #000 0%, rgba(0,0,0,0.5) 52%, transparent 86%);
          mask-image: radial-gradient(ellipse 70% 76% at 50% 28%, #000 0%, rgba(0,0,0,0.5) 52%, transparent 86%);
}

/* Aurora in one hue. Two gold sources and one cool sink. A third colour is
   the exact point where this stops being ours and becomes a stock gradient. */
.bg-aurora::before {
  background-image:
    radial-gradient(46% 52% at 14% 6%,   rgba(201,168,76,0.26),  transparent 68%),
    radial-gradient(38% 46% at 86%  0%,  rgba(201,168,76,0.15),  transparent 70%),
    radial-gradient(34% 40% at 62% 88%,  rgba(201,168,76,0.075), transparent 72%),
    radial-gradient(80% 60% at 50% 112%, rgba(36,31,26,0.92),    transparent 74%);
}

.bg-grain::before {
  background-image: var(--noise);
  background-size: 120px 120px;
  opacity: 0.14;
  mix-blend-mode: overlay;
}

/* ── PAPER ────────────────────────────────────────────────────────────────
   A flat fill reads as paint; a surface with tooth reads as material. One
   fixed grain layer over the whole document does for our charcoal what stock
   paper texture does for Anthropic's off-white, at zero bytes: it reuses the
   --noise data URI from the tokens.

   Fixed rather than scrolling, so the grain belongs to the screen and not to
   the content. pointer-events: none so it can never eat a click. Kept at 0.03
   because grain you can consciously see is a filter, and grain you cannot is
   a surface. */
body::after {
  content: '';
  position: fixed; inset: 0;
  z-index: 9999;
  pointer-events: none;
  background-image: var(--noise);
  background-size: 140px 140px;
  /* Plain alpha, no blend mode. A fixed full-viewport mix-blend-mode layer
     forces the compositor to re-blend the whole screen every scrolled frame;
     measured 2026-08-06 at 1440x2 it was ~6fps of scroll cost and the single
     largest jank source after the WebGL field. Normal-blend grain at 0.02
     keeps the tooth for a fraction of the price. */
  opacity: 0.02;
}
/* A phone renders this over a much smaller area for the same cost, and mobile
   GPUs pay for full-screen blend modes. Off below the tablet breakpoint. */
@media (max-width: 860px) { body::after { display: none; } }

/* Depth without a starfield: one hairline of caught light along the top
   edge, one shadow beneath it. That is the entire trick. */
.surface {
  background: linear-gradient(180deg, rgba(255,255,255,0.038), rgba(255,255,255,0) 140px), var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.05), var(--lift-1);
}
.surface-sunken {
  background: linear-gradient(180deg, rgba(0,0,0,0.35), rgba(0,0,0,0) 90px), var(--bg);
  box-shadow: inset 0 1px 3px rgba(0,0,0,0.5), inset 0 -1px 0 rgba(255,255,255,0.035);
}

/* Conic belongs on a rim, never in a blob. */
.rim-gold {
  border: 1px solid transparent;
  background:
    linear-gradient(var(--bg-2), var(--bg-2)) padding-box,
    conic-gradient(from 210deg at 50% 50%, var(--gold-3), var(--gold) 22%, var(--gold-3) 46%, var(--line) 62%, var(--gold-3)) border-box;
}

/* The same rim, turning. One element per page at most - this is the thing
   the eye lands on, and a second one would make it a carousel. The angle is
   an @property so it interpolates instead of snapping. */
.rim-live {
  border: 1px solid transparent;
  background:
    linear-gradient(var(--bg-2), var(--bg-2)) padding-box,
    conic-gradient(from var(--aq-angle) at 50% 50%,
      transparent 0%, var(--gold-3) 12%, var(--gold-hover) 25%, var(--gold-3) 38%,
      transparent 52%, var(--gold-3) 68%, var(--gold) 80%, var(--gold-3) 90%, transparent 100%) border-box;
}
@media (prefers-reduced-motion: no-preference) {
  .rim-live { animation: aq-edge 7s linear infinite; }
}

/* .cosmos::after is inset:-50% — a 200vw x 200vh blended layer with an
   unsized SVG behind it. Nothing animates it, so the oversize buys nothing
   and costs a full-page composite plus a re-raster on every resize. Same
   appearance, about one sixteenth of the raster area. */
.cosmos::after {
  inset: 0;
  background-image: var(--noise);
  background-size: 120px 120px;
}

/* The global grid was retired 2026-08-06 in the calm pass: both reference
   sites keep running copy on flat ground, and a faint engineering grid on
   every screen is exactly the generic-AI-page tell this site avoids. The
   ambient gold halo at :189 remains the only fixed layer. */


/* ── 23. CONTROLS ─────────────────────────────────────────────────────────
   Additive to §8, and now almost empty — deliberately. The sheen sweep,
   the animated gradient rim, the pointer magnet and the press-scale were
   removed 2026-08-06 after reading both parents' shipped CSS: across the
   whole of apple.com and anthropic.com not one interactive element moves,
   glows, sweeps or shrinks. Hover answers in colour; the cursor is enough.
   .btn-edge and .btn-magnet remain valid class names in old markup and
   simply render as their base variants.

   @property survives because .rim-live (§22) still turns its angle. */

@property --aq-angle { syntax: '<angle>'; inherits: false; initial-value: 120deg; }
@keyframes aq-edge { to { --aq-angle: 480deg; } }

/* The ring at :146 is rgba(201,168,76,0.30), which composites to #433921 on
   --bg: 1.74:1. WCAG 2.2 SC 1.4.11 requires 3:1, so the focus indicator on
   this site currently fails. Solid gold on --bg is 8.66:1, and the inner
   --bg ring gives that same separation when the indicator lands on a gold
   button. The transparent outline is the ring Windows High Contrast sees —
   box-shadow is dropped in forced-colors mode, so without it there is none. */
:focus-visible {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--gold);
  outline: 2px solid transparent;
  outline-offset: 2px;
}
.btn-gold:focus-visible { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--gold-hover); }
.input:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible {
  box-shadow: 0 0 0 1px var(--gold), 0 0 0 4px var(--gold-20);
}


/* ── 24. CARD FIELD ───────────────────────────────────────────────────────
   Additive to §7. The spotlight is driven by two custom properties written
   by ONE delegated listener on document (AQ.pointer), not one listener per
   card — a twelve-card grid would otherwise mean twelve handlers firing on
   every mouse move.
   ────────────────────────────────────────────────────────────────────── */

.card-spot { position: relative; isolation: isolate; }
.card-spot::before {
  content: '';
  position: absolute; inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 0%), rgba(201,168,76,0.30), rgba(201,168,76,0.07) 40%, transparent 68%);
  opacity: 0;
  transition: opacity var(--t-card);
}
@media (hover: hover) and (pointer: fine) {
  .card-spot:hover::before { opacity: 1; }
}

.card-edge { transition: background var(--t-card), border-color var(--t-card); }
.card-edge:hover {
  border-color: transparent;
  background:
    linear-gradient(var(--bg-2), var(--bg-2)) padding-box,
    linear-gradient(120deg, var(--gold-25), var(--line) 44%, var(--gold-20)) border-box;
}

/* Capped at 2.5deg — the amount you feel and do not see. Past that it stops
   reading as depth and starts reading as a widget. The hover lift that used
   to ride alongside it is gone with the rest of the hover motion. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .card-tilt {
    transform: perspective(900px) rotateX(var(--aq-rx, 0deg)) rotateY(var(--aq-ry, 0deg));
    transition: transform var(--t-card);
  }
}


/* ── 25. TYPE MOVES ───────────────────────────────────────────────────── */

h1, h2, h3, h4, .h1, .h2, .h3, .h4,
.pull, .empty h4, .notice h4 { text-wrap: balance; }

p, .lede, .legal p, .story p, .band p, .legal li { text-wrap: pretty; }

/* Machine register gets machine alignment. §4 covers .mono, .stat-value and
   .readout dd; these were missed. */
.feed-time, .legal-date, .badge, kbd, td, .waypoint b { font-variant-numeric: tabular-nums; }

/* Gold at the terminal stop is 8.66:1 on --bg and the light stop is --text.
   Never run this into --gold-3 (3.74:1) below display sizes — legal for
   large text, illegal for anything else. */
.text-gild {
  background-image: linear-gradient(96deg, var(--text) 6%, var(--gold-hover) 52%, var(--gold-2) 94%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.text-gild::selection { -webkit-text-fill-color: var(--text); background: var(--gold-25); }
@media (forced-colors: active) {
  .text-gild { background-image: none; color: CanvasText; -webkit-text-fill-color: currentColor; }
}




/* ── 26. STAGE — WEBGL, SPLIT TEXT, 3D DECK ───────────────────────────────
   The heavy layer. Everything here is opt-in per page and every piece has a
   no-JS / no-GPU / reduced-motion resting state that looks deliberate rather
   than broken.
   ────────────────────────────────────────────────────────────────────── */

/* --- The gold canvas ------------------------------------------------------
   Two traps this rule exists to beat: `body > * { position: relative;
   z-index: 1 }` at :126, and `.cosmos > main { z-index: 1 }` at :792. Both
   would drag the canvas into the content layer. Explicit fixed + -1 wins.

   The poster paints first and is never removed — it is the LCP-safe base,
   the reduced-motion state, the mobile state, and the WebGL-failure state,
   all at once. The canvas fades in over it only once a frame has drawn. */
.gold-stage {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  background:
    radial-gradient(58% 48% at 18% 8%,  rgba(201,168,76,0.30), transparent 66%),
    radial-gradient(44% 40% at 82% 2%,  rgba(201,168,76,0.16), transparent 70%),
    radial-gradient(70% 55% at 50% 104%, rgba(10,10,15,0.96),  transparent 72%),
    var(--bg);
}
body > .gold-stage { position: fixed; z-index: -1; }

.gold-stage canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 1.1s ease;
}
.gold-stage.lit canvas { opacity: 1; }

/* A hairline of light where the stage meets the page, and a vignette so the
   corners fall away instead of ending. */
.gold-stage::after {
  content: '';
  position: absolute; inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 35%, transparent 42%, rgba(10,10,15,0.55) 78%, rgba(10,10,15,0.9) 100%);
}

/* --- Split text -----------------------------------------------------------
   SplitText with mask:"lines" generates the clip wrapper; these rules give
   the lines somewhere to travel from. The resting state is VISIBLE, so a
   page whose JS never runs shows finished text rather than nothing. */
.split-line { display: block; }
.js-split .split-mask { overflow: clip; display: block; }
.js-split .split-line { will-change: transform; }

/* --- 3D deck --------------------------------------------------------------
   Perspective belongs on the stage, never on the card, and never animated —
   animating perspective repaints the entire subtree. Only rotate/translateZ
   are scrubbed, and both composite. */
.deck-stage {
  perspective: 1400px;
  perspective-origin: 50% 45%;
}
.deck {
  transform-style: preserve-3d;
  will-change: transform;
}
.deck > * { transform-style: preserve-3d; }

/* Depth tiers for the agent grid. Set as a custom property so JS scrubs one
   value and CSS does the composition. */
.deck-card {
  transform: translate3d(0, 0, calc(var(--z, 0) * 1px)) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: box-shadow var(--t-card), border-color var(--t-card);
}

/* --- Scroll velocity --------------------------------------------------------
   AQ.smooth() republishes Lenis' velocity here. Used for the speed-reactive
   gold rule under section headings. */
.velo-rule {
  height: 1px;
  background: linear-gradient(90deg, var(--gold), var(--gold-3) 40%, transparent);
  transform: scaleX(clamp(0.12, calc(0.12 + var(--velo, 0) * 0.9), 1));
  transform-origin: 0 50%;
  transition: transform var(--t-slow);
}

/* --- Footer taxonomy ------------------------------------------------------
   Columns, stamped by scripts/site-chrome.js — the footer is a map of the
   company, not a strip of links. Column heads are captions; links are the
   standard dim body-sm. */
.foot-cols {
  /* Flex, not grid: inside the footer's shrink-to-fit flex row, auto-fit
     grid tracks have no definite width to fill and collapse to one column. */
  display: flex;
  flex-wrap: wrap;
  gap: var(--s6) var(--s8);
  align-items: flex-start;
}
.foot-cols > div { display: flex; flex-direction: column; gap: 10px; min-width: 96px; }
.foot-cols .caption { color: var(--text-3); margin-bottom: 2px; }
@media (max-width: 620px) {
  .foot-cols { gap: var(--s6) var(--s7); }
}

@media (prefers-reduced-motion: reduce) {
  .gold-stage canvas { display: none; }
  .deck-card { transform: none; }
  .velo-rule { transform: scaleX(1); }
  .js-split .split-line { transform: none !important; opacity: 1 !important; }
}

/* ── 27. REDUCED MOTION + FORCED COLORS — KEEP THIS LAST IN THE FILE ──────
   The global block at :181 neutralises DURATIONS only. It does not reset
   opacity, transform, translate, scale or animation-name, and its `*`
   selector cannot reach ::view-transition-* pseudo-elements at all — they
   live in a separate pseudo tree. Anything that starts hidden must be
   un-hidden here, by name, or it stays hidden forever.

   No !important is needed except on the view-transition tree: :181 sets
   only animation-duration, animation-iteration-count, transition-duration
   and scroll-behavior, and nothing below touches those four.
   ────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {

  /* §14 never had a reset. It survives today only because AQ.reveal()
     always lands .in, including via its 3s failsafe — which means content
     visibility depends on JS running, the one thing §14 set out to avoid. */
  .js-reveal .reveal { opacity: 1; transform: none; }

  /* §20 */
  .js-reveal .reveal,
  .js-reveal .arrive { animation-name: none; opacity: 1; transform: none; }
  .scroll-progress   { animation-name: none; transform: scaleX(var(--p, 0)); }

  /* §21 — unreachable from :181, and the UA supplies its own cross-fade,
     so this is the one place !important is load-bearing. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
  ::view-transition-new(*) { opacity: 1; }

  /* §23 is colour-only now; nothing there moves, so nothing needs resetting. */

  /* §24 — a gradient that chases the cursor reads as motion even though it
     is technically a hover state. */
  .card-spot::before { display: none; }
  .card-tilt { transform: none; }
}

@media (forced-colors: active) {
  .bg-layer::before, .card-spot::before { display: none; }
  .rim-gold, .rim-live, .card-edge:hover { background: Canvas; border-color: ButtonBorder; }
  .scroll-progress { background: Highlight; }
}
