/* =============================================================================================
   SalX.UI — design tokens
   ---------------------------------------------------------------------------------------------
   Three layers (docs/design-system/PLAN.md, Part 2):

     Layer 1  ramps      --sx-blue-600, --sx-gray-900 …   NEVER read by components.
     Layer 2  semantic   --sx-surface-2, --sx-text-2 …    the component contract. Redefined per theme.
     Layer 3  component  --sx-btn-height-md …             optional, local to a component.

   Theme switch = ONE attribute:   <html data-sx-theme="dark">
     :root                        light  ("Liquid Glass")   — the default, no attribute needed
     [data-sx-theme="dark"]       dark   ("Soft Graphite")
     [data-sx-theme="olb-warm"]   the light set + the booking wizard's warm palette (bottom of file)
     [data-sx-theme="portal"]     the dark set + the client portal's slate palette (bottom of file)
   Nested overrides work for free: put data-sx-theme on any element.

   EVERY theme block must define the COMPLETE layer-2 set. A missing custom property fails silently
   (the declaration is dropped) — the exact failure mode that made the old library's 489 palette variable reads fragile.
   Consumers should still write var(--sx-x, <fallback>) so a future miss degrades instead of vanishing.

   Breakpoints (can't be custom properties — media queries don't resolve var()). Match MudBlazor:
     xs < 600px · sm 600–959 · md 960–1279 · lg 1280–1919 · xl ≥ 1920
   ============================================================================================= */

:root {
  /* ----------------------------------------------------------------------------------------
     LAYER 1 — ramps (theme-independent)
     ---------------------------------------------------------------------------------------- */
  --sx-blue-50:  #eaf3fd;
  --sx-blue-100: #d3e6fa;
  --sx-blue-200: #a9cdf5;
  --sx-blue-300: #7ab8f5;
  --sx-blue-400: #5aa2ee;
  --sx-blue-500: #2f86dc;
  --sx-blue-600: #1f6fc6;
  --sx-blue-700: #1a63b3;
  --sx-blue-800: #165699;
  --sx-blue-900: #113f70;

  /* Cool graphite — blue-tinted neutrals. The dark theme's surfaces live in 800–975. */
  --sx-gray-50:  #f6f8fb;
  --sx-gray-100: #eceff5;
  --sx-gray-200: #dfe3ec;
  --sx-gray-300: #c6ccd8;
  --sx-gray-400: #a3a9b8;
  --sx-gray-500: #7d8698;
  --sx-gray-600: #616a7d;
  --sx-gray-700: #4b5565;
  --sx-gray-800: #2e3648;
  --sx-gray-850: #272e3e;
  --sx-gray-900: #202634;
  --sx-gray-925: #1a1f2b;
  --sx-gray-950: #131722;
  --sx-gray-975: #0f131b;

  --sx-violet-300: #b7abf5;
  --sx-violet-400: #a394f0;
  --sx-violet-500: #8b7be6;
  --sx-violet-600: #6d5bd0;
  --sx-violet-700: #5b49c0;

  --sx-green-300: #5fd39b;
  --sx-green-400: #3fbf82;
  --sx-green-500: #22a06b;
  --sx-green-600: #177a4d;
  --sx-green-700: #136a42;

  --sx-amber-300: #f0bb63;
  --sx-amber-400: #e0a341;
  --sx-amber-500: #c8821b;
  --sx-amber-600: #a85d08;
  --sx-amber-700: #8a4b00;

  --sx-red-300: #f68a8a;
  --sx-red-400: #ef6b6b;
  --sx-red-500: #e04e4e;
  --sx-red-600: #c93a3a;
  --sx-red-700: #b42f2f;

  --sx-cyan-300: #63cbdc;
  --sx-cyan-400: #3fb7cc;
  --sx-cyan-500: #1c98ad;
  --sx-cyan-600: #0b7a8f;
  --sx-cyan-700: #086a7c;

  /* ----------------------------------------------------------------------------------------
     LAYER 2 — theme-independent groups (typography, radius, spacing, motion, effects, layout)
     ---------------------------------------------------------------------------------------- */

  /* Typography. Fira Sans is <link>ed in index.html; it previously reached the app only through
     MudBlazor's typography layer, so it MUST be named here explicitly (PLAN Part 1). */
  --sx-font-sans: 'Fira Sans', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --sx-font-mono: ui-monospace, 'Cascadia Mono', 'SFMono-Regular', Menlo, Consolas, 'Liberation Mono', monospace;

  /* 12 steps × (size, line-height, letter-spacing, weight). Mud origin in [brackets]. */
  --sx-text-display-lg-size: 2.75rem;   --sx-text-display-lg-line: 1.1;  --sx-text-display-lg-tracking: -0.02em;  --sx-text-display-lg-weight: 600;
  --sx-text-display-md-size: 2.25rem;   --sx-text-display-md-line: 1.15; --sx-text-display-md-tracking: -0.015em; --sx-text-display-md-weight: 600;
  --sx-text-display-sm-size: 1.875rem;  --sx-text-display-sm-line: 1.2;  --sx-text-display-sm-tracking: -0.01em;  --sx-text-display-sm-weight: 600;  /* [h4] */
  --sx-text-title-lg-size:   1.5rem;    --sx-text-title-lg-line:   1.3;  --sx-text-title-lg-tracking:   -0.005em; --sx-text-title-lg-weight:   600;  /* [h5] */
  --sx-text-title-md-size:   1.25rem;   --sx-text-title-md-line:   1.35; --sx-text-title-md-tracking:   0;        --sx-text-title-md-weight:   600;  /* [h6] */
  --sx-text-title-sm-size:   1rem;      --sx-text-title-sm-line:   1.5;  --sx-text-title-sm-tracking:   0;        --sx-text-title-sm-weight:   600;  /* [subtitle1] */
  --sx-text-label-lg-size:   0.875rem;  --sx-text-label-lg-line:   1.45; --sx-text-label-lg-tracking:   0.005em;  --sx-text-label-lg-weight:   500;  /* [subtitle2] */
  --sx-text-body-size:       1rem;      --sx-text-body-line:       1.55; --sx-text-body-tracking:       0;        --sx-text-body-weight:       400;  /* [body1 / unset] */
  --sx-text-body-sm-size:    0.875rem;  --sx-text-body-sm-line:    1.5;  --sx-text-body-sm-tracking:    0;        --sx-text-body-sm-weight:    400;  /* [body2] */
  --sx-text-caption-size:    0.75rem;   --sx-text-caption-line:    1.4;  --sx-text-caption-tracking:    0.01em;   --sx-text-caption-weight:    400;  /* [caption] */
  --sx-text-overline-size:   0.6875rem; --sx-text-overline-line:   1.4;  --sx-text-overline-tracking:   0.08em;   --sx-text-overline-weight:   600;  /* [overline] uppercase */
  --sx-text-mono-size:       0.8125rem; --sx-text-mono-line:       1.5;  --sx-text-mono-tracking:       0;        --sx-text-mono-weight:       400;

  /* Radius. Everything is rounded; there is no sharp corner in the system. Continuous radius rule
     for nesting: inner-radius = outer-radius − padding (never below --sx-radius-xs). */
  --sx-radius-xs:   6px;
  --sx-radius-sm:   10px;
  --sx-radius-md:   14px;
  --sx-radius-lg:   18px;
  --sx-radius-xl:   24px;
  --sx-radius-full: 9999px;

  /* Spacing — 4px base, MudBlazor's exact arithmetic (pa-4 = 16px). utilities.css is generated from
     this scale; keep the two in sync. */
  --sx-space-0:  0;
  --sx-space-1:  4px;
  --sx-space-2:  8px;
  --sx-space-3:  12px;
  --sx-space-4:  16px;
  --sx-space-5:  20px;
  --sx-space-6:  24px;
  --sx-space-7:  28px;
  --sx-space-8:  32px;
  --sx-space-9:  36px;
  --sx-space-10: 40px;
  --sx-space-11: 44px;
  --sx-space-12: 48px;
  --sx-space-13: 52px;
  --sx-space-14: 56px;
  --sx-space-15: 60px;
  --sx-space-16: 64px;

  /* Motion — short, eased, purposeful. Zeroed under prefers-reduced-motion (bottom of file). */
  --sx-dur-fast: 120ms;
  --sx-dur-base: 200ms;
  --sx-dur-slow: 320ms;
  --sx-ease-out:    cubic-bezier(0.2, 0.8, 0.2, 1);
  --sx-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --sx-ease-spring: cubic-bezier(0.34, 1.3, 0.64, 1);

  /* Effects */
  --sx-blur-sm: 8px;
  --sx-blur-md: 20px;
  --sx-blur-lg: 40px;
  /* Backdrop blur behind dialog / overlay scrims. Deliberately lighter than --sx-blur-sm:
     the scrim already darkens, so heavy blur just makes the page behind unreadable mush. */
  --sx-scrim-blur: 2px;
  /* Matte grain: a tiny fractal-noise tile. Apply as a background-image on an ::after overlay at
     --sx-grain-opacity (2–4%). This is what kills the plastic look. */
  --sx-grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");

  /* Layout */
  --sx-appbar-h:  48px;   /* MainLayout's bottom app bar — was a hard-coded 48px in app.css */
  --sx-touch-min: 44px;   /* minimum hit target on touch, even when the visual control is smaller */
  /* Icon sizes. Sm ≈ Mud Small (20), Md ≈ Mud Medium (24), Xl ≈ Mud Large (35) — each a touch tighter. */
  --sx-icon-xs: 14px;
  --sx-icon-sm: 18px;
  --sx-icon-md: 22px;
  --sx-icon-lg: 28px;
  --sx-icon-xl: 36px;

  /* Layering. Mirrored in C# by SxZIndex (SalX.UI/SxZIndex.cs) — change both. Sits ABOVE MudBlazor's
     scale (drawer 1100 · popover 1200 · appbar 1300 · dialog 1400 · snackbar 1500 · tooltip 1600) where
     the two must interleave: an Sx dialog over a Mud app bar, an Sx menu over an Sx dialog. Popovers
     also raise themselves above any positioned ancestor at runtime (sx.js openPopover). */
  --sx-z-sticky:   1000;   /* a sticky header inside a scrolling pane */
  --sx-z-appbar:   1300;   /* deliberately Mud's app-bar value, so nothing reorders while both exist */
  --sx-z-drawer:   1320;   /* a temporary nav drawer must cover the bar it was opened from */
  --sx-z-overlay:  1350;
  --sx-z-dialog:   1400;
  --sx-z-popover:  1450;
  --sx-z-snackbar: 1500;
  --sx-z-toast:    1550;   /* persistent admin toasts — they outrank transient snackbars */
  --sx-z-tooltip:  1600;
  --sx-z-context:  1650;   /* a page-owned context menu (schedule right-click) */
  --sx-z-busy:     1700;   /* a blocking busy scrim — nothing may sit above it but the lock screen */
}

/* ============================================================================================
   LIGHT — "Liquid Glass"
   Clean, airy, weightless. Frosted panes floating over faintly tinted light.
   olb-warm currently inherits this set; its own block (below) is a reserved override slot.
   ============================================================================================ */
:root,
[data-sx-theme="light"],
[data-sx-theme="olb-warm"],
/* A tooltip is an INVERTED surface: it is dark on a light page and light on a dark one. Everything
   inside it therefore needs the OPPOSITE theme's tokens, so a tooltip on a DARK page takes this
   light set. Pairing the blocks like this keeps one source of truth — the alternative was
   restating ~30 tokens inside `.sx-tooltip`, which would drift the first time a colour moved.
   Specificity (0,2,0) beats the plain `[data-sx-theme]` block (0,1,0), and custom properties
   inherit, so the whole bubble subtree resolves from here. See the matching pair in DARK. */
[data-sx-theme="dark"] .sx-tooltip,
[data-sx-theme="portal"] .sx-tooltip {
  color-scheme: light;

  /* Surfaces. The page is NOT #fff — surfaces pop forward off a tinted base. */
  --sx-bg:        #f3f5f9;
  --sx-bg-image:  radial-gradient(1200px 700px at 12% -10%, rgba(31, 111, 198, 0.10), transparent 60%),
                  radial-gradient(900px 600px at 100% 100%, rgba(109, 91, 208, 0.07), transparent 60%),
                  linear-gradient(180deg, #f6f8fb 0%, #eef1f6 100%);
  --sx-surface-1: #fbfcfe;   /* resting card / list / table */
  --sx-surface-2: #ffffff;   /* raised card, drawer, app bar */
  --sx-surface-3: #ffffff;   /* menu, popover, tooltip */
  --sx-surface-4: #ffffff;   /* dialog */
  --sx-surface-sunken: #eceff5;
  --sx-surface-hover:  rgba(20, 40, 80, 0.05);
  --sx-surface-pressed: rgba(20, 40, 80, 0.09);
  --sx-scrim: rgba(15, 20, 35, 0.45);

  /* Glass. Always pair --sx-glass-bg with a backdrop-filter fallback to --sx-glass-bg-fallback. */
  --sx-glass-bg:          rgba(255, 255, 255, 0.70);
  --sx-glass-bg-fallback: #fbfcfe;
  --sx-glass-filter:      blur(20px) saturate(140%);
  --sx-glass-border:      rgba(255, 255, 255, 0.60);

  /* Lines. Depth comes from layering, not borders — hairlines stay faint. */
  --sx-line:        rgba(16, 24, 40, 0.08);
  --sx-line-strong: rgba(16, 24, 40, 0.16);
  --sx-line-input:  rgba(16, 24, 40, 0.48);   /* ≥ 3:1 on --sx-surface-2 (UI boundary contrast) */
  --sx-divider:     rgba(16, 24, 40, 0.07);
  --sx-edge:        inset 0 1px 0 rgba(255, 255, 255, 0.65);   /* the glass edge — motif #1 */
  /* The same motif on a SATURATED fill. 0.65 white reads as a lit top edge on a near-white
     surface, but as a hard white bar across the top of a solid coloured button. Anything with
     a strong background colour uses this instead. */
  --sx-edge-on-fill: inset 0 1px 0 rgba(255, 255, 255, 0.16);

  /* Text. Contrast on --sx-bg / --sx-surface-2: text-1 16:1, text-2 6.9:1, text-3 5.0:1. */
  --sx-text-1:        #151a24;
  --sx-text-2:        #4b5565;
  --sx-text-3:        #616a7d;
  --sx-text-disabled: #a3a9b8;
  --sx-text-on-accent: #ffffff;
  --sx-text-on-status: #ffffff;

  /* Accent — deeper, slightly desaturated azure. #6AB0F5 could not carry text on white; this can
     (white on accent 5.1:1, accent-text on surface 6.0:1). */
  --sx-accent:             var(--sx-blue-600);
  --sx-accent-hover:       var(--sx-blue-700);
  --sx-accent-pressed:     var(--sx-blue-800);
  --sx-accent-soft:        rgba(31, 111, 198, 0.10);
  --sx-accent-soft-border: rgba(31, 111, 198, 0.28);
  --sx-accent-text:        var(--sx-blue-700);
  --sx-accent-on:          #ffffff;
  --sx-accent-glow:        0 0 0 0 transparent;   /* glow is a dark-theme device */

  /* Accent-2 — muted violet. For the reviewed `Secondary` sites only. */
  --sx-accent2:             var(--sx-violet-600);
  --sx-accent2-hover:       var(--sx-violet-700);
  --sx-accent2-pressed:     #4d3daa;
  --sx-accent2-soft:        rgba(109, 91, 208, 0.10);
  --sx-accent2-soft-border: rgba(109, 91, 208, 0.28);
  --sx-accent2-text:        var(--sx-violet-700);
  --sx-accent2-on:          #ffffff;

  /* Status ×4 — base (white text ≥ 4.9:1) · soft fill · soft border · text (≥ 5.6:1 on bg). */
  --sx-success:             var(--sx-green-600);
  --sx-success-soft:        rgba(23, 122, 77, 0.10);
  --sx-success-soft-border: rgba(23, 122, 77, 0.30);
  --sx-success-text:        var(--sx-green-700);
  --sx-warning:             var(--sx-amber-600);
  --sx-warning-soft:        rgba(168, 93, 8, 0.10);
  --sx-warning-soft-border: rgba(168, 93, 8, 0.30);
  --sx-warning-text:        var(--sx-amber-700);
  --sx-danger:              var(--sx-red-600);
  --sx-danger-soft:         rgba(201, 58, 58, 0.10);
  --sx-danger-soft-border:  rgba(201, 58, 58, 0.30);
  --sx-danger-text:         var(--sx-red-700);
  --sx-info:                var(--sx-cyan-600);
  --sx-info-soft:           rgba(11, 122, 143, 0.10);
  --sx-info-soft-border:    rgba(11, 122, 143, 0.30);
  --sx-info-text:           var(--sx-cyan-700);

  /* Neutral ladder — Tone.Default / Tone.Muted fills (grey buttons, chips). */
  --sx-neutral:             #e3e7ee;
  --sx-neutral-hover:       #d6dbe5;
  --sx-neutral-pressed:     #c6ccd8;
  --sx-neutral-soft:        rgba(16, 24, 40, 0.06);
  --sx-neutral-soft-border: rgba(16, 24, 40, 0.16);
  --sx-neutral-text:        var(--sx-text-1);
  --sx-neutral-on:          var(--sx-text-1);

  /* Numeric ladder — teal, money / numeric emphasis (Tone.Numeric ← Color.Tertiary). White on base 4.9:1. */
  --sx-numeric:             #0c8068;
  --sx-numeric-hover:       #0a6f5a;
  --sx-numeric-pressed:     #085e4c;
  --sx-numeric-soft:        rgba(12, 128, 104, 0.10);
  --sx-numeric-soft-border: rgba(12, 128, 104, 0.30);
  --sx-numeric-text:        #0a6f5a;

  /* Chart — categorical slots, in FIXED order (the order is the colour-vision-safety mechanism,
     not cosmetic). Drawn from the ramps above and validated with the dataviz palette checker
     against surface-1 and #fff: lightness band, chroma floor, adjacent-pair CVD ΔE ≥ 8, normal-
     vision ΔE ≥ 15, ≥ 3:1 contrast — all PASS on light. A 6th series folds into "Other". */
  --sx-chart-1:   var(--sx-blue-600);    /* #1f6fc6 */
  --sx-chart-2:   var(--sx-amber-500);   /* #c8821b */
  --sx-chart-3:   var(--sx-numeric);     /* #0c8068 */
  --sx-chart-4:   var(--sx-violet-600);  /* #6d5bd0 */
  --sx-chart-5:   var(--sx-red-500);     /* #e04e4e */
  --sx-chart-gap: var(--sx-surface-1);   /* the 2px seam between slices — the surface the pie sits on */

  /* Status hover / pressed steps (solid buttons). Darker on light. */
  --sx-success-hover:   var(--sx-green-700);   --sx-success-pressed: #105a38;
  --sx-warning-hover:   var(--sx-amber-700);   --sx-warning-pressed: #733e00;
  --sx-danger-hover:    var(--sx-red-700);     --sx-danger-pressed:  #9d2828;
  --sx-info-hover:      var(--sx-cyan-700);    --sx-info-pressed:    #065a6a;

  /* Contrast (inverse) surface — tooltips, dark chips. */
  --sx-contrast-bg:   #1f2533;
  --sx-contrast-text: #f3f5f9;

  /* Elevation — two layers, tight contact + wide ambient, both tinted toward the accent hue.
     Mud elevation → sx:  0→0 · 1,2→1 · 3,4→2 · 5,6→3 · 8→4 · 12→5 */
  --sx-shadow-0: none;
  --sx-shadow-1: 0 1px 2px rgba(20, 40, 80, 0.06), 0 1px 1px rgba(20, 40, 80, 0.03);
  --sx-shadow-2: 0 1px 2px rgba(20, 40, 80, 0.05), 0 4px 12px -2px rgba(20, 40, 80, 0.08);
  --sx-shadow-3: 0 2px 4px rgba(20, 40, 80, 0.05), 0 10px 24px -6px rgba(20, 40, 80, 0.12);
  --sx-shadow-4: 0 2px 6px rgba(20, 40, 80, 0.06), 0 18px 40px -10px rgba(20, 40, 80, 0.16);
  --sx-shadow-5: 0 4px 10px rgba(20, 40, 80, 0.08), 0 32px 64px -16px rgba(20, 40, 80, 0.22);

  /* Focus — the soft double ring (motif #2): thin high-opacity ring + wide low-opacity halo. */
  --sx-focus-ring-color: rgba(31, 111, 198, 0.85);
  --sx-focus-halo-color: rgba(31, 111, 198, 0.22);
  --sx-focus-shadow: 0 0 0 1.5px var(--sx-focus-ring-color), 0 0 0 6px var(--sx-focus-halo-color);

  /* Grain — 3% on light. */
  --sx-grain-opacity: 0.03;

  /* Selection / misc */
  --sx-selection-bg: rgba(31, 111, 198, 0.18);
  --sx-skeleton: rgba(16, 24, 40, 0.07);
  --sx-skeleton-shine: rgba(255, 255, 255, 0.6);
}

/* ============================================================================================
   DARK — "Soft Graphite"
   Deep, low-chroma, substantial. Elevation from surface value, not shadow. Accent may glow —
   on exactly one primary action per view.
   portal currently inherits this set; its own block (below) is a reserved override slot.
   ============================================================================================ */
[data-sx-theme="dark"],
[data-sx-theme="portal"],
/* The inverted-tooltip pair — see the note in LIGHT. A tooltip on a LIGHT page is a dark bubble,
   so its contents take this dark set. Without this, chips inside a rich tooltip rendered with
   page-polarity tokens: `Tone.Default` resolved to --sx-neutral-soft (a dark translucent) over
   --sx-neutral-text #151a24, i.e. near-black on a near-black bubble. The "Pending" chip on the
   schedule hover panel was effectively invisible. */
[data-sx-theme="light"] .sx-tooltip,
[data-sx-theme="olb-warm"] .sx-tooltip {
  color-scheme: dark;

  --sx-bg:        var(--sx-gray-950);
  --sx-bg-image:  radial-gradient(1200px 700px at 12% -10%, rgba(90, 162, 238, 0.10), transparent 60%),
                  radial-gradient(900px 600px at 100% 100%, rgba(163, 148, 240, 0.06), transparent 60%),
                  linear-gradient(180deg, #151a26 0%, #10141d 100%);
  --sx-surface-1: var(--sx-gray-925);
  --sx-surface-2: var(--sx-gray-900);
  --sx-surface-3: var(--sx-gray-850);
  --sx-surface-4: var(--sx-gray-800);
  --sx-surface-sunken: var(--sx-gray-975);
  --sx-surface-hover:  rgba(255, 255, 255, 0.05);
  --sx-surface-pressed: rgba(255, 255, 255, 0.09);
  --sx-scrim: rgba(0, 0, 0, 0.60);

  /* Smoked glass. */
  --sx-glass-bg:          rgba(255, 255, 255, 0.04);
  --sx-glass-bg-fallback: var(--sx-gray-900);
  --sx-glass-filter:      blur(20px) saturate(120%);
  --sx-glass-border:      rgba(255, 255, 255, 0.07);

  --sx-line:        rgba(255, 255, 255, 0.07);
  --sx-line-strong: rgba(255, 255, 255, 0.14);
  --sx-line-input:  rgba(255, 255, 255, 0.34);   /* ≥ 3:1 on --sx-surface-1/2 */
  --sx-divider:     rgba(255, 255, 255, 0.06);
  --sx-edge:        inset 0 1px 0 rgba(255, 255, 255, 0.06);
  /* On dark the surface edge is already faint, so the on-fill variant matches it. */
  --sx-edge-on-fill: inset 0 1px 0 rgba(255, 255, 255, 0.08);

  /* Contrast on --sx-surface-1: text-1 13.7:1, text-2 8.1:1, text-3 6.2:1; text-3 stays ≥ 4.5:1
     even on --sx-surface-4 (dialogs), which is the brightest dark surface. */
  --sx-text-1:        #e6eaf2;
  --sx-text-2:        #adb5c5;
  --sx-text-3:        #96a0b2;
  --sx-text-disabled: #555d6e;
  /* On dark the accent LIGHTENS, so text on it must be dark (7.0:1). Same rule as --olb-on-accent. */
  --sx-text-on-accent: #0b1220;
  --sx-text-on-status: #0b1220;

  --sx-accent:             var(--sx-blue-400);
  --sx-accent-hover:       #6faff2;
  --sx-accent-pressed:     #4a93e0;
  --sx-accent-soft:        rgba(90, 162, 238, 0.14);
  --sx-accent-soft-border: rgba(90, 162, 238, 0.32);
  --sx-accent-text:        var(--sx-blue-300);
  --sx-accent-on:          #0b1220;
  --sx-accent-glow:        0 0 24px -8px rgba(90, 162, 238, 0.85);

  --sx-accent2:             var(--sx-violet-400);
  --sx-accent2-hover:       #b1a4f3;
  --sx-accent2-pressed:     #9384e8;
  --sx-accent2-soft:        rgba(163, 148, 240, 0.14);
  --sx-accent2-soft-border: rgba(163, 148, 240, 0.32);
  --sx-accent2-text:        var(--sx-violet-300);
  --sx-accent2-on:          #0b1220;

  --sx-success:             var(--sx-green-400);
  --sx-success-soft:        rgba(63, 191, 130, 0.14);
  --sx-success-soft-border: rgba(63, 191, 130, 0.32);
  --sx-success-text:        var(--sx-green-300);
  --sx-warning:             var(--sx-amber-400);
  --sx-warning-soft:        rgba(224, 163, 65, 0.14);
  --sx-warning-soft-border: rgba(224, 163, 65, 0.32);
  --sx-warning-text:        var(--sx-amber-300);
  --sx-danger:              var(--sx-red-400);
  --sx-danger-soft:         rgba(239, 107, 107, 0.14);
  --sx-danger-soft-border:  rgba(239, 107, 107, 0.32);
  --sx-danger-text:         var(--sx-red-300);
  --sx-info:                var(--sx-cyan-400);
  --sx-info-soft:           rgba(63, 183, 204, 0.14);
  --sx-info-soft-border:    rgba(63, 183, 204, 0.32);
  --sx-info-text:           var(--sx-cyan-300);

  --sx-neutral:             var(--sx-gray-800);
  --sx-neutral-hover:       #38415a;
  --sx-neutral-pressed:     #414b66;
  --sx-neutral-soft:        rgba(255, 255, 255, 0.06);
  --sx-neutral-soft-border: rgba(255, 255, 255, 0.16);
  --sx-neutral-text:        var(--sx-text-1);
  --sx-neutral-on:          var(--sx-text-1);

  /* Numeric — lighter teal on dark, dark text on it (8.9:1). */
  --sx-numeric:             #34c9a3;
  --sx-numeric-hover:       #4fd4b2;
  --sx-numeric-pressed:     #2bb894;
  --sx-numeric-soft:        rgba(52, 201, 163, 0.14);
  --sx-numeric-soft-border: rgba(52, 201, 163, 0.32);
  --sx-numeric-text:        #5ad8b8;

  /* Chart — same five hues, re-stepped for the dark band (L 0.48–0.67 on gray-925/900), NOT the
     light values flipped. Validated as a set: everything passes except one WARN, amber↔green at
     CVD ΔE 7.9 (legal in the 6–8 band because every pie ships slice gaps, a legend and hover
     labels — the secondary encoding the rule asks for). Re-run the checker if you change one. */
  --sx-chart-1:   var(--sx-blue-500);    /* #2f86dc */
  --sx-chart-2:   var(--sx-amber-500);   /* #c8821b */
  --sx-chart-3:   var(--sx-green-500);   /* #22a06b */
  --sx-chart-4:   var(--sx-violet-500);  /* #8b7be6 */
  --sx-chart-5:   var(--sx-red-500);     /* #e04e4e */
  --sx-chart-gap: var(--sx-surface-1);

  /* Status hover / pressed — lighter on dark. */
  --sx-success-hover:   #55cb93;   --sx-success-pressed: #38b077;
  --sx-warning-hover:   #e8b25c;   --sx-warning-pressed: #d3953a;
  --sx-danger-hover:    #f38080;   --sx-danger-pressed:  #e85c5c;
  --sx-info-hover:      #5cc3d5;   --sx-info-pressed:    #35a9bd;

  --sx-contrast-bg:   #eef1f6;
  --sx-contrast-text: #151a24;

  /* Shadows barely read on dark ground; they exist for overlays lifting off the page. */
  --sx-shadow-0: none;
  --sx-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.30);
  --sx-shadow-2: 0 2px 6px rgba(0, 0, 0, 0.35);
  --sx-shadow-3: 0 6px 16px -4px rgba(0, 0, 0, 0.45);
  --sx-shadow-4: 0 12px 32px -8px rgba(0, 0, 0, 0.55);
  --sx-shadow-5: 0 24px 56px -12px rgba(0, 0, 0, 0.65);

  --sx-focus-ring-color: rgba(90, 162, 238, 0.90);
  --sx-focus-halo-color: rgba(90, 162, 238, 0.24);
  --sx-focus-shadow: 0 0 0 1.5px var(--sx-focus-ring-color), 0 0 0 6px var(--sx-focus-halo-color);

  /* Grain slightly stronger on dark — flat dark fills band on cheap panels. */
  --sx-grain-opacity: 0.04;

  --sx-selection-bg: rgba(90, 162, 238, 0.28);
  --sx-skeleton: rgba(255, 255, 255, 0.06);
  --sx-skeleton-shine: rgba(255, 255, 255, 0.10);
}

/* ============================================================================================
   SLOT OVERRIDES — olb-warm and portal.
   Each inherits a COMPLETE set from the shared selector above (light / dark) and overrides only the
   colours below, so a page under either attribute is never left with an unresolved token.

   These are the palettes the two shells gave the old component library, carried over at the Phase 7
   cutover so the booking page and the portal look the same as before. They are not a redesign: the
   proper OLB-warm and portal migrations are still separate work (PLAN Part 4). The booking wizard's
   own --olb-* system stays the source of truth INSIDE the wizard (OlbWizard.razor.css points the Sx
   tokens at --olb-* there). This slot covers what renders outside it: menus, dialogs, snackbars.
   ============================================================================================ */
[data-sx-theme="olb-warm"] {
  /* Public booking wizard, light: warm off-white, terracotta accent. The accent is provisional —
     read project_olb_light_theme.md before changing it, and change OlbWizard.razor.css with it. */
  --sx-bg:                 #faf9f7;
  --sx-bg-image:           none;
  --sx-surface-1:          #fbfaf8;
  --sx-surface-2:          #ffffff;
  --sx-surface-3:          #ffffff;
  --sx-surface-4:          #ffffff;
  --sx-surface-sunken:     #f4f1ec;
  --sx-surface-hover:      #f4f1ec;
  --sx-line:               #e7e3dc;
  --sx-line-strong:        #d8d2c8;
  --sx-line-input:         #d8d2c8;
  --sx-divider:            #efece6;
  --sx-text-1:             #1c1917;
  --sx-text-2:             #57534e;
  --sx-text-3:             #78716c;
  --sx-text-disabled:      #a8a29e;
  --sx-accent:             #9a3412;
  --sx-accent-hover:       #7c2d12;
  --sx-accent-pressed:     #7c2d12;
  --sx-accent-soft:        #fff7ed;
  --sx-accent-soft-border: #fbcfa5;
  --sx-accent-text:        #9a3412;
  --sx-accent-on:          #ffffff;
  --sx-text-on-accent:     #ffffff;
  --sx-accent2:            #0f766e;
  --sx-accent2-text:       #0f766e;
  /* Info re-pointed at the warm stone ramp: the stock cool info would be the page's only blue. */
  --sx-info:               #57534e;
  --sx-info-text:          #57534e;
  --sx-info-soft:          rgba(87, 83, 78, 0.08);
  --sx-info-soft-border:   rgba(87, 83, 78, 0.24);
  --sx-success:            #059669;
  --sx-warning:            #b45309;
  --sx-danger:             #dc2626;
  --sx-danger-text:        #b91c1c;
  --sx-focus-ring-color:   rgba(154, 52, 18, 0.85);
  --sx-focus-halo-color:   rgba(154, 52, 18, 0.16);
  --sx-selection-bg:       rgba(154, 52, 18, 0.16);
}

[data-sx-theme="portal"] {
  /* Client portal: hard-coded dark, cool slate chrome with a dodger-blue accent. */
  --sx-bg:                 #0f172a;
  --sx-bg-image:           none;
  --sx-surface-1:          #1e293b;
  --sx-surface-2:          #1e293b;
  --sx-surface-3:          #273449;
  --sx-surface-4:          #273449;
  --sx-text-1:             #f8fafc;
  --sx-text-2:             #94a3b8;
  --sx-line-input:         rgba(255, 255, 255, 0.15);
  --sx-accent:             #1e90ff;
  --sx-accent-hover:       #4aa6ff;
  --sx-accent-pressed:     #1478d6;
  --sx-accent-soft:        rgba(30, 144, 255, 0.14);
  --sx-accent-soft-border: rgba(30, 144, 255, 0.34);
  --sx-accent-text:        #6cb6ff;
  --sx-accent-on:          #ffffff;
  --sx-text-on-accent:     #ffffff;
  --sx-accent-glow:        0 0 24px -8px rgba(30, 144, 255, 0.85);
  --sx-accent2:            #06b6d4;
  --sx-accent2-text:       #22d3ee;
  --sx-focus-ring-color:   rgba(30, 144, 255, 0.90);
  --sx-focus-halo-color:   rgba(30, 144, 255, 0.24);
  --sx-selection-bg:       rgba(30, 144, 255, 0.28);
}

/* ============================================================================================
   Reduced motion — durations collapse to zero; components must animate via these tokens only.
   ============================================================================================ */
@media (prefers-reduced-motion: reduce) {
  :root {
    --sx-dur-fast: 0ms;
    --sx-dur-base: 0ms;
    --sx-dur-slow: 0ms;
  }
}
