/*
 * Semantic Design Tokens
 *
 * These tokens map semantic names to theme-specific values.
 * Components should use these tokens instead of theme-* variables directly.
 *
 * Legacy aliases are provided at the bottom for backward compatibility
 * during migration. DO NOT use legacy aliases in new code.
 */

:root {
  /* === Typography === */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  /* The mono face (#633; readout reverted round 6). Reserved for two things:
     (1) the device CALL-SIGN identity on the instrument bezel
     (DeviceCardInline .bezel .name — uppercased, letter-spaced: a designed label),
     and (2) code-like reference data — part numbers, IDs, assembly refs on the
     hardware / device-overview pages. NOT the SDR readout (state word or frequency
     range): the operator found mono reads as broken typewriter text there, so the
     readout uses Inter + tabular-nums. Never general UI. System stack: zero payload,
     Cyrillic-capable everywhere we ship (full rule: .claude/rules/css-styling.md). */
  --font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

  /* === Type scale (EPIC #990) — role-named, theme-invariant ===
     Role-named type tokens for the design-system unification. These NAMES are the
     stable contract; the values are TARGET values set to each band's dominant
     de-facto cluster (docs/design/type-spacing-inventory.md). A size that IS its
     band's cluster migrates unchanged; a band outlier (e.g. a lone 2rem or 1rem)
     snaps to the role — a deliberate, per-site-reviewed change, not a silent alias.
     Provisional until the unification finalizes them (with line-height/weight/
     tracking). DO NOT hand-tune per component — add a role here if one is missing.
     Not yet consumed; migrate families onto these. */
  --font-size-display: 30px;   /* page-level hero numerals / big display */
  --font-size-h1: 22px;        /* page title */
  --font-size-h2: 18px;        /* section heading */
  --font-size-title: 15px;     /* panel / card title */
  --font-size-body: 14px;      /* running text, controls */
  --font-size-label: 13px;     /* form labels, nav items, list rows */
  --font-size-caption: 12px;   /* secondary metadata */
  --font-size-micro: 11px;     /* uppercase micro-labels, badges */
  --font-size-nano: 10px;      /* sub-micro: dense legend / axis-tick / tiny badge labels (the 0.65rem/~10.4px cluster snaps here; canvas-only labels <=8px may stay raw literals) */
  --font-size-readout: 12.5px; /* SDR readout numerals (pair with tabular-nums) */

  /* === Spacing scale (EPIC #990) — 4px grid, theme-invariant ===
     Same contract as the type scale. Values are the strict 4px grid PLUS four
     documented half-steps (2/6/10/14px) that preserve the app's four high-frequency
     off-grid magnitudes exactly; the low-frequency off-grid long tail
     (1/3/5/7/9/18/22/28/30px) snaps to the nearest token during migration. */
  --space-0: 0;
  --space-0_5: 2px;   /* hairline gaps (off-grid, ~114 uses) — half-step so migration preserves the exact value */
  --space-1: 4px;
  --space-1_5: 6px;   /* off-grid, ~170 uses — half-step */
  --space-2: 8px;
  --space-2_5: 10px;  /* off-grid, ~122 uses — half-step */
  --space-3: 12px;
  --space-3_5: 14px;  /* off-grid, ~74 uses — half-step */
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;

  /* === Surface Colors === */
  --color-surface-page: var(--theme-surface-page);
  --color-surface-panel: var(--theme-surface-panel);
  /* The grey CONTROL fill — secondary buttons, chips, tab/segment fills, list-row +
     control hovers, small insets. Content CARDS do NOT use this: they use
     --color-surface-panel (white in light, lifting off the grey page — the B mock look).
     Only genuine interactive/inset controls sit on elevated. */
  --color-surface-elevated: var(--theme-surface-elevated);
  /* Recessed filled CONTROLS (toggle track, button/list-row hover, tab segment).
     Despite the name this is NOT the text-field fill — use --color-surface-field
     for `input`/`select`/`textarea` (#686). */
  --color-surface-input: var(--theme-surface-input);
  --color-surface-overlay: var(--theme-surface-overlay);
  /* Recessed PLANE surface (#990 N2b) — the full-bleed instrument devplane; a
     plane deeper than --color-surface-panel (the app bar). NOT a control fill
     (--color-surface-input) and NOT an elevation (--color-surface-elevated). */
  --color-surface-inset: var(--theme-surface-inset);

  /* === Text-field surfaces (#686) — `input` / `select` / `textarea` only === */
  --color-surface-field: var(--theme-surface-field);
  --color-surface-field-disabled: var(--theme-surface-field-disabled);
  --color-text-field-disabled: var(--theme-text-field-disabled);

  /* === Border Colors === */
  --color-border-default: var(--theme-border-default);
  --color-border-subtle: var(--theme-border-subtle);
  --color-border-focus: var(--theme-border-focus);
  --color-border-field: var(--theme-border-field);

  /* Hover scrim (#685). Use this for a pointer-over cue on a nav/tab/control — do
     NOT hand-roll `rgba(var(--color-text-primary-rgb), <alpha>)`: an alpha picked
     against dark is invisible in light, which is how BOTH nav rows ended up with
     no perceptible hover in light theme. */
  --color-hover-scrim: var(--theme-hover-scrim);

  /* === Text Colors === */
  --color-text-primary: var(--theme-text-primary);
  --color-text-secondary: var(--theme-text-secondary);
  --color-text-muted: var(--theme-text-muted);
  --color-text-inverse: var(--theme-text-inverse);

  /* === Accent Colors === */
  --color-accent-primary: var(--theme-accent-primary);
  --color-accent-primary-dim: var(--theme-accent-primary-dim);
  --color-accent-primary-dark: var(--theme-accent-primary-dark);
  /* Foreground drawn ON TOP of a solid accent-primary fill (toggle knob, checkbox tick). */
  --color-accent-primary-contrast: var(--theme-accent-primary-contrast);
  --color-accent-secondary: var(--theme-accent-secondary);
  --color-accent-info: var(--theme-accent-info);

  /* === Action Colors (solid affirmative-action fill — primary buttons) ===
     THEME-INVARIANT: defined ONCE here as literals (like the radii / spacing
     scales), NOT split per-theme — the primary ACTION is the same branded fill in
     dark and light, so it never inherits the wayfinding accent's ink-flip (dark ink
     on the bright dark accent read as disabled — #990 council). Distinct from
     --color-accent-*, which stays pure wayfinding (nav / selection / marks). WHITE
     label clears 4.5 on all three fills (rest 4.548 / hover 5.568 / active 7.096);
     floored by theme-integrity.test. */
  --color-action-fill: #2f6fed;
  --color-action-fill-hover: #1f5fe0;
  --color-action-fill-active: #1a4fc4;
  --color-action-ink: #ffffff;
  /* On-fill INK — the single near-black glyph/label drawn ON ANY solid --color-status-X fill. Theme-invariant literal (all four status fills need the same black to clear 4.5 — light error #d3454b is the binding case at 4.72). Replaces the former four --color-status-*-contrast tokens. Floored in theme-integrity.test. */
  --color-ink-on-status: #000000;

  /* === Status Colors === */
  --color-status-success: var(--theme-status-success);
  --color-status-error: var(--theme-status-error);
  --color-status-warning: var(--theme-status-warning);
  --color-status-active: var(--theme-status-active);
  /* Status TEXT inks (deepened, text-safe) — every status color used AS TEXT
     points here; the base tokens above are SIGNAL hues (dots / fills / borders). */
  --color-status-success-ink: var(--theme-status-success-ink);
  --color-status-error-ink: var(--theme-status-error-ink);
  --color-status-warning-ink: var(--theme-status-warning-ink);
  --color-status-active-ink: var(--theme-status-active-ink);
  --color-status-scanning: var(--theme-status-scanning);
  /* Static, deliberately subordinate fleet presence. Unlike muted copy, this must
     remain legible when composited over a basemap at reduced marker opacity. */
  --color-status-offline: var(--theme-status-offline);

  /* Fleet-map role color for lab units (teal) — deliberately distinct from the purple
     scanning ripple so a scanning lab stays legible over its own coverage oval (#647).
     Device cards keep lab purple via their own CSS; only the map (which overlays activity
     ripples) needs the divergence. */
  --color-role-lab: var(--theme-role-lab);

  /* === Threat Classification Colors === */
  --color-threat-enemy: var(--theme-threat-enemy);
  --color-threat-friend: var(--theme-threat-friend);
  --color-threat-protected: var(--theme-threat-protected);
  --color-threat-unknown: var(--theme-threat-unknown);
  --color-threat-fm-radio: var(--theme-threat-fm-radio);

  /* === Threat Background Colors === */
  --color-threat-enemy-bg: var(--theme-threat-enemy-bg);
  --color-threat-friend-bg: var(--theme-threat-friend-bg);
  --color-threat-protected-bg: var(--theme-threat-protected-bg);
  --color-threat-unknown-bg: var(--theme-threat-unknown-bg);
  --color-threat-fm-radio-bg: var(--theme-threat-fm-radio-bg);

  /* === Threat RGB Values (for layered rgba() usage) === */
  --color-threat-enemy-rgb: var(--theme-threat-enemy-rgb);
  --color-threat-friend-rgb: var(--theme-threat-friend-rgb);
  --color-threat-protected-rgb: var(--theme-threat-protected-rgb);
  --color-threat-unknown-rgb: var(--theme-threat-unknown-rgb);
  --color-threat-unknown-fill-rgb: var(--theme-threat-unknown-fill-rgb);
  --color-threat-fm-radio-rgb: var(--theme-threat-fm-radio-rgb);

  /* === Overlay Colors === */
  --color-dim-overlay: var(--theme-dim-overlay);
  /* Modal/drawer scrim — stronger than --color-dim-overlay (too light on the light theme for a
     full-surface backdrop). The mobile fleet-roster drawer dims the map behind it (#946). */
  --color-scrim: var(--theme-scrim);

  /* === Shadow Tokens === */
  --shadow-panel: var(--theme-shadow-panel);
  --shadow-focus: var(--theme-shadow-focus);
  --shadow-hover: var(--theme-shadow-hover);
  --shadow-hover-strong: var(--theme-shadow-hover-strong);
  --shadow-modal: var(--theme-shadow-modal);
  --shadow-error: var(--theme-shadow-error);
  --shadow-active: var(--theme-shadow-active);

  /* === Border Radius Tokens (EPIC #990 — hardened-B band) ===
     The jury's "tighten to 4–6px" graft is scoped to NAV / OPERATIONAL CHROME
     (controls, pills, inputs, list rows): B's raw 10–14px THERE read as
     "generic soft SaaS". Content SURFACES keep B's softer radii — over-applying
     the tightening to cards + modals (6/8px) flattened the mock's content look,
     so panels/cards restore to 10px and modals/large containers to 14px. */
  --radius-sm: 3px;      /* Chrome: tags, badges, small action buttons */
  --radius-md: 4px;      /* Chrome controls: inputs, buttons, list rows (nav idiom — do NOT enlarge) */
  --radius-lg: 10px;     /* Content surfaces: panels, cards */
  --radius-xl: 14px;     /* Content surfaces: modals, large containers */
  --radius-pill: 999px;  /* Fully-rounded pills (chips, count badges) + knobs — NOT
                            control chrome (those are --radius-md) */

  /* === Z-index scale ===
   * Leaflet owns panes and controls through 1000. Fleet content starts above
   * that ceiling; focused detection popups cover fleet flyouts; application
   * modals remain the top blocking layer. Nested modals sit one step higher.
   * Keep the numeric contract in common/Popover.tsx popoverStacking in sync;
   * Modal.tsx's numeric fallback is legacy compatibility outside #632. */
  --z-map-overlay: 1200;
  --z-detection-popup: 1400;
  --z-modal: 9998;
  --z-modal-nested: 9999;
  /* Toasts/notifications outrank even nested modals — a confirmation toast must
     be visible over the dialog that triggered it. */
  --z-toast: 10000;

  /* === RGB Values === */
  --color-accent-primary-rgb: var(--theme-accent-primary-rgb);
  --color-accent-secondary-rgb: var(--theme-accent-secondary-rgb);
  --color-accent-info-rgb: var(--theme-accent-info-rgb);
  --color-status-success-rgb: var(--theme-status-success-rgb);
  --color-status-error-rgb: var(--theme-status-error-rgb);
  --color-status-warning-rgb: var(--theme-status-warning-rgb);
  --color-status-active-rgb: var(--theme-status-active-rgb);
  --color-status-scanning-rgb: var(--theme-status-scanning-rgb);
  --color-role-lab-rgb: var(--theme-role-lab-rgb);
  --color-border-default-rgb: var(--theme-border-default-rgb);
  --color-text-primary-rgb: var(--theme-text-primary-rgb);
  --color-text-secondary-rgb: var(--theme-text-secondary-rgb);
  --color-text-muted-rgb: var(--theme-text-muted-rgb);
  --color-text-inverse-rgb: var(--theme-text-inverse-rgb);
  --color-surface-page-rgb: var(--theme-surface-page-rgb);
  --color-surface-panel-rgb: var(--theme-surface-panel-rgb);
  --color-surface-elevated-rgb: var(--theme-surface-elevated-rgb);
  --color-surface-input-rgb: var(--theme-surface-input-rgb);
  --color-surface-inset-rgb: var(--theme-surface-inset-rgb);

  /* === Dim/hover status variants === */
  --color-status-error-dim: var(--theme-status-error-dim);
  --color-status-warning-dim: var(--theme-status-warning-dim);

  /* === TRANSMIT button + CRT-effect palette === */
  --color-transmit-button-bg: var(--theme-transmit-button-bg);
  --color-transmit-trace: var(--theme-transmit-trace);
  --color-transmit-trace-rgb: var(--theme-transmit-trace-rgb);
  --color-crt-tube-bg: var(--theme-crt-tube-bg);
  --color-crt-tube-bg-active: var(--theme-crt-tube-bg-active);
  --color-crt-tube-bg-error: var(--theme-crt-tube-bg-error);
  --color-crt-scanline-rgb: var(--theme-crt-scanline-rgb);
  --color-crt-scanline-warning-rgb: var(--theme-crt-scanline-warning-rgb);

  /* === Spectrum-Sweep gradient (slider tracks; canvas surfaces use spectrumPalette.ts) === */
  --gradient-spectrum-sweep: var(--theme-gradient-spectrum-sweep);

  /* === Spectrum sweep tail glow (canvas overlay) === */
  --color-spectrum-glow-rgb: var(--theme-spectrum-glow-rgb);

  /* === Chart chrome (grid lattice + axis ticks; read from canvas via getComputedStyle) ===
   * Separate from --color-text-muted: on light, the dB/MHz lattice has to stay
   * legible under a faint spectrum fill, so it sits darker than muted body text. */
  --color-chart-grid-rgb: var(--theme-chart-grid-rgb);
  --color-chart-axis-tick: var(--theme-chart-axis-tick);

  /* ============================================
   * LEGACY ALIASES - For backward compatibility
   * DO NOT USE IN NEW CODE
   * These will be removed after full migration
   * ============================================ */

  /* Old color names -> New semantic names */
  --primary: var(--color-accent-primary);
  --primary-dim: var(--color-accent-primary-dim);
  --primary-dark: var(--color-accent-primary-dark);
  --secondary: var(--color-accent-secondary);
  --accent: var(--color-border-default);
  --text: var(--color-text-primary);
  --text-dim: var(--color-text-secondary);
  --text-muted: var(--color-text-muted);
  --bg-dark: var(--color-surface-page);
  --bg-panel: var(--color-surface-panel);
  --bg-input: var(--color-surface-input);
  --border: var(--color-border-default);
  --border-dim: var(--color-border-subtle);
  --error: var(--color-status-error);
  --warning: var(--color-status-warning);
  --scanning: var(--color-status-scanning);
  --scanning-rgb: var(--color-status-scanning-rgb);

  /* Threat colors - keep same names */
  --threat-enemy: var(--color-threat-enemy);
  --threat-friend: var(--color-threat-friend);
  --threat-protected: var(--color-threat-protected);
  --threat-unknown: var(--color-threat-unknown);
  --threat-fm-radio: var(--color-threat-fm-radio);
  --threat-enemy-bg: var(--color-threat-enemy-bg);
  --threat-friend-bg: var(--color-threat-friend-bg);
  --threat-protected-bg: var(--color-threat-protected-bg);
  --threat-unknown-bg: var(--color-threat-unknown-bg);
  --threat-fm-radio-bg: var(--color-threat-fm-radio-bg);
  --threat-enemy-rgb: var(--color-threat-enemy-rgb);
  --threat-friend-rgb: var(--color-threat-friend-rgb);
  --threat-protected-rgb: var(--color-threat-protected-rgb);
  --threat-unknown-rgb: var(--color-threat-unknown-rgb);
  --threat-fm-radio-rgb: var(--color-threat-fm-radio-rgb);
}
