/* =====================================================================
   ANTAEUS — web design tokens
   ---------------------------------------------------------------------
   A direct port of src/theme/{colors,typography,spacing,radius}.ts.
   The app is the source of truth: when a token changes there, change it
   here, with the same name. Nothing on this site should introduce a
   colour, size, or radius that the app doesn't have.

   Doctrine: docs/design-reference/LEDGER_SPEC.md (APPROVED 2026-08-24),
   which outranks the older INSTRUMENT_SPEC for layout and chrome:
     1. The margin belongs to time and the coach. Position says who
        acted; prose never says "the coach said".
     2. Entries, not cards. A 2px rule head starts a section; hairlines
        separate rows. Containers are for the ONE commit and for sheets.
     3. One scan path — mono labels left, figures in a fixed column.
     4. Type does hierarchy. No fills, no badges, no pills doing rank.
     5. Accent is EARNED only; amber is the coach; hue never carries
        meaning alone.
   ===================================================================== */

/* --- faces (self-hosted; both are SIL OFL, safe to serve) ----------- */
@font-face {
  font-family: 'Barlow SC';
  src: url('fonts/BarlowSemiCondensed-Medium.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'Barlow SC';
  src: url('fonts/BarlowSemiCondensed-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('fonts/IBMPlexMono-Regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Plex Mono';
  src: url('fonts/IBMPlexMono-Medium.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}

:root {
  /* --- typography ------------------------------------------------- */
  --f-sys: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI',
    Roboto, 'Helvetica Neue', sans-serif;
  --f-display: 'Barlow SC', 'Helvetica Neue Condensed', Impact, sans-serif;
  --f-mono: 'Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* --- spacing (spacing.ts) --------------------------------------- */
  --s-xxs: 2px;
  --s-xs: 4px;
  --s-sm: 8px;
  --s-md: 12px;
  --s-lg: 16px;
  --s-xl: 20px;
  --s-xxl: 24px;
  --s-xxxl: 32px;
  --s-huge: 48px;

  /* --- radius (radius.ts) — chamfer, never pill -------------------- */
  --r-xs: 2px;
  --r-sm: 4px;
  --r-md: 6px;
  --r-lg: 8px;
  --r-xl: 12px;

  --maxw: 1080px;
  --gutter: 32px;

  /* --- the ledger chassis (LEDGER_SPEC §3) ------------------------ */
  --mgn: 96px;        /* margin column: marks live here */
  --mgn-pad: 12px;    /* spine → content */
  --tick-w: 3px;      /* the coach's margin tick */

  /* --- DARK is the app's default; declared here so an un-stamped
         document with a dark OS lands on it via the media query below,
         and so [data-theme="dark"] can force it. Light is the bare
         :root fallback further down. ------------------------------- */
}

/* =====================================================================
   LIGHT — the app's lightPalette, verbatim. NOT an inversion: it was
   contrast-tuned on its own terms (textMuted #6B6B73 is ~7:1 on white,
   an explicit audit fix), and accent drops to the darker green that
   survives on a white ground.
   ===================================================================== */
:root {
  --bg: #f4f4f5;
  --surface: #ffffff;
  --card: #ffffff;
  --card-el: #ffffff;
  --border: #e0e0e3;
  --border-sub: #ececef;

  --t1: #0a0a0b;
  --t2: #52525a;
  --t3: #6b6b73;

  --accent: #1f8a3a;
  --accent-muted: #0d5c24;
  --accent-soft: rgba(31, 138, 58, 0.1);

  --danger: #b83b3b;
  --danger-soft: rgba(184, 59, 59, 0.1);
  --warn: #8f6404;
  --warn-soft: rgba(143, 100, 4, 0.1);
  --tip: #b58500;
  --info: #3460c2;
  --info-soft: rgba(52, 96, 194, 0.1);

  --ring-train: #b8355c;
  --ring-fuel: #0f7280;

  --ghost: rgba(10, 10, 11, 0.58);
  --ghost-outline: rgba(10, 10, 11, 0.45);
  --tick: #d4d4d9;
  --lift: #ffffff;
  --keycap: #e6e6ea;
  --inverse: #0a0a0b;
  --inverse-text: #f4f4f5;

  --overlay: rgba(0, 0, 0, 0.4);
  --shadow: 0 1px 2px rgba(10, 10, 11, 0.06), 0 8px 24px rgba(10, 10, 11, 0.06);

  color-scheme: light;
}

/* --- DARK via system preference, unless light was explicitly chosen -- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --bg: #09090b;
    --surface: #0f0f12;
    --card: #141417;
    --card-el: #1a1a1e;
    --border: #222226;
    --border-sub: #1a1a1e;

    --t1: #f2f2f4;
    --t2: #a1a1a8;
    --t3: #8a8a92;

    --accent: #86e07b;
    --accent-muted: #4a8542;
    --accent-soft: rgba(134, 224, 123, 0.1);

    --danger: #e0655a;
    --danger-soft: rgba(224, 101, 90, 0.12);
    --warn: #e0a64b;
    --warn-soft: rgba(224, 166, 75, 0.12);
    --tip: #f2c94c;
    --info: #6e9bdd;
    --info-soft: rgba(110, 155, 221, 0.12);

    --ring-train: #e4589b;
    --ring-fuel: #45c4ce;

    --ghost: rgba(242, 242, 244, 0.55);
    --ghost-outline: rgba(242, 242, 244, 0.38);
    --tick: #2a2a2f;
    --lift: #17171b;
    --keycap: #26262b;
    --inverse: #f2f2f4;
    --inverse-text: #0b0b0d;

    --overlay: rgba(0, 0, 0, 0.6);
    --shadow: 0 3px 8px rgba(0, 0, 0, 0.12), 0 24px 60px rgba(0, 0, 0, 0.45);

    color-scheme: dark;
  }
}

/* --- DARK forced by the toggle -------------------------------------- */
:root[data-theme='dark'] {
  --bg: #09090b;
  --surface: #0f0f12;
  --card: #141417;
  --card-el: #1a1a1e;
  --border: #222226;
  --border-sub: #1a1a1e;

  --t1: #f2f2f4;
  --t2: #a1a1a8;
  --t3: #8a8a92;

  --accent: #86e07b;
  --accent-muted: #4a8542;
  --accent-soft: rgba(134, 224, 123, 0.1);

  --danger: #e0655a;
  --danger-soft: rgba(224, 101, 90, 0.12);
  --warn: #e0a64b;
  --warn-soft: rgba(224, 166, 75, 0.12);
  --tip: #f2c94c;
  --info: #6e9bdd;
  --info-soft: rgba(110, 155, 221, 0.12);

  --ring-train: #e4589b;
  --ring-fuel: #45c4ce;

  --ghost: rgba(242, 242, 244, 0.55);
  --ghost-outline: rgba(242, 242, 244, 0.38);
  --tick: #2a2a2f;
  --lift: #17171b;
  --keycap: #26262b;
  --inverse: #f2f2f4;
  --inverse-text: #0b0b0d;

  --overlay: rgba(0, 0, 0, 0.6);
  --shadow: 0 3px 8px rgba(0, 0, 0, 0.12), 0 24px 60px rgba(0, 0, 0, 0.45);

  color-scheme: dark;
}

/* =====================================================================
   RESET + BASE
   ===================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--t2);
  font-family: var(--f-sys);
  font-size: 15px;
  line-height: 22px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
svg {
  max-width: 100%;
  display: block;
}

a {
  color: var(--t1);
  text-decoration-color: var(--border);
  text-underline-offset: 3px;
}
a:hover {
  text-decoration-color: currentColor;
}

/* Focus: a real, visible ring in both themes (the app has no hover, so
   the web version must at least be keyboard-honest). */
:focus-visible {
  outline: 2px solid var(--t1);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

::selection {
  background: var(--accent-soft);
  color: var(--t1);
}

/* =====================================================================
   TYPE REGISTERS — the app's three, and only these three.
   ===================================================================== */

/* Measurement register: Barlow Semi Condensed, tabular. Numerals and
   the one editorial headline size. Never below 15px. */
.display {
  font-family: var(--f-display);
  font-weight: 600;
  letter-spacing: -0.2px;
  color: var(--t1);
  margin: 0;
}
.metric {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 20px;
  line-height: 24px;
  letter-spacing: -0.2px;
  font-variant-numeric: tabular-nums;
  color: var(--t1);
}
.metric-lg {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 30px;
  line-height: 34px;
  letter-spacing: -0.4px;
  font-variant-numeric: tabular-nums;
  color: var(--t1);
}
.exercise {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 22px;
  line-height: 26px;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  color: var(--t1);
}
.agate {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.2px;
  font-variant-numeric: tabular-nums;
}
.ghost-fig {
  font-family: var(--f-display);
  font-weight: 500;
  font-size: 20px;
  line-height: 24px;
  font-variant-numeric: tabular-nums;
  color: var(--ghost);
}

/* Micro register: IBM Plex Mono, ALWAYS CAPS for overlines. The app's
   connective tissue — section heads, labels, units, legends, buttons. */
.mono {
  font-family: var(--f-mono);
  font-weight: 500;
  font-size: 11px;
  line-height: 14px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--t3);
}
.mono-13 {
  font-family: var(--f-mono);
  font-weight: 500;
  font-size: 13px;
  line-height: 18px;
  letter-spacing: 0.4px;
  font-variant-numeric: tabular-nums;
  color: var(--t3);
}

/* Prose register: system face, invisible and fast. */
.lede {
  font-size: 17px;
  line-height: 26px;
  color: var(--t2);
}
.cap {
  font-size: 13px;
  line-height: 18px;
  color: var(--t2);
  font-variant-numeric: tabular-nums;
}
.strong {
  font-weight: 600;
  color: var(--t1);
  font-variant-numeric: tabular-nums;
}

/* =====================================================================
   THE LEDGER GRAMMAR — ports of the app's shared components.
   ===================================================================== */

/* SectionRule: mono overline caps sitting ON a hairline rule, with an
   optional right-aligned caption. Never floating bold text. */
.rule {
  display: flex;
  align-items: flex-end;
  gap: var(--s-sm);
  padding-bottom: var(--s-sm);
  border-bottom: 1px solid var(--border);
  margin: 0 0 var(--s-md);
}
.rule > .mono:first-child {
  color: var(--t2);
}
.rule .rule-cap {
  margin-left: auto;
  text-align: right;
  font-size: 13px;
  line-height: 18px;
  color: var(--t3);
}

/* LedgerStatRow: fixed mono label column, figure in the measurement
   face, baseline-aligned. The anti-KPI-tile. */
.lrow {
  display: flex;
  align-items: baseline;
  gap: var(--s-md);
  min-height: 28px;
  padding: var(--s-xs) 0;
}
.lrow > .mono:first-child {
  width: 116px;
  flex: none;
}
.lrow .lrow-val {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 20px;
  line-height: 24px;
  font-variant-numeric: tabular-nums;
  color: var(--t1);
}
.lrow .lrow-suffix {
  margin-left: var(--s-xs);
}

/* Ruled record rows — the app's `entryRow` + hairline separation. */
.entries > * + * {
  border-top: 1px solid var(--border-sub);
}
/* ⚠️ ONE DEFINITION. `.entry` was declared here as a flex record row AND
   again in styles-12.css as a bare `position: relative`, with different
   stated meanings and no comment linking them; which properties an entry
   actually had depended on the link order of two stylesheets. They are
   the same concept — a record row that its margin mark hangs from — so
   `position: relative` belongs here, with the row. */
.entry {
  display: flex;
  gap: var(--s-md);
  padding: var(--s-md) 0;
  align-items: flex-start;
  position: relative;
}
/* The margin tick: a 2×14 ink stroke at the left edge of a record row. */
.tick {
  width: 2px;
  height: 14px;
  background: var(--t1);
  flex: none;
  margin-top: 3px;
}
.tick.ok { background: var(--accent); }
.tick.warn { background: var(--warn); }
.tick.over { background: var(--danger); }
.tick.none { background: var(--tick); }

/* AppButton: an outlined chamfered ledger cell. Hierarchy reads from
   border + label colour; labels are mono caps. The one exception is
   .primary, which is the commit slab — see below. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-sm);
  min-height: 44px;
  padding: var(--s-sm) var(--s-lg);
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--t2);
  font-family: var(--f-mono);
  font-weight: 500;
  font-size: 13px;
  line-height: 16px;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 120ms ease, opacity 120ms ease;
}
.btn:hover { background: var(--lift); }
.btn:active { opacity: 0.85; }
/* The ONE commit (LEDGER_SPEC §9) — an inverse slab, not an outlined
   cell. This is the only filled control in the system, and a page may
   carry one action that wears it. */
.btn.primary {
  border-color: var(--inverse);
  background: var(--inverse);
  color: var(--inverse-text);
}
.btn.primary:hover { background: var(--inverse); opacity: 0.88; }
/* Accent is a COMPLETION colour. On this site it appears on exactly one
   thing per page — never on a nav item or a workflow button. */
.btn.accent {
  border-color: var(--accent);
  color: var(--accent);
}
.btn.ghost {
  border-color: transparent;
  color: var(--t1);
  padding-left: 0;
  padding-right: 0;
}
.btn.lg { min-height: 52px; padding: var(--s-md) var(--s-xl); }
.btn.sm { min-height: 36px; padding: var(--s-xs) var(--s-md); font-size: 11px; }
.btn[disabled],
.btn[aria-disabled='true'] {
  opacity: 0.45;
  pointer-events: none;
}

/* EmptyState: the unwritten ledger entry — a DASHED chamfered slot,
   left-aligned, one strong line + one muted line + one quiet action.
   The only dashed border in the system. */
.empty {
  border: 1px dashed var(--border);
  border-radius: var(--r-sm);
  padding: var(--s-lg);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-xs);
}
.empty h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--t1);
}
.empty p {
  margin: 0;
  font-size: 13px;
  line-height: 18px;
  color: var(--t3);
  max-width: 46ch;
}

/* Coach annotation (LEDGER_SPEC §8): a tip tick in the MARGIN, a mono
   kicker, one sentence. No box, no fill, and no bulb — the glyph is
   banned app-wide, because POSITION is what says who spoke.

   ⚠️ THE TICK IS OFFSET FROM THE CALLOUT, NOT FROM THE SPINE. `.callout`
   is itself `position: relative`, so it — not any ancestor — is the
   containing block, and it must be, because the tick takes its VERTICAL
   extent from this element. The offset therefore only lands in a margin
   when the callout's left edge IS a ledger's content edge. An earlier
   comment here claimed a `.ledger-page` ancestor was doing the
   positioning, which was never true and hid the bug: nested callouts
   painted detached bars mid-page. Containers that host callouts away
   from the page spine carry their own margin (`.ledger`, `.tool-out` in
   styles-12.css). Put a callout somewhere new and give it a chassis. */
.callout {
  position: relative;
  padding: var(--s-xs) 0;
}
.callout::before {
  content: '';
  position: absolute;
  left: calc(-1 * (var(--mgn-pad) + var(--tick-w) + 5px));
  top: 3px;
  bottom: 3px;
  width: var(--tick-w);
  background: var(--tip);
}
.callout p { margin: var(--s-xxs) 0 0; color: var(--t1); font-weight: 600; }
.callout .cap { font-weight: 400; color: var(--t2); }

/* ⚠️ NOT THE COACH. Someone else's words, or a plain status fact.
   `.callout.ok` and `.callout.info` used to carry this with a coloured
   left border; when the callout was rebuilt as a bare amber tick both
   modifiers were deleted from the stylesheet but left in the markup, so
   a submitter's own quoted sentence and the waitlist receipt started
   speaking in the coach's voice. CLAUDE.md is explicit: never lend the
   coach's mark to the athlete's own words. An ink hairline at the
   block's own edge is a quotation; the amber tick in the margin is the
   coach, and the two must not be confusable. */
.aside {
  padding: var(--s-xs) 0 var(--s-xs) var(--s-md);
  border-left: 1px solid var(--border);
}
.aside p { margin: var(--s-xxs) 0 0; color: var(--t1); }
.aside .cap { color: var(--t2); }

/* Inputs: flat blocks with a hairline bottom border, never outlined
   pills (INSTRUMENT_SPEC §5). */
.field {
  width: 100%;
  background: var(--surface);
  color: var(--t1);
  border: 1px solid var(--border-sub);
  border-bottom-color: var(--border);
  border-radius: var(--r-sm);
  padding: var(--s-md);
  font-family: var(--f-sys);
  font-size: 16px; /* ≥16 so iOS doesn't zoom on focus */
  line-height: 22px;
  min-height: 48px;
}
.field::placeholder { color: var(--t3); }
.field:focus-visible {
  outline: 2px solid var(--t1);
  outline-offset: 1px;
}
textarea.field {
  min-height: 104px;
  resize: vertical;
}
select.field {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--t3) 50%),
    linear-gradient(135deg, var(--t3) 50%, transparent 50%);
  background-position: calc(100% - 20px) 22px, calc(100% - 14px) 22px;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 40px;
}

/* =====================================================================
   LAYOUT
   ===================================================================== */
.wrap {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* The machinist ruler that used to live here — a fixed hairline and tick
   marks at left:22px — is GONE, and deliberately.

   The ledger chassis draws a spine at the margin's right edge, so the
   ruler put a SECOND continuous vertical rule on every page, ~100px to
   its left and unable to align with it at any width (the ruler was
   viewport-fixed; the spine tracks the centred wrap). That is the
   defect the app ruled out in `8a7ad4b — Ledger: the page has one left
   edge`, and the same rule binds here.

   The spine is the better version of the same idea: it is the page's
   measured left edge, and unlike the ruler it carries information —
   marks hang off it. If the ruler is ever wanted back, the spine is
   what it would have to replace, not sit beside. */

/* =====================================================================
   NAV + FOOTER
   ===================================================================== */
.nav {
  position: sticky;
  top: 0;
  z-index: 20;
  /* Opaque, not 92% — once the bar actually stuck, the page text slid
     under it and showed through the wordmark. Translucent chrome over
     moving content is the glass effect this design system rejects
     anyway; there is no blur to hide behind. */
  background: var(--bg);
  /* iOS lets the page scroll UNDER the status bar, and a bar stuck at
     top:0 stops short of it — so lines of body text drifted across the
     notch above the wordmark. Growing the bar by the safe-area inset
     paints its own background up there instead. */
  padding-top: env(safe-area-inset-top, 0px);
  border-bottom: 1px solid var(--border-sub);
}
.nav-in {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: var(--s-md) var(--gutter);
  display: flex;
  align-items: center;
  gap: var(--s-lg);
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s-sm);
  text-decoration: none;
  color: var(--t1);
}
.brand svg { width: 22px; height: 22px; }
.brand span {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: var(--s-lg);
  margin-left: auto;
}
.nav-links a {
  font-family: var(--f-mono);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--t3);
  text-decoration: none;
  padding: var(--s-sm) 0;
}
.nav-links a:hover { color: var(--t1); }
.nav-links a[aria-current='page'] {
  color: var(--t1);
  box-shadow: inset 0 -2px 0 var(--t1);
}
/* The nav's one control: an outlined cell at the link's own type size,
   never the filled slab (that is the hero's, once per page). Declared
   after `.nav-links a` because that rule's specificity would otherwise
   strip the border and padding back off. */
.nav-links .btn {
  min-height: 34px;
  padding: 0 var(--s-md);
  font-size: 11px;
  letter-spacing: 1.2px;
  color: var(--t1);
  border-color: var(--border);
}

/* Theme toggle — an InkCell, exactly like the app's segment control. */
.theme-toggle {
  display: inline-flex;
  border: 1px solid var(--border-sub);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--lift);
}
.theme-toggle button {
  min-width: 34px;
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background: transparent;
  color: var(--t3);
  cursor: pointer;
  padding: 0 var(--s-sm);
}
.theme-toggle button[aria-pressed='true'] {
  color: var(--t1);
  box-shadow: inset 0 0 0 1px var(--t1);
  border-radius: var(--r-xs);
}
.theme-toggle svg { width: 15px; height: 15px; }

/* Mobile disclosure menu. <details> so it opens with no JavaScript;
   theme.js only adds the niceties (close on Escape, on outside tap, and
   after following a link). Hidden above the breakpoint, where the full
   link row fits. */
.navmenu { position: relative; margin-left: auto; display: none; }
.navmenu > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: var(--s-sm);
  min-height: 36px;
  padding: 0 var(--s-sm) 0 var(--s-md);
  border: 1px solid var(--border-sub);
  border-radius: var(--r-sm);
  background: var(--lift);
  color: var(--t2);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
}
.navmenu > summary::-webkit-details-marker { display: none; }
.navmenu > summary::marker { content: ''; }
.navmenu > summary:focus-visible { outline: 2px solid var(--t1); outline-offset: 1px; }
/* Three ruled bars — the same hairline vocabulary as the section rules,
   not a rounded icon-font glyph. */
.navmenu-bars,
.navmenu-bars::before,
.navmenu-bars::after {
  display: block;
  width: 15px;
  height: 1.5px;
  background: currentColor;
  content: '';
}
.navmenu-bars { position: relative; }
.navmenu-bars::before { position: absolute; top: -5px; }
.navmenu-bars::after { position: absolute; top: 5px; }
.navmenu[open] > summary { color: var(--t1); box-shadow: inset 0 0 0 1px var(--t1); }
.navmenu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--s-sm));
  min-width: 210px;
  display: flex;
  flex-direction: column;
  padding: var(--s-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: 0 12px 28px rgb(0 0 0 / 28%);
}
.navmenu-panel a {
  padding: var(--s-md);
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--t2);
  text-decoration: none;
  border-bottom: 1px solid var(--border-sub);
}
.navmenu-panel a:last-of-type { border-bottom: 0; }
.navmenu-panel a:hover { color: var(--t1); }
.navmenu-panel a[aria-current='page'] { color: var(--t1); }
.navmenu-panel .btn {
  margin-top: var(--s-sm);
  justify-content: center;
  border-bottom: 1px solid var(--accent);
}

.site-footer {
  border-top: 1px solid var(--border-sub);
  margin-top: var(--s-huge);
  padding: var(--s-xxl) 0 var(--s-huge);
}
.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-lg) var(--s-xxl);
  align-items: baseline;
}
.site-footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-lg);
  margin-left: auto;
}
.site-footer a {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--t3);
  text-decoration: none;
}
.site-footer a:hover { color: var(--t1); }

/* =====================================================================
   UTILITIES
   ===================================================================== */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--card);
  color: var(--t1);
  padding: var(--s-md);
  z-index: 100;
  border: 1px solid var(--t1);
  border-radius: var(--r-sm);
}
.skip:focus { left: var(--s-md); top: var(--s-md); }

.ok { color: var(--accent); }
.warn-c { color: var(--warn); }
.over-c { color: var(--danger); }
.muted { color: var(--t3); }
.t2 { color: var(--t2); }
.t1 { color: var(--t1); }

/* Motion: the app animates almost nothing. Two short fades, one earned
   draw-in, and Reduce Motion is honoured. Web follows the same budget. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Nothing may push the document wider than the viewport. */
/* `overflow-x: hidden` here was silently disabling the sticky header:
   clipping with `hidden` makes the element a scroll container, and a
   sticky descendant then sticks to THAT box instead of the viewport, so
   the nav scrolled away on every page. `clip` clips without creating a
   scroll container, so the nav sticks again. The fallback keeps the old
   behaviour (clipped, non-sticky) on engines without `clip`. */
html, body { max-width: 100%; overflow-x: clip; }
@supports not (overflow: clip) {
  html, body { overflow-x: hidden; }
}
/* The nav is sticky now, so in-page anchors have to clear it. */
html { scroll-padding-top: 72px; }

@media (max-width: 760px) {
  :root { --gutter: 22px; }
  /* Brand + five links + a toggle cannot share one line on a phone.
     Hiding three of the five was the old answer, and it buried the two
     that matter — a reader had to scroll to the footer to find them.
     The whole row folds into the disclosure menu instead, so nothing is
     unreachable from the top of any page. */
  /* A label and a right-aligned caption can't share a phone-width line:
     the label wrapped mid-phrase while the caption hugged the right
     edge, and two adjacent rows ended up aligned opposite ways. Below
     this width the caption drops to its own line and reads left, like
     everything around it. */
  .rule { flex-wrap: wrap; }
  .rule .rule-cap { margin-left: 0; text-align: left; flex-basis: 100%; }

  .nav-in { gap: var(--s-sm); }
  .nav-links { display: none; }
  /* nav-links carried the margin-left:auto that pushed the right-hand
     group over. With it gone, the toggle has to take that job or it
     ends up sitting against the wordmark. */
  .theme-toggle { margin-left: auto; }
  .navmenu { display: block; margin-left: 0; }
  html { scroll-padding-top: 64px; }
  .site-footer .wrap { flex-direction: column; align-items: flex-start; }
  .site-footer nav { margin-left: 0; }
}

/* =====================================================================
   THE CHASSIS' RESPONSIVE MARGIN
   The margin never collapses — preserving the chassis down to 320px is
   the point, and a breakpoint that dropped the spine would say the
   language only works on desktop. Below 400px marks shorten to <=3
   characters instead (see styles-12.css).
   ===================================================================== */
@media (max-width: 900px) { :root { --mgn: 64px; } }
@media (max-width: 560px) { :root { --mgn: 40px; --gutter: 16px; } }
