/* SR-2 Tailwind dark-mode compatibility layer — v1
 * ============================================================================
 * THE PROBLEM
 * 383+ SR-2 templates use raw Tailwind utility colors (bg-white, text-gray-600,
 * bg-slate-100, border-gray-300, hover:bg-gray-50, chip strips, etc.). SR-2's
 * dark mode is the scott_common shell flipping `data-theme="dark"` on <html>
 * (see scott_common/css/tokens.css [data-theme="dark"] block). That flips the
 * shell's SURFACE/TEXT *tokens* (--bg, --card-bg, --text...), turning the page
 * background dark — but the hardcoded Tailwind utilities bypass those tokens
 * entirely. So `text-gray-700` stays dark-gray on a now-dark surface
 * (invisible), `bg-white` cards stay white islands, `bg-slate-100 text-slate-700`
 * buttons collapse, inactive chips (`bg-white border text-gray-700`) vanish.
 *
 * v0.88 (scott_common) + sr2_brand.css already fixed Bootstrap `.btn-*` and
 * saturated `bg-<color>-500/600/700 text-white` buttons. This layer fixes the
 * remaining NEUTRAL/low-contrast Tailwind utilities only.
 *
 * SCOPE / SAFETY
 * - EVERY rule below is scoped under `[data-theme="dark"]` ONLY. Light mode is
 *   byte-for-byte untouched — none of these selectors match in light mode.
 * - We remap only NEUTRAL utilities that collapse in dark mode. Saturated
 *   buttons (bg-blue-600/emerald-600/red-600 + text-white) are left ALONE —
 *   they are legible in both modes and sr2_brand.css already backs them.
 * - Values reuse the scott_common dark tokens (tokens.css [data-theme="dark"])
 *   so the look stays consistent with the shell's own dark surfaces:
 *       --card-bg #1e293b (slate-800), --bg #0f172a (slate-900),
 *       --card-border #334155 (slate-700), --text #f1f5f9, --text-muted #94a3b8,
 *       --text-soft #cbd5e1.
 * - Specificity: `[data-theme="dark"] .bg-white` (0,2,0) beats Tailwind's
 *   `.bg-white` (0,1,0) regardless of source order, so this WINS even though
 *   the Tailwind Play CDN injects its <style> after our link. No !important
 *   needed (and avoiding it keeps light-mode + saturated-button rules safe).
 *
 * WIRED VIA: imported at the END of sr2_brand.css (brand.shell_css), which the
 * scott_common shell links LAST in <head> (after scott_common shell.css). So
 * these overrides sit at the end of the app cascade. See sr2_brand.css tail.
 *
 * TODO (noted in handoff): promote to scott_common so plastics / trucking /
 * pulse / superstore inherit it too. SR-2-local now for speed.
 * ========================================================================== */

/* ── Surfaces: white / light-gray / light-slate → dark card surface ──────── */
/* Audit (recycling/templates): bg-white 764, bg-slate-100 197, bg-gray-100 133,
 * bg-gray-50 123, bg-slate-50 113, bg-gray-200 40, bg-slate-200 29, plus a long
 * tail of -200/-300/-400 light tints. All collapse on the dark slate surface. */
[data-theme="dark"] .bg-white      { background-color: #1e293b; } /* slate-800 = --card-bg */
[data-theme="dark"] .bg-gray-50    { background-color: #1e293b; }
[data-theme="dark"] .bg-gray-100   { background-color: #273548; } /* slightly lifted */
[data-theme="dark"] .bg-gray-200   { background-color: #334155; } /* tint / divider strip */
[data-theme="dark"] .bg-gray-300   { background-color: #3c4a5e; }
[data-theme="dark"] .bg-gray-400   { background-color: #475569; }
[data-theme="dark"] .bg-slate-50   { background-color: #1e293b; }
[data-theme="dark"] .bg-slate-100  { background-color: #273548; } /* table thead, Import btn */
[data-theme="dark"] .bg-slate-200  { background-color: #334155; }
[data-theme="dark"] .bg-slate-300  { background-color: #3c4a5e; }
[data-theme="dark"] .bg-zinc-50    { background-color: #1e293b; }
[data-theme="dark"] .bg-zinc-100   { background-color: #273548; }
[data-theme="dark"] .bg-zinc-200   { background-color: #334155; }
[data-theme="dark"] .bg-neutral-50  { background-color: #1e293b; }
[data-theme="dark"] .bg-neutral-100 { background-color: #273548; }
[data-theme="dark"] .bg-neutral-200 { background-color: #334155; }
/* NOTE: bg-gray-500..900 / bg-slate-500..900 / bg-black are ALREADY dark
 * surfaces (used as banners, dark footers, mid-tone buttons w/ text-white).
 * Leaving them ALONE — they're legible in both modes and host light text. */

/* ── Text: dark grays → light, hierarchy preserved ──────────────────────── */
/* Darkest body text → brightest; muted captions → muted light. Audit top hits:
 * text-gray-500 897, text-gray-600 624, text-gray-700 346, text-gray-400 139,
 * text-slate-700 81, text-slate-500 80, text-slate-600/400 33 each, + -800/-900.
 * Map -900/-800 → --text (#f1f5f9); -700/-600 → --text-soft (#cbd5e1);
 * -500/-400 → --text-muted (#94a3b8). Hierarchy preserved, all legible on dark. */
[data-theme="dark"] .text-gray-900  { color: #f1f5f9; } /* --text */
[data-theme="dark"] .text-gray-800  { color: #f1f5f9; }
[data-theme="dark"] .text-gray-700  { color: #cbd5e1; } /* --text-soft */
[data-theme="dark"] .text-gray-600  { color: #cbd5e1; }
[data-theme="dark"] .text-gray-500  { color: #94a3b8; } /* --text-muted */
[data-theme="dark"] .text-gray-400  { color: #94a3b8; }

[data-theme="dark"] .text-slate-900 { color: #f1f5f9; }
[data-theme="dark"] .text-slate-800 { color: #f1f5f9; }
[data-theme="dark"] .text-slate-700 { color: #cbd5e1; } /* Import btn label */
[data-theme="dark"] .text-slate-600 { color: #94a3b8; }
[data-theme="dark"] .text-slate-500 { color: #94a3b8; }
[data-theme="dark"] .text-slate-400 { color: #94a3b8; }

[data-theme="dark"] .text-zinc-900 { color: #f1f5f9; }
[data-theme="dark"] .text-zinc-800 { color: #f1f5f9; }
[data-theme="dark"] .text-zinc-700 { color: #cbd5e1; }
[data-theme="dark"] .text-zinc-600 { color: #cbd5e1; }
[data-theme="dark"] .text-zinc-500 { color: #94a3b8; }
[data-theme="dark"] .text-neutral-900 { color: #f1f5f9; }
[data-theme="dark"] .text-neutral-800 { color: #f1f5f9; }
[data-theme="dark"] .text-neutral-700 { color: #cbd5e1; }
[data-theme="dark"] .text-neutral-600 { color: #cbd5e1; }
[data-theme="dark"] .text-neutral-500 { color: #94a3b8; }
/* NOTE: text-gray-100/200/300 + text-slate-100/200/300 + text-white are LIGHT
 * text utilities. In SR-2 they ride on element-level DARK containers
 * (bg-slate-800 verify banners, bg-slate-900 footers, bg-gray-700 buttons) and
 * must STAY light in dark mode too — so we deliberately DON'T remap them here.
 * See the light-mode section at the bottom for why they're also left alone in
 * light mode. */

/* ── Borders: light gray/slate borders → dark border token ──────────────── */
/* Audit: border-gray-300 130, border-gray-200 46, border-gray-100 26,
 * border-slate-200 8, + a tail of -400/-100/slate-300/800. Light borders
 * disappear (or glare) on dark; pull them to --card-border (#334155). */
[data-theme="dark"] .border-gray-100  { border-color: #334155; }
[data-theme="dark"] .border-gray-200  { border-color: #334155; } /* --card-border */
[data-theme="dark"] .border-gray-300  { border-color: #334155; }
[data-theme="dark"] .border-gray-400  { border-color: #475569; }
[data-theme="dark"] .border-slate-100 { border-color: #334155; }
[data-theme="dark"] .border-slate-200 { border-color: #334155; }
[data-theme="dark"] .border-slate-300 { border-color: #334155; }
[data-theme="dark"] .border-slate-400 { border-color: #475569; }
[data-theme="dark"] .border-zinc-200    { border-color: #334155; }
[data-theme="dark"] .border-neutral-200 { border-color: #334155; }
/* Bare `border` utility (chips use `border` w/o a color) defaults to a very
   light gray in Tailwind → near-invisible-but-glaring on dark. Pull it in. */
[data-theme="dark"] .border           { border-color: #334155; }
[data-theme="dark"] .border-t         { border-top-color: #334155; }

/* ── Hover surfaces: light tints → subtle dark hover ────────────────────── */
[data-theme="dark"] .hover\:bg-gray-50:hover   { background-color: #334155; } /* slate-700 */
[data-theme="dark"] .hover\:bg-gray-100:hover  { background-color: #334155; }
[data-theme="dark"] .hover\:bg-gray-200:hover  { background-color: #475569; }
[data-theme="dark"] .hover\:bg-slate-50:hover  { background-color: #334155; } /* table rows */
[data-theme="dark"] .hover\:bg-slate-100:hover { background-color: #334155; }
[data-theme="dark"] .hover\:bg-slate-200:hover { background-color: #475569; }
[data-theme="dark"] .hover\:bg-blue-50:hover   { background-color: #1e3a5f; } /* navy-tinted hover for nav cards */
[data-theme="dark"] .hover\:bg-green-50:hover  { background-color: #14532d; } /* deep green tint */

/* ── Chips ──────────────────────────────────────────────────────────────── */
/* Inactive chip = `chip ... bg-white border border-gray-300 hover:bg-gray-50
   text-gray-700`. The bg/border/text/hover overrides above already cover it,
   but pin the composite for clarity + to guarantee a legible resting state. */
[data-theme="dark"] .chip:not(.chip-active) {
  background-color: #273548;
  border-color: #334155;
  color: #cbd5e1;
}
[data-theme="dark"] .chip:not(.chip-active):hover {
  background-color: #334155;
}
/* chip-active (bg-blue-600 text-white) is saturated + legible — leave it. */

/* ── Bootstrap outline button variants v0.88 missed ─────────────────────────
 * v0.88 / sr2_brand.css pinned ``--bs-btn-color`` only for .btn-outline-primary
 * (and -secondary). The semantic outline variants (warning / success / danger /
 * info) keep Bootstrap's defaults, whose resting text is the saturated semantic
 * color — e.g. outline-warning = amber #ffc107 (washes out on a LIGHT surface)
 * and the lighter ones drop low-contrast on the DARK slate surface. The
 * inventory item detail page (/inventory/<pk>/) uses .btn-outline-warning.
 *
 * Same fix v0.88 used for outline-primary: pin a resting text color that
 * contrasts the surface, keep the saturated border, and go WHITE once the solid
 * fill paints on hover/active. These rules are NOT [data-theme]-scoped because
 * they must hold in BOTH modes — but they ONLY touch the four variants v0.88
 * left alone, set Bootstrap CSS vars (no layout change), and (per BS 5.3 var
 * theming) leave light-mode *fills* identical; only the resting text color is
 * darkened for contrast. The dark-mode resting color is then lifted below. */
.btn-outline-warning {
  --bs-btn-color: #946200;          /* darker amber — legible on white */
  --bs-btn-border-color: #C9941A;
  --bs-btn-hover-color: #1a1a1a;    /* dark text on amber fill */
  --bs-btn-active-color: #1a1a1a;
}
.btn-outline-success {
  --bs-btn-color: #1f6b32;          /* deep green — legible on white */
  --bs-btn-border-color: #2D7A3E;
  --bs-btn-hover-color: #ffffff;
  --bs-btn-active-color: #ffffff;
}
.btn-outline-danger {
  --bs-btn-color: #a32a2a;          /* deep red — legible on white */
  --bs-btn-border-color: #B33A3A;
  --bs-btn-hover-color: #ffffff;
  --bs-btn-active-color: #ffffff;
}
.btn-outline-info {
  --bs-btn-color: #1E3A5F;          /* navy carries info (BRAND.md) */
  --bs-btn-border-color: #1E3A5F;
  --bs-btn-hover-color: #ffffff;
  --bs-btn-active-color: #ffffff;
}
/* Dark mode: the deep resting colors above would read dark-on-dark — lift the
 * resting text to a light tint of each semantic color (border stays saturated).
 * Mirrors the [data-theme="dark"] .btn-outline-primary lift in sr2_brand.css. */
[data-theme="dark"] .btn-outline-warning { --bs-btn-color: #f3c969; }
[data-theme="dark"] .btn-outline-success { --bs-btn-color: #7fd49a; }
[data-theme="dark"] .btn-outline-danger  { --bs-btn-color: #e89696; }
[data-theme="dark"] .btn-outline-info    { --bs-btn-color: #9DC3EC; }

/* ── Faint status badges that ride on neutral tints (e.g. archived 🗄️ tag:
   bg-yellow-100 text-yellow-800). Keep them readable without recoloring the
   saturated palette. Only the *light* -100/-800 pairs need help. ────────── */
[data-theme="dark"] .bg-yellow-100 { background-color: #422006; }
[data-theme="dark"] .text-yellow-800 { color: #fde68a; }

/* ── Semantic light panels: hue-50/100 → deep tint + readable hue text ────
 * A bare light semantic panel inherits --text, which is already light in dark
 * mode. Paired text-700/800/900 panels need the explicit light hue below.
 * These values pair Tailwind's deepest tints with its 200-level foregrounds;
 * every pair clears WCAG AA for normal text. Keep selectors theme-scoped: the
 * light palette is intentionally untouched. */
[data-theme="dark"] .bg-amber-50,
[data-theme="dark"] .bg-amber-100 { background-color: #451a03; }
[data-theme="dark"] .bg-blue-50,
[data-theme="dark"] .bg-blue-100 { background-color: #172554; }
[data-theme="dark"] .bg-green-50,
[data-theme="dark"] .bg-green-100 { background-color: #052e16; }
[data-theme="dark"] .bg-red-50,
[data-theme="dark"] .bg-red-100 { background-color: #450a0a; }
[data-theme="dark"] .bg-indigo-50,
[data-theme="dark"] .bg-indigo-100 { background-color: #1e1b4b; }
[data-theme="dark"] .bg-purple-50,
[data-theme="dark"] .bg-purple-100 { background-color: #3b0764; }
[data-theme="dark"] .bg-emerald-50,
[data-theme="dark"] .bg-emerald-100 { background-color: #022c22; }
[data-theme="dark"] .bg-orange-50,
[data-theme="dark"] .bg-orange-100 { background-color: #431407; }
[data-theme="dark"] .bg-rose-50,
[data-theme="dark"] .bg-rose-100 { background-color: #4c0519; }
[data-theme="dark"] .bg-violet-50,
[data-theme="dark"] .bg-violet-100 { background-color: #2e1065; }
[data-theme="dark"] .bg-teal-50,
[data-theme="dark"] .bg-teal-100 { background-color: #042f2e; }
/* 1784: cyan was the one semantic hue in use with NO dark remap at all —
 * customers/csr_queue.html and customers/expansion_report.html both render a
 * `bg-cyan-100 text-cyan-800/900` badge, which stayed a bright light chip on the
 * dark slate surface while every sibling badge deepened. tests/
 * test_dark_mode_hue_coverage.py has guarded this since 1355; no gate collected
 * the module, so it was red on main and nothing was red (1779). */
[data-theme="dark"] .bg-cyan-50,
[data-theme="dark"] .bg-cyan-100 { background-color: #083344; } /* cyan-950 */
[data-theme="dark"] .bg-yellow-50 { background-color: #422006; }

[data-theme="dark"] .bg-amber-50.text-amber-700,
[data-theme="dark"] .bg-amber-50.text-amber-800,
[data-theme="dark"] .bg-amber-50.text-amber-900,
[data-theme="dark"] .bg-amber-100.text-amber-700,
[data-theme="dark"] .bg-amber-100.text-amber-800,
[data-theme="dark"] .bg-amber-100.text-amber-900 { color: #fde68a; }
[data-theme="dark"] .bg-blue-50.text-blue-700,
[data-theme="dark"] .bg-blue-50.text-blue-800,
[data-theme="dark"] .bg-blue-50.text-blue-900,
[data-theme="dark"] .bg-blue-100.text-blue-700,
[data-theme="dark"] .bg-blue-100.text-blue-800,
[data-theme="dark"] .bg-blue-100.text-blue-900 { color: #bfdbfe; }
[data-theme="dark"] .bg-green-50.text-green-700,
[data-theme="dark"] .bg-green-50.text-green-800,
[data-theme="dark"] .bg-green-50.text-green-900,
[data-theme="dark"] .bg-green-100.text-green-700,
[data-theme="dark"] .bg-green-100.text-green-800,
[data-theme="dark"] .bg-green-100.text-green-900 { color: #bbf7d0; }
[data-theme="dark"] .bg-red-50.text-red-700,
[data-theme="dark"] .bg-red-50.text-red-800,
[data-theme="dark"] .bg-red-50.text-red-900,
[data-theme="dark"] .bg-red-100.text-red-700,
[data-theme="dark"] .bg-red-100.text-red-800,
[data-theme="dark"] .bg-red-100.text-red-900 { color: #fecaca; }
[data-theme="dark"] .bg-indigo-50.text-indigo-700,
[data-theme="dark"] .bg-indigo-50.text-indigo-800,
[data-theme="dark"] .bg-indigo-50.text-indigo-900,
[data-theme="dark"] .bg-indigo-100.text-indigo-700,
[data-theme="dark"] .bg-indigo-100.text-indigo-800,
[data-theme="dark"] .bg-indigo-100.text-indigo-900 { color: #c7d2fe; }
[data-theme="dark"] .bg-purple-50.text-purple-700,
[data-theme="dark"] .bg-purple-50.text-purple-800,
[data-theme="dark"] .bg-purple-50.text-purple-900,
[data-theme="dark"] .bg-purple-100.text-purple-700,
[data-theme="dark"] .bg-purple-100.text-purple-800,
[data-theme="dark"] .bg-purple-100.text-purple-900 { color: #e9d5ff; }
[data-theme="dark"] .bg-emerald-50.text-emerald-700,
[data-theme="dark"] .bg-emerald-50.text-emerald-800,
[data-theme="dark"] .bg-emerald-50.text-emerald-900,
[data-theme="dark"] .bg-emerald-100.text-emerald-700,
[data-theme="dark"] .bg-emerald-100.text-emerald-800,
[data-theme="dark"] .bg-emerald-100.text-emerald-900 { color: #a7f3d0; }
[data-theme="dark"] .bg-orange-50.text-orange-700,
[data-theme="dark"] .bg-orange-50.text-orange-800,
[data-theme="dark"] .bg-orange-50.text-orange-900,
[data-theme="dark"] .bg-orange-100.text-orange-700,
[data-theme="dark"] .bg-orange-100.text-orange-800,
[data-theme="dark"] .bg-orange-100.text-orange-900 { color: #fed7aa; }
[data-theme="dark"] .bg-rose-50.text-rose-700,
[data-theme="dark"] .bg-rose-50.text-rose-800,
[data-theme="dark"] .bg-rose-50.text-rose-900,
[data-theme="dark"] .bg-rose-100.text-rose-700,
[data-theme="dark"] .bg-rose-100.text-rose-800,
[data-theme="dark"] .bg-rose-100.text-rose-900 { color: #fecdd3; }
[data-theme="dark"] .bg-violet-50.text-violet-700,
[data-theme="dark"] .bg-violet-50.text-violet-800,
[data-theme="dark"] .bg-violet-50.text-violet-900,
[data-theme="dark"] .bg-violet-100.text-violet-700,
[data-theme="dark"] .bg-violet-100.text-violet-800,
[data-theme="dark"] .bg-violet-100.text-violet-900 { color: #ddd6fe; }
[data-theme="dark"] .bg-teal-50.text-teal-700,
[data-theme="dark"] .bg-teal-50.text-teal-800,
[data-theme="dark"] .bg-teal-50.text-teal-900,
[data-theme="dark"] .bg-teal-100.text-teal-700,
[data-theme="dark"] .bg-teal-100.text-teal-800,
[data-theme="dark"] .bg-teal-100.text-teal-900 { color: #99f6e4; }
[data-theme="dark"] .bg-cyan-50.text-cyan-700,
[data-theme="dark"] .bg-cyan-50.text-cyan-800,
[data-theme="dark"] .bg-cyan-50.text-cyan-900,
[data-theme="dark"] .bg-cyan-100.text-cyan-700,
[data-theme="dark"] .bg-cyan-100.text-cyan-800,
[data-theme="dark"] .bg-cyan-100.text-cyan-900 { color: #a5f3fc; } /* cyan-200 */
[data-theme="dark"] .bg-yellow-50.text-yellow-700,
[data-theme="dark"] .bg-yellow-50.text-yellow-800,
[data-theme="dark"] .bg-yellow-50.text-yellow-900,
[data-theme="dark"] .bg-yellow-100.text-yellow-700,
[data-theme="dark"] .bg-yellow-100.text-yellow-800,
[data-theme="dark"] .bg-yellow-100.text-yellow-900 { color: #fef08a; }

/* ============================================================================
 * LIGHT-MODE remap layer (the other half of the toggle bug)
 * ----------------------------------------------------------------------------
 * Dan reported text vanishing in BOTH directions of the toggle. The dark half
 * is above. The light half is the inverse risk: a LIGHT text utility (text-white
 * / text-gray-100..300 / text-slate-100..300) sitting on a WHITE/light surface
 * is invisible in LIGHT mode.
 *
 * SCOPE: every rule here is scoped to `[data-theme="light"]` so it ONLY fires in
 * light mode and never disturbs the dark layer above. (The no-flash bootstrap in
 * _shell.html always writes an explicit data-theme of "dark" OR "light" — it
 * never leaves the attribute absent — so light mode is reliably labeled. The
 * "no-attribute === light" fallback is also covered via :root:not([data-theme])
 * for the brief pre-script window / JS-off.)
 *
 * AUDIT-DRIVEN SAFETY — why this layer is SURGICAL, not a blanket remap:
 * The audit of recycling/templates shows the light-text utilities are NOT
 * actually broken on white in SR-2:
 *   - `text-white` (606 uses): every instance rides a saturated/branded/dark/
 *     mid-tone background — bg-blue-600, bg-emerald-600, bg-gray-500/700,
 *     bg-slate-500/700/800/900, bg-success/primary/info/danger (Bootstrap),
 *     bg-brand, bg-gradient-* — OR is a `hover:text-white` that only paints once
 *     a saturated hover fill is present. There are ZERO `.bg-white.text-white`
 *     same-element combos (verified by grep). So blanket-remapping `text-white`
 *     would DESTROY hundreds of legible saturated buttons. We do NOT touch it.
 *   - `text-gray-300` / `text-slate-300` (and -100/-200): used as (a) subtle
 *     breadcrumb separators ("/", "|", "→") and "0" placeholders — intentionally
 *     faint on white, and (b) LIGHT body text inside element-level DARK
 *     containers (stations: <div class="bg-slate-800 text-white"><p
 *     class="text-slate-300">; footers: bg-slate-900 text-slate-300). CSS cannot
 *     see the parent's background, so a blanket light-mode remap of these to a
 *     dark color would BLACK-OUT the dark-container text (the exact bug we're
 *     fixing, just flipped). So we do NOT blanket-remap these either.
 *
 * THE ONE UNAMBIGUOUS LIGHT-MODE BUG WE CAN FIX BLIND:
 * a light text utility combined with a WHITE/light-neutral background on the
 * SAME element. That's always invisible regardless of any parent, and never a
 * saturated button. We pin it to the dark text token. (Grep finds none today in
 * SR-2, so these are defensive — they cost nothing and guard against a future
 * template author writing `bg-white text-white`.)
 * ========================================================================== */

/* White/light text on a white/light-neutral surface (same element) → dark text.
 * Always a bug; never a saturated button. Defensive (0 hits in current audit). */
[data-theme="light"] .bg-white.text-white,
:root:not([data-theme]) .bg-white.text-white,
[data-theme="light"] .bg-gray-50.text-white,
[data-theme="light"] .bg-gray-100.text-white,
[data-theme="light"] .bg-slate-50.text-white,
[data-theme="light"] .bg-slate-100.text-white,
[data-theme="light"] .bg-white.text-gray-100,
[data-theme="light"] .bg-white.text-gray-200,
[data-theme="light"] .bg-white.text-gray-300,
[data-theme="light"] .bg-white.text-slate-100,
[data-theme="light"] .bg-white.text-slate-200,
[data-theme="light"] .bg-white.text-slate-300 {
  color: #0f172a; /* --text (light mode) */
}

/* AMBIGUOUS CASES DELIBERATELY LEFT FOR HUMAN REVIEW (see handoff):
 *   - bare `text-white` / `hover:text-white` (606) — virtually all on saturated
 *     or dark surfaces; cannot be remapped blind without breaking buttons.
 *   - bare `text-gray-300` / `text-slate-300` separators on white — subtle by
 *     design; bumping contrast is a design call, not a legibility bug.
 *   - `text-white-50` (2: pickups/create.html, routing/_run_sheet_table.html) —
 *     both inside saturated headers; legible. Left alone.
 * If any of these turn out invisible in practice, the right fix is per-template
 * (swap the utility), not a sibling-blind CSS rule. */
