/* ============================================================================
   QuickPlay — design tokens
   The single source of colour, type, space, radius, elevation and motion.
   Never hard-code a colour or a pixel value outside this file: use a token.
   Light is the default; [data-theme="dark"] on <html> swaps the semantic layer.
   ========================================================================= */

:root {
    /* ---- Palette: cool-tinted ink neutrals ------------------------------ */
    --qp-ink-0: #ffffff;
    --qp-ink-25: #fcfcfd;
    --qp-ink-50: #f8f9fb;
    --qp-ink-100: #f1f2f6;
    --qp-ink-150: #e9eaf1;
    --qp-ink-200: #e1e3ec;
    --qp-ink-250: #d7d9e4;
    --qp-ink-300: #c6c9d7;
    --qp-ink-400: #9ea2b6;
    --qp-ink-500: #767a8e;
    --qp-ink-600: #5a5e72;
    --qp-ink-700: #434758;
    --qp-ink-800: #2e313f;
    --qp-ink-900: #1d1f29;
    --qp-ink-950: #121319;
    --qp-ink-1000: #0b0c11;

    /* ---- Palette: Iris accent ------------------------------------------ */
    --qp-iris-50: #f4f5ff;
    --qp-iris-100: #eef0ff;
    --qp-iris-200: #dfe1fd;
    --qp-iris-300: #c3c5f8;
    --qp-iris-400: #9a9bef;
    --qp-iris-500: #5b5bd6;
    --qp-iris-600: #5151cd;
    --qp-iris-700: #4443b4;
    --qp-iris-800: #383890;
    --qp-iris-900: #2c2c6e;
    --qp-iris-light: #8e8ef5;

    /* ---- Palette: semantics -------------------------------------------- */
    --qp-pass-500: #1f9d60;
    --qp-fail-500: #dc3d43;
    --qp-warn-500: #d9822b;
    --qp-info-500: #2f7de1;
    --qp-prod-500: #b4371e;

    /* ---- Type ----------------------------------------------------------- */
    --qp-font-sans: "Inter", "Inter var", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --qp-font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, "Liberation Mono", monospace;

    --qp-text-3xs: 0.625rem; /* 10 — sparing: keycaps, overline */
    --qp-text-2xs: 0.6875rem; /* 11 — overline / meta */
    --qp-text-xs: 0.75rem; /* 12 */
    --qp-text-sm: 0.8125rem; /* 13 — dense tables, secondary */
    --qp-text-md: 0.875rem; /* 14 — base */
    --qp-text-lg: 1rem; /* 16 */
    --qp-text-xl: 1.25rem; /* 20 */
    --qp-text-2xl: 1.5rem; /* 24 */
    --qp-text-3xl: 2rem; /* 32 */

    --qp-leading-tight: 1.25;
    --qp-leading-snug: 1.4;
    --qp-leading-normal: 1.55;
    --qp-leading-relaxed: 1.7;

    --qp-weight-normal: 400;
    --qp-weight-medium: 500;
    --qp-weight-semibold: 600;

    --qp-tracking-tight: -0.014em;
    --qp-tracking-tighter: -0.02em;
    --qp-tracking-wide: 0.04em;
    --qp-tracking-caps: 0.06em;

    /* ---- Space (4-pt grid) ---------------------------------------------- */
    --qp-space-0: 0;
    --qp-space-1: 0.25rem; /* 4 */
    --qp-space-2: 0.5rem; /* 8 */
    --qp-space-3: 0.75rem; /* 12 */
    --qp-space-4: 1rem; /* 16 */
    --qp-space-5: 1.25rem; /* 20 */
    --qp-space-6: 1.5rem; /* 24 */
    --qp-space-8: 2rem; /* 32 */
    --qp-space-10: 2.5rem; /* 40 */
    --qp-space-12: 3rem; /* 48 */
    --qp-space-16: 4rem; /* 64 */
    --qp-space-20: 5rem; /* 80 */

    /* ---- Radius ---------------------------------------------------------- */
    --qp-radius-xs: 4px;
    --qp-radius-sm: 6px; /* controls */
    --qp-radius-md: 8px;
    --qp-radius-lg: 10px; /* surfaces */
    --qp-radius-xl: 14px;
    --qp-radius-full: 999px; /* pills */

    /* ---- Layout ---------------------------------------------------------- */
    --qp-sidebar-width: 248px;
    --qp-sidebar-rail: 56px;
    --qp-topbar-height: 56px;
    --qp-content-max: 1440px;
    --qp-gutter: var(--qp-space-8);

    /* ---- Motion ---------------------------------------------------------- */
    --qp-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
    --qp-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --qp-duration-fast: 120ms;
    --qp-duration-base: 160ms;
    --qp-duration-slow: 200ms;
    --qp-transition: var(--qp-duration-base) var(--qp-ease);

    /* ---- Z ---------------------------------------------------------------- */
    --qp-z-sticky: 20;
    --qp-z-sidebar: 40;
    --qp-z-scrim: 50;
    --qp-z-drawer: 60;
    --qp-z-popover: 70;
    --qp-z-dialog: 80;
    --qp-z-palette: 90;
    --qp-z-toast: 100;
    --qp-z-tooltip: 110;
}

/* ============================================================================
   Semantic layer — LIGHT
   ========================================================================= */
:root,
:root[data-theme="light"] {
    color-scheme: light;

    /* surfaces */
    --qp-canvas: var(--qp-ink-50);
    --qp-surface: var(--qp-ink-0);
    --qp-surface-sunken: var(--qp-ink-100);
    --qp-surface-raised: var(--qp-ink-0);
    --qp-surface-overlay: var(--qp-ink-0);
    --qp-surface-hover: color-mix(in oklab, var(--qp-ink-900) 4%, transparent);
    --qp-surface-active: color-mix(in oklab, var(--qp-ink-900) 7%, transparent);
    --qp-surface-selected: var(--qp-iris-100);
    --qp-sidebar-bg: var(--qp-ink-50);

    /* text
     *
     * subtle and faint no longer point at ink-500 / ink-400. Those were 4.25:1 and 2.53:1 on white and
     * 3.80:1 and 2.26:1 on the sunken surface, against a WCAG AA floor of 4.5:1 — and they carry the
     * secondary text on nearly every screen (69 uses of faint, 26 of subtle), so axe reported the same two
     * tokens fifty-one times across the page sweep. The values below are the lightest points on the same
     * ramp that clear 4.5:1 against the worst background each is used on, which keeps the
     * muted > subtle > faint hierarchy legible instead of collapsing it:
     *
     *   muted  #5a5e72  6.40 on white  5.73 on sunken
     *   subtle #5f6377  5.94 on white  5.31 on sunken
     *   faint  #6a6e7e  5.07 on white  4.53 on sunken
     *
     * ink-400 and ink-500 themselves are unchanged — they are still the right borders and fills; they were
     * only ever wrong as text.
     *
     * Second pass, from the design side: meeting the floor is not the whole job. Those first values put
     * muted, subtle and faint within ΔL* 2.1 and 4.3 of each other — they pass axe and look like one
     * grey, so a caption, a timestamp and a placeholder stopped being three different weights of
     * information. muted moves down to open the band, and the three are spread across it evenly:
     *
     *   muted  #494d5c  8.40 on white  7.51 on sunken   ΔL* 20.9 from text
     *   subtle #5a5e6f  6.43 on white  5.75 on sunken   ΔL*  7.2 from muted
     *   faint  #6a6e7e  5.07 on white  4.53 on sunken   ΔL*  6.5 from subtle
     *
     * Third pass, from a sweep with more data in it: "the worst background" was being read as the page
     * and the sunken panel, and these tokens also sit on tinted rows — a selected row, a failed step, a
     * warning strip. faint at #6a6e7e was 3.96:1 on ink-200, which a selected row resolves to. A token's
     * contract is AA on *any* surface it is allowed on, so all three are now measured against every
     * surface and tint in this file and the ramp is re-spread underneath that floor:
     *
     *   muted  #3f434f  9.87 on white, 7.71 at worst   ΔL* 16.5 from text
     *   subtle #505363  7.61 on white, 5.95 at worst   ΔL*  7.1 from muted
     *   faint  #626574  5.78 on white, 4.51 at worst   ΔL*  7.4 from subtle
     *
     * faint sits on the AA floor by construction: there is nothing quieter available.
     */
    --qp-text: var(--qp-ink-900);
    --qp-text-strong: var(--qp-ink-950);
    --qp-text-muted: #3f434f;
    --qp-text-subtle: #505363;
    --qp-text-faint: #626574;
    --qp-text-on-accent: #ffffff;
    --qp-text-inverse: var(--qp-ink-50);

    /* lines */
    --qp-border: var(--qp-ink-200);
    --qp-border-subtle: var(--qp-ink-150);
    --qp-border-strong: var(--qp-ink-300);
    --qp-border-field: var(--qp-ink-250);
    --qp-field-bg: var(--qp-surface);

    /* accent */
    --qp-accent: var(--qp-iris-500);
    --qp-accent-hover: var(--qp-iris-600);
    --qp-accent-active: var(--qp-iris-700);
    --qp-accent-subtle: var(--qp-iris-100);
    --qp-accent-subtle-hover: var(--qp-iris-200);
    --qp-accent-border: var(--qp-iris-300);
    --qp-accent-text: var(--qp-iris-700);
    --qp-focus-ring: var(--qp-iris-500);

    /* semantic foreground / background pairs */
    --qp-pass: #197a4b;
    --qp-pass-bg: #e6f6ed;
    --qp-pass-border: #b3e3c9;
    --qp-fail: #c22a30;
    --qp-fail-bg: #fdeaea;
    --qp-fail-border: #f5c2c4;
    --qp-warn: #a25d13;
    --qp-warn-bg: #fdf1e2;
    --qp-warn-border: #f2d3a9;
    --qp-info: #1d63ba;
    --qp-info-bg: #e8f1fd;
    --qp-info-border: #bcd7f7;
    --qp-neutral: var(--qp-ink-600);
    --qp-neutral-bg: var(--qp-ink-100);
    --qp-neutral-border: var(--qp-ink-200);
    --qp-prod: #9c2f19;
    --qp-prod-bg: #fdece7;
    --qp-prod-border: #f6c7b9;

    /* elevation — soft, low contrast */
    --qp-shadow-1: 0 1px 2px -1px rgb(16 18 28 / 0.08), 0 1px 3px rgb(16 18 28 / 0.06);
    --qp-shadow-2: 0 2px 4px -2px rgb(16 18 28 / 0.08), 0 6px 16px -4px rgb(16 18 28 / 0.10);
    --qp-shadow-3: 0 4px 8px -4px rgb(16 18 28 / 0.10), 0 16px 40px -8px rgb(16 18 28 / 0.16);
    --qp-shadow-inset: inset 0 1px 0 rgb(255 255 255 / 0.6);

    --qp-scrim: rgb(20 22 32 / 0.34);
    --qp-skeleton: var(--qp-ink-150);
    --qp-skeleton-shine: var(--qp-ink-100);
    --qp-selection: color-mix(in oklab, var(--qp-iris-500) 22%, transparent);
    --qp-scrollbar: var(--qp-ink-300);
    --qp-scrollbar-hover: var(--qp-ink-400);
    --qp-code-bg: var(--qp-ink-100);
}

/* ============================================================================
   Semantic layer — DARK
   ========================================================================= */
:root[data-theme="dark"] {
    color-scheme: dark;

    --qp-canvas: #0e0f14;
    --qp-surface: #16171d;
    --qp-surface-sunken: #111218;
    --qp-surface-raised: #1b1d25;
    --qp-surface-overlay: #1e2029;
    --qp-surface-hover: color-mix(in oklab, #ffffff 6%, transparent);
    --qp-surface-active: color-mix(in oklab, #ffffff 10%, transparent);
    --qp-surface-selected: color-mix(in oklab, var(--qp-iris-light) 16%, transparent);
    --qp-sidebar-bg: #111218;

    --qp-text: #e6e7ee;
    --qp-text-strong: #f6f7fa;
    /* faint was 3.59:1 on the base surface and 3.25:1 on the overlay — below the 4.5:1 floor, and the
       overlay is exactly where it was used most (the command palette's group headings and hints).
       Raising it alone left it ΔL* 1.6 from subtle, which is the same colour twice: the palette's
       headings and its hints became indistinguishable. All three move up together instead, so the
       floor is met and the steps stay visible — measured on surface, raised and overlay:

         muted  #aeb2c2  8.47 / 7.96 / 7.69   ΔL* 19.0 from text
         subtle #979bab  6.46 / 6.08 / 5.87   ΔL*  8.6 from muted
         faint  #82869a  4.96 / 4.66 / 4.50   ΔL*  7.9 from subtle

       …and then a sweep with a real run in it found the same mistake one level up: surface, raised and
       overlay are not the darkest things these sit on. A selected result row is #292a40, a failed step's
       strip is #3e2327, a table row on the sunken panel is #24252b, and faint read 3.88–4.24 on all
       three. Measured against every surface and tint in this file, the worst case is what the floor has
       to clear, so the ramp moves up again and keeps its spacing:

         muted  #babdcb  9.56 on surface, 7.49 at worst   ΔL* 15.0 from text
         subtle #a4a8b6  7.54 on surface, 5.91 at worst   ΔL*  7.8 from muted
         faint  #9093a5  5.88 on surface, 4.60 at worst   ΔL*  7.8 from subtle */
    --qp-text-muted: #babdcb;
    --qp-text-subtle: #a4a8b6;
    --qp-text-faint: #9093a5;
    --qp-text-on-accent: #0d0e13;
    --qp-text-inverse: var(--qp-ink-900);

    --qp-border: #282b36;
    --qp-border-subtle: #212430;
    --qp-border-strong: #383c4a;
    --qp-border-field: #3a3e4d;
    --qp-field-bg: #101117;

    --qp-accent: var(--qp-iris-light);
    --qp-accent-hover: #a2a2f8;
    --qp-accent-active: #b4b4fa;
    --qp-accent-subtle: color-mix(in oklab, var(--qp-iris-light) 14%, var(--qp-surface));
    --qp-accent-subtle-hover: color-mix(in oklab, var(--qp-iris-light) 22%, var(--qp-surface));
    --qp-accent-border: color-mix(in oklab, var(--qp-iris-light) 34%, transparent);
    --qp-accent-text: #aeaef8;
    --qp-focus-ring: var(--qp-iris-light);

    --qp-pass: #45cc8b;
    --qp-pass-bg: color-mix(in oklab, #1f9d60 20%, var(--qp-surface));
    --qp-pass-border: color-mix(in oklab, #1f9d60 40%, transparent);
    --qp-fail: #ff7b80;
    --qp-fail-bg: color-mix(in oklab, #dc3d43 22%, var(--qp-surface));
    --qp-fail-border: color-mix(in oklab, #dc3d43 42%, transparent);
    --qp-warn: #f0a94f;
    --qp-warn-bg: color-mix(in oklab, #d9822b 22%, var(--qp-surface));
    --qp-warn-border: color-mix(in oklab, #d9822b 42%, transparent);
    --qp-info: #6aa9f2;
    --qp-info-bg: color-mix(in oklab, #2f7de1 22%, var(--qp-surface));
    --qp-info-border: color-mix(in oklab, #2f7de1 42%, transparent);
    --qp-neutral: var(--qp-text-muted);
    --qp-neutral-bg: color-mix(in oklab, #ffffff 7%, transparent);
    --qp-neutral-border: var(--qp-border);
    --qp-prod: #f08064;
    --qp-prod-bg: color-mix(in oklab, #b4371e 26%, var(--qp-surface));
    --qp-prod-border: color-mix(in oklab, #b4371e 48%, transparent);

    --qp-shadow-1: 0 1px 2px rgb(0 0 0 / 0.4);
    --qp-shadow-2: 0 2px 6px rgb(0 0 0 / 0.42), 0 8px 20px -6px rgb(0 0 0 / 0.5);
    --qp-shadow-3: 0 6px 14px -6px rgb(0 0 0 / 0.5), 0 24px 56px -12px rgb(0 0 0 / 0.64);
    --qp-shadow-inset: inset 0 1px 0 rgb(255 255 255 / 0.04);

    --qp-scrim: rgb(4 5 8 / 0.62);
    --qp-skeleton: #23252f;
    --qp-skeleton-shine: #2b2e3a;
    --qp-selection: color-mix(in oklab, var(--qp-iris-light) 30%, transparent);
    --qp-scrollbar: #3a3e4d;
    --qp-scrollbar-hover: #4a4f61;
    --qp-code-bg: #1b1d25;
}
