/*
 * Copyright (c) 2026 Tuning-Database.
 * All rights reserved. Proprietary and confidential.
 * Licensed exclusively for instatuner.tuning-database.co.uk.
 *
 * Design tokens. One file, three themes, nothing else.
 *
 * Names are fixed -- roughly 7,900 lines of CSS reference them. Only values
 * change. Hairlines are tinted from the accent rather than neutral grey;
 * that tint is what makes the surface read as one system rather than a
 * grey panel with coloured buttons.
 *
 * Colour tokens are bare "R G B" triplets (no alpha), consumed as
 * rgb(var(--token)) or rgb(var(--token) / 0.NN) throughout the app -- the
 * CSS Color 4 relative-alpha syntax. --border-hairline and --border-strong
 * deliberately do NOT bake an alpha into the token itself (no "/ 0.16"
 * suffix): most call sites use the bare form for a fully-opaque hairline,
 * and a smaller set supplies its own alpha via "rgb(var(--x) / 0.4)". A
 * token-level alpha would double up with that second group and produce an
 * invalid two-slash colour, silently dropping the declaration.
 */

:root,
[data-theme="glass"] {
    /* Accent */
    --accent:            255 122 26;
    --accent-hot:         255 86 32;
    --accent-cool:        255 168 74;
    --accent-2:           var(--accent-hot);   /* alias: undefined elsewhere, used as a gradient second stop */

    /* Surfaces, darkest to lightest */
    --bg-base:            10 11 13;
    --bg-surface:         16 18 21;
    --bg-surface-2:       21 24 28;
    --bg-elevated:        27 30 35;    /* opaque surface for dropdowns/popovers */
    --surface-2:          var(--bg-surface-2);  /* alias: undefined elsewhere, same tier as bg-surface-2 */
    --surface-3:          var(--bg-elevated);   /* alias: undefined elsewhere, next tier up */

    /* z-index scale -- single source of truth so popovers can't get
       hidden behind sibling glass cards (which create their own stacking
       context via backdrop-filter). Always reference these tokens. */
    --z-base:             0;
    --z-dropdown:         1000;
    --z-sticky:           1020;
    --z-fixed:            1030;
    --z-modal-backdrop:   1040;
    --z-modal:            70;    /* second z-scale in the old file redeclared this later and won; kept effective value */
    --z-popover:          1060;
    --z-tooltip:          1070;
    --z-toast:            60;    /* second z-scale in the old file redeclared this later and won; kept effective value */
    --z-bg:               0;
    --z-default:          1;
    --z-overlay:          10;
    --z-nav:              20;

    /* Lines, tinted from the accent, never neutral grey */
    --border-hairline:   58 42 32;
    --border-strong:     92 62 42;

    /* Text */
    --text-primary:      240 240 245;
    --text-secondary:    176 176 186;
    /* Was 112 112 128 -- 4.05:1 against the flat --bg-base pair (fails AA's
       4.5:1) and as low as 3.44:1 against the opaque --bg-elevated surface
       that dropdowns/popovers actually render on (e.g. the navbar account
       menu email row) and ~3.9:1 against the footer's real composited
       background. Raised to clear 4.5:1 against every surface tier
       (bg-base/bg-surface/bg-surface-2/bg-elevated) plus the footer
       composite; see task-7-report.md for the full before/after table. */
    --text-muted:        136 136 152;
    --ink-strong:        var(--text-primary);   /* alias: undefined elsewhere, same role as text-primary */
    --ink-mute:          var(--text-muted);     /* alias: undefined elsewhere, same role as text-muted */

    /* Typography -- one sans face for the whole interface, one mono for
       code/data. Same across all three themes, so declared once here and
       never overridden per [data-theme]. */
    --font-sans:          'Chakra Petch', 'Segoe UI', -apple-system, sans-serif;
    --font-mono:          'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
    --font-body:          var(--font-sans);   /* alias: undefined elsewhere, body copy uses the same sans face */
    --font-display:       var(--font-sans);   /* alias: undefined elsewhere, headings/stat numerals use the same sans face */

    /* Radii -- tight */
    --r-tight:            4px;
    --r-default:          7px;
    --r-card:             9px;
    --r-lg:               12px;
    --r-pill:             999px;

    /* Signals */
    --signal-ok:          64 200 120;
    --signal-lime:        150 210 60;
    --signal-amber:       240 176 40;
    --signal-crimson:     226 72 72;
    --signal-cyan:        70 190 220;
    --signal-green:       var(--signal-ok);       /* alias: undefined elsewhere, "positive" fallback chain */
    --amber:              var(--signal-amber);    /* alias: undefined elsewhere, used by badge/status components */
    --cyan:               var(--signal-cyan);     /* alias: undefined elsewhere, used by badge/status components */
    --lime:               var(--signal-lime);     /* alias: undefined elsewhere, used by badge/status components */
    --danger:             var(--signal-crimson);  /* alias: undefined elsewhere, used by badge/status components */
    --accent-info:        var(--signal-cyan);     /* alias: undefined elsewhere, hover state on the report copy row */
    --accent-positive:    var(--signal-ok);       /* alias: undefined elsewhere, "positive" fallback chain */

    /* Spacing scale (8-pt) -- reuse instead of magic px in components */
    --space-1:            4px;
    --space-2:            8px;
    --space-3:            12px;
    --space-4:            16px;
    --space-5:            20px;
    --space-6:            24px;
    --space-8:            32px;
    --space-10:           40px;
    --space-12:           48px;
    --space-16:           64px;

    /* Motion */
    --motion-fast:        150ms;
    --motion-base:        240ms;
    --motion-slow:        480ms;
    --easing-standard:    cubic-bezier(0.2, 0, 0, 1);
    --easing-emphasized:  cubic-bezier(0.3, 0, 0, 1);
    --easing-decel:       cubic-bezier(0, 0, 0, 1);
    --easing-accel:       cubic-bezier(0.4, 0, 1, 1);  /* alias: undefined elsewhere, standard "accelerate" curve, mirrors easing-decel */

    /* Glass + shadow */
    --blur-glass:         18px;
    --shadow-card:        0 8px 32px -8px rgba(0, 0, 0, 0.5),
                           inset 0 0 0 1px rgba(255, 255, 255, 0.06);
    --shadow-elev:        0 16px 64px -16px rgba(0, 0, 0, 0.7),
                           inset 0 0 0 1px rgba(255, 255, 255, 0.08);
    /* Was a hardcoded rgba(255, 106, 0, 0.4) -- the old flat orange, correct
       only by coincidence back when every theme shared one accent. Now that
       spotify-dark has its own green accent (and light its own retuned
       orange, see below), a literal here would glow the wrong colour on
       two of the three themes. Deliberately declared ONCE, not per theme:
       var(--accent) resolves against whichever [data-theme] block is
       active on <html> at the point .btn--primary:hover consumes this
       token, the same nested-custom-property behaviour spotify-dark
       already relies on for its inherited --bg-elevated/--signal-* below
       -- so this single declaration is already "per-theme", no redeclare
       needed in the light/spotify-dark blocks. */
    --shadow-glow-accent: 0 0 24px -4px rgb(var(--accent) / 0.4);

    /* Editor (AI File Editor workbench) -- mapped onto the surface/text
       tokens above so the editor stops hardcoding dark values and its
       banners stay legible in every theme. */
    --ide-bg:             rgb(var(--bg-base));
    --ide-bg-elev:        rgb(var(--bg-elevated));
    --ide-border:         rgb(var(--border-hairline));
    --ide-text:           rgb(var(--text-primary));
    --ide-text-muted:     rgb(var(--text-muted));

    color-scheme: dark;
}

/* Light theme (override only diverging tokens) */
[data-theme="light"] {
    /* Was 214 88 8 -- fails AA as text everywhere it's used (it's the
       global link colour, instatuner.css:42-43): 3.99:1 on white surfaces,
       3.83:1 on --bg-base, 3.66:1 on --bg-surface-2, 3.89:1 on the
       composited footer. Darkened to 180 66 0, which clears 5.17-5.65:1
       against all four light surface tiers -- see fix-wave-report.md for
       the full before/after table. White text on the new value also
       reaches 5.65:1 at rest, which retired the black/white .btn--primary
       colour flip in instatuner.css (was lines 219-220) and let
       .tier-badge--vip go back to a single white text colour instead of
       black (black drops to ~3.72:1 against this new value). */
    --accent:             180 66 0;
    --accent-hot:         196 60 12;
    --accent-cool:        224 132 40;

    --bg-base:            250 250 251;
    --bg-surface:         255 255 255;
    --bg-surface-2:       244 245 247;
    --bg-elevated:        255 255 255;

    --border-hairline:    228 202 180;
    --border-strong:      206 158 118;

    --text-primary:       15 23 42;
    --text-secondary:     71 85 105;
    /* Was 113 113 128 -- 4.40:1 against --bg-surface-2 (the darkest of this
       theme's surface tiers, and the real worst case for dark-on-light
       text). Darkened to clear 4.5:1 against every surface tier. */
    --text-muted:         104 104 119;

    /* All four below were failing AA as text (used as `color:` at 173
       sites in instatuner.css): --signal-lime 98 150 20 (3.27:1 vs
       --bg-surface-2), --signal-amber 176 118 8 (3.54:1), --signal-cyan
       26 132 164 (3.94:1), --signal-ok 22 140 76 (3.94:1) -- worst case in
       each is always --bg-surface-2, the darkest of this theme's four
       tiers. Darkened/deepened to clear ~4.85-5.16:1 against
       --bg-surface-2 and correspondingly more against --bg-base and
       --bg-elevated; see fix-wave-report.md for the full per-surface
       table. --signal-crimson was already passing (4.5:1+ on every tier)
       and is unchanged. */
    --signal-ok:          16 120 64;
    --signal-lime:        80 116 12;
    --signal-amber:       150 96 4;
    --signal-crimson:     186 40 40;
    --signal-cyan:        22 112 140;

    --shadow-card:        0 4px 16px -4px rgba(0, 0, 0, 0.08),
                           inset 0 0 0 1px rgba(0, 0, 0, 0.04);
    --shadow-elev:        0 12px 48px -12px rgba(0, 0, 0, 0.15),
                           inset 0 0 0 1px rgba(0, 0, 0, 0.06);

    --ide-bg:             rgb(var(--bg-base));
    --ide-bg-elev:        rgb(var(--bg-elevated));
    --ide-border:         rgb(var(--border-hairline));
    --ide-text:           rgb(var(--text-primary));
    --ide-text-muted:     rgb(var(--text-muted));

    color-scheme: light;
}

/* "Spotify-dark" theme (recognizable to existing users from related products) */
[data-theme="spotify-dark"] {
    --accent:             30 215 96;
    --accent-hot:         24 180 80;
    --accent-cool:        120 230 160;

    --bg-base:            9 9 9;
    --bg-surface:         18 18 18;
    --bg-surface-2:       24 24 24;

    --border-hairline:    34 48 40;
    --border-strong:      46 72 56;

    --text-primary:       255 255 255;
    --text-secondary:     179 179 179;
    /* Was 130 130 130 -- 4.35:1 against --bg-elevated (inherited from glass,
       see the block comment below on --signal-* for why this theme doesn't
       redeclare every surface/text token). Raised to clear 4.5:1 against
       every surface tier this theme actually uses, including the inherited
       --bg-elevated. */
    --text-muted:         138 138 138;

    /* --bg-elevated and --signal-ok/--signal-lime/--signal-amber/
       --signal-crimson/--signal-cyan are deliberately NOT redeclared here --
       this theme inherits the glass values for all of them (the `:root,
       [data-theme="glass"]` block at the top of this file sets them on
       <html> unconditionally; a [data-theme="spotify-dark"] block only
       overrides what it explicitly lists). That's a choice, not a gap --
       but "clears 4.5:1 against this theme's own backgrounds" only holds
       against --bg-base. It is NOT true per surface. --signal-ok/-lime/
       -amber/-cyan are all bright enough to clear 7.5:1+ against every
       tier regardless, so --signal-crimson (226 72 72) is the only one
       that matters, and its real numbers are:
         vs --bg-base (9 9 9)          4.98:1  pass
         vs --bg-surface (18 18 18)    4.69:1  pass
         vs --bg-surface-2 (24 24 24)  4.44:1  FAIL
         vs --bg-elevated (27 30 35)   4.18:1  FAIL
       --bg-elevated is the inherited glass value, so glass measures the
       same on that tier (4.18:1, also a fail) and is only marginally
       better on its own --bg-surface-2 (21 24 28): 4.46:1, still a fail.
       --signal-crimson feeds .field__error text and the danger
       badge/button family -- both render on --bg-surface-2 or
       --bg-elevated in normal use, so this is a live near-miss on both
       themes, not a passing case. Retuning --signal-crimson is a sitewide
       colour change (same class of decision as retuning --accent was for
       light, see above) and deliberately not done in this pass -- give it
       a real per-surface-passing value, in both this block and glass's,
       the next time this token is touched. See fix-wave-report.md for
       the numbers this replaces. */
    --shadow-card:        0 8px 32px -8px rgba(0, 0, 0, 0.7),
                           inset 0 0 0 1px rgba(255, 255, 255, 0.04);

    --ide-bg:             rgb(var(--bg-base));
    --ide-bg-elev:        rgb(var(--bg-elevated));
    --ide-border:         rgb(var(--border-hairline));
    --ide-text:           rgb(var(--text-primary));
    --ide-text-muted:     rgb(var(--text-muted));

    color-scheme: dark;
}
