@layer reset, tokens, base, components, patterns, utilities;

/* ---- dist/tokens.css ---- */
@layer tokens {
/* Generated by ds build — edit tokens/*.json, not this file. */

:root {
  color-scheme: light dark;
  --color-gray-0: #ffffff;
  --color-gray-50: #f8fafc;
  --color-gray-100: #f1f5f9;
  --color-gray-200: #e2e8f0;
  --color-gray-300: #cbd5e1;
  --color-gray-400: #94a3b8;
  --color-gray-500: #64748b;
  --color-gray-600: #475569;
  --color-gray-700: #334155;
  --color-gray-800: #1e293b;
  --color-gray-900: #0f172a;
  --color-gray-950: #020617;
  --color-gray-1000: #000000;
  --color-blue-50: #eff6ff;
  --color-blue-100: #dbeafe;
  --color-blue-200: #bfdbfe;
  --color-blue-300: #93c5fd;
  --color-blue-400: #60a5fa;
  --color-blue-500: #3b82f6;
  --color-blue-600: #2563eb;
  --color-blue-700: #1d4ed8;
  --color-blue-800: #1e40af;
  --color-blue-900: #1e3a8a;
  --color-red-50: #fef2f2;
  --color-red-100: #fee2e2;
  --color-red-200: #fecaca;
  --color-red-400: #f87171;
  --color-red-500: #ef4444;
  --color-red-600: #dc2626;
  --color-red-700: #b91c1c;
  --color-red-800: #991b1b;
  --color-red-900: #7f1d1d;
  --color-green-50: #f0fdf4;
  --color-green-100: #dcfce7;
  --color-green-200: #bbf7d0;
  --color-green-400: #4ade80;
  --color-green-600: #16a34a;
  --color-green-700: #15803d;
  --color-green-800: #166534;
  --color-green-900: #14532d;
  --color-amber-50: #fffbeb;
  --color-amber-100: #fef3c7;
  --color-amber-200: #fde68a;
  --color-amber-400: #fbbf24;
  --color-amber-600: #d97706;
  --color-amber-700: #b45309;
  --color-amber-800: #92400e;
  --color-amber-900: #78350f;
  --color-alpha-scrim-light: #0f172a99;
  --color-alpha-scrim-dark: #020617cc;
  --color-alpha-transparent: #00000000;
  --color-alpha-shadow: #0f172a1f;
  --color-alpha-shadow-strong: #0f172a33;
  --color-bg-canvas: var(--color-gray-0);
  --color-bg-surface: var(--color-gray-0);
  --color-bg-subtle: var(--color-gray-50);
  --color-bg-muted: var(--color-gray-100);
  --color-bg-raised: var(--color-gray-0);
  --color-bg-inverse: var(--color-gray-900);
  --color-bg-overlay: var(--color-alpha-scrim-light);
  --color-text-default: var(--color-gray-900);
  --color-text-muted: var(--color-gray-600);
  --color-text-subtle: var(--color-gray-500);
  --color-text-disabled: var(--color-gray-400);
  --color-text-inverse: var(--color-gray-0);
  --color-text-link: var(--color-teal-700);
  --color-text-link-visited: var(--color-blue-900);
  --color-border-subtle: var(--color-gray-100);
  --color-border-default: var(--color-gray-200);
  --color-border-strong: var(--color-gray-500);
  --color-border-focus: var(--color-teal-500);
  --color-border-invalid: var(--color-red-600);
  --color-action-primary-bg: var(--color-teal-700);
  --color-action-primary-bg-hover: var(--color-teal-800);
  --color-action-primary-bg-active: var(--color-teal-900);
  --color-action-primary-fg: var(--color-gray-0);
  --color-action-secondary-bg: var(--color-gray-0);
  --color-action-secondary-bg-hover: var(--color-gray-100);
  --color-action-secondary-bg-active: var(--color-gray-200);
  --color-action-secondary-fg: var(--color-gray-900);
  --color-action-secondary-border: var(--color-gray-300);
  --color-action-ghost-bg: var(--color-alpha-transparent);
  --color-action-ghost-bg-hover: var(--color-gray-100);
  --color-action-ghost-bg-active: var(--color-gray-200);
  --color-action-ghost-fg: var(--color-gray-900);
  --color-action-danger-bg: var(--color-red-600);
  --color-action-danger-bg-hover: var(--color-red-700);
  --color-action-danger-bg-active: var(--color-red-800);
  --color-action-danger-fg: var(--color-gray-0);
  --color-selected-bg: var(--color-teal-50);
  --color-selected-fg: var(--color-teal-700);
  --color-selected-border: var(--color-teal-700);
  --color-feedback-info-bg: var(--color-blue-50);
  --color-feedback-info-fg: var(--color-blue-800);
  --color-feedback-info-border: var(--color-blue-200);
  --color-feedback-info-icon: var(--color-blue-600);
  --color-feedback-success-bg: var(--color-green-50);
  --color-feedback-success-fg: var(--color-green-900);
  --color-feedback-success-border: var(--color-green-200);
  --color-feedback-success-icon: var(--color-green-700);
  --color-feedback-warning-bg: var(--color-amber-50);
  --color-feedback-warning-fg: var(--color-amber-900);
  --color-feedback-warning-border: var(--color-amber-200);
  --color-feedback-warning-icon: var(--color-amber-700);
  --color-feedback-danger-bg: var(--color-red-50);
  --color-feedback-danger-fg: var(--color-red-900);
  --color-feedback-danger-border: var(--color-red-200);
  --color-feedback-danger-icon: var(--color-red-600);
  --color-elevation-surface-sunken: var(--color-gray-50);
  --color-elevation-surface-default: var(--color-bg-surface);
  --color-elevation-surface-raised: var(--color-gray-0);
  --color-elevation-surface-overlay: var(--color-gray-0);
  --color-highlight-bg: var(--color-amber-100);
  --color-highlight-fg: var(--color-gray-900);
  --color-highlight-current: var(--color-amber-400);
  --color-teal-50: oklch(0.971 0.0069 186.39);
  --color-teal-100: oklch(0.936 0.0155 186.39);
  --color-teal-200: oklch(0.885 0.0301 186.39);
  --color-teal-300: oklch(0.808 0.0516 186.39);
  --color-teal-400: oklch(0.704 0.0731 186.39);
  --color-teal-500: oklch(0.639 0.0861 186.39);
  --color-teal-600: oklch(0.581 0.0861 186.39);
  --color-teal-700: #0f766e;
  --color-teal-800: oklch(0.448 0.0645 186.39);
  --color-teal-900: oklch(0.398 0.0516 186.39);
  --color-teal-950: oklch(0.258 0.0387 186.39);
  --font-family-sans: "Inter", system-ui, -apple-system, sans-serif;
  --font-family-serif: "Georgia", serif;
  --font-family-mono: "JetBrains Mono", ui-monospace, monospace;
  --font-size-xs: 0.75rem;
  --font-size-sm: 0.875rem;
  --font-size-md: 1rem;
  --font-size-lg: 1.125rem;
  --font-size-xl: 1.25rem;
  --font-size-2xl: 1.5rem;
  --font-size-3xl: 1.875rem;
  --font-size-4xl: 2.25rem;
  --font-size-5xl: 3rem;
  --font-size-6xl: 3.75rem;
  --font-size-7xl: 4.5rem;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --font-line-height-tight: 1.2;
  --font-line-height-snug: 1.35;
  --font-line-height-normal: 1.5;
  --font-line-height-relaxed: 1.7;
  --font-tracking-tight: -0.02em;
  --font-tracking-normal: 0em;
  --font-tracking-wide: 0.06em;
  --space-0: 0rem;
  --space-px: 0.0625rem;
  --space-0-5: 0.125rem;
  --space-1: 0.25rem;
  --space-1-5: 0.375rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;
  --space-32: 8rem;
  --space-40: 10rem;
  --radius-none: 0rem;
  --radius-sm: 0.25rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;
  --radius-xl: 1rem;
  --radius-full: 9999px;
  --border-width-thin: 1px;
  --border-width-thick: 2px;
  --shadow-sm: 0px 1px 2px 0px var(--color-alpha-shadow);
  --shadow-md: 0px 4px 8px -2px var(--color-alpha-shadow), 0px 2px 4px -2px var(--color-alpha-shadow);
  --shadow-lg: 0px 12px 24px -6px var(--color-alpha-shadow-strong);
  --shadow-xl: 0px 24px 48px -12px var(--color-alpha-shadow-strong);
  --motion-duration-instant: 0ms;
  --motion-duration-fast: 120ms;
  --motion-duration-base: 200ms;
  --motion-duration-slow: 320ms;
  --motion-duration-slower: 500ms;
  --motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);
  --motion-easing-enter: cubic-bezier(0, 0, 0.2, 1);
  --motion-easing-exit: cubic-bezier(0.4, 0, 1, 1);
  --motion-easing-emphasized: cubic-bezier(0.3, 0, 0, 1);
  --z-base: 0;
  --z-raised: 10;
  --z-sticky: 1100;
  --z-fixed: 1200;
  --z-overlay: 1300;
  --z-modal: 1400;
  --z-dropdown: 1500;
  --z-popover: 1500;
  --z-toast: 1600;
  --z-tooltip: 1700;
  --breakpoint-sm: 40rem;
  --breakpoint-md: 48rem;
  --breakpoint-lg: 64rem;
  --breakpoint-xl: 80rem;
  --breakpoint-2xl: 96rem;
  --opacity-disabled: 0.5;
  --opacity-hover-overlay: 0.08;
  --opacity-pressed-overlay: 0.12;
  --opacity-state-hover: 0.08;
  --opacity-state-focus: 0.1;
  --opacity-state-pressed: 0.1;
  --opacity-state-dragged: 0.16;
  --typography-display-font-family: var(--font-family-sans);
  --typography-display-font-size: var(--font-size-5xl);
  --typography-display-font-weight: var(--font-weight-bold);
  --typography-display-line-height: var(--font-line-height-tight);
  --typography-h1-font-family: var(--font-family-sans);
  --typography-h1-font-size: var(--font-size-4xl);
  --typography-h1-font-weight: var(--font-weight-bold);
  --typography-h1-line-height: var(--font-line-height-tight);
  --typography-h2-font-family: var(--font-family-sans);
  --typography-h2-font-size: var(--font-size-3xl);
  --typography-h2-font-weight: var(--font-weight-semibold);
  --typography-h2-line-height: var(--font-line-height-tight);
  --typography-h3-font-family: var(--font-family-sans);
  --typography-h3-font-size: var(--font-size-2xl);
  --typography-h3-font-weight: var(--font-weight-semibold);
  --typography-h3-line-height: var(--font-line-height-snug);
  --typography-h4-font-family: var(--font-family-sans);
  --typography-h4-font-size: var(--font-size-xl);
  --typography-h4-font-weight: var(--font-weight-semibold);
  --typography-h4-line-height: var(--font-line-height-snug);
  --typography-h5-font-family: var(--font-family-sans);
  --typography-h5-font-size: var(--font-size-lg);
  --typography-h5-font-weight: var(--font-weight-semibold);
  --typography-h5-line-height: var(--font-line-height-snug);
  --typography-h6-font-family: var(--font-family-sans);
  --typography-h6-font-size: var(--font-size-md);
  --typography-h6-font-weight: var(--font-weight-semibold);
  --typography-h6-line-height: var(--font-line-height-snug);
  --typography-lead-font-family: var(--font-family-sans);
  --typography-lead-font-size: var(--font-size-lg);
  --typography-lead-font-weight: var(--font-weight-regular);
  --typography-lead-line-height: var(--font-line-height-relaxed);
  --typography-body-font-family: var(--font-family-sans);
  --typography-body-font-size: var(--font-size-md);
  --typography-body-font-weight: var(--font-weight-regular);
  --typography-body-line-height: var(--font-line-height-normal);
  --typography-small-font-family: var(--font-family-sans);
  --typography-small-font-size: var(--font-size-sm);
  --typography-small-font-weight: var(--font-weight-regular);
  --typography-small-line-height: var(--font-line-height-normal);
  --typography-caption-font-family: var(--font-family-sans);
  --typography-caption-font-size: var(--font-size-xs);
  --typography-caption-font-weight: var(--font-weight-medium);
  --typography-caption-line-height: var(--font-line-height-normal);
  --typography-code-font-family: var(--font-family-mono);
  --typography-code-font-size: var(--font-size-sm);
  --typography-code-font-weight: var(--font-weight-regular);
  --typography-code-line-height: var(--font-line-height-normal);
  --typography-display-lg-font-family: var(--font-family-sans);
  --typography-display-lg-font-size: var(--font-size-7xl);
  --typography-display-lg-font-weight: var(--font-weight-bold);
  --typography-display-lg-line-height: var(--font-line-height-tight);
  --size-control-sm: 2rem;
  --size-control-md: 2.5rem;
  --size-control-lg: 3rem;
  --size-touch-target: 2.75rem;
  --size-container-sm: 40rem;
  --size-container-md: 48rem;
  --size-container-lg: 64rem;
  --size-container-xl: 80rem;
  --size-measure: 65ch;
  --size-sticky-offset: 4rem;
  --size-sheet-peek: 96px;
  --size-swipe-action: 80px;
  --focus-ring-width: 2px;
  --focus-ring-offset: 2px;
  --focus-ring-color: var(--color-border-focus);
  --density-comfortable-control-padding-x: var(--space-4);
  --density-comfortable-cell-padding-y: var(--space-3);
  --density-compact-control-padding-x: var(--space-3);
  --density-compact-cell-padding-y: var(--space-1-5);
  --density-spacious-control-padding-x: var(--space-5);
  --density-spacious-cell-padding-y: var(--space-4);
  --icon-size-sm: 1rem;
  --icon-size-md: 1.25rem;
  --icon-size-lg: 1.5rem;
  --icon-stroke: 1.5;
  --dataviz-categorical-1: #0072b2;
  --dataviz-categorical-2: #e69f00;
  --dataviz-categorical-3: #009e73;
  --dataviz-categorical-4: #cc79a7;
  --dataviz-categorical-5: #56b4e9;
  --dataviz-categorical-6: #d55e00;
  --dataviz-categorical-7: #8c6d00;
  --dataviz-categorical-8: #5c5c5c;
  --dataviz-sequential-1: var(--color-blue-100);
  --dataviz-sequential-2: var(--color-blue-300);
  --dataviz-sequential-3: var(--color-blue-500);
  --dataviz-sequential-4: var(--color-blue-700);
  --dataviz-sequential-5: var(--color-blue-900);
  --dataviz-diverging-neg: var(--color-red-600);
  --dataviz-diverging-mid: var(--color-gray-200);
  --dataviz-diverging-pos: var(--color-blue-600);
  --section-padding-block-sm: clamp(2.5rem, 6vw, 4rem);
  --section-padding-block-md: clamp(3.5rem, 9vw, 6rem);
  --section-padding-block-lg: clamp(4.5rem, 12vw, 8rem);
  --section-gap: clamp(2rem, 5vw, 4rem);
  --section-max-inline: var(--size-container-xl);
  --elevation-raised: var(--shadow-md);
  --elevation-overlay: var(--shadow-xl);
  --button-radius: var(--radius-md);
  --button-height-sm: var(--size-control-sm);
  --button-height-md: var(--size-control-md);
  --button-height-lg: var(--size-control-lg);
  --button-font-weight: var(--font-weight-semibold);
  --input-radius: var(--radius-md);
  --input-border: var(--color-border-strong);
  --input-bg: var(--color-bg-surface);
  --card-radius: var(--radius-lg);
  --card-shadow: var(--shadow-sm);
  --card-padding: var(--space-6);
  --overlay-radius: var(--radius-lg);
  --overlay-shadow: var(--shadow-xl);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
  color-scheme: dark;
  --color-bg-canvas: var(--color-gray-950);
  --color-bg-surface: var(--color-gray-900);
  --color-bg-subtle: var(--color-gray-800);
  --color-bg-muted: var(--color-gray-800);
  --color-bg-raised: var(--color-gray-800);
  --color-bg-inverse: var(--color-gray-50);
  --color-bg-overlay: var(--color-alpha-scrim-dark);
  --color-text-default: var(--color-gray-50);
  --color-text-muted: var(--color-gray-300);
  --color-text-subtle: var(--color-gray-400);
  --color-text-disabled: var(--color-gray-600);
  --color-text-inverse: var(--color-gray-900);
  --color-text-link: var(--color-teal-400);
  --color-text-link-visited: var(--color-blue-200);
  --color-border-subtle: var(--color-gray-800);
  --color-border-default: var(--color-gray-700);
  --color-border-strong: var(--color-gray-500);
  --color-border-focus: var(--color-teal-400);
  --color-border-invalid: var(--color-red-400);
  --color-action-primary-bg: var(--color-teal-500);
  --color-action-primary-bg-hover: var(--color-teal-400);
  --color-action-primary-bg-active: var(--color-teal-300);
  --color-action-primary-fg: var(--color-gray-950);
  --color-action-secondary-bg: var(--color-gray-900);
  --color-action-secondary-bg-hover: var(--color-gray-800);
  --color-action-secondary-bg-active: var(--color-gray-700);
  --color-action-secondary-fg: var(--color-gray-50);
  --color-action-secondary-border: var(--color-gray-600);
  --color-action-ghost-bg-hover: var(--color-gray-800);
  --color-action-ghost-bg-active: var(--color-gray-700);
  --color-action-ghost-fg: var(--color-gray-50);
  --color-action-danger-bg: var(--color-red-500);
  --color-action-danger-bg-hover: var(--color-red-400);
  --color-action-danger-bg-active: var(--color-red-200);
  --color-action-danger-fg: var(--color-gray-950);
  --color-selected-bg: var(--color-teal-900);
  --color-selected-fg: var(--color-teal-100);
  --color-selected-border: var(--color-teal-400);
  --color-feedback-info-bg: var(--color-blue-900);
  --color-feedback-info-fg: var(--color-blue-100);
  --color-feedback-info-border: var(--color-blue-700);
  --color-feedback-info-icon: var(--color-blue-400);
  --color-feedback-success-bg: var(--color-green-900);
  --color-feedback-success-fg: var(--color-green-100);
  --color-feedback-success-border: var(--color-green-700);
  --color-feedback-success-icon: var(--color-green-400);
  --color-feedback-warning-bg: var(--color-amber-900);
  --color-feedback-warning-fg: var(--color-amber-100);
  --color-feedback-warning-border: var(--color-amber-700);
  --color-feedback-warning-icon: var(--color-amber-400);
  --color-feedback-danger-bg: var(--color-red-900);
  --color-feedback-danger-fg: var(--color-red-100);
  --color-feedback-danger-border: var(--color-red-700);
  --color-feedback-danger-icon: var(--color-red-400);
  --color-elevation-surface-sunken: var(--color-gray-950);
  --color-elevation-surface-default: var(--color-gray-900);
  --color-elevation-surface-raised: var(--color-gray-800);
  --color-elevation-surface-overlay: var(--color-gray-700);
  --color-highlight-bg: var(--color-amber-800);
  --color-highlight-fg: var(--color-gray-0);
  --color-highlight-current: var(--color-amber-600);
  }
}

[data-theme="dark"], .theme-dark {
  color-scheme: dark;
  --color-bg-canvas: var(--color-gray-950);
  --color-bg-surface: var(--color-gray-900);
  --color-bg-subtle: var(--color-gray-800);
  --color-bg-muted: var(--color-gray-800);
  --color-bg-raised: var(--color-gray-800);
  --color-bg-inverse: var(--color-gray-50);
  --color-bg-overlay: var(--color-alpha-scrim-dark);
  --color-text-default: var(--color-gray-50);
  --color-text-muted: var(--color-gray-300);
  --color-text-subtle: var(--color-gray-400);
  --color-text-disabled: var(--color-gray-600);
  --color-text-inverse: var(--color-gray-900);
  --color-text-link: var(--color-teal-400);
  --color-text-link-visited: var(--color-blue-200);
  --color-border-subtle: var(--color-gray-800);
  --color-border-default: var(--color-gray-700);
  --color-border-strong: var(--color-gray-500);
  --color-border-focus: var(--color-teal-400);
  --color-border-invalid: var(--color-red-400);
  --color-action-primary-bg: var(--color-teal-500);
  --color-action-primary-bg-hover: var(--color-teal-400);
  --color-action-primary-bg-active: var(--color-teal-300);
  --color-action-primary-fg: var(--color-gray-950);
  --color-action-secondary-bg: var(--color-gray-900);
  --color-action-secondary-bg-hover: var(--color-gray-800);
  --color-action-secondary-bg-active: var(--color-gray-700);
  --color-action-secondary-fg: var(--color-gray-50);
  --color-action-secondary-border: var(--color-gray-600);
  --color-action-ghost-bg-hover: var(--color-gray-800);
  --color-action-ghost-bg-active: var(--color-gray-700);
  --color-action-ghost-fg: var(--color-gray-50);
  --color-action-danger-bg: var(--color-red-500);
  --color-action-danger-bg-hover: var(--color-red-400);
  --color-action-danger-bg-active: var(--color-red-200);
  --color-action-danger-fg: var(--color-gray-950);
  --color-selected-bg: var(--color-teal-900);
  --color-selected-fg: var(--color-teal-100);
  --color-selected-border: var(--color-teal-400);
  --color-feedback-info-bg: var(--color-blue-900);
  --color-feedback-info-fg: var(--color-blue-100);
  --color-feedback-info-border: var(--color-blue-700);
  --color-feedback-info-icon: var(--color-blue-400);
  --color-feedback-success-bg: var(--color-green-900);
  --color-feedback-success-fg: var(--color-green-100);
  --color-feedback-success-border: var(--color-green-700);
  --color-feedback-success-icon: var(--color-green-400);
  --color-feedback-warning-bg: var(--color-amber-900);
  --color-feedback-warning-fg: var(--color-amber-100);
  --color-feedback-warning-border: var(--color-amber-700);
  --color-feedback-warning-icon: var(--color-amber-400);
  --color-feedback-danger-bg: var(--color-red-900);
  --color-feedback-danger-fg: var(--color-red-100);
  --color-feedback-danger-border: var(--color-red-700);
  --color-feedback-danger-icon: var(--color-red-400);
  --color-elevation-surface-sunken: var(--color-gray-950);
  --color-elevation-surface-default: var(--color-gray-900);
  --color-elevation-surface-raised: var(--color-gray-800);
  --color-elevation-surface-overlay: var(--color-gray-700);
  --color-highlight-bg: var(--color-amber-800);
  --color-highlight-fg: var(--color-gray-0);
  --color-highlight-current: var(--color-amber-600);
}

@media (prefers-contrast: more) {
  :root:not([data-theme]) {
  color-scheme: light;
  --color-bg-canvas: var(--color-gray-0);
  --color-bg-surface: var(--color-gray-0);
  --color-bg-subtle: var(--color-gray-0);
  --color-bg-muted: var(--color-gray-100);
  --color-text-default: var(--color-gray-1000);
  --color-text-muted: var(--color-gray-900);
  --color-text-subtle: var(--color-gray-800);
  --color-text-link: var(--color-teal-800);
  --color-border-subtle: var(--color-gray-700);
  --color-border-default: var(--color-gray-900);
  --color-border-strong: var(--color-gray-1000);
  --color-border-focus: var(--color-gray-1000);
  --color-action-primary-bg: var(--color-teal-800);
  --color-action-primary-bg-hover: var(--color-gray-1000);
  --color-action-primary-fg: var(--color-gray-0);
  --color-action-danger-bg: var(--color-red-900);
  --color-action-danger-bg-hover: var(--color-gray-1000);
  --color-action-danger-fg: var(--color-gray-0);
  --color-selected-bg: var(--color-gray-1000);
  --color-selected-fg: var(--color-gray-0);
  }
}

[data-theme="high-contrast"], .theme-high-contrast {
  color-scheme: light;
  --color-bg-canvas: var(--color-gray-0);
  --color-bg-surface: var(--color-gray-0);
  --color-bg-subtle: var(--color-gray-0);
  --color-bg-muted: var(--color-gray-100);
  --color-text-default: var(--color-gray-1000);
  --color-text-muted: var(--color-gray-900);
  --color-text-subtle: var(--color-gray-800);
  --color-text-link: var(--color-teal-800);
  --color-border-subtle: var(--color-gray-700);
  --color-border-default: var(--color-gray-900);
  --color-border-strong: var(--color-gray-1000);
  --color-border-focus: var(--color-gray-1000);
  --color-action-primary-bg: var(--color-teal-800);
  --color-action-primary-bg-hover: var(--color-gray-1000);
  --color-action-primary-fg: var(--color-gray-0);
  --color-action-danger-bg: var(--color-red-900);
  --color-action-danger-bg-hover: var(--color-gray-1000);
  --color-action-danger-fg: var(--color-gray-0);
  --color-selected-bg: var(--color-gray-1000);
  --color-selected-fg: var(--color-gray-0);
}

[data-theme="light"], .theme-light {
  color-scheme: light;
  --color-action-danger-bg: var(--color-red-600);
  --color-action-danger-bg-active: var(--color-red-800);
  --color-action-danger-bg-hover: var(--color-red-700);
  --color-action-danger-fg: var(--color-gray-0);
  --color-action-ghost-bg-active: var(--color-gray-200);
  --color-action-ghost-bg-hover: var(--color-gray-100);
  --color-action-ghost-fg: var(--color-gray-900);
  --color-action-primary-bg: var(--color-teal-700);
  --color-action-primary-bg-active: var(--color-teal-900);
  --color-action-primary-bg-hover: var(--color-teal-800);
  --color-action-primary-fg: var(--color-gray-0);
  --color-action-secondary-bg: var(--color-gray-0);
  --color-action-secondary-bg-active: var(--color-gray-200);
  --color-action-secondary-bg-hover: var(--color-gray-100);
  --color-action-secondary-border: var(--color-gray-300);
  --color-action-secondary-fg: var(--color-gray-900);
  --color-bg-canvas: var(--color-gray-0);
  --color-bg-inverse: var(--color-gray-900);
  --color-bg-muted: var(--color-gray-100);
  --color-bg-overlay: var(--color-alpha-scrim-light);
  --color-bg-raised: var(--color-gray-0);
  --color-bg-subtle: var(--color-gray-50);
  --color-bg-surface: var(--color-gray-0);
  --color-border-default: var(--color-gray-200);
  --color-border-focus: var(--color-teal-500);
  --color-border-invalid: var(--color-red-600);
  --color-border-strong: var(--color-gray-500);
  --color-border-subtle: var(--color-gray-100);
  --color-elevation-surface-default: var(--color-bg-surface);
  --color-elevation-surface-overlay: var(--color-gray-0);
  --color-elevation-surface-raised: var(--color-gray-0);
  --color-elevation-surface-sunken: var(--color-gray-50);
  --color-feedback-danger-bg: var(--color-red-50);
  --color-feedback-danger-border: var(--color-red-200);
  --color-feedback-danger-fg: var(--color-red-900);
  --color-feedback-danger-icon: var(--color-red-600);
  --color-feedback-info-bg: var(--color-blue-50);
  --color-feedback-info-border: var(--color-blue-200);
  --color-feedback-info-fg: var(--color-blue-800);
  --color-feedback-info-icon: var(--color-blue-600);
  --color-feedback-success-bg: var(--color-green-50);
  --color-feedback-success-border: var(--color-green-200);
  --color-feedback-success-fg: var(--color-green-900);
  --color-feedback-success-icon: var(--color-green-700);
  --color-feedback-warning-bg: var(--color-amber-50);
  --color-feedback-warning-border: var(--color-amber-200);
  --color-feedback-warning-fg: var(--color-amber-900);
  --color-feedback-warning-icon: var(--color-amber-700);
  --color-highlight-bg: var(--color-amber-100);
  --color-highlight-current: var(--color-amber-400);
  --color-highlight-fg: var(--color-gray-900);
  --color-selected-bg: var(--color-teal-50);
  --color-selected-border: var(--color-teal-700);
  --color-selected-fg: var(--color-teal-700);
  --color-text-default: var(--color-gray-900);
  --color-text-disabled: var(--color-gray-400);
  --color-text-inverse: var(--color-gray-0);
  --color-text-link: var(--color-teal-700);
  --color-text-link-visited: var(--color-blue-900);
  --color-text-muted: var(--color-gray-600);
  --color-text-subtle: var(--color-gray-500);
}

}
/* ---- css/base.css ---- */
/* base.css — reset + global accessibility baseline. Loaded after dist/tokens.css.
   Cascade layers (order declared at the top of dist/ds.css): reset, tokens, base, components, patterns, utilities.
   Component CSS goes in `@layer components { … }`, pattern CSS in `@layer patterns { … }` — so specificity
   never decides between layers and component CSS never needs !important. App CSS that isn't layered
   overrides the whole system, which is what consuming apps expect.
   The few !important declarations below are accessibility guarantees (hidden, sr-only, reduced motion)
   that must win even over unlayered app CSS. */

/* Shared fallbacks for anchor-positioned surfaces (menus, popovers, tooltips, toggletips).
   Usage: position-try-fallbacks: --flip-block, --flip-inline; */
@position-try --flip-block { position-area: block-start; }
@position-try --flip-inline { position-area: inline-start; }

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; hanging-punctuation: first last; }
  img, picture, video, canvas, svg { display: block; max-width: 100%; }
  input, button, textarea, select { font: inherit; color: inherit; }
  p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
}

@layer base {
  html { interpolate-size: allow-keywords; scroll-padding-block-start: var(--size-sticky-offset, 0px); }
  body {
    min-height: 100dvh;
    background: var(--color-bg-canvas);
    color: var(--color-text-default);
    font-family: var(--typography-body-font-family);
    font-size: var(--typography-body-font-size);
    line-height: var(--typography-body-line-height);
    -webkit-font-smoothing: antialiased;
  }
  h1, h2, h3, h4, h5, h6 { text-wrap: balance; }
  p { text-wrap: pretty; }

  /* One focus treatment for the whole system. Components may refine, never remove. */
  :focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Windows High Contrast / forced colors: keep boundaries visible. */
  @media (forced-colors: active) {
    :focus-visible { outline-color: Highlight; }
  }
}

@layer utilities {
  [hidden] { display: none !important; }

  /* Visually hidden but available to assistive tech. */
  .sr-only {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip-path: inset(50%) !important;
    white-space: nowrap !important;
    border: 0 !important;
  }
  .sr-only--focusable:focus-visible,
  .sr-only--focusable:active {
    position: static !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
    overflow: visible !important;
    clip-path: none !important;
    white-space: normal !important;
  }

  @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;
    }
  }

  /* Explicit reduced-motion switch (docs toggle, Storybook global, user setting). Mirrors the media query. */
  [data-reduced-motion], [data-reduced-motion] *, [data-reduced-motion] *::before, [data-reduced-motion] *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Print: light, ink-friendly, no interactive chrome, URLs visible. */
  @media print {
    :root { color-scheme: light; --color-bg-canvas: #fff; --color-bg-surface: #fff; --color-text-default: #000; }
    nav, dialog, [popover], .ds-no-print, [data-print="hide"] { display: none !important; }
    a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; }
    article, figure, table, pre, blockquote, .card { break-inside: avoid; }
    h1, h2, h3 { break-after: avoid; }
  }
}

/* ---- css/components/accordion.css ---- */
/* accordion.css — Accordion and Disclosure, both native <details>/<summary>. No JavaScript.
   Accordion: <div class="accordion"> of <details class="accordion__item" name="<group>"> (shared name = only one open;
              omit name = several may be open)
     Parts:   .accordion__summary (summary), .accordion__title, .accordion__meta (trailing text, e.g. a count),
              .accordion__icon (chevron svg, aria-hidden), .accordion__panel (content)
   Disclosure: <details class="disclosure"> with .disclosure__summary + .disclosure__panel — one show/hide, lighter look.
   States:    [open] (real), :hover / :focus-visible on the summary (docs freeze: .is-hover, .is-focus-visible)
   Motion:    chevron rotates; panel height animates with ::details-content where supported, instant elsewhere. */
@layer components {
  .accordion {
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: var(--color-bg-surface);
  }
  .accordion__item + .accordion__item { border-block-start: var(--border-width-thin) solid var(--color-border-default); }

  .accordion__summary,
  .disclosure__summary {
    --_bg: transparent;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    list-style: none;
    cursor: pointer;
    background: var(--_bg);
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .accordion__summary::-webkit-details-marker,
  .disclosure__summary::-webkit-details-marker { display: none; }

  .accordion__summary {
    min-block-size: var(--size-touch-target);
    padding-block: var(--space-3);
    padding-inline: var(--space-4);
    font-weight: var(--font-weight-semibold);
  }
  .accordion__item:first-child > .accordion__summary { border-start-start-radius: inherit; border-start-end-radius: inherit; }
  .accordion__title { flex: 1; min-inline-size: 0; }
  .accordion__meta {
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-regular);
    font-variant-numeric: tabular-nums;
  }
  .accordion__icon,
  .disclosure__icon {
    flex-shrink: 0;
    inline-size: var(--icon-size-md);
    block-size: var(--icon-size-md);
    stroke-width: var(--icon-stroke);
    transition: transform var(--motion-duration-base) var(--motion-easing-standard);
  }
  [open] > .accordion__summary .accordion__icon { transform: rotate(180deg); }

  .accordion__panel {
    padding-block: 0 var(--space-4);
    padding-inline: var(--space-4);
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
  }

  /* Disclosure: inline trigger that reads like a link-weight control. */
  .disclosure__summary {
    display: inline-flex;
    min-block-size: var(--size-control-sm);
    padding-inline: var(--space-1);
    border-radius: var(--radius-sm);
    color: var(--color-text-link);
    font-weight: var(--font-weight-medium);
  }
  .disclosure__icon { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); }
  .disclosure__icon:dir(rtl) { transform: scaleX(-1); }
  [open] > .disclosure__summary .disclosure__icon { transform: rotate(90deg); }
  .disclosure__panel { padding-block-start: var(--space-2); padding-inline-start: var(--space-6); font-size: var(--font-size-sm); }

  /* States */
  .accordion__summary:hover, .accordion__summary.is-hover,
  .disclosure__summary:hover, .disclosure__summary.is-hover { --_bg: var(--color-action-ghost-bg-hover); }

  .accordion__summary:focus-visible, .accordion__summary.is-focus-visible,
  .disclosure__summary:focus-visible, .disclosure__summary.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: calc(var(--focus-ring-width) * -1);
  }
  .disclosure__summary:focus-visible, .disclosure__summary.is-focus-visible { outline-offset: var(--focus-ring-offset); }

  /* Height animation where ::details-content exists (needs interpolate-size from base.css). */
  @supports selector(::details-content) {
    .accordion__item::details-content,
    .disclosure::details-content {
      block-size: 0;
      overflow: clip;
      transition:
        block-size var(--motion-duration-base) var(--motion-easing-standard),
        content-visibility var(--motion-duration-base) var(--motion-easing-standard) allow-discrete;
    }
    .accordion__item[open]::details-content,
    .disclosure[open]::details-content { block-size: auto; }
  }

  @media (forced-colors: active) {
    .accordion { border-color: CanvasText; }
    .accordion__summary:focus-visible, .disclosure__summary:focus-visible { outline-color: Highlight; }
    .disclosure__summary { color: LinkText; }
  }
}

/* ---- css/components/action-sheet.css ---- */
/* action-sheet.css — Bottom-anchored list of actions for one item. Block alias: .action-sheet
   Markup:   <dialog class="action-sheet" aria-labelledby="t" closedby="any"> opened by an invoker
             <button commandfor="id" command="show-modal">; every item closes it with command="close". No JS.
               .action-sheet__header (optional): .action-sheet__title + .action-sheet__message
               .action-sheet__item (+ --danger) buttons, then <hr class="action-sheet__separator"> and .action-sheet__cancel
   Layout:   anchored to the bottom edge below 40rem (full width, above the home indicator), centered card above.
             One surface with start-aligned rows, the same shape as the native DsActionList, so snapshots compare.
   States:   real ones via [open] / :modal. Docs-only freeze: .is-preview (renders an open sheet in the page flow).
   Motion:   slides up on enter (base, enter easing), down on exit (fast, exit easing); base.css neutralizes it
             under reduced motion. */
@layer components {
  .action-sheet {
    inline-size: min(calc(var(--size-container-sm) * 0.75), 100% - 2 * var(--space-2));
    max-inline-size: none;
    margin: auto auto var(--space-2);
    padding: 0;
    padding-block: var(--space-2);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--overlay-radius);
    background: var(--color-elevation-surface-overlay);
    color: var(--color-text-default);
    box-shadow: var(--overlay-shadow);
    flex-direction: column;
    translate: 0 100%;
    transition:
      translate var(--motion-duration-fast) var(--motion-easing-exit),
      overlay var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete,
      display var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete;
  }
  .action-sheet[open] {
    display: flex;
    translate: 0 0;
    transition-duration: var(--motion-duration-base);
    transition-timing-function: var(--motion-easing-enter);
  }
  @starting-style {
    .action-sheet[open] { translate: 0 100%; }
  }
  .action-sheet::backdrop { background: var(--color-bg-overlay); }
  @media (width < 40rem) {
    .action-sheet {
      inline-size: 100%;
      margin: auto 0 0;
      padding-block-end: max(var(--space-2), env(safe-area-inset-bottom));
      border-end-start-radius: 0;
      border-end-end-radius: 0;
    }
  }
  @media (width >= 40rem) {
    .action-sheet { margin: auto; translate: 0 var(--space-2); }
    @starting-style {
      .action-sheet[open] { translate: 0 var(--space-2); }
    }
  }

  .action-sheet__header {
    display: grid;
    gap: var(--space-1);
    padding-block: var(--space-2);
    padding-inline: var(--space-4);
  }
  .action-sheet__title,
  .action-sheet__message {
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--typography-small-font-size);
  }
  .action-sheet__title { font-weight: var(--font-weight-semibold); }

  .action-sheet__item {
    display: flex;
    align-items: center;
    min-block-size: var(--size-touch-target);
    padding-inline: var(--space-4);
    border: 0;
    background: transparent;
    color: var(--color-text-default);
    font: inherit;
    font-size: var(--typography-body-font-size);
    text-align: start;
    cursor: pointer;
  }
  .action-sheet__item:hover { background: var(--color-action-ghost-bg-hover); }
  .action-sheet__item:focus-visible { outline-offset: calc(-1 * var(--focus-ring-width)); }
  .action-sheet__item--danger { color: var(--color-feedback-danger-fg); }
  .action-sheet__separator {
    margin-block: var(--space-1);
    border: 0;
    border-block-start: var(--border-width-thin) solid var(--color-border-subtle);
  }

  /* Docs-only: show an open sheet inside a demo card instead of the top layer. */
  .action-sheet.is-preview {
    position: static;
    inset: auto;
    margin: 0;
    inline-size: 100%;
    max-inline-size: calc(var(--size-container-sm) * 0.75);
    display: flex;
    translate: none;
    transition: none;
  }

  @media (forced-colors: active) {
    .action-sheet { border: var(--border-width-thin) solid CanvasText; }
    .action-sheet::backdrop { background: Canvas; opacity: 0.8; }
    .action-sheet__item:focus-visible { outline-color: Highlight; }
  }
}

/* ---- css/components/alert.css ---- */
/* alert.css — Inline alert (contextual message block). Block alias: .alert
   Tones:    .alert--info (default) | .alert--success | .alert--warning | .alert--danger
   Parts:    .alert__icon (svg, aria-hidden), .alert__content, .alert__title, .alert__description,
             .alert__actions, .alert__dismiss (icon button with aria-label; behavior in js/alert.js)
   Roles:    none for alerts present at page load; role="status" when inserted (info/success),
             role="alert" when inserted and urgent (danger). Tone is icon + title, never color alone.
   Pattern:  tones only set private custom properties (--_bg, --_fg, --_border, --_icon). */
@layer components {
  .alert {
    --_bg: var(--color-feedback-info-bg);
    --_fg: var(--color-feedback-info-fg);
    --_border: var(--color-feedback-info-border);
    --_icon: var(--color-feedback-info-icon);

    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding-block: var(--space-3);
    padding-inline: var(--space-4);
    border: var(--border-width-thin) solid var(--_border);
    border-inline-start-width: var(--space-1);
    border-radius: var(--radius-md);
    background: var(--_bg);
    color: var(--_fg);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-normal);
  }
  .alert--success {
    --_bg: var(--color-feedback-success-bg);
    --_fg: var(--color-feedback-success-fg);
    --_border: var(--color-feedback-success-border);
    --_icon: var(--color-feedback-success-icon);
  }
  .alert--warning {
    --_bg: var(--color-feedback-warning-bg);
    --_fg: var(--color-feedback-warning-fg);
    --_border: var(--color-feedback-warning-border);
    --_icon: var(--color-feedback-warning-icon);
  }
  .alert--danger {
    --_bg: var(--color-feedback-danger-bg);
    --_fg: var(--color-feedback-danger-fg);
    --_border: var(--color-feedback-danger-border);
    --_icon: var(--color-feedback-danger-icon);
  }

  .alert__icon {
    flex-shrink: 0;
    inline-size: var(--icon-size-md);
    block-size: var(--icon-size-md);
    margin-block-start: var(--space-px);
    color: var(--_icon);
    stroke-width: var(--icon-stroke);
  }
  .alert__content { flex: 1; min-inline-size: 0; display: grid; gap: var(--space-1); }
  .alert :is(a, .link) { color: inherit; }   /* link color fails on tinted feedback fills (dark/HC) */
  .alert__title { font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); line-height: var(--font-line-height-snug); }
  .alert__description { margin: 0; }
  .alert__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-block-start: var(--space-2); }
  .alert__dismiss {
    flex-shrink: 0;
    margin-block: calc(-1 * var(--space-1));
    margin-inline-end: calc(-1 * var(--space-2));
    --_fg: var(--_icon);
  }
  .alert .btn--ghost { --_fg: currentColor; }

  @media (forced-colors: active) {
    .alert { border-color: CanvasText; }
    .alert__icon { color: CanvasText; }
  }
}

/* ---- css/components/avatar.css ---- */
/* avatar.css — Avatar. Block alias: .avatar
   Content (pick one): img.avatar__img (alt = name, or alt="" when the name is printed beside it)
                       → span.avatar__initials → svg.avatar__icon (generic person, aria-hidden)
   Sizes:  .avatar--sm (32px) | md default (40px) | .avatar--lg (48px) → --size-control-*, so avatars line up with
           buttons and inputs in the same row.
   Tones (initials): .avatar--tone-neutral (default) | --tone-teal | --tone-blue — pick by a stable hash of the
           person's id (id % 3) so a mechanic keeps the same color everywhere. Pairs are contrast-checked tokens.
   Status: .avatar__status[data-status="available|busy|away|off"] — a dot with a distinct shape per status
           (filled / bar / ring), plus visible or .sr-only text. Never color alone.
   Pattern: private props --_size, --_bg, --_fg. */
@layer components {
  .avatar {
    --_size: var(--size-control-md);
    --_bg: var(--color-bg-subtle);
    --_fg: var(--color-text-default);
    --_border: var(--color-border-default);

    position: relative;
    display: inline-grid;
    place-items: center;
    flex-shrink: 0;
    inline-size: var(--_size);
    block-size: var(--_size);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--radius-full);
    background: var(--_bg);
    color: var(--_fg);
    font-size: calc(var(--_size) * 0.4);
    font-weight: var(--font-weight-semibold);
    line-height: 1;
    user-select: none;
  }

  .avatar--sm { --_size: var(--size-control-sm); }
  .avatar--lg { --_size: var(--size-control-lg); }

  .avatar--tone-neutral { --_bg: var(--color-bg-subtle); --_fg: var(--color-text-default); }
  .avatar--tone-teal { --_bg: var(--color-selected-bg); --_fg: var(--color-selected-fg); --_border: var(--color-selected-bg); }
  .avatar--tone-blue { --_bg: var(--color-feedback-info-bg); --_fg: var(--color-feedback-info-fg); --_border: var(--color-feedback-info-border); }

  /* Parts */
  .avatar__img {
    inline-size: 100%;
    block-size: 100%;
    border-radius: inherit;
    object-fit: cover;
  }
  .avatar__initials { letter-spacing: var(--font-tracking-wide); text-transform: uppercase; }
  .avatar__icon {
    inline-size: 60%;
    block-size: 60%;
    stroke-width: var(--icon-stroke);
    color: var(--color-text-muted);
  }

  .avatar__status {
    --_dot: var(--color-feedback-success-icon);
    position: absolute;
    inset-block-end: calc(var(--border-width-thick) * -1);
    inset-inline-end: calc(var(--border-width-thick) * -1);
    display: grid;
    place-items: center;
    inline-size: max(var(--space-3), calc(var(--_size) * 0.3));
    block-size: max(var(--space-3), calc(var(--_size) * 0.3));
    border-radius: var(--radius-full);
    background: var(--_dot);
    box-shadow: 0 0 0 var(--border-width-thick) var(--color-bg-surface);
  }
  /* Shape carries meaning too: busy = bar, away = ring, off = hollow grey ring. */
  .avatar__status[data-status="busy"] { --_dot: var(--color-feedback-danger-icon); }
  .avatar__status[data-status="busy"]::after {
    content: "";
    inline-size: 60%;
    block-size: var(--border-width-thick);
    border-radius: var(--radius-full);
    background: var(--color-bg-surface);
  }
  .avatar__status[data-status="away"] { --_dot: var(--color-feedback-warning-icon); }
  .avatar__status[data-status="away"]::after {
    content: "";
    inline-size: 40%;
    block-size: 40%;
    border-radius: var(--radius-full);
    background: var(--color-bg-surface);
  }
  .avatar__status[data-status="off"] {
    --_dot: var(--color-bg-surface);
    border: var(--border-width-thick) solid var(--color-border-strong);
  }

  /* Avatar + name row (name printed beside the avatar → img alt=""). */
  .avatar-label {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    min-inline-size: 0;
  }
  .avatar-label__text { display: grid; min-inline-size: 0; line-height: var(--font-line-height-snug); }
  .avatar-label__name { font-weight: var(--font-weight-semibold); }
  .avatar-label__detail { color: var(--color-text-muted); font-size: var(--font-size-sm); }

  @media (forced-colors: active) {
    .avatar { border-color: CanvasText; }
    .avatar__status { background: CanvasText; forced-color-adjust: none; }
  }
}

/* ---- css/components/badge.css ---- */
/* badge.css — Badge (status or count pill). Block alias: .badge. Not interactive.
   Tones:    .badge--neutral (default) | --info | --success | --warning | --danger
             → color.feedback.{tone}.fg on color.feedback.{tone}.bg (contrast-checked pairs, 4.5:1 in every theme)
   Variants: .badge--count (solid inverse pill, tabular numerals, cap at "99+")
             .badge--dot (8px dot, decorative; the parent must carry the text, e.g. "Work orders, new updates")
   Parts:    .badge__icon (shape per tone, aria-hidden) — tone is never shown by color alone; the label says it.
             .badge__dot (status dot inside a labelled badge: "● In service")
   Pattern:  tones set private props --_bg, --_fg, --_border, --_dot. */
@layer components {
  .badge {
    --_bg: var(--color-bg-subtle);
    --_fg: var(--color-text-default);
    --_border: var(--color-border-default);
    --_dot: var(--color-text-muted);

    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-block-size: var(--space-6);
    max-inline-size: 100%;
    padding-block: 0;
    padding-inline: var(--space-2);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--radius-full);
    background: var(--_bg);
    color: var(--_fg);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    line-height: var(--font-line-height-tight);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    vertical-align: middle;
  }

  .badge--neutral { --_bg: var(--color-bg-subtle); --_fg: var(--color-text-default); --_border: var(--color-border-default); }
  .badge--info    { --_bg: var(--color-feedback-info-bg);    --_fg: var(--color-feedback-info-fg);    --_border: var(--color-feedback-info-border);    --_dot: var(--color-feedback-info-icon); }
  .badge--success { --_bg: var(--color-feedback-success-bg); --_fg: var(--color-feedback-success-fg); --_border: var(--color-feedback-success-border); --_dot: var(--color-feedback-success-icon); }
  .badge--warning { --_bg: var(--color-feedback-warning-bg); --_fg: var(--color-feedback-warning-fg); --_border: var(--color-feedback-warning-border); --_dot: var(--color-feedback-warning-icon); }
  .badge--danger  { --_bg: var(--color-feedback-danger-bg);  --_fg: var(--color-feedback-danger-fg);  --_border: var(--color-feedback-danger-border);  --_dot: var(--color-feedback-danger-icon); }

  .badge__icon {
    flex-shrink: 0;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
    margin-inline-start: calc(var(--space-0-5) * -1);
  }
  .badge__dot {
    flex-shrink: 0;
    inline-size: var(--space-2);
    block-size: var(--space-2);
    border-radius: var(--radius-full);
    background: var(--_dot);
  }

  /* Count: solid, compact, numbers line up. */
  .badge--count {
    --_bg: var(--color-bg-inverse);
    --_fg: var(--color-text-inverse);
    --_border: transparent;
    justify-content: center;
    min-inline-size: var(--space-6);
    padding-inline: var(--space-1-5);
  }

  /* Dot: no text inside; attach to something that has the text. */
  .badge--dot {
    --_bg: var(--color-feedback-danger-icon);
    --_border: var(--color-bg-surface);
    inline-size: var(--space-2);
    block-size: var(--space-2);
    min-block-size: 0;
    padding: 0;
  }

  /* Anchor a count or dot to the corner of an icon/button: wrap both in .badge-anchor. */
  .badge-anchor { position: relative; display: inline-flex; }
  .badge-anchor > .badge {
    position: absolute;
    inset-block-start: calc(var(--space-1) * -1);
    inset-inline-end: calc(var(--space-1) * -1);
    box-shadow: 0 0 0 var(--border-width-thick) var(--color-bg-surface);
    pointer-events: none;
  }

  @media (forced-colors: active) {
    .badge { border-color: CanvasText; }
    .badge__dot, .badge--dot { background: CanvasText; forced-color-adjust: none; }
  }
}

/* ---- css/components/box.css ---- */
/* box.css — token-driven container. The escape hatch that keeps ad-hoc CSS out of apps.
   Block: .box
   Modifiers (token steps only):
     padding  .box--pad-2 | --pad-3 | --pad-4 | --pad-6 | --pad-8
     surface  .box--surface | --surface-subtle | --surface-sunken | --surface-raised
     border   .box--bordered
     radius   .box--radius-md | --radius-lg   (md = 8px, the Fleetline shape) */
@layer components {
  .box {
    display: block;
    min-inline-size: 0;
    padding: var(--box-padding, 0);
    border-radius: var(--box-radius, 0);
  }
  .box--pad-2 { --box-padding: var(--space-2); }
  .box--pad-3 { --box-padding: var(--space-3); }
  .box--pad-4 { --box-padding: var(--space-4); }
  .box--pad-6 { --box-padding: var(--space-6); }
  .box--pad-8 { --box-padding: var(--space-8); }

  .box--surface { background: var(--color-bg-surface); }
  .box--surface-subtle { background: var(--color-bg-subtle); }
  .box--surface-sunken { background: var(--color-elevation-surface-sunken); }
  .box--surface-raised { background: var(--color-elevation-surface-raised); box-shadow: var(--elevation-raised); }

  .box--bordered { border: var(--border-width-thin) solid var(--color-border-default); }

  .box--radius-md { --box-radius: var(--radius-md); }
  .box--radius-lg { --box-radius: var(--radius-lg); }

  /* Surfaces distinguished by fill alone need a boundary in forced colors. */
  @media (forced-colors: active) {
    :is(.box--surface-subtle, .box--surface-sunken, .box--surface-raised) {
      border: var(--border-width-thin) solid CanvasText;
    }
  }
}

/* ---- css/components/breadcrumbs.css ---- */
/* breadcrumbs.css — Hierarchy trail. Block: .breadcrumbs (<nav aria-label="Breadcrumb">, container: breadcrumbs)
   Parts:   .breadcrumbs__list (<ol>), .breadcrumbs__item (<li>; separator "/" drawn by CSS with empty alt text,
            so it is never read), .breadcrumbs__link (a), .breadcrumbs__current (<span aria-current="page">, not a link),
            .breadcrumbs__more (button "…" for collapsed middle levels; commandfor + command="toggle-popover"),
            .breadcrumbs__overflow (<ul popover> of the hidden levels — disclosure navigation, plain links)
   Narrow (container < 30rem): only the parent level shows, as "← Parent".
   States:  link :hover :focus-visible; docs-only .is-hover, .is-focus-visible. */
@layer components {
  .breadcrumbs { container: breadcrumbs / inline-size; font-size: var(--font-size-sm); }

  .breadcrumbs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .breadcrumbs__item { display: inline-flex; align-items: center; gap: var(--space-1); min-inline-size: 0; }
  .breadcrumbs__item + .breadcrumbs__item::before {
    content: "/" / "";
    color: var(--color-text-subtle);
  }

  .breadcrumbs__link {
    display: inline-flex;
    align-items: center;
    min-block-size: var(--space-6);
    padding-inline: var(--space-1);
    border-radius: var(--radius-sm);
    color: var(--color-text-link);
    text-decoration: underline;
    text-decoration-thickness: var(--border-width-thin);
    text-underline-offset: 0.2em;
  }
  .breadcrumbs__link:hover,
  .breadcrumbs__link.is-hover { text-decoration-thickness: var(--border-width-thick); }
  .breadcrumbs__link:focus-visible,
  .breadcrumbs__link.is-focus-visible,
  .breadcrumbs__more:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
  .breadcrumbs__current {
    padding-inline: var(--space-1);
    color: var(--color-text-default);
    font-weight: var(--font-weight-semibold);
    overflow-wrap: anywhere;
  }

  .breadcrumbs__more {
    display: inline-grid;
    place-items: center;
    min-inline-size: var(--space-6);
    min-block-size: var(--space-6);
    padding-inline: var(--space-1);
    border: var(--border-width-thin) solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text-muted);
    font: inherit;
    cursor: pointer;
  }
  .breadcrumbs__more:hover,
  .breadcrumbs__more[aria-expanded="true"] { background: var(--color-action-ghost-bg-hover); color: var(--color-text-default); }

  .breadcrumbs__overflow {
    inset: auto;
    margin: var(--space-1);
    position-area: block-end span-inline-end;
    position-try-fallbacks: --flip-block, --flip-inline;
    min-inline-size: 12rem;
    padding: var(--space-1);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--overlay-radius);
    background: var(--color-elevation-surface-overlay);
    box-shadow: var(--overlay-shadow);
    list-style: none;
  }
  .breadcrumbs__overflow .breadcrumbs__link { display: flex; min-block-size: var(--size-control-md); padding-inline: var(--space-2); }

  @container breadcrumbs (max-width: 30rem) {
    .breadcrumbs__item:not(:nth-last-child(2)) { display: none; }
    .breadcrumbs__item:nth-last-child(2)::before { content: "←" / ""; color: var(--color-text-muted); }
    .breadcrumbs__item:nth-last-child(2):dir(rtl)::before { content: "→" / ""; }
  }

  @media (forced-colors: active) {
    .breadcrumbs__more { border-color: ButtonText; }
    .breadcrumbs__overflow { border-color: CanvasText; }
  }
}

/* ---- css/components/button.css ---- */
/* button.css — Button. Block alias: .btn
   Variants: .btn--primary | --secondary (default look) | --ghost (tertiary) | --destructive
   Sizes:    .btn--sm | (md default) | .btn--lg   → heights = --button-height-* = --size-control-*
   Layout:   .btn--full-width
   Parts:    .btn__label, .btn__icon (svg, aria-hidden), .btn__spinner (aria-hidden)
   States:   real ones via attributes — :hover :focus-visible :active, disabled, aria-disabled="true",
             aria-busy="true" (loading). Docs-only freeze classes share the same selectors:
             .is-hover, .is-focus-visible, .is-active.
   Pattern:  variants only set private custom properties (--_bg, --_fg, …); state rules swap them.
             Other interactive components (icon-button, toggle, menu item) should copy this pattern. */
@layer components {
  .btn {
    --_h: var(--button-height-md);
    --_px: var(--density-comfortable-control-padding-x);
    --_font-size: var(--font-size-sm);
    --_icon: var(--icon-size-sm);
    --_bg: var(--color-action-secondary-bg);
    --_bg-hover: var(--color-action-secondary-bg-hover);
    --_bg-active: var(--color-action-secondary-bg-active);
    --_fg: var(--color-action-secondary-fg);
    --_border: var(--color-action-secondary-border);

    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-block-size: var(--_h);
    min-inline-size: var(--_h);
    padding-block: 0;
    padding-inline: var(--_px);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--button-radius);
    background: var(--_bg);
    color: var(--_fg);
    font-family: inherit;
    font-size: var(--_font-size);
    font-weight: var(--button-font-weight);
    line-height: var(--font-line-height-tight);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition:
      background-color var(--motion-duration-fast) var(--motion-easing-standard),
      border-color var(--motion-duration-fast) var(--motion-easing-standard),
      color var(--motion-duration-fast) var(--motion-easing-standard);
  }

  /* Variants */
  .btn--primary {
    --_bg: var(--color-action-primary-bg);
    --_bg-hover: var(--color-action-primary-bg-hover);
    --_bg-active: var(--color-action-primary-bg-active);
    --_fg: var(--color-action-primary-fg);
    --_border: transparent;
  }
  .btn--secondary { /* explicit alias of the default look */
    --_bg: var(--color-action-secondary-bg);
    --_border: var(--color-action-secondary-border);
  }
  .btn--ghost {
    --_bg: var(--color-action-ghost-bg);
    --_bg-hover: var(--color-action-ghost-bg-hover);
    --_bg-active: var(--color-action-ghost-bg-active);
    --_fg: var(--color-action-ghost-fg);
    --_border: transparent;
  }
  .btn--destructive {
    --_bg: var(--color-action-danger-bg);
    --_bg-hover: var(--color-action-danger-bg-hover);
    --_bg-active: var(--color-action-danger-bg-active);
    --_fg: var(--color-action-danger-fg);
    --_border: transparent;
  }

  /* Sizes — sm/md/lg line up with .input--sm/md/lg in the same row. */
  .btn--sm { --_h: var(--button-height-sm); --_px: var(--space-3); --_font-size: var(--font-size-sm); }
  .btn--lg { --_h: var(--button-height-lg); --_px: var(--space-5); --_font-size: var(--font-size-md); --_icon: var(--icon-size-md); }
  [data-density="compact"] .btn:not(.btn--lg) { --_px: var(--density-compact-control-padding-x); }

  .btn--full-width { display: flex; inline-size: 100%; }

  /* Parts */
  .btn__icon {
    flex-shrink: 0;
    inline-size: var(--_icon);
    block-size: var(--_icon);
    stroke-width: var(--icon-stroke);
  }
  .btn__label { overflow: hidden; text-overflow: ellipsis; }

  /* States — the .is-* classes exist only so docs can freeze a state. */
  .btn:hover:not(:disabled, [aria-disabled="true"], [aria-busy="true"]),
  .btn.is-hover { background: var(--_bg-hover); }

  .btn:active:not(:disabled, [aria-disabled="true"], [aria-busy="true"]),
  .btn.is-active { background: var(--_bg-active); }

  .btn:focus-visible,
  .btn.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* disabled = not focusable; aria-disabled="true" = stays focusable so a tooltip can explain why. */
  .btn:disabled,
  .btn[aria-disabled="true"]:not([aria-busy="true"]) {
    --_bg: var(--color-bg-muted);
    --_fg: var(--color-text-disabled);
    --_border: transparent;
    cursor: not-allowed;
  }
  .btn--ghost:disabled,
  .btn--ghost[aria-disabled="true"]:not([aria-busy="true"]) { --_bg: transparent; }

  /* Loading: width stays stable, label stays in the accessibility tree (opacity, not visibility). */
  .btn[aria-busy="true"] { cursor: progress; pointer-events: none; }
  .btn[aria-busy="true"] > :not(.btn__spinner) { opacity: 0; }
  .btn__spinner { display: none; }
  .btn[aria-busy="true"] > .btn__spinner {
    display: block;
    position: absolute;
    inset: 0;
    margin: auto;
    inline-size: var(--_icon);
    block-size: var(--_icon);
    border: var(--border-width-thick) solid currentColor;
    border-inline-end-color: transparent;
    border-radius: var(--radius-full);
    animation: btn-spin calc(var(--motion-duration-slower) * 1.6) linear infinite;
  }

  @media (forced-colors: active) {
    .btn { border-color: ButtonText; }
    .btn:disabled, .btn[aria-disabled="true"] { color: GrayText; border-color: GrayText; }
  }
}

@keyframes btn-spin { to { transform: rotate(1turn); } }

/* ---- css/components/card.css ---- */
/* card.css — Card. Block alias: .card
   Variants: .card--interactive (one stretched primary link: .card__link) | .card--selectable (checkbox in .card__select)
             media cards are any card with a .card__media first child
   Parts:    .card__media, .card__header, .card__title, .card__meta, .card__body, .card__footer, .card__actions,
             .card__link (primary link; its ::after covers the card), .card__select (label + checkbox)
   States:   :hover on .card--interactive (docs freeze: .is-hover), focus on .card__link (docs freeze: .is-focus-visible),
             selected = :has(.card__select :checked) (no class needed)
   Layout:   container-type inline-size → footer stacks under 20rem. Equal heights in grids: block-size 100%.
   Pattern:  private props --_pad, --_border, --_shadow; states swap them. */
@layer components {
  .card {
    --_pad: var(--card-padding);
    --_border: var(--color-border-default);
    --_shadow: var(--card-shadow);

    position: relative;
    container-type: inline-size;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    block-size: 100%;
    padding: var(--_pad);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--card-radius);
    background: var(--color-elevation-surface-raised);
    box-shadow: var(--_shadow);
    color: var(--color-text-default);
    transition:
      box-shadow var(--motion-duration-fast) var(--motion-easing-standard),
      border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  [data-density="compact"] .card { --_pad: var(--space-4); }

  /* Parts */
  .card__media {
    display: grid;
    place-items: center;
    aspect-ratio: 16 / 9;
    margin-inline: calc(var(--_pad) * -1);
    margin-block-start: calc(var(--_pad) * -1);
    border-start-start-radius: inherit;
    border-start-end-radius: inherit;
    background: var(--color-elevation-surface-sunken);
    color: var(--color-text-muted);
    overflow: hidden;
  }
  .card__media > img, .card__media > svg:only-child:not(.icon) { inline-size: 100%; block-size: 100%; object-fit: cover; }

  .card__header { display: grid; gap: var(--space-1); }
  .card__title {
    font-family: var(--typography-h5-font-family);
    font-size: var(--typography-h5-font-size);
    font-weight: var(--typography-h5-font-weight);
    line-height: var(--typography-h5-line-height);
  }
  .card__meta {
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-variant-numeric: tabular-nums;
  }
  .card__body { color: var(--color-text-default); font-size: var(--font-size-sm); }
  .card__footer,
  .card__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
    margin-block-start: auto; /* pins actions to the bottom so cards in a row line up */
  }
  .card__footer { justify-content: space-between; }

  /* Interactive: one real link, stretched over the card. Secondary controls sit above it. */
  .card__link { color: inherit; text-decoration: none; }
  .card__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
  .card__link:hover { text-decoration: underline; }
  .card__actions,
  .card--interactive .card__footer :is(a, button, input) { position: relative; z-index: var(--z-raised); }

  .card--interactive:hover,
  .card--interactive.is-hover {
    --_border: var(--color-border-strong);
    --_shadow: var(--elevation-raised);
  }
  .card__link:focus-visible,
  .card__link.is-focus-visible { outline: var(--focus-ring-width) solid transparent; } /* ring moves to the card below */
  .card--interactive:has(.card__link:focus-visible),
  .card--interactive:has(.card__link.is-focus-visible) {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Selectable: a real checkbox labelled by the card title. */
  .card__select {
    position: relative;
    z-index: var(--z-raised);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-block-size: var(--size-control-sm);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
  }
  .card__select input {
    inline-size: var(--icon-size-md);
    block-size: var(--icon-size-md);
    accent-color: var(--color-action-primary-bg);
    cursor: pointer;
  }
  .card--selectable { cursor: default; }
  .card--selectable:has(.card__select :checked) {
    --_border: var(--color-selected-border);
    box-shadow: inset 0 0 0 var(--border-width-thin) var(--color-selected-border), var(--_shadow);
  }

  @container (inline-size < 20rem) {
    .card__footer { flex-direction: column; align-items: stretch; }
  }

  @media (forced-colors: active) {
    .card { border-color: CanvasText; }
    .card--selectable:has(.card__select :checked) { border-color: Highlight; border-width: var(--border-width-thick); }
    .card--interactive:has(.card__link:focus-visible) { outline-color: Highlight; }
  }
}

/* ---- css/components/checkbox.css ---- */
/* checkbox.css — Checkbox and checkbox group. Block alias: .checkbox
   Item:      <div class="checkbox">
                <input class="checkbox__input" type="checkbox" id="…" [aria-describedby="…-hint"]>
                <label class="checkbox__label" for="…">…</label>
                <p class="checkbox__hint" id="…-hint">…</p>        (optional)
              </div>
   Group:     <fieldset class="fieldset checkbox-group" aria-describedby="…hint …error">
                <legend class="fieldset__legend">…</legend> [.field__hint] [.field__error]
                <div class="checkbox-group__items"> .checkbox × n </div>
              </fieldset>
   Modifiers: .checkbox-group--horizontal (items in a wrapping row), .checkbox--sm (20px box, dense tables)
   States:    :checked, :indeterminate (set .indeterminate in JS — js/checkbox.js), :disabled,
              aria-invalid="true" | :user-invalid (single checkbox), group error = a .field__error inside
              the group (left rule + red boxes). Docs-only freeze classes: .is-hover, .is-focus-visible.
   Pattern:   the native input is restyled with appearance:none; the mark is a masked ::before so it
              follows --_mark (a token), and the label's for= makes the whole text a hit target. */
@layer components {
  .checkbox {
    --_size: var(--icon-size-lg);
    --_bg: var(--input-bg);
    --_border: var(--input-border);
    --_mark: transparent;

    display: grid;
    grid-template-columns: var(--_size) minmax(0, 1fr);
    column-gap: var(--space-3);
    row-gap: var(--space-1);
    align-items: start;
    min-inline-size: 0;
  }
  .checkbox--sm { --_size: var(--icon-size-md); column-gap: var(--space-2); }

  .checkbox__input {
    appearance: none;
    display: grid;
    place-content: center;
    inline-size: var(--_size);
    block-size: var(--_size);
    margin: 0;
    border: var(--border-width-thick) solid var(--_border);
    border-radius: var(--radius-sm);
    background: var(--_bg);
    color: var(--_mark);
    cursor: pointer;
    transition:
      background-color var(--motion-duration-fast) var(--motion-easing-standard),
      border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .checkbox__input::before {
    content: "";
    inline-size: calc(var(--_size) - var(--space-1));
    block-size: calc(var(--_size) - var(--space-1));
    background: currentColor;
    -webkit-mask: var(--_glyph) center / contain no-repeat;
    mask: var(--_glyph) center / contain no-repeat;
    --_glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 8.5l3 3 6-7' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  }
  .checkbox__input:indeterminate::before {
    --_glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 8h8' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round'/%3E%3C/svg%3E");
  }

  .checkbox__label {
    /* Line box centred on the box: (box - line height) / 2 */
    padding-block-start: calc((var(--_size) - 1lh) / 2);
    color: var(--color-text-default);
    font-size: var(--font-size-md);
    line-height: var(--font-line-height-snug);
    cursor: pointer;
  }
  .checkbox--sm .checkbox__label { font-size: var(--font-size-sm); }
  .checkbox__hint {
    grid-column: 2;
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-snug);
  }

  /* Hover (unchecked: stronger border; checked: darker fill) */
  .checkbox__input:hover:not(:disabled),
  .checkbox:has(> .checkbox__label:hover) > .checkbox__input:not(:disabled, :checked, :indeterminate),
  .checkbox__input.is-hover { --_border: var(--color-text-default); }
  .checkbox__input:is(:checked, :indeterminate):hover:not(:disabled),
  .checkbox__input:is(:checked, :indeterminate).is-hover {
    --_bg: var(--color-action-primary-bg-hover);
    --_border: var(--color-action-primary-bg-hover);
  }

  /* Checked / indeterminate */
  .checkbox__input:is(:checked, :indeterminate) {
    --_bg: var(--color-action-primary-bg);
    --_border: var(--color-action-primary-bg);
    --_mark: var(--color-action-primary-fg);
  }

  /* Focus */
  .checkbox__input:focus-visible,
  .checkbox__input.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Invalid — single checkbox (aria-invalid / :user-invalid) or any box inside a group with an error. */
  .checkbox__input[aria-invalid="true"]:not(:checked),
  .checkbox__input:user-invalid,
  .checkbox-group:has(> .field__error) .checkbox__input:not(:checked, :disabled) {
    --_border: var(--color-border-invalid);
  }

  /* Disabled — both values stay readable */
  .checkbox__input:disabled {
    --_bg: var(--color-bg-muted);
    --_border: var(--color-border-default);
    --_mark: var(--color-text-disabled);
    cursor: not-allowed;
  }
  .checkbox:has(.checkbox__input:disabled) .checkbox__label {
    color: var(--color-text-disabled);
    cursor: not-allowed;
  }

  /* Group */
  .checkbox-group__items {
    display: grid;
    gap: var(--space-3);
  }
  .checkbox-group--horizontal .checkbox-group__items {
    display: flex;
    flex-wrap: wrap;
    column-gap: var(--space-6);
    row-gap: var(--space-3);
  }
  /* Group error: a left rule ties legend, message and boxes together (GOV.UK pattern). */
  .checkbox-group:has(> .field__error) {
    padding-inline-start: var(--space-4);
    border-inline-start: var(--border-width-thick) solid var(--color-border-invalid);
  }

  @media (forced-colors: active) {
    .checkbox__input { border-color: CanvasText; background: Canvas; }
    .checkbox__input:is(:checked, :indeterminate) { border-color: Highlight; background: Highlight; }
    .checkbox__input::before { forced-color-adjust: none; background: Canvas; }
    .checkbox__input:not(:checked, :indeterminate)::before { background: transparent; }
    .checkbox__input:disabled { border-color: GrayText; }
    .checkbox__input:disabled:is(:checked, :indeterminate) { background: GrayText; }
    .checkbox:has(:disabled) .checkbox__label { color: GrayText; }
  }
}

/* ---- css/components/close-button.css ---- */
/* close-button.css — Standard dismiss control for dialogs, drawers, toasts, alerts and popovers.
   Block alias: .close-btn   Sizes: .close-btn--sm (toasts, alerts, chips) | (md default) | .close-btn--lg (tablet)
   Parts:  .close-btn__icon (svg "x", aria-hidden)
   States: :hover :focus-visible :active, disabled (rare: only while a dialog is saving).
           Docs-only freeze classes share the selectors: .is-hover, .is-focus-visible, .is-active.
   Placement: the parent puts it top inline-end (e.g. grid-area or align-self: start; justify-self: end).
   Name:   aria-label="Close" (dialogs) or a specific one ("Dismiss notification", "Close vehicle details"). */
@layer components {
  .close-btn {
    --_h: var(--button-height-md);
    --_icon: var(--icon-size-md);
    --_bg: var(--color-action-ghost-bg);
    --_fg: var(--color-text-muted);

    display: inline-grid;
    place-items: center;
    flex-shrink: 0;
    inline-size: var(--_h);
    block-size: var(--_h);
    padding: 0;
    border: var(--border-width-thin) solid transparent;
    border-radius: var(--button-radius);
    background: var(--_bg);
    color: var(--_fg);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition:
      background-color var(--motion-duration-fast) var(--motion-easing-standard),
      color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .close-btn--sm { --_h: var(--button-height-sm); --_icon: var(--icon-size-sm); }
  .close-btn--lg { --_h: var(--button-height-lg); --_icon: var(--icon-size-lg); }

  .close-btn__icon {
    inline-size: var(--_icon);
    block-size: var(--_icon);
    stroke-width: var(--icon-stroke);
    pointer-events: none;
  }

  .close-btn:hover:not(:disabled),
  .close-btn.is-hover { --_bg: var(--color-action-ghost-bg-hover); --_fg: var(--color-text-default); }

  .close-btn:active:not(:disabled),
  .close-btn.is-active { --_bg: var(--color-action-ghost-bg-active); --_fg: var(--color-text-default); }

  .close-btn:focus-visible,
  .close-btn.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  .close-btn:disabled { --_bg: transparent; --_fg: var(--color-text-disabled); cursor: not-allowed; }

  @media (forced-colors: active) {
    .close-btn { color: ButtonText; }
    .close-btn:hover, .close-btn.is-hover { border-color: ButtonText; }
    .close-btn:disabled { color: GrayText; }
  }
}

/* ---- css/components/date-field.css ---- */
/* date-field.css — memorable date (GOV.UK pattern): day / month / year text inputs in a fieldset.
   Block alias: .date-field
     <fieldset class="fieldset date-field" aria-describedby="…-hint [ …-error]">
       <legend class="fieldset__legend">When was the vehicle last serviced?</legend>
       <p class="field__hint" id="…-hint">For example, 14 3 2026</p>
       [<p class="field__error" id="…-error">…</p>]
       <div class="date-field__inputs">
         <div class="date-field__item" data-part="day">
           <label class="label" for="…-day">Day</label>
           <input class="input date-field__input date-field__input--2ch" id="…-day" type="text" inputmode="numeric">
         </div> … month (--2ch) … year (--4ch)
       </div>
     </fieldset>
   Inputs reuse .input (text-field.css) for border, focus ring, invalid and disabled styling.
   Modifiers: .date-field__input--2ch | --4ch (character widths that still shrink at 320px)
   States:    aria-invalid="true" on the offending input(s) only (partial-invalid) or on all three;
              <fieldset disabled> disables every part natively.
   Order:     DOM order is the reading order. js/date-field.js reorders items by locale
              ([data-locale-order], Intl.DateTimeFormat#formatToParts) and accepts month names. */
@layer components {
  .date-field__inputs {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-4);
  }
  .date-field__item {
    display: grid;
    gap: var(--space-1-5);
    min-inline-size: 0;
  }
  .date-field__input {
    --_chars: 2;
    inline-size: 100%;
    max-inline-size: calc(var(--_chars) * 1ch + 2 * var(--space-3) + 2 * var(--border-width-thin) + var(--space-3));
    font-variant-numeric: tabular-nums;
  }
  .date-field__input--2ch { --_chars: 2; }
  .date-field__input--4ch { --_chars: 4; }
  .date-field__item:has(.date-field__input--2ch) { inline-size: calc(2ch + 3 * var(--space-3) + 2 * var(--border-width-thin)); }
  .date-field__item:has(.date-field__input--4ch) { inline-size: calc(4ch + 3 * var(--space-3) + 2 * var(--border-width-thin)); }

  /* Error: left rule ties legend, message and inputs together (same as choice groups). */
  .date-field:has(> .field__error) {
    padding-inline-start: var(--space-4);
    border-inline-start: var(--border-width-thick) solid var(--color-border-invalid);
  }

  .date-field:disabled .label,
  .date-field:disabled .fieldset__legend { color: var(--color-text-disabled); }

  @media (forced-colors: active) {
    .date-field:has(> .field__error) { border-inline-start-color: CanvasText; }
    .date-field:disabled .label { color: GrayText; }
  }
}

/* ---- css/components/description-list.css ---- */
/* description-list.css — Description list (key/value pairs). Block alias: .dl
   Markup:   <dl class="dl"> <div class="dl__row"><dt>Odometer</dt><dd>84,212 km</dd></div> …  (div wrappers are valid HTML)
   Variants: stacked (default: term above value) | .dl--horizontal (two aligned columns via subgrid; falls back to
             stacked when the list is narrower than 28rem — container query, no breakpoint)
   Parts:    .dl__row, dt, dd, .dl__num (tabular numerals), .dl__empty (em dash + .sr-only "Not set")
   Density:  [data-density="compact"] tightens row padding. */
@layer components {
  .dl {
    --_py: var(--space-3);
    container-type: inline-size;
    display: grid;
    margin: 0;
  }
  [data-density="compact"] .dl { --_py: var(--space-2); }

  .dl__row {
    display: grid;
    gap: var(--space-1);
    padding-block: var(--_py);
    border-block-start: var(--border-width-thin) solid var(--color-border-default);
  }
  .dl__row:first-child { border-block-start: 0; padding-block-start: 0; }

  .dl dt {
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
  }
  .dl dd {
    margin: 0;
    color: var(--color-text-default);
    overflow-wrap: anywhere;
  }
  .dl__num { font-variant-numeric: tabular-nums; }
  .dl__empty { color: var(--color-text-muted); }

  /* Horizontal: rows share one column track so all values start on the same line. */
  .dl--horizontal { grid-template-columns: minmax(8rem, max-content) 1fr; column-gap: var(--space-6); }
  .dl--horizontal > .dl__row {
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    align-items: baseline;
    column-gap: var(--space-6);
  }
  @container (inline-size < 28rem) {
    .dl--horizontal > .dl__row { grid-template-columns: 1fr; }
  }

  @media (forced-colors: active) {
    .dl__row { border-color: CanvasText; }
  }
}

/* ---- css/components/divider.css ---- */
/* divider.css — boundaries between content.
   Block: .divider
     <hr class="divider">                                      thematic break (semantic)
     <span class="divider divider--vertical" role="separator" aria-orientation="vertical"></span>
     <div class="divider-label"><span>or</span></div>           labelled break; the text is read normally
   Modifiers: .divider--strong (border-strong, for 3:1 when the line itself carries meaning) */
@layer components {
  .divider {
    flex-shrink: 0;
    align-self: stretch;
    block-size: 0;
    border: 0;
    border-block-start: var(--border-width-thin) solid var(--color-border-default);
    margin: 0;
  }
  .divider--strong { border-color: var(--color-border-strong); }
  .divider--vertical {
    display: block;
    block-size: auto;
    min-block-size: var(--space-6);
    inline-size: 0;
    border-block-start: 0;
    border-inline-start: var(--border-width-thin) solid var(--color-border-default);
  }

  .divider-label {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    color: var(--color-text-muted);
    font-size: var(--typography-small-font-size);
    line-height: var(--typography-small-line-height);
  }
  .divider-label::before,
  .divider-label::after {
    content: "";
    flex: 1;
    border-block-start: var(--border-width-thin) solid var(--color-border-default);
  }

  @media (forced-colors: active) {
    .divider, .divider-label::before, .divider-label::after { border-color: CanvasText; }
  }
}

/* ---- css/components/error-summary.css ---- */
/* error-summary — form-level list of problems linking to each field (GOV.UK pattern), on an .alert--danger surface.
   API: .error-summary (+ .alert.alert--danger), .error-summary__list; tabindex="-1" so js/error-summary.js can focus it. */
@layer components {
  .error-summary:focus-visible, .error-summary:focus { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
  .error-summary__list { display: grid; gap: var(--space-1); padding-inline-start: var(--space-5); }
  .error-summary__list .link { color: var(--color-feedback-danger-fg); }
  @media (forced-colors: active) { .error-summary:focus-visible { outline-color: Highlight; } }
}

/* ---- css/components/form-field.css ---- */
/* form-field.css — Label, form field wrapper, fieldset. Every form control renders inside .field.
   Blocks: .field, .label, .fieldset
   .field parts:   .field__hint (helper, id → aria-describedby), .field__error (id → aria-describedby,
                   icon + visually hidden "Error:"), .field__counter (polite live counter, js/form-field.js),
                   .field__control (row for the control when it is not a single element)
   .field modifier: .field--horizontal (label beside control from 48rem / --breakpoint-md)
   .label parts:   .label__required ("*", explained in the form intro), .label__optional ("(optional)")
   .fieldset parts: .fieldset__legend, .fieldset__body
   Invalid styling comes from the control (aria-invalid="true" or :user-invalid), never from a class. */
@layer components {
  .field {
    display: grid;
    gap: var(--space-1-5);
    min-inline-size: 0;
    max-inline-size: var(--field-max, 32rem);
  }

  .label {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-1);
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    line-height: var(--font-line-height-snug);
  }
  .label__required { color: var(--color-feedback-danger-fg); font-weight: var(--font-weight-bold); }
  .label__optional { color: var(--color-text-muted); font-weight: var(--font-weight-regular); }

  .field__hint,
  .field__counter {
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-snug);
  }
  .field__counter { font-variant-numeric: tabular-nums; justify-self: end; }
  .field__counter[data-over="true"] { color: var(--color-feedback-danger-fg); font-weight: var(--font-weight-semibold); }

  .field__error {
    display: flex;
    align-items: flex-start;
    gap: var(--space-1-5);
    color: var(--color-feedback-danger-fg);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    line-height: var(--font-line-height-snug);
  }
  .field__error-icon {
    flex-shrink: 0;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    margin-block-start: var(--space-px);
    color: var(--color-feedback-danger-icon);
    stroke-width: var(--icon-stroke);
  }

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

  /* Horizontal: label column + control column, only where there is room. */
  @media (min-width: 48rem) {
    .field--horizontal {
      --field-max: 44rem;
      grid-template-columns: 12rem minmax(0, 1fr);
      column-gap: var(--space-4);
      align-items: start;
    }
    .field--horizontal > .label { grid-column: 1; padding-block-start: var(--space-2); }
    .field--horizontal > :not(.label) { grid-column: 2; }
  }

  .fieldset {
    display: grid;
    gap: var(--space-4);
    min-inline-size: 0;
    margin: 0;
    padding: 0;
    border: 0;
  }
  .fieldset__legend {
    float: inline-start; /* lets the legend sit inside the grid flow with a normal gap */
    inline-size: 100%;
    margin-block-end: var(--space-1);
    padding: 0;
    color: var(--color-text-default);
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-semibold);
    line-height: var(--font-line-height-snug);
  }
  .fieldset__legend + * { clear: both; }
  .fieldset__body { display: grid; gap: var(--space-4); }
}

/* ---- css/components/grid.css ---- */
/* grid.css — two-dimensional layout and page width.
   Blocks: .grid (12 columns), .grid--auto-fit (no media queries), .container
   Spans: .col-span-1 … .col-span-12, responsive .col-span-{sm|md|lg|xl}-N
     Breakpoints are literal rem copies of --breakpoint-* (custom properties can't be used in @media):
     sm 40rem · md 48rem · lg 64rem · xl 80rem
   Custom properties: --grid-gap (default --space-4), --grid-min (auto-fit track minimum, default 16rem) */
@layer components {
  .grid {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: var(--grid-gap, var(--space-4));
  }
  .grid > * { grid-column: span 12; min-inline-size: 0; }

  .grid--auto-fit {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--grid-min, 16rem)), 1fr));
  }
  .grid--auto-fit > * { grid-column: auto; }

  .grid > .col-span-1 { grid-column: span 1; }
  .grid > .col-span-2 { grid-column: span 2; }
  .grid > .col-span-3 { grid-column: span 3; }
  .grid > .col-span-4 { grid-column: span 4; }
  .grid > .col-span-6 { grid-column: span 6; }
  .grid > .col-span-8 { grid-column: span 8; }
  .grid > .col-span-9 { grid-column: span 9; }
  .grid > .col-span-12 { grid-column: span 12; }

  @media (min-width: 40rem) {
    .grid > .col-span-sm-4 { grid-column: span 4; }
    .grid > .col-span-sm-6 { grid-column: span 6; }
    .grid > .col-span-sm-12 { grid-column: span 12; }
  }
  @media (min-width: 48rem) {
    .grid > .col-span-md-3 { grid-column: span 3; }
    .grid > .col-span-md-4 { grid-column: span 4; }
    .grid > .col-span-md-6 { grid-column: span 6; }
    .grid > .col-span-md-8 { grid-column: span 8; }
  }
  @media (min-width: 64rem) {
    .grid > .col-span-lg-3 { grid-column: span 3; }
    .grid > .col-span-lg-4 { grid-column: span 4; }
    .grid > .col-span-lg-8 { grid-column: span 8; }
    .grid > .col-span-lg-9 { grid-column: span 9; }
  }
  @media (min-width: 80rem) {
    .grid > .col-span-xl-2 { grid-column: span 2; }
    .grid > .col-span-xl-3 { grid-column: span 3; }
  }

  .container {
    inline-size: 100%;
    max-inline-size: var(--container-max, var(--size-container-xl));
    margin-inline: auto;
    padding-inline: var(--space-4);
  }
  .container--md { --container-max: var(--size-container-md); }
  .container--lg { --container-max: var(--size-container-lg); }
  @media (min-width: 48rem) { .container { padding-inline: var(--space-6); } }
  @media (min-width: 64rem) { .container { padding-inline: var(--space-8); } }
}

/* ---- css/components/icon-button.css ---- */
/* icon-button.css — Icon-only button. Block alias: .icon-btn
   Shapes:   .icon-btn--square (default, --button-radius) | .icon-btn--circle
   Emphasis: (ghost default) | .icon-btn--outline | .icon-btn--primary
   Sizes:    .icon-btn--sm | (md default) | .icon-btn--lg   → square of --button-height-* (32 / 40 / 48px)
   Parts:    .icon-btn__icon (svg, aria-hidden), .icon-btn__badge (count dot, aria-hidden; count goes in aria-label)
   States:   :hover :focus-visible :active, disabled, aria-disabled="true", aria-pressed="true" (toggle icon buttons).
             Docs-only freeze classes share the selectors: .is-hover, .is-focus-visible, .is-active.
   Pattern:  copies .btn — modifiers set private props (--_bg, --_fg, --_border, --_h), states swap them.
   Name:     always aria-label (verb or noun: "Edit work order", "Notifications, 3 unread") + a tooltip with the same text. */
@layer components {
  .icon-btn {
    --_h: var(--button-height-md);
    --_icon: var(--icon-size-md);
    --_radius: var(--button-radius);
    --_bg: var(--color-action-ghost-bg);
    --_bg-hover: var(--color-action-ghost-bg-hover);
    --_bg-active: var(--color-action-ghost-bg-active);
    --_fg: var(--color-action-ghost-fg);
    --_border: transparent;

    position: relative;
    display: inline-grid;
    place-items: center;
    flex-shrink: 0;
    inline-size: var(--_h);
    block-size: var(--_h);
    padding: 0;
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--_radius);
    background: var(--_bg);
    color: var(--_fg);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition:
      background-color var(--motion-duration-fast) var(--motion-easing-standard),
      border-color var(--motion-duration-fast) var(--motion-easing-standard),
      color var(--motion-duration-fast) var(--motion-easing-standard);
  }

  /* Shapes */
  .icon-btn--square { --_radius: var(--button-radius); }
  .icon-btn--circle { --_radius: var(--radius-full); }

  /* Emphasis */
  .icon-btn--outline {
    --_bg: var(--color-action-secondary-bg);
    --_bg-hover: var(--color-action-secondary-bg-hover);
    --_bg-active: var(--color-action-secondary-bg-active);
    --_fg: var(--color-action-secondary-fg);
    --_border: var(--color-action-secondary-border);
  }
  .icon-btn--primary {
    --_bg: var(--color-action-primary-bg);
    --_bg-hover: var(--color-action-primary-bg-hover);
    --_bg-active: var(--color-action-primary-bg-active);
    --_fg: var(--color-action-primary-fg);
  }

  /* Sizes — same heights as .btn--sm/md/lg so they sit in one row. */
  .icon-btn--sm { --_h: var(--button-height-sm); --_icon: var(--icon-size-sm); }
  .icon-btn--lg { --_h: var(--button-height-lg); --_icon: var(--icon-size-lg); }

  /* Parts */
  .icon-btn__icon {
    inline-size: var(--_icon);
    block-size: var(--_icon);
    stroke-width: var(--icon-stroke);
    pointer-events: none;
  }
  .icon-btn__badge {
    position: absolute;
    inset-block-start: var(--space-0-5);
    inset-inline-end: var(--space-0-5);
    min-inline-size: var(--space-4);
    block-size: var(--space-4);
    padding-inline: var(--space-1);
    border-radius: var(--radius-full);
    background: var(--color-action-danger-bg);
    color: var(--color-action-danger-fg);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    line-height: var(--space-4);
    font-variant-numeric: tabular-nums;
    pointer-events: none;
  }

  /* States */
  .icon-btn:hover:not(:disabled, [aria-disabled="true"]),
  .icon-btn.is-hover { background: var(--_bg-hover); }

  .icon-btn:active:not(:disabled, [aria-disabled="true"]),
  .icon-btn.is-active { background: var(--_bg-active); }

  .icon-btn:focus-visible,
  .icon-btn.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Toggle icon buttons: pressed = selected colors + border, not color alone. */
  .icon-btn[aria-pressed="true"] {
    --_bg: var(--color-selected-bg);
    --_bg-hover: var(--color-selected-bg);
    --_fg: var(--color-selected-fg);
    --_border: var(--color-selected-border);
  }

  .icon-btn:disabled,
  .icon-btn[aria-disabled="true"] {
    --_bg: transparent;
    --_fg: var(--color-text-disabled);
    --_border: transparent;
    cursor: not-allowed;
  }
  .icon-btn--outline:disabled,
  .icon-btn--outline[aria-disabled="true"],
  .icon-btn--primary:disabled,
  .icon-btn--primary[aria-disabled="true"] { --_bg: var(--color-bg-muted); }

  @media (forced-colors: active) {
    .icon-btn { border-color: ButtonText; color: ButtonText; }
    .icon-btn[aria-pressed="true"] { background: Highlight; color: HighlightText; }
    .icon-btn:disabled, .icon-btn[aria-disabled="true"] { color: GrayText; border-color: GrayText; }
    .icon-btn__badge { border: var(--border-width-thin) solid CanvasText; }
  }
}

/* ---- css/components/icon.css ---- */
/* icon.css — Icon wrapper.
   Block: .icon  ·  Modifiers: .icon--sm | --md (default) | --lg, .icon--mirror-rtl
   Markup: <svg class="icon" aria-hidden="true" focusable="false"><use href="#icon-wrench"></use></svg>
   Symbols are Lucide-style 24×24 outline paths (ISC). They set fill="none" stroke="currentColor";
   stroke width comes from --icon-stroke so the whole set stays one weight. Color is inherited (currentColor). */
@layer components {
  .icon {
    --_size: var(--icon-size-md);
    display: inline-block;
    flex-shrink: 0;
    inline-size: var(--_size);
    block-size: var(--_size);
    vertical-align: middle;
    color: inherit;
    stroke-width: var(--icon-stroke);
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .icon--sm { --_size: var(--icon-size-sm); }
  .icon--md { --_size: var(--icon-size-md); }
  .icon--lg { --_size: var(--icon-size-lg); }

  /* Directional glyphs (arrows, chevrons pointing "forward") flip in RTL. */
  .icon--mirror-rtl:dir(rtl) { transform: scaleX(-1); }

  /* Text-paired icon: aligns to the first line of adjacent text. */
  .icon-text {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1-5);
  }

  @media (forced-colors: active) {
    .icon { color: CanvasText; }
  }
}

/* ---- css/components/link.css ---- */
/* link.css — Text link. Block: .link
   Variants: (inline default: underlined, inherits size) | .link--standalone (no underline until hover; weight + optional
             trailing icon carry the cue) | .link--external (adds an icon + visually hidden "(opens in new tab)")
             .link--subtle (inherits text color, still underlined — for dense tables)
   Parts:    .link__icon (svg, aria-hidden; arrow icons also get .icon--mirror-rtl)
   States:   :hover :focus-visible :active :visited. Docs-only freeze classes share the selectors:
             .is-hover, .is-focus-visible, .is-active, .is-visited.
   Rule:     <a href> only. Never a button substitute; never color-only (WCAG 1.4.1). */
@layer components {
  .link {
    --_fg: var(--color-text-link);
    --_thickness: var(--border-width-thin);

    color: var(--_fg);
    font-weight: inherit;
    text-decoration-line: underline;
    text-decoration-thickness: var(--_thickness);
    text-underline-offset: 0.2em;
    text-decoration-skip-ink: auto;
    border-radius: var(--radius-sm);
    transition: text-decoration-thickness var(--motion-duration-fast) var(--motion-easing-standard);
  }

  .link--standalone {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-block-size: var(--space-6);
    font-weight: var(--font-weight-semibold);
    text-decoration-line: none;
  }
  .link--subtle { --_fg: inherit; }
  .link--external { display: inline; }

  .link__icon {
    display: inline-block;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    vertical-align: -0.125em;
    stroke-width: var(--icon-stroke);
    flex-shrink: 0;
  }
  .link--external .link__icon { margin-inline-start: var(--space-0-5); }

  .link:visited,
  .link.is-visited { color: var(--color-text-link-visited); }
  .link--subtle:visited { color: inherit; }

  .link:hover,
  .link.is-hover { --_thickness: var(--border-width-thick); text-decoration-line: underline; }

  .link:active,
  .link.is-active { --_thickness: var(--border-width-thick); background: var(--color-selected-bg); color: var(--color-selected-fg); }   /* link color fails on the selected fill in dark/HC */

  .link:focus-visible,
  .link.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
    text-decoration-line: underline;
  }

  @media (forced-colors: active) {
    .link { color: LinkText; text-decoration-line: underline; }
    .link:visited { color: VisitedText; }
  }
}

/* ---- css/components/list-group.css ---- */
/* list-group.css — List group (multi-row list). Block alias: .list-group
   Markup:   <ul class="list-group" role="list"> <li class="list-group__item">…
   Variants: .list-group--interactive (each row has one .list-group__link; its ::after covers the row)
             rows with trailing actions: put buttons in .list-group__actions (they sit above the stretched link)
   Parts:    .list-group__leading (avatar/icon), .list-group__content > .list-group__primary + .list-group__secondary,
             .list-group__meta (trailing text/badge, tabular numerals), .list-group__actions
   States:   :hover / :focus-within on interactive rows (docs freeze: .is-hover, .is-focus-visible),
             aria-current="page" on the link = current row (teal bar + fill; the link's name already says which row).
   Density:  [data-density="compact"] tightens row padding. */
@layer components {
  .list-group {
    --_py: var(--space-3);

    display: grid;
    padding: 0;
    list-style: none;
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: var(--color-elevation-surface-raised);
  }
  [data-density="compact"] .list-group { --_py: var(--density-compact-cell-padding-y); }

  .list-group__item {
    --_bg: transparent;
    --_bar: transparent;

    position: relative;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-block-size: var(--size-touch-target);
    padding-block: var(--_py);
    padding-inline: var(--space-4);
    background: var(--_bg);
    box-shadow: inset var(--border-width-thick) 0 0 var(--_bar);
    transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .list-group__item:dir(rtl) { box-shadow: inset calc(var(--border-width-thick) * -1) 0 0 var(--_bar); }
  .list-group__item + .list-group__item { border-block-start: var(--border-width-thin) solid var(--color-border-default); }
  .list-group__item:first-child { border-start-start-radius: inherit; border-start-end-radius: inherit; }
  .list-group__item:last-child { border-end-start-radius: inherit; border-end-end-radius: inherit; }

  .list-group__leading { flex-shrink: 0; display: inline-flex; color: var(--color-text-muted); }
  .list-group__leading > .icon { inline-size: var(--icon-size-lg); block-size: var(--icon-size-lg); }
  .list-group__content { flex: 1; display: grid; gap: var(--space-0-5); min-inline-size: 0; }
  .list-group__primary {
    font-weight: var(--font-weight-semibold);
    overflow-wrap: anywhere;
  }
  .list-group__secondary { color: var(--color-text-muted); font-size: var(--font-size-sm); }
  .list-group__meta {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-variant-numeric: tabular-nums;
    text-align: end;
  }
  .list-group__actions {
    position: relative;
    z-index: var(--z-raised);
    flex-shrink: 0;
    display: inline-flex;
    gap: var(--space-1);
  }

  /* Interactive rows */
  .list-group__link { color: inherit; text-decoration: none; }
  .list-group__link::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
  .list-group__link:focus-visible { outline: var(--focus-ring-width) solid transparent; } /* ring drawn on the row */
  .list-group--interactive .list-group__item:hover,
  .list-group--interactive .list-group__item.is-hover { --_bg: var(--color-action-ghost-bg-hover); }
  .list-group--interactive .list-group__item:hover .list-group__link { text-decoration: underline; }
  .list-group__item:has(.list-group__link:focus-visible),
  .list-group__item.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: calc(var(--focus-ring-width) * -1);
  }
  .list-group__item:has(.list-group__link[aria-current="page"]) {
    --_bg: var(--color-selected-bg);
    --_bar: var(--color-selected-border);
  }
  /* A selected row recolors ALL its text: secondary/meta on the selected fill must pass too (high contrast fills black). */
  .list-group__item:has(.list-group__link[aria-current="page"]) :is(.list-group__primary, .list-group__secondary, .list-group__meta) { color: var(--color-selected-fg); }

  @media (forced-colors: active) {
    .list-group { border-color: CanvasText; }
    .list-group__item:has(.list-group__link:focus-visible) { outline-color: Highlight; }
    .list-group__item:has(.list-group__link[aria-current="page"]) { border-inline-start: var(--border-width-thick) solid Highlight; }
  }
}

/* ---- css/components/menu.css ---- */
/* menu.css — Menu button + dropdown menu (APG Menu Button). Block: .menu
   Trigger:  any .btn / .icon-btn with aria-haspopup="menu" aria-expanded aria-controls, opened by
             commandfor="<menu id>" command="toggle-popover". Optional .menu-trigger__chevron (svg) rotates when open.
   Surface:  <div class="menu" id popover role="menu" aria-labelledby|aria-label> — anchored to the trigger with
             CSS anchor positioning (style="anchor-name:--x" on trigger, style="position-anchor:--x" on menu) and
             the shared try-set from base.css (--flip-block, --flip-inline). Without anchor support it opens centered.
   Variants: .menu--sub (submenu, opens inline-end) · .menu--static (docs-only in-flow preview of an open menu)
   Parts:    .menu__item (button role=menuitem | menuitemcheckbox | menuitemradio), .menu__icon, .menu__label,
             .menu__shortcut (<kbd>), .menu__check (svg, shown when aria-checked="true"), .menu__chevron (submenu),
             .menu__group (role=group + aria-labelledby), .menu__group-label, .menu__separator (role=separator)
   Item modifiers: .menu__item--danger
   States:   item :hover / :focus-visible (highlight), aria-disabled="true" (stays focusable, not actionable),
             aria-checked="true", aria-expanded="true" (submenu parent). Docs-only: .is-hover, .is-focus-visible.
   Behavior: js/menu.js — roving focus (↑/↓/Home/End, typeahead), Esc + Tab close, focus returns to the trigger. */
@layer components {
  .menu {
    --_item-h: var(--size-control-md);

    inset: auto;
    margin: var(--space-1);
    position-area: block-end span-inline-end;
    position-try-fallbacks: --flip-block, --flip-inline;
    min-inline-size: 12rem;
    max-inline-size: min(22rem, calc(100vw - var(--space-8)));
    max-block-size: calc(100dvh - var(--space-8));
    overflow-y: auto;
    padding: var(--space-1);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--overlay-radius);
    background: var(--color-elevation-surface-overlay);
    box-shadow: var(--overlay-shadow);
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
    z-index: var(--z-dropdown);
  }
  .menu:popover-open,
  .menu--static { display: grid; gap: var(--space-0-5); }

  .menu--sub {
    position-area: inline-end span-block-end;
    position-try-fallbacks: --flip-inline, --flip-block;
    margin: 0 var(--space-1);
  }
  .menu--static {
    position: static;
    inline-size: max-content;
    margin: 0;
    box-shadow: var(--elevation-raised);
  }

  @media (prefers-reduced-motion: no-preference) {
    .menu:popover-open {
      animation: menu-enter var(--motion-duration-fast) var(--motion-easing-enter);
    }
  }

  /* Item */
  .menu__item {
    --_bg: transparent;
    --_fg: var(--color-text-default);

    display: grid;
    grid-template-columns: var(--icon-size-sm) 1fr auto;
    align-items: center;
    gap: var(--space-2);
    inline-size: 100%;
    min-block-size: var(--_item-h);
    padding-block: var(--space-1);
    padding-inline: var(--space-2) var(--space-3);
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--_bg);
    color: var(--_fg);
    font: inherit;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
  }
  [data-density="compact"] .menu { --_item-h: var(--size-control-sm); }

  .menu__item:hover:not([aria-disabled="true"]),
  .menu__item.is-hover,
  .menu__item:focus-visible,
  .menu__item.is-focus-visible,
  .menu__item[aria-expanded="true"] { --_bg: var(--color-action-ghost-bg-hover); }

  .menu__item:focus-visible,
  .menu__item.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: calc(var(--focus-ring-width) * -1);
  }

  .menu__item[aria-disabled="true"] { --_fg: var(--color-text-disabled); cursor: not-allowed; }
  .menu__item--danger { --_fg: var(--color-feedback-danger-fg); }
  .menu__item--danger:hover:not([aria-disabled="true"]),
  .menu__item--danger:focus-visible { --_bg: var(--color-feedback-danger-bg); }

  /* Parts */
  .menu__icon,
  .menu__check,
  .menu__chevron {
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
  }
  /* Parts sit on one row by column, so DOM order is free (a submenu's chevron may come before its label). */
  .menu__item > * { grid-row: 1; }
  .menu__icon { grid-column: 1; color: var(--color-text-muted); }
  .menu__item[aria-disabled="true"] .menu__icon { color: inherit; }
  .menu__label { grid-column: 2; min-inline-size: 0; overflow-wrap: anywhere; }
  .menu__check { grid-column: 1; grid-row: 1; visibility: hidden; color: var(--color-selected-fg); }
  .menu__item[aria-checked="true"] .menu__check { visibility: visible; }
  .menu__shortcut {
    grid-column: 3;
    color: var(--color-text-muted);
    font-family: inherit;
    font-size: var(--font-size-xs);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  .menu__chevron { grid-column: 3; color: var(--color-text-muted); }
  .menu__chevron:dir(rtl) { transform: scaleX(-1); }

  .menu__group { display: grid; gap: var(--space-0-5); }
  .menu__group-label {
    padding-block: var(--space-1);
    padding-inline: var(--space-2);
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
  }
  .menu__separator {
    block-size: var(--border-width-thin);
    margin-block: var(--space-1);
    border: 0;
    background: var(--color-border-subtle);
  }

  /* Trigger chevron */
  .menu-trigger__chevron {
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
    transition: transform var(--motion-duration-fast) var(--motion-easing-standard);
  }
  [aria-expanded="true"] > .menu-trigger__chevron { transform: rotate(180deg); }

  @media (forced-colors: active) {
    .menu { border-color: CanvasText; }
    .menu__item:hover, .menu__item:focus-visible, .menu__item.is-hover, .menu__item.is-focus-visible {
      background: Highlight; color: HighlightText;
    }
    .menu__item[aria-disabled="true"] { color: GrayText; }
    .menu__separator { background: CanvasText; }
  }
}

@keyframes menu-enter {
  from { opacity: 0; translate: 0 calc(var(--space-1) * -1); }
}

/* ---- css/components/modal.css ---- */
/* modal.css — Modal dialog and alert (confirm) dialog. Block alias: .modal
   Markup:   <dialog class="modal" aria-labelledby aria-describedby> opened by an invoker
             <button commandfor="id" command="show-modal">; closed by command="close". No JS.
   Sizes:    .modal--sm | (md default) | .modal--lg   → 30rem / 40rem / 48rem, never wider than the viewport
   Variants: .modal--fullscreen-mobile (fills the screen below 40rem), .modal--alert (role="alertdialog")
   Parts:    .modal__header, .modal__icon (alert only, aria-hidden), .modal__title, .modal__close,
             .modal__body (the only part that scrolls), .modal__footer (actions, primary at inline-end)
   States:   real ones via [open] / :modal. Docs-only freeze classes: .is-preview (renders an open dialog
             in the page flow so docs can show it) and .is-mobile (forces the fullscreen-mobile layout).
   Pattern:  sizes only set --_w; tones set --_icon-bg / --_icon-fg.
   Motion:   fade + 8px rise on enter (base, enter easing), shorter fade on exit (fast, exit easing);
             @starting-style + allow-discrete on display/overlay. base.css neutralizes it under reduced motion. */
@layer components {
  .modal {
    --_w: var(--size-container-sm);
    --_gutter: var(--space-4);
    --_icon-bg: var(--color-feedback-info-bg);
    --_icon-fg: var(--color-feedback-info-icon);

    inline-size: min(var(--_w), 100% - 2 * var(--_gutter));
    max-inline-size: none;
    max-block-size: calc(100dvh - 2 * var(--space-8));
    padding: 0;
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--overlay-radius);
    background: var(--color-elevation-surface-overlay);
    color: var(--color-text-default);
    box-shadow: var(--overlay-shadow);
    flex-direction: column;
    overflow: hidden;
    opacity: 0;
    translate: 0 var(--space-2);
    transition:
      opacity var(--motion-duration-fast) var(--motion-easing-exit),
      translate var(--motion-duration-fast) var(--motion-easing-exit),
      overlay var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete,
      display var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete;
  }
  .modal[open] {
    display: flex;
    opacity: 1;
    translate: 0 0;
    transition-duration: var(--motion-duration-base);
    transition-timing-function: var(--motion-easing-enter);
  }
  @starting-style {
    .modal[open] { opacity: 0; translate: 0 var(--space-2); }
  }

  .modal::backdrop {
    background: var(--color-bg-overlay);
    opacity: 0;
    transition:
      opacity var(--motion-duration-fast) var(--motion-easing-exit),
      overlay var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete,
      display var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete;
  }
  .modal[open]::backdrop { opacity: 1; transition-duration: var(--motion-duration-base); }
  @starting-style {
    .modal[open]::backdrop { opacity: 0; }
  }

  /* The page behind a modal must not scroll. */
  html:has(.modal:modal) { overflow: hidden; scrollbar-gutter: stable; }

  /* Sizes */
  .modal--sm { --_w: calc(var(--size-container-sm) * 0.75); }
  .modal--lg { --_w: var(--size-container-md); }

  /* Parts */
  .modal__header {
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding-block: var(--space-5) var(--space-3);
    padding-inline: var(--space-6) var(--space-4);
  }
  .modal__title {
    flex: 1;
    min-inline-size: 0;
    padding-block-start: var(--space-1);
    font-family: var(--typography-h4-font-family);
    font-size: var(--typography-h4-font-size);
    font-weight: var(--typography-h4-font-weight);
    line-height: var(--typography-h4-line-height);
  }
  .modal__close { flex-shrink: 0; }
  .modal__icon {
    display: grid;
    place-items: center;
    flex-shrink: 0;
    inline-size: var(--size-control-md);
    block-size: var(--size-control-md);
    border-radius: var(--radius-full);
    background: var(--_icon-bg);
    color: var(--_icon-fg);
  }
  .modal__icon > svg {
    inline-size: var(--icon-size-md);
    block-size: var(--icon-size-md);
    stroke-width: var(--icon-stroke);
  }
  .modal__body {
    flex: 1 1 auto;
    min-block-size: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    display: grid;
    align-content: start;
    gap: var(--space-3);
    padding-block: 0 var(--space-5);
    padding-inline: var(--space-6);
    color: var(--color-text-muted);
  }
  .modal__body:focus-visible { outline-offset: calc(-1 * var(--focus-ring-width)); }
  /* Scrolling body: a hairline separates header/footer only when content actually scrolls. */
  .modal--scroll .modal__header { border-block-end: var(--border-width-thin) solid var(--color-border-default); }
  .modal--scroll .modal__footer { border-block-start: var(--border-width-thin) solid var(--color-border-default); }
  .modal--scroll .modal__body { padding-block-start: var(--space-4); }
  .modal__footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: var(--space-3);
    padding-block: var(--space-4);
    padding-inline: var(--space-6);
    background: var(--color-elevation-surface-overlay);
  }

  /* Alert dialog: tone of the icon follows the consequence. */
  .modal--alert { --_w: calc(var(--size-container-sm) * 0.75); }
  .modal--alert .modal__header { padding-inline-end: var(--space-6); }
  .modal--danger { --_icon-bg: var(--color-feedback-danger-bg); --_icon-fg: var(--color-feedback-danger-icon); }
  .modal--warning { --_icon-bg: var(--color-feedback-warning-bg); --_icon-fg: var(--color-feedback-warning-icon); }

  /* Fullscreen on small screens (the media query and the docs-only .is-mobile share one look). */
  @media (width < 40rem) {
    .modal--fullscreen-mobile {
      inline-size: 100%;
      max-block-size: 100dvh;
      block-size: 100dvh;
      border: 0;
      border-radius: 0;
    }
    .modal--fullscreen-mobile .modal__footer { flex-direction: column-reverse; }
    .modal--fullscreen-mobile .modal__footer > .btn { inline-size: 100%; min-block-size: var(--size-touch-target); }
  }
  .modal--fullscreen-mobile.is-mobile {
    inline-size: 100%;
    block-size: 100%;
    border: 0;
    border-radius: 0;
  }
  .modal--fullscreen-mobile.is-mobile .modal__footer { flex-direction: column-reverse; }
  .modal--fullscreen-mobile.is-mobile .modal__footer > .btn { inline-size: 100%; min-block-size: var(--size-touch-target); }

  /* Docs-only: show an open dialog inside a demo card instead of the top layer. */
  .modal.is-preview {
    position: static;
    inset: auto;
    margin: 0;
    inline-size: 100%;
    max-inline-size: var(--_w);
    max-block-size: none;
    display: flex;
    opacity: 1;
    translate: none;
    transition: none;
  }

  @media (forced-colors: active) {
    .modal { border: var(--border-width-thin) solid CanvasText; }
    .modal::backdrop { background: Canvas; opacity: 0.8; }
    .modal__icon { border: var(--border-width-thin) solid CanvasText; }
  }
}

/* ---- css/components/page-header.css ---- */
/* page-header.css — Title, meta and actions at the top of a page. Block: .page-header (<header> inside <main>;
   container: page-header)
   Parts:   .page-header__breadcrumbs (slot for .breadcrumbs), .page-header__main (title + actions row),
            .page-header__heading, .page-header__title (the page's only <h1>), .page-header__description,
            .page-header__meta (<dl>/<ul> of status, owner, updated time), .page-header__meta-item,
            .page-header__status (dot + text; data-tone="success|warning|danger|info"), .page-header__actions,
            .page-header__tabs (slot for .tabs; URL tabs use links + aria-current)
   Narrow (container < 40rem): actions wrap under the title; secondary actions go into the overflow menu. */
@layer components {
  .page-header {
    container: page-header / inline-size;
    display: grid;
    gap: var(--space-3);
    min-inline-size: 0;
  }

  .page-header__main {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3) var(--space-6);
  }
  .page-header__heading { display: grid; gap: var(--space-2); min-inline-size: 0; flex: 1 1 20rem; }

  .page-header__title {
    color: var(--color-text-default);
    font-family: var(--typography-h1-font-family);
    font-size: var(--typography-h2-font-size);
    font-weight: var(--typography-h1-font-weight);
    line-height: var(--typography-h1-line-height);
    overflow-wrap: anywhere;
  }
  .page-header__description { max-inline-size: var(--size-measure); color: var(--color-text-muted); }

  .page-header__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1) var(--space-4);
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
  }
  .page-header__meta-item { display: inline-flex; align-items: center; gap: var(--space-1-5); }
  .page-header__meta-icon { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); stroke-width: var(--icon-stroke); }

  .page-header__status {
    --_dot: var(--color-feedback-info-icon);
    display: inline-flex;
    align-items: center;
    gap: var(--space-1-5);
    color: var(--color-text-default);
    font-weight: var(--font-weight-semibold);
  }
  .page-header__status::before {
    content: "";
    inline-size: var(--space-2);
    block-size: var(--space-2);
    border-radius: var(--radius-full);
    background: var(--_dot);
  }
  .page-header__status[data-tone="success"] { --_dot: var(--color-feedback-success-icon); }
  .page-header__status[data-tone="warning"] { --_dot: var(--color-feedback-warning-icon); }
  .page-header__status[data-tone="danger"] { --_dot: var(--color-feedback-danger-icon); }

  .page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
  .page-header__tabs { margin-block-start: var(--space-1); }

  @container page-header (max-width: 40rem) {
    .page-header__title { font-size: var(--typography-h3-font-size); }
    .page-header__actions { inline-size: 100%; }
  }

  @media (forced-colors: active) {
    .page-header__status::before { background: CanvasText; }
  }
}

/* ---- css/components/pagination.css ---- */
/* pagination.css — Page index navigation. Block: .pagination (<nav aria-label="Pagination, …">)
   Parts:   .pagination__list (<ul>), .pagination__link (a; aria-current="page" = current: selected bg + border + weight),
            .pagination__link--step (Previous / Next with icon), .pagination__link[aria-disabled="true"] (a <span>, not a
            link, on the first / last page), .pagination__ellipsis, .pagination__icon (svg, mirrors in RTL),
            .pagination__status (compact "Page 3 of 12"), .pagination__bar (data-table footer row),
            .pagination__size (label + select "Rows per page"), .pagination__select, .pagination__range ("Showing 21–40 of 312")
   Variants: .pagination--compact (prev / status / next only)
   States:  :hover :focus-visible, aria-current="page", aria-disabled="true". Docs-only freeze: .is-hover, .is-focus-visible. */
@layer components {
  .pagination { font-size: var(--font-size-sm); }

  .pagination__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-1);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .pagination__link {
    --_bg: transparent;
    --_fg: var(--color-text-default);
    --_border: transparent;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-1);
    min-inline-size: var(--size-control-md);
    min-block-size: var(--size-control-md);
    padding-inline: var(--space-2);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--radius-md);
    background: var(--_bg);
    color: var(--_fg);
    font-variant-numeric: tabular-nums;
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .pagination__link--step { padding-inline: var(--space-3); }

  a.pagination__link:hover,
  .pagination__link.is-hover { --_bg: var(--color-action-ghost-bg-hover); }
  .pagination__link:focus-visible,
  .pagination__link.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
  .pagination__link[aria-current="page"] {
    --_bg: var(--color-selected-bg);
    --_fg: var(--color-selected-fg);
    --_border: var(--color-selected-border);
    font-weight: var(--font-weight-bold);
  }
  .pagination__link[aria-disabled="true"] { --_fg: var(--color-text-disabled); cursor: not-allowed; }

  .pagination__icon {
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
  }
  .pagination__icon:dir(rtl) { transform: scaleX(-1); }

  .pagination__ellipsis {
    display: inline-grid;
    place-items: center;
    min-inline-size: var(--size-control-sm);
    color: var(--color-text-muted);
  }
  .pagination__status { padding-inline: var(--space-2); color: var(--color-text-default); font-variant-numeric: tabular-nums; }

  /* Data-table footer row: page size · range · pages */
  .pagination__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3) var(--space-6);
    font-size: var(--font-size-sm);
  }
  .pagination__size { display: inline-flex; align-items: center; gap: var(--space-2); color: var(--color-text-default); }
  .pagination__select {
    min-block-size: var(--size-control-sm);
    padding-inline: var(--space-2);
    border: var(--border-width-thin) solid var(--input-border);
    border-radius: var(--input-radius);
    background: var(--input-bg);
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
  }
  .pagination__select:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
  .pagination__range { color: var(--color-text-muted); font-variant-numeric: tabular-nums; }

  @media (forced-colors: active) {
    .pagination__link[aria-current="page"] { border-color: Highlight; }
    .pagination__link[aria-disabled="true"] { color: GrayText; }
  }
}

/* ---- css/components/password-input.css ---- */
/* password-input.css — password field with reveal toggle and optional strength meter. Block alias: .password
   Builds on .input--affixed (text-field.css), so border, focus ring and invalid states are shared:
     <div class="input input--affixed password">
       <input class="input__control" type="password" id="pw" autocomplete="current-password|new-password">
       <button type="button" class="password__toggle" aria-controls="pw" aria-pressed="false" hidden>Show</button>
     </div>
   The toggle ships hidden and js/password-input.js reveals and wires it (progressive enhancement).
   Parts:     .password__toggle (text button inside the border; aria-pressed="true" while visible)
              .password__strength (wrapper) > .password__meter (<meter>) + .password__strength-text
              .password__rules (requirement list) > li[data-met="true|false"] with .password__rule-icon
   States:    toggle :hover, :focus-visible, aria-pressed; meter tone follows <meter> low/high/optimum.
              Docs-only freeze classes on the toggle: .is-hover, .is-focus-visible. */
@layer components {
  .password { padding-inline-end: var(--space-1); }

  .password__toggle {
    --_bg: var(--color-action-ghost-bg);
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    min-block-size: calc(var(--size-control-md) - var(--space-2));
    min-inline-size: var(--size-control-md);
    margin: 0;
    padding-block: 0;
    padding-inline: var(--space-2);
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--_bg);
    color: var(--color-action-ghost-fg);
    font: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
  }
  .password__toggle .icon { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); }
  .password__toggle:hover,
  .password__toggle.is-hover { --_bg: var(--color-action-ghost-bg-hover); }
  .password__toggle:active { --_bg: var(--color-action-ghost-bg-active); }
  .password__toggle:focus-visible,
  .password__toggle.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: 0;
  }
  .password:has(.input__control:disabled) .password__toggle { color: var(--color-text-disabled); cursor: not-allowed; }

  /* Strength meter: bar + text (never color alone) */
  .password__strength {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--space-2);
  }
  .password__meter {
    appearance: none;
    inline-size: 100%;
    block-size: var(--space-2);
    border: 0;
    border-radius: var(--radius-full);
    background: var(--color-bg-muted);
    overflow: hidden;
  }
  .password__meter::-webkit-meter-bar { border: 0; border-radius: var(--radius-full); background: var(--color-bg-muted); block-size: var(--space-2); }
  .password__meter::-webkit-meter-optimum-value { background: var(--color-feedback-success-icon); }
  .password__meter::-webkit-meter-suboptimum-value { background: var(--color-feedback-warning-icon); }
  .password__meter::-webkit-meter-even-less-good-value { background: var(--color-feedback-danger-icon); }
  .password__meter:-moz-meter-optimum::-moz-meter-bar { background: var(--color-feedback-success-icon); }
  .password__meter:-moz-meter-sub-optimum::-moz-meter-bar { background: var(--color-feedback-warning-icon); }
  .password__meter:-moz-meter-sub-sub-optimum::-moz-meter-bar { background: var(--color-feedback-danger-icon); }
  .password__strength-text {
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
  }

  /* Requirements: icon + text, met items get a check */
  .password__rules {
    display: grid;
    gap: var(--space-1);
    margin: 0;
    padding: 0;
    list-style: none;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-snug);
  }
  .password__rules li { display: flex; align-items: flex-start; gap: var(--space-1-5); }
  .password__rule-icon {
    flex-shrink: 0;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    margin-block-start: var(--space-px);
  }
  .password__rules li[data-met="true"] { color: var(--color-feedback-success-fg); }
  .password__rules li[data-met="true"] .password__rule-icon--todo,
  .password__rules li:not([data-met="true"]) .password__rule-icon--met { display: none; }

  @media (forced-colors: active) {
    .password__toggle { border: var(--border-width-thin) solid ButtonText; }
    .password__meter { border: var(--border-width-thin) solid CanvasText; }
  }
}

/* ---- css/components/popover.css ---- */
/* popover.css — Popover: a floating, non-modal surface with interactive content. Block alias: .popover
   Markup:   <button commandfor="p1" command="toggle-popover" style="anchor-name:--p1">…</button>
             <div id="p1" class="popover" popover role="dialog" aria-labelledby="p1-title" style="position-anchor:--p1">
   Placement (logical, RTL-safe): (block-end default) | .popover--block-start | .popover--inline-start | .popover--inline-end
             Flips with the shared try-set from base.css: position-try-fallbacks: --flip-block, --flip-inline.
             Without anchor positioning the UA default applies: the popover opens centered (still usable).
   Variants: .popover--arrow + <span class="popover__arrow" aria-hidden="true"> (arrow follows a block flip
             where `container-type: anchored` is supported; otherwise it stays on the default side).
   Parts:    .popover__header, .popover__title, .popover__body, .popover__footer
   States:   real one via :popover-open. Docs-only freeze class: .is-open (renders in page flow, no [popover]).
   Motion:   fade + 4px offset, base/enter; exit fast/exit; @starting-style + allow-discrete. */
@layer components {
  .popover {
    --_offset: var(--space-2);
    inline-size: max-content;
    max-inline-size: min(22rem, 100vw - 2 * var(--space-4));
    padding: 0;
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--overlay-radius);
    background: var(--color-elevation-surface-overlay);
    color: var(--color-text-default);
    box-shadow: var(--overlay-shadow);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-normal);
    overflow: visible;
    opacity: 0;
    transition:
      opacity var(--motion-duration-fast) var(--motion-easing-exit),
      overlay var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete,
      display var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete;
  }
  .popover:popover-open,
  .popover.is-open {
    opacity: 1;
    transition-duration: var(--motion-duration-base);
    transition-timing-function: var(--motion-easing-enter);
  }
  .popover.is-open { transition: none; }   /* docs-only frozen state: a static picture must never be mid-fade */
  @starting-style {
    .popover:popover-open { opacity: 0; }
  }

  /* Anchor positioning — primary path. */
  @supports (anchor-name: --a) {
    .popover[popover] {
      inset: auto;
      margin: var(--_offset);
      position-area: block-end span-inline-end;
      position-try-fallbacks: --flip-block, --flip-inline;
      max-block-size: calc(100dvh - 2 * var(--space-4));
      overflow-y: auto;
    }
    .popover--block-start[popover] { position-area: block-start span-inline-end; position-try-fallbacks: flip-block, --flip-inline; }
    .popover--inline-start[popover] { position-area: inline-start center; position-try-fallbacks: flip-inline, --flip-block; }
    .popover--inline-end[popover] { position-area: inline-end center; position-try-fallbacks: --flip-inline, --flip-block; }
    .popover--arrow[popover] { --_offset: var(--space-3); container-type: anchored; }
  }

  /* Parts */
  .popover__header {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding-block: var(--space-3) 0;
    padding-inline: var(--space-4) var(--space-2);
  }
  .popover__title {
    flex: 1;
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-semibold);
    line-height: var(--font-line-height-snug);
  }
  .popover__body {
    display: grid;
    gap: var(--space-2);
    padding-block: var(--space-2) var(--space-4);
    padding-inline: var(--space-4);
    color: var(--color-text-muted);
  }
  .popover__footer {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding-block: var(--space-3);
    padding-inline: var(--space-4);
    border-block-start: var(--border-width-thin) solid var(--color-border-default);
  }

  /* Arrow: a rotated square sharing the surface's fill and border. */
  .popover__arrow { display: none; }
  .popover--arrow .popover__arrow {
    display: block;
    position: absolute;
    inset-block-start: calc(-1 * var(--space-1-5));
    inset-inline-start: var(--space-5);
    inline-size: var(--space-3);
    block-size: var(--space-3);
    background: inherit;
    border: inherit;
    border-block-end-color: transparent;
    border-inline-end-color: transparent;
    border-radius: var(--radius-none);
    rotate: 45deg;
  }
  .popover--arrow.popover--block-start .popover__arrow {
    inset-block: auto calc(-1 * var(--space-1-5));
    rotate: 225deg;
  }
  .popover--arrow.popover--inline-start .popover__arrow,
  .popover--arrow.popover--inline-end .popover__arrow { display: none; }
  /* The arrow keeps its default side when the popover flips. `@container anchored(fallback: …)` would follow it,
     but it's Chromium-only syntax that build-time minifiers (lightningcss in Vite/Storybook) reject — see
     references/css-architecture.md. */

  /* Docs-only: an open popover rendered in the demo flow. */
  .popover.is-open { position: relative; display: block; }

  @media (forced-colors: active) {
    .popover { border-color: CanvasText; }
  }
}

/* ---- css/components/progress.css ---- */
/* progress.css — Progress bar on a native <progress>. Block alias: .progress
   Markup:   <div class="progress">
               <div class="progress__header"><label class="progress__label" for="p1">Uploading inspection photos</label>
                 <span class="progress__value">60%</span></div>
               <progress id="p1" class="progress__bar" max="100" value="60">60%</progress>
               <p class="progress__hint">12 of 20 photos</p></div>
   States:   determinate (value set) · indeterminate (no value → :indeterminate, moving segment)
             · [data-state="complete"] · [data-state="error"] (tone + text change, never color alone)
   Sizes:    .progress--thin (page-top / inline loading, 4px track)
   Motion:   indeterminate segment slides (slower, linear); stopped by base.css under reduced motion. */
@layer components {
  .progress {
    --_track: var(--color-bg-muted);
    --_fill: var(--color-action-primary-bg);
    --_h: var(--space-2);

    display: grid;
    gap: var(--space-1-5);
    font-size: var(--font-size-sm);
  }
  .progress[data-state="complete"] { --_fill: var(--color-feedback-success-icon); }
  .progress[data-state="error"] { --_fill: var(--color-feedback-danger-icon); }
  .progress--thin { --_h: var(--space-1); }

  .progress__header { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
  .progress__label { font-weight: var(--font-weight-medium); color: var(--color-text-default); }
  .progress__value { font-variant-numeric: tabular-nums; color: var(--color-text-muted); }
  .progress__hint { display: flex; align-items: center; gap: var(--space-1-5); margin: 0; color: var(--color-text-muted); }
  .progress[data-state="complete"] .progress__hint { color: var(--color-feedback-success-fg); }
  .progress[data-state="error"] .progress__hint { color: var(--color-feedback-danger-fg); }
  .progress__hint > svg { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); flex-shrink: 0; stroke-width: var(--icon-stroke); }

  .progress__bar {
    appearance: none;
    display: block;
    inline-size: 100%;
    block-size: var(--_h);
    border: 0;
    border-radius: var(--radius-full);
    background: var(--_track);
    color: var(--_fill);
    overflow: hidden;
  }
  .progress__bar::-webkit-progress-bar { background: var(--_track); border-radius: var(--radius-full); }
  .progress__bar::-webkit-progress-value {
    background: var(--_fill);
    border-radius: var(--radius-full);
    transition: inline-size var(--motion-duration-base) var(--motion-easing-standard);
  }
  .progress__bar::-moz-progress-bar { background: var(--_fill); border-radius: var(--radius-full); }

  /* Indeterminate: a 35% segment sweeping the track. */
  .progress__bar:indeterminate {
    background:
      linear-gradient(to right, transparent 0 35%, var(--_fill) 35% 70%, transparent 70%) 0 0 / 300% 100% no-repeat,
      var(--_track);
    animation: progress-sweep calc(var(--motion-duration-slower) * 3) linear infinite;
  }
  .progress__bar:indeterminate::-webkit-progress-bar { background: transparent; }
  .progress__bar:indeterminate::-moz-progress-bar { background: transparent; }
  .progress__bar:indeterminate:dir(rtl) { animation-direction: reverse; }

  @media (forced-colors: active) {
    .progress__bar { border: var(--border-width-thin) solid CanvasText; }
    .progress__bar::-webkit-progress-value { background: Highlight; }
    .progress__bar::-moz-progress-bar { background: Highlight; }
  }
}

@keyframes progress-sweep {
  from { background-position: 100% 0, 0 0; }
  to { background-position: 0% 0, 0 0; }
}

/* ---- css/components/radio.css ---- */
/* radio.css — Radio and radio group. Block alias: .radio
   Item:      <div class="radio">
                <input class="radio__input" type="radio" name="…" id="…" [aria-describedby="…-hint"]>
                <label class="radio__label" for="…">…</label>
                <p class="radio__hint" id="…-hint">…</p>             (optional)
              </div>
   Group:     <fieldset class="fieldset radio-group" aria-describedby="…hint …error">
                <legend class="fieldset__legend">…</legend> [.field__hint] [.field__error]
                <div class="radio-group__items"> .radio × n </div>
              </fieldset>
   Modifiers: .radio-group--horizontal (wrapping row, short answers only),
              .radio-group--cards (each .radio becomes a bordered tile; the label stretches over it)
   States:    :checked, :disabled, :user-invalid (required radios after interaction), group error = a
              .field__error inside the group. Arrow keys between radios are native (same name).
              Docs-only freeze classes: .is-hover, .is-focus-visible. */
@layer components {
  .radio {
    --_size: var(--icon-size-lg);
    --_bg: var(--input-bg);
    --_border: var(--input-border);
    --_dot: transparent;

    display: grid;
    grid-template-columns: var(--_size) minmax(0, 1fr);
    column-gap: var(--space-3);
    row-gap: var(--space-1);
    align-items: start;
    min-inline-size: 0;
  }

  .radio__input {
    appearance: none;
    display: grid;
    place-content: center;
    inline-size: var(--_size);
    block-size: var(--_size);
    margin: 0;
    border: var(--border-width-thick) solid var(--_border);
    border-radius: var(--radius-full);
    background: var(--_bg);
    cursor: pointer;
    transition: border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .radio__input::before {
    content: "";
    inline-size: calc(var(--_size) / 2);
    block-size: calc(var(--_size) / 2);
    border-radius: var(--radius-full);
    background: var(--_dot);
    transform: scale(0);
    transition: transform var(--motion-duration-fast) var(--motion-easing-standard);
  }

  .radio__label {
    padding-block-start: calc((var(--_size) - 1lh) / 2);
    color: var(--color-text-default);
    font-size: var(--font-size-md);
    line-height: var(--font-line-height-snug);
    cursor: pointer;
  }
  .radio__title { display: block; font-weight: var(--font-weight-semibold); }
  .radio__hint {
    grid-column: 2;
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-snug);
  }

  /* Hover */
  .radio__input:hover:not(:disabled),
  .radio:has(> .radio__label:hover) > .radio__input:not(:disabled, :checked),
  .radio__input.is-hover { --_border: var(--color-text-default); }

  /* Checked: ring in the action color + filled centre dot (shape, not only color) */
  .radio__input:checked {
    --_border: var(--color-action-primary-bg);
    --_dot: var(--color-action-primary-bg);
  }
  .radio__input:checked::before { transform: scale(1); }
  .radio__input:checked:hover:not(:disabled),
  .radio__input:checked.is-hover {
    --_border: var(--color-action-primary-bg-hover);
    --_dot: var(--color-action-primary-bg-hover);
  }

  /* Focus */
  .radio__input:focus-visible,
  .radio__input.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Invalid */
  .radio__input:user-invalid,
  .radio-group:has(> .field__error) .radio__input:not(:checked, :disabled) {
    --_border: var(--color-border-invalid);
  }
  .radio-group:has(> .field__error):not(.radio-group--cards) {
    padding-inline-start: var(--space-4);
    border-inline-start: var(--border-width-thick) solid var(--color-border-invalid);
  }

  /* Disabled — both values */
  .radio__input:disabled {
    --_bg: var(--color-bg-muted);
    --_border: var(--color-border-default);
    --_dot: var(--color-text-disabled);
    cursor: not-allowed;
  }
  .radio:has(> .radio__input:disabled) .radio__label {
    color: var(--color-text-disabled);
    cursor: not-allowed;
  }

  /* Group layout */
  .radio-group__items { display: grid; gap: var(--space-3); }
  .radio-group--horizontal .radio-group__items {
    display: flex;
    flex-wrap: wrap;
    column-gap: var(--space-6);
    row-gap: var(--space-3);
  }

  /* Cards: whole tile is the hit area (label ::after stretches over it), selected = border + tint + dot. */
  .radio-group--cards .radio-group__items {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  }
  .radio-group--cards .radio {
    --_card-border: var(--color-border-default);
    position: relative;
    padding: var(--space-4);
    border: var(--border-width-thin) solid var(--_card-border);
    border-radius: var(--radius-md);
    background: var(--color-bg-surface);
    box-shadow: inset 0 0 0 var(--_card-ring, 0) var(--_card-border);
  }
  .radio-group--cards .radio__label::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
  }
  .radio-group--cards .radio__hint { position: relative; pointer-events: none; }
  .radio-group--cards .radio:hover:not(:has(:disabled)),
  .radio-group--cards .radio:has(.is-hover) { --_card-border: var(--color-text-muted); }
  .radio-group--cards .radio:has(> .radio__input:checked) :is(.radio__label, .radio__hint) { color: var(--color-selected-fg); }
  .radio-group--cards .radio:has(> .radio__input:checked) {
    --_card-border: var(--color-selected-border);
    --_card-ring: var(--border-width-thin);
    background: var(--color-selected-bg);
  }
  .radio-group--cards .radio:has(> .radio__input:focus-visible),
  .radio-group--cards .radio:has(> .radio__input.is-focus-visible) {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
  .radio-group--cards .radio__input:focus-visible { outline-color: transparent; }
  .radio-group--cards .radio:has(> .radio__input:disabled) { background: var(--color-bg-subtle); }
  .radio-group--cards:has(> .field__error) .radio:not(:has(:checked)) { --_card-border: var(--color-border-invalid); }

  @media (forced-colors: active) {
    .radio__input { border-color: CanvasText; background: Canvas; }
    .radio__input:checked { border-color: Highlight; }
    .radio__input::before { forced-color-adjust: none; background: Highlight; }
    .radio__input:disabled { border-color: GrayText; }
    .radio__input:disabled::before { background: GrayText; }
    .radio:has(:disabled) .radio__label { color: GrayText; }
    .radio-group--cards .radio { border-color: CanvasText; }
    .radio-group--cards .radio:has(:checked) { border-color: Highlight; }
    .radio-group--cards .radio:has(:focus-visible) { outline-color: Highlight; }
  }
}

/* ---- css/components/result-panel.css ---- */
/* result-panel.css — Outcome of an action or process. Block alias: .result
   Markup:   <section class="result result--success" aria-labelledby="r-title">
               <span class="result__icon" aria-hidden="true"><svg>…</svg></span>
               <h2 id="r-title" class="result__title" tabindex="-1">Work order WO-1042 closed</h2>
               <p class="result__description">…<code class="result__reference">WO-1042</code></p>
               <div class="result__actions">…</div>
               <details class="result__details">…</details></section>
   Tones:    .result--success | --error | --warning | --info | --no-permission (neutral, lock icon)
   Layout:   centered column, max one measure wide; .result--page adds page-level spacing (title is the <h1>).
   Pattern:  tones only set --_icon-bg / --_icon-fg. Tone is carried by icon + title words, not color. */
@layer components {
  .result {
    --_icon-bg: var(--color-feedback-info-bg);
    --_icon-fg: var(--color-feedback-info-icon);

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    max-inline-size: var(--size-measure);
    margin-inline: auto;
    padding-block: var(--space-8);
    padding-inline: var(--space-4);
    text-align: center;
    color: var(--color-text-default);
  }
  .result--page { padding-block: var(--space-16); }
  .result--success { --_icon-bg: var(--color-feedback-success-bg); --_icon-fg: var(--color-feedback-success-icon); }
  .result--error { --_icon-bg: var(--color-feedback-danger-bg); --_icon-fg: var(--color-feedback-danger-icon); }
  .result--warning { --_icon-bg: var(--color-feedback-warning-bg); --_icon-fg: var(--color-feedback-warning-icon); }
  .result--no-permission { --_icon-bg: var(--color-bg-muted); --_icon-fg: var(--color-text-muted); }

  .result__icon {
    display: grid;
    place-items: center;
    inline-size: var(--space-16);
    block-size: var(--space-16);
    margin-block-end: var(--space-2);
    border-radius: var(--radius-full);
    background: var(--_icon-bg);
    color: var(--_icon-fg);
  }
  .result__icon > svg { inline-size: var(--space-8); block-size: var(--space-8); stroke-width: var(--icon-stroke); }
  .result__title {
    font-family: var(--typography-h3-font-family);
    font-size: var(--typography-h3-font-size);
    font-weight: var(--typography-h3-font-weight);
    line-height: var(--typography-h3-line-height);
  }
  .result__title:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
  .result__description { margin: 0; color: var(--color-text-muted); text-wrap: pretty; }
  .result__reference {
    padding-inline: var(--space-1);
    border-radius: var(--radius-sm);
    background: var(--color-bg-muted);
    color: var(--color-text-default);
    font-family: var(--typography-code-font-family);
    font-size: var(--typography-code-font-size);
    user-select: all;
  }
  .result__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--space-3);
    margin-block-start: var(--space-3);
  }
  .result__details {
    align-self: stretch;
    margin-block-start: var(--space-3);
    padding-block: var(--space-3);
    padding-inline: var(--space-4);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: var(--color-bg-subtle);
    text-align: start;
    font-size: var(--font-size-sm);
  }
  .result__details > summary { cursor: pointer; font-weight: var(--font-weight-medium); }
  .result__details > summary:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
  .result__details[open] > summary { margin-block-end: var(--space-2); }
  .result__details dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-1) var(--space-4); margin: 0; }
  .result__details dt { color: var(--color-text-muted); }
  .result__details dd { margin: 0; font-family: var(--typography-code-font-family); overflow-wrap: anywhere; }

  @media (forced-colors: active) {
    .result__icon { border: var(--border-width-thin) solid CanvasText; }
  }
}

/* ---- css/components/search-input.css ---- */
/* search-input.css — query field inside a search landmark. Block alias: .search
   Builds on .input--affixed (text-field.css) for border, focus ring and sizes:
     <search class="search">
       <form class="search__form" action="/vehicles" method="get">
         <label class="label" for="q">Search vehicles</label>       (or .sr-only when a heading names it)
         <div class="input input--affixed search__box">
           <svg class="search__icon" aria-hidden="true">…</svg>
           <input class="input__control search__control" type="search" id="q" name="q">
           <span class="search__spinner" aria-hidden="true"></span>
           <kbd class="search__kbd" aria-hidden="true">/</kbd>              (optional shortcut hint)
           <button type="button" class="search__clear" aria-label="Clear search" hidden>…</button>
         </div>
         <p class="search__status sr-only" role="status"></p>
       </form>
     </search>
   States:    empty, filled (clear button shown by js/search-input.js), loading = aria-busy="true" on
              .search__box (spinner replaces the shortcut hint; status text announced).
   Docs-only freeze classes on the clear button: .is-hover, .is-focus-visible. */
@layer components {
  .search { display: block; min-inline-size: 0; }
  .search__form { display: grid; gap: var(--space-1-5); max-inline-size: var(--field-max, 32rem); }

  .search__icon {
    flex-shrink: 0;
    inline-size: var(--icon-size-md);
    block-size: var(--icon-size-md);
    color: var(--color-text-muted);
    stroke-width: var(--icon-stroke);
  }
  .search__box { padding-inline-end: var(--space-1); }
  /* Native clear "x" is replaced by .search__clear once the script has enhanced the field. */
  .search[data-enhanced] .search__control::-webkit-search-cancel-button { appearance: none; }

  .search__kbd {
    flex-shrink: 0;
    display: inline-grid;
    place-content: center;
    min-inline-size: var(--icon-size-lg);
    block-size: var(--icon-size-lg);
    margin-inline-end: var(--space-1);
    padding-inline: var(--space-1);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-sm);
    background: var(--color-bg-subtle);
    color: var(--color-text-muted);
    font-family: var(--font-family-mono);
    font-size: var(--font-size-xs);
  }
  /* Hint hides once there is a query or the field is focused (the shortcut is already used). */
  .search__box:has(.search__control:focus),
  .search__box:has(.search__control:not(:placeholder-shown)) { --_kbd-display: none; }
  .search__kbd { display: var(--_kbd-display, inline-grid); }

  .search__clear {
    --_bg: var(--color-action-ghost-bg);
    flex-shrink: 0;
    display: inline-grid;
    place-content: center;
    inline-size: calc(var(--size-control-md) - var(--space-2));
    block-size: calc(var(--size-control-md) - var(--space-2));
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--_bg);
    color: var(--color-text-muted);
    cursor: pointer;
  }
  .search__clear .icon { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); }
  .search__clear:hover,
  .search__clear.is-hover { --_bg: var(--color-action-ghost-bg-hover); color: var(--color-text-default); }
  .search__clear:focus-visible,
  .search__clear.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: 0;
  }

  /* Loading */
  .search__spinner {
    display: none;
    flex-shrink: 0;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    margin-inline-end: var(--space-2);
    border: var(--border-width-thick) solid var(--color-border-default);
    border-block-start-color: var(--color-action-primary-bg);
    border-radius: var(--radius-full);
    animation: search-spin calc(var(--motion-duration-slower) * 1.6) linear infinite;
  }
  .search__box[aria-busy="true"] .search__spinner { display: block; }
  .search__box[aria-busy="true"] .search__kbd { display: none; }

  @media (forced-colors: active) {
    .search__clear { color: ButtonText; }
    .search__kbd { border-color: CanvasText; }
    .search__spinner { border-color: CanvasText; border-block-start-color: Highlight; }
  }
}
@keyframes search-spin { to { transform: rotate(1turn); } }

/* ---- css/components/select.css ---- */
/* select.css — native select, restyled. Block alias: .select
   Markup:    <div class="select [select--sm|--lg]">
                <select class="select__control" id="…" name="…">…</select>
              </div>
              The wrapper only draws the chevron (a masked ::after in currentColor, so it follows themes
              and forced colors); the <select> keeps all semantics, keyboard and the OS picker.
   Sizes:     .select--sm | (md) | .select--lg → --size-control-* (line up with .input and .btn)
   States:    :hover, :focus-visible, :disabled, aria-invalid="true" | :user-invalid,
              read-only = aria-readonly="true" with only the current option rendered (select has no
              readonly attribute). Docs-only freeze classes on the control: .is-hover, .is-focus-visible.
   Progressive: appearance: base-select (customizable select, Chrome 135+/Safari 27) styles the picker
              with the same tokens; other browsers keep the native picker. */
@layer components {
  .select {
    --_h: var(--size-control-md);
    --_px: var(--space-3);
    --_chevron: var(--icon-size-sm);

    position: relative;
    display: block;
    min-inline-size: 0;
    max-inline-size: 100%;
    color: var(--color-text-muted);
  }
  .select--sm { --_h: var(--size-control-sm); --_px: var(--space-2); }
  .select--lg { --_h: var(--size-control-lg); --_px: var(--space-4); --_chevron: var(--icon-size-md); }

  .select::after {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-end: var(--_px);
    inline-size: var(--_chevron);
    background: currentColor;
    -webkit-mask: var(--_glyph) center / contain no-repeat;
    mask: var(--_glyph) center / contain no-repeat;
    pointer-events: none;
    --_glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='m6 9 6 6 6-6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  }

  .select__control {
    --_border: var(--input-border);
    --_bg: var(--input-bg);

    appearance: none;
    display: block;
    inline-size: 100%;
    block-size: var(--_h);
    margin: 0;
    padding-block: 0;
    padding-inline-start: var(--_px);
    padding-inline-end: calc(var(--_px) + var(--_chevron) + var(--space-2));
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--input-radius);
    background: var(--_bg);
    color: var(--color-text-default);
    font-family: inherit;
    font-size: var(--font-size-md);
    line-height: var(--font-line-height-normal);
    text-overflow: ellipsis;
    cursor: pointer;
    transition: border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .select--sm .select__control { font-size: var(--font-size-sm); }
  /* Placeholder option ("Choose a depot") reads as a prompt, not a value */
  .select__control:has(option[value=""]:checked) { color: var(--color-text-muted); }
  .select__control option { color: var(--color-text-default); }

  /* Hover */
  .select__control:hover:not(:disabled, [aria-readonly="true"]),
  .select__control.is-hover { --_border: var(--color-text-muted); }
  .select:has(.select__control:hover:not(:disabled)) { color: var(--color-text-default); }

  /* Focus */
  .select__control:focus-visible,
  .select__control.is-focus-visible {
    --_border: var(--color-border-focus);
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Invalid */
  .select__control[aria-invalid="true"],
  .select__control:user-invalid {
    --_border: var(--color-border-invalid);
    box-shadow: inset 0 0 0 var(--border-width-thin) var(--_border);
  }

  /* Read-only: focusable, value readable and submitted, no chevron */
  .select__control[aria-readonly="true"] {
    --_bg: var(--color-bg-subtle);
    --_border: var(--color-border-default);
    padding-inline-end: var(--_px);
    cursor: default;
  }
  .select:has(> .select__control[aria-readonly="true"])::after { display: none; }

  /* Disabled */
  .select__control:disabled {
    --_bg: var(--color-bg-muted);
    --_border: var(--color-border-subtle);
    color: var(--color-text-disabled);
    cursor: not-allowed;
  }
  .select:has(> .select__control:disabled) { color: var(--color-text-disabled); }

  /* Customizable select — refinement only; unsupported browsers drop these rules. */
  @supports (appearance: base-select) {
    .select__control,
    .select__control::picker(select) { appearance: base-select; }
    .select__control::picker-icon { display: none; }
    .select__control::picker(select) {
      margin-block: var(--space-1);
      padding: var(--space-1);
      border: var(--border-width-thin) solid var(--color-border-default);
      border-radius: var(--overlay-radius);
      background: var(--color-bg-overlay);
      box-shadow: var(--overlay-shadow);
    }
    .select__control option {
      padding-block: var(--space-2);
      padding-inline: var(--space-3);
      border-radius: var(--radius-sm);
    }
    .select__control option:is(:hover, :focus-visible) { background: var(--color-bg-subtle); }
    .select__control option:checked { background: var(--color-selected-bg); color: var(--color-selected-fg); }
    .select__control optgroup { color: var(--color-text-muted); font-size: var(--font-size-sm); font-weight: var(--font-weight-semibold); }
  }

  @media (forced-colors: active) {
    .select__control { border-color: CanvasText; }
    .select::after { forced-color-adjust: none; background: CanvasText; }
    .select:has(:disabled)::after { background: GrayText; }
    .select__control:disabled { border-color: GrayText; color: GrayText; }
  }
}

/* ---- css/components/side-nav.css ---- */
/* side-nav.css — Sidebar navigation. Block: .side-nav (<nav aria-label="…">)
   Parts:   .side-nav__header (collapse button row), .side-nav__collapse (.icon-btn, aria-expanded, js/side-nav.js),
            .side-nav__section, .side-nav__heading (section heading, next heading level), .side-nav__list,
            .side-nav__link (a; aria-current="page" = current: selected bg + inline-start bar + weight),
            .side-nav__icon (svg), .side-nav__label, .side-nav__count (tabular count; put meaning in text, e.g. "12 open"),
            .side-nav__group (<details>; nested group, max 2 levels), .side-nav__summary (its <summary>, also .side-nav__link),
            .side-nav__chevron (rotates when open), .side-nav__list--nested
   State:   [data-collapsed] on .side-nav → icons only; labels stay in the accessibility tree (clipped, not removed),
            nested lists hide. Collapse state is the button's aria-expanded and is persisted by js/side-nav.js.
   Docs-only freeze: .is-hover, .is-focus-visible on a link. */
@layer components {
  .side-nav {
    --_w: 16rem;
    --_rail: calc(var(--size-control-md) + var(--space-4));

    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    inline-size: var(--_w);
    max-inline-size: 100%;
    padding: var(--space-2);
    background: var(--color-bg-surface);
    border-inline-end: var(--border-width-thin) solid var(--color-border-default);
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
    transition: inline-size var(--motion-duration-base) var(--motion-easing-standard);
  }
  .side-nav[data-collapsed] { inline-size: var(--_rail); }

  .side-nav__header { display: flex; justify-content: flex-end; }
  .side-nav__collapse-icon { transition: transform var(--motion-duration-fast) var(--motion-easing-standard); }
  .side-nav__collapse-icon:dir(rtl),
  .side-nav[data-collapsed] .side-nav__collapse-icon { transform: scaleX(-1); }
  .side-nav[data-collapsed] .side-nav__collapse-icon:dir(rtl) { transform: none; }

  .side-nav__section { display: grid; gap: var(--space-1); }
  .side-nav__heading {
    padding-inline: var(--space-3);
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--font-tracking-wide);
    text-transform: uppercase;
  }

  .side-nav__list {
    display: grid;
    gap: var(--space-0-5);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .side-nav__list--nested { padding-block-start: var(--space-0-5); padding-inline-start: var(--space-6); }

  .side-nav__link {
    --_bar: transparent;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-block-size: var(--size-control-md);
    padding-inline: var(--space-2) var(--space-3);
    border-inline-start: var(--border-width-thick) solid var(--_bar);
    border-radius: var(--radius-md);
    color: var(--color-text-muted);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .side-nav__link:hover,
  .side-nav__link.is-hover { background: var(--color-action-ghost-bg-hover); color: var(--color-text-default); }
  .side-nav__link:focus-visible,
  .side-nav__link.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: calc(var(--focus-ring-width) * -1);
  }
  .side-nav__link[aria-current="page"] {
    --_bar: var(--color-selected-border);
    background: var(--color-selected-bg);
    color: var(--color-selected-fg);
    font-weight: var(--font-weight-semibold);
  }
  [data-density="compact"] .side-nav__link { min-block-size: var(--size-control-sm); }

  .side-nav__icon,
  .side-nav__chevron {
    flex-shrink: 0;
    inline-size: var(--icon-size-md);
    block-size: var(--icon-size-md);
    stroke-width: var(--icon-stroke);
  }
  .side-nav__label { flex: 1; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .side-nav__count {
    min-inline-size: var(--space-6);
    padding-inline: var(--space-1-5);
    border-radius: var(--radius-full);
    background: var(--color-bg-muted);
    color: var(--color-text-default);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
    text-align: center;
  }

  /* Nested group (<details>) */
  .side-nav__summary { list-style: none; }
  .side-nav__summary::-webkit-details-marker { display: none; }
  .side-nav__chevron { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); transition: transform var(--motion-duration-fast) var(--motion-easing-standard); }
  .side-nav__group[open] > .side-nav__summary .side-nav__chevron { transform: rotate(180deg); }
  .side-nav__group:has([aria-current="page"]) > .side-nav__summary { color: var(--color-text-default); font-weight: var(--font-weight-semibold); }

  /* Collapsed: icons only; labels clipped (still the accessible name), tooltips via title on the link. */
  .side-nav[data-collapsed] :is(.side-nav__label, .side-nav__heading, .side-nav__count) {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .side-nav[data-collapsed] :is(.side-nav__chevron, .side-nav__list--nested) { display: none; }
  .side-nav[data-collapsed] .side-nav__header { justify-content: center; }
  .side-nav[data-collapsed] .side-nav__link { justify-content: center; padding-inline: 0; }

  @media (forced-colors: active) {
    .side-nav__link[aria-current="page"] { border-inline-start-color: Highlight; forced-color-adjust: none; background: Canvas; color: CanvasText; }
  }
}

/* ---- css/components/skeleton.css ---- */
/* skeleton.css — Placeholder geometry while content loads. Block alias: .skeleton
   Markup:   <div class="skeleton-group" aria-busy="true">
               <span class="sr-only" role="status">Loading vehicle list…</span>
               <div aria-hidden="true"> ….skeleton blocks… </div></div>
   Shapes:   .skeleton--text (one line; widths .skeleton--w-40 | -60 | -80 | default 100%) | .skeleton--heading
             | .skeleton--avatar (circle) | .skeleton--media (16:9 block) | .skeleton--cell (table cell bar)
   Layouts:  .skeleton-card (media + lines, matches .card), .skeleton-table (rows with --density cell padding)
   Motion:   shimmer sweeps every 1.5s; base.css stops it under reduced motion (static blocks remain). */
@layer components {
  .skeleton-group { display: grid; gap: var(--space-3); }

  .skeleton {
    display: block;
    inline-size: 100%;
    block-size: var(--space-4);
    border-radius: var(--radius-sm);
    background:
      linear-gradient(to right, transparent 0%, var(--color-bg-subtle) 50%, transparent 100%) 0 0 / 50% 100% no-repeat,
      var(--color-bg-muted);
    animation: skeleton-shimmer calc(var(--motion-duration-slower) * 3) var(--motion-easing-standard) infinite;
  }
  .skeleton--text { block-size: 1em; }
  .skeleton--heading { block-size: var(--space-6); inline-size: 60%; }
  .skeleton--w-40 { inline-size: 40%; }
  .skeleton--w-60 { inline-size: 60%; }
  .skeleton--w-80 { inline-size: 80%; }
  .skeleton--avatar {
    inline-size: var(--size-control-md);
    block-size: var(--size-control-md);
    border-radius: var(--radius-full);
    flex-shrink: 0;
  }
  .skeleton--media { block-size: auto; aspect-ratio: 16 / 9; border-radius: var(--radius-md); }
  .skeleton--cell { block-size: var(--space-3); }

  .skeleton-row { display: flex; align-items: center; gap: var(--space-3); }
  .skeleton-lines { flex: 1; display: grid; gap: var(--space-2); }

  .skeleton-card {
    display: grid;
    gap: var(--space-3);
    padding: var(--space-4);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-lg);
    background: var(--color-elevation-surface-raised);
  }

  .skeleton-table { display: grid; border: var(--border-width-thin) solid var(--color-border-default); border-radius: var(--radius-md); }
  .skeleton-table__row {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 1fr;
    gap: var(--space-4);
    padding-block: var(--density-comfortable-cell-padding-y);
    padding-inline: var(--space-4);
    border-block-end: var(--border-width-thin) solid var(--color-border-default);
  }
  .skeleton-table__row:last-child { border-block-end: 0; }
  .skeleton-table__row--head { background: var(--color-bg-subtle); }
  [data-density="compact"] .skeleton-table__row { padding-block: var(--density-compact-cell-padding-y); }

  .skeleton:dir(rtl) { animation-direction: reverse; }

  @media (forced-colors: active) {
    .skeleton { background: Canvas; border: var(--border-width-thin) solid GrayText; }
  }
}

@keyframes skeleton-shimmer {
  from { background-position: -100% 0, 0 0; }
  to { background-position: 200% 0, 0 0; }
}

/* ---- css/components/skip-link.css ---- */
/* skip-link.css — Skip link. Block: .skip-link
   Markup: first focusable element in <body>: <a class="skip-link" href="#main">Skip to main content</a>,
           target <main id="main" tabindex="-1">. Several are fine (.skip-link + .skip-link: "Skip to search").
   States: hidden (clipped off-screen, still in the tab order) → :focus-visible / :focus shows it at the top inline-start
           corner above sticky headers. Docs-only freeze: .is-focus-visible (shows it in place), .skip-link--preview
           (renders in flow instead of fixed so docs can show it inside a demo card). */
@layer components {
  .skip-link {
    position: fixed;
    inset-block-start: var(--space-2);
    inset-inline-start: var(--space-2);
    z-index: var(--z-tooltip);
    padding-block: var(--space-2);
    padding-inline: var(--space-4);
    border-radius: var(--button-radius);
    background: var(--color-action-primary-bg);
    color: var(--color-action-primary-fg);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    text-decoration: underline;
    text-underline-offset: 0.2em;
    box-shadow: var(--elevation-overlay);
  }
  /* Hidden until focused — clipped rather than display:none so it stays in the tab order. */
  .skip-link:not(:focus, .is-focus-visible) {
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .skip-link:focus-visible,
  .skip-link.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
  .skip-link--preview { position: static; display: inline-block; }

  @media (forced-colors: active) {
    .skip-link { border: var(--border-width-thick) solid CanvasText; }
  }
}

/* ---- css/components/spinner.css ---- */
/* spinner.css — Spinner (indeterminate processing) and inline spinner. Block aliases: .spinner, .inline-spinner
   Markup:   <div class="spinner" role="status"><span class="spinner__ring" aria-hidden="true"></span>
               <span class="sr-only">Loading service history…</span></div>
             Visible label: .spinner--labelled + <span class="spinner__label">Loading service history…</span>
   Sizes:    .spinner--sm (16px) | (md default, 24px) | .spinner--lg (40px)
   Inline:   <span class="inline-spinner" aria-hidden="true"></span> — 1em, currentColor, sits next to text or
             inside a control; the control/region carries aria-busy="true" and a role="status" says what's happening.
   Delay:    the spinner fades in after --motion-duration-slow so quick responses never flash a loader.
   Motion:   rotation stops under reduced motion (base.css); the ring and the text still say "loading". */
@layer components {
  .spinner {
    --_size: var(--icon-size-lg);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-action-primary-bg);
    animation: spinner-reveal var(--motion-duration-instant) step-end var(--motion-duration-slow) both;
  }
  .spinner--sm { --_size: var(--icon-size-sm); }
  .spinner--lg { --_size: var(--size-control-md); }
  .spinner--labelled { color: var(--color-text-muted); font-size: var(--font-size-sm); }
  .spinner--labelled .spinner__ring { color: var(--color-action-primary-bg); }
  .spinner--stacked { flex-direction: column; }

  .spinner__ring,
  .inline-spinner {
    display: inline-block;
    flex-shrink: 0;
    inline-size: var(--_size);
    block-size: var(--_size);
    border: var(--border-width-thick) solid currentColor;
    border-inline-end-color: transparent;
    border-radius: var(--radius-full);
    animation: spinner-rotate calc(var(--motion-duration-slower) * 1.6) linear infinite;
  }
  .spinner--lg .spinner__ring { border-width: calc(var(--border-width-thick) * 2); }
  .spinner__label { color: inherit; }

  .inline-spinner {
    --_size: 1em;
    vertical-align: -0.125em;
  }

  @media (forced-colors: active) {
    .spinner__ring, .inline-spinner { border-color: CanvasText; border-inline-end-color: transparent; }
  }
}

@keyframes spinner-rotate { to { transform: rotate(1turn); } }
@keyframes spinner-reveal { from { opacity: 0; } to { opacity: 1; } }

/* ---- css/components/stack.css ---- */
/* stack.css — one-dimensional layout. The parent owns spacing; children stay margin-free.
   Blocks: .stack (vertical), .cluster (wrapping row)
   Modifiers: .stack--horizontal, .stack--gap-1 | -2 | -3 | -4 (default) | -6 | -8,
              .stack--align-center, .cluster--between
   Custom property: --stack-gap / --cluster-gap (only assign a --space-* token) */
@layer components {
  .stack {
    display: flex;
    flex-direction: column;
    gap: var(--stack-gap, var(--space-4));
    min-inline-size: 0;
  }
  .stack--horizontal { flex-direction: row; align-items: center; }
  .stack--align-center { align-items: center; }

  .stack--gap-1 { --stack-gap: var(--space-1); }
  .stack--gap-2 { --stack-gap: var(--space-2); }
  .stack--gap-3 { --stack-gap: var(--space-3); }
  .stack--gap-4 { --stack-gap: var(--space-4); }
  .stack--gap-6 { --stack-gap: var(--space-6); }
  .stack--gap-8 { --stack-gap: var(--space-8); }

  .cluster {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--cluster-gap, var(--space-2));
  }
  .cluster--between { justify-content: space-between; }
}

/* ---- css/components/stat.css ---- */
/* stat.css — Metric / statistic. Block alias: .stat
   Markup:   <div class="stat"> <dl class="stat__body"><dt class="stat__label">…</dt><dd class="stat__value">…</dd></dl> …
             (or a plain <div> structure; group several in a .stat-group)
   Parts:    .stat__label, .stat__value (large, tabular numerals), .stat__unit, .stat__delta (arrow icon + text,
             direction is in the words: "Up 1.2 pts vs last week"), .stat__note, .stat__sparkline (decorative SVG,
             aria-hidden — the delta text carries the trend)
   Delta tone: .stat__delta--good | --bad | --flat → feedback success/danger/neutral pairs. Tone follows meaning,
             not direction: more uptime is good, more overdue services is bad.
   States:   aria-busy="true" on .stat = loading skeleton (keep the label visible; sr-only text says what loads)
   Layout:   .stat-group — auto-fit grid of stats. */
@layer components {
  .stat {
    display: grid;
    align-content: start;
    gap: var(--space-2);
    padding: var(--space-5);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--card-radius);
    background: var(--color-elevation-surface-raised);
    color: var(--color-text-default);
    font-variant-numeric: tabular-nums;
  }
  .stat__body { display: grid; gap: var(--space-1); margin: 0; }
  .stat__label {
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
  }
  .stat__value {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-1);
    margin: 0;
    font-size: var(--font-size-3xl);
    font-weight: var(--font-weight-semibold);
    line-height: var(--font-line-height-tight);
    letter-spacing: var(--font-tracking-tight);
  }
  .stat__unit {
    color: var(--color-text-muted);
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--font-tracking-normal);
  }
  .stat__note { color: var(--color-text-muted); font-size: var(--font-size-sm); }

  .stat__delta {
    --_bg: var(--color-bg-subtle);
    --_fg: var(--color-text-default);
    --_border: var(--color-border-default);
    justify-self: start;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding-block: var(--space-0-5);
    padding-inline: var(--space-2);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--radius-full);
    background: var(--_bg);
    color: var(--_fg);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
  }
  .stat__delta--good { --_bg: var(--color-feedback-success-bg); --_fg: var(--color-feedback-success-fg); --_border: var(--color-feedback-success-border); }
  .stat__delta--bad  { --_bg: var(--color-feedback-danger-bg);  --_fg: var(--color-feedback-danger-fg);  --_border: var(--color-feedback-danger-border); }
  .stat__delta--flat { --_bg: var(--color-bg-subtle); --_fg: var(--color-text-default); --_border: var(--color-border-default); }
  .stat__delta svg {
    flex-shrink: 0;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
  }

  .stat__sparkline {
    inline-size: 100%;
    block-size: var(--space-10);
    color: var(--dataviz-categorical-1);
    overflow: visible;
  }
  .stat__sparkline path { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
  .stat__sparkline circle { fill: currentColor; }

  /* Loading skeleton */
  .stat__skeleton {
    display: block;
    block-size: var(--space-4);
    inline-size: 60%;
    border-radius: var(--radius-sm);
    background: var(--color-bg-muted);
    animation: stat-pulse calc(var(--motion-duration-slower) * 3) var(--motion-easing-standard) infinite alternate;
  }
  .stat__skeleton--value { block-size: var(--space-8); inline-size: 45%; }
  .stat__skeleton--delta { block-size: var(--space-5); inline-size: 35%; border-radius: var(--radius-full); }
  .stat[aria-busy="true"] { cursor: progress; }

  .stat-group {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
    padding: 0;
    list-style: none;
  }

  @media (forced-colors: active) {
    .stat, .stat__delta { border-color: CanvasText; }
    .stat__sparkline { color: CanvasText; }
    .stat__skeleton { background: GrayText; }
  }
}

@keyframes stat-pulse { from { opacity: 1; } to { opacity: 0.45; } }

/* ---- css/components/swipe-actions.css ---- */
/* swipe-actions.css — List row that reveals actions on a horizontal swipe. Block alias: .swipe-row
   Markup:   <ul class="list-group swipe-list" role="list"> <li class="swipe-row" style="--_lead: 1; --_trail: 2">
               <div class="swipe-row__track">
                 <div class="swipe-row__actions swipe-row__actions--leading" inert> buttons </div>
                 <div class="swipe-row__content"> .swipe-row__main (link + secondary) + "More actions" menu button </div>
                 <div class="swipe-row__actions swipe-row__actions--trailing" inert> buttons, edge action last </div>
               </div></li>
   Behavior: CSS scroll snap does the swipe (momentum, RTL, rubber-banding). Snap points: content start (rest),
             end of the trailing buttons (revealed), end of the trailing zone (full swipe). js/swipe-actions.js puts
             each row at rest, toggles inert on hidden actions, keeps one row open and runs the edge action on a
             full swipe. The same actions are always in the row's menu button (WCAG 2.5.7).
   Parts:    .swipe-row__action (+ --primary | --danger), .swipe-row__link (stretched over the content), .swipe-row__menu
   States:   real ones from scroll position (+ .is-full while a full swipe is armed). Docs-only freeze classes:
             .is-revealed-trailing, .is-revealed-leading, .is-full-swipe, .is-focus-visible.
   Tokens:   --size-swipe-action (each action's width), --size-touch-target (row height).
   Pointer:  fine pointers (mouse, trackpad) don't scroll the row; they use the menu button. */
@layer components {
  .swipe-list { overflow: hidden; align-self: start; align-content: start; }

  .swipe-row {
    --_w: var(--size-swipe-action);
    --_lead: 0;
    --_trail: 0;
    --_zone: 40cqi;
    --_dir: -1;

    position: relative;
    container-type: inline-size;
    list-style: none;
  }
  .swipe-row:dir(rtl) { --_dir: 1; }
  .swipe-row + .swipe-row { border-block-start: var(--border-width-thin) solid var(--color-border-subtle); }

  .swipe-row__track {
    position: relative;
    display: flex;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .swipe-row__track::-webkit-scrollbar { display: none; }
  @media (hover: hover) and (pointer: fine) {
    .swipe-row__track { overflow-x: hidden; }
  }

  .swipe-row__content {
    position: relative;
    flex: 0 0 100%;
    display: flex;
    align-items: center;
    gap: var(--space-3);
    min-block-size: var(--size-touch-target);
    padding-block: var(--space-3);
    padding-inline: var(--space-4) var(--space-2);
    background: var(--color-elevation-surface-raised);
    scroll-snap-align: start;
    scroll-initial-target: nearest;
  }
  .swipe-row__main { display: grid; flex: 1; min-inline-size: 0; }
  .swipe-row__link {
    color: var(--color-text-default);
    font-weight: var(--font-weight-semibold);
    text-decoration: none;
  }
  .swipe-row__link::after { content: ""; position: absolute; inset: 0; }
  .swipe-row__link:focus-visible { outline: var(--focus-ring-width) solid transparent; }   /* the content box shows the ring */
  .swipe-row__content:has(.swipe-row__link:focus-visible),
  .swipe-row.is-focus-visible .swipe-row__content {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: calc(-1 * var(--focus-ring-width));
  }
  .swipe-row__secondary { color: var(--color-text-muted); font-size: var(--typography-small-font-size); }
  .swipe-row__menu { position: relative; z-index: var(--z-raised); flex-shrink: 0; }

  .swipe-row__actions { display: flex; flex: none; }
  .swipe-row__actions--leading { scroll-snap-align: start; }
  .swipe-row__actions--trailing {
    padding-inline-end: var(--_zone);
    background: var(--color-action-primary-bg);
    scroll-snap-align: end;
  }
  .swipe-row__actions--trailing:has(> .swipe-row__action--danger:last-child) { background: var(--color-action-danger-bg); }
  .swipe-row__actions--trailing > :last-child { scroll-snap-align: end; }

  .swipe-row__action {
    display: grid;
    place-items: center;
    inline-size: var(--_w);
    min-block-size: var(--size-touch-target);
    padding-inline: var(--space-2);
    border: 0;
    background: var(--color-action-secondary-bg);
    color: var(--color-action-secondary-fg);
    font: inherit;
    font-size: var(--typography-small-font-size);
    font-weight: var(--font-weight-semibold);
    cursor: pointer;
  }
  .swipe-row__action--primary { background: var(--color-action-primary-bg); color: var(--color-action-primary-fg); }
  .swipe-row__action--danger { background: var(--color-action-danger-bg); color: var(--color-action-danger-fg); }
  .swipe-row__action:focus-visible { outline-offset: calc(-1 * var(--focus-ring-width)); }

  /* Full swipe armed: the edge action's color covers the other actions; its label stays readable. */
  .swipe-row.is-full .swipe-row__actions--trailing > :not(:last-child),
  .swipe-row.is-full-swipe .swipe-row__actions--trailing > :not(:last-child) { visibility: hidden; }

  /* Docs-only freezes: show a scroll position without scrolling (children shift, the track clips). */
  .swipe-row:is(.is-revealed-trailing, .is-revealed-leading, .is-full-swipe, .is-focus-visible) .swipe-row__track {
    overflow: hidden;
    scroll-snap-type: none;   /* a snap container re-snaps even when it can't be scrolled by the user */
  }
  .swipe-row:is(.is-revealed-trailing, .is-revealed-leading, .is-full-swipe, .is-focus-visible) .swipe-row__content { scroll-initial-target: none; }
  .swipe-row:is(.is-revealed-trailing, .is-revealed-leading, .is-full-swipe, .is-focus-visible) .swipe-row__track > * {
    translate: calc(var(--_dir) * var(--_shift));
  }
  .swipe-row { --_shift: calc(var(--_lead) * var(--_w)); }
  .swipe-row.is-revealed-trailing { --_shift: calc((var(--_lead) + var(--_trail)) * var(--_w)); }
  .swipe-row.is-revealed-leading { --_shift: 0px; }
  .swipe-row.is-full-swipe { --_shift: calc((var(--_lead) + var(--_trail)) * var(--_w) + var(--_zone)); }

  @media (forced-colors: active) {
    .swipe-row__action { border: var(--border-width-thin) solid ButtonText; }
    .swipe-row__content:has(.swipe-row__link:focus-visible) { outline-color: Highlight; }
  }
}

/* ---- css/components/switch.css ---- */
/* switch.css — Switch / toggle for settings that apply immediately. Block alias: .switch
   Markup:    <div class="switch">
                <input class="switch__input" type="checkbox" role="switch" id="…" [aria-describedby="…-hint"]>
                <label class="switch__label" for="…">Notify drivers of schedule changes</label>
                <p class="switch__hint" id="…-hint">…</p>              (optional)
              </div>
   Modifiers: .switch--label-start (label first, switch pushed to the inline end — settings lists)
   States:    :checked (on), :disabled (both values), aria-busy="true" on .switch while an async
              change is saving. Docs-only freeze classes: .is-hover, .is-focus-visible.
   Pattern:   native checkbox with appearance:none draws the track; ::before is the thumb. On = thumb
              at the end + filled track (position and fill), so state is never color alone. */
@layer components {
  .switch {
    --_track-h: var(--icon-size-lg);
    --_track-w: calc(var(--icon-size-lg) * 2 - var(--space-1));
    --_thumb: calc(var(--_track-h) - var(--space-1-5));
    --_bg: var(--color-bg-muted);
    --_border: var(--input-border);
    --_thumb-bg: var(--color-text-muted);

    display: grid;
    grid-template-columns: var(--_track-w) minmax(0, 1fr);
    column-gap: var(--space-3);
    row-gap: var(--space-1);
    align-items: start;
    min-inline-size: 0;
  }

  .switch__input {
    appearance: none;
    position: relative;
    display: block;
    inline-size: var(--_track-w);
    block-size: var(--_track-h);
    margin: 0;
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--radius-full);
    background: var(--_bg);
    cursor: pointer;
    transition:
      background-color var(--motion-duration-fast) var(--motion-easing-standard),
      border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .switch__input::before {
    content: "";
    position: absolute;
    inset-block-start: 50%;
    inset-inline-start: var(--space-0-5);
    inline-size: var(--_thumb);
    block-size: var(--_thumb);
    border-radius: var(--radius-full);
    background: var(--_thumb-bg);
    transform: translateY(-50%);
    transition:
      inset-inline-start var(--motion-duration-fast) var(--motion-easing-standard),
      background-color var(--motion-duration-fast) var(--motion-easing-standard);
  }

  .switch__label {
    padding-block-start: calc((var(--_track-h) - 1lh) / 2);
    color: var(--color-text-default);
    font-size: var(--font-size-md);
    line-height: var(--font-line-height-snug);
    cursor: pointer;
  }
  .switch__hint {
    grid-column: 2;
    margin: 0;
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-snug);
  }

  /* Label first, switch at the end (settings rows) */
  .switch--label-start { grid-template-columns: minmax(0, 1fr) var(--_track-w); }
  .switch--label-start .switch__input { grid-column: 2; grid-row: 1; }
  .switch--label-start .switch__label { grid-column: 1; grid-row: 1; }
  .switch--label-start .switch__hint { grid-column: 1; }

  /* Hover */
  .switch__input:hover:not(:disabled),
  .switch:has(> .switch__label:hover) > .switch__input:not(:disabled, :checked),
  .switch__input.is-hover { --_border: var(--color-text-default); --_thumb-bg: var(--color-text-default); }

  /* On */
  .switch__input:checked {
    --_bg: var(--color-action-primary-bg);
    --_border: var(--color-action-primary-bg);
    --_thumb-bg: var(--color-action-primary-fg);
  }
  .switch__input:checked::before {
    inset-inline-start: calc(100% - var(--_thumb) - var(--space-0-5));
  }
  .switch__input:checked:hover:not(:disabled),
  .switch__input:checked.is-hover {
    --_bg: var(--color-action-primary-bg-hover);
    --_border: var(--color-action-primary-bg-hover);
    --_thumb-bg: var(--color-action-primary-fg);
  }

  /* Focus */
  .switch__input:focus-visible,
  .switch__input.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Disabled — both values; the thumb position still tells on/off */
  .switch__input:disabled {
    --_bg: var(--color-bg-subtle);
    --_border: var(--color-border-default);
    --_thumb-bg: var(--color-text-disabled);
    cursor: not-allowed;
  }
  .switch__input:disabled:checked { --_bg: var(--color-bg-muted); }
  .switch:has(> .switch__input:disabled) .switch__label {
    color: var(--color-text-disabled);
    cursor: not-allowed;
  }

  /* Saving (async): thumb pulses, control is inert until the request settles */
  .switch[aria-busy="true"] .switch__input { pointer-events: none; }
  .switch[aria-busy="true"] .switch__input::before {
    animation: switch-pulse var(--motion-duration-slower) var(--motion-easing-standard) infinite alternate;
  }

  @media (forced-colors: active) {
    .switch__input { border-color: CanvasText; background: Canvas; }
    .switch__input::before { forced-color-adjust: none; background: CanvasText; }
    .switch__input:checked { background: Highlight; border-color: Highlight; }
    .switch__input:checked::before { background: HighlightText; }
    .switch__input:disabled { border-color: GrayText; }
    .switch__input:disabled::before { background: GrayText; }
    .switch:has(:disabled) .switch__label { color: GrayText; }
  }
}
@keyframes switch-pulse { to { opacity: var(--opacity-disabled); } }

/* ---- css/components/table.css ---- */
/* table.css — Table (basic). Block alias: .table
   Markup:   <div class="table-wrap" role="region" aria-labelledby="<caption id>" tabindex="0"> <table class="table">…
   Variants: .table--striped | .table--compact | .table--bordered   (default: row dividers only)
   Parts:    caption (.table__caption, visible or .sr-only), th[scope], .table__num (numeric cell: end-aligned,
             tabular-nums), .table__secondary (muted second line inside a cell)
   Wrapper:  .table-wrap — focusable scroll container for horizontal overflow (keyboard users can scroll it).
   Density:  [data-density="compact"] on any ancestor = .table--compact.
   Pattern:  variants only set private custom properties (--_py, --_px, --_stripe, --_cell-border). */
@layer components {
  .table-wrap {
    max-inline-size: 100%;
    overflow-x: auto;
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: var(--color-bg-surface);
  }
  .table-wrap:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  .table {
    --_py: var(--density-comfortable-cell-padding-y);
    --_px: var(--space-4);
    --_stripe: transparent;
    --_cell-border: transparent;

    inline-size: 100%;
    border-collapse: collapse;
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-normal);
    color: var(--color-text-default);
  }

  .table caption,
  .table__caption {
    caption-side: top;
    padding-block: var(--space-3);
    padding-inline: var(--_px);
    text-align: start;
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-semibold);
    color: var(--color-text-default);
  }

  .table th,
  .table td {
    padding-block: var(--_py);
    padding-inline: var(--_px);
    border-block-end: var(--border-width-thin) solid var(--color-border-default);
    border-inline: var(--border-width-thin) solid var(--_cell-border);
    text-align: start;
    vertical-align: top;
  }
  .table thead th {
    background: var(--color-bg-subtle);
    color: var(--color-text-default);
    font-weight: var(--font-weight-semibold);
    white-space: nowrap;
    border-block-end-color: var(--color-border-strong);
    vertical-align: bottom;
  }
  .table tbody th { font-weight: var(--font-weight-semibold); }
  .table tbody tr:last-child > * { border-block-end-color: transparent; }

  .table .table__num {
    text-align: end;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }
  .table__secondary {
    display: block;
    color: var(--color-text-muted);
    font-size: var(--font-size-xs);
  }

  /* Variants */
  .table--striped tbody tr:nth-child(even) > * { background: var(--color-bg-subtle); }
  .table--compact,
  [data-density="compact"] .table { --_py: var(--density-compact-cell-padding-y); --_px: var(--space-3); }
  .table--bordered { --_cell-border: var(--color-border-default); }

  @media (forced-colors: active) {
    .table th, .table td { border-color: CanvasText; }
    .table--striped tbody tr:nth-child(even) > * { background: Canvas; }
  }
}

/* ---- css/components/tabs.css ---- */
/* tabs.css — Tabs (APG Tabs). Block: .tabs
   Variants: .tabs--underline (default) | .tabs--contained (segmented pill row for compact view switches)
   Overflow: the tablist scrolls horizontally (scroll-snap); .tabs--overflow adds edge padding + thin scrollbar.
   Parts:    .tabs__list (role="tablist" + aria-label; or <ul> inside <nav> for URL tabs), .tabs__tab (button role="tab"
             aria-selected aria-controls — or <a aria-current="page"> for navigation tabs), .tabs__count (number badge),
             .tabs__icon (svg), .tabs__panel (role="tabpanel" aria-labelledby tabindex="0")
   States:   aria-selected="true" / aria-current="page" (bar + weight + color), :hover, :focus-visible,
             aria-disabled="true" (focusable, not selectable). Docs-only freeze: .is-hover, .is-focus-visible.
   Behavior: js/tabs.js — roving focus (←/→, Home/End), automatic activation; data-activation="manual" waits for Enter/Space. */
@layer components {
  .tabs { display: grid; gap: var(--space-4); min-inline-size: 0; }

  .tabs__list {
    display: flex;
    gap: var(--space-1);
    margin: 0;
    padding: 0;
    list-style: none;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    border-block-end: var(--border-width-thin) solid var(--color-border-default);
  }

  .tabs__tab {
    --_bar: transparent;
    --_fg: var(--color-text-muted);
    --_bg: transparent;

    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    gap: var(--space-2);
    min-block-size: var(--size-control-md);
    padding-inline: var(--space-3);
    border: 0;
    border-block-end: var(--border-width-thick) solid var(--_bar);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    background: var(--_bg);
    color: var(--_fg);
    font: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    white-space: nowrap;
    scroll-snap-align: start;
    cursor: pointer;
    transition:
      background-color var(--motion-duration-fast) var(--motion-easing-standard),
      color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .tabs__tab:hover:not([aria-disabled="true"]),
  .tabs__tab.is-hover { --_bg: var(--color-action-ghost-bg-hover); --_fg: var(--color-text-default); }
  .tabs__tab:focus-visible,
  .tabs__tab.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: calc(var(--focus-ring-width) * -1);
  }
  .tabs__tab[aria-selected="true"],
  .tabs__tab[aria-current="page"] {
    --_bar: var(--color-selected-border);
    --_fg: var(--color-selected-fg);
    font-weight: var(--font-weight-semibold);
  }
  .tabs__tab[aria-disabled="true"] { --_fg: var(--color-text-disabled); cursor: not-allowed; }

  .tabs__icon { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); stroke-width: var(--icon-stroke); }
  .tabs__count {
    min-inline-size: var(--space-5);
    padding-inline: var(--space-1-5);
    border-radius: var(--radius-full);
    background: var(--color-bg-muted);
    color: var(--color-text-default);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
    text-align: center;
  }

  .tabs__panel { min-inline-size: 0; border-radius: var(--radius-sm); }
  .tabs__panel:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Contained (segmented look) */
  .tabs--contained .tabs__list {
    display: inline-flex;
    max-inline-size: 100%;
    padding: var(--space-1);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: var(--color-bg-subtle);
    justify-self: start;
  }
  .tabs--contained .tabs__tab {
    min-block-size: var(--size-control-sm);
    border: var(--border-width-thin) solid transparent;
    border-radius: var(--radius-sm);
  }
  .tabs--contained .tabs__tab[aria-selected="true"],
  .tabs--contained .tabs__tab[aria-current="page"] {
    --_bg: var(--color-bg-surface);
    --_fg: var(--color-text-default);
    border-color: var(--color-border-strong);
    box-shadow: var(--shadow-sm);
  }

  .tabs--overflow .tabs__list { padding-block-end: var(--space-1); }

  @media (forced-colors: active) {
    .tabs__tab[aria-selected="true"], .tabs__tab[aria-current="page"] { border-block-end-color: Highlight; }
    .tabs--contained .tabs__tab[aria-selected="true"] { border-color: Highlight; }
    .tabs__tab[aria-disabled="true"] { color: GrayText; }
  }
}

/* ---- css/components/tag.css ---- */
/* tag.css — Tag / Chip. Block alias: .tag
   Variants: static   <span class="tag">  (metadata, not interactive)
             removable <span class="tag tag--removable"> + <button class="tag__remove" aria-label="Remove filter: …">
             selectable <button type="button" class="tag tag--selectable" aria-pressed="false|true"> (filter chip)
   Parts:    .tag__label (truncates; put the full text in title), .tag__icon, .tag__check (shown when pressed),
             .tag__remove (24px+ hit area)
   States:   :hover / :focus-visible (docs freeze: .is-hover, .is-focus-visible), [aria-pressed="true"] = selected,
             disabled. Selected shows a check icon as well as the teal fill — never color alone.
   Pattern:  private props --_bg, --_fg, --_border; states swap them. 8px radius like every control. */
@layer components {
  .tag {
    --_bg: var(--color-bg-subtle);
    --_fg: var(--color-text-default);
    --_border: var(--color-border-default);

    display: inline-flex;
    align-items: center;
    gap: var(--space-1-5);
    max-inline-size: 16rem;
    min-block-size: var(--size-control-sm);
    padding-block: 0;
    padding-inline: var(--space-3);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--radius-md);
    background: var(--_bg);
    color: var(--_fg);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    line-height: var(--font-line-height-tight);
    white-space: nowrap;
    vertical-align: middle;
    transition:
      background-color var(--motion-duration-fast) var(--motion-easing-standard),
      border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .tag__label { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; }
  .tag__icon, .tag__check {
    flex-shrink: 0;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
  }

  /* Removable */
  .tag--removable { padding-inline-end: var(--space-1); }
  .tag__remove {
    display: inline-grid;
    place-items: center;
    flex-shrink: 0;
    inline-size: var(--space-6);
    block-size: var(--space-6);
    padding: 0;
    border: 0;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--color-text-muted);
    cursor: pointer;
  }
  .tag__remove svg { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); stroke-width: var(--icon-stroke); }
  .tag__remove:hover, .tag__remove.is-hover { background: var(--color-action-ghost-bg-hover); color: var(--color-text-default); }
  .tag__remove:focus-visible, .tag__remove.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: 0;
  }

  /* Selectable (filter chip) */
  .tag--selectable { cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
  .tag--selectable .tag__check { display: none; }
  .tag--selectable:hover:not(:disabled), .tag--selectable.is-hover { --_bg: var(--color-action-secondary-bg-hover); --_border: var(--color-border-strong); }
  .tag--selectable[aria-pressed="true"] {
    --_bg: var(--color-selected-bg);
    --_fg: var(--color-selected-fg);
    --_border: var(--color-selected-border);
  }
  .tag--selectable[aria-pressed="true"] .tag__check { display: block; }
  .tag--selectable:focus-visible, .tag--selectable.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
  .tag--selectable:disabled {
    --_bg: var(--color-bg-muted);
    --_fg: var(--color-text-disabled);
    --_border: transparent;
    cursor: not-allowed;
  }

  .tag-list { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 0; list-style: none; }

  @media (forced-colors: active) {
    .tag { border-color: CanvasText; }
    .tag--selectable[aria-pressed="true"] { border-color: Highlight; border-width: var(--border-width-thick); }
    .tag--selectable:disabled { color: GrayText; border-color: GrayText; }
  }
}

/* ---- css/components/text-field.css ---- */
/* text-field.css — single-line text input. Block alias: .input
   Plain:     <input class="input" type="text" …>
   Affixed:   <div class="input input--affixed"> <span class="input__affix">$</span>
                <input class="input__control" …> <span class="input__affix">km</span> </div>
   Sizes:     .input--sm | (md default) | .input--lg → --size-control-* (align with .btn sizes)
   States:    :hover, :focus-visible, :disabled, :read-only (real attributes), invalid via
              aria-invalid="true" or :user-invalid (only after interaction).
              Docs-only freeze classes: .is-hover, .is-focus-visible. */
@layer components {
  .input {
    --_h: var(--size-control-md);
    --_border: var(--input-border);
    --_bg: var(--input-bg);

    display: block;
    inline-size: 100%;
    min-inline-size: 0;
    block-size: var(--_h);
    padding-block: 0;
    padding-inline: var(--space-3);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--input-radius);
    background: var(--_bg);
    color: var(--color-text-default);
    font-family: inherit;
    font-size: var(--font-size-md); /* 16px: no iOS zoom on focus */
    line-height: var(--font-line-height-normal);
    transition: border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .input::placeholder { color: var(--color-text-subtle); opacity: 1; }

  .input--sm { --_h: var(--size-control-sm); padding-inline: var(--space-2); font-size: var(--font-size-sm); }
  .input--lg { --_h: var(--size-control-lg); padding-inline: var(--space-4); }

  /* Affixed wrapper: the border lives on the wrapper, the inner input is borderless. */
  .input--affixed {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    cursor: text;
  }
  .input__control {
    flex: 1;
    min-inline-size: 0;
    block-size: 100%;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    font: inherit;
  }
  /* The ring is drawn on the wrapper (.input--affixed:has(:focus-visible)); a transparent outline
     stays here so forced-colors mode still shows one. */
  .input__control:focus-visible { outline-color: transparent; }
  .input__control::placeholder { color: var(--color-text-subtle); opacity: 1; }
  .input__affix {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    white-space: nowrap;
  }
  .input__affix .icon { inline-size: var(--icon-size-sm); block-size: var(--icon-size-sm); }

  /* Hover */
  input.input:hover:not(:disabled, :read-only),
  .input--affixed:hover:not(:has(.input__control:disabled, .input__control:read-only)),
  .input.is-hover { --_border: var(--color-text-muted); }

  /* Focus — ring, not just a border color change. */
  .input:focus-visible,
  .input--affixed:has(.input__control:focus-visible),
  .input.is-focus-visible {
    --_border: var(--color-border-focus);
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Invalid — a second inset line doubles the border weight without shifting layout. */
  .input[aria-invalid="true"],
  input.input:user-invalid,
  .input--affixed:has(.input__control[aria-invalid="true"], .input__control:user-invalid) {
    --_border: var(--color-border-invalid);
    box-shadow: inset 0 0 0 var(--border-width-thin) var(--_border);
  }

  /* Read-only: focusable and copyable, no emphasis. */
  input.input:read-only:not(:disabled),
  .input--affixed:has(.input__control:read-only:not(:disabled)) {
    --_bg: var(--color-bg-subtle);
    --_border: var(--color-border-default);
  }

  /* Disabled: muted, not focusable. */
  .input:disabled,
  .input--affixed:has(.input__control:disabled) {
    --_bg: var(--color-bg-muted);
    --_border: var(--color-border-subtle);
    color: var(--color-text-disabled);
    cursor: not-allowed;
  }
  .input:disabled::placeholder,
  .input__control:disabled::placeholder { color: var(--color-text-disabled); }

  @media (forced-colors: active) {
    .input { border-color: CanvasText; }
    .input:disabled, .input--affixed:has(:disabled) { border-color: GrayText; color: GrayText; }
    .input--affixed:has(.input__control:focus-visible) { outline-color: Highlight; }
  }
}

/* ---- css/components/textarea.css ---- */
/* textarea.css — multi-line text input. Block alias: .textarea
   Markup:    <textarea class="textarea" id="…" rows="4" …></textarea>
   Modifiers: .textarea--auto-grow (field-sizing: content between --textarea-min-rows and
              --textarea-max-rows, then scrolls; falls back to rows + vertical resize)
   Counter:   reuse .field__counter + js/form-field.js (data-counter on the textarea)
   States:    :hover, :focus-visible, :disabled, :read-only, aria-invalid="true" | :user-invalid.
              Docs-only freeze classes: .is-hover, .is-focus-visible.
   Visual language matches .input (text-field.css): same border, radius, ring and state tokens. */
@layer components {
  .textarea {
    --_border: var(--input-border);
    --_bg: var(--input-bg);
    --textarea-min-rows: 3;
    --textarea-max-rows: 12;

    display: block;
    inline-size: 100%;
    min-inline-size: 0;
    min-block-size: calc(var(--size-control-md) * 2);
    margin: 0;
    padding-block: var(--space-2);
    padding-inline: var(--space-3);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--input-radius);
    background: var(--_bg);
    color: var(--color-text-default);
    font-family: inherit;
    font-size: var(--font-size-md); /* 16px: no iOS zoom on focus */
    line-height: var(--font-line-height-normal);
    resize: vertical;
    transition: border-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .textarea::placeholder { color: var(--color-text-subtle); opacity: 1; }

  /* Auto-grow: content-sized between min and max rows. Without support, rows= + resize apply. */
  @supports (field-sizing: content) {
    .textarea--auto-grow {
      field-sizing: content;
      min-block-size: calc(var(--textarea-min-rows) * 1lh + 2 * var(--space-2) + 2 * var(--border-width-thin));
      max-block-size: calc(var(--textarea-max-rows) * 1lh + 2 * var(--space-2) + 2 * var(--border-width-thin));
      resize: none;
    }
  }

  /* Hover */
  .textarea:hover:not(:disabled, :read-only),
  .textarea.is-hover { --_border: var(--color-text-muted); }

  /* Focus — ring plus focus border */
  .textarea:focus-visible,
  .textarea.is-focus-visible {
    --_border: var(--color-border-focus);
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  /* Invalid — inset line doubles the border weight without layout shift */
  .textarea[aria-invalid="true"],
  .textarea:user-invalid {
    --_border: var(--color-border-invalid);
    box-shadow: inset 0 0 0 var(--border-width-thin) var(--_border);
  }

  /* Read-only: focusable, copyable, no emphasis */
  .textarea:read-only:not(:disabled) {
    --_bg: var(--color-bg-subtle);
    --_border: var(--color-border-default);
    resize: none;
  }

  /* Disabled */
  .textarea:disabled {
    --_bg: var(--color-bg-muted);
    --_border: var(--color-border-subtle);
    color: var(--color-text-disabled);
    cursor: not-allowed;
    resize: none;
  }
  .textarea:disabled::placeholder { color: var(--color-text-disabled); }

  @media (forced-colors: active) {
    .textarea { border-color: CanvasText; }
    .textarea:disabled { border-color: GrayText; color: GrayText; }
  }
}

/* ---- css/components/theme-toggle.css ---- */
/* theme-toggle.css — Theme switch (behavior: js/theme.js + js/theme-toggle.js).
   Block alias: .theme-toggle (cycling button; extends .btn: <button class="btn btn--ghost theme-toggle" data-theme-cycle>)
     Parts: .theme-toggle__icon (three svgs: [data-for="system|light|dark"], only the current one shows),
            .theme-toggle__label ([data-theme-label]; text "Theme: dark" is the accessible name and updates)
     The current icon follows :root[data-theme] (no attribute = system). Docs-only freeze: [data-preview="light|dark|system"].
   Block: .theme-choice (radio group form for settings pages) — <fieldset class="theme-choice">
     Parts: .theme-choice__legend, .theme-choice__option (label wrapping a visually hidden radio), .theme-choice__icon
     States: :checked (selected bg + border + check of the radio, not color alone), :focus-visible on the radio,
             docs-only .is-focus-visible on an option. */
@layer components {
  /* Cycling button */
  .theme-toggle__icon {
    display: none;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
  }
  :root:not([data-theme]) .theme-toggle:not([data-preview]) .theme-toggle__icon[data-for="system"],
  :root[data-theme="light"] .theme-toggle:not([data-preview]) .theme-toggle__icon[data-for="light"],
  :root[data-theme="dark"] .theme-toggle:not([data-preview]) .theme-toggle__icon[data-for="dark"],
  :root[data-theme="high-contrast"] .theme-toggle:not([data-preview]) .theme-toggle__icon[data-for="system"],
  .theme-toggle[data-preview="system"] .theme-toggle__icon[data-for="system"],
  .theme-toggle[data-preview="light"] .theme-toggle__icon[data-for="light"],
  .theme-toggle[data-preview="dark"] .theme-toggle__icon[data-for="dark"] { display: block; }

  /* Radio group */
  .theme-choice {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    min-inline-size: 0;
    padding: 0;
    border: 0;
  }
  .theme-choice__legend {
    inline-size: 100%;
    margin-block-end: var(--space-2);
    padding: 0;
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
  }
  .theme-choice__option {
    --_bg: var(--color-action-secondary-bg);
    --_border: var(--color-action-secondary-border);
    --_fg: var(--color-action-secondary-fg);

    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-block-size: var(--size-control-md);
    padding-inline: var(--space-3) var(--space-4);
    border: var(--border-width-thin) solid var(--_border);
    border-radius: var(--button-radius);
    background: var(--_bg);
    color: var(--_fg);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    cursor: pointer;
    transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .theme-choice__option:hover { --_bg: var(--color-action-secondary-bg-hover); }
  .theme-choice__option > input {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
  }
  .theme-choice__icon {
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    stroke-width: var(--icon-stroke);
  }
  .theme-choice__option:has(:checked) {
    --_bg: var(--color-selected-bg);
    --_border: var(--color-selected-border);
    --_fg: var(--color-selected-fg);
    font-weight: var(--font-weight-semibold);
    box-shadow: inset 0 0 0 var(--border-width-thin) var(--color-selected-border);
  }
  .theme-choice__option:has(:focus-visible),
  .theme-choice__option.is-focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }

  @media (forced-colors: active) {
    .theme-choice__option { border-color: ButtonText; }
    .theme-choice__option:has(:checked) { background: Highlight; color: HighlightText; }
  }
}

/* ---- css/components/toast.css ---- */
/* toast.css — Toast: a transient global notice. Block alias: .toast (+ host .toast-region)
   Host:     <section class="toast-region" popover="manual" aria-label="Notifications"> created by js/toast.js,
             bottom inline-end, newest at the bottom, at most 3 visible. Top layer, so it sits above dialogs;
             without popover support it falls back to position: fixed + --z-toast.
   Tones:    .toast--info (default) | .toast--success | .toast--warning | .toast--danger
   Parts:    .toast__icon (aria-hidden), .toast__content, .toast__title, .toast__message,
             .toast__action (a .btn--sm), .toast__close (icon button, aria-label="Dismiss notification")
   States:   [data-state="closing"] while the exit transition runs (set by js/toast.js).
             .toast-stack is a docs-only static list for the stacked demo.
   Motion:   slide 8px from the inline-end edge + fade (base/enter); exit fast/exit. */
@layer components {
  .toast-region {
    position: fixed;
    inset: auto;
    inset-block-end: var(--space-4);
    inset-inline-end: var(--space-4);
    z-index: var(--z-toast);
    inline-size: min(24rem, 100vw - 2 * var(--space-4));
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    overflow: visible;
    pointer-events: none;
  }
  .toast-region__list,
  .toast-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .toast {
    --_icon: var(--color-feedback-info-icon);
    --_dir: 1;

    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    padding-block: var(--space-3);
    padding-inline: var(--space-4) var(--space-2);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-inline-start: var(--space-1) solid var(--_icon);
    border-radius: var(--radius-md);
    background: var(--color-elevation-surface-overlay);
    color: var(--color-text-default);
    box-shadow: var(--elevation-overlay);
    font-size: var(--font-size-sm);
    line-height: var(--font-line-height-normal);
    pointer-events: auto;
    opacity: 1;
    translate: 0 0;
    transition:
      opacity var(--motion-duration-base) var(--motion-easing-enter),
      translate var(--motion-duration-base) var(--motion-easing-enter);
  }
  @starting-style {
    .toast-region .toast { opacity: 0; translate: calc(var(--_dir) * var(--space-2)) 0; }
  }
  .toast:dir(rtl) { --_dir: -1; }
  .toast[data-state="closing"] {
    opacity: 0;
    translate: calc(var(--_dir) * var(--space-2)) 0;
    transition-duration: var(--motion-duration-fast);
    transition-timing-function: var(--motion-easing-exit);
  }

  .toast--success { --_icon: var(--color-feedback-success-icon); }
  .toast--warning { --_icon: var(--color-feedback-warning-icon); }
  .toast--danger { --_icon: var(--color-feedback-danger-icon); }

  .toast__icon {
    flex-shrink: 0;
    inline-size: var(--icon-size-md);
    block-size: var(--icon-size-md);
    margin-block-start: var(--space-px);
    color: var(--_icon);
    stroke-width: var(--icon-stroke);
  }
  .toast__content { flex: 1; min-inline-size: 0; display: grid; gap: var(--space-0-5); padding-block-start: var(--space-px); }
  .toast__title { font-weight: var(--font-weight-semibold); }
  .toast__message { margin: 0; color: var(--color-text-muted); }
  .toast__action { align-self: center; flex-shrink: 0; }
  .toast__close { flex-shrink: 0; margin-block: calc(-1 * var(--space-1)); }

  @media (forced-colors: active) {
    .toast { border-color: CanvasText; }
    .toast__icon { color: CanvasText; }
  }
}

/* ---- css/components/tooltip.css ---- */
/* tooltip.css — Tooltip: one short, non-interactive line shown on hover AND focus. Block alias: .tooltip
   Markup:   <button type="button" class="btn" aria-describedby="tt-1" data-tooltip-trigger="tt-1">…</button>
             <div id="tt-1" class="tooltip" popover="hint" role="tooltip">Last synced 4 minutes ago</div>
             popover="hint" falls back to "manual" where unsupported; js/tooltip.js shows it after 400ms,
             keeps it while the pointer is over it, hides it on Esc without moving focus (WCAG 1.4.13).
   Placement (logical): (block-start default) | .tooltip--block-end | .tooltip--inline-start | .tooltip--inline-end
             Flips with the built-in flip-block and the shared --flip-inline try from base.css.
   States:   real one via :popover-open. Docs-only freeze class: .is-open (renders in page flow).
   Motion:   opacity only, fast. */
@layer components {
  .tooltip {
    max-inline-size: min(18rem, 100vw - 2 * var(--space-4));
    padding-block: var(--space-1-5);
    padding-inline: var(--space-2);
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--color-bg-inverse);
    color: var(--color-text-inverse);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    line-height: var(--font-line-height-snug);
    box-shadow: var(--shadow-md);
    opacity: 0;
    transition:
      opacity var(--motion-duration-fast) var(--motion-easing-exit),
      overlay var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete,
      display var(--motion-duration-fast) var(--motion-easing-exit) allow-discrete;
  }
  .tooltip:popover-open,
  .tooltip.is-open {
    opacity: 1;
    transition-timing-function: var(--motion-easing-enter);
  }
  @starting-style {
    .tooltip:popover-open { opacity: 0; }
  }

  @supports (anchor-name: --a) {
    .tooltip[popover] {
      inset: auto;
      margin: var(--space-1-5);
      position-area: block-start;
      position-try-fallbacks: flip-block, --flip-inline;
    }
    .tooltip--block-end[popover] { position-area: block-end; position-try-fallbacks: --flip-block, --flip-inline; }
    .tooltip--inline-start[popover] { position-area: inline-start; position-try-fallbacks: flip-inline, --flip-block; }
    .tooltip--inline-end[popover] { position-area: inline-end; position-try-fallbacks: --flip-inline, --flip-block; }
  }

  /* Docs-only: a visible tooltip rendered in the demo flow. */
  .tooltip.is-open { position: relative; display: block; inline-size: max-content; }

  @media (forced-colors: active) {
    .tooltip { border: var(--border-width-thin) solid CanvasText; background: Canvas; color: CanvasText; }
  }
}

/* ---- css/components/top-nav.css ---- */
/* top-nav.css — Global navigation bar (app header). Block: .top-nav  (container: top-nav)
   Markup order (= tab order): .top-nav__toggle → .top-nav__brand → .top-nav__panel (nav + search) → .top-nav__actions
   Parts:   .top-nav__bar (grid row), .top-nav__brand (home link: logo + product name), .top-nav__logo (svg),
            .top-nav__toggle (.btn "Menu", aria-expanded + aria-controls → panel; only shown when narrow),
            .top-nav__panel (id; wraps nav + search), .top-nav__nav (<nav aria-label="Main">), .top-nav__list,
            .top-nav__link (aria-current="page" = current: weight + bottom bar, not color alone),
            .top-nav__search (<form role="search">), .top-nav__search-input, .top-nav__search-icon,
            .top-nav__actions (icon buttons, profile menu button), .top-nav__avatar (initials)
   Modifier: .top-nav--sticky (sticky at the top; pair with html { scroll-padding-top } so focus isn't hidden — WCAG 2.4.11)
   Narrow (container < 48rem): links + search move into the panel below the bar, toggled by the Menu button.
   Without JS the toggle has no aria-expanded, so it stays hidden and the panel stays open (progressive enhancement).
   States: link :hover :focus-visible, aria-current="page". Docs-only freeze: .is-hover, .is-focus-visible.
   Behavior: js/top-nav.js (toggle), js/menu.js (profile menu). */
@layer components {
  .top-nav {
    container: top-nav / inline-size;
    background: var(--color-bg-surface);
    border-block-end: var(--border-width-thin) solid var(--color-border-default);
    color: var(--color-text-default);
  }
  .top-nav--sticky { position: sticky; inset-block-start: 0; z-index: var(--z-sticky); }

  .top-nav__bar {
    display: grid;
    grid-template-columns: auto auto 1fr auto;
    grid-template-areas: "toggle brand panel actions";
    align-items: center;
    gap: var(--space-2) var(--space-4);
    min-block-size: calc(var(--size-control-lg) + var(--space-2));
    padding-block: var(--space-1);
    padding-inline: var(--space-4);
  }

  .top-nav__toggle { grid-area: toggle; }
  .top-nav__toggle:not([aria-expanded]) { display: none; }

  .top-nav__brand {
    grid-area: brand;
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-block-size: var(--size-control-md);
    padding-inline: var(--space-1);
    border-radius: var(--radius-sm);
    color: var(--color-text-default);
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-bold);
    text-decoration: none;
    white-space: nowrap;
  }
  .top-nav__logo {
    inline-size: var(--icon-size-lg);
    block-size: var(--icon-size-lg);
    color: var(--color-action-primary-bg);
    stroke-width: var(--icon-stroke);
  }

  .top-nav__panel {
    grid-area: panel;
    display: flex;
    align-items: center;
    gap: var(--space-4);
    min-inline-size: 0;
  }
  .top-nav__nav { min-inline-size: 0; }
  .top-nav__list {
    display: flex;
    gap: var(--space-1);
    margin: 0;
    padding: 0;
    list-style: none;
  }

  .top-nav__link {
    --_bar: transparent;
    display: inline-flex;
    align-items: center;
    min-block-size: var(--size-control-md);
    padding-inline: var(--space-3);
    border-radius: var(--radius-md);
    box-shadow: inset 0 calc(var(--border-width-thick) * -1) 0 var(--_bar);
    color: var(--color-text-muted);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color var(--motion-duration-fast) var(--motion-easing-standard);
  }
  .top-nav__link:hover,
  .top-nav__link.is-hover { background: var(--color-action-ghost-bg-hover); color: var(--color-text-default); }
  .top-nav__link:focus-visible,
  .top-nav__link.is-focus-visible,
  .top-nav__brand:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
  .top-nav__link[aria-current="page"] {
    --_bar: var(--color-selected-border);
    color: var(--color-text-default);
    font-weight: var(--font-weight-semibold);
  }

  .top-nav__search {
    position: relative;
    flex: 1 1 12rem;
    max-inline-size: 22rem;
    margin-inline-start: auto;
  }
  .top-nav__search-icon {
    position: absolute;
    inset-block: 0;
    inset-inline-start: var(--space-3);
    margin-block: auto;
    inline-size: var(--icon-size-sm);
    block-size: var(--icon-size-sm);
    color: var(--color-text-muted);
    stroke-width: var(--icon-stroke);
    pointer-events: none;
  }
  .top-nav__search-input {
    inline-size: 100%;
    min-block-size: var(--size-control-md);
    padding-inline: calc(var(--space-3) + var(--icon-size-sm) + var(--space-2)) var(--space-3);
    border: var(--border-width-thin) solid var(--input-border);
    border-radius: var(--input-radius);
    background: var(--input-bg);
    color: var(--color-text-default);
    font-size: var(--font-size-sm);
  }
  .top-nav__search-input::placeholder { color: var(--color-text-muted); }
  .top-nav__search-input:focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: 0;
    border-color: var(--color-border-focus);
  }

  .top-nav__actions {
    grid-area: actions;
    display: flex;
    align-items: center;
    gap: var(--space-1);
  }
  .top-nav__avatar {
    display: inline-grid;
    place-items: center;
    inline-size: var(--size-control-sm);
    block-size: var(--size-control-sm);
    border-radius: var(--radius-full);
    background: var(--color-selected-bg);
    color: var(--color-selected-fg);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-bold);
  }

  /* Narrow: the panel drops below the bar and is toggled by the Menu button. */
  @container top-nav (max-width: 48rem) {
    .top-nav__bar {
      grid-template-columns: auto 1fr auto;
      grid-template-areas: "toggle brand actions" "panel panel panel";
      padding-inline: var(--space-2);
    }
    .top-nav__toggle[aria-expanded="false"] ~ .top-nav__panel { display: none; }
    .top-nav__panel {
      flex-direction: column;
      align-items: stretch;
      gap: var(--space-3);
      padding-block: var(--space-2) var(--space-3);
      border-block-start: var(--border-width-thin) solid var(--color-border-subtle);
    }
    .top-nav__search { order: -1; flex: none; max-inline-size: none; margin-inline-start: 0; }
    .top-nav__list { flex-direction: column; gap: var(--space-0-5); }
    .top-nav__link {
      inline-size: 100%;
      min-block-size: var(--size-touch-target);
      box-shadow: inset var(--border-width-thick) 0 0 var(--_bar);
    }
    .top-nav__link:dir(rtl) { box-shadow: inset calc(var(--border-width-thick) * -1) 0 0 var(--_bar); }
    .top-nav__link[aria-current="page"] { background: var(--color-selected-bg); color: var(--color-selected-fg); }
  }
  @container top-nav (min-width: 48.01rem) {
    .top-nav__toggle { display: none; }
  }

  @media (forced-colors: active) {
    .top-nav__link[aria-current="page"] { text-decoration: underline; text-decoration-thickness: var(--border-width-thick); }
    .top-nav__search-input { border-color: CanvasText; }
  }
}

/* ---- css/components/typography.css ---- */
/* typography.css — type roles, code and lists.
   Role utilities (visual size is independent of the semantic level):
     .text-display .text-h1 … .text-h6 .text-lead .text-body .text-small .text-caption .text-overline
   Modifiers: .text-muted, .text-tabular (tabular numerals for data columns)
   Code: .code (inline <code>), .code-block (<pre tabindex="0"><code>…</code></pre>)
   Lists: .list (ul/ol), .list--unstyled (keep role="list" in markup — Safari drops list semantics) */
@layer components {
  :where(.text-display, .text-h1, .text-h2, .text-h3, .text-h4, .text-h5, .text-h6) {
    text-wrap: balance;
    letter-spacing: var(--font-tracking-tight);
    color: var(--color-text-default);
  }
  .text-display {
    font-family: var(--typography-display-font-family);
    font-size: var(--typography-display-font-size);
    font-weight: var(--typography-display-font-weight);
    line-height: var(--typography-display-line-height);
  }
  .text-h1 {
    font-family: var(--typography-h1-font-family);
    font-size: var(--typography-h1-font-size);
    font-weight: var(--typography-h1-font-weight);
    line-height: var(--typography-h1-line-height);
  }
  .text-h2 {
    font-family: var(--typography-h2-font-family);
    font-size: var(--typography-h2-font-size);
    font-weight: var(--typography-h2-font-weight);
    line-height: var(--typography-h2-line-height);
  }
  .text-h3 {
    font-family: var(--typography-h3-font-family);
    font-size: var(--typography-h3-font-size);
    font-weight: var(--typography-h3-font-weight);
    line-height: var(--typography-h3-line-height);
  }
  .text-h4 {
    font-family: var(--typography-h4-font-family);
    font-size: var(--typography-h4-font-size);
    font-weight: var(--typography-h4-font-weight);
    line-height: var(--typography-h4-line-height);
  }
  .text-h5 {
    font-family: var(--typography-h5-font-family);
    font-size: var(--typography-h5-font-size);
    font-weight: var(--typography-h5-font-weight);
    line-height: var(--typography-h5-line-height);
  }
  .text-h6 {
    font-family: var(--typography-h6-font-family);
    font-size: var(--typography-h6-font-size);
    font-weight: var(--typography-h6-font-weight);
    line-height: var(--typography-h6-line-height);
  }

  :where(.text-lead, .text-body, .text-small) { max-inline-size: var(--size-measure); text-wrap: pretty; }
  .text-lead {
    font-family: var(--typography-lead-font-family);
    font-size: var(--typography-lead-font-size);
    font-weight: var(--typography-lead-font-weight);
    line-height: var(--typography-lead-line-height);
    color: var(--color-text-muted);
  }
  .text-body {
    font-family: var(--typography-body-font-family);
    font-size: var(--typography-body-font-size);
    font-weight: var(--typography-body-font-weight);
    line-height: var(--typography-body-line-height);
  }
  .text-small {
    font-family: var(--typography-small-font-family);
    font-size: var(--typography-small-font-size);
    font-weight: var(--typography-small-font-weight);
    line-height: var(--typography-small-line-height);
  }
  .text-caption {
    font-family: var(--typography-caption-font-family);
    font-size: var(--typography-caption-font-size);
    font-weight: var(--typography-caption-font-weight);
    line-height: var(--typography-caption-line-height);
    color: var(--color-text-muted);
  }
  .text-overline {
    font-family: var(--typography-caption-font-family);
    font-size: var(--typography-caption-font-size);
    font-weight: var(--font-weight-semibold);
    line-height: var(--typography-caption-line-height);
    letter-spacing: var(--font-tracking-wide);
    text-transform: uppercase;
    color: var(--color-text-muted);
  }
  .text-muted { color: var(--color-text-muted); }
  .text-tabular { font-variant-numeric: tabular-nums; }

  /* Code */
  .code {
    padding-block: var(--space-px);
    padding-inline: var(--space-1);
    border-radius: var(--radius-sm);
    background: var(--color-bg-muted);
    font-family: var(--typography-code-font-family);
    font-size: 0.9em;
    overflow-wrap: anywhere;
  }
  .code-block {
    overflow-x: auto;
    padding: var(--space-4);
    border: var(--border-width-thin) solid var(--color-border-default);
    border-radius: var(--radius-md);
    background: var(--color-bg-subtle);
    font-family: var(--typography-code-font-family);
    font-size: var(--typography-code-font-size);
    font-weight: var(--typography-code-font-weight);
    line-height: var(--typography-code-line-height);
    white-space: pre;
    tab-size: 2;
  }
  .code-block > code { font: inherit; }

  /* Lists */
  .list {
    display: grid;
    gap: var(--space-1-5);
    padding-inline-start: var(--space-6);
    max-inline-size: var(--size-measure);
  }
  .list > li { padding-inline-start: var(--space-1); }
  .list > li::marker { color: var(--color-text-muted); }
  ol.list > li::marker { font-variant-numeric: tabular-nums; }
  .list--unstyled { list-style: none; padding-inline-start: 0; }
  .list--unstyled > li { padding-inline-start: 0; }
}

/* ---- css/components/visually-hidden.css ---- */
/* visually-hidden.css — content for assistive technology only.
   .sr-only and .sr-only--focusable live in css/base.css (utilities layer, !important) so nothing can
   accidentally reveal them. This file only styles what a revealed focusable element looks like:
   .skip-link — first element in <body>: <a class="skip-link sr-only sr-only--focusable" href="#main">.
   When focused, base.css returns it to normal flow at the top of the page; this gives it a surface. */
@layer components {
  .skip-link:focus-visible,
  .skip-link.is-focus-visible {
    display: inline-block;
    margin: var(--space-2);
    padding-block: var(--space-2);
    padding-inline: var(--space-4);
    border-radius: var(--radius-md);
    background: var(--color-bg-inverse);
    color: var(--color-text-inverse);
    font-weight: var(--font-weight-semibold);
    text-decoration: underline;
    outline: var(--focus-ring-width) solid var(--focus-ring-color);
    outline-offset: var(--focus-ring-offset);
  }
}

/* ---- css/patterns/app-shell.css ---- */
/* app-shell.css — Application shell (pattern). Block: .app-shell  (container: app-shell)
   Composition only: skip-link → header.top-nav → nav.side-nav → main → optional aside → footer.
     <div class="app-shell">                         (or directly on <body>)
       <a class="skip-link" href="#main">Skip to main content</a>
       <header class="top-nav top-nav--sticky app-shell__header">…</header>
       <div class="app-shell__body">
         <nav class="side-nav app-shell__nav" aria-label="Workshop">…</nav>
         <main class="app-shell__main" id="main" tabindex="-1">…</main>
         <aside class="app-shell__aside" aria-label="…">…</aside>      (optional)
       </div>
       <footer class="app-shell__footer">…</footer>
     </div>
   Variants: (sidebar default) | .app-shell--top-nav-only (no side-nav; main centred to --size-container-xl)
   Responsive (container query on the shell, literal copy of --breakpoint-lg = 64rem): below lg the side-nav
             is hidden and the top-nav Menu carries navigation (top-nav collapses itself below 48rem).
   Prefer document scroll: the shell grows with content; nothing scrolls independently.
   Custom property: --app-shell-min-block-size (default 100dvh; docs frames set it to 100%).
   Layout only — every visual comes from the components. */
@layer patterns {
  .app-shell {
    container: app-shell / inline-size;
    display: grid;
    grid-template-rows: auto 1fr auto;
    min-block-size: var(--app-shell-min-block-size, 100dvh);
  }

  .app-shell__body {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "nav main";
    min-inline-size: 0;
  }
  .app-shell__body:has(> .app-shell__aside) {
    grid-template-columns: auto minmax(0, 1fr) 20rem;
    grid-template-areas: "nav main aside";
  }

  .app-shell__nav { grid-area: nav; }

  .app-shell__main {
    grid-area: main;
    display: grid;
    align-content: start;
    gap: var(--space-6);
    min-inline-size: 0;
    padding-block: var(--space-6) var(--space-10);
    padding-inline: var(--space-6);
  }

  .app-shell__aside {
    grid-area: aside;
    display: grid;
    align-content: start;
    gap: var(--space-4);
    padding-block: var(--space-6);
    padding-inline: 0 var(--space-6);
  }

  .app-shell__footer {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--space-2) var(--space-6);
    padding-block: var(--space-4);
    padding-inline: var(--space-6);
  }

  /* Top-nav only: one column, readable width. */
  .app-shell--top-nav-only .app-shell__body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "main";
  }
  .app-shell--top-nav-only .app-shell__body:has(> .app-shell__aside) {
    grid-template-columns: minmax(0, 1fr) 20rem;
    grid-template-areas: "main aside";
  }
  .app-shell--top-nav-only .app-shell__main {
    inline-size: 100%;
    max-inline-size: var(--size-container-xl);
    margin-inline: auto;
  }

  /* Below lg: side-nav off-canvas (top-nav Menu takes over), aside drops under main. */
  @container app-shell (inline-size < 64rem) {
    .app-shell__nav { display: none; }
    .app-shell__body,
    .app-shell__body:has(> .app-shell__aside),
    .app-shell--top-nav-only .app-shell__body:has(> .app-shell__aside) {
      grid-template-columns: minmax(0, 1fr);
      grid-template-areas: "main" "aside";
    }
    .app-shell__aside { padding-inline: var(--space-6); }
  }

  /* Mobile: tighter gutters for tablets in portrait and phones. */
  @container app-shell (inline-size < 40rem) {
    .app-shell__main { gap: var(--space-4); padding-block: var(--space-4) var(--space-8); padding-inline: var(--space-4); }
    .app-shell__aside,
    .app-shell__footer { padding-inline: var(--space-4); }
  }
}

/* ---- css/patterns/empty-state.css ---- */
/* empty-state.css — Empty state (pattern). Block: .empty-state
   Composition only: a .result panel (result-panel.css; info tone by default) placed where the list, table or
   page content would be. The pattern only reserves the region so the page doesn't jump when data arrives.
     <div class="empty-state" role="status"?>                          (role only when it replaces content live)
       <section class="result" aria-labelledby="…">
         <span class="result__icon" aria-hidden="true"><svg>…</svg></span>
         <h2 class="result__title" id="…">No work orders yet</h2>
         <p class="result__description">One sentence of guidance.</p>
         <div class="result__actions"> one primary button (+ optional secondary link) </div>
       </section>
     </div>
   Variants (content, not classes): first use · no results (+ clear filters) · cleared ("All caught up").
   Custom property: --empty-state-min-block-size (default 20rem; match the height of the content it replaces).
   Layout only. */
@layer patterns {
  .empty-state {
    display: grid;
    align-content: center;
    min-block-size: var(--empty-state-min-block-size, 20rem);
    min-inline-size: 0;
  }

  /* Filter bar above a no-results state: search + filters + clear, wrapping on narrow screens. */
  .empty-state__toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: end;
    gap: var(--space-3) var(--space-4);
  }
  .empty-state__toolbar > :first-child { flex: 1 1 16rem; }
}

/* ---- css/patterns/error-page.css ---- */
/* error-page.css — Error pages: 404, 403, 500, offline (pattern). Block: .error-page
   Composition only: app-shell (top-nav-only, so users can recover) + a .result.result--page whose title is the <h1>.
     <body>
       <a class="skip-link" href="#main">Skip to main content</a>
       <div class="app-shell app-shell--top-nav-only">
         <header class="top-nav app-shell__header">…</header>
         <div class="app-shell__body">
           <main class="app-shell__main error-page" id="main" tabindex="-1">
             <section class="result result--page [--error|--warning|--no-permission]" aria-labelledby="err-t">
               …<h1 class="result__title" id="err-t">We can't find that page</h1>…
               [<search class="search error-page__search">…</search>]   (404)
             </section>
           </main>
   Parts:   .error-page__search (search form inside the result, readable width)
   Layout only. */
@layer patterns {
  .error-page {
    display: grid;
    align-content: center;
  }

  .error-page__search {
    align-self: stretch;
    inline-size: 100%;
    max-inline-size: var(--size-container-sm);
    margin-inline: auto;
  }
}

/* ---- css/patterns/form-layout.css ---- */
/* form-layout.css — Form layout (pattern). Block: .form-layout  (container: form-layout)
   Composition only: alert (error summary) → sections (heading + description + fields) → action bar.
     <form class="form-layout" novalidate>
       [<div class="alert alert--danger form-layout__summary" tabindex="-1">…error summary…</div>]
       <section class="form-layout__section" aria-labelledby="…">
         <div class="form-layout__intro"><h2 id="…">Vehicle</h2><p class="text-muted">…</p></div>
         <div class="form-layout__fields"> .field / fieldset.fieldset … </div>
       </section>
       <hr class="divider">
       …
       <div class="form-layout__actions [form-layout__actions--sticky]"> primary first, then secondary </div>
     </form>
   Parts:    .form-layout__summary, .form-layout__section, .form-layout__intro, .form-layout__fields,
             .form-layout__row (two short related fields side by side from 28rem of form width),
             .form-layout__actions
   Modifier: .form-layout__actions--sticky (sticks to the bottom of the scrollport on long forms)
   Decision: primary action at inline-start for page forms (dialogs: inline-end, see modal).
   Width:    one column capped at --size-container-sm (fastest to complete, label above control).
   Layout only. The sticky bar's surface + top rule are the one visual exception (no action-bar component yet). */
@layer patterns {
  .form-layout {
    container: form-layout / inline-size;
    display: grid;
    gap: var(--space-8);
    max-inline-size: var(--size-container-sm);
  }

  .form-layout__summary { scroll-margin-block: var(--space-16); }

  .form-layout__section {
    display: grid;
    gap: var(--space-4);
  }
  .form-layout__intro {
    display: grid;
    gap: var(--space-1);
  }
  .form-layout__fields {
    display: grid;
    gap: var(--space-5);
  }

  .form-layout__row {
    display: grid;
    gap: var(--space-5) var(--space-4);
    grid-template-columns: minmax(0, 1fr);
  }
  @container form-layout (inline-size >= 28rem) {
    .form-layout__row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

  .form-layout__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-3);
  }
  .form-layout__actions--sticky {
    position: sticky;
    inset-block-end: 0;
    z-index: var(--z-sticky);
    padding-block: var(--space-3);
    background: var(--color-bg-surface);
    border-block-start: var(--border-width-thin) solid var(--color-border-default);
  }
}
