/* ============================================================
   xmesh DS · _xmesh-extensions.css — non-MD3 tokens.

   Anything that has no canonical MD3 home but is needed to keep
   xmesh's voice intact lives here under the `--xm-*` namespace.
   Components may reference these alongside `--md-sys-*` tokens.
   ============================================================ */

:root {
  /* Categorical badges — HTTP method + file extension.
     These signal *category*, not severity. Not an MD3 concept. */
  --xm-method-get-bg:    oklch(0.32 0.08 220);
  --xm-method-get-ink:   oklch(0.86 0.10 220);
  --xm-method-post-bg:   oklch(0.32 0.08 145);
  --xm-method-post-ink:  oklch(0.86 0.10 145);
  --xm-method-put-bg:    oklch(0.32 0.08 70);
  --xm-method-put-ink:   oklch(0.86 0.10 70);
  --xm-method-delete-bg: oklch(0.32 0.10 25);
  --xm-method-delete-ink: oklch(0.86 0.12 25);
  --xm-method-patch-bg:  oklch(0.32 0.07 290);
  --xm-method-patch-ink: oklch(0.86 0.10 290);

  --xm-ext-yml-bg:  oklch(0.32 0.08 70);
  --xm-ext-yml-ink: oklch(0.86 0.10 70);
  --xm-ext-json-bg: oklch(0.32 0.08 145);
  --xm-ext-json-ink: oklch(0.86 0.12 145);

  /* Snackbar scrim — neutral gradient, not an MD3 concept. */
  --xm-snackbar-scrim-strong: oklch(0 0 0 / 0.42);
  --xm-snackbar-scrim:        oklch(0 0 0 / 0.32);
  --xm-snackbar-scrim-soft:   oklch(0 0 0 / 0.18);

  /* Alert severity palette — categorical exception to the "no hue for
     severity" rule. The original rule (POLICIES.md 3a) assumed icon +
     copy alone could carry severity, but inline alerts also need to be
     scannable at a glance in long content surfaces, so we tint the bg /
     border / ink per severity. Hues align with --xm-method-* (blue 220
     / green 145 / amber 70 / red 25) so the categorical palettes stay
     coherent. Chroma stays low so the surface still reads as chrome,
     not as content. Dark-theme values use a dim, desaturated tint;
     light-theme values use a pale wash on the cream canvas. */
  --xm-alert-info-bg:     oklch(0.27 0.05 235);
  --xm-alert-info-border: oklch(0.42 0.08 235);
  --xm-alert-info-ink:    oklch(0.92 0.06 235);
  --xm-alert-info-chip:   oklch(0.42 0.10 235);

  --xm-alert-success-bg:     oklch(0.27 0.05 150);
  --xm-alert-success-border: oklch(0.42 0.08 150);
  --xm-alert-success-ink:    oklch(0.92 0.08 150);
  --xm-alert-success-chip:   oklch(0.42 0.10 150);

  --xm-alert-warning-bg:     oklch(0.28 0.06 75);
  --xm-alert-warning-border: oklch(0.46 0.10 75);
  --xm-alert-warning-ink:    oklch(0.94 0.10 90);
  --xm-alert-warning-chip:   oklch(0.46 0.12 75);

  --xm-alert-critical-bg:     oklch(0.28 0.07 25);
  --xm-alert-critical-border: oklch(0.48 0.13 25);
  --xm-alert-critical-ink:    oklch(0.94 0.08 30);
  --xm-alert-critical-chip:   oklch(0.48 0.16 25);

  /* Photo overlay (image artifact backdrop) */
  --xm-photo-overlay:     oklch(0 0 0 / 0.5);
  --xm-photo-overlay-ink: var(--x-ink-canvas-0);

  /* Paper artboard — warm cream sheet for previews */
  --xm-color-paper: var(--x-paper);

  /* On-surface fourth tier — MD3 only ships on-surface + variant.
     xmesh's old --c-text-canvas-soft (very faint metadata) lives
     here as the third soft tier. */
  --xm-color-on-surface-soft: var(--x-ink-canvas-3);

  /* Inverse on-surface third tier (muted metadata on the card stack).
     The card stack is theme-following (ADR 0006): in dark theme the card
     is dark, so this muted tier is a LIGHT ink; light theme keeps the
     dark muted ink (overridden in the light block below). */
  --xm-color-inverse-on-surface-muted: var(--x-ink-canvas-2);

  /* Pressed-primary tint — MD3 prescribes a state-layer overlay,
     but a few callsites need a specific darker primary value. */
  --xm-color-primary-pressed: var(--x-accent-strong);

  /* Primary FILL — the resting coral background for filled CTAs.
     --md-sys-color-primary (L~0.64) doubles as accent *text* on the dark
     canvas, where it must stay light enough to read; as a button *fill*
     behind white ink that same tone only reaches 3.5:1. This token splits
     the fill role off at a darker tone so white-on-fill clears WCAG AA
     (5.1:1) without darkening accent-as-text. AA-validated by
     scripts/check-contrast.mjs. */
  --xm-color-primary-fill: oklch(0.55 0.115 40);

  /* Disabled inks — MD3 has no disabled-text role; it prescribes an opacity
     overlay, which dims ink AND surface together and crushes contrast below
     AA (the foot-gun these replace). These are pre-darkened/lightened so the
     disabled label still clears 4.5:1 on its host family. Components set
     `color:` to one of these instead of `opacity:` on the whole control.
       *-on-surface-disabled         → on the dark canvas / surface family
       *-inverse-on-surface-disabled → on the card stack (inverse-surface);
          a light dimmed ink in dark theme (dark card), dark in light. */
  --xm-color-on-surface-disabled:         oklch(0.66 0.01 60);
  --xm-color-inverse-on-surface-disabled: oklch(0.72 0.01 60);

  /* Disabled filled-container fill — for filled controls (primary button,
     filled chips) so the whole element no longer gets dimmed by opacity.
     A muted neutral the disabled ink above is validated against (canvas-1
     gives the on-surface-disabled ink ~5.1:1 of headroom). */
  --xm-state-disabled-container: var(--x-canvas-1);

  /* Bubble border — outline-variant doesn't quite read on the
     bubble surface; this is a slightly stronger hairline. */
  --xm-color-bubble-outline: oklch(0.34 0.006 60);

  /* Mono typescale — JetBrains Mono. Not an MD3 concept. */
  --xm-typescale-mono-font:        var(--t-family-mono);
  --xm-typescale-mono-size:        13px;
  --xm-typescale-mono-line-height: 1.5;
  --xm-typescale-mono-tracking:    0;
  --xm-typescale-mono-weight:      400;

  /* Dense data surface — the grid family's own type ramp. A data grid is a
     denser reading context than the rest of the library: rows carry more
     figures per line and the eye scans columns, not prose. MD3 has no such
     tier, so these are xmesh extensions rather than typescale overrides, and
     they are referenced only by xm-data-table / xm-data-grid. */
  --xm-typescale-grid-cell-font:             var(--t-family-ui);
  --xm-typescale-grid-cell-size:             14px;
  --xm-typescale-grid-cell-line-height:      22px;
  --xm-typescale-grid-cell-weight:           400;

  --xm-typescale-grid-mono-font:             var(--t-family-mono);
  --xm-typescale-grid-mono-size:             13.5px;
  --xm-typescale-grid-mono-line-height:      22px;
  --xm-typescale-grid-mono-weight:           400;

  --xm-typescale-grid-header-font:           var(--t-family-ui);
  --xm-typescale-grid-header-size:           13px;
  --xm-typescale-grid-header-line-height:    18px;
  --xm-typescale-grid-header-weight:         600;

  --xm-typescale-grid-totals-font:           var(--t-family-mono);
  --xm-typescale-grid-totals-size:           13px;
  --xm-typescale-grid-totals-line-height:    20px;
  --xm-typescale-grid-totals-weight:         600;

  --xm-typescale-grid-band-font:             var(--t-family-mono);
  --xm-typescale-grid-band-size:             10px;
  --xm-typescale-grid-band-line-height:      30px;
  --xm-typescale-grid-band-tracking:         0.14em;
  --xm-typescale-grid-band-weight:           500;

  --xm-typescale-grid-control-font:          var(--t-family-ui);
  --xm-typescale-grid-control-size:          11px;
  --xm-typescale-grid-control-line-height:   1;
  --xm-typescale-grid-control-weight:        500;

  /* Dense corner ramp — the shape scale jumps straight from `none` (0) to
     `extra-small` (6px), which is too coarse for chrome measured in tens of
     pixels: a 17px twisty and a 20px toolbar button need a corner that reads
     as a corner. Additive; the MD3 shape tokens are untouched. */
  --xm-shape-corner-hairline:  1px;
  --xm-shape-corner-dense-xs:  2px;
  --xm-shape-corner-dense-sm:  3px;
  --xm-shape-corner-dense-md:  4px;
  --xm-shape-corner-dense-lg:  5px;

  /* Wordmark — display family at button size, weight 500, lh 1 */
  --xm-typescale-wordmark-font:        var(--t-family-display);
  --xm-typescale-wordmark-size:        18px;
  --xm-typescale-wordmark-line-height: 1;
  --xm-typescale-wordmark-tracking:    -0.01em;
  --xm-typescale-wordmark-weight:      500;

  /* Drawer directional shadow — has no MD3 home (MD3 elevation
     levels are non-directional). */
  --xm-elevation-drawer: -16px 0 40px oklch(0 0 0 / 0.35);

  /* Snackbar inner highlight rim + composite shadow */
  --xm-elevation-snackbar:
    0 1px 0 oklch(1 0 0 / 0.04) inset,
    0 18px 40px oklch(0 0 0 / 0.32),
    0 4px 10px oklch(0 0 0 / 0.18);

  /* Pressed inset (button :active feel — kept as canonical xmesh) */
  --xm-elevation-pressed:      inset 0 1px 0 oklch(0 0 0 / 0.10);
  --xm-elevation-pressed-soft: inset 0 1px 0 oklch(0 0 0 / 0.08);

  /* Focus ring — MD3 doesn't standardise the box-shadow form */
  --xm-state-focus-ring: 0 0 0 1px var(--md-sys-color-primary-container);

  /* Switch (xm-switch) — MD3 ships no switch role tokens, so the off-track fill
     and the thumb shadow live here (AD-10). On-track is the coral primary role;
     the off-track is a muted neutral that reads on the inverse-surface card and
     gives the (dark, off-state) thumb something to sit on. The thumb itself
     uses MD3 roles directly: outline ink when off (on the off-track), on-primary
     when on (on the coral track). */
  --xm-switch-track-off:    var(--x-surface-5);
  --xm-switch-thumb-shadow: 0 1px 2px oklch(0 0 0 / 0.3);

  /* Slider (xm-slider) — MD3 ships no slider role tokens. The active fill +
     thumb are the coral primary role; these are the sub-values with no MD3 home
     (AD-10): the inactive (unfilled) track color, plus the track height and
     thumb size geometry. The slider rides the inverse-surface card tier, so the
     inactive track is a muted neutral that reads on the card. */
  --xm-slider-track-inactive: var(--x-surface-5);
  --xm-slider-track-height:   4px;
  --xm-slider-thumb-size:     16px;
  --xm-slider-thumb-shadow:   0 1px 2px oklch(0 0 0 / 0.3);

  /* Overlay stacking tier (AD-5a) — fixed order, not open-order luck:
     tooltip < menu/select-listbox < dialog. The native top layer already
     gives last-opened-wins within one primitive class; these z-index values
     order the NON-modal popovers among themselves (a menu sits above a
     tooltip). Modal <dialog>s ride the native top layer above every popover
     by spec, which matches `dialog` being the highest tier. A Floating-UI-
     positioned escape-hatch overlay reuses these values — it must NOT invent
     its own z-index. */
  --xm-overlay-z-tooltip: 1000;
  --xm-overlay-z-menu:    1100;
  --xm-overlay-z-dialog:  1200;
}

:root[data-theme="light"] {
  /* Categorical badges in cream theme */
  --xm-method-get-bg:    oklch(0.94 0.07 220); --xm-method-get-ink:    oklch(0.36 0.10 220);
  --xm-method-post-bg:   oklch(0.94 0.07 145); --xm-method-post-ink:   oklch(0.36 0.10 145);
  --xm-method-put-bg:    oklch(0.94 0.07 70);  --xm-method-put-ink:    oklch(0.36 0.10 70);
  --xm-method-delete-bg: oklch(0.94 0.07 25);  --xm-method-delete-ink: oklch(0.40 0.12 25);
  --xm-method-patch-bg:  oklch(0.94 0.06 290); --xm-method-patch-ink:  oklch(0.38 0.10 290);

  --xm-ext-yml-bg:  oklch(0.92 0.08 70);  --xm-ext-yml-ink:  oklch(0.40 0.10 70);
  --xm-ext-json-bg: oklch(0.92 0.08 145); --xm-ext-json-ink: oklch(0.38 0.12 145);

  --xm-snackbar-scrim-strong: oklch(0.40 0.01 60 / 0.28);
  --xm-snackbar-scrim:        oklch(0.40 0.01 60 / 0.18);
  --xm-snackbar-scrim-soft:   oklch(0.40 0.01 60 / 0.08);

  /* Alert palette — cream-theme washes. Backgrounds sit slightly
     above the cream canvas; ink is the deep version of the hue so it
     reads on the pale tint. */
  --xm-alert-info-bg:     oklch(0.94 0.04 235);
  --xm-alert-info-border: oklch(0.82 0.07 235);
  --xm-alert-info-ink:    oklch(0.34 0.10 235);
  --xm-alert-info-chip:   oklch(0.78 0.08 235);

  --xm-alert-success-bg:     oklch(0.94 0.05 150);
  --xm-alert-success-border: oklch(0.80 0.09 150);
  --xm-alert-success-ink:    oklch(0.34 0.10 150);
  --xm-alert-success-chip:   oklch(0.78 0.10 150);

  --xm-alert-warning-bg:     oklch(0.95 0.06 85);
  --xm-alert-warning-border: oklch(0.80 0.10 75);
  --xm-alert-warning-ink:    oklch(0.36 0.10 60);
  --xm-alert-warning-chip:   oklch(0.78 0.12 75);

  --xm-alert-critical-bg:     oklch(0.95 0.04 25);
  --xm-alert-critical-border: oklch(0.80 0.10 25);
  --xm-alert-critical-ink:    oklch(0.38 0.14 25);
  --xm-alert-critical-chip:   oklch(0.78 0.13 25);

  --xm-photo-overlay:     oklch(1 0 0 / 0.7);
  --xm-photo-overlay-ink: oklch(0.22 0.01 60);

  --xm-color-bubble-outline: oklch(0.86 0.014 85);

  /* Card stack stays white in light theme — muted metadata is a dark ink. */
  --xm-color-inverse-on-surface-muted: var(--x-ink-3);

  /* Primary fill — light theme accent is already deep (L0.62); the fill role
     drops to the strong tone so white ink clears AA on the cream canvas. */
  --xm-color-primary-fill: oklch(0.50 0.115 38);

  /* Disabled inks — dark ink on the cream canvas / white card. */
  --xm-color-on-surface-disabled:         oklch(0.45 0.01 60);
  --xm-color-inverse-on-surface-disabled: oklch(0.46 0.01 60);

  --xm-state-disabled-container: var(--x-canvas-3);
}
