/* Design tokens - single source for every color/shadow/overlay token used
   across dashboard.html, help.html, and the auth pages (main.py). Two
   first-class palettes selected via [data-theme] on <html>, set by a small
   blocking init script in each page's <head> (localStorage override, else
   prefers-color-scheme) - see THEME_INIT_JS. No @media queries live here;
   the JS always resolves to an explicit "light" or "dark" before this
   stylesheet's selectors ever need to match, so the cascade stays flat.

   All light/dark pairs below are WCAG AA contrast-checked (4.5:1 text) -
   see the mission's contrast report for the full ratio table. --muted and
   the heat-tile gain/loss text colors were tuned during that pass; every
   accent/warn/danger/success value was already AA-safe and is carried
   over unchanged from the pre-token-system palette. */

:root[data-theme="light"] {
  /* warm-neutral paper */
  --bg: #F7F6F3;
  --surface: #FFFFFF;
  --ink: #1F2124;
  --muted: #6B6660;
  --hairline: #E8E6E1;
  --hairline-width: 0.5px;
  --accent: #2F4BC7;
  --accent-bg: #E9EDFB;
  --warn: #854F0B;
  --warn-bg: #FAEEDA;
  --danger: #A32D2D;
  --danger-bg: #FCEBEB;
  --success: #3B6D11;
  --success-bg: #EAF3DE;

  /* heat ramp (treemap/movers/day-change) - 4 steps, <1% / <2.5% / <5% / >=5% */
  --heat-gain-0: #EAF3DE; --heat-gain-1: #C0DD97; --heat-gain-2: #97C459; --heat-gain-3: #639922;
  --heat-loss-0: #FCEBEB; --heat-loss-1: #F7C1C1; --heat-loss-2: #F09595; --heat-loss-3: #E24B4A;
  --heat-gain-text: #0D2400;
  --heat-loss-text: #280505;
  --heat-neutral-bg: #EFEEEA;
  --heat-neutral-text: #2C2C2A;

  /* categorical (sector donut/legend) */
  --pal-0: #5B8DEF; --pal-1: #63A375; --pal-2: #E0A458; --pal-3: #C76B6B;
  --pal-4: #8B7BC7; --pal-5: #4FADAD; --pal-6: #D98CB3; --pal-7: #A3A857;
  --pal-8: #C78F5B; --pal-9: #7A9CC6; --pal-10: #B56576; --pal-11: #6B8E23;

  --overlay-scrim: rgba(31,33,36,.62);
  --shadow: rgba(31,33,36,.18);
  --shadow-strong: rgba(31,33,36,.28);
}

:root[data-theme="dark"] {
  /* charcoal terminal */
  --bg: #16181D;
  --surface: #1E2128;
  --ink: #E8EAED;
  --muted: #8B92A0;
  --hairline: #2A2E37;
  --hairline-width: 0.5px;
  --accent: #9AB0F5;
  --accent-bg: #232C45;
  --warn: #FAC775;
  --warn-bg: #3A2C12;
  --danger: #F09595;
  --danger-bg: #3D1B1B;
  --success: #C0DD97;
  --success-bg: #24330F;

  /* heat ramp - desaturated moss/brick tints, not the light palette's
     bright pastels (which vibrate against charcoal). Text colors are a
     separate light tint per direction, not the light-mode dark text -
     dark tiles need light text, not the same near-black used on light
     tiles. */
  --heat-gain-0: #212922; --heat-gain-1: #243A28; --heat-gain-2: #2C3B2E; --heat-gain-3: #35502F;
  --heat-loss-0: #2A2224; --heat-loss-1: #3A272A; --heat-loss-2: #4A2F31; --heat-loss-3: #5C3438;
  --heat-gain-text: #B7D6AA;
  --heat-loss-text: #EAB9BC;
  --heat-neutral-bg: #262A31;
  --heat-neutral-text: #C9CDD3;

  --pal-0: #7FA6F5; --pal-1: #7FBF97; --pal-2: #E8B978; --pal-3: #D68989;
  --pal-4: #A99AD6; --pal-5: #6FC4C4; --pal-6: #E3A6C4; --pal-7: #BFC378;
  --pal-8: #D6A97D; --pal-9: #96B3D9; --pal-10: #C98A9C; --pal-11: #8FAE4A;

  --overlay-scrim: rgba(0,0,0,.72);
  --shadow: rgba(0,0,0,.4);
  --shadow-strong: rgba(0,0,0,.55);
}

/* Tabular numerals app-wide (prices, values, percentages, metrics, risk
   numbers, timestamps) so columns stop jittering on refresh - applied once
   at body level rather than hunting down every numeric element; harmless
   no-op wherever there's no numeral. .mono (tickers) keeps its own
   explicit font-family, unaffected by this. */
body {
  font-variant-numeric: tabular-nums;
}

/* ---------- UI mutation-feedback doctrine (project memory) ----------
   Every control that triggers a server mutation shows visible progress for
   its full duration and is never silent - see withBusy() in dashboard.html,
   which wraps a button/checkbox in this state for the length of its async
   work. Dependency-light (no animation library) and theme-aware by
   construction: both use currentColor/tokens, so there is nothing separate
   to tune per palette. */
.spinner {
  display: inline-block;
  width: 12px; height: 12px;
  margin-right: 5px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  opacity: .85;
  border-radius: 50%;
  vertical-align: -2px;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Inline status text next to a checkbox/control that can't host a spinner
   directly (e.g. a native checkbox) - "Updating…" while in flight, cleared
   once the view reflects the change. */
.busy-note {
  font-size: 12px;
  color: var(--muted);
  margin-left: 8px;
}

/* Content-shaped loading placeholder, for a first paint that would
   otherwise be a blank gap rather than a specific control's busy state.
   Available alongside .spinner; not every surface needs it. */
.skeleton {
  display: inline-block;
  min-height: 1em;
  background: linear-gradient(90deg, var(--hairline) 25%, var(--surface) 50%, var(--hairline) 75%);
  background-size: 200% 100%;
  border-radius: 6px;
  animation: skeleton-shimmer 1.2s ease-in-out infinite;
}
@keyframes skeleton-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
