/* =========================================================================
   Nonclusive by Design — accessibility-first design system
   colors_and_type.css — v3

   THESIS
   ------
   Accessibility is not a layer added to this system. It is the system.
   Every token is chosen because it removes a barrier. Every pairing is
   documented with its WCAG contrast ratio so designers never have to guess.

   RULES THE SYSTEM ENFORCES
   -------------------------
   1. Body text pairs meet WCAG 2.2 AAA (7:1). UI text meets AA+ (4.5:1 minimum).
   2. No italic display type. Italics reduce legibility for dyslexic readers.
      Emphasis is rendered as weight + color, never slant.
   3. No font below 16px. Caption floor is 14px, body floor is 18px (1.125rem).
   4. Line height ≥ 1.5 for body, ≥ 1.2 for display. Measure ≤ 72ch.
   5. Focus is a visible, 3-px, high-contrast ring. Never removed.
   6. Hit targets ≥ 44 × 44 CSS px (WCAG 2.5.8 AAA / 2.2 AA).
   7. All animation respects prefers-reduced-motion.
   8. Color is never the sole carrier of meaning — always paired with
      shape, weight, icon, or text.
   9. Text uses rem so zoom never breaks layout.
   ========================================================================= */


/* ---------- FONTS --------------------------------------------------------
   One face does the heavy lifting: Atkinson Hyperlegible Next, the newer
   superset of Atkinson Hyperlegible, engineered by the Braille Institute
   specifically for low-vision readers. Distinct letterforms on the pairs
   that commonly fail (I/l/1, O/0, rn/m, a/o). Works as UI and as display.

   Served locally from ./fonts/ — full seven-weight range (200–800) plus
   matching italics. JetBrains Mono still comes from Google Fonts.

   There is no italic face in the system by convention. Emphasis = weight +
   color. Italic files are declared so authors can opt in for direct
   quotations, foreign words, or citations where the non-italic convention
   would be misleading.
--------------------------------------------------------------------------- */
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap');

/* Atkinson Hyperlegible Next — 200 / 300 / 400 / 500 / 600 / 700 / 800 */
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: normal; font-weight: 200;
  src: url('/fonts/AtkinsonHyperlegibleNext-ExtraLight.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: italic; font-weight: 200;
  src: url('/fonts/AtkinsonHyperlegibleNext-ExtraLightItalic.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: normal; font-weight: 300;
  src: url('/fonts/AtkinsonHyperlegibleNext-Light.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: italic; font-weight: 300;
  src: url('/fonts/AtkinsonHyperlegibleNext-LightItalic.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: normal; font-weight: 400;
  src: url('/fonts/AtkinsonHyperlegibleNext-Regular.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: italic; font-weight: 400;
  src: url('/fonts/AtkinsonHyperlegibleNext-RegularItalic.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: normal; font-weight: 500;
  src: url('/fonts/AtkinsonHyperlegibleNext-Medium.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: italic; font-weight: 500;
  src: url('/fonts/AtkinsonHyperlegibleNext-MediumItalic.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: normal; font-weight: 600;
  src: url('/fonts/AtkinsonHyperlegibleNext-SemiBold.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: italic; font-weight: 600;
  src: url('/fonts/AtkinsonHyperlegibleNext-SemiBoldItalic.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: normal; font-weight: 700;
  src: url('/fonts/AtkinsonHyperlegibleNext-Bold.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: italic; font-weight: 700;
  src: url('/fonts/AtkinsonHyperlegibleNext-BoldItalic.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: normal; font-weight: 800;
  src: url('/fonts/AtkinsonHyperlegibleNext-ExtraBold.otf') format('opentype'); font-display: swap; }
@font-face { font-family: 'Atkinson Hyperlegible Next'; font-style: italic; font-weight: 800;
  src: url('/fonts/AtkinsonHyperlegibleNext-ExtraBoldItalic.otf') format('opentype'); font-display: swap; }


/* ============================================================================
   TOKENS — LIGHT (default)
   ============================================================================
   Paper is a faintly warm near-white (#FCFBF9), not pure white — reduces
   glare for photosensitive readers, and avoids the halation Khalipina names
   in her contrast posts. Pairs with Apple-near-black ink (#1D1D1F) at 16.27:1.
   Every colour listed shows its measured AAA contrast ratio against --paper.
   Ratios re-verified 2026-07-11 against the actual hex pairs.
   ----------------------------------------------------------------------------*/
:root {
  /* ---- Surfaces ---------------------------------------------------------*/
  /* Warm near-white system. Near-neutral grays with a slight warm cast
     that sits well with the field photos and the hot-rose accent. Tight
     steps between paper levels, no pure #000 / #fff anywhere. Tone:
     clean, minimal, editorial, accessible. History: warm-cream register
     (FBFAF6) -> cool Apple register (FBFBFD, 2026-05-16) -> nudged back
     "a little, little bit warmer" on PeO's call 2026-07-11, then the page
     ground pulled back to a whisper (#FCFAF7 read too yellow; PeO same
     day): --paper is now just one nuance off neutral while --paper-2/-3
     (tiles, borders) keep the fuller warmth he approved. All ratios
     recomputed; the tight pairs on --paper-2 (accent 7.04:1, ink-3
     7.13:1) match the old cool register exactly. */
  --paper:        #FCFBF9;   /* page ground — faintly warm near-white       */
  --paper-2:      #F7F5F1;   /* sunken surface / zebra row — warm step      */
  --paper-3:      #EBE7E1;   /* card border / hairline rule                 */
  --figure-plate: #FCFBF9;   /* fixed light ground behind content images.
                                Deliberately NOT theme-flipped: transparent
                                diagrams (black line art) go invisible on a
                                dark ground, so the plate stays light in
                                dark mode too — same convention as the
                                Quartz reader's lightbox card and the /sv
                                video-tile pictogram. Invisible behind
                                opaque photos, so it is safe to apply to
                                every content <img>. (PeO, 2026-08-30.)
                                Exception: theme-aware inline SVGs that use
                                currentColor (e.g. the matrix figure in
                                Tools.astro) keep a theme-flipping ground. */
  --ink:          #1D1D1F;   /* primary text — 16.27:1 on paper (AAA)       */
  --ink-2:        #404043;   /* secondary text — 9.99:1 on paper (AAA)      */
  --ink-3:        #525258;   /* muted text — 7.50:1 on paper (AAA body) —
                                darkened 2026-05-16 from #5C5C61 (was
                                6.43:1, failed AAA body). Halation on
                                small fonts (Khalipina) makes headroom
                                matter here more than elsewhere.            */
  --ink-rule:     #D6D1CA;   /* decorative rule — non-text only             */

  /* ---- Brand & accent ---------------------------------------------------
     All accent colors have a companion "-text" variant that clears AAA 7:1
     on --paper. Use the base color for fills and large text only; use
     -text for any body-sized text. */
  --brand:        #153863;   /* ink-blue anchor — 11.42:1 on paper (AAA) */
  --brand-2:      #0B2446;   /* pressed / deep anchor — 15.00:1 (AAA) */
  --brand-soft:   #D6E0EE;   /* tinted surface — decorative */

  /* Accent (hot-rose / deep magenta) — the single non-neutral colour.
     Serves as both accent and signal: emphasis, links-on-hover, focus ring,
     norm-critical register, status-new, and the bracket motif. */
  --accent:       #A01655;   /* deep magenta — 7.41:1 on paper (AAA body) */
  --accent-text:  #8A1248;   /* accent for body text — 8.98:1 (AAA) */
  --accent-soft:  #F4D4E2;   /* tinted surface */

  /* Back-compat aliases — older files may still reference --signal*. */
  --signal:       var(--accent);
  --signal-text:  var(--accent-text);
  --signal-soft:  var(--accent-soft);

  --highlight:    #F2D64F;   /* label-tape yellow — background only, never text */

  /* ---- Semantic status --------------------------------------------------
     Every status color is paired with a shape/icon convention in components.
     Color alone never carries the meaning. */
  --success:      #2A6639;   /* 6.64:1 — paired with icon (AA+ body) */
  --success-text: #1D4B28;   /* 9.73:1 (AAA) */
  --warn:         #8A5800;   /* 5.84:1 — paired with icon (AA body) */
  --warn-text:    #6A4200;   /* 8.49:1 (AAA) */
  --error:        #A01811;   /* 7.72:1 (AAA) */
  --error-text:   #841008;   /* 9.87:1 (AAA) */

  /* ---- Focus ------------------------------------------------------------
     Two-ring focus: a paper-colored inset gap guarantees visibility on any
     surface color, then a thick signal-colored outer ring. 3 px ring +
     2 px offset meets WCAG 2.4.11 (focus-appearance AAA). */
  --focus-color:  var(--signal);
  --focus-ring:   0 0 0 2px var(--paper), 0 0 0 5px var(--focus-color);
  --focus-ring-inverse: 0 0 0 2px var(--ink), 0 0 0 5px var(--focus-color);

  /* ---- Links ------------------------------------------------------------
     Always underlined — color is never the sole signal. Underline is thick
     enough to survive anti-aliasing. */
  --link:         var(--brand-2);
  --link-hover:   var(--signal-text);

  /* ================ TYPE — FLUID, REM-BASED ==========================
     Everything uses rem so browser-zoom (200 %+) scales the whole system
     without breaking layout. Body = 1.125rem (18 px at default root).
     Captions = 0.875rem (14 px floor) — never smaller. */
  --font-sans:    'Atkinson Hyperlegible Next', 'Atkinson Hyperlegible',
                  -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-display: 'Atkinson Hyperlegible Next', 'Atkinson Hyperlegible',
                  -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --t-caption:  0.875rem;     /* 14 px — minimum size anywhere in system */
  --t-small:    1rem;         /* 16 px — minimum body size */
  --t-body:     1.125rem;     /* 18 px — default body */
  --t-lead:     1.375rem;     /* 22 px */
  --t-h5:       1.125rem;
  --t-h4:       1.375rem;
  --t-h3:       clamp(1.5rem, 1.2rem + 1vw, 1.875rem);       /* 24 → 30 */
  --t-h2:       clamp(1.875rem, 1.4rem + 2.2vw, 2.75rem);    /* 30 → 44 */
  --t-h1:       clamp(2.5rem, 1.6rem + 4vw, 4.25rem);        /* 40 → 68 */
  --t-display:  clamp(3.5rem, 2rem + 7vw, 7rem);             /* 56 → 112 */

  /* Line heights — WCAG 1.4.12 says user must be able to reach 1.5 on body;
     we ship that as the default so it's never the user's problem. */
  --lh-body:    1.6;
  --lh-long:    1.75;
  --lh-snug:    1.3;
  --lh-tight:   1.15;

  /* Letter-spacing — no negative tracking on body; display uses -0.01em max
     (tighter than that harms letterform identification). */
  --track-caps: 0.08em;
  --track-body: 0;
  --track-display: -0.01em;

  /* Reading measures — capped at 72ch (WCAG 1.4.8 AAA ≤ 80). */
  --measure:    68ch;
  --measure-s:  52ch;

  /* ================ SPACING (4 px base, rem for zoom) ==================*/
  --s-0:  0;
  --s-1:  0.25rem;    /* 4 */
  --s-2:  0.5rem;     /* 8 */
  --s-3:  0.75rem;    /* 12 */
  --s-4:  1rem;       /* 16 */
  --s-5:  1.5rem;     /* 24 */
  --s-6:  2rem;       /* 32 */
  --s-7:  3rem;       /* 48 */
  --s-8:  4rem;       /* 64 */
  --s-9:  6rem;       /* 96 */
  --s-10: 8rem;       /* 128 */

  /* Hit target — WCAG 2.5.8 AAA requires 44 × 44. */
  --hit: 2.75rem;     /* 44 px */

  /* ================ RADII =============================================*/
  --r-0: 0;
  --r-1: 2px;
  --r-2: 6px;
  --r-3: 12px;
  --r-4: 20px;
  --r-pill: 999px;

  /* ---- Cut-corner card -------------------------------------------------
     Signature card shape: three soft corners + one square (bottom-left).
     A single squared corner gives a content card a clipped, editorial
     feel while staying inside the radius scale. Value order = TL TR BR BL.
     Use ONLY on discrete content cards (article / project / tool cards) —
     never on pills, buttons, inputs, avatars, or media that needs
     symmetric rounding. This is a corner treatment, NOT the bracket motif
     (the [ ] lockup is reserved per the brand rules). */
  --r-card:        var(--r-3);                                 /* 12px card corner */
  --r-card-cut:    var(--r-card) var(--r-card) var(--r-card) 0;
  --r-card-cut-lg: var(--r-4) var(--r-4) var(--r-4) 0;         /* for --r-4 cards */

  /* ================ BORDERS & SHADOWS ================================ */
  --border-1:       1px solid var(--ink-rule);
  --border-2:       1px solid var(--paper-3);
  --border-strong:  2px solid var(--ink);

  --shadow-1: 0 1px 0 rgba(14,21,34,.04), 0 2px 6px -2px rgba(14,21,34,.10);
  --shadow-2: 0 2px 0 rgba(14,21,34,.04), 0 10px 24px -10px rgba(14,21,34,.18);
  --shadow-3: 0 4px 0 rgba(14,21,34,.04), 0 28px 50px -18px rgba(14,21,34,.26);

  /* ================ MOTION ===========================================
     Short and meaningful. Any component that animates MUST swap to
     instant under prefers-reduced-motion. The --dur-* tokens are the only
     durations allowed in the system. */
  --dur-instant: 0ms;
  --dur-fast:    120ms;
  --dur-base:    200ms;
  --dur-slow:    360ms;
  --ease:        cubic-bezier(.2, 0, 0, 1);
}


/* ============================================================================
   DARK THEME — explicit only (opt-in). Every pair re-verified AAA.
   ============================================================================*/
[data-theme="dark"] {
  /* Soft near-black, NOT pure #000. Pure black causes halation
     (white-on-black bloom) and eye strain for many readers,
     especially with astigmatism or low vision — contradicting
     the accessibility-first thesis of this system. Apple uses
     the same #1C–1D register everywhere except the OLED home
     screen. Single register across the site: #1D1D1F matches
     the footer and the header dark band exactly. */
  --paper:        #1D1D1F;   /* Apple near-black, soft dark surface     */
  --paper-2:      #2C2C2E;   /* lifted surface for sunken bands         */
  --paper-3:      #3A3A3C;   /* borders / hairline rule                 */
  --ink:          #F5F5F7;   /* 15.46:1 on paper (AAA)                  */
  --ink-2:        #D1D1D6;   /* 11.06:1 (AAA)                           */
  --ink-3:        #BBBBBF;   /* 8.79:1 on paper, 7.28:1 on paper-2 (AAA
                                body on both) — lifted 2026-08-30 from
                                #AEAEB2, which cleared paper (7.61:1) but
                                failed the paper-2 card ground (6.30:1);
                                caught by scripts/check-a11y.mjs           */
  --ink-rule:     #48484A;   /* decorative rule, non-text               */

  --brand:        #A6C7F5;   /* light ink-blue — 9.70:1 on paper (AAA) */
  --brand-2:      #D1E0F7;   /* 12.60:1 */
  --brand-soft:   #1E2D45;

  --accent:       #F286B6;   /* 7.10:1 (AAA body) */
  --accent-text:  #F4A3C8;   /* 8.75:1 (AAA) */
  --accent-soft:  #3A1830;

  /* Back-compat aliases — older files may still reference --signal*. */
  --signal:       var(--accent);
  --signal-text:  var(--accent-text);
  --signal-soft:  var(--accent-soft);

  --highlight:    #F2D64F;

  --success:      #74C488;
  --success-text: #A3DAB1;
  --warn:         #E8B567;
  --warn-text:    #F2CD96;
  --error:        #F29189;
  --error-text:   #F4B1AB;

  --link:         var(--brand-2);
  --link-hover:   var(--signal-text);
  --focus-ring:   0 0 0 2px var(--paper), 0 0 0 5px var(--focus-color);

  --shadow-1: 0 1px 0 rgba(0,0,0,.45), 0 2px 6px -2px rgba(0,0,0,.55);
  --shadow-2: 0 2px 0 rgba(0,0,0,.45), 0 10px 24px -10px rgba(0,0,0,.65);
  --shadow-3: 0 4px 0 rgba(0,0,0,.45), 0 28px 50px -18px rgba(0,0,0,.75);
}


/* ============================================================================
   HIGH-CONTRAST MODE — Windows / forced-colors. Let the OS take over.
   ============================================================================*/
@media (forced-colors: active) {
  * {
    border-color: CanvasText !important;
  }
  a, .link { color: LinkText !important; }
  :focus-visible { outline: 3px solid Highlight !important; outline-offset: 2px; }
}


/* ============================================================================
   MOTION — global reduced-motion contract
   ============================================================================*/
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0ms !important;
    scroll-behavior: auto !important;
  }
}


/* ============================================================================
   BASE — reset + typography roles
   ============================================================================*/
html {
  -webkit-text-size-adjust: 100%;
  /* Do NOT set a fixed root font-size — let the user's browser/OS scale. */
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: var(--lh-long);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* --- Type roles ---------------------------------------------------------*/
.t-kicker, .kicker {
  font-family: var(--font-mono);
  font-size: var(--t-caption);
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-3);
}

.t-display, .display {
  font-family: var(--font-display);
  font-size: var(--t-display);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  color: var(--ink);
  text-wrap: balance;
  margin: 0;
}

h1, .t-h1 {
  font-family: var(--font-display);
  font-size: var(--t-h1);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  color: var(--ink);
  text-wrap: balance;
  margin: 0 0 var(--s-5);
}

h2, .t-h2 {
  font-family: var(--font-display);
  font-size: var(--t-h2);
  font-weight: 700;
  line-height: var(--lh-snug);
  letter-spacing: var(--track-display);
  color: var(--ink);
  text-wrap: balance;
  margin: var(--s-7) 0 var(--s-4);
}

h3, .t-h3 {
  font-family: var(--font-sans);
  font-size: var(--t-h3);
  font-weight: 700;
  line-height: var(--lh-snug);
  color: var(--ink);
  margin: var(--s-6) 0 var(--s-3);
}

h4, .t-h4 {
  font-family: var(--font-sans);
  font-size: var(--t-h4);
  font-weight: 700;
  line-height: 1.3;
  color: var(--ink);
  margin: var(--s-5) 0 var(--s-2);
}

.t-lead, .lead {
  font-family: var(--font-sans);
  font-size: var(--t-lead);
  font-weight: 400;
  line-height: var(--lh-body);
  color: var(--ink-2);
  max-width: var(--measure);
  margin: 0 0 var(--s-5);
}

.t-body, p, li {
  font-family: var(--font-sans);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: var(--lh-long);
  color: var(--ink);
  letter-spacing: var(--track-body);
}

p { max-width: var(--measure); margin: 0 0 var(--s-4); }

.t-small, small {
  font-family: var(--font-sans);
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--ink-2);
}

.t-caption, figcaption {
  font-family: var(--font-sans);
  font-size: var(--t-caption);
  line-height: 1.5;
  color: var(--ink-3);
  letter-spacing: 0.01em;
}

.t-mono, code, kbd, pre {
  font-family: var(--font-mono);
  font-size: 0.92em;
  font-weight: 500;
}

/* Emphasis is weight + color, NOT italic. */
strong, b, em, .t-strong {
  font-weight: 700;
  color: var(--ink);
  font-style: normal;
}
.t-emph, .signal-word { color: var(--signal-text); font-weight: 700; }

/* Block quotes — we use a rule + weight shift, not italic. */
.t-quote, blockquote {
  font-family: var(--font-display);
  font-size: clamp(1.375rem, 1.15rem + 0.8vw, 1.875rem);
  line-height: 1.4;
  font-weight: 400;
  color: var(--ink);
  border-left: 4px solid var(--signal);
  padding: var(--s-2) 0 var(--s-2) var(--s-5);
  margin: var(--s-6) 0;
  max-width: var(--measure);
  text-wrap: balance;
}
.t-quote cite, blockquote cite {
  display: block;
  margin-top: var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--t-caption);
  font-style: normal;
  font-weight: 500;
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ---------- Links — always underlined -----------------------------------*/
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  transition: color var(--dur-fast) var(--ease),
              text-decoration-color var(--dur-fast) var(--ease);
}
a:hover { color: var(--link-hover); }
a:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: 2px;
}

/* Skip link — first tab stop on every page. */
.skip-link {
  position: absolute;
  top: var(--s-2);
  left: var(--s-2);
  padding: var(--s-3) var(--s-5);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-sans);
  font-weight: 700;
  text-decoration: none;
  border-radius: var(--r-2);
  transform: translateY(-200%);
  z-index: 9999;
}
.skip-link:focus-visible {
  transform: translateY(0);
  box-shadow: var(--focus-ring);
}

/* Selection — use label-tape yellow, always with ink text (guaranteed AAA). */
::selection { background: var(--highlight); color: var(--ink); }

/* Highlight marker — background only, never text. */
mark, .marked {
  background: color-mix(in oklab, var(--highlight) 80%, transparent);
  color: var(--ink);
  padding: 0 0.25em;
  border-radius: 2px;
}

/* Bracket motif — a norm-critical inline mark. */
.bracketed::before { content: "[ "; color: var(--signal); font-weight: 700; }
.bracketed::after  { content: " ]"; color: var(--signal); font-weight: 700; }

/* Strike-through — protest marker; AT will announce. */
.struck {
  text-decoration: line-through;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--signal);
}

/* Cut-corner card helper — apply to a content card's outer box element.
   Squares the bottom-left corner while keeping the other three soft.
   Pair -lg with cards built on --r-4. */
.card-cut    { border-radius: var(--r-card-cut); }
.card-cut-lg { border-radius: var(--r-card-cut-lg); }

/* Hit target utility — apply to any clickable small thing. */
.hit-target {
  min-width: var(--hit);
  min-height: var(--hit);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Global focus — any focusable element gets the ring by default, no excuse. */
:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: 2px;
}

/* Visually-hidden but available to screen readers. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}


/* ============================================================================
   COMPONENT UTILITIES
   ============================================================================
   History: the 2026-08 "come alive" pass introduced a three-role chord
   (rose ink / tape-yellow surface / dark-band frame). PeO's 2026-08-12
   "book/clean" pass retired two of the three legs: the tape-yellow
   .tape-chip labels were removed everywhere ("stuck out"; content-kind
   labels now use the quiet mono meta register in --ink-3, or nothing),
   and the chrome went light (the two mid-page bands, softened to
   #2C2C2E, are the only dark moments). ROSE remains the single accent:
   text emphasis, state, action, borders-on-hover, section indices. */

/* Editorial section head — strong 2px ink rule across the content
   width, bracketed kicker on the left, running mono index on the right
   ("03 / 08"). Numbering a long page turns the scroll into a legible
   sequence. Pair the kicker with .kicker-bracketed / .bracketed. */
.head-rule {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  border-top: 2px solid var(--ink);
  padding-top: 16px;
}
.head-rule .kicker-bracketed { margin: 0; }
.sec-idx {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--accent-text);   /* 8.98:1 light / 8.75:1 dark (AAA) */
}

/* Solid primary pill — the resting primary CTA is the FULL deep rose
   (the pale accent-soft resting chip was retired 2026-08-13: too quiet
   once the surrounding design sharpened). Paper text on --accent
   7.41:1; hover deepens to --accent-text 8.98:1. Dark theme flips via
   the tokens to bright rose + near-black text (7.10:1). */
.btn-solid-accent {
  color: var(--paper);
  background: var(--accent);
  border: 1px solid var(--accent);
}
.btn-solid-accent:hover {
  color: var(--paper);
  background: var(--accent-text);
  border-color: var(--accent-text);
}

/* Dark chrome bands — pattern, not a class. Header and footer are dark
   surfaces in BOTH themes: set data-theme="dark" on the band element
   and every token inside flips to its AAA dark counterpart (a wordmark
   on the band picks up the favicon-chip colours for free — white word,
   rose brackets). State language ON a dark band:
   (single-tone, one line per element — the ring-plus-glow double
   outline was decluttered 2026-08-14):
   - HOVER and CLICKABLE ACTIVE = the full bright-rose chip with
     near-black text/icon (#1D1D1F on #F286B6, 7.10:1); aria-current
     carries the semantic difference.
   - NON-CLICKABLE current-state marker (e.g. the active language) =
     bold light text with a bright-rose underline (#F286B6, 5.88:1 vs
     the band as a UI signal), no box.
   Translucent glows alone are too pale as hover feedback on dark
   (tried at 0.18 and 0.30 opacity; PeO rejected both, 2026-08-13). */
