/* ============================================================================
   StockWatch BC — Design Tokens (single source of truth)
   ----------------------------------------------------------------------------
   This file is the ONE canonical place for brand colour, the neutral ramp,
   status/signal colours, radii, shadows, spacing, motion and the type scale.
   It is loaded FIRST on every page (before page CSS / inline <style>), so every
   surface resolves the same values.

   2026-08 OCEAN BLUE REBRAND: the brand moved from steel navy (#25567F) to the
   Ocean Blue system (ocean-900 #0A4D68 → ocean-100 #E3F2FD). Neutrals moved
   from the Tailwind slate ramp to the cool gray ramp (#111827…#F9FAFB) — the
   --slate-* NAMES are kept (hundreds of consumers) but now resolve to the gray
   values; --gray-* aliases below are canonical for new code. Status colours
   moved to the semantic ramps (success/warning/danger/purple) defined here.
   Semantic meaning is fixed app-wide: In Stock = green, Low = amber,
   Out = red, Ships/Online = purple, brand/interaction = Ocean Blue.

   Migration note: the older stylesheets historically defined their own brand
   names (`--lenovo-red`, `--roku-purple`, `--brand-purple`) and ramps. Those
   names are kept as ALIASES below so nothing breaks, but they now resolve from
   the canonical `--brand-*` / `--slate-*` tokens here — change a value once and
   it propagates everywhere. New code should use the canonical names.
   ============================================================================ */
:root {
  /* ── Ocean Blue brand ramp ──────────────────────────────────────────────── */
  /* 900 = brand/nav emphasis and primary-button hover; 700 = THE interactive
     colour (buttons, links, active tabs, focus); 800 = AA text step (700 is
     3.68:1 on white — fine for fills/large text/UI, below 4.5:1 for small
     text, so small blue text on white uses 800 at 4.6:1); 500 = hover/support
     accents & chart series; 300 = subtle highlights + dark-theme accent;
     100 = selected/info surfaces. */
  --ocean-900: #0A4D68;
  --ocean-800: #1976D2;
  --ocean-700: #1E88E5;
  --ocean-500: #42A5F5;
  --ocean-300: #90CAF9;
  --ocean-100: #E3F2FD;

  /* ── Brand (Ocean Blue) ─────────────────────────────────────────────────── */
  --brand-primary:        var(--ocean-700);
  --brand-primary-dk:     var(--ocean-900);
  --brand-primary-md:     var(--ocean-500);
  --brand-primary-lt:     var(--ocean-300);
  --brand-primary-soft:   rgba(30, 136, 229, 0.08);
  --brand-primary-border: rgba(30, 136, 229, 0.24);
  /* Brand-blue for SMALL TEXT (links, active nav/tab labels, text buttons).
     ocean-700 is 3.68:1 on white — fine for fills/icons/large text, fails
     WCAG AA (4.5:1) for body-size text. This step passes on EVERY light
     surface: 5.75 white · 5.5 gray-50 · 5.22 gray-100 · 5.03 ocean-100
     (2026-08 contrast audit). swApplyBranding() recomputes it per tenant. */
  --brand-primary-text:   #1565C0;

  /* The brand as a bare RGB triple, so CSS can compose ANY alpha:
       rgba(var(--brand-rgb), 0.12)
     Without this, every brand tint had to be a hardcoded rgba() literal — and
     hardcoded literals do not recolor. swApplyBranding() (dashboard-system.js)
     overrides --brand-rgb per tenant, so all tints follow the accent. */
  --brand-rgb: 30, 136, 229;

  /* The brand blue used for GLYPHS/wordmarks (icon strokes, logo text). Dark
     mode re-pivots it to the brand's light step so brand-coloured marks stay
     readable on dark surfaces. Fills keep --brand-primary; body-size TEXT
     uses --brand-primary-text (AA) — this token is only for glyphs and
     large/bold marks. */
  --brand-text: var(--brand-primary);

  /* Brand tint surfaces (deal cards, active tabs, icon chips). Ocean-100 for
     the default brand; swApplyBranding() recomputes them from the tenant hex. */
  --brand-tint:        var(--ocean-100);
  --brand-tint-border: #BBDEFB;

  /* ── Brand gradient — PRIMARY ACTIONS ONLY ──────────────────────────────── */
  /* One definition of "this is the primary thing to do on this screen". It is
     deliberately scarce: buttons that submit, save, create, confirm or open a
     deal. Not pagination arrows, not filter chips, not dropdowns, not "view
     all" — those stay white/outlined, and that restraint is what makes the
     gradient read as premium instead of as decoration.

     NEVER use these on cards, inputs, table rows, badges, charts or page
     backgrounds. Inventory status keeps its own semantics (green / amber /
     red / purple); this ramp means BRAND + PRIMARY ACTION, nothing else.

     The default stops are the brand ramp. swApplyBranding() (dashboard-system.js)
     RECOMPUTES all three from a tenant's accent colour, so a white-label tenant
     gets their own gradient rather than Ocean Blue on their primary buttons. */
  --sw-gradient-brand:        linear-gradient(135deg, #0A4D68 0%, #0878D1 48%, #1E88E5 100%);
  --sw-gradient-brand-hover:  linear-gradient(135deg, #083E55 0%, #086CBD 48%, #1976D2 100%);
  --sw-gradient-brand-active: linear-gradient(135deg, #07384D 0%, #075FA6 50%, #1565C0 100%);
  /* Large brand SURFACES (the login panel / mobile brand header) — a longer,
     darker ramp than the button gradient because it covers far more area.
     Centralised here so the login page stops carrying two literal copies. */
  --sw-gradient-brand-panel:  linear-gradient(145deg, #062F4A 0%, #0A4D68 45%, #075E9B 100%);
  /* Subtle lift on hover, and the focus ring primary buttons share. */
  --sw-shadow-brand-hover: 0 4px 12px rgba(10, 77, 104, 0.16);
  --sw-focus-ring-brand:   0 0 0 3px rgba(30, 136, 229, 0.20);

  /* ── Neutral ramp (cool gray) ───────────────────────────────────────────── */
  /* Values are the cool-gray ramp (#111827 family). The --slate-* names are
     load-bearing across every stylesheet, so they stay; --gray-* below are
     the canonical aliases. Avoid pure black. */
  --slate-50:  #F9FAFB;
  --slate-100: #F3F4F6;
  --slate-200: #E5E7EB;
  --slate-300: #D1D5DB;
  --slate-400: #9CA3AF;   /* decorative / borders only — see --color-text-muted for text */
  --slate-500: #6B7280;
  --slate-600: #4B5563;
  --slate-700: #374151;
  --slate-800: #1F2937;
  --slate-900: #111827;

  /* Canonical neutral names (formerly re-declared per page — now here once). */
  --gray-50:  var(--slate-50);
  --gray-100: var(--slate-100);
  --gray-200: var(--slate-200);
  --gray-300: var(--slate-300);
  --gray-400: var(--slate-400);
  --gray-500: var(--slate-500);
  --gray-600: var(--slate-600);
  --gray-700: var(--slate-700);
  --gray-800: var(--slate-800);
  --gray-900: var(--slate-900);
  --white:    #FFFFFF;

  /* ── Semantic colour roles ──────────────────────────────────────────────── */
  --color-page:        var(--slate-100);   /* app/page background (#F3F4F6) */
  --color-bg:          var(--color-page);
  --color-surface:     #FFFFFF;            /* cards, modals, dropdowns */
  --color-surface-2:   var(--slate-50);    /* subtle fill: table heads, inset panels */
  --color-surface-secondary: #F8FAFC;      /* secondary panels inside cards */
  --color-border:        var(--slate-200); /* cards, dividers (#E5E7EB) */
  --color-border-subtle: var(--slate-200);
  --color-border-strong: var(--slate-300); /* controls needing definition (#D1D5DB) */
  /* Text-FIELD borders only (inputs/selects/textareas), NOT cards: darkened
     until ≥3:1 on white (WCAG 1.4.11 non-text contrast). 2026-08 audit:
     gray-400 is only 2.54:1 — this is gray-400 pulled down in lightness,
     hue/sat kept (#858E9D = 3.31:1 on white, 3.0:1 on the gray-100 page
     background, so fields pass on AND off white cards). Cards keep
     --color-border. */
  --color-border-input: #858E9D;
  --color-text:        var(--slate-900);
  --color-text-primary:   var(--slate-900);
  --color-text-soft:   var(--slate-700);
  --color-text-secondary: var(--slate-700);
  --color-text-muted:  #69707D;   /* gray-500 darkened for AA everywhere it sits: 4.86:1 on white, 4.53:1 on gray-100 (2026-08 contrast audit) — never use gray-400 for text */

  /* Brand-role semantics (Ocean Blue) */
  --color-brand:          var(--ocean-900);
  --color-primary:        var(--ocean-700);
  --color-primary-hover:  var(--ocean-500);  /* hover for links/soft accents; filled primary buttons darken to ocean-900 instead */
  --color-primary-subtle: var(--ocean-100);

  /* ── Status ramps ───────────────────────────────────────────────────────── */
  /* -700 for text/borders on white, -500 for fills/segments/dots, -300 for
     supporting accents + dark theme, -100 for tint surfaces. -rgb triples
     compose alphas: rgba(var(--success-rgb), 0.35). */
  --success-700: #068F46;
  --success-500: #10B981;
  --success-300: #34D399;
  --success-100: #D1FAE5;
  --success-rgb: 16, 185, 129;
  --success-800: #057E3E;   /* AA text on success-100 tints (4.56:1 — #068F46 is 3.68:1 there) */

  --warning-700: #B45309;
  --warning-500: #F59E0B;
  --warning-300: #FBBF24;
  --warning-100: #FEF3C7;
  --warning-rgb: 245, 158, 11;

  --danger-700: #991B1B;
  --danger-600: #DC2626;    /* AA text step on white (4.83:1); -700 for text on -100 tints */
  --danger-500: #EF4444;
  --danger-300: #F87171;
  --danger-100: #FEE2E2;
  --danger-rgb: 239, 68, 68;

  /* ── Purple supporting accent (data category, never decoration) ─────────── */
  /* Ships/online availability, secondary chart categories, specialized data
     states. Deliberately distinct from the Ocean brand hue so a status colour
     never reads as brand chrome. */
  --purple-700: #5821B6;
  --purple-500: #7C3AED;
  --purple-300: #A78BFA;
  --purple-100: #EDE9FE;
  --purple-rgb: 124, 58, 237;

  /* ── Categorical accent (legacy names → purple ramp) ────────────────────── */
  /* "ships from online", "undercut", "lead store", "client". */
  --cat-violet:        var(--purple-500);
  --cat-violet-dk:     var(--purple-700);
  --cat-violet-soft:   rgba(124, 58, 237, 0.10);
  --cat-violet-border: rgba(124, 58, 237, 0.35);

  /* Ships/online pill trio (canonical — page ramps alias these) */
  --ship-bg:   var(--purple-100);
  --ship-bd:   #DDD6FE;
  --ship-text: var(--purple-700);

  /* ── Status / signal colours (text-safe, AA on white) ───────────────────── */
  /* 2026-08 Ocean audit: signal tokens carry TEXT (stat numbers, alert copy),
     so each is the AA step of its ramp: ok = success-700 pulled down to 4.56:1
     (#068F46 is 4.18:1), low = warning-700 (5.02:1), out = danger-600
     (4.83:1), info = ocean-800 (4.60:1 — ocean-700 is 3.68:1). Fills and
     segments use the -500 / --inventory-* tokens instead. Dark theme
     re-pivots these to the pastel -300s — see the block after :root. */
  --signal-ok:   #068842;
  --signal-low:  var(--warning-700);
  --signal-out:  var(--danger-600);
  --signal-info: var(--ocean-800);

  /* ── Inventory snapshot semantics (segments, bars, dots — fills) ────────── */
  --inventory-total:    var(--ocean-900);
  --inventory-in-stock: var(--success-500);
  --inventory-shipping: var(--purple-500);
  --inventory-low:      var(--warning-500);
  --inventory-out:      var(--danger-500);

  /* ── Chart series sequence (categorical, non-status data) ───────────────── */
  /* When a chart encodes inventory STATUS, the semantic colours above override
     this sequence (In Stock green, Ships purple, Low amber, Out red). */
  --chart-1: #1E88E5;
  --chart-2: #42A5F5;
  --chart-3: #10B981;
  --chart-4: #7C3AED;
  --chart-5: #F59E0B;
  --chart-6: #EF4444;
  --chart-7: #90CAF9;
  --chart-8: #6B7280;

  /* ── Radii ──────────────────────────────────────────────────────────────── */
  --radius-sm:   6px;
  --radius-md:   8px;
  --radius-lg:   10px;
  --radius-xl:   12px;
  --radius-pill: 100px;

  /* ── Shadows (neutral, gray-900 based — never coloured) ─────────────────── */
  --shadow-xs:    0 1px 2px rgba(17, 24, 39, 0.04);
  --shadow-sm:    0 1px 2px rgba(17, 24, 39, 0.06);
  --shadow-md:    0 2px 8px rgba(17, 24, 39, 0.06);
  --shadow-lg:    0 8px 24px rgba(17, 24, 39, 0.10);
  --shadow-brand: 0 1px 2px rgba(17, 24, 39, 0.08);

  /* ── Interaction ────────────────────────────────────────────────────────── */
  /* WCAG 2.2 SC 2.5.8 (Target Size Minimum, AA): every pointer target must
     offer at least 24×24 CSS px. Use this token for min-width/min-height on
     small controls (icon buttons, chips' dismiss ×, dense table controls)
     instead of hardcoding 24px. 44px (2.5.5 AAA) remains the ideal where the
     layout affords it. */
  --target-min: 24px;

  /* ── Spacing scale (4px base) ───────────────────────────────────────────── */
  --space-1: 0.25rem;   /* 4px  */
  --space-2: 0.5rem;    /* 8px  */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-5: 1.5rem;    /* 24px */
  --space-6: 2rem;      /* 32px */
  --space-8: 3rem;      /* 48px */

  /* ── Motion ─────────────────────────────────────────────────────────────── */
  --motion-fast: 150ms;
  --motion-base: 250ms;
  --motion-slow: 350ms;

  /* ── Type scale ─────────────────────────────────────────────────────────── */
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --text-xs:   0.72rem;
  --text-sm:   0.85rem;
  --text-base: 0.95rem;
  --text-lg:   1.15rem;
  --text-xl:   1.45rem;
  --text-2xl:  1.9rem;

  /* Responsive breakpoints are documented here for reference (CSS custom
     properties can't be used inside @media): sm 640px · md 900px · lg 1080px ·
     xl 1280px · 2xl 1620px. Use these values when adding media queries. */

  /* (component utilities like .skip-link are defined after :root, below) */

  /* ── Back-compat aliases → canonical (legacy names, do not add new ones) ─── */
  --brand-purple:    var(--brand-primary);
  --brand-purple-dk: var(--brand-primary-dk);
  --brand-purple-md: var(--brand-primary-md);
  --brand-purple-lt: var(--brand-primary-lt);
  --brand-purple-bg: var(--brand-primary-soft);
  --brand-purple-bd: var(--brand-primary-border);
  --lenovo-red:        var(--brand-primary);
  --lenovo-red-dark:   var(--brand-primary-dk);
  --lenovo-red-soft:   var(--brand-primary-soft);
  --lenovo-red-border: var(--brand-primary-border);
}

/* Dark theme signal colours (2026-08 contrast audit). The light -700s land at
   ≤3.1:1 on slate-800/900 surfaces, so dark pivots every var-driven signal
   use (stat numbers, alert text, toast edges, bars/dots) to the pastel -300
   of the SAME ramp: all ≥5.3:1 on slate-800 and slate-900. Theme attribute is
   set pre-paint by boot-theme.js. */
html[data-theme="dark"] {
  /* ── Dark surfaces & text ────────────────────────────────────────────────
     Until now dark mode was built per-selector: manager/admin carried ~300
     hand-written `html[data-theme="dark"]` rules while the rep pages
     (dashboard, competition) carried three between them, so the two
     most-used screens simply never went dark. Flipping the SEMANTIC roles
     here makes every consumer of --color-* theme itself, which is what those
     tokens were for. The --slate-* ramp is deliberately NOT inverted: the
     existing per-selector dark rules address those steps literally, and
     flipping them would turn every one of those rules inside out.
     Values are the dark end of the Ocean/gray system: page #0A1A2A,
     card #111827, input surface #1F2937 (per the Ocean Blue spec §8). */
  --color-page:        #0A1A2A;
  --color-surface:     #111827;
  --color-surface-2:   #182233;
  --color-border:      #374151;
  --color-border-input:#4A5A70;
  --color-text:        #F3F4F6;   /* 15.5:1 on surface */
  --color-text-soft:   #D1D5DB;   /* 11.5:1 on surface */
  --color-text-muted:  #9FB0C4;   /*  7.3:1 on surface — the light-mode
                                      muted value lands near 1.7:1 here */
  --brand-text:         var(--brand-primary-lt);
  --brand-primary-text: var(--ocean-300);
  --cat-violet:    var(--purple-300);
  --cat-violet-dk: var(--purple-300);
  --signal-ok:   var(--success-300);
  --signal-low:  var(--warning-300);
  --signal-out:  var(--danger-300);
  --signal-info: var(--ocean-300);
}

/* Webfonts removed 2026-08: the app now renders on the platform's native UI
   stack (system-ui) — zero font network requests, zero swap-shift, and a look
   that matches the OS. The old Inter/DM Mono metric-fallback @font-faces are
   gone with them. */

/* Skip-to-content link (WCAG 2.4.1 bypass blocks). Hidden until keyboard-focused,
   then slides into view as the first focusable element on the page. */
.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: var(--sw-z-skip-link, 910);
  background: var(--brand-primary);
  color: #fff;
  padding: 10px 16px;
  border-radius: var(--radius-md, 10px);
  font: 700 0.9rem/1 var(--font-sans, sans-serif);
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus {
  top: 8px;
  outline: 2px solid #fff;
  outline-offset: 2px;
}
