/*
 * Meridian design tokens — authoritative source per ADR-026.
 * Translated 1:1 from docs/ux/claude-design/theme-v2.js.
 * Light is the default under :root; dark overrides via [data-theme="dark"].
 * The inline script in App.razor resolves system preference before this file loads.
 */

/* -------- Fonts (self-hosted; no remote fetches) -------------------- */

@font-face {
    font-family: 'Geist';
    src: url('/fonts/geist-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

@font-face {
    font-family: 'Geist';
    src: url('/fonts/geist-500.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

@font-face {
    font-family: 'Geist';
    src: url('/fonts/geist-600.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

@font-face {
    font-family: 'JetBrains Mono';
    src: url('/fonts/jetbrains-mono-400.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

@font-face {
    font-family: 'JetBrains Mono';
    src: url('/fonts/jetbrains-mono-500.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

/* -------- Light theme (default) ------------------------------------- */

:root {
    --meridian-bg:            #f3f5f8;
    --meridian-bg-panel:      #fafbfc;
    --meridian-bg-sunk:       #e7eaef;
    --meridian-bg-raised:     #ffffff;
    --meridian-border:        #d7dce4;
    --meridian-border-strong: #b7bfcc;
    --meridian-border-hair:   #e7eaef;

    --meridian-text:          #0e1116;
    --meridian-text-mid:      #3d4450;
    /* WCAG AA (#646 Full-AA sweep): text-dim must be ≥4.5:1 on both bg (#f3f5f8)
       and bg-sunk (#e7eaef). Prior #6c7482 was 4.31:1 on bg. #5f6675 gives
       5.28:1 on bg / 4.78:1 on bg-sunk — the least-dark AA-passing value. */
    --meridian-text-dim:      #5f6675;
    --meridian-text-faint:    #a3abb8;

    --meridian-accent:        #18b800;
    --meridian-accent-soft:   #dcf6d1;
    /* On-accent text — dark ink on the lime primary is 7.11:1 (WCAG AA pass);
       light ink was only ~2.7:1 and failed. See issue #646. */
    --meridian-accent-text:   #0e1116;
    /* I-audit fix — accent on accent-soft is 2.29:1 (fails AA). Darker
       lime-green for body-text usage. */
    --meridian-accent-strong: #0c6b00;
    /* WCAG AA (#646): white-on-pass fill (StatusChip/MudButton success) was
       4.48:1 on #108a2b — just under. #0f8527 gives white 4.77:1. */
    --meridian-pass:          #0f8527;
    --meridian-pass-soft:     #d3f3d8;
    /* I-audit fix — pass on near-white background needs 4.5:1 for WCAG AA;
       the base --meridian-pass (#108a2b) gives 4.31:1 which is below
       threshold. Darker shade for body-text usage on bg-canvas / bg-sunk. */
    --meridian-pass-strong:   #0c6b21;
    --meridian-fail:          #e01f2b;
    --meridian-fail-soft:     #fcd6d8;
    /* I-audit fix — fail on bg-sunk is 3.95:1 (just below AA). Slightly
       deeper red for body-text usage. */
    --meridian-fail-strong:   #a4181f;
    --meridian-warn:          #d97706;
    --meridian-warn-soft:     #fde6c4;
    /* I-audit fix — warn on warn-soft is 2.62:1 (fails AA badly).
       Darker amber for warn-on-warn-soft body text patterns (e.g. nav badges). */
    --meridian-warn-strong:   #8a4a02;
    --meridian-info:          #0aa8c7;
    --meridian-info-soft:     #cdeff6;
    /* I-audit fix — info on info-soft is 2.32:1 (fails AA). Darker teal
       for body-text usage. */
    --meridian-info-strong:   #056478;
    --meridian-muted:         #7a8394;
    --meridian-chip-bg:       #e7eaef;

    /* Loading-skeleton fill + shimmer band (#775). Same as bg-sunk/bg-raised —
       already a clearly visible light-grey block against the white/near-white
       panel surfaces in light theme. See dark override below for why this
       pair is dedicated rather than reusing bg-sunk/bg-raised directly. */
    --meridian-skeleton-base:    #e7eaef;
    --meridian-skeleton-shimmer: #ffffff;

    --meridian-lane-row:      rgba(14,17,22,0.015);
    --meridian-lane-row-alt:  rgba(14,17,22,0.035);

    /* Promotion-lane palette — ordered six-slot categorical set. A promotion
       lane takes the slot at its index in the project's lane list, so
       Standard/Hotfix/Express land on slots 0/1/2 by default. Hues are reused
       from the semantic set so the topology stays in-family; lane-alt-3 is the
       one new hue needed for a sixth distinct slot. lane-muted covers a lane
       past the palette, or one that is not in the project's list at all.
       Canonical source: docs/ux/claude-design/theme-v2.js. */
    --meridian-lane-standard: #0aa8c7;
    --meridian-lane-hotfix:   #e01f2b;
    --meridian-lane-express:  #8b5cf6;
    --meridian-lane-alt-1:    #d97706;
    --meridian-lane-alt-2:    #18b800;
    --meridian-lane-alt-3:    #c026d3;
    --meridian-lane-muted:    #5f6675;

    /* Environment identities */
    --env-dev:     #0aa8c7;
    --env-staging: #d97706;
    --env-prod:    #8b5cf6;
    --env-canary:  #18b800;
    --env-perf:    #e01f2b;

    /* Typography */
    --meridian-font-sans: 'Geist', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    --meridian-font-mono: 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, Consolas, monospace;

    /* Dimensions — density defaults per ADR-026 / principles §5 */
    --meridian-row-height: 34px;
    --meridian-radius:      2px;
    /* #1883 — cap for the top-bar scope popovers (project / environment / service):
       viewport minus top bar, popover offset and a bottom gutter. */
    --meridian-topbar-popover-max-height: calc(100vh - 72px);

    /* Layout density — driven by the per-user Profile preference. The default
       (compact) matches the design baseline; comfortable loosens vertical rhythm
       and table row height. Applied via [data-density] on <html> below. */
    --meridian-density-row-height:  var(--meridian-row-height);
    --meridian-density-main-pad:    24px;

    color-scheme: light;
}

/* Compact is the design baseline; declared explicitly so a saved preference of
   "compact" reverts cleanly from comfortable. */
html[data-density="compact"] {
    --meridian-density-row-height: 34px;
    --meridian-density-main-pad:   24px;
}

/* Comfortable — looser spacing for users who prefer a roomier layout. */
html[data-density="comfortable"] {
    --meridian-density-row-height: 44px;
    --meridian-density-main-pad:   36px;
}

/* Apply the density spacing to the primary page container and table rows so the
   change is visible app-wide after the preference loads. */
html[data-density] .m-main-with-status .mud-container {
    padding-top:    var(--meridian-density-main-pad);
    padding-bottom: var(--meridian-density-main-pad);
}

html[data-density] .mud-table-row {
    height: var(--meridian-density-row-height);
}

/* -------- Dark theme ------------------------------------------------- */

[data-theme="dark"] {
    --meridian-bg:            #0a0d12;
    --meridian-bg-panel:      #11151c;
    --meridian-bg-sunk:       #060809;
    --meridian-bg-raised:     #171c24;
    --meridian-border:        #242b36;
    --meridian-border-strong: #3a424f;
    --meridian-border-hair:   #1a1f27;

    --meridian-text:          #eef1f6;
    --meridian-text-mid:      #9aa3b1;
    /* WCAG AA (#646 Full-AA sweep): dark text-dim must be ≥4.5:1 on bg (#0a0d12),
       panel (#11151c) and raised (#171c24). Prior #6a7283 was 3.54–4.03:1.
       #7c8497 gives 4.56–5.36:1 — the least-light AA-passing value. */
    --meridian-text-dim:      #7c8497;
    --meridian-text-faint:    #434b59;

    --meridian-accent:        #9cff3a;
    --meridian-accent-soft:   #223a12;
    /* On-accent text — dark ink on neon lime is 15.55:1 (already passing). */
    --meridian-accent-text:   #0a0d12;
    /* Dark theme already passes AA — alias each -strong to its base token. */
    --meridian-accent-strong: #9cff3a;
    --meridian-pass:          #49e65c;
    --meridian-pass-soft:     #0e2a12;
    --meridian-pass-strong:   #49e65c;
    --meridian-fail:          #ff4757;
    --meridian-fail-soft:     #3a0f14;
    --meridian-fail-strong:   #ff4757;
    --meridian-warn:          #ffb020;
    --meridian-warn-strong:   #ffb020;
    --meridian-warn-soft:     #3a2608;
    --meridian-info:          #25d3f0;
    --meridian-info-soft:     #07323b;
    --meridian-info-strong:   #25d3f0;
    --meridian-muted:         #4a5263;
    --meridian-chip-bg:       #171c24;

    /* Loading-skeleton fill + shimmer band (#775 contrast fix). bg-sunk/bg-raised
       are both DARKER than bg-panel in dark theme (a "recessed" elevation pair),
       so a skeleton block that reused them rendered as a near-black rectangle on
       a near-black page — effectively invisible. This dedicated pair is
       deliberately lighter than bg/bg-panel/bg-raised so both the block and its
       shimmer sweep read clearly against every dark surface (>=3:1 contrast vs
       bg #0a0d12, bg-panel #11151c and bg-raised #171c24 — WCAG 1.4.11 non-text
       UI component contrast; computed relative-luminance ratios ~3.2-3.6:1).
       skeleton-base is untouched by #779 (still the #775-verified fill colour);
       skeleton-shimmer was brightened from #838da3 → #c3cbdb (#779) — the
       original value gave the moving highlight band only ~1.7x luminance over
       the base fill, reading as a barely-perceptible ripple next to light
       theme's base→white sweep (~1.25x nominal, but white pops far more on a
       light fill than a mid-tone one does on a dark fill). #c3cbdb lifts that
       to ~3.3x, closer to --meridian-text (#eef1f6) so the wave reads as
       clearly as it does in light mode without flashing pure white. */
    --meridian-skeleton-base:    #626b7f;
    --meridian-skeleton-shimmer: #c3cbdb;

    --meridian-lane-row:      rgba(255,255,255,0.015);
    --meridian-lane-row-alt:  rgba(255,255,255,0.04);

    /* Promotion-lane palette — see the light block for the slot rule. */
    --meridian-lane-standard: #25d3f0;
    --meridian-lane-hotfix:   #ff4757;
    --meridian-lane-express:  #b18cff;
    --meridian-lane-alt-1:    #ffb020;
    --meridian-lane-alt-2:    #9cff3a;
    --meridian-lane-alt-3:    #f472d0;
    --meridian-lane-muted:    #7c8497;

    --env-dev:     #25d3f0;
    --env-staging: #ffb020;
    --env-prod:    #b18cff;
    --env-canary:  #9cff3a;
    --env-perf:    #ff4757;

    color-scheme: dark;
}

/* -------- Baseline element styling --------------------------------- */

html, body {
    background: var(--meridian-bg);
    color: var(--meridian-text);
    font-family: var(--meridian-font-sans);
    font-size: 13px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

code, kbd, pre, samp {
    font-family: var(--meridian-font-mono);
}

/* Tabular numerals for numeric metrics */
.meridian-tabular,
.mud-table td.mud-table-cell-numeric,
.mud-table-cell-numeric {
    font-variant-numeric: tabular-nums;
}

/* -------- MudBlazor palette variable bridge ------------------------- */
/*
 * MudBlazor exposes its theme as CSS custom properties under --mud-palette-*.
 * We bind the subset most pages read from (backgrounds, text, surfaces,
 * borders, semantic colours) to Meridian tokens so any page that reads
 * --mud-palette-* inherits Meridian theming automatically.
 * Pages that read MudTheme.* via C# take the palette set in MeridianTheme.cs —
 * the two are kept in sync by convention (see blazor-implementation-strategy.md §1.3).
 *
 * These mappings are declared `!important` and keyed off the `data-theme`
 * attribute so they are the single authoritative source for the semantic
 * palette. MudThemeProvider emits its own `--mud-palette-*` block at runtime;
 * because that block renders into the document body it would otherwise win the
 * cascade over this head-level layer by source order. Forcing the Meridian
 * mapping keeps the palette faithful even where the provider's palette drifts
 * or is not applied (e.g. the isolated BlazingStory story-preview canvas, which
 * otherwise fell back to MudBlazor's default Material palette and to
 * default-light text on the Meridian dark background). The values are identical
 * to MeridianTheme.cs, so production rendering is unchanged; only correctness
 * and robustness improve. Driven by `data-theme`, dark-mode switching no longer
 * depends on the provider's IsDarkMode state. See issue #646 (Full-AA sweep).
 */

:root,
[data-theme="light"] {
    --mud-palette-background:           var(--meridian-bg) !important;
    --mud-palette-background-gray:      var(--meridian-bg-sunk) !important;
    --mud-palette-surface:              var(--meridian-bg-panel) !important;
    --mud-palette-drawer-background:    var(--meridian-bg-panel) !important;
    --mud-palette-drawer-text:          var(--meridian-text-mid) !important;
    --mud-palette-appbar-background:    var(--meridian-bg-panel) !important;
    --mud-palette-appbar-text:          var(--meridian-text) !important;

    --mud-palette-text-primary:         var(--meridian-text) !important;
    --mud-palette-text-secondary:       var(--meridian-text-mid) !important;
    --mud-palette-text-disabled:        var(--meridian-text-faint) !important;

    --mud-palette-lines-default:        var(--meridian-border) !important;
    --mud-palette-lines-inputs:         var(--meridian-border) !important;
    --mud-palette-divider:              var(--meridian-border-hair) !important;
    --mud-palette-divider-light:        var(--meridian-border-hair) !important;
    --mud-palette-table-lines:          var(--meridian-border-hair) !important;
    --mud-palette-table-striped:        var(--meridian-lane-row-alt) !important;
    --mud-palette-table-hover:          var(--meridian-lane-row-alt) !important;

    --mud-palette-action-default:       var(--meridian-text-mid) !important;
    --mud-palette-action-disabled:      var(--meridian-text-faint) !important;
    --mud-palette-action-disabled-background: var(--meridian-bg-sunk) !important;

    --mud-palette-primary:              var(--meridian-accent) !important;
    --mud-palette-primary-text:         var(--meridian-accent-text) !important;
    /* WCAG AA (#725): MudBlazor uses primary-hover as a SUBTLE translucent hover /
       selected *background* across tabs, text buttons, nav links, outlined/selected
       chips, treeview, list items and pagination. Mapping it to the OPAQUE accent
       turned every one of those into a solid lime block with unstyled light text
       (white-on-lime, fails AA — e.g. the user "Roles" tab). A translucent accent
       tint restores the intended wash so the existing foreground stays readable. */
    --mud-palette-primary-hover:        color-mix(in srgb, var(--meridian-accent) 15%, transparent) !important;
    --mud-palette-primary-lighten:      var(--meridian-accent-soft) !important;
    /* Secondary was unmapped, so MudBlazor fell back to its Material default
       (#ff4081 pink) — white-on-pink is 3.33:1. Mirror the primary-text pattern:
       secondary base = Meridian info cyan; on-secondary text = dark ink
       (#0e1116 on #0aa8c7 = 6.70:1; on dark #25d3f0 = 10.7:1). #646. */
    --mud-palette-secondary:            var(--meridian-info) !important;
    --mud-palette-secondary-text:       #0e1116 !important;
    --mud-palette-secondary-lighten:    var(--meridian-info-soft) !important;
    --mud-palette-success:              var(--meridian-pass) !important;
    --mud-palette-success-text:         #ffffff !important;
    --mud-palette-success-lighten:      var(--meridian-pass-soft) !important;
    --mud-palette-error:                var(--meridian-fail) !important;
    --mud-palette-error-text:           #ffffff !important;
    --mud-palette-error-lighten:        var(--meridian-fail-soft) !important;
    --mud-palette-warning:              var(--meridian-warn) !important;
    /* On-warning text: white on amber fails (3.19:1 light / worse dark). Dark
       ink passes both (#0e1116 on #d97706 = 5.94:1, on #ffb020 = 10.6:1). */
    --mud-palette-warning-text:         #0e1116 !important;
    --mud-palette-warning-lighten:      var(--meridian-warn-soft) !important;
    --mud-palette-info:                 var(--meridian-info) !important;
    /* On-info text: white on cyan fails (2.82:1). Dark ink passes both. */
    --mud-palette-info-text:            #0e1116 !important;
    --mud-palette-info-lighten:         var(--meridian-info-soft) !important;
    /* MudAlert (text variant) colours its message with the *-darken derivative,
       not the base, and MudBlazor derives those at runtime from the base — the
       Meridian info/warn bases darken to ~#098ba5 / #b36205 which still fail AA
       on the pale alert fill. Pin the darken derivatives (used only by MudBlazor
       for alert/text-utility foreground) to the AA-passing -strong tokens. #646. */
    --mud-palette-info-darken:          var(--meridian-info-strong) !important;
    --mud-palette-warning-darken:       var(--meridian-warn-strong) !important;

    --mud-default-borderradius:         var(--meridian-radius) !important;
}

/* Dark theme — mirror the full semantic mapping so the authoritative (!important)
   layer switches with `data-theme` independently of MudThemeProvider.IsDarkMode.
   The Meridian dark tokens are already resolved by the [data-theme="dark"] block
   above; here we only need to (re)assert the mud-palette bridge for dark and the
   per-theme on-fill text overrides. */
[data-theme="dark"] {
    --mud-palette-background:           var(--meridian-bg) !important;
    --mud-palette-background-gray:      var(--meridian-bg-sunk) !important;
    --mud-palette-surface:              var(--meridian-bg-panel) !important;
    --mud-palette-drawer-background:    var(--meridian-bg-panel) !important;
    --mud-palette-drawer-text:          var(--meridian-text-mid) !important;
    --mud-palette-appbar-background:    var(--meridian-bg-panel) !important;
    --mud-palette-appbar-text:          var(--meridian-text) !important;

    --mud-palette-text-primary:         var(--meridian-text) !important;
    --mud-palette-text-secondary:       var(--meridian-text-mid) !important;
    --mud-palette-text-disabled:        var(--meridian-text-faint) !important;

    --mud-palette-lines-default:        var(--meridian-border) !important;
    --mud-palette-lines-inputs:         var(--meridian-border) !important;
    --mud-palette-divider:              var(--meridian-border-hair) !important;
    --mud-palette-divider-light:        var(--meridian-border-hair) !important;
    --mud-palette-table-lines:          var(--meridian-border-hair) !important;
    --mud-palette-table-striped:        var(--meridian-lane-row-alt) !important;
    --mud-palette-table-hover:          var(--meridian-lane-row-alt) !important;

    --mud-palette-action-default:       var(--meridian-text-mid) !important;
    --mud-palette-action-disabled:      var(--meridian-text-faint) !important;
    --mud-palette-action-disabled-background: var(--meridian-bg-sunk) !important;

    --mud-palette-primary:              var(--meridian-accent) !important;
    --mud-palette-primary-text:         var(--meridian-accent-text) !important;
    /* WCAG AA (#725): MudBlazor uses primary-hover as a SUBTLE translucent hover /
       selected *background* across tabs, text buttons, nav links, outlined/selected
       chips, treeview, list items and pagination. Mapping it to the OPAQUE accent
       turned every one of those into a solid lime block with unstyled light text
       (white-on-lime, fails AA — e.g. the user "Roles" tab). A translucent accent
       tint restores the intended wash so the existing foreground stays readable. */
    --mud-palette-primary-hover:        color-mix(in srgb, var(--meridian-accent) 15%, transparent) !important;
    --mud-palette-primary-lighten:      var(--meridian-accent-soft) !important;
    --mud-palette-secondary:            var(--meridian-info) !important;
    --mud-palette-secondary-text:       #0a0d12 !important;
    --mud-palette-secondary-lighten:    var(--meridian-info-soft) !important;
    --mud-palette-success:              var(--meridian-pass) !important;
    /* success/error fills are dark-saturated in light (white text passes) but
       bright in dark (white fails, dark ink passes). */
    --mud-palette-success-text:         #0a0d12 !important; /* on #49e65c → 11.8:1 */
    --mud-palette-success-lighten:      var(--meridian-pass-soft) !important;
    --mud-palette-error:                var(--meridian-fail) !important;
    --mud-palette-error-text:           #0a0d12 !important; /* on #ff4757 → 5.83:1 */
    --mud-palette-error-lighten:        var(--meridian-fail-soft) !important;
    --mud-palette-warning:              var(--meridian-warn) !important;
    --mud-palette-warning-text:         #0a0d12 !important;
    --mud-palette-warning-lighten:      var(--meridian-warn-soft) !important;
    --mud-palette-info:                 var(--meridian-info) !important;
    --mud-palette-info-text:            #0a0d12 !important;
    --mud-palette-info-lighten:         var(--meridian-info-soft) !important;
    /* Dark: alert fills are dark tints, so the message needs a BRIGHT foreground —
       the base info/warn tokens (bright in dark) pass; -strong aliases to base in
       dark anyway. Pin the darken derivatives to the bright base. #646. */
    --mud-palette-info-darken:          var(--meridian-info) !important;
    --mud-palette-warning-darken:       var(--meridian-warn) !important;

    --mud-default-borderradius:         var(--meridian-radius) !important;
}
