/* ═══════════════════════════════════════════════════════════════════
   Jetfolio Design Tokens — THE single source of truth
   Design System 2.0 · Direction A "Slate, refined" (owner-approved
   2026-08-25, docs/design/MODERNIZATION-ROADMAP.md D1–D3)

   Rules:
   - Every color in the product comes from this file via var().
   - This file is linked statically in every page's <head>, before all
     other stylesheets. No runtime injection.
   - Hard-coded hex values in pages are defects (Phase 3 sweeps them).
   - The "legacy alias" section keeps every historical token name alive
     so existing pages keep rendering; new code uses canonical names.
   ═══════════════════════════════════════════════════════════════════ */

/* Brand type: DM Sans throughout — one face; operational data is the same
   face with tabular numerals (the monospace role was retired 2026-09-04).
   Allowed by the hosting CSP (style-src fonts.googleapis.com,
   font-src fonts.gstatic.com). display=swap avoids invisible text. */
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&display=swap');

:root {
    /* ── Canonical: ground & surfaces ─────────────────────────────── */
    --paper: #f6f2ea;            /* Slate & Paper — the beige ground (18.1) */
    --bg: var(--paper);          /* page background */
    --surface: #ffffff;          /* cards, inputs, tables */
    --wash: #faf8f4;             /* hover tint, subtle fills */
    --line: #e2dbcc;             /* borders, dividers */
    --line-strong: #cfc5b0;      /* input borders, emphasis */
    --navy-bar: #101c2e;         /* app bar, dark sidebars */

    /* ── Canonical: ink ───────────────────────────────────────────── */
    --ink: #16202e;              /* headings, KPI numbers, data */
    --ink-body: #2a3648;         /* body text */
    --ink-2: #55627a;            /* secondary text */
    /* Muted text. Phase 5 (2026-08-28): the previous values were AA on WHITE
       only — #64748b measured 3.86:1 on --bg-secondary and #7d89a0 as low as
       2.86:1, and both are routinely used on the tinted grounds (--bg,
       --bg-secondary, --wash), so they failed in place. #5b6779 clears 4.5:1
       on every surface in this file (worst case 4.65:1 on #e2e8f0).
       At AA on tinted grounds the "muted" and "label" greys converge, so
       --ink-label now points at --ink-muted: the label hierarchy is carried
       by size, weight and letter-spacing, not by a lighter colour. */
    --ink-muted: #5b6779;        /* muted text — AA on every surface here */
    --ink-label: var(--ink-muted); /* 11px uppercase labels */

    /* ── Canonical: accent (the ONE brand color) ──────────────────── */
    --accent: #2c5282;
    --accent-deep: #1e3a5f;
    --bar-bg: #1e3a5f;           /* the navigation bar (18.2) */
    --bar-ink: #f6f2ea;          /* paper on navy — 10.3:1 */
    --bar-ink-dim: rgba(246, 242, 234, 0.72);
    --accent-light: #4a7ab5;
    --accent-soft: #e7eef7;

    /* ── Grid chrome ──────────────────────────────────────────────────
       Owner, 2026-09-09: "the dark navys suck the users eyes in."

       The date headers and label rails on the scheduling surfaces were the
       app bar's --navy-bar. That made the CHROME the darkest thing on an
       otherwise light page: the eye landed on the frame instead of on the
       schedule, and the assignment bars read as washed out beside it. The
       frame recedes now, and the data is the darkest thing on the page.

       The app bar itself stays dark. One dark band at the top of the window
       is an anchor; a dark band around every grid is a distraction. */
    --grid-head:      var(--accent-soft);  /* the date header band */
    --grid-head-alt:  #dbe6f3;             /* weekends — one step deeper */
    --grid-rail:      var(--surface);      /* the label columns down the side */
    --grid-ink:       var(--ink);          /* on the header band */
    --grid-ink-2:     var(--ink-body);
    --grid-ink-muted: var(--ink-muted);
    --grid-line:      var(--line-strong);  /* the rule that ends the header */
    --grid-hairline:  var(--line);
    /* One calendar day's column width, shared by every day-columns-across
       grid. Unified 2026-09-12 (Build stage 3 of 4): scheduler-grid.css and
       rotation-view.css each hardcoded their own value (72px vs 74px) —
       one shared token so the two grids' day columns are always the same
       width. scheduler-grid.css's --sched-day-w still exists as the local
       per-table var its resize handle writes to at runtime; this is only
       its default. */
    --grid-day-w: 72px;
    /* Rotation pages only (2026-09-13, item 1 of the geometry pass): a full
       tail chip ("N517GH") and a status badge like "Medical Leave" were
       truncating/wrapping at the shared 72px day width — the scheduler
       grid's own day cells never carry that much single-cell text, so it
       never needed the room. Derived from --grid-day-w rather than a
       literal so the two grids can never drift back to unrelated numbers;
       rotation-view.css's own auto-fit pass (_applySegmentColumnWidths)
       still widens a banded day further when its measured content needs
       more than this floor. */
    --rv-day-w: calc(var(--grid-day-w) + 40px);

    /* ── Canonical: status (bg / ink pairs) ───────────────────────── */
    --ok-bg: #e3f3e8;    --ok-ink: #1a6b3c;
    --warn-bg: #fbeedd;  --warn-ink: #92500e;
    --bad-bg: #fbe5e5;   --bad-ink: #a12626;
    --info-bg: #e4eefb;  --info-ink: #23568f;
    --neutral-bg: #e9edf3; --neutral-ink: #55627a;
    /* A status ink painted as a SOLID fill — a danger or approve button —
       needs a pressed/hover shade, the way --accent has --accent-deep. Each
       is its ink taken 20% toward black. Added 2026-09-14 with the ruling
       that put the Tailwind status names on this palette; until then those
       hovers used Tailwind's own darker steps (#991b1b, #166534). */
    --ok-deep: #155630;
    --warn-deep: #75400b;
    --bad-deep: #811e1e;
    --info-deep: #1c4572;

    /* ── Training Timeline (T1) currency bands ──────────────────────
       DUE (amber) / GRACE (red) — distinct from --warn-* / --bad-* on
       purpose: those are the app's general status vocabulary (pills,
       compliance cells); these two are a bar painted UNDER a rotation
       cell's own on/off fill and chip content, so they need to read at a
       lower visual weight than a solid status pill at the same time as
       staying legible against both --ok-bg and --bg-card underneath them. */
    --band-due-bg: #f2c97a;    --band-due-border: #d9ad4f;  --band-due-ink: #5a4008;
    --band-grace-bg: #e9a2a2;  --band-grace-border: #cf7f7f; --band-grace-ink: #6a1f1f;

    /* ── Training on-rotation marker (batch 39, item 7) ──────────────
       An ACCEPTED class overlapping a rotation/unavailable day — the
       band's own amber top edge + the name-cell ledger warning line.
       Its own pair, not --warn-bg/--warn-ink: those already mean
       something else here (a PENDING option's still-unresolved
       conflict, training-view.css's .tl-opt-band--conflict), and this
       marker is advisory only, on a booking that already happened —
       same "distinct on purpose" reasoning as --band-due-*/--band-
       grace-* above. Matches the owner-approved mock (Claude outputs/
       training_on_rotation_marker_options.html) exactly. */
    --onrot-edge: #e0a33a; --onrot-warn-ink: #8a5a0a;

    /* ── Overtime — ONE token set (batch 37, item 6) ─────────────────
       OT used to be painted two different ways: a hand-typed tan hex
       triplet on the rotation-page tail chip and the Training mini
       chip, and the generic --warn-bg/--warn-ink (a DIFFERENT color,
       #fbeedd/#92500e — that pair's own comment above calls it "OT
       tan", which is exactly the drift this fixes) on the scheduler's
       run blocks and crew-day-bands. Neither was the same
       amber as the Training DUE band. This is the same family as
       --band-due-* on purpose (an OT hour and a due check are both
       "amber, pay attention") but its own distinct values, so a caller
       painting OT never has to reach for --warn-bg (which every OTHER,
       non-OT warning in the app still uses, unchanged) again. */
    --ot-bg: #f0cf8a;  --ot-border: #b8860b;  --ot-ink: #4a3300;

    /* ── Batch 37, item 7 — the month row pinned above the day header on
       the timeline pages (scheduler/rotations/training), so the visible
       month never scrolls out of sight. A distinct light band, never the
       dark header chrome (--rv-chrome-2/--sched-navy) the day row itself
       uses, so the two rows read as two different jobs — "which month"
       vs. "which day" — not one taller header. */
    --month-row-bg: #e0e8f2; --month-row-ink: #2f4f7d;

    /* ── CAE coordinator view (Training T3, item 2) — a range note (any
       type: vacation, appointment, anything) renders generically, stripped
       of the note's own text/type, since projectForCoordinator() never
       lets the reason reach this page. */
    --band-unavail-bg: #e4e7ec; --band-unavail-border: #c4c9d2; --band-unavail-ink: #4a5262;

    /* ── Crew-day-bands: LEG tints (batch 18, item 3 — approved
       split_segment_tint_options option B) ───────────────────────────
       A band's tint marks its SEGMENT INDEX (1st leg of the day, 2nd,
       3rd…), never crew identity or status — so these five are deliberately
       spread across hue, not drawn from the status palette above, and kept
       clearly apart from --warn-bg (OT tan) and --bad-bg (conflict/
       not-legal red) so a tint is never mistaken for either. Each also has
       its own solid "disc" tone (the segment number badge/hover-outline
       color) plus a legible on-disc text color. See
       css/scheduler/crew-day-bands.css for where they're used. */
    --cdb-tint-0: #f3f0e8;  /* seg 1 — parchment */
    --cdb-tint-0-disc: #c9c2b4;
    --cdb-tint-0-text: #1f2a44; /* dark */
    --cdb-tint-1: #dbe6f5;  /* seg 2 — sky blue */
    --cdb-tint-1-disc: #7fa3d6;
    --cdb-tint-1-text: #ffffff;
    --cdb-tint-2: #e9dff3;  /* seg 3 — lavender */
    --cdb-tint-2-disc: #a985c9;
    --cdb-tint-2-text: #ffffff;
    --cdb-tint-3: #dfeee3;  /* seg 4 — soft green */
    --cdb-tint-3-disc: #7fb59a;
    --cdb-tint-3-text: #ffffff;
    --cdb-tint-4: #f6e9d4;  /* seg 5 — amber */
    --cdb-tint-4-disc: #d1a05a;
    --cdb-tint-4-text: #1f2a44; /* dark */

    /* Two block shades (2026-09-13, item 10 of the geometry pass): a seat
       row's blocks alternate --neutral-bg / --sched-block-shade-2 whenever
       they abut (interlock or end-to-start with no empty day between),
       resetting to --neutral-bg after any empty day. Deliberately its own
       value rather than reusing --cdb-tint-3 (close in hue) — that family
       is an IDENTITY cue for banded/multi-segment days (see the note above
       cdb-tint-0) and must never be mistaken for this plain alternation,
       which carries no identity meaning at all. scheduler-grid.css only —
       rotation-view never shades by adjacency. */
    --sched-block-shade-2: #dbe1e8;

    /* R1 — scheduler_requests grid overlay (item 1): the wash behind PIC/
       SIC/FA cells for an open request's own date range, and the tag that
       hangs from the PIC row's top edge on the range's first day. */
    --sched-req-wash: rgba(127, 181, 154, .26);
    --sched-req-tag-bg: #4f9a6a;
    --sched-req-tag-cleared: #9aa3b2;

    /* ── Typography ───────────────────────────────────────────────── */
    --font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    /* 2026-09-04: the monospace role is retired (owner: too computer-looking).
       The token stays so every usage keeps resolving; it now aliases the
       interface face, and figures get tabular numerals where the kit applies
       them (data classes, tables, the clock). */
    --font-mono: var(--font-family);

    /* ── Type scale ───────────────────────────────────────────────────
       Phase 1 (2026-08-29). Until now this scale existed only as prose in
       docs/STYLE-GUIDE.md, so 83 pages each invented their own — 152 distinct
       font-size literals and 43 distinct rendered sizes were measured across
       the product. These are the tokens that prose described.

       Floors from the style guide: nothing below 11px, and 11px is for
       uppercase labels only; body text never below 13px.

       NOTE ON MONO WEIGHT: DM Sans ships 300/400/500 ONLY — there is no 600 or
       700 face. Google Fonts silently drops unavailable weights from the
       request, so a mono rule asking for 600/700 gets FAUX BOLD synthesised by
       the browser, not a real face. Do not "fix" this by adding weights to the
       @import above; it has no effect. Cap mono at --weight-data-strong. */
    --text-title: 22px;          /* one page title per page */
    --text-section: 17px;        /* section heading */
    --text-card: 15px;           /* card heading */
    --text-body: 14px;           /* body copy */
    /* NOT called --text-secondary: that name is already an established COLOUR
       alias further down this file (--text-secondary: var(--ink-2)) with ~5,500
       consumers. Declaring it twice in one :root made the later colour win and
       silently killed the size token — .jf-page-sub fell back to 16px. */
    --text-support: 13px;        /* secondary / supporting copy */
    --text-label: 11px;          /* UPPERCASE letter-spaced labels ONLY */
    --text-data: 13.5px;         /* operational data, tabular figures */
    /* Dense operational grids ONLY — a surface packing a month of day-columns
       against thirty-odd crew rows: the scheduler, the rotation views, the
       master calendar. Added 2026-09-08 (Initiative 20) after measuring 70
       declarations sitting at 12/12.5px across those grids with no token to
       land on. The alternative was --text-support (13px), which makes the
       already-tight crew columns clip more names, and clipped names were the
       first thing the owner flagged. NOT for prose, NOT for chrome, NOT for
       anything outside a data grid: everywhere else the floor stays 13px. */
    --text-dense: 12px;

    --weight-title: 700;
    --weight-section: 700;
    --weight-card: 600;
    --weight-body: 400;
    --weight-label: 600;
    --weight-data: 400;
    --weight-data-strong: 500;   /* data-strong weight (kept at 500 when the mono face left) */

    /* ── Names/chips/badges type (2026-09-13, item 3 of the geometry pass) ──
       The scheduler grid, the rotation pages and the crew roster each
       rendered a crew name/tail chip/status badge at its own weight and
       size — crew-day-bands.css's --cdb-name-* trio already unified this
       for band content shared by scheduler-grid and rotation-view; these
       are the canonical values (moved here, tokens.css being the single
       source) and crew-day-bands.css now points at them instead of
       re-declaring them. --font-ui names the one interface face so a page
       can opt a name/chip/badge rule onto it without reaching for the more
       general --font-family (same value; a semantic alias for this
       specific vocabulary). */
    --font-ui: var(--font-family);
    --font-name-weight: 400;
    --font-name-size: var(--text-dense);
    --font-chip-weight: 600;
    --font-chip-size: var(--text-label);

    --tracking-label: 0.06em;    /* the letter-spacing that makes 11px legible */
    --leading-tight: 1.25;
    --leading-normal: 1.5;

    /* Modal/dialog scrim. 18 distinct scrim colours were measured across 44
       files, none of them tokenised. */
    --scrim: rgba(16, 28, 46, 0.55);

    /* ── Shape ────────────────────────────────────────────────────── */
    --radius-sm: 6px;
    --radius-md: 8px;            /* controls */
    --radius-lg: 10px;           /* cards */
    --radius-xl: 12px;
    --radius-2xl: 16px;
    --radius-full: 9999px;

    /* ── Shadows — neutral slate, whisper-quiet ───────────────────── */
    --shadow-none: none;
    --shadow-xs: 0 1px 2px rgba(22, 32, 46, 0.04);
    --shadow-sm: 0 1px 2px rgba(22, 32, 46, 0.05);
    --shadow-md: 0 2px 6px rgba(22, 32, 46, 0.07);
    --shadow-lg: 0 4px 14px rgba(22, 32, 46, 0.09);
    --shadow-xl: 0 8px 22px rgba(22, 32, 46, 0.11);
    --shadow-inner: inset 0 2px 4px 0 rgba(22, 32, 46, 0.04);
    --shadow-card: none;

    /* ── Spacing ──────────────────────────────────────────────────── */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    --spacing-2xl: 3rem;
    --spacing-3xl: 4rem;

    /* ── Z-index scale ────────────────────────────────────────────── */
    --z-base: 1;
    --z-dropdown: 100;
    --z-sticky: 500;
    --z-header: 600;
    --z-modal-backdrop: 1000;
    --z-modal: 1001;
    --z-toast: 2000;
    --z-tooltip: 3000;

    /* ── Touch targets ────────────────────────────────────────────── */
    --touch-target-min: 44px;
    --touch-target-comfortable: 48px;
    --touch-target-large: 56px;

    /* ── Transitions ──────────────────────────────────────────────── */
    --transition-fast: 150ms ease;
    --transition-normal: 250ms ease;
    --transition-slow: 350ms ease;

    /* ══════════════════════════════════════════════════════════════
       LEGACY ALIASES — every historical token name, resolved to the
       canonical palette above. Pages keep using these names until
       their Phase 3 sweep; delete each alias when its last consumer
       is migrated. Never point one of these at a non-canonical value.
       ══════════════════════════════════════════════════════════════ */

    /* primary / accent family */
    --primary-color: var(--accent);
    --warm-accent: var(--accent);
    --warm-accent-light: var(--accent-light);
    --warm-accent-dark: #1e3a6e;
    --warm-dark: var(--accent-deep);          /* was undefined → brown hovers */
    --warm-brown: var(--accent);              /* was undefined */
    --secondary-color: var(--accent-light);
    --contrast-navy: var(--accent-deep);
    --icon-color: var(--accent-deep);
    --icon-secondary: #475569;
    --navy-accent: #1e3a6e;
    --navy-accent-light: var(--accent-light);
    --navy-accent-dark: var(--accent-deep);
    --primary-navy: var(--accent);
    --primary-navy-light: var(--accent-light);
    --primary-navy-dark: #1e3a6e;
    --sky-blue: var(--accent-light);
    --sky-blue-light: #8fb8db;
    --sky-blue-dark: var(--accent);
    --accent-purple: var(--accent);
    --primary-purple: #1e3a6e;
    --purple: var(--accent);
    --purple-light: var(--accent-light);
    --purple-dark: #1e3a6e;
    --accent-blue: var(--accent);
    --accent-dark: var(--accent-deep);
    --accent-soft-bg: var(--accent-soft);

    /* gold family → slate blues (gold is retired) */
    --gold: #6b9fd4;
    --gold-light: #8fb8db;
    --gold-dark: #3468a0;
    --gold-accent: #3468a0;                   /* was undefined → gold literals */

    /* surfaces */
    --bg-primary: var(--bg);
    --bg-secondary: #ede7db;
    --bg-tertiary: #f0ebe0;                   /* was undefined → warm cream */
    --bg-card: var(--surface);
    --card-bg: var(--surface);                /* misspelling in live use */
    --bg-card-alt: #faf8f4;
    --bg-elevated: var(--surface);
    --bg-muted: var(--wash);                  /* was undefined */
    --warm-bg: var(--bg);
    --warm-card: var(--surface);
    --warm-subtle: var(--bg-card-alt);

    /* borders */
    --warm-border: var(--line);
    --warm-border-dark: var(--line-strong);   /* was undefined → tan borders */
    --warm-divider: var(--line);
    --border-default: var(--line);
    --border-subtle: #ece6da;
    --border-strong: var(--line-strong);
    --border-color: var(--line);              /* was undefined */

    /* text */
    /* These two were LITERALS while their siblings were aliases, so the
       app's default body colour was #1e293b — a Tailwind slate, one shade
       off the palette's own --ink and owned by nobody. 455 uses of
       --text-primary followed it, including `body { color: … }` in
       global.css, which is to say most text in the product. Owner ruled
       them clean on 2026-09-12. Contrast improves slightly on white
       (#16202e is marginally darker than #1e293b); nothing else moves. */
    --text-color: var(--ink);
    --text-primary: var(--ink);
    --text-secondary: var(--ink-2);
    --text-muted: var(--ink-muted);
    --text-on-light: #3d4a5f;
    --text-heading: var(--ink);
    --text-decorative: #94a3b8;               /* decoration only, never body text */
    --text-inverse: #ffffff;

    /* gradients — navy only; the warm/tan gradients are retired */
    --gradient-warm: linear-gradient(135deg, #2c5282 0%, #4a7ab5 100%);
    --gradient-warm-subtle: linear-gradient(135deg, rgba(44,82,130,0.08) 0%, rgba(74,122,181,0.05) 100%);
    --gradient-navy: linear-gradient(135deg, #1e3a6e 0%, #1e3a5f 100%);
    --gradient-sky: linear-gradient(135deg, #4a7ab5 0%, #6b9fd4 100%);
    --gradient-success: linear-gradient(135deg, var(--success-green-dark) 0%, var(--success-green) 100%);
    --gradient-danger: linear-gradient(135deg, var(--danger-red-dark) 0%, var(--danger-red) 100%);

    /* semantic status (legacy names)
       RULED 2026-09-14: our palette, not Tailwind's. Every name here now
       resolves to a status pair above: the plain and -text names to the
       ink, -bg to the ground, -dark to the deep shade. -light goes to the
       ink as well; a light Tailwind step had no job here but failing
       contrast (#22c55e is 2.3:1 on white). Until the ruling this block was
       Tailwind-derived and one shade off the palette everywhere:
       --success-color #15803d against --ok-ink #1a6b3c, --warning-color
       #b45309 against --warn-ink #92500e, --danger-color #b91c1c against
       --bad-ink #a12626. */
    --success-color: var(--ok-ink);
    --success-green: var(--ok-ink);
    --success-green-light: var(--ok-ink);
    --success-green-dark: var(--ok-deep);
    --success-bg: var(--ok-bg);
    --success-text: var(--ok-ink);
    --warning-color: var(--warn-ink);
    --warning-yellow: var(--warn-ink);
    --warning-amber: var(--warn-ink);
    --warning-bg: var(--warn-bg);
    --warning-text: var(--warn-ink);
    /* --error-color is the ONLY member of this family that was never
       declared. Five sites asked for it — the toast component, utils,
       auth-manager and login — and an undeclared name does not fail: the
       browser quietly takes the #ef4444 written beside it. So every error
       message in the product painted a Tailwind red that is not in the
       palette, and nothing ever reported it. Owner ruled it to our red on
       2026-09-12. It points at the canonical --bad-ink rather than at
       --danger-color, which was itself off-palette until 2026-09-14. */
    --error-color: var(--bad-ink);
    --danger-color: var(--bad-ink);
    --danger-red: var(--bad-ink);
    --danger-red-dark: var(--bad-deep);
    --danger-bg: var(--bad-bg);
    --danger-text: var(--bad-ink);
    --info-color: var(--accent);
    --info-text: var(--info-ink);
    --status-comp: var(--accent);             /* crew calendars; was brown */

    /* grayscale (Tailwind-era names in live use) */
    --gray-50: #f9fafb;
    --gray-100: #f3f4f6;
    --gray-200: #e5e7eb;
    --gray-300: #d1d5db;
    --gray-400: #9ca3af;
    --gray-500: #6b7280;
    --gray-600: #4b5563;
    --gray-700: #374151;
    --gray-800: #1f2937;
    --gray-900: #111827;

    /* risk levels (FRMS) */
    --risk-low: #22c55e;
    --risk-low-bg: rgba(34, 197, 94, 0.15);
    --risk-moderate: #eab308;
    --risk-moderate-bg: rgba(234, 179, 8, 0.15);
    --risk-high: #f97316;
    --risk-high-bg: rgba(249, 115, 22, 0.15);
    --risk-critical: #ef4444;
    --risk-critical-bg: rgba(239, 68, 68, 0.15);

    /* ── Status palette, as shipped ───────────────────────────────────
       Phase 6 step 1 (2026-08-28). Generated markup across FRMS, SMS,
       Pro Forma and the quote tools hardcodes a Tailwind-derived status
       palette — 4,609 standalone colour literals, 368 distinct values.
       These 17 names covered the dominant ~1,250 of them at their exact
       values, so pointing code at them changed no pixels. Centralising
       first made the duplication visible; rationalising was step two.

       Step two, RULED 2026-09-14 with the legacy block above: the names
       resolve to the palette's pairs. Solid and -ink names take the ink,
       -soft the ground, -dark the deep shade, -light the ink. The
       duplicates this block exposed are one colour each now: --status-
       danger (#dc2626) and --danger-color (#b91c1c) are both --bad-ink, and
       --status-warning-ink (#92400e) is --warn-ink.

       Outside the ruling: --risk-* above, FRMS's four levels, which have no
       one-to-one match with three statuses; and the literals still written
       straight into markup. */

    /* solid */
    --status-success: var(--ok-ink);
    --status-success-dark: var(--ok-deep);
    --status-warning: var(--warn-ink);
    --status-warning-dark: var(--warn-deep);
    --status-warning-light: var(--warn-ink);
    --status-danger: var(--bad-ink);
    --status-info: var(--info-ink);
    --status-info-dark: var(--info-deep);

    /* soft badge pairs (background + its text) */
    --status-success-soft: var(--ok-bg);
    --status-success-ink: var(--ok-ink);
    --status-warning-soft: var(--warn-bg);
    --status-warning-ink: var(--warn-ink);
    --status-danger-soft: var(--bad-bg);
    --status-info-soft: var(--info-bg);
    --status-info-ink: var(--info-ink);

    /* neutral extremes used by generated markup */
    --slate-900: #0f172a;
    --slate-100: #f1f5f9;
}

/* ── Base: every page gets the brand ground and type ──────────────── */
body {
    font-family: var(--font-family);
    background: var(--bg-primary);
    color: var(--text-primary);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Operational data reads in the data font wherever pages opt in */
.mono, .tail-number, .icao, .zulu-time {
    font-family: var(--font-mono); font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum';
}

/* ══════════════════════════════════════════════════════════════════
   PHASE-1 COMPATIBILITY OVERRIDES — retire during Phase 3 sweeps.
   Carried over from the retired v905-theme.css so dozens of pages
   keep their navy card headers while they await their sweep.
   ══════════════════════════════════════════════════════════════════ */
.card-header,
.section-header-bar,
[class*="card-header"]:not(.settings-card-header):not(.format-card-header):not(.metric-card-header) {
    background: #1e3a6e !important;
    color: #ffffff !important;
    border-bottom: none !important;
}

/* Child headings inside those navy bands often carry their own dark
   color rule — force them legible until each page's Phase 3 sweep. */
.card-header h1, .card-header h2, .card-header h3, .card-header h4,
.section-header-bar h1, .section-header-bar h2, .section-header-bar h3,
[class*="card-header"]:not(.settings-card-header):not(.format-card-header):not(.metric-card-header) h1,
[class*="card-header"]:not(.settings-card-header):not(.format-card-header):not(.metric-card-header) h2,
[class*="card-header"]:not(.settings-card-header):not(.format-card-header):not(.metric-card-header) h3,
[class*="card-header"]:not(.settings-card-header):not(.format-card-header):not(.metric-card-header) h4 {
    color: #ffffff !important;
}
