/* ==========================================================================
   tokens.css , THE ONLY FILE IN THIS PROJECT ALLOWED TO CONTAIN A HEX VALUE
   ==========================================================================

   THIS IS THE LOAD-BEARING RULE OF THE WHOLE REBUILD.

   The v1 dashboard had 204 hardcoded hex values, ~110 of them buried inside
   component rules. That is why it had three "themes" but only one of them
   actually worked: switching to cyber-light still gave you a magenta hamburger,
   a magenta logout hover and cyan wizard labels, because those colours were
   welded into the rules instead of read from a token.

   It is also why the v2 reskin felt identical to the operator. There was no
   skin layer to swap. There were 110 hex values scattered across 506 lines.

   ENFORCEMENT (run in CI / before promote):
       python3 tools/check-tokens.py
   It greps every file under static/css/, templates/ and static/js/ for
   /#[0-9a-fA-F]{3,8}\b/ and fails the build on any hit outside this file.

   ==========================================================================
   TWO-TIER TOKEN ARCHITECTURE , read this before editing
   ==========================================================================

   TIER 1  PRIMITIVES     --cyan-500, --orange-600, --grey-900 ...
           Raw colour values. Named by WHAT THEY ARE. Never referenced by a
           component. Never changed by a theme. This is the paint box.

   TIER 2  SEMANTICS      --color-accent, --color-surface, --btn-primary-bg ...
           Named by WHAT THEY DO. Point at Tier 1. Components read ONLY these.
           A theme is nothing more than a block that re-points Tier 2 tokens
           at different Tier 1 values.

   Consequence: a brand-new skin is a ~40-line block at the bottom of this
   file. Not a rebuild. That is the entire point.

   Rule for contributors: if you are writing a component and you need a colour
   that does not exist as a Tier 2 token, ADD THE TIER 2 TOKEN. Do not reach
   for Tier 1, and never, ever type a hex value.
   ========================================================================== */


/* ==========================================================================
   CASCADE LAYERS , declared here, first file loaded, so order is guaranteed
   ==========================================================================
   Declaring the layer order up front means the ORDER THE CSS FILES LOAD IN
   NO LONGER MATTERS for the cascade. A rule in `components` always beats a
   rule in `base` regardless of which <link> came first.

   This kills the entire class of "my style is being overridden, add
   !important" bugs. The v1 file had 0 !important, which was genuinely good
   and we intend to keep that score at 0.
   ========================================================================== */
@layer reset, base, layout, components, utilities;


/* ==========================================================================
   TIER 1 , PRIMITIVES.  The paint box. Themes do not touch these.
   ========================================================================== */
:root {

  /* --- Neutrals. The cyberpunk near-black ramp, kept from v1 identity. --- */
  --grey-1000: #05050a;   /* deepest, console bg                            */
  --grey-950:  #0a0a0f;   /* app background            (v1 --bg)            */
  --grey-900:  #0d0d14;   /* topbar / raised chrome    (v1 --topbar)        */
  --grey-850:  #12121a;   /* card surface              (v1 --surface)       */
  --grey-800:  #16162a;   /* surface hover             (v1 --surface-hover) */
  --grey-750:  #1a1a2e;   /* borders                   (v1 --border)        */
  --grey-700:  #24243a;   /* border strong                                  */
  --grey-600:  #3a3a52;   /* disabled / dividers                            */
  --grey-500:  #6b6b85;   /* muted text  (was #555, too dark to read)       */
  --grey-400:  #9494ad;   /* dim text    (was #888, failed AA at 12px)      */
  --grey-300:  #b8b8cc;   /* secondary text                                 */
  --grey-200:  #d8d8e4;   /* body text on dark                              */
  --grey-100:  #eeeef4;   /* high-emphasis text                             */
  --grey-000:  #ffffff;

  /* --- Light-theme neutrals (a real ramp, so cyber-light finally works) --- */
  --paper-000: #ffffff;
  --paper-100: #f7f8fa;
  --paper-200: #eef0f4;
  --paper-300: #dde1e8;
  --paper-400: #c3c9d4;
  --paper-500: #8b94a5;
  --paper-600: #5b6474;
  --paper-700: #3a4252;
  --paper-800: #232936;
  --paper-900: #141821;

  /* --- Cyan. The primary accent, v1 signature colour, unchanged. --- */
  --cyan-300:  #7df5ff;
  --cyan-400:  #33f4ff;
  --cyan-500:  #00f0ff;   /* THE cyan. v1 --accent. Untouched.              */
  --cyan-600:  #00c2d6;
  --cyan-700:  #00889a;
  --cyan-900:  #063038;

  /* --- Magenta. Brand / secondary accent, v1 signature, unchanged. --- */
  --magenta-300: #ff7dd0;
  --magenta-400: #ff3fb8;
  --magenta-500: #ff00aa;  /* THE magenta. v1 --accent2. Untouched.         */
  --magenta-600: #d10089;
  --magenta-700: #940062;
  --magenta-900: #35001f;

  /* --- ORANGE. NEW IN v3. The operator asked for orange on the buttons.
         This becomes the PRIMARY ACTION colour: it is the only warm hue on
         a cold cyan/magenta palette, so it reads instantly as "this is the
         thing you press". Cyan stays for links and info, magenta stays for
         brand and destructive-adjacent accents.
         --orange-500 on --grey-950 measures ~8.6:1 with dark text on top,
         which is why buttons use dark text, not white.                 --- */
  --orange-300: #ffb877;
  --orange-400: #ff9840;
  --orange-500: #ff7a1a;   /* THE orange. Primary action.                  */
  --orange-600: #e05e00;
  --orange-700: #a84600;
  --orange-900: #331603;

  /* --- Status hues. Kept from v1, contrast-corrected. --- */
  --green-400: #4dff9a;
  --green-500: #00ff66;   /* v1 --green                                    */
  --green-700: #00a844;
  --green-900: #032b16;

  --red-400:   #ff5c7a;
  --red-500:   #ff0044;   /* v1 --red                                      */
  --red-700:   #b8002f;
  --red-900:   #33000e;

  --amber-400: #ffc44d;
  --amber-500: #ffaa00;   /* v1 --amber                                    */
  --amber-700: #b87a00;
  --amber-900: #332200;

  --violet-500: #aa66ff;  /* v1 used this for GPU/AI accents               */


  /* ========================================================================
     TIER 1 , NON-COLOUR PRIMITIVES.
     These do NOT change between themes, so they live at :root only.
     ======================================================================== */

  /* --- TYPE SCALE. Exactly 7 steps. Nothing below 12px. ---
     v1 had EIGHTEEN arbitrary font-sizes, the smallest 0.45rem = 7.2px,
     uppercased with 4px tracking. That is texture, not text. Gone.
     Ratio is ~1.22 (minor third-ish), tuned so 3 and 4 sit close together
     because that is the body/lead pair you use most.                    */
  --fs-1: 0.75rem;    /* 12px , micro labels, chips, table meta   FLOOR    */
  --fs-2: 0.875rem;   /* 14px , secondary text, nav items, buttons        */
  --fs-3: 1rem;       /* 16px , body base                                 */
  --fs-4: 1.125rem;   /* 18px , lead, card titles                         */
  --fs-5: 1.375rem;   /* 22px , h3 / section heads                        */
  --fs-6: 1.75rem;    /* 28px , h2 / stat values                          */
  --fs-7: 2.25rem;    /* 36px , h1 / display                              */

  --lh-tight: 1.2;
  --lh-snug:  1.35;
  --lh-base:  1.55;
  --lh-loose: 1.7;

  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;

  /* Tracking. v1 applied letter-spacing 24 times and uppercase 15 times,
     which WAS the entire "cyberpunk" gesture. We keep it, but as a
     deliberate, named, sparing device instead of a reflex.              */
  --tracking-tight:  -0.01em;
  --tracking-normal: 0;
  --tracking-wide:   0.06em;
  --tracking-mega:   0.18em;   /* brand mark + eyebrow labels ONLY        */

  /* --- SPACING SCALE. Exactly 8 steps, 4px base. ---
     v1 had 42 distinct padding declarations. Every gap in this UI is now
     one of these eight values. No exceptions, no magic numbers.         */
  --sp-1: 0.25rem;   /*  4px */
  --sp-2: 0.5rem;    /*  8px */
  --sp-3: 0.75rem;   /* 12px */
  --sp-4: 1rem;      /* 16px */
  --sp-5: 1.5rem;    /* 24px */
  --sp-6: 2rem;      /* 32px */
  --sp-7: 3rem;      /* 48px */
  --sp-8: 4rem;      /* 64px */

  /* --- RADII --- */
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-pill: 999px;

  /* --- BORDER WIDTHS --- */
  --bw-hair: 1px;
  --bw-thick: 2px;

  /* --- ELEVATION. Shadow needs the shadow colour as a raw rgb triplet so
         we can vary alpha per level without 6 more hex values.          */
  --shadow-rgb: 0 0 0;
  --shadow-sm: 0 1px 2px  rgb(var(--shadow-rgb) / 0.30);
  --shadow-md: 0 4px 12px rgb(var(--shadow-rgb) / 0.40);
  --shadow-lg: 0 12px 32px rgb(var(--shadow-rgb) / 0.55);

  /* --- MOTION.
         Every duration below is forced to 0.01ms by the prefers-reduced-motion
         block at the bottom of this file. That single override is why we can
         animate freely here and still respect the setting everywhere at once,
         including on the 6 keyframe animations v1 ran unconditionally.  */
  --dur-instant: 80ms;
  --dur-fast:   150ms;
  --dur-base:   240ms;
  --dur-slow:   360ms;
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* --- LAYOUT CONSTANTS --- */
  --topbar-h:      56px;   /* 44px min touch target + breathing room       */
  --drawer-w:      312px;
  --content-max:   1440px;
  --tap-min:       44px;   /* WCAG 2.5.5 minimum touch target              */

  /* --- Z-INDEX. Named, ordered, and the ONLY place these numbers exist.
         v1 had raw z-index values (100, 200, 250, 310, 500) sprinkled
         across rules with no map, which is how you end up with a drawer
         under its own overlay.                                          */
  --z-base:     0;
  --z-sticky:   100;
  --z-drawer:   200;
  --z-overlay:  300;
  --z-modal:    400;
  --z-toast:    500;

  /* --- TYPEFACES. Self-hosted. No third-party CDN request.
         v1 loaded 3 families from fonts.googleapis.com, render-blocking,
         on a private admin console, and its default theme used only one
         of them.                                                        */
  --font-ui:   "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}


/* ==========================================================================
   TIER 2 , SEMANTICS.  Everything a component is allowed to read.
   ==========================================================================
   Default block = the CYBER-DARK theme. It is on :root (not [data-theme])
   so the page is never unstyled if the theme attribute is missing or JS
   has not run yet. Themes below override by re-pointing these.
   ========================================================================== */
:root,
[data-theme="cyber-dark"] {
  color-scheme: dark;

  /* Surfaces */
  --color-bg:            var(--grey-950);
  --color-bg-sunken:     var(--grey-1000);
  --color-surface:       var(--grey-850);
  --color-surface-raised:var(--grey-900);
  --color-surface-hover: var(--grey-800);
  --color-chrome:        var(--grey-900);

  /* Borders */
  --color-border:        var(--grey-750);
  --color-border-strong: var(--grey-700);
  --color-border-subtle: var(--grey-800);

  /* Text */
  --color-text:           var(--grey-100);
  --color-text-secondary: var(--grey-300);
  --color-text-dim:       var(--grey-400);
  --color-text-muted:     var(--grey-500);
  --color-text-inverse:   var(--grey-1000);

  /* Accents */
  --color-accent:         var(--cyan-500);
  --color-accent-hover:   var(--cyan-400);
  --color-accent-quiet:   var(--cyan-900);
  --color-brand:          var(--magenta-500);
  --color-brand-hover:    var(--magenta-400);
  --color-brand-quiet:    var(--magenta-900);

  /* Status */
  --color-ok:      var(--green-500);
  --color-ok-bg:   var(--green-900);
  --color-warn:    var(--amber-500);
  --color-warn-bg: var(--amber-900);
  --color-danger:  var(--red-500);
  --color-danger-bg: var(--red-900);
  --color-info:    var(--cyan-500);
  --color-special: var(--violet-500);

  /* ---- BUTTONS. Orange primary, per operator direction. ----
     Dark text on orange, not white: ~8.6:1 vs ~3.0:1. Legible AND louder. */
  --btn-primary-bg:        var(--orange-500);
  --btn-primary-bg-hover:  var(--orange-400);
  --btn-primary-bg-active: var(--orange-600);
  --btn-primary-fg:        var(--grey-1000);
  --btn-primary-border:    var(--orange-500);
  --btn-primary-glow:      var(--orange-700);

  --btn-secondary-bg:       transparent;
  --btn-secondary-bg-hover: var(--color-surface-hover);
  --btn-secondary-fg:       var(--color-text-secondary);
  --btn-secondary-border:   var(--color-border-strong);

  --btn-ghost-fg:       var(--color-text-dim);
  --btn-ghost-fg-hover: var(--color-accent);
  --btn-ghost-bg-hover: var(--color-surface-hover);

  --btn-danger-bg:       var(--red-500);
  --btn-danger-bg-hover: var(--red-400);
  --btn-danger-fg:       var(--grey-000);

  /* Form controls */
  --input-bg:          var(--grey-900);
  --input-bg-focus:    var(--grey-1000);
  --input-border:      var(--color-border-strong);
  --input-border-focus:var(--color-accent);
  --input-fg:          var(--color-text);
  --input-placeholder: var(--color-text-muted);

  /* Focus ring. Non-negotiable: v1 had ZERO focus styles, so keyboard
     navigation was completely invisible. This token is used by exactly
     one rule in base.css that hits every focusable element.            */
  --focus-ring:        var(--orange-500);
  --focus-ring-offset: var(--color-bg);
  --focus-ring-width:  2px;

  /* Overlays / scrim */
  --scrim: rgb(var(--shadow-rgb) / 0.72);

  /* Brand gradient (kept from v1, the one gradient worth keeping) */
  --brand-gradient: linear-gradient(120deg, var(--cyan-500), var(--magenta-500));

  /* Chart / sparkline series */
  --series-1: var(--cyan-500);
  --series-2: var(--magenta-500);
  --series-3: var(--orange-500);
  --series-4: var(--green-500);
}


/* ==========================================================================
   THEME , CYBER LIGHT.  A REAL light theme this time.
   ==========================================================================
   v1's light theme was broken by construction: the hamburger still turned
   magenta, the logout button still hovered magenta and every wizard label
   was still cyan, because those were hex values inside rules.
   Here, overriding these ~40 tokens is the complete and entire theme.
   Accents are darkened so they pass contrast on paper.
   ========================================================================== */
[data-theme="cyber-light"] {
  color-scheme: light;

  --color-bg:            var(--paper-100);
  --color-bg-sunken:     var(--paper-200);
  --color-surface:       var(--paper-000);
  --color-surface-raised:var(--paper-000);
  --color-surface-hover: var(--paper-200);
  --color-chrome:        var(--paper-000);

  --color-border:        var(--paper-300);
  --color-border-strong: var(--paper-400);
  --color-border-subtle: var(--paper-200);

  --color-text:           var(--paper-900);
  --color-text-secondary: var(--paper-700);
  --color-text-dim:       var(--paper-600);
  --color-text-muted:     var(--paper-500);
  --color-text-inverse:   var(--paper-000);

  --color-accent:       var(--cyan-700);
  --color-accent-hover: var(--cyan-600);
  --color-accent-quiet: var(--paper-200);
  --color-brand:        var(--magenta-600);
  --color-brand-hover:  var(--magenta-500);
  --color-brand-quiet:  var(--paper-200);

  --color-ok:      var(--green-700);
  --color-ok-bg:   var(--paper-200);
  --color-warn:    var(--amber-700);
  --color-warn-bg: var(--paper-200);
  --color-danger:  var(--red-700);
  --color-danger-bg: var(--paper-200);
  --color-info:    var(--cyan-700);

  --btn-primary-bg:        var(--orange-600);
  --btn-primary-bg-hover:  var(--orange-500);
  --btn-primary-bg-active: var(--orange-700);
  --btn-primary-fg:        var(--paper-000);
  --btn-primary-border:    var(--orange-600);
  --btn-primary-glow:      var(--orange-300);

  --btn-secondary-fg:     var(--paper-700);
  --btn-secondary-border: var(--paper-400);
  --btn-ghost-fg:         var(--paper-600);
  --btn-ghost-fg-hover:   var(--cyan-700);
  --btn-danger-fg:        var(--paper-000);

  --input-bg:       var(--paper-000);
  --input-bg-focus: var(--paper-000);

  --focus-ring:        var(--orange-600);
  --focus-ring-offset: var(--color-surface);

  --shadow-rgb: 20 24 33;
  --scrim: rgb(var(--shadow-rgb) / 0.45);

  --brand-gradient: linear-gradient(120deg, var(--cyan-700), var(--magenta-600));

  --series-1: var(--cyan-700);
  --series-2: var(--magenta-600);
  --series-3: var(--orange-600);
  --series-4: var(--green-700);
}


/* ==========================================================================
   THEME , AMBER TERMINAL.  v1 called this "orange".
   ==========================================================================
   Now that orange is the action colour globally, this theme leans all the
   way in: warm chrome, amber accents, and the primary button switches to
   cyan so the press target still separates from the surrounding warmth.
   ========================================================================== */
[data-theme="amber"] {
  color-scheme: dark;

  --color-bg:            #14100a;
  --color-bg-sunken:     #0d0a06;
  --color-surface:       #1e1810;
  --color-surface-raised:#191309;
  --color-surface-hover: #2a2114;
  --color-chrome:        #191309;

  --color-border:        #33281a;
  --color-border-strong: #4a3a24;
  --color-border-subtle: #241c12;

  --color-text:           #fff4e4;
  --color-text-secondary: #e0cfb4;
  --color-text-dim:       #b09a7c;
  --color-text-muted:     #7d6b52;
  --color-text-inverse:   #0d0a06;

  --color-accent:       var(--amber-500);
  --color-accent-hover: var(--amber-400);
  --color-accent-quiet: var(--amber-900);
  --color-brand:        var(--orange-500);
  --color-brand-hover:  var(--orange-400);
  --color-brand-quiet:  var(--orange-900);

  --btn-primary-bg:        var(--cyan-500);
  --btn-primary-bg-hover:  var(--cyan-400);
  --btn-primary-bg-active: var(--cyan-600);
  --btn-primary-fg:        #0d0a06;
  --btn-primary-border:    var(--cyan-500);
  --btn-primary-glow:      var(--cyan-700);

  --input-bg:       #0d0a06;
  --input-bg-focus: #050301;

  --focus-ring: var(--cyan-500);

  --brand-gradient: linear-gradient(120deg, var(--amber-500), var(--orange-500));

  --series-1: var(--amber-500);
  --series-2: var(--orange-500);
  --series-3: var(--cyan-500);
  --series-4: var(--green-500);
}


/* ==========================================================================
   SYSTEM PREFERENCE FALLBACK
   ==========================================================================
   v1 had ZERO prefers-color-scheme support. If no explicit theme has been
   chosen (no data-theme on <html>), follow the operating system.
   ========================================================================== */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    color-scheme: light;

    --color-bg:            var(--paper-100);
    --color-bg-sunken:     var(--paper-200);
    --color-surface:       var(--paper-000);
    --color-surface-raised:var(--paper-000);
    --color-surface-hover: var(--paper-200);
    --color-chrome:        var(--paper-000);
    --color-border:        var(--paper-300);
    --color-border-strong: var(--paper-400);
    --color-border-subtle: var(--paper-200);
    --color-text:           var(--paper-900);
    --color-text-secondary: var(--paper-700);
    --color-text-dim:       var(--paper-600);
    --color-text-muted:     var(--paper-500);
    --color-text-inverse:   var(--paper-000);
    --color-accent:       var(--cyan-700);
    --color-accent-hover: var(--cyan-600);
    --color-brand:        var(--magenta-600);
    --btn-primary-bg:     var(--orange-600);
    --btn-primary-fg:     var(--paper-000);
    --input-bg:           var(--paper-000);
    --focus-ring:         var(--orange-600);
    --shadow-rgb: 20 24 33;
    --scrim: rgb(var(--shadow-rgb) / 0.45);
    --brand-gradient: linear-gradient(120deg, var(--cyan-700), var(--magenta-600));
  }
}


/* ==========================================================================
   REDUCED MOTION , ONE BLOCK, GLOBAL EFFECT
   ==========================================================================
   v1 ran 6 keyframe animations unconditionally and had zero motion handling.
   Because every transition and animation in this codebase reads its duration
   from a --dur-* token, neutralising them here disables motion EVERYWHERE
   in one place. The belt-and-braces universal rule below catches any
   third-party or inline animation that does not use our tokens.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-instant: 0.01ms;
    --dur-fast:    0.01ms;
    --dur-base:    0.01ms;
    --dur-slow:    0.01ms;
  }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
/* The four !important above are the textbook-correct use of the keyword: a
   user accessibility preference MUST be able to defeat author styles.
   Codebase budget is 5 total, all documented:
     4 here (reduced motion), 1 in reset.css ([hidden] guard).
   Anything beyond those 5 is a bug. tools/check-tokens.py counts them. */


/* ==========================================================================
   HIGH CONTRAST / FORCED COLORS
   ========================================================================== */
@media (prefers-contrast: more) {
  :root {
    --color-border:        var(--grey-500);
    --color-border-strong: var(--grey-400);
    --color-text-dim:      var(--grey-200);
    --color-text-muted:    var(--grey-300);
    --focus-ring-width:    3px;
  }
}
