/* ─────────────────────────────────────────────────────────────
   lash · docs · shared stylesheet · warm iron
   Sodium spine threads every page from the band/opener through
   the body content and into the landscape strand convergence.
   Light + dark via [data-theme] on <html>; theme-init.js sets
   it pre-paint so there's no flash.
   ────────────────────────────────────────────────────────── */

/* ── shared tokens (theme-agnostic) ─────────────────── */
:root {
  --space-3xs: 0.125rem;
  --space-2xs: 0.25rem;
  --space-xs:  0.5rem;
  --space-sm:  0.75rem;
  --space-md:  1rem;
  --space-lg:  1.5rem;
  --space-xl:  2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;
  --band-h:    3.4rem; /* sticky docs header height — keeps the sticky TOC clear of the band */
  --space-4xl: 6rem;

  --font-display: "Big Shoulders Display", "Helvetica Neue", sans-serif;
  --font-body:    "Spectral", "Iowan Old Style", Georgia, serif;
  --font-mono:    "Chivo Mono", "JetBrains Mono", ui-monospace, monospace;

  /* width of the left rail column that hosts the spine + knot */
  --rail: 9rem;
  --page-max: 88rem;

  /* spine sits at this X inside the .toc — a thin gutter on the left,
     so titles + items hang to the right of it as a left rail. Title
     and item padding-left below MUST clear this value. */
  --toc-rail-x: 0.625rem;

}

/* ── dark theme (warm-iron, twilight) ───────────────── */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:           #141412;
  --bg-elev:      #1b1a17;
  --bg-faint:     #201d18;
  --bg-tint:      #2b2722;
  --ink:          #e8e4d0;
  --ink-mid:      #c0bca8;
  --ink-dim:      #a09e91;
  --ink-faint:    #5a5a50;
  --rule:         #2b2925;
  --rule-strong:  #5a5a50;
  --sodium:       #e8a33c;
  --sodium-deep:  #ffb054;
  --sodium-soft:  color-mix(in oklch, var(--sodium) 22%, transparent);
  --code-bg:      #1b1814;
  --code-rule:    #2b2925;
  --code-ink:     #d8d3bd;

  --range-far-light:   #7a7669;
  --range-far-shadow:  #635d4f;
  --range-mid-light:   #5a5448;
  --range-mid-shadow:  #3e3a30;
  --range-near-light:  #322f27;
  --range-near-shadow: #1f1d18;
  --sky-top:           #141412;
  --sky-mid:           #1a1814;
  --sky-bot:           #221d16;
  --ground:            #1d1b16;
  --ground2:           #22201a;
  --horizon-line:      #2d2925;
  --haze:              #1a1814;
  --nun-robe:          #14110d;
  --nun-headdress:     #e8e4d0;
  --nun-chin:          #bdb39a;
  --instrument-dark:   #1d1c19;
}

/* ── light theme (warm-paper, daylight) ─────────────── */
:root[data-theme="light"] {
  color-scheme: light;
  --bg:           #f5efe0;
  --bg-elev:      #efe9d9;
  --bg-faint:     #ebe4d2;
  --bg-tint:      #e3dcc5;
  --ink:          #1d1c19;
  --ink-mid:      #4c4a45;
  --ink-dim:      #7a7872;
  --ink-faint:    #b0aea6;
  --rule:         #d9d3c1;
  --rule-strong:  #c5bea8;
  --sodium:       #c97a1f;
  --sodium-deep:  #a35e10;
  --sodium-soft:  color-mix(in oklch, var(--sodium) 18%, transparent);
  --code-bg:      #eee6cf;
  --code-rule:    #d9d3c1;
  --code-ink:     #1d1c19;

  --range-far-light:   #d0c8b8;
  --range-far-shadow:  #b3aea1;
  --range-mid-light:   #918b7f;
  --range-mid-shadow:  #5e5a52;
  --range-near-light:  #383530;
  --range-near-shadow: #1d1c19;
  --sky-top:           #f5efe0;
  --sky-mid:           #f3ecdb;
  --sky-bot:           #efe5cf;
  --ground:            #e9e1cc;
  --ground2:           #e3d9c0;
  --horizon-line:      #c5bea8;
  --haze:              #f5efe0;
  --nun-robe:          #1d1c19;
  --nun-headdress:     #dfd4b6;
  --nun-chin:          #e7dcbf;
  --instrument-dark:   #1d1c19;
}

:root[data-theme] body {
  transition: background-color 280ms ease, color 280ms ease;
}

/* ── base ───────────────────────────────────────────── */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Paint the root with --bg too: while body is FOUC-hidden (visibility:hidden
   below until fonts settle), without this rule the browser's default white
   background flashes through. theme.js sets data-theme on <html> pre-paint,
   so var(--bg) resolves immediately. */
html { background: var(--bg); }
body {
  background: var(--bg);
  color: var(--ink-mid);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.66;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Spectral OpenType: kerning + ligatures + contextual alternates +
     old-style figures for prose. Mono blocks override with tnum. */
  font-feature-settings: "kern", "liga", "calt", "onum";
  font-variant-numeric: oldstyle-nums proportional-nums;
  font-kerning: normal;
}
/* dark mode wants slightly looser leading — light text on dark reads
   as lighter weight, so it needs more air to breathe */
:root[data-theme="dark"] body { line-height: 1.7; }

/* monospace contexts: lining tabular figures so code, ids, and
   numbers align in columns */
code, pre, kbd, samp, var,
.font-mono,
.band,
.knot__id,
.knot__name {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum", "calt";
}

/* display-face titles get tighter optical kerning */
.opener__title,
.stanza__title,
.section-header h2,
.section h2,
.stanza__body h3,
.section h3,
.toc__group-title {
  font-feature-settings: "kern", "liga", "ss01";
}
/* Section tabs in the top band — Guide / Reference / Internals / CLI.
   The active section is the active edge: sodium text + underline so it
   reads at a glance. Inactive tabs stay chalk-dim and lift to chalk on
   hover; the underline is the accent, reserved for the active one. */
.band__sections {
  display: flex;
  align-items: center;
  gap: var(--space-lg);
  flex-wrap: wrap;
}
.band__section {
  color: var(--ink-dim);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  padding-bottom: 0.3rem;
  border-bottom: 2px solid transparent;
  transition: color 160ms ease, border-color 160ms ease;
}
.band__section:hover { color: var(--ink); }
.band__section:focus-visible {
  outline: none;
  color: var(--sodium);
  border-bottom-color: var(--sodium);
}
.band__section.is-active {
  color: var(--sodium);
  border-bottom-color: var(--sodium);
}
::selection { background: var(--sodium-soft); color: var(--ink); }
p { margin: 0 0 var(--space-md); max-width: 65ch; }
a { color: var(--sodium); text-decoration: none; }
a:hover { color: var(--sodium-deep); }
em { font-style: italic; }
strong { color: var(--ink); font-weight: 600; }
.body :where(p, li, dd, td) a:not(.cta) {
  text-decoration: underline;
  text-decoration-thickness: 0.08em;
  text-underline-offset: 0.18em;
  text-decoration-color: color-mix(in oklch, currentColor 62%, transparent);
}
.body :where(p, li, dd, td) a:not(.cta):hover {
  text-decoration-color: currentColor;
}
.body :where(p, li, dd, td) a strong {
  color: inherit;
}
hr { border: none; border-top: 1px solid var(--rule); margin: var(--space-xl) 0; }

/* inline code in body prose — kept understated so dense reference
   pages don't strobe with sodium. The block-level <pre> keeps its
   neutral code-ink. Identifiers in lede/title positions inherit a
   sodium tint via parent rules so important call-outs still pop. */
code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  color: var(--ink);
  background: transparent;
  padding: 0;
  font-feature-settings: "tnum", "calt";
}
/* sodium-tint inline code only where it does call-out work: the
   first paragraph of each section. Everywhere else inline code stays
   in ink so the page doesn't strobe with sodium. */
.stanza__lede code,
.opener__lede code,
.section-header > p code {
  color: var(--sodium);
}

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus {
  left: var(--space-md); top: var(--space-md);
  background: var(--bg); color: var(--sodium);
  padding: var(--space-xs) var(--space-md);
  border: 1px solid var(--sodium); border-radius: 2px;
  z-index: 10;
}

/* ── band — sticky running header ───────────────────── */
.band {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-md);
  /* full-bleed surface; content stays aligned to the page-max column so
     the wordmark/tabs line up with the docs grid below on any width. */
  padding-block: var(--space-sm);
  padding-inline: max(var(--space-xl), calc((100% - var(--page-max)) / 2 + var(--space-xl)));
  background: var(--bg);
  border-bottom: 1px solid var(--rule-strong);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
/* Keep the sticky header to one row where the sidebar is sticky (≥981px),
   so --band-h stays accurate and the TOC clears it. Below 980px the TOC is
   a static disclosure, so let the band scroll away instead of pinning a
   wrapped, multi-row header over the mobile fold. */
@media (min-width: 981px) { .band { flex-wrap: nowrap; } }
@media (max-width: 980px) { .band { position: static; } }
.band__brand,
.band__brand a {
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: 0.02em;
  text-transform: lowercase;
}
.band__brand a:hover { color: var(--sodium); }
.band__right {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  flex-wrap: wrap;
  justify-content: flex-end;
}
.band__right b { color: var(--sodium); font-weight: 500; }
.band__btn {
  /* unified button chassis — same height across the band so the
     search / github / theme cluster reads as one row of equals */
  appearance: none;
  background: transparent;
  border: 1px solid var(--rule-strong);
  color: var(--ink-dim);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  height: 1.85rem;
  padding: 0 0.6rem;
  border-radius: 3px;
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  line-height: 1;
  box-sizing: border-box;
  text-decoration: none;
}
.band__btn:hover { color: var(--sodium); border-color: var(--sodium); }
.band__btn:focus-visible {
  outline: none; color: var(--sodium); border-color: var(--sodium);
  box-shadow: 0 0 0 3px var(--sodium-soft);
}
.band__btn .glyph { color: var(--sodium); display: inline-flex; align-items: center; }
/* icon-only band button — square aspect, same height as the rest */
.band__btn--icon {
  width: 1.85rem;
  padding: 0;
  justify-content: center;
}
.band__btn--icon svg { display: block; }

/* ── channel switcher — main / staging dropdown in the band ── */
.channel {
  position: relative;
  display: inline-flex;
}
.channel__btn {
  /* tighter than the default band button so the trio reads as a
     single horizontal beat with theme + search */
  text-transform: lowercase;
}
.channel__dot {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--sodium);
  box-shadow: 0 0 6px color-mix(in oklch, var(--sodium) 60%, transparent);
  display: inline-block;
}
.channel__caret {
  font-size: 0.7rem;
  line-height: 1;
  color: var(--ink-faint);
  margin-left: 0.05rem;
}
/* Menu styles that apply IN ALL CASES (when actually visible) —
   colour, font, shadow. Note: no `display` here, so the UA's
   `display: none` default for `[popover]` (closed) and `[hidden]`
   (fallback) wins until we explicitly open it. */
.channel__menu {
  margin: 0;
  padding: 0;
  min-width: 7rem;
  background: var(--bg-elev, var(--bg));
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  z-index: 50;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: lowercase;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
}
/* Open popover: flex layout, anchored under the trigger button. */
.channel__btn { anchor-name: --channel-btn; }
.channel__menu:popover-open {
  display: flex;
  flex-direction: column;
  position: fixed;
  inset: auto;
  position-anchor: --channel-btn;
  top: anchor(bottom);
  right: anchor(right);
  margin-top: 0.35rem;
}
/* Browsers without CSS anchor positioning: hard-snap under the
   band's right edge. Same metrics for both cases. */
@supports not (anchor-name: --x) {
  .channel__menu:popover-open {
    top: 3.4rem;
    right: var(--space-md, 1rem);
  }
}
/* Manual-toggle fallback (no popover API) — re-style when the menu
   has no popover attribute and isn't hidden. */
.channel__menu:not([popover]):not([hidden]) {
  display: flex;
  flex-direction: column;
  position: absolute;
  top: calc(100% + 0.35rem);
  right: 0;
}
.channel__opt {
  padding: 0.55rem 0.75rem;
  color: var(--ink-dim);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  transition: color 140ms ease, background 140ms ease;
}
.channel__opt + .channel__opt {
  border-top: 1px solid var(--rule);
}
.channel__opt:hover,
.channel__opt:focus-visible {
  color: var(--sodium);
  background: color-mix(in oklch, var(--sodium-soft) 35%, transparent);
  outline: none;
}
.channel__opt.is-active {
  color: var(--ink);
}
.channel__opt.is-active::before {
  content: "";
  width: 0.38rem;
  height: 0.38rem;
  border-radius: 50%;
  background: var(--sodium);
  box-shadow: 0 0 6px color-mix(in oklch, var(--sodium) 60%, transparent);
  display: inline-block;
}
.channel__opt:not(.is-active)::before {
  content: "";
  width: 0.38rem;
  height: 0.38rem;
  border-radius: 50%;
  border: 1px solid var(--rule-strong);
  display: inline-block;
}

/* ── opener — breadcrumbs, title, lede ──────────────── */
.opener {
  max-width: var(--page-max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--space-xl);
  align-items: end;
  padding: var(--space-2xl) var(--space-xl) var(--space-2xl);
  border-bottom: 1px solid var(--rule);
  position: relative;
}
.opener::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: calc(var(--space-xl) + var(--rail) * 14 / 120);
  width: 1px;
  background: var(--sodium);
  pointer-events: none;
  z-index: 0;
}
.opener > * { position: relative; z-index: 1; }
.opener__title {
  grid-column: 2;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.8rem, 6.5vw, 4.6rem);
  line-height: 0.92;
  letter-spacing: -0.034em;
  text-transform: lowercase;
  color: var(--ink);
}
.opener__title em { font-style: normal; color: var(--ink-faint); font-weight: 600; }
.opener__title .slash { color: var(--sodium); font-weight: 600; padding: 0 0.05em; }
.opener__lede {
  grid-column: 2;
  margin: var(--space-lg) 0 0;
  max-width: 60ch;
  font-size: 1.12rem;
  line-height: 1.55;
  color: var(--ink);
}
.opener__lede em { color: var(--sodium); font-style: normal; font-weight: 500; }
.opener__lede code { color: var(--sodium); }
.opener__status {
  grid-column: 2;
  margin: var(--space-lg) 0 0;
  padding: var(--space-sm) 0 var(--space-sm) var(--space-lg);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  max-width: 56ch;
  color: var(--ink-mid);
  font-size: 0.94rem;
}
.opener__status strong { color: var(--sodium); }
.opener__cta-row {
  grid-column: 2;
  margin-top: var(--space-xl);
  display: flex;
  align-items: baseline;
  gap: var(--space-xl);
  flex-wrap: wrap;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  color: var(--sodium);
  border: 1px solid var(--sodium);
  padding: 0.55rem 1rem 0.45rem;
  border-radius: 2px;
  transition: background 160ms ease, color 160ms ease;
}
.cta:hover { background: var(--sodium); color: var(--bg); }
.cta-secondary {
  color: var(--ink-mid);
  border: 1px solid var(--rule-strong);
  padding: 0.55rem 1rem 0.45rem;
  border-radius: 2px;
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  transition: color 160ms ease, border-color 160ms ease;
}
.cta-secondary:hover { color: var(--ink); border-color: var(--ink); }

/* ── body — spine + stanzas ─────────────────────────── */
.body {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 var(--space-xl) 0;
  position: relative;
}
/* The TOC spine is the rail. The body does not paint a second one. */
.body > * { position: relative; z-index: 1; }

/* a stanza is a numbered section in the body; the rail hosts a knot
   (sodium bead + section number + name) and the body holds the
   actual content. The .section class from older pages is aliased to
   the same layout so existing markup renders without restructuring. */
.stanza,
.section {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--space-xl);
  padding: var(--space-3xl) 0 var(--space-2xl);
  align-items: start;
}
.stanza__rail { position: relative; align-self: stretch; }

.knot {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: var(--space-sm);
  row-gap: var(--space-2xs);
  padding-top: var(--space-md);
}
.knot__bead {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: start;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--sodium);
  box-shadow: 0 0 0 3px var(--bg);
  margin-left: calc(var(--rail) * 14 / 120 - 4.5px);
  margin-top: 0.45em;
  z-index: 2;
}
.knot__id {
  grid-column: 2; grid-row: 1;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  line-height: 1.2;
  letter-spacing: 0.12em;
  color: var(--sodium);
  text-transform: uppercase;
  font-weight: 500;
}
.knot__name {
  grid-column: 2; grid-row: 2;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  line-height: 1.3;
  letter-spacing: 0.10em;
  color: var(--ink);
  text-transform: uppercase;
}

.stanza__body { min-width: 0; grid-column: 2; }

/* section-header from existing pages — works as a stanza title */
.section-header {
  grid-column: 2;
  margin-bottom: var(--space-lg);
}
.section > .section-header + * { grid-column: 2; }
.section > :not(.section-header) { grid-column: 2; min-width: 0; }
.section-header h2,
.stanza__title,
.section h2 {
  margin: 0 0 var(--space-md);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, 4.2vw, 2.8rem);
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-transform: lowercase;
  color: var(--ink);
}
/* h2 titles render in ink only; the slash device is reserved for the
   wordmark and the h1 opener title. The trailing `.accent` period is
   stripped from the markup — the wordmark owns that signature. */
.section-header > p,
.stanza__lede {
  margin: 0 0 var(--space-lg);
  max-width: 65ch;
  font-size: 1.04rem;
  color: var(--ink-mid);
}
.section-header > p code { color: var(--sodium); }

.stanza__title a { color: inherit; }
.stanza__title a:hover { color: var(--sodium); }
.stanza__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sodium);
  margin-top: var(--space-md);
}
.stanza__link:hover { color: var(--sodium-deep); }
.stanza__link .arrow { transition: transform 200ms ease; }
.stanza__link:hover .arrow { transform: translateX(4px); }

/* inline links in body prose — a soft underline sets them apart from code/em */
.stanza__body p a,
.stanza__body dd a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in oklch, var(--sodium) 45%, transparent);
  transition: color 140ms ease, text-decoration-color 140ms ease;
}
.stanza__body p a:hover,
.stanza__body dd a:hover { text-decoration-color: var(--sodium-deep); }

/* sub-headings inside a stanza */
.section h3,
.stanza__body h3 {
  margin: var(--space-xl) 0 var(--space-sm);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.5rem;
  letter-spacing: -0.01em;
  text-transform: lowercase;
  color: var(--ink);
}
.section h4,
.stanza__body h4 {
  margin: var(--space-lg) 0 var(--space-xs);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 0.82rem;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sodium);
}

/* ── code blocks ────────────────────────────────────── */
pre {
  margin: var(--space-md) 0 var(--space-lg);
  padding: var(--space-md) var(--space-lg);
  background: var(--code-bg);
  border: 1px solid var(--code-rule);
  border-radius: 3px;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.65;
  color: var(--code-ink);
  position: relative;
}
pre code { color: inherit; background: transparent; font-size: inherit; }
pre::before {
  content: attr(data-lang);
  position: absolute;
  top: 0.45rem;
  right: 0.75rem;
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ── syntax highlighting — Prism token palette tied to warm-iron.
   Token classes come from Prism (syntax.js loads it on demand). We
   only set colours; layout + font + monospace come from `pre` above.
   Both themes share the same token surface; only the tones flip. */
:root[data-theme="dark"] {
  --tok-comment:     #6f6a5c;
  --tok-keyword:     #e8a33c;
  --tok-string:      #b6c79a;
  --tok-number:      #e0b178;
  --tok-type:        #d6caa6;
  --tok-function:    #e8e4d0;
  --tok-builtin:     #e8a33c;
  --tok-attribute:   #c98a5f;
  --tok-macro:       #e8a33c;
  --tok-operator:    #a8a395;
  --tok-punctuation: #837d6e;
  --tok-lifetime:    #d8a878;
  --tok-property:    #d6caa6;
  --tok-bool:        #e8a33c;
  --tok-regex:       #b6c79a;
  --tok-tag:         #e8a33c;
  --tok-deleted:     #d77272;
  --tok-inserted:    #b6c79a;
}
:root[data-theme="light"] {
  --tok-comment:     #8e8676;
  --tok-keyword:     #a35e10;
  --tok-string:      #3f6b34;
  --tok-number:      #a35e10;
  --tok-type:        #2b2722;
  --tok-function:    #1d1c19;
  --tok-builtin:     #a35e10;
  --tok-attribute:   #c97a1f;
  --tok-macro:       #a35e10;
  --tok-operator:    #4c4a45;
  --tok-punctuation: #6a665c;
  --tok-lifetime:    #a35e10;
  --tok-property:    #2b2722;
  --tok-bool:        #a35e10;
  --tok-regex:       #3f6b34;
  --tok-tag:         #a35e10;
  --tok-deleted:     #8a2828;
  --tok-inserted:    #3f6b34;
}
pre code .token { background: transparent; }
pre code .token.comment,
pre code .token.prolog,
pre code .token.cdata     { color: var(--tok-comment); font-style: italic; }
pre code .token.doc-comment { color: var(--tok-comment); font-style: italic; }
pre code .token.keyword,
pre code .token.atrule,
pre code .token.important { color: var(--tok-keyword); }
pre code .token.string,
pre code .token.char,
pre code .token.attr-value,
pre code .token.regex,
pre code .token.url-link  { color: var(--tok-string); }
pre code .token.number,
pre code .token.boolean,
pre code .token.constant,
pre code .token.symbol    { color: var(--tok-number); }
pre code .token.class-name,
pre code .token.type      { color: var(--tok-type); }
pre code .token.function,
pre code .token.function-definition,
pre code .token.method    { color: var(--tok-function); }
pre code .token.builtin,
pre code .token.namespace { color: var(--tok-builtin); }
pre code .token.attribute,
pre code .token.attr-name { color: var(--tok-attribute); }
pre code .token.macro,
pre code .token.macro-rules,
pre code .token.macro.property { color: var(--tok-macro); }
pre code .token.operator,
pre code .token.entity    { color: var(--tok-operator); }
pre code .token.punctuation { color: var(--tok-punctuation); }
pre code .token.lifetime-annotation { color: var(--tok-lifetime); font-style: italic; }
pre code .token.property,
pre code .token.key       { color: var(--tok-property); }
pre code .token.tag       { color: var(--tok-tag); }
pre code .token.deleted   { color: var(--tok-deleted); }
pre code .token.inserted  { color: var(--tok-inserted); }
pre code .token.italic    { font-style: italic; }
pre code .token.bold      { font-weight: 600; }
/* shell prompt + flag accents */
pre code .language-bash .token.variable,
pre code .language-bash .token.environment { color: var(--tok-builtin); }

/* ── definition list (editorial — hanging mono terms) ── */
.defs,
.def-list {
  margin: var(--space-md) 0 var(--space-lg);
  padding: 0;
  display: grid;
  grid-template-columns: minmax(11rem, 16rem) 1fr;
  column-gap: var(--space-xl);
  row-gap: 0;
}
.defs dt,
.def-list dt {
  grid-column: 1;
  /* Grid items default to min-width:auto (min-content); a long
     unbreakable mono identifier would then spill out of the capped
     label track and over the prose column. Let it shrink and wrap. */
  min-width: 0;
  overflow-wrap: anywhere;
  padding: var(--space-md) 0 var(--space-xs);
  border-top: 1px solid var(--rule);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--sodium);
  font-weight: 500;
}
.defs dt:first-of-type,
.def-list dt:first-of-type { border-top: 1px solid var(--rule-strong); }
.defs dd,
.def-list dd {
  grid-column: 2;
  min-width: 0;
  overflow-wrap: anywhere;
  margin: 0;
  padding: var(--space-md) 0;
  border-top: 1px solid var(--rule);
  color: var(--ink-mid);
  font-size: 0.98rem;
  line-height: 1.6;
}
.defs dd:first-of-type,
.def-list dd:first-of-type { border-top: 1px solid var(--rule-strong); }
.defs dd code,
.def-list dd code { font-family: var(--font-mono); font-size: 0.86em; color: var(--ink); }
.defs dt code,
.def-list dt code { font-size: inherit; color: inherit; }
.defs::after,
.def-list::after {
  content: "";
  grid-column: 1 / -1;
  border-top: 1px solid var(--rule-strong);
}

/* ── hairline-divided list (editorial — labels + body) ── */
.listing {
  margin: var(--space-md) 0 0;
  border-top: 1px solid var(--rule-strong);
}
.listing__row {
  display: grid;
  grid-template-columns: minmax(8rem, 11rem) 1fr;
  column-gap: var(--space-xl);
  padding: var(--space-md) 0;
  border-bottom: 1px solid var(--rule);
}
.listing__row:last-child { border-bottom: 1px solid var(--rule-strong); }
.listing__label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  /* chalk, not accent — these are row taxonomy, not actions. The mono
     caps + tracking + weight read as a label; sodium stays reserved for
     active states and the recommended-action label. (Interactive
     a.listing__row rows still go sodium on hover — that IS an action.) */
  color: var(--ink);
  font-weight: 500;
  align-self: start;
}
.listing__body p { margin: 0; color: var(--ink-mid); font-size: 0.98rem; max-width: 60ch; }
.listing__body code { font-family: var(--font-mono); font-size: 0.86em; color: var(--ink); }
.docs-registry-row__meta {
  display: inline-block;
  margin-top: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ── task-first docs components ─────────────────────── */
.callout,
.note,
.gotcha,
.use-when,
.avoid,
.contract {
  margin: var(--space-md) 0 var(--space-lg);
  padding: var(--space-md) var(--space-lg);
  border-top: 1px solid var(--rule-strong);
  border-bottom: 1px solid var(--rule);
  background: color-mix(in oklch, var(--bg-faint) 74%, transparent);
}
.callout > :first-child,
.note > :first-child,
.gotcha > :first-child,
.use-when > :first-child,
.avoid > :first-child,
.contract > :first-child { margin-top: 0; }
.callout > :last-child,
.note > :last-child,
.gotcha > :last-child,
.use-when > :last-child,
.avoid > :last-child,
.contract > :last-child { margin-bottom: 0; }
.callout strong:first-child,
.note strong:first-child,
.gotcha strong:first-child,
.use-when strong:first-child,
.avoid strong:first-child,
.contract strong:first-child {
  display: block;
  margin-bottom: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sodium);
}
/* Differentiate the callout family by its mono label, not a side-stripe
   (STYLEGUIDE guardrail #2). Sodium label = the recommended action
   (use-when); chalk = neutral statement (contract); ash = the quieter
   alternative or aside (avoid / note / gotcha). Accent still means action. */
.callout--contract strong:first-child,
.contract strong:first-child { color: var(--ink); }
.callout--note strong:first-child,
.note strong:first-child,
.callout--gotcha strong:first-child,
.gotcha strong:first-child,
.callout--avoid strong:first-child,
.avoid strong:first-child { color: var(--ink-dim); }

/* Paired decision: two asides side-by-side so a choose-X/choose-Y call
   reads as one comparison, and the page gets a second editorial texture
   beyond the listing rows. Stacks on narrow viewports. */
.choice-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-md);
  margin: var(--space-md) 0 var(--space-lg);
}
.choice-grid > .use-when,
.choice-grid > .avoid { margin: 0; }
@media (max-width: 820px) {
  .choice-grid { grid-template-columns: 1fr; }
}

.related-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--space-sm);
  margin: var(--space-md) 0 var(--space-lg);
}
.related-links__item {
  display: grid;
  gap: var(--space-2xs);
  padding: var(--space-sm) 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  color: inherit;
  text-decoration: none;
}
.related-links__item:hover {
  color: inherit;
  border-top-color: var(--sodium);
}
.related-links__item:hover strong { color: var(--sodium); }
.related-links__kind {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.related-links__item strong {
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1;
  text-transform: lowercase;
  color: var(--ink);
}
.related-links__item span:last-child {
  max-width: 42ch;
  font-size: 0.9rem;
  line-height: 1.48;
  color: var(--ink-mid);
}

/* ── tables ─────────────────────────────────────────── */
.table,
table {
  margin: var(--space-md) 0 var(--space-lg);
  width: 100%;
  border-collapse: collapse;
  font-size: 0.94rem;
}
.table table { margin: 0; }
.table { overflow-x: auto; }
th, td {
  text-align: left;
  vertical-align: top;
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--rule);
  color: var(--ink-mid);
}
th {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sodium);
  font-weight: 500;
  border-bottom: 1px solid var(--rule-strong);
}
td code { color: var(--ink); }
tbody tr:last-child td { border-bottom: 1px solid var(--rule-strong); }

/* ── module-grid — rendered as a hairline-divided reference list
   (not a card grid). Same .module-grid + .panel markup the legacy
   pages used; the new look is reference-style rows so panels with
   one-sentence bodies don't strand alongside long ones in cards. */
.module-grid {
  display: block;
  margin: var(--space-md) 0 var(--space-lg);
  border-top: 1px solid var(--rule-strong);
}
.panel {
  display: grid;
  grid-template-columns: minmax(8rem, 11rem) 1fr;
  column-gap: var(--space-xl);
  row-gap: var(--space-sm);
  align-items: start;
  padding: var(--space-sm) 0;
  border-bottom: 1px solid var(--rule);
  background: transparent;
  border-radius: 0;
}
.panel:last-child { border-bottom: 1px solid var(--rule-strong); }
/* label in col 1; heading + body + lists stack in col 2 */
.panel > small { grid-column: 1; grid-row: 1; }
.panel > h3,
.panel > h4,
.panel > p,
.panel > ul,
.panel > ol,
.panel > dl { grid-column: 2; margin-left: 0; }
.panel > small {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
/* heading sits in ink (not sodium) — accent means action, headings
   in a static dictionary don't qualify. weight + mono + uppercase
   already give the panel heading enough hierarchy. */
.panel h3 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--ink);
  font-weight: 600;
  align-self: start;
}
.panel p {
  margin: 0;
  color: var(--ink-mid);
  font-size: 0.94rem;
  max-width: 60ch;
  line-height: 1.55;
}
.panel p code { font-family: var(--font-mono); font-size: 0.86em; color: var(--ink); }
/* code blocks and diagrams inside a panel span the full row so they
   don't auto-flow into the narrow label column and get clipped */
.panel > pre,
.panel > .diagram,
.panel > .mermaid,
.panel > table { grid-column: 1 / -1; max-width: 100%; }

/* ── pager — continues the spine into the landscape ─── */
.pager {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-2xl) var(--space-xl);
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  column-gap: var(--space-xl);
  position: relative;
}
.pager::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: calc(var(--space-xl) + var(--rail) * 14 / 120);
  width: 1px;
  background: var(--sodium);
  pointer-events: none;
  z-index: 0;
}
.pager > * { position: relative; z-index: 1; }
.pager__rail {
  grid-column: 1;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
  padding-top: var(--space-md);
}
.pager__main {
  grid-column: 2;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
  padding-top: var(--space-md);
}
.pager__prev,
.pager__next {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-sm);
  color: var(--sodium);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.pager__prev:hover,
.pager__next:hover { color: var(--sodium-deep); }
.pager__prev strong,
.pager__next strong {
  font-family: var(--font-display);
  font-size: 1.6rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-transform: lowercase;
  font-weight: 700;
  line-height: 1;
}
.pager__prev:hover strong,
.pager__next:hover strong { color: var(--sodium); }
.pager__prev .arrow,
.pager__next .arrow { transition: transform 200ms ease; }
.pager__next:hover .arrow { transform: translateX(4px); }
.pager__prev:hover .arrow { transform: translateX(-4px); }

/* ── landscape footer ───────────────────────────────── */
.cover {
  position: relative;
  margin: 0;
  padding: 0;
  max-width: none;
  /* clip the slide-in transforms so they can't visually bleed onto
     the spine / text / page bg during a regen. */
  overflow: hidden;
}

/* FOUC guard — until fonts have downloaded (or the failsafe fires),
   hide the body so users don't see a flash of serif Times before the
   page typography settles. theme.js sets `.lash-ready` on <html>. */
:root:not(.lash-ready) body {
  visibility: hidden;
}
:root.lash-ready body {
  visibility: visible;
}
.cover__svg {
  width: 100%;
  height: auto;
  display: block;
  background: var(--bg);
  overflow: hidden;
}
.cover__caption {
  max-width: var(--page-max);
  margin: var(--space-lg) auto 0;
  padding: 0 var(--space-xl) var(--space-3xl);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
}
.cover__caption b { color: var(--sodium); font-weight: 500; }
.cover__caption em { font-style: normal; color: var(--ink); font-weight: 500; }
.cover__caption code {
  font-family: var(--font-mono);
  color: var(--ink);
  font-size: 1em;
  text-transform: none;
  letter-spacing: 0.02em;
}
.cover__src {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted color-mix(in oklch, var(--ink-faint) 70%, transparent);
  transition: color 140ms ease, border-color 140ms ease;
}
.cover__src:hover {
  color: var(--sodium);
  border-bottom-color: var(--sodium);
}
.cover__src:hover code { color: var(--sodium); }

/* ─────────────────────────────────────────────────────────────
   docs subpage layout · TOC sidebar + compact prose
   Body gets class="docs-page". Landing keeps the editorial design.
   ────────────────────────────────────────────────────────── */

body.docs-page {
  font-size: 15.5px;
  line-height: 1.62;
}

.docs-layout {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 var(--space-xl);
  display: grid;
  grid-template-columns: 14.5rem minmax(0, 1fr);
  column-gap: var(--space-3xl);
  align-items: start;
  position: relative;
}
.docs-layout > .docs-main { position: relative; z-index: 1; }
/* .toc gets sticky positioning below — only the z-index applies here */
.docs-layout > .toc { z-index: 1; }

/* the organic snake — one continuous sodium thread that rises out
   of the brazier at the bottom and snakes up through the TOC area.
   Drawn by docs.js into .spine-snake; replaces the static
   border-left on .toc__items. */
.spine-snake {
  position: absolute;
  top: 0;
  pointer-events: none;
  z-index: 0;
  color: var(--sodium);
}

/* the main vertical thread draws UP on first visit — continuing
   the lash that bloomed out of the brazier at the bottom of the
   cover SVG. Triggered by html.spine-revealed (set by scene.js
   after its intro bloom reaches the spine attachment point).
   .lash-revisit (set by theme.js on 2nd+ pageviews) skips the
   entrance so the TOC feels snappy on later navs.

   Implemented as a keyframe animation rather than a transition
   because SVG stroke-dashoffset doesn't reliably react to CSS
   transitions in Chrome — but it does animate via @keyframes. */
.spine-thread {
  opacity: 1;
  stroke-dasharray: 4000;
}
:root:not(.lash-revisit):not(.spine-revealed) .spine-thread {
  stroke-dashoffset: 4000;
}
:root.spine-revealed:not(.lash-revisit) .spine-thread {
  animation: spine-draw-up 1500ms cubic-bezier(0.22, 0.72, 0.18, 1) forwards;
}
@keyframes spine-draw-up {
  from { stroke-dashoffset: 4000; }
  to   { stroke-dashoffset: 0; }
}

/* staggered fade-in of TOC entries — first visit only */
:root:not(.lash-revisit) .toc__group,
:root:not(.lash-revisit) .toc__label {
  opacity: 0;
  transform: translateY(4px);
  animation: toc-rise 460ms cubic-bezier(0.2, 0.6, 0.2, 1) forwards;
}
:root:not(.lash-revisit) .toc__label                { animation-delay:  60ms; }
:root:not(.lash-revisit) .toc__group:nth-of-type(1) { animation-delay: 140ms; }
:root:not(.lash-revisit) .toc__group:nth-of-type(2) { animation-delay: 240ms; }
:root:not(.lash-revisit) .toc__group:nth-of-type(3) { animation-delay: 340ms; }
:root:not(.lash-revisit) .toc__group:nth-of-type(4) { animation-delay: 440ms; }
:root:not(.lash-revisit) .toc__group:nth-of-type(5) { animation-delay: 540ms; }
@keyframes toc-rise {
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  :root:not(.lash-revisit) .toc__group,
  :root:not(.lash-revisit) .toc__label {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

/* cross-document view transition — Chrome 126+ smoothly fades
   between same-origin pages, killing the "full reload" feel even
   on the very first navigation.

   Gated above the layout breakpoint on purpose. The default crossfade
   snapshots the whole root and dissolves the outgoing page into the
   incoming one at the same coordinates. On wide screens the TOC is a
   fixed-width sticky sidebar, so the content column keeps the same Y on
   every page and the two snapshots line up. Below 980px the TOC becomes
   an inline block whose height varies per page (the active page's group
   auto-expands), so the heading lands at a different Y on each page and
   the crossfade ghosts the outgoing TOC over the incoming heading — the
   "weird overlap" seen on narrow windows. Only opt in where it aligns. */
@media (min-width: 981px) {
  @view-transition { navigation: auto; }
}

/* floating marker beside each entry — hollow ring (normal) or
   filled dot (active page). Never touches the thread or the text. */
.spine-mark {
  transition:
    opacity 220ms ease,
    r 240ms cubic-bezier(0.2, 0.6, 0.2, 1),
    stroke-width 220ms ease;
}
.spine-mark.is-hover {
  opacity: 1;
  stroke-width: 1.4;
}
.spine-mark.spine-mark--group {
  /* groups read a touch more present than their items */
}
.spine-mark.is-active {
  /* a single steady halo — the earlier pulsing animation read as a
     visual blip rather than a "you are here" cue. Static is calmer. */
  filter: drop-shadow(0 0 3px var(--sodium));
}

@media (prefers-reduced-motion: reduce) {
  .spine-thread { animation: none; stroke-dashoffset: 0; }
}

/* ── TOC sidebar ────────────────────────────────────── */
.toc {
  /* sticky — the TOC follows scroll so the reader's "you are here"
     stays in view. The spine snake lives inside the sticky element
     so the thread and its eyelets travel with the items. The column
     occupies the full viewport-aligned height so the spine reads as
     a continuous line down the page instead of stopping mid-air. */
  position: sticky;
  top: calc(var(--band-h) + var(--space-sm));
  align-self: start;
  height: calc(100vh - var(--band-h) - var(--space-xl));
  overflow-y: auto;
  overflow-x: hidden;
  /* hide the scrollbar UI — content still scrolls via wheel / drag /
     keyboard. Standard rule for Firefox, vendor selector for WebKit. */
  scrollbar-width: none;
  padding: var(--space-xl) 0 var(--space-2xl);
  font-size: 0.92rem;
}
.toc::-webkit-scrollbar { width: 0; height: 0; }

.toc__label {
  margin: 0 0 var(--space-md);
  padding-left: var(--space-md);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim); /* AA-passing (6.85:1); --ink-faint was sub-AA */
}

.toc__group {
  margin: 0 0 var(--space-sm);
}
.toc__group-title {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0 0 var(--space-2xs);
  /* left padding MUST sit comfortably past --toc-rail-x so the spine
     never crosses the caret/title text */
  padding: 0.18rem var(--space-sm) 0.18rem var(--space-md);
  /* industrial signage voice — not editorial italic */
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  text-transform: lowercase;
  color: var(--ink);
  border-radius: 4px;
}
/* When the title is a <button> the whole row toggles the group's
   collapse state. Reset browser defaults so it looks identical to
   the <p> variant used for non-collapsible groups. */
button.toc__group-title {
  width: 100%;
  background: transparent;
  border: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  text-transform: lowercase;
  color: var(--ink);
  transition: background 140ms ease, color 140ms ease;
}
button.toc__group-title:hover {
  background: color-mix(in oklch, var(--ink) 6%, transparent);
  color: var(--sodium);
}
button.toc__group-title:focus-visible {
  outline: 2px solid var(--sodium);
  outline-offset: 2px;
}
.toc__group-title-text {
  color: inherit;
  flex: 1;
  min-width: 0;
}
.toc__group-title.is-active { color: var(--ink); font-weight: 600; }

/* caret indicator — rotates with the group's open state. The whole
   title row is the toggle now, so the caret has no separate handler. */
.toc__caret-wrap {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
}
.toc__caret { transition: transform 180ms cubic-bezier(0.2, 0.6, 0.2, 1); }
.toc__group:not(.is-collapsed) .toc__caret { transform: rotate(90deg); }
.toc__caret-spacer { display: inline-block; width: 16px; height: 16px; flex: 0 0 auto; }

.toc__group.is-collapsed .toc__items { display: none; }

/* ── TOC disclosure wrapper ──────────────────────────────────
   buildTOC() wraps the groups in a native <details class="toc-disclosure">
   so the whole nav can collapse behind a "Contents" summary on narrow
   viewports (see the @media block below). On desktop the disclosure is
   inert chrome: the summary is hidden and the panel always shows, so the
   sticky sidebar looks identical to the pre-disclosure layout. The mobile
   summary styling (tappable target, caret, focus ring) lives in the
   responsive block — keeping the desktop default here as the no-chrome
   baseline. */
.toc-disclosure {
  margin: 0;
}
.toc-disclosure__summary {
  /* desktop: no summary chrome at all. The responsive block re-shows and
     styles it below 980px. */
  display: none;
}
/* The native marker (triangle) is suppressed everywhere — we draw our own
   caret. Both selectors are needed for cross-browser coverage. */
.toc-disclosure__summary::-webkit-details-marker { display: none; }
.toc-disclosure__summary::marker { content: ""; }
/* Desktop default: the panel is always laid out regardless of [open], so a
   stale closed state can never hide the sidebar on wide screens. */
.toc-disclosure__panel { display: block; }

.toc__items {
  list-style: none;
  margin: 0;
  /* items sit indented from the group title — leaves room for the
     rail/spine on the left edge */
  padding: 0 0 var(--space-2xs) calc(var(--space-md) + 16px + 0.35rem);
}
.toc__items li { margin: 0; }
.toc__items a {
  display: block;
  padding: 0.22rem var(--space-sm);
  margin: 1px 0;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.01em;
  color: var(--ink-dim);
  text-decoration: none;
  border-radius: 4px;
  transition: color 140ms ease, background 140ms ease;
}
.toc__items a:hover {
  color: var(--ink);
  background: color-mix(in oklch, var(--ink) 6%, transparent);
}
.toc__items a.is-active {
  color: var(--ink);
  font-weight: 500;
  background: color-mix(in oklch, var(--sodium) 14%, transparent);
}

/* per-page outline — the active page's sections + subsections, nested
   under its sidebar entry. Quieter than the page list; scroll-spy
   marks the section being read. */
.toc__outline,
.toc__outline ol {
  list-style: none;
  margin: 0;
  padding: 0;
}
.toc__outline {
  margin: 2px 0 var(--space-xs);
  padding-left: var(--space-sm);
}
.toc__outline a {
  display: block;
  padding: 0.14rem var(--space-sm);
  margin: 1px 0;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.35;
  letter-spacing: 0.01em;
  color: var(--ink-faint);
  text-decoration: none;
  border-radius: 4px;
  overflow-wrap: anywhere;
  transition: color 140ms ease, background 140ms ease;
}
.toc__outline-sec > a { color: var(--ink-dim); }
.toc__outline-subs a { padding-left: calc(var(--space-sm) + 0.85rem); font-size: 0.73rem; }
.toc__outline a:hover { color: var(--ink-mid); background: color-mix(in oklch, var(--ink) 5%, transparent); }
.toc__outline a.is-current { color: var(--ink); background: color-mix(in oklch, var(--sodium) 12%, transparent); }
.toc__outline-sec > a.is-current { color: var(--sodium); }

/* anchored headings clear the top edge when jumped to */
body.docs-page .body > .section[id],
/* offset in-page anchor jumps (outline links, ⌘K section results) so the
   target heading clears the sticky band instead of hiding under it. */
body.docs-page .body :is(.section, section, .stanza, h2, h3)[id] {
  scroll-margin-top: calc(var(--band-h) + var(--space-md));
}


/* ── compact opener for docs pages ──────────────────── */
body.docs-page .opener {
  display: block;
  padding: var(--space-2xl) 0 var(--space-lg);
  margin: 0;
  max-width: 78ch;
  border-bottom: 1px solid var(--rule);
}
body.docs-page .opener::before { display: none; } /* TOC is the spine now */
body.docs-page .opener > * { grid-column: auto; }
body.docs-page .opener__title {
  margin: 0;
  font-size: clamp(2rem, 4.5vw, 2.8rem);
  line-height: 0.96;
}
body.docs-page .opener__lede {
  margin-top: var(--space-md);
  font-size: 1.04rem;
  line-height: 1.55;
  max-width: 62ch;
}

/* ── compact body prose ─────────────────────────────── */
body.docs-page .body {
  /* fill the grid column — paragraph max-width below keeps lines
     readable while code blocks, tables, and diagrams use the full
     available width */
  max-width: none;
  margin: 0;
  padding: 0;
}
body.docs-page .body > * { position: static; }

body.docs-page .stanza,
body.docs-page .section {
  display: block;
  padding: var(--space-xl) 0 var(--space-md);
  border-top: 1px solid var(--rule);
}
body.docs-page .body > :first-child.stanza,
body.docs-page .body > :first-child.section {
  border-top: none;
  padding-top: var(--space-xl);
}
body.docs-page .stanza__rail { display: none; }
body.docs-page .section-header { margin-bottom: var(--space-sm); }
body.docs-page .section-header h2,
body.docs-page .stanza__title,
body.docs-page .section h2 {
  margin: 0 0 var(--space-2xs);
  font-size: clamp(1.32rem, 2.4vw, 1.55rem);
  line-height: 1.18;
  letter-spacing: -0.01em;
  font-weight: 700;
  color: var(--ink);
}
body.docs-page .section-header > p,
body.docs-page .stanza__lede {
  margin: 0 0 var(--space-sm);
  font-size: 0.98rem;
  color: var(--ink-mid);
  max-width: 72ch;
}
body.docs-page .section h3,
body.docs-page .stanza__body h3 {
  margin: var(--space-lg) 0 var(--space-2xs);
  font-size: 1.05rem;
  font-family: var(--font-display);
}
body.docs-page .section h4,
body.docs-page .stanza__body h4 {
  margin: var(--space-md) 0 var(--space-2xs);
  font-size: 0.7rem;
}
body.docs-page p {
  font-size: 0.98rem;
  line-height: 1.62;
  max-width: 75ch;
  margin: 0 0 var(--space-sm);
}
body.docs-page pre {
  margin: var(--space-sm) 0 var(--space-md);
  padding: var(--space-sm) var(--space-md);
  font-size: 0.78rem;
  line-height: 1.55;
  max-width: 100%;
}
body.docs-page .defs,
body.docs-page .def-list {
  margin: var(--space-sm) 0 var(--space-md);
  grid-template-columns: minmax(9rem, 13rem) 1fr;
  column-gap: var(--space-lg);
}
body.docs-page .defs dt,
body.docs-page .def-list dt { padding: var(--space-sm) 0 var(--space-2xs); font-size: 0.74rem; }
body.docs-page .defs dd,
body.docs-page .def-list dd { padding: var(--space-sm) 0; font-size: 0.94rem; }
body.docs-page table,
body.docs-page .table table { font-size: 0.86rem; }
body.docs-page th, body.docs-page td { padding: var(--space-2xs) var(--space-sm); }
body.docs-page .listing__row { padding: var(--space-sm) 0; }
body.docs-page .listing__body p { font-size: 0.94rem; }
body.docs-page .module-grid { gap: var(--space-sm); }
body.docs-page .panel { padding: var(--space-sm); }
body.docs-page .panel h3 { font-size: 0.7rem; }

/* ── compact pager for docs pages ───────────────────── */
body.docs-page .pager {
  display: block;
  max-width: 65ch;
  margin: 0;
  padding: var(--space-xl) 0;
  border-top: 1px solid var(--rule);
}
body.docs-page .pager::before { display: none; }
body.docs-page .pager__rail { display: none; }
body.docs-page .pager__main { padding-top: 0; gap: var(--space-lg); }
body.docs-page .pager__prev strong,
body.docs-page .pager__next strong { font-size: 1.18rem; }

/* ── compact cover for docs pages ───────────────────── */
.cover--compact { /* placeholder hook */ }
body.docs-page .cover { margin-top: 0; }
/* docs subpages: drop the SOURCE listing under the SVG entirely.
   The floating #toc-jump button is the single way back to top, and
   the source paths were producing a multi-line strip below an
   otherwise flush scene. Mountains plant at the bottom edge; the
   page ends there. */
body.docs-page .cover__caption { display: none; }
body.docs-page .cover__top     { display: none; }

/* ── floating "back to contents" button ─────────────────
   Appears once the TOC has scrolled out of view; clicking
   jumps the page back to the top so the contents are visible
   again. Only rendered on docs-page bodies. */
.toc-jump {
  position: fixed;
  left: var(--space-lg);
  bottom: var(--space-lg);
  z-index: 20;
  appearance: none;
  border: 1px solid var(--sodium);
  background: var(--bg);
  color: var(--sodium);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 0.55rem 0.9rem 0.5rem;
  border-radius: 2px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition:
    opacity 240ms ease,
    transform 240ms cubic-bezier(0.2, 0.6, 0.2, 1),
    background 200ms ease,
    color 200ms ease;
}
.toc-jump.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.toc-jump:hover {
  background: var(--sodium);
  color: var(--bg);
}
.toc-jump:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--sodium-soft);
}
.toc-jump .arrow {
  display: inline-block;
  transition: transform 240ms cubic-bezier(0.2, 0.6, 0.2, 1);
}
.toc-jump:hover .arrow { transform: translateY(-2px); }

/* ── diagram zoom modal — used by architecture/mermaid.js for the
   "click-to-fullscreen" diagram view. Lives here so every page
   that loads styles.css can render it (the legacy architecture
   styles.css is no longer loaded on the new shell). */
.diagram {
  position: relative;
}
.diagram-zoom {
  appearance: none;
  position: absolute;
  top: var(--space-sm);
  right: var(--space-sm);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  background: var(--bg-faint);
  border: 1px solid var(--rule-strong);
  color: var(--ink-mid);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: var(--space-2xs) var(--space-sm);
  cursor: pointer;
  border-radius: 2px;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}
.diagram-zoom__glyph {
  font-size: 0.95rem;
  line-height: 1;
}
.diagram-zoom:hover {
  background: var(--bg-tint);
  color: var(--sodium);
  border-color: var(--sodium);
}
.diagram-zoom:focus-visible {
  outline: none;
  color: var(--sodium);
  border-color: var(--sodium);
  box-shadow: 0 0 0 3px var(--sodium-soft);
}

.diagram-modal {
  display: flex;
  flex-direction: column;
  width: min(95vw, 1600px);
  max-width: 95vw;
  height: min(92vh, 1100px);
  max-height: 92vh;
  margin: auto;
  padding: 0;
  border: 1px solid var(--rule-strong);
  background: var(--bg-elev);
  color: var(--ink);
  border-radius: 4px;
}
.diagram-modal:not([open]) {
  display: none;
}
.diagram-modal::backdrop {
  background: color-mix(in oklch, var(--bg) 78%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.diagram-modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--rule);
  background: var(--bg-faint);
}
.diagram-modal__title {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.diagram-modal__controls {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}
.diagram-modal__btn {
  appearance: none;
  border: 1px solid var(--rule-strong);
  background: transparent;
  color: var(--ink-mid);
  padding: var(--space-2xs) var(--space-sm);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  cursor: pointer;
  min-width: 32px;
  border-radius: 2px;
  transition: color 160ms ease, border-color 160ms ease;
}
.diagram-modal__btn:hover {
  color: var(--sodium);
  border-color: var(--sodium);
}
.diagram-modal__btn:focus-visible {
  outline: none;
  color: var(--sodium);
  border-color: var(--sodium);
  box-shadow: 0 0 0 3px var(--sodium-soft);
}
.diagram-modal__zoom {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--ink-dim);
  min-width: 4ch;
  text-align: center;
  font-variant-numeric: tabular-nums lining-nums;
}
.diagram-modal__body {
  flex: 1;
  position: relative;
  overflow: hidden;
  background: var(--bg);
  cursor: grab;
  user-select: none;
}
.diagram-modal__body.is-panning { cursor: grabbing; }
.diagram-modal__stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.diagram-modal__body svg {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  display: block;
}

/* ── responsive — collapse TOC into a top toggle on small viewports ── */
@media (max-width: 980px) {
  .docs-layout {
    /* minmax(0, 1fr), not 1fr: a bare 1fr track keeps an implicit
       min-width:auto, so a wide table / <pre> / diagram forces the
       whole column past the viewport (page-wide horizontal scroll,
       clipped content). minmax(0,…) lets that content's own
       overflow-x:auto engage instead. */
    grid-template-columns: minmax(0, 1fr);
    padding: 0 var(--space-md);
  }
  .toc {
    position: static;
    /* reset the desktop sticky sidebar's fixed viewport height
       (height: calc(100vh - …)) — otherwise it leaks down here and the
       collapsed disclosure reserves a full screen of empty space above
       the content. Let the TOC size to its content (44px summary when
       closed, the panel when open). */
    height: auto;
    max-height: none;
    overflow: visible;
    padding: var(--space-md) 0 var(--space-md);
    border-bottom: 1px solid var(--rule);
    margin-bottom: var(--space-md);
  }
  /* On narrow viewports the TOC is a collapsed disclosure: the reader
     taps "Contents" to reveal the multi-group nav, so the page content
     (the <h1> and prose) sits right at the top instead of below two
     screens of links. buildTOC() defaults the <details> closed here. */
  .toc-disclosure__summary {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    /* generous tap target — ~2.75rem keeps it comfortably above the 44px
       touch-target floor */
    min-height: 2.75rem;
    padding: var(--space-xs) var(--space-sm);
    /* chrome voice — matches the mono labels used elsewhere */
    font-family: var(--font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-mid);
    background: var(--bg-elev);
    border: 1px solid var(--rule);
    border-radius: 6px;
    cursor: pointer;
    list-style: none; /* belt-and-braces marker suppression */
    user-select: none;
    transition: background 140ms ease, color 140ms ease;
  }
  .toc-disclosure__summary:hover {
    color: var(--sodium);
    background: color-mix(in oklch, var(--ink) 6%, transparent);
  }
  /* native <details><summary> handles aria-expanded itself, but the focus
     ring is ours to provide — never a bare outline:none */
  .toc-disclosure__summary:focus-visible {
    outline: 2px solid var(--sodium);
    outline-offset: 2px;
  }
  .toc-disclosure__caret {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ink-faint);
  }
  /* the disclosure caret points right when closed, down when open —
     mirrors the per-group caret idiom */
  .toc-disclosure[open] .toc-disclosure__caret .toc__caret {
    transform: rotate(90deg);
  }
  .toc-disclosure__label { color: inherit; }
  /* closed: hide the panel; the native <details> does this via [open], but
     we set it explicitly so the desktop "always display:block" rule (which
     wins by source order otherwise) doesn't leak the panel open at <=980px */
  .toc-disclosure:not([open]) .toc-disclosure__panel { display: none; }
  .toc-disclosure__panel {
    padding-top: var(--space-sm);
  }
}

/* ── delight — interactive suns, hover affordances ─── */
.sun {
  cursor: pointer;
  outline: none;
  transition: transform 220ms cubic-bezier(0.2, 0.6, 0.2, 1);
  transform-box: fill-box;
  transform-origin: center;
}
.sun:hover { transform: scale(1.12); }
.sun:active { transform: scale(0.98); }
.sun:focus-visible .sun__disc {
  filter: drop-shadow(0 0 6px var(--sodium));
}
.sun .sun__glow,
.sun .sun__corona,
.sun .sun__disc {
  transition: opacity 220ms ease;
}
.sun:hover .sun__glow   { opacity: 0.18; }
.sun:hover .sun__corona { opacity: 0.40; }
.sun:hover .sun__disc   { opacity: 1.00; }

/* sun click → ignition burst. One quick pop so beat 1 (inhale) ends
   visibly before beat 2 (slide + bloom) begins. */
.sun--burst { animation: sun-burst 300ms cubic-bezier(0.18, 0.7, 0.22, 1.05); }
.sun--burst .sun__glow   { animation: sun-burst-glow   300ms cubic-bezier(0.2, 0.7, 0.2, 1); }
.sun--burst .sun__corona { animation: sun-burst-corona 300ms cubic-bezier(0.2, 0.7, 0.2, 1); }
.sun--burst .sun__disc   { animation: sun-burst-disc   300ms cubic-bezier(0.2, 0.7, 0.2, 1); }
@keyframes sun-burst {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.6); }
  100% { transform: scale(1); }
}
@keyframes sun-burst-glow   { 0%, 100% { opacity: 0.10; } 40% { opacity: 0.85; } }
@keyframes sun-burst-corona { 0%, 100% { opacity: 0.22; } 40% { opacity: 0.95; } }
@keyframes sun-burst-disc {
  0%, 100% { filter: drop-shadow(0 0 0 transparent); opacity: 0.92; }
  40%      { filter: drop-shadow(0 0 20px var(--sodium)); opacity: 1; }
}

/* ── parallax swap — mountain ranges slide past each other on
   regenerate. JS sets inline transforms on .scene-enter wrappers
   inside .cover; CSS owns transition timing, easing, and per-depth
   staggering. Strictly scoped to .cover so spine / TOC / body /
   pager are never touched by these rules. */
.cover .scene-enter,
.cover .scene-exit {
  transform-box: fill-box;
  transform-origin: center;
}
/* will-change only WHILE a layer is in motion. Each .scene-enter
   wrapper persists after it lands (it's the layer for the next
   regen's exit), so a blanket will-change would pin all six layers
   to their own GPU composite layers for the lifetime of the page —
   wasted memory/compositing with nothing animating. settleEnter()
   adds --settled once the entrance transition is armed, which drops
   the hint here; .scene-exit nodes are short-lived (removed ~1100ms)
   so they keep it for their whole life. Purely a compositing hint —
   no effect on the rendered frame. */
.cover .scene-enter:not(.scene-enter--settled),
.cover .scene-exit {
  will-change: transform, opacity;
}
.cover .scene-enter {
  transition:
    transform 760ms cubic-bezier(0.22, 0.72, 0.18, 1),
    opacity  520ms cubic-bezier(0.22, 0.72, 0.18, 1);
}
.cover .scene-enter--depth-back    { transition-delay: 0ms;   }
.cover .scene-enter--depth-ground  { transition-delay: 40ms;  }
.cover .scene-enter--depth-mid     { transition-delay: 90ms;  }
.cover .scene-enter--depth-near    { transition-delay: 170ms; }
.cover .scene-enter--depth-figures { transition-delay: 260ms; }

/* INTRO — first generate() of the page. Slower, more cinematic
   pace: deeper stagger, longer transit, gentler ease. Lets the
   eye register the scene composing itself. Stripped after the
   intro plays so later regens (sun click) feel snappy. */
.cover.cover--intro .scene-enter {
  transition:
    transform 1280ms cubic-bezier(0.22, 0.72, 0.18, 1),
    opacity   920ms cubic-bezier(0.22, 0.72, 0.18, 1);
}
.cover.cover--intro .scene-enter--depth-back    { transition-delay: 0ms;   }
.cover.cover--intro .scene-enter--depth-ground  { transition-delay: 100ms; }
.cover.cover--intro .scene-enter--depth-mid     { transition-delay: 220ms; }
.cover.cover--intro .scene-enter--depth-near    { transition-delay: 400ms; }
.cover.cover--intro .scene-enter--depth-figures { transition-delay: 580ms; }
.cover.cover--intro .ray-emit {
  transition:
    transform 880ms cubic-bezier(0.22, 0.72, 0.18, 1),
    opacity   520ms cubic-bezier(0.22, 0.72, 0.18, 1);
}
.cover.cover--intro .ray-emit--strand {
  transition:
    transform 980ms cubic-bezier(0.22, 0.72, 0.18, 1),
    opacity   600ms cubic-bezier(0.22, 0.72, 0.18, 1);
}

.cover .scene-exit {
  transition:
    transform 620ms cubic-bezier(0.42, 0, 0.30, 1),
    opacity  520ms cubic-bezier(0.42, 0, 0.30, 1);
}
.cover .scene-exit--depth-back    { transition-delay: 60ms; }
.cover .scene-exit--depth-ground  { transition-delay: 20ms; }
.cover .scene-exit--depth-mid     { transition-delay: 30ms; }
.cover .scene-exit--depth-near    { transition-delay: 0ms;  }
.cover .scene-exit--depth-figures { transition-delay: 0ms;  }

/* Lash rays — anchored at their source sun via inline transform-
   origin (set in JS). Default transition is the elegant grow used
   during the BEAT 2.b bloom. The recede on sun click overrides
   inline with a snappier duration. */
.cover .ray-emit {
  transition:
    transform 560ms cubic-bezier(0.22, 0.72, 0.18, 1),
    opacity   360ms cubic-bezier(0.22, 0.72, 0.18, 1);
}
.cover .ray-emit--strand {
  transition:
    transform 680ms cubic-bezier(0.22, 0.72, 0.18, 1),
    opacity   420ms cubic-bezier(0.22, 0.72, 0.18, 1);
}

@media (prefers-reduced-motion: reduce) {
  .cover .scene-enter,
  .cover .scene-exit,
  .cover .ray-emit { transition: opacity 160ms linear !important; }
  .cover .sun--burst,
  .cover .sun--burst .sun__glow,
  .cover .sun--burst .sun__corona,
  .cover .sun--burst .sun__disc { animation: none !important; }
}

/* knot bead — gentle pulse on hover when clickable (links nearby) */
.knot__bead {
  transition: transform 220ms cubic-bezier(0.2, 0.6, 0.2, 1),
              box-shadow 220ms ease;
}
.stanza:hover .knot__bead,
.section:hover .knot__bead {
  transform: scale(1.25);
  box-shadow: 0 0 0 3px var(--bg), 0 0 0 5px var(--sodium-soft);
}

/* CTA fill animation */
.cta { position: relative; overflow: hidden; }
.cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--sodium);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 320ms cubic-bezier(0.2, 0.6, 0.2, 1);
  z-index: -1;
}
.cta:hover { background: transparent; color: var(--bg); }
.cta:hover::after { transform: scaleX(1); }

/* back-to-top link in the cover caption */
.cover__top {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-xs);
  color: var(--ink-dim);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  transition: color 200ms ease;
}
.cover__top .arrow {
  display: inline-block;
  color: var(--sodium);
  transition: transform 280ms cubic-bezier(0.2, 0.6, 0.2, 1);
}
.cover__top:hover { color: var(--sodium); }
.cover__top:hover .arrow { transform: translateY(-3px); }
.cover__top:focus-visible {
  outline: 1px solid var(--sodium);
  outline-offset: 4px;
}

/* opener __title and stanza__title links — subtle slide on hover */
.opener__title a,
.stanza__title a {
  position: relative;
  display: inline-block;
  transition: color 180ms ease;
}
.opener__title a::after,
.stanza__title a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0.04em;
  height: 2px;
  background: var(--sodium);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 320ms cubic-bezier(0.2, 0.6, 0.2, 1);
}
.opener__title a:hover::after,
.stanza__title a:hover::after { transform: scaleX(1); }

/* code blocks — subtle hover glow at the lang tag */
pre { transition: border-color 220ms ease; }
pre:hover { border-color: var(--rule-strong); }

/* listing rows — subtle background tint on hover */
.listing__row { transition: background-color 180ms ease; }
.listing__row:hover { background: var(--bg-faint); }

/* table rows — subtle background tint on hover */
tbody tr { transition: background-color 180ms ease; }
tbody tr:hover { background: var(--bg-faint); }

/* link hover delight — sodium underline that animates in */
.body a:not(.stanza__link):not(.stanza__title a) {
  position: relative;
}

/* ── responsive ─────────────────────────────────────── */
@media (max-width: 820px) {
  :root { --rail: 3rem; }
  .band { padding: var(--space-sm) var(--space-md); font-size: 0.62rem; }
  .band__right { gap: var(--space-sm); }
  .opener {
    grid-template-columns: var(--rail) 1fr;
    column-gap: var(--space-md);
    padding: var(--space-xl) var(--space-md) var(--space-xl);
  }
  .opener__title { font-size: clamp(2.4rem, 9vw, 3.6rem); }
  .opener__lede { font-size: 1.02rem; }
  .body { padding: 0 var(--space-md); }
  .stanza,
  .section {
    grid-template-columns: var(--rail) 1fr;
    column-gap: var(--space-md);
    padding: var(--space-xl) 0;
  }
  .section-header h2,
  .stanza__title,
  .section h2 { font-size: clamp(1.6rem, 6.5vw, 2.2rem); }
  .knot {
    grid-template-columns: auto;
    grid-template-rows: auto;
    padding-top: var(--space-sm);
  }
  .knot__bead { grid-row: 1; grid-column: 1; }
  .knot__id, .knot__name { display: none; }
  .defs,
  .def-list {
    grid-template-columns: 1fr;
    row-gap: var(--space-2xs);
  }
  .defs dt,
  .def-list dt { padding-bottom: var(--space-2xs); border-top: 1px solid var(--rule); }
  .defs dd,
  .def-list dd { padding-top: 0; border-top: none; padding-bottom: var(--space-md); }
  .defs dt:first-of-type,
  .def-list dt:first-of-type { border-top: 1px solid var(--rule-strong); }
  .defs dd:first-of-type,
  .def-list dd:first-of-type { border-top: none; }
  .defs::after,
  .def-list::after { display: none; }
  .listing__row { grid-template-columns: 1fr; row-gap: var(--space-xs); }
  .pager { padding: var(--space-xl) var(--space-md); grid-template-columns: var(--rail) 1fr; column-gap: var(--space-md); }
  .cover__caption { padding: 0 var(--space-md) var(--space-2xl); }
  pre { padding: var(--space-md); font-size: 0.74rem; }
  th, td { padding: var(--space-xs) var(--space-sm); }
}

/* ── cmdk search — band trigger + ⌘K modal ──────────── */
.band__btn--search { gap: 0.55rem; }
.band__btn--search .cmdk-kbd {
  /* shortcut chip — no inner border or background, just dimmed
     text so it reads as a hint, not a nested button */
  font-family: var(--font-mono);
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  color: var(--ink-faint);
  line-height: 1;
}
.band__btn--search:hover .cmdk-kbd,
.band__btn--search:focus-visible .cmdk-kbd {
  color: var(--sodium);
}

.cmdk {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh var(--space-md) var(--space-md);
}
.cmdk.is-open { display: flex; }
html.cmdk-open { overflow: hidden; }

.cmdk__dimmer {
  position: absolute;
  inset: 0;
  background: color-mix(in oklch, var(--bg) 70%, transparent);
  backdrop-filter: blur(2px);
  cursor: pointer;
}
.cmdk__card {
  position: relative;
  width: min(640px, 100%);
  max-height: min(70vh, 640px);
  display: flex;
  flex-direction: column;
  background: var(--bg-elev);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  box-shadow:
    0 1px 0 var(--rule) inset,
    0 22px 60px -20px rgba(0, 0, 0, 0.55),
    0 6px 20px -8px rgba(0, 0, 0, 0.35);
  overflow: hidden;
  font-family: var(--font-body);
}
.cmdk__search-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  border-bottom: 1px solid var(--rule);
  background: var(--bg-faint);
}
/* The input itself strips its border/outline (it reads as a bare search
   field, not a boxed control). The focus ring lives on the row so the
   whole search bar lights up when the field has focus — never a bare
   outline:none. Inset keeps it flush with the card's rounded top edge. */
.cmdk__search-row:focus-within {
  box-shadow: inset 0 0 0 1px var(--sodium);
}
.cmdk__icon {
  color: var(--sodium);
  font-size: 1rem;
  line-height: 1;
}
.cmdk__input {
  flex: 1;
  appearance: none;
  background: transparent;
  border: none;
  outline: none;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.3;
  padding: 0.35rem 0;
}
.cmdk__input::placeholder { color: var(--ink-dim); }
.cmdk__esc {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  padding: 0.18rem 0.4rem;
  background: var(--bg-elev);
  line-height: 1;
}
.cmdk__list {
  list-style: none;
  margin: 0;
  padding: var(--space-xs) 0;
  overflow: auto;
  flex: 1;
}
.cmdk__list li { margin: 0; padding: 0; }
.cmdk__list li::marker { content: none; }
.cmdk__empty {
  padding: var(--space-md) var(--space-md);
  color: var(--ink-faint);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.cmdk__row {
  display: grid;
  grid-template-columns: 5rem 1fr;
  align-items: baseline;
  gap: var(--space-sm);
  padding: 0.55rem var(--space-md);
  color: var(--ink-mid);
  text-decoration: none;
  border-radius: 0;
  transition: background 120ms ease, color 120ms ease;
}
.cmdk__row-kind {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.cmdk__row-body {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
}
.cmdk__row-title {
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.96rem;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmdk__row-heading {
  color: var(--ink-dim);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmdk__row.is-active {
  background: color-mix(in oklch, var(--sodium) 14%, transparent);
  color: var(--ink);
}
.cmdk__row.is-active .cmdk__row-title { color: var(--ink); }
.cmdk__row.is-active .cmdk__row-heading { color: var(--ink-mid); }
.cmdk__row.is-active .cmdk__row-kind { color: var(--sodium); }
.cmdk__hint {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  align-items: center;
  padding: 0.5rem var(--space-md);
  border-top: 1px solid var(--rule);
  background: var(--bg-faint);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.cmdk__hint span { display: inline-flex; align-items: center; gap: 0.35rem; }
.cmdk__hint kbd {
  font-family: var(--font-mono);
  font-size: 0.6rem;
  padding: 0.1rem 0.3rem;
  border: 1px solid var(--rule-strong);
  border-radius: 2px;
  color: var(--ink-dim);
  background: var(--bg-elev);
  line-height: 1;
}

@media (max-width: 640px) {
  .cmdk { padding-top: 6vh; }
  .cmdk__row { grid-template-columns: 4rem 1fr; }
  .band__btn--search .cmdk-label { display: none; }
}

/* ─────────────────────────────────────────────────────────────
   landing · scrolling editorial page
   The scene fills the hero (first fold) as a backdrop; substance
   scrolls beneath it on the warm-iron field, threaded by a sodium
   spine, and the landscape returns as a static horizon footer.
   ────────────────────────────────────────────────────────── */
body.landing { position: relative; background: var(--bg); }
body.landing .hero,
body.landing .stanza { scroll-margin-top: 5rem; }

/* ── fixed band — transparent over the hero, surfaced on scroll ── */
body.landing .band {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 30;
  max-width: none;
  width: 100%;
  margin: 0;
  align-items: center;
  padding-top: var(--space-sm);
  padding-bottom: var(--space-sm);
  /* keep controls aligned to the page-max column while the surface
     spans full width on wide screens */
  padding-left: max(var(--space-xl), calc((100% - var(--page-max)) / 2 + var(--space-xl)));
  padding-right: max(var(--space-xl), calc((100% - var(--page-max)) / 2 + var(--space-xl)));
  /* transparent over the hero scene; .is-solid surfaces it on scroll */
  background: transparent;
  border-bottom: 1px solid transparent;
  /* clicks fall through the empty band to the scene; buttons re-enable */
  pointer-events: none;
  transition: background 240ms ease, border-color 240ms ease;
}
body.landing .band a,
body.landing .band button { pointer-events: auto; }
body.landing .band.is-solid {
  background: var(--bg);
  border-bottom-color: var(--rule);
  pointer-events: auto;
}
.band__wordmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: 0.01em;
  text-transform: lowercase;
  color: var(--ink);
  text-decoration: none;
  line-height: 1;
  opacity: 0;
  transform: translateY(-3px);
  pointer-events: none;
  transition: opacity 240ms ease, transform 240ms ease;
}
.band__wordmark .slash { color: var(--sodium); }
.band__wordmark:hover { color: var(--sodium); }
.band.is-solid .band__wordmark { opacity: 1; transform: none; pointer-events: auto; }

/* ── hero — first fold, scene as backdrop ───────────── */
.hero {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
  isolation: isolate;
}
.hero__scene {                 /* the .cover wrapper around #range */
  position: absolute;
  inset: 0;
  z-index: 0;
  margin: 0;
  pointer-events: none;
  /* dissolve the scene's base into the page so the mountains settle
     into darkness instead of cutting hard against the content below */
  -webkit-mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 82%, transparent 100%);
}
body.landing .cover__svg {
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: auto;        /* sun-click regenerates the scene */
}
/* legibility scrim — a top fade for the band/eyebrow plus a soft
   left veil so the text column stays calm over the scene's brazier,
   while the figure + suns on the right read clearly. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to bottom,
      var(--bg) 0%,
      color-mix(in oklch, var(--bg) 0%, transparent) 24%),
    linear-gradient(to right,
      color-mix(in oklch, var(--bg) 80%, transparent) 0%,
      color-mix(in oklch, var(--bg) 0%, transparent) 46%);
}
.hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-3xl) var(--space-xl) var(--space-2xl);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
  /* let clicks on empty hero space fall through to the scene */
  pointer-events: none;
}
.hero__inner > * { max-width: 100%; }
.hero__inner a,
.hero__inner button { pointer-events: auto; }

.hero__eyebrow {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sodium);
}
.hero__wordmark {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(3.5rem, 9vw, 7rem);
  line-height: 0.9;
  letter-spacing: -0.02em;
  text-transform: lowercase;
  color: var(--ink);
}
.hero__wordmark .slash,
.hero__statement .slash {
  /* the period is the ember — static sodium with a small glow. The
     brazier flame below is the moving element; the wordmark holds
     still (calm over long sessions). */
  color: var(--sodium);
  filter:
    drop-shadow(0 0 10px color-mix(in oklch, var(--sodium) 50%, transparent))
    drop-shadow(0 0 2px  color-mix(in oklch, var(--sodium) 80%, transparent));
}
.hero__statement {
  margin: calc(-1 * var(--space-2xs)) 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.5rem, 3.4vw, 2.7rem);
  line-height: 1;
  letter-spacing: -0.01em;
  text-transform: lowercase;
  color: var(--ink);
}
.hero__lede {
  margin: var(--space-sm) 0 0;
  max-width: 56ch;
  font-family: var(--font-body);
  font-size: clamp(1.04rem, 1.4vw, 1.24rem);
  line-height: 1.58;
  color: var(--ink);
}
.hero__lede em { font-style: normal; color: var(--sodium); font-weight: 500; }
.hero__cta-row {
  margin-top: var(--space-md);
  display: flex;
  align-items: center;
  gap: var(--space-md);
  flex-wrap: wrap;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.hero__ghlink {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  color: var(--ink-mid);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: color 160ms ease, border-color 160ms ease;
}
.hero__ghlink:hover { color: var(--sodium); border-bottom-color: var(--sodium); }
.hero__scrollcue {
  position: absolute;
  left: 50%;
  bottom: var(--space-lg);
  transform: translateX(-50%);
  z-index: 3;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-dim);
  text-decoration: none;
  pointer-events: auto;
  transition: color 160ms ease;
}
.hero__scrollcue:hover { color: var(--sodium); }
.hero__scrollcue-mark {
  font-size: 0.85rem;
  letter-spacing: 0;
  animation: cue-bob 2.4s ease-in-out infinite;
}
@keyframes cue-bob {
  0%, 100% { transform: translateY(0); opacity: 0.55; }
  50%      { transform: translateY(3px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hero__scrollcue-mark { animation: none; }
}

/* ── narrow screens: stack the hero (text, then a scene band) ──
   Below 1000px there isn't room to seat the scene's figures beside
   the headline, so the scene drops to a band under the text instead
     of sitting behind it. scene.js drops its clearX reserve at
   the same width, so the landscape uses the full band. */
@media (max-width: 999px) {
  .hero { min-height: 0; justify-content: flex-start; }
  .hero::before { display: none; }
  .hero__inner {
    order: 0;
    padding-top: calc(var(--space-3xl) + 1.5rem);
    padding-bottom: var(--space-lg);
  }
  .hero__scene {
    order: 1;
    position: relative;
    inset: auto;
    height: clamp(240px, 46vh, 420px);
  }
  .hero__scrollcue { display: none; }
}

/* ── sodium spine threaded down the landing body ────── */
body.landing .body {
  position: relative;
  padding-top: var(--space-md);
  padding-bottom: var(--space-2xl);
}
body.landing .body::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  left: calc(var(--space-xl) + var(--rail) * 14 / 120);
  width: 1px;
  background: var(--sodium);
  opacity: 0.5;
  z-index: 0;
  pointer-events: none;
  /* fade the thread in at the top (it grows out of the ember below
     the dissolving hero) and out at the bottom (before the footer) */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 5%, #000 87%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 5%, #000 87%, transparent 100%);
}
/* the ember the spine grows from — the head of the thread, sitting
   in the dark just under the dissolving hero scene */
body.landing .body::after {
  content: "";
  position: absolute;
  top: 0;
  left: calc(var(--space-xl) + var(--rail) * 14 / 120 - 3px);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sodium);
  box-shadow:
    0 0 10px 2px color-mix(in oklch, var(--sodium) 50%, transparent),
    0 0 3px 1px  color-mix(in oklch, var(--sodium) 80%, transparent);
  z-index: 0;
  pointer-events: none;
}

/* ── ledger — the inversion contrast (two hairline cells) ── */
.ledger {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin: var(--space-lg) 0 var(--space-xl);
  border-top: 1px solid var(--rule-strong);
  border-bottom: 1px solid var(--rule-strong);
}
.ledger__cell { padding: var(--space-lg) var(--space-lg) var(--space-lg) 0; }
.ledger__cell + .ledger__cell {
  border-left: 1px solid var(--rule);
  padding-left: var(--space-lg);
}
.ledger__eyebrow {
  margin: 0 0 var(--space-xs);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.ledger__cell--lash .ledger__eyebrow { color: var(--sodium); }
.ledger__body {
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.58;
  color: var(--ink-mid);
  max-width: 42ch;
}
.ledger__cell--lash .ledger__body { color: var(--ink); }

/* ── architecture stack (§01) ───────────────────────── */
.stack {
  /* No panel of its own — the SVG's host-application frame is the only
     box, so the diagram sits directly on the page instead of nesting a
     bordered card inside a bordered frame. */
  margin: var(--space-lg) 0 var(--space-md);
  position: relative;
}
.stack__svg {
  display: block;
  width: 100%;
  height: auto;
}
.stack__host {
  fill: color-mix(in oklch, var(--bg) 80%, transparent);
  stroke: var(--rule);
  stroke-width: 1.4;
}
.stack__title {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: 0.035em;
  text-transform: uppercase;
  fill: var(--ink);
}
.stack__title--host {
  font-size: 28px;
  fill: var(--ink);
}
.stack__title--core {
  font-size: 26px;
  fill: var(--ink);
}
.stack__copy,
.stack__eyebrow,
.stack__port text,
.stack__hook text,
.stack__flow text,
.stack__commit-title {
  font-family: var(--font-mono);
  font-size: 16px;
  letter-spacing: 0.01em;
  fill: var(--ink-dim);
}
.stack__copy--host {
  font-size: 17px;
  fill: var(--ink-mid);
}
.stack__copy--core-row {
  font-size: 16px;
  fill: var(--ink-mid);
}
.stack__eyebrow {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  fill: var(--ink-dim);
}
.stack__core-shell {
  fill: color-mix(in oklch, var(--code-bg) 86%, transparent);
  stroke: color-mix(in oklch, var(--sodium) 16%, var(--ink-dim));
  stroke-width: 2;
}

/* plugin hooks compose the core's left edge — structure, not flow */
.stack__hook path {
  fill: none;
  stroke: var(--ink-dim);
  stroke-width: 1.6;
  stroke-linecap: round;
}
.stack__hook circle {
  fill: var(--ink-dim);
  stroke: none;
}
.stack__hook text {
  font-size: 15px;
  font-weight: 700;
  fill: var(--ink-mid);
}

/* host-owned resources across the boundary */
.stack__port rect {
  fill: color-mix(in oklch, var(--code-bg) 80%, transparent);
  stroke: var(--rule);
  stroke-width: 2;
}
.stack__port text {
  font-size: 16px;
  fill: var(--ink);
}

/* the typed boundary: the runtime's right edge — the active edge */
.stack__membrane {
  fill: none;
  stroke: var(--sodium);
  stroke-width: 2.4;
  stroke-dasharray: 2 5;
  stroke-linecap: round;
  filter: drop-shadow(0 0 4px color-mix(in oklch, var(--sodium) 45%, transparent));
}
.stack__boundary-label {
  font-family: var(--font-mono);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  fill: color-mix(in oklch, var(--sodium) 82%, var(--ink));
}

/* effect / outcome crossings + the per-turn atomic commit */
.stack__flow-line,
.stack__return-line,
.stack__commit-line {
  fill: none;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.stack__flow-line {
  stroke: var(--sodium);
  marker-end: url("#stack-arrow-sodium");
}
.stack__return-line {
  stroke: var(--sodium-deep);
  marker-end: url("#stack-arrow-return");
}
.stack__flow text {
  font-size: 15px;
  fill: var(--sodium);
}
.stack__flow .stack__flow-label--back { fill: var(--sodium-deep); }
.stack__commit-line {
  stroke: var(--sodium);
  stroke-dasharray: 7 5;
  marker-end: url("#stack-arrow-sodium");
}
.stack__commit-title {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.06em;
  fill: var(--sodium);
}

/* animated overlay — one turn traced through the runtime.
   Hidden by default; the turn-trace driver fades each pulse in as it
   sweeps, so the static diagram stands alone without JS or motion. */
.stack__signals path,
.stack__glows rect,
.stack__glows circle,
.stack__glows path { opacity: 0; }
.stack__sig {
  fill: none;
  stroke: var(--sodium-deep);
  stroke-width: 3.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 9 220;
  filter: drop-shadow(0 0 3px color-mix(in oklch, var(--sodium) 72%, transparent));
}
.stack__sig--commit { stroke: var(--sodium); }
.stack__glow {
  fill: none;
  stroke: var(--sodium);
  stroke-width: 2.6;
  filter: drop-shadow(0 0 6px color-mix(in oklch, var(--sodium) 58%, transparent));
}
.stack__glow--line { stroke-width: 2.6; }
.stack__glow--hook {
  fill: var(--sodium);
  stroke: none;
  filter: drop-shadow(0 0 4px color-mix(in oklch, var(--sodium) 70%, transparent));
}
@media (prefers-reduced-motion: reduce) {
  .stack__signals path,
  .stack__glows rect,
  .stack__glows circle,
  .stack__glows path { opacity: 0 !important; }
}
@media (max-width: 560px) {
  .stack {
    overflow-x: auto;
    scrollbar-color: var(--sodium) transparent;
  }
  .stack__svg {
    min-width: 760px;
  }
}

/* ── listing rows as links (read-on track) ──────────── */
a.listing__row {
  text-decoration: none;
  color: inherit;
  align-items: center;
  transition: background 150ms ease;
}
a.listing__row:hover { background: var(--bg-elev); }
a.listing__row:hover .listing__label { color: var(--sodium-deep); }
a.listing__row .listing__label::after {
  content: " →";
  color: var(--sodium);
  opacity: 0;
  transition: opacity 150ms ease;
}
a.listing__row:hover .listing__label::after { opacity: 1; }
a.listing__row:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring, 0 0 0 3px var(--sodium-soft));
}

/* ── landscape footer — static horizon reprise ──────── */
.landing-foot {
  position: relative;
  margin-top: var(--space-3xl);
  background: var(--bg);
  border-top: 1px solid var(--rule);
}
.landing-foot__horizon {
  display: block;
  width: 100%;
  height: clamp(72px, 11vh, 132px);
}
.landing-foot__range--far  { fill: var(--range-mid-shadow); }
.landing-foot__range--near { fill: var(--range-near-shadow); }
.landing-foot__ember {
  fill: var(--sodium);
  filter: drop-shadow(0 0 6px color-mix(in oklch, var(--sodium) 55%, transparent));
}
.landing-foot__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--space-xl) var(--space-xl) var(--space-3xl);
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-lg);
  flex-wrap: wrap;
}
.landing-foot__mark { display: flex; flex-direction: column; gap: var(--space-3xs); }
.landing-foot__word {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 5vw, 3rem);
  line-height: 0.9;
  letter-spacing: -0.02em;
  text-transform: lowercase;
  color: var(--ink);
}
.landing-foot__word .slash { color: var(--sodium); }
.landing-foot__tag {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.landing-foot__links {
  display: flex;
  align-items: baseline;
  gap: var(--space-lg);
  flex-wrap: wrap;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.landing-foot__links a {
  color: var(--ink-mid);
  display: inline-flex;
  align-items: center;
  gap: var(--space-3xs);
  transition: color 150ms ease;
}
.landing-foot__links a:hover { color: var(--sodium); }

/* ── landing mobile ─────────────────────────────────── */
@media (max-width: 820px) {
  body.landing .band {
    padding-left: var(--space-md);
    padding-right: var(--space-md);
  }
  .hero__inner { padding: var(--space-3xl) var(--space-md) var(--space-2xl); }
  body.landing .body::before {
    left: calc(var(--space-md) + var(--rail) * 14 / 120);
  }
  body.landing .body::after {
    left: calc(var(--space-md) + var(--rail) * 14 / 120 - 3px);
  }
  .ledger { grid-template-columns: 1fr; }
  .ledger__cell { padding: var(--space-md) 0; border-top: 1px solid var(--rule); }
  .ledger__cell:first-child { border-top: none; padding-top: 0; }
  .ledger__cell + .ledger__cell { border-left: none; padding-left: 0; }
  /* stack what's-inside panels (label over body) so they don't strand
     in a cramped two-column layout on narrow screens */
  body.landing .panel { grid-template-columns: 1fr; row-gap: var(--space-2xs); }
  body.landing .panel > small { grid-column: 1; grid-row: auto; }
  body.landing .panel > h3,
  body.landing .panel > p { grid-column: 1; }
  .landing-foot__inner { padding: var(--space-lg) var(--space-md) var(--space-2xl); }
}
