  /* ── A3K palette (ANSI-256 -> hex). Look reference; runtime values live in Phos4. ── */
  :root {
    --magenta: #ff5fff;  --rose: #ff5fd7;  --pink: #d75fd7;
    --purple:  #af5fff;  --indigo: #875fff; --blue: #5fafff;
    --cyan:    #00d7ff;  --brtcyan: #00ffff; --accent: #00afff;

    --bg:    #0a0a12;
    --panel: #12121f;
    --ink:   #e8e8f4;
    --dim:   #8a8aa6;
    --rail:  #2a2a3e;
    /* A3K web status colours (canonical home: y3k-brand IDENTITY.md §2) — softened web hexes. */
    --ok:    #7ddc7d;   /* success · complete · in-hand      (ANSI 42)  */
    --warn:  #ffcf6a;   /* caution · in-progress · undecided (ANSI 220) */
    --err:   #ff5f5f;   /* error · blocked · destructive     (ANSI 203) */

    --ramp: linear-gradient(100deg,
      var(--magenta), var(--pink), var(--purple), var(--indigo),
      var(--blue), var(--cyan), var(--brtcyan));

    /* Shared ease + duration for the active phase-shift. Smooth, not a flash. */
    --t: 250ms;
    --ease: cubic-bezier(.22, .61, .36, 1);
  }

  * { box-sizing: border-box; }
  html { color-scheme: dark; }
  body {
    margin: 0;
    background:
      radial-gradient(900px 500px at 8% -8%,  color-mix(in srgb, var(--magenta) 16%, transparent), transparent 55%),
      radial-gradient(900px 500px at 100% 108%, color-mix(in srgb, var(--cyan) 12%, transparent), transparent 55%),
      radial-gradient(1200px 600px at 50% -10%, #1a1030 0%, transparent 60%),
      var(--bg);
    color: var(--ink);
    font: 16px/1.6 ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
    min-height: 100vh;
    padding: 6vh 24px 64px;
  }

  /* Global synthwave floor grid — faint, fades before the header. */
  body::before {
    content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
    background:
      repeating-linear-gradient(to right,  color-mix(in srgb, var(--cyan) 7%, transparent) 0 1px, transparent 1px 64px),
      repeating-linear-gradient(to bottom, color-mix(in srgb, var(--magenta) 5%, transparent) 0 1px, transparent 1px 64px);
    -webkit-mask-image: linear-gradient(to bottom, transparent 50%, #000 100%);
            mask-image: linear-gradient(to bottom, transparent 50%, #000 100%);
    opacity: .55;
  }
  /* Global CRT scanlines on top of everything — static (no idle flicker). */
  body::after {
    content: ""; position: fixed; inset: 0; z-index: 200; pointer-events: none;
    background:
      repeating-linear-gradient(to bottom, rgba(0,0,0,.14) 0 1px, transparent 1px 4px),
      repeating-linear-gradient(to bottom, color-mix(in srgb, var(--cyan) 8%, transparent) 0 1px, transparent 1px 4px);
    background-size: 100% 4px;
  }

  /* ── Header ── */
  header {
    max-width: 1240px; margin: 0 auto 44px;
    display: flex; flex-direction: column; align-items: center; text-align: center;
  }

  /* ── Wordmark ── lifted verbatim from the Y3K RC hub so the garage reads as a
     sibling. Double-line box + glow, gradient-filled page-name wordmark
     ("The Garage"), periodic tile (01 RC). The h1 gradient/fringe is scoped to
     .mark, mirroring the RadioMaster sub-page header idiom. */
  .mark {
    position: relative;
    border: 3px double color-mix(in srgb, var(--purple) 30%, var(--rail));
    border-radius: 12px;
    /* Top padding trimmed vs. bottom: line-height 1.2 adds half-leading above the
       caps, so a smaller top pad re-balances the box against the descender room
       below — wordmark stays optically centered, descenders (g/y/p/q) clear. */
    padding: 14px 44px 18px;
    background: rgba(255,255,255,.015);
    box-shadow: 0 0 80px -24px var(--purple), inset 0 0 40px -30px var(--magenta);
  }
  .mark h1 {
    margin: 0;
    font-size: clamp(40px, 10vw, 84px);
    font-weight: 800;
    letter-spacing: .04em;
    /* Was line-height:1 (baseline == box bottom → descenders clipped). 1.2 opens
       room below the baseline so g/y/p/q tails render fully inside the box. */
    line-height: 1.2;
    white-space: nowrap;
    background: var(--ramp);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    /* Phosphor bloom + chromatic fringe on the wordmark only. */
    filter:
      drop-shadow(-2px 0 0 color-mix(in srgb, var(--magenta) 65%, transparent))
      drop-shadow( 2px 0 0 color-mix(in srgb, var(--cyan)    65%, transparent))
      drop-shadow(0 0 18px color-mix(in srgb, var(--purple) 35%, transparent));
  }
  /* Periodic element cell straddling the top-right corner: atomic number (01)
     top-left, symbol (RC) big-center. Kept deliberately spare. */
  .el-tile {
    position: absolute; top: -18px; right: -18px;
    width: 57px; height: 64px;
    display: grid; place-items: center; padding: 6px;
    border: 1px solid color-mix(in srgb, var(--cyan) 45%, var(--rail));
    border-radius: 8px;
    background: #060608;                       /* clinical black */
    box-shadow: 0 0 16px -12px var(--cyan);
  }
  .el-num {
    position: absolute; top: 6px; left: 7px;
    font-size: 9.5px; font-weight: 700; line-height: 1; letter-spacing: .04em;
    background: linear-gradient(100deg, var(--cyan), var(--blue), var(--indigo));
    -webkit-background-clip: text; background-clip: text; color: transparent;
  }
  .el-sym {
    font-size: 26px; font-weight: 800; line-height: 1; letter-spacing: -.01em;
    color: var(--ink);
    text-shadow: 0 0 10px color-mix(in srgb, var(--cyan) 35%, transparent);
    transform: translateY(4px);
  }

  /* ── Eyebrow / brand tag ── ported from the RadioMaster sub-page so the garage
     header reads as a sibling: bracketed "[ Y3K RC ]", cyan, wide tracking. ── */
  .eyebrow {
    margin: 0 0 18px;
    color: color-mix(in srgb, var(--cyan) 80%, var(--ink));
    letter-spacing: .34em;
    text-transform: uppercase;
    font-size: 11px;
    font-weight: 700;
    text-shadow: 0 0 12px color-mix(in srgb, var(--cyan) 30%, transparent);
  }
  .eyebrow::before { content: "[ "; color: var(--accent); }
  .eyebrow::after  { content: " ]"; color: var(--accent); }
  .lede {
    max-width: 64ch; margin: 18px auto 0;
    color: color-mix(in srgb, var(--ink) 70%, var(--dim)); font-size: 14px;
  }
  .lede b { color: var(--ink); font-weight: 700; }

  /* ── Catalog grid ── */
  .stages {
    max-width: 1240px; margin: 0 auto;
    display: grid; gap: 32px;
    grid-template-columns: repeat(2, 1fr);
  }
  @media (max-width: 860px) { .stages { grid-template-columns: 1fr; max-width: 520px; } }

  figure.card {
    margin: 0;
    border: 1px solid var(--rail);
    border-radius: 16px;
    background: linear-gradient(180deg, color-mix(in srgb, var(--panel) 70%, transparent), color-mix(in srgb, var(--bg) 60%, transparent));
    overflow: hidden;
    display: flex; flex-direction: column;
  }

  /* The 1:1 stage. Houses subject + atmosphere.
     --cx is the resting Vibe split; .is-active widens it (see below). */
  .stage {
    position: relative;
    aspect-ratio: 1 / 1;
    background:
      radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--purple) 9%, transparent), transparent 60%),
      linear-gradient(180deg, #0c0c18 0%, #07070e 72%, #05050a 100%);
    overflow: hidden;
    isolation: isolate; /* contain blend modes to the stage */
    cursor: pointer;

    /* ── Vibe dials, resting values ── */
    /* --cx = hard RGB phase-shift offset (wordmark technique), resting subtle. */
    --cx: 2.5px; --rim: 3px; --rim-a: 62%; --bloom-a: 30%;
    --fringe-a: 70%;
    --floor-opacity: .42;
    --subjscan-a: .2; --bloom-top: 9%; --vig-on: .55;

    transition: border-color var(--t) var(--ease);
  }

  /* Per-stage synthwave grid floor (denser/brighter than the page grid). */
  .floor {
    position: absolute; inset: 55% 0 0 0; z-index: 1; pointer-events: none;
    perspective: 340px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 12%, #000 100%);
            mask-image: linear-gradient(to bottom, transparent 0%, #000 12%, #000 100%);
    opacity: var(--floor-opacity, .4);
  }
  .floor::before {
    content: ""; position: absolute; inset: -20% -40% -10% -40%;
    transform: rotateX(74deg);
    background:
      repeating-linear-gradient(to right,
        color-mix(in srgb, var(--cyan) 60%, transparent) 0 2px, transparent 2px 44px),
      repeating-linear-gradient(to bottom,
        color-mix(in srgb, var(--magenta) 50%, transparent) 0 2px, transparent 2px 44px);
  }

  /* The rig: a single hero <img> carrying the wordmark-style hard RGB fringe. */
  .rig {
    position: absolute; left: 50%; top: 50%; z-index: 5;
    width: 78%; height: 78%; transform: translate(-50%, -54%);
  }
  .rig img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: contain; object-position: center;
    display: block; -webkit-user-drag: none; user-select: none;
  }
  .rig .base { position: relative; }

  /* Hard RGB phase-shift fringe — the SITE WORDMARK technique, applied to the
     rig. Two zero-blur drop-shadow color offsets: magenta shifted left, cyan
     shifted right, hugging the cutout silhouette as crisp colored edges.
     --cx drives the offset: subtle at rest, big & loud on active. The neon rim /
     phosphor bloom is layered AFTER the fringe so it complements the hard edges
     without softening them. */
  .rig .base {
    filter:
      drop-shadow(calc(var(--cx, 2.5px) * -1) 0 0 color-mix(in srgb, var(--magenta) var(--fringe-a, 70%), transparent))
      drop-shadow(var(--cx, 2.5px)            0 0 color-mix(in srgb, var(--cyan)    var(--fringe-a, 70%), transparent))
      drop-shadow(0 0  var(--rim, 3px) color-mix(in srgb, var(--cyan)    var(--rim-a, 60%), transparent))
      drop-shadow(0 0  var(--rim, 3px) color-mix(in srgb, var(--magenta) var(--rim-a, 60%), transparent))
      drop-shadow(0 0  calc(var(--rim, 3px) * 4) color-mix(in srgb, var(--purple) var(--bloom-a, 28%), transparent));
    transition: filter var(--t) var(--ease);
  }

  /* Scanlines drawn directly OVER the subject (subject zone only). */
  .subject-scan {
    position: absolute; inset: 0; z-index: 8; pointer-events: none;
    background: repeating-linear-gradient(to bottom,
      rgba(0,0,0, var(--subjscan-a, .22)) 0 1px, transparent 1px 3px);
    -webkit-mask-image: radial-gradient(58% 52% at 50% 46%, #000 60%, transparent 100%);
            mask-image: radial-gradient(58% 52% at 50% 46%, #000 60%, transparent 100%);
  }

  /* Vignette + top bloom over the whole stage. */
  .stage .vig {
    position: absolute; inset: 0; z-index: 10; pointer-events: none;
    background:
      radial-gradient(70% 60% at 50% 38%, color-mix(in srgb, var(--magenta) var(--bloom-top, 0%), transparent), transparent 70%),
      radial-gradient(120% 120% at 50% 50%, transparent 52%, rgba(0,0,0,.55) 100%);
    opacity: var(--vig-on, .5);
  }

  /* ── ACTIVE state ──
     Static at rest. Active = dramatic: the chromatic split opens ~2.5px -> ~24px,
     the rim/bloom surge — eased over ~250ms (var(--t)). Triggered by:
       • desktop : :hover / :focus-within
       • touch   : .is-active toggled by JS (scroll-center IO + tap) */
  .stage.is-active {
    --cx: 24px; --fringe-a: 100%; --rim: 9px; --rim-a: 92%; --bloom-a: 56%;
    --bloom-top: 16%;
    border-color: color-mix(in srgb, var(--cyan) 45%, var(--rail));
  }

  @media (hover: hover) {
    .stage:hover, .stage:focus-within {
      --cx: 24px; --fringe-a: 100%; --rim: 9px; --rim-a: 92%; --bloom-a: 56%;
      --bloom-top: 16%;
      border-color: color-mix(in srgb, var(--cyan) 45%, var(--rail));
    }
  }
  .stage:focus-within { outline: none; }
  .stage:focus-visible {
    outline: 2px solid color-mix(in srgb, var(--cyan) 70%, transparent);
    outline-offset: -3px;
  }

  /* Tap-pinned cards (touch) get a tiny corner tick so the toggle is legible. */
  .stage.is-pinned::after {
    content: "◉ LIVE"; position: absolute; right: 10px; top: 10px; z-index: 12;
    font-size: 9px; letter-spacing: .18em; color: var(--brtcyan);
    text-shadow: 0 0 8px color-mix(in srgb, var(--cyan) 80%, transparent);
    opacity: .9; pointer-events: none;
  }

  /* Reduced-motion: states apply instantly, nothing animates. */
  @media (prefers-reduced-motion: reduce) {
    .stage, .rig .base { transition: none; }
  }

  /* ── Caption / labels ── */
  figcaption {
    margin: 18px 20px 0; display: flex; align-items: flex-end; gap: 10px;
    flex-wrap: wrap;
  }
  .lvl {
    font-weight: 800; font-size: 19px; letter-spacing: .02em; line-height: 1;
    background: var(--ramp); -webkit-background-clip: text; background-clip: text; color: transparent;
  }
  .lvl-num {
    margin-left: auto;                 /* ride the right edge, bottom-aligned to the title */
    font-size: 10.5px; color: var(--accent);
    border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--rail));
    border-radius: 999px; padding: 1px 9px; letter-spacing: .12em; white-space: nowrap;
    text-transform: uppercase;
  }
  .type-tag {
    margin-left: auto; font-size: 10px; letter-spacing: .22em; text-transform: uppercase;
    color: var(--dim);
  }

  /* ── Lifecycle status ── color = realized (running); not-yet-real builds
     (planned / building) wear a baked greyscale-glitch hero (_tools/glitch.py).
     The status badge names the stage. */
  .status-pill {
    font-size: 9.5px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
    border-radius: 999px; padding: 1px 9px; white-space: nowrap;
  }
  .status-pill--planned {
    color: var(--blue);
    border: 1px solid color-mix(in srgb, var(--blue) 50%, var(--rail));
    background: color-mix(in srgb, var(--blue) 14%, transparent);
  }
  .status-pill--building {
    color: var(--warn);
    border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--rail));
    background: color-mix(in srgb, var(--warn) 10%, transparent);
  }

  /* ── Spec panel ── */
  .spec {
    margin: 16px 20px 22px; padding-top: 16px;
    border-top: 1px solid color-mix(in srgb, var(--rail) 80%, transparent);
    font-size: 13px;
  }
  .spec-core { margin: 0; display: grid; gap: 0; }
  .spec-row {
    display: grid; grid-template-columns: 116px 1fr; gap: 12px;
    padding: 5px 0;
    border-bottom: 1px dashed color-mix(in srgb, var(--rail) 50%, transparent);
  }
  .spec-row dt {
    color: var(--accent); text-transform: uppercase; letter-spacing: .14em;
    font-size: 10.5px; padding-top: 2px;
  }
  .spec-row dd { margin: 0; color: var(--ink); }
  .spec-row dd a {
    color: var(--cyan); text-decoration: none;
    border-bottom: 1px solid color-mix(in srgb, var(--cyan) 40%, transparent);
  }
  .spec-row dd a:hover { color: var(--brtcyan); border-bottom-color: var(--brtcyan); }

  /* stock_remote (Tier-B) — model + label-ID badge + channels. */
  .spec-stock { margin-top: 16px; }
  .spec-list-label {
    display: block; color: var(--magenta);
    text-transform: uppercase; letter-spacing: .2em; font-size: 10px;
    margin-bottom: 7px;
  }
  .stock-line { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
  .stock-model { color: var(--ink); font-weight: 700; }
  .badge-id {
    font-size: 11px; font-weight: 700; letter-spacing: .12em;
    color: var(--bg); background: var(--cyan);
    border-radius: 5px; padding: 2px 8px;
    box-shadow: 0 0 10px color-mix(in srgb, var(--cyan) 55%, transparent);
  }
  .badge-ch {
    font-size: 10.5px; letter-spacing: .1em; color: var(--cyan);
    border: 1px solid color-mix(in srgb, var(--cyan) 45%, var(--rail));
    border-radius: 999px; padding: 1px 8px;
  }

  /* upgrades / planned. */
  .spec-mods {
    margin-top: 18px; display: grid; gap: 16px;
    grid-template-columns: 1fr 1fr;
  }
  @media (max-width: 420px) { .spec-mods { grid-template-columns: 1fr; } }
  .spec-list ul { list-style: none; margin: 0; padding: 0; }
  .spec-list li {
    position: relative; padding-left: 18px; padding-block: 2px; color: var(--ink);
    font-size: 12.5px;
  }
  .spec-list--done .spec-list-label { color: var(--cyan); }
  .spec-list--done li::before {
    content: "▰"; position: absolute; left: 0; color: var(--cyan); font-size: 10px;
  }
  .spec-list--planned .spec-list-label { color: var(--purple); }
  .spec-list--planned li::before {
    content: "▱"; position: absolute; left: 0; color: var(--purple); font-size: 10px;
  }

  .spec-notes {
    margin-top: 18px; padding-top: 16px;
    border-top: 1px dashed color-mix(in srgb, var(--rail) 50%, transparent);
    color: color-mix(in srgb, var(--ink) 78%, var(--dim));
    font-size: 12.5px; line-height: 1.65;
  }
  .spec-notes p { margin: 0 0 10px; }
  .spec-notes p:last-child { margin-bottom: 0; }
  .spec-notes strong { color: var(--ink); }

  /* ── Bill of materials ── the build's procurement tracker, lifted to the top
     of the spec panel. part · spec (linked) · via tag · price, with a known total. */
  .bom { margin: 2px 0 20px; }
  .bom-head {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    margin-bottom: 9px; padding-bottom: 8px;
    border-bottom: 1px solid color-mix(in srgb, var(--rail) 85%, transparent);
  }
  .bom-title {
    color: var(--magenta); text-transform: uppercase; letter-spacing: .2em;
    font-size: 11px; font-weight: 700;
  }
  /* Total — labels + separators recede (dim); the figures carry the colour, each mirroring its rows. */
  .bom-total { color: var(--dim); font-size: 12.5px; font-weight: 700; white-space: nowrap; }
  .bom-total em { color: var(--dim); font-style: normal; font-weight: 400; font-size: 11px; }
  .bom-total .acq  { color: var(--ok); }    /* in hand — ties to the green acquired rows */
  .bom-total .ord  { color: var(--ok); }    /* bought, in transit — same green (money spent); label disambiguates */
  .bom-total .togo { color: var(--ink); }   /* still to buy — mirrors the white row prices */
  .bom-total .tbd  { color: var(--warn); }  /* unknown cost — same amber as TO-SOURCE */
  .bom-list { list-style: none; margin: 0; padding: 0; }
  .bom-line {
    display: grid; grid-template-columns: 16px 92px 1fr auto; column-gap: 10px; row-gap: 5px;
    align-items: baseline; padding: 6px 0 6px 12px;
    border-bottom: 1px dashed color-mix(in srgb, var(--rail) 45%, transparent);
    font-size: 12.5px;
  }
  /* Acquisition checkbox — ✓ = owned/in-hand, empty box = still to get. */
  .bom-ck {
    width: 14px; height: 14px; align-self: start; margin-top: 2px; border-radius: 4px;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 10px; line-height: 1; font-weight: 700;
  }
  .bom-ck--off { border: 1.5px solid color-mix(in srgb, var(--rail) 55%, var(--dim)); }
  .bom-ck--on  { border: 1.5px solid var(--ok); background: color-mix(in srgb, var(--ok) 20%, transparent); color: var(--ok); }
  .bom-via-empty { display: inline-block; }
  /* Acquired row (bought part or downloaded file) — green left rail (sits in the 12px gutter,
     clear of the checkbox) + faint wash; part, price, AND link all turn the same --ok green so the
     whole row reads "got it" at a glance (the link keeps its underline, so it's still obviously a link). */
  .bom-line.acquired {
    background: color-mix(in srgb, var(--ok) 9%, transparent);
    box-shadow: inset 3px 0 0 var(--ok); border-radius: 2px;
  }
  .bom-line.acquired .bom-part { color: var(--ok); }
  .bom-line.acquired .bom-price { color: var(--ok); }
  /* a `downloaded` row is acquired (green) AND print-kind — green wins for the row, its option links +
     ▸ bullets follow green; only the persistent PRINT pill stays purple (printing still pending). */
  .bom-line.acquired .bom-options a { color: var(--ok); border-bottom-color: color-mix(in srgb, var(--ok) 40%, transparent); }
  .bom-line.acquired .bom-options li::before { color: var(--ok); }
  .bom-line.acquired .bom-spec a { color: var(--ok); border-bottom-color: color-mix(in srgb, var(--ok) 40%, transparent); }
  .bom-line.acquired .bom-spec a:hover { color: color-mix(in srgb, var(--ok) 55%, #fff); border-bottom-color: color-mix(in srgb, var(--ok) 55%, #fff); }
  /* Ordered row (bought, in transit — decided 2026-07-05): the acquired green treatment minus the
     ✓ (checkbox stays empty until it physically arrives; flip via: ordered → owned then). Slightly
     fainter wash than acquired so in-hand still reads one notch "more done" at a glance. */
  .bom-line.ordered {
    background: color-mix(in srgb, var(--ok) 6%, transparent);
    box-shadow: inset 3px 0 0 color-mix(in srgb, var(--ok) 70%, transparent); border-radius: 2px;
  }
  .bom-line.ordered .bom-part { color: var(--ok); }
  .bom-line.ordered .bom-spec { color: color-mix(in srgb, var(--ok) 80%, var(--ink)); }
  .bom-line.ordered .bom-price { color: var(--ok); }
  .bom-line.ordered .bom-spec a { color: var(--ok); border-bottom-color: color-mix(in srgb, var(--ok) 40%, transparent); }
  .bom-line.ordered .bom-spec a:hover { color: color-mix(in srgb, var(--ok) 55%, #fff); border-bottom-color: color-mix(in srgb, var(--ok) 55%, #fff); }
  .bom-line.ordered .bom-options a { color: var(--ok); border-bottom-color: color-mix(in srgb, var(--ok) 40%, transparent); }
  .bom-line.ordered .bom-options li::before { color: var(--ok); }
  /* Links take the row's KIND colour, so links + badge + row agree (acquired→green is above). */
  .bom-line--print .bom-spec a, .bom-line--print .bom-options a { color: var(--purple); border-bottom-color: color-mix(in srgb, var(--purple) 40%, transparent); }
  .bom-line--print .bom-spec a:hover, .bom-line--print .bom-options a:hover { color: color-mix(in srgb, var(--purple) 55%, #fff); border-bottom-color: color-mix(in srgb, var(--purple) 55%, #fff); }
  .bom-line--source .bom-spec a, .bom-line--source .bom-options a { color: var(--warn); border-bottom-color: color-mix(in srgb, var(--warn) 40%, transparent); }
  .bom-line--source .bom-spec a:hover, .bom-line--source .bom-options a:hover { color: color-mix(in srgb, var(--warn) 55%, #fff); border-bottom-color: color-mix(in srgb, var(--warn) 55%, #fff); }
  /* …the part label AND the option ▸ bullets too, so the whole row (label · bullets · links · badge)
     agrees on its kind colour. (print bullets are already purple via the default below.) */
  .bom-line--print .bom-part,  .bom-line--print .bom-spec  { color: var(--purple); }
  .bom-line--source .bom-part, .bom-line--source .bom-spec { color: var(--warn); }
  .bom-line--source .bom-options li::before { color: var(--warn); }
  /* buy = the default kind — unify its label + description on the link blue (--cyan), so the row
     reads as one colour like the others (rather than --accent label + --cyan link + white text). */
  .bom-line--buy .bom-part,    .bom-line--buy .bom-spec    { color: var(--cyan); }
  .bom-part {
    color: var(--accent); text-transform: uppercase; letter-spacing: .08em;
    font-size: 10px; padding-top: 1px;
  }
  .bom-spec { color: var(--ink); min-width: 0; }
  .bom-spec a {
    color: var(--cyan); text-decoration: none;
    border-bottom: 1px solid color-mix(in srgb, var(--cyan) 40%, transparent);
  }
  .bom-spec a:hover { color: var(--brtcyan); border-bottom-color: var(--brtcyan); }
  /* Options ride their own grid row spanning spec→price, so per-option prices right-align to the
     SAME column as the main row prices (not the narrower spec cell). */
  .bom-options { grid-column: 3 / -1; list-style: none; margin: 0; padding: 0; display: grid; gap: 3px; }
  .bom-options li { position: relative; padding-left: 15px; font-size: 12px; color: var(--dim);
    display: flex; align-items: baseline; gap: 10px; }
  .bom-options li::before { content: "▸"; position: absolute; left: 0; color: var(--purple); }
  .bom-options a {
    color: var(--cyan); text-decoration: none;
    border-bottom: 1px solid color-mix(in srgb, var(--cyan) 40%, transparent);
  }
  .bom-options a:hover { color: var(--brtcyan); border-bottom-color: var(--brtcyan); }
  /* opt-label keeps the link inline (so its underline hugs the text, even when it wraps); the
     per-option price is right-aligned in its own little column, mirroring the white row prices. */
  .opt-label { min-width: 0; }
  .opt-price { margin-left: auto; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
  .opt-price--tbd { color: var(--dim); }   /* unknown cost (e.g. "TBD") — recedes, not a real figure */
  .bom-price { color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
  /* Pill + price share the rightmost cell so both align to one column (a row has one or the other). */
  .bom-end { display: flex; align-items: baseline; justify-content: flex-end; gap: 8px; white-space: nowrap; }
  .bom-via {
    font-size: 8.5px; letter-spacing: .1em; text-transform: uppercase;
    border-radius: 4px; padding: 1px 6px; white-space: nowrap;
  }
  /* buy/owned carry no tag (buy is the default); print persists onto downloaded rows. */
  .bom-via--print { color: var(--purple); border: 1px solid color-mix(in srgb, var(--purple) 50%, var(--rail)); }
  .bom-via--source { color: var(--warn); border: 1px solid color-mix(in srgb, var(--warn) 45%, var(--rail)); }
  .bom-via--ordered { color: var(--ok); border: 1px solid color-mix(in srgb, var(--ok) 45%, var(--rail)); }
  /* owned no longer renders a badge — the checkbox (.bom-ck--on) + green row carry it. */
  @media (max-width: 420px) {
    .bom-line { grid-template-columns: 16px 1fr auto; row-gap: 2px; column-gap: 10px; }
    .bom-ck    { grid-area: 1 / 1 / 3 / 2; }
    .bom-part  { grid-area: 1 / 2 / 2 / 3; }
    .bom-end   { grid-area: 1 / 3 / 2 / 4; justify-self: end; }
    .bom-spec  { grid-area: 2 / 2 / 3 / 4; }
    .bom-options { grid-area: 3 / 2 / 4 / 4; }
  }

  /* ── Footer note ── */
  /* Footer — the canonical Y3K surface footer (parity with y3krc.com / radiomaster):
     a gradient all-caps motto + the lineage line. */
  footer {
    max-width: 60ch; margin: 56px auto 0; text-align: center;
    color: var(--dim); font-size: 12px;
  }
  footer p { margin: 6px 0; }
  footer .motto {
    background: var(--ramp);
    -webkit-background-clip: text; background-clip: text; color: transparent;
    letter-spacing: .18em; text-transform: uppercase; font-weight: 700;
  }
  footer a { color: var(--blue); text-decoration: none; }
  footer a:hover { text-decoration: underline; }

  /* Wordmark scales down on small screens (mirrors the hub's breakpoint). */
  @media (max-width: 560px) {
    .mark { padding: 12px 26px 16px; border-radius: 10px; }
    .mark h1 { font-size: clamp(34px, 11vw, 56px); }
    .el-tile { width: 50px; height: 56px; top: -15px; right: -15px; }
    .el-num { font-size: 8.5px; top: 5px; left: 6px; }
    .el-sym { font-size: 22px; transform: translateY(3px); }
  }

  /* ═══════════════════════════════════════════════════════════════════════════
     Multi-page split (Phase 3a). Reuses .card / .stage / .spec; adds the gallery
     umbrella sections, the compact card-as-link, breadcrumb, and the centered
     detail layout. List-surface rules at the end are ready for Phase 3b content.
     ═══════════════════════════════════════════════════════════════════════════ */

  /* ── Umbrella sections on the index (The Fleet / The Equipment / The Parts) ── */
  .umbrella { max-width: 1240px; margin: 0 auto 52px; }
  .umbrella-head {
    display: flex; align-items: baseline; gap: 14px;
    margin: 0 auto 22px; padding-bottom: 10px;
    border-bottom: 1px solid color-mix(in srgb, var(--rail) 70%, transparent);
  }
  .umbrella-title {
    margin: 0; font-size: 15px; font-weight: 800; letter-spacing: .2em; text-transform: uppercase;
    background: var(--ramp); -webkit-background-clip: text; background-clip: text; color: transparent;
  }
  .umbrella-count { font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--dim); }

  /* ── Index card as a link — the whole poster navigates to the detail page;
     hovering anywhere on it powers up the A3K hero (same dials as .stage:hover). ── */
  a.card-link { text-decoration: none; color: inherit; display: block; }
  a.card-link:focus-visible { outline: none; }
  a.card-link:focus-visible .stage {
    outline: 2px solid color-mix(in srgb, var(--cyan) 70%, transparent); outline-offset: -3px;
  }
  @media (hover: hover) {
    a.card-link:hover .stage {
      --cx: 24px; --fringe-a: 100%; --rim: 9px; --rim-a: 92%; --bloom-a: 56%; --bloom-top: 16%;
      border-color: color-mix(in srgb, var(--cyan) 45%, var(--rail));
    }
  }
  /* The compact one-line key-spec under an index card's caption (no price). */
  .card-spec {
    margin: 10px 20px 20px; font-size: 12.5px; letter-spacing: .02em;
    color: color-mix(in srgb, var(--ink) 72%, var(--dim));
  }
  .card-spec b { color: var(--ink); font-weight: 700; }
  /* "Based on" — a quiet lead-in before a donor platform (it's the base, not the maker). */
  .card-spec .based { color: var(--dim); font-size: .92em; }

  /* ── Breadcrumb on detail pages ── */
  .crumb {
    max-width: 680px; margin: 0 auto 20px; font-size: 12px; letter-spacing: .04em; color: var(--dim);
  }
  .crumb a { color: var(--cyan); text-decoration: none; }
  .crumb a:hover { color: var(--brtcyan); }
  .crumb .sep { color: var(--rail); margin: 0 8px; }

  /* ── Detail page ── one wide, centered card carrying the full spec panel; the
     hero is bigger because the card is wider. It rests and powers up on hover like
     the gallery cards — but the hard chromatic offset is a HOVER-ONLY reward here:
     clean at rest (the rim bloom + grid floor + baked glitch carry the A3K vibe, and
     a resting offset would double a glitched hero's own baked RGB-split). The
     :not(:hover) lifts specificity above .stage:hover so the hover boost still wins. ── */
  .detail { max-width: 680px; margin: 0 auto; }
  .detail .stage { cursor: default; }
  .detail .stage:not(:hover) { --cx: 0px; }

  /* A vehicle's bound radio renders as an internal link into /radios/. */
  .spec-row dd a.radio-link {
    color: var(--magenta); border-bottom-color: color-mix(in srgb, var(--magenta) 40%, transparent);
  }
  .spec-row dd a.radio-link:hover { color: var(--rose); border-bottom-color: var(--rose); }
  /* The radio page's reverse list — the rigs a radio runs. */
  .runs { margin: 18px 20px 22px; }
  .runs a {
    color: var(--cyan); text-decoration: none;
    border-bottom: 1px solid color-mix(in srgb, var(--cyan) 40%, transparent);
  }
  .runs a:hover { color: var(--brtcyan); border-bottom-color: var(--brtcyan); }

  /* ── List surfaces (parts / batteries / chargers) — ready for Phase 3b content. ── */
  .inv { max-width: 1000px; margin: 0 auto; }
  .inv-row {
    display: grid; grid-template-columns: 150px 1fr auto; gap: 14px; align-items: baseline;
    padding: 10px 0; border-bottom: 1px dashed color-mix(in srgb, var(--rail) 50%, transparent);
    font-size: 13px;
  }
  .inv-row .k { color: var(--accent); text-transform: uppercase; letter-spacing: .1em; font-size: 10.5px; }
  @media (max-width: 560px) { .inv-row { grid-template-columns: 1fr; row-gap: 3px; } }

  /* ── Batteries — heroless per-pack cards (Equipment grid) + spec-forward pages ── */
  /* Equipment grid card with no hero: name + qty + a one-line spec. Sits among the
     radio hero cards; aligns to the top of its grid cell. */
  .card--batt { align-self: start; }
  .card--batt figcaption { margin-top: 20px; }
  .qty-badge {
    font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
    color: var(--bg); background: var(--cyan); border-radius: 5px; padding: 2px 8px; white-space: nowrap;
  }
  /* Detail page: a title row, a stat-tile grid, then the Powers list. */
  .battery { padding-bottom: 6px; }
  .batt-title { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 20px 22px 0; }
  .batt-title .lvl { font-size: 24px; }
  .batt-status {
    font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--dim);
    border: 1px solid var(--rail); border-radius: 999px; padding: 2px 10px;
  }
  .stat-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 12px;
    margin: 20px 22px;
  }
  .stat {
    background: color-mix(in srgb, var(--panel) 60%, transparent);
    border: 1px solid color-mix(in srgb, var(--rail) 70%, transparent);
    border-radius: 12px; padding: 12px 14px; display: flex; flex-direction: column; gap: 5px;
  }
  .stat-k { color: var(--accent); text-transform: uppercase; letter-spacing: .14em; font-size: 10px; }
  .stat-v { color: var(--ink); font-size: 16px; font-weight: 700; }
  .powers-none { color: var(--dim); font-size: 12.5px; font-style: italic; }

  /* Per-unit tracking table — one row per physical pack (label · purchased · status). */
  .units { margin: 4px 22px 0; }
  .units-table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 12.5px; }
  .units-table th {
    text-align: left; color: var(--accent); text-transform: uppercase; letter-spacing: .12em;
    font-size: 10px; font-weight: 700; padding: 4px 12px 6px 0;
    border-bottom: 1px solid color-mix(in srgb, var(--rail) 75%, transparent);
  }
  .units-table td {
    padding: 6px 12px; color: var(--ink); font-variant-numeric: tabular-nums;
    border-bottom: 1px dashed color-mix(in srgb, var(--rail) 45%, transparent);
  }
  .units-table td:first-child { padding-left: 0; }

  /* ── Nickname ── a rig's personal name, a quoted eyebrow above the model name. */
  .nick {
    flex-basis: 100%; margin: 0 0 1px;
    color: var(--magenta); font-size: 12.5px; font-style: italic; letter-spacing: .02em;
    text-shadow: 0 0 12px color-mix(in srgb, var(--magenta) 28%, transparent);
  }

  /* ── Detail-page documentary gallery (running rigs) ── honest, UNTREATED photos —
     no cutout, no glitch — in A3K frames. The FRAME wears the brand (dark field, rail
     edge, the wordmark RGB phase-shift fringe — subtle at rest, surging on interaction);
     the PHOTO itself gets NO filter. A horizontal filmstrip of uniform-height frames at
     natural width, scroll-snapped (touch-friendly). Detail-page only — index cards stay
     hero-only. Attribution, where needed, is the TEXT caption, never a visual treatment. */
  .gallery { margin: 22px 20px 24px; }
  /* Single column: one big image per row, scroll down through them — these cinematic scene
     composites earn the size (was a 220px-tall side-scrolling strip). */
  .gallery-strip {
    display: flex; flex-direction: column; gap: 30px; margin-top: 14px;
  }
  .shot {
    margin: 0; display: flex; flex-direction: column;
  }
  /* The A3K frame: dark field + rail edge + a resting chromatic fringe (magenta left /
     cyan right hard offsets — the same wordmark technique the heroes use, here on the
     FRAME, not the photo). overflow:hidden clips the photo's corners to the radius but
     never the frame's own box-shadow. Surges on hover/focus; the photo never moves. */
  .shot-frame {
    /* Lifted above the global CRT scanlines (body::after, z-index 200): gallery photos are
       real photographs, not the synthwave hero, so the scanlines fight them. The rest of the
       page keeps its CRT — this is a deliberate carve-out for the documentary images. */
    position: relative; z-index: 201;
    border-radius: 12px; overflow: hidden;
    background: linear-gradient(180deg, #0c0c18, #07070e);
    border: 1px solid var(--rail);
    box-shadow:
      -2px 0 0 -1px color-mix(in srgb, var(--magenta) 42%, transparent),
       2px 0 0 -1px color-mix(in srgb, var(--cyan) 42%, transparent),
       0 0 16px -11px var(--purple);
    transition: box-shadow var(--t) var(--ease), border-color var(--t) var(--ease);
  }
  /* The honest photo — uniform height, natural width (no crop of documentary detail),
     and crucially NO filter: the frame is treated, the image is not. */
  .shot-frame img {
    display: block; width: 100%; height: auto;
    -webkit-user-drag: none; user-select: none;
  }
  .shot-frame:focus-within {
    border-color: color-mix(in srgb, var(--cyan) 45%, var(--rail));
  }
  @media (hover: hover) {
    .shot-frame:hover {
      border-color: color-mix(in srgb, var(--cyan) 45%, var(--rail));
      box-shadow:
        -7px 0 0 -1px color-mix(in srgb, var(--magenta) 92%, transparent),
         7px 0 0 -1px color-mix(in srgb, var(--cyan) 92%, transparent),
         0 0 26px -8px var(--purple);
    }
  }
  .shot-cap {
    margin: 11px 2px 0; max-width: none;
    color: color-mix(in srgb, var(--ink) 74%, var(--dim));
    font-size: 12.5px; line-height: 1.5; letter-spacing: .02em;
  }
  @media (prefers-reduced-motion: reduce) { .shot-frame { transition: none; } }
  @media (max-width: 560px) { .gallery-strip { gap: 22px; } }

  /* Lightbox — click a gallery shot to enlarge; ‹ ›/arrow-keys navigate, Esc/✕/backdrop closes. */
  .shot-frame { cursor: zoom-in; }
  .lightbox {
    position: fixed; inset: 0; z-index: 1000;
    display: flex; align-items: center; justify-content: center; padding: 5vmin;
    background: color-mix(in srgb, #04040a 92%, transparent);
    -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px);
    animation: lb-in .18s var(--ease);
  }
  .lightbox[hidden] { display: none; }
  @keyframes lb-in { from { opacity: 0 } to { opacity: 1 } }
  .lb-figure {
    margin: 0; display: flex; flex-direction: column; align-items: center;
    max-width: min(94vw, 1180px); max-height: 92vh;
  }
  .lb-img {
    max-width: 100%; max-height: 84vh; width: auto; height: auto; display: block;
    border-radius: 12px; border: 1px solid var(--rail);
    box-shadow:
      -4px 0 0 -1px color-mix(in srgb, var(--magenta) 80%, transparent),
       4px 0 0 -1px color-mix(in srgb, var(--cyan) 80%, transparent),
       0 0 60px -12px var(--purple);
  }
  .lb-cap {
    margin-top: 14px; text-align: center; letter-spacing: .02em; font-size: 13px;
    color: color-mix(in srgb, var(--ink) 82%, var(--dim));
  }
  .lb-close, .lb-nav {
    position: fixed; z-index: 1001; display: flex; align-items: center; justify-content: center;
    color: var(--ink); cursor: pointer; line-height: 1;
    background: color-mix(in srgb, #0c0c18 78%, transparent);
    border: 1px solid var(--rail); border-radius: 50%;
    transition: border-color var(--t) var(--ease), background var(--t) var(--ease), transform var(--t) var(--ease);
  }
  .lb-close { top: 16px; right: 18px; width: 42px; height: 42px; font-size: 24px; }
  .lb-nav { top: 50%; transform: translateY(-50%); width: 48px; height: 48px; font-size: 30px; }
  .lb-prev { left: 14px } .lb-next { right: 14px }
  .lb-nav[hidden] { display: none; }
  @media (hover: hover) {
    .lb-close:hover, .lb-nav:hover {
      border-color: color-mix(in srgb, var(--cyan) 55%, var(--rail));
      background: color-mix(in srgb, #0c0c18 94%, transparent);
    }
    .lb-prev:hover { transform: translateY(-50%) translateX(-2px) }
    .lb-next:hover { transform: translateY(-50%) translateX(2px) }
  }
  .lb-close:focus-visible, .lb-nav:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
  @media (prefers-reduced-motion: reduce) { .lightbox { animation: none; } }
