/* ===========================================================================
   FE Probability Solver — Web Demo · Design Tokens
   Style: Data-Dense Research Dashboard
   Single source of truth for color, type, spacing, radius, elevation, z-index,
   motion. Consumed by every component CSS file and by the Plotly/JS chart theming
   layer (read via getComputedStyle on :root).

   Contract: webapp/docs/contracts/04-ui-spec.md
   Do NOT hard-code colors/sizes in component CSS — reference these vars only.
   WCAG AA: all text/background pairings below are >= 4.5:1 (>= 3:1 for large
   text and non-text UI). See the contrast table in 04-ui-spec.md sec. 9.
   =========================================================================== */

:root {
  /* ---------------------------------------------------------------------
     1. BRAND / CORE PALETTE  (light mode is the default theme)
     --------------------------------------------------------------------- */
  --color-primary:        #1E40AF;   /* blue-800 — primary actions, active tab, links */
  --color-primary-hover:  #1B3A9C;   /* darker on hover */
  --color-primary-active: #172E7C;   /* pressed */
  --color-secondary:      #3B82F6;   /* blue-500 — secondary accents, secondary series */
  --color-secondary-hover:#2563EB;
  --color-accent:         #F59E0B;   /* amber-500 — CTA (Run), highlights, focus glow */
  --color-accent-hover:   #D97706;   /* amber-600 — accent hover (AA text on amber needs dark fg) */
  --color-accent-active:  #B45309;

  /* Neutrals / surfaces */
  --color-bg:             #F8FAFC;   /* app background (slate-50) */
  --color-surface:        #FFFFFF;   /* cards, panels, tab bodies */
  --color-surface-2:      #F1F5F9;   /* nested surface, table header, input wells (slate-100) */
  --color-surface-3:      #E2E8F0;   /* sunken / hover row tint (slate-200) */
  --color-border:         #CBD5E1;   /* default 1px borders (slate-300) */
  --color-border-strong:  #94A3B8;   /* emphasized dividers, input border (slate-400) */

  /* Text — all measured on --color-surface / --color-bg */
  --color-text:           #1E3A8A;   /* primary text (blue-900) — 8.6:1 on #FFF */
  --color-text-body:      #0F172A;   /* dense body/numbers, max legibility (slate-900) */
  --color-text-muted:     #475569;   /* labels, captions, axis ticks — 7.5:1 on #FFF (slate-600) */
  --color-text-subtle:    #556070;   /* small hints/units/captions — AA (>=4.5:1) on bg #F8FAFC and surface-2 #F1F5F9; the old #64748B failed 4.5:1 on those (4.55/4.34:1) */
  --color-text-on-primary:#FFFFFF;   /* text on primary/secondary fills */
  --color-text-on-accent: #1E293B;   /* dark text on amber CTA — AA on #F59E0B (5.9:1) */
  --color-link:           #1E40AF;
  --color-link-hover:     #3B82F6;

  /* Semantic / status (KPI deltas, validation, run states) */
  --color-success:        #047857;   /* emerald-700 — pass / valid — AA on surface */
  --color-success-bg:     #ECFDF5;
  --color-warning:        #B45309;   /* amber-700 — large-geometry caveat, soft validation */
  --color-warning-bg:     #FFFBEB;
  --color-danger:         #B91C1C;   /* red-700 — error, unphysical input — AA on surface */
  --color-danger-bg:      #FEF2F2;
  --color-info:           #1E40AF;
  --color-info-bg:        #EFF6FF;

  /* Focus ring (visible, high-contrast; amber glow + dark inner per surface) */
  --focus-ring-color:     #F59E0B;
  --focus-ring-contrast:  #1E293B;   /* inner hairline so the ring is visible on amber/blue too */
  --focus-ring-width:     2px;
  --focus-ring-offset:    2px;

  /* Data-viz categorical ramp (Plotly traces, hazard legend, live curves).
     Ordered for max separability on light surfaces; reused 1:1 in dark mode
     via the overrides below so chart code never branches on theme. */
  --viz-1:  #1E40AF;   /* S1 / primary reliability series */
  --viz-2:  #3B82F6;   /* S2 */
  --viz-3:  #0EA5E9;   /* S3 (sky-500) */
  --viz-4:  #F59E0B;   /* accent series / design-load marker */
  --viz-5:  #7C3AED;   /* violet-600 */
  --viz-6:  #059669;   /* emerald-600 */
  --viz-7:  #DB2777;   /* pink-600 */
  --viz-8:  #0D9488;   /* teal-600 */
  /* Sequential hazard scale (3D map low->high). Light-mode ramp. */
  --hazard-0:  #EFF6FF;
  --hazard-1:  #93C5FD;
  --hazard-2:  #3B82F6;
  --hazard-3:  #F59E0B;
  --hazard-4:  #DC2626;   /* critical site */
  --hazard-grid:   #CBD5E1;
  --chart-gridline:#E2E8F0;
  --chart-axis:    #475569;
  --chart-plot-bg: #FFFFFF;
  --chart-paper-bg:#FFFFFF;

  /* ---------------------------------------------------------------------
     2. TYPOGRAPHY
     Fira Sans = body/labels; Fira Code = headings, numbers, monospace data.
     Loaded via Google Fonts with font-display: swap (see <head> / app.css).
     --------------------------------------------------------------------- */
  --font-sans: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-mono: 'Fira Code', ui-monospace, 'SFMono-Regular', 'Cascadia Code', Consolas, monospace;
  --font-heading: var(--font-mono);   /* headings + KPI numbers are Fira Code */
  --font-data:    var(--font-mono);   /* tables, param values, axis numbers */

  /* Type scale — dense dashboard, 1.20 minor-third, base 14px.
     rem assumes html { font-size: 16px } (do NOT shrink root for a11y zoom). */
  --fs-2xs: 0.6875rem;  /* 11px — table micro-labels, units, badges */
  --fs-xs:  0.75rem;    /* 12px — captions, axis ticks, helper text */
  --fs-sm:  0.8125rem;  /* 13px — secondary labels */
  --fs-base:0.875rem;   /* 14px — body / inputs (dense default) */
  --fs-md:  1rem;       /* 16px — emphasized body, tab titles */
  --fs-lg:  1.25rem;    /* 20px — section / panel headings */
  --fs-xl:  1.5rem;     /* 24px — KPI value (small card) */
  --fs-2xl: 2rem;       /* 32px — KPI value (hero card) */
  --fs-3xl: 2.5rem;     /* 40px — page-level display (rare) */

  --lh-tight:   1.15;   /* headings, KPI numbers */
  --lh-snug:    1.35;   /* labels, single-line controls */
  --lh-normal:  1.5;    /* body copy */
  --fw-regular: 400;
  --fw-medium:  500;
  --fw-semibold:600;
  --fw-bold:    700;
  --ls-tight:  -0.01em;
  --ls-normal:  0;
  --ls-wide:    0.02em;  /* uppercase micro-labels / KPI captions */

  /* ---------------------------------------------------------------------
     3. SPACING  (4px base; dense dashboard favors the low end)
     --------------------------------------------------------------------- */
  --space-0:  0;
  --space-px: 1px;
  --space-1:  0.25rem;  /* 4  */
  --space-2:  0.5rem;   /* 8  */
  --space-3:  0.75rem;  /* 12 */
  --space-4:  1rem;     /* 16 */
  --space-5:  1.25rem;  /* 20 */
  --space-6:  1.5rem;   /* 24 */
  --space-8:  2rem;     /* 32 */
  --space-10: 2.5rem;   /* 40 */
  --space-12: 3rem;     /* 48 */

  /* Component-semantic spacing (reference these in layout, not raw scale) */
  --pad-card:       var(--space-3);   /* 12px — dense KPI/panel padding */
  --pad-card-lg:    var(--space-4);
  --pad-input-y:    var(--space-2);
  --pad-input-x:    var(--space-3);
  --gap-grid:       var(--space-3);   /* gutter between dashboard regions */
  --gap-grid-tight: var(--space-2);   /* gutter inside KPI grids */
  --gap-stack:      var(--space-2);   /* vertical rhythm in the param column */
  --row-h-input:    2rem;             /* 32px — dense control height */
  --row-h-table:    1.75rem;          /* 28px — dense table row */

  /* ---------------------------------------------------------------------
     4. RADII
     --------------------------------------------------------------------- */
  --radius-xs:  2px;
  --radius-sm:  4px;    /* inputs, badges, table cells */
  --radius-md:  6px;    /* cards, tabs, buttons */
  --radius-lg:  10px;   /* panels, modals */
  --radius-xl:  16px;
  --radius-pill:9999px;

  /* ---------------------------------------------------------------------
     5. ELEVATION  (subtle — dense UIs read depth from borders first)
     --------------------------------------------------------------------- */
  --shadow-xs: 0 1px 1px rgba(15, 23, 42, 0.04);
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06), 0 1px 1px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 2px 6px rgba(15, 23, 42, 0.08), 0 1px 2px rgba(15, 23, 42, 0.05);
  --shadow-lg: 0 8px 24px rgba(15, 23, 42, 0.12);
  --shadow-focus: 0 0 0 var(--focus-ring-offset) var(--color-surface),
                  0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
  --ring-inset:  inset 0 0 0 1px var(--color-border);

  /* ---------------------------------------------------------------------
     6. Z-INDEX SCALE  (named tiers — never invent magic numbers)
     --------------------------------------------------------------------- */
  --z-base:        0;
  --z-raised:      10;   /* sticky geometry selector / param-column header */
  --z-sticky:      20;   /* sticky table headers, KPI rail */
  --z-dropdown:    100;  /* select menus, param presets */
  --z-overlay:     200;  /* chart fullscreen, dim backdrop */
  --z-modal:       300;  /* large-geometry confirm, error dialog */
  --z-popover:     400;  /* tooltips on top of modals */
  --z-tooltip:     500;  /* hover tooltips (always topmost) */
  --z-toast:       600;  /* transient run notices */

  /* ---------------------------------------------------------------------
     7. MOTION  (150–300ms; respect prefers-reduced-motion below)
     --------------------------------------------------------------------- */
  --dur-fast:   150ms;  /* hover, focus, row highlight, tooltip */
  --dur-base:   200ms;  /* tab expand/collapse, input states */
  --dur-slow:   300ms;  /* panel/results reveal, spinner fade */
  --ease-standard: cubic-bezier(0.4, 0.0, 0.2, 1);
  --ease-out:      cubic-bezier(0.0, 0.0, 0.2, 1);
  --ease-in:       cubic-bezier(0.4, 0.0, 1, 1);
  --transition-colors: color var(--dur-fast) var(--ease-standard),
                       background-color var(--dur-fast) var(--ease-standard),
                       border-color var(--dur-fast) var(--ease-standard),
                       box-shadow var(--dur-fast) var(--ease-standard);

  /* ---------------------------------------------------------------------
     8. LAYOUT TOKENS  (region widths + the 4 breakpoints, sec. 1 of spec)
     --------------------------------------------------------------------- */
  --layout-max:        1440px;  /* content cap; ultrawide centers with gutters */
  --header-h:          3rem;    /* 48px global header */
  --geo-selector-h:    3.5rem;  /* 56px sticky geometry bar */
  --param-col-w:       380px;   /* LEFT param column @ >=1024px */
  --param-col-w-wide:  420px;   /* LEFT param column @ >=1440px */
  --results-min-w:     560px;   /* RIGHT results min before stacking */
  --kpi-min:           150px;   /* KPI card min track (auto-fill grid) */
  --chart-min-h:       300px;   /* reserved chart height (no layout shift) */
  --hazard-min-h:      680px;   /* reserved 3D map height (enlarged for the page-scroll layout) */
  --bp-xs:             375px;
  --bp-sm:             768px;
  --bp-md:             1024px;
  --bp-lg:             1440px;
  color-scheme: light;
}

/* ===========================================================================
   DARK MODE
   Toggle by setting <html data-theme="dark"> (JS, persisted to localStorage).
   The media query is the system fallback when no explicit choice is stored.
   Every token from sec. 1 is re-mapped; sizing/motion tokens are theme-agnostic
   and are NOT repeated.
   =========================================================================== */
:root[data-theme="dark"] {
  --color-primary:        #60A5FA;   /* blue-400 — lifts on dark for AA */
  --color-primary-hover:  #93C5FD;
  --color-primary-active: #BFDBFE;
  --color-secondary:      #3B82F6;
  --color-secondary-hover:#60A5FA;
  --color-accent:         #FBBF24;   /* amber-400 — brighter CTA on dark */
  --color-accent-hover:   #FCD34D;
  --color-accent-active:  #F59E0B;

  --color-bg:             #0B1120;   /* slate-950-ish app bg */
  --color-surface:        #111827;   /* gray-900 cards */
  --color-surface-2:      #1E293B;   /* slate-800 nested */
  --color-surface-3:      #334155;   /* slate-700 hover row */
  --color-border:         #334155;   /* slate-700 */
  --color-border-strong:  #475569;   /* slate-600 */

  --color-text:           #E2E8F0;   /* slate-200 — 12:1 on surface */
  --color-text-body:      #F1F5F9;   /* slate-100 */
  --color-text-muted:     #94A3B8;   /* slate-400 — 6.4:1 on #111827 */
  --color-text-subtle:    #94A3B8;   /* slate-400 — AA on all dark surfaces; old #64748B failed 4.5:1 (3.07:1 on surface-2) for small text */
  --color-text-on-primary:#0B1120;   /* dark text on the lifted blue */
  --color-text-on-accent: #1E293B;   /* dark text on amber */
  --color-link:           #60A5FA;
  --color-link-hover:     #93C5FD;

  --color-success:        #34D399;   /* emerald-400 */
  --color-success-bg:     #052E2B;
  --color-warning:        #FBBF24;
  --color-warning-bg:     #2A1E05;
  --color-danger:         #F87171;   /* red-400 — AA on dark surface */
  --color-danger-bg:      #2A0E0E;
  --color-info:           #60A5FA;
  --color-info-bg:        #0B2447;

  --focus-ring-color:     #FBBF24;
  --focus-ring-contrast:  #0B1120;

  /* Viz ramp re-tuned for dark backgrounds (same slot order/meaning) */
  --viz-1:  #60A5FA;
  --viz-2:  #3B82F6;
  --viz-3:  #38BDF8;
  --viz-4:  #FBBF24;
  --viz-5:  #A78BFA;
  --viz-6:  #34D399;
  --viz-7:  #F472B6;
  --viz-8:  #2DD4BF;
  --hazard-0:  #0B2447;
  --hazard-1:  #1D4ED8;
  --hazard-2:  #3B82F6;
  --hazard-3:  #FBBF24;
  --hazard-4:  #F87171;
  --hazard-grid:   #334155;
  --chart-gridline:#1E293B;
  --chart-axis:    #94A3B8;
  --chart-plot-bg: #111827;
  --chart-paper-bg:#111827;

  /* Elevation reads via lighter borders on dark; soften shadows */
  --shadow-xs: 0 1px 1px rgba(0, 0, 0, 0.30);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
  --shadow-md: 0 2px 6px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.55);
  --ring-inset: inset 0 0 0 1px var(--color-border);

  color-scheme: dark;
}

/* System-preference fallback: applies dark tokens only when the user has NOT
   made an explicit choice (no data-theme attribute on <html>). */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    --color-primary:        #60A5FA;
    --color-primary-hover:  #93C5FD;
    --color-primary-active: #BFDBFE;
    --color-secondary:      #3B82F6;
    --color-secondary-hover:#60A5FA;
    --color-accent:         #FBBF24;
    --color-accent-hover:   #FCD34D;
    --color-accent-active:  #F59E0B;
    --color-bg:             #0B1120;
    --color-surface:        #111827;
    --color-surface-2:      #1E293B;
    --color-surface-3:      #334155;
    --color-border:         #334155;
    --color-border-strong:  #475569;
    --color-text:           #E2E8F0;
    --color-text-body:      #F1F5F9;
    --color-text-muted:     #94A3B8;
    --color-text-subtle:    #94A3B8;   /* AA on dark surfaces (was #64748B = fail) */
    --color-text-on-primary:#0B1120;
    --color-text-on-accent: #1E293B;
    --color-link:           #60A5FA;
    --color-link-hover:     #93C5FD;
    --color-success:        #34D399;
    --color-success-bg:     #052E2B;
    --color-warning:        #FBBF24;
    --color-warning-bg:     #2A1E05;
    --color-danger:         #F87171;
    --color-danger-bg:      #2A0E0E;
    --color-info:           #60A5FA;
    --color-info-bg:        #0B2447;
    --focus-ring-color:     #FBBF24;
    --focus-ring-contrast:  #0B1120;
    --viz-1:#60A5FA; --viz-2:#3B82F6; --viz-3:#38BDF8; --viz-4:#FBBF24;
    --viz-5:#A78BFA; --viz-6:#34D399; --viz-7:#F472B6; --viz-8:#2DD4BF;
    --hazard-0:#0B2447; --hazard-1:#1D4ED8; --hazard-2:#3B82F6;
    --hazard-3:#FBBF24; --hazard-4:#F87171;
    --hazard-grid:#334155; --chart-gridline:#1E293B; --chart-axis:#94A3B8;
    --chart-plot-bg:#111827; --chart-paper-bg:#111827;
    --shadow-xs: 0 1px 1px rgba(0,0,0,0.30);
    --shadow-sm: 0 1px 2px rgba(0,0,0,0.40);
    --shadow-md: 0 2px 6px rgba(0,0,0,0.45);
    --shadow-lg: 0 8px 24px rgba(0,0,0,0.55);
    color-scheme: dark;
  }
}

/* ===========================================================================
   MOTION PREFERENCE — global kill-switch for non-essential animation.
   Components must gate decorative motion on these durations (already near-0)
   AND still honor the explicit reduced-motion rule below.
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 1ms;
    --dur-base: 1ms;
    --dur-slow: 1ms;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ===========================================================================
   FOCUS-VISIBLE — single canonical visible focus ring for every interactive
   element. Components should NOT override outline; they inherit this.
   =========================================================================== */
:where(a, button, input, select, textarea, [tabindex], [role="tab"], [role="button"]):focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
  border-radius: var(--radius-sm);
}
