/* =============================================================================
   Backsplice — Design Tokens (single source of truth)

   Every color, spacing, radius, shadow, and type value used anywhere in the
   product resolves to a custom property defined HERE. Light values live in
   :root; dark mode is ONLY a remap inside [data-theme="dark"] — components
   must never need their own dark rules if they use these tokens.

   Loaded BEFORE app.css (see templates/partials/head.php). Lint (lint:ui)
   flags raw hex values and deprecated aliases in templates.
   ============================================================================= */

/* Self-hosted Schibsted Grotesk (latin variable font) — the system voice
   (guide §Typography, revised 2026-07-24: a distinctive grotesque replaces the
   stock Inter default). One file covers weights 400–900. font-display:swap
   keeps text visible during load; the file is <link rel=preload>ed in head.php. */
@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/assets/fonts/schibsted-grotesk-latin.woff2') format('woff2');
}

/* ---- CSS Custom Properties -------------------------------- */
:root {
  /* Brand */
  --primary:        #672dea;
  --primary-hover:  #5a1ad3;
  --primary-light:  #efeefe;
  --primary-text:   #6329e2;
  /* Brand INK for non-anchor text (buttons, spans). Aliases --primary-text so it
     inherits the dark remap; --primary is a FILL step and measures 3.35:1 as ink
     on dark's --bg-surface, below AA. Anchors got --primary-text anyway from the
     dark `a:where(...)` rule (0,1,1), which is what hid the failure on buttons. */
  --text-brand:     var(--primary-text);
  --primary-dark:   #4b09b6;
  --accent:         #008398;
  --accent-light:   #e3f6f9;
  --accent-strong:  #00707f; /* white-text fill (5.8:1) — see rule 10 */
  --accent-text:    #006c7d; /* coloured INK (6.1:1); the base is 4.47:1 — rule 10 */

  /* Legacy aliases (keep for existing code) */
  --success:  #008a4e;
  --warning:  #ac6900;
  --danger:   #d40c1a;
  --info:     #007cab;

  /* Semantic shorthand aliases (used by utility CSS) */
  --bg:      #f9f9fe;
  --bg-card: #ffffff;
  --border:  #dcdce9;
  /* Legacy aliases — referenced by older inline styles. Map to --bg-alt so
     code that says `var(--surface-secondary, var(--bg-secondary))` resolves
     to a defined value instead of falling through to nothing. */
  --surface-secondary: #eeeffa;
  --bg-secondary:      #eeeffa;

  /* Surfaces */
  --bg-body:           #f9f9fe;
  --bg-surface:        #ffffff;
  --bg-surface-raised: #ffffff;
  --bg-alt:            #eeeffa;
  --bg-hover:          #f6f6fe;

  /* Text */
  --text-primary:   #19172f;
  --text-secondary: #45445f;
  /* Clears WCAG AA body (>=4.5) even on the tinted --bg-alt surface (#eeeffa),
     where muted text often sits: 4.73:1. */
  --text-muted:     #686880;
  /* --text-subtle is used for hint/secondary label text, so it must clear WCAG
     AA-large (>=3:1) on every light surface (body/surface/alt). The Backsplice
     value clears full AA too (4.61:1 on --bg-alt, 5.28:1 on white). --text-disabled is
     for disabled controls (WCAG-exempt) and stays at the fainter value. */
  --text-subtle:    #6a6a7f;
  --text-disabled:  #a0a0b9;
  --text-inverse:   #ffffff;

  /* Borders */
  --border-color:  #dcdce9;
  --border-strong: #c8c9da;
  --border-focus:  #672dea;

  /* Semantic colors — light variants */
  --success-light:  #e8f8ee;
  --warning-light:  #fdf1e4;
  --danger-light:   #ffeeec;
  --info-light:     #e6f7ff;

  /* Semantic colors */
  --color-success:        #008a4e;
  --color-success-strong: #00874c; /* white-text fill (4.6:1) — see rule 10 */
  --color-success-bg:     #e8f8ee;
  --color-success-border: #b1dec2;
  --color-success-text:   #136842;
  --color-warning:        #ac6900;
  --color-warning-strong: #a86600; /* white-text fill (4.6:1) — see rule 10 */
  --color-warning-bg:     #fdf1e4;
  --color-warning-border: #eacba6;
  --color-warning-text:   #7a4d00;
  --color-danger:         #d40c1a;
  --color-danger-strong:  #d40c1a; /* white-text fill (5.9:1); see .btn-danger */
  --color-danger-bg:      #ffeeec;
  --color-danger-border:  #f6c3bc;
  --color-danger-text:    #a21a1b;
  --color-info:           #007cab;
  --color-info-strong:    #007cab; /* white-text fill (4.7:1); base already clears AA */
  --color-info-bg:        #e6f7ff;
  --color-info-border:    #aad9f2;
  --color-info-text:      #006186;
  --color-purple:         #a1319b;
  --color-purple-bg:      #fbeffa;
  /* Ink for text ON --color-purple-bg (rule 10). Same value as the base because
     purple already clears AA on its own tint (5.49:1) — defined so every semantic
     family exposes the SAME triad and the pairing rule is uniform. */
  --color-purple-text:    #a1319b;
  --color-white:          #ffffff;

  /* Gray ramp, 50 (nearest the surface) to 900 (nearest the ink). Pinned in the
     contract since 2026-09-26: until then it was the stock Tailwind gray, never
     reskinned, so every --gray-* paint read cool slate beside the indigo
     neutrals. Each step now IS one of those neutrals (or sits between two):
     50 = --bg-body, 100 = --bg-alt, 200 = --border-color, 300 = --border-strong,
     500 = --text-muted, 600 = --text-secondary, 900 = --text-primary. */
  --gray-50:  #f9f9fe;
  --gray-100: #eeeffa;
  --gray-200: #dcdce9;
  --gray-300: #c8c9da;
  --gray-400: #9898ad;
  --gray-500: #686880;
  --gray-600: #45445f;
  --gray-700: #36354f;
  --gray-800: #28263f;
  --gray-900: #19172f;

  /* Shadows */
  --shadow-xs: 0 1px 2px rgb(2 6 23 / 0.05);
  --shadow-sm: 0 1px 2px rgb(2 6 23 / 0.06), 0 12px 30px -18px rgb(2 6 23 / 0.18);
  --shadow:    0 1px 3px rgb(2 6 23 / 0.07), 0 16px 40px -20px rgb(2 6 23 / 0.20);
  --shadow-md: 0 2px 4px rgb(2 6 23 / 0.07), 0 20px 44px -20px rgb(2 6 23 / 0.22);
  --shadow-lg: 0 2px 4px rgb(2 6 23 / 0.08), 0 30px 60px -24px rgb(2 6 23 / 0.26);
  --shadow-xl: 0 4px 8px rgb(2 6 23 / 0.10), 0 40px 80px -28px rgb(2 6 23 / 0.30);

  /* Radius */
  --radius-sm: 6px;
  --radius:    10px;
  --radius-md: 10px;
  --radius-lg: 18px;
  --radius-xl: 26px;
  --radius-full: 9999px;

  /* Marketing section rhythm. ONE value, because the 18 marketing sections had
     picked their own from {5, 5.5, 6}rem with no rule behind which got which —
     measured as six different padding pairs on the homepage alone (88/72, 96/96,
     88/88, 80/80, 8/88, 0/44). A single step is what makes a page read as designed
     rather than assembled. The thin logo strip keeps its own smaller value; it is
     a rule, not a section. */
  --section-pad: 6rem;

  /* One reading-column width for every public content page (legal, docs, guide,
     status, blog). They were 800 / 840 / 760px, i.e. three widths one nav-click
     apart — no page looked wrong alone, only the transition between them did. */
  --reading-max: 800px;

  /* Transitions */
  --transition:      150ms ease;
  --transition-fast: 120ms ease;
  --transition-base: 150ms ease;
  --transition-slow: 300ms ease;
  --transition-md:   250ms ease;

  /* Sidebar */
  --sidebar-width:            240px;
  --sidebar-bg:               #ffffff;
  --sidebar-border:           #dcdce9;
  --sidebar-link-color:       #45445f;
  --sidebar-link-hover-bg:    #eeeffa;
  --sidebar-link-active-bg:   #efeefe;
  --sidebar-link-active-color:#5d26d6; /* 6.76:1 on --sidebar-link-active-bg; Prusik's #2867e4 was 4.45:1 */

  /* Code blocks keep a fixed dark-slate palette in both themes */
  --code-bg:   #1e293b;
  --code-text: #e2e8f0;
  /* Theme-aware faint surface overlays */
  --overlay-faint: rgba(0, 0, 0, .03);
  --overlay-soft:  rgba(0, 0, 0, .06);

  /* ---- Data-visualization palette (categorical, fixed order) ---------------
     Validated with the dataviz validator against this app's own chart surface in
     BOTH themes (white light, dark-slate dark). Each mode passes the lightness
     band, chroma floor, adjacent CVD separation (worst dE 9.1 light / 8.4 dark,
     target >=8) and the normal-vision floor (22.9 / 19.8, floor >=15). Light mode
     WARNs on contrast for the aqua and yellow steps, which obligates relief, so
     every chart using them ships direct labels AND a table view.
     Assign these in FIXED order per entity, never by rank, or a filter would
     repaint the survivors. Do not re-step without re-running the validator.
     NOTE: keep "name colon value" patterns out of this comment — the token
     contract test parses declarations by regex and would read them as real ones. */
  --viz-1: #2a78d6;   /* blue   */
  --viz-2: #eb6834;   /* orange */
  --viz-3: #1baf7a;   /* aqua   */
  --viz-4: #eda100;   /* yellow */
  --viz-grid:    #e5e6f8;   /* hairline gridlines: one step off surface */
  --viz-surface: #ffffff;   /* the surface marks are drawn on (ring/gap color) */

  --font-sans: 'Schibsted Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'SF Mono', 'Fira Code', Consolas, monospace;
}

/* ---- Semantic tiers (modernization additions) ---------------------------- */
:root {
  /* Surfaces: 1 = page, 2 = card, 3 = raised/popover */
  --surface-1: var(--bg-body);
  --surface-2: var(--bg-surface);
  --surface-3: var(--bg-surface-raised);

  /* Text: 1 = primary, 2 = secondary, 3 = muted */
  --text-1: var(--text-primary);
  --text-2: var(--text-secondary);
  --text-3: var(--text-muted);

  /* Focus & overlays */
  --focus-ring:   0 0 0 3px rgba(103, 45, 234, .35);  /* --primary at 35% */
  --overlay:      rgba(14, 13, 32, .5);                 /* --bg-body (dark) at 50% */

  /* Marketing background (hero grid / glows / shapes / starfield).
     Dark values are remapped below so the dynamic background stays visible
     and on-palette in both themes. */
  --hero-gradient: linear-gradient(135deg, #f9f9fe 0%, #efeefe 50%, #f0fdfe 100%);
  --hero-grid-line: rgba(103, 45, 234, .04);
  --hero-glow-1:   #d9d3ff;
  --hero-glow-2:   #a5f3fc;
  --hero-glow-opacity: .35;
  --hero-shape:    rgba(103, 45, 234, .14);
  --hero-star:     rgba(103, 45, 234, .35);

  /* Banded-scale families (style-guide §severity/§matrix; matrix is fixed art
     in both themes, orange re-themes) */
  --color-orange: #d84b00;
  /* Ink for orange TEXT (rule 10). The base is a fill: it is only 4.26:1 on
     white and 4.1:1 on its own 14% tint, so text must use this darker step. */
  --color-orange-text: #b94000;
  /* White-text fill: white on the base is only 4.26:1 light / 2.83:1 dark. */
  --color-orange-strong: #cd4700;
  /* The orange tint for a High-severity pill (V-26, 2026-09-24): orange-text on
     it measures 4.88:1. Severity had no orange pill, so High was amber in one
     register and red in the next. */
  --color-orange-bg: #fdeee4;
  --color-orange-border: #f0c7ab;
  --matrix-1: #50d492;
  --matrix-2: #edcc48;
  --matrix-3: #fc9f30;
  --matrix-4: #fc6b33;
  /* Ink on the four matrix FILLS. Deliberately NOT remapped in dark: the fills
     are theme-stable, and --gray-800 (the ink used until 2026-09-09) flips to
     #f1f5f9 in dark, where it measured 1.44:1 on --matrix-2. */
  --matrix-ink: #19172f;
  /* Role tokens added 2026-07-23 (guide §Color): --primary-soft = soft primary
     text on tinted chips (AA-proven both themes); --bg-inverse = the fixed deep
     chip surface (bulk bar, kbd hints) that stays dark in BOTH themes, pairing
     with --text-inverse. */
  --primary-soft: #4b09b6;
  --bg-inverse: #17152b;
}

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

  /* Semantic shorthand aliases */
  --bg:      #0e0d20;
  --bg-card: #17152b;
  --border:  #313045;
  --surface-secondary: #070517;
  --bg-secondary:      #070517;

  --bg-body:           #0e0d20;
  --bg-surface:        #17152b;
  --bg-surface-raised: #1f1e36;
  --bg-alt:            #070517;
  --overlay-faint: rgba(255, 255, 255, .04);
  --overlay-soft:  rgba(255, 255, 255, .08);
  --bg-hover:          #1f1e36;

  /* Data-viz palette, dark steps. NOT a flip of the light values — the same four
     hues re-stepped for the dark surface and validated as a set against --viz-surface #17152b
     (4.59-5.80:1 there, re-measured 2026-09-26: all four clear 3:1, so dark needs no relief rule). */
  --viz-1: #3987e5;
  --viz-2: #d95926;
  --viz-3: #199e70;
  --viz-4: #c98500;
  --viz-grid:    #313045;
  --viz-surface: #17152b;

  --text-primary:   #f3f4ff;
  --text-secondary: #bbbbd0;
  --text-muted:     #9c9cb1;
  /* AA-large (>=3:1) on every dark surface incl. raised #1f1e36 (4.67:1); stays lighter
     than --text-muted. --text-disabled (disabled controls, WCAG-exempt) keeps
     the fainter value. */
  --text-subtle:    #88889d;
  --text-disabled:  #51516c;

  --border-color:  #313045;
  --border-strong: #4b4b61;
  --border-focus:  #22cde5;

  /* Semantic light variants — dark equivalents */
  --success-light:  #092617;
  --warning-light:  #2b1c03;
  --danger-light:   #321613;
  --info-light:     #032331;

  --color-success:        #00c37a;
  /* Dark's base success/warning are BRIGHT (they read as text on dark ground),
     so white ink on them is only 2.31:1 / 1.98:1. The -strong step is the
     white-text fill — much darker than the base, unlike in light mode. */
  --color-success-strong: #008654; /* white 4.63:1 */
  --color-success-bg:     #092617;
  --color-success-border: #12452c;
  --color-success-text:   #69c090;
  --color-warning:        #f2ab19;
  --color-warning-strong: #9a6d0f; /* white 4.6:1 */
  --color-warning-bg:     #2b1c03;
  --color-warning-border: #4e3504;
  --color-warning-text:   #cea35f;
  --color-danger:         #f1453f;
  --color-danger-strong:  #d92b25; /* white-text fill stays AA (4.86:1); base stays bright for danger-as-text */
  --color-danger-bg:      #321613;
  --color-danger-border:  #5a2b26;
  --color-danger-text:    #fb8276;
  --color-info:           #40b8ee;
  --color-info-strong:    #2b7da1; /* white 4.61:1 — dark's base is bright (2.26:1) */
  --color-info-bg:        #032331;
  --color-info-border:    #024059;
  --color-info-text:      #6db5da;
  --color-purple:         #d765cf;
  --color-purple-bg:      #341832;
  --color-purple-text:    #d765cf;   /* 5.03:1 on the tint — see rule 10 */

  --shadow-xs: 0 1px 2px rgb(0 0 0 / 0.35);
  --shadow-sm: 0 8px 30px -12px rgb(0 0 0 / 0.55);
  --shadow-md: 0 12px 40px -14px rgb(0 0 0 / 0.60);
  --shadow-lg: 0 24px 60px -20px rgb(0 0 0 / 0.68);
  --shadow-xl: 0 32px 80px -24px rgb(0 0 0 / 0.75);

  --sidebar-bg:               #17152b;
  --sidebar-border:           #313045;
  --sidebar-link-color:       #9c9cb1;
  --sidebar-link-hover-bg:    #1f1e36;
  --sidebar-link-active-bg:   rgba(115,70,247,.22);
  --sidebar-link-active-color:#ada6ff;
  --primary-light:            rgba(115,70,247,.22); /* --primary at 22%, like the active nav */
  --primary-text:             #ada6ff;

  /* Gray ramp, dark. The ROLE of each step is kept, not its lightness: 50
     stays nearest the surface and 900 nearest the ink, so the ramp runs light
     to dark here (as the slate ramp it replaces did). 50 = --bg-surface,
     100 = --bg-surface-raised, 200 = --border-color, 300 = --border-strong,
     500 = --text-muted, 900 = --text-primary; the rest interpolate. */
  --gray-50:  #17152b;
  --gray-100: #1f1e36;
  --gray-200: #313045;
  --gray-300: #4b4b61;
  --gray-400: #747489;
  --gray-500: #9c9cb1;
  --gray-600: #b2b2c5;
  --gray-700: #c8c8d8;
  --gray-800: #dddeec;
  --gray-900: #f3f4ff;
}


/* ---- Dark remap for the modernization additions --------------------------- */
[data-theme="dark"] {
  --focus-ring: 0 0 0 3px rgba(173, 166, 255, .4); /* --primary-text at 40% */
  --overlay:    rgba(7, 5, 23, .65);                /* --bg-alt at 65% */

  --hero-gradient: linear-gradient(135deg, #0e0d20 0%, #17152b 55%, #0b1f2a 100%);
  --hero-grid-line: rgba(173, 166, 255, .05);
  --hero-glow-1:   #3a1f8f;
  --hero-glow-2:   #164e63;
  --hero-glow-opacity: .22;
  --hero-shape:    rgba(173, 166, 255, .18);
  --hero-star:     rgba(200, 197, 255, .65);

  /* ---- 2026 additions (tokens introduced/overridden by the 2026 system) ---- */
  --primary: #7346f7;
  --primary-hover: #6a36ed; /* white 6.24:1; a hover is a white-text FILL, so it steps DARKER, not brighter */
  --accent: #22cde5;
  --accent-strong: #158190; /* white 4.59:1 — dark's base is bright (1.92:1) */
  --accent-text: #22cde5;   /* dark's base IS the ink step here: 9.28:1 on surface */
  --success: #00c37a;
  --warning: #f2ab19;
  --danger: #f1453f;
  --info: #40b8ee;
  --color-orange: #f27636;
  /* Dark orange already clears AA as text (6.3:1 on surface), so the ink
     aliases the base — same uniform-triad reasoning as --color-purple-text. */
  --color-orange-text: #f27636;
  --color-orange-strong: #b75929; /* white 4.69:1 */
  --color-orange-bg: #2b1405;     /* orange-text on it 6.16:1 */
  --color-orange-border: #5a2a0c;
  --primary-soft: #c8c5ff;
  --bg-inverse: #1f1e36;
}
