/* ==========================================================================
   tokens.css — the single source of truth for every design value.
   WHY: every other stylesheet consumes ONLY these custom properties, so a
   theme swap is one attribute flip on <html> (data-theme) and never a
   rewrite. Nothing below may hardcode a colour that is also a token.

   Themes are authored independently, not inverted: the dark palette is a
   near-black app canvas with genuinely *lifted* surfaces (each step adds
   light, not opacity), the light palette is a warm off-white paper with its
   own shadow hue. Borders are hairlines at low alpha in both so panels read
   as edges of glass rather than boxes.

   Contract: ARCHITECTURE.md §13.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* ---- Accent -------------------------------------------------------- */
  --accent: #7c5cff;
  --accent-hover: #8f74ff;
  --accent-press: #6a48f0;
  --accent-soft: rgba(124, 92, 255, 0.12);
  --accent-contrast: #ffffff;
  /* additive: second stop for accent gradients (buttons, charts, glows) */
  --accent-2: #5ad1ff;
  /* Text-bearing fill. The brand accent #7c5cff only reaches 4.35:1 with white and the
     old mid-stop #a37bff just 3.07:1 — both below the 4.5:1 WCAG AA bar for button text.
     These stops all clear it (5.00 / 5.69 / 6.23). --accent itself is unchanged: as a
     border, ring or active marker it is a UI component and only needs 3:1. */
  --accent-gradient: linear-gradient(135deg, #7450f4 0%, #6b46ea 55%, #6340e3 160%);

  /* ---- Surfaces (each step is genuinely lighter, not just alpha) ------ */
  --bg-0: #0d0e13;   /* app canvas */
  --bg-1: #14161d;   /* panels: topbar, sidebar, dock */
  --bg-2: #1a1d26;   /* elevated: cards, menus, modals */
  --bg-3: #242835;   /* hover / active surface */
  --bg-inset: #090a0e; /* wells: inputs, image stage, code */

  /* ---- Glass --------------------------------------------------------- */
  --glass: rgba(20, 22, 29, 0.72);
  --glass-border: rgba(255, 255, 255, 0.08);
  --blur: saturate(180%) blur(18px);

  /* ---- Lines --------------------------------------------------------- */
  --border: rgba(255, 255, 255, 0.075);
  --border-strong: rgba(255, 255, 255, 0.16);

  /* ---- Text ---------------------------------------------------------- */
  --text-0: #e9ecf3;
  --text-1: #a7afc2;
  --text-2: #6e7689;
  --text-inverse: #0d0e13;

  /* ---- Semantic ------------------------------------------------------ */
  --success: #3fd07f;
  --warning: #f0b429;
  --danger: #ff5f6d;
  --info: #4c9aff;
  --success-soft: rgba(63, 208, 127, 0.14);
  --warning-soft: rgba(240, 180, 41, 0.14);
  --danger-soft: rgba(255, 95, 109, 0.14);
  --info-soft: rgba(76, 154, 255, 0.14);

  /* ---- Radii --------------------------------------------------------- */
  --radius-xs: 4px;
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 22px;
  --radius-full: 999px;

  /* ---- Elevation: layered (contact shadow + ambient) ------------------ */
  --shadow-1:
    0 1px 1px rgba(0, 0, 0, 0.30),
    0 1px 3px rgba(0, 0, 0, 0.36);
  --shadow-2:
    0 2px 4px -2px rgba(0, 0, 0, 0.40),
    0 6px 16px -4px rgba(0, 0, 0, 0.52);
  --shadow-3:
    0 4px 10px -4px rgba(0, 0, 0, 0.50),
    0 18px 44px -12px rgba(0, 0, 0, 0.72),
    0 1px 0 0 rgba(255, 255, 255, 0.04) inset;
  --shadow-glow:
    0 0 0 1px rgba(124, 92, 255, 0.36),
    0 8px 30px -8px rgba(124, 92, 255, 0.48);

  /* additive: reusable focus/soft ring + overlay scrim + scrollbar paint */
  --ring: 0 0 0 3px var(--accent-soft);
  --overlay: rgba(6, 7, 11, 0.66);
  --scrollbar-thumb: rgba(255, 255, 255, 0.13);
  --scrollbar-thumb-hover: rgba(255, 255, 255, 0.24);

  /* ---- Spacing ------------------------------------------------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 48px;

  /* ---- Type ---------------------------------------------------------- */
  --font-sans:
    "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
    "Segoe UI", Roboto, "Helvetica Neue", Ubuntu, Cantarell, "Noto Sans",
    system-ui, sans-serif;
  --font-mono:
    ui-monospace, "SFMono-Regular", "JetBrains Mono", "Cascadia Mono",
    "Roboto Mono", Menlo, Consolas, "Liberation Mono", monospace;

  /* ---- Motion -------------------------------------------------------- */
  --dur-fast: 120ms;
  --dur: 200ms;
  --dur-slow: 340ms;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* ---- Layout metrics ------------------------------------------------ */
  --topbar-h: 56px;
  --sidebar-w: 272px;
  --sidebar-w-collapsed: 68px;
  --dock-h: 168px;
  --thumb: 132px;

  /* ---- Stacking ------------------------------------------------------ */
  --z-base: 0;
  --z-dock: 20;
  --z-sidebar: 30;
  --z-topbar: 40;
  --z-menu: 60;
  --z-modal: 70;
  --z-lightbox: 90;
  --z-toast: 100; /* above the lightbox: feedback must survive any overlay */
}

/* ==========================================================================
   Light theme — warm off-white paper, warm-grey shadows, darker accent so
   text-on-accent and accent-on-paper both clear WCAG AA.
   ========================================================================== */

:root[data-theme="light"] {
  color-scheme: light;

  --accent: #7c5cff;
  --accent-hover: #6d4bf2;
  --accent-press: #5b38dd;
  --accent-soft: rgba(124, 92, 255, 0.12);
  --accent-contrast: #ffffff;
  --accent-2: #22a9e0;
  --accent-gradient: linear-gradient(135deg, #7450f4 0%, #6b46ea 55%, #6340e3 160%);

  --bg-0: #f4f2ee;
  --bg-1: #fbfaf8;
  --bg-2: #ffffff;
  --bg-3: #eeebe5;
  --bg-inset: #e9e6df;

  --glass: rgba(252, 251, 249, 0.78);
  --glass-border: rgba(24, 20, 13, 0.08);
  --blur: saturate(160%) blur(16px);

  --border: rgba(24, 20, 13, 0.10);
  --border-strong: rgba(24, 20, 13, 0.22);

  --text-0: #1a1814;
  --text-1: #4c4840;
  --text-2: #7b7568;
  --text-inverse: #ffffff;

  --success: #10814a;
  --warning: #9a6700;
  --danger: #c9303e;
  --info: #0b62d6;
  --success-soft: rgba(16, 129, 74, 0.12);
  --warning-soft: rgba(154, 103, 0, 0.13);
  --danger-soft: rgba(201, 48, 62, 0.11);
  --info-soft: rgba(11, 98, 214, 0.11);

  --shadow-1:
    0 1px 1px rgba(48, 40, 26, 0.05),
    0 1px 3px rgba(48, 40, 26, 0.07);
  --shadow-2:
    0 2px 4px -2px rgba(48, 40, 26, 0.07),
    0 6px 16px -4px rgba(48, 40, 26, 0.11);
  --shadow-3:
    0 4px 10px -4px rgba(48, 40, 26, 0.09),
    0 20px 48px -16px rgba(48, 40, 26, 0.20),
    0 1px 0 0 rgba(255, 255, 255, 0.70) inset;
  --shadow-glow:
    0 0 0 1px rgba(124, 92, 255, 0.30),
    0 10px 30px -8px rgba(124, 92, 255, 0.34);

  --overlay: rgba(36, 30, 20, 0.42);
  --scrollbar-thumb: rgba(24, 20, 13, 0.18);
  --scrollbar-thumb-hover: rgba(24, 20, 13, 0.32);
}

/* Safety net for theme="auto": main.js is expected to resolve 'auto' to a
   concrete data-theme, but if it ever leaves the literal value in place the
   OS preference still produces a correct light palette rather than dark. */
@media (prefers-color-scheme: light) {
  :root[data-theme="auto"] {
    color-scheme: light;
    --accent-hover: #6d4bf2;
    --accent-press: #5b38dd;
    --accent-2: #22a9e0;
    --bg-0: #f4f2ee;
    --bg-1: #fbfaf8;
    --bg-2: #ffffff;
    --bg-3: #eeebe5;
    --bg-inset: #e9e6df;
    --glass: rgba(252, 251, 249, 0.78);
    --glass-border: rgba(24, 20, 13, 0.08);
    --blur: saturate(160%) blur(16px);
    --border: rgba(24, 20, 13, 0.10);
    --border-strong: rgba(24, 20, 13, 0.22);
    --text-0: #1a1814;
    --text-1: #4c4840;
    --text-2: #7b7568;
    --text-inverse: #ffffff;
    --success: #10814a;
    --warning: #9a6700;
    --danger: #c9303e;
    --info: #0b62d6;
    --success-soft: rgba(16, 129, 74, 0.12);
    --warning-soft: rgba(154, 103, 0, 0.13);
    --danger-soft: rgba(201, 48, 62, 0.11);
    --info-soft: rgba(11, 98, 214, 0.11);
    --shadow-1: 0 1px 1px rgba(48, 40, 26, 0.05), 0 1px 3px rgba(48, 40, 26, 0.07);
    --shadow-2: 0 2px 4px -2px rgba(48, 40, 26, 0.07), 0 6px 16px -4px rgba(48, 40, 26, 0.11);
    --shadow-3:
      0 4px 10px -4px rgba(48, 40, 26, 0.09),
      0 20px 48px -16px rgba(48, 40, 26, 0.20),
      0 1px 0 0 rgba(255, 255, 255, 0.70) inset;
    --shadow-glow: 0 0 0 1px rgba(124, 92, 255, 0.30), 0 10px 30px -8px rgba(124, 92, 255, 0.34);
    --overlay: rgba(36, 30, 20, 0.42);
    --scrollbar-thumb: rgba(24, 20, 13, 0.18);
    --scrollbar-thumb-hover: rgba(24, 20, 13, 0.32);
  }
}

/* ==========================================================================
   Motion kill-switch.

   WHY two rules: data-anim="off" is the explicit in-app setting and always
   wins. The OS-level preference is honoured by default, but NOT when the
   user has explicitly opted in with data-anim="on" — an explicit product
   choice outranks an inherited system default.

   Every entrance animation in animations.css keeps its "from" state inside
   the @keyframes only (never on the base class), so `animation: none` can
   never strand an element at opacity 0.
   ========================================================================== */

:root[data-anim="off"],
:root[data-anim="off"] *,
:root[data-anim="off"] *::before,
:root[data-anim="off"] *::after {
  animation: none !important;
  transition: none !important;
  scroll-behavior: auto !important;
}

@media (prefers-reduced-motion: reduce) {
  :root:not([data-anim="on"]),
  :root:not([data-anim="on"]) *,
  :root:not([data-anim="on"]) *::before,
  :root:not([data-anim="on"]) *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================================
   Chart tokens
   --------------------------------------------------------------------------
   Categorical slots are assigned to a provider by REGISTRATION ORDER and never
   by rank, so filtering or re-sorting a chart never repaints the survivors.

   These are NOT the provider badge colours. The badge hexes (waifu.im pink vs
   nekobot cyan) measure ΔE 4.1 under deuteranopia — indistinguishable to a
   red-green colourblind reader. These steps are validated in both modes:
   lightness band, chroma floor, CVD separation, normal-vision floor, contrast.

   Light mode: series-3 and series-4 fall below 3:1 on white, so every chart
   using them must carry visible value labels (relief, not decoration).
   ========================================================================== */
:root {
  --series-1: #3987e5;   /* blue    */
  --series-2: #d95926;   /* orange  */
  --series-3: #199e70;   /* aqua    */
  --series-4: #c98500;   /* yellow  */
  --series-5: #d55181;   /* magenta */
  --series-6: #008300;   /* green   */
  --series-7: #9085e9;   /* violet  */
  --series-8: #e66767;   /* red     */

  --chart-grid: #2c2c2a;
  --chart-axis: #383835;
  --chart-muted: #898781;
}

:root[data-theme="light"] {
  --series-1: #2a78d6;
  --series-2: #eb6834;
  --series-3: #1baf7a;
  --series-4: #eda100;
  --series-5: #e87ba4;
  --series-6: #008300;
  --series-7: #4a3aa7;
  --series-8: #e34948;

  --chart-grid: #e1e0d9;
  --chart-axis: #c3c2b7;
  --chart-muted: #898781;
}
