/* ============================================================================
   CS Toolbox — Design System (R0.2, 2026-06-11)
   ----------------------------------------------------------------------------
   Single source of truth for the UI tokens. Dark-first; a light mode mirror is
   provided so the theme toggle can flip a single attribute.

   How to use it:
     1. Link this file BEFORE any per-page CSS so cascades work as expected.
     2. Reference tokens by var(--<name>) — never hard-code colors, spacing,
        radius, or shadow values in new code.
     3. Old per-page CSS keeps working (this file doesn't fight existing rules);
        the R1+ rebuilds will swap them out one at a time.

   Accessibility floor (R4 will audit, R0 enforces here):
     - Body text  : WCAG AAA contrast (≥ 7:1)
     - UI chrome  : WCAG AA   contrast (≥ 4.5:1)
     - Focus ring : visible at 200% zoom, never `outline: none` without replacement
     - Motion     : respects `prefers-reduced-motion`
   ============================================================================ */

:root {
    /* ── COLOR — LIGHT (default, 2026-06-11 — user direction: "go for white") ─── */

    /* Surfaces — clean, low-noise whites + near-whites. Body text on bg-base is
       AAA (≥ 7:1); UI chrome is AA (≥ 4.5:1). */
    --color-bg-base:        #ffffff;   /* page background */
    --color-bg-raised-1:    #f7f8fa;   /* cards, primary panels */
    --color-bg-raised-2:    #ffffff;   /* modals, inputs (sit on top of bg-raised-1) */
    --color-bg-raised-3:    #ffffff;   /* popovers, menus on top of modals */
    --color-bg-hover:       #f0f2f5;   /* row/button hover */
    --color-bg-pressed:     #e7ebf0;   /* row/button active */

    /* Text */
    --color-text-strong:    #0b0d10;   /* primary content, headings */
    --color-text-default:   #2a313b;   /* body */
    --color-text-muted:     #5a6370;   /* labels, helper, metadata */
    --color-text-faint:     #8a93a0;   /* placeholders, captions, dividers */
    --color-text-on-accent: #ffffff;   /* always white on the accent surface */
    --color-text-disabled:  #b8bfc7;

    /* Borders */
    --color-border-subtle:  #ebeef2;
    --color-border-default: #d8dde4;
    --color-border-strong:  #c5cbd3;
    --color-border-focus:   rgba(71, 85, 105, 0.4);

    /* Accent — default is Slate (a neutral grey that reads as restrained on
       both modes). Users override via the in-app accent picker, which writes
       `color_theme` to localStorage. Brand red ships as the `red` theme. */
    --color-accent:         #475569;
    --color-accent-hover:   #334155;
    --color-accent-active:  #1e293b;
    --color-accent-faint:   rgba(71, 85, 105, 0.08);

    /* Semantic — used by toasts, banners, badges. NEVER reuse `--color-accent`
       for danger; they coincidentally look similar but mean different things. */
    --color-success:        #10b981;
    --color-success-faint:  rgba(16, 185, 129, 0.14);
    --color-warning:        #f59e0b;
    --color-warning-faint:  rgba(245, 158, 11, 0.14);
    --color-danger:         #ef4444;
    --color-danger-faint:   rgba(239, 68, 68, 0.14);
    --color-info:           #60a5fa;
    --color-info-faint:     rgba(96, 165, 250, 0.14);

    /* ── TYPOGRAPHY ───────────────────────────────────────────────────────── */

    /* System font stack — SF on macOS, Segoe UI on Windows, Roboto on Android,
       Inter on Linux if installed. We can vendor Inter as woff2 later if the
       team wants the exact same render across OSes. */
    --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Inter', Roboto,
                 'Helvetica Neue', Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
                 'Liberation Mono', monospace;

    /* Type scale. Body text is 15px (15/22) — denser than 16/24 for a tool used
       full-day at a desk. Bump to 17px (--font-size-md) for forms of consequence. */
    --font-size-xs:     12px;
    --font-size-sm:     13px;
    --font-size-base:   15px;
    --font-size-md:     17px;
    --font-size-lg:     22px;
    --font-size-xl:     28px;
    --font-size-2xl:    36px;

    --line-height-tight:  1.25;
    --line-height-base:   1.5;
    --line-height-loose:  1.7;

    --font-weight-regular:  400;
    --font-weight-medium:   500;
    --font-weight-semibold: 600;
    --font-weight-bold:     700;

    /* Letter-spacing — small text needs +tracking for legibility on dark bg */
    --letter-spacing-tight:  -0.01em;
    --letter-spacing-normal: 0;
    --letter-spacing-loose:   0.02em;
    --letter-spacing-caps:    0.06em;  /* uppercase eyebrows / badges */

    /* ── SPACING (8pt grid) ───────────────────────────────────────────────── */

    --space-0:   0;
    --space-1:   4px;
    --space-2:   8px;
    --space-3:  12px;
    --space-4:  16px;
    --space-5:  24px;
    --space-6:  32px;
    --space-7:  48px;
    --space-8:  64px;
    --space-9:  96px;

    /* ── RADIUS ───────────────────────────────────────────────────────────── */

    --radius-xs:    2px;
    --radius-sm:    4px;
    --radius-md:    6px;
    --radius-lg:    8px;
    --radius-xl:   12px;
    --radius-2xl:  16px;
    --radius-full: 9999px;

    /* ── SHADOW (three levels — keep the set small) ───────────────────────── */

    --shadow-raised: 0 1px 2px rgba(0, 0, 0, 0.5),
                     0 2px 4px rgba(0, 0, 0, 0.3);
    --shadow-popover: 0 4px 12px rgba(0, 0, 0, 0.55),
                      0 12px 32px rgba(0, 0, 0, 0.45);
    --shadow-modal:   0 24px 48px rgba(0, 0, 0, 0.7),
                      0 12px 24px rgba(0, 0, 0, 0.45);

    /* Inset shadow used by focus rings + pressed states */
    --shadow-focus-ring: 0 0 0 2px var(--color-bg-base),
                         0 0 0 4px var(--color-border-focus);

    /* ── MOTION ───────────────────────────────────────────────────────────── */

    --duration-instant: 0ms;
    --duration-fast:    120ms;
    --duration-base:    180ms;
    --duration-slow:    280ms;

    /* Natural-feeling ease — same curve as the "ease-out-quint" family */
    --ease-out:     cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in-out:  cubic-bezier(0.45, 0, 0.55, 1);

    /* ── Z-INDEX (centralised so nothing fights) ──────────────────────────── */

    --z-base:           0;
    --z-header:       100;
    --z-dropdown:     200;
    --z-toast:        300;
    --z-modal-back:   400;
    --z-modal:        401;
    --z-tooltip:      500;

    /* ── LAYOUT ───────────────────────────────────────────────────────────── */

    --layout-page-max: 1280px;
    --layout-narrow:    720px;   /* forms, prose */
    --layout-content:  1080px;   /* dashboards, tables in narrow mode */

    --layout-header-height: 64px;
    --layout-footer-height: 48px;
}

/* ── DARK MODE (override) ────────────────────────────────────────────────────
   Light is the default; users opt into dark via the header toggle, which sets
   <html data-mode="dark">. Tokens redefined here override the :root defaults. */

[data-mode="dark"] {
    --color-bg-base:        #0b0d10;
    --color-bg-raised-1:    #14171c;
    --color-bg-raised-2:    #1c2027;
    --color-bg-raised-3:    #252a33;
    --color-bg-hover:       #1a1e25;
    --color-bg-pressed:     #11141a;

    --color-text-strong:    #f1f3f6;
    --color-text-default:   #dde1e7;
    --color-text-muted:     #b0b8c2;
    --color-text-faint:     #8e96a3;
    --color-text-disabled:  #5a616c;

    --color-border-subtle:  #232830;
    --color-border-default: #2e343e;
    --color-border-strong:  #3a414c;
    --color-border-focus:   rgba(71, 85, 105, 0.55);

    --color-accent-hover:   #64748b;
    --color-accent-active:  #334155;
    --color-accent-faint:   rgba(71, 85, 105, 0.14);

    --shadow-raised: 0 1px 2px rgba(0, 0, 0, 0.5),
                     0 2px 4px rgba(0, 0, 0, 0.3);
    --shadow-popover: 0 4px 12px rgba(0, 0, 0, 0.55),
                      0 12px 32px rgba(0, 0, 0, 0.45);
    --shadow-modal:   0 24px 48px rgba(0, 0, 0, 0.7),
                      0 12px 24px rgba(0, 0, 0, 0.45);

    --shadow-focus-ring: 0 0 0 2px var(--color-bg-base),
                         0 0 0 4px var(--color-border-focus);
}

/* ── ACCENT VARIANTS ──────────────────────────────────────────────────────
   Override --color-accent-* tokens when [data-theme="X"] is set on <html>.
   Pre-paint init in theme-init.js; UI in accent-picker.js. Default accent
   (PING red) lives in :root above — requires no [data-theme] attribute. */

[data-theme="red"] {
    --color-accent:         #c8102e;
    --color-accent-hover:   #b00d27;
    --color-accent-active:  #960822;
    --color-accent-faint:   rgba(200, 16, 46, 0.08);
    --color-border-focus:   rgba(200, 16, 46, 0.4);
}
[data-theme="orange"] {
    --color-accent:         #ea580c;
    --color-accent-hover:   #c2410c;
    --color-accent-active:  #9a3412;
    --color-accent-faint:   rgba(234, 88, 12, 0.08);
    --color-border-focus:   rgba(234, 88, 12, 0.4);
}
[data-theme="emerald"] {
    --color-accent:         #10b981;
    --color-accent-hover:   #059669;
    --color-accent-active:  #047857;
    --color-accent-faint:   rgba(16, 185, 129, 0.08);
    --color-border-focus:   rgba(16, 185, 129, 0.4);
}
[data-theme="teal"] {
    --color-accent:         #0d9488;
    --color-accent-hover:   #0f766e;
    --color-accent-active:  #115e59;
    --color-accent-faint:   rgba(13, 148, 136, 0.08);
    --color-border-focus:   rgba(13, 148, 136, 0.4);
}
[data-theme="blue"] {
    --color-accent:         #3b82f6;
    --color-accent-hover:   #2563eb;
    --color-accent-active:  #1e40af;
    --color-accent-faint:   rgba(59, 130, 246, 0.08);
    --color-border-focus:   rgba(59, 130, 246, 0.4);
}
[data-theme="indigo"] {
    --color-accent:         #4f46e5;
    --color-accent-hover:   #4338ca;
    --color-accent-active:  #3730a3;
    --color-accent-faint:   rgba(79, 70, 229, 0.08);
    --color-border-focus:   rgba(79, 70, 229, 0.4);
}
[data-theme="violet"] {
    --color-accent:         #7c3aed;
    --color-accent-hover:   #6d28d9;
    --color-accent-active:  #5b21b6;
    --color-accent-faint:   rgba(124, 58, 237, 0.08);
    --color-border-focus:   rgba(124, 58, 237, 0.4);
}

/* Dark-mode per-accent — hover lightens on dark bg (not darkens); faint tint
   is more opaque so it stays visible against raised-1. */

[data-mode="dark"][data-theme="red"] {
    --color-accent-hover:   #e51d3f;
    --color-accent-active:  #b00d27;
    --color-accent-faint:   rgba(200, 16, 46, 0.14);
    --color-border-focus:   rgba(200, 16, 46, 0.55);
}
[data-mode="dark"][data-theme="orange"] {
    --color-accent-hover:   #fb923c;
    --color-accent-active:  #ea580c;
    --color-accent-faint:   rgba(234, 88, 12, 0.14);
    --color-border-focus:   rgba(234, 88, 12, 0.55);
}
[data-mode="dark"][data-theme="emerald"] {
    --color-accent-hover:   #34d399;
    --color-accent-faint:   rgba(16, 185, 129, 0.14);
    --color-border-focus:   rgba(16, 185, 129, 0.55);
}
[data-mode="dark"][data-theme="teal"] {
    --color-accent-hover:   #14b8a6;
    --color-accent-faint:   rgba(13, 148, 136, 0.14);
    --color-border-focus:   rgba(13, 148, 136, 0.55);
}
[data-mode="dark"][data-theme="blue"] {
    --color-accent-hover:   #60a5fa;
    --color-accent-active:  #2563eb;
    --color-accent-faint:   rgba(59, 130, 246, 0.14);
    --color-border-focus:   rgba(59, 130, 246, 0.55);
}
[data-mode="dark"][data-theme="indigo"] {
    --color-accent-hover:   #6366f1;
    --color-accent-faint:   rgba(79, 70, 229, 0.14);
    --color-border-focus:   rgba(79, 70, 229, 0.55);
}
[data-mode="dark"][data-theme="violet"] {
    --color-accent-hover:   #a78bfa;
    --color-accent-active:  #7c3aed;
    --color-accent-faint:   rgba(124, 58, 237, 0.14);
    --color-border-focus:   rgba(124, 58, 237, 0.55);
}

/* ── LEGACY TOKEN BRIDGE ──────────────────────────────────────────────────
   Pages that opt in with <body class="app-shell"> get the legacy css/themes.css
   variable family (--primary-*, --bg-surface-*, --text-*, --border-*, --shadow-*)
   redirected to the new --color-* tokens. Higher specificity (class+element)
   beats themes.css's :root declarations regardless of stylesheet order.

   This is a transitional shim: it lets the new app shell sit on top of
   not-yet-rebuilt page bodies (m3-* apps, sso-callback) without rewriting
   thousands of lines of page-specific CSS. Delete the bridge once every page
   uses the new --color-* tokens directly. */

body.app-shell {
    --primary:           var(--color-accent);
    --primary-dark:      var(--color-accent-active);
    --primary-darker:    var(--color-accent-active);
    --primary-hover:     var(--color-accent-hover);
    --primary-lightest:  var(--color-accent-faint);
    --primary-light:     var(--color-accent-faint);
    --primary-lighter:   var(--color-accent-faint);
    --primary-ring:      var(--color-accent-faint);
    --primary-shadow:    var(--color-accent-faint);

    --bg-surface:           var(--color-bg-raised-1);
    --bg-surface-secondary: var(--color-bg-base);
    --bg-surface-tertiary:  var(--color-bg-hover);
    --bg-hover:             var(--color-bg-hover);
    --bg-input:             var(--color-bg-raised-2);

    --text-primary:    var(--color-text-strong);
    --text-secondary:  var(--color-text-default);
    --text-tertiary:   var(--color-text-muted);
    --text-muted:      var(--color-text-muted);
    --text-faint:      var(--color-text-faint);

    --border-color:   var(--color-border-subtle);
    --border-medium:  var(--color-border-default);

    --shadow-color: rgba(0, 0, 0, 0.06);
    --shadow-md:    rgba(0, 0, 0, 0.10);
    --shadow-lg:    rgba(0, 0, 0, 0.18);

    /* Soften per-page banner gradients (m3-orders/audits SSO banner uses these
       fallback vars when set; previously fell through to a loud yellow gradient). */
    --sso-banner-bg:      var(--color-warning-faint);
    --sso-banner-border:  var(--color-warning);
    --sso-banner-heading: var(--color-text-strong);
    --sso-banner-text:    var(--color-text-muted);
}

/* Dark-mode bridge adjustments. Legacy CSS uses --primary-dark and
   --primary-darker as text colors in ~20 places (headings, info-values, link
   colors). In light mode these resolve to --color-accent-active (a deep,
   readable accent). In dark mode that same darker shade sits on a near-black
   bg → invisible. Flip both to --color-accent-hover, which design-system.css
   explicitly lightens for every accent's dark variant. */
[data-mode="dark"] body.app-shell {
    --primary-dark:   var(--color-accent-hover);
    --primary-darker: var(--color-accent-hover);
}

/* App-shell page surface — neutral bg + tokens win over legacy styles.css's
   primary-gradient body, white-on-gradient .welcome-heading, and the bare
   <main> / <footer> rules that assumed a colored canvas. */
body.app-shell {
    background: var(--color-bg-base);
    color: var(--color-text-default);
    font-family: var(--font-sans);
    line-height: var(--line-height-base);
}
body.app-shell .welcome-heading {
    color: var(--color-text-strong);
}
body.app-shell .welcome-sub {
    color: var(--color-text-muted);
    opacity: 1;
}
/* Page-section eyebrows use the muted-gray default — high contrast in both
   modes. Brand eyebrow (.app-header-brand-eyebrow) keeps its accent tint. */
body.app-shell .page-header .ds-eyebrow {
    color: var(--color-text-muted);
}
/* Global default size for sprite icons: inline icons inherit the surrounding
   text size (matching the emoji they replaced in the app-wide emoji→icon sweep).
   Component rules that set `… svg { width }` are more specific and win, so
   existing icons (header, cards, buttons, banner) are unaffected. */
.ds-icon {
    width: 1em;
    height: 1em;
    flex-shrink: 0;
    vertical-align: -0.125em;
}

/* Lucide icons rendered inside legacy banner-icon hosts. */
body.app-shell .banner-icon svg.ds-icon {
    width: 32px;
    height: 32px;
    color: var(--color-warning);
}

/* Reconnect button — legacy styles.css hardcodes a blue gradient + blue glow
   that ignores the accent picker. Force it onto the accent tokens so the
   button always matches the user's chosen accent and reads cleanly in both
   modes. Higher specificity (body.app-shell ...) overrides the legacy rule. */
body.app-shell .sso-reconnect-btn {
    background: var(--color-accent);
    box-shadow: none;
    transition: background var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
}
body.app-shell .sso-reconnect-btn:hover {
    background: var(--color-accent-hover);
    box-shadow: none;
}
[data-mode="dark"] body.app-shell .sso-reconnect-btn {
    background: var(--color-accent);
}
[data-mode="dark"] body.app-shell .sso-reconnect-btn:hover {
    background: var(--color-accent-hover);
}

/* Dark-mode SSO banner — each per-page CSS sets a dark-amber gradient that
   reads as a heavy alert. Replace with the subtle warning-tinted card the
   bridge already uses in light mode. */
[data-mode="dark"] body.app-shell .sso-required-banner {
    --sso-banner-bg:      var(--color-warning-faint);
    --sso-banner-border:  var(--color-warning);
    --sso-banner-heading: var(--color-text-strong);
    --sso-banner-text:    var(--color-text-muted);
}

/* ============================================================================
   ELEMENT BASELINES (a deliberately small reset)
   ============================================================================ */

*, *::before, *::after { box-sizing: border-box; }

html {
    -webkit-text-size-adjust: 100%;
    color-scheme: light;
}
[data-mode="dark"] html { color-scheme: dark; }

body {
    margin: 0;
    background: var(--color-bg-base);
    color: var(--color-text-default);
    font-family: var(--font-sans);
    font-size: var(--font-size-base);
    line-height: var(--line-height-base);
    font-weight: var(--font-weight-regular);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, h5, h6 {
    margin: 0;
    color: var(--color-text-strong);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-tight);
    line-height: var(--line-height-tight);
}
h1 { font-size: var(--font-size-2xl); }
h2 { font-size: var(--font-size-xl); }
h3 { font-size: var(--font-size-lg); }
h4 { font-size: var(--font-size-md); }
h5, h6 { font-size: var(--font-size-base); }

p { margin: 0; }

a {
    color: inherit;
    text-decoration: none;
    transition: color var(--duration-fast) var(--ease-out);
}
a:hover { color: var(--color-accent-hover); }

button, input, select, textarea {
    font: inherit;
    color: inherit;
}

/* Focus ring — visible on any keyboard-focused element, regardless of element
   type. Mouse focus on buttons doesn't show the ring (`:focus-visible`). */
:focus { outline: none; }
:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus-ring);
    border-radius: var(--radius-sm);
}

/* Skip link — visible only when focused (keyboard) */
.skip-link {
    position: absolute;
    left: var(--space-3);
    top: var(--space-3);
    padding: var(--space-2) var(--space-4);
    background: var(--color-accent);
    color: var(--color-text-on-accent);
    border-radius: var(--radius-md);
    font-weight: var(--font-weight-semibold);
    z-index: var(--z-tooltip);
    transform: translateY(-200%);
    transition: transform var(--duration-fast) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

/* ============================================================================
   REUSABLE COMPONENT CLASSES
   ----------------------------------------------------------------------------
   Small, sturdy classes the R1 rebuilds use directly. Per-page CSS can extend
   them; new code should prefer these over hand-rolled rules.
   ============================================================================ */

/* ── Container ───────────────────────────────────────────────────────────── */

.ds-container {
    max-width: var(--layout-page-max);
    margin: 0 auto;
    padding: 0 var(--space-5);
}

.ds-container--narrow { max-width: var(--layout-narrow); }
.ds-container--content { max-width: var(--layout-content); }

/* ── Buttons ─────────────────────────────────────────────────────────────── */

.ds-btn {
    --btn-bg:       var(--color-bg-raised-2);
    --btn-bg-hover: var(--color-bg-raised-3);
    --btn-fg:       var(--color-text-strong);
    --btn-border:   var(--color-border-default);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    height: 36px;

    background: var(--btn-bg);
    color: var(--btn-fg);
    border: 1px solid var(--btn-border);
    border-radius: var(--radius-md);

    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    line-height: 1;
    letter-spacing: var(--letter-spacing-normal);

    cursor: pointer;
    transition: background var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                transform var(--duration-fast) var(--ease-out);
    white-space: nowrap;
    user-select: none;
}
.ds-btn:hover { background: var(--btn-bg-hover); }
.ds-btn:active { transform: translateY(1px); }
.ds-btn[disabled],
.ds-btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

.ds-btn--primary {
    --btn-bg:       var(--color-accent);
    --btn-bg-hover: var(--color-accent-hover);
    --btn-fg:       var(--color-text-on-accent);
    --btn-border:   transparent;
}

.ds-btn--ghost {
    --btn-bg:       transparent;
    --btn-bg-hover: var(--color-bg-hover);
    --btn-border:   transparent;
}

.ds-btn--danger {
    --btn-bg:       transparent;
    --btn-bg-hover: var(--color-danger-faint);
    --btn-fg:       var(--color-danger);
    --btn-border:   var(--color-danger);
}

.ds-btn--lg {
    height: 44px;
    padding: var(--space-3) var(--space-5);
    font-size: var(--font-size-base);
}

.ds-btn--sm {
    height: 28px;
    padding: var(--space-1) var(--space-3);
    font-size: var(--font-size-xs);
}

.ds-btn--icon-only {
    width: 36px;
    padding: 0;
}
.ds-btn--icon-only.ds-btn--sm { width: 28px; }
.ds-btn--icon-only.ds-btn--lg { width: 44px; }

/* SVG icons inside buttons */
.ds-btn svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    /* `currentColor` on the SVG paths so a single token controls icon colour */
    color: currentColor;
}
.ds-btn--lg svg { width: 18px; height: 18px; }
.ds-btn--sm svg { width: 14px; height: 14px; }

/* ── Cards ───────────────────────────────────────────────────────────────── */

.ds-card {
    background: var(--color-bg-raised-1);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-xl);
    padding: var(--space-5);
    box-shadow: var(--shadow-raised);
}

.ds-card--flat {
    box-shadow: none;
    background: transparent;
    border-color: var(--color-border-default);
}

/* ── Inputs ──────────────────────────────────────────────────────────────── */

.ds-field {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.ds-field-label {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    color: var(--color-text-muted);
}

.ds-input,
.ds-select,
.ds-textarea {
    width: 100%;
    padding: var(--space-2) var(--space-3);
    height: 36px;
    background: var(--color-bg-raised-2);
    color: var(--color-text-strong);
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-md);
    font-size: var(--font-size-base);
    line-height: 1.4;
    transition: border-color var(--duration-fast) var(--ease-out),
                background var(--duration-fast) var(--ease-out);
}
.ds-textarea {
    height: auto;
    min-height: 88px;
    padding: var(--space-3);
    resize: vertical;
}
.ds-input:hover,
.ds-select:hover,
.ds-textarea:hover { border-color: var(--color-border-strong); }
.ds-input::placeholder,
.ds-textarea::placeholder { color: var(--color-text-faint); }

/* ── Labels / Badges ────────────────────────────────────────────────────── */

.ds-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 2px var(--space-2);
    background: var(--color-bg-raised-2);
    color: var(--color-text-muted);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-full);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--letter-spacing-caps);
    text-transform: uppercase;
}
.ds-badge--success {
    background: var(--color-success-faint);
    color: var(--color-success);
    border-color: transparent;
}
.ds-badge--warning {
    background: var(--color-warning-faint);
    color: var(--color-warning);
    border-color: transparent;
}
.ds-badge--danger {
    background: var(--color-danger-faint);
    color: var(--color-danger);
    border-color: transparent;
}
.ds-badge--info {
    background: var(--color-info-faint);
    color: var(--color-info);
    border-color: transparent;
}

/* ── Env badge ───────────────────────────────────────────────────────────── */
/* Session-environment indicator rendered on every authenticated page by
   js/about.js → initEnvBadge. PRD is pinned to red so a CSR can never
   perform a real M3 write thinking they're in test — that distinction is
   load-bearing and must not depend on the accent. TST follows the user's
   accent (per UX request). TRN stays amber as a neutral "non-prod" tint. */
.env-badge {
    display: inline-block;
    padding: 0.15rem 0.45rem;
    border-radius: 4px;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: #fff;
    vertical-align: middle;
    margin-left: 0.5rem;
    text-transform: uppercase;
    line-height: 1.4;
}
.env-badge--tst { background: var(--color-accent); }
.env-badge--trn { background: #F59E0B; }
.env-badge--prd { background: #DC2626; }

/* When placed in the modern app header, the badge is a sibling between the
   brand link and the action nav inside a `justify-content: space-between` flex
   row. margin-right:auto pushes the actions to the right edge so the badge
   stays glued to the brand instead of floating centered. */
.app-header-inner .env-badge {
    margin-left: 0.5rem;
    margin-right: auto;
}

@media (prefers-reduced-motion: no-preference) {
    .env-badge { animation: env-badge-pulse 2.5s ease-in-out infinite; }
}
@keyframes env-badge-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

/* ── Eyebrow / Section heading ───────────────────────────────────────────── */

.ds-eyebrow {
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-muted);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-caps);
}

/* ── Stacks (vertical/horizontal flow with consistent gap) ───────────────── */

.ds-stack { display: flex; flex-direction: column; gap: var(--space-3); }
.ds-stack--sm { gap: var(--space-2); }
.ds-stack--lg { gap: var(--space-5); }

.ds-row { display: flex; align-items: center; gap: var(--space-3); }
.ds-row--sm { gap: var(--space-2); }
.ds-row--lg { gap: var(--space-5); }
.ds-row--between { justify-content: space-between; }

/* ── Visually-hidden (for screen-reader-only labels) ─────────────────────── */

.ds-visually-hidden {
    position: absolute !important;
    width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%);
    white-space: nowrap; border: 0;
}

/* SSO-required banner — shown when an M3 SSO session is missing/expired.
   Previously duplicated byte-for-byte in 9 per-page CSS files. Dark-mode
   colors are handled by the body.app-shell bridge above (lines ~429-434). */
.sso-required-banner {
    background: var(--sso-banner-bg);
    border: 1px solid var(--sso-banner-border);
    border-radius: var(--radius-md);
    padding: var(--space-6);
    text-align: center;
    margin-bottom: var(--space-5);
}
.sso-required-banner .banner-icon {
    font-size: 2.5rem;
    margin-bottom: var(--space-3);
}
.sso-required-banner h3 {
    color: var(--sso-banner-heading);
    font-size: var(--font-size-lg);
    margin-bottom: var(--space-2);
}
.sso-required-banner p {
    color: var(--sso-banner-text);
    font-size: var(--font-size-sm);
    max-width: 500px;
    margin: 0 auto;
    line-height: var(--line-height-base);
}

/* ============================================================================
   MOTION — respects user preference
   ============================================================================ */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ============================================================================
   PRINT — for the rare table-export case
   ============================================================================ */

@media print {
    :root {
        --color-bg-base: #ffffff;
        --color-text-default: #000000;
        --color-text-strong: #000000;
    }
    body { background: #ffffff; color: #000000; }
    .ds-btn, header, footer, nav { display: none !important; }
}

/* Spin for loading icons (loader-circle). */
@keyframes ds-spin { to { transform: rotate(360deg); } }
