/*! MoonSync UI v0.1.0-dev | css bundle | built 2026-06-12T05:07:21.821Z */
/* tokens.css */
/**
 * engine/ui/tokens.css — Design System Tokens
 *
 * SINGLE SOURCE OF TRUTH for all design tokens used by engine + 1_5_4+.
 * Every value here exists exactly once. Duplicate declarations were the
 * root cause of the "inconsistent look" reported 2026-04-21.
 *
 * Theme: Earth — Forest Green primary, Warm Beige secondary.
 * Aligned with UX_STANDARDS.md. Backward-compatible with legacy token
 * names (--spacing-*, --font-size-*, --radius, --transition-*).
 *
 * Phase 5 consolidation 2026-04-21.
 */

:root {
  /* ═══════════════════════════════════════════════════════════════════════
     BRAND PALETTE
     ═══════════════════════════════════════════════════════════════════════ */

  /* Primary — Forest Green. Used for actions, active states, links. */
  --color-primary-50:  #EFF6ED;
  --color-primary-100: #D4E6D8;
  --color-primary-200: #A8D5BA;
  --color-primary-300: #8EBC8A;
  --color-primary-400: #7BA572;   /* brand anchor */
  --color-primary-500: #649158;
  --color-primary-600: #5A8659;
  --color-primary-700: #3D5C3C;
  --color-primary-800: #2B4030;
  --color-primary-900: #1C2C20;

  --color-primary:         var(--color-primary-400);
  --color-primary-light:   var(--color-primary-200);
  --color-primary-lighter: var(--color-primary-100);
  --color-primary-dark:    var(--color-primary-600);
  --color-primary-darker:  var(--color-primary-700);
  --color-primary-rgb:     123, 165, 114;  /* must match --color-primary-400 */
  /* Unprefixed legacy aliases (Bootstrap-ish) */
  --primary:               var(--color-primary);
  --primary-color:         var(--color-primary);
  --primary-rgb:           var(--color-primary-rgb);
  --color-accent-gold:     var(--color-warning);  /* old 3-accent palette fallback */

  /* Secondary — Warm Beige. Headers, dividers, neutral surfaces. */
  --color-secondary-50:  #F5F1EA;
  --color-secondary-100: #E8E4D8;
  --color-secondary-200: #D4C5B9;
  --color-secondary-300: #B8A98E;   /* brand anchor */
  --color-secondary-400: #A39378;
  --color-secondary-500: #8A7E6A;
  --color-secondary-600: #6B6150;
  --color-secondary-700: #5C5446;
  --color-secondary-800: #3D362C;

  --color-secondary:         var(--color-secondary-300);
  --color-secondary-light:   var(--color-secondary-200);
  --color-secondary-lighter: var(--color-secondary-100);
  --color-secondary-dark:    var(--color-secondary-500);
  --color-secondary-darker:  var(--color-secondary-700);
  --color-secondary-rgb:     184, 169, 142;

  /* Accent — single accent (Deep Teal). Warm/gold variants are reserved
     for semantic use (warning, info) to avoid palette fragmentation. */
  --color-accent:        #2A6A80;
  --color-accent-light:  #4F8EA4;
  --color-accent-dark:   #1D4D5C;
  --color-accent-rgb:    42, 106, 128;

  /* ── Shell accent (workspace chrome only — overridable by JS accent picker) ──
     Set these three on :root via element.style.setProperty() to change the
     sidebar active bar, brand icon, and active tint without touching the
     rest of the design system. */
  --shell-accent:      var(--color-primary-700);
  --shell-accent-fg:   #ffffff;
  --shell-accent-rgb:  var(--color-primary-rgb);
  --shell-accent-soft: rgba(var(--color-primary-rgb), 0.07);

  /* Dynamic UI accent bridge. Components should use these tokens for brand,
     selected, focus, hover, and active UI states so shell accent changes
     propagate without page-local CSS overrides. */
  --ui-accent:          var(--shell-accent);
  --ui-accent-fg:       var(--shell-accent-fg);
  --ui-accent-rgb:      var(--shell-accent-rgb);
  --ui-accent-soft:     var(--shell-accent-soft);
  --ui-accent-muted:    rgba(var(--ui-accent-rgb), 0.12);
  --ui-accent-active:   rgba(var(--ui-accent-rgb), 0.18);
  --ui-accent-selected: rgba(var(--ui-accent-rgb), 0.14);
  --ui-focus-ring:      rgba(var(--ui-accent-rgb), 0.32);
  --ui-control-bg:      var(--bg-primary);
  --ui-control-border:  var(--border-color);
  --ui-control-hover:   var(--ui-accent-soft);
  --ui-control-active:  var(--ui-accent-active);
  --ui-link:            var(--ui-accent);
  --ui-link-hover:      var(--ui-accent);

  /* ═══════════════════════════════════════════════════════════════════════
     NEUTRAL SCALE — canonical grays
     ═══════════════════════════════════════════════════════════════════════ */
  --color-white: #FFFFFF;
  --color-black: #000000;

  --color-gray-50:  #FAFAF9;
  --color-gray-100: #F5F4F2;
  --color-gray-200: #E8E4D8;
  --color-gray-300: #D9D3CC;
  --color-gray-400: #B8B2A8;
  --color-gray-500: #8A857C;
  --color-gray-600: #5C5852;
  --color-gray-700: #3D3A36;
  --color-gray-800: #2A2824;
  --color-gray-900: #1A1916;

  /* ═══════════════════════════════════════════════════════════════════════
     SEMANTIC COLORS
     ═══════════════════════════════════════════════════════════════════════ */
  --color-success:       #2F7D3A;
  --color-success-light: #4AA055;
  --color-success-dark:  #1F5626;
  --color-success-bg:    #E4F1E5;
  --color-success-rgb:   47, 125, 58;

  --color-error:         #B23A3A;
  --color-error-light:   #D06060;
  --color-error-dark:    #7A2828;
  --color-error-bg:      #F7E4E4;
  --color-error-rgb:     178, 58, 58;

  --color-warning:       #B8832A;
  --color-warning-light: #D6A84A;
  --color-warning-dark:  #8C5F1E;
  --color-warning-bg:    #F7ECD4;
  --color-warning-rgb:   184, 131, 42;

  --color-info:          var(--color-accent);
  --color-info-light:    var(--color-accent-light);
  --color-info-bg:       #DDE9EE;
  --color-info-rgb:      var(--color-accent-rgb);

  /* Numbered scale — used by components for color-mix() tints and status variants.
     Values are aliased from the existing semantic tokens above. */
  --color-success-300: #7DC88A;
  --color-success-400: #4AA055;   /* = --color-success-light */
  --color-success-500: #2F7D3A;   /* = --color-success */
  --color-success-600: #266832;
  --color-success-700: #1F5626;   /* = --color-success-dark */

  --color-danger-300:  #E8A0A0;
  --color-danger-400:  #D06060;   /* = --color-error-light */
  --color-danger-500:  #B23A3A;   /* = --color-error */
  --color-danger-600:  #962F2F;
  --color-danger-700:  #7A2828;   /* = --color-error-dark */

  --color-warning-400: #D6A84A;   /* = --color-warning-light */
  --color-warning-500: #B8832A;   /* = --color-warning */
  --color-warning-600: #A06B1A;
  --color-warning-700: #8C5F1E;   /* = --color-warning-dark */

  /* Legacy aliases (Bootstrap-ish naming from pre-engine view CSS) */
  --color-danger:        var(--color-error);
  --color-danger-light:  var(--color-error-light);
  --color-danger-bg:     var(--color-error-bg);
  --color-danger-rgb:    var(--color-error-rgb);

  --color-primary-bg:    rgba(var(--ui-accent-rgb), 0.08);  /* tint-primary-8-ish */

  /* ═══════════════════════════════════════════════════════════════════════
     SURFACES (bg-*)
     ═══════════════════════════════════════════════════════════════════════ */
  --bg-body:        #F9F8F5;
  --bg-primary:     #FFFFFF;
  --bg-secondary:   var(--color-gray-100);
  --bg-tertiary:    var(--color-gray-200);
  --bg-card:        #FFFFFF;
  --bg-card-hover:  #FAFAFA;
  --bg-subtle:      var(--color-gray-50);
  --bg-muted:       var(--bg-subtle);
  --surface-overlay: rgba(255, 255, 255, 0.94);
  --bg-light:           var(--bg-subtle);    /* legacy alias */
  --bg-surface:         var(--bg-card);      /* legacy alias */
  --bg-secondary-light: var(--bg-subtle);    /* legacy alias */
  --bg-primary-light:   var(--bg-subtle);    /* legacy alias */

  /* Legacy color-bg* aliases (from pre-engine view CSS) */
  --color-bg:           var(--bg-body);
  --color-bg-hover:     var(--bg-hover);
  --color-bg-light:     var(--bg-subtle);
  --color-bg-secondary: var(--bg-secondary);
  --color-surface:      var(--bg-card);
  --color-surface-alt:  var(--bg-card-hover);
  --color-background-soft: var(--bg-subtle);
  --color-hover:        var(--bg-hover);

  /* Interactive tints — DERIVED from --color-primary-rgb so hover/active
     always match the primary color. This was the #1 coherence bug. */
  --bg-hover:            rgba(var(--ui-accent-rgb), 0.08);
  --bg-hover-secondary:  rgba(var(--color-secondary-rgb), 0.10);
  --bg-active:           rgba(var(--ui-accent-rgb), 0.16);
  --bg-selected:         rgba(var(--ui-accent-rgb), 0.12);

  /* Progress / skeleton background */
  --bg-progress: var(--color-gray-200);  /* flat per 2026-04-21 no-gradient direction */

  /* ═══════════════════════════════════════════════════════════════════════
     TINTS — all derived from brand RGBs (no hardcoded mismatches)
     ═══════════════════════════════════════════════════════════════════════ */
  --tint-primary-5:   rgba(var(--ui-accent-rgb), 0.05);
  --tint-primary-10:  rgba(var(--ui-accent-rgb), 0.10);
  --tint-primary-15:  rgba(var(--ui-accent-rgb), 0.15);
  --tint-primary-20:  rgba(var(--ui-accent-rgb), 0.20);
  --tint-primary-30:  rgba(var(--ui-accent-rgb), 0.30);

  --tint-secondary-5:  rgba(var(--color-secondary-rgb), 0.05);
  --tint-secondary-10: rgba(var(--color-secondary-rgb), 0.10);
  --tint-secondary-15: rgba(var(--color-secondary-rgb), 0.15);
  --tint-secondary-20: rgba(var(--color-secondary-rgb), 0.20);

  --tint-white-25: rgba(255, 255, 255, 0.25);
  --tint-white-30: rgba(255, 255, 255, 0.30);
  --tint-white-95: rgba(255, 255, 255, 0.95);
  --tint-white-98: rgba(255, 255, 255, 0.98);

  --tint-black-5:  rgba(0, 0, 0, 0.05);
  --tint-black-10: rgba(0, 0, 0, 0.10);
  --tint-black-20: rgba(0, 0, 0, 0.20);

  /* ═══════════════════════════════════════════════════════════════════════
     TEXT
     ═══════════════════════════════════════════════════════════════════════ */
  --text-primary:   #2E2B28;    /* body */
  --text-secondary: #5C5852;    /* subtitles, labels */
  --text-muted:     #8A857C;    /* hints, timestamps */
  --text-light:     #B8B2A8;    /* placeholders */
  --text-tertiary:  var(--text-muted);
  --text-white:     #FFFFFF;
  --text-inverse:   #FFFFFF;
  --text-link:       var(--ui-link);
  --text-link-hover: var(--ui-link-hover);

  --color-text-primary:   var(--text-primary);
  --color-text-secondary: var(--text-secondary);
  --color-text-muted:     var(--text-muted);
  --color-text:           var(--text-primary);  /* legacy alias for --text-primary */
  --text-main:            var(--text-primary);  /* legacy alias for --text-primary */
  --color-text-dark:      var(--text-primary);  /* legacy alias */
  --color-text-placeholder: var(--text-light);  /* legacy alias */

  /* ═══════════════════════════════════════════════════════════════════════
     BORDERS
     ═══════════════════════════════════════════════════════════════════════ */
  --border-color:       var(--color-gray-300);
  --border-color-light: var(--color-gray-200);
  --border-color-dark:  var(--color-gray-400);
  --border-light:       var(--border-color-light);  /* legacy alias */
  --border-focus:       var(--ui-accent);

  --color-border:       var(--border-color);
  --color-border-light: var(--border-color-light);

  /* Focus ring — WCAG 2.4.11 compliant (3:1 against adjacent colors) */
  --color-focus-ring:   var(--ui-accent);
  --focus-ring-width:   3px;
  --focus-ring-offset:  2px;
  --shadow-focus:       0 0 0 var(--focus-ring-width) var(--ui-focus-ring);

  /* ═══════════════════════════════════════════════════════════════════════
     ELEVATION — SINGLE shadow system (removed duplicate "bold" set)
     ═══════════════════════════════════════════════════════════════════════ */
  --shadow-none: none;
  --shadow-xs:   0 1px 2px rgba(26, 21, 16, 0.06);
  --shadow-sm:   0 1px 3px rgba(26, 21, 16, 0.08), 0 1px 2px rgba(26, 21, 16, 0.04);
  --shadow:      0 2px 6px rgba(26, 21, 16, 0.08), 0 1px 3px rgba(26, 21, 16, 0.06);
  --shadow-md:   0 4px 12px rgba(26, 21, 16, 0.10), 0 2px 4px rgba(26, 21, 16, 0.06);
  --shadow-lg:   0 10px 24px rgba(26, 21, 16, 0.12), 0 4px 8px rgba(26, 21, 16, 0.06);
  --shadow-xl:   0 20px 48px rgba(26, 21, 16, 0.14), 0 8px 16px rgba(26, 21, 16, 0.08);
  --shadow-inner: inset 0 2px 4px rgba(0, 0, 0, 0.06);
  --shadow-card:  var(--shadow-md);
  --shadow-glow:  0 0 16px rgba(var(--ui-accent-rgb), 0.35);

  /* Button shadows — derived from primary so hover glow matches color */
  --shadow-btn-primary:       0 4px 12px rgba(var(--ui-accent-rgb), 0.35);
  --shadow-btn-primary-hover: 0 6px 20px rgba(var(--ui-accent-rgb), 0.45);
  --shadow-progress:          0 2px 8px rgba(var(--ui-accent-rgb), 0.35);

  /* ═══════════════════════════════════════════════════════════════════════
     GRADIENTS — flattened to solid colors (single-stop). The design
     direction decided 2026-04-21 is flat color across all components;
     tokens are kept for backward compatibility with legacy page CSS
     that still references `var(--gradient-*)`, but every one resolves
     to a single color so nothing renders with a visible color ramp.
     Do NOT use these for new work — use the solid color tokens above.
     ═══════════════════════════════════════════════════════════════════════ */
  --gradient-body:          var(--bg-body);
  --gradient-primary:       var(--ui-accent);
  --gradient-primary-hover: var(--ui-accent);
  --gradient-secondary:     var(--color-secondary-500);
  --gradient-accent:        var(--color-accent);
  --gradient-card:          var(--bg-card);
  --gradient-card-hover:    var(--bg-card-hover);
  --gradient-header:        var(--bg-primary);
  --gradient-progress:      var(--ui-accent);

  /* ═══════════════════════════════════════════════════════════════════════
     SPACING — 4px base. Numeric scale is canonical; t-shirt aliases kept
     for existing callsites.
     ═══════════════════════════════════════════════════════════════════════ */
  --space-0:   0;
  --space-1:   4px;
  --space-2:   8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-7:  28px;
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;

  --spacing-xs:  var(--space-1);
  --spacing-sm:  var(--space-2);
  --spacing-md:  var(--space-4);
  --spacing-lg:  var(--space-6);
  --spacing-xl:  var(--space-8);
  --spacing-2xl: var(--space-12);

  /* ═══════════════════════════════════════════════════════════════════════
     RADIUS — one scale, aliased for legacy
     ═══════════════════════════════════════════════════════════════════════ */
  --radius-none: 0;
  --radius-xs:   2px;
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:  12px;
  --radius-xl:  16px;
  --radius-2xl: 24px;
  --radius-full: 9999px;

  --radius: var(--radius-md);   /* default */

  /* ═══════════════════════════════════════════════════════════════════════
     TYPOGRAPHY — font-family matches what is actually loaded (Sarabun +
     system stack). Poppins reference removed — it was declared but never
     loaded, producing a silent fallback that hid the real rendering.
     ═══════════════════════════════════════════════════════════════════════ */
  --font-family: 'Sarabun', -apple-system, BlinkMacSystemFont, 'Segoe UI',
                 'Noto Sans Thai', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-family-display: var(--font-family);
  --font-mono: 'SF Mono', 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
  --font-family-mono: var(--font-mono);  /* legacy alias */

  /* Type scale — px values as spec. rem aliases kept for legacy callsites. */
  --text-xs:   12px;   /* LH 16 */
  --text-sm:   14px;   /* LH 20 */
  --text-base: 16px;   /* LH 24 — body default */
  --text-lg:   18px;   /* LH 28 */
  --text-xl:   20px;   /* LH 28 */
  --text-2xl:  24px;   /* LH 32 */
  --text-3xl:  30px;   /* LH 36 */
  --text-4xl:  36px;   /* LH 40 */
  --text-5xl:  48px;   /* LH 52 */

  --font-size-xs:   0.75rem;
  --font-size-sm:   0.875rem;
  --font-size-base: 1rem;
  --font-size-md:   1rem;
  --font-size-lg:   1.125rem;
  --font-size-xl:   1.25rem;
  --font-size-xxl:  1.5rem;  /* legacy alias for --font-size-2xl */
  --font-size-2xl:  1.5rem;
  --font-size-3xl:  1.875rem;

  /* Semantic size aliases for older view CSS */
  --label-font-size: var(--font-size-sm);
  --event-font-size: var(--font-size-xs);

  --font-weight-light:    300;
  --font-weight-normal:   400;
  --font-weight-medium:   500;
  --font-weight-semibold: 600;
  --font-weight-bold:     700;
  --font-medium:          var(--font-weight-medium);   /* legacy alias */
  --font-bold:            var(--font-weight-bold);     /* legacy alias */
  --font-normal:          var(--font-weight-normal);   /* legacy alias */
  --font-semibold:        var(--font-weight-semibold); /* legacy alias */

  --line-height-tight:   1.2;
  --line-height-snug:    1.35;
  --line-height-normal:  1.5;
  --line-height-relaxed: 1.75;

  --letter-spacing-tight:  -0.01em;
  --letter-spacing-normal:  0;
  --letter-spacing-wide:    0.02em;

  /* ═══════════════════════════════════════════════════════════════════════
     MOTION — duration + easing split; bundled --transition-* kept for legacy
     ═══════════════════════════════════════════════════════════════════════ */
  --duration-instant: 100ms;
  --duration-fast:    150ms;
  --duration-normal:  250ms;
  --duration-slow:    400ms;
  --duration-slower:  600ms;

  --ease-standard:   cubic-bezier(0.4, 0, 0.2, 1);
  --ease-accelerate: cubic-bezier(0.4, 0, 1, 1);
  --ease-decelerate: cubic-bezier(0, 0, 0.2, 1);
  --ease-bounce:     cubic-bezier(0.68, -0.55, 0.265, 1.55);

  --transition-fast:   var(--duration-fast) var(--ease-standard);
  --transition:        var(--duration-normal) var(--ease-standard);
  --transition-normal: var(--duration-normal) var(--ease-standard);
  --transition-slow:   var(--duration-slow) var(--ease-standard);
  --transition-bounce: var(--duration-slow) var(--ease-bounce);

  /* ═══════════════════════════════════════════════════════════════════════
     LAYOUT
     ═══════════════════════════════════════════════════════════════════════ */
  --header-height:           64px;
  --header-height-mobile:    56px;
  --sidebar-width:           260px;
  --sidebar-collapsed-width: 64px;
  --content-max-width:       1600px;
  --content-gutter:          var(--space-6);

  /* ═══════════════════════════════════════════════════════════════════════
     BREAKPOINTS — exposed for JS (CSS @media still needs literal px)
     ═══════════════════════════════════════════════════════════════════════ */
  --breakpoint-xs:  480px;
  --breakpoint-sm:  640px;
  --breakpoint-md:  768px;
  --breakpoint-lg: 1024px;
  --breakpoint-xl: 1280px;
  --breakpoint-2xl: 1536px;

  /* ═══════════════════════════════════════════════════════════════════════
     Z-INDEX
     ═══════════════════════════════════════════════════════════════════════ */
  --z-base:            0;
  --z-dropdown:      100;
  --z-sticky:        200;
  --z-fixed:         300;
  --z-header:       1000;
  --z-modal-backdrop: 1100;
  --z-modal:        1200;
  --z-popover:      1300;
  --z-tooltip:      1400;
  --z-toast:        1500;
  --z-debug:        9999;

  /* ═══════════════════════════════════════════════════════════════════════
     COMPONENT SIZING
     ═══════════════════════════════════════════════════════════════════════ */
  --input-height:    40px;
  --input-height-xs: 24px;
  --input-height-sm: 32px;
  --input-height-lg: 48px;
  --input-padding-x: var(--space-3);

  --btn-height:    40px;
  --btn-height-xs: 24px;
  --btn-height-sm: 32px;
  --btn-height-lg: 48px;
  --btn-padding-x: var(--space-4);

  /* Icon button sizes (square buttons for icons only) */
  --icon-btn-height:    40px;
  --icon-btn-height-xs: 28px;
  --icon-btn-height-sm: 32px;
  --icon-btn-height-lg: 48px;

  --table-row-height: 48px;
  --table-header-bg:  var(--bg-secondary);
  --table-stripe-bg:  rgba(0, 0, 0, 0.02);
  --table-hover-bg:   var(--bg-hover);

  /* Touch target baseline (WCAG 2.5.8) */
  --touch-target: 44px;

  --root-font-size: 16px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   DARK THEME — class + data-theme toggle
   ═══════════════════════════════════════════════════════════════════════════ */
[data-theme="dark"],
.dark-mode {
  --bg-body:       #16181C;
  --bg-primary:    #1E2127;
  --bg-secondary:  #262A31;
  --bg-tertiary:   #2F343C;
  --bg-card:       #1E2127;
  --bg-card-hover: #262A31;
  --bg-subtle:     #1A1D22;
  --bg-muted:      var(--bg-subtle);
  --surface-overlay: rgba(30, 33, 39, 0.96);

  --bg-hover:      rgba(var(--ui-accent-rgb), 0.12);
  --bg-hover-secondary: rgba(var(--color-secondary-rgb), 0.12);
  --bg-active:     rgba(var(--ui-accent-rgb), 0.20);
  --bg-selected:   rgba(var(--ui-accent-rgb), 0.16);

  /* Flat per 2026-04-21 no-gradient direction (dark overrides) */
  --gradient-body:   var(--bg-body);
  --gradient-card:   var(--bg-card);
  --gradient-header: var(--bg-primary);

  --text-primary:   #EDEEF0;
  --text-secondary: #B4B8BF;
  --text-muted:     #7A7F88;
  --text-light:     #4A4F58;
  --text-tertiary:  var(--text-muted);
  --text-link:       var(--ui-link);
  --text-link-hover: var(--ui-link-hover);

  --border-color:       #343940;
  --border-color-light: #262A31;
  --border-color-dark:  #444B55;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35);
  --shadow:    0 2px 6px rgba(0, 0, 0, 0.40);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 10px 24px rgba(0, 0, 0, 0.50);
  --shadow-xl: 0 20px 48px rgba(0, 0, 0, 0.55);

  /* Shell accent dark-mode overrides — higher alpha for dark bg readability */
  --shell-accent-soft: rgba(var(--ui-accent-rgb), 0.16);

  /* Surface tokens missing from dark block */
  --bg-progress:     #2F343C;
  --table-stripe-bg: rgba(255, 255, 255, 0.03);

  /* Semantic numbered scale — 700/600 text tokens need to be lighter on dark
     backgrounds; 400/500 border+tint bases are intentionally kept as-is since
     they mix with the overridden --bg-card value. */
  --color-success-600: #4AA055;
  --color-success-700: #5DB56B;
  --color-danger-600:  #D06060;
  --color-danger-700:  #E07070;
  --color-warning-600: #C89030;
  --color-warning-700: #E0B04A;
}

/* ═══════════════════════════════════════════════════════════════════════════
   ACCENT THEME VARIANTS — alternate brand skins
   Same token contract, different primary family. Applied on <body> or a
   container via `data-theme="blue"` etc.
   ═══════════════════════════════════════════════════════════════════════════ */

[data-theme="blue"],
.theme-service {
  --color-primary-100: #C4D9F4;
  --color-primary-200: #A3C4ED;
  --color-primary-300: #7DA7DF;
  --color-primary-400: #5B8DD9;
  --color-primary-500: #4A7DC9;
  --color-primary-600: #3D6BB3;
  --color-primary-700: #2D5090;
  --color-primary-800: #1F3A6B;

  --color-primary:         var(--color-primary-400);
  --color-primary-light:   var(--color-primary-200);
  --color-primary-lighter: var(--color-primary-100);
  --color-primary-dark:    var(--color-primary-600);
  --color-primary-darker:  var(--color-primary-700);
  --color-primary-rgb:     91, 141, 217;
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOTION — reduced-motion override (WCAG 2.3.3)
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* reset.css */
/**
 * App Base Styles
 * Reset, typography, and global element styles
 */

/* ======================================
   Utilities
   ====================================== */
.position-relative {
    position: relative !important;
}

.w-100 {
    width: 100% !important;
}

.h-100 {
    height: 100% !important;
}

.line-height-1 {
    line-height: 1.2 !important;
}

/* ======================================
   CSS Reset
   ====================================== */
*,
*::before,
*::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    /* Base font size for desktop */
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Mobile-only font scaling */
@media (max-width: 1024px) {
    html {
        font-size: var(--root-font-size, 16px);
    }
}

body {
    font-family: var(--font-family);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-normal);
    line-height: var(--line-height-normal);
    color: var(--text-primary);
    background-color: var(--bg-body);
    min-height: 100vh;
    min-height: 100dvh;
    overflow-x: hidden;
}

/* ======================================
   Typography & Text Management
   ====================================== */
.text-truncate,
.truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
    display: inline-block;
}

/* Global overflow protection for common UI elements on mobile */
@media (max-width: 1024px) {

    /* Ensure flex containers allow children to truncate */
    .nav-link,
    .dropdown-item,
    .navbar-brand,
    .card-header,
    .btn {
        min-width: 0;
    }

    /* Target text containers specifically */
    .nav-link span,
    .dropdown-item span,
    .card-title,
    .brand-text,
    h1,
    h2,
    h3,
    h4,
    h5,
    h6,
    p {
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        max-width: 100%;
    }

    /* Required for consistency */
    .card-title,
    .brand-text {
        max-width: 100%;
    }
}

/* Special case for flex children */
.nav-link span,
.dropdown-item span {
    display: inline-block;
    vertical-align: middle;
}

h1,
h2,
h3,
h4,
h5,
h6 {
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
    color: var(--text-primary);
    margin-bottom: var(--spacing-sm);
}

h1 {
    font-size: var(--font-size-3xl);
}

h2 {
    font-size: var(--font-size-2xl);
}

h3 {
    font-size: var(--font-size-xl);
}

h4 {
    font-size: var(--font-size-lg);
}

h5 {
    font-size: var(--font-size-md);
}

h6 {
    font-size: var(--font-size-base);
}

p {
    margin-bottom: var(--spacing-md);
}

a {
    color: var(--text-link);
    text-decoration: none;
    transition: color var(--transition-fast);
}

a:hover {
    color: var(--ui-link-hover);
}

strong,
b {
    font-weight: var(--font-weight-semibold);
}

small {
    font-size: var(--font-size-sm);
}

code,
pre {
    font-family: var(--font-mono);
    font-size: var(--font-size-sm);
}

code {
    background: var(--bg-tertiary);
    padding: 2px 6px;
    border-radius: var(--radius-sm);
}

pre {
    background: var(--bg-secondary);
    padding: var(--spacing-md);
    border-radius: var(--radius);
    overflow-x: auto;
}

/* ======================================
   Lists
   ====================================== */
ul,
ol {
    padding-left: var(--spacing-lg);
    margin-bottom: var(--spacing-md);
}

li {
    margin-bottom: var(--spacing-xs);
}

/* ======================================
   Images & Media
   ====================================== */
img,
video {
    max-width: 100%;
    height: auto;
}

/* ======================================
   Tables (Base)
   ====================================== */
table {
    width: 100%;
    border-collapse: collapse;
}

th,
td {
    padding: var(--spacing-sm) var(--spacing-md);
    text-align: left;
    border-bottom: 1px solid var(--border-color);
}

th {
    font-weight: var(--font-weight-semibold);
    background: var(--table-header-bg);
}

/* ======================================
   Forms (Base)
   ====================================== */
input,
textarea,
select,
button {
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
}

button {
    cursor: pointer;
    border: none;
    background: none;
}

fieldset {
    border: none;
    padding: 0;
    margin: 0;
}

label {
    display: block;
    font-weight: var(--font-weight-medium);
    margin-bottom: var(--spacing-xs);
}

/* ======================================
   Utility Classes
   ====================================== */
.hidden {
    display: none !important;
}

/* Mobile/Desktop Visibility Utilities */
.mobile-only {
    display: none !important;
}

@media (max-width: 1024px) {
    .mobile-only {
        display: block !important;
    }

    .desktop-only {
        display: none !important;
    }
}

.invisible {
    visibility: hidden;
}

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Text utilities */
.text-xs {
    font-size: var(--text-xs);
}

.text-sm {
    font-size: var(--text-sm);
}

.text-base {
    font-size: var(--text-base);
}

.text-lg {
    font-size: var(--text-lg);
}

.text-xl {
    font-size: var(--text-xl);
}

.text-2xl {
    font-size: var(--text-2xl);
}

.text-3xl {
    font-size: var(--text-3xl);
}

.text-center {
    text-align: center;
}

.text-left {
    text-align: left;
}

.text-right {
    text-align: right;
}

.text-muted {
    color: var(--text-muted);
}

.text-primary {
    color: var(--ui-accent);
}

.text-success {
    color: var(--color-success);
}

.text-error {
    color: var(--color-error);
}

.text-danger {
    color: var(--color-error);
}

.text-warning {
    color: var(--color-warning);
}

.text-info {
    color: var(--color-info);
}

/* Font weights */
.font-normal {
    font-weight: var(--font-weight-normal);
}

.font-medium {
    font-weight: var(--font-weight-medium);
}

.font-semibold {
    font-weight: var(--font-weight-semibold);
}

.font-bold {
    font-weight: var(--font-weight-bold);
}

/* Text utilities */
.text-nowrap {
    white-space: nowrap !important;
}

.text-wrap {
    white-space: normal !important;
}

.text-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Spacing utilities */
.m-0 {
    margin: 0;
}

.p-0 {
    padding: 0;
}

.mt-1 {
    margin-top: var(--spacing-xs);
}

.mt-2 {
    margin-top: var(--spacing-sm);
}

.mt-3 {
    margin-top: var(--spacing-md);
}

.mt-4 {
    margin-top: var(--spacing-lg);
}

.mb-1 {
    margin-bottom: var(--spacing-xs);
}

.mb-0 {
    margin-bottom: 0;
}

.mb-2 {
    margin-bottom: var(--spacing-sm);
}

.mb-3 {
    margin-bottom: var(--spacing-md);
}

.mb-4 {
    margin-bottom: var(--spacing-lg);
}

/* Flex utilities */
.d-flex,
.flex {
    display: flex;
}

.d-grid,
.grid {
    display: grid;
}

.d-block {
    display: block;
}

.d-inline {
    display: inline;
}

.d-none {
    display: none;
}

.flex-wrap {
    flex-wrap: wrap;
}

.flex-row {
    flex-direction: row;
}

.flex-col {
    flex-direction: column;
}

.items-center {
    align-items: center;
}

.items-start {
    align-items: flex-start;
}

.items-end {
    align-items: flex-end;
}

.justify-center {
    justify-content: center;
}

.justify-between {
    justify-content: space-between;
}

.justify-end {
    justify-content: flex-end;
}

.gap-1 {
    gap: var(--spacing-xs);
}

.gap-2 {
    gap: var(--spacing-sm);
}

.gap-3 {
    gap: var(--spacing-md);
}

.gap-4 {
    gap: var(--spacing-lg);
}

.gap-5 {
    gap: var(--space-5);
}

.gap-6 {
    gap: var(--space-6);
}

/* Grid utilities */
.d-grid,
.grid {
    display: grid;
}

.grid-cols-2 {
    grid-template-columns: repeat(2, 1fr);
}

.grid-cols-3 {
    grid-template-columns: repeat(3, 1fr);
}

.grid-cols-4 {
    grid-template-columns: repeat(4, 1fr);
}

/* Background utilities */
.bg-body {
    background: var(--bg-body);
}

.bg-surface {
    background: var(--bg-card);
}

.bg-muted {
    background: var(--bg-subtle);
}

.bg-primary-100 {
    background: var(--ui-accent-soft);
}

/* ======================================
   Loading State
   ====================================== */
.loading {
    position: relative;
    pointer-events: none;
}

.loading::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    border: 2px solid var(--border-color);
    border-top-color: var(--ui-accent);
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

/* ======================================
   Scrollbar Styling
   ====================================== */
::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}

::-webkit-scrollbar-track {
    background: var(--bg-secondary);
}

::-webkit-scrollbar-thumb {
    background: var(--border-color);
    border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--text-muted);
}

/* ======================================
   Selection
   ====================================== */
::selection {
    background: var(--ui-accent);
    color: var(--ui-accent-fg);
}

/* ======================================
   Focus Ring
   ====================================== */
:focus {
    outline: none;
}

:focus-visible {
    outline: 2px solid var(--ui-accent);
    outline-offset: 2px;
}

/* ======================================
   Print Styles
   ====================================== */
@media print {
    body {
        background: white;
    }

    .no-print {
        display: none !important;
    }
}

/* ======================================
   ✨ MODERN ANIMATIONS & KEYFRAMES
   ====================================== */

/* Fade In */
@keyframes fadeIn {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

.animate-fade-in {
    animation: fadeIn var(--transition-normal) forwards;
}

/* Slide Up */
@keyframes slideUp {
    from {
        opacity: 0;
        transform: translateY(20px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.animate-slide-up {
    animation: slideUp var(--transition-normal) forwards;
}

/* Scale In (Pop) */
@keyframes scaleIn {
    from {
        opacity: 0;
        transform: scale(0.95);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

.animate-scale-in {
    animation: scaleIn var(--transition-normal) forwards;
}

/* Staggered Delays */
.delay-100 {
    animation-delay: 100ms;
}

.delay-200 {
    animation-delay: 200ms;
}

.delay-300 {
    animation-delay: 300ms;
}

/* ======================================
   ✨ MODERN INTERACTION UTILITIES
   ====================================== */

/* Hover Lift */
.hover-lift {
    transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.hover-lift:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-lg);
}

/* Glassmorphism */
.glass-panel {
    background: rgba(255, 255, 255, 0.7);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.5);
    box-shadow: var(--shadow-lg);
}

/* Soft Card */
.soft-card {
    background: var(--color-white);
    box-shadow: var(--shadow-md);
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-color-light);
    transition: box-shadow var(--transition-normal);
}

.soft-card:hover {
    box-shadow: var(--shadow-xl);
}

/* layout.css */
/**
 * Layout primitives
 * Purpose: page shell, content region, page headers, and common responsive composition.
 */

.ui-root {
  height: 100vh;
  height: 100dvh;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--bg-body);
  overflow: hidden;
}

.ui-root.login-mode {
  overflow: auto;
}

.ui-content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.content-area {
  flex: 1;
  min-height: 0;
  min-width: 0;
  width: 100%;
  max-width: var(--content-max-width);
  margin-inline: auto;
  padding: var(--content-gutter);
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}

.content-area-full {
  max-width: none;
  padding: 0;
}

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-block-end: var(--space-6);
  min-width: 0;
}

.page-header-left {
  min-width: 0;
  flex: 1 1 auto;
}

.page-header-right,
.page-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  flex: 0 0 auto;
  flex-wrap: wrap;
}

.page-title {
  margin: 0;
  color: var(--text-primary);
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);
  letter-spacing: var(--letter-spacing-normal);
}

.page-subtitle {
  margin: var(--space-1) 0 0;
  color: var(--text-secondary);
  font-size: var(--text-sm);
  line-height: var(--line-height-normal);
}

.page-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-end: var(--space-3);
  color: var(--text-link);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
}

.page-back:hover {
  color: var(--text-link-hover);
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-end: var(--space-4);
  padding: var(--space-3);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
}

.toolbar-left,
.toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  flex-wrap: wrap;
}

.search-box {
  position: relative;
  min-width: min(18rem, 100%);
}

.search-box .form-control {
  padding-left: calc(var(--space-8) + var(--space-2));
}

.search-box .search-icon {
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  pointer-events: none;
}

.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: var(--space-4);
}

.info-section {
  min-width: 0;
  padding: var(--space-5);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
}

.info-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-end: var(--space-4);
  padding-block-end: var(--space-3);
  border-bottom: 1px solid var(--border-color-light);
}

.info-section-title {
  color: var(--text-primary);
  font-weight: var(--font-weight-semibold);
}

.info-row {
  display: grid;
  grid-template-columns: minmax(7rem, 0.45fr) minmax(0, 1fr);
  gap: var(--space-3);
  margin-block-end: var(--space-2);
}

.info-label {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.info-value {
  min-width: 0;
  color: var(--text-primary);
}

.split-layout {
  display: grid;
  grid-template-columns: minmax(16rem, 20rem) minmax(0, 1fr);
  gap: var(--space-6);
  min-height: calc(100vh - var(--header-height) - var(--space-12));
}

.split-sidebar,
.split-content {
  min-width: 0;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
}

.split-sidebar {
  padding: var(--space-4);
  overflow: auto;
}

.split-content {
  padding: var(--space-6);
}

.error-screen,
.loading-screen {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-6);
  background: var(--bg-body);
  text-align: center;
}

.error-screen i {
  color: var(--color-error);
  font-size: var(--text-5xl);
}

.error-screen h1 {
  margin: 0;
  color: var(--text-primary);
  font-size: var(--text-2xl);
}

.error-screen p,
.loading-text {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.loading-spinner {
  width: 3rem;
  height: 3rem;
  border: 3px solid var(--ui-accent-active);
  border-top-color: var(--ui-accent);
  border-radius: var(--radius-full);
  animation: spin 700ms linear infinite;
}

@media (max-width: 1024px) {
  .split-layout {
    grid-template-columns: 1fr;
  }

  .split-sidebar {
    order: 2;
  }
}

@media (max-width: 768px) {
  .content-area {
    padding: var(--space-4);
  }

  .page-header,
  .toolbar {
    align-items: stretch;
    flex-direction: column;
  }

  .page-header-right,
  .page-actions,
  .toolbar-left,
  .toolbar-right {
    width: 100%;
    justify-content: flex-start;
  }

  .page-title {
    font-size: var(--text-xl);
  }

  .search-box {
    width: 100%;
  }

  .info-row {
    grid-template-columns: 1fr;
    gap: var(--space-1);
  }

  .split-content {
    padding: var(--space-4);
  }
}

@media (max-width: 480px) {
  .content-area {
    padding: var(--space-3);
  }

  .toolbar {
    padding: var(--space-2);
  }
}

/* utilities.css */
/**
 * Utilities
 * Purpose: Single-purpose helper classes only.
 * Rule: no component styling, no page/domain-specific selectors.
 * Added: 2026-04-22
 * Updated: 2026-04-25
 */

.container {
  width: 100%;
  max-width: var(--content-max-width);
  margin-inline: auto;
  padding-inline: var(--content-gutter);
}

.container-sm { max-width: 640px; }
.container-md { max-width: 768px; }
.container-lg { max-width: 1024px; }
.container-xl { max-width: 1280px; }
.container-fluid { max-width: none; }

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.cluster {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.split {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.center {
  display: grid;
  place-items: center;
}

.full-width { width: 100%; }
.min-w-0 { min-width: 0; }
.overflow-hidden { overflow: hidden; }
.overflow-auto { overflow: auto; }
.overflow-x-auto { overflow-x: auto; }
.overflow-y-auto { overflow-y: auto; }

.rounded-sm { border-radius: var(--radius-sm); }
.rounded-md { border-radius: var(--radius-md); }
.rounded-lg { border-radius: var(--radius-lg); }
.rounded-xl { border-radius: var(--radius-xl); }
.rounded-full { border-radius: var(--radius-full); }

.shadow-none { box-shadow: none; }
.shadow-sm { box-shadow: var(--shadow-sm); }
.shadow-md { box-shadow: var(--shadow-md); }
.shadow-lg { box-shadow: var(--shadow-lg); }

.border { border: 1px solid var(--border-color); }
.border-light { border: 1px solid var(--border-color-light); }
.border-0 { border: 0 !important; }

.bg-card { background: var(--bg-card); }
.bg-subtle { background: var(--bg-subtle); }
.bg-primary-surface { background: var(--bg-primary); }

.text-primary-strong { color: var(--text-primary); }
.text-secondary { color: var(--text-secondary); }
.text-muted { color: var(--text-muted); }
.text-link { color: var(--text-link); }

.text-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

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

@media (max-width: 768px) {
  .container {
    padding-inline: var(--space-4);
  }

  .split {
    align-items: stretch;
    flex-direction: column;
  }
}

@media (max-width: 480px) {
  .container {
    padding-inline: var(--space-3);
  }
}

/* ======================================
   Global Loading Overlay
   ====================================== */
.loading-overlay {
  position: fixed;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: var(--space-6);
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  z-index: var(--z-overlay, 99999);
  opacity: 0;
  transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Prevent overlay from flashing during initial boot */
.ui-root.loading ~ .loading-overlay {
  display: none !important;
}

.loading-overlay.show {
  display: flex;
  opacity: 1;
}

.loading-card {
  background: rgba(255, 255, 255, 0.85);
  padding: 3rem 4rem;
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-xl);
  border: 1px solid rgba(255, 255, 255, 0.4);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  min-width: 280px;
  transform: scale(0.9);
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.loading-overlay.show .loading-card {
  transform: scale(1);
}

/* Table-level loading overlay */
.table-loading-overlay {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  background: rgba(255, 255, 255, 0.66);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  z-index: var(--z-dropdown, 1000);
  border-radius: inherit;
}

.table-loading-overlay.show {
  display: flex;
}

.table-loading-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-width: 8rem;
  padding: var(--space-4);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  background: var(--surface-overlay);
  box-shadow: var(--shadow-md);
  animation: loading-card-enter var(--duration-fast) var(--ease-decelerate) both;
}

.table-loading-text {
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-tight);
  text-align: center;
}

.table-loading-track {
  position: relative;
  width: 7rem;
  height: 0.25rem;
  overflow: hidden;
  border-radius: var(--radius-full);
  background: var(--bg-progress);
}

.table-loading-bar {
  position: absolute;
  inset-block: 0;
  left: 0;
  width: 40%;
  border-radius: inherit;
  background: var(--ui-accent);
  animation: loading-track-indeterminate 1.1s var(--ease-standard) infinite;
}

.table-loading-overlay.is-navigation-loading {
  background: rgba(255, 255, 255, 0.72);
}

.table-loading-overlay.is-navigation-loading .table-loading-card {
  min-width: 10rem;
}

.table-loading-overlay.is-navigation-loading .table-loading-track {
  width: 8rem;
}

@keyframes loading-card-enter {
  from {
    opacity: 0;
    transform: translateY(4px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes loading-track-indeterminate {
  0% {
    transform: translateX(-120%);
  }
  100% {
    transform: translateX(280%);
  }
}

/* animations.css */
/**
 * animations.css — Shared keyframes
 *
 * Centralized so multiple components can reference the same motion name
 * without collision. Every keyframe here is declared exactly once.
 *
 * Respects prefers-reduced-motion — disabling handled globally via the
 * @media block in tokens.css / reset.css, not per-keyframe.
 *
 * Added:   2026-04-22
 * Updated: 2026-04-22
 */

@keyframes spin {
  to { transform: rotate(360deg); }
}

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes slide-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes slide-down {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes pulse-scale {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.03); }
}

@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

/* components/alert.css */
/**
 * Component: Alert
 * Purpose:   Inline semantic banner (success / error / warning / info).
 * Base:      alert
 * Sub:       alert-icon, alert-body, alert-title
 * Variants:  success, error (alias: danger), warning, info
 * Depends:   tokens.css
 * Added:     2026-04-22
 */

.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid transparent;
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  color: var(--text-primary);
  font-size: var(--text-sm);
  line-height: var(--line-height-normal);
}
.alert-icon {
  flex: none;
  font-size: var(--text-lg);
  line-height: 1;
  margin-top: 1px;
}
.alert-body { flex: 1; }
.alert-title {
  font-weight: var(--font-weight-semibold);
  margin-bottom: var(--space-1);
}

.alert-success { background: var(--color-success-bg); border-left-color: var(--color-success); color: var(--color-success-dark); }
.alert-error,
.alert-danger  { background: var(--color-error-bg);   border-left-color: var(--color-error);   color: var(--color-error-dark); }
.alert-warning { background: var(--color-warning-bg); border-left-color: var(--color-warning); color: var(--color-warning-dark); }
.alert-info    { background: var(--color-info-bg);    border-left-color: var(--color-info);    color: var(--color-accent-dark); }

/* components/workspace-shell.css */
/**
 * Component: Workspace Shell
 * Purpose:   Authenticated workspace — flex layout: sidebar + main column + status bar.
 * Design:    Claude Design reference (Business App.zip, 2026-05-11)
 * Replaces:  Previous fixed-position topbar/sidebar approach.
 */

/* ══════════════════════════════════════════════════════════════
   SKIP NAV — WCAG 2.4.1 Bypass Blocks
   ══════════════════════════════════════════════════════════════ */
.skip-nav {
  position: fixed;
  top: -100px;
  left: var(--space-4);
  z-index: 9999;
  padding: var(--space-2) var(--space-5);
  background: var(--shell-accent);
  color: var(--shell-accent-fg);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  transition: top var(--transition-fast);
  white-space: nowrap;
}
.skip-nav:focus { top: 0; outline: none; box-shadow: var(--shadow-focus); }

/* ══════════════════════════════════════════════════════════════
   APP ROOT — flex column, full viewport
   #app-header (.shell-header) uses display:contents so its child
   .workspace-shell and .shell-statusbar participate directly in
   #app's flex column without an extra wrapper box.
   ══════════════════════════════════════════════════════════════ */
.shell-header {
  display: contents;
}

/* Activated by JS (AppHeader.restructureLayout) once DOM is ready */
#app[data-shell="workspace"] {
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow: hidden;
}

/* Hide old legacy footer — shell-statusbar replaces it */
#app[data-shell="workspace"] .shell-footer {
  display: none;
}

/* ══════════════════════════════════════════════════════════════
   WORKSPACE SHELL — flex row: sidebar + main column
   ══════════════════════════════════════════════════════════════ */
.workspace-shell {
  /* Design dimensions (Claude Design reference) */
  --_sw:   232px;   /* sidebar expanded  */
  --_swc:   56px;   /* sidebar collapsed */
  --_tbh:   52px;   /* topbar height     */
  --_sbh:   26px;   /* statusbar height  */

  display: flex;
  flex-direction: row;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  background: var(--bg-body);
  position: relative; /* anchor for mobile sidebar */
}

/* ══════════════════════════════════════════════════════════════
   SIDEBAR
   ══════════════════════════════════════════════════════════════ */
.shell-sidebar {
  width: var(--_sw);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border-right: 1px solid var(--border-color-light);
  overflow: hidden;
  transition: width 160ms ease, margin-right 160ms ease;
  z-index: 1;
}

/* ── Brand row (same height as topbar) ── */
.shell-sidebar-brand {
  height: var(--_tbh);
  padding: 0 8px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--border-color-light);
  flex-shrink: 0;
}

/* Close button — hidden except on mobile full-width drawer */
.shell-sidebar-brand .shell-sidebar-close { display: none; margin-left: auto; }

/* Shared brand element (sidebar + topbar navbar variant) */
.shell-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border-radius: var(--radius-md);
  text-decoration: none;
  color: var(--text-primary);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: background-color var(--transition-fast);
  min-width: 0;
}
.shell-brand:hover { background: var(--bg-hover); color: var(--text-primary); }
.shell-brand.is-active { background: var(--shell-accent-soft); color: var(--text-primary); }

.shell-brand-icon {
  width: 26px;
  height: 26px;
  border-radius: var(--radius-md);
  background: var(--shell-accent);
  color: var(--shell-accent-fg);
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: -0.02em;
  flex-shrink: 0;
}

.shell-brand-info {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.15;
  min-width: 0;
  overflow: hidden;
}

.shell-brand-name {
  font-weight: 600;
  font-size: var(--text-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.shell-brand-sub {
  font-size: 10px;
  color: var(--text-light);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* ── Nav scroll area ── */
.shell-nav {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 12px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  scrollbar-width: thin;
  scrollbar-color: var(--border-color-light) transparent;
}

/* ── Nav groups ── */
.shell-nav-group {
  display: flex;
  flex-direction: column;
}
.shell-nav-group + .shell-nav-group { margin-top: 14px; }

.shell-nav-group-label {
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-light);
  padding: 4px 10px 6px;
  font-weight: 500;
}

/* Divider: replaces label when sidebar is collapsed */
.shell-nav-group-divider {
  height: 1px;
  background: var(--border-color-light);
  margin: 8px 6px;
  display: none;
}

.shell-nav-group-items {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* ── Nav items ── */
/* Fixed height (not min-height) keeps items the same size regardless of
   whether text labels are shown or hidden (icon-only collapsed mode).
   Vertical centering is handled by align-items: center, not padding.    */
.shell-nav-item,
.shell-nav-child {
  position: relative;
  width: 100%;
  height: 36px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 10px;
  border-radius: var(--radius-md);
  background: transparent;
  border: 0;
  color: var(--text-muted);
  font-size: 13.5px;
  font-weight: 400;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 80ms ease, color 80ms ease;
  flex-shrink: 0;
}

.shell-nav-item:hover,
.shell-nav-child:hover { color: var(--text-primary); }

/* Icon slot: fixed-width container — centers icon at the SAME pixel position
   in all sidebar states (collapsed, expanded, hover).
   Width = collapsed_sidebar(56) - nav_padding×2(20) = 36px, always.
   margin-left: -10px cancels item's left padding so slot aligns with nav left edge.
   Icon center = 10(nav-pad) + 18(half-slot) = 28px = exact center of 56px sidebar. */
.shell-nav-icon-slot {
  width: calc(var(--_swc) - 20px);
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-left: -10px;
}
.shell-nav-icon-slot i {
  width: 17px;
  text-align: center;
  font-size: 14px;
  color: inherit;
}

.shell-nav-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.shell-nav-chevron {
  font-size: 0.65rem;
  color: var(--text-light);
  transition: transform var(--transition-fast);
  flex-shrink: 0;
}
.shell-nav-parent.expanded .shell-nav-chevron { transform: rotate(180deg); }

/* Children — tree-style with left border line (Claude Design reference) */
.shell-nav-children {
  display: none;
  flex-direction: column;
  gap: 1px;
  padding-left: 14px;
  margin-left: 11px;
  margin-top: 2px;
  margin-bottom: 4px;
  border-left: 1px solid var(--border-color-light);
}
.shell-nav-parent.expanded .shell-nav-children { display: flex; }

.shell-nav-child {
  height: 32px;
  padding: 0 10px;
  font-size: 12.5px;
}

/* ── Active states (Claude Design pattern) ── */
/* Parent trigger: soft accent tint — "you're in this section" */
.shell-sidebar .shell-nav-parent-trigger.active {
  background: var(--shell-accent-soft);
  color: var(--text-primary);
  font-weight: 500;
}
.shell-sidebar .shell-nav-parent-trigger.active i { color: inherit; }

/* Leaf item: tint + 2px accent bar at left-1px — "you're on this page"
   left: -1px makes the bar sit at the very edge of the sidebar padding,
   matching the Claude Design reference exactly. */
.shell-sidebar .shell-nav-item.active:not(.shell-nav-parent-trigger),
.shell-sidebar .shell-nav-child.active {
  background: var(--shell-accent-soft);
  color: var(--text-primary);
  font-weight: 500;
}
/* Leaf item active bar: at left edge of the item (inside nav padding) */
.shell-sidebar .shell-nav-item.active:not(.shell-nav-parent-trigger)::before {
  content: '';
  position: absolute;
  left: -1px;
  top: 6px;
  bottom: 6px;
  width: 2px;
  background: var(--shell-accent);
  border-radius: 2px;
}

/* Child item active bar: at the tree border-left line (-14px padding - 1px border) */
.shell-sidebar .shell-nav-child.active::before {
  content: '';
  position: absolute;
  left: -15px;
  top: 4px;
  bottom: 4px;
  width: 2px;
  background: var(--shell-accent);
  border-radius: 2px;
}

/* Collapsed child-active dot: small accent dot on parent icon when icon-only + child active */
.shell-nav-parent.child-active .shell-nav-parent-trigger { position: relative; }
.shell-nav-parent.child-active .shell-nav-parent-trigger::after {
  content: '';
  position: absolute;
  top: 4px;
  right: 4px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--shell-accent);
  pointer-events: none;
}

/* ── Sidebar collapse button (bottom strip) ── */
.shell-sidebar-collapse {
  height: 36px;
  border-top: 1px solid var(--border-color-light);
  background: transparent;
  border-left: 0; border-right: 0; border-bottom: 0;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 12px;
  gap: 8px;
  font-size: var(--text-xs);
  cursor: pointer;
  transition: color var(--transition-fast);
  flex-shrink: 0;
  width: 100%;
}
.shell-sidebar-collapse:hover { color: var(--text-primary); }


.shell-collapse-icon {
  transition: transform 160ms ease;
  font-size: 12px;
  flex-shrink: 0;
}

/* ══════════════════════════════════════════════════════════════
   DESKTOP SIDEBAR-COLLAPSED STATE
   (.sidebar-collapsed on .workspace-shell, set by JS)
   Sidebar floats as an absolute overlay at --_swc width.
   Hover-expand: sidebar grows to --_sw and floats over content.
   ══════════════════════════════════════════════════════════════ */
@media (min-width: 1280px) {
  /* Collapsed: stays in flex flow (no position change = no layout jump).
     Negative margin-right on hover makes the sidebar "float" over main content
     without a position change — all properties are CSS-transitionable. */
  .workspace-shell.sidebar-collapsed .shell-sidebar {
    width: var(--_swc);
    z-index: 20;
  }

  /* Icon-only: padding stays FIXED at 0 10px (same as expanded) — icon never moves.
     Labels are clipped by overflow-x: hidden on .shell-nav (label starts at 49px,
     nav clips at 46px = entirely hidden). Icon center: 10+10+8.5=28.5px ≈ 28px center. */
  .workspace-shell.sidebar-collapsed .shell-nav-label,
  .workspace-shell.sidebar-collapsed .shell-nav-chevron,
  .workspace-shell.sidebar-collapsed .shell-collapse-label,
  .workspace-shell.sidebar-collapsed .shell-brand-info { display: none; }
  .workspace-shell.sidebar-collapsed .shell-nav-children,
  .workspace-shell.sidebar-collapsed .shell-nav-parent.expanded .shell-nav-children { display: none; }
  .workspace-shell.sidebar-collapsed .shell-nav-group-label { display: none; }
  .workspace-shell.sidebar-collapsed .shell-nav-group + .shell-nav-group .shell-nav-group-divider { display: block; }
  .workspace-shell.sidebar-collapsed .shell-sidebar-collapse { justify-content: center; padding-inline: 0; }
  .workspace-shell.sidebar-collapsed .shell-collapse-icon { transform: rotate(180deg); }
  .workspace-shell.sidebar-collapsed .shell-brand { width: 40px; justify-content: center; padding-inline: 0; }

  /* Hover-expand: grow to full width, negative margin-right pulls back the space so
     main content doesn't move — sidebar visually floats over it at z-index 30. */
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover {
    width: var(--_sw);
    margin-right: calc(var(--_swc) - var(--_sw));
    box-shadow: var(--shadow-xl);
    z-index: 30;
  }
  /* Restore sidebar content when hovered */
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-nav-label,
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-nav-chevron,
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-collapse-label,
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-brand-info { display: flex; }
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-nav-parent.expanded .shell-nav-children { display: flex; }
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-nav-group-label { display: block; }
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-nav-group + .shell-nav-group .shell-nav-group-divider { display: none; }
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-sidebar-collapse { justify-content: flex-end; padding: 0 12px; }
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-collapse-icon { transform: rotate(0deg); }
  .workspace-shell.sidebar-collapsed .shell-sidebar:hover .shell-brand { width: auto; justify-content: flex-start; padding-inline: 8px; }
}

/* ══════════════════════════════════════════════════════════════
   MAIN COLUMN (topbar + content)
   ══════════════════════════════════════════════════════════════ */
.shell-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--bg-body);
}

/* ── Topbar ── */
.shell-topbar {
  height: var(--_tbh);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 16px;
  background: var(--bg-card);
  border-bottom: 1px solid var(--border-color-light);
  position: relative;
  z-index: 2;
}

.shell-topbar-left {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  flex: 1;
}

.shell-topbar-spacer { flex: 1; }

.shell-topbar-vdivider {
  width: 1px;
  height: 20px;
  background: var(--border-color-light);
  flex-shrink: 0;
  display: none; /* shown only in navbar mode */
}

/* ── Shell icon button ── */
.shell-icon-btn {
  width: 34px;
  height: 34px;
  padding: 0;
  display: grid;
  place-items: center;
  border-radius: var(--radius-md);
  background: transparent;
  border: 0;
  color: var(--text-muted);
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast);
  position: relative;
  flex-shrink: 0;
}
.shell-icon-btn:hover,
.shell-icon-btn:focus-visible { background: var(--bg-hover); color: var(--text-primary); outline: none; }
.shell-icon-btn.is-active,
.shell-icon-btn[aria-expanded="true"] { background: var(--bg-hover); color: var(--text-primary); }

/* Hamburger: hidden on desktop, shown tablet/mobile */
.shell-menu-toggle { display: none; }

/* Brand in topbar: navbar mode only */
.shell-brand--navbar { display: none; flex-shrink: 0; }

/* ── Navbar menu ── */
.shell-navbar-menu,
.shell-navbar-menu.nav {
  display: none;
  align-items: center;
  gap: 2px;
  min-width: 0;
  overflow: visible;
  flex-wrap: nowrap;
}

.shell-navbar-menu .shell-navbar-primary {
  flex-shrink: 0;
  white-space: nowrap;
}

.shell-navbar-menu .nav-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 11px;
  border-radius: var(--radius-md);
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font-size: 13.5px;
  font-weight: 400;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}
.shell-navbar-menu .nav-link:hover { color: var(--text-primary); }
.shell-navbar-menu .nav-link.active,
.shell-navbar-menu .nav-link.active:hover {
  background: var(--shell-accent-soft);
  color: var(--text-primary);
  font-weight: 500;
}

.shell-navbar-menu .dropdown-menu {
  min-width: 14rem; left: 0; right: auto; margin: 0; list-style: none;
}
.shell-navbar-menu .nav-overflow-hidden { display: none !important; }
.shell-navbar-menu .dropdown-item { gap: var(--space-2); white-space: nowrap; }
.shell-navbar-menu .dropdown-item i:first-child { width: 20px; text-align: center; }
.shell-navbar-menu .nav-more-container { display: none; flex-shrink: 0; }
.shell-navbar-menu .more-submenu { position: relative; }
.shell-navbar-menu .more-submenu-toggle { justify-content: space-between; }
.shell-navbar-menu .more-submenu-arrow { margin-left: auto; font-size: 0.72rem; color: var(--text-muted); }

.shell-navbar-menu .more-submenu-content {
  position: absolute; top: 0; left: calc(100% + 4px); right: auto;
  min-width: 14rem; display: none; flex-direction: column; gap: var(--space-1);
  margin: 0; padding: var(--space-2); list-style: none;
  background: var(--bg-card); border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  z-index: calc(var(--z-dropdown) + 10);
}
.shell-navbar-menu .more-submenu-content::before {
  content: ''; position: absolute; top: 0; left: -8px; right: auto; width: 8px; height: 100%;
}
.shell-navbar-menu .more-submenu.dir-left .more-submenu-content { left: auto; right: calc(100% + 4px); }
.shell-navbar-menu .more-submenu.dir-left .more-submenu-content::before { left: auto; right: -8px; }

@media (hover: hover) and (pointer: fine) {
  .shell-navbar-menu .more-submenu:hover > .more-submenu-content { display: flex; }
}
.shell-navbar-menu .more-submenu-content.show { display: flex; }

/* ── Settings slot ── */
.shell-settings-slot {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}

.shell-slot-divider {
  width: 1px;
  height: 20px;
  background: var(--border-color-light);
  margin: 0 4px;
  flex-shrink: 0;
}

/* ── Branch selector ── */
.shell-branch-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color-light);
  background: transparent;
  color: var(--text-primary);
  font-size: var(--text-sm);
  cursor: pointer;
  white-space: nowrap;
  max-width: min(24vw, 240px);
  transition: background-color var(--transition-fast);
  text-decoration: none;
}
.shell-branch-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.shell-branch-btn .chevron { font-size: 10px; color: var(--text-muted); }
.shell-branch-btn .branch-text {
  overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0;
}
.branch-text-stack { display: flex; flex-direction: column; line-height: 1.15; text-align: left; min-width: 0; overflow: hidden; }
.branch-text-business { font-size: var(--text-xs); font-weight: 400; opacity: 0.78; letter-spacing: 0.04em; text-transform: uppercase; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.branch-text-name { font-size: var(--text-sm); font-weight: var(--font-weight-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.branch-text-plan { font-size: var(--text-xs); opacity: 0.78; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Notification badge ── */
.shell-notif-badge {
  position: absolute;
  top: 4px; right: 4px;
  min-width: 14px; height: 14px; padding: 0 3px;
  border-radius: 8px;
  background: var(--shell-accent);
  color: var(--shell-accent-fg);
  font-size: 9px; font-weight: 600;
  display: grid; place-items: center;
  border: 2px solid var(--bg-card);
  line-height: 1;
}

/* ── User avatar ── */
.shell-user-avatar {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--bg-subtle);
  border: 1px solid var(--border-color-light);
  display: grid; place-items: center;
  font-size: 10.5px; font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 0.02em; line-height: 1;
  flex-shrink: 0; text-transform: uppercase; user-select: none;
}
.shell-user-avatar--lg { width: 36px; height: 36px; font-size: 14px; }

/* ── User button (trigger) ── */
.shell-user-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 4px;
  border-radius: var(--radius-md);
  background: transparent;
  border: 0;
  color: var(--text-muted);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}
.shell-user-btn:hover,
.shell-user-btn[aria-expanded="true"] { background: var(--bg-hover); }
.shell-user-btn .fa-chevron-down { font-size: 10px; }

/* ══════════════════════════════════════════════════════════════
   POPOVERS (settings, user menu, notifications)
   ══════════════════════════════════════════════════════════════ */
.shell-popover-wrap { position: relative; }
.shell-popover-wrap:not(.dropdown-open):not(.is-open):not(.open) > .shell-popover {
  display: none;
}

.shell-popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  z-index: var(--z-dropdown);
  overflow: hidden;
  min-width: 280px;
}
.shell-popover[hidden] { display: none; }

.shell-popover-hd {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-color-light);
  font-weight: 600;
  font-size: 13.5px;
  color: var(--text-primary);
}
.shell-popover-hd--user {
  display: flex; align-items: center; gap: 12px;
}
.shell-popover-hd--row {
  display: flex; align-items: center; justify-content: space-between;
}

.shell-popover-action {
  background: transparent; border: 0;
  color: var(--text-muted); font-size: 12px;
  cursor: pointer; padding: 0;
}
.shell-popover-action:hover { color: var(--text-primary); }

.shell-popover-bd { padding: 6px; }

.shell-popover-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 10px;
  border-radius: var(--radius-sm);
  background: transparent; border: 0;
  color: var(--text-primary); font-size: 13px;
  text-decoration: none; cursor: pointer;
  transition: background-color var(--transition-fast);
}
.shell-popover-item:hover { background: var(--bg-hover); }
.shell-popover-item i { width: 15px; text-align: center; color: inherit; flex-shrink: 0; }
.shell-popover-item--danger { color: var(--color-error); }

.shell-popover-divider {
  height: 1px; background: var(--border-color-light); margin: 4px 0;
}

.shell-user-popover { min-width: 240px; }

/* Notifications popover */
.shell-notif-popover { min-width: 340px; }

.shell-notif-list { max-height: 360px; overflow-y: auto; }

.shell-notif-empty {
  padding: 28px 14px; text-align: center;
  color: var(--text-muted); font-size: 13px;
}

.shell-notif-item {
  display: flex; gap: 10px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--border-color-light);
  cursor: pointer;
  transition: background-color var(--transition-fast);
}
.shell-notif-item:hover { background: var(--bg-hover); }
.shell-notif-item.is-unread { background: var(--shell-accent-soft); }

.shell-notif-icon {
  width: 30px; height: 30px; border-radius: var(--radius-sm);
  background: var(--bg-subtle); display: grid; place-items: center;
  color: var(--text-muted); flex-shrink: 0;
}
.shell-notif-body { flex: 1; min-width: 0; }
.shell-notif-title { font-size: 13px; color: var(--text-primary); line-height: 1.35; }
.shell-notif-time { font-size: 11.5px; color: var(--text-light); margin-top: 2px; }
.shell-notif-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--shell-accent); flex-shrink: 0; margin-top: 5px;
}

/* ── Settings: segmented controls ── */
.shell-seg-row { padding: 10px 14px; }

.shell-seg-label {
  font-size: 11px; color: var(--text-light);
  margin-bottom: 6px;
  text-transform: uppercase; letter-spacing: 0.06em;
}

.shell-seg-ctrl {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 0;
  background: var(--bg-subtle);
  border-radius: var(--radius-md);
  padding: 2px;
}

.shell-seg-opt {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  padding: 6px 8px; border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted);
  font-size: 12.5px; font-weight: 400; cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
  white-space: nowrap;
}
.shell-seg-opt.is-active {
  background: var(--bg-card); color: var(--text-primary);
  font-weight: 500; box-shadow: var(--shadow-sm);
}
.shell-seg-opt i { font-size: 11px; }

/* ── Accent color swatches ── */
.shell-swatch-row {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  padding: 2px 0 4px;
}

.shell-swatch {
  width: 24px;
  height: 24px;
  border-radius: 6px;
  border: 2px solid transparent;
  outline: 2px solid transparent;
  outline-offset: -1px;
  background: var(--sw-color, #ccc);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: transform 80ms ease, border-color 80ms ease, outline-color 80ms ease;
}
.shell-swatch:hover { transform: scale(1.18); }
.shell-swatch.is-active {
  border-color: var(--text-primary);
  outline-color: var(--border-color-light);
}

/* ══════════════════════════════════════════════════════════════
   CONTENT AREA  (#content-area moved here by JS)
   ══════════════════════════════════════════════════════════════ */
.shell-content {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.shell-content > #content-area,
.shell-content > .content-area {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0;
  margin: 0;
  max-width: none;
  width: 100%;
  /* Stacking context: confines scoped overlays (z-index 100) to this layer.
     z-index:0 keeps the entire content area below shell chrome (sidebar z≥1, topbar z=2). */
  position: relative;
  z-index: 0;
}

/* ══════════════════════════════════════════════════════════════
   STATUS BAR (26px strip, flex item in #app column)
   ══════════════════════════════════════════════════════════════ */
.shell-statusbar {
  flex-shrink: 0;
  height: var(--_sbh, 26px);
  background: var(--bg-card);
  border-top: 1px solid var(--border-color-light);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 12px;
  font-size: 11px;
  color: var(--text-muted);
  user-select: none;
  gap: 12px;
}

.statusbar-left { display: flex; align-items: center; gap: 12px; min-width: 0; overflow: hidden; }
.statusbar-right { flex-shrink: 0; }

.statusbar-connection,
.statusbar-branch,
.statusbar-user { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.statusbar-connection i, .statusbar-branch i, .statusbar-user i { font-size: 10px; }

.statusbar-connection.is-online { color: var(--color-success); }
.statusbar-connection.is-offline { color: var(--color-error); }

.statusbar-divider { width: 1px; height: 10px; background: var(--border-color-light); flex-shrink: 0; }
.statusbar-role-sep, .statusbar-role { color: var(--text-light); }
.statusbar-version { font-size: 10.5px; color: var(--text-light); font-variant-numeric: tabular-nums; }

/* ══════════════════════════════════════════════════════════════
   MOBILE BACKDROP
   ══════════════════════════════════════════════════════════════ */
.shell-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-header) - 2);
  background: var(--tint-black-20);
}

/* ══════════════════════════════════════════════════════════════
   DROPDOWN (branch selector — uses existing $sm.ui.dropdown)
   ══════════════════════════════════════════════════════════════ */
.workspace-shell .nav-item.dropdown { position: relative; display: inline-flex; }

.workspace-shell .dropdown-menu {
  min-width: 220px;
  padding: var(--space-2);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0; left: auto;
  list-style: none;
  flex-direction: column;
  gap: var(--space-1);
  display: none;
  z-index: var(--z-dropdown);
  max-height: 70vh;
  overflow-y: auto;
}
.workspace-shell .dropdown-open > .dropdown-menu { display: flex; }

.workspace-shell .dropdown-item {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  color: var(--text-primary); text-decoration: none;
  font-size: var(--text-sm); cursor: pointer;
  background: transparent; border: 0;
  white-space: nowrap;
  transition: background-color var(--transition-fast);
}
.workspace-shell .dropdown-item:hover { background: var(--bg-hover); }
.workspace-shell .dropdown-item.active { color: var(--shell-accent); font-weight: 500; }

.workspace-shell .dropdown-header {
  padding: var(--space-1) var(--space-3);
  color: var(--text-muted); font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
}
.workspace-shell .dropdown-divider { height: 1px; background: var(--border-color-light); margin: var(--space-1) 0; }

/* Profile meta (in popover header) */
.user-name { color: var(--text-primary); font-weight: var(--font-weight-semibold); font-size: 13.5px; }
.user-role, .branch-location { color: var(--text-muted); font-size: var(--text-xs); }

/* ══════════════════════════════════════════════════════════════
   NAVBAR LAYOUT MODE
   ══════════════════════════════════════════════════════════════ */
.workspace-shell[data-menu-layout="navbar"] .shell-sidebar { display: none; }
.workspace-shell[data-menu-layout="navbar"] .shell-brand--navbar { display: flex; }
.workspace-shell[data-menu-layout="navbar"] .shell-topbar-vdivider { display: block; }
.workspace-shell[data-menu-layout="navbar"] .shell-navbar-menu,
.workspace-shell[data-menu-layout="navbar"] .shell-navbar-menu.nav {
  display: flex;
  flex: 1;       /* fill remaining topbar-left space after brand + vdivider */
  min-width: 0;  /* allow shrinking below content size */
}
/* Spacer must NOT grow in navbar mode — topbar-left (flex:1) gets all remaining space */
.workspace-shell[data-menu-layout="navbar"] .shell-topbar-spacer { flex: 0; width: 0; }

/* ── Navbar mobile collapse (< 768px) — Bootstrap-style toggle ── */
@media (max-width: 767px) {
  /* Hamburger only visible on mobile in navbar mode */
  .workspace-shell[data-menu-layout="navbar"] .shell-menu-toggle { display: inline-grid; }
  /* Hide inline menu and vdivider on mobile */
  .workspace-shell[data-menu-layout="navbar"] .shell-navbar-menu,
  .workspace-shell[data-menu-layout="navbar"] .shell-navbar-menu.nav { display: none; }
  .workspace-shell[data-menu-layout="navbar"] .shell-topbar-vdivider { display: none; }

  /* Open: menu as absolute overlay panel below topbar (topbar height stays fixed) */
  .workspace-shell[data-menu-layout="navbar"].navbar-open .shell-topbar { overflow: visible; }
  .workspace-shell[data-menu-layout="navbar"].navbar-open .shell-navbar-menu,
  .workspace-shell[data-menu-layout="navbar"].navbar-open .shell-navbar-menu.nav {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--bg-card);
    border-bottom: 1px solid var(--border-color-light);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    z-index: var(--z-header);
    padding: 8px;
    gap: 2px;
  }
  /* Full-width items */
  .workspace-shell[data-menu-layout="navbar"].navbar-open .shell-navbar-menu .nav-link {
    width: 100%;
    justify-content: flex-start;
    border-radius: var(--radius-md);
  }
  /* Show ALL items — skip overflow logic */
  .workspace-shell[data-menu-layout="navbar"].navbar-open .shell-navbar-menu .nav-overflow-hidden {
    display: flex !important;
    flex-direction: column;
  }
  /* Hide the "more" overflow button — all items visible */
  .workspace-shell[data-menu-layout="navbar"].navbar-open .shell-navbar-menu .nav-more-container {
    display: none !important;
  }
}

/* ══════════════════════════════════════════════════════════════
   TABLET: 768px–1279px
   Sidebar always floats as an absolute overlay at --_swc width.
   Hover-expand: sidebar floats at full width over content.
   Hamburger: opens as full overlay drawer.
   Collapse button is disabled (forced-collapsed by screen size).
   ══════════════════════════════════════════════════════════════ */
/* ══════════════════════════════════════════════════════════════
   TABLET: 768px–1279px — sidebar as always-visible 56px strip
   Collapse button opens full-width overlay. No hamburger.
   ══════════════════════════════════════════════════════════════ */
@media (min-width: 768px) and (max-width: 1279px) {
  /* Branch selector: compact — icon + branch name only (hide business/plan row) */
  .shell-branch-btn { max-width: min(18vw, 160px); padding: 5px 8px; }
  .branch-text-business,
  .branch-text-plan { display: none; }

  /* Sidebar: absolute strip always visible at collapsed width */
  .workspace-shell:not([data-menu-layout="navbar"]) .shell-sidebar {
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: var(--_swc);
    z-index: 20;
    transition: width 200ms ease, box-shadow 200ms ease;
  }
  .workspace-shell:not([data-menu-layout="navbar"]) .shell-main {
    margin-left: var(--_swc);
    transition: margin-left 200ms ease;
  }

  /* Icon-only: hide labels — collapse icon → = "expand" */
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-nav-label,
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-nav-chevron,
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-collapse-label,
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-brand-info { display: none; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-nav-children,
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-nav-parent.expanded .shell-nav-children { display: none; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-nav-group-label { display: none; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-nav-group + .shell-nav-group .shell-nav-group-divider { display: block; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar-collapse { justify-content: center; padding-inline: 0; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-collapse-icon { transform: rotate(180deg); }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-brand { width: 40px; justify-content: center; padding-inline: 0; }

  /* Hover-expand: float over content */
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover {
    width: var(--_sw);
    box-shadow: var(--shadow-xl);
    z-index: 30;
    transition: width 160ms ease, box-shadow 160ms ease;
  }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-nav-label,
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-nav-chevron,
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-collapse-label,
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-brand-info { display: flex; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-nav-parent.expanded .shell-nav-children { display: flex; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-nav-group-label { display: block; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-nav-group + .shell-nav-group .shell-nav-group-divider { display: none; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-sidebar-collapse { justify-content: flex-end; padding: 0 12px; }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-collapse-icon { transform: rotate(0deg); }
  .workspace-shell:not([data-menu-layout="navbar"]):not(.menu-open) .shell-sidebar:hover .shell-brand { width: auto; justify-content: flex-start; padding-inline: 8px; }

  /* menu-open: expand sidebar + push content right */
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-main { margin-left: var(--_sw); }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-sidebar {
    width: var(--_sw);
    box-shadow: var(--shadow-xl);
    z-index: 30;
  }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-nav-label,
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-nav-chevron,
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-collapse-label,
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-brand-info { display: flex; }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-nav-parent.expanded .shell-nav-children { display: flex; }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-nav-group-label { display: block; }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-nav-group + .shell-nav-group .shell-nav-group-divider { display: none; }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-sidebar-collapse { justify-content: flex-end; padding: 0 12px; }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-collapse-icon { transform: rotate(0deg); }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-brand { width: auto; justify-content: flex-start; padding-inline: 8px; }
}

/* ══════════════════════════════════════════════════════════════
   MOBILE: < 768px — sidebar hidden, hamburger reveals it
   ══════════════════════════════════════════════════════════════ */
@media (max-width: 767px) {
  /* Hamburger: sidebar mode → far left via order; navbar mode → far right (last in HTML) */
  .workspace-shell:not([data-menu-layout="navbar"]) .shell-menu-toggle {
    display: inline-grid;
    order: -1;
  }

  /* ── Sidebar drawer (ALL layouts on mobile) ── */

  /* Navbar mode: override global display:none — sidebar is a drawer here too */
  .workspace-shell[data-menu-layout="navbar"] .shell-sidebar {
    display: flex;
    position: absolute;
    top: 0; left: 0; bottom: 0;
    width: 100%;
    transform: translateX(-100%);
    transition: transform 200ms ease, box-shadow 200ms ease;
    z-index: var(--z-header);
  }
  /* Sidebar mode: same drawer behaviour */
  .workspace-shell:not([data-menu-layout="navbar"]) .shell-sidebar {
    position: absolute;
    top: 0; left: 0; bottom: 0;
    width: 100%;
    transform: translateX(-100%);
    transition: transform 200ms ease, box-shadow 200ms ease;
    z-index: var(--z-header);
  }

  /* Revealed on menu-open (hamburger click) — both layouts */
  .workspace-shell.menu-open .shell-sidebar {
    transform: translateX(0);
    box-shadow: var(--shadow-xl);
  }

  /* Close button visible when drawer is open — both layouts */
  .workspace-shell.menu-open .shell-sidebar-close { display: inline-grid; }

  /* Always show expanded labels when drawer opens — both layouts */
  .workspace-shell.menu-open .shell-nav-label,
  .workspace-shell.menu-open .shell-nav-chevron,
  .workspace-shell.menu-open .shell-collapse-label,
  .workspace-shell.menu-open .shell-brand-info { display: flex; }
  .workspace-shell.menu-open .shell-nav-parent.expanded .shell-nav-children { display: flex; }
  .workspace-shell.menu-open .shell-nav-group-label { display: block; }
  .workspace-shell.menu-open .shell-nav-group + .shell-nav-group .shell-nav-group-divider { display: none; }
  .workspace-shell.menu-open .shell-brand { width: auto; justify-content: flex-start; padding-inline: 8px; }

  /* Sidebar collapse button: visible in sidebar mode, hidden in navbar mode (irrelevant there) */
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-sidebar-collapse { justify-content: flex-end; padding: 0 12px; }
  .workspace-shell:not([data-menu-layout="navbar"]).menu-open .shell-collapse-icon { transform: rotate(0deg); }
  .workspace-shell[data-menu-layout="navbar"] .shell-sidebar-collapse { display: none; }

  .shell-topbar { padding: 0 12px; }

  /* Branch selector: icon-only on mobile */
  .shell-branch-btn {
    width: 34px;
    height: 34px;
    padding: 0;
    max-width: none;
    border: 1px solid var(--border-color-light);
    border-radius: var(--radius-md);
    justify-content: center;
    gap: 0;
    background: transparent;
  }
  .shell-branch-btn .branch-text,
  .shell-branch-btn .chevron { display: none; }

  .shell-statusbar .statusbar-branch,
  .shell-statusbar .statusbar-user { display: none; }
  .shell-statusbar .statusbar-divider { display: none; }
}

/* components/avatar.css */
/**
 * Component: Avatar
 * Purpose:   User / entity image or initials, circular by default.
 * Added:     2026-04-22
 * Updated:   2026-04-22
 */

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  font-weight: var(--font-weight-semibold);
  font-size: var(--text-sm);
  overflow: hidden;
  flex: none;
}

.avatar.size-xs { width: 24px; height: 24px; font-size: 0.6875rem; }
.avatar.size-sm,
.avatar-sm { width: 32px; height: 32px; font-size: var(--text-xs); }
.avatar.size-lg,
.avatar-lg { width: 56px; height: 56px; font-size: var(--text-lg); }
.avatar.size-xl,
.avatar-xl { width: 80px; height: 80px; font-size: var(--text-2xl); }

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-initials {
  text-transform: uppercase;
}

.avatar-group {
  display: inline-flex;
  align-items: center;
}

.avatar-group .avatar + .avatar {
  margin-left: -0.5rem;
  border: 2px solid var(--bg-card);
}

/* components/badge.css */
/**
 * Component: Badge
 * Purpose:   Small label, counter, or status indicator.
 * Variants:  primary, secondary, muted, success, warning, error, danger, info, outline, inverse
 * Sizes:     size-sm, size-lg
 * Modifiers: badge-pill, badge-dot, badge-kicker
 * Depends:   tokens.css
 * Added:     2026-04-22
 * Updated:   2026-04-25
 */

.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  line-height: 1.4;
  letter-spacing: var(--letter-spacing-wide);
}

.badge-kicker {
  width: fit-content;
  padding: var(--space-1) var(--space-3);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  font-size: 0.75rem;
  font-weight: var(--font-weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.badge-primary { background: var(--ui-accent-soft); color: var(--ui-accent); }
.badge-secondary,
.badge-muted { background: var(--bg-subtle); color: var(--text-secondary); }
.badge-success { background: var(--color-success-bg); color: var(--color-success); }
.badge-warning { background: var(--color-warning-bg); color: var(--color-warning); }
.badge-error,
.badge-danger { background: var(--color-error-bg); color: var(--color-error); }
.badge-info { background: var(--color-info-bg); color: var(--color-info); }
.badge-outline { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); }

.badge-inverse {
  background: var(--tint-white-25);
  color: var(--text-white);
  border: 1px solid var(--tint-white-30);
}

.badge-pill { border-radius: var(--radius-full); }
.badge.size-sm { padding: 1px var(--space-2); font-size: 0.6875rem; }
.badge.size-lg { padding: var(--space-1) var(--space-3); font-size: var(--text-sm); }

.badge-dot {
  width: 0.5rem;
  height: 0.5rem;
  padding: 0;
  border-radius: var(--radius-full);
}

/* components/breadcrumb.css */
/**
 * Component: Breadcrumb
 * Purpose:   Path navigation — sequence of links showing hierarchy.
 * Base:      breadcrumb, breadcrumb-separator
 * Depends:   tokens.css
 * Added:     2026-04-22 (ported from engine/ui/templates.css)
 *
 * Usage:
 *   <nav class="breadcrumb">
 *     <a href="/">Home</a>
 *     <span class="breadcrumb-separator">/</span>
 *     <a href="/customers">Customers</a>
 *     <span class="breadcrumb-separator">/</span>
 *     <span>Alice</span>
 *   </nav>
 */

.breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-bottom: var(--space-3);
  flex-wrap: wrap;
}
.breadcrumb a { color: var(--text-secondary); text-decoration: none; }
.breadcrumb a:hover { color: var(--ui-accent); }
.breadcrumb-separator { color: var(--color-gray-400); }

/* components/button.css */
/**
 * Component: Button
 * Purpose:   Primary action element - filled, outline, ghost, grouped.
 * Variants:  primary, secondary, success, danger, warning, info, ghost, link,
 *            outline, outline-primary, outline-secondary, outline-danger, outline-success
 * Sizes:     size-xs, size-sm, size-md, size-lg
 * Modifiers: btn-icon (square), btn-block (full width), btn-group (segmented)
 * States:    :hover, :active, .active, :disabled, [aria-disabled="true"], .is-loading
 * Depends:   tokens.css, animations.css
 * Added:     2026-04-22
 * Updated:   2026-04-22
 */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--btn-height);
  min-width: var(--btn-height);
  padding: 0 var(--btn-padding-x);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-family);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1;
  letter-spacing: var(--letter-spacing-normal);
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast),
    box-shadow var(--transition-fast),
    transform var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
}

.btn:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.btn:active:not(:disabled) {
  transform: translateY(1px);
}

.btn-primary {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
}

.btn-primary:hover:not(:disabled) {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  box-shadow: var(--shadow-btn-primary-hover);
}

.btn-primary:active:not(:disabled),
.btn-primary.active {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  box-shadow: inset 0 0 0 999px var(--tint-black-10);
}

.btn-secondary {
  background: var(--bg-primary);
  border-color: var(--border-color);
  color: var(--text-primary);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--border-color-dark);
}

.btn-secondary:active:not(:disabled),
.btn-secondary.active {
  background: var(--ui-control-active);
  border-color: var(--ui-accent);
  color: var(--ui-accent);
}

.btn-success {
  background: var(--color-success);
  border-color: var(--color-success);
  color: var(--text-white);
}

.btn-success:hover:not(:disabled),
.btn-success:active:not(:disabled),
.btn-success.active {
  background: var(--color-success-dark);
  border-color: var(--color-success-dark);
}

.btn-danger {
  background: var(--color-error);
  border-color: var(--color-error);
  color: var(--text-white);
}

.btn-danger:hover:not(:disabled),
.btn-danger:active:not(:disabled),
.btn-danger.active {
  background: var(--color-error-dark);
  border-color: var(--color-error-dark);
}

.btn-warning {
  background: var(--color-warning);
  border-color: var(--color-warning);
  color: var(--text-white);
}

.btn-warning:hover:not(:disabled),
.btn-warning:active:not(:disabled),
.btn-warning.active {
  background: var(--color-warning-dark);
  border-color: var(--color-warning-dark);
}

.btn-info {
  background: var(--color-info);
  border-color: var(--color-info);
  color: var(--text-white);
}

.btn-info:hover:not(:disabled),
.btn-info:active:not(:disabled),
.btn-info.active {
  background: var(--color-accent-dark);
  border-color: var(--color-accent-dark);
}

.btn-outline {
  background: transparent;
  border-color: var(--border-color-dark);
  color: var(--text-primary);
}

.btn-outline:hover:not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--ui-accent);
}

.btn-outline.active,
.btn-outline:active:not(:disabled) {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
}

.btn-outline-primary {
  background: transparent;
  border-color: var(--ui-accent);
  color: var(--ui-accent);
}

.btn-outline-primary:hover:not(:disabled) {
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

.btn-outline-primary.active,
.btn-outline-primary:active:not(:disabled) {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
}

.btn-outline-secondary {
  background: transparent;
  border-color: var(--color-secondary-500);
  color: var(--color-secondary-700);
}

.btn-outline-secondary:hover:not(:disabled) {
  background: var(--tint-secondary-10);
  color: var(--color-secondary-800);
}

.btn-outline-secondary.active,
.btn-outline-secondary:active:not(:disabled) {
  background: var(--color-secondary-700);
  border-color: var(--color-secondary-700);
  color: var(--text-white);
}

.btn-outline-danger {
  background: transparent;
  border-color: var(--color-error);
  color: var(--color-error);
}

.btn-outline-danger:hover:not(:disabled) {
  background: var(--color-error-bg);
}

.btn-outline-danger.active,
.btn-outline-danger:active:not(:disabled) {
  background: var(--color-error);
  border-color: var(--color-error);
  color: var(--text-white);
}

.btn-outline-success {
  background: transparent;
  border-color: var(--color-success);
  color: var(--color-success);
}

.btn-outline-success:hover:not(:disabled) {
  background: var(--color-success-bg);
}

.btn-outline-success.active,
.btn-outline-success:active:not(:disabled) {
  background: var(--color-success);
  border-color: var(--color-success);
  color: var(--text-white);
}

.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
}

.btn-ghost:hover:not(:disabled) {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.btn-ghost:active:not(:disabled) {
  background: var(--bg-active);
}

.btn-link {
  min-width: 0;
  height: auto;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-link);
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.btn-link:hover:not(:disabled) {
  background: transparent;
  color: var(--text-link-hover);
  box-shadow: none;
  transform: none;
}

.btn-link:active:not(:disabled) {
  transform: none;
}

.btn.size-xs,
.btn-xs {
  height: var(--btn-height-xs);
  font-size: var(--text-xs);
  padding: 0 var(--space-2);
}

.btn.size-sm,
.btn-sm {
  height: var(--btn-height-sm);
  font-size: var(--text-xs);
  padding: 0 var(--space-3);
}

.btn.size-md {
  height: var(--btn-height);
  font-size: var(--text-sm);
  padding: 0 var(--btn-padding-x);
}

.btn.size-lg,
.btn-lg {
  height: var(--btn-height-lg);
  font-size: var(--text-base);
  padding: 0 var(--space-6);
}

.btn-icon {
  padding: 0;
  width: var(--btn-height);
  aspect-ratio: 1 / 1;
}

.btn-icon.size-xs,
.btn-icon.btn-xs {
  width: var(--btn-height-xs);
}

.btn-icon.size-sm,
.btn-icon.btn-sm {
  width: var(--btn-height-sm);
}

.btn-icon.size-lg,
.btn-icon.btn-lg {
  width: var(--btn-height-lg);
}

.btn-block {
  width: 100%;
}

.btn.is-loading {
  color: transparent !important;
  pointer-events: none;
  position: relative;
}

.btn.is-loading::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-full);
  color: var(--text-white);
  animation: spin 700ms linear infinite;
}

.btn-secondary.is-loading::after,
.btn-ghost.is-loading::after,
.btn-link.is-loading::after {
  color: var(--ui-accent);
}

.btn-group {
  display: inline-flex;
  align-items: stretch;
}

.btn-group > .btn {
  border-radius: 0;
  position: relative;
}

.btn-group > .btn:first-child {
  border-top-left-radius: var(--radius-md);
  border-bottom-left-radius: var(--radius-md);
}

.btn-group > .btn:last-child {
  border-top-right-radius: var(--radius-md);
  border-bottom-right-radius: var(--radius-md);
}

.btn-group > .btn + .btn {
  margin-left: -1px;
}

.btn-group > .btn:hover,
.btn-group > .btn.active,
.btn-group > .btn:focus-visible {
  z-index: 1;
}

@media (max-width: 640px) {
  .btn:not(.btn-link):not(.btn-icon) {
    min-height: var(--touch-target);
  }

  .btn.size-xs:not(.btn-icon),
  .btn-xs:not(.btn-icon),
  .btn.size-sm:not(.btn-icon),
  .btn-sm:not(.btn-icon) {
    min-height: var(--touch-target);
  }

  .btn-block-mobile {
    width: 100%;
  }
}

/* components/icon-button.css */
/**
 * Component: Icon Button
 * Purpose:   Square icon-only buttons for navbar, toolbars, compact actions.
 * Base:      icon-button
 * Variants:  icon-button-primary, icon-button-secondary, icon-button-danger, icon-button-ghost, icon-button-link
 * Sizes:     size-xs, size-sm, size-md, size-lg
 * Modifiers: icon-button-round (circular), icon-button-badge (badge positioning support)
 * States:    :hover, :focus-visible, :active, .active, :disabled, [aria-disabled="true"], .is-loading
 * Depends:   tokens.css, animations.css
 * Added:     2026-04-25
 * Note:      Follows .btn pattern for consistency.
 */

.icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-btn-height);
  height: var(--icon-btn-height);
  min-width: var(--icon-btn-height);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-primary);
  font-size: var(--text-base);
  line-height: 1;
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast),
    box-shadow var(--transition-fast),
    transform var(--transition-fast);
  -webkit-tap-highlight-color: transparent;
}

.icon-button:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.icon-button:disabled,
.icon-button[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.icon-button:active:not(:disabled) {
  transform: translateY(1px);
}

/* ─────────────────────────────────────────────────────────────
   Variants (color themes)
   ───────────────────────────────────────────────────────────── */

.icon-button-primary {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
}

.icon-button-primary:hover:not(:disabled) {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  box-shadow: var(--shadow-btn-primary-hover);
}

.icon-button-primary:active:not(:disabled),
.icon-button-primary.active {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  box-shadow: inset 0 0 0 999px var(--tint-black-10);
}

.icon-button-secondary {
  background: var(--bg-primary);
  border-color: var(--border-color);
  color: var(--text-primary);
}

.icon-button-secondary:hover:not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--border-color-dark);
}

.icon-button-secondary:active:not(:disabled),
.icon-button-secondary.active {
  background: var(--ui-control-active);
  border-color: var(--ui-accent);
  color: var(--ui-accent);
}

.icon-button-success {
  background: var(--color-success);
  border-color: var(--color-success);
  color: var(--text-white);
}

.icon-button-success:hover:not(:disabled),
.icon-button-success:active:not(:disabled),
.icon-button-success.active {
  background: var(--color-success-dark);
  border-color: var(--color-success-dark);
}

.icon-button-danger {
  background: var(--color-error);
  border-color: var(--color-error);
  color: var(--text-white);
}

.icon-button-danger:hover:not(:disabled),
.icon-button-danger:active:not(:disabled),
.icon-button-danger.active {
  background: var(--color-error-dark);
  border-color: var(--color-error-dark);
}

.icon-button-warning {
  background: var(--color-warning);
  border-color: var(--color-warning);
  color: var(--text-white);
}

.icon-button-warning:hover:not(:disabled),
.icon-button-warning:active:not(:disabled),
.icon-button-warning.active {
  background: var(--color-warning-dark);
  border-color: var(--color-warning-dark);
}

.icon-button-info {
  background: var(--color-info);
  border-color: var(--color-info);
  color: var(--text-white);
}

.icon-button-info:hover:not(:disabled),
.icon-button-info:active:not(:disabled),
.icon-button-info.active {
  background: var(--color-accent-dark);
  border-color: var(--color-accent-dark);
}

.icon-button-ghost {
  background: transparent;
  color: var(--text-secondary);
}

.icon-button-ghost:hover:not(:disabled) {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.icon-button-ghost:active:not(:disabled) {
  background: var(--bg-active);
}

.icon-button-link {
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-link);
}

.icon-button-link:hover:not(:disabled) {
  background: transparent;
  color: var(--text-link-hover);
  box-shadow: none;
  transform: none;
}

.icon-button-link:active:not(:disabled) {
  transform: none;
}

/* ─────────────────────────────────────────────────────────────
   Sizes (square dimensions)
   ───────────────────────────────────────────────────────────── */

.icon-button.size-xs,
.icon-button-xs {
  width: var(--icon-btn-height-xs);
  height: var(--icon-btn-height-xs);
  font-size: var(--text-xs);
}

.icon-button.size-sm,
.icon-button-sm {
  width: var(--icon-btn-height-sm);
  height: var(--icon-btn-height-sm);
  font-size: var(--text-sm);
}

.icon-button.size-md {
  width: var(--icon-btn-height);
  height: var(--icon-btn-height);
  font-size: var(--text-base);
}

.icon-button.size-lg,
.icon-button-lg {
  width: var(--icon-btn-height-lg);
  height: var(--icon-btn-height-lg);
  font-size: var(--text-lg);
}

/* ─────────────────────────────────────────────────────────────
   Modifiers
   ───────────────────────────────────────────────────────────── */

/* Circular icon button (instead of rounded square) */
.icon-button-round {
  border-radius: var(--radius-full);
}

/* Support badge positioning (e.g., cart with item count) */
.icon-button-badge {
  position: relative;
}

/* Badge element inside icon-button */
.icon-button-badge::after {
  content: attr(data-badge);
  position: absolute;
  top: -0.375rem;
  right: -0.25rem;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 var(--space-1);
  border-radius: var(--radius-full);
  background: var(--color-danger);
  color: var(--text-white);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-bold);
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* Hide badge when empty or absent */
.icon-button-badge[data-badge=""]::after,
.icon-button-badge:not([data-badge])::after {
  display: none;
}

/* ─────────────────────────────────────────────────────────────
   States
   ───────────────────────────────────────────────────────────── */

.icon-button.is-loading {
  color: transparent !important;
  pointer-events: none;
  position: relative;
}

.icon-button.is-loading::before {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: var(--radius-full);
  color: var(--text-white);
  animation: spin 700ms linear infinite;
}

.icon-button-secondary.is-loading::before,
.icon-button-ghost.is-loading::before,
.icon-button-link.is-loading::before {
  color: var(--ui-accent);
}

/* ─────────────────────────────────────────────────────────────
   Responsive
   ───────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
  /* Ensure icon buttons stay touchable on mobile (44px minimum) */
  .icon-button {
    min-width: 2.75rem;
    min-height: 2.75rem;
  }
}

/* components/card.css */
/**
 * Component: Card
 * Purpose:   Content surface with optional header / body / footer.
 * Sub:       card-header, card-title, card-subtitle, card-body, card-footer
 * Modifiers: is-interactive (hover lift)
 * States:    :hover (on .is-interactive)
 * Depends:   tokens.css
 * Added:     2026-04-22
 */

.card {
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
  transition: box-shadow var(--transition-fast),
              border-color var(--transition-fast),
              transform var(--transition-fast);
}
.card.is-interactive { cursor: pointer; }
.card.is-interactive:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--border-color);
  transform: translateY(-1px);
}
.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--border-color-light);
  background: var(--bg-subtle);
}
.card-title {
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  letter-spacing: var(--letter-spacing-normal);
  line-height: var(--line-height-snug);
}
.card-subtitle {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  margin-top: var(--space-1);
}
.card-body {
  padding: var(--space-6);
}
.card-footer {
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--border-color-light);
  background: var(--bg-subtle);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

/* Card variants */

.card.card-compact,
.card.size-sm {
  box-shadow: none;
  border-color: var(--border-color);
}

.card.card-compact .card-header,
.card.size-sm .card-header {
  padding: var(--space-2) var(--space-3);
}

.card.card-compact .card-body,
.card.size-sm .card-body {
  padding: var(--space-3);
}

.card.card-compact .card-footer,
.card.size-sm .card-footer {
  padding: var(--space-2) var(--space-3);
}

.card.card-compact .card-title,
.card.size-sm .card-title {
  font-size: var(--text-sm);
}

.card.card-muted {
  background: var(--bg-subtle);
  border-color: var(--border-color);
  box-shadow: none;
}

.card.card-muted .card-header {
  background: var(--bg-muted);
}

.card.card-muted .card-footer {
  background: var(--bg-muted);
}

.card.size-lg .card-header {
  padding: var(--space-6) var(--space-8);
}

.card.size-lg .card-body {
  padding: var(--space-8);
}

.card.size-lg .card-footer {
  padding: var(--space-6) var(--space-8);
}

.card.size-lg .card-title {
  font-size: var(--text-lg);
}

@media (max-width: 640px) {
  .card-header,
  .card-footer {
    align-items: stretch;
    flex-direction: column;
    padding: var(--space-3) var(--space-4);
  }

  .card-body {
    padding: var(--space-4);
  }

  .card.size-lg .card-header,
  .card.size-lg .card-body,
  .card.size-lg .card-footer {
    padding: var(--space-4);
  }
}

/* components/chip.css */
/**
 * Component: Chip
 * Purpose:   Compact toggle / filter / tag element. Outlined by default;
 *            fills to primary when .active (or legacy .is-active).
 * Sub:       chip-close (small dismiss button)
 * States:    :hover, .active, .is-active (alias)
 * Depends:   tokens.css
 * Added:     2026-04-22
 */

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 28px;
  padding: 0 var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition: background-color var(--transition-fast),
              border-color var(--transition-fast),
              color var(--transition-fast);
}
.chip:hover {
  background: var(--bg-hover);
  border-color: var(--border-color-dark);
  color: var(--text-primary);
}
.chip.active,
.chip.is-active {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
}
.chip-close { cursor: pointer; opacity: 0.6; }
.chip-close:hover { opacity: 1; }

/* Static (display-only) chip — no hover, no cursor */
.chip-static {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--text-secondary);
  background: var(--bg-secondary);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-full);
  padding: 2px var(--space-3);
  white-space: nowrap;
  cursor: default;
  pointer-events: none;
}

/* components/dropdown.css */
/**
 * Component: Dropdown
 * Purpose:   Toggle-triggered menu surface for actions and small selectors.
 * Variants:  right, flush
 * Sizes:     inherited from trigger/content
 * States:    .is-open, [aria-expanded="true"]
 * Added:     2026-04-22
 */

.dropdown {
  position: relative;
  display: inline-flex;
}

.dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.dropdown-menu {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 0;
  min-width: 12rem;
  padding: var(--space-2);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px);
  transition: opacity var(--transition-fast), transform var(--transition-fast), visibility var(--transition-fast);
  z-index: var(--z-dropdown);
  max-width: min(24rem, calc(100vw - var(--space-4) * 2));
}

.dropdown.is-open .dropdown-menu,
.dropdown.open .dropdown-menu,
.dropdown[aria-expanded="true"] .dropdown-menu {
  display: flex;
  flex-direction: column;
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.dropdown.align-right .dropdown-menu,
.dropdown-menu.align-right {
  left: auto;
  right: 0;
}

.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  background: transparent;
  border: 0;
  color: var(--text-primary);
  text-decoration: none;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.dropdown-item:hover,
.dropdown-item:focus-visible {
  background: var(--bg-hover);
  color: var(--ui-accent);
  outline: none;
}

.dropdown-divider {
  height: 1px;
  margin: var(--space-2) 0;
  background: var(--border-color-light);
}

/* Touch-target fix: apply at all mobile sizes, not just ≤480px */
@media (max-width: 767px) {
  .dropdown-item {
    min-height: var(--touch-target); /* WCAG 2.5.8 — 44px */
  }
}

@media (max-width: 480px) {
  .dropdown-menu {
    min-width: min(16rem, calc(100vw - var(--space-4) * 2));
  }
}

/* components/export.css */
/**
 * Component: Export
 * Purpose:   Export action dropdown and generated export surfaces.
 * Base:      export-menu, export-action, export-table
 * Added:     2026-05-20
 */

.export-menu {
  display: inline-flex;
  position: relative;
}

.export-menu .dropdown-toggle {
  min-width: var(--btn-height);
}

.export-action {
  white-space: nowrap;
}

.export-action i {
  width: 1.25rem;
  text-align: center;
  color: var(--text-muted);
}

.export-action:hover i,
.export-action:focus-visible i {
  color: var(--ui-accent);
}

.export-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-family);
  font-size: var(--text-sm);
}

.export-table th,
.export-table td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border-color-light);
  text-align: left;
  vertical-align: top;
}

.export-table th {
  background: var(--table-header-bg);
  font-weight: var(--font-semibold);
}

.export-document {
  background: #fff;
  color: #111827;
  font-family: var(--font-family);
  padding: var(--space-8);
}

.export-document-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-2xl);
  font-weight: var(--font-semibold);
}

.export-document-subtitle,
.export-document-footer {
  color: #6b7280;
  font-size: var(--text-sm);
}

.export-document-footer {
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  border-top: 1px solid #e5e7eb;
  text-align: right;
}

@media print {
  .export-no-print {
    display: none !important;
  }
}

/* components/form.css */
/**
 * Component: Form
 * Purpose:   Form field wrapper + controls (input / textarea / select) + input group.
 * Base:      form-field, form-control, form-select, form-label, form-hint, form-error
 * Group:     input-group, input-group-addon
 * Sizes:     size-sm, size-lg
 * States:    :hover, :focus, :disabled, .is-invalid
 * Depends:   tokens.css
 * Added:     2026-04-22
 * Updated:   2026-04-22
 */

.form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.form-label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
}

.form-label .required {
  color: var(--color-error);
  margin-left: var(--space-1);
}

.form-hint,
.form-text {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.form-error {
  font-size: var(--text-xs);
  color: var(--color-error);
}

.form-control,
.form-select {
  width: 100%;
  height: var(--input-height);
  min-width: 0;
  padding: 0 var(--input-padding-x);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-primary);
  color: var(--text-primary);
  font-family: var(--font-family);
  font-size: var(--text-sm);
  line-height: 1.4;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast), color var(--transition-fast);
}

.form-control::placeholder,
.form-select::placeholder {
  color: var(--text-light);
}

.form-control:hover:not(:disabled):not(:focus),
.form-select:hover:not(:disabled):not(:focus) {
  border-color: var(--border-color-dark);
}

.form-control:focus,
.form-select:focus {
  outline: none;
  border-color: var(--ui-accent);
  box-shadow: 0 0 0 3px var(--ui-focus-ring);
}

.form-control:disabled,
.form-select:disabled {
  background: var(--bg-subtle);
  color: var(--text-muted);
  cursor: not-allowed;
}

.form-control.is-valid,
.form-select.is-valid,
.form-field.is-valid .form-control,
.form-field.is-valid .form-select {
  border-color: var(--color-success);
  box-shadow: 0 0 0 3px rgba(var(--color-success-rgb), 0.15);
}

.form-control.is-invalid,
.form-select.is-invalid,
.form-field.is-invalid .form-control,
.form-field.is-invalid .form-select {
  border-color: var(--color-error);
  box-shadow: 0 0 0 3px rgba(var(--color-error-rgb), 0.15);
}

.form-control.is-warning,
.form-select.is-warning,
.form-field.is-warning .form-control,
.form-field.is-warning .form-select {
  border-color: var(--color-warning);
  box-shadow: 0 0 0 3px rgba(var(--color-warning-rgb), 0.15);
}

.form-control.is-info,
.form-select.is-info,
.form-field.is-info .form-control,
.form-field.is-info .form-select {
  border-color: var(--color-info);
  box-shadow: 0 0 0 3px rgba(var(--color-info-rgb), 0.15);
}

/* Form checkbox/radio validation states */
.form-check.is-valid .form-check-input {
  border-color: var(--color-success);
  accent-color: var(--color-success);
}

.form-check.is-invalid .form-check-input {
  border-color: var(--color-error);
  accent-color: var(--color-error);
}

.form-check.is-warning .form-check-input {
  border-color: var(--color-warning);
  accent-color: var(--color-warning);
}

.form-check.is-info .form-check-input {
  border-color: var(--color-info);
  accent-color: var(--color-info);
}

textarea.form-control {
  height: auto;
  min-height: 96px;
  padding: var(--space-3);
  resize: vertical;
}

.form-select,
select.form-select,
select.form-control {
  appearance: none;
  padding-right: var(--space-8);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%235C5852' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
}

.form-control.size-xs,
.form-select.size-xs,
.form-control-xs {
  height: var(--input-height-xs);
  font-size: var(--text-xs);
}

.form-control.size-sm,
.form-select.size-sm,
.form-control-sm {
  height: var(--input-height-sm);
  font-size: var(--text-xs);
}

.form-control.size-lg,
.form-select.size-lg,
.form-control-lg {
  height: var(--input-height-lg);
  font-size: var(--text-base);
}

.input-group {
  --input-group-height: var(--input-height);
  display: flex;
  align-items: stretch;
  position: relative;
  min-width: 0;
}

.input-group:has(.size-xs),
.input-group:has(.form-control-xs) {
  --input-group-height: var(--input-height-xs);
}

.input-group:has(.size-sm),
.input-group:has(.form-control-sm) {
  --input-group-height: var(--input-height-sm);
}

.input-group:has(.size-lg),
.input-group:has(.form-control-lg) {
  --input-group-height: var(--input-height-lg);
}

.input-group .form-control,
.input-group .form-select,
.input-group .btn,
.input-group .input-group-addon {
  height: var(--input-group-height);
  min-height: var(--input-group-height);
  border-radius: 0;
}

.input-group .btn,
.input-group .input-group-addon {
  flex: 0 0 auto;
}

.input-group .form-control:first-child,
.input-group .form-select:first-child,
.input-group .btn:first-child,
.input-group .input-group-addon:first-child {
  border-top-left-radius: var(--radius-md);
  border-bottom-left-radius: var(--radius-md);
}

.input-group .form-control:last-child,
.input-group .form-select:last-child,
.input-group .btn:last-child,
.input-group .input-group-addon:last-child {
  border-top-right-radius: var(--radius-md);
  border-bottom-right-radius: var(--radius-md);
}

.input-group > * + * {
  margin-left: -1px;
}

.input-group > *:focus,
.input-group > *:focus-visible,
.input-group > .form-control:focus,
.input-group > .form-select:focus,
.input-group > .btn:focus-visible {
  position: relative;
  z-index: 1;
}

.input-group-addon {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--space-3);
  background: var(--bg-subtle);
  border: 1px solid var(--border-color);
  min-width: var(--input-height);
  justify-content: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.input-group:has(.size-xs) .input-group-addon,
.input-group:has(.form-control-xs) .input-group-addon,
.input-group:has(.size-sm) .input-group-addon,
.input-group:has(.form-control-sm) .input-group-addon {
  font-size: var(--text-xs);
}

.sm-datepicker {
  position: relative;     /* anchor for .hidden-date-input */
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  width: auto;
  min-width: 13rem;
  cursor: pointer;
}

/*
 * Hidden native <input type="date"> — invisible 1px anchor for showPicker().
 * Placed at the BOTTOM of the wrapper (inset: auto auto 0 0) so the browser
 * opens the calendar popup BELOW the datepicker control, not above it.
 * Every datepicker that uses initDatePicker() gets .sm-datepicker added
 * automatically — this rule covers all of them; no local copies needed.
 */
.sm-datepicker .hidden-date-input {
  position: absolute;
  inset: auto auto 0 0;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Calendar trigger button — base style; pages may extend for local sizing/color */
.sm-datepicker .btn-date-trigger {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text-muted, currentColor);
  cursor: pointer;
  line-height: 1;
}

/* ── Custom calendar popup (sm-datepicker-popup / sdp-*) ──────────────────
 * Injected by initDatePicker() into every .sm-datepicker wrapper.
 * Desktop: custom app-styled month grid (consistent, locale-aware).
 * Mobile/touch: falls back to native showPicker() — this popup stays hidden.
 * ─────────────────────────────────────────────────────────────────────── */

/*
 * Portal variant — rendered at <body> level when the datepicker is inside a
 * scroll container (.modal-body, overflow:hidden wrappers).  JS sets top/left
 * via getBoundingClientRect(), so position:fixed escapes all overflow clipping.
 * z-index sits just above --z-modal (1200) so it paints over modal content.
 */
.sm-datepicker-popup.sdp-portal {
  position: fixed;
  z-index: calc(var(--z-modal, 1200) + 10);
}

.sm-datepicker-popup {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: 0;
  z-index: var(--z-popover, 1300);
  display: none;
  width: 18rem;
  padding: var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  box-shadow: var(--shadow-lg);
  color: var(--text-primary);
}

.sm-datepicker-popup.sdp-open {
  display: block;
}

.sdp-header {
  display: grid;
  grid-template-columns: 2rem 1fr 2rem;
  align-items: center;
  gap: var(--space-1);
  margin-bottom: var(--space-2);
}

.sdp-month-year {
  color: var(--text-primary);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  text-align: center;
}

.sdp-weekdays,
.sdp-days {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--space-1);
}

.sdp-weekday {
  color: var(--text-secondary);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  text-align: center;
  padding-block: var(--space-1);
}

.sdp-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1;
  min-width: 2rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-primary);
  font-size: var(--text-sm);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.sdp-cell:hover,
.sdp-cell:focus-visible {
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  outline: none;
}

.sdp-cell.sdp-other {
  color: var(--text-muted);
}

.sdp-cell.sdp-today {
  box-shadow: inset 0 0 0 1px var(--ui-accent);
}

.sdp-cell.sdp-selected {
  background: var(--ui-accent);
  color: var(--ui-accent-fg);
  font-weight: var(--font-weight-semibold);
}

.sdp-cell.sdp-selected:hover {
  background: var(--ui-accent);
  color: var(--ui-accent-fg);
}

.sm-datepicker.size-xs,
.sm-datepicker.form-control-xs {
  min-width: 9rem;
}

.sm-datepicker.size-sm,
.sm-datepicker.form-control-sm {
  min-width: 12rem;
}

.sm-datepicker.size-lg,
.sm-datepicker.form-control-lg {
  min-width: 15rem;
}

.sm-datepicker .date-text,
.sm-datepicker .picker-date {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sm-datepicker .date-text {
  flex: 1;
}

.sm-datepicker .date-text-input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}

.form-check {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 0;
  cursor: pointer;
}

.form-check-input {
  width: 1rem;
  height: 1rem;
  flex: 0 0 auto;
  margin: 0;
  accent-color: var(--ui-accent);
}

.form-switch {
  min-height: var(--input-height);
}

.form-switch .form-check-input {
  position: relative;
  order: 2;
  width: 2.25rem;
  height: 1.25rem;
  border: 1px solid var(--border-color-dark);
  border-radius: var(--radius-full);
  background: var(--bg-tertiary);
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form-switch .form-check-input::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 2px;
  width: calc(1.25rem - 6px);
  height: calc(1.25rem - 6px);
  border-radius: var(--radius-full);
  background: var(--bg-primary);
  box-shadow: var(--shadow-sm);
  transform: translateY(-50%);
  transition: transform var(--transition-fast), background-color var(--transition-fast);
}

.form-switch .form-check-input:checked {
  border-color: var(--ui-accent);
  background: var(--ui-accent);
}

.form-switch .form-check-input:checked::after {
  background: var(--ui-accent-fg);
  transform: translate(1rem, -50%);
}

.form-switch .form-check-input:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.form-switch .form-check-input:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.form-switch .form-check-input:disabled + .form-check-label {
  color: var(--text-muted);
  cursor: not-allowed;
}

.form-switch .form-check-label,
.form-switch > span {
  order: 1;
  min-width: 0;
}

.switch-field {
  width: 100%;
  height: var(--input-height);
  min-height: var(--input-height);
  justify-content: space-between;
  padding: 0 var(--input-padding-x);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-primary);
  transition: background-color var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.switch-field:hover {
  border-color: var(--border-color-dark);
}

.switch-field:has(.form-check-input:focus-visible) {
  border-color: var(--ui-accent);
  box-shadow: 0 0 0 3px var(--ui-focus-ring);
}

.switch-field .form-check-input:focus-visible {
  box-shadow: none;
}

.form-check-label {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.form-check.is-valid .form-check-label {
  color: var(--color-success);
}

.form-check.is-invalid .form-check-label {
  color: var(--color-error);
}

.form-check.is-warning .form-check-label {
  color: var(--color-warning);
}

.form-check.is-info .form-check-label {
  color: var(--color-info);
}

.form-feedback {
  font-size: var(--text-xs);
  margin-top: var(--space-1);
  display: block;
}

.form-feedback-success,
.form-feedback.success {
  color: var(--color-success);
}

.form-feedback-danger,
.form-feedback.danger,
.form-feedback-error,
.form-feedback.error {
  color: var(--color-error);
}

.form-feedback-warning,
.form-feedback.warning {
  color: var(--color-warning);
}

.form-feedback-info,
.form-feedback.info {
  color: var(--color-info);
}

@media (max-width: 640px) {
  .form-control,
  .form-select {
    min-height: var(--touch-target);
  }

  .form-control.size-xs,
  .form-select.size-xs,
  .form-control-xs,
  .form-control.size-sm,
  .form-select.size-sm,
  .form-control-sm {
    min-height: var(--touch-target);
  }

  .input-group {
    width: 100%;
    --input-group-height: var(--touch-target);
  }

  .form-check {
    min-height: var(--touch-target);
  }
}

/* components/icon-box.css */
/**
 * Component: Icon box
 * Purpose:   Square tinted container for an icon or glyph. Used in stat cards,
 *            feature lists, menu items, empty states, etc.
 *
 * Sizes:    size-xs (1.5rem), size-sm (2rem), size-md (2.5rem, default),
 *           size-lg (3rem), size-xl (4rem)
 * Colors:   is-primary (default), is-secondary, is-success, is-warning,
 *           is-danger, is-info, is-neutral, is-inverse
 * Shapes:   default (rounded-md), .icon-box-circle (circle),
 *           .icon-box-square (no radius)
 *
 * Depends:  tokens.css
 * Added:    2026-04-24
 */

.icon-box {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-md);
  background: var(--tint-primary-10);
  color: var(--ui-accent);
  font-size: 1.125rem;
  line-height: 1;
}

.icon-box.size-xs { width: 1.5rem; height: 1.5rem; font-size: 0.75rem; border-radius: var(--radius-sm); }
.icon-box.size-sm { width: 2rem;   height: 2rem;   font-size: 0.9375rem; }
.icon-box.size-md { width: 2.5rem; height: 2.5rem; font-size: 1.125rem; }
.icon-box.size-lg { width: 3rem;   height: 3rem;   font-size: 1.25rem; }
.icon-box.size-xl { width: 4rem;   height: 4rem;   font-size: 1.75rem; border-radius: var(--radius-lg); }

.icon-box.is-primary   { background: var(--ui-accent-soft);   color: var(--ui-accent); }
.icon-box.is-secondary { background: var(--tint-secondary-10); color: var(--color-secondary-700); }
.icon-box.is-success   { background: var(--color-success-bg);  color: var(--color-success); }
.icon-box.is-warning   { background: var(--color-warning-bg);  color: var(--color-warning); }
.icon-box.is-danger    { background: var(--color-error-bg);    color: var(--color-error); }
.icon-box.is-info      { background: var(--color-info-bg);     color: var(--color-info); }
.icon-box.is-neutral   { background: var(--bg-subtle);         color: var(--text-secondary); }
.icon-box.is-inverse   { background: rgba(255, 255, 255, 0.12); color: var(--text-white); }

.icon-box-circle { border-radius: var(--radius-full); }
.icon-box-square { border-radius: 0; }

/* components/list-group.css */
/**
 * Component: List group
 * Purpose:   Vertical sequence of items with optional active / disabled states.
 * Added:     2026-04-22
 */

.list-group {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--bg-card);
}

.list-group-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  color: var(--text-primary);
  text-decoration: none;
  background: var(--bg-card);
  border-bottom: 1px solid var(--border-color-light);
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.list-group-item:last-child {
  border-bottom: 0;
}

.list-group-item:hover {
  background: var(--bg-hover);
}

.list-group-item.active {
  background: var(--tint-primary-10);
  color: var(--ui-accent);
}

.list-group-item.disabled,
.list-group-item[aria-disabled="true"] {
  opacity: 0.55;
  pointer-events: none;
}

/* components/modal.css */
/**
 * Component: Modal
 * Purpose:   Dialog overlay with backdrop, header/body/footer slots.
 * Added:     2026-04-22
 * Updated:   2026-04-22
 */

.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: none;
  align-items: center;
  justify-content: center;
  padding: max(var(--space-4), env(safe-area-inset-top)) max(var(--space-4), env(safe-area-inset-right)) max(var(--space-4), env(safe-area-inset-bottom)) max(var(--space-4), env(safe-area-inset-left));
  overflow-y: auto;
}

body.modal-open {
  overflow: hidden;
}

body.modal-loading-open {
  cursor: progress;
}

.modal.is-open,
.modal.open,
.modal.show,
.modal.active,
.modal.is-closing {
  display: flex;
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.modal-dialog,
.modal-content {
  position: relative;
  z-index: 1;
  width: min(100%, 32rem);
  max-height: min(calc(100vh - 4rem), calc(100dvh - 4rem));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
}

.modal-dialog > .modal-content {
  z-index: auto;
  width: 100%;
  max-height: none;
  min-height: 0;
  border: 0;
  border-radius: inherit;
  box-shadow: none;
}

.modal-dialog.size-sm { width: min(100%, 20rem); }
.modal-dialog.size-md { width: min(100%, 30rem); }
.modal-dialog.size-lg { width: min(100%, 45rem); }
.modal-dialog.size-xl { width: min(100%, 60rem); }
.modal-dialog.size-fullscreen {
  width: min(100%, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
}

.modal-sm .modal-dialog,
.modal-sm.modal-dialog,
.modal-content.modal-sm {
  width: min(100%, 24rem);
}

.modal-lg .modal-dialog,
.modal-lg.modal-dialog,
.modal-content.modal-lg {
  width: min(100%, 52rem);
}

.modal-full .modal-dialog,
.modal-full.modal-dialog,
.modal-content.modal-full {
  width: min(100%, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
}

.modal-centered {
  align-items: center;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border-color-light);
}

.modal-title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-snug);
}

.modal-close,
.modal-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  min-width: 2rem;
  border-radius: var(--radius-full);
  border: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

.modal-close:hover,
.modal-dismiss:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.modal-body {
  flex: 1;
  overflow: auto;
  padding: var(--space-5);
}

.modal-scrollable .modal-body {
  overflow-y: auto;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-top: 1px solid var(--border-color-light);
  background: var(--bg-subtle);
}

.modal.is-loading .modal-body {
  pointer-events: none;
}

/* ─── Inner loading overlay (data phase) ────────
   Injected by modal-service when component calls
   context.openWithLoading(). Removed on setReady(). */
.modal-inner-loading {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: inherit;
  background: rgba(var(--bg-card-rgb, 255 255 255) / 0.82);
  backdrop-filter: blur(1px);
  -webkit-backdrop-filter: blur(1px);
  animation: modal-loading-card-in 160ms var(--ease-decelerate, ease) both;
}

.modal-loading-overlay {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-modal) + 1);
  display: none;
  align-items: center;
  justify-content: center;
  padding: max(var(--space-4), env(safe-area-inset-top)) max(var(--space-4), env(safe-area-inset-right)) max(var(--space-4), env(safe-area-inset-bottom)) max(var(--space-4), env(safe-area-inset-left));
  pointer-events: auto;
}

.modal-loading-overlay.is-open {
  display: flex;
}

.modal-loading-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.28);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.modal-loading-card {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  min-height: var(--touch-target);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  color: var(--text-primary);
  box-shadow: var(--shadow-lg);
  animation: modal-loading-card-in 160ms var(--ease-decelerate) both;
}

.modal-loading-spinner {
  width: 1.25rem;
  height: 1.25rem;
  flex: 0 0 1.25rem;
  border: 2px solid var(--border-color-light);
  border-top-color: var(--ui-accent);
  border-radius: var(--radius-full);
  animation: modal-loading-spin 720ms linear infinite;
}

.modal-loading-text {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-tight);
  white-space: nowrap;
}

.modal-animate-fade,
.modal-animate-scale,
.modal-animate-slide-up,
.modal-animate-slide-down,
.modal-animate-slide-left,
.modal-animate-slide-right {
  --modal-animation-duration: 180ms;
  --modal-animation-ease: var(--ease-decelerate);
}

.modal-animate-fade.is-open .modal-backdrop,
.modal-animate-fade.show .modal-backdrop,
.modal-animate-fade.open .modal-backdrop,
.modal-animate-scale.is-open .modal-backdrop,
.modal-animate-scale.show .modal-backdrop,
.modal-animate-scale.open .modal-backdrop,
.modal-animate-slide-up.is-open .modal-backdrop,
.modal-animate-slide-up.show .modal-backdrop,
.modal-animate-slide-up.open .modal-backdrop,
.modal-animate-slide-down.is-open .modal-backdrop,
.modal-animate-slide-down.show .modal-backdrop,
.modal-animate-slide-down.open .modal-backdrop,
.modal-animate-slide-left.is-open .modal-backdrop,
.modal-animate-slide-left.show .modal-backdrop,
.modal-animate-slide-left.open .modal-backdrop,
.modal-animate-slide-right.is-open .modal-backdrop,
.modal-animate-slide-right.show .modal-backdrop,
.modal-animate-slide-right.open .modal-backdrop {
  animation: modal-backdrop-in var(--modal-animation-duration) var(--modal-animation-ease) both;
}

.modal-animate-fade.is-closing .modal-backdrop,
.modal-animate-scale.is-closing .modal-backdrop,
.modal-animate-slide-up.is-closing .modal-backdrop,
.modal-animate-slide-down.is-closing .modal-backdrop,
.modal-animate-slide-left.is-closing .modal-backdrop,
.modal-animate-slide-right.is-closing .modal-backdrop {
  animation: modal-backdrop-out var(--modal-animation-duration) var(--ease-accelerate) both;
}

.modal-animate-fade.is-open .modal-dialog,
.modal-animate-fade.show .modal-dialog,
.modal-animate-fade.open .modal-dialog {
  animation: modal-fade-in var(--modal-animation-duration) var(--modal-animation-ease) both;
}

.modal-animate-fade.is-closing .modal-dialog {
  animation: modal-fade-out var(--modal-animation-duration) var(--ease-accelerate) both;
}

.modal-animate-scale.is-open .modal-dialog,
.modal-animate-scale.show .modal-dialog,
.modal-animate-scale.open .modal-dialog {
  animation: modal-scale-in var(--modal-animation-duration) var(--modal-animation-ease) both;
}

.modal-animate-scale.is-closing .modal-dialog {
  animation: modal-scale-out var(--modal-animation-duration) var(--ease-accelerate) both;
}

.modal-animate-slide-up.is-open .modal-dialog,
.modal-animate-slide-up.show .modal-dialog,
.modal-animate-slide-up.open .modal-dialog {
  animation: modal-slide-up-in var(--modal-animation-duration) var(--modal-animation-ease) both;
}

.modal-animate-slide-up.is-closing .modal-dialog {
  animation: modal-slide-up-out var(--modal-animation-duration) var(--ease-accelerate) both;
}

.modal-animate-slide-down.is-open .modal-dialog,
.modal-animate-slide-down.show .modal-dialog,
.modal-animate-slide-down.open .modal-dialog {
  animation: modal-slide-down-in var(--modal-animation-duration) var(--modal-animation-ease) both;
}

.modal-animate-slide-down.is-closing .modal-dialog {
  animation: modal-slide-down-out var(--modal-animation-duration) var(--ease-accelerate) both;
}

.modal-animate-slide-left.is-open .modal-dialog,
.modal-animate-slide-left.show .modal-dialog,
.modal-animate-slide-left.open .modal-dialog {
  animation: modal-slide-left-in var(--modal-animation-duration) var(--modal-animation-ease) both;
}

.modal-animate-slide-left.is-closing .modal-dialog {
  animation: modal-slide-left-out var(--modal-animation-duration) var(--ease-accelerate) both;
}

.modal-animate-slide-right.is-open .modal-dialog,
.modal-animate-slide-right.show .modal-dialog,
.modal-animate-slide-right.open .modal-dialog {
  animation: modal-slide-right-in var(--modal-animation-duration) var(--modal-animation-ease) both;
}

.modal-animate-slide-right.is-closing .modal-dialog {
  animation: modal-slide-right-out var(--modal-animation-duration) var(--ease-accelerate) both;
}

@keyframes modal-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes modal-backdrop-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes modal-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes modal-fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes modal-scale-in {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes modal-scale-out {
  from { opacity: 1; transform: scale(1); }
  to { opacity: 0; transform: scale(0.96); }
}

@keyframes modal-slide-up-in {
  from { opacity: 0; transform: translateY(1rem); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes modal-slide-up-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(1rem); }
}

@keyframes modal-slide-down-in {
  from { opacity: 0; transform: translateY(-1rem); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes modal-slide-down-out {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-1rem); }
}

@keyframes modal-slide-left-in {
  from { opacity: 0; transform: translateX(1rem); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes modal-slide-left-out {
  from { opacity: 1; transform: translateX(0); }
  to { opacity: 0; transform: translateX(1rem); }
}

@keyframes modal-slide-right-in {
  from { opacity: 0; transform: translateX(-1rem); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes modal-slide-right-out {
  from { opacity: 1; transform: translateX(0); }
  to { opacity: 0; transform: translateX(-1rem); }
}

@keyframes modal-loading-card-in {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1); }
}

@keyframes modal-loading-spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 768px) {
  .modal {
    align-items: flex-end;
    padding: 0;
  }

  .modal-dialog,
  .modal-content {
    width: 100% !important;
    max-height: min(92vh, 92dvh);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  }

  .modal-header,
  .modal-body,
  .modal-footer {
    padding-inline: var(--space-4);
  }

  .modal-footer {
    align-items: stretch;
    flex-direction: column-reverse;
  }

  .modal-footer .btn {
    width: 100%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .modal-animate-fade .modal-backdrop,
  .modal-animate-fade .modal-dialog,
  .modal-animate-scale .modal-backdrop,
  .modal-animate-scale .modal-dialog,
  .modal-animate-slide-up .modal-backdrop,
  .modal-animate-slide-up .modal-dialog,
  .modal-animate-slide-down .modal-backdrop,
  .modal-animate-slide-down .modal-dialog,
  .modal-animate-slide-left .modal-backdrop,
  .modal-animate-slide-left .modal-dialog,
  .modal-animate-slide-right .modal-backdrop,
  .modal-animate-slide-right .modal-dialog {
    animation: none !important;
  }

  .modal-loading-card,
  .modal-loading-spinner {
    animation: none !important;
  }
}

/* components/offcanvas.css */
/**
 * Component: Offcanvas
 * Purpose:   Slide-in side panel for persistent workspace settings.
 * Base:      offcanvas, offcanvas-panel
 * Added:     2026-04-25
 */

.offcanvas {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: none;
}

body.offcanvas-open {
  overflow: hidden;
}

.offcanvas.is-open,
.offcanvas.open,
.offcanvas.show,
.offcanvas.active {
  display: block;
}

.offcanvas-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.offcanvas-panel {
  position: absolute;
  top: 0;
  bottom: 0;
  width: min(100%, 28rem);
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  box-shadow: var(--shadow-xl);
  transform: translateX(0);
}

.offcanvas-end .offcanvas-panel,
.offcanvas-panel.align-end {
  right: 0;
  border-right: 0;
  border-radius: var(--radius-lg) 0 0 var(--radius-lg);
}

.offcanvas-start .offcanvas-panel,
.offcanvas-panel.align-start {
  left: 0;
  border-left: 0;
  border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
}

.offcanvas-header,
.offcanvas-body,
.offcanvas-footer {
  padding: var(--space-5);
}

.offcanvas-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  border-bottom: 1px solid var(--border-color-light);
}

.offcanvas-title {
  margin: 0;
  color: var(--text-primary);
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-snug);
}

.offcanvas-subtitle {
  margin: var(--space-1) 0 0;
  color: var(--text-secondary);
  font-size: var(--text-sm);
  line-height: var(--line-height-normal);
}

.offcanvas-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  min-width: 2rem;
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

.offcanvas-close:hover,
.offcanvas-close:focus-visible {
  background: var(--bg-hover);
  color: var(--text-primary);
  outline: none;
}

.offcanvas-body {
  flex: 1;
  overflow: auto;
}

.offcanvas-footer {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  border-top: 1px solid var(--border-color-light);
  background: var(--bg-subtle);
}

.settings-section {
  display: grid;
  gap: var(--space-4);
}

.settings-section + .settings-section {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border-color-light);
}

.settings-section-title {
  margin: 0;
  color: var(--text-primary);
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
}

.settings-choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-3);
}

.settings-choice {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--touch-target);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: border-color var(--transition-fast), background-color var(--transition-fast), box-shadow var(--transition-fast);
}

.settings-choice:hover,
.settings-choice:focus-visible {
  border-color: var(--border-focus);
  background: var(--bg-hover);
  outline: none;
}

.settings-choice.is-selected {
  border-color: var(--ui-accent);
  background: var(--bg-selected);
  box-shadow: 0 0 0 3px var(--ui-focus-ring);
}

.settings-choice-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  flex: 0 0 2rem;
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  color: var(--ui-accent);
}

.settings-choice-body {
  min-width: 0;
}

.settings-choice-title {
  display: block;
  color: var(--text-primary);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  line-height: var(--line-height-snug);
}

.settings-choice-description {
  display: block;
  color: var(--text-secondary);
  font-size: var(--text-xs);
  line-height: var(--line-height-normal);
}

.settings-choice.is-selected .settings-choice-icon {
  background: var(--ui-accent);
  color: var(--text-inverse);
}

@media (max-width: 480px) {
  .offcanvas-panel {
    width: 100%;
    border-radius: 0;
  }

  .offcanvas-footer {
    align-items: stretch;
    flex-direction: column-reverse;
  }

  .offcanvas-footer .btn {
    width: 100%;
  }
}

/* components/nav.css */
/**
 * Component: Nav
 * Purpose:   Sidebar / menu list navigation.
 * Base:      nav, nav-link
 * Modifiers: nav-vertical
 * States:    :hover, .active, .is-active (alias), [aria-current="page"], .disabled
 * Depends:   tokens.css
 * Added:     2026-04-22
 *
 * Distinct from Tabs (tabs.css) which is the underline-style strip at the top of a section.
 */

.nav {
  display: flex;
  gap: var(--space-1);
  padding: 0;
  margin: 0;
  list-style: none;
}
.nav-vertical { flex-direction: column; }

.nav-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition-fast),
              border-color var(--transition-fast),
              color var(--transition-fast);
}
.nav-link:hover:not(.disabled) {
  background: var(--bg-hover);
  color: var(--text-primary);
}
.nav-link.active,
.nav-link.is-active,
.nav-link[aria-current="page"] {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
}
.nav-link.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* components/navbar.css */
/**
 * Component: Navbar
 * Purpose:   Horizontal top navigation shell.
 * Added:     2026-04-22
 */

.navbar {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 4rem;
  padding: var(--space-3) var(--space-6);
  background: var(--surface-overlay);
  border-bottom: 1px solid var(--border-color-light);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--shadow-sm);
}

.navbar-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--text-primary);
  text-decoration: none;
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
}

.navbar-nav,
.navbar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.navbar.is-sticky {
  box-shadow: var(--shadow-md);
}

.site-nav {
  padding: 0;
}

.site-nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  min-height: 4rem;
  padding-block: var(--space-3);
}

.site-nav-inner-fluid {
  max-width: none;
  padding-inline: var(--space-6);
}

.brand {
  min-width: 0;
  white-space: nowrap;
}

.brand-logo {
  display: block;
  width: 1.75rem;
  height: 1.75rem;
  flex: 0 0 1.75rem;
  object-fit: contain;
}

.nav-actions {
  margin-left: auto;
  flex-wrap: nowrap;
}

.nav-selector,
.nav-actions .btn,
.nav-actions .icon-button {
  flex-shrink: 0;
}

.nav-selector {
  position: relative;
}

/* Selector trigger extension for compact text + icon controls. */
.selector-trigger {
  width: auto;
  min-width: var(--icon-btn-height);
  gap: var(--space-2);
  padding: 0 var(--space-3);
}

.selector-trigger i {
  font-size: 0.75rem;
  color: var(--text-muted);
  transition: transform var(--transition-fast);
}

.nav-selector.active .selector-trigger i:last-child,
.nav-selector.open .selector-trigger i:last-child {
  transform: rotate(180deg);
}

.selector-menu {
  position: absolute;
  top: calc(100% + 0.625rem);
  right: 0;
  min-width: 10rem;
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-2);
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  transition: var(--transition-fast);
  z-index: var(--z-dropdown);
  border: 1px solid var(--border-color-light);
}

.nav-selector.active .selector-menu,
.nav-selector.open .selector-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.selector-option {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  border-radius: var(--radius-md);
  transition: var(--transition-fast);
  color: var(--text-primary);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
}

.selector-option:hover {
  background: var(--tint-primary-5);
  color: var(--ui-accent);
}

.selector-option.selected,
.selector-option.active {
  background: var(--tint-primary-10);
  color: var(--ui-accent);
  font-weight: var(--font-weight-semibold);
}

@media (max-width: 768px) {
  .navbar {
    padding: var(--space-3) var(--space-4);
    flex-wrap: wrap;
  }

  .site-nav-inner {
    gap: var(--space-3);
    min-height: auto;
    flex-wrap: wrap;
  }

  .site-nav-inner-fluid {
    padding-inline: var(--space-4);
  }

  .nav-actions {
    width: 100%;
    justify-content: flex-end;
  }

  .selector-menu {
    min-width: 11.25rem;
  }
}

@media (max-width: 480px) {
  .navbar-actions,
  .nav-actions {
    gap: var(--space-2);
  }

  .selector-trigger {
    max-width: 100%;
  }
}

/* components/mobile-section-tabs.css */
.mobile-section-tabs {
  position: fixed;
  z-index: var(--z-fixed, 60);
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  grid-template-columns: repeat(var(--mobile-section-count, 4), minmax(0, 1fr));
  gap: 0;
  padding: var(--space-1) var(--space-2) calc(var(--space-1) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border-color-light);
  background: var(--bg-card);
  box-shadow: var(--shadow-lg);
}

.mobile-section-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  min-width: 0;
  min-height: var(--touch-target);
  padding: 0 var(--space-1);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
}

.mobile-section-tab > span:not(.badge) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mobile-section-tab.is-active,
.mobile-section-tab[aria-pressed="true"] {
  color: var(--shell-accent);
  background: var(--shell-accent-soft);
}

.mobile-section-tab:focus-visible {
  outline: 2px solid var(--focus-ring-color);
  outline-offset: 2px;
}

/* components/pagination.css */
/**
 * Component: Pagination
 * Purpose:   Page-number and prev/next controls for navigating multi-page lists.
 * Variants:  pagination-sm, pagination-lg
 * Elements:  pagination-item, pagination-ellipsis
 * Modifiers: active (current page), disabled
 * Container: pagination-wrap (centred, with top spacing)
 * States:    :hover, .active, .disabled, :disabled
 * Depends:   tokens.css
 * Added:     2026-04-22
 * Updated:   2026-05-14
 */

/* ─── Wrap (centering container) ─────────────────── */

.pagination-wrap {
  display: flex;
  justify-content: center;
  margin-top: var(--space-4);
}

/* ─── Row container ──────────────────────────────── */

.pagination {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}

/* ─── Item (button or anchor) ────────────────────── */

.pagination-item {
  min-width: 2.25rem;
  height: 2.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--space-2);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-card);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  line-height: 1;
  transition: background-color var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
  user-select: none;
}

.pagination-item:hover:not(.active):not(.disabled):not(:disabled) {
  background: var(--bg-hover);
  border-color: var(--border-color-dark);
  color: var(--text-primary);
}

.pagination-item:focus-visible {
  outline: 2px solid var(--ui-focus-ring);
  outline-offset: 2px;
}

.pagination-item.active {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
  cursor: default;
  pointer-events: none;
}

.pagination-item.disabled,
.pagination-item:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

/* ─── Prev / Next arrow items ────────────────────── */

.pagination-item.pagination-prev,
.pagination-item.pagination-next {
  font-size: var(--text-base);
  min-width: 2.25rem;
}

/* ─── Ellipsis ───────────────────────────────────── */

.pagination-ellipsis {
  min-width: 2.25rem;
  height: 2.25rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: var(--text-sm);
  cursor: default;
  user-select: none;
}

/* ─── Size: sm ───────────────────────────────────── */

.pagination-sm .pagination-item,
.pagination-sm .pagination-ellipsis {
  min-width: 1.875rem;
  height: 1.875rem;
  font-size: var(--text-xs);
  padding: 0 var(--space-2);
}

/* ─── Size: lg ───────────────────────────────────── */

.pagination-lg .pagination-item,
.pagination-lg .pagination-ellipsis {
  min-width: 2.75rem;
  height: 2.75rem;
  font-size: var(--text-base);
  padding: 0 var(--space-3);
}

/* components/progress.css */
/**
 * Component: Progress
 * Purpose:   Horizontal progress indicator.
 * Added:     2026-04-22
 */

.progress {
  width: 100%;
  height: 0.625rem;
  overflow: hidden;
  background: var(--bg-progress);
  border-radius: var(--radius-full);
}

.progress-bar {
  height: 100%;
  width: 0;
  background: var(--ui-accent);
  border-radius: inherit;
  transition: width var(--transition-normal);
}

.progress-bar.success { background: var(--color-success); }
.progress-bar.warning { background: var(--color-warning); }
.progress-bar.danger,
.progress-bar.error { background: var(--color-error); }
.progress-bar.info { background: var(--color-info); }

.progress.is-indeterminate .progress-bar {
  width: 40%;
  animation: mui-progress-indeterminate 1.2s ease infinite;
}

/* App-level progress surface injected by engine/ui/primitives/ui.js. */
.global-progress-container {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(32px + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-toast);
  display: none;
  width: 100%;
  padding: var(--space-3) var(--space-6);
  background: var(--bg-card);
  border-top: 1px solid var(--border-color-light);
  box-shadow: var(--shadow-lg);
}

.global-progress-inner {
  width: min(100%, 75rem);
  margin-inline: auto;
}

.global-progress-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.global-progress-status,
.global-progress-percent {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
}

.global-progress-status {
  min-width: 0;
  color: var(--text-secondary);
}

.global-progress-percent {
  color: var(--ui-accent);
  white-space: nowrap;
}

.global-progress-track {
  height: 0.375rem;
  overflow: hidden;
  background: var(--bg-progress);
  border-radius: var(--radius-full);
}

.global-progress-bar {
  width: 0;
  height: 100%;
  background: var(--ui-accent);
  border-radius: inherit;
  transition: width var(--transition-normal);
}

@keyframes mui-progress-indeterminate {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(280%); }
}

/* components/spinner.css */
/**
 * Component: Spinner
 * Purpose:   Loading indicator.
 * Added:     2026-04-22
 * Updated:   2026-04-22
 */

.spinner {
  display: inline-flex;
  width: 1.25rem;
  height: 1.25rem;
  color: var(--ui-accent);
  border: 2px solid var(--ui-accent-active);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

.spinner.size-xs { width: 0.75rem; height: 0.75rem; }
.spinner.size-sm { width: 1rem; height: 1rem; }
.spinner.size-md { width: 1.25rem; height: 1.25rem; }
.spinner.size-lg { width: 1.75rem; height: 1.75rem; }
.spinner.size-xl { width: 2.5rem; height: 2.5rem; }

/* components/stat.css */
/**
 * Component: Stat card
 * Purpose:   KPI / metric tile used on dashboards.
 * Structure:
 *   .stat-grid                   responsive auto-fit grid wrapper
 *   > .stat-card                 single KPI tile
 *     > .stat-icon               square colored icon box (uses .icon-box tokens)
 *     > .stat-body               text column
 *       > .stat-label            uppercase caption
 *       > .stat-value            large number
 *       > .stat-delta            trend indicator (positive / negative / neutral)
 *
 * Variants: stat-card.is-clickable (hover lift)
 * Depends:  tokens.css, card.css
 * Added:    2026-04-24
 */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-4);
}

.stat-card {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  transition:
    transform var(--transition-fast),
    box-shadow var(--transition-fast),
    border-color var(--transition-fast);
}

.stat-card.is-clickable {
  cursor: pointer;
}

.stat-card.is-clickable:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
  border-color: var(--ui-accent);
}

.stat-icon {
  flex: 0 0 auto;
  width: 3rem;
  height: 3rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: var(--tint-primary-10);
  color: var(--ui-accent);
  font-size: 1.25rem;
}

.stat-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}

.stat-label {
  margin: 0;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1.2;
}

.stat-value {
  margin: 0;
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.stat-delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
}

.stat-delta.is-positive { color: var(--color-success); }
.stat-delta.is-negative { color: var(--color-error); }
.stat-delta.is-neutral  { color: var(--text-tertiary); }

/* Color variants — reuse icon-box color tokens */
.stat-icon.is-success { background: var(--color-success-bg); color: var(--color-success); }
.stat-icon.is-warning { background: var(--color-warning-bg); color: var(--color-warning); }
.stat-icon.is-danger  { background: var(--color-error-bg); color: var(--color-error); }
.stat-icon.is-info    { background: var(--color-info-bg); color: var(--color-info); }

/* components/skeleton.css */
/**
 * Component: Skeleton loader
 * Purpose:   Placeholder shapes shown while content is loading.
 * Structure:
 *   .skeleton                    generic shimmering block
 *   .skeleton-text               single line of fake text
 *   .skeleton-title              slightly taller block for headings
 *   .skeleton-circle             round avatar placeholder
 *   .skeleton-card               card-shaped block with header + body
 *
 * Variants: .skeleton-text.size-sm | .size-lg
 *           .skeleton-text.w-25 | .w-50 | .w-75 | .w-100 (width helpers)
 *
 * Accessibility: wrap skeletons in an element with aria-busy="true" and
 *                aria-live="polite"; swap to real content when ready.
 * Motion:   Respects prefers-reduced-motion — shimmer disabled.
 * Depends:  tokens.css
 * Added:    2026-04-24
 */

.skeleton {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--bg-subtle);
  border-radius: var(--radius-sm);
  color: transparent;
  user-select: none;
  pointer-events: none;
}

.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.45) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  animation: mui-skeleton-shimmer 1.6s ease-in-out infinite;
}

@keyframes mui-skeleton-shimmer {
  100% { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton::after { animation: none; }
}

.skeleton-text {
  height: 0.75rem;
  margin: 0.25rem 0;
  border-radius: var(--radius-sm);
}

.skeleton-text.size-sm { height: 0.625rem; }
.skeleton-text.size-lg { height: 1rem; }

.skeleton-title {
  height: 1.5rem;
  margin: 0.25rem 0;
  border-radius: var(--radius-sm);
}

.skeleton-circle {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: var(--radius-full);
}

.skeleton-card {
  height: 8rem;
  border-radius: var(--radius-lg);
}

.skeleton.w-25  { width: 25%; }
.skeleton.w-50  { width: 50%; }
.skeleton.w-75  { width: 75%; }
.skeleton.w-100 { width: 100%; }

/* components/empty-state.css */
/**
 * Component: Empty state
 * Purpose:   Placeholder shown when a list / table / section has no data.
 * Structure:
 *   .empty-state
 *     > .empty-state-icon
 *     > .empty-state-title
 *     > .empty-state-description
 *     > .empty-state-action     (any .btn)
 *
 * Variants: empty-state.size-sm (compact, inline in cards)
 * Depends:  tokens.css
 * Added:    2026-04-24
 */

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--text-secondary);
}

.empty-state-icon {
  width: 3rem;
  height: 3rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  color: var(--text-tertiary);
  font-size: 1.5rem;
  margin-bottom: var(--space-1);
}

.empty-state-title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  line-height: 1.4;
}

.empty-state-description {
  margin: 0;
  max-width: 32rem;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.5;
}

.empty-state-action {
  margin-top: var(--space-2);
}

.empty-state.size-sm {
  padding: var(--space-4) var(--space-3);
  gap: var(--space-2);
}

.empty-state.size-sm .empty-state-icon {
  width: 2rem;
  height: 2rem;
  font-size: 1rem;
}

.empty-state.size-sm .empty-state-title {
  font-size: var(--text-sm);
}

.empty-state.size-sm .empty-state-description {
  font-size: var(--text-xs);
}

/* components/auth.css */
/**
 * Component: Auth layout
 * Purpose:   Reusable shell for login / register / password-reset screens.
 * Structure:
 *   .auth-layout                 centered viewport wrapper, brand-aware bg
 *   > .auth-card                 elevated card, max-width ~420px
 *     > .auth-header             logo + title + subtitle
 *       > .auth-logo
 *       > .auth-title
 *       > .auth-subtitle
 *     > .auth-body               form slot
 *     > .auth-divider            "OR" separator between auth methods
 *     > .auth-footer             secondary actions (switch portal, help)
 *   > .auth-language-switcher    floating lang picker (top-right)
 *
 * Depends:   tokens.css, card.css
 * Added:     2026-04-24
 */

.auth-layout {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6) var(--space-4);
  background: var(--bg-secondary);
  position: relative;
}

.auth-card {
  width: 100%;
  max-width: 26rem;
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-8) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.auth-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  text-align: center;
}

.auth-logo {
  width: 3.5rem;
  height: 3.5rem;
  margin-bottom: var(--space-2);
}

.auth-title {
  margin: 0;
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  line-height: 1.3;
}

.auth-subtitle {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  line-height: 1.5;
}

.auth-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.auth-divider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.auth-divider::before,
.auth-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border-color);
}

.auth-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-align: center;
}

.auth-footer a {
  color: var(--text-link);
  text-decoration: none;
}

.auth-footer a:hover {
  color: var(--text-link-hover);
  text-decoration: underline;
}

.auth-language-switcher {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
}

@media (max-width: 480px) {
  .auth-card {
    padding: var(--space-6) var(--space-4);
    border-radius: var(--radius-md);
  }

  .auth-language-switcher {
    top: var(--space-2);
    right: var(--space-2);
  }
}

/* components/table.css */
/**
 * Component: Table
 * Purpose:   Styled table with striping, hover, borders and responsive wrapper.
 * Added:     2026-04-22
 */

.table-responsive {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  background: var(--bg-card);
}

.table {
  width: 100%;
  border-collapse: collapse;
  background: var(--bg-card);
  color: var(--text-primary);
  font-size: var(--text-sm);
}

.table th,
.table td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--border-color-light);
  vertical-align: middle;
  min-height: var(--table-row-height);
}

.table th {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--letter-spacing-wide);
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--table-header-bg);
  white-space: nowrap;
}

.table-striped tbody tr:nth-child(odd) {
  background: var(--table-stripe-bg);
}

.table-hover tbody tr:hover {
  background: var(--bg-hover);
}

.table-bordered {
  border: 1px solid var(--border-color-light);
}

.table-bordered th,
.table-bordered td {
  border: 1px solid var(--border-color-light);
}

/* Table density variants */

.table-compact th,
.table-compact td {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
}

.table-compact th {
  font-size: var(--text-xs);
}

.table-sm th,
.table-sm td {
  padding: var(--space-2) var(--space-3);
}

.table-sm th {
  font-size: var(--text-xs);
}

.table-sm td {
  font-size: var(--text-xs);
}

.table-lg th,
.table-lg td {
  padding: var(--space-4) var(--space-6);
}

.table-lg th {
  font-size: var(--text-sm);
}

.table-lg td {
  font-size: var(--text-base);
}

.table td.is-numeric,
.table th.is-numeric,
.table .text-end {
  text-align: right;
}

.table td.is-nowrap,
.table th.is-nowrap {
  white-space: nowrap;
}

@media (max-width: 640px) {
  .table th,
  .table td {
    padding: var(--space-2) var(--space-3);
  }
}

/* components/tabs.css */
/**
 * Component: Tabs
 * Purpose:   Underline-style tab strip for in-page section switching.
 * Base:      tabs (strip), tab (item)
 * States:    :hover, .active, .is-active (alias), [aria-selected="true"], .disabled
 * Depends:   tokens.css
 * Added:     2026-04-22
 *
 * For panel toggling behavior, see src/js/tabs.js.
 */

.tabs {
  display: flex;
  gap: var(--space-4);
  border-bottom: 1px solid var(--border-color-light);
  padding: 0;
  margin: 0 0 var(--space-4);
  list-style: none;
}
.tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  color: var(--text-secondary);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  text-decoration: none;
  cursor: pointer;
  transition: color var(--transition-fast);
}

.tab i {
  font-size: 0.8rem;
  flex-shrink: 0;
}
.tab:hover:not(.disabled) { color: var(--text-primary); }
.tab.active,
.tab.is-active,
.tab[aria-selected="true"] {
  color: var(--ui-accent);
}
.tab.active::after,
.tab.is-active::after,
.tab[aria-selected="true"]::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--ui-accent);
  border-radius: var(--radius-full);
}
.tab.disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.tab-panel { display: none; }
.tab-panel.active,
.tab-panel.is-active { display: block; }

/* ── Sub-page tab panels (managed by engine/ui/primitives/sub-page-tabs.js) ── */
.sub-page-tab-panel {
  animation: sub-page-tab-fade var(--transition-normal) ease;
}

.sub-page-tab-loading {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) 0;
}

@keyframes sub-page-tab-fade {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* components/toast.css */
/**
 * Component: Toast
 * Purpose:   Transient notification stack.
 * Added:     2026-04-22
 * Updated:   2026-04-22
 */

.toast-stack {
  position: fixed;
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: min(100vw - 2rem, 24rem);
}

.toast-stack.top-right {
  right: var(--space-4);
  top: var(--space-4);
}

.toast-stack.top-left {
  left: var(--space-4);
  top: var(--space-4);
}

.toast-stack.top-center {
  left: 50%;
  top: var(--space-4);
  transform: translateX(-50%);
}

.toast-stack.bottom-right {
  right: var(--space-4);
  bottom: var(--space-4);
}

.toast-stack.bottom-left {
  left: var(--space-4);
  bottom: var(--space-4);
}

.toast-stack.bottom-center {
  left: 50%;
  bottom: var(--space-4);
  transform: translateX(-50%);
}

.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-left: 4px solid var(--ui-accent);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  color: var(--text-primary);
}

.toast-success { border-left-color: var(--color-success); }
.toast-warning { border-left-color: var(--color-warning); }
.toast-danger,
.toast-error { border-left-color: var(--color-error); }
.toast-info { border-left-color: var(--color-info); }

.toast-body {
  flex: 1;
}

.toast-title {
  margin: 0 0 var(--space-1);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
}

.toast-close {
  border: 0;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}

/* Mobile responsive adjustments */
@media (max-width: 640px) {
  .toast-stack {
    max-width: min(100vw - 1rem, 20rem);
    gap: var(--space-2);
  }

  /* On mobile, prefer centered top position for better visibility */
  .toast-stack.top-right,
  .toast-stack.top-left {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    top: var(--space-3);
  }

  .toast-stack.top-center {
    top: var(--space-3);
  }

  /* Bottom toasts: account for mobile nav bars and safe areas */
  .toast-stack.bottom-right,
  .toast-stack.bottom-left {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    bottom: var(--space-3);
  }

  .toast-stack.bottom-center {
    bottom: var(--space-3);
  }

  /* Increase touch target for close button on mobile */
  .toast-close {
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-2);
    margin: calc(var(--space-2) * -1);
  }
}

/* Very small phones (< 480px) */
@media (max-width: 480px) {
  .toast-stack {
    max-width: calc(100vw - var(--space-2) * 2);
  }

  .toast {
    padding: var(--space-3);
    font-size: var(--text-xs);
  }

  .toast-title {
    font-size: var(--text-xs);
  }
}

/* components/tooltip.css */
/**
 * Component: Tooltip & Popover
 * Purpose:   Contextual hints and content popovers with arrow positioning.
 * Added:     2026-04-25
 * Updated:   2026-04-25
 */

.tooltip,
.popover {
  position: absolute;
  z-index: var(--z-tooltip);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-fast);
}

.tooltip.show,
.popover.show {
  opacity: 1;
  pointer-events: auto;
}

/* Tooltip: compact inline hint */
.tooltip {
  padding: var(--space-2) var(--space-3);
  background: var(--text-primary);
  color: var(--bg-body);
  font-size: var(--text-xs);
  line-height: 1.4;
  border-radius: var(--radius-sm);
  max-width: 200px;
  word-wrap: break-word;
}

/* Popover: larger content block */
.popover {
  padding: 0;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  max-width: 300px;
  z-index: var(--z-popover);
}

.popover-header {
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  border-bottom: 1px solid var(--border-color-light);
}

.popover-body {
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.popover-footer {
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--border-color-light);
  display: flex;
  gap: var(--space-2);
  justify-content: flex-end;
}

/* Arrow indicators */
.tooltip::before,
.popover::before {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  border-style: solid;
}

/* Tooltip arrow */
.tooltip::before {
  border-width: 4px;
}

/* Popover arrow */
.popover::before {
  border-width: 6px;
}

/* Top positioning */
.tooltip.top,
.popover.top {
  bottom: 100%;
  margin-bottom: var(--space-2);
}

.tooltip.top::before,
.popover.top::before {
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
}

.tooltip.top::before {
  border-color: var(--text-primary) transparent transparent transparent;
}

.popover.top::before {
  border-color: var(--bg-card) transparent transparent transparent;
  border-left-color: var(--border-color);
  border-right-color: var(--border-color);
}

/* Right positioning */
.tooltip.right,
.popover.right {
  left: 100%;
  margin-left: var(--space-2);
}

.tooltip.right::before,
.popover.right::before {
  left: -8px;
  top: 50%;
  transform: translateY(-50%);
}

.tooltip.right::before {
  border-color: transparent var(--text-primary) transparent transparent;
}

.popover.right::before {
  border-color: transparent var(--bg-card) transparent transparent;
  border-top-color: var(--border-color);
  border-bottom-color: var(--border-color);
}

/* Bottom positioning */
.tooltip.bottom,
.popover.bottom {
  top: 100%;
  margin-top: var(--space-2);
}

.tooltip.bottom::before,
.popover.bottom::before {
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
}

.tooltip.bottom::before {
  border-color: transparent transparent var(--text-primary) transparent;
}

.popover.bottom::before {
  border-color: transparent transparent var(--bg-card) transparent;
  border-left-color: var(--border-color);
  border-right-color: var(--border-color);
}

/* Left positioning */
.tooltip.left,
.popover.left {
  right: 100%;
  margin-right: var(--space-2);
}

.tooltip.left::before,
.popover.left::before {
  right: -8px;
  top: 50%;
  transform: translateY(-50%);
}

.tooltip.left::before {
  border-color: transparent transparent transparent var(--text-primary);
}

.popover.left::before {
  border-color: transparent transparent transparent var(--bg-card);
  border-top-color: var(--border-color);
  border-bottom-color: var(--border-color);
}

/* Center alignment for tooltips */
.tooltip[data-align="center"]::before,
.popover[data-align="center"]::before {
  left: 50%;
  transform: translateX(-50%);
}

/* Responsive: stack on mobile */
@media (max-width: 640px) {
  .tooltip {
    max-width: 150px;
    font-size: var(--text-xs);
  }

  .popover {
    max-width: 250px;
  }

  .tooltip.left,
  .tooltip.right,
  .popover.left,
  .popover.right {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    bottom: 100%;
    top: auto;
    margin-left: 0;
    margin-right: 0;
    margin-bottom: var(--space-2);
  }
}

/* components/page-header.css */
/**
 * Component: Page Header
 * Purpose:   Page-level title block with optional breadcrumb and right-side action slot.
 * Structure:
 *   .page-header              flex row container
 *   > .page-header-body       title + subtitle column (grows)
 *     > .page-title           primary heading (h1/h2)
 *     > .page-subtitle        secondary description text
 *   > .page-header-actions    right-aligned action buttons
 * Variants:  page-header.is-sticky (fixed below topbar on scroll)
 * Depends:   tokens.css
 * Added:     2026-04-26
 */

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-5);
  margin-bottom: var(--space-5);
  border-bottom: 1px solid var(--border-color-light);
  flex-wrap: wrap;
}

.page-header-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.page-title {
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  line-height: var(--line-height-snug);
  letter-spacing: var(--letter-spacing-tight);
  margin: 0;
}

.page-subtitle {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  margin: 0;
  line-height: var(--line-height-normal);
}

.page-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* Back-button variant: icon-button as first direct child, title fills remaining space.
   Single-row layout at ALL viewport sizes — back ← | title (flex:1) | actions.
   Never collapses to column, even on mobile. */
.page-header.has-back {
  align-items: center;
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: var(--space-3);
}

.page-header.has-back .page-header-body {
  flex: 1;
  min-width: 0;
}

/* Truncate long titles in the has-back row so they never break to a new line */
.page-header.has-back .page-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Actions slot in has-back never wraps — icon buttons must stay on the same row */
.page-header.has-back .page-header-actions {
  flex-shrink: 0;
  flex-wrap: nowrap;
}

/* Sticky variant: sits below the fixed topbar */
.page-header.is-sticky {
  position: sticky;
  top: var(--header-height);
  z-index: calc(var(--z-sticky) - 1);
  background: var(--bg-body);
  padding-top: var(--space-4);
  margin-bottom: var(--space-4);
}

@media (max-width: 640px) {
  /* Standard page header: stack body + actions vertically on small screens */
  .page-header:not(.has-back) {
    flex-direction: column;
    align-items: stretch;
  }

  /* has-back always stays as a single row — never stack back/title/actions */
  .page-header.has-back {
    flex-direction: row;
    align-items: center;
  }

  .page-header:not(.has-back) .page-header-actions {
    flex-wrap: wrap;
  }

  .page-title {
    font-size: var(--text-xl);
  }
}

/* components/filter-bar.css */
/**
 * Component: Filter Bar
 * Purpose:   Search input + chip filter row placed above data lists and tables.
 * Structure:
 *   .filter-bar               flex row wrapper (card background)
 *   > .filter-bar-search      search input slot (grows to fill space)
 *   > .filter-bar-groups      chip group(s) cluster (shrinks)
 *     > .filter-bar-group     single set of related chips (role, status, etc.)
 *   > .filter-bar-actions     far-right supplemental actions slot (optional)
 * Depends:   tokens.css, form.css, chip.css
 * Added:     2026-04-26
 */

.filter-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
  flex-wrap: wrap;
}

.filter-bar .form-field {
  gap: var(--space-1);
  margin-bottom: 0;
}

.filter-bar .form-control,
.filter-bar .form-select,
.filter-bar .sm-datepicker,
.filter-bar .custom-date-picker.form-control,
.filter-bar > .btn,
.filter-bar .btn-group > .btn {
  height: var(--input-height);
  min-height: var(--input-height);
}

.filter-bar .btn-group {
  align-self: flex-end;
  min-height: var(--input-height);
}

.filter-bar .btn-group > .btn {
  min-width: var(--input-height);
}

.filter-bar-search {
  flex: 1 1 14rem;
  min-width: 0;
  position: relative;
}

.filter-bar-search .form-control {
  padding-left: var(--space-8);
}

.filter-bar-search::before {
  content: '\f002';
  font-family: 'Font Awesome 6 Free', 'Font Awesome 5 Free';
  font-weight: 900;
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  font-size: var(--text-sm);
  pointer-events: none;
  z-index: 1;
}

.filter-bar-groups {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.filter-bar-group {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  flex-wrap: wrap;
}

.filter-bar-group-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  white-space: nowrap;
  margin-right: var(--space-1);
}

.filter-bar-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
  flex-shrink: 0;
}

/* Divider between groups */
.filter-bar-divider {
  width: 1px;
  height: 1.25rem;
  background: var(--border-color);
  flex-shrink: 0;
}

/* ── Filter Pill Dropdown ── */
.filter-pill-dropdown {
  position: relative;
  flex-shrink: 0;
}

.filter-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: var(--btn-height-sm);
  padding: 0 var(--space-3);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-full);
  background: var(--bg-card);
  font-size: var(--text-sm);
  font-family: inherit;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
}

.filter-pill:hover {
  background: var(--bg-subtle);
  border-color: var(--border-color-dark);
}

.filter-pill.is-active {
  background: var(--ui-accent-soft);
  border-color: var(--ui-accent);
  color: var(--ui-accent);
}

.filter-pill-chevron {
  font-size: 0.65rem;
  color: var(--text-muted);
  flex-shrink: 0;
  transition: transform var(--transition-fast);
}

.filter-pill-dropdown.is-open .filter-pill-chevron {
  transform: rotate(180deg);
}

.filter-pill-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 var(--space-1);
  border-radius: var(--radius-full);
  background: var(--ui-accent);
  color: var(--ui-accent-fg);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  line-height: 1;
}

.filter-pill-menu {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  min-width: 14rem;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-2);
  display: none;
  flex-direction: column;
  z-index: var(--z-dropdown);
}

.filter-pill-menu.is-open {
  display: flex;
}

.filter-pill-menu-more {
  min-width: 18rem;
}

.filter-pill-section {
  display: flex;
  flex-direction: column;
}

.filter-pill-section-title {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-2) var(--space-2) var(--space-1);
  margin: 0;
}

.filter-pill-separator {
  height: 1px;
  background: var(--border-color-light);
  margin: var(--space-1) 0;
}

.filter-pill-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  border: none;
  background: none;
  font-size: var(--text-sm);
  font-family: inherit;
  color: var(--text-primary);
  cursor: pointer;
  width: 100%;
  text-align: left;
  transition: background var(--transition-fast);
}

.filter-pill-option:hover {
  background: var(--bg-subtle);
}

.filter-pill-option.is-selected {
  color: var(--ui-accent);
  font-weight: var(--font-weight-medium);
}

.filter-pill-option-check {
  width: 14px;
  flex-shrink: 0;
  font-size: var(--text-xs);
  color: var(--ui-accent);
  visibility: hidden;
}

.filter-pill-option.is-selected .filter-pill-option-check {
  visibility: visible;
}

.filter-pill-option-icon {
  width: 14px;
  flex-shrink: 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-align: center;
}

.filter-pill-option[data-type="flag"].is-selected {
  color: var(--ui-accent);
  background: var(--ui-accent-soft);
}

.filter-pill-option[data-type="flag"].is-selected .filter-pill-option-icon {
  color: var(--ui-accent);
}

@media (max-width: 640px) {
  .filter-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-bar-search {
    flex: 1 1 100%;
  }
  .filter-bar-groups {
    gap: var(--space-3);
  }
  .filter-bar-actions {
    margin-left: 0;
  }
}

/* components/page-types.css */
/**
 * Component: Page Types
 * Purpose:   Canonical page-type taxonomy for routed SPA pages.
 *            Every <section> page uses exactly one type class for shared
 *            layout; the unique #id scopes domain-specific CSS and JS.
 *
 * Types:
 *   .list-page       Data table / master-data pages
 *   .view-page       Entity detail / dashboard sub-pages  (structure: view-page.css)
 *   .dashboard-page  Home and summary/chart pages
 *   .loading-page    SPA boot / full-screen loading screen
 *
 * Pattern:
 *   class = page TYPE  — shared, canonical, consistent layout
 *   id    = page ID    — unique, used for JS and domain CSS scoping
 *
 * HTML:
 *   <section class="list-page"      id="users-page"      ...>
 *   <section class="view-page"      id="users-view-page" ...>
 *   <section class="dashboard-page" id="home-page"        ...>
 *   <section class="loading-page"   id="loading-page"     ...>
 *
 * Domain CSS rule:
 *   #users-page .my-widget { ... }   ✅
 *   .users-page .my-widget { ... }   ❌ — class is not a namespace
 *
 * Depends: tokens.css
 * Added:   2026-04-27
 */

/* ── All page types: base behaviour ─────────────────────── */
.list-page,
.view-page,
.dashboard-page,
.loading-page {
  min-width: 0;
  animation: fadeIn var(--transition-normal) ease;
}

/* ── Content pages: standard flex-column with page padding ── */
.list-page,
.view-page,
.dashboard-page {
  display: flex;
  flex-direction: column;
  padding: var(--space-6);
}

/*
 * Gap is intentionally split by page type:
 *   list-page     12px — compact; data rows + filter bar read as one unit
 *   view-page     16px — detail cards need slightly more breathing room
 *   dashboard-page 16px — widget sections need air between them
 *
 * Do NOT set per-page gap overrides. If a page feels too tight or too
 * loose, adjust it here for the whole type.
 */
.list-page      { gap: var(--space-3); }
.view-page,
.dashboard-page { gap: var(--space-4); }

/*
 * Child-component margin-bottom zero-out.
 *
 * .page-header and .filter-bar carry a standalone margin-bottom so they
 * look correct when used outside a page-type container. When they ARE a
 * direct child of a flex page container, the container gap already owns
 * all inter-section spacing — the component margin-bottom stacks on top
 * and makes the gap appear 2-3× wider than intended.
 *
 * Rule: zero it out here; never patch this per page.
 */
.list-page > .page-header,
.view-page > .page-header,
.dashboard-page > .page-header,
.list-page > .filter-bar,
.dashboard-page > .filter-bar {
  margin-bottom: 0;
}

/* ── Loading page: full-screen centred layout ────────────── */
.loading-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--space-6) var(--space-4);
  background: var(--bg-body);
}

/* ── Responsive ──────────────────────────────────────────── */
@media (max-width: 640px) {
  .list-page,
  .view-page,
  .dashboard-page {
    padding: var(--space-4);
    gap: var(--space-3);
  }
}

@media (max-width: 480px) {
  .loading-page {
    padding-inline: var(--space-6);
  }
}

/* components/view-page.css */
/**
 * Component: View Page
 * Purpose:   Structural shell for entity detail / dashboard sub-pages.
 * Structure:
 *   .view-page                section wrapper
 *   .view-loading             centred spinner state
 *   .view-hero                hero card (used as modifier on .card)
 *   > .view-hero-profile      avatar + info row
 *     > .view-hero-info       info column (name, handle, meta)
 *       > .view-hero-name-row name + status badge
 *       > .view-hero-name     primary heading (h2)
 *       > .view-hero-handle   username / subtitle text
 *       > .view-hero-meta     meta chip row
 *   > .view-kpi-strip         horizontal KPI row (border-top divider)
 *     > .view-kpi             single KPI cell
 *       > .view-kpi-value     metric number / value
 *       > .view-kpi-label     metric label
 *   .view-tab-container       lazy-loaded tab panel mount point
 * Depends:   tokens.css, card.css
 * Added:     2026-04-27
 */

/* ── Loading state ───────────────────────────────────── */
.view-loading {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 12rem;
}

/* ── Hero card ───────────────────────────────────────── */
.view-hero {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-6);
  margin-bottom: var(--space-4);
}

.view-hero-profile {
  display: flex;
  align-items: flex-start;
  gap: var(--space-5);
}

.view-hero-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.view-hero-name-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.view-hero-name {
  margin: 0;
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  line-height: 1.2;
}

.view-hero-handle {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.view-hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

/* ── KPI strip ───────────────────────────────────────── */
.view-kpi-strip {
  display: flex;
  gap: 0;
  border-top: 1px solid var(--border-color-light);
  padding-top: var(--space-4);
}

.view-kpi {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: var(--space-1) var(--space-2);
  text-align: center;
}

.view-kpi + .view-kpi {
  border-left: 1px solid var(--border-color-light);
}

.view-kpi-value {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.view-kpi-label {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

/* ── Tab container ───────────────────────────────────── */
.view-tab-container {
  min-height: 10rem;
}

/* ── Detail grid (two-column card layout) ────────────── */
.detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

/* Sidebar variant: main content + fixed-width sidebar */
.detail-grid.has-sidebar {
  grid-template-columns: 1fr 320px;
  align-items: start;
}

/* ── Detail list (key-value property list) ───────────── */
.detail-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0;
}

.detail-row {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-color-light);
  align-items: baseline;
}

.detail-row:last-child {
  border-bottom: none;
}

.detail-label {
  flex: 0 0 9rem;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.detail-value {
  flex: 1;
  font-size: var(--text-sm);
  color: var(--text-primary);
  word-break: break-word;
  margin: 0;
}

/* ── Responsive ──────────────────────────────────────── */
@media (max-width: 640px) {
  .view-hero {
    padding: var(--space-4);
  }

  .view-hero-profile {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .view-hero-name-row {
    justify-content: center;
  }

  .view-hero-meta {
    justify-content: center;
  }

  .view-kpi-strip {
    flex-wrap: wrap;
  }

  .view-kpi {
    flex: 1 0 50%;
    border-left: none !important;
    border-top: 1px solid var(--border-color-light);
  }

  .view-kpi:nth-child(-n+2) {
    border-top: none;
  }
}

@media (max-width: 900px) {
  .detail-grid.has-sidebar {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .detail-grid {
    grid-template-columns: 1fr;
  }

  .detail-label {
    flex: 0 0 7rem;
  }
}

/* components/search-box.css */
/**
 * Component: Search Box
 * Purpose:   Debounced live-search input with result dropdown list.
 * Structure:
 *   .search-box              relative wrapper (position parent for dropdown)
 *   > .search-box-input      text input (full-width, left-padded for icon)
 *   > .search-box-clear      dismiss button (shown when input has value)
 *   > .search-box-results    absolutely-positioned result list
 *     > .search-box-item     single result row (button element)
 *     > .search-box-empty    "no results" state row
 *     > .search-box-loading  spinner row while fetching
 * States:    .is-open (results visible), .is-loading, .is-focused
 * Depends:   tokens.css, form.css, spinner.css
 * Added:     2026-05-10
 */

.search-box {
  position: relative;
}

/* Input slot */
.search-box-input {
  width: 100%;
  padding-left: var(--space-9);
  padding-right: var(--space-9);
}

/* Search icon overlay */
.search-box::before {
  content: '\f002';
  font-family: 'Font Awesome 6 Free', 'Font Awesome 5 Free';
  font-weight: 900;
  position: absolute;
  left: var(--space-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
  font-size: var(--text-sm);
  pointer-events: none;
  z-index: 1;
}

/* Clear button */
.search-box-clear {
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  border-radius: var(--radius-full);
  color: var(--text-muted);
  cursor: pointer;
  font-size: var(--text-xs);
  transition: color var(--transition-fast), background var(--transition-fast);
  z-index: 1;
}

.search-box-clear:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.search-box:not(.has-value) .search-box-clear {
  display: none;
}

/* Results dropdown */
.search-box-results {
  position: absolute;
  top: calc(100% + var(--space-1));
  left: 0;
  right: 0;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  max-height: 260px;
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: var(--z-dropdown);
  display: none;
  flex-direction: column;
  padding: var(--space-1) 0;
}

.search-box.is-open .search-box-results {
  display: flex;
}

/* Individual result row */
.search-box-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: none;
  background: none;
  font-family: inherit;
  font-size: var(--text-sm);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  width: 100%;
  transition: background var(--transition-fast);
  min-height: 40px;
}

.search-box-item:hover,
.search-box-item.is-focused {
  background: var(--bg-subtle);
}

.search-box-item-avatar {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  object-fit: cover;
  flex-shrink: 0;
  background: var(--bg-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: var(--text-xs);
}

.search-box-item-body {
  flex: 1;
  min-width: 0;
}

.search-box-item-name {
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-box-item-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.search-box-item-badge {
  flex-shrink: 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* Empty / loading states inside dropdown */
.search-box-empty,
.search-box-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.search-box-loading .spinner {
  width: 16px;
  height: 16px;
}

/* Section divider inside results */
.search-box-separator {
  height: 1px;
  background: var(--border-color-light);
  margin: var(--space-1) 0;
}

.search-box-section-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-2) var(--space-3) var(--space-1);
}

/* Keyboard highlight mark inside item name */
mark.search-box-highlight {
  background: var(--ui-accent-active);
  color: inherit;
  border-radius: 2px;
  padding: 0 1px;
}

/* components/combobox.css */
/**
 * Component: Combobox
 * Purpose:   Text-filter select control — filters a pre-loaded list as the user types.
 *            Distinct from SearchBox (remote fetch). Use when the option set is known
 *            upfront (services, employees, rooms, sources, etc.).
 *
 * Structure:
 *   .ms-combobox                 position parent; states: .is-open .has-value .has-clear .is-disabled .is-invalid .is-loading
 *   > input[type=hidden]         actual form value (not visible)
 *   > .ms-combobox-input         visible text filter (form-control)
 *   > .ms-combobox-clear         ×  clear button (hidden when no value)
 *   > .ms-combobox-toggle        ⌄  chevron toggle
 *   > .ms-combobox-menu          absolutely-positioned dropdown (role=listbox)
 *     > .ms-combobox-group       optional group header (non-interactive)
 *     > .ms-combobox-option      single option (role=option)
 *       > .ms-combobox-option-label   primary label text
 *       > .ms-combobox-option-meta    optional subtitle / metadata
 *     > .ms-combobox-empty       shown when filter has no results
 *     > .ms-combobox-loading     shown while async items load
 *
 * Depends:   tokens.css, form.css, icon-button.css, spinner.css, animations.css
 * Added:     2026-05-17
 */

/* ── Wrapper ──────────────────────────────────────────────────────────────── */

.ms-combobox {
  position: relative;
  display: block;
  width: 100%;
}

/* ── Visible text input ───────────────────────────────────────────────────── */

.ms-combobox .ms-combobox-input {
  width: 100%;
  /* right-pad for the chevron toggle button */
  padding-right: 2.25rem;
  cursor: default;
}

/* When the wrapper carries .has-clear, leave space for clear + toggle */
.ms-combobox.has-clear .ms-combobox-input {
  padding-right: 4.25rem;
}

/* Mirror focus ring onto wrapper when input is focused */
.ms-combobox .ms-combobox-input:focus {
  /* focus is handled by form-control natively; wrapper ring below for keyboard */
}

/* ── Action buttons (toggle & clear) ─────────────────────────────────────── */

/* Both buttons sit inside the input bounds, centred vertically */
.ms-combobox-toggle,
.ms-combobox-clear {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  /* These are icon-button-ghost size-sm — 32×32 */
}

/* Chevron: always at the far right */
.ms-combobox-toggle {
  right: 2px;
}

/* Chevron rotates when open */
.ms-combobox.is-open .ms-combobox-toggle .fa-chevron-down {
  transform: rotate(180deg);
  transition: transform var(--transition-fast, 0.15s ease);
}
.ms-combobox:not(.is-open) .ms-combobox-toggle .fa-chevron-down {
  transform: rotate(0deg);
  transition: transform var(--transition-fast, 0.15s ease);
}

/* Clear: just to the left of the toggle */
.ms-combobox-clear {
  right: 2.1rem; /* 33.6px — leaves room for the 32px toggle at right:2px */
}

/* Hide clear button when there is no value */
.ms-combobox:not(.has-value) .ms-combobox-clear {
  display: none;
}

/* ── Disabled state ───────────────────────────────────────────────────────── */

.ms-combobox.is-disabled .ms-combobox-input {
  background: var(--bg-secondary);
  color: var(--text-muted);
  cursor: not-allowed;
  pointer-events: none;
}
.ms-combobox.is-disabled .ms-combobox-toggle,
.ms-combobox.is-disabled .ms-combobox-clear {
  pointer-events: none;
  opacity: 0.4;
}

/* ── Invalid / error state ────────────────────────────────────────────────── */

.ms-combobox.is-invalid .ms-combobox-input {
  border-color: var(--color-error, #dc2626);
  box-shadow: 0 0 0 2px var(--color-error-light, rgba(220, 38, 38, 0.15));
}

/* ── Dropdown menu ────────────────────────────────────────────────────────── */

.ms-combobox-menu {
  position: absolute;
  top: calc(100% + var(--space-1, 4px));
  left: 0;
  right: 0;
  z-index: var(--z-dropdown, 40);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light, var(--border-color));
  border-radius: var(--radius-lg, 8px);
  box-shadow: var(--shadow-lg);
  max-height: min(280px, 45vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-1, 4px) 0;
  /* Hidden by default */
  display: none;
  flex-direction: column;
  gap: 0;
  animation: ms-combobox-drop-in var(--transition-fast, 0.15s) ease;
}

.ms-combobox.is-open .ms-combobox-menu {
  display: flex;
}

@keyframes ms-combobox-drop-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── Group header ─────────────────────────────────────────────────────────── */

.ms-combobox-group {
  padding: var(--space-2, 8px) var(--space-3, 12px) var(--space-1, 4px);
  font-size: var(--text-xs, 0.75rem);
  font-weight: var(--font-weight-semibold, 600);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  user-select: none;
  /* Separator above group (except first) */
}

.ms-combobox-group + .ms-combobox-group,
.ms-combobox-option + .ms-combobox-group {
  border-top: 1px solid var(--border-color-light, var(--border-color));
  margin-top: var(--space-1, 4px);
  padding-top: var(--space-2, 8px);
}

/* ── Option button ────────────────────────────────────────────────────────── */

.ms-combobox-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2, 8px);
  width: 100%;
  min-height: var(--control-height-sm, 2rem);
  padding: var(--space-2, 8px) var(--space-3, 12px);
  border: none;
  background: transparent;
  font-family: inherit;
  font-size: var(--text-sm, 0.875rem);
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast, 0.15s ease);
  /* Prevent layout shift when .is-selected checkmark appears */
}

.ms-combobox-option:hover:not(.is-disabled),
.ms-combobox-option.is-focused:not(.is-disabled) {
  background: var(--bg-subtle, var(--bg-secondary));
}

/* Selected option: accent tint + checkmark via pseudo-element */
.ms-combobox-option.is-selected {
  background: var(--ui-accent-soft, var(--bg-subtle));
  color: var(--ui-accent, var(--color-primary));
  font-weight: var(--font-weight-medium, 500);
}

.ms-combobox-option.is-selected::after {
  content: '\f00c'; /* fa-check */
  font-family: 'Font Awesome 6 Free', 'Font Awesome 5 Free';
  font-weight: 900;
  font-size: var(--text-xs, 0.75rem);
  color: var(--ui-accent, var(--color-primary));
  flex-shrink: 0;
}

/* Disabled option */
.ms-combobox-option.is-disabled {
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 0.6;
}

/* ── Option label + meta ──────────────────────────────────────────────────── */

.ms-combobox-option-label {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ms-combobox-option-meta {
  font-size: var(--text-xs, 0.75rem);
  color: var(--text-muted);
  white-space: nowrap;
  flex-shrink: 0;
}

/* Meta inside selected option stays readable */
.ms-combobox-option.is-selected .ms-combobox-option-meta {
  color: var(--ui-accent, var(--color-primary));
  opacity: 0.75;
}

/* ── Empty / loading states ───────────────────────────────────────────────── */

.ms-combobox-empty,
.ms-combobox-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2, 8px);
  padding: var(--space-4, 16px) var(--space-3, 12px);
  font-size: var(--text-sm, 0.875rem);
  color: var(--text-muted);
}

.ms-combobox-loading .spinner {
  width: 16px;
  height: 16px;
}

/* ── Query highlight inside option labels ─────────────────────────────────── */

.ms-combobox-option mark {
  background: var(--ui-accent-active, rgba(37,99,235,0.12));
  color: inherit;
  border-radius: 2px;
  padding: 0 1px;
}

/* components/staff-card.css */
/**
 * Component: Staff Card
 * Purpose:   Avatar + name card for staff/employee selection grids.
 * Structure:
 *   .staff-grid              flex-wrap grid wrapper
 *   > .staff-card            clickable card (button element recommended)
 *     > .staff-card-avatar   circular avatar image or initials fallback
 *     > .staff-card-name     primary label
 *     > .staff-card-meta     secondary label (role, status)
 *     > .staff-card-badge    optional top-right indicator (count, status dot)
 * States:    .active / .is-active (selected), .is-disabled, .is-busy
 * Depends:   tokens.css, avatar.css
 * Added:     2026-05-10
 */

/* Grid layout */
.staff-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-1) 0;
}

.staff-grid-compact {
  gap: var(--space-1);
}

/* Card */
.staff-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  min-width: 80px;
  max-width: 104px;
  background: var(--bg-card);
  border: 1.5px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  cursor: pointer;
  text-align: center;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    box-shadow var(--transition-fast);
  font-family: inherit;
  user-select: none;
}

.staff-card:hover:not(.is-disabled) {
  background: var(--bg-subtle);
  border-color: var(--ui-accent);
  box-shadow: var(--shadow-xs);
}

.staff-card.active,
.staff-card.is-active {
  background: var(--ui-accent-soft);
  border-color: var(--ui-accent);
  box-shadow: 0 0 0 2px var(--ui-focus-ring);
}

.staff-card.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.staff-card.is-busy .staff-card-avatar {
  opacity: 0.55;
}

/* Avatar */
.staff-card-avatar {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  object-fit: cover;
  background: var(--bg-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--text-secondary);
  overflow: hidden;
  flex-shrink: 0;
  border: 2px solid var(--border-color-light);
}

.staff-card.active .staff-card-avatar,
.staff-card.is-active .staff-card-avatar {
  border-color: var(--ui-accent);
}

/* Name & meta */
.staff-card-name {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
  line-height: var(--line-height-tight);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.staff-card-meta {
  font-size: 10px;
  color: var(--text-muted);
  margin-top: -var(--space-1);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Status badge overlay (top-right corner) */
.staff-card-badge {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: var(--radius-full);
  background: var(--ui-accent);
  color: var(--ui-accent-fg);
  font-size: 10px;
  font-weight: var(--font-weight-semibold);
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

.staff-card-badge.badge-busy {
  background: var(--color-warning-600, #ca8a04);
}

.staff-card-badge.badge-off {
  background: var(--color-gray-400);
}

/* Status dot (small, inline with name) */
.staff-card-status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--color-gray-300);
  flex-shrink: 0;
}

.staff-card-status-dot.is-available { background: var(--color-success-500, #22c55e); }
.staff-card-status-dot.is-busy      { background: var(--color-warning-500, #eab308); }
.staff-card-status-dot.is-off       { background: var(--color-gray-400); }

/* components/service-card.css */
/**
 * Component: Service Card
 * Purpose:   Card for service/package selection grids (POS servicein, sell).
 * Structure:
 *   .service-grid              flex-wrap grid
 *   > .service-card            clickable card (button element)
 *     > .service-card-icon     category icon badge (optional)
 *     > .service-card-body     content area
 *       > .service-card-name   primary name
 *       > .service-card-meta   duration / use type label
 *       > .service-card-price  displayed price
 * States:    .active / .is-active (selected), .is-disabled, .is-package
 * Depends:   tokens.css
 * Added:     2026-05-10
 */

/* Grid */
.service-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--space-3);
}

.service-grid-compact {
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-2);
}

/* Card */
.service-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--bg-card);
  border: 1.5px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  cursor: pointer;
  text-align: left;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    box-shadow var(--transition-fast);
  font-family: inherit;
  user-select: none;
}

.service-card:hover:not(.is-disabled) {
  background: var(--bg-subtle);
  border-color: var(--ui-accent);
  box-shadow: var(--shadow-xs);
}

.service-card.active,
.service-card.is-active {
  background: var(--ui-accent-soft);
  border-color: var(--ui-accent);
  box-shadow: 0 0 0 2px var(--ui-focus-ring);
}

.service-card.is-disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Package variant */
.service-card.is-package {
  border-style: dashed;
}

/* Icon */
.service-card-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-md);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-base);
  flex-shrink: 0;
}

/* Body */
.service-card-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  flex: 1;
}

.service-card-name {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
  line-height: var(--line-height-tight);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.service-card-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.service-card-price {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--ui-accent);
  margin-top: auto;
}

/* Category tag */
.service-card-tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 6px;
  border-radius: var(--radius-full);
  background: var(--bg-secondary);
  color: var(--text-muted);
  font-size: 10px;
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* Selected checkmark overlay */
.service-card.active::after,
.service-card.is-active::after {
  content: '\f00c';
  font-family: 'Font Awesome 6 Free', 'Font Awesome 5 Free';
  font-weight: 900;
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  font-size: var(--text-xs);
  color: var(--ui-accent);
}

/* components/session-card.css */
/**
 * Component: Session Card
 * Purpose:   Active service-session display card (in-progress treatment).
 * Structure:
 *   .session-grid              vertical or horizontal list wrapper
 *   > .session-card            card container
 *     > .session-card-header   room + start-time row
 *     > .session-card-body     service name + therapist + duration
 *     > .session-card-footer   actions (checkout, extend) + elapsed timer
 * States:    .is-overdue (elapsed > booked), .is-ending-soon
 * Depends:   tokens.css, badge.css
 * Added:     2026-05-10
 */

/* Grid */
.session-grid {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.session-grid-horizontal {
  flex-direction: row;
  flex-wrap: wrap;
}

/* Card */
.session-card {
  background: var(--bg-card);
  border: 1.5px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.session-grid-horizontal .session-card {
  min-width: 260px;
  flex: 1 1 260px;
  max-width: 340px;
}

/* Overdue / warning variants */
.session-card.is-ending-soon {
  border-color: var(--color-warning-400, #facc15);
}

.session-card.is-overdue {
  border-color: var(--color-danger-400, #f87171);
}

/* Header bar */
.session-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border-color-light);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.session-card.is-ending-soon .session-card-header {
  background: color-mix(in srgb, var(--color-warning-400, #facc15) 12%, transparent);
}

.session-card.is-overdue .session-card-header {
  background: color-mix(in srgb, var(--color-danger-500, #ef4444) 10%, transparent);
  color: var(--color-danger-700, #b91c1c);
}

.session-card-room {
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.session-card-time {
  font-variant-numeric: tabular-nums;
}

/* Body */
.session-card-body {
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  flex: 1;
}

.session-card-service {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  line-height: var(--line-height-tight);
}

.session-card-therapist {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.session-card-meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-top: var(--space-1);
}

/* Elapsed timer */
.session-card-elapsed {
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-weight-medium);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.session-card.is-ending-soon .session-card-elapsed {
  color: var(--color-warning-700, #a16207);
}

.session-card.is-overdue .session-card-elapsed {
  color: var(--color-danger-600, #dc2626);
  font-weight: var(--font-weight-semibold);
}

/* Footer actions */
.session-card-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--border-color-light);
  background: var(--bg-subtle);
}

/* Customer info chip inside session */
.session-card-customer {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

.session-card-customer-avatar {
  width: 18px;
  height: 18px;
  border-radius: var(--radius-full);
  background: var(--bg-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  color: var(--text-muted);
  flex-shrink: 0;
}

/* components/qty-stepper.css */
/**
 * Component: Quantity Stepper
 * Purpose:   +/- increment/decrement control for cart and POS quantity input.
 * Structure:
 *   .qty-stepper              flex row wrapper
 *   > .qty-stepper-btn        decrement or increment button (- / +)
 *   > .qty-stepper-value      current value display (input or span)
 * Sizes:     default, .qty-stepper-sm, .qty-stepper-lg
 * States:    :disabled (both buttons and wrapper), .is-at-min, .is-at-max
 * Depends:   tokens.css
 * Added:     2026-05-10
 */

.qty-stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-card);
  height: var(--btn-height-md, 38px);
  user-select: none;
}

/* Size variants */
.qty-stepper-sm {
  height: var(--btn-height-sm, 30px);
}

.qty-stepper-lg {
  height: var(--btn-height-lg, 48px);
}

/* Buttons */
.qty-stepper-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 100%;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text-secondary);
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  transition: background var(--transition-fast), color var(--transition-fast);
  flex-shrink: 0;
}

.qty-stepper-sm .qty-stepper-btn {
  width: 28px;
  font-size: var(--text-sm);
}

.qty-stepper-lg .qty-stepper-btn {
  width: 48px;
  font-size: var(--text-xl);
}

.qty-stepper-btn:hover:not(:disabled) {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.qty-stepper-btn:active:not(:disabled) {
  background: var(--bg-subtle);
}

.qty-stepper-btn:disabled,
.qty-stepper.is-at-min .qty-stepper-btn:first-child,
.qty-stepper.is-at-max .qty-stepper-btn:last-child {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Value display */
.qty-stepper-value {
  flex: 1;
  min-width: 36px;
  text-align: center;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  border: none;
  border-left: 1px solid var(--border-color-light);
  border-right: 1px solid var(--border-color-light);
  background: none;
  padding: 0 var(--space-2);
  height: 100%;
  line-height: 1;
  cursor: default;
  /* remove native spin for number input */
  -moz-appearance: textfield;
}

.qty-stepper-value::-webkit-inner-spin-button,
.qty-stepper-value::-webkit-outer-spin-button {
  -webkit-appearance: none;
}

.qty-stepper-value:focus {
  outline: none;
  background: var(--bg-subtle);
}

.qty-stepper-sm .qty-stepper-value {
  min-width: 28px;
  font-size: var(--text-xs);
}

.qty-stepper-lg .qty-stepper-value {
  min-width: 52px;
  font-size: var(--text-lg);
}

/* Disabled whole stepper */
.qty-stepper:has(.qty-stepper-btn:disabled) {
  opacity: 0.5;
}

/* components/pay-method.css */
/**
 * Component: Payment Method
 * Purpose:   Payment method selector button grid for POS checkout.
 * Structure:
 *   .pay-method-grid           flex-wrap grid wrapper
 *   > .pay-method-btn          single method card (button element)
 *     > .pay-method-icon       icon or logo image slot
 *     > .pay-method-label      method name
 *     > .pay-method-sub        optional subtitle (account, terminal name)
 *   .pay-method-amount-row     row for per-method amount input + chip
 * States:    .active / .is-active (selected), .is-disabled
 * Depends:   tokens.css
 * Added:     2026-05-10
 */

/* Grid */
.pay-method-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Button card */
.pay-method-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  min-width: 76px;
  background: var(--bg-card);
  border: 1.5px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  cursor: pointer;
  font-family: inherit;
  text-align: center;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    box-shadow var(--transition-fast);
  user-select: none;
}

.pay-method-btn:hover:not(.is-disabled) {
  background: var(--bg-subtle);
  border-color: var(--ui-accent);
}

.pay-method-btn.active,
.pay-method-btn.is-active {
  background: var(--ui-accent-soft);
  border-color: var(--ui-accent);
  box-shadow: 0 0 0 2px var(--ui-focus-ring);
}

.pay-method-btn.is-disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Icon slot */
.pay-method-icon {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-lg);
  color: var(--text-secondary);
  border-radius: var(--radius-md);
  background: var(--bg-secondary);
  overflow: hidden;
}

.pay-method-btn.active .pay-method-icon,
.pay-method-btn.is-active .pay-method-icon {
  color: var(--ui-accent);
  background: var(--ui-accent-soft);
}

.pay-method-icon img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Labels */
.pay-method-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
  white-space: nowrap;
}

.pay-method-sub {
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 80px;
}

/* Compact horizontal list variant */
.pay-method-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.pay-method-list .pay-method-btn {
  flex-direction: row;
  justify-content: flex-start;
  text-align: left;
  width: 100%;
  max-width: none;
  padding: var(--space-3);
  gap: var(--space-3);
}

.pay-method-list .pay-method-label {
  font-size: var(--text-sm);
}

/* Amount input row (mixed-payment mode) */
.pay-method-amount-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-subtle);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
}

.pay-method-amount-row .form-control {
  flex: 1;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-weight-semibold);
}

/* components/amount-display.css */
/**
 * Component: Amount Display
 * Purpose:   Large currency amount readout for POS totals, cart summary,
 *            payment confirmation, and receipt header.
 * Structure:
 *   .amount-display              block/flex wrapper
 *   > .amount-display-label      small label above the amount
 *   > .amount-display-value      primary large amount
 *     > .amount-display-currency currency symbol prefix
 *     > .amount-display-integer  integer part
 *     > .amount-display-decimal  decimal separator + cents
 *   > .amount-display-sub        smaller secondary line (e.g. "inc. tax")
 * Sizes:     default, .amount-display-sm, .amount-display-lg, .amount-display-xl
 * Variants:  .amount-display-primary, .amount-display-success, .amount-display-danger
 * Depends:   tokens.css
 * Added:     2026-05-10
 */

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

/* Label */
.amount-display-label {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-medium);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
  line-height: 1;
}

/* Value row */
.amount-display-value {
  display: flex;
  align-items: baseline;
  gap: 2px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--text-primary);
}

/* Currency symbol */
.amount-display-currency {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
  align-self: flex-start;
  padding-top: 2px;
}

/* Integer part */
.amount-display-integer {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  line-height: 1;
}

/* Decimal part */
.amount-display-decimal {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-medium);
  color: var(--text-secondary);
}

/* Sub line */
.amount-display-sub {
  font-size: var(--text-xs);
  color: var(--text-muted);
  line-height: 1;
}

/* Size variants */
.amount-display-sm .amount-display-integer  { font-size: var(--text-xl); }
.amount-display-sm .amount-display-decimal  { font-size: var(--text-sm); }
.amount-display-sm .amount-display-currency { font-size: var(--text-xs); }

.amount-display-lg .amount-display-integer  { font-size: var(--text-4xl); }
.amount-display-lg .amount-display-decimal  { font-size: var(--text-2xl); }
.amount-display-lg .amount-display-currency { font-size: var(--text-base); }

.amount-display-xl .amount-display-integer  {
  font-size: clamp(2.5rem, 6vw, 3.5rem);
  font-weight: 800;
}
.amount-display-xl .amount-display-decimal  { font-size: var(--text-3xl); }
.amount-display-xl .amount-display-currency { font-size: var(--text-lg); }

/* Color variants */
.amount-display-primary .amount-display-integer  { color: var(--ui-accent); }
.amount-display-primary .amount-display-currency { color: var(--ui-accent); opacity: 0.78; }
.amount-display-primary .amount-display-decimal  { color: var(--ui-accent); opacity: 0.78; }

.amount-display-success .amount-display-integer  { color: var(--color-success-700, #15803d); }
.amount-display-success .amount-display-currency { color: var(--color-success-500, #22c55e); }
.amount-display-success .amount-display-decimal  { color: var(--color-success-500, #22c55e); }

.amount-display-danger .amount-display-integer   { color: var(--color-danger-700, #b91c1c); }
.amount-display-danger .amount-display-currency  { color: var(--color-danger-400, #f87171); }
.amount-display-danger .amount-display-decimal   { color: var(--color-danger-400, #f87171); }

/* Inline compact variant (single line, no column layout) */
.amount-display-inline {
  flex-direction: row;
  align-items: baseline;
  gap: var(--space-2);
}

.amount-display-inline .amount-display-label {
  font-size: var(--text-sm);
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-secondary);
  font-weight: var(--font-weight-normal);
}

/* components/cart.css */
/**
 * Component: Cart
 * Purpose:   Cart item row and cart list container for POS sell/servicein.
 * Structure:
 *   .cart                      vertical list container
 *   > .cart-empty              empty state (shown when no items)
 *   > .cart-item               single line item row
 *     > .cart-item-name        service/product name + meta column
 *     > .cart-item-qty         quantity stepper or plain badge
 *     > .cart-item-price       unit price
 *     > .cart-item-total       line total
 *     > .cart-item-actions     remove button + per-item actions
 *   .cart-footer               sticky bottom row (subtotal / tax / total)
 *   > .cart-footer-row         label + value pair
 *   > .cart-footer-total       emphasized total row
 * Depends:   tokens.css, qty-stepper.css
 * Added:     2026-05-10
 */

/* Container */
.cart {
  display: flex;
  flex-direction: column;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

/* Empty state */
.cart-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.cart-empty-icon {
  font-size: var(--text-3xl);
  opacity: 0.25;
}

/* Scrollable items region */
.cart-items {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  min-height: 0;
}

/* Item row */
.cart-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-3);
  border-bottom: 1px solid var(--border-color-light);
  transition: background var(--transition-fast);
}

.cart-item:last-child {
  border-bottom: none;
}

.cart-item:hover {
  background: var(--bg-subtle);
}

.cart-item.is-selected {
  background: var(--ui-accent-soft);
}

/* Name column */
.cart-item-name {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.cart-item-label {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
  line-height: var(--line-height-tight);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cart-item-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cart-item-discount {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--text-xs);
  color: var(--color-success-700, #15803d);
  font-weight: var(--font-weight-medium);
}

/* Quantity */
.cart-item-qty {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

/* Price columns */
.cart-item-price,
.cart-item-total {
  flex-shrink: 0;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
  padding-top: 2px;
}

.cart-item-price {
  color: var(--text-muted);
  min-width: 52px;
}

.cart-item-total {
  color: var(--text-primary);
  font-weight: var(--font-weight-semibold);
  min-width: 64px;
}

/* Actions */
.cart-item-actions {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.cart-item-remove {
  width: 24px;
  height: 24px;
  border: none;
  background: none;
  border-radius: var(--radius-full);
  color: var(--text-muted);
  font-size: var(--text-xs);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.cart-item-remove:hover {
  background: color-mix(in srgb, var(--color-danger-500, #ef4444) 12%, transparent);
  color: var(--color-danger-600, #dc2626);
}

/* Footer summary */
.cart-footer {
  border-top: 1px solid var(--border-color);
  background: var(--bg-subtle);
  padding: var(--space-3) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.cart-footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

.cart-footer-row-value {
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-weight-medium);
}

.cart-footer-total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-color);
  margin-top: var(--space-1);
}

.cart-footer-total-value {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
  color: var(--ui-accent);
}

/* components/numpad.css */
/**
 * Component: Numpad
 * Purpose:   Numeric keypad grid for touch-friendly amount composition in POS.
 * Structure:
 *   .numpad                    outer wrapper
 *   > .numpad-display          current value readout (optional, can be external)
 *   > .numpad-grid             12-key grid (3 col × 4 row)
 *     > .numpad-key            digit or action button
 *       .numpad-key-digit      0-9 digit key
 *       .numpad-key-dot        decimal point key
 *       .numpad-key-back       backspace key
 *       .numpad-key-clear      clear / CE key
 *       .numpad-key-confirm    confirm / enter key (spans cols)
 * Variants:  .numpad-compact (reduced padding)
 * Depends:   tokens.css
 * Added:     2026-05-10
 */

/* Wrapper */
.numpad {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* Value readout above grid */
.numpad-display {
  background: var(--bg-subtle);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  text-align: right;
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-bold);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  line-height: 1.2;
  min-height: 64px;
  word-break: break-all;
}

.numpad-display-placeholder {
  color: var(--text-muted);
  font-weight: var(--font-weight-normal);
}

/* 3-column key grid */
.numpad-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}

/* Key base styles */
.numpad-key {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 56px;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  font-size: var(--text-xl);
  font-weight: var(--font-weight-medium);
  font-family: inherit;
  color: var(--text-primary);
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    transform 60ms;
  touch-action: manipulation;
}

.numpad-key:active {
  transform: scale(0.94);
  background: var(--bg-subtle);
}

.numpad-key:hover {
  background: var(--bg-subtle);
  border-color: var(--border-color);
}

/* Digit key */
.numpad-key-digit {
  font-size: var(--text-xl);
}

/* Decimal point */
.numpad-key-dot {
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-bold);
}

/* Backspace */
.numpad-key-back {
  color: var(--text-secondary);
  font-size: var(--text-lg);
}

.numpad-key-back:hover {
  color: var(--color-danger-600, #dc2626);
  background: color-mix(in srgb, var(--color-danger-500, #ef4444) 8%, var(--bg-card));
}

/* Clear */
.numpad-key-clear {
  color: var(--text-muted);
  font-size: var(--text-sm);
  letter-spacing: 0.04em;
}

.numpad-key-clear:hover {
  color: var(--color-danger-700, #b91c1c);
  background: color-mix(in srgb, var(--color-danger-500, #ef4444) 10%, var(--bg-card));
  border-color: var(--color-danger-300, #fca5a5);
}

/* Confirm / enter (spans full width) */
.numpad-key-confirm {
  grid-column: 1 / -1;
  height: 52px;
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
  font-size: var(--text-base);
  font-weight: var(--font-weight-semibold);
  border-radius: var(--radius-lg);
}

.numpad-key-confirm:hover {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  box-shadow: inset 0 0 0 999px var(--tint-black-5);
}

.numpad-key-confirm:active {
  background: var(--ui-accent);
}

/* Compact variant */
.numpad-compact .numpad-key {
  height: 44px;
}

.numpad-compact .numpad-display {
  font-size: var(--text-2xl);
  min-height: 52px;
  padding: var(--space-2) var(--space-3);
}

.numpad-compact .numpad-key-digit {
  font-size: var(--text-lg);
}

/* components/receipt-preview.css */
/**
 * Component: Receipt Preview
 * Purpose:   Thermal-style receipt / bill layout for POS receipt modal and print view.
 * Structure:
 *   .receipt-preview           outer frame (centered column, max-width ~380px)
 *   > .receipt-header          branch logo + name + address block
 *   > .receipt-divider         dashed divider line
 *   > .receipt-meta            receipt no, date, cashier row
 *   > .receipt-customer        customer name row (optional)
 *   > .receipt-items           line item list
 *     > .receipt-item          single item row
 *       .receipt-item-name     name + meta column
 *       .receipt-item-qty      qty × price column
 *       .receipt-item-total    line total column
 *   > .receipt-summary         subtotal, discount, tax, total block
 *   > .receipt-payments        payment method rows
 *   > .receipt-change          change / balance row
 *   > .receipt-footer          thank-you note, QR code, barcode
 * Variants:  .receipt-preview-modal (padded card), .receipt-preview-print (no border/shadow)
 * Depends:   tokens.css
 * Added:     2026-05-10
 */

/* Frame */
.receipt-preview {
  width: 100%;
  max-width: 380px;
  margin: 0 auto;
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  font-family: 'Courier New', 'Sarabun', monospace, sans-serif;
  font-size: 13px;
  color: var(--text-primary);
  overflow: hidden;
  line-height: 1.5;
}

.receipt-preview-modal {
  box-shadow: none;
  border-radius: 0;
  border: none;
  max-width: 100%;
}

/* Header */
.receipt-header {
  padding: var(--space-4) var(--space-4) var(--space-3);
  text-align: center;
  background: var(--bg-subtle);
}

.receipt-header-logo {
  max-height: 48px;
  max-width: 140px;
  object-fit: contain;
  margin: 0 auto var(--space-2);
  display: block;
}

.receipt-header-name {
  font-size: var(--text-base);
  font-weight: var(--font-weight-bold);
  margin: 0 0 var(--space-1);
}

.receipt-header-address,
.receipt-header-phone {
  font-size: 12px;
  color: var(--text-secondary);
  margin: 0;
}

/* Divider */
.receipt-divider {
  border: none;
  border-top: 1.5px dashed var(--border-color);
  margin: var(--space-2) var(--space-3);
}

/* Meta row */
.receipt-meta {
  padding: var(--space-2) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.receipt-meta-row {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--text-secondary);
}

.receipt-meta-row strong {
  color: var(--text-primary);
  font-weight: var(--font-weight-medium);
}

/* Customer */
.receipt-customer {
  padding: var(--space-1) var(--space-3);
  font-size: 12px;
  color: var(--text-secondary);
}

/* Items */
.receipt-items {
  padding: var(--space-2) var(--space-3);
}

.receipt-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: 3px 0;
}

.receipt-item-name {
  flex: 1;
  min-width: 0;
}

.receipt-item-label {
  font-size: 13px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.receipt-item-meta {
  font-size: 11px;
  color: var(--text-muted);
}

.receipt-item-qty {
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
  flex-shrink: 0;
  text-align: right;
  min-width: 80px;
}

.receipt-item-total {
  font-size: 13px;
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  flex-shrink: 0;
  text-align: right;
  min-width: 60px;
  font-variant-numeric: tabular-nums;
}

/* Summary block */
.receipt-summary {
  padding: var(--space-2) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.receipt-summary-row {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text-secondary);
}

.receipt-summary-row-value {
  font-variant-numeric: tabular-nums;
}

.receipt-summary-total {
  display: flex;
  justify-content: space-between;
  padding: var(--space-2) 0 0;
  margin-top: var(--space-1);
  border-top: 1.5px solid var(--border-color);
  font-size: var(--text-base);
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
}

.receipt-summary-total-value {
  font-size: var(--text-lg);
  font-variant-numeric: tabular-nums;
  color: var(--ui-accent);
}

/* Payments */
.receipt-payments {
  padding: var(--space-1) var(--space-3);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.receipt-payment-row {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--text-secondary);
}

/* Change */
.receipt-change {
  display: flex;
  justify-content: space-between;
  padding: var(--space-1) var(--space-3);
  font-size: 12px;
  color: var(--color-success-700, #15803d);
  font-weight: var(--font-weight-medium);
}

/* Footer */
.receipt-footer {
  padding: var(--space-3) var(--space-3) var(--space-4);
  text-align: center;
  background: var(--bg-subtle);
}

.receipt-footer-note {
  font-size: 12px;
  color: var(--text-muted);
  margin: 0 0 var(--space-2);
}

.receipt-footer-qr {
  display: flex;
  justify-content: center;
  margin: var(--space-2) auto;
}

.receipt-footer-qr img {
  width: 80px;
  height: 80px;
  object-fit: contain;
}

/* Print variant — removes all chrome */
@media print {
  .receipt-preview {
    max-width: 100%;
    box-shadow: none;
    border: none;
    border-radius: 0;
  }
  .receipt-preview-print {
    box-shadow: none;
    border: none;
    border-radius: 0;
  }
}

/* components/time-slot.css */
/**
 * Component: Time Slot
 * Purpose:   Bookable time slot button grid for booking availability display.
 * Structure:
 *   .time-slot-grid            flex-wrap or CSS grid wrapper
 *   > .time-slot-btn           individual slot button
 * States:    .is-available, .is-booked, .is-past, .is-selected, .is-blocked, .is-partial
 * Depends:   tokens.css
 * Added:     2026-05-10
 */

/* Grid */
.time-slot-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Fixed-column grid variant */
.time-slot-grid-fixed {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(68px, 1fr));
  gap: var(--space-2);
}

/* Slot button */
.time-slot-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-2) var(--space-3);
  min-width: 64px;
  height: 38px;
  border: 1.5px solid var(--border-color-light);
  border-radius: var(--radius-md);
  background: var(--bg-card);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast);
  white-space: nowrap;
  user-select: none;
}

/* Available (default + explicit) */
.time-slot-btn.is-available {
  border-color: var(--color-success-400, #4ade80);
  color: var(--color-success-700, #15803d);
}

.time-slot-btn.is-available:hover {
  background: color-mix(in srgb, var(--color-success-400, #4ade80) 10%, var(--bg-card));
  border-color: var(--color-success-500, #22c55e);
}

/* Selected */
.time-slot-btn.is-selected,
.time-slot-btn.active {
  background: var(--ui-accent);
  border-color: var(--ui-accent);
  color: var(--ui-accent-fg);
  box-shadow: 0 0 0 2px var(--ui-focus-ring);
}

/* Booked / unavailable */
.time-slot-btn.is-booked {
  background: var(--bg-secondary);
  border-color: var(--border-color-light);
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 0.6;
  text-decoration: line-through;
}

/* Partially booked */
.time-slot-btn.is-partial {
  background: color-mix(in srgb, var(--color-warning-400, #facc15) 10%, var(--bg-card));
  border-color: var(--color-warning-400, #facc15);
  color: var(--color-warning-700, #a16207);
}

.time-slot-btn.is-partial:hover {
  background: color-mix(in srgb, var(--color-warning-400, #facc15) 18%, var(--bg-card));
}

/* Past slots */
.time-slot-btn.is-past {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Blocked / closed */
.time-slot-btn.is-blocked {
  background: repeating-linear-gradient(
    45deg,
    var(--bg-secondary) 0px,
    var(--bg-secondary) 4px,
    var(--bg-card) 4px,
    var(--bg-card) 8px
  );
  border-color: var(--border-color-light);
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 0.5;
}

/* Time slot label sub-line (room count, capacity) */
.time-slot-sub {
  display: block;
  font-size: 10px;
  font-weight: var(--font-weight-normal);
  color: inherit;
  opacity: 0.75;
}

/* Column header for time-range grids (room name, date) */
.time-slot-col-header {
  font-size: var(--text-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-muted);
  text-align: center;
  padding: var(--space-1) 0;
  border-bottom: 1px solid var(--border-color-light);
  margin-bottom: var(--space-1);
}

/* Row header (time label on left side of grid) */
.time-slot-row-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-align: right;
  padding-right: var(--space-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  align-self: center;
}

/* components/confirm-dialog.css */
/**
 * Component: Confirm Dialog
 * Purpose:   Compact inline confirmation panel (not a full modal overlay).
 *            Used for destructive row actions: delete, void, cancel.
 * Structure:
 *   .confirm-dialog              inline card
 *   > .confirm-dialog-icon       warning / danger icon
 *   > .confirm-dialog-body       message text + action buttons
 *     > .confirm-dialog-title    short question
 *     > .confirm-dialog-message  supporting detail
 *     > .confirm-dialog-actions  confirm + cancel buttons
 * Variants:  .confirm-dialog-danger, .confirm-dialog-warning, .confirm-dialog-info
 * Depends:   tokens.css, button.css
 * Added:     2026-05-10
 */

/* Container */
.confirm-dialog {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-card);
  border: 1.5px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  animation: confirm-dialog-in var(--transition-fast) ease;
}

@keyframes confirm-dialog-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

/* Variants — left border accent */
.confirm-dialog-danger {
  border-left: 4px solid var(--color-danger-500, #ef4444);
}

.confirm-dialog-warning {
  border-left: 4px solid var(--color-warning-500, #eab308);
}

.confirm-dialog-info {
  border-left: 4px solid var(--ui-accent);
}

/* Icon */
.confirm-dialog-icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-base);
  background: color-mix(in srgb, var(--color-danger-500, #ef4444) 10%, transparent);
  color: var(--color-danger-600, #dc2626);
}

.confirm-dialog-warning .confirm-dialog-icon {
  background: color-mix(in srgb, var(--color-warning-500, #eab308) 12%, transparent);
  color: var(--color-warning-700, #a16207);
}

.confirm-dialog-info .confirm-dialog-icon {
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

/* Body */
.confirm-dialog-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.confirm-dialog-title {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  margin: 0;
  line-height: var(--line-height-tight);
}

.confirm-dialog-message {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  margin: 0;
  line-height: var(--line-height-normal);
}

/* Actions */
.confirm-dialog-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* Dismiss / close (top-right, optional) */
.confirm-dialog-close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
  width: 20px;
  height: 20px;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--text-muted);
  font-size: var(--text-xs);
  border-radius: var(--radius-full);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.confirm-dialog-close:hover {
  background: var(--bg-hover);
  color: var(--text-secondary);
}

/* Relative wrapper needed when using confirm-dialog-close */
.confirm-dialog {
  position: relative;
}

/* Inline embed inside table rows / list items */
.confirm-dialog-inline {
  border-radius: var(--radius-md);
  box-shadow: none;
  padding: var(--space-2) var(--space-3);
  gap: var(--space-2);
}

.confirm-dialog-inline .confirm-dialog-icon {
  width: 24px;
  height: 24px;
  font-size: var(--text-sm);
}

.confirm-dialog-inline .confirm-dialog-title {
  font-size: var(--text-xs);
}

/* patterns.css */
/**
 * Patterns
 * Composite UI built from primitives. Shared across multiple pages.
 * Added: 2026-04-22
 */

.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
  flex-wrap: wrap;
}

.page-header-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.page-title {
  margin: 0;
  font-size: var(--text-3xl);
  line-height: 1.1;
}

.page-subtitle {
  margin: 0;
  color: var(--text-muted);
}

.page-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-4);
}

.stat-card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-5);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}

.stat-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: var(--radius-lg);
}

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

.stat-value {
  font-size: var(--text-2xl);
  font-weight: var(--font-weight-semibold);
  line-height: 1.1;
}

.stat-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  letter-spacing: var(--letter-spacing-wide);
  text-transform: uppercase;
}

.stat-trend {
  font-size: var(--text-sm);
  font-weight: var(--font-weight-medium);
}

.card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--radius-lg);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  font-size: 1.25rem;
}

.hero {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-7);
  border-radius: var(--radius-xl);
  background: var(--ui-accent);
  color: var(--ui-accent-fg);
  box-shadow: var(--shadow-lg);
}

.hero-info {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
}

.hero-title,
.hero-subtitle {
  margin: 0;
  color: inherit;
}

.hero-badges,
.hero-stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.hero-stat {
  min-width: 5rem;
}

.hero-stat-value {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
}

.hero-stat-label {
  font-size: var(--text-xs);
  color: rgba(255, 255, 255, 0.72);
  text-transform: uppercase;
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-xl);
}

.toolbar-left,
.toolbar-right {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.detail-card {
  background: var(--bg-card);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.detail-header {
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border-color-light);
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-4);
  padding: var(--space-5);
}

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

.detail-label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: var(--letter-spacing-wide);
}

.detail-value {
  margin: 0;
  font-weight: var(--font-weight-medium);
  color: var(--text-primary);
}

@media (max-width: 1024px) {
  .hero,
  .toolbar {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* templates.css */
/**
 * Templates
 * Page-level scaffolds.
 * Added: 2026-04-22
 */

.tpl-auth {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  background:
    radial-gradient(circle at top left, var(--ui-accent-soft), transparent 24%),
    var(--bg-body);
}

.tpl-auth .card {
  width: 100%;
  max-width: 28rem;
}

.tpl-dashboard {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  min-height: 100vh;
  background: var(--bg-body);
}

.tpl-sidebar {
  padding: var(--space-5);
  border-right: 1px solid var(--border-color-light);
  background: var(--bg-card);
}

.tpl-main {
  padding: var(--space-6);
}

.widget-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--space-4);
}

.widget-grid > * {
  grid-column: span 4;
}

.tpl-list,
.tpl-form,
.tpl-detail,
.tpl-split {
  min-height: 100vh;
  padding: var(--space-6);
  background: var(--bg-body);
}

.tpl-detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--space-6);
}

.tpl-form .tpl-main {
  max-width: 45rem;
  margin: 0 auto;
}

.tpl-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 420px;
  gap: var(--space-6);
}

@media (max-width: 1024px) {
  .tpl-dashboard,
  .tpl-detail,
  .tpl-split {
    grid-template-columns: 1fr;
  }

  .widget-grid > * {
    grid-column: span 12;
  }
}

/* states.css */
/**
 * engine/ui/states.css — Common UI State Primitives
 *
 * Phase 5 § "define common states" — loading, empty, error, success
 * rendered as reusable CSS classes. No JS required; drop markup into
 * any container. Pair with components.css.
 *
 * 2026-04-21.
 */

/* ═══════════════════════════════════════════════════════════════════════════
   LOADING
   ═══════════════════════════════════════════════════════════════════════════ */

/* Initial-loader compatibility — legacy classes used by app/index.html
   before the engine bundle loads. These match the pre-1_5_3 visuals so
   both coreMode and engineMode render the same boot screen. */
.loading-screen {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  background: var(--bg-body);
  z-index: var(--z-toast);
}
.loading-screen .loading-spinner {
  width: 48px;
  height: 48px;
  border: 4px solid var(--ui-accent-active);
  border-top-color: var(--ui-accent);
  border-radius: var(--radius-full);
  animation: spin 700ms linear infinite;
}
.loading-screen .loading-text {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  margin: 0;
}

/* Full-container spinner */
.state-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-12) var(--space-4);
  color: var(--text-muted);
  font-size: var(--text-sm);
}
.state-loading-spinner {
  width: 32px;
  height: 32px;
  border: 3px solid var(--ui-accent-active);
  border-top-color: var(--ui-accent);
  border-radius: var(--radius-full);
  animation: spin 700ms linear infinite;
}
.state-loading-spinner.is-lg { width: 48px; height: 48px; border-width: 4px; }
.state-loading-spinner.is-sm { width: 20px; height: 20px; border-width: 2px; }

/* Skeleton primitives moved to components/skeleton.css (2026-04-24).
   Legacy compound shapes kept here as aliases for any page still using them. */
.skeleton-avatar    { width: 40px; height: 40px; border-radius: var(--radius-full); }
.skeleton-thumbnail { width: 64px; height: 64px; border-radius: var(--radius-md); }
.skeleton-block     { height: 120px; }

.skeleton-row {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-3) 0;
}
.skeleton-row-body { flex: 1; }

/* Progress bar */
.progress {
  width: 100%;
  height: 4px;
  background: var(--color-gray-200);
  border-radius: var(--radius-full);
  overflow: hidden;
}
.progress-bar {
  height: 100%;
  background: var(--ui-accent);
  border-radius: inherit;
  transition: width var(--transition-normal);
}
.progress.is-indeterminate .progress-bar {
  width: 30%;
  animation: progress-indeterminate 1.4s var(--ease-standard) infinite;
}

@keyframes progress-indeterminate {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(400%); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   EMPTY — no data
   ═══════════════════════════════════════════════════════════════════════════ */
.state-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-12) var(--space-6);
  text-align: center;
  color: var(--text-muted);
}

.state-empty-compact {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  background: var(--surface-overlay);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  text-align: center;
}
.state-empty-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  color: var(--color-gray-400);
  font-size: 32px;
}
.state-empty-title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  margin: 0;
}
.state-empty-description {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  max-width: 42ch;
  line-height: var(--line-height-relaxed);
  margin: 0;
}
.state-empty-actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-2);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ERROR
   ═══════════════════════════════════════════════════════════════════════════ */
.state-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-12) var(--space-6);
  text-align: center;
}
.state-error-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: var(--radius-full);
  background: var(--color-error-bg);
  color: var(--color-error);
  font-size: 32px;
}
.state-error-title {
  font-size: var(--text-lg);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  margin: 0;
}
.state-error-description {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  max-width: 48ch;
  line-height: var(--line-height-relaxed);
  margin: 0;
}
.state-error-details {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
  background: var(--bg-subtle);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  max-width: 100%;
  overflow: auto;
  text-align: left;
}
.state-error-actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-2);
}

/* ═══════════════════════════════════════════════════════════════════════════
   SUCCESS
   ═══════════════════════════════════════════════════════════════════════════ */
.state-success {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-12) var(--space-6);
  text-align: center;
  animation: slide-up var(--duration-normal) var(--ease-decelerate);
}
.state-success-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 80px;
  height: 80px;
  border-radius: var(--radius-full);
  background: var(--color-success-bg);
  color: var(--color-success);
  font-size: 36px;
  animation: pulse-scale 900ms var(--ease-standard) 1;
}
.state-success-title {
  font-size: var(--text-xl);
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
  margin: 0;
}
.state-success-description {
  font-size: var(--text-sm);
  color: var(--text-secondary);
  max-width: 48ch;
  line-height: var(--line-height-relaxed);
  margin: 0;
}
.state-success-actions {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-2);
}

/* ═══════════════════════════════════════════════════════════════════════════
   A11Y — global focus-visible safety net (2026-04-24)
   ═══════════════════════════════════════════════════════════════════════════

   Every interactive primitive should have a focus-visible outline even if
   the component CSS forgot to declare one. Components that declare their
   own focus ring override this via cascade specificity.
*/
.nav-link:focus-visible,
.navbar a:focus-visible,
.tab:focus-visible,
.tab-link:focus-visible,
.page-item:focus-visible,
.pagination a:focus-visible,
.breadcrumb-item:focus-visible,
.chip:focus-visible,
.list-group-item:focus-visible,
.card-link:focus-visible,
.table th[role="button"]:focus-visible,
.table [data-sort]:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}

/* Honour reduced motion globally — any transition/animation shorter than
   the preference is respected by individual components; this is a belt
   and braces catch-all. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
