/* ===================================================================
   GFSEP — Wave 4.1 design tokens
   OWNER: Agent 4.1A. This file is the single source of truth for the
   theme. Other Wave 4.1 agents CONSUME these tokens; do not redefine
   a token here in another file, and do not hardcode a hex that a
   token already covers.

   Provenance labels used below:
     [Stated]   the original designer's own style-guide frame, or a value
                handed down verbatim by the coordinator. Authoritative.
     [Spec]     docs/wave41-ui-theme-spec.md — ratio-estimated from a
                half-scale JPEG. Directionally right, not measured.
     [Derived]  chosen by Agent A because the source was silent or the
                stated value failed an accessibility check. Every one of
                these carries its reasoning inline.

   All contrast ratios in the comments were COMPUTED (WCAG 2.1 relative
   luminance), not estimated. AA thresholds: 4.5:1 body, 3:1 large text
   (>=18.66px bold / >=24px regular) and non-text UI boundaries.
   =================================================================== */

:root {
    /* ---------------------------------------------------------------
       1. SURFACES
       A four-step scale. Every step above --bg-surface is a white
       overlay on the stated #221F20, so the family stays warm-neutral.
       --------------------------------------------------------------- */
    --bg-base: #090607;                 /* [Stated] page background */
    --bg-surface: #221F20;              /* [Stated] cards, panels, assistant bubbles, inputs */

    /* [Derived] 5% white over #221F20 (midpoint of the 4-6% band the
       coordinator specified; 4% => #2B2829, 6% => #2F2C2D). Used for
       hover states on --bg-surface and for raised rows inside a panel. */
    --bg-raised: #2D2A2B;

    /* [Derived] 8% white over #221F20. Lands exactly on the #343132
       target the coordinator gave for "one step further raised".
       Used for popovers, menus, tooltips, and hover-on-raised. */
    --bg-overlay: #343132;

    /* [Derived] Accent-tinted selection/active backgrounds. GFSEP's
       established idiom is rgba(accent,.12-.16) behind active nav items;
       these preserve it at the new hue.
       16% #AC1ED6 over --bg-base == #230A28; --text-primary on it = 16.33:1. */
    --accent-tint: rgba(172, 30, 214, .16);
    --accent-tint-strong: rgba(172, 30, 214, .24);

    /* [Derived] Scrim behind modals/drawers. */
    --bg-scrim: rgba(9, 6, 7, .72);

    /* ---------------------------------------------------------------
       2. ACCENT
       --------------------------------------------------------------- */
    --accent-primary: #AC1ED6;          /* [Stated] primary purple — FILLS ONLY (see --accent-text) */
    --accent-rose: #C26E73;             /* [Stated] dusty rose — gradient stop / decorative only */
    --accent-highlight: #F4F1F2;        /* [Stated] pale highlight */

    /* [Derived] #AC1ED6 mixed 10% toward --accent-highlight.
       Hover fill for primary buttons. White on it = 4.78:1 (AA body). */
    --accent-hover: #B333D9;

    /* [Derived] #AC1ED6 * 0.84. Pressed/active fill.
       White on it = 7.04:1. */
    --accent-active: #9019B4;

    /* [Derived] *** READ THIS ONE. ***
       #AC1ED6 as TEXT fails AA everywhere: 3.76:1 on --bg-base,
       3.04:1 on --bg-surface, 2.65:1 on --bg-raised, 2.40:1 on
       --bg-overlay. It is a fill colour, not a foreground colour.
       --accent-text is a 50/50 mix of --accent-primary and
       --accent-highlight and passes AA body on all four surfaces:
       8.00 / 6.48 / 5.63 / 5.10. Use this for links, active tab
       labels, accent icons and any accent-coloured glyph. */
    --accent-text: #D088E4;

    /* [Derived] 1px accent hairline for borders / focus-adjacent chrome
       where the accent must read as accent, not as text. */
    --accent-border: #AC1ED6;

    /* ---------------------------------------------------------------
       3. GRADIENTS
       Two gradients, and they are NOT interchangeable.
       --------------------------------------------------------------- */

    /* [Stated] ACCESSIBILITY-CORRECTED. This is the default for user
       message bubbles and for any gradient that carries body text.
       #FFFFFF on the stops = 4.80 / 4.72 / 5.37:1 — AA body throughout.
       Note --text-primary (#F4F1F2) does NOT clear AA on this gradient
       (4.27 / 4.21 / 4.78) — text on it must be --text-on-accent. */
    --grad-user-bubble: linear-gradient(100deg, #A55E62 0%, #BE4884 45%, #AC1ED6 100%);

    /* [Spec] The ORIGINAL, brighter mockup gradient (rose -> bright
       magenta -> purple).
       *** DECORATIVE ONLY. NEVER PUT BODY TEXT ON THIS. ***
       #FFFFFF on its stops = 3.64 / 3.53 / 5.37:1 — the first two stops
       fail AA body and only just clear the 3:1 large-text floor.
       Legitimate uses: hero wash, avatar/sparkle fills, the orb fallback,
       icon fills, 1-2px rules. Illegitimate: message bubbles, buttons
       with labels, badges with numbers. */
    /* 4.1E2: the mid stop was the bright transitional magenta that exists ONLY
       inside the orb's vertex shader (see C_MAG in js/ai-orb-shader.js). That
       value is barred from every .css file and from every design token, so it
       is not spelled out here either — a grep for it across CSS must come back
       empty, and a comment quoting it would defeat that.
       It is now #BE4884, the same mid stop --grad-user-bubble already uses, so
       the two gradients share a hue. This token has no consumers — verified
       with `grep -rn "grad-decorative" src/`, whose only other hit is a comment
       in css/ai-orb.css — so nothing renders differently. */
    --grad-decorative: linear-gradient(100deg, #C26E73 0%, #BE4884 45%, #AC1ED6 100%);

    /* [Spec] Ambient magenta wash bleeding from the top edge. Decorative.
       4.1E2: the first stop was the SAME barred shader-internal magenta as
       --grad-decorative above, written in decimal rgba() instead of hex — the
       identical colour, just invisible to a grep for the hex. That is the only
       reason it survived 4.1A's audit. It is now rgb(190, 72, 132) = #BE4884.
       Also currently unconsumed (`grep -rn "grad-glow" src/` hits only this
       file), so nothing renders differently today; if it is adopted later the
       wash is very slightly less pink. 55% alpha, carries no text. */
    --grad-glow: radial-gradient(120% 90% at 60% 0%,
            rgba(190, 72, 132, .55) 0%, rgba(172, 30, 214, .28) 40%, transparent 75%);

    /* [Derived] Login page backdrop — replaces the amber-era
       radial-gradient(circle at 30% 20%, #2A2320 ...). #1D0920 is 12%
       --accent-primary over --bg-base. --text-primary on it = 16.82:1. */
    --grad-auth-backdrop: radial-gradient(circle at 30% 20%, #1D0920 0%, var(--bg-base) 60%);

    /* ---------------------------------------------------------------
       4. TEXT
       Every value here was contrast-checked against ALL FOUR surfaces,
       not just --bg-base. Worst-case ratio is quoted.
       --------------------------------------------------------------- */
    --text-primary: #F4F1F2;            /* [Stated] worst case 11.47:1 (on --bg-overlay). AA/AAA */

    /* [Derived] The spec's eyeballed #9B9598 fails AA on --bg-overlay
       (4.38:1). #A8A2A5 is the existing amber-era --text-secondary
       (#A8A29E) hue-rotated off its green cast into the magenta family,
       and clears AA on every surface: 8.05 / 6.52 / 5.67 / 5.13. */
    --text-secondary: #A8A2A5;

    /* [Derived] Deliberately sub-AA-body. Worst case 3.18:1, so this is
       LARGE-TEXT / NON-ESSENTIAL METADATA ONLY (timestamps, disabled
       labels, decorative counts). If the string matters, use
       --text-secondary. Enforced nowhere; this comment is the contract. */
    --text-muted: #827D7F;

    /* [Derived] MUST be pure white, not --text-primary. On the corrected
       bubble gradient #F4F1F2 measures 4.21-4.78:1 (fails at two of the
       three stops) while #FFFFFF measures 4.72-5.37:1 (passes at all
       three). The 3-point luminance difference is the whole margin. */
    --text-on-accent: #FFFFFF;

    --text-inverse: #090607;            /* [Derived] for the rare light-surface case */

    /* ---------------------------------------------------------------
       5. BORDERS — four roles, four tokens. Pick by ROLE, not by taste.
       --------------------------------------------------------------- */

    /* Role 1: separators inside a list or table. The faintest line in
       the system. Non-interactive, so WCAG 1.4.11 does not apply.
       [Derived] 8% --text-primary; composites to ~1.16-1.26:1. */
    --border-divider: rgba(244, 241, 242, .08);

    /* Role 2: the outer edge of a card, panel, bubble or chip. Slightly
       stronger than a divider so a panel reads as an object. Still
       non-interactive. [Derived] 14% --text-primary; ~1.36-1.52:1. */
    --border-subtle: rgba(244, 241, 242, .14);

    /* Role 3: the boundary of an INTERACTIVE control — text inputs,
       selects, textareas, ghost/outline buttons, toggles.
       *** This one is load-bearing for accessibility. ***
       WCAG 1.4.11 wants 3:1 between a control's boundary and its
       adjacent colour. A translucent hairline cannot reach that on this
       palette at any alpha you would actually ship (0.36 alpha white is
       still only 3.23:1 on --bg-base and looks like a box, not a
       hairline). So this role gets a solid value:
       #6E6B6D vs --bg-surface (the input fill) = 3.10:1. PASSES.
       Do not swap it for --border-subtle to make a form look prettier. */
    --border-control: #6E6B6D;

    /* Role 4: the focus indicator. See --focus-ring / :focus-visible below.
       [Stated] #F4F1F2 measures 17.98 / 14.56 / 12.66 / 11.47:1 against
       the four surfaces and 4.78:1 against --accent-primary, so a single
       ring colour works on every background in the app. */
    --border-focus: #F4F1F2;

    /* [Derived] hover/active border for controls. */
    --border-control-hover: var(--accent-border);

    --border-width: 1px;

    /* ---------------------------------------------------------------
       6. SEMANTIC (status) — [Stated] all four.
       All clear AA body on all four surfaces:
         success 11.04/8.94/7.78/7.04 · warning 12.84/10.40/9.04/8.19
         error    8.07/6.54/5.69/5.15 · info     9.39/7.61/6.61/5.99
       --------------------------------------------------------------- */
    --success: #5FD68D;
    --warning: #F4C95D;
    --error: #FF7A8A;
    --info: #6CB6FF;
    --neutral: #827D7F;                 /* [Derived] "unknown"/offline status, == --text-muted */

    /* [Derived] 12% tints for banner/row backgrounds. The matching
       semantic colour on its own tint stays >= 7:1. */
    --success-tint: rgba(95, 214, 141, .12);
    --warning-tint: rgba(244, 201, 93, .12);
    --error-tint: rgba(255, 122, 138, .12);
    --info-tint: rgba(108, 182, 255, .12);

    /* ---------------------------------------------------------------
       7. RADII — [Stated] scale, named by ROLE so the intent survives.
       --------------------------------------------------------------- */
    --r-chip: 8px;                      /* chips, tags, small icon tiles, code spans */
    --r-control: 10px;                  /* buttons, inputs, selects, menu items */
    --r-panel: 12px;                    /* panels, table cards, toolbars */
    --r-card: 16px;                     /* cards, modals, login card */
    --r-bubble: 20px;                   /* chat message bubbles */
    --r-pill: 999px;                    /* pills, toggles, the composer, FAB */
    --r-circle: 50%;                    /* [Derived] avatars, status dots, spinners */

    /* ---------------------------------------------------------------
       8. SPACING — [Spec] 4px base rhythm.
       --------------------------------------------------------------- */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;                       /* default gutter */
    --sp-5: 20px;
    --sp-6: 24px;
    --sp-8: 32px;
    --sp-10: 40px;                      /* [Derived] extends the scale for desktop layouts */
    --sp-12: 48px;                      /* [Derived] */
    --sp-16: 64px;                      /* [Derived] */

    /* ---------------------------------------------------------------
       9. TYPOGRAPHY
       [Stated] the typeface is Epilogue (Google Fonts, OFL). Wired in
       Components/App.razor. Weights loaded: 400 500 600 700 800.
       --------------------------------------------------------------- */
    --font-sans: 'Epilogue', system-ui, -apple-system, 'Segoe UI', sans-serif;
    /* [Derived] no mono face appears in the source design; GFSEP needs
       one for code, IDs and metric readouts. Keeping the incumbent. */
    --font-mono: 'JetBrains Mono', 'Fira Code', 'Source Code Pro', monospace;

    /* Sizes. [Spec] values are ratio-derived from a half-scale mobile
       raster — treat as a starting scale, not measurements. */
    --fs-display: 28px;                 /* [Spec] hero / empty-state heading */
    --fs-h1: 20px;                      /* [Spec] page + section heading */
    --fs-h2: 17px;                      /* [Spec] card / panel heading */
    --fs-h3: 15px;                      /* [Derived] the source has no third heading level;
                                           GFSEP's admin pages need one. */
    --fs-body: 15px;                    /* [Spec] and it matches GFSEP's current body size,
                                           so nothing reflows on adoption. */
    --fs-sm: 13px;                      /* [Spec] secondary / placeholder / dense table */
    --fs-xs: 11px;                      /* [Spec] metadata, uppercase labels */

    /* [Derived] the spec puts chat copy at 13px. That is a 393pt phone
       value. GFSEP reads chat in a 780px desktop column and 13px would
       be a readability regression against today's 15px. Committing to
       body size for message copy. */
    --fs-msg: 15px;

    /* Weights. [Spec] only "bold vs regular" is separable in the source;
       the mid weights are [Derived] to give a usable ramp. */
    --fw-regular: 400;
    --fw-medium: 500;
    --fw-semibold: 600;
    --fw-bold: 700;
    --fw-display: 700;

    /* Line heights. */
    --lh-tight: 1.15;                   /* [Spec] display headings */
    --lh-heading: 1.3;                  /* [Derived] h1-h3 */
    --lh-body: 1.45;                    /* [Spec] */
    --lh-relaxed: 1.6;                  /* [Derived] matches GFSEP's current .msg-content */

    --tracking-caps: .5px;              /* [Derived] uppercase micro-labels */

    /* ---------------------------------------------------------------
       10. ELEVATION — [Derived], all of it.
       The spec is explicit that shadows are NOT determinable from the
       source (a composited 3D phone render on a lit backdrop). These are
       deliberately conservative and reuse GFSEP's existing login-card
       shadow so nothing jumps.
       --------------------------------------------------------------- */
    --shadow-none: none;
    --shadow-panel: 0 2px 8px rgba(0, 0, 0, .35);
    --shadow-raised: 0 6px 20px rgba(0, 0, 0, .45);
    --shadow-modal: 0 12px 48px rgba(0, 0, 0, .55);
    --shadow-accent-glow: 0 8px 28px rgba(172, 30, 214, .30);  /* [Spec] primary CTA / FAB only */

    /* ---------------------------------------------------------------
       11. MOTION — [Derived], all of it. Nothing is observable in a
       static image. Generic, non-bouncy defaults.
       --------------------------------------------------------------- */
    --ease-standard: cubic-bezier(.4, 0, .2, 1);
    --ease-out: cubic-bezier(0, 0, .2, 1);
    --ease-in: cubic-bezier(.4, 0, 1, 1);
    --dur-fast: 150ms;
    --dur-base: 220ms;
    --dur-slow: 400ms;

    /* ---------------------------------------------------------------
       12. FOCUS — [Stated] mixin.
       Two-ring construction: a 2px --bg-base halo punches the indicator
       away from whatever it sits on, then a 2px --border-focus ring
       carries the contrast. Works on every surface AND on the accent
       (ring vs --accent-primary = 4.78:1), which a single-colour ring
       would not.
       --------------------------------------------------------------- */
    --focus-ring: 0 0 0 2px #090607, 0 0 0 4px #f4f1f2;
    --focus-ring-offset: 2px;

    /* ---------------------------------------------------------------
       13. LAYOUT + Z — [Derived] from GFSEP's existing shell.
       --------------------------------------------------------------- */
    --topbar-h: 56px;
    --sidebar-w: 260px;
    --content-max: 1100px;
    --chat-col-max: 780px;
    --bubble-max: 78%;                  /* [Spec] */

    --z-base: 0;
    --z-sidebar: 20;
    --z-sticky: 40;
    --z-overlay: 60;
    --z-toast: 80;
    --z-error: 1000;                    /* matches #blazor-error-ui */
}

/* ===================================================================
   Global focus treatment. [Stated] — applies app-wide, so no component
   has to remember it. Components that need the ring on a non-focus
   trigger can compose box-shadow: var(--focus-ring).
   =================================================================== */
:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px #090607, 0 0 0 4px #f4f1f2;
}

/* [Derived] Respect the OS reduced-motion preference. Not in the source
   design (a static image has no motion design at all), but shipping
   animation without this is a WCAG 2.3.3 / vestibular problem. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --dur-fast: 0ms;
        --dur-base: 0ms;
        --dur-slow: 0ms;
    }

    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}
