/* ============================================================================
   TRAK FOUNDATION CSS
   Design system for TRAK3

   Philosophy: Professional, high-density enterprise UI with greyscale-first
   aesthetic and subtle accent colors. Smart, modern, clean, delightful.
   ============================================================================ */

/* ============================================================================
   1. DESIGN TOKENS
   ============================================================================ */

:root {
  /* === NEUTRALS (GREYSCALE PALETTE) === */
  --neutral-950: #0a0a0b;
  --neutral-900: #0b0b0c;
  --neutral-800: #1f1f21;
  --neutral-700: #3a3a3d;
  --neutral-600: #545459;
  --neutral-500: #6f7377;
  --neutral-400: #9ca3af;
  --neutral-300: #d1d5db;
  --neutral-200: #e5e7eb;
  --neutral-100: #f3f4f6;
  --neutral-50: #f9fafb;

  /* === ACCENT COLORS === */
  /* Primary accent - cyan from company logo */
  --accent-primary-600: #007d94;
  --accent-primary-500: #009cb6;
  --accent-primary-400: #00b7d3;

  /* Secondary accent - amber for warnings/highlights */
  --accent-secondary-600: #d97706;
  --accent-secondary-500: #f59e0b;
  --accent-secondary-400: #fbbf24;

  /* === STATUS COLORS === */
  --status-success-700: #15803d;
  --status-success-600: #16a34a;
  --status-success-500: #22c55e;
  --status-success-100: #dcfce7;

  --status-danger-700: #b91c1c;
  --status-danger-600: #dc2626;
  --status-danger-500: #ef4444;
  --status-danger-400: #f87171;
  --status-danger-100: #fee2e2;

  --status-warning-700: #c2410c;
  --status-warning-600: #ea580c;
  --status-warning-500: #f97316;
  --status-warning-100: #ffedd5;

  --status-info-700: #1d4ed8;
  --status-info-600: #2563eb;
  --status-info-500: #3b82f6;
  --status-info-100: #dbeafe;

  /* === SEMANTIC TOKENS === */
  /* Text hierarchy */
  --text-strong: var(--neutral-950);
  --text: var(--neutral-900);
  --text-muted: var(--neutral-600);
  --text-subtle: var(--neutral-500);
  --text-inverse: #ffffff;
  /* Text saying something went wrong, AA on every surface */
  --text-danger: var(--status-danger-600);

  /* Interactive elements */
  --link: var(--accent-primary-500);
  --link-hover: var(--accent-primary-600);

  /* Surface hierarchy */
  --bg-page: var(--neutral-50);
  --bg-elev-1: #ffffff;
  --bg-elev-2: var(--neutral-100);
  --bg-elev-3: var(--neutral-200);

  /* Borders */
  --border: var(--neutral-300);
  --border-strong: var(--neutral-400);
  --border-subtle: var(--neutral-200);

  /* Header/footer */
  --bg-header: var(--neutral-950);
  --bg-footer: var(--neutral-900);

  /* === SPACING SCALE (4px base) === */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;

  /* === TYPOGRAPHY === */
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SF Mono", Monaco, Consolas, "Liberation Mono", "Courier New", monospace;

  /* Font sizes - compact scale for high density */
  --text-xs: 0.6875rem;
  /* 11px */
  --text-sm: 0.8125rem;
  /* 13px */
  --text-base: 0.875rem;
  /* 14px */
  --text-md: 0.9375rem;
  /* 15px */
  --text-lg: 1rem;
  /* 16px */
  --text-xl: 1.125rem;
  /* 18px */
  --text-2xl: 1.25rem;
  /* 20px */
  --text-3xl: 1.5rem;
  /* 24px */
  --text-4xl: 1.875rem;
  /* 30px */

  /* Font weights */
  --font-normal: 400;
  --font-medium: 500;
  --font-semibold: 600;
  --font-bold: 700;

  /* Line heights - compact */
  --leading-tight: 1.25;
  --leading-normal: 1.4;
  --leading-relaxed: 1.5;

  /* === EFFECTS === */
  /* Border radius */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-xl: 12px;

  /* Shadows - subtle */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.05), 0 2px 4px rgba(0, 0, 0, 0.03);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.05), 0 4px 6px rgba(0, 0, 0, 0.03);

  /* Focus ring */
  --focus-ring: 0 0 0 3px rgba(59, 130, 246, 0.15);
  --focus-ring-danger: 0 0 0 3px rgba(239, 68, 68, 0.15);

  /* Transitions */
  --duration-fast: 120ms;
  --duration-base: 150ms;
  --duration-slow: 200ms;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);

  /* === VENDOR SYSTEM COLOURS === */
  --vendor-caw-bg: #fef3d6;
  --vendor-caw-text: #7c5a04;
  --vendor-caw-border: #f5d98e;
  --vendor-cwm-bg: #d1fae5;
  --vendor-cwm-text: #065f46;
  --vendor-cwm-border: #6ee7b7;
  --vendor-iloq-bg: #dbeafe;
  --vendor-iloq-text: #1e40af;
  --vendor-iloq-border: #93c5fd;

  /* === CHART TOKENS === */
  --chart-open: #c87a2e;
  --chart-active: #3d8f32;
  --chart-completed: #475cb9;
  --chart-overdue: #c4282d;
  --chart-now-line: var(--text);
  --chart-grid: var(--neutral-400);
  --chart-label: var(--text);
  --chart-bg: var(--bg-elev-1);
  --chart-incident: #d4a017;
  --chart-multi: #7c5cbf;

  /* Categorical ramp for data visualisation. Validated for CVD separation,
     chroma and contrast against the light surface — slots are assigned in
     fixed order, never cycled; slot 1 is the brand-cyan anchor. Values are
     re-stepped for dark mode below. */
  --chart-1: #0089a5;
  --chart-2: #c2255c;
  --chart-3: #3b76db;
  --chart-4: #946300;
  --chart-5: #a8329a;
  --chart-6: #7048e8;
  --chart-muted: var(--neutral-400);

  /* === Z-INDEX TOKENS === */
  --z-tooltip: 1000;
  /* Above Leaflet's panes (up to 1000), below modals (2000) */
  --z-detail-panel: 1500;
}

/* ============================================================================
   DARK THEME
   ============================================================================ */

[data-theme="dark"] {
  color-scheme: dark;

  /* === SEMANTIC TOKENS (DARK MODE) === */
  /* Text hierarchy - inverted */
  --text-strong: #f9fafb;
  --text: #f3f4f6;
  --text-muted: #9ca3af;
  --text-subtle: #6f7377;
  --text-danger: var(--status-danger-400);
  /* Note: --text-inverse stays #ffffff - header is always dark */

  /* Interactive elements - slightly brighter in dark mode */
  --link: var(--accent-primary-400);
  --link-hover: var(--accent-primary-500);

  /* Surface hierarchy - darker base, lighter elevations */
  --bg-page: #1a1d21;
  --bg-elev-1: #1f1f21;
  --bg-elev-2: #2a2a2d;
  --bg-elev-3: #35353a;

  /* Borders - lighter for visibility on dark backgrounds */
  --border: #3a3a3d;
  --border-strong: #545459;
  --border-subtle: #2a2a2d;

  /* Header/footer - keep very dark */
  --bg-header: #23262a;
  --bg-footer: #0b0b0c;

  /* === EFFECTS (DARK MODE) === */
  /* Shadows - stronger for depth on dark backgrounds */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.6), 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.7), 0 2px 4px rgba(0, 0, 0, 0.6);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.8), 0 4px 6px rgba(0, 0, 0, 0.7);

  /* Focus rings - adjusted for dark backgrounds */
  --focus-ring: 0 0 0 3px rgba(0, 183, 211, 0.3);
  --focus-ring-danger: 0 0 0 3px rgba(239, 68, 68, 0.3);

  /* Form fields - darker backgrounds */
  --field-bg: #1f1f21;
  --field-border: var(--border);
  --field-border-focus: var(--accent-primary-400);
  --field-shadow-focus: var(--focus-ring);

  /* Vendor system colours — dark mode */
  --vendor-caw-bg: #422006;
  --vendor-caw-text: #fcd34d;
  --vendor-caw-border: #92400e;
  --vendor-cwm-bg: #064e3b;
  --vendor-cwm-text: #6ee7b7;
  --vendor-cwm-border: #065f46;
  --vendor-iloq-bg: #1e3a5f;
  --vendor-iloq-text: #93c5fd;
  --vendor-iloq-border: #1e40af;

  /* Chart tokens — brighter for dark backgrounds */
  --chart-open: #eb8322;
  --chart-active: #57b947;
  --chart-completed: #6b7fd4;
  --chart-overdue: #e21e25;
  --chart-now-line: var(--text);
  --chart-grid: var(--neutral-500);
  --chart-label: var(--text);
  --chart-bg: var(--bg-elev-2);
  --chart-incident: #e6b526;
  --chart-multi: #9b7fd4;

  /* Categorical ramp — same hues, re-stepped against the dark surface */
  --chart-1: #0097b2;
  --chart-2: #cf3d6e;
  --chart-3: #3a6cd0;
  --chart-4: #b07c00;
  --chart-5: #d05dc4;
  --chart-6: #7158e2;
  --chart-muted: #545459;
}

/* Dark mode: Keep status alert/card text dark for contrast on light backgrounds */
/* Alerts */
[data-theme="dark"] .alert--info,
[data-theme="dark"] .alert--info .alert__title,
[data-theme="dark"] .alert--info .alert__message {
  color: var(--status-info-700);
}

[data-theme="dark"] .alert--success,
[data-theme="dark"] .alert--success .alert__title,
[data-theme="dark"] .alert--success .alert__message {
  color: var(--status-success-700);
}

[data-theme="dark"] .alert--warning,
[data-theme="dark"] .alert--warning .alert__title,
[data-theme="dark"] .alert--warning .alert__message {
  color: var(--status-warning-700);
}

[data-theme="dark"] .alert--danger,
[data-theme="dark"] .alert--danger .alert__title,
[data-theme="dark"] .alert--danger .alert__message {
  color: var(--status-danger-700);
}

/* Cards - target all child elements to override global text colors */
[data-theme="dark"] .card--info,
[data-theme="dark"] .card--info *,
[data-theme="dark"] .card--info h1,
[data-theme="dark"] .card--info h2,
[data-theme="dark"] .card--info h3,
[data-theme="dark"] .card--info h4,
[data-theme="dark"] .card--info h5,
[data-theme="dark"] .card--info h6,
[data-theme="dark"] .card--info p {
  color: var(--status-info-700) !important;
}

[data-theme="dark"] .card--success,
[data-theme="dark"] .card--success *,
[data-theme="dark"] .card--success h1,
[data-theme="dark"] .card--success h2,
[data-theme="dark"] .card--success h3,
[data-theme="dark"] .card--success h4,
[data-theme="dark"] .card--success h5,
[data-theme="dark"] .card--success h6,
[data-theme="dark"] .card--success p {
  color: var(--status-success-700) !important;
}

[data-theme="dark"] .card--warning,
[data-theme="dark"] .card--warning *,
[data-theme="dark"] .card--warning h1,
[data-theme="dark"] .card--warning h2,
[data-theme="dark"] .card--warning h3,
[data-theme="dark"] .card--warning h4,
[data-theme="dark"] .card--warning h5,
[data-theme="dark"] .card--warning h6,
[data-theme="dark"] .card--warning p {
  color: var(--status-warning-700) !important;
}

[data-theme="dark"] .card--danger,
[data-theme="dark"] .card--danger *,
[data-theme="dark"] .card--danger h1,
[data-theme="dark"] .card--danger h2,
[data-theme="dark"] .card--danger h3,
[data-theme="dark"] .card--danger h4,
[data-theme="dark"] .card--danger h5,
[data-theme="dark"] .card--danger h6,
[data-theme="dark"] .card--danger p {
  color: var(--status-danger-700) !important;
}

/* Dark mode adjustments for specific components */
[data-theme="dark"] .user-menu__dropdown {
  background: #1f1f21;
  border-color: var(--border);
}

[data-theme="dark"] .user-menu__header {
  background: #2a2a2d;
  border-bottom-color: var(--border-subtle);
}

[data-theme="dark"] code {
  background: #2a2a2d;
  color: var(--text-strong);
}

[data-theme="dark"] pre {
  background: #2a2a2d;
}

/* ============================================================================
   2. CSS RESET & BASE STYLES
   ============================================================================ */

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

[hidden] {
  display: none !important;
}

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-size: 16px;
}

body {
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--text);
  background: var(--bg-page);
  min-height: 100vh;
}



/* ============================================================================
   3. TYPOGRAPHY
   ============================================================================ */

h1,
h2,
h3,
h4,
h5,
h6 {
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  line-height: var(--leading-tight);
  margin: 0;
}

h1 {
  font-size: var(--text-4xl);
  margin-bottom: var(--space-6);
}

h2 {
  font-size: var(--text-3xl);
  margin-bottom: var(--space-5);
}

h3 {
  font-size: var(--text-2xl);
  margin-bottom: var(--space-4);
}

h4 {
  font-size: var(--text-xl);
  margin-bottom: var(--space-3);
}

h5 {
  font-size: var(--text-lg);
  margin-bottom: var(--space-3);
}

h6 {
  font-size: var(--text-md);
  margin-bottom: var(--space-2);
}

p {
  margin: 0 0 var(--space-4) 0;
  line-height: var(--leading-normal);
}

p:last-child {
  margin-bottom: 0;
}

a {
  color: var(--link);
  text-decoration: none;
  transition: color var(--duration-base) var(--ease);
}

a:hover {
  color: var(--link-hover);
  text-decoration: underline;
}

a:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
  border-radius: 2px;
}

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

em,
i {
  font-style: italic;
}

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

code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--bg-elev-2);
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  color: var(--text-strong);
}

pre {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  background: var(--bg-elev-2);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  overflow-x: auto;
  line-height: var(--leading-relaxed);
}

pre code {
  background: none;
  padding: 0;
}

ul,
ol {
  margin: 0 0 var(--space-4) 0;
  padding-left: var(--space-6);
}

ul {
  list-style-type: disc;
}

ol {
  list-style-type: decimal;
}

li {
  margin-bottom: var(--space-2);
  line-height: var(--leading-normal);
}

li:last-child {
  margin-bottom: 0;
}

ul ul,
ol ul {
  list-style-type: circle;
  margin-top: var(--space-2);
  margin-bottom: var(--space-2);
}

ul ol,
ol ol {
  list-style-type: lower-alpha;
  margin-top: var(--space-2);
  margin-bottom: var(--space-2);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.text-overline {
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

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

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

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

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

.leading-tight {
  line-height: var(--leading-tight);
}

.leading-normal {
  line-height: var(--leading-normal);
}

.leading-relaxed {
  line-height: var(--leading-relaxed);
}

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

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

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

.text-nowrap {
  white-space: nowrap;
}

/* Preserve user-entered line breaks in body copy (notes, comments).
   Content is still escaped at render time — this only affects whitespace. */
.preserve-lines {
  white-space: pre-wrap;
}

/* Two-column label/value grid for metadata description lists. Used for
   "Zone", "Access type", "Filed at" etc. on detail pages. */
.meta-dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
}

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

/* ============================================================================
   4. LAYOUT & SURFACES
   ============================================================================ */

.container {
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 var(--space-6);
}

.container--narrow {
  max-width: 1000px;
}

.container--form {
  max-width: 700px;
}

.container--wide {
  max-width: 1600px;
}

.section {
  padding: var(--space-12) 0;
}

.section--sm {
  padding: var(--space-8) 0;
}

.section--lg {
  padding: var(--space-16) 0;
}

/* Card component */
.card {
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-xs);
}

.card--interactive {
  cursor: pointer;
  transition: box-shadow var(--duration-base) var(--ease),
    transform var(--duration-base) var(--ease),
    border-color var(--duration-base) var(--ease);
}

.card--interactive:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
  border-color: var(--border-strong);
}

.card--interactive:active {
  transform: translateY(0);
}

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

.card--inset {
  background: var(--bg-elev-2);
}

.card--spacious {
  padding: var(--space-8);
}

.card__header {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}

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

.card__title {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  margin: 0;
}

.card__subtitle {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: var(--space-1);
}

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

.card__heading {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  margin-bottom: var(--space-3);
}

/* A small heading over one group of a card's content */
.card__subheading {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.card__footer {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
}

/* Bunch key list — flat list items inside a card, no nested cards */
.bunch-key-list {
  display: flex;
  flex-direction: column;
}

.bunch-key-item {
  padding: var(--space-3) 0;
}

.bunch-key-item:first-child {
  padding-top: 0;
}

.bunch-key-item:last-child {
  padding-bottom: 0;
}

.bunch-key-item--bordered {
  border-bottom: 1px solid var(--border-subtle);
}

.bunch-key-icon {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  background: var(--bg-elev-2);
  color: var(--text-muted);
}

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

.bunch-name-view__display h1 {
  margin: 0;
}

.bunch-name-view__form {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
  /* Match the h1's line-box height so the subtitle badges don't shift when toggling states. */
  min-height: calc(var(--text-4xl) * var(--leading-tight));
}

.bunch-name-view__form .input {
  min-width: 200px;
  max-width: 400px;
  width: 100%;
}

.bunch-name-edit-actions {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* A card's content in columns with a rule between, side by side once
   there is room for them */
.card__columns {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-6);
}

@media (min-width: 900px) {
  .card__columns {
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
  }

  .card__columns > * + * {
    padding-left: var(--space-6);
    border-left: 1px solid var(--border-subtle);
  }
}

@media (max-width: 899px) {
  .card__columns > * + * {
    padding-top: var(--space-6);
    border-top: 1px solid var(--border-subtle);
  }
}

/* A sub-section's heading inside a card: its icon, its name, where it
   comes from */
.card__group-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}

.card__group-title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

.card__group-head .badge {
  margin-left: auto;
}

/* Card grid - two column layout, stacks on mobile */
.card-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

@media (min-width: 768px) {
  .card-grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* Card variants */
.card--danger {
  background: var(--status-danger-100);
  border-color: var(--status-danger-500);
}

.card--warning {
  background: var(--status-warning-100);
  border-color: var(--status-warning-500);
}

.card--success {
  background: var(--status-success-100);
  border-color: var(--status-success-500);
}

.card--info {
  background: var(--status-info-100);
  border-color: var(--status-info-500);
}

/* ============================================================================
   DEFINITION LIST - Key-value detail layout
   ============================================================================ */

/* Two-column grid on desktop, single-column stack on mobile.
   Handles long values (UUIDs, URLs) without overflowing the card. */
.dl-detail {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: var(--space-2) var(--space-4);
}

.dl-detail dt {
  color: var(--text-muted);
  min-width: 0;
}

.dl-detail dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* Wider key column for data with longer labels */
.dl-detail--wide-key {
  grid-template-columns: 200px 1fr;
}

/* Mobile: stack key above value */
@media (max-width: 767px) {

  .dl-detail,
  .dl-detail--wide-key {
    grid-template-columns: 1fr;
    gap: var(--space-1) 0;
  }

  .dl-detail dd {
    margin-bottom: var(--space-3);
  }

  .dl-detail dd:last-child {
    margin-bottom: 0;
  }
}

/* ============================================================================
   LIST CARD GRID - Responsive grid for list pages
   ============================================================================ */

/* Grid container - fills width, responsive columns */
.list-card-grid {
  display: grid;
  gap: var(--space-3);
  /* Mobile: 2 columns that fill available width */
  grid-template-columns: repeat(2, 1fr);
}

/* Very small screens: single column */
@media (max-width: 399px) {
  .list-card-grid {
    grid-template-columns: 1fr;
  }
}

/* Tablet and up: 3 columns */
@media (min-width: 640px) {
  .list-card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Desktop: 4 columns */
@media (min-width: 1024px) {
  .list-card-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Large desktop: 5 columns */
@media (min-width: 1280px) {
  .list-card-grid {
    grid-template-columns: repeat(5, 1fr);
  }
}

/* List card - clickable item in a list */
.list-card {
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  cursor: pointer;
  transition: border-color var(--duration-base) var(--ease),
    box-shadow var(--duration-base) var(--ease);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  min-width: 0;
  /* Allow flex item to shrink */
}

.list-card:hover {
  border-color: var(--accent-primary-400);
  box-shadow: var(--shadow-sm);
}

.list-card:focus-visible {
  outline: 2px solid var(--accent-primary-500);
  outline-offset: 2px;
}

/* List card as anchor - remove link styling */
a.list-card {
  text-decoration: none;
  color: inherit;
}

a.list-card:hover {
  text-decoration: none;
  color: inherit;
}

/* List card field hierarchy */
.list-card--attention {
  border-left: 3px solid var(--status-warning-500);
}

/* An outcome told by an accent, as a table row's (.table__row--ok, --danger) */
.list-card--ok {
  border-left: 3px solid var(--status-success-600);
}

.list-card--danger {
  border-left: 3px solid var(--status-danger-500);
  background: color-mix(in srgb, var(--status-danger-500) 6%, var(--bg-elev-1));
}

.list-card__primary {
  font-weight: 600;
  font-size: var(--text-lg);
  color: var(--text-strong);
}

.list-card__secondary {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.list-card__badges {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.list-card__meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* What went wrong, as a meta line */
.list-card__meta--danger {
  color: var(--text-danger);
}

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

.list-card__title {
  font-weight: 600;
  color: var(--text-strong);
}

.list-card__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-2);
}

/* ============================================================================
   ITEM ROWS - A list of things one full-width row each, for a column too
   narrow for a card grid (a detail panel, a dashboard panel): a tone accent
   on the left, a name over a muted line, and pills at the end that never
   shrink. A row with role="button" opens the item. Names wrap rather than
   being cut short, as a narrow column has room for the lines but not for
   the width.
   ============================================================================ */

.item-rows {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.item-rows > li {
  margin: 0;
}

.item-row {
  --item-tone: var(--border-strong);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 48px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--item-tone);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
  color: var(--text);
}

.item-row--ok { --item-tone: var(--status-success-600); }
.item-row--info { --item-tone: var(--status-info-500); }
.item-row--warning { --item-tone: var(--status-warning-500); }
.item-row--muted { --item-tone: var(--neutral-400); }

.item-row--danger {
  --item-tone: var(--status-danger-500);
  background: color-mix(in srgb, var(--status-danger-500) 6%, var(--bg-elev-1));
}

.item-row[role="button"] {
  cursor: pointer;
  transition: border-color var(--duration-base) var(--ease),
    box-shadow var(--duration-base) var(--ease);
}

.item-row[role="button"]:hover {
  border-color: var(--border-strong);
  border-left-color: var(--item-tone);
  box-shadow: var(--shadow-sm);
}

.item-row[role="button"]:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.item-row__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.item-row__title {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.item-row__meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

/* What went wrong, under the name */
.item-row__meta--danger {
  color: var(--text-danger);
}

.item-row__end {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
  font-size: var(--text-xs);
  color: var(--text-muted);
  white-space: nowrap;
}

/* ============================================================================
   ITEM ROWS, COMPACT — denser rows for a narrow column (a dashboard's
   aside): no box, a hairline between rows, the tone as a dot. A row led by
   an avatar or icon (`--lead`) has no dot.
   ============================================================================ */

.item-rows--compact {
  gap: 0;
}

.item-rows--compact .item-row {
  min-height: 44px;
  padding: var(--space-2) 0;
  border: 0;
  border-bottom: 1px solid var(--border-subtle);
  border-radius: 0;
  background: none;
}

.item-rows--compact > li:last-child .item-row {
  border-bottom: 0;
}

.item-rows--compact .item-row::before {
  content: "";
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  align-self: flex-start;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--item-tone);
}

.item-rows--compact .item-row--danger {
  background: none;
}

.item-rows--compact .item-row--lead::before {
  content: none;
}

/* ============================================================================
   DEVICE TILE — one piece of hardware: its drawing (an icon tile with its
   state at the corner), its name and kind, where it is, its state, and
   what it holds. For communicators, vaults and gateways alike. A tile that
   is a <button> opens it.
   ============================================================================ */

.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 270px), 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.device-grid > li {
  display: flex;
  margin: 0;
}

.device-tile {
  display: grid;
  flex: 1;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  gap: var(--space-2) var(--space-3);
  min-width: 0;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-elev-1);
  color: var(--text);
  text-align: left;
  font: inherit;
}

.device-tile > .icon-tile {
  grid-row: 1 / span 2;
}

button.device-tile {
  cursor: pointer;
  transition: border-color var(--duration-base) var(--ease), box-shadow var(--duration-base) var(--ease);
}

button.device-tile:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

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

.device-tile--danger {
  border-color: color-mix(in srgb, var(--status-danger-500) 45%, var(--border-subtle));
}

.device-tile__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-2);
  min-width: 0;
}

.device-tile__name {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.device-tile__kind {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.device-tile__body {
  display: grid;
  align-content: end;
  gap: var(--space-2);
  min-width: 0;
}

.device-tile__meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

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

/* ============================================================================
   PILL GROUP - Several pills or badges together, wrapping with a gap both
   ways, in a table cell or anywhere else
   ============================================================================ */

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

/* Figures: each a small label over its value, as many to a row as fit.
   A figure's tone colours its value; a nought or a figure not known recedes
   (--muted), so the figures that matter are what is read. */
.figure-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(5.5rem, 1fr));
  gap: var(--space-3);
  margin: 0;
}

.figure {
  min-width: 0;
}

.figure__label {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.figure__value {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
}

.figure-row--lg .figure__value {
  font-size: var(--text-2xl);
}

/* How old the value is, or why there is none */
.figure__note {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--font-normal);
  color: var(--text-muted);
}

.figure--ok .figure__value { color: var(--status-success-600); }
.figure--warning .figure__value { color: var(--status-warning-600); }
.figure--danger .figure__value { color: var(--text-danger); }

/* "of N", after a figure out of a whole */
.figure__of {
  margin-left: var(--space-1);
  font-size: var(--text-base);
  font-weight: var(--font-medium);
  color: var(--text-muted);
}

.figure--muted .figure__value {
  font-weight: var(--font-normal);
  color: var(--text-subtle);
}

/* A value that opens more about it (a panel), drawn as the value */
.figure__action {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--link);
  cursor: pointer;
}

.figure__action:hover {
  text-decoration: underline;
}

.figure__action:focus-visible {
  outline: none;
  border-radius: var(--radius-sm);
  box-shadow: var(--focus-ring);
}

/* ============================================================================
   METER LIST — what something watches, a line each: an icon, its name, its
   figure (toned only when it says how things are), a segment bar for a
   whole's shares, and a note beneath (the shares in words, or how old the
   figure is). A site card's seals, gateways, communicators, locks and keys.
   ============================================================================ */

.meter-list {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.meter-list > li {
  margin: 0;
}

.meter {
  display: grid;
  gap: var(--space-1);
}

.meter__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
}

.meter__head > .icon {
  color: var(--text-subtle);
}

.meter__label {
  flex: 1;
  min-width: 0;
  color: var(--text-muted);
}

.meter__value {
  font-weight: var(--font-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--text-strong);
}

.meter__value--ok { color: var(--status-success-600); }
.meter__value--warning { color: var(--status-warning-600); }
.meter__value--danger { color: var(--status-danger-600); }

.meter__value--muted {
  font-weight: var(--font-medium);
  color: var(--text-muted);
}

.meter__note {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* ============================================================================
   TALLY — counts of kinds, each an optional icon, a name and a number
   ("CK-BLUE3 12", "Gen 2 1"), wrapping as they need.
   ============================================================================ */

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

.tally-list > li {
  margin: 0;
}

.tally {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-elev-2);
  font-size: var(--text-sm);
  color: var(--text);
}

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

.tally__count {
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
}

/* -700 in light, for AA at this size; the dark theme's -500 and -600 read
   well enough on its surfaces */
.tally__count--ok { color: var(--status-success-700); }
.tally__count--warning { color: var(--status-warning-700); }
.tally__count--danger { color: var(--text-danger); }
.tally__count--muted { font-weight: var(--font-medium); color: var(--text-muted); }

[data-theme="dark"] .tally__count--ok { color: var(--status-success-600); }
[data-theme="dark"] .tally__count--warning { color: var(--status-warning-500); }

/* Plain — a run of icon-and-number figures with no boxes, for a row with
   little room; each names itself to assistive technology and on hover */
.tally-list--plain {
  gap: var(--space-1) var(--space-4);
}

.tally-list--plain .tally {
  gap: var(--space-1);
  padding: 0;
  border: 0;
  background: none;
}

/* ============================================================================
   VITALS — one tile per thing a page watches: its icon tile, its name, one
   headline figure and the shares beneath it. The grid takes as many as
   there are, so a page watching two things and one watching eight both
   read as complete. A tile that is a link opens that thing. Only a tile
   calling for attention carries a rule in its tone along the top: a calm
   page is a quiet one.
   ============================================================================ */

.vital-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-6);
  padding: 0;
  list-style: none;
}

/* Every tile shares its row's five tracks (head, figure, caption, chart,
   note), so the charts and notes of tiles side by side line up whatever
   sits above them. A tile draws all five, an empty caption included. */
.vital-grid > li {
  display: grid;
  grid-row: span 5;
  grid-template-rows: subgrid;
  row-gap: 0;
  margin: 0;
}

.vital {
  --vital-tone: transparent;
  position: relative;
  display: grid;
  grid-row: 1 / -1;
  grid-template-rows: subgrid;
  row-gap: var(--space-3);
  min-width: 0;
  padding: var(--space-4);
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-elev-1);
  box-shadow: var(--shadow-xs);
  color: var(--text);
  text-decoration: none;
}

.vital::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--vital-tone);
}

.vital--warning { --vital-tone: var(--status-warning-500); }
.vital--danger { --vital-tone: var(--status-danger-500); }

a.vital {
  transition: border-color var(--duration-base) var(--ease),
    box-shadow var(--duration-base) var(--ease),
    transform var(--duration-base) var(--ease);
}

a.vital:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
  text-decoration: none;
  color: var(--text);
}

a.vital:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.vital__head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

/* The tile's drawing, bare, in the brand's tint or the tile's tone; grey
   for a figure that can't be read */
.vital__icon {
  color: var(--text-subtle);
}

.vital__icon--primary { color: var(--accent-primary-500); }
.vital__icon--warning { color: var(--status-warning-500); }
.vital__icon--danger { color: var(--status-danger-500); }

.vital__label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-muted);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.vital__value {
  display: flex;
  align-items: baseline;
  gap: var(--space-1);
  margin: 0;
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  line-height: 1;
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.vital__of {
  font-size: var(--text-lg);
  font-weight: var(--font-medium);
  color: var(--text-muted);
  letter-spacing: 0;
}

.vital__caption {
  margin: calc(-1 * var(--space-2)) 0 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* A bar sits on the line a histogram stands on */
.vital > .segment-bar,
.vital > .histogram {
  align-self: end;
}

/* The one thing to know beneath the figure: a state dot and a few words */
.vital__note {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.vital__note--danger {
  font-weight: var(--font-medium);
  color: var(--text-danger);
}

.vital__note--warning {
  font-weight: var(--font-medium);
  color: var(--status-warning-600);
}

[data-theme="dark"] .vital__note--warning {
  color: var(--status-warning-500);
}

/* Not read yet: the figure and its shares shimmer in place */
.vital--loading .vital__value,
.vital--loading .segment-bar {
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--bg-elev-2) 0%, var(--bg-elev-3) 50%, var(--bg-elev-2) 100%);
  background-size: 200% 100%;
  color: transparent;
}

.vital--loading .vital__value {
  width: 60%;
}

.vital--loading .segment-bar__part {
  visibility: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  .vital--loading .vital__value,
  .vital--loading .segment-bar {
    animation: shimmer 1.4s linear infinite;
  }
}

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

/* ============================================================================
   STAT CARDS - Clickable statistic display cards
   ============================================================================ */

.stat-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--space-3);
}

.stat-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-4);
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: box-shadow var(--duration-base) var(--ease),
    transform var(--duration-base) var(--ease),
    border-color var(--duration-base) var(--ease);
}

.stat-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  border-color: var(--border-strong);
}

.stat-card:active {
  transform: translateY(0);
}

.stat-card:focus-visible {
  outline: 2px solid var(--accent-primary-500);
  outline-offset: 2px;
}

/* Stat card as anchor - remove link styling */
a.stat-card {
  text-decoration: none;
  color: inherit;
}

a.stat-card:hover {
  text-decoration: none;
  color: inherit;
}

.stat-card__value {
  font-size: var(--text-3xl);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  line-height: 1;
}

.stat-card__label {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: var(--space-2);
}

/* ============================================================================
   TOGGLE SWITCH - Binary on/off control for settings and module toggles
   ============================================================================ */

.toggle-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 44px;
  height: 24px;
  background-color: var(--neutral-500);
  border: none;
  border-radius: 12px;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease);
  padding: 0;
  flex-shrink: 0;
}

.toggle-switch__slider {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background-color: var(--text-inverse);
  border-radius: 50%;
  transition: transform var(--duration-fast) var(--ease);
  pointer-events: none;
}

.toggle-switch--on {
  background-color: var(--status-success-600);
}

.toggle-switch--on .toggle-switch__slider {
  transform: translateX(20px);
}

.toggle-switch:hover {
  opacity: 0.85;
}

.toggle-switch:focus-visible {
  box-shadow: var(--focus-ring);
  outline: none;
}

.toggle-switch:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

/* Module/settings item row */
.module-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) 0;
}

.toggle-switch-form+.toggle-switch-form .module-item {
  border-top: 1px solid var(--border-subtle);
}

.module-item__info {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.module-item__name {
  font-weight: var(--font-medium);
  color: var(--text);
}

.module-item__description {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

@media (prefers-reduced-motion: reduce) {

  .toggle-switch,
  .toggle-switch__slider {
    transition: none;
  }
}

/* ============================================================================
   5. HEADER
   ============================================================================ */

.header {
  background: var(--bg-header);
  color: var(--text-inverse);
  border-bottom: 1px solid var(--neutral-800);
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: var(--shadow-sm);
}

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-6);
  max-width: 1600px;
  margin: 0 auto;
}

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

.header__brand:hover {
  text-decoration: none;
  opacity: 0.9;
}

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

.header__link {
  color: var(--text-inverse);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  transition: background-color var(--duration-base) var(--ease);
}

.header__link:hover {
  background: rgba(255, 255, 255, 0.1);
  text-decoration: none;
}

.header__link--active {
  background: rgba(255, 255, 255, 0.15);
}

/* User menu dropdown */
.user-menu {
  position: relative;
}

.user-menu__trigger {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border: none;
  background: transparent;
  color: var(--text-inverse);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  cursor: pointer;
  border-radius: var(--radius-md);
  transition: background-color var(--duration-base) var(--ease);
}

.user-menu__trigger:hover {
  background: rgba(255, 255, 255, 0.1);
}

.user-menu__dropdown {
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  min-width: 240px;
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: 1000;
  overflow: hidden;
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 0.1s ease-out, transform 0.1s ease-out;
}

.user-menu__dropdown--open {
  opacity: 1;
  transform: scale(1);
}

.user-menu__header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  background: var(--bg-elev-2);
}

.user-menu__identity {
  min-width: 0;
}

.user-menu__name {
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  font-size: var(--text-sm);
  margin-bottom: var(--space-1);
}

.user-menu__email {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* Avatar — circular profile photo (user menu, user detail header) */
.avatar {
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  background: var(--bg-elev-2);
}

.avatar--sm {
  width: 28px;
  height: 28px;
}

.avatar--lg {
  width: 64px;
  height: 64px;
}

/* A person without a photo, as their initials */
.avatar--initials {
  display: inline-grid;
  place-items: center;
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  color: var(--text-muted);
  background: var(--bg-elev-3);
  letter-spacing: 0.02em;
}

.avatar--md {
  width: 36px;
  height: 36px;
}

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

.user-menu__links {
  padding: var(--space-2) 0;
}

.user-menu__footer {
  padding: var(--space-2) 0;
  border-top: 1px solid var(--border-subtle);
}

.user-menu__link {
  display: block;
  padding: var(--space-2) var(--space-4);
  color: var(--text);
  font-size: var(--text-sm);
  text-decoration: none;
  transition: background-color var(--duration-base) var(--ease);
}

.user-menu__link:hover {
  background: var(--bg-elev-2);
  text-decoration: none;
}

.user-menu__link--danger {
  color: var(--status-danger-600);
}

.user-menu__link--danger:hover {
  background: var(--status-danger-100);
}

/* ============================================================================
   6. FOOTER
   ============================================================================ */

.footer {
  padding: var(--space-6);
  margin-top: auto;
}

.footer__text {
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-align: center;
  margin: 0;
}

/* ============================================================================
   7. BUTTONS
   ============================================================================ */

:root {
  --btn-radius: var(--radius-md);
  --btn-padding-y: 8px;
  --btn-padding-x: 14px;
  --btn-font-size: var(--text-sm);
  --btn-font-weight: var(--font-medium);
  --btn-transition: all var(--duration-base) var(--ease);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border-radius: var(--btn-radius);
  font-size: var(--btn-font-size);
  font-weight: var(--btn-font-weight);
  font-family: inherit;
  line-height: 1;
  padding: var(--btn-padding-y) var(--btn-padding-x);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: var(--btn-transition);
  white-space: nowrap;
  user-select: none;
}

.btn:hover {
  text-decoration: none;
}

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

.btn:active {
  transform: translateY(0.5px);
}

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

/* Button with icon */
.btn__icon {
  flex-shrink: 0;
}

/* Button variants */
.btn--primary {
  background: var(--accent-primary-500);
  color: var(--text-inverse);
  border-color: var(--accent-primary-500);
}

.btn--primary:hover {
  background: var(--accent-primary-600);
  color: var(--text-inverse);
  border-color: var(--accent-primary-600);
}

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

.btn--secondary:hover {
  background: var(--accent-primary-500);
  color: var(--text-inverse);
  border-color: var(--accent-primary-500);
}

.btn--tertiary {
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}

.btn--tertiary:hover {
  background: var(--bg-elev-2);
  color: var(--text);
  border-color: var(--border-strong);
}

/* A <button> that reads as a link: for an action that belongs in running
   text, such as opening a panel from a name. Used alone, without .btn. */
.btn--link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--link);
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.btn--link:hover {
  color: var(--link-hover);
}

.btn--link:focus-visible {
  outline: none;
  border-radius: var(--radius-sm);
  box-shadow: var(--focus-ring);
}

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

.btn--ghost:hover {
  background: var(--bg-elev-2);
  color: var(--text);
}

.btn--danger {
  background: var(--status-danger-600);
  color: var(--text-inverse);
  border-color: var(--status-danger-600);
}

.btn--danger:hover {
  background: var(--status-danger-700);
  color: var(--text-inverse);
  border-color: var(--status-danger-700);
}

.btn--danger:focus-visible {
  box-shadow: var(--focus-ring-danger);
}

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

.btn--danger-outline:hover {
  background: var(--status-danger-600);
  color: var(--text-inverse);
  border-color: var(--status-danger-600);
}

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

.btn--success {
  background: var(--status-success-600);
  color: var(--text-inverse);
  border-color: var(--status-success-600);
}

.btn--success:hover {
  background: var(--status-success-700);
  color: var(--text-inverse);
  border-color: var(--status-success-700);
}

/* Button sizes */
.btn--xs {
  padding: 4px 8px;
  font-size: var(--text-xs);
  gap: 4px;
}

.btn--sm {
  padding: 6px 10px;
  font-size: var(--text-sm);
}

.btn--lg {
  padding: 10px 18px;
  font-size: var(--text-md);
}

.btn--xl {
  padding: 12px 22px;
  font-size: var(--text-lg);
}

/* Button block (full width) */
.btn--block {
  display: flex;
  width: 100%;
}

/* Icon-only buttons */
.pencil-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  padding: var(--space-1);
  cursor: pointer;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  flex-shrink: 0;
  transition: color var(--duration-base) var(--ease),
              background var(--duration-base) var(--ease);
}

.pencil-btn:hover,
.pencil-btn:focus-visible {
  color: var(--text-strong);
  background: var(--bg-elev-2);
  outline: none;
}

.pencil-btn:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
}


/* ============================================================================
   8. FORMS
   ============================================================================ */

:root {
  --field-radius: var(--radius-md);
  --field-padding-y: 8px;
  --field-padding-x: 10px;
  --field-bg: var(--bg-elev-1);
  --field-border: var(--border);
  --field-border-focus: var(--accent-primary-500);
  --field-shadow-focus: var(--focus-ring);
  --field-font-size: var(--text-sm);
}

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

/* Only zero the bottom margin when a `.field` is the literal last child of
   a top-level form container (`form`, `.card`, `fieldset`). Without the
   parent qualifier, intermediate `.field`s nested inside containers like
   the per-day scheduled rows would lose their gap when they happen to
   end a wrapper. */
form > .field:last-child,
.card > .field:last-child,
fieldset > .field:last-child {
  margin-bottom: 0;
}

.inline-fields {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.inline-fields .field {
  flex: 1;
  min-width: 150px;
  margin-bottom: 0;
}

.inline-fields .select {
  width: 100%;
}

.label {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-strong);
  display: block;
}

.label--required::after {
  content: " *";
  color: var(--status-danger-500);
}

.input,
.textarea,
.select {
  width: 100%;
  background: var(--field-bg);
  color: var(--text);
  border: 1px solid var(--field-border);
  border-radius: var(--field-radius);
  padding: var(--field-padding-y) var(--field-padding-x);
  font-size: var(--field-font-size);
  font-family: inherit;
  line-height: var(--leading-normal);
  transition: border-color var(--duration-base) var(--ease),
    box-shadow var(--duration-base) var(--ease);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--text-subtle);
}

.input:hover,
.textarea:hover,
.select:hover {
  border-color: var(--border-strong);
}

.input:focus,
.textarea:focus,
.select:focus {
  outline: none;
  border-color: var(--field-border-focus);
  box-shadow: var(--field-shadow-focus);
}

.input:disabled,
.textarea:disabled,
.select:disabled {
  background: var(--bg-elev-2);
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 0.6;
}

/* Read-only display fields: visibly non-editable (no text cursor, no
   hover/focus affordances) but still focusable so assistive tech
   announces the read-only state. */
.input[readonly],
.textarea[readonly] {
  background: var(--bg-elev-2);
  color: var(--text-muted);
  cursor: default;
}

.input[readonly]:hover,
.textarea[readonly]:hover {
  border-color: var(--field-border);
}

.input[readonly]:focus,
.textarea[readonly]:focus {
  border-color: var(--field-border);
  box-shadow: none;
}

/* Validation states */
.input[aria-invalid="true"],
.textarea[aria-invalid="true"],
.select[aria-invalid="true"] {
  border-color: var(--status-danger-500);
}

.input[aria-invalid="true"]:focus,
.textarea[aria-invalid="true"]:focus,
.select[aria-invalid="true"]:focus {
  box-shadow: var(--focus-ring-danger);
}

/* Input sizes */
.input--sm,
.select--sm {
  padding: 6px 8px;
  font-size: var(--text-xs);
}

.input--lg,
.select--lg {
  padding: 10px 12px;
  font-size: var(--text-base);
}

.input--medium,
.select--medium {
  max-width: 300px;
}

.input--narrow,
.select--narrow {
  max-width: 160px;
}

/* Phone input — dial-code select beside the national number. Wraps on
   narrow viewports so the trailing verify button never overflows. */
.phone-input {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.phone-input__country {
  flex: 0 1 11rem;
  min-width: 8rem;
}

.phone-input__number {
  flex: 1 1 10rem;
}

/* Textarea */
.textarea {
  min-height: 80px;
  resize: vertical;
}

.textarea--sm {
  min-height: 60px;
  padding: 6px 8px;
  font-size: var(--text-xs);
}

.textarea--lg {
  min-height: 120px;
  padding: 10px 12px;
  font-size: var(--text-base);
}

/* Helper text */
.help-text {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin: 0;
}

.error-text {
  font-size: var(--text-xs);
  color: var(--status-danger-600);
  margin: 0;
}

.success-text {
  font-size: var(--text-xs);
  color: var(--status-success-600);
  margin: 0;
}

/* Radio group fieldset — reset browser chrome for accessible grouping */
.radio-fieldset {
  border: none;
  margin: 0;
  padding: 0;
  min-inline-size: 0;
}

/* A group of related fields under its own heading (one site's location
   in a list of sites, say), without the browser's border. Groups stack
   with space between them. */
.fieldset {
  border: none;
  margin: 0 0 var(--space-6) 0;
  padding: 0;
  min-inline-size: 0;
}

.fieldset:last-child {
  margin-bottom: 0;
}

.fieldset__legend {
  padding: 0;
  margin-bottom: var(--space-3);
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

/* Checkbox and radio */
.checkbox,
.radio {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  cursor: pointer;
  margin-bottom: var(--space-3);
}

.checkbox input[type="checkbox"],
.radio input[type="radio"] {
  width: 16px;
  height: 16px;
  cursor: pointer;
  accent-color: var(--accent-primary-500);
}

.checkbox input[type="checkbox"]:focus-visible,
.radio input[type="radio"]:focus-visible {
  outline: 2px solid var(--accent-primary-500);
  outline-offset: 2px;
}

.checkbox__label,
.radio__label {
  font-size: var(--text-sm);
  color: var(--text);
  cursor: pointer;
}

.radio__description {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin-top: var(--space-1);
  font-weight: normal;
}

/* Radio with description — align radio to top of multi-line label */
.radio--with-description {
  align-items: flex-start;
}

.radio--with-description input[type="radio"] {
  margin-top: 2px;
}

/* Radio group — container for a set of radio buttons */
.radio-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.radio-group .radio {
  margin-bottom: 0;
}

.radio-group--inline {
  flex-direction: row;
  gap: var(--space-4);
}

/* Card-style radio group — each radio renders as a bordered card with its
   own padding and hover / checked affordances. Use for "pick one of two"
   decisions that deserve visual weight (e.g. a mode toggle at the top of
   a form). Composes with .radio-group--inline for side-by-side cards. */
.radio-group--cards {
  gap: var(--space-3);
}

.radio-group--cards .radio {
  flex: 1;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
  min-height: 44px;
  margin-bottom: 0;
  transition:
    border-color var(--duration-base) var(--ease),
    background-color var(--duration-base) var(--ease);
}

.radio-group--cards .radio:hover {
  border-color: var(--accent-primary-300);
}

.radio-group--cards .radio:has(input:checked) {
  border-color: var(--accent-primary-500);
  background: var(--accent-primary-50);
}

.radio-group--cards .radio__label {
  font-weight: var(--font-medium);
}

/* Checkbox grid — scrollable multi-select surface, one column on narrow
   screens, two columns from 768px up. Each item is a full-width, tap-
   sized row with a border-radius so hover feels at home on touch. */
.checkbox-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2);
  max-height: 16rem;
  overflow-y: auto;
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
}

@media (min-width: 768px) {
  .checkbox-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.checkbox-grid__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2);
  min-height: 44px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  margin: 0;
}

.checkbox-grid__item:hover {
  background: var(--bg-elev-2);
}

.checkbox-grid__item input[type="checkbox"] {
  width: 18px;
  height: 18px;
}

/* Pick-list — a bordered, scrollable `<ul>` of rows, each with a label
   on the left and an action (typically a button) on the right. Drops
   into any "search and link" / "search and pick" surface. */
.pick-list {
  list-style: none;
  padding: 0;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  max-height: 16rem;
  overflow-y: auto;
  background: var(--bg-elev-1);
}

.pick-list__item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.pick-list__item:last-child {
  border-bottom: none;
}

/* Repeatable row — a bordered block used in dynamic list-of-items
   forms (e.g. adding keys to a bunch). Pair with .repeat-row__header
   for a title + remove-button strip, and any grid utility (e.g.
   .form-grid .form-grid--3) for the field layout. */
.repeat-row {
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-2);
}

.repeat-row__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-2);
}

.repeat-row .field {
  margin-bottom: 0;
}

/* Form grid */
.form-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-4);
}

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

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

/* Form actions */
.form-actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-6);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
  justify-content: space-between;
}

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

.form-actions--right {
  justify-content: flex-end;
}

.form-actions--compact {
  margin-top: var(--space-3);
  padding-top: 0;
  border-top: 0;
}

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

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

/* Horizontal row of buttons/forms that wraps on narrow screens.
   Distinct from .form-actions (which has delete-left / discard-save-right
   semantics) — use .action-row for inline rows of peer actions. */
.action-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

/* Form that shrinks to its content so a button inside can sit inline
   with sibling anchors/buttons (typical in table action cells). */
.inline-form {
  display: inline;
}

/* Dynamic item list — editable bullet list backed by individual inputs. */
.item-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

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

.item-list__handle {
  display: none;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  user-select: none;
  flex-shrink: 0;
  width: 28px;
  align-self: stretch;
  cursor: grab;
  border-radius: var(--radius-sm);
}

@media (min-width: 768px) {
  .item-list__handle {
    display: flex;
  }
}

.item-list__handle:hover {
  color: var(--text-secondary);
  background: var(--surface-hover);
}

.item-list__handle:active {
  cursor: grabbing;
}

.item-list__row--dragging {
  opacity: 0.4;
}

.item-list__drop-indicator {
  height: 2px;
  background: var(--accent);
  border-radius: 1px;
}

.item-list__input {
  flex: 1;
  min-width: 0;
}

.item-list__arrows {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  gap: 2px;
}

.item-list__arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 18px;
  padding: 0;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--surface-hover);
  color: var(--text-muted);
  cursor: pointer;
}

.item-list__arrow:hover:not(:disabled) {
  color: var(--text);
  background: var(--border);
}

.item-list__arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

@media (min-width: 768px) {
  .item-list__arrows {
    display: none;
  }
}

.item-list__remove {
  flex-shrink: 0;
  color: var(--text-muted);
}

.item-list__remove:hover:not(:disabled) {
  color: var(--danger);
}

.item-list__remove:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Page header with back link */
.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.page-header> :first-child {
  flex: 1;
  min-width: 0;
}

.page-header__title {
  margin: 0 0 var(--space-2) 0;
}

.page-header__identity {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.page-header__subtitle {
  color: var(--text-muted);
  font-size: var(--text-sm);
  margin: 0;
}

.page-header__back {
  color: var(--text-muted);
  font-size: var(--text-sm);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2) 0;
  transition: color var(--transition-fast);
}

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

.page-header__actions {
  display: flex;
  flex-shrink: 0;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-1);
}

/* Sticky — the header stays beneath the top bar as the page scrolls, so
   what the page is about, and the chips that change it, stay in reach.
   From 768px only: on a phone it would take too much of the screen. */
@media (min-width: 768px) {
  .page-header--sticky {
    position: sticky;
    top: var(--top-nav-height, 0px);
    z-index: 20;
    padding: var(--space-3) 0;
    border-bottom: 1px solid var(--border-subtle);
    background: var(--bg-page);
  }

  .page-header--sticky .page-header__title {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  /* What the page scrolls to, or focus moves to, lands below the top bar
     and the header, not beneath them. The page's script keeps
     --sticky-header-height to the header's height. */
  html:has(.page-header--sticky) {
    scroll-padding-top: calc(var(--top-nav-height, 0px) + var(--sticky-header-height, 0px) + var(--space-2));
  }
}

/* Beside the title, a verdict takes at most half the header, cut short,
   so a long one never squeezes the title away */
@media (min-width: 768px) {
  .page-header__actions:has(> .attention-button) {
    min-width: 0;
    max-width: 50%;
  }
}

/* Mobile: stack page header vertically with actions above title */
@media (max-width: 767px) {
  .page-header {
    flex-direction: column;
    align-items: stretch;
  }

  .page-header__actions {
    order: -1;
    margin-top: 0;
    margin-bottom: var(--space-3);
  }

  .page-header__back {
    display: none;
  }
}

/* Meta chips — small facts beside a page's title (where it is, how many
   areas, a policy, a clock), each an icon and a few words. A chip that is
   a <button> opens more about it (a trailing `icon--chevron` says it
   chooses something); one that is a link goes somewhere. `--icon` is a
   chip that is only an icon, its name in its aria-label. */
.meta-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}

.meta-chips > li {
  min-width: 0;
  margin: 0;
}

.meta-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: 100%;
  min-height: 28px;
  padding: 2px var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  background: var(--bg-elev-1);
  color: var(--text-muted);
  font: inherit;
  font-size: var(--text-sm);
  white-space: nowrap;
}

.meta-chip__text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.meta-chip .icon {
  color: var(--text-subtle);
}

.meta-chip strong {
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

button.meta-chip,
a.meta-chip {
  cursor: pointer;
  text-decoration: none;
  transition: border-color var(--duration-base) var(--ease), color var(--duration-base) var(--ease);
}

button.meta-chip:hover,
a.meta-chip:hover {
  border-color: var(--border-strong);
  color: var(--text);
  text-decoration: none;
}

button.meta-chip:focus-visible,
a.meta-chip:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.meta-chip--icon {
  justify-content: center;
  width: 28px;
  padding: 0;
}

.meta-chip--ok .icon { color: var(--status-success-600); }
.meta-chip--warning { border-color: color-mix(in srgb, var(--status-warning-500) 50%, var(--border-subtle)); }
.meta-chip--warning .icon { color: var(--status-warning-500); }

/* A row of chips heading the card they describe (a site's address, its
   policy and CAW's clock above its summary tiles), ruled off beneath */
.meta-chips--bar {
  margin: 0 0 var(--space-5);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}

/* Date grid component — compact date selector for scheduling */
.date-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--space-1);
}

.date-grid__btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 44px;
  padding: var(--space-2) var(--space-1);
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition:
    background-color var(--duration-base) var(--ease),
    border-color var(--duration-base) var(--ease);
}

.date-grid__btn:hover {
  border-color: var(--accent-primary-400);
}

.date-grid__btn--today {
  border-color: var(--accent-primary-500);
}

.date-grid__btn--selected {
  background: var(--accent-primary-500);
  border-color: var(--accent-primary-500);
  color: #fff;
}

.date-grid__btn--selected .date-grid__day {
  opacity: 0.9;
}

.date-grid__day {
  font-size: var(--text-xs);
  opacity: 0.7;
}

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

/* Autocomplete component */
.autocomplete {
  position: relative;
}

.autocomplete__search {
  width: 100%;
}

.autocomplete__results {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  box-shadow: var(--shadow-md);
  max-height: 300px;
  overflow-y: auto;
}

.autocomplete__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  border-bottom: 1px solid var(--border-subtle);
  transition: background-color var(--duration-base) var(--ease);
}

.autocomplete__item:last-child {
  border-bottom: none;
}

.autocomplete__item:hover {
  background: var(--bg-elev-2);
}

.autocomplete__item--create {
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
  color: var(--accent-primary-500);
  font-weight: var(--font-medium);
  border-top: 1px solid var(--border);
  background: var(--bg-elev-2);
}

.autocomplete__item--create:hover {
  background: var(--bg-elev-3);
}

.autocomplete__item-icon {
  font-size: var(--text-lg);
  font-weight: var(--font-bold);
}

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

.autocomplete__item-meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.autocomplete__empty {
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-align: center;
}

.autocomplete__selected {
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.autocomplete__selected-text {
  flex: 1;
  font-size: var(--text-sm);
  color: var(--text);
}

.autocomplete__clear {
  flex-shrink: 0;
  padding: var(--space-1);
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  font-size: var(--text-sm);
  line-height: 1;
  transition: color var(--duration-base) var(--ease);
}

.autocomplete__clear:hover {
  color: var(--text);
}

/* Inline create fields */
.autocomplete__create {
  display: none;
  padding: var(--space-4);
  margin-top: var(--space-2);
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.autocomplete__create-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.autocomplete__create-title {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-strong);
}

.autocomplete__create-cancel {
  font-size: var(--text-xs);
  color: var(--text-muted);
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: underline;
}

.autocomplete__create-cancel:hover {
  color: var(--text);
}

/* ============================================================================
   8b. TABS
   ============================================================================ */

.tabs {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-6);
}

.tabs__tab {
  padding: var(--space-2) var(--space-4);
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-muted);
  cursor: pointer;
  transition: all var(--transition-fast);
  text-decoration: none;
}

.tabs__tab:hover {
  color: var(--text);
  border-bottom-color: var(--neutral-300);
}

.tabs__tab--active {
  color: var(--accent-primary-500);
  border-bottom-color: var(--accent-primary-500);
}

.tabs__tab--active:hover {
  color: var(--accent-primary-600);
  border-bottom-color: var(--accent-primary-600);
}

/* A long tab row scrolls sideways on a narrow screen instead of wrapping
   under itself or pushing the page wide */
.tabs--scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.tabs--scroll::-webkit-scrollbar {
  display: none;
}

.tabs--scroll .tabs__tab {
  flex-shrink: 0;
  white-space: nowrap;
}

.tabs__panel {
  display: none;
}

.tabs__panel--active {
  display: block;
}

/* Tabs in sections (a segmented control above the row names them): only
   the open section's tabs are in the row, and a section with one tab has
   no row at all. tabs.js keeps both as the section changes. */
.tabs__tab--off-group,
.tabs--single {
  display: none;
}

/* ============================================================================
   SEGMENTED — a few options on one rail, the current one filled with the
   brand's tint: a page's sections above its tabs, or two ways of showing
   one list. Each option is a link or button with an optional icon and a
   state dot at its end, `--active` (and aria-current) on the current one.
   Choosing one changes only its fill and colours, never its size, so the
   rail never shifts. `--scroll` scrolls sideways on a narrow screen rather
   than wrapping.
   ============================================================================ */

.segmented {
  display: inline-flex;
  max-width: 100%;
  gap: 2px;
  margin-bottom: var(--space-3);
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-elev-1);
  box-shadow: var(--shadow-xs);
}

.segmented--scroll {
  overflow-x: auto;
  scrollbar-width: none;
}

.segmented--scroll::-webkit-scrollbar {
  display: none;
}

.segmented__option {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--space-2);
  min-height: 34px;
  padding: 0 var(--space-4);
  border: 0;
  border-radius: calc(var(--radius-lg) - 3px);
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease),
    color var(--duration-fast) var(--ease);
}

.segmented__option:hover {
  background: var(--bg-elev-2);
  color: var(--text);
  text-decoration: none;
}

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

.segmented__option--active,
.segmented__option--active:hover {
  background: color-mix(in srgb, var(--accent-primary-500) 14%, var(--bg-elev-1));
  color: var(--text-strong);
}

.segmented__option .icon {
  color: var(--text-subtle);
  transition: color var(--duration-fast) var(--ease);
}

.segmented__option--active .icon {
  color: var(--accent-primary-500);
}

/* Something in the section calls for attention */
.segmented__dot {
  width: 7px;
  height: 7px;
}

/* ============================================================================
   8c. MULTI-SELECT
   ============================================================================ */

.multi-select__items {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.multi-select__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-size: var(--text-sm);
  color: var(--text);
}

.multi-select__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 50%;
  font-size: var(--text-xs);
  color: var(--text-muted);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.multi-select__remove:hover {
  background: var(--status-danger-100);
  color: var(--status-danger-600);
}

.multi-select__empty {
  font-size: var(--text-sm);
  color: var(--text-muted);
  margin-top: var(--space-3);
}


/* ============================================================================
   8d. MODAL
   ============================================================================ */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: var(--space-4);
}

.modal {
  background: var(--bg-elev-1);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 500px;
  max-height: calc(100vh - var(--space-8));
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.modal__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.modal__header h3 {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
}

.modal__body {
  padding: var(--space-4);
  overflow-y: auto;
  flex: 1;
}

.modal__footer {
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
  padding: var(--space-4);
  border-top: 1px solid var(--border);
}

.modal__subtitle {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.modal__close {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text-muted);
  font-size: var(--text-xl);
  line-height: 1;
  cursor: pointer;
}

.modal__close:hover {
  background: var(--bg-elev-2);
  color: var(--text);
}

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

@media (prefers-reduced-motion: no-preference) {
  .modal-overlay:not([hidden]) .modal {
    animation: modal-enter var(--duration-slow) var(--ease);
  }
}

@keyframes modal-enter {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
  }
}

/* ============================================================================
   9. DATA TABLES
   ============================================================================ */

.table-wrapper {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-elev-1);
}

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

.table thead {
  background: var(--bg-elev-2);
  border-bottom: 1px solid var(--border);
}

.table th {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  font-weight: var(--font-semibold);
  font-size: var(--text-xs);
  color: var(--text-strong);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.table td {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border-subtle);
}

.table tbody tr:first-child td {
  border-top: none;
}

/* Interactive rows - hover highlight only, links handle navigation */
.table--interactive tbody tr {
  transition: background-color var(--duration-fast) var(--ease);
}

.table--interactive tbody tr:hover {
  background: var(--bg-elev-2);
}

/* Clickable rows: a link (data-href) or a script-opened panel (role="button") */
.table--interactive tbody tr[data-href],
.table--interactive tbody tr[role="button"] {
  cursor: pointer;
}

/* Drawn inside the row, so a scrolling wrapper never clips it and a row's
   accent edge stays */
.table--interactive tbody tr[data-href]:focus-visible,
.table--interactive tbody tr[role="button"]:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: -2px;
  background: var(--bg-elev-2);
}

/* Compact variant */
.table--compact th,
.table--compact td {
  padding: var(--space-2) var(--space-3);
}

/* Striped variant */
.table--striped tbody tr:nth-child(even) {
  background: var(--bg-elev-2);
}

/* Column alignment */
.table th.align-right,
.table td.align-right {
  text-align: right;
}

.table th.align-center,
.table td.align-center {
  text-align: center;
}

/* Table cell links */
.table__link {
  color: var(--text-strong);
  text-decoration: none;
  font-weight: var(--font-semibold);
}

.table__link:hover {
  color: var(--accent-primary-600);
  text-decoration: underline;
}

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

/* Status cell */
.table__status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
}

.table__status--active {
  background: var(--status-success-100);
  color: var(--status-success-700);
}

.table__status--inactive {
  background: var(--neutral-200);
  color: var(--neutral-700);
}

.table__status--warning {
  background: var(--status-warning-100);
  color: var(--status-warning-700);
}

.table__status--danger {
  background: var(--status-danger-100);
  color: var(--status-danger-700);
}

/* A row needing admin attention (e.g. an unplaced gateway) */
.table__row--attention td:first-child {
  box-shadow: inset 3px 0 0 var(--status-warning-500);
}

/* A row's outcome told by an accent rather than a column: a quiet green
   edge for a good one, a red edge and wash for a bad one */
.table__row--ok td:first-child {
  box-shadow: inset 3px 0 0 var(--status-success-600);
}

.table__row--danger td {
  background: color-mix(in srgb, var(--status-danger-500) 6%, transparent);
}

.table__row--danger td:first-child {
  box-shadow: inset 3px 0 0 var(--status-danger-500);
}

/* A cell's second line: the lesser fact beneath its main one */
.table__sub {
  display: block;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* A second line telling what went wrong */
.table__sub--danger {
  color: var(--text-danger);
}

/* Right-aligned action cell: holds Edit/Toggle/Delete buttons in list tables.
   Kept tight (no-wrap) so the buttons stay on one line even on narrow rows. */
.table__cell--actions {
  text-align: right;
  white-space: nowrap;
}

/* ============================================================================
   PAGINATION
   ============================================================================ */

.pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-4) 0;
  margin-top: var(--space-4);
  border-top: 1px solid var(--border);
  gap: var(--space-4);
}

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

.pagination__controls {
  display: flex;
  gap: var(--space-2);
}

.pagination .btn--disabled {
  opacity: 0.4;
  pointer-events: none;
}

@media (max-width: 767px) {
  .pagination {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
  }

  .pagination__controls {
    justify-content: center;
  }
}

/* A postal address set out line by line */
.address {
  font-style: normal;
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--text-strong);
}

.address__line {
  display: block;
}

/* Detail grid for displaying key-value pairs */
.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-4);
}

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

.detail-item--full {
  grid-column: 1 / -1;
}

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

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

/* ============================================================================
   9b. LIST CARDS
   Mobile-friendly card grids for list pages
   ============================================================================ */

/* Grid container - fills width, responsive columns */
/* ============================================================================
   9c. VIEW SWITCHER
   Toggle between table and card views on list pages
   ============================================================================ */

/* View switcher - hidden on mobile */
.view-switcher {
  display: none;
}

@media (min-width: 768px) {
  .view-switcher {
    display: flex;
    gap: var(--space-1);
    align-items: center;
  }

  .view-switcher__label {
    font-size: var(--text-sm);
    color: var(--text-muted);
    margin-right: var(--space-2);
  }

  .view-switcher__btn {
    padding: var(--space-2);
    border: 1px solid var(--border);
    background: var(--bg-elev-1);
    border-radius: var(--radius-sm);
    cursor: pointer;
    color: var(--text-muted);
    transition: all 0.2s;
  }

  .view-switcher__btn:hover {
    background: var(--bg-elev-2);
    border-color: var(--border-strong);
  }

  .view-switcher__btn--active {
    background: var(--accent-primary-500);
    border-color: var(--accent-primary-500);
    color: var(--text-inverse);
  }

  .view-switcher__btn--active:hover {
    background: var(--accent-primary-600);
    border-color: var(--accent-primary-600);
  }

  .view-switcher__btn svg {
    width: 18px;
    height: 18px;
    display: block;
  }
}

/* Filter bar — row of filter buttons above a list or table. Wraps on
   narrow viewports so the 4–6 state chips common on our list pages
   don't force horizontal overflow. Use with .btn btn--sm / btn--xs
   children; drive active state by toggling btn--primary / btn--ghost. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

/* Secondary controls, pushed to the far end */
.filter-bar__end {
  display: flex;
  gap: var(--space-1);
  margin-left: auto;
}

/* Linked card — the whole card is one link, without being an <a>. The link
   sits on the card's title and is stretched over it, so other controls can
   live inside the card: lift them above the link with .card__raised. */
.card--linked {
  position: relative;
}

.card__link {
  color: inherit;
  text-decoration: none;
}

.card__link:hover {
  text-decoration: none;
}

.card__link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.card__link:focus-visible {
  outline: none;
}

.card--linked:has(.card__link:focus-visible) {
  box-shadow: var(--focus-ring);
}

.card__raised {
  position: relative;
  z-index: 1;
}

/* Attention strip — the few items on a page that need someone, lifted out
   of wherever they sit and listed flat, worst first */
.attention-strip {
  margin-bottom: var(--space-5);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-left: 4px solid var(--status-warning-500);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
}

.attention-strip--danger {
  border-left-color: var(--status-danger-500);
}

.attention-strip__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.attention-strip__title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

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

.attention-strip__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.attention-strip__list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: 0;
}

/* The item keeps 16rem beside its action, or the action takes its own line
   beneath it (always, on a phone), so a long label or action never
   squeezes the name. Items in a row stand as tall as the tallest, their
   content at the top. */
.attention-strip__list li > .attention-strip__item {
  flex: 1 1 16rem;
  align-self: stretch;
  min-width: 0;
}

/* An action for the item (a small POST form or link), beside its link,
   never inside it: a form can't sit inside a link */
.attention-strip__action {
  flex-shrink: 0;
  margin: 0 0 0 auto;
}

.attention-strip__item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-content: start;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--status-warning-500) 8%, var(--bg-elev-1));
  color: inherit;
  text-decoration: none;
}

/* A danger item is the page's alarm (a seal missing): ruled and washed in
   red, its label (how long, say) in red, its tile pulsing */
.attention-strip__item--danger {
  border-color: var(--status-danger-500);
  background: color-mix(in srgb, var(--status-danger-500) 12%, var(--bg-elev-1));
}

.attention-strip__item--danger .attention-strip__label {
  font-weight: var(--font-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--status-danger-600);
}

[data-theme="dark"] .attention-strip__item--danger .attention-strip__label {
  color: var(--status-danger-500);
}

@media (prefers-reduced-motion: no-preference) {
  .attention-strip__item--danger > .icon-tile {
    animation: status-pill-alarm 1.2s ease-in-out infinite;
  }
}

/* An item that opens a panel rather than a page: a role="button" element,
   since a <button> can't hold the item's list of facts */
.attention-strip__item[role="button"] {
  cursor: pointer;
}

.attention-strip__item:hover {
  text-decoration: none;
  box-shadow: var(--shadow-xs);
}

.attention-strip__item:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.attention-strip__names {
  display: grid;
  min-width: 0;
}

.attention-strip__name {
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.attention-strip__context {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* An item's problems, one a line beneath its names */
.attention-strip__item > .state-list {
  grid-column: 1 / -1;
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-subtle);
}

.attention-strip__label {
  min-width: 0;
  text-align: right;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text);
}

/* In a modal or a narrow column: one item a row */
.attention-strip__list--stack {
  grid-template-columns: minmax(0, 1fr);
}

/* Attention button — a page's verdict in its header: what is wrong, in the
   tone of the worst of it, opening the list of what needs attention. With
   nothing wrong it is a quiet line of status, not a button. A danger (a
   seal missing) pulses its tile. */
.attention-button {
  --attention-tone: var(--status-success-600);
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  max-width: min(100%, 30rem);
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid color-mix(in srgb, var(--attention-tone) 45%, var(--border-subtle));
  border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--attention-tone) 9%, var(--bg-elev-1));
  color: var(--text);
  font: inherit;
  font-size: var(--text-sm);
  text-align: left;
}

.attention-button--muted { --attention-tone: var(--neutral-400); }
.attention-button--warning { --attention-tone: var(--status-warning-500); }
.attention-button--danger { --attention-tone: var(--status-danger-500); }

button.attention-button {
  cursor: pointer;
  box-shadow: var(--shadow-xs);
  transition: border-color var(--duration-base) var(--ease),
    box-shadow var(--duration-base) var(--ease),
    transform var(--duration-base) var(--ease);
}

button.attention-button:hover {
  border-color: var(--attention-tone);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

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

.attention-button > .icon {
  color: var(--text-muted);
}

.attention-button__text {
  display: grid;
  min-width: 0;
}

.attention-button__label {
  overflow: hidden;
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  white-space: nowrap;
  text-overflow: ellipsis;
}

.attention-button__hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

@media (prefers-reduced-motion: no-preference) {
  .attention-button--danger > .icon-tile {
    animation: status-pill-alarm 1.2s ease-in-out infinite;
  }
}

/* Rail tree — a hierarchy drawn as a family tree turned on its side. Every
   branch is a <details> whose <summary> is a card, and a rail runs down from
   it with an elbow into each thing directly beneath: another branch, or any
   block of leaves. It stays one column wide, so it reads the same at 375px
   as on a desktop, and a closed branch costs one row whatever is inside. */
.rail-tree {
  --rail-card-edge: 4px;
  --rail-marker: 6px;
  display: grid;
  gap: var(--space-4);
}

.rail-tree__node {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  min-height: 44px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-left: var(--rail-card-edge) solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
  box-shadow: var(--shadow-xs);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.rail-tree__branch--ok > .rail-tree__node { border-left-color: var(--status-success-600); }
.rail-tree__branch--warning > .rail-tree__node { border-left-color: var(--status-warning-500); }
.rail-tree__branch--danger > .rail-tree__node { border-left-color: var(--status-danger-500); }

/* A node with nothing beneath it: a card that opens nothing, its name
   lined up with the headings' beside their markers */
.rail-tree__node--leaf {
  padding-left: calc(var(--space-4) + var(--rail-marker) + var(--space-3));
  cursor: default;
}

.rail-tree__node--ok { border-left-color: var(--status-success-600); }
.rail-tree__node--warning { border-left-color: var(--status-warning-500); }
.rail-tree__node--danger { border-left-color: var(--status-danger-500); }

/* A node that is a row of a list (a site or an area, say): its name, the
   link, at body size, a line of state beneath it, and its figures at the
   end */
.rail-tree__node--row .rail-tree__name {
  font-size: var(--text-base);
}

.rail-tree__status {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.rail-tree__status--warning { color: var(--status-warning-700); }
.rail-tree__status--danger { font-weight: var(--font-medium); color: var(--text-danger); }

[data-theme="dark"] .rail-tree__status--warning { color: var(--status-warning-500); }

/* On a phone a node's meta takes a line of its own beneath its name */
@media (max-width: 639px) {
  .rail-tree__node > .rail-tree__meta {
    flex-basis: 100%;
    justify-content: flex-start;
  }
}

/* A node on one side only (in CAW but not in Trak, say): dimmed and flat,
   while its actions stay lit */
.rail-tree__node--dimmed,
.rail-tree__branch--dimmed > .rail-tree__node {
  border-style: dashed;
  border-left-style: solid;
  border-left-color: var(--border-strong);
  background: var(--bg-elev-2);
  box-shadow: none;
}

.rail-tree__node--dimmed .rail-tree__name,
.rail-tree__branch--dimmed > .rail-tree__node .rail-tree__name {
  color: var(--text-muted);
  font-weight: var(--font-medium);
}

/* Information, not a node: flat, no shadow */
.rail-tree__node--muted {
  min-height: 0;
  border-style: dashed;
  box-shadow: none;
  background: transparent;
}

.rail-tree__node::-webkit-details-marker {
  display: none;
}

/* A heading's open and closed marker */
.rail-tree__branch > .rail-tree__node::before {
  content: "";
  flex-shrink: 0;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 4px 0 4px var(--rail-marker);
  border-color: transparent transparent transparent var(--text-muted);
  transition: transform var(--duration-fast) var(--ease);
}

.rail-tree__branch[open] > .rail-tree__node::before {
  transform: rotate(90deg);
}

.rail-tree__node:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* The name keeps 12rem beside the meta, or the meta drops beneath it, so a
   long run of figures never squeezes the name into a column of letters */
.rail-tree__titles {
  display: grid;
  min-width: 0;
  flex: 1 1 12rem;
}

.rail-tree__name {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.rail-tree__description {
  display: -webkit-box;
  overflow: hidden;
  font-size: var(--text-sm);
  color: var(--text-muted);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

/* Once on a line of its own, the meta wraps within itself rather than run
   past the node's edge */
.rail-tree__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  min-width: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.rail-tree__children {
  --rail-indent: var(--space-3);
  --rail-gap: var(--space-4);
  --rail-elbow: var(--space-6);
  display: grid;
  gap: var(--rail-gap);
  margin-left: var(--space-2);
  padding: var(--rail-gap) 0 0 var(--rail-indent);
}

.rail-tree__children > * {
  position: relative;
}

/* The elbow into each child, reaching up through the gap above it to the
   child's left edge */
.rail-tree__children > *::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--rail-gap));
  left: calc(-1 * var(--rail-indent));
  width: var(--rail-indent);
  height: calc(var(--rail-gap) + var(--rail-elbow));
  border-left: 2px solid var(--border-strong);
  border-bottom: 2px solid var(--border-strong);
  border-bottom-left-radius: var(--radius-md);
  pointer-events: none;
}

/* The rail carries on past every child but the last, where it ends at the elbow */
.rail-tree__children > *:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: calc(-1 * var(--rail-gap));
  left: calc(-1 * var(--rail-indent));
  border-left: 2px solid var(--border-strong);
  pointer-events: none;
}

/* A leaf card places its rails from inside its border, as every absolutely
   placed box does; moved out by the border, they meet a branch's */
.rail-tree__children > .rail-tree__node::before,
.rail-tree__children > .rail-tree__node::after {
  margin: -1px 0 0 calc(-1 * var(--rail-card-edge));
}

@media (min-width: 768px) {
  .rail-tree__children {
    --rail-indent: var(--space-8);
    margin-left: var(--space-5);
  }
}

/* Beneath a branch at the deepest level the tree indents, rows stack at the
   branch's own level, each naming its path, so a deep tree keeps its
   branches without running off the page. */
.rail-tree__children.rail-tree__children--flat {
  margin-left: 0;
  padding-left: 0;
}

.rail-tree__children--flat > *::before,
.rail-tree__children--flat > *::after {
  content: none;
}

/* Rail layout and rail nav — a page that splits by something (areas of a
   site, say) keeps the choice on the page at every width. The nav is always
   a vertical tree, indented as its items nest (tree-depth-card-N on the
   item): stacked above the content when narrow, taking the height it needs,
   and a sticky rail at the end of the row from 1200px. */
.rail-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}

.rail-layout__main {
  min-width: 0;
}

.rail-nav {
  display: grid;
  gap: var(--space-3);
  min-width: 0;
  padding: var(--space-3) var(--space-4);
}

.rail-nav__header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}

.rail-nav__title {
  margin: 0;
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

.rail-nav__hint {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.rail-nav__list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail-nav__list li {
  margin: 0;
}

.rail-nav__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-1) var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  color: var(--text);
  font-size: var(--text-sm);
  text-decoration: none;
}

.rail-nav__item:hover {
  background: var(--bg-elev-2);
  text-decoration: none;
}

.rail-nav__item:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.rail-nav__item--selected {
  border-color: var(--accent-primary-500);
  background: color-mix(in srgb, var(--accent-primary-500) 12%, var(--bg-elev-1));
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

.rail-nav__name {
  min-width: 0;
  overflow-wrap: anywhere;
}

.rail-nav__meta {
  margin-left: auto;
  flex-shrink: 0;
  font-size: var(--text-xs);
  font-weight: var(--font-normal);
  color: var(--text-muted);
}

@media (min-width: 1200px) {
  .rail-layout--with-rail {
    grid-template-columns: minmax(0, 1fr) 280px;
    align-items: start;
  }

  .rail-layout--with-rail > .rail-layout__main {
    grid-column: 1;
    grid-row: 1;
  }

  .rail-layout--with-rail > .rail-nav {
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    /* Beneath the fixed top bar, with the page's gap above it */
    top: calc(var(--top-nav-height, 0px) + var(--space-4));
    grid-template-rows: auto minmax(0, 1fr);
    max-height: calc(100vh - var(--top-nav-height, 0px) - var(--space-8));
  }

  .rail-layout--with-rail .rail-nav__list {
    overflow-y: auto;
  }

  /* The rail is narrow, so the meta drops under the name */
  .rail-layout--with-rail .rail-nav__item {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: 0;
    min-height: 0;
  }

  .rail-layout--with-rail .rail-nav__meta {
    grid-column: 2;
    margin-left: 0;
  }
}

/* Rail layout, lead — the page's choice (a site's areas, say) in a column
   before its content from 1024px, sticky beneath the top bar and the page's
   sticky header and scrolling on its own when long; stacked above the
   content on narrower screens. */
.rail-layout__lead {
  min-width: 0;
}

@media (min-width: 1024px) {
  .rail-layout--lead {
    grid-template-columns: 300px minmax(0, 1fr);
    align-items: start;
    gap: var(--space-5);
  }

  .rail-layout--lead > .rail-layout__lead {
    position: sticky;
    top: calc(var(--top-nav-height, 0px) + var(--sticky-header-height, 0px) + var(--space-4));
    max-height: calc(100vh - var(--top-nav-height, 0px) - var(--sticky-header-height, 0px) - var(--space-8));
    overflow-y: auto;
    scrollbar-width: thin;
  }
}

/* List view visibility - default state */
.list-table-view {
  display: block;
}

.list-card-view {
  display: none;
}

/* Mobile: always show cards, hide table */
@media (max-width: 767px) {
  .list-table-view {
    display: none !important;
  }

  .list-card-view {
    display: grid !important;
  }
}

/* Desktop: controlled by JavaScript via body attribute */
@media (min-width: 768px) {
  body[data-list-view="table"] .list-table-view {
    display: block;
  }

  body[data-list-view="table"] .list-card-view {
    display: none;
  }

  body[data-list-view="cards"] .list-table-view {
    display: none;
  }

  body[data-list-view="cards"] .list-card-view {
    display: grid;
  }
}

/* ============================================================================
   10. ALERTS & STATUS
   ============================================================================ */

.alert {
  padding: var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid;
  display: flex;
  gap: var(--space-3);
  align-items: start;
  margin-bottom: var(--space-4);
}

.alert__icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 1px;
}

.alert__content {
  flex: 1;
  min-width: 0;
}

.alert__title {
  font-weight: var(--font-semibold);
  font-size: var(--text-sm);
  margin: 0 0 var(--space-1) 0;
}

.alert__message {
  font-size: var(--text-sm);
  margin: 0;
  line-height: var(--leading-relaxed);
}

/* Alert variants */
.alert--info {
  background: var(--status-info-100);
  border-color: var(--status-info-500);
  color: var(--status-info-700);
}

.alert--success {
  background: var(--status-success-100);
  border-color: var(--status-success-500);
  color: var(--status-success-700);
}

.alert--warning {
  background: var(--status-warning-100);
  border-color: var(--status-warning-500);
  color: var(--status-warning-700);
}

.alert--danger {
  background: var(--status-danger-100);
  border-color: var(--status-danger-500);
  color: var(--status-danger-700);
}

/* Compact variant */
.alert--compact {
  padding: var(--space-3);
}

/* Badge component */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  line-height: 1;
  white-space: nowrap;
}

.badge--primary {
  background: var(--accent-primary-500);
  color: var(--text-inverse);
}

.badge--secondary {
  background: var(--neutral-200);
  color: var(--neutral-700);
}

.badge--success {
  background: var(--status-success-100);
  color: var(--status-success-700);
}

.badge--warning {
  background: var(--status-warning-100);
  color: var(--status-warning-700);
}

.badge--danger {
  background: var(--status-danger-100);
  color: var(--status-danger-700);
}

.badge--info {
  background: var(--status-info-100);
  color: var(--status-info-700);
}

.badge--cyberkey {
  background: #fef3d6;
  color: #7c5a04;
}

.badge--cliq {
  background: var(--accent-primary-500);
  color: var(--text-inverse);
}

.badge--caw {
  background: var(--vendor-caw-bg);
  color: var(--vendor-caw-text);
  border-color: var(--vendor-caw-border);
}

.badge--cwm {
  background: var(--vendor-cwm-bg);
  color: var(--vendor-cwm-text);
  border-color: var(--vendor-cwm-border);
}

.badge--iloq {
  background: var(--vendor-iloq-bg);
  color: var(--vendor-iloq-text);
  border-color: var(--vendor-iloq-border);
}

/* Tree node — nested tree view for workflow definitions and execution logs */
.tree-node {
  margin-bottom: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-elev-1);
  border-left: 3px solid var(--border);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.tree-node--danger {
  border-left-color: var(--status-danger-500);
}

.tree-node__header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
}

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

.tree-node__title {
  font-weight: 500;
}

.tree-node__type {
  font-size: var(--font-xs);
  color: var(--text-muted);
}

.tree-node__detail {
  font-size: var(--font-xs);
  color: var(--text-muted);
  margin-top: var(--space-1);
}

.tree-node__info {
  font-size: var(--font-sm);
  color: var(--text-muted);
  margin-bottom: var(--space-1);
}

.tree-node__info--error {
  color: var(--status-danger-600);
  font-weight: 500;
}

.tree-node__timestamp {
  font-size: var(--font-xs);
  color: var(--text-muted);
}

/* Table tree — indented rows for tree views in tables */
.table tr.tr--danger {
  background: var(--status-danger-50);
}

.table .td--nowrap {
  white-space: nowrap;
}

.table .tree-cell {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

/* Tree depth — table row indentation (padding-left) */
.tree-depth-table-0 {
  padding-left: 0;
}

.tree-depth-table-1 {
  padding-left: var(--space-5);
}

.tree-depth-table-2 {
  padding-left: var(--space-10);
}

.tree-depth-table-3 {
  padding-left: calc(var(--space-5) * 3);
}

.tree-depth-table-4 {
  padding-left: calc(var(--space-5) * 4);
}

.tree-depth-table-5 {
  padding-left: calc(var(--space-5) * 5);
}

.tree-depth-table-6 {
  padding-left: calc(var(--space-5) * 6);
}

.tree-depth-table-7 {
  padding-left: calc(var(--space-5) * 7);
}

.tree-depth-table-8 {
  padding-left: calc(var(--space-5) * 8);
}

/* Tree depth — card view indentation (margin-left) */
.tree-depth-card-0 {
  margin-left: 0;
}

.tree-depth-card-1 {
  margin-left: var(--space-3);
}

.tree-depth-card-2 {
  margin-left: var(--space-6);
}

.tree-depth-card-3 {
  margin-left: calc(var(--space-3) * 3);
}

.tree-depth-card-4 {
  margin-left: calc(var(--space-3) * 4);
}

.tree-depth-card-5 {
  margin-left: calc(var(--space-3) * 5);
}

.tree-depth-card-6 {
  margin-left: calc(var(--space-3) * 6);
}

.tree-depth-card-7 {
  margin-left: calc(var(--space-3) * 7);
}

.tree-depth-card-8 {
  margin-left: calc(var(--space-3) * 8);
}

/* A row drawn shallower than it is: the ancestors it isn't drawn beneath,
   before its name. Trees indent eight levels at most and keep their
   structure beneath that, so a deeper row names where it sits. */
.tree-path {
  display: inline-block;
  max-width: 100%;
  vertical-align: bottom;
  flex-shrink: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* ============================================================================
   PROGRESS — a bar for work that takes a while: an upload, or a CAW Sync
   job. Markup: `.progress` with `role="progressbar"` and
   `aria-valuenow`, holding `.progress__bar` (its width set inline or by
   script); an optional `.progress__label` beneath says what is happening.
   ============================================================================ */

.progress {
  width: 100%;
  height: 6px;
  background-color: var(--bg-elev-2);
  border-radius: 3px;
  overflow: hidden;
}

.progress__bar {
  height: 100%;
  width: 0;
  background-color: var(--accent-primary-500);
  transition: width 0.2s ease;
  border-radius: 3px;
}

.progress__label {
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.progress--danger .progress__bar {
  background-color: var(--status-danger-500);
}

/* ============================================================================
   TREE TOGGLE — collapsible branches for a depth-first list of rows. Each
   row carries `data-depth` (its real depth, which gives the tree its
   structure at any depth), `data-tree-indent` (the level it is drawn at, 0
   to 8: deeper rows are drawn at 8 with their ancestors in a `.tree-path`)
   and `data-tree-name`. Without JS its indenting element
   (`[data-tree-slot]`, or the row) indents with `tree-depth-card-N` and
   every row shows. `tree-toggle.js` enhances a
   `[data-tree-toggle]` container, or one a script passes to
   `TrakTreeToggle.enhance`: the depth class gives way to in-row indent
   guides and a chevron toggle per branch, rows with `data-tree-closed`
   start collapsed, and a `[data-tree-filter]` input filters by name.
   Each level's guide is `--tree-guide-width` wide, narrower on a phone so
   deep rows keep room for their names.
   ============================================================================ */

:root {
  --tree-guide-width: var(--space-3);
}

@media (max-width: 640px) {
  :root {
    --tree-guide-width: var(--space-2);
  }
}

.tree-toggle__guides {
  --tree-guide-overhang: calc(1.5 * var(--space-1));
  display: flex;
  align-self: stretch;
  flex-shrink: 0;
}

.tree-toggle__guide {
  width: var(--tree-guide-width);
  position: relative;
}

/* Each guide draws a vertical line through the row, extended over the
   row's padding so branch lines read as continuous. */
.tree-toggle__guide::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--tree-guide-overhang));
  bottom: calc(-1 * var(--tree-guide-overhang));
  left: calc(var(--tree-guide-width) / 2);
  width: 1px;
  background: var(--border);
}

.tree-toggle__button {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  flex-shrink: 0;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-sm);
}

/* A larger hit area than the chevron, reaching into the row's padding. */
.tree-toggle__button::before {
  content: "";
  position: absolute;
  inset: -6px -4px -6px -8px;
}

.tree-toggle__button--leaf::before {
  content: none;
}

.tree-toggle__button:hover {
  color: var(--text);
}

.tree-toggle__button:focus-visible {
  outline: 2px solid var(--accent-primary-500);
  outline-offset: -2px;
}

.tree-toggle__button--leaf {
  cursor: default;
}

.tree-toggle__chevron {
  transition: transform var(--duration-fast) var(--ease);
}

.tree-toggle__button[aria-expanded="true"] .tree-toggle__chevron {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  .tree-toggle__chevron {
    transition: none;
  }
}

/* ============================================================================
   TREE ROWS — a slim tree in a card or modal: one row per node, its state
   dot, then its name with its counts on the line beneath (a link, when
   choosing it does something). The counts wrap rather than squeeze the
   name. Each row is a tree-toggle.js slot, so the indent guides and
   chevrons are the ones used everywhere else; without the script rows
   indent with tree-depth-card-N.
   ============================================================================ */

.tree-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}

.tree-rows > li {
  margin: 0;
}

.tree-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 36px;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--text);
}

.tree-row:has(.tree-row__link):hover {
  background: var(--bg-elev-2);
}

.tree-row--selected,
.tree-row--selected:has(.tree-row__link):hover {
  background: color-mix(in srgb, var(--accent-primary-500) 12%, var(--bg-elev-1));
}

.tree-row__link,
.tree-row__body {
  flex: 1;
  min-width: 0;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  justify-content: center;
  color: inherit;
  text-decoration: none;
}

.tree-row__link:hover {
  color: var(--text-strong);
  text-decoration: none;
}

.tree-row__link:focus-visible {
  outline: none;
  border-radius: var(--radius-sm);
  box-shadow: var(--focus-ring);
}

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

.tree-row--selected .tree-row__name {
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

.tree-row__meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   PAIR TREE — two trees side by side, row by row: each row pairs a node on
   the left with one on the right (either may be missing), with a choice.
   The rows share one set of columns (subgrid), and only the left side
   indents: it is the rows' tree toggle slot (see TREE TOGGLE).
   ============================================================================ */

.pair-tree {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 1.5rem minmax(0, 1fr) minmax(12rem, auto);
  column-gap: var(--space-2);
}

.pair-tree__row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  padding: var(--space-2) 0;
  border-top: 1px solid var(--border-subtle);
}

.pair-tree__row .tree-toggle__guides {
  --tree-guide-overhang: var(--space-2);
}

.pair-tree__row--header {
  border-top: none;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text-muted);
}

.pair-tree__side {
  min-width: 0;
  overflow-wrap: anywhere;
}

.pair-tree__side--left {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.pair-tree__link {
  text-align: center;
  color: var(--text-muted);
}

.pair-tree__choice {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  justify-content: flex-end;
}

.pair-tree__meta {
  white-space: nowrap;
}

/* The fixed pair the tree hangs from: not a choice, set apart from the rows. */
.pair-tree__row--root {
  font-weight: var(--font-semibold);
  border-bottom: 2px solid var(--border-subtle);
}

/* A row's note (a compact alert), on its own line across every column. */
.pair-tree__note {
  grid-column: 1 / -1;
  margin: var(--space-2) 0 0;
}

/* The message when there are no rows, across every column. */
.pair-tree__empty {
  grid-column: 1 / -1;
  margin: var(--space-2) 0 0;
}

.pair-tree__row--suggested .pair-tree__link {
  color: var(--accent-primary-500);
  font-weight: var(--font-semibold);
}

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

@media (max-width: 640px) {
  .pair-tree {
    grid-template-columns: minmax(0, 1fr) 1.5rem minmax(0, 1fr);
  }

  .pair-tree__choice {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }
}

/* ============================================================================
   OUTCOME TREE — one tree as a plain indented list, for the tree toggle:
   each row's slot holds its dot, name and badges.
   ============================================================================ */

.outcome-tree__row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) 0;
  border-top: 1px solid var(--border-subtle);
}

.outcome-tree__row [data-tree-slot] {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  overflow-wrap: anywhere;
}

/* A row's choice, at its end; a note beneath it, on a line of its own */
.outcome-tree__row {
  flex-wrap: wrap;
}

.outcome-tree__choice {
  flex-shrink: 0;
  margin-left: auto;
}

.outcome-tree__note {
  flex-basis: 100%;
}

/* ============================================================================
   ICON — a single-colour glyph drawn as a mask, so it takes the colour of
   its text and follows the theme. Each glyph is an SVG in /static/icons
   whose opaque parts are the drawing. Name the thing, never the look:
   `.icon--padlock`, not `.icon--grey-padlock`.
   ============================================================================ */

.icon {
  --icon: none;
  display: inline-block;
  width: 1.25rem;
  height: 1.25rem;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
  vertical-align: middle;
}

.icon--xs { width: 0.875rem; height: 0.875rem; }
.icon--sm { width: 1rem; height: 1rem; }
.icon--lg { width: 1.5rem; height: 1.5rem; }
.icon--xl { width: 2.25rem; height: 2.25rem; }

/* Hardware, from the product artwork */
.icon--seal { --icon: url("/static/icons/seal.svg"); }
.icon--cyberlock { --icon: url("/static/icons/cyberlock.svg"); }
/* CyberLock the system, beside its locks: the face in its ring */
.icon--cyberlock-system { --icon: url("/static/icons/cyberlock-system.svg"); }
.icon--padlock { --icon: url("/static/icons/padlock.svg"); }
.icon--cylinder { --icon: url("/static/icons/cylinder.svg"); }
.icon--key-rechargeable { --icon: url("/static/icons/key-rechargeable.svg"); }
.icon--key-replaceable { --icon: url("/static/icons/key-replaceable.svg"); }
.icon--cliq-key { --icon: url("/static/icons/cliq-key.svg"); }
.icon--validikey-2 { --icon: url("/static/icons/validikey-2.svg"); }
.icon--validikey-20 { --icon: url("/static/icons/validikey-20.svg"); }
.icon--web-authoriser { --icon: url("/static/icons/web-authoriser.svg"); }

/* Line glyphs, and hardware the artwork doesn't draw yet */
.icon--lock { --icon: url("/static/icons/lock.svg"); }
.icon--key { --icon: url("/static/icons/key.svg"); }
.icon--mission { --icon: url("/static/icons/mission.svg"); }
.icon--flex-hub { --icon: url("/static/icons/flex-hub.svg"); }
.icon--web-station { --icon: url("/static/icons/web-station.svg"); }
.icon--vault { --icon: url("/static/icons/vault.svg"); }
.icon--person { --icon: url("/static/icons/person.svg"); }
.icon--people { --icon: url("/static/icons/people.svg"); }
.icon--clock { --icon: url("/static/icons/clock.svg"); }
.icon--map-pin { --icon: url("/static/icons/map-pin.svg"); }
.icon--shield { --icon: url("/static/icons/shield.svg"); }
.icon--areas { --icon: url("/static/icons/areas.svg"); }
.icon--gateway { --icon: url("/static/icons/gateway.svg"); }
.icon--access { --icon: url("/static/icons/access.svg"); }
.icon--now { --icon: url("/static/icons/now.svg"); }
.icon--alert { --icon: url("/static/icons/alert.svg"); }
.icon--chevron { --icon: url("/static/icons/chevron.svg"); }
.icon--close { --icon: url("/static/icons/close.svg"); }
.icon--arrow-right { --icon: url("/static/icons/arrow-right.svg"); }
.icon--eye { --icon: url("/static/icons/eye.svg"); }
.icon--node { --icon: url("/static/icons/node.svg"); }
.icon--rows { --icon: url("/static/icons/rows.svg"); }
.icon--cards { --icon: url("/static/icons/cards.svg"); }

/* ============================================================================
   ICON TILE — an icon on a soft square: grey by default, the brand's tint
   (`--primary`) or a state's (`--ok`, `--warning`, `--danger`). `--sm` (with
   an `icon--sm`) beside a line of text, in place of a state dot; `--lg` for
   a piece of hardware's drawing.
   ============================================================================ */

.icon-tile {
  --icon-tile-size: 32px;
  --icon-tile-tone: var(--text-muted);
  display: inline-grid;
  place-items: center;
  width: var(--icon-tile-size);
  height: var(--icon-tile-size);
  flex-shrink: 0;
  border-radius: var(--radius-md);
  background: var(--bg-elev-2);
  color: var(--icon-tile-tone);
}

.icon-tile--sm {
  --icon-tile-size: 24px;
  border-radius: var(--radius-sm);
}

.icon-tile--lg {
  --icon-tile-size: 64px;
}

.icon-tile--primary,
.icon-tile--ok,
.icon-tile--warning,
.icon-tile--danger {
  background: color-mix(in srgb, var(--icon-tile-tone) 14%, transparent);
}

.icon-tile--primary { --icon-tile-tone: var(--accent-primary-500); }
.icon-tile--ok { --icon-tile-tone: var(--status-success-600); }
.icon-tile--warning { --icon-tile-tone: var(--status-warning-500); }
.icon-tile--danger { --icon-tile-tone: var(--status-danger-500); }


/* ============================================================================
   STATE DOT & STATUS PILL — compact state indicators. Colour never stands
   alone: a dot sits beside a name or label, a pill always carries text.
   ============================================================================ */

.state-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--neutral-400);
}

.state-dot--ok { background: var(--status-success-600); }
.state-dot--info { background: var(--status-info-500); }
.state-dot--warning { background: var(--status-warning-500); }
.state-dot--danger { background: var(--status-danger-500); }
.state-dot--muted { background: var(--neutral-400); }
.state-dot--accent { background: var(--accent-primary-500); }

/* A key of dots: each item a dot, its label and how many carry it. */
.dot-key {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  font-size: var(--text-sm);
}

.dot-key__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* The base list item margin, on every item but the last, would drop the
     last item below the rest of the row. */
  margin: 0;
}

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

/* States, one a line: each a dot and what it says ("1 key lost") */
.state-list {
  display: grid;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  color: var(--text);
}

.state-list__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

/* A fact beside the state: its icon in place of a dot, receding */
.state-list__item > .icon {
  color: var(--text-subtle);
}

.status-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 2px var(--space-3);
  border-radius: 999px;
  border: 1px solid var(--border-subtle);
  background: var(--bg-elev-1);
  color: var(--text);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  white-space: nowrap;
}

.status-pill__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--neutral-400);
}

.status-pill--ok .status-pill__dot { background: var(--status-success-600); }
.status-pill--info .status-pill__dot { background: var(--status-info-500); }
.status-pill--warning .status-pill__dot { background: var(--status-warning-500); }
.status-pill--danger .status-pill__dot { background: var(--status-danger-500); }

.status-pill--danger {
  border-color: var(--status-danger-500);
}

.status-pill--lg {
  padding: var(--space-1) var(--space-4);
  font-size: var(--text-base);
}

/* A healthy pill breathes; a danger pill pulses faster. Both are decoration
   on top of the label, so reduced motion simply drops them. */
@media (prefers-reduced-motion: no-preference) {
  .status-pill--ok .status-pill__dot {
    animation: status-pill-breathe 2.4s ease-in-out infinite;
  }

  .status-pill--danger .status-pill__dot {
    animation: status-pill-alarm 1.2s ease-in-out infinite;
  }
}

@keyframes status-pill-breathe {
  0%, 100% { box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.35); }
  50% { box-shadow: 0 0 0 4px rgba(22, 163, 74, 0); }
}

@keyframes status-pill-alarm {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.45); }
  50% { box-shadow: 0 0 0 5px rgba(239, 68, 68, 0); }
}

/* ============================================================================
   STATUS RING - Pure-CSS ring of a whole's shares by tone: danger, warning,
   info and ok, each a percentage; the remainder is neutral. Pair it with a
   legend or figures. The site dashboards' seal ring is one use of it.
   ============================================================================ */


/* Registered so the ring's segments animate when the counts change */
@property --ring-ok {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@property --ring-info {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@property --ring-warning {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

@property --ring-danger {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

.status-ring {
  --ring-size: 76px;
  --ring-width: 9px;
  position: relative;
  display: grid;
  place-items: center;
  align-content: center;
  flex-shrink: 0;
  width: var(--ring-size);
  height: var(--ring-size);
  transition: --ring-ok 600ms var(--ease), --ring-info 600ms var(--ease),
    --ring-warning 600ms var(--ease), --ring-danger 600ms var(--ease);
}

/* Danger leads from twelve o'clock, then warning, so that a sliver of red
   or amber is never lost at the tail of the ring */
.status-ring::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    var(--status-danger-500) 0 calc(var(--ring-danger) * 1%),
    var(--status-warning-500) 0 calc((var(--ring-danger) + var(--ring-warning)) * 1%),
    var(--status-info-500) 0 calc((var(--ring-danger) + var(--ring-warning) + var(--ring-info)) * 1%),
    var(--status-success-600) 0 calc((var(--ring-danger) + var(--ring-warning) + var(--ring-info) + var(--ring-ok)) * 1%),
    var(--chart-muted) 0
  );
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - var(--ring-width)), #000 calc(100% - var(--ring-width) + 1px));
  mask: radial-gradient(farthest-side, transparent calc(100% - var(--ring-width)), #000 calc(100% - var(--ring-width) + 1px));
}

.status-ring__value {
  position: relative;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
}

.status-ring__label {
  position: relative;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.status-ring--md {
  --ring-size: 116px;
  --ring-width: 13px;
}

.status-ring--md .status-ring__value {
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  line-height: 1;
}

.status-ring--lg {
  --ring-size: 168px;
  --ring-width: 18px;
}

.status-ring--lg .status-ring__value {
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  line-height: 1;
}

/* --- Ring summary: a status ring beside its legend ----------------------- */

/* One legend line per state: its dot, its name and its count, so the
   numbers sit beside the shape the ring gives them. A line without a dot
   (.ring-summary__extra) is a figure beside the shares, not one of them. */
.ring-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-4) var(--space-6);
}

.ring-summary__legend {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.ring-summary__legend li {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-2);
  min-width: 150px;
  margin: 0;
}

.ring-summary__legend strong {
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
}

.ring-summary__legend .ring-summary__extra {
  grid-template-columns: 1fr auto;
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-subtle);
}

.ring-summary__extra + .ring-summary__extra {
  padding-top: 0;
  border-top: 0;
}

/* ============================================================================
   SEGMENT BAR — a whole's shares by tone, as a line: the flat partner of
   the status ring, for a tile or a row with no room for a ring. Each
   part's share is its flex-grow, set inline; a part of nought is left out.
   Colour never stands alone: pair it with a legend or a note.
   ============================================================================ */

.segment-bar {
  display: flex;
  gap: 2px;
  height: 6px;
  margin: 0;
  overflow: hidden;
  border-radius: 3px;
  background: var(--bg-elev-3);
}

.segment-bar--lg {
  height: 10px;
  border-radius: 5px;
}

.segment-bar__part {
  flex: 1 1 0;
  min-width: 3px;
  background: var(--chart-muted);
  transition: flex-grow 600ms var(--ease);
}

.segment-bar__part--ok { background: var(--status-success-600); }
.segment-bar__part--info { background: var(--status-info-500); }
.segment-bar__part--warning { background: var(--status-warning-500); }
.segment-bar__part--danger { background: var(--status-danger-500); }
.segment-bar__part--accent { background: var(--accent-primary-500); }
.segment-bar__part--muted { background: var(--chart-muted); }

/* ============================================================================
   HISTOGRAM — counts over time as bars, each stacked by tone (authorised
   beneath, unauthorised on top, say). A bar's height is its share of the
   tallest, and its parts share it by flex-grow, both set inline; a part of
   nought is left out. `--sm` is a sparkline's worth, for a tile.
   ============================================================================ */

.histogram {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  align-items: end;
  gap: 3px;
  height: 88px;
  margin: 0;
  padding: 0 0 var(--space-1);
  border-bottom: 1px solid var(--border-subtle);
  list-style: none;
}

.histogram--sm {
  gap: 2px;
  height: 28px;
  padding: 0;
  border-bottom: 0;
}

.histogram > li {
  display: flex;
  flex-direction: column-reverse;
  gap: 1px;
  min-height: 2px;
  margin: 0;
  overflow: hidden;
  border-radius: 2px 2px 0 0;
  background: var(--bg-elev-3);
}

.histogram__part {
  flex: 1 1 0;
  min-height: 2px;
  background: var(--status-success-600);
}

.histogram__part--warning { background: var(--status-warning-500); }
.histogram__part--danger { background: var(--status-danger-500); }
.histogram__part--muted { background: var(--chart-muted); }

.histogram__axis {
  display: flex;
  justify-content: space-between;
  margin: var(--space-1) 0 0;
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   DETAIL PANEL — slide-in panel for inspecting one item without leaving the
   page. Right-hand panel on desktop, bottom sheet on mobile. Opened and
   closed by detail-panel.js; unrelated to the sidebar drawer in
   navigation.css.
   ============================================================================ */

.detail-panel {
  position: fixed;
  inset: 0;
  z-index: var(--z-detail-panel);
  visibility: hidden;
  pointer-events: none;
  /* Stay painted until the slide-out has finished */
  transition: visibility 0s linear var(--duration-slow);
}

.detail-panel--open {
  visibility: visible;
  pointer-events: auto;
  transition: none;
}

.detail-panel__scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  opacity: 0;
  transition: opacity var(--duration-slow) var(--ease);
}

.detail-panel--open .detail-panel__scrim {
  opacity: 1;
}

.detail-panel__surface {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-elev-1);
  border-top: 1px solid var(--border);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  box-shadow: var(--shadow-lg);
  transform: translateY(100%);
  transition: transform var(--duration-slow) var(--ease);
}

.detail-panel--open .detail-panel__surface {
  transform: none;
}

/* Focus is parked on the surface when the panel opens; the panel itself is
   the indicator */
.detail-panel__surface:focus {
  outline: none;
}

.detail-panel__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.detail-panel__title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  overflow-wrap: anywhere;
}

.detail-panel__subtitle {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.detail-panel__heading {
  flex: 1;
  min-width: 0;
}

.detail-panel__back,
.detail-panel__close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: calc(-1 * var(--space-2));
  border: 0;
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--text-muted);
  font-size: var(--text-2xl);
  line-height: 1;
  cursor: pointer;
}

.detail-panel__back {
  margin-right: 0;
  font-size: var(--text-xl);
}

.detail-panel__back:hover,
.detail-panel__close:hover {
  background: var(--bg-elev-2);
  color: var(--text);
}

.detail-panel__back:focus-visible,
.detail-panel__close:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.detail-panel__body {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4);
  overscroll-behavior: contain;
}

.detail-panel__section + .detail-panel__section {
  margin-top: var(--space-5);
}

.detail-panel__section-title {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

/* A numbered or bulleted list of longer items in the panel body; a list
   of things with states or that open is .item-rows */
.detail-panel__list {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding-left: var(--space-5);
}

/* The list's gap spaces its items, so the base margin would add to it */
.detail-panel__list > li {
  margin: 0;
}

.detail-panel__footer {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border);
}

body.detail-panel-open {
  overflow: hidden;
}

@media (min-width: 768px) {
  .detail-panel__surface {
    top: 0;
    left: auto;
    width: 420px;
    max-width: 100%;
    max-height: none;
    border-top: 0;
    border-left: 1px solid var(--border);
    border-radius: 0;
    transform: translateX(100%);
  }
}

/* A wider panel on desktop, for content that needs the room (a tree, say).
   The mobile bottom sheet is unchanged. */
@media (min-width: 768px) {
  .detail-panel--wide .detail-panel__surface {
    width: 640px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .detail-panel,
  .detail-panel__scrim,
  .detail-panel__surface {
    transition: none;
  }
}

/* ============================================================================
   11. UTILITY CLASSES
   ============================================================================ */

/* Display */
.block {
  display: block;
}

.inline-block {
  display: inline-block;
}

.inline {
  display: inline;
}

.flex {
  display: flex;
}

.inline-flex {
  display: inline-flex;
}

.grid {
  display: grid;
}

.hidden {
  display: none;
}

/* Present to assistive technology, absent from the page */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Flexbox */
.flex-row {
  flex-direction: row;
}

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

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

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

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

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

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

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

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

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

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

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

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

.flex-1 {
  flex: 1;
}

.flex-auto {
  flex: auto;
}

.flex-none {
  flex: none;
}

/* Gap */
.gap-1 {
  gap: var(--space-1);
}

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

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

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

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

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

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

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

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

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

.m-1 {
  margin: var(--space-1);
}

.m-2 {
  margin: var(--space-2);
}

.m-3 {
  margin: var(--space-3);
}

.m-4 {
  margin: var(--space-4);
}

.m-6 {
  margin: var(--space-6);
}

.m-8 {
  margin: var(--space-8);
}

.mt-0 {
  margin-top: 0;
}

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

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

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

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

.mt-6 {
  margin-top: var(--space-6);
}

.mt-8 {
  margin-top: var(--space-8);
}

.mt-12 {
  margin-top: var(--space-12);
}

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

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

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

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

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

.mb-6 {
  margin-bottom: var(--space-6);
}

.mb-8 {
  margin-bottom: var(--space-8);
}

.mb-12 {
  margin-bottom: var(--space-12);
}

.ml-0 {
  margin-left: 0;
}

.ml-1 {
  margin-left: var(--space-1);
}

.ml-2 {
  margin-left: var(--space-2);
}

.ml-3 {
  margin-left: var(--space-3);
}

.ml-4 {
  margin-left: var(--space-4);
}

.ml-auto {
  margin-left: auto;
}

.mr-0 {
  margin-right: 0;
}

.mr-1 {
  margin-right: var(--space-1);
}

.mr-2 {
  margin-right: var(--space-2);
}

.mr-3 {
  margin-right: var(--space-3);
}

.mr-4 {
  margin-right: var(--space-4);
}

.mr-auto {
  margin-right: auto;
}

.mx-auto {
  margin-left: auto;
  margin-right: auto;
}

/* Spacing - Padding */
.p-0 {
  padding: 0;
}

.p-1 {
  padding: var(--space-1);
}

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

.p-3 {
  padding: var(--space-3);
}

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

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

.p-8 {
  padding: var(--space-8);
}

.pt-0 {
  padding-top: 0;
}

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

.pt-4 {
  padding-top: var(--space-4);
}

.pt-6 {
  padding-top: var(--space-6);
}

.pt-8 {
  padding-top: var(--space-8);
}

.pb-0 {
  padding-bottom: 0;
}

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

.pb-4 {
  padding-bottom: var(--space-4);
}

.pb-6 {
  padding-bottom: var(--space-6);
}

.pb-8 {
  padding-bottom: var(--space-8);
}

.px-2 {
  padding-left: var(--space-2);
  padding-right: var(--space-2);
}

.px-3 {
  padding-left: var(--space-3);
  padding-right: var(--space-3);
}

.px-4 {
  padding-left: var(--space-4);
  padding-right: var(--space-4);
}

.px-6 {
  padding-left: var(--space-6);
  padding-right: var(--space-6);
}

.py-2 {
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}

.py-3 {
  padding-top: var(--space-3);
  padding-bottom: var(--space-3);
}

.py-4 {
  padding-top: var(--space-4);
  padding-bottom: var(--space-4);
}

.py-6 {
  padding-top: var(--space-6);
  padding-bottom: var(--space-6);
}

/* Width & Height */
.w-full {
  width: 100%;
}

.w-auto {
  width: auto;
}

.h-full {
  height: 100%;
}

.h-auto {
  height: auto;
}

/* Border */
.border {
  border: 1px solid var(--border);
}

.border-t {
  border-top: 1px solid var(--border);
}

.border-b {
  border-bottom: 1px solid var(--border);
}

.border-l {
  border-left: 1px solid var(--border);
}

.border-r {
  border-right: 1px solid var(--border);
}

.rounded {
  border-radius: var(--radius-md);
}

.rounded-sm {
  border-radius: var(--radius-sm);
}

.rounded-lg {
  border-radius: var(--radius-lg);
}

.rounded-xl {
  border-radius: var(--radius-xl);
}

.bg-elev-1 {
  background: var(--bg-elev-1);
}

.bg-elev-2 {
  background: var(--bg-elev-2);
}

.bg-elev-3 {
  background: var(--bg-elev-3);
}

/* Shadow */
.shadow-xs {
  box-shadow: var(--shadow-xs);
}

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

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

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

.shadow-none {
  box-shadow: none;
}

/* Opacity */
.opacity-0 {
  opacity: 0;
}

.opacity-50 {
  opacity: 0.5;
}

.opacity-75 {
  opacity: 0.75;
}

.opacity-100 {
  opacity: 1;
}

/* Cursor */
.cursor-pointer {
  cursor: pointer;
}

.cursor-not-allowed {
  cursor: not-allowed;
}

.cursor-default {
  cursor: default;
}

/* Overflow */
.overflow-auto {
  overflow: auto;
}

.overflow-hidden {
  overflow: hidden;
}

.overflow-scroll {
  overflow: scroll;
}

.overflow-x-auto {
  overflow-x: auto;
}

.overflow-y-auto {
  overflow-y: auto;
}

/* Position */
.relative {
  position: relative;
}

.absolute {
  position: absolute;
}

.fixed {
  position: fixed;
}

.sticky {
  position: sticky;
}

/* ============================================================================
   SYSTEM CODE INPUT & ANIMATION
   ============================================================================ */

/* Code input container (input + regenerate button) */
.code-input-container {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  max-width: 240px;
}

/* Special input styling for code field */
.input--code {
  text-align: center;
  font-size: 20px;
  font-weight: 600;
  text-transform: uppercase;
  font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace;
  letter-spacing: 0.25em;
  flex: 1;
  min-width: 0;
}

/* Disabled state during animation */
.input--code:disabled {
  opacity: 0.7;
  cursor: wait;
}

/* Icon button (for regenerate) */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elev-1);
  color: var(--text);
  font-size: 18px;
  cursor: pointer;
  transition: all 0.15s ease;
  flex-shrink: 0;
}

.btn-icon:hover:not(:disabled) {
  background: var(--bg-elev-2);
  border-color: var(--border-strong);
}

.btn-icon:active:not(:disabled) {
  transform: scale(0.95);
}

.btn-icon:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ============================================================================
   12. RESPONSIVE
   ============================================================================ */

@media (max-width: 1200px) {
  .container {
    max-width: 100%;
  }
}

@media (max-width: 768px) {

  /* Adjust spacing for mobile */
  .container {
    padding: 0 var(--space-4);
  }

  .section {
    padding: var(--space-8) 0;
  }

  /* Stack form grids on mobile */
  .form-grid,
  .form-grid--3,
  .form-grid--4 {
    grid-template-columns: 1fr;
  }

  /* Adjust card padding */
  .card {
    padding: var(--space-4);
  }

  /* Header adjustments */
  .header__inner {
    padding: var(--space-3) var(--space-4);
  }

  .header__nav {
    gap: var(--space-3);
  }

  /* Responsive typography */
  h1 {
    font-size: var(--text-3xl);
  }

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

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

  /* Table horizontal scroll */
  .table-wrapper {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Responsive utilities */
  .hide-mobile {
    display: none !important;
  }
}

@media (min-width: 769px) {
  .hide-desktop {
    display: none !important;
  }
}

/* ============================================================================
   ACTIVITY PANEL
   ============================================================================ */

.activity-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.activity-panel__header {
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.activity-panel__title {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
}

.activity-panel__tabs {
  display: flex;
  gap: var(--space-1);
}

.activity-panel__tab {
  padding: var(--space-2) var(--space-4);
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-muted);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.activity-panel__tab:hover {
  background: var(--bg-elev-2);
  color: var(--text);
}

.activity-panel__tab--active {
  background: var(--primary);
  color: var(--white);
}

.activity-panel__tab--active:hover {
  background: var(--primary-dark);
  color: var(--white);
}

.activity-panel__content {
  flex: 1;
  min-height: 0;
  /* Required for flex overflow to work */
  overflow-y: auto;
  padding: var(--space-4);
}

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

.activity-panel__empty {
  text-align: center;
  padding: var(--space-8) var(--space-4);
}

.activity-panel__load-more {
  width: 100%;
  margin-bottom: var(--space-4);
}

/* Activity items */
.activity-item {
  padding: var(--space-3);
  background: var(--bg-page);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}

.activity-item--field_change,
.activity-item--created,
.activity-item--deleted {
  background: transparent;
  border: none;
  padding: var(--space-2) 0;
  border-left: 2px solid var(--border);
  padding-left: var(--space-3);
  margin-left: var(--space-2);
}

.activity-item__header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
}

.activity-item__author {
  font-weight: var(--font-medium);
  color: var(--text-strong);
}

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

.activity-item__time {
  color: var(--text-subtle);
  font-size: var(--text-xs);
  margin-left: auto;
}

.activity-item__edited {
  font-style: italic;
}

.activity-item__content {
  font-size: var(--text-base);
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.activity-item__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-subtle);
}

.activity-item__like {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-2);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  cursor: pointer;
  font-size: var(--text-xs);
  transition: all var(--duration-fast);
}

.activity-item__like:hover {
  background: var(--bg-elev-2);
  color: var(--status-danger-600);
}

.activity-item__like--liked {
  color: var(--status-danger-600);
}

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

.activity-item__action {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: var(--text-xs);
  cursor: pointer;
  padding: var(--space-1);
}

.activity-item__action:hover {
  color: var(--text);
  text-decoration: underline;
}

.activity-item__action--danger:hover {
  color: var(--status-danger-600);
}

/* Field changes */
.activity-item__changes {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  font-size: var(--text-sm);
}

.activity-item__change {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}

.activity-item__change-field {
  font-weight: var(--font-medium);
  color: var(--text);
  min-width: 80px;
}

.activity-item__change-old {
  color: var(--text-muted);
  text-decoration: line-through;
}

.activity-item__change-arrow {
  color: var(--text-subtle);
}

.activity-item__change-new {
  color: var(--text);
}

/* Comment form */
.activity-panel__form {
  padding: var(--space-4);
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}

.activity-comment-form__input {
  width: 100%;
  padding: var(--space-3);
  background: var(--field-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-sm);
  resize: vertical;
  min-height: 60px;
}

.activity-comment-form__input::placeholder {
  color: var(--text-muted);
}

.activity-comment-form__input:focus {
  outline: none;
  border-color: var(--accent-primary-500);
  box-shadow: 0 0 0 3px rgba(0, 156, 182, 0.1);
}

.activity-comment-form__actions {
  display: flex;
  justify-content: flex-end;
  margin-top: var(--space-2);
}

/* Mention autocomplete */
.activity-panel__form {
  position: relative;
}

.mention-autocomplete {
  position: absolute;
  bottom: 100%;
  left: 0;
  width: max-content;
  min-width: 200px;
  max-width: 280px;
  max-height: 200px;
  overflow-y: auto;
  background: var(--bg-elev-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
  margin-bottom: var(--space-2);
  z-index: 100;
  display: none;
}

.mention-autocomplete--visible {
  display: block;
}

.mention-autocomplete__item {
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.mention-autocomplete__item:hover,
.mention-autocomplete__item--selected {
  background: var(--bg-secondary);
}

.mention-autocomplete__name {
  font-weight: 500;
}

.mention-autocomplete__hint {
  color: var(--text-muted);
  font-size: var(--text-xs);
}

.mention-autocomplete__empty {
  padding: var(--space-2) var(--space-3);
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* ============================================================================
   External panel styles (customer conversation)
   ============================================================================ */

/* External panel background tint for visual differentiation */
.activity-panel--external {
  background: linear-gradient(135deg, rgba(0, 156, 182, 0.03) 0%, rgba(0, 156, 182, 0.06) 100%), var(--bg-elev-1);
}

.activity-panel__content--external {
  background: rgba(0, 156, 182, 0.02);
}

/* External tab button styling */
.activity-panel__tab--external {
  background: var(--accent-primary-500);
}

.activity-panel__tab--external:hover {
  background: var(--accent-primary-600);
}

/* External message items */
.external-item {
  padding: var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}

.external-item--customer {
  background: var(--bg-page);
  border-left: 3px solid var(--text-muted);
}

.external-item--staff {
  background: rgba(0, 156, 182, 0.08);
  border-left: 3px solid var(--accent-primary-500);
}

.external-item--event {
  background: transparent;
  border: none;
  padding: var(--space-2) 0;
  border-left: 2px solid var(--border);
  padding-left: var(--space-3);
  margin-left: var(--space-2);
}

.external-item__header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.external-item__author {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: var(--font-medium);
}

.external-item__time {
  font-size: var(--text-xs);
}

.external-item__content {
  white-space: pre-wrap;
  word-break: break-word;
  line-height: 1.5;
}

.external-item__event {
  display: flex;
  gap: var(--space-2);
}

/* External recipient display */
.external-recipient {
  background: var(--bg-page);
  border: 1px solid var(--accent-primary-200);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  margin-bottom: var(--space-3);
}

.external-recipient__label {
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: var(--space-1);
}

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

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

/* External comment form */
.activity-panel__form--external {
  background: rgba(0, 156, 182, 0.04);
  border-top: 1px solid var(--accent-primary-200);
}

.external-comment-form__input {
  width: 100%;
  padding: var(--space-3);
  background: var(--bg-page);
  color: var(--text);
  border: 1px solid var(--accent-primary-200);
  border-radius: var(--radius-md);
  font-family: inherit;
  font-size: var(--text-sm);
  resize: vertical;
  min-height: 80px;
}

.external-comment-form__input::placeholder {
  color: var(--text-muted);
}

.external-comment-form__input:focus {
  outline: none;
  border-color: var(--accent-primary-500);
  box-shadow: 0 0 0 3px rgba(0, 156, 182, 0.15);
}

.external-comment-form__footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: var(--space-3);
  gap: var(--space-3);
}

/* External warning message */
.external-warning {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--accent-primary-600);
  font-size: var(--text-sm);
}

.external-warning svg {
  flex-shrink: 0;
  color: var(--accent-primary-500);
}

/* External send button */
.btn--external {
  background: var(--accent-primary-500);
  color: var(--white);
  border: none;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  font-weight: var(--font-medium);
  cursor: pointer;
  transition: background var(--transition-fast);
  white-space: nowrap;
}

.btn--external:hover {
  background: var(--accent-primary-600);
}

.btn--external:active {
  background: var(--accent-primary-700);
}

/* Activity panel mobile layout - form at top, newest first */
@media (max-width: 1023px) {

  /* Move form to top */
  .activity-panel__form {
    order: -1;
    border-top: none;
    border-bottom: 1px solid var(--border);
  }

  /* Make content a flex container to reorder children */
  .activity-panel__content {
    display: flex;
    flex-direction: column;
  }

  /* Reverse activity list (newest first) */
  .activity-panel__list {
    display: flex;
    flex-direction: column-reverse;
  }

  /* Move "Load earlier" button to bottom */
  .activity-panel__load-more {
    order: 1;
    margin-top: var(--space-4);
  }
}

/* Layout with activity panel
   On desktop: main content scrolls with page, activity panel is fixed on the right
   On mobile: panel drops below main content

   Fixed panel positioning calculation:
   - Container is max 1400px centered, so right edge of container from viewport right is:
     max(0, (100vw - 1400px) / 2) + container padding
   - Panel width is 380px
   - We use CSS variables to make this maintainable */
.page-with-activity {
  --panel-width: 380px;
  --panel-gap: var(--space-6);
  display: block;
}

.page-with-activity__main {
  /* On mobile, full width */
}

.page-with-activity__activity {
  /* On mobile, flows naturally below content */
  margin-top: var(--space-6);
  max-height: 500px;
  display: flex;
  flex-direction: column;
}

@media (min-width: 1024px) {
  .page-with-activity {
    /* Reserve space on right for fixed panel */
    padding-right: calc(var(--panel-width) + var(--panel-gap));
  }

  .page-with-activity__main {
    min-width: 0;
  }

  .page-with-activity__activity {
    position: fixed;
    top: 80px;
    /* Header height + extra spacing */
    /* Position from right: container padding when viewport <= container max-width,
       otherwise account for centred container */
    right: max(var(--space-6), calc((100vw - 1400px) / 2 + var(--space-6)));
    width: var(--panel-width);
    height: calc(100vh - 80px - var(--space-6));
    max-height: none;
    margin-top: 0;
    z-index: 50;
    /* Above page content, below header/modals */
  }

  /* Centre footer relative to main content pane, not full width */
  .container:has(.page-with-activity)~.footer {
    padding-right: calc(380px + var(--space-6));
  }
}

/* ============================================================================
   TICKET DETAIL LAYOUT
   On desktop: left sidebar for ticket details, fixed activity panel on right
   On mobile: stacked layout with panel below main content
   ============================================================================ */

.ticket-layout {
  --panel-width: 380px;
  --panel-gap: var(--space-6);
  display: block;
}

.ticket-layout__main {
  /* On mobile, full width, stacked vertically */
}

.ticket-layout__panel {
  /* On mobile, flows below content */
  margin-top: var(--space-6);
  max-height: 500px;
  display: flex;
  flex-direction: column;
}

.ticket-layout__panel>.activity-panel,
.ticket-layout__panel>.activity-panel--external {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

@media (min-width: 1024px) {
  .ticket-layout {
    /* Reserve space on right for fixed panel */
    padding-right: calc(var(--panel-width) + var(--panel-gap));
  }

  .ticket-layout__main {
    /* Main content is naturally positioned */
  }

  .ticket-layout__panel {
    position: fixed;
    top: 80px;
    /* Header height + extra spacing */
    /* Position from right: container padding when viewport <= container max-width,
       otherwise account for centred container */
    right: max(var(--space-6), calc((100vw - 1400px) / 2 + var(--space-6)));
    width: var(--panel-width);
    height: calc(100vh - 80px - var(--space-6));
    max-height: none;
    margin-top: 0;
    z-index: 50;
    /* Above page content, below header/modals */
  }
}

/* Detail list for ticket metadata */
.detail-list {
  margin: 0;
}

.detail-list__item {
  display: flex;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
}

.detail-list__item:last-child {
  border-bottom: none;
}

.detail-list__item dt {
  width: 100px;
  flex-shrink: 0;
  font-weight: 500;
  color: var(--text-muted);
}

.detail-list__item dd {
  margin: 0;
}

/* ============================================================================
   HOME PAGE LAYOUT
   ============================================================================ */

.home-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}

@media (min-width: 1024px) {
  .home-layout {
    grid-template-columns: 1fr 400px;
  }

  .home-layout__main {
    min-width: 0;
  }

  .home-layout__feed {
    position: sticky;
    top: var(--space-4);
    height: calc(100vh - var(--space-8));
    max-height: 800px;
  }
}

/* Mobile: Feed first */
@media (max-width: 1023px) {
  .home-layout__feed {
    order: -1;
  }
}

/* ============================================================================
   ACTIVITY FEED (Home page global feed)
   ============================================================================ */

.activity-feed {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.activity-feed__header {
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.activity-feed__title {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  margin: 0;
}

.activity-feed__content {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-4);
}

.activity-feed__empty {
  text-align: center;
  padding: var(--space-8);
}

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

/* Activity feed items */
.activity-feed-item {
  padding: var(--space-3);
  background: var(--bg-page);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-subtle);
}

.activity-feed-item__context {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
}

.activity-feed-item__entity {
  font-weight: var(--font-medium);
  color: var(--link);
  text-decoration: none;
}

.activity-feed-item__entity:hover {
  text-decoration: underline;
}

.activity-feed-item__entity-type {
  color: var(--text-muted);
  font-size: var(--text-xs);
}

.activity-feed-item__entity-type::before {
  content: "·";
  margin-right: var(--space-2);
}

.activity-feed-item__header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1);
  font-size: var(--text-sm);
}

.activity-feed-item__author {
  font-weight: var(--font-medium);
  color: var(--text);
}

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

.activity-feed-item__time {
  color: var(--text-subtle);
  font-size: var(--text-xs);
  margin-left: auto;
}

.activity-feed-item__content {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text);
  white-space: pre-wrap;
}

.activity-feed-item__changes {
  margin-top: var(--space-2);
  font-size: var(--text-xs);
}

.activity-feed-item__change {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) 0;
}

.activity-feed-item__change-field {
  font-weight: var(--font-medium);
  color: var(--text-muted);
  min-width: 80px;
}

.activity-feed-item__change-old {
  color: var(--text-subtle);
  text-decoration: line-through;
}

.activity-feed-item__change-arrow {
  color: var(--text-subtle);
}

.activity-feed-item__change-new {
  color: var(--text);
}

/* ============================================================================
   DISCLOSURE — collapsible sections on <details>/<summary>. Mechanism only:
   chevron, summary row, content panel, open/close rotation. No border, radius,
   or background — wrap in .card (or use an existing .card parent) for chrome.
   ============================================================================ */

.disclosure__summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
  list-style: none;
  user-select: none;
}

.disclosure__summary::-webkit-details-marker {
  display: none;
}

.disclosure__summary::before {
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 18 15 12 9 6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 18 15 12 9 6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform var(--duration-fast) ease;
}

.disclosure[open] > .disclosure__summary::before {
  transform: rotate(90deg);
}

.disclosure__content {
  padding: var(--space-3) var(--space-4);
}

/* Muted variant — filter bars (now_chart, missions) */
.disclosure--muted > .disclosure__summary {
  padding: var(--space-2) 0;
  color: var(--text-muted);
}

.disclosure--muted > .disclosure__content {
  padding: var(--space-3) 0 0;
}

/* A summary's parts, when it holds more than a few words: its title, a line
   of what the section holds (shown folded or open), and pills at its end */
.disclosure__title {
  min-width: 0;
  margin: 0;
  overflow: hidden;
  font: inherit;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.disclosure__meta {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-size: var(--text-sm);
  font-weight: var(--font-normal);
  color: var(--text-muted);
  white-space: nowrap;
  text-overflow: ellipsis;
}

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

/* Card variant — the card itself folds to its heading: an icon tile, the
   title, its meta and pills, the chevron at the end. card-collapse.js
   remembers each viewer's choice for one with `data-collapse-key`. */
.card.disclosure--card {
  padding: 0;
}

.disclosure--card > .disclosure__summary {
  gap: var(--space-3);
  min-height: 60px;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-lg);
}

.disclosure--card > .disclosure__summary::before {
  order: 1;
  margin-left: auto;
  color: var(--text-subtle);
}

.disclosure--card > .disclosure__summary:hover::before {
  color: var(--text);
}

.disclosure--card > .disclosure__summary:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.disclosure--card[open] > .disclosure__summary {
  border-bottom: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.disclosure--card .disclosure__title {
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

.disclosure--card > .disclosure__content {
  padding: var(--space-5);
}

/* Super-admin module toggles — plain .disclosure inside .card--module-groups */
.card--module-groups {
  padding: 0;
  overflow: hidden;
}

.card--module-groups__empty {
  padding: var(--space-5);
  margin: 0;
}

.card--module-groups > .disclosure:not(:last-child) {
  border-bottom: 1px solid var(--border-subtle);
}

.card--module-groups > .disclosure > .disclosure__summary {
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
}

.card--module-groups > .disclosure > .disclosure__content {
  padding: 0 var(--space-5) var(--space-3);
}

.card--module-groups > .disclosure .toggle-switch-form:last-child .module-item {
  padding-bottom: var(--space-4);
}

/* ============================================================================
   TOOLTIP
   ============================================================================ */

.tooltip {
  position: absolute;
  z-index: var(--z-tooltip);
  pointer-events: none;
  background: var(--bg-elev-3);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  box-shadow: var(--shadow-md);
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease);
  max-width: 280px;
  white-space: nowrap;
}

.tooltip--visible {
  opacity: 1;
}

/* Show tooltip on hover without JS */
.tooltip-wrap:hover .tooltip {
  opacity: 1;
}

/* Chart tooltip — viewport-fixed, rich content, used by missions + NoW charts */
.chart-tooltip {
  position: fixed;
  visibility: hidden;
  z-index: var(--z-tooltip);
  pointer-events: none;
  background: var(--bg-elev-3);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-sm);
  line-height: 1.5;
  box-shadow: var(--shadow-md);
  max-width: 340px;
}

.chart-tooltip--visible {
  visibility: visible;
}

.chart-tooltip--interactive {
  pointer-events: auto;
}

.chart-tooltip__heading {
  font-weight: 600;
  margin-bottom: var(--space-2);
}

.chart-tooltip__item {
  padding: var(--space-2);
  margin: 0 calc(-1 * var(--space-2));
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.chart-tooltip__item:hover {
  background: var(--bg-elev-2);
}

.chart-tooltip__item--expanded {
  background: var(--bg-elev-2);
}

/* ============================================================================
   TIMELINE CHART
   ============================================================================ */

.timeline-chart {
  position: relative;
  min-height: 60px;
  overflow-x: auto;
}

.timeline-chart__empty {
  text-align: center;
  padding: var(--space-8);
  color: var(--text-muted);
}

.timeline-chart svg {
  display: block;
  /* Safari clips SVG overflow by default; markers sit on the bar top edge. */
  overflow: visible;
}

.timeline-chart .axis text {
  fill: var(--chart-label);
  font-size: var(--text-xs);
}

.timeline-chart .axis line,
.timeline-chart .axis path {
  stroke: var(--chart-grid);
}

.timeline-chart .date-line {
  stroke: var(--chart-now-line);
  stroke-width: 2;
  stroke-dasharray: 5 5;
}

.timeline-chart__legend-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: var(--radius-sm);
}

/* ============================================================================
   CHART LEGEND (disclosure key)
   ============================================================================ */

.chart-legend-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  color: var(--text);
}

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

.chart-legend-swatch {
  display: inline-block;
  flex-shrink: 0;
  width: 12px;
  height: 12px;
  overflow: visible;
}

/* Glyph colour via CSS — Safari ignores var() in SVG presentation attributes. */
.chart-legend-swatch__glyph {
  fill: var(--bg-elev-1);
}

.chart-legend-swatch--open,
.chart-legend-swatch--active,
.chart-legend-swatch--completed,
.chart-legend-swatch--overdue {
  border-radius: var(--radius-sm);
}

.chart-legend-swatch--on-site,
.chart-legend-swatch--off-site,
.chart-legend-swatch--incident,
.chart-legend-swatch--multi {
  border-radius: 50%;
}

.chart-legend-swatch--open        { background: var(--chart-open); }
.chart-legend-swatch--active      { background: var(--chart-active); }
.chart-legend-swatch--completed   { background: var(--chart-completed); }
.chart-legend-swatch--overdue     { background: var(--chart-overdue); }
.chart-legend-swatch--on-site     { background: var(--text); }
.chart-legend-swatch--off-site    { background: var(--text-muted); }
.chart-legend-swatch--incident    { background: var(--chart-incident); }
.chart-legend-swatch--multi       { background: var(--chart-multi); }

/* ============================================================================
   SEGMENTED CONTROL (day picker)
   ============================================================================ */

.segmented-control {
  display: inline-flex;
  align-items: stretch;
  background: var(--bg-elev-2);
  border-radius: var(--radius-md);
  padding: 2px;
}

.segmented-control__item {
  display: flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border-radius: calc(var(--radius-md) - 2px);
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-family: inherit;
  line-height: 1;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: background var(--duration-fast) ease,
              color var(--duration-fast) ease;
}

.segmented-control__item:hover {
  color: var(--text);
}

.segmented-control__item--active {
  background: var(--bg-elev-3);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}

/* ============================================================================
   MODAL VARIANTS
   ============================================================================ */

.modal--wide {
  max-width: 640px;
}

/* Spinner animation for loading state */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ============================================================================
   TUTORIAL CARDS
   ============================================================================ */

.tutorial-card {
  display: block;
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: box-shadow var(--duration-base) var(--ease),
    transform var(--duration-base) var(--ease);
}

.tutorial-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.tutorial-card__thumbnail {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--bg-elev-2);
  overflow: hidden;
}

.tutorial-card__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.tutorial-card__placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--text-muted);
}

.tutorial-card__body {
  padding: var(--space-3);
}

.tutorial-card__badge {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: var(--space-1);
}

.tutorial-card__title {
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text);
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tutorial-card__description {
  font-size: var(--text-xs);
  color: var(--text-muted);
  margin: var(--space-1) 0 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ============================================================================
   TUTORIAL BREADCRUMBS
   ============================================================================ */

.tutorial-breadcrumbs {
  margin-bottom: var(--space-4);
}

.tutorial-breadcrumbs__list {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1);
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: var(--text-sm);
}

.tutorial-breadcrumbs__item:not(:last-child)::after {
  content: "/";
  margin-left: var(--space-1);
  color: var(--text-muted);
}

.tutorial-breadcrumbs__icon {
  margin-right: var(--space-1);
  vertical-align: -0.125em;
}

.tutorial-breadcrumbs__link {
  color: var(--accent-primary-500);
  text-decoration: none;
}

.tutorial-breadcrumbs__link:hover {
  text-decoration: underline;
}

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

/* ============================================================================
   TUTORIAL SEARCH
   ============================================================================ */

.tutorial-search {
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
}

.tutorial-search .input {
  flex: 1;
}

/* ============================================================================
   VIDEO PLAYER
   ============================================================================ */

.video-player {
  --video-player-bg: #000;
  background: var(--video-player-bg);
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: var(--space-4);
}

.video-player__video {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: contain;
  display: block;
}

/* ============================================================================
   CMS CONTENT META (shared across all content formats)
   ============================================================================ */

.cms-content__meta {
  margin-top: var(--space-4);
  padding: var(--space-5) var(--space-6);
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.cms-content__title {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  color: var(--text);
  margin: 0 0 var(--space-3);
}

.cms-content__categories {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.cms-content__description {
  color: var(--text-secondary);
  font-size: var(--text-base);
  line-height: 1.7;
  border-top: 1px solid var(--border-subtle);
  padding-top: var(--space-4);
}

.cms-content__description p {
  margin: 0;
}

/* ============================================================================
   CONTENT VIEWERS (non-video formats)
   ============================================================================ */

/* Markdown article body */
.content-body--markdown {
  font-size: var(--text-base);
  line-height: 1.8;
  color: var(--text);
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: var(--space-6) var(--space-8);
  margin-bottom: var(--space-4);
}

.content-body--markdown h1,
.content-body--markdown h2,
.content-body--markdown h3,
.content-body--markdown h4 {
  margin-top: var(--space-6);
  margin-bottom: var(--space-3);
  font-weight: var(--font-semibold);
  color: var(--text);
}

.content-body--markdown h1 {
  font-size: var(--text-xl);
}

.content-body--markdown h2 {
  font-size: var(--text-lg);
}

.content-body--markdown h3 {
  font-size: var(--text-base);
}

.content-body--markdown p {
  margin: 0 0 var(--space-4);
}

.content-body--markdown ul,
.content-body--markdown ol {
  margin: 0 0 var(--space-4);
  padding-left: var(--space-6);
}

.content-body--markdown li {
  margin-bottom: var(--space-1);
}

.content-body--markdown code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--bg-elev-2);
  padding: 0.125em 0.375em;
  border-radius: 4px;
}

.content-body--markdown pre {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: var(--space-4);
  overflow-x: auto;
  margin: 0 0 var(--space-4);
}

.content-body--markdown pre code {
  background: none;
  padding: 0;
  border-radius: 0;
}

.content-body--markdown blockquote {
  border-left: 3px solid var(--accent-primary-500);
  padding-left: var(--space-4);
  margin: 0 0 var(--space-4);
  color: var(--text-secondary);
}

.content-body--markdown a {
  color: var(--accent-primary-500);
  text-decoration: underline;
}

.content-body--markdown img {
  max-width: 100%;
  height: auto;
  border-radius: 6px;
}

/* PDF viewer */
.content-viewer--pdf {
  margin-bottom: var(--space-4);
}

/* Image viewer */
.content-viewer--image {
  margin-bottom: var(--space-4);
}

.content-viewer__image {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  display: block;
}

/* ============================================================================
   TIMELINE COMPONENT
   Horizontal and vertical timeline for activity feeds and conversation views.
   BEM namespace: timeline
   ============================================================================ */

/* === Shared elements === */

.timeline__node {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent-primary-500);
  flex-shrink: 0;
  z-index: 1;
  position: relative;
}

.timeline__node--muted {
  background: var(--text-subtle);
  width: 8px;
  height: 8px;
  margin-top: 2px; /* Centre 8px node on same axis as 12px nodes */
}

.timeline__node--secondary {
  background: var(--accent-secondary-500);
}

.timeline__node--warning {
  background: var(--status-warning-500);
}

.timeline__node--success {
  background: var(--status-success-500);
}

.timeline__node--danger {
  background: var(--status-danger-500);
}

.timeline__node--icon {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
}

.timeline__node--icon svg {
  width: 10px;
  height: 10px;
}

.timeline__actor {
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

.timeline__time {
  font-size: var(--text-xs);
  color: var(--text);
  font-weight: var(--font-medium);
}

.timeline__clock-icon {
  vertical-align: -1px;
  margin-right: 2px;
}

.timeline__content {
  font-size: var(--text-base);
  color: var(--text-muted);
  line-height: 1.5;
}

.timeline__system-label {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-style: italic;
}

/* === Horizontal timeline === */

.timeline--horizontal {
  display: none;
  position: relative;
  padding: var(--space-8) 0 var(--space-4) 0;
}

@media (min-width: 768px) {
  .timeline--horizontal {
    display: block;
  }
  .timeline--vertical {
    display: none;
  }
}

.timeline__track {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding: 0 var(--space-4) var(--space-4) var(--space-4);
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
  /* Track line via background — spans full scrollable width */
  background: linear-gradient(
    to bottom,
    transparent 5px,
    var(--border) 5px,
    var(--border) 7px,
    transparent 7px
  );
}

.timeline__track::-webkit-scrollbar {
  height: 6px;
}

.timeline__track::-webkit-scrollbar-track {
  background: transparent;
}

.timeline__track::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 3px;
}

/* Right-edge fade when content overflows — subtle hint only */
.timeline--horizontal::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 32px;
  background: linear-gradient(to right, transparent, color-mix(in srgb, var(--bg-page) 70%, transparent));
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  transition: opacity var(--duration-base);
}

.timeline--horizontal.has-overflow::after {
  opacity: 1;
}

/* Individual entry along the horizontal track */
.timeline__entry--horizontal {
  display: flex;
  flex-direction: column;
  align-items: center;
  scroll-snap-align: start;
  min-width: 200px;
  max-width: 260px;
  flex-shrink: 0;
}

/* Vertical stem connecting node to card */
.timeline__stem {
  width: 2px;
  height: var(--space-3);
  background: var(--border);
}

/* Activity card (horizontal) */
.timeline__card {
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-3);
  width: 100%;
  transition: box-shadow var(--duration-base) var(--ease);
}

.timeline__card:hover {
  box-shadow: var(--shadow-sm);
}

.timeline__card--user {
  border-left: 3px solid var(--accent-primary-500);
}

.timeline__card--agent {
  border-left: 3px solid var(--accent-secondary-500);
}

.timeline__card-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

/* Truncation for long comments — expandable via JS */
.timeline__card--expandable .timeline__content {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  cursor: pointer;
}

.timeline__card--expanded .timeline__content {
  display: block;
  -webkit-line-clamp: unset;
  overflow: visible;
}

/* System event (horizontal) — compact, no card */
.timeline__event--horizontal {
  display: flex;
  flex-direction: column;
  align-items: center;
  scroll-snap-align: start;
  min-width: 100px;
  max-width: 140px;
  flex-shrink: 0;
  text-align: center;
}

.timeline__event-label {
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-style: italic;
  line-height: 1.4;
}

/* === Vertical timeline ===
   .timeline--vertical is the mobile half of an adaptive pair with
   .timeline--horizontal (hidden on ≥768px — see the media query above).
   .timeline--stack is the always-vertical variant for timelines that do
   not have a horizontal counterpart (execution events, ticket activity,
   incident follow-ups). Both share the same visual. */

.timeline--vertical,
.timeline--stack {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: var(--space-3) 0;
  position: relative;
  margin-left: var(--space-3);
}

/* Vertical track line */
.timeline--vertical::before,
.timeline--stack::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 5px; /* Centred on 12px node */
  width: 2px;
  background: var(--border);
}

/* Vertical entry — conversation variant (default) */
.timeline__entry--vertical {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  position: relative;
  padding-bottom: var(--space-4);
}

.timeline__entry--vertical:last-child {
  padding-bottom: 0;
}

.timeline__entry--vertical .timeline__node {
  margin-top: 3px; /* Align with first line of text */
}

.timeline__entry--vertical .timeline__node--muted {
  margin-top: 5px;
  margin-left: 2px; /* Centre 8px node on the same axis as 12px */
  margin-right: 2px;
}

.timeline__entry-body {
  flex: 1;
  min-width: 0;
}

.timeline__entry-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
}

.timeline--stack .timeline__entry-header {
  flex-direction: column;
  gap: var(--space-1);
}

/* Vertical comment content — full text, no truncation */
.timeline__entry-body .timeline__content {
  padding-bottom: var(--space-1);
}

/* User/agent accent for vertical conversation entries */
.timeline__entry--vertical.timeline__entry--user .timeline__entry-body {
  border-left: 3px solid var(--accent-primary-500);
  padding-left: var(--space-3);
  margin-left: calc(-1 * var(--space-1));
}

.timeline__entry--vertical.timeline__entry--agent .timeline__entry-body {
  border-left: 3px solid var(--accent-secondary-500);
  padding-left: var(--space-3);
  margin-left: calc(-1 * var(--space-1));
}

/* Follow-up notes nested under a parent timeline entry (e.g. incident
   follow-ups on the NoW execution timeline). Unordered list rendered as a
   bulleted column with a subtle left rule to signal nesting. */
.timeline__follow-ups {
  list-style: none;
  padding-left: var(--space-4);
  margin: 0;
  border-left: 2px solid var(--border-subtle);
}

/* === Vertical timeline — list card variant === */
/* Clickable summary cards for list views (e.g. ticket list on mobile) */

.timeline__entry--vertical.timeline__entry--list-card {
  padding-bottom: var(--space-3);
}

.timeline__entry--list-card .timeline__entry-body {
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-3);
  transition:
    box-shadow var(--duration-base) var(--ease);
}

.timeline__entry--list-card .timeline__entry-body:hover {
  box-shadow: var(--shadow-sm);
}

.timeline__entry--list-card .timeline__entry-body a {
  color: inherit;
  text-decoration: none;
  display: block;
}

.timeline__list-card-title {
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  margin-bottom: var(--space-1);
}

.timeline__list-card-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

/* === Reply form (sticky on mobile) === */

@media (max-width: 767px) {
  .timeline-reply {
    position: sticky;
    bottom: 0;
    background: var(--bg-page);
    border-top: 1px solid var(--border);
    padding: var(--space-3);
    margin: var(--space-4) calc(-1 * var(--space-4)) 0;
    z-index: 1;
  }
}

/* === Unread indicator === */

.timeline-unread {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent-primary-500);
  display: inline-block;
  flex-shrink: 0;
}

/* Reduced motion: disable chart, tooltip, tutorial card and timeline transitions */
@media (prefers-reduced-motion: reduce) {
  .tooltip {
    transition: none;
  }

  .timeline-chart rect,
  .timeline-chart line,
  .timeline-chart text {
    transition: none;
  }

  .tutorial-card {
    transition: none;
  }

  .tutorial-card:hover {
    transform: none;
  }

  .timeline__card {
    transition: none;
  }

  .timeline__entry--list-card .timeline__entry-body {
    transition: none;
  }
}

/* ============================================================================
   File upload component
   Ported from TMS: static/js/file-upload.js
   ============================================================================ */

.file-upload {
  width: 100%;
}

.file-upload__dropzone {
  border: 2px dashed var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s;
}

.file-upload__dropzone:hover {
  border-color: var(--accent-primary-500);
  background-color: var(--bg-elev-2);
}

.file-upload__dropzone--active {
  border-color: var(--accent-primary-500);
  background-color: var(--bg-elev-2);
}

.file-upload__dropzone--has-file {
  border-style: solid;
  border-color: var(--border);
}

.file-upload__input {
  display: none;
}

.file-upload__prompt {
  color: var(--text-muted);
  font-size: var(--text-sm);
  margin: 0;
}

.file-upload__prompt-icon {
  display: block;
  margin: 0 auto var(--space-2);
  color: var(--text-muted);
}

.file-upload__preview {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  justify-content: center;
}

.file-upload__preview-image {
  max-width: 120px;
  max-height: 120px;
  border-radius: var(--radius-md);
  object-fit: cover;
}

.file-upload__filename {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
}

.file-upload__filesize {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.file-upload__actions {
  margin-top: var(--space-2);
  text-align: center;
}

.file-upload__error {
  color: var(--status-danger-600);
  font-size: var(--text-sm);
  margin-top: var(--space-2);
}

/* ============================================================================
   Incident photos
   ============================================================================ */

/* Thumbnail for an incident photo as it appears in a timeline entry. */
.incident-thumb {
  max-width: 240px;
  max-height: 180px;
  border-radius: var(--radius-md);
}

/* Full-size incident photo on the incident detail page. */
.incident-photo {
  max-width: 100%;
  max-height: 400px;
  border-radius: var(--radius-md);
}

/* ============================================================================
   Work evidence
   BEM namespace: work-evidence
   Before/after proof-of-work photos on the NoW detail, approval detail,
   and job report pages.
   ============================================================================ */

/* Two slots side by side on desktop, stacked on mobile. */
.work-evidence__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

@media (min-width: 768px) {
  .work-evidence__grid {
    grid-template-columns: 1fr 1fr;
  }
}

.work-evidence__slot-title {
  font-size: var(--text-sm);
  font-weight: 600;
  margin-bottom: var(--space-2);
}

.work-evidence__meta {
  margin-top: var(--space-2);
}

/* ============================================================================
   Audit photo
   BEM namespace: audit-photo
   Bordered container for read-only audit photos. Mirrors the file-upload
   dropzone appearance so editable and read-only states sit consistently
   in the same grid.
   ============================================================================ */

.audit-photo {
  border: 2px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  text-align: center;
}

.audit-photo__image {
  max-width: 100%;
  max-height: 320px;
  border-radius: var(--radius-sm);
  object-fit: contain;
  display: block;
  margin: 0 auto;
}

/* ============================================================================
   NoW detail cards
   BEM namespace: now-card
   Used by templates/pages/now_detail.html and now_approval_detail.html.
   ============================================================================ */

/* Core info card layout — two-column "letter" layout on desktop with
   the main attributes on the left and a postal-format address block
   on the right; collapses to a single stacked column on mobile. */
.now-card__core-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) max-content;
  gap: var(--space-6);
  align-items: start;
}

/* Stacked postal address — replaces the previous inline single-line
   format which read awkwardly. Right-aligned at desktop so it sits
   visually like a letter address opposite the main details. */
.now-card__address-block {
  display: flex;
  flex-direction: column;
  font-style: normal;
  font-size: var(--text-sm);
  color: var(--text-muted);
  line-height: 1.5;
  text-align: right;
  white-space: nowrap;
}

.now-card__directions-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-sm);
  color: var(--link);
  text-decoration: none;
  margin-top: var(--space-3);
}

.now-card__directions-link:hover {
  text-decoration: underline;
}

@media (max-width: 600px) {
  .now-card__core-grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }

  .now-card__address-block {
    text-align: left;
    order: 2;
  }
}

/* Two-column key/value grid. Key column sized to its widest natural
   width; stacks to a single column at the mobile breakpoint. Drop-in
   replacement for the inline-style `<dl style="display: grid; ...">`
   pattern used across detail views. */
.dl-grid {
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: var(--space-4);
  row-gap: var(--space-2);
  margin: 0;
}

.dl-grid > dt {
  color: var(--text-muted);
  min-width: 0;
}

.dl-grid > dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}

@media (max-width: 600px) {
  .dl-grid {
    grid-template-columns: 1fr;
    row-gap: var(--space-1);
  }

  .dl-grid > dt {
    margin-top: var(--space-2);
  }

  .dl-grid > dt:first-child {
    margin-top: 0;
  }
}

.dl-grid--sm {
  column-gap: var(--space-3);
  row-gap: var(--space-1);
  font-size: var(--text-sm);
}

/* Card actions row. Resets child form margins so adjacent button-bearing
   forms sit flush. `--footer` modifier picks up a divider and right-
   aligns; use at the bottom of a card. */
.now-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

.now-card__actions > form {
  margin: 0;
}

.now-card__actions--footer {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
  justify-content: flex-end;
}

/* Range slider with bound labels and a live value display. */
.range-slider {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.range-slider__bound {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.range-slider__input {
  flex: 1;
}

.range-slider__value {
  font-weight: var(--font-semibold);
  min-width: 3rem;
  text-align: right;
}

.now-card__mission-id {
  font-family: var(--font-mono);
  font-size: var(--text-2xl);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  margin: 0;
  letter-spacing: 0.05em;
}

/* Compact card body — used for the bold mission-ID slip above the
   On-site card. No heading, tighter padding than a normal info card.
   Flex row places the copy control beside the ID. */
.now-card--mission-id {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
}

.now-card--mission-id .copy-btn {
  flex-shrink: 0;
}

/* ============================================================================
   CAW STATUS STRIP — subtle, persistent strip below the page header on
   NoW list pages. Mirrors the missions chart's "Last updated" line in
   weight, with three states driven by data-caw-status:
     loading | ok | failed
   ============================================================================ */

.caw-status-strip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.caw-status-strip__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-muted);
  flex-shrink: 0;
}

.caw-status-strip[data-caw-status="loading"] .caw-status-strip__dot {
  background: var(--color-info, #3b82f6);
  animation: caw-status-pulse 1.4s ease-in-out infinite;
}

.caw-status-strip[data-caw-status="ok"] .caw-status-strip__dot {
  background: var(--color-success, #10b981);
}

.caw-status-strip[data-caw-status="failed"] .caw-status-strip__dot {
  background: var(--color-warning, #f59e0b);
}

.caw-status-strip[data-caw-status="failed"] .caw-status-strip__text {
  color: var(--color-warning, #f59e0b);
}

@keyframes caw-status-pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 1; }
}

/* Inline spinner appended inside CAW-dependent filter buttons while
   the refinement fetch is in flight. Removed once the fetch settles. */
.btn--loading {
  position: relative;
}

.btn--loading::after {
  content: "";
  display: inline-block;
  margin-left: var(--space-2);
  width: 0.7em;
  height: 0.7em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -0.125em;
  animation: spin 0.7s linear infinite;
}

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

.now-card__incidents {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.now-card__incidents > li {
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
}

.now-card__incidents > li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

/* Lock-groups list inside the Core info card. Bulletless flex rows
   with an inline lock SVG sitting where a list bullet would. */
.now-card__lock-groups {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.now-card__lock-groups > li {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.lock-icon {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
  color: var(--text-muted);
}

/* Inline coordinate pin link rendered next to a `location_label` value. */
.map-pin-link {
  display: inline-flex;
  align-items: center;
  margin-left: var(--space-1);
  color: var(--text-subtle);
  vertical-align: text-bottom;
}

.map-pin-link:hover {
  color: var(--accent-primary-500);
}

.map-pin-icon {
  width: 14px;
  height: 14px;
}

/* Map pin as button — reset default button chrome */
button.map-pin-link {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
}

button.map-pin-link:focus-visible {
  outline: 2px solid var(--link);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Leaflet container inside location modal */
.location-map {
  height: 400px;
  width: 100%;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--neutral-100);
}

@media (max-width: 767px) {
  .location-map {
    height: 50vh;
    min-height: 240px;
  }
}

/* Map and detail — a map beside a panel about the place it shows (its
   address, its coordinates, what to do with them), in a wider modal;
   stacked on a phone. Without a position the panel stands alone. */
.modal--map {
  max-width: 880px;
}

.map-detail {
  display: grid;
  gap: var(--space-4);
}

.map-detail__aside {
  display: grid;
  align-content: start;
  gap: var(--space-3);
}

@media (min-width: 768px) {
  .map-detail:not(.map-detail--no-map) {
    grid-template-columns: minmax(0, 1fr) 240px;
    align-items: start;
  }
}

.location-map__unavailable {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* Inline help text variant used by per-day scheduler validation. */
.help-text--error {
  color: var(--status-danger-500);
}

/* ============================================================================
   Schedule strip — visual representation of an access window over a 24h rail.
   Used in the NoW detail card. Positioned by static/js/schedule-strip.js
   via custom properties on `.schedule-strip__segment`.
   ============================================================================ */

.schedule-strips__heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  flex-wrap: wrap;
}

.schedule-strips {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.schedule-strip__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-1);
  flex-wrap: wrap;
}

.schedule-strip__date {
  font-weight: var(--font-medium);
  color: var(--text-strong);
}

.schedule-strip__times {
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.schedule-strip__overnight {
  margin-left: var(--space-1);
}

.schedule-strip__rail {
  position: relative;
  height: 8px;
  border-radius: var(--radius-pill, 999px);
  background: var(--bg-elev-2, var(--border-subtle));
  overflow: hidden;
}

.schedule-strip__segment {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--strip-start, 0%);
  width: var(--strip-width, 0%);
  background: linear-gradient(
    90deg,
    var(--accent-primary-400, var(--accent-primary-500)),
    var(--accent-primary-500)
  );
  border-radius: inherit;
  transition: left var(--duration-base) var(--ease),
              width var(--duration-base) var(--ease);
}

/* Hour-axis labels sit directly under the rail's gridlines at 0/25/50/
   75/100% — the same anchor points the segment uses. Absolutely
   positioned so they line up exactly; an equal-column grid with
   centred text would push the middle three labels off-anchor (they'd
   sit at 30/50/70% instead of 25/50/75%). */
.schedule-strip__hours {
  position: relative;
  height: 1.1em;
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-variant-numeric: tabular-nums;
}

.schedule-strip__hours > span {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
}

.schedule-strip__hours > span:nth-child(1) {
  left: 0;
  transform: none;
}

.schedule-strip__hours > span:nth-child(2) {
  left: 25%;
}

.schedule-strip__hours > span:nth-child(3) {
  left: 50%;
}

.schedule-strip__hours > span:nth-child(4) {
  left: 75%;
}

.schedule-strip__hours > span:nth-child(5) {
  left: 100%;
  transform: translateX(-100%);
}

.schedule-strip__hours--shared {
  margin-top: var(--space-2);
}

/* ============================================================================
   NoW form: per-day schedule picker
   BEM namespace: scheduled-days
   Used by templates/pages/now_form.html with static/js/form-scheduler.js.
   ============================================================================ */

.scheduled-days__picker {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--space-2);
}

@media (max-width: 600px) {
  .scheduled-days__picker {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.scheduled-days__pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--space-2) var(--space-1);
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--text);
  cursor: pointer;
  transition: background var(--duration-base) var(--ease),
              border-color var(--duration-base) var(--ease),
              color var(--duration-base) var(--ease);
  font-family: inherit;
}

.scheduled-days__pill:hover {
  border-color: var(--accent-primary-500);
}

.scheduled-days__pill[aria-pressed="true"] {
  background: var(--accent-primary-500);
  border-color: var(--accent-primary-500);
  color: var(--text-inverse, #fff);
}

.scheduled-days__pill-weekday {
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.85;
}

.scheduled-days__pill-day {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  line-height: 1.1;
}

.scheduled-days__pill-month {
  font-size: var(--text-xs);
  opacity: 0.75;
}

.scheduled-days__rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.scheduled-days__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--bg-elev-1);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  flex-wrap: wrap;
}

.scheduled-days__row-label {
  font-weight: var(--font-medium);
  color: var(--text-strong);
}

.scheduled-days__row-times {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.scheduled-days__time {
  width: auto;
  min-width: 7rem;
}

.scheduled-days__sep {
  color: var(--text-subtle);
}

/* ============================================================================
   DATE RANGE CONTROLS
   ============================================================================ */

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

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

.date-range__separator {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.date-range__quick-selects {
  display: flex;
  gap: var(--space-1);
}

@media (max-width: 767px) {
  .date-range {
    flex-direction: column;
    align-items: stretch;
  }

  .date-range__inputs {
    flex-direction: column;
  }

  .date-range__inputs .input {
    width: 100%;
  }

  .date-range__quick-selects {
    flex-wrap: wrap;
  }
}

/* ============================================================================
   BLE GATEWAY MAP
   ============================================================================ */

/* Gateway view — map + sidebar panel */
.gateway-view {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: var(--space-4);
  min-height: 600px;
}

.gateway-view__map {
  min-height: 400px;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
}

.gateway-view__panel {
  overflow-y: auto;
  max-height: 80vh;
}

@media (max-width: 1023px) {
  .gateway-view {
    grid-template-columns: 1fr;
  }

  .gateway-view__map {
    min-height: 300px;
    height: 50vh;
  }

  .gateway-view__panel {
    max-height: none;
  }
}

/* Map container fills its parent */
.gateway-map {
  width: 100%;
  height: 100%;
  min-height: inherit;
  background: var(--bg-elev-2);
}

/* Pulsing gateway marker on the map */
.gateway-marker {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: var(--accent-primary-500);
  border: 2px solid var(--bg-elev-1);
  box-shadow: var(--shadow-sm);
  z-index: 2;
}

.gateway-marker__pulse {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 32px;
  height: 32px;
  margin: -16px 0 0 -16px;
  border-radius: 50%;
  background: var(--accent-primary-400);
  opacity: 0;
  animation: gateway-pulse 2s ease-out infinite;
  z-index: 1;
}

@keyframes gateway-pulse {
  0% {
    transform: scale(0.5);
    opacity: 0.6;
  }
  100% {
    transform: scale(2);
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .gateway-marker__pulse {
    animation: none;
    opacity: 0;
  }
}

/* Signal strength bar — CSS-only, driven by data-strength attribute */
.signal-bar {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  height: 14px;
  vertical-align: middle;
}

.signal-bar__segment {
  width: 3px;
  border-radius: 1px;
  background: var(--neutral-300);
  transition: background var(--duration-base) var(--ease);
}

.signal-bar__segment:nth-of-type(1) { height: 4px; }
.signal-bar__segment:nth-of-type(2) { height: 7px; }
.signal-bar__segment:nth-of-type(3) { height: 10px; }
.signal-bar__segment:nth-of-type(4) { height: 14px; }

.signal-bar[data-strength="close"] .signal-bar__segment {
  background: var(--status-success-600);
}

.signal-bar[data-strength="medium"] .signal-bar__segment:nth-of-type(1),
.signal-bar[data-strength="medium"] .signal-bar__segment:nth-of-type(2),
.signal-bar[data-strength="medium"] .signal-bar__segment:nth-of-type(3) {
  background: var(--accent-secondary-500);
}

.signal-bar[data-strength="far"] .signal-bar__segment:nth-of-type(1),
.signal-bar[data-strength="far"] .signal-bar__segment:nth-of-type(2) {
  background: var(--status-danger-500);
}

.signal-bar__rssi {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  margin-right: var(--space-1);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* Beacon marker on the map — small dot coloured by proximity */
.beacon-marker {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1.5px solid var(--bg-elev-1);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

.beacon-marker--close {
  background: var(--status-success-600);
}

.beacon-marker--medium {
  background: var(--accent-secondary-500);
}

.beacon-marker--far {
  background: var(--status-danger-500);
}

/* Beacon cluster marker — count badge when a ring has too many devices */
.beacon-cluster {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid var(--bg-elev-1);
  box-shadow: var(--shadow-sm);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  color: var(--text-inverse);
  cursor: pointer;
}

.beacon-cluster--close {
  background: var(--status-success-600);
}

.beacon-cluster--medium {
  background: var(--accent-secondary-500);
}

.beacon-cluster--far {
  background: var(--status-danger-500);
}

/* Beacon card — device entry in the gateway sidebar */
.beacon-card {
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  margin-bottom: var(--space-2);
}

.beacon-card--matched {
  border-left: 3px solid var(--accent-primary-500);
}

.beacon-card__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: var(--space-2);
}

.beacon-card__name {
  font-weight: var(--font-semibold);
  font-size: var(--text-sm);
  color: var(--text-strong);
  text-decoration: none;
}

a.beacon-card__name:hover {
  color: var(--accent-primary-600);
}

.beacon-card__meta {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
}

/* Live indicator — pulsing dot */
.live-indicator {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--status-success-500);
  animation: live-pulse 2s ease-in-out infinite;
  vertical-align: middle;
}

.live-indicator--offline {
  background: var(--neutral-400);
  animation: none;
}

@keyframes live-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}

@media (prefers-reduced-motion: reduce) {
  .live-indicator {
    animation: none;
  }
}

/* Beacon card — highlighted state (e.g. when selected on the map) */
.beacon-card--active {
  border-color: var(--accent-primary-400);
  box-shadow: 0 0 0 1px var(--accent-primary-400);
}

/* Countdown hourglass */
.countdown-hourglass {
  display: inline-block;
  animation: hourglass-flip 6s ease-in-out infinite;
  vertical-align: -1px;
}

@keyframes hourglass-flip {
  0%, 40% { transform: rotate(0deg); }
  50%, 90% { transform: rotate(180deg); }
  100% { transform: rotate(360deg); }
}

/* Print styles */
@media print {

  .header,
  .footer,
  .btn,
  .no-print {
    display: none !important;
  }

  body {
    background: white;
    color: black;
  }

  .card {
    border: 1px solid #ccc;
    box-shadow: none;
  }
}

/* ============================================================================
   ONBOARDING STEPPER
   ============================================================================ */

/* Step-by-step form presentation. Without JavaScript every step
   renders stacked and the progress header and nav stay hidden. */
.stepper__progress {
  margin-bottom: var(--space-5);
}

.stepper__progress-label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  margin-bottom: var(--space-2);
}

.stepper__dots {
  display: flex;
  gap: var(--space-2);
}

.stepper__dot {
  flex: 1;
  height: 4px;
  border-radius: var(--radius-sm);
  background: var(--border);
}

.stepper__dot--active {
  background: var(--accent-primary-500);
}

.stepper__step-title {
  font-size: var(--text-lg);
  margin: 0 0 var(--space-4) 0;
}

.stepper__nav {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.stepper__review {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-5) 0;
}

.stepper__review dt {
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.stepper__review dd {
  font-size: var(--text-sm);
  color: var(--text-strong);
  margin: 0;
  overflow-wrap: anywhere;
}

/* Profile photo step */
.photo-step__take-btn {
  margin-top: var(--space-3);
  width: 100%;
}

.photo-step__current {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}

.camera-modal__video {
  display: block;
  width: 100%;
  border-radius: var(--radius-md);
  background: #000;
}

/* ============================================================================
   ONBOARDING SPLASH
   ============================================================================ */

/* Post-onboarding splash screen — full-width on mobile, centred card
   on desktop, with a prominent server-code block for app setup. */
.onboarding-splash {
  max-width: 480px;
  margin: var(--space-8) auto;
  padding: 0 var(--space-4);
  text-align: center;
}

.onboarding-splash__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  margin-bottom: var(--space-4);
}

.onboarding-splash__icon--success {
  background: var(--status-success-100);
  color: var(--status-success-700);
}

.onboarding-splash__icon--pending {
  background: var(--status-warning-100);
  color: var(--status-warning-700);
}

.onboarding-splash__title {
  font-size: var(--text-2xl);
  margin-bottom: var(--space-3);
}

.onboarding-splash__lead {
  color: var(--text-muted);
  margin-bottom: var(--space-4);
}

.onboarding-splash__app-card {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  margin: var(--space-6) 0;
}

.onboarding-splash__app-title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-4);
}

.onboarding-splash__store-links {
  display: flex;
  gap: var(--space-3);
  justify-content: center;
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}

.onboarding-splash__server-code {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  background: var(--bg-elev-1);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-2);
}

.onboarding-splash__server-code-label {
  font-size: var(--text-sm);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.onboarding-splash__server-code-value {
  font-family: var(--font-mono);
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  letter-spacing: 0.15em;
  color: var(--text-strong);
}

.onboarding-splash__signin {
  margin-top: var(--space-6);
}

.onboarding-splash__signin-hint {
  color: var(--text-muted);
  margin-bottom: var(--space-3);
}

/* ============================================================================
   Zone picker — tree-aware multi-select for node assignment
   ============================================================================ */

/* Area tree — the read-only tree on a site's view and the inline
   builder on its edit page. Rows reuse the picker's depth-class indents. */
.area-tree {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.area-tree__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  min-height: 36px;
  border-radius: var(--radius-sm);
}

.area-tree__row:hover {
  background: var(--bg-elev-2);
}

.area-tree__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.area-tree__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  flex-shrink: 0;
}

.area-tree__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-2);
  padding: var(--space-2);
  border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
}

.area-tree__form .field {
  margin-bottom: 0;
  flex: 1 1 8rem;
}

.area-tree__empty {
  color: var(--text-muted);
  padding: var(--space-2);
}

/* Zone path — the horizontal variant of the area tree: one chip per zone
   from the site down to the assigned area, chevrons between. Wraps on
   narrow screens instead of scrolling. The chevron sits on the list item,
   outside the chip, so every chip is the same box. */
.zone-path {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
  padding: 0;
  margin: var(--space-2) 0 0;
  font-size: var(--text-sm);
}

/* The base `li` rule gives every item but the last a bottom margin, which
   would lift them off-centre in the flex row. */
.zone-path__item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  margin: 0;
  line-height: 1;
}

.zone-path__item:not(:last-child)::after {
  content: "";
  display: inline-block;
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  background: var(--text-subtle);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 18 15 12 9 6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='9 18 15 12 9 6'/%3E%3C/svg%3E") center / contain no-repeat;
}

.zone-path__step {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 26px;
  padding: 0 var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elev-1);
  color: var(--text-muted);
  line-height: 1;
  white-space: nowrap;
}

.zone-path__step--site {
  border-color: var(--border-strong);
  color: var(--text);
}

.zone-path__step--current {
  background: var(--bg-elev-2);
  border-color: var(--border-strong);
  color: var(--text-strong);
}

.zone-path__icon {
  flex-shrink: 0;
  color: var(--text-muted);
}

.zone-picker {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
}

.zone-picker__search {
  padding: var(--space-2);
  border-bottom: 1px solid var(--border);
}

.zone-picker__search:has([hidden]) {
  display: none;
}

.zone-picker__tree {
  max-height: 18rem;
  overflow-y: auto;
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.zone-picker__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  min-height: 36px;
  border-radius: var(--radius-sm);
  margin-bottom: 0;
}

.zone-picker__item:hover {
  background: var(--bg-elev-2);
}

/* The checkbox and what names it. The row's tree toggle sits beside it,
   outside the label, so the label's control stays the checkbox. */
.zone-picker__choice {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  min-width: 0;
  min-height: 36px;
  margin: 0;
  cursor: pointer;
}

/* Read-only picker: the selection is shown, not offered. */
.zone-picker__item:has(.zone-picker__checkbox:disabled) .zone-picker__choice {
  cursor: default;
}

.zone-picker__item:not(.zone-picker__item--inherited):has(.zone-picker__checkbox:disabled):hover {
  background: none;
}

.zone-picker__item--inherited {
  background: var(--bg-elev-2);
  opacity: 0.75;
}

.zone-picker--enhanced .zone-picker__item--inherited {
  background: transparent;
  position: relative;
}

.zone-picker--enhanced .zone-picker__item--inherited::after {
  content: "";
  position: absolute;
  inset: 0;
  left: calc(var(--space-2) + var(--tree-indent, 0) * var(--tree-guide-width));
  background: var(--bg-elev-2);
  border-radius: var(--radius-sm);
  pointer-events: none;
  z-index: 0;
}

.zone-picker--enhanced .zone-picker__item--inherited > * {
  position: relative;
  z-index: 1;
}

.zone-picker__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.zone-picker__badge {
  font-size: var(--text-xs);
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-1);
  flex-shrink: 0;
}

/* Selected-descendant count shown on a collapsed branch */
.zone-picker__badge--count {
  color: var(--accent-primary-500);
  border-color: var(--accent-primary-500);
}

/* Info trigger — small circled "i" beside section headings */
.info-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1.5px solid var(--accent-primary-500);
  color: var(--accent-primary-500);
  background: transparent;
  font-size: var(--text-xs);
  font-weight: 700;
  font-style: italic;
  font-family: Georgia, "Times New Roman", serif;
  cursor: pointer;
  vertical-align: middle;
  margin-left: var(--space-2);
  line-height: 1;
  padding: 0;
  transition: background 0.15s, color 0.15s;
}

.info-trigger:hover {
  background: var(--accent-primary-500);
  color: var(--text-inverse);
}

/* Info modal — full-screen overlay with a centred card */
.info-modal {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  opacity: 0;
  transition: opacity 0.2s ease;
  padding: var(--space-4);
}

.info-modal--visible {
  opacity: 1;
}

.info-modal__card {
  background: var(--bg-elev-1);
  border-radius: var(--radius-lg);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  max-width: 440px;
  width: 100%;
  transform: translateY(8px) scale(0.97);
  transition: transform 0.2s ease;
  overflow: hidden;
}

.info-modal--visible .info-modal__card {
  transform: translateY(0) scale(1);
}

.info-modal__header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-5) var(--space-3);
  color: var(--accent-primary-500);
}

.info-modal__header h3 {
  margin: 0;
  font-size: var(--text-lg);
  color: var(--text-strong);
}

.info-modal__body {
  padding: 0 var(--space-5);
}

.info-modal__section {
  padding: var(--space-3) 0;
  border-top: 1px solid var(--border-subtle);
}

.info-modal__section-title {
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent-primary-500);
  margin-bottom: var(--space-1);
}

.info-modal__section p {
  font-size: var(--text-sm);
  color: var(--text);
  margin: 0;
  line-height: 1.5;
}

.info-modal__footer {
  padding: var(--space-4) var(--space-5);
  display: flex;
  justify-content: flex-end;
}

@media (prefers-reduced-motion: reduce) {
  .info-modal,
  .info-modal__card {
    transition: none;
  }
}

.zone-picker__panel {
  border-top: 1px solid var(--border);
  padding: var(--space-2) var(--space-3);
}

.zone-picker__panel-title {
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: var(--space-1);
}

.zone-picker__panel-line {
  font-size: var(--text-sm);
  margin-bottom: var(--space-1);
}

/* Vendor coverage — per-credential sections on the vendor links panel */
.vendor-coverage {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
}

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

/* ============================================================================
   SITE DASHBOARDS
   The site list cards and the per-site dashboard: hero (with the status ring), area
   register, bunch chips, gateway tiles, activity feed, map markers, heat strip
   and presence lanes. Presence colours are the status tokens — present is
   success, out is info, missing is danger, unseen is neutral — and every
   state also carries an icon or a label, never colour alone. Chart marks read
   their colours from custom properties at render time, so one code path
   serves both themes.
   ============================================================================ */

/* --- Site list ---------------------------------------------------------- */

/* The sites list is built from the generic attention strip, filter bar and
   rail tree; what follows is only what is particular to a site's card, in
   its details popup */
.site-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* The verdict and the CAW badge */
.site-card__state {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.site-card__description {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

/* The chips sit at the card's foot */
.site-card__chips {
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-subtle);
}

/* --- Dashboard layout --------------------------------------------------- */

/* Lists here are laid out by grid or flex gaps. The base `li` margin would
   add to those gaps on every item but the last, leaving it out of line. */
.site-dash li,
.site-feed__item,
.site-detail__bunches li {
  margin-bottom: 0;
}

/* The feed is the one panel that scrolls inside the page. It keeps a gutter
   of its own, so the bar never sits on top of the content, and wears the
   app's thin scrollbar. The timeline deliberately does not scroll: a second
   vertical scroller inside the page fights the first. */
.site-feed {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
  scrollbar-gutter: stable;
}

.site-feed::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.site-feed::-webkit-scrollbar-track {
  background: transparent;
}

.site-feed::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: 3px;
}

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

.site-dash__live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--status-success-600);
}

.site-dash__live-dot--stale {
  background: var(--neutral-400);
}

@media (prefers-reduced-motion: no-preference) {
  .site-dash__live-dot:not(.site-dash__live-dot--stale) {
    animation: status-pill-breathe 2.4s ease-in-out infinite;
  }
}

.site-dash__areas {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
}

.site-dash__section {
  margin-top: var(--space-4);
}

.site-dash__gateways {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--space-3);
}

/* The Gateways tab has the full width to itself */
.site-dash__gateways--wide {
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}

/* A muted line saying why there is nothing to show, or what is shown.
   Space above it only when something comes before it, so one at the top
   of a card's body sits flush, as the body's other content does. */
.site-dash__note {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

* + .site-dash__note {
  margin-top: var(--space-3);
}

.site-dash__key {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.site-dash__key li {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

/* The area after the site's name in the page title */
.page-header__crumb {
  color: var(--text-muted);
  font-weight: var(--font-semibold);
}

.page-header__crumb-link {
  color: inherit;
  text-decoration: none;
}

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

/* --- Register: filters, area cards and bunch chips ------------------------ */

.site-register__filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.site-register__count {
  margin-left: var(--space-1);
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
}

.site-register__search {
  flex: 1 1 200px;
  max-width: 320px;
}

.area-card__group + .area-card__group {
  margin-top: var(--space-4);
}

.area-card__group-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.area-card__group--attention .area-card__group-title {
  color: var(--status-danger-600);
}

.area-card__group-count {
  font-weight: var(--font-normal);
  font-variant-numeric: tabular-nums;
}

.area-card__header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
}

.area-card__name {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
}

.area-card__path {
  margin: var(--space-1) 0 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.area-card__summary {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-muted);
}

.area-card__bunches {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 640px) {
  .area-card__bunches {
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  }
}

.bunch-chip {
  --chip-colour: var(--neutral-400);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 48px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--chip-colour);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
  color: var(--text);
  font: inherit;
  text-align: left;
  transition: border-color 400ms var(--ease), background-color 400ms var(--ease),
    box-shadow var(--duration-base) var(--ease);
}

.bunch-chip--present { --chip-colour: var(--status-success-600); }
.bunch-chip--out { --chip-colour: var(--status-info-500); }

.bunch-chip--late {
  --chip-colour: var(--status-warning-500);
  background: color-mix(in srgb, var(--status-warning-500) 8%, var(--bg-elev-1));
}

.bunch-chip--missing {
  --chip-colour: var(--status-danger-500);
  background: color-mix(in srgb, var(--status-danger-500) 9%, var(--bg-elev-1));
  border-color: var(--status-danger-500);
}

/* Chips become controls only once the script has wired them up */
.bunch-chip--interactive {
  cursor: pointer;
}

.bunch-chip--interactive:hover {
  border-color: var(--border-strong);
  border-left-color: var(--chip-colour);
  box-shadow: var(--shadow-sm);
}

.bunch-chip--interactive:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.bunch-chip__icon {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  background: var(--chip-colour);
  transition: background-color 400ms var(--ease);
  /* unseen: a dashed circle */
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-dasharray='3 4'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-dasharray='3 4'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* present: a ticked circle */
.bunch-chip--present .bunch-chip__icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.5l2.8 2.8L16 9.5'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8 12.5l2.8 2.8L16 9.5'/%3E%3C/svg%3E");
}

/* out: an arrow leaving a doorway */
.bunch-chip--out .bunch-chip__icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4'/%3E%3Cpath d='M16 17l5-5-5-5'/%3E%3Cpath d='M21 12H9'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4'/%3E%3Cpath d='M16 17l5-5-5-5'/%3E%3Cpath d='M21 12H9'/%3E%3C/svg%3E");
}

/* late: a clock */
.bunch-chip--late .bunch-chip__icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
}

/* missing: a warning triangle */
.bunch-chip--missing .bunch-chip__icon {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E");
}

.bunch-chip__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.bunch-chip__name {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--text-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bunch-chip__detail {
  font-size: var(--text-xs);
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bunch-chip__state {
  flex-shrink: 0;
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  color: var(--text-muted);
}

.bunch-chip--late .bunch-chip__state {
  color: var(--status-warning-700);
}

.bunch-chip--missing .bunch-chip__state {
  color: var(--status-danger-600);
}

@media (prefers-reduced-motion: no-preference) {
  .bunch-chip--changed {
    animation: bunch-chip-changed 1400ms var(--ease);
  }
}

@keyframes bunch-chip-changed {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--chip-colour) 55%, transparent); }
  100% { box-shadow: 0 0 0 10px transparent; }
}

/* --- Gateway tiles ------------------------------------------------------- */

.gateway-tile {
  min-width: 0;
  padding: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-elev-1);
  text-align: left;
  font: inherit;
  color: var(--text);
  transition: border-color var(--duration-base) var(--ease),
    box-shadow var(--duration-base) var(--ease);
}

.gateway-tile--offline {
  background: var(--bg-elev-2);
}

.gateway-tile--offline .gateway-tile__name {
  color: var(--text-muted);
}

.gateway-tile--interactive {
  cursor: pointer;
}

.gateway-tile--interactive:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-sm);
}

.gateway-tile--interactive:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

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

.gateway-tile__name {
  flex: 1;
  min-width: 0;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--text-strong);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gateway-tile__type {
  font-size: var(--text-xs);
  color: var(--text-subtle);
}

.gateway-tile__area {
  margin: var(--space-1) 0 var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.gateway-tile__figures {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.gateway-tile__figures strong {
  font-size: var(--text-base);
  color: var(--text-strong);
  font-variant-numeric: tabular-nums;
}

.gateway-tile__spark {
  height: 32px;
  margin-top: var(--space-2);
}

.gateway-tile__spark svg,
.heat-strip svg,
.presence-lanes svg {
  display: block;
  width: 100%;
}

.gateway-tile__spark svg {
  height: 32px;
}

/* --- Activity feed (also the detail panel's trail) ----------------------- */

.site-feed {
  display: grid;
  margin: 0;
  padding: 0 var(--space-3) 0 0;
  list-style: none;
  max-height: 420px;
  overflow-y: auto;
}

.site-feed--trail {
  max-height: none;
  padding-right: 0;
  overflow-y: visible;
}

/* The Activity tab has the page to itself */
.site-feed--full {
  max-height: 70vh;
}

/* --- Compact gateway list (dashboard overview, unplaced gateways) -------- */

.site-health {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-health__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 40px;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--text-sm);
}

.site-health__item:last-child {
  border-bottom: 0;
}

.site-health__item[data-gateway-key] {
  cursor: pointer;
}

.site-health__item[data-gateway-key]:hover .site-health__name {
  color: var(--link-hover);
}

.site-health__name {
  min-width: 0;
  color: var(--text-strong);
  font-weight: var(--font-medium);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.site-health__meta {
  margin-left: auto;
  flex-shrink: 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.site-feed__item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--text-sm);
}

.site-feed__item:last-child {
  border-bottom: 0;
}

.site-feed__item .state-dot {
  transform: translateY(-1px);
}

.site-feed__text {
  min-width: 0;
  color: var(--text);
  overflow-wrap: anywhere;
}

.site-feed__time {
  font-size: var(--text-xs);
  color: var(--text-muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: no-preference) {
  .site-feed__item--new {
    animation: site-feed-enter 500ms var(--ease);
  }
}

@keyframes site-feed-enter {
  from {
    opacity: 0;
    transform: translateY(-8px);
    background: color-mix(in srgb, var(--accent-primary-500) 12%, transparent);
  }
}

/* --- Heat strip and lanes ------------------------------------------------ */

.heat-strip {
  min-height: 56px;
}

.presence-lanes {
  position: relative;
  min-height: 120px;
}

.presence-lanes__area {
  fill: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.presence-lanes__name {
  fill: var(--text);
  font-size: var(--text-xs);
}

.presence-lanes__tick {
  fill: var(--text-muted);
  font-size: var(--text-xs);
}

.presence-lanes__lane {
  cursor: pointer;
}

/* --- Active NoWs --------------------------------------------------------- */

.site-nows {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-nows__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 44px;
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border-subtle);
}

.site-nows__item:last-child {
  border-bottom: 0;
}

.site-nows__link {
  display: flex;
  flex-direction: column;
  min-width: 0;
  color: inherit;
  text-decoration: none;
}

.site-nows__link:hover .site-nows__title {
  color: var(--link-hover);
  text-decoration: underline;
}

.site-nows__title {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--link);
}

.site-nows__meta,
.site-nows__window {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.site-nows__window {
  flex-shrink: 0;
}

/* --- Map ------------------------------------------------------------------ */

.site-map-card {
  padding: 0;
  overflow: hidden;
}

.site-map {
  position: relative;
  height: 60vh;
  min-height: 360px;
  max-height: 640px;
  background: var(--bg-elev-2);
  /* Keeps Leaflet's panes beneath the page's own layers */
  isolation: isolate;
}

.site-map__fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  margin: 0;
  padding: var(--space-4);
  text-align: center;
  color: var(--text-muted);
}

.site-map__marker {
  --marker-colour: var(--accent-primary-500);
  position: relative;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 3px solid var(--bg-elev-1);
  border-radius: 50%;
  background: var(--marker-colour);
  box-shadow: var(--shadow-md);
  color: var(--text-inverse);
  font-size: var(--text-sm);
  font-weight: var(--font-bold);
  cursor: pointer;
}

.site-map__marker--offline {
  --marker-colour: var(--neutral-500);
  opacity: 0.75;
}

.site-map__marker--van {
  --marker-colour: var(--neutral-950);
  border-radius: var(--radius-lg);
}

[data-theme="dark"] .site-map__marker--van {
  --marker-colour: var(--neutral-700);
}

.site-map__marker--van::before {
  content: "";
  width: 20px;
  height: 20px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 5h14v11H1z'/%3E%3Cpath d='M15 9h4l4 4v3h-8z'/%3E%3Ccircle cx='6' cy='18.5' r='2'/%3E%3Ccircle cx='18' cy='18.5' r='2'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 5h14v11H1z'/%3E%3Cpath d='M15 9h4l4 4v3h-8z'/%3E%3Ccircle cx='6' cy='18.5' r='2'/%3E%3Ccircle cx='18' cy='18.5' r='2'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Things placed at one position, not a sensor: a square pin */
.site-map__marker--pin {
  --marker-colour: var(--neutral-700);
  border-radius: var(--radius-md);
}

/* Several gateways the zoom cannot tell apart: a second rim peeking out
   behind says "more than one here", the badge says how many */
.site-map__marker--cluster {
  width: 40px;
  height: 40px;
  box-shadow: 5px -4px 0 -1px var(--marker-colour), 5px -4px 0 2px var(--bg-elev-1),
    var(--shadow-md);
}

/* The one gateway whose rings and bunches are showing */
.site-map__marker--selected {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--marker-colour) 45%, transparent),
    var(--shadow-md);
}

.site-map__badge {
  position: absolute;
  top: -9px;
  right: -9px;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  border: 2px solid var(--bg-elev-1);
  border-radius: 999px;
  background: var(--status-info-600);
  color: var(--text-inverse);
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  line-height: 16px;
  text-align: center;
}

.site-map__badge--gateways {
  background: var(--neutral-700);
}

/* A little gateway mast before the number, so it cannot be read as bunches */
.site-map__badge--gateways::before,
.site-map__badge--warning::before {
  content: "";
  display: inline-block;
  width: 9px;
  height: 9px;
  margin-right: 2px;
  vertical-align: -1px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M12 21V11'/%3E%3Ccircle cx='12' cy='8' r='2'/%3E%3Cpath d='M6 13a8 8 0 0 1 0-10'/%3E%3Cpath d='M18 13a8 8 0 0 0 0-10'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M12 21V11'/%3E%3Ccircle cx='12' cy='8' r='2'/%3E%3Cpath d='M6 13a8 8 0 0 1 0-10'/%3E%3Cpath d='M18 13a8 8 0 0 0 0-10'/%3E%3C/svg%3E") center / contain no-repeat;
}

.site-map__badge--warning {
  background: var(--status-warning-600);
}

/* A bunch the gateway can see, on the ring for its signal strength. The
   ring colours are the gateway page's: they say how near, not how well. */
.site-map__bunch {
  --bunch-colour: rgb(0, 156, 182);
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 2px solid var(--bunch-colour);
  border-radius: 50%;
  background: var(--bg-elev-1);
  box-shadow: var(--shadow-sm);
  color: var(--bunch-colour);
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  cursor: pointer;
}

.site-map__bunch--medium { --bunch-colour: rgb(217, 119, 6); }
.site-map__bunch--far { --bunch-colour: rgb(220, 38, 38); }

/* A ring of keys */
.site-map__bunch:not(.site-map__bunch--cluster)::before {
  content: "";
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='7.5' cy='15.5' r='4.5'/%3E%3Cpath d='M10.7 12.3L20 3'/%3E%3Cpath d='M16 7l3 3'/%3E%3Cpath d='M13.5 9.5l2 2'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='7.5' cy='15.5' r='4.5'/%3E%3Cpath d='M10.7 12.3L20 3'/%3E%3Cpath d='M16 7l3 3'/%3E%3Cpath d='M13.5 9.5l2 2'/%3E%3C/svg%3E") center / contain no-repeat;
}

.site-map__bunch--cluster {
  width: 28px;
  height: 28px;
}

/* A van carries its rings and bunches inside its own marker so that they
   glide with it. The rings sit behind the van and never take a click meant
   for a gateway underneath them. */
.site-map__van {
  position: relative;
  width: 36px;
  height: 36px;
}

.site-map__van-detail {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
}

.site-map__van-ring {
  position: absolute;
  top: 0;
  left: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.site-map__bunch--aboard {
  position: absolute;
  top: 0;
  left: 0;
}

.site-map__bunch:hover,
.site-map__bunch:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bunch-colour) 35%, transparent);
}

.site-map__marker:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--marker-colour) 40%, transparent);
}

.site-map__note {
  margin: 0;
  padding: var(--space-2) var(--space-4);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* What the map can't show yet: lock positions still being read */
.site-map__note--status {
  color: var(--text);
  background: var(--bg-elev-2);
}

.site-map__label {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-elev-1);
  box-shadow: var(--shadow-sm);
  color: var(--text);
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
}

.site-map__label::before {
  display: none;
}

/* Edge markers: a place with gateways or locks out of view, at the map's
   edge in its direction; selecting one goes there. Above the markers,
   beneath Leaflet's controls. */
.site-map__edges {
  position: absolute;
  inset: 0;
  z-index: 800;
  pointer-events: none;
}

.site-map__edge {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: 28px;
  padding: 2px var(--space-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-elev-1);
  box-shadow: var(--shadow-md);
  color: var(--text);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  white-space: nowrap;
  transform: translate(-50%, -50%);
  pointer-events: auto;
  cursor: pointer;
}

.site-map__edge:hover {
  border-color: var(--border-strong);
}

.site-map__edge:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

.site-map__edge .icon {
  color: var(--accent-primary-500);
}

/* The van glides between polls. Leaflet repositions every marker when the
   zoom changes, so the glide is suspended for the length of a zoom. */
@media (prefers-reduced-motion: no-preference) {
  .site-map:not(.site-map--zooming) .site-map__glide {
    transition: transform 9s linear;
  }
}

/* --- Presence simulation controls ---------------------------------------- */

.site-sim {
  padding: 0;
}

.site-sim .site-dash__note:first-child {
  margin-top: 0;
}

.site-sim__form {
  display: grid;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.site-sim__toggles {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
}

.site-sim__lose {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}

.site-sim__lose-title {
  margin: 0 0 var(--space-1);
  font-size: var(--text-base);
  font-weight: var(--font-semibold);
}

.site-sim__lose .site-dash__note {
  margin: 0;
}

.site-sim__lose .checkbox {
  margin-top: var(--space-2);
}

/* --- Detail panel content -------------------------------------------------- */

.site-detail__state {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-4);
}

.site-detail__facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  font-size: var(--text-sm);
}

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

.site-detail__facts dd {
  margin: 0;
  color: var(--text);
  overflow-wrap: anywhere;
}

.site-detail__bunches {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
