/* ═══════════════════════════════════════════════════════════════════
   STRUCTURAL COLOR — Aaron Sleeper personal-brand primitive library
   LOCAL / staging. The single source of truth for the brand's stable
   primitives (tokens · type · toggle · gradient-ring · panel · chrome).
   Novel/moving bits (raven, flight animation) live in brand.js + page markup.
   Themes: Aurora (dark, default) · Feather (light).
   ═══════════════════════════════════════════════════════════════════ */

@property --sa { syntax: "<angle>"; inherits: false; initial-value: 120deg; }
@property --sb { syntax: "<angle>"; inherits: false; initial-value: 120deg; }

:root {
  /* interference ramp — DARK (Aurora) */
  --c1:#F06BB7; --c2:#8F6CF0; --c3:#5E7CFF; --c4:#3FC6E0; --c5:#3EDBA8;
  /* ground ramp — depth by plane, never shadow: inset < ground < surface < raised */
  --ground:#0F0D13; --surface:#15121B; --raised:#1C1826; --inset:#0A090E;
  /* field-engine dark albedo floor — deep blue-violet, super-dark: makes magenta/teal pop by contrast
     ("colorless without being colorless"). spike-07 look-insight; Brand to ratify the exact tint + the
     anti-space-purple guard (must stay a super-dark FLOOR, never a purple field = reject #9). */
  --base-tint:#181B40;
  --ink:#EDEBF2; --ink-2:#C3BED0; --muted:#9B96A8; --hairline:#2A2536;
  /* --ink-2: lifted secondary ink for small labels that muted leaves under-legible */
  /* ── INK RAMP, stops 4 + 5 — CANDIDATE, pending Aaron's final hex (his production role, like --pr-*).
     --muted-2: the 4th LEGIBLE rung. Authored per-theme (NOT a color-mix) because its target is a
     CONTRAST RATIO, and a fixed mix % does not hold a ratio across two grounds — the same 86% mix
     lands 5.03:1 on Aurora and 4.51:1 on Feather. See operator-district/ink-ramp-4th-rung.md §3.
     Carries "present but below the reader's current altitude / focus": recessive and still READ.
     AA (>=4.5:1) on every plane it is permitted on — verified 2026-07-29: ground 5.03 / surface 4.82
     / raised 4.53 (Aurora), ground 4.51 / surface 4.84 / raised 5.05 (Feather).
     Hue + chroma held to --muted's family: an ink stop never separates on chroma (hue is spent on data).
     --ink-faint: the 5th stop, DERIVED (brand's own color-mix idiom), SUB-AA BY DESIGN and therefore
     DECORATIVE / DISABLED ONLY — never load-bearing text. The name deliberately BREAKS the -2 grammar:
     it is not another rung of the same kind, and the grammar break is the signal. Derived from --muted
     so it tracks any retune of it. Gate: no element with a semantic role resolves to --ink-faint. */
  --muted-2:#848090;
  --ink-faint:color-mix(in oklab,var(--muted) 55%,var(--ground));
  /* ── SELECTION — RATIFIED 2026-07-31 against a render (walk D1). Aaron's value, his production role.
     TOKENIZED from the rule that had been inline at ::selection since the beginning. The rule was fine;
     the fact that it was ONLY a rule was not. A <link> carries rules; a vendored :root carries VALUES —
     so site/, museum/, field/ and proof-surface/ inherited ::selection for free while obsidian-theme,
     vscode-theme and the operator surface, which hand-carry a token block, inherited NOTHING and
     rendered the browser default. That is I11 one layer deeper than drift: a failure no --check could
     ever catch, because there is nothing to compare. A token can be emitted by a generator; a rule cannot.
     TWO FLOORS, and the old 34% only ever met one of them:
       --select-ink on the fill  >= 4.5:1  (selected text stays readable)   — 34% met this at ~10:1
       the fill vs --ground      >= 3:1    (1.4.11: selection reads as a STATE) — 34% was 1.58:1
     72% clears both in both themes, MEASURED IN A REAL COMPOSITOR (not modelled):
       Aurora  #6B51B2  separation 3.17:1  text 5.16:1
       Feather #907DE1  separation 3.02:1  text 5.37:1
     DERIVED, not authored-per-theme — deliberately, and unlike --muted-2 above. This token's target is
     contrast FROM the ground it mixes with, where fraction and ground move together, so one fraction
     holds the ratio across both themes (measured within 0.02). --muted-2's target moves the other way,
     which is exactly why IT had to be authored twice. Same idiom, opposite reason.
     Probe: operator-district/selection-fill-probe/ — both themes, four fractions, live drag regions. */
  --select-fill:color-mix(in oklab,var(--c2) 72%,transparent);
  /* --select-ink looks like indirection without information and is not, for one reason: the three
     vendoring consumers cannot inherit the RULE, so they must re-author it, and a re-authored rule
     reaching for --ink directly re-spells the pairing instead of referencing it. The token is what makes
     the pair syncable AS A PAIR. If a future topology has every surface link this sheet, retire it. */
  --select-ink:var(--ink);
  /* ── SCROLLBAR — CANDIDATE values, RATIFIED mechanism (walk D6). STANDARD PROPERTIES ONLY, and the
     reason is layout rather than taste: ::-webkit-scrollbar{width} converts a macOS overlay scrollbar
     into a classic one that takes layout space, silently subtracting from measures the operator surface
     asserts as CONTRACTUAL. So the finer instrument is the one with the side effect, and coarse is the
     correct resolution for chrome anyway — the ramp is rationed and never fills chrome (thesis #1).
     Thumb is ink-family, NEVER accent: --c2 already has four consumers. */
  --scrollbar-thumb:color-mix(in oklab,var(--ink) 22%,transparent);
  --scrollbar-thumb-hover:color-mix(in oklab,var(--ink) 38%,transparent);
  --scrollbar-track:transparent;
  /* semantics — flat, never iridescent (Aurora values: brighter, read on dark) */
  --success:#3BC98A; --warn:#E8A93C; --error:#F0616B;
  /* ── PROOF DISTRICT (pr-) token group — CANDIDATE, pending Aaron's final hex (his production role).
     Authored HERE once (source-of-truth invariant); proof.css composes only var(--pr-*), zero hex.
     Method: dataviz palette (sequential=confidence · diverging=for/against · muted marks · WCAG-first).
     BID-Corvus direction: cool single-hue confidence ramp reads "measured/known"; for/against are two
     STRUCTURAL hues in tension (teal↔mauve), never good/bad / green↔red; K grounded-lit, U quiet-hollow. */
  /* sequential — confidence (low→high; low recedes toward paper "not-yet-proven", high earns .ring) */
  --pr-conf-1:#4A5170; --pr-conf-2:#515C87; --pr-conf-3:#586BA4; --pr-conf-4:#6183CE; --pr-conf-5:#7AA0FF;
  /* diverging — for/against margin (neutral midpoint = the paper's own ground = absence) */
  --pr-for:#48A6B4; --pr-against:#C77BAF;
  /* KIU evidence tiers — honesty encoded in weight (K grounded, I reasoned, U hollow/open) */
  --pr-tier-k:#4AC79A; --pr-tier-i:#7AA0FF; --pr-tier-u:#BFA06A;
  --ease:cubic-bezier(.3,0,0,1);
  /* ── DIMENSIONAL FOUNDATION (--text/space/radius/leading/track) — CANDIDATE, values pending Aaron's
     tuning (his production role, like the --pr-* hexes). Theme-INVARIANT → defined here at ONE altitude,
     never duplicated into [data-theme="feather"] (size/space/radius don't change between themes).
     Derived from the ~237 raw values already in use (ds-foundation-assessment §4): a codify-not-redesign
     rationalization that snaps ad-hoc values to a scale, not a new look. Consume via var(); never re-guess. */
  /* type scale — modular minor-third 1.2, 18px anchor. READING-COMFORT BUMP (2026-07-25, ratified):
     anchor moved 16→18px — Instrument Sans's moderate x-height (~.50 em) reads a step under its set size,
     so 18px reads generous-not-oversized and answers the felt "runs small". Reading core (mono→h3) rides
     full 1.2 grid steps from the 18px body. --text-micro is KEPT as a DELIBERATE FLOORED token at ~11px
     (off the strict −3 step's 10.42px; held legible the way --radius-pill is a deliberate non-ratio
     extreme) — its fine-mono-label tier stays pointed here, NOT retired. --text-mono is the rail/folio
     identity signature at 12.5px. h2/display FLOORS re-floored so the bumped h3 (31.1px) never exceeds h2
     (anti-inversion); caps held (no display balloon — the mono rail stays load-bearing). CANDIDATE — Aaron
     tunes like --pr-*. Derivation of record: proof-surface/scale-function-token-derivation.md +
     proof-surface/type-scale-bump-proposal.md */
  --text-micro:.69rem; --text-mono:.78rem; --text-small:.94rem;
  --text-body:1.125rem; --text-body-lg:1.35rem; --text-lede:1.62rem; --text-h3:1.944rem;
  --text-h2:clamp(2.1rem,4.6vw,3.4rem); --text-display:clamp(3rem,7vw,6rem);
  /* leading (line-height) + tracking (letter-spacing) — paired scales for the type roles */
  --leading-display:1; --leading-tight:1.15; --leading-snug:1.22; --leading-body:1.45; --leading-relaxed:1.6; --leading-loose:1.75;
  --track-display:-.035em; --track-tight:-.02em; --track-normal:0; --track-wide:.02em;
  --track-mono:.06em; --track-caps:.1em; --track-caps-lg:.14em; --track-caps-xl:.2em;
  /* spacing — 4px base (the grid Corvus documents in comments but never tokenized); consumed by name */
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px; --space-5:20px;
  --space-6:24px; --space-8:32px; --space-10:40px; --space-12:48px; --space-16:64px;
  /* the two fluid rhythms, named once (section vertical rhythm · page gutter) — were re-clamped per file */
  --space-section:clamp(72px,12vh,128px); --space-gutter:clamp(22px,5vw,72px);
  /* radius — curated-geometric (ratified): ~1.5× guided low, gently decelerating (1.5·1.5·1.44·1.23),
     envelope-preserving (top=16, no corner-drama); pill UNIFIED (retires the 100px/999px split → one token) */
  --radius-xs:4px; --radius-sm:6px; --radius-md:9px; --radius-lg:13px; --radius-panel:16px; --radius-pill:999px;
  /* measure (line length) — I10 tier, landed 2026-07-28. The reading-comfort axis the 2026-07-25
     foundation pass never enumerated: measure was enforced by EIGHT hand-set `ch` literals scattered
     across brand.css + proof.css + one page's inline <style> (34/44/46/52/56/72/74ch), with no token
     and therefore no coverage guarantee — so a primitive authored without one simply had none, and
     .pr-claim-defeat shipped five lines of narrative prose at 122ch (Space Mono, 12.5px, no cap).
     Theme-INVARIANT → :root only, same one-altitude rule as --text/space/radius/font.
     SCALE FUNCTION IS CURATED-EMPIRICAL, NOT MODULAR — deliberate, and the reason is not aesthetic:
     measure is bounded by an EMPIRICAL reading band (45–75ch), not by perceived proportion, so a
     ratio would generate steps outside the band and dress an arbitrary choice as a system. Three
     curated steps, each pinned to a reading fact, is the honest shape (Typography Craft, `measure`).
     UNIT IS ch, NEVER px — ch scales with the font, so these caps survive any future --text-* bump
     unchanged (the 2026-07-25 bump already proved this: the ch-bound roles held, the uncapped ones
     did not). CANDIDATE — Aaron tunes like --pr-*. Derivation: proof-surface/feedback-ds-obligations.md */
  --measure-tight:34ch; --measure-lede:46ch; --measure-prose:66ch;
  /* NOT a measure axis, deliberately excluded: display BALANCE caps (h1 16ch, .h2 17ch, .catch 26ch)
     are a text-wrap:balance companion for 2–3-word display lines — a different problem from reading
     measure, and folding them in would imply the 45–75ch band governs them. They stay authored raw
     and are named in verify.mjs's gate-5 allowlist so the exclusion is explicit, not an oversight. */
  /* ── FONT-FAMILY FOUNDATION (--font-*) — I10 tier, landed 2026-07-27. Theme-INVARIANT → :root only,
     never duplicated into [data-theme="feather"] (a family doesn't change between themes), same one-altitude
     rule as --text/space/radius. Each token carries its COMPLETE stack INCLUDING fallbacks, declared ONCE;
     selectors reference the token and never re-spell a family name. Repair of record: the four faces load
     from a Google Fonts CDN with font-display:swap, and the display/serif/mono declarations named the brand
     face with NO fallback at all — so a blocked/slow CDN dropped h1/.h2/.brandmark to the browser's DEFAULT
     SERIF (Times), i.e. a different brand rather than a degraded one. Stacks are measured, not guessed:
     fallbacks ordered by advance-width + x-height proximity to the brand face (fontTools over the real CDN
     binaries) and by weight-axis coverage — system-ui leads the sans stacks because .brandmark/h1/.btn ask
     for 600/700 and the variable system faces cover those continuously where Arial/Helvetica would
     synthesize. Derivation + per-face degraded-state bar: proof-surface/font-token-tier.md */
  --font-display:"Bricolage Grotesque",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-text:"Instrument Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-accent:"Instrument Serif",ui-serif,"Times New Roman",Times,Georgia,serif;
  --font-mono:"Space Mono",ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
  /* the one signature gradient, define-once */
  --ramp:linear-gradient(120deg,var(--c1),var(--c2),var(--c3),var(--c4),var(--c5));
  --ramp-loop:linear-gradient(var(--sa),var(--c1),var(--c2),var(--c3),var(--c4),var(--c5),var(--c1));
  /* --ramp-radial: adjacent radial gradients (Argyle heritage) — each hue radiates, so the
     midpoints stay vibrant instead of muddying through a linear interpolation. The DEFAULT for
     substantial color FIELDS; --ramp (linear) stays for hairlines/text-clip/bookmarks. */
  --ramp-radial:
    radial-gradient(ellipse 62% 150% at 2% 46%,  var(--c1), transparent 56%),
    radial-gradient(ellipse 56% 150% at 27% 54%, var(--c2), transparent 56%),
    radial-gradient(ellipse 56% 150% at 50% 44%, var(--c3), transparent 56%),
    radial-gradient(ellipse 56% 150% at 73% 56%, var(--c4), transparent 56%),
    radial-gradient(ellipse 64% 150% at 98% 48%, var(--c5), transparent 58%),
    var(--c3);
}
[data-theme="feather"] {
  /* interference ramp — LIGHT (Feather) */
  --c1:#C93B92; --c2:#6B4FD8; --c3:#3D5FE0; --c4:#0E7F9E; --c5:#0F8A64;
  /* pure white is reserved for raised — surface stays in the paper family (ruling 2026-07-16) */
  --ground:#F1F2F6; --surface:#FAFAFC; --raised:#FFFFFF; --inset:#E8E8EF;
  --ink:#17141F; --ink-2:#3D3A49; --muted:#5D5A6B; --hairline:#DDDDE6;
  /* INK RAMP stop 4 — CANDIDATE. Feather is NOT a mix-percentage twin of Aurora: the same 86% mix
     lands 5.03:1 on Aurora and 4.51:1 here, so the value is authored to the RATIO, not copied.
     Theme-parity (I10): --muted-2 is defined in both themes; --ink-faint needs no override because
     it derives from --muted and --ground, which are already themed. */
  --muted-2:#6F6D7D;
  /* --ink-faint is re-declared here rather than inherited. ink-ramp-4th-rung.md §2b argued it
     "needs no override because it derives from --muted and --ground, which are already themed" —
     true of how it RESOLVES, false of what theme-parity/light-co-equal checks, which is DECLARATION.
     The gate caught it on first run (2026-07-29). It is not `theme-invariant` either: it resolves to
     a different colour per theme, so marking it so would be a lie to satisfy a check. Same
     expression, declared in both blocks — the mix re-resolves against Feather's --muted/--ground. */
  --ink-faint:color-mix(in oklab,var(--muted) 55%,var(--ground));
  /* SELECTION + SCROLLBAR — same construction as --ink-faint directly above, and re-declared for the
     same reason: the expression is theme-neutral but the RESULT is not, so the parity gate wants both
     blocks and `theme-invariant` would be a lie told to satisfy a check. The mixes re-resolve against
     Feather's --c2 / --ink / --ground. Feather at 72%: fill #907DE1, separation 3.02:1, text 5.37:1 —
     measured in a real compositor, and it is the WORSE of the two themes, which is why 72% is the
     crossing rather than a round number. See :root for the two-floor rationale. */
  --select-fill:color-mix(in oklab,var(--c2) 72%,transparent);
  --select-ink:var(--ink);
  --scrollbar-thumb:color-mix(in oklab,var(--ink) 22%,transparent);
  --scrollbar-thumb-hover:color-mix(in oklab,var(--ink) 38%,transparent);
  --scrollbar-track:transparent;
  /* --warn darkened #C7871A→#8A5A0F for the WCAG AA floor: it is TEXT in .pr-against--empty on paper
     (was 2.49:1, now 4.85:1 vs --inset) and the .pr-claim-defeat border (was 2.92:1 <3, now 5.67:1).
     Feather-only; Aurora --warn stays bright (passes 8.97:1). CANDIDATE amber — Aaron may retune ≥AA. */
  --success:#2E9E6B; --warn:#8A5A0F; --error:#D93843;
  /* PROOF DISTRICT (pr-) — CANDIDATE, pending Aaron's final hex. Feather: marks darken to read on paper;
     low confidence = faint blue-gray near paper, high = deep structural blue.
     Two AA-floor nudges (Feather-only, ≥4.5:1 as text): --pr-tier-u #8A6A30→#7E5F28 (verdict-exceptions
     text was 4.11:1 vs --inset, now 4.84); --pr-tier-k #1E8A64→#16785A (the knockout "K" badge letter
     was 3.85:1, now 4.85). Candidate hues — Aaron retunes, keeping ≥AA. */
  --pr-conf-1:#B9C0D2; --pr-conf-2:#8E9CC0; --pr-conf-3:#5F79AE; --pr-conf-4:#3A5BB8; --pr-conf-5:#22468F;
  --pr-for:#1C7C8C; --pr-against:#A24C8A;
  --pr-tier-k:#16785A; --pr-tier-i:#22468F; --pr-tier-u:#7E5F28;
}

*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{
  background:var(--ground); color:var(--ink);
  font-family:var(--font-text);
  font-size:clamp(15px,1.05vw,17px); line-height:var(--leading-relaxed);
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
  transition:background .5s var(--ease), color .5s var(--ease);
}
/* ── the weight floor (F13 · R3) ──
   The UA default for <b>/<strong> is `bolder`, which computes to 700 from an
   inherited 400/500 — and --font-text (Instrument Sans) loads 400/500/600 upright,
   so an untamed <b> is a 700 request against a 600 master: SYNTHETIC bold, smeared
   letterforms and metrics that do not match the fallback's.
   This was previously neutralized by TWELVE hand-written per-container `b` rules,
   and two containers were missed (.pull at 2.2rem on an italic serif; .ps-spec-note).
   Per-selector discipline requires enumerating every selector correctly, once, and
   again after every addition — a convention, not a mechanism (I11).
   One foundation rule instead: a selector cannot opt out by omission, only by
   declaring. Inline emphasis is 500 plus one ink step; where a container genuinely
   wants 600 it declares it and can say why. Pinned by `weight-floor` (qa/check.mjs). */
b,strong{font-weight:500;color:var(--ink)}
::selection{background:var(--select-fill);color:var(--select-ink)}
/* scrollbars — standard properties, so a treatment cannot move a measure. See the token block above.
   Set on html ONLY: both properties INHERIT, so one declaration reaches every scroll container, and a
   wider selector ([class], body, *) would be blast radius bought for nothing. Deliberately NOT paired
   with scrollbar-gutter here — whether a gutter is RESERVED is a per-surface layout decision (it costs
   ~1.10ch of measure), and inheriting it from brand core would make it a styling side effect, which is
   the exact failure walk D6 ruled against. Surfaces with contractual measures declare it themselves. */
html{scrollbar-color:var(--scrollbar-thumb) var(--scrollbar-track);scrollbar-width:thin}
.wrap{max-width:1500px;margin:0 auto;padding:0 var(--space-gutter)}
.mono{font-family:var(--font-mono)}

/* ── gradient-ring utility: a hairline that FOLLOWS border-radius (no corner clip) ──
   apply to any positioned, radius'd box via a ::before. mask-composite cuts the interior. */
.ring::before{content:"";position:absolute;inset:0;pointer-events:none;border-radius:inherit;padding:1px;
  background:var(--ramp);opacity:.5;transition:opacity .4s var(--ease);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask-composite:exclude}

/* ── top rail: interference hairline that catches the pointer ── */
.rail{position:fixed;top:0;left:0;right:0;height:1.5px;z-index:60;pointer-events:none;
  background:linear-gradient(90deg,var(--c1),var(--c2),var(--c3),var(--c4),var(--c5));opacity:.30}
.rail::after{content:"";position:absolute;inset:0;background:inherit;opacity:1;
  -webkit-mask:radial-gradient(140px 3px at var(--rx,50%) 50%,#000,transparent 70%);
          mask:radial-gradient(140px 3px at var(--rx,50%) 50%,#000,transparent 70%)}

/* ── masthead / folio ── */
.masthead{position:sticky;top:0;z-index:50;
  background:color-mix(in oklab,var(--ground) 80%,transparent);
  backdrop-filter:blur(14px) saturate(120%);
  border-bottom:1px solid var(--hairline)}
.masthead .bar{display:flex;align-items:center;justify-content:space-between;gap:var(--space-6);height:66px}
.brandmark{font-family:var(--font-display);font-weight:700;letter-spacing:var(--track-normal);font-size:var(--text-body);
  display:flex;align-items:center;gap:var(--space-2)}
.glyph{width:22px;height:22px;display:inline-block;flex:none}
.glyph path{stroke:var(--ink);stroke-width:1.6;fill:none;stroke-linecap:round;stroke-linejoin:round}
.glyph circle{fill:var(--c2)}
.folio{font-family:var(--font-mono);font-size:var(--text-mono);letter-spacing:var(--track-caps-xl);text-transform:uppercase;
  color:var(--muted);display:flex;gap:var(--space-5);align-items:center;flex-wrap:wrap}
.folio .tick{color:var(--ink)}
@media(max-width:640px){.folio span{display:none}}

/* ── theme toggle (single canonical affordance across all surfaces) ── */
.toggle{display:flex;align-items:center;gap:var(--space-2);border:1px solid var(--hairline);
  background:var(--surface);color:var(--muted);
  font-family:var(--font-mono);font-size:var(--text-mono);letter-spacing:var(--track-mono);text-transform:uppercase;
  padding:var(--space-2) var(--space-3);border-radius:var(--radius-pill);cursor:pointer;
  transition:color .3s var(--ease),border-color .3s var(--ease)}
.toggle:hover{color:var(--ink);border-color:color-mix(in oklab,var(--c3) 45%,var(--hairline))}
.toggle .dot{width:9px;height:9px;border-radius:50%;
  background:linear-gradient(var(--sb),var(--c1),var(--c3),var(--c5));animation:spin 9s linear infinite}
@keyframes spin{to{--sb:480deg}}

/* ── hero scaffold: full-bleed canvas + left-anchored copy (balanced, not lop-sided) ── */
.hero{position:relative;min-height:calc(100svh - 66px);overflow:hidden;isolation:isolate}
.hero::before{content:"";position:absolute;inset:-18%;z-index:0;pointer-events:none;
  background:
    radial-gradient(46% 40% at 20% 44%, color-mix(in oklab,var(--c2) 20%,transparent), transparent 72%),
    radial-gradient(58% 44% at 74% 32%, color-mix(in oklab,var(--c2) 28%,transparent), transparent 70%),
    radial-gradient(52% 40% at 88% 62%, color-mix(in oklab,var(--c4) 24%,transparent), transparent 70%),
    radial-gradient(60% 50% at 60% 92%, color-mix(in oklab,var(--c1) 16%,transparent), transparent 72%);
  filter:blur(26px) saturate(115%);opacity:.6;mix-blend-mode:screen;
  animation:drift 36s ease-in-out infinite alternate}
[data-theme="feather"] .hero::before{opacity:.5;mix-blend-mode:multiply;filter:blur(30px)}
@keyframes drift{0%{transform:translate3d(-2%,-1%,0) scale(1.02)}100%{transform:translate3d(3%,2%,0) scale(1.07)}}
#field{position:absolute;inset:0;z-index:1;width:100%;height:100%;display:block}
.catch{position:absolute;inset:-10% -5%;pointer-events:none;z-index:2;opacity:.16;
  background:conic-gradient(from 90deg,var(--c1),var(--c2),var(--c3),var(--c4),var(--c5),var(--c1));
  -webkit-mask:radial-gradient(420px circle at var(--mx,60%) var(--my,42%),#000 0,transparent 62%);
          mask:radial-gradient(420px circle at var(--mx,60%) var(--my,42%),#000 0,transparent 62%);
  transition:opacity .6s var(--ease)}
.catch.lit{opacity:.30}
.hero::after{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(100deg,
    color-mix(in oklab,var(--ground) 90%,transparent) 0%,
    color-mix(in oklab,var(--ground) 62%,transparent) 32%,
    transparent 58%)}
[data-theme="feather"] .hero::after{background:linear-gradient(100deg,
    color-mix(in oklab,var(--ground) 84%,transparent) 0%,
    color-mix(in oklab,var(--ground) 46%,transparent) 34%,
    transparent 60%)}
.hero-inner{position:relative;z-index:4;max-width:1500px;margin:0 auto;
  min-height:calc(100svh - 66px);display:flex;align-items:center;
  padding:clamp(40px,8vh,96px) var(--space-gutter)}
.hero-copy{max-width:var(--measure-tight)}

/* ── type primitives ── */
.eyebrow{font-family:var(--font-accent);font-style:italic;font-size:var(--text-lede);color:var(--ink-2);
  display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-6);white-space:nowrap}
/* section bookmark — thick gradient bar, rounded endcaps; punctuates, never overreaches */
.eyebrow::before,.label::before{content:"";width:30px;height:4px;border-radius:var(--radius-pill);background:var(--ramp);flex:none}
h1,.h1{font-family:var(--font-display);font-weight:600;letter-spacing:var(--track-display);line-height:var(--leading-display);
  font-size:var(--text-display);max-width:16ch;text-wrap:balance}
.shimmer{--sa:120deg;background:var(--ramp-loop);background-size:220% 220%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  animation:sheen 9s linear infinite;font-style:italic;padding-right:.06em}
@keyframes sheen{to{--sa:480deg}}
.lede{margin-top:var(--space-6);max-width:var(--measure-lede);color:var(--muted);font-size:var(--text-lede)}
.chip{font-family:var(--font-mono);font-size:var(--text-mono);letter-spacing:var(--track-wide);color:var(--muted);
  margin-top:var(--space-10);display:inline-flex;align-items:center;gap:var(--space-2);
  border:1px solid var(--hairline);border-radius:var(--radius-pill);padding:var(--space-2) var(--space-4)}
.chip i{width:6px;height:6px;border-radius:50%;background:var(--c5);font-style:normal}
.cap{position:absolute;right:clamp(22px,5vw,64px);bottom:clamp(22px,4vh,44px);z-index:4;
  font-family:var(--font-mono);font-size:var(--text-micro);letter-spacing:var(--track-caps);text-transform:uppercase;
  color:var(--muted);text-align:right;line-height:var(--leading-loose);opacity:.8;max-width:42%}
@media(max-width:900px){.cap{display:none}}

/* ── section frame ── */
section.block{padding:var(--space-section) 0;border-top:1px solid var(--hairline)}
.label{font-family:var(--font-accent);font-style:italic;color:var(--ink-2);font-size:var(--text-lede);margin-bottom:var(--space-4);
  display:flex;align-items:center;gap:var(--space-3)}
.h2{font-family:var(--font-display);font-weight:600;letter-spacing:var(--track-tight);line-height:var(--leading-display);
  font-size:var(--text-h2);max-width:17ch;text-wrap:balance}

/* ── flight paths (hand-crafted novel bit — scaffold only lives here) ── */
.flight{margin-top:clamp(36px,6vw,72px);position:relative}
.flight svg{width:100%;height:auto;display:block;overflow:visible}
.flight-copy{max-width:var(--measure-lede);color:var(--muted);margin-top:var(--space-8);font-size:var(--text-body-lg)}
.pathline{fill:none;stroke-width:2.4;stroke-linecap:round;
  stroke-dasharray:var(--len);stroke-dashoffset:var(--len);
  transition:stroke-dashoffset 2.1s var(--ease)}
.drawn .pathline{stroke-dashoffset:0}
.drawn .pathM{transition-delay:1.4s}
.node{r:0;fill:var(--ink);transition:r .5s var(--ease) 1.9s}
.drawn .node{r:5}
.pulse{transform-box:fill-box;transform-origin:center}
.drawn .pulse{animation:pulse 3.4s var(--ease) 2.2s infinite}
@keyframes pulse{0%,100%{r:5;opacity:1}50%{r:8;opacity:.55}}
.comet{opacity:0}.drawn .comet{opacity:1}
.chev{fill:none;stroke:var(--muted);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round;opacity:0;transition:opacity .6s ease 1.7s}
.drawn .chev{opacity:.7}

/* ── .steps — an ordered sequence where the order is the point ──
   LAYOUT ONLY, in the family of .grid and .railed: it hosts .panel children and supplies no voice
   of its own. The delta against .grid is exactly order + connection — a sequence read out of order
   is a different object from a set read in any order — which is why this is a layout rather than a
   new card.

   TWO CONDITIONS, both places this layout would otherwise quietly acquire a voice it claims not to
   have (Design System Steward, 2026-07-30):

   · THE SPINE IS --hairline, AND A --ramp SPINE IS REFUSED. The ramp is rationed — it fires where
     earned and never fills chrome (digest 1) — and a four-step connector is chrome. .railed already
     takes --hairline for its column border, so converging on it is the precedent rather than a new
     call.
   · THE INDEX IS .panel's EXISTING .n, and .steps authors no second index register. The draft
     contract said the layout supplies "an index per step" while also claiming to supply no voice of
     its own; both cannot be true. `.n` is already the mono index label on .panel, and
     specificity-first applies INSIDE a primitive exactly as it does between them. So there is no
     .steps-index, no counter, no pill: the step number is the panel's own. */
.steps{position:relative;display:flex;flex-direction:column;gap:var(--space-5);
  margin-top:var(--space-10);padding-left:var(--space-8)}
/* The spine reads as a CONNECTOR only if it sits near what it connects; at a wider gutter it reads
   as a page rule and the sequence loses the thing that makes it a sequence. 16px, on the grid. */
.steps::before{content:"";position:absolute;left:var(--space-4);top:var(--space-4);bottom:var(--space-4);
  width:1px;background:var(--hairline)}
@media(max-width:640px){.steps{padding-left:var(--space-5)}.steps::before{left:var(--space-1)}}

/* ── .terms — what is offered, stated as an offer ──
   The transactional register, and the one primitive here whose absence costs money rather than
   polish: a buyer's four questions (what does it cost, what do I get, what is first, how long) were
   answerable only by reading a paragraph. Brand core had no key/value shape of ANY kind — .chip is
   a pill, .rail-note a dated aside, .folio a metadata strip — so this is a genuine gap rather than
   a near-miss.

   A real <dl>: keys and values are definitionally paired, and the element says so. Keys ride the
   mono label voice; values ride the reading face. Scannable without reading, which is the contract. */
.terms{display:flex;flex-direction:column;margin-top:var(--space-8);
  border-top:1px solid var(--hairline);border-bottom:1px solid var(--hairline)}
.terms-row{display:grid;grid-template-columns:minmax(9rem,1fr) 3fr;gap:var(--space-4);
  padding:var(--space-4) 0;align-items:baseline}
.terms-row + .terms-row{border-top:1px solid var(--hairline)}
.terms-key{font-family:var(--font-mono);font-size:var(--text-mono);letter-spacing:var(--track-mono);
  color:var(--muted);line-height:var(--leading-snug)}
.terms-val{font-size:var(--text-body);color:var(--ink-2);line-height:var(--leading-snug);margin:0}
@media(max-width:640px){.terms-row{grid-template-columns:1fr;gap:var(--space-1)}}

/* ── .stat — a quantity set as a quantity ──
   The assertive register's smallest primitive, and the one the system most obviously lacked: a
   number that carries an argument was being set as body text inside a paragraph, which is the
   strongest object on a page rendered as its weakest.

   Face first, size second, weight last (§ Type-role assignment): the value rides --font-display,
   which is where a weight ramp actually exists, and reaches --text-display standalone. It is loud
   because it is set differently and set large — not because it is heavy.

   .stat-row PINS THE TIER RATHER THAN ASSUMING IT. The contract's claim is that stats in a row sit
   on ONE baseline, and that is only true if the values share a type tier — a row mixing --text-h2
   and --text-display breaks the alignment silently, and silently is the whole problem. So the row
   SETS the tier for its children instead of documenting a hope. The Steward's condition was "pin
   one tier per row, or drop the baseline claim"; this pins it. */
.stat{display:flex;flex-direction:column;gap:var(--space-2)}
.stat-value{font-family:var(--font-display);font-weight:600;font-size:var(--text-display);
  letter-spacing:var(--track-display);line-height:var(--leading-display);color:var(--ink);
  font-variant-numeric:tabular-nums}
.stat-label{font-family:var(--font-mono);font-size:var(--text-mono);letter-spacing:var(--track-mono);
  color:var(--ink-2);line-height:var(--leading-snug)}
.stat-note{font-size:var(--text-small);color:var(--muted);line-height:var(--leading-body);
  max-width:var(--measure-tight)}
.stat-row{display:flex;flex-wrap:wrap;gap:var(--space-10) var(--space-16);align-items:baseline;
  margin-top:var(--space-8)}
/* One tier for every value in the row — the baseline claim, made structural. */
.stat-row .stat-value{font-size:var(--text-h2)}

/* ── .compare — alternatives read positionally, across shared named dimensions ──
   The assertive register's comparison shape: two or more alternatives set across the SAME named
   dimensions so the difference is seen instead of narrated. Not `pr-diff` — that is before/after
   against an approved snapshot and its poles are TEMPORAL. This is alternatives, and its poles are
   nothing at all.

   IT IS A REAL <table>, and that is a contract decision rather than a convenience. Alternatives ×
   named dimensions IS tabular data: a <table> gives row/column association in the a11y tree for
   free (`scope` on the headers), aligns rows without a single layout knob, and needs no
   `display:contents` wrapper — which would have stripped the very structure a screen reader needs
   to read a comparison as a comparison. A grid of divs would have looked identical and read as a
   flat list of eleven unrelated strings.

   NEUTRALITY IS THE DISTRICT'S RULE, NOT THIS ONE, and it deliberately has no expression here.
   Off a proof surface a preferred column is legitimate — a pricing table SHOULD point at a plan —
   so brand core styles every alternative identically and stops. Forcing sameness by declaration was
   tested and rejected: a declaration is a DEFAULT and a page-local rule overrides a default, which
   would look like enforcement without being it. On proof surfaces the prohibition is held by
   `compare-col-symmetry` (PROOF-INDEX § District constraints).

   The axis column is `.compare-axis`, deliberately NOT a `.compare-cell`: the dimension NAMES are
   not alternatives, so they are free to be styled differently, and keeping them a separate class is
   what lets the symmetry gate constrain only the things that are actually being compared. */
.compare{width:100%;border-collapse:collapse;table-layout:fixed;margin-top:var(--space-8);text-align:left}
/* The AXIS column is narrowed deliberately: it is not an alternative, so it need not share the
   alternatives' width — and at an equal third it pushed the things being compared apart far enough
   that the comparison stopped reading positionally, which is the whole contract. The ALTERNATIVES
   still split the remainder equally; that half of the equal-width claim is what neutrality means. */
.compare-axis{width:22%}
.compare-head{font-family:var(--font-display);font-weight:600;font-size:var(--text-h3);
  letter-spacing:var(--track-tight);line-height:var(--leading-snug);color:var(--ink);
  padding:0 var(--space-4) var(--space-4);vertical-align:bottom;text-wrap:balance}
/* Leading is --leading-snug on both, and that is a design call rather than a gate dodge: a compare
   cell holds a SHORT PHRASE, not running prose, so prose leading would open it up for a reading it
   never does. It also keeps these rules honestly outside gate 6's proxy (reading size + prose
   leading ⇒ a measure cap), which would otherwise have collected its first false positive here —
   and the answer to a false positive is never to manufacture the cap it asks for.
   No max-width: `table-layout:fixed` + `width:100%` divides the columns EQUALLY, which is where the
   real measure control lives, and equal column width is itself part of what neutrality means. */
.compare-axis{font-size:var(--text-small);color:var(--muted);font-weight:400;
  line-height:var(--leading-snug);padding:var(--space-4) var(--space-4) var(--space-4) 0;
  vertical-align:baseline}
.compare-cell{font-size:var(--text-body);color:var(--ink-2);line-height:var(--leading-snug);
  padding:var(--space-4);vertical-align:baseline}
.compare tbody tr{border-top:1px solid var(--hairline)}
/* The corner cell names nothing and must not read as a dimension. */
.compare thead .compare-axis{padding-bottom:var(--space-4)}
.compare-note{font-size:var(--text-small);color:var(--muted);margin-top:var(--space-4);
  line-height:var(--leading-body);max-width:var(--measure-prose)}
@media(max-width:640px){
  .compare-head{font-size:var(--text-body-lg)}
  .compare-axis,.compare-cell{padding-left:var(--space-2);padding-right:var(--space-2)}
}

/* ── principles: inset panels with corner-following gradient ring ── */
.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(12px,1.6vw,20px);margin-top:clamp(36px,5vw,60px)}
@media(max-width:760px){.grid{grid-template-columns:1fr}}
.panel{position:relative;background:var(--surface);border:1px solid var(--hairline);border-radius:var(--radius-panel);
  padding:clamp(22px,2.4vw,30px);overflow:hidden;
  box-shadow:inset 0 1px 0 color-mix(in oklab,var(--ink) 7%,transparent);
  transition:border-color .4s var(--ease),transform .5s var(--ease)}
.panel:hover{border-color:color-mix(in oklab,var(--c3) 40%,var(--hairline))}
.panel:hover.ring::before{opacity:.9}
.panel .n{font-family:var(--font-mono);font-size:var(--text-mono);color:var(--muted);letter-spacing:var(--track-mono)}
.panel h3{font-family:var(--font-display);font-weight:600;letter-spacing:var(--track-tight);font-size:var(--text-h3);margin:var(--space-4) 0 var(--space-2)}
.panel p{color:var(--muted);font-size:var(--text-body)}

/* ── specimen: standalone attribute words that catch the light on hover ── */
.specimen{margin-top:clamp(40px,6vw,68px);display:flex;flex-wrap:wrap;gap:.28em .7em;
  font-family:var(--font-display);font-weight:600;letter-spacing:var(--track-tight);
  font-size:clamp(1.5rem,4vw,2.6rem);line-height:var(--leading-tight)}
.specimen span{color:var(--ink);cursor:default;position:relative;white-space:nowrap;
  transition:color .35s var(--ease)}
.specimen span::after{content:attr(data-w);position:absolute;inset:0;background:var(--ramp);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  opacity:0;transition:opacity .35s var(--ease)}
.specimen span:hover{color:transparent}
.specimen span:hover::after{opacity:1}

/* ── footer ── */
footer{border-top:1px solid var(--hairline);padding:clamp(48px,7vh,80px) 0 clamp(40px,6vh,64px)}
.foot{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--space-8);flex-wrap:wrap}
.pull{font-family:var(--font-accent);font-style:italic;font-size:clamp(1.4rem,3.4vw,2.2rem);
  max-width:26ch;line-height:var(--leading-snug);text-wrap:balance}
/* --font-accent is ONE master — Instrument Serif italic 400, no upright and no bold.
   So .pull's emphasis channel is zero weight steps wide, and the b,strong floor's 500
   would be a phantom step here at best. Emphasis is INK ONLY (F13 · R2): the word reads
   as lit rather than heavy, which is the more Corvus answer — depth is plane value, not
   drama. `inherit` states that intent; it is not a workaround for the floor. */
.pull b{font-weight:inherit;color:var(--ink)}
.foot .chip{margin-top:0}

/* ── annotation rail: a mono margin column (dates, commit-style asides), like a drawing set —
   the identity's structural signature. Collapses to stacked-inline on narrow viewports. ── */
.railed{display:grid;grid-template-columns:1fr;gap:var(--space-5)}
.rail-col{font-family:var(--font-mono);font-size:var(--text-mono);color:var(--muted);line-height:var(--leading-loose)}
/* THE REGISTER TRAVELS WITH THE ATOM (BID-Corvus 2026-07-27, §2a): the note is the atom of the
   identity's structural signature, so it carries its own mono voice — family + size + voice-color —
   and is usable standalone (in a .panel, a card, a pr-figure) without a hand-added .mono.
   line-height is DELIBERATELY NOT here: --leading-loose is tuned to .rail-col's 210px measure, and
   leading answers to measure. Inside .rail-col it inherits loose (unchanged); standalone it inherits
   the host's. Register travels; layout-tuned properties stay with the layout.
   Zero visual regression: equal specificity, later source order, identical values. */
.rail-note{font-family:var(--font-mono);font-size:var(--text-mono);color:var(--muted);margin-bottom:var(--space-6)}
.rail-note .rd{display:flex;align-items:center;gap:var(--space-2);color:var(--ink-2);margin-bottom:var(--space-1);white-space:nowrap}
.rail-note .rd::before{content:"";width:16px;height:3px;border-radius:var(--radius-pill);background:var(--ramp);flex:none}
.rail-note p{color:var(--muted);margin:0}
@media(min-width:1000px){
  .railed{grid-template-columns:210px minmax(0,1fr);gap:0}
  .rail-col{border-right:1px solid var(--hairline);padding-right:var(--space-6);text-align:right}
  /* SCOPED to the column (2026-07-27). Right-alignment is layout, not register: it exists
     because the 210px rail is right-aligned against its border. Unscoped, it also reached
     standalone notes — a note inside a panel/card/figure had its dated head flung to the
     right edge of its host. Same register/layout line as the .rail-note move above, applied
     to the one rule that crossed it. Zero regression inside .rail-col (proven by diff). */
  .rail-col .rail-note .rd{justify-content:flex-end}
  .rail-main{padding-left:var(--space-8)}
}

/* ── actions: buttons · link · focus ── */
.btn{display:inline-flex;align-items:center;gap:var(--space-2);font-family:var(--font-display);font-weight:600;
  font-size:var(--text-body);letter-spacing:var(--track-normal);line-height:var(--leading-display);padding:var(--space-3) var(--space-5);border-radius:var(--radius-md);cursor:pointer;
  border:1px solid var(--hairline);background:var(--surface);color:var(--ink);position:relative;
  transition:border-color .3s var(--ease),transform .2s var(--ease),color .3s var(--ease)}
.btn:hover{transform:translateY(-1px);border-color:color-mix(in oklab,var(--c3) 45%,var(--hairline))}
.btn:active{transform:translateY(0)}
.btn-ghost{background:transparent}
/* primary — the rationed gradient moment: a gradient-ring edge (compose with .ring) */
.btn.ring{border-color:transparent}
.btn.ring::before{opacity:.85}
.btn.ring:hover::before{opacity:1}
/* bold — one loud CTA per view: radial-ramp fill (Argyle heritage), ground-colored text */
.btn-bold{border-color:transparent;background:var(--ramp-radial);color:var(--ground);font-weight:700}
.btn-bold:hover{transform:translateY(-1px);filter:saturate(108%)}
/* inline link — a gradient underline that grows on hover */
.link{color:var(--ink);text-decoration:none;background-image:var(--ramp);
  background-size:100% 1.5px;background-repeat:no-repeat;background-position:0 100%;
  padding-bottom:1.5px;transition:background-size .3s var(--ease)}
.link:hover{background-size:100% 2.5px}
/* focus — a visible ramp-violet ring, never removed */
:where(a,button,.btn,.toggle,input,select,textarea,[tabindex]):focus-visible{
  outline:2px solid var(--c2);outline-offset:2px;border-radius:var(--radius-sm)}

/* ── skip link — the a11y floor, composed into every emitted page by
   render/page-shell.mjs (H9). Chrome, not district canon, so it lives here
   with the other chrome and is available to every surface family.
   HIDDEN BY TRANSFORM, NEVER display:none — the whole point is that it stays
   in the tab order; display:none or visibility:hidden would remove it from
   the only interaction that reaches it. Reveals on :focus (not :focus-visible)
   so it appears for any focus route, and the ring above still draws. ── */
.skip-link{position:absolute;left:var(--space-2);top:var(--space-2);z-index:100;
  transform:translateY(-200%);
  font-family:var(--font-mono);font-size:var(--text-mono);letter-spacing:var(--track-mono);
  color:var(--ink);background:var(--raised);border:1px solid var(--hairline);
  border-radius:var(--radius-sm);padding:var(--space-2) var(--space-3);text-decoration:none;
  transition:transform .2s var(--ease)}
.skip-link:focus{transform:none}

/* ── scroll reveal ── */
.reveal{opacity:0;transform:translateY(18px);transition:opacity .8s var(--ease),transform .8s var(--ease)}
.reveal.in{opacity:1;transform:none}
.reveal.d1{transition-delay:.08s}.reveal.d2{transition-delay:.16s}.reveal.d3{transition-delay:.24s}

/* ── reduced motion ── */
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .shimmer{--sa:120deg}.reveal{opacity:1;transform:none}
  .pathline{stroke-dashoffset:0}.node,.pulse{r:5}.chev{opacity:.7}.catch{opacity:.12}
}
