/* =========================================================================
   Car Tracking — application stylesheet (v2, "instrument cluster")

   Layer order:
     1. token bridge + base reset          (this file, top)
     2. app shell / navigation
     3. surfaces, data display, controls
     4. feature areas (trips, routes, dashboard, landing)
     5. motion & polish layer              (bottom of this file)

   Values come from design-system/tokens/tokens.css via [data-theme] on <html>;
   nothing below hardcodes a brand color.
   ========================================================================= */

:root {
  /* Design-system integration: these keep their old names (140 call sites
     below and across pages/components) but source their values from
     design-system/tokens/tokens.css, which is theme-reactive via [data-theme]
     on <html>. Nothing downstream needed to change for dark/light switching. */
  --bg: var(--color-bg-canvas);
  --panel: var(--color-bg-surface);
  --panel-2: var(--color-bg-surface-raised);
  --panel-3: var(--color-bg-surface-overlay);
  --inset: var(--color-bg-inset);
  --border: var(--color-border-default);
  --border-strong: var(--color-border-strong);
  --text: var(--color-fg-ink);
  --body: var(--color-fg-body);
  --muted: var(--color-fg-muted);
  --faint: var(--color-fg-faint);
  --accent: var(--color-accent);
  --accent-2: var(--color-accent-2);
  --danger: var(--color-danger);
  --warn: var(--color-warning);
  --ok: var(--color-success);

  --shadow: var(--shadow-2);
  --radius: var(--radius-surface);
  --radius-ctl: var(--radius-control);

  --icon-default: var(--text);
  --icon-accent: var(--accent);
  --icon-success: var(--color-success);
  --icon-warn: var(--warn);
  --icon-danger: var(--danger);
  --icon-device: var(--color-accent-2);

  /* Shared transition recipes — one vocabulary for every interactive element. */
  --t-fast: var(--motion-duration-fast) var(--motion-ease-standard);
  --t-med: var(--motion-duration-medium) var(--motion-ease-standard);
  --t-enter: var(--motion-duration-entry) var(--motion-ease-enter);

  /* Page gutter, fluid between mobile and desktop. */
  --gutter: clamp(1rem, 0.4rem + 2vw, 2.25rem);

  font-family: var(--font-family-body);
  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--body);
  min-height: 100%;
  font-size: 16px;
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Inter is variable across 100-900, so let it pick real optical sizes and
     never let the browser fake a weight the fallback stack does not have —
     a synthesised bold on system-ui reads as broken rather than as a fallback. */
  font-optical-sizing: auto;
  font-synthesis-weight: none;
}

/* Ambient light: two very soft brand-tinted pools anchored to the viewport, so
   scrolling a long page keeps the same atmospheric background instead of
   revealing a flat slab. Fixed + non-interactive + GPU-cheap (no blur filter). */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(900px 520px at 12% -8%, var(--color-accent-softer), transparent 70%),
    radial-gradient(760px 480px at 105% 8%, color-mix(in srgb, var(--color-accent-2) 7%, transparent), transparent 70%);
}

a { color: var(--accent); text-decoration: none; transition: color var(--t-fast); }
a:hover { color: var(--color-accent-hover); text-decoration: none; }

::selection { background: var(--color-accent-soft); color: var(--text); }

/* One focus ring for the whole app. Mouse users never see it; keyboard users
   always do, on every control, in the same shape. */
:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--radius-xs);
}

/* Scrollbars: thin, theme-aware, and quiet until hovered. */
* { scrollbar-width: thin; scrollbar-color: var(--color-border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--color-border-strong);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--muted); background-clip: content-box; }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-display-semibold);
  color: var(--text);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
}
h1 { font-size: clamp(24px, 1.25rem + 0.9vw, 31px); letter-spacing: var(--tracking-tighter); }
h2 { font-size: clamp(19px, 1.05rem + 0.5vw, 23px); letter-spacing: var(--tracking-tighter); }
h3 { font-size: var(--text-lg); }

/* Every metric/number reads in tabular monospace — the data-dense signature. */
.stat-row-value, .stat-value, .landing-mock-kpi strong, .table td.num,
.dash-car-metric-value, .metric-chip-value, .dash-gauge-value, .context-chip-num {
  font-family: var(--font-family-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tighter);
}

/* Micro-label: the small uppercase caption above a number or beside an icon. */
.stat-label, .metric-chip-label, .dash-car-metric-label,
.telemetry-signal-label, .context-chip-label {
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
}

.app-shell {
  display: grid;
  grid-template-columns: 264px minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100dvh;
}
.mobile-topbar { display: none; }
.nav-backdrop { display: none; }

.brand-logo {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-sm);
  object-fit: cover;
  flex-shrink: 0;
  box-shadow: 0 0 0 1px var(--border), var(--shadow-1);
}

.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  height: 100dvh;
  max-height: 100vh;
  max-height: 100dvh;
  overflow-x: hidden;
  overflow-y: auto;
  background:
    var(--gradient-surface),
    var(--panel);
  border-right: 1px solid var(--border);
  padding: 1.35rem 0.9rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 1.35rem;
  box-sizing: border-box;
  z-index: 40;
}
/* Brand-tinted hairline down the sidebar edge — the one place the signature
   gradient touches the chrome. */
.sidebar::after {
  content: "";
  position: absolute;
  inset: 0 0 0 auto;
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--color-border-accent) 22%, transparent 78%);
  opacity: 0.7;
  pointer-events: none;
}

.brand {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-display-bold);
  letter-spacing: var(--tracking-tight);
  font-size: var(--text-lg);
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.15rem 0.45rem 0;
  min-width: 0;
}

.nav-group-label {
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-medium);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  color: var(--faint);
  padding: 0 0.75rem;
  margin: 0 0 0.3rem;
}
.nav-group-label:not(:first-child) { margin-top: 1rem; }

.nav { display: flex; flex-direction: column; gap: 0.15rem; }
.nav a {
  position: relative;
  color: var(--body);
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-ctl);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-height: 42px;
  font-size: var(--text-base);
  font-weight: var(--font-weight-body-medium);
  transition: color var(--t-fast), background var(--t-fast), transform var(--t-fast);
}
/* The active rail: a gradient bar that grows out of the item's left edge.
   It lives on ::before so switching routes animates height, not layout. */
.nav a::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 3px;
  height: 0;
  border-radius: 0 3px 3px 0;
  background: var(--gradient-brand-vivid);
  transform: translateY(-50%);
  transition: height var(--motion-duration-medium) var(--motion-ease-spring-soft);
}
.nav a .icon { transition: transform var(--t-med), color var(--t-fast); }
.nav a:hover {
  background: var(--color-accent-softer);
  color: var(--text);
  text-decoration: none;
}
.nav a:hover .icon { transform: translateX(1px) scale(1.08); }
.nav a.active {
  background: var(--color-accent-soft);
  color: var(--text);
  font-weight: var(--font-weight-body-bold);
}
.nav a.active::before { height: 20px; }
.nav a.active .icon { color: var(--accent); }

.sidebar-foot .row { gap: 0.5rem; flex-wrap: nowrap; }
.sidebar-foot .btn.icon-btn {
  width: 32px;
  height: 32px;
  min-width: 32px;
}
.sidebar-foot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--border);
}

.connectivity-banner {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  padding: 0.7rem 0.95rem;
  border-radius: var(--radius-md);
  margin-bottom: 1rem;
  font-size: var(--text-base);
  line-height: 1.4;
  color: var(--text);
  border: 1px solid var(--border);
  background: var(--panel);
  box-shadow: var(--shadow-1);
  animation: banner-drop var(--motion-duration-entry) var(--motion-ease-spring-soft) both;
}
@keyframes banner-drop {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: none; }
}
.connectivity-banner.offline {
  border-color: color-mix(in srgb, var(--color-warning) 40%, transparent);
  background: var(--color-warning-subtle);
}
.connectivity-banner.update {
  border-color: var(--color-border-accent);
  background: var(--color-info-subtle);
}
.connectivity-banner .btn { margin-left: auto; }

.btn.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  padding: 0;
  min-width: 42px;
  border-radius: var(--radius-ctl);
}

.user-card {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.55rem;
  border-radius: var(--radius-ctl);
  min-width: 0;
  transition: background var(--t-fast);
}
.user-card:hover { background: var(--color-accent-softer); }
.user-avatar {
  width: 38px;
  height: 38px;
  border-radius: var(--radius-avatar);
  object-fit: cover;
  background: var(--panel-2);
  box-shadow: 0 0 0 1px var(--border), 0 0 0 3px var(--color-accent-softer);
  flex-shrink: 0;
}
.user-avatar-fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: var(--font-weight-body-bold);
  font-size: var(--text-base);
  color: var(--color-fg-on-accent);
  background: var(--gradient-brand-vivid);
}
.user-meta { min-width: 0; flex: 1; }
.user-name {
  font-weight: var(--font-weight-body-medium);
  color: var(--text);
  font-size: var(--text-base);
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-mail {
  font-size: var(--text-xs);
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.main {
  padding: clamp(1.1rem, 0.6rem + 1.4vw, 2rem) var(--gutter) 4rem;
  min-width: 0;
  min-height: 100vh;
  min-height: 100dvh;
}
/* Long-form pages stay readable on ultrawide displays instead of stretching
   a 6-column KPI strip across 2500px. */
.main > * { max-width: 1440px; margin-inline: auto; }

/* Route-level entry. `.page-view` is a permanent wrapper around <Outlet/>; its
   children are remounted by the router on every navigation, so the animation
   replays per route without the wrapper itself ever re-running. Successive
   top-level blocks cascade rather than all arriving at once.
   Fill mode is `backwards`, never `both`: a forwards fill keeps an opacity/
   transform animation in effect forever, which makes every block its own
   stacking context. Popovers (the trip Export menu, sticky bars) would then be
   trapped inside their block and painted under the blocks that follow it. The
   end keyframe equals the resting style, so dropping the forwards fill is
   visually identical. Same rule for the stagger/row entries further down. */
.page-view > * { animation: page-in var(--motion-duration-entry) var(--motion-ease-enter) backwards; }
.page-view > *:nth-child(2) { animation-delay: 50ms; }
.page-view > *:nth-child(3) { animation-delay: 100ms; }
.page-view > *:nth-child(4) { animation-delay: 150ms; }
.page-view > *:nth-child(n + 5) { animation-delay: 200ms; }
@keyframes page-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* Keyboard-first affordance: hidden until focused, then it parks over the
   content area as a real, clickable target. */
.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 100;
  transform: translateY(-160%);
  padding: 0.6rem 1rem;
  border-radius: var(--radius-ctl);
  background: var(--accent);
  color: var(--color-fg-on-accent);
  font-weight: var(--font-weight-body-bold);
  box-shadow: var(--shadow-3);
  transition: transform var(--motion-duration-medium) var(--motion-ease-spring-soft);
}
.skip-link:focus-visible { transform: translateY(0); color: var(--color-fg-on-accent); }

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 1.5rem;
  gap: 1rem 1.25rem;
  flex-wrap: wrap;
}
.topbar h1 { margin-bottom: 0.3rem; }
.topbar .muted { margin: 0; font-size: var(--text-base); max-width: 60ch; }

h1, h2, h3 { margin: 0 0 0.75rem; }
.muted { color: var(--muted); }
.grid { display: grid; gap: 1.1rem; }
.grid.stats { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.grid.two { grid-template-columns: 1.2fr 1fr; }

/* ---- Surfaces ------------------------------------------------------------
   One card recipe: tinted surface, hairline border, real (soft, wide) shadow,
   and a top-edge highlight that reads as a light source above the page. */
.card {
  position: relative;
  background: var(--gradient-surface), var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.15rem 1.25rem;
  box-shadow: var(--shadow-2), var(--shadow-inset-top);
  transition: border-color var(--t-med), box-shadow var(--t-med), transform var(--t-med);
}
.card + .card, .card + .grid, .grid + .card, section + section { margin-top: 1.25rem; }

/* Cards that are themselves a link target get the lift; static containers don't. */
a > .card:hover, .card.is-interactive:hover {
  transform: translateY(-2px);
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-3), var(--shadow-inset-top);
}

.stat-value {
  font-size: var(--text-3xl);
  font-weight: var(--font-weight-body-bold);
  color: var(--text);
  line-height: 1.1;
}

/* ---- KPI strip -----------------------------------------------------------
   Hairline-separated instrument row — no per-metric card wrapper. Replaces the
   equal-card grid anti-pattern for a screen's top-line numbers. */
.kpi-hairline-row {
  display: flex;
  flex-wrap: wrap;
  background: var(--gradient-surface), var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-2), var(--shadow-inset-top);
  overflow: hidden;
  margin-bottom: 1.5rem;
}
.kpi-hairline-item {
  position: relative;
  flex: 1 1 165px;
  padding: 1rem 1.25rem 1.05rem;
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  min-width: 0;
  transition: background var(--t-fast);
}
.kpi-hairline-item:first-child { border-left: none; }
.kpi-hairline-item:hover { background: var(--color-accent-softer); }
/* Accent underline that wipes in on hover — cheap, GPU-only, and it makes the
   strip feel like a control surface rather than static text. */
.kpi-hairline-item::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--gradient-brand-vivid);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--motion-duration-medium) var(--motion-ease-enter);
}
.kpi-hairline-item:hover::after { transform: scaleX(1); }
.kpi-hairline-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.kpi-hairline-head .icon { opacity: 0.75; transition: opacity var(--t-fast), transform var(--t-fast); }
.kpi-hairline-item:hover .kpi-hairline-head .icon { opacity: 1; transform: scale(1.1); }

/* ---- Loading -------------------------------------------------------------
   Skeletons mirror the shape of the content they stand in for; the shimmer is
   first-load only and disappears entirely under prefers-reduced-motion. */
.skeleton-block {
  position: relative;
  overflow: hidden;
  background: var(--panel-2);
  border-radius: var(--radius-xs);
}
.skeleton-block::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--color-border-strong), transparent);
  animation: skeleton-shimmer var(--motion-duration-ambient-shimmer, 1500ms) linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-block::after { animation: none; }
}
@keyframes skeleton-shimmer {
  to { transform: translateX(100%); }
}

/* Inline spinner, used by .btn.is-loading and anywhere a small async wait
   needs a marker. */
.spinner {
  width: 1em;
  height: 1em;
  border-radius: 50%;
  border: 2px solid currentColor;
  border-right-color: transparent;
  opacity: 0.85;
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---- Buttons -------------------------------------------------------------
   Interaction model, identical for every variant:
     hover  → 1px lift + elevation + a sheen that sweeps once across the face
     active → press back down (fast, so it feels mechanical)
     focus  → the app-wide ring, never an outline jump
     :disabled / .is-loading → no lift, no sheen, no pointer */
.btn {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  appearance: none;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  border-radius: var(--radius-ctl);
  padding: 0.58rem 1rem;
  min-height: 40px;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--text-base);
  font-weight: var(--font-weight-body-medium);
  letter-spacing: var(--tracking-tight);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  white-space: nowrap;
  box-shadow: var(--shadow-1);
  transition:
    transform var(--t-fast),
    box-shadow var(--t-med),
    background-color var(--t-fast),
    border-color var(--t-fast),
    color var(--t-fast),
    opacity var(--t-fast);
}
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--gradient-sheen);
  transform: translateX(-130%);
  opacity: 0;
  pointer-events: none;
}
.btn:hover:not(:disabled):not(.is-loading) {
  transform: translateY(-1px);
  border-color: var(--border-strong);
  background: var(--panel-3);
  box-shadow: var(--shadow-2);
}
.btn:hover:not(:disabled):not(.is-loading)::after {
  opacity: 0.7;
  transform: translateX(130%);
  transition: transform var(--motion-duration-slow) var(--motion-ease-standard), opacity var(--t-fast);
}
.btn:active:not(:disabled):not(.is-loading) {
  transform: translateY(0) scale(0.985);
  box-shadow: var(--shadow-1);
  transition-duration: 60ms;
}
.btn:focus-visible { box-shadow: var(--ring), var(--shadow-2); }
.btn .icon { transition: transform var(--t-med); }
.btn:hover:not(:disabled) .icon { transform: translateX(1px); }

.btn.primary {
  background-color: var(--accent);
  background-image: linear-gradient(160deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0) 60%);
  border-color: transparent;
  color: var(--color-fg-on-accent);
  font-weight: var(--font-weight-body-bold);
  box-shadow: var(--shadow-accent-glow);
}
.btn.primary:hover:not(:disabled):not(.is-loading) {
  background-color: var(--color-accent-hover);
  border-color: transparent;
  box-shadow: var(--shadow-accent-glow), var(--shadow-2);
}
.btn.primary:active:not(:disabled) { background-color: var(--color-accent-active); }

.btn.secondary,
.btn.btn-secondary {
  background: var(--color-accent-soft);
  border-color: var(--color-border-accent);
  color: var(--accent);
  font-weight: var(--font-weight-body-bold);
}
.btn.secondary:hover:not(:disabled),
.btn.btn-secondary:hover:not(:disabled) {
  background: var(--color-accent-soft);
  border-color: var(--accent);
  color: var(--color-accent-hover);
}

.btn.btn-ghost,
.btn.ghost {
  background: transparent;
  border-color: transparent;
  color: var(--muted);
  box-shadow: none;
}
.btn.btn-ghost:hover:not(:disabled),
.btn.ghost:hover:not(:disabled) {
  color: var(--text);
  background: var(--color-accent-softer);
  border-color: var(--border);
}

.btn.danger {
  background: transparent;
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
  color: var(--danger);
}
.btn.danger:hover:not(:disabled) {
  background: var(--color-danger-subtle);
  border-color: var(--danger);
  color: var(--danger);
}

.btn.btn-sm { padding: 0.32rem 0.7rem; min-height: 32px; font-size: var(--text-sm); gap: 0.35rem; }
.btn.btn-lg { padding: 0.75rem 1.4rem; min-height: 48px; font-size: var(--text-lg); }
.btn.btn-block { width: 100%; }

.btn:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }

/* Loading: the label stays (no layout jump), a spinner takes over the leading
   slot, and the whole control stops responding to hover. */
.btn.is-loading { cursor: progress; color: transparent; }
.btn.is-loading .icon, .btn.is-loading > * { visibility: hidden; }
.btn.is-loading::before {
  content: "";
  position: absolute;
  width: 1.05em;
  height: 1.05em;
  border-radius: 50%;
  border: 2px solid var(--text);
  border-right-color: transparent;
  animation: spin 700ms linear infinite;
}
.btn.primary.is-loading::before { border-color: var(--color-fg-on-accent); border-right-color: transparent; }

/* Toolbar / segmented surfaces ------------------------------------------- */
.traffic-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.85rem 1rem;
  margin: 0.9rem 0 1rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--gradient-brand-soft), var(--panel);
  box-shadow: var(--shadow-1);
}
.traffic-run-btn {
  min-height: 40px;
  padding: 0.5rem 1.15rem;
  border-radius: var(--radius-chip);
  font-weight: var(--font-weight-body-bold);
  font-size: var(--text-base);
}
.traffic-chip-row { margin: 0 0 0.9rem; }
.traffic-err-banner { margin: 0 0 0.8rem; }

/* ---- Forms ---------------------------------------------------------------
   Inputs sit *inset* (darker than their card in dark mode, tinted in light),
   so a form reads as a set of wells rather than floating boxes. */
input, select, textarea {
  width: 100%;
  background: var(--inset);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-ctl);
  padding: 0.62rem 0.8rem;
  font-family: inherit;
  font-size: var(--text-base);
  min-height: 42px;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
input::placeholder, textarea::placeholder { color: var(--faint); }
input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) {
  border-color: var(--border-strong);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  background: var(--panel);
  border-color: var(--color-border-accent);
  box-shadow: var(--ring);
}
input:disabled, select:disabled, textarea:disabled { opacity: 0.55; cursor: not-allowed; }
textarea { min-height: 96px; resize: vertical; line-height: var(--leading-normal); }
select {
  appearance: none;
  padding-right: 2.2rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 17px) calc(50% + 1px), calc(100% - 12px) calc(50% + 1px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
input[type="checkbox"], input[type="radio"] {
  width: 18px;
  height: 18px;
  min-height: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-medium);
  color: var(--body);
  margin-bottom: 0.35rem;
}
.form-row { margin-bottom: 1rem; }
.field-hint { font-size: var(--text-xs); color: var(--muted); margin-top: 0.35rem; }

/* ---- Tables --------------------------------------------------------------
   Header is a sticky micro-label rail; rows highlight on hover with a left
   accent edge so the eye can track across wide rows. */
.table { width: 100%; border-collapse: collapse; }
.table th, .table td {
  text-align: left;
  padding: 0.75rem 0.6rem;
  border-bottom: 1px solid var(--border);
}
.table th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--panel);
  color: var(--muted);
  font-weight: var(--font-weight-body-medium);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
}
.table tbody tr { transition: background var(--t-fast), box-shadow var(--t-fast); }
.table tbody tr:hover { background: var(--color-accent-softer); }
.table tbody tr:hover td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
.table tbody tr:last-child td { border-bottom: none; }
.table td { color: var(--body); font-size: var(--text-base); }
.table td.num { color: var(--text); }

/* Mobile: rows become single-line summary cards instead of a table
   squeezed sideways (a real "responsive density strategy" call-out from
   the design system's own foundations docs). Scoped to .dash-trips-table
   rather than every .table — routes/settings/cars tables aren't verified
   against this pattern yet. */
@media (max-width: 640px) {
  .dash-trips-table thead {
    display: none;
  }
  .dash-trips-table, .dash-trips-table tbody, .dash-trips-table tr {
    display: block;
    width: 100%;
  }
  .dash-trips-table tr {
    border: 1px solid var(--border);
    border-radius: var(--radius-chip);
    padding: 0.7rem 0.8rem;
    margin-bottom: 0.6rem;
  }
  .dash-trips-table tr:last-child {
    margin-bottom: 0;
  }
  .dash-trips-table td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.2rem 0;
    border-bottom: none;
  }
  .dash-trips-table td[data-label]:not([data-label=""])::before {
    content: attr(data-label);
    font-size: var(--text-2xs);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    color: var(--muted);
    flex-shrink: 0;
  }
  .dash-trips-table td:first-child {
    font-weight: var(--font-weight-body-bold);
    font-size: var(--text-lg);
    padding-bottom: 0.4rem;
    margin-bottom: 0.3rem;
    border-bottom: 1px solid var(--border);
  }
  .dash-trips-table td:last-child {
    justify-content: center;
    border-top: 1px solid var(--border);
    margin-top: 0.4rem;
    padding-top: 0.5rem;
  }
}
/* ---- Badges & status chips ---------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-chip);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  border: 1px solid transparent;
  white-space: nowrap;
}
.badge.owner { color: var(--color-success); background: var(--color-success-subtle); border-color: color-mix(in srgb, var(--color-success) 26%, transparent); }
.badge.editor { color: var(--color-info); background: var(--color-info-subtle); border-color: var(--color-border-accent); }
/* Default car: the star next to its name in the cars list. */
.car-name-cell { display: inline-flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.car-default-toggle { color: var(--color-fg-muted); }
.car-default-toggle.is-default { color: var(--color-warning); }
.badge.default-car-badge { color: var(--color-warning); background: var(--color-warning-subtle); border-color: color-mix(in srgb, var(--color-warning) 26%, transparent); }
.badge.viewer { color: var(--color-warning); background: var(--color-warning-subtle); border-color: color-mix(in srgb, var(--color-warning) 26%, transparent); }

/* ---- Map & chart frames -------------------------------------------------- */
.map {
  width: 100%;
  height: 360px;
  border-radius: var(--radius-md);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--inset);
  box-shadow: var(--shadow-1);
}
.chart { width: 100%; height: 280px; }
.chart.chart-tall { height: 320px; }

/* —— Trips list filters —— */
.trips-filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  margin-bottom: 1.25rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--gradient-surface), var(--panel);
  box-shadow: var(--shadow-1);
}
.trips-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
/* Filter chip: the pressed state is carried by fill + a colored hairline, not
   by weight alone, so the active filter survives a squint test. */
.trips-filter-chip {
  position: relative;
  appearance: none;
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--muted);
  border-radius: var(--radius-chip);
  padding: 0.36rem 0.85rem;
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-medium);
  line-height: 1.2;
  transition: color var(--t-fast), background var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}
.trips-filter-chip:hover {
  color: var(--text);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}
.trips-filter-chip:active { transform: translateY(0) scale(0.97); transition-duration: 60ms; }
.trips-filter-chip.is-active {
  color: var(--color-fg-on-accent);
  background: var(--accent);
  border-color: transparent;
  font-weight: var(--font-weight-body-bold);
  box-shadow: var(--shadow-accent-glow);
}
.trips-filter-meta {
  color: var(--muted);
  font-size: var(--text-sm);
}
.trips-filter-tools {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-left: auto;
  flex-wrap: wrap;
}
/* Overrides the global full-width form control: in a toolbar the car filter is
   a chip-shaped control sized to its content, not a form field. */
.trips-car-select {
  width: auto;
  min-width: 11rem;
  min-height: 38px;
  padding-block: 0.35rem;
  border-radius: var(--radius-chip);
  font-size: var(--text-md);
}
.trips-search {
  position: relative;
  display: flex;
  align-items: center;
}
.trips-search-input {
  width: clamp(180px, 26vw, 280px);
  min-height: 38px;
  padding: 0.4rem 0.8rem 0.4rem 2.1rem;
  border-radius: var(--radius-chip);
  background: var(--inset);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: var(--text-md);
  transition: width var(--t-med), border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.trips-search .icon {
  position: absolute;
  left: 0.7rem;
  color: var(--faint);
  pointer-events: none;
  transition: color var(--t-fast);
}
.trips-search-input::placeholder { color: var(--faint); }
.trips-search-input:focus {
  outline: none;
  background: var(--panel);
  border-color: var(--color-border-accent);
  box-shadow: var(--ring);
  width: clamp(220px, 30vw, 340px);
}
.trips-search:focus-within .icon { color: var(--accent); }

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

/* —— Trips list cards —— */
.trip-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(360px, 1fr));
  gap: 1.1rem;
}
.trip-grid > a {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: var(--radius);
}
.trip-grid > a:hover { text-decoration: none; }
.trip-grid > a:focus-visible { box-shadow: var(--ring); }

.trip-card {
  position: relative;
  overflow: hidden;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  background: var(--gradient-surface), var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.05rem 1.15rem 0.9rem;
  box-shadow: var(--shadow-2), var(--shadow-inset-top);
  transition: transform var(--t-med), border-color var(--t-med), box-shadow var(--t-med);
}
/* Gradient hairline along the top edge, revealed on hover — the card's
   "this is a link" tell, without adding chrome at rest. */
.trip-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--gradient-brand-vivid);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--motion-duration-medium) var(--motion-ease-enter);
}
.trip-grid > a:hover .trip-card,
.trip-grid > a:focus-visible .trip-card {
  transform: translateY(-3px);
  border-color: var(--color-border-accent);
  box-shadow: var(--shadow-3), var(--shadow-inset-top);
}
.trip-grid > a:hover .trip-card::before,
.trip-grid > a:focus-visible .trip-card::before { transform: scaleX(1); }

.trip-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}
.trip-card-title {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-display-semibold);
  font-size: var(--text-lg);
  color: var(--text);
  line-height: var(--leading-snug);
}
.trip-card-sub { font-size: var(--text-sm); margin-top: 0.25rem; color: var(--muted); }

.trip-card-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  gap: 0.5rem;
}
/* Metric well: inset, so a row of them reads as an instrument block. */
.metric-chip {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.55rem 0.65rem;
  border-radius: var(--radius-sm);
  background: var(--inset);
  border: 1px solid var(--border);
  min-width: 0;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.trip-card:hover .metric-chip { border-color: var(--border-strong); }
.metric-chip-label {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}
.metric-chip-value {
  font-size: var(--text-base);
  font-weight: var(--font-weight-mono-medium);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.trip-card-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: auto;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}
.trip-card-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--accent);
  font-size: var(--text-md);
  font-weight: var(--font-weight-body-medium);
}
.trip-card-actions a { color: var(--accent); }
.trip-card-actions .icon { transition: transform var(--t-med); }
.trip-grid > a:hover .trip-card-actions .icon { transform: translateX(3px); }
.trip-card > a { color: var(--accent); }

.trip-detail-actions {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  align-items: center;
}

/* ---- Pills ---------------------------------------------------------------
   Status atoms. Every pill carries a dot so state is readable without relying
   on color alone (WCAG 1.4.1). */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.22rem 0.65rem 0.22rem 0.55rem;
  border-radius: var(--radius-chip);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-body-bold);
  letter-spacing: var(--tracking-wide);
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--muted);
  white-space: nowrap;
}
.pill::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}
.pill-ok, .pill.ok {
  color: var(--color-success);
  background: var(--color-success-subtle);
  border-color: color-mix(in srgb, var(--color-success) 26%, transparent);
}
.pill-warn, .pill.warn {
  color: var(--color-warning);
  background: var(--color-warning-subtle);
  border-color: color-mix(in srgb, var(--color-warning) 26%, transparent);
}
.pill-danger, .pill.danger {
  color: var(--color-danger);
  background: var(--color-danger-subtle);
  border-color: color-mix(in srgb, var(--color-danger) 26%, transparent);
}
/* Live: the dot breathes. It is the only ambient animation in the data layer,
   so "in progress" is unmistakable. */
.pill-live {
  color: var(--color-info);
  background: var(--color-info-subtle);
  border-color: var(--color-border-accent);
}
.pill-live::before { animation: pill-pulse var(--motion-duration-ambient-pulse) var(--motion-ease-ambient) infinite; }
@keyframes pill-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-info) 55%, transparent); opacity: 1; }
  50% { box-shadow: 0 0 0 5px transparent; opacity: 0.55; }
}
.routes-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
}

/* —— Trip detail analytics ——
   Grouped stat panels. Eight metrics carry two borders instead of eight, and
   every row is one line tall: hints live in a tooltip, so no panel stretches to
   match a sibling's explanation the way the old equal-card grid did. */
.stat-panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 0.85rem;
  margin-bottom: 1.25rem;
}
/* These panels are grid cells, not stacked page sections — the global
   `section + section` stack rule would offset every panel but the first. */
.stat-panel-grid > section + section { margin-top: 0; }
.stat-panel {
  position: relative;
  overflow: hidden;
  /* Rows reflow against the panel's own width, not the viewport's — the app
     shell's sidebar makes viewport breakpoints lie about how wide this is. */
  container-type: inline-size;
  background: var(--gradient-surface), var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.85rem 1.1rem 0.95rem;
  box-shadow: var(--shadow-1), var(--shadow-inset-top);
  transition: border-color var(--t-med), box-shadow var(--t-med), transform var(--t-med);
}
.stat-panel:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-2), var(--shadow-inset-top);
}
/* Corner glow — reads as a light catching the panel's edge. */
.stat-panel::after {
  content: "";
  position: absolute;
  top: -40%;
  right: -30%;
  width: 130px;
  height: 130px;
  border-radius: 50%;
  background: var(--color-accent-soft);
  filter: blur(28px);
  opacity: 0.6;
  pointer-events: none;
  transition: opacity var(--t-med);
}
.stat-panel:hover::after { opacity: 1; }
/* A group caption, not a heading in the reading hierarchy — so it drops out of
   the h2 type ramp down to micro-label size. */
.stat-panel-title {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.2rem;
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-medium);
  letter-spacing: var(--tracking-wide);
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--muted);
}
.stat-rows {
  position: relative;
  margin: 0;
}
/* Wide enough for two label/value pairs side by side: halves the panel's height
   and closes the gap a full-width row would otherwise leave mid-line. */
@container (min-width: 420px) {
  .stat-rows {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  /* A rule rather than a gap: without it the left row's value and the right
     row's label sit adjacent and read as one pair. */
  .stat-rows > .stat-row:nth-child(odd) { padding-right: 1.25rem; }
  .stat-rows > .stat-row:nth-child(even) {
    padding-left: 1.25rem;
    border-left: 1px solid var(--border);
  }
}
.stat-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.42rem 0;
  border-top: 1px solid var(--border);
}
.stat-row-label {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin: 0;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-body-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
}
.stat-row-value {
  margin: 0;
  font-size: var(--text-lg);
  font-weight: var(--font-weight-mono-medium);
  color: var(--text);
  line-height: 1.2;
  white-space: nowrap;
}
/* Hint marker: the "why is this number what it is" note, on hover/focus. */
.stat-row-info {
  display: inline-flex;
  color: var(--muted);
  cursor: help;
  opacity: 0.6;
  transition: opacity var(--t-fast), color var(--t-fast);
}
.stat-row-info:hover,
.stat-row-info:focus-visible {
  opacity: 1;
  color: var(--text);
}
.stat-row-info {
  position: relative;
}
/* Hint text for the info marker: visible on hover and on keyboard focus, and
   referenced by aria-describedby so assistive tech reads it without either. */
.stat-row-tip {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 0.4rem);
  transform: translateX(-50%);
  z-index: 5;
  width: max-content;
  max-width: 16rem;
  padding: 0.4rem 0.55rem;
  border-radius: var(--radius-chip);
  background: var(--color-bg-surface-overlay);
  color: var(--text);
  box-shadow: var(--shadow-overlay);
  font-size: var(--text-xs);
  font-weight: normal;
  line-height: 1.35;
  text-transform: none;
  letter-spacing: normal;
  white-space: normal;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--t-fast);
}
.stat-row-info:hover .stat-row-tip,
.stat-row-info:focus-visible .stat-row-tip {
  visibility: visible;
  opacity: 1;
}

.route-card {
  margin-bottom: 1.25rem;
}
.route-card .map {
  height: min(48vh, 460px);
  min-height: 300px;
}
.map-legend {
  margin: 0.65rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.map-speed-legend {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  max-width: 28rem;
}
.map-speed-label {
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  min-width: 4.25rem;
  white-space: nowrap;
}
.map-speed-label#trip-speed-max {
  text-align: right;
}
.map-speed-bar {
  flex: 1;
  height: 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  /* Viridis, matching the route ramp in components/map.rs (colour-blind safe). */
  background: linear-gradient(
    90deg,
    #440154 0%,
    #3b528b 25%,
    #21918c 50%,
    #5ec962 75%,
    #fde725 100%
  );
  box-shadow: inset 0 0 0 1px var(--color-border-strong);
}
.map-traffic-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.85rem;
}
.map-traffic-legend[hidden] {
  display: none;
}
.map-traffic-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--text-xs);
  color: var(--muted);
}
.map-traffic-swatch {
  width: 1rem;
  height: 0.55rem;
  border-radius: 999px;
  flex-shrink: 0;
  box-shadow: inset 0 0 0 1px var(--color-border-strong);
}
.map-speed-bar.is-empty {
  opacity: 0.35;
  filter: grayscale(0.6);
}
.map-legend-note {
  margin: 0;
  font-size: var(--text-sm);
  flex: 1;
}
.map-legend-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}
/* MapLibre stop dwell popup (injected on body). */
.maplibregl-popup.trip-stop-popup .maplibregl-popup-content,
.maplibregl-popup.trip-route-popup .maplibregl-popup-content {
  background: var(--color-bg-surface-overlay);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.45rem 0.65rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  font-size: var(--text-sm);
}
.maplibregl-popup.trip-stop-popup .maplibregl-popup-tip,
.maplibregl-popup.trip-route-popup .maplibregl-popup-tip {
  border-top-color: var(--color-bg-surface-overlay);
}
.trip-stop-popup-inner {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 4.5rem;
}
.trip-stop-popup-inner strong {
  color: var(--warn);
  font-weight: var(--font-weight-body-semibold);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}
.trip-stop-popup-inner span {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.trip-route-popup-inner {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 8.5rem;
}
.trip-route-popup-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.trip-route-popup-row span {
  color: var(--muted);
  font-size: var(--text-xs);
}
.trip-route-popup-row strong {
  color: var(--text);
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-weight-body-semibold);
}
.telemetry-block {
  display: flex;
  flex-direction: column;
  gap: 0.95rem;
}
.telemetry-block-head {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.telemetry-block-head .section-title { margin-bottom: 0.1rem; }
.telemetry-dashboard {
  display: flex;
  flex-direction: column;
  gap: 0.95rem;
}

/* Signal strip — the live instrument readout above the charts. */
.telemetry-signal-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  gap: 0.55rem;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}
.telemetry-signal-chip {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
  padding: 0.6rem 0.75rem 0.65rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--gradient-surface), var(--panel-2);
  box-shadow: var(--shadow-inset-top);
  transition: border-color var(--t-fast), transform var(--t-fast);
}
.telemetry-signal-chip:hover {
  border-color: var(--color-border-accent);
  transform: translateY(-1px);
}
.telemetry-signal-value {
  font-family: var(--font-family-mono);
  font-size: var(--text-lg);
  font-weight: var(--font-weight-mono-medium);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  letter-spacing: var(--tracking-tighter);
  line-height: 1.2;
}

.telemetry-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 0.9rem;
}
.telemetry-toolbar-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
}
.telemetry-toolbar-note {
  margin: -0.15rem 0 0;
  font-size: var(--text-xs);
  color: var(--muted);
}

/* Scrollable category rail + segmented control share one "track holds pills"
   recipe, so the trip page reads as a single control surface. */
.telemetry-cat-scroll,
.seg-control {
  display: flex;
  gap: 0.15rem;
  padding: 0.2rem;
  border-radius: var(--radius-chip);
  border: 1px solid var(--border);
  background: var(--inset);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12);
}
.telemetry-cat-scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  max-width: 100%;
  scrollbar-width: none;
}
.telemetry-cat-scroll::-webkit-scrollbar { display: none; }
.seg-control { display: inline-flex; }

.telemetry-cat-btn,
.seg-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-medium);
  padding: 0.4rem 0.85rem;
  border-radius: var(--radius-chip);
  cursor: pointer;
  white-space: nowrap;
  flex: 0 0 auto;
  transition: color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
.telemetry-cat-btn:hover,
.seg-btn:hover { color: var(--text); background: var(--color-accent-softer); }
.telemetry-cat-btn.is-active,
.seg-btn.is-active {
  color: var(--text);
  background: var(--panel-3);
  box-shadow: var(--shadow-1), inset 0 0 0 1px var(--color-border-accent);
  font-weight: var(--font-weight-body-bold);
}
.seg-btn { font-size: var(--text-xs); padding: 0.34rem 0.75rem; }

/* Keep head utility used by Route card */
.telemetry-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}
.telemetry-section-head .section-title { margin-bottom: 0; }
.section-index,
.section-meta {
  font-family: var(--font-family-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  color: var(--muted);
}
.telemetry-panels {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem;
}
.telemetry-panel {
  padding: 0.7rem 0.8rem 0.5rem;
  overflow: hidden;
  min-width: 0;
  border-radius: var(--radius-md);
}
.telemetry-panel-primary { grid-column: 1 / -1; }
.telemetry-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.15rem;
  min-height: 1.5rem;
}
.telemetry-panel-title {
  margin: 0;
  font-size: var(--text-md);
  font-weight: var(--font-weight-body-bold);
  letter-spacing: var(--tracking-tight);
  color: var(--text);
}

/* Inline help: a quiet "?" that expands an explanation in place. */
.telemetry-help {
  position: relative;
  flex: 0 0 auto;
  font-size: var(--text-xs);
  color: var(--muted);
}
.telemetry-help summary {
  cursor: pointer;
  list-style: none;
  color: var(--accent);
  font-weight: var(--font-weight-body-bold);
  user-select: none;
  width: 1.6rem;
  height: 1.6rem;
  display: inline-grid;
  place-items: center;
  border-radius: var(--radius-avatar);
  border: 1px solid var(--color-border-accent);
  background: var(--color-accent-soft);
  line-height: 1;
  transition: background var(--t-fast), transform var(--t-fast), color var(--t-fast);
}
.telemetry-help summary::-webkit-details-marker { display: none; }
.telemetry-help summary:hover { background: var(--accent); color: var(--color-fg-on-accent); transform: scale(1.06); }
.telemetry-help[open] summary { background: var(--accent); color: var(--color-fg-on-accent); }
.telemetry-help p {
  margin: 0.5rem 0 0.2rem;
  padding: 0.65rem 0.75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--panel-2);
  line-height: 1.5;
  color: var(--body);
  max-width: 36rem;
  animation: page-in var(--motion-duration-medium) var(--motion-ease-enter) backwards;
}
@media (max-width: 860px) {
  .telemetry-panels { grid-template-columns: 1fr; }
  .telemetry-signal-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 420px) {
  .telemetry-signal-strip { grid-template-columns: 1fr 1fr; }
}

.info-banner {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.8rem 0.95rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-accent);
  background: var(--color-info-subtle);
  color: var(--text);
  font-size: var(--text-base);
  line-height: 1.45;
}

/* ---- Auth & error shells -------------------------------------------------
   Full-bleed centered shells with a soft brand aurora. The card floats on the
   overlay elevation so it reads as the only thing on screen that matters. */
.login-wrap, .not-found-wrap {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
  overflow: hidden;
  background: var(--bg);
}
.login-wrap::before, .not-found-wrap::before {
  content: "";
  position: absolute;
  inset: -20%;
  pointer-events: none;
  background:
    radial-gradient(620px 460px at 18% 22%, var(--color-accent-soft), transparent 62%),
    radial-gradient(560px 420px at 84% 12%, color-mix(in srgb, var(--color-accent-2) 12%, transparent), transparent 60%),
    radial-gradient(520px 400px at 62% 96%, color-mix(in srgb, var(--color-success) 8%, transparent), transparent 58%);
  animation: aurora-drift 22s var(--motion-ease-ambient) infinite alternate;
}
@keyframes aurora-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(2.5%, -2%, 0) scale(1.08); }
}
@media (prefers-reduced-motion: reduce) {
  .login-wrap::before, .not-found-wrap::before { animation: none; }
}
.login-card, .not-found-card {
  position: relative;
  box-shadow: var(--shadow-4), var(--shadow-inset-top);
  animation: card-rise var(--motion-duration-slow) var(--motion-ease-spring-soft) both;
}
@keyframes card-rise {
  from { opacity: 0; transform: translateY(18px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
.login-card { width: min(430px, 100%); padding: 1.75rem 1.65rem; }
.login-card .section-title { justify-content: center; }

.not-found-card {
  width: min(520px, 100%);
  text-align: center;
  gap: 0.9rem;
  padding: 2rem 1.75rem;
}
.not-found-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0 0.15rem;
}
.not-found-code {
  font-family: var(--font-family-display);
  font-size: clamp(52px, 12vw, 80px);
  font-weight: var(--font-weight-display-bold);
  letter-spacing: var(--tracking-wide);
  line-height: 1;
  background: var(--gradient-brand-vivid);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.not-found-title { margin: 0; font-size: clamp(20px, 3.5vw, 26px); line-height: 1.3; }
.not-found-lead { margin: 0; font-size: var(--text-base); line-height: 1.5; color: var(--muted); }
.not-found-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  margin: 0 auto;
  font-size: var(--text-md);
}
.not-found-actions {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  margin-top: 0.5rem;
}
.not-found-actions .btn.primary { justify-content: center; }
.not-found-secondary {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
}
.not-found-hint { margin: 0.35rem 0 0; font-size: var(--text-xs); line-height: 1.45; color: var(--faint); }

.qr-box {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1rem;
  background: white;
  border-radius: 12px;
  min-height: 280px;
}
.qr-box canvas {
  width: min(100%, 320px) !important;
  height: auto !important;
  image-rendering: pixelated;
}
/* ---- Inline feedback ----------------------------------------------------- */
.error, .success {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.75rem 0.95rem;
  border-radius: var(--radius-md);
  border: 1px solid;
  font-size: var(--text-base);
  line-height: 1.45;
  animation: banner-drop var(--motion-duration-medium) var(--motion-ease-spring-soft) both;
}
.error {
  color: var(--color-danger);
  background: var(--color-danger-subtle);
  border-color: color-mix(in srgb, var(--color-danger) 34%, transparent);
}
.success {
  color: var(--color-success);
  background: var(--color-success-subtle);
  border-color: color-mix(in srgb, var(--color-success) 34%, transparent);
}

.stack { display: flex; flex-direction: column; gap: 0.75rem; }
.row { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }
.row.end { justify-content: flex-end; }
.row.between { justify-content: space-between; }

.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  flex-shrink: 0;
  color: var(--icon-default);
  vertical-align: middle;
}
.icon.sm { font-size: 16px; }
.icon.md { font-size: 20px; }
.icon.lg { font-size: 28px; }
.icon.xl { font-size: 40px; }
.icon.accent { color: var(--icon-accent); }
.icon.tone-success { color: var(--icon-success); }
.icon.warn { color: var(--icon-warn); }
.icon.danger { color: var(--icon-danger); }
.icon.device { color: var(--icon-device); }
/* Icons in buttons follow the button's own text color (e.g. white on .btn.primary)
   unless a semantic tone class (.accent/.tone-success/etc.) is explicitly set. */
.btn .icon:not(.accent, .tone-success, .warn, .danger, .device) {
  color: inherit;
}
/* Phosphor duotone secondary layer */
.icon.ph-duotone::before { opacity: 0.28; }

.icon-label {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.stat-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
}

/* ---- Empty states --------------------------------------------------------
   The icon sits in a haloed disc so an empty screen still has a focal point,
   and the copy gets a headline + a next action rather than one gray sentence. */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.6rem;
  padding: 3rem 1.25rem;
  color: var(--muted);
}
.empty-state .icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  margin-bottom: 0.35rem;
  border-radius: var(--radius-avatar);
  background: var(--gradient-brand-soft);
  box-shadow: 0 0 0 1px var(--border), 0 0 0 8px var(--color-accent-softer);
}
.empty-state > div { max-width: 44ch; line-height: 1.55; }
.empty-state .btn, .empty-state button { margin-top: 0.5rem; }
.empty-state.compact { padding: 1.5rem 1rem; }
.empty-state.compact .icon { width: 52px; height: 52px; box-shadow: 0 0 0 1px var(--border); }

.section-title {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin: 0 0 0.85rem;
}
a.icon-label { text-decoration: none; }
a.icon-label:hover { text-decoration: none; color: var(--color-accent-hover); }

@media (max-width: 900px) {
  .app-shell { grid-template-columns: 1fr; }
  .sidebar {
    position: static;
    align-self: stretch;
    height: auto;
    max-height: none;
    overflow: visible;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  .main {
    min-height: 0;
  }
  .grid.two { grid-template-columns: 1fr; }
  .trip-card-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .route-card .map { height: 280px; min-height: 240px; }
  .chart.chart-tall { height: 280px; }
}

/* Settings — unit preference */
.settings-card .card-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.5rem;
  font-size: var(--text-lg);
}
.unit-choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.75rem;
  margin-top: 1rem;
}
/* Selectable tile: the checked state is a filled accent wash plus a ring, and
   a check mark appears in the corner — three signals, not just a border. */
.unit-choice {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2rem;
  text-align: left;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 0.95rem 1.05rem;
  color: var(--text);
  cursor: pointer;
  width: 100%;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast), transform var(--t-fast);
}
.unit-choice:hover { border-color: var(--color-border-accent); transform: translateY(-1px); }
.unit-choice.active {
  border-color: var(--accent);
  background: var(--color-accent-soft);
  box-shadow: var(--shadow-accent-glow);
}
.unit-choice.active::after {
  content: "✓";
  position: absolute;
  top: 0.6rem;
  right: 0.75rem;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-bold);
  color: var(--accent);
  animation: check-pop var(--motion-duration-bump) var(--motion-ease-spring-bump) both;
}
@keyframes check-pop {
  from { opacity: 0; transform: scale(0.4); }
  to { opacity: 1; transform: scale(1); }
}
.unit-choice:disabled { opacity: 0.7; cursor: wait; }
.unit-choice-title { font-weight: var(--font-weight-body-bold); margin-bottom: 0.25rem; }
.unit-choice-meta { color: var(--muted); font-size: var(--text-sm); }

/* Compact trip context chips (odometer / engine run time) */
.context-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
  margin: -0.25rem 0 1rem;
  align-items: stretch;
}
.context-chip {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem 0.75rem;
  max-width: 100%;
  padding: 0.45rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel-2);
  background-image: linear-gradient(145deg, color-mix(in srgb, var(--color-warning) 10%, transparent), transparent 60%);
  font-size: var(--text-sm);
  line-height: 1.25;
  box-shadow: none;
}
.context-chip-label {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-weight: var(--font-weight-body-semibold);
  color: var(--muted);
  white-space: nowrap;
}
.context-chip-range {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  font-variant-numeric: tabular-nums;
  flex-wrap: wrap;
}
.context-chip-num {
  font-weight: var(--font-weight-body-semibold);
}
.context-chip-arrow {
  color: var(--muted);
  opacity: 0.85;
}
.context-chip-delta {
  margin-left: 0.1rem;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
  color: var(--accent);
  font-weight: var(--font-weight-body-bold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .context-chip {
    border-radius: 12px;
    width: 100%;
  }
}



/* AI route analysis */
.trip-card-badges {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.35rem;
}
.pill-ai {
  background: var(--panel-2);
  color: var(--color-chart-series-4);
  border: 1px solid color-mix(in srgb, var(--color-chart-series-4) 35%, transparent);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-body-semibold);
  letter-spacing: var(--tracking-normal);
  white-space: nowrap;
}
.pill-ai.is-running {
  background: var(--panel-2);
  color: var(--color-info);
  border-color: color-mix(in srgb, var(--color-accent) 35%, transparent);
}
.pill-ai.is-failed {
  background: var(--panel-2);
  color: var(--color-danger);
  border-color: color-mix(in srgb, var(--color-danger) 35%, transparent);
}
.ai-analysis-card {
  margin-bottom: 1rem;
  padding-top: 0.65rem;
  padding-bottom: 0.65rem;
}
.ai-analysis-toggle {
  appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  width: 100%;
  text-align: left;
  cursor: pointer;
  padding: 0.15rem 0.1rem;
  border-radius: 12px;
}
.ai-analysis-toggle:hover {
  background: color-mix(in srgb, var(--color-chart-series-4) 6%, transparent);
}
.ai-analysis-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem 0.75rem;
  width: 100%;
}
.ai-analysis-head-main {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-width: 0;
  flex: 1 1 auto;
}
.ai-analysis-head .section-title {
  margin: 0;
  font-size: var(--text-lg);
}
.ai-analysis-head-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.45rem 0.65rem;
}
.ai-analysis-chevron {
  margin-left: auto;
  color: var(--muted);
  font-size: var(--text-base);
  transition: transform 0.15s ease;
  flex: 0 0 auto;
}
.ai-analysis-card:not(.is-open) .ai-analysis-chevron {
  transform: rotate(-90deg);
}
.ai-analysis-body {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  margin-top: 0.75rem;
  padding-top: 0.15rem;
}
.ai-analysis-card:not(.is-open) .ai-analysis-body {
  display: none;
}
.ai-analysis-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.85rem 1rem;
  margin-bottom: 0.35rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--color-chart-series-4) 8%, transparent), var(--panel-2));
}
.ai-status-block {
  display: flex;
  flex-direction: column;
  gap: 0.28rem;
  min-width: 0;
}
.ai-status-badge {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  font-size: var(--text-md);
  font-weight: var(--font-weight-body-semibold);
  letter-spacing: var(--tracking-normal);
  border: 1px solid transparent;
}
.ai-status-badge.is-idle {
  background: var(--panel-2);
  color: var(--muted);
  border-color: var(--border);
}
.ai-status-badge.is-running {
  background: var(--panel-2);
  color: var(--color-info);
  border-color: color-mix(in srgb, var(--color-accent) 35%, transparent);
}
.ai-status-badge.is-done {
  background: var(--panel-2);
  color: var(--color-chart-series-4);
  border-color: color-mix(in srgb, var(--color-chart-series-4) 40%, transparent);
}
.ai-status-badge.is-failed {
  background: var(--panel-2);
  color: var(--color-danger);
  border-color: color-mix(in srgb, var(--color-danger) 35%, transparent);
}
.ai-status-meta {
  font-size: var(--text-sm);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: min(100%, 28rem);
}
.ai-toolbar-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem;
  margin-left: auto;
}
.ai-run-btn {
  min-height: 2.35rem;
  padding: 0.45rem 1rem;
  border-radius: 999px;
  font-weight: var(--font-weight-body-semibold);
  font-size: var(--text-base);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-chart-series-4) 25%, transparent);
}
.ai-running-hint {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--text-md);
}
.banner.err .banner-hint {
  color: inherit;
  opacity: 0.85;
  font-weight: var(--font-weight-body-medium);
}
.ai-report {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.ai-summary-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.55rem 0.85rem;
}
.ai-download-btn {
  white-space: nowrap;
}
.ai-summary p {
  margin: 0.35rem 0 0.25rem;
}
.ai-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0.85rem;
}
.ai-block {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0.75rem 0.85rem;
  background: var(--panel-2);
}
.ai-block h3 {
  margin: 0 0 0.5rem;
  font-size: var(--text-base);
}
.ai-findings {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}
.ai-finding-head {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  align-items: center;
}
.severity-low { background: var(--color-success-subtle); color: var(--color-success); }
.severity-medium { background: var(--color-warning-subtle); color: var(--color-warning); }
.severity-high { background: var(--color-danger-subtle); color: var(--color-danger); }
.settings-card .field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin-top: 0.75rem;
}
.settings-card .field input {
  padding: 0.55rem 0.7rem;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: inherit;
}

/* —— Dashboard per-car cards —— */
.dash-cars-section { margin-bottom: 1.5rem; }
.dash-section-heading { margin-bottom: 0.95rem; }
.dash-car-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1.1rem;
}
.dash-car-grid > a {
  color: inherit;
  text-decoration: none;
  display: block;
  height: 100%;
  border-radius: var(--radius);
}
.dash-car-grid > a:hover { text-decoration: none; }
.dash-car-grid > a:focus-visible { box-shadow: var(--ring); }

.dash-car-card {
  position: relative;
  overflow: hidden;
  background: var(--gradient-surface), var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem 1.15rem;
  box-shadow: var(--shadow-2), var(--shadow-inset-top);
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  transition: transform var(--t-med), border-color var(--t-med), box-shadow var(--t-med);
}
/* Ambient brand glow behind the photo corner; intensifies on hover so the
   whole card feels lit rather than merely outlined. */
.dash-car-card::before {
  content: "";
  position: absolute;
  top: -55%;
  left: -20%;
  width: 240px;
  height: 240px;
  border-radius: 50%;
  background: var(--color-accent-soft);
  filter: blur(46px);
  opacity: 0.55;
  pointer-events: none;
  transition: opacity var(--motion-duration-medium) var(--motion-ease-standard);
}
.dash-car-grid > a:hover .dash-car-card {
  transform: translateY(-3px);
  border-color: var(--color-border-accent);
  box-shadow: var(--shadow-3), var(--shadow-inset-top);
}
.dash-car-grid > a:hover .dash-car-card::before { opacity: 1; }

.dash-car-card-top {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.9rem;
}
.dash-car-photo-wrap { flex-shrink: 0; }
.dash-car-photo {
  width: 72px;
  height: 72px;
  border-radius: var(--radius-md);
  object-fit: cover;
  background: var(--panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 1px var(--border), var(--shadow-1);
  transition: transform var(--motion-duration-medium) var(--motion-ease-spring-soft), box-shadow var(--t-med);
}
.dash-car-grid > a:hover .dash-car-photo {
  transform: scale(1.04) rotate(-1deg);
  box-shadow: 0 0 0 1px var(--color-border-accent), var(--shadow-2);
}
.dash-car-photo-fallback { color: var(--muted); }
.dash-car-titles { min-width: 0; }
.dash-car-name {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-display-semibold);
  font-size: var(--text-lg);
  line-height: 1.25;
  color: var(--text);
}
.dash-car-sub { font-size: var(--text-sm); margin-top: 0.2rem; color: var(--muted); }

/* Card body: radial gauge (the visual centerpiece) + a hairline-stacked
   stat column. State-of-charge/fuel reads as a color-coded ring instead of a
   small bar buried among plain numbers. */
.dash-car-body {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1.1rem;
  border-top: 1px solid var(--border);
  padding-top: 0.95rem;
  margin-top: auto;
}
.dash-car-stats {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.dash-car-stat {
  padding: 0.45rem 0;
  border-top: 1px solid var(--border);
}
.dash-car-stat:first-child { border-top: none; padding-top: 0; }
.dash-car-metric-label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.25rem;
}
.dash-car-metric-value {
  font-weight: var(--font-weight-mono-medium);
  font-size: var(--text-lg);
  line-height: 1.2;
  color: var(--text);
  word-break: break-word;
}

/* Radial gauge — semantic color by threshold (success/warning/danger),
   matching the tokens the KPI row uses for state. The ring draws itself in on
   mount: the keyframe only declares `from`, so the `to` value is whatever
   stroke-dashoffset the markup computed for the real reading. */
.dash-gauge {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
}
.dash-gauge-ring { position: relative; width: 72px; height: 72px; }
.dash-gauge-track { stroke: var(--border); }
.dash-gauge-fill {
  transition: stroke-dashoffset var(--motion-duration-medium) var(--motion-ease-enter);
  animation: gauge-draw var(--motion-duration-slow) var(--motion-ease-enter) both;
  filter: drop-shadow(0 0 6px color-mix(in srgb, currentColor 40%, transparent));
}
@keyframes gauge-draw {
  from { stroke-dashoffset: 190; opacity: 0.2; }
}
@media (prefers-reduced-motion: reduce) {
  .dash-gauge-fill { animation: none; }
}
.dash-gauge--success .dash-gauge-fill { stroke: var(--color-success); color: var(--color-success); }
.dash-gauge--warning .dash-gauge-fill { stroke: var(--color-warning); color: var(--color-warning); }
.dash-gauge--danger .dash-gauge-fill { stroke: var(--color-danger); color: var(--color-danger); }
.dash-gauge--unknown .dash-gauge-fill { stroke: var(--color-border-strong); color: transparent; }
.dash-gauge-center {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.dash-gauge-value {
  font-weight: var(--font-weight-mono-medium);
  font-size: var(--text-lg);
  color: var(--text);
}
.dash-gauge--success .dash-gauge-value { color: var(--color-success); }
.dash-gauge--warning .dash-gauge-value { color: var(--color-warning); }
.dash-gauge--danger .dash-gauge-value { color: var(--color-danger); }
.dash-gauge-label {
  display: flex;
  align-items: center;
  gap: 0.28rem;
  font-size: var(--text-2xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  white-space: nowrap;
}
.dash-global-stats { margin-bottom: 1rem; }
@media (max-width: 640px) {
  .dash-car-body {
    flex-direction: column;
    align-items: stretch;
    gap: 1.4rem;
  }
  .dash-gauge { align-self: center; margin-bottom: 0.4rem; }
}


/* —— Car photo editor (detail) + list thumbs —— */
.car-photo-editor {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-2);
  margin-bottom: 0.35rem;
}
.car-photo-preview-wrap {
  flex-shrink: 0;
}
.car-photo-preview {
  width: 96px;
  height: 96px;
  border-radius: 14px;
  object-fit: cover;
  border: 1px solid var(--border);
  background: var(--panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
}
.car-photo-preview-fallback {
  color: var(--muted);
}
.car-photo-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
label.btn.car-photo-pick {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
}
label.btn.car-photo-pick:has(input:disabled) {
  opacity: 0.65;
  cursor: not-allowed;
}
.car-list-thumb-cell {
  width: 48px;
  padding-right: 0.25rem !important;
}
.car-list-thumb {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  object-fit: cover;
  border: 1px solid var(--border);
  background: var(--panel-2);
  display: flex;
  align-items: center;
  justify-content: center;
}
.car-list-thumb-fallback {
  color: var(--muted);
}
@media (max-width: 640px) {
  .car-photo-editor {
    flex-direction: column;
    align-items: stretch;
  }
  .car-photo-preview {
    width: 100%;
    height: 160px;
  }
}

/* —— Routes Optimization —— */
.routes-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem 1rem;
  margin-bottom: 0.75rem;
}
.routes-toolbar .form-row {
  flex: 1;
  min-width: 180px;
}
.routes-insight-grid,
.routes-corridor-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 0.75rem;
}
.routes-insight h3 {
  margin: 0.35rem 0;
  font-size: var(--text-lg);
}
.routes-insight-kind {
  display: inline-flex;
  align-items: center;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-body-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--muted);
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--panel-2);
}
.routes-insight-kind.is-positive {
  color: var(--color-success);
  border-color: color-mix(in srgb, var(--color-success) 35%, transparent);
  background: var(--color-success-subtle);
}
.routes-insight-kind.is-warn {
  color: var(--color-warning);
  border-color: color-mix(in srgb, var(--color-warning) 35%, transparent);
  background: var(--color-warning-subtle);
}
.routes-insight-kind.is-neutral {
  color: var(--color-info);
  border-color: color-mix(in srgb, var(--color-accent) 35%, transparent);
  background: var(--color-info-subtle);
}
.routes-insight-kind.is-muted {
  color: var(--muted);
}
.routes-insight-empty {
  grid-column: 1 / -1;
}
.routes-corridor-card {
  transition: border-color 0.15s ease, transform 0.15s ease;
  height: 100%;
}
a:hover .routes-corridor-card {
  border-color: var(--accent);
  transform: translateY(-1px);
}
.routes-corridor-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
}
.routes-corridor-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0.75rem;
  margin-top: 0.55rem;
  font-size: var(--text-sm);
}
.routes-rec {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.routes-opt-map {
  width: 100%;
  height: min(420px, 55vh);
  min-height: 280px;
}
.banner.warn {
  background: var(--color-warning-subtle);
  border: 1px solid color-mix(in srgb, var(--color-warning) 35%, transparent);
  color: var(--color-warning);
  padding: 0.65rem 0.85rem;
  border-radius: var(--radius);
  margin-bottom: 0.75rem;
}
.pill {
  display: inline-flex;
  align-items: center;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: var(--font-weight-body-semibold);
  border: 1px solid var(--border);
}
.pill.ok {
  background: var(--color-success-subtle);
  color: var(--color-success);
  border-color: color-mix(in srgb, var(--color-success) 35%, transparent);
}
.pill.warn {
  background: var(--color-warning-subtle);
  color: var(--color-warning);
  border-color: color-mix(in srgb, var(--color-warning) 35%, transparent);
}

.routes-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
  justify-content: flex-end;
}

/* Corridor comparison map legend */
.routes-map-legend {
  padding: 0.75rem 1rem 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  border-top: 1px solid var(--border);
  background: var(--panel-2);
}
.routes-map-legend-group {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.routes-map-legend-title {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-semibold);
  color: var(--text);
}
.routes-map-legend-items {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 0.85rem;
  padding-left: 0.15rem;
}
.routes-map-swatch-item {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--text-xs);
  color: var(--muted);
}
.routes-map-swatch {
  width: 1rem;
  height: 1rem;
  border-radius: 3px;
  flex-shrink: 0;
  box-shadow: inset 0 0 0 1px var(--color-border-strong), 0 0 0 1px rgba(255,255,255,0.12);
}
.routes-map-swatch.is-variant {
  border-radius: 3px;
}
.routes-map-swatch.is-ors {
  border-radius: 999px;
  /* dashed ring cue for router alts */
  box-shadow:
    inset 0 0 0 2px rgba(255, 255, 255, 0.55),
    0 0 0 2px rgba(255, 45, 149, 0.55);
}
.routes-line-sample {
  width: 2rem;
  height: 0;
  border-top-width: 4px;
  border-top-style: solid;
  display: inline-block;
  flex-shrink: 0;
}
.routes-line-sample.is-variant {
  border-top-color: #0077ff;
  border-top-style: solid;
  border-top-width: 5px;
}
.routes-line-sample.is-ors {
  border-top-color: #ff2d95;
  border-top-style: dashed;
  border-top-width: 3px;
}
.routes-map-legend-hint {
  margin: 0;
  font-size: var(--text-xs);
}
.routes-name-with-swatch {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* Variant selection: a row / legend chip picks the line highlighted on the map.
   Unselected rows dim like their lines do, so list and map read the same way. */
.routes-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
}
/* Negative block margins: appearing must not push the legend down. */
.routes-map-legend-title .routes-show-all { margin: -0.5rem 0 -0.5rem auto; }
.routes-variant-toggle,
.routes-variant-chip {
  appearance: none;
  background: none;
  border: 0;
  margin: 0;
  font-family: inherit;
  line-height: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: var(--radius-xs);
}
.routes-variant-toggle {
  padding: 0.15rem 0.25rem;
  margin: -0.15rem -0.25rem;
  font-size: inherit;
  color: inherit;
}
.routes-variant-chip {
  padding: 0.2rem 0.45rem;
  margin: -0.2rem -0.45rem;
  border-radius: var(--radius-chip);
  transition: background var(--t-fast), color var(--t-fast);
}
.routes-variant-chip:hover { color: var(--text); background: var(--color-accent-softer); }
/* No weight change on select: bolder text would reflow the chips / columns. */
.routes-variant-chip.is-selected {
  color: var(--text);
  background: var(--color-accent-soft);
}
.routes-variant-row { cursor: pointer; }
.routes-variant-row td { transition: opacity var(--t-fast); }
.routes-variant-table.has-selection .routes-variant-row:not(.is-selected):not(:hover) td { opacity: 0.55; }
.table tbody tr.routes-variant-row.is-selected { background: var(--color-accent-soft); }
.table tbody tr.routes-variant-row.is-selected td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
.routes-variant-toggle[aria-pressed="true"] { color: var(--text); }
/* Selected swatch gets a ring, echoing the white casing on its map line. */
.routes-variant-toggle[aria-pressed="true"] .routes-map-swatch,
.routes-variant-chip.is-selected .routes-map-swatch {
  box-shadow: 0 0 0 2px var(--panel), 0 0 0 3.5px var(--text);
}
.route-opt-popup-inner {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 10rem;
}
.route-opt-popup-kind {
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}
.route-opt-popup-kind.is-variant {
  color: #4db8ff;
}
.route-opt-popup-kind.is-ors {
  color: #ff5cb0;
}
.route-opt-popup-style {
  font-size: var(--text-xs);
  color: var(--muted);
}

/* ========== Marketing landing (/) ==========================================
   The public page is the only surface allowed a full atmospheric treatment:
   aurora orbs, a fine engineering grid, a perspective-tilted product mock, and
   scroll-linked reveals. Everything still resolves to design tokens, so the
   landing switches themes with the rest of the product.
   ========================================================================= */
.landing-boot {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  background: var(--bg);
}
.landing-boot-inner {
  font-size: var(--text-base);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

.landing-page {
  position: relative;
  isolation: isolate;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--body);
  /* `clip`, not `hidden`: overflow-x:hidden would make this element a scroll
     container, which silently breaks `position: sticky` on the nav inside it.
     `clip` trims the orbs' horizontal bleed without creating one. */
  overflow-x: clip;
}

/* ---- Atmosphere ---- */
/* Sits behind the page content but in front of .landing-page's own background:
   inside a stacking context, negative-z children paint after the parent's
   background and before its in-flow descendants. Using z-index:-1 here (rather
   than lifting every sibling with position:relative) keeps `position: sticky`
   working on the nav. */
.landing-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}
.landing-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.75;
  will-change: transform;
}
.landing-orb-a {
  top: -18vh;
  left: -10vw;
  width: 62vw;
  height: 62vw;
  max-width: 820px;
  max-height: 820px;
  background: radial-gradient(circle at 40% 40%, color-mix(in srgb, var(--color-accent) 55%, transparent), transparent 68%);
  animation: orb-float-a 26s var(--motion-ease-ambient) infinite alternate;
}
.landing-orb-b {
  top: 22vh;
  right: -16vw;
  width: 54vw;
  height: 54vw;
  max-width: 720px;
  max-height: 720px;
  background: radial-gradient(circle at 60% 40%, color-mix(in srgb, var(--color-accent-2) 45%, transparent), transparent 68%);
  animation: orb-float-b 32s var(--motion-ease-ambient) infinite alternate;
}
@keyframes orb-float-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(6%, 8%, 0) scale(1.12); }
}
@keyframes orb-float-b {
  from { transform: translate3d(0, 0, 0) scale(1.05); }
  to { transform: translate3d(-7%, -6%, 0) scale(0.95); }
}
/* Engineering grid, faded out toward the fold. */
.landing-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--color-border-strong) 1px, transparent 1px),
    linear-gradient(to bottom, var(--color-border-strong) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 78%);
  opacity: 0.9;
}

/* ---- Nav ---- */
.landing-nav {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.85rem clamp(1rem, 4vw, 3rem);
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  border-bottom: 1px solid var(--glass-border);
}
.landing-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-display-bold);
  font-size: var(--text-lg);
  color: var(--text);
  letter-spacing: var(--tracking-tight);
}
.landing-brand:hover { text-decoration: none; color: var(--text); }
.landing-nav-links {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: 0.75rem;
}
.landing-nav-links a {
  position: relative;
  color: var(--muted);
  font-size: var(--text-md);
  font-weight: var(--font-weight-body-medium);
  padding: 0.4rem 0.7rem;
  border-radius: var(--radius-ctl);
  transition: color var(--t-fast), background var(--t-fast);
}
.landing-nav-links a::after {
  content: "";
  position: absolute;
  left: 0.7rem;
  right: 0.7rem;
  bottom: 0.22rem;
  height: 1.5px;
  border-radius: 2px;
  background: var(--gradient-brand-vivid);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--motion-duration-medium) var(--motion-ease-enter);
}
.landing-nav-links a:hover { color: var(--text); text-decoration: none; }
.landing-nav-links a:hover::after { transform: scaleX(1); }
.landing-nav-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-left: auto;
}
.landing-btn-ghost {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
}
.landing-btn-ghost:hover { border-color: var(--accent); background: var(--color-accent-softer); }
.landing-btn-lg {
  padding: 0.8rem 1.5rem;
  min-height: 50px;
  font-size: var(--text-lg);
  border-radius: var(--radius-ctl);
}

/* ---- Hero ---- */
.landing-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(2rem, 5vw, 4.5rem);
  max-width: 1280px;
  margin: 0 auto;
  padding: clamp(3rem, 8vw, 6.5rem) clamp(1rem, 4vw, 3rem) clamp(2.5rem, 6vw, 5rem);
}
.landing-hero-copy > * { animation: hero-in var(--motion-duration-slow) var(--motion-ease-enter) both; }
.landing-hero-copy > *:nth-child(1) { animation-delay: 40ms; }
.landing-hero-copy > *:nth-child(2) { animation-delay: 110ms; }
.landing-hero-copy > *:nth-child(3) { animation-delay: 180ms; }
.landing-hero-copy > *:nth-child(4) { animation-delay: 250ms; }
.landing-hero-copy > *:nth-child(5) { animation-delay: 320ms; }
@keyframes hero-in {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}

.landing-kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1.1rem;
  padding: 0.3rem 0.8rem 0.3rem 0.55rem;
  border-radius: var(--radius-chip);
  border: 1px solid var(--color-border-accent);
  background: var(--color-accent-soft);
  color: var(--accent);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-body-bold);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
}
.landing-kicker-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  animation: pill-pulse var(--motion-duration-ambient-pulse) var(--motion-ease-ambient) infinite;
}
.landing-title {
  margin: 0 0 1.1rem;
  font-size: clamp(38px, 1.4rem + 4.2vw, 66px);
  line-height: 1.03;
  letter-spacing: var(--tracking-tighter);
  color: var(--text);
}
.landing-title-accent {
  background: var(--gradient-brand-vivid);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.landing-lead {
  margin: 0 0 1.75rem;
  font-size: clamp(15px, 0.95rem + 0.3vw, 18px);
  line-height: var(--leading-relaxed);
  color: var(--muted);
  max-width: 54ch;
}
.landing-hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 1.75rem;
}
.landing-hero-bullets {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.landing-hero-bullets li {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--muted);
  font-size: var(--text-base);
}

/* ---- Product mock ----
   A tilted glass panel. The tilt eases out on hover so the visitor gets a
   direct, flat look at the product the moment they engage with it. */
.landing-hero-visual { min-width: 0; perspective: 1600px; }
.landing-mock {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 0.9rem;
  border-radius: var(--radius-xl);
  border: 1px solid var(--glass-border);
  background: var(--glass-bg);
  backdrop-filter: blur(calc(var(--glass-blur) * 1.2));
  -webkit-backdrop-filter: blur(calc(var(--glass-blur) * 1.2));
  box-shadow: var(--shadow-4), var(--shadow-inset-top);
  transform: rotateY(-11deg) rotateX(5deg) translateZ(0);
  transform-style: preserve-3d;
  transition: transform var(--motion-duration-slow) var(--motion-ease-spring-soft), box-shadow var(--motion-duration-slow) var(--motion-ease-standard);
  animation: mock-in 900ms var(--motion-ease-enter) both 200ms;
}
@keyframes mock-in {
  from { opacity: 0; transform: rotateY(-20deg) rotateX(9deg) translateY(28px); }
}
.landing-mock:hover {
  transform: rotateY(0deg) rotateX(0deg) translateY(-4px);
  box-shadow: var(--shadow-4), 0 0 0 1px var(--color-border-accent);
}
@media (prefers-reduced-motion: reduce) {
  .landing-mock { transform: none; animation: none; }
}
.landing-mock-top {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.15rem 0.35rem 0.55rem;
  border-bottom: 1px solid var(--border);
}
.landing-mock-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  opacity: 0.75;
}
.landing-mock-dot:nth-child(1) { background: var(--color-danger); }
.landing-mock-dot:nth-child(2) { background: var(--color-warning); }
.landing-mock-dot:nth-child(3) { background: var(--color-success); }
.landing-mock-title {
  margin-left: 0.5rem;
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--faint);
}
.landing-mock-kpis {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.5rem;
}
.landing-mock-kpi {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.55rem 0.6rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--panel);
  min-width: 0;
}
.landing-mock-kpi span { font-size: var(--text-2xs); letter-spacing: var(--tracking-wider); text-transform: uppercase; }
.landing-mock-kpi strong { font-size: var(--text-base); color: var(--text); }
.landing-mock-map {
  position: relative;
  height: 168px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background:
    linear-gradient(var(--color-border-default) 1px, transparent 1px) 0 0 / 100% 26px,
    linear-gradient(90deg, var(--color-border-default) 1px, transparent 1px) 0 0 / 26px 100%,
    var(--inset);
  overflow: hidden;
}
.landing-mock-route {
  position: absolute;
  inset: 0 0 auto;
  width: 100%;
  height: 108px;
  display: block;
}
/* The route draws itself, then loops — the page's one piece of "live" motion. */
.landing-route-path {
  stroke-dasharray: 420;
  stroke-dashoffset: 420;
  filter: drop-shadow(0 0 6px var(--color-accent-soft));
  animation: route-draw 5s var(--motion-ease-standard) infinite;
}
@keyframes route-draw {
  0% { stroke-dashoffset: 420; }
  50% { stroke-dashoffset: 0; }
  88% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 0.12; }
}
.landing-route-marker { animation: marker-pop 5s var(--motion-ease-standard) infinite; }
@keyframes marker-pop {
  0%, 12% { transform: scale(0.2); opacity: 0; }
  22%, 90% { transform: scale(1); opacity: 1; }
  100% { transform: scale(1); opacity: 0.12; }
}
@media (prefers-reduced-motion: reduce) {
  .landing-route-path { animation: none; stroke-dashoffset: 0; }
  .landing-route-marker { animation: none; }
}
.landing-mock-chart {
  position: absolute;
  left: 0.6rem;
  right: 0.6rem;
  bottom: 0.55rem;
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 52px;
}
.landing-bar {
  flex: 1;
  border-radius: 3px 3px 0 0;
  background: var(--gradient-brand-vivid);
  opacity: 0.9;
  transform-origin: bottom;
  animation: bar-grow 700ms var(--motion-ease-spring-soft) both;
}
.landing-bar:nth-child(1) { animation-delay: 320ms; }
.landing-bar:nth-child(2) { animation-delay: 370ms; }
.landing-bar:nth-child(3) { animation-delay: 420ms; }
.landing-bar:nth-child(4) { animation-delay: 470ms; }
.landing-bar:nth-child(5) { animation-delay: 520ms; }
.landing-bar:nth-child(6) { animation-delay: 570ms; }
.landing-bar:nth-child(7) { animation-delay: 620ms; }
.landing-bar:nth-child(8) { animation-delay: 670ms; }
.landing-bar:nth-child(even) { opacity: 0.55; }
@keyframes bar-grow {
  from { transform: scaleY(0); }
  to { transform: scaleY(1); }
}
.landing-mock-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.landing-mock-tags span {
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-chip);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-wide);
}

/* ---- Trust rail ---- */
.landing-trust {
  border-block: 1px solid var(--border);
  background: color-mix(in srgb, var(--panel) 55%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.landing-trust-inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem clamp(1.25rem, 4vw, 3rem);
  max-width: 1280px;
  margin: 0 auto;
  padding: 1rem clamp(1rem, 4vw, 3rem);
}
.landing-trust-item {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--muted);
  font-size: var(--text-xs);
  font-weight: var(--font-weight-body-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  transition: color var(--t-fast);
}
.landing-trust-item:hover { color: var(--text); }

/* ---- Content sections ---- */
.landing-section {
  max-width: 1280px;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6rem) clamp(1rem, 4vw, 3rem);
}
.landing-section-head {
  max-width: 62ch;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.landing-section-head h2 {
  margin: 0 0 0.75rem;
  font-size: clamp(30px, 1.2rem + 1.8vw, 40px);
  line-height: 1.12;
  letter-spacing: var(--tracking-tighter);
}
.landing-section-lead { margin: 0; line-height: var(--leading-relaxed); font-size: var(--text-lg); }

.landing-feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.1rem;
}
.landing-feature-card {
  position: relative;
  overflow: hidden;
  padding: 1.5rem 1.4rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--gradient-surface), color-mix(in srgb, var(--panel) 75%, transparent);
  box-shadow: var(--shadow-1), var(--shadow-inset-top);
  transition: transform var(--t-med), border-color var(--t-med), box-shadow var(--t-med);
}
.landing-feature-card::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--gradient-brand-soft);
  opacity: 0;
  transition: opacity var(--motion-duration-medium) var(--motion-ease-standard);
  pointer-events: none;
}
.landing-feature-card:hover {
  transform: translateY(-4px);
  border-color: var(--color-border-accent);
  box-shadow: var(--shadow-3);
}
.landing-feature-card:hover::before { opacity: 1; }
.landing-feature-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  margin-bottom: 1rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border-accent);
  background: var(--color-accent-soft);
  color: var(--accent);
  transition: transform var(--motion-duration-medium) var(--motion-ease-spring-bump);
}
.landing-feature-card:hover .landing-feature-icon { transform: translateY(-2px) scale(1.06); }
.landing-feature-card h3 {
  position: relative;
  margin: 0 0 0.5rem;
  font-size: var(--text-lg);
}
.landing-feature-card p {
  position: relative;
  margin: 0;
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
}

/* ---- How it works ---- */
.landing-how { padding-top: clamp(2rem, 5vw, 3rem); }
.landing-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  align-items: flex-start;
}
.landing-steps > .landing-step { flex: 1 1 220px; }
.landing-step {
  position: relative;
  padding: 1.35rem 1.25rem;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--panel) 65%, transparent);
  transition: border-color var(--t-med), transform var(--t-med);
}
.landing-step:hover { border-color: var(--color-border-accent); transform: translateY(-2px); }
.landing-step-num {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-bottom: 0.85rem;
  border-radius: var(--radius-avatar);
  background: var(--gradient-brand-vivid);
  color: var(--color-fg-on-accent);
  font-family: var(--font-family-mono);
  font-weight: var(--font-weight-body-bold);
  font-size: var(--text-md);
  box-shadow: var(--shadow-accent-glow);
}
.landing-step h3 { margin: 0 0 0.45rem; font-size: var(--text-lg); }
.landing-step p { margin: 0; font-size: var(--text-base); line-height: var(--leading-relaxed); color: var(--muted); }
.landing-step-arrow {
  flex: 0 0 auto;
  /* Sits on the step-number row rather than the card's centre, which is where
     the old absolute `top: 2.1rem` was aiming. */
  margin-top: 2.1rem;
  color: var(--faint);
}

/* ---- Intelligence ---- */
.landing-intel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1.25rem;
}
.landing-intel-card {
  position: relative;
  overflow: hidden;
  padding: 1.65rem 1.5rem;
  border-radius: var(--radius-xl);
  border: 1px solid var(--border);
  background: var(--gradient-surface), color-mix(in srgb, var(--panel) 78%, transparent);
  box-shadow: var(--shadow-2), var(--shadow-inset-top);
}
.landing-intel-card::after {
  content: "";
  position: absolute;
  top: -30%;
  right: -20%;
  width: 260px;
  height: 260px;
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0.5;
  pointer-events: none;
}
.landing-intel-ai::after { background: var(--color-accent-soft); }
.landing-intel-routes::after { background: color-mix(in srgb, var(--color-accent-2) 16%, transparent); }
.landing-intel-badge {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.9rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--radius-chip);
  border: 1px solid var(--color-border-accent);
  background: var(--color-accent-soft);
  color: var(--accent);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
.landing-intel-card h3 {
  position: relative;
  margin: 0 0 0.6rem;
  font-size: clamp(20px, 1.05rem + 0.5vw, 24px);
}
.landing-intel-card > p {
  position: relative;
  margin: 0 0 1rem;
  line-height: var(--leading-relaxed);
  color: var(--muted);
}
.landing-intel-list {
  position: relative;
  margin: 0;
  padding-left: 1.15rem;
  color: var(--muted);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
}
.landing-intel-list li { margin-bottom: 0.3rem; }
.landing-intel-list li::marker { color: var(--accent); }

/* ---- Telemetry grid ---- */
.landing-telemetry-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1rem;
}
.landing-telemetry-item {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 1.15rem 1.2rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: color-mix(in srgb, var(--panel) 60%, transparent);
  transition: border-color var(--t-med), background var(--t-med);
}
.landing-telemetry-item:hover {
  border-color: var(--color-border-accent);
  background: color-mix(in srgb, var(--panel) 85%, transparent);
}
.landing-telemetry-item strong { font-size: var(--text-base); color: var(--text); }
.landing-telemetry-item span { font-size: var(--text-md); line-height: var(--leading-relaxed); color: var(--muted); }

/* ---- Closing CTA ---- */
.landing-cta-band {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 3rem) clamp(3.5rem, 8vw, 6rem);
}
.landing-cta-inner {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: clamp(2.5rem, 6vw, 4rem) clamp(1.5rem, 5vw, 3rem);
  border-radius: var(--radius-2xl);
  border: 1px solid var(--color-border-accent);
  background: var(--gradient-brand-soft), var(--panel);
  box-shadow: var(--shadow-3), var(--shadow-inset-top);
}
.landing-cta-inner::before {
  content: "";
  position: absolute;
  inset: -50% 20% auto;
  height: 300px;
  background: radial-gradient(ellipse at center, var(--color-accent-soft), transparent 70%);
  pointer-events: none;
}
.landing-cta-inner h2 {
  position: relative;
  margin: 0 0 0.75rem;
  font-size: clamp(30px, 1.2rem + 1.8vw, 38px);
  letter-spacing: var(--tracking-tighter);
}
.landing-cta-inner > p {
  position: relative;
  margin: 0 auto 1.75rem;
  max-width: 56ch;
  color: var(--muted);
  line-height: var(--leading-relaxed);
}
.landing-cta-inner .landing-hero-ctas {
  position: relative;
  justify-content: center;
  margin-bottom: 0;
}

/* ---- Footer ---- */
.landing-footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1.5rem;
  max-width: 1280px;
  margin: 0 auto;
  padding: 1.75rem clamp(1rem, 4vw, 3rem) 2.5rem;
  border-top: 1px solid var(--border);
}
.landing-footer-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: var(--font-weight-body-bold);
  color: var(--text);
}
.landing-footer-copy { color: var(--faint); font-size: var(--text-sm); }
.landing-footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
  margin-left: auto;
}
.landing-footer-links a { color: var(--muted); font-size: var(--text-md); }
.landing-footer-links a:hover { color: var(--accent); }

/* Scroll-linked reveals where the browser supports them; everything above is
   fully visible without this, so it is pure enhancement. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .landing-feature-card,
    .landing-step,
    .landing-intel-card,
    .landing-telemetry-item,
    .landing-cta-inner,
    .landing-section-head {
      animation: reveal-up linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 26%;
    }
  }
}
@keyframes reveal-up {
  from { opacity: 0; transform: translateY(26px); }
  to { opacity: 1; transform: none; }
}

@media (max-width: 960px) {
  .landing-hero {
    grid-template-columns: 1fr;
    padding-top: clamp(2rem, 7vw, 3.5rem);
  }
  .landing-hero-visual { order: -1; }
  .landing-mock { transform: none; }
  .landing-nav-links { display: none; }
  .landing-step-arrow { display: none; }
}
@media (max-width: 640px) {
  .landing-mock-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .landing-hero-ctas .btn { width: 100%; }
  .landing-footer-links { margin-left: 0; }
  .landing-trust-inner { gap: 0.6rem 1.25rem; }
}
@media (prefers-reduced-motion: reduce) {
  .landing-orb, .landing-bar, .landing-hero-copy > *, .landing-kicker-dot { animation: none; }
}

/* —— App shell: mobile / tablet —— */
@media (max-width: 900px) {
  /* Block layout: fixed drawer/backdrop must not steal grid tracks. */
  .app-shell {
    display: block;
    min-height: 100dvh;
  }
  .mobile-topbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    position: sticky;
    top: 0;
    z-index: 50;
    padding: 0.55rem 0.75rem;
    padding-top: max(0.55rem, env(safe-area-inset-top));
    padding-left: max(0.75rem, env(safe-area-inset-left));
    padding-right: max(0.75rem, env(safe-area-inset-right));
    background: var(--glass-bg);
    border-bottom: 1px solid var(--glass-border);
    backdrop-filter: blur(var(--glass-blur)) saturate(140%);
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  }
  .mobile-topbar-brand {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--font-family-display);
    font-weight: var(--font-weight-display-semibold);
    font-size: var(--text-lg);
    color: var(--text);
    min-width: 0;
  }
  .mobile-topbar-brand .brand-logo { width: 28px; height: 28px; }
  .mobile-topbar-spacer {
    width: 42px;
    flex-shrink: 0;
    margin-left: auto;
  }
  .nav-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: var(--color-overlay-scrim);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--motion-duration-medium) var(--motion-ease-standard);
  }
  .app-shell.nav-open .nav-backdrop { opacity: 1; pointer-events: auto; }
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: min(304px, 88vw);
    height: 100dvh;
    max-height: 100dvh;
    z-index: 60;
    transform: translateX(-105%);
    transition: transform var(--motion-duration-entry) var(--motion-ease-enter);
    padding-top: max(1.25rem, env(safe-area-inset-top));
    padding-bottom: max(1rem, env(safe-area-inset-bottom));
    box-shadow: var(--shadow-4);
  }
  .app-shell.nav-open .sidebar { transform: translateX(0); }
  /* Drawer contents cascade in behind the panel edge. */
  .app-shell.nav-open .nav > * {
    animation: drawer-item-in var(--motion-duration-medium) var(--motion-ease-enter) both;
  }
  .app-shell.nav-open .nav > *:nth-child(6) { animation-delay: 260ms; }
  .app-shell.nav-open .nav > *:nth-child(7) { animation-delay: 300ms; }
  .app-shell.nav-open .nav > *:nth-child(8) { animation-delay: 340ms; }
  .app-shell.nav-open .nav > *:nth-child(1) { animation-delay: 60ms; }
  .app-shell.nav-open .nav > *:nth-child(2) { animation-delay: 100ms; }
  .app-shell.nav-open .nav > *:nth-child(3) { animation-delay: 140ms; }
  .app-shell.nav-open .nav > *:nth-child(4) { animation-delay: 180ms; }
  .app-shell.nav-open .nav > *:nth-child(5) { animation-delay: 220ms; }
  @keyframes drawer-item-in {
    from { opacity: 0; transform: translateX(-12px); }
    to { opacity: 1; transform: none; }
  }
  .main {
    padding: 1rem;
    padding-bottom: max(2rem, env(safe-area-inset-bottom));
    min-height: auto;
  }
  .grid.two { grid-template-columns: 1fr; }
  .grid.stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .topbar {
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
  }
  .topbar h1 { font-size: var(--text-xl); }
  .map { height: 260px; min-height: 220px; }
  .chart { height: 240px; }
  .chart.chart-tall { height: 260px; }
  .trip-grid { grid-template-columns: 1fr; }
  .telemetry-toolbar { flex-direction: column; align-items: stretch; }
  .telemetry-toolbar-right { width: 100%; justify-content: space-between; }
  .trips-filter-tools { margin-left: 0; width: 100%; }
  .trips-search, .trips-search-input, .trips-search-input:focus { width: 100%; }
  body { overflow-x: hidden; }
}

@media (max-width: 480px) {
  .grid.stats { grid-template-columns: 1fr 1fr; }
  .main { padding: 0.85rem; }
  .card { padding: 0.95rem 1rem; }
  .stat-value { font-size: var(--text-2xl); }
  .kpi-hairline-item { flex-basis: 50%; padding: 0.85rem 1rem; }
}

/* =========================================================================
   Motion & polish layer
   Cross-cutting behaviour that applies on top of every component above:
   entry choreography, list staggering, overlays, and the reduced-motion
   contract. Kept last so it wins ties without raising specificity.
   ========================================================================= */

/* ---- Staggered list entry ------------------------------------------------
   Any grid/list whose children should cascade in. Children get their index via
   nth-child rather than inline styles, so no markup carries animation state.
   `backwards` (not `both`) for the stacking-context reason noted at
   `.page-view > *`; it also lets the cards' own :hover transform lift apply,
   which a forwards-filled `transform: none` would override. */
.trip-grid > a,
.dash-car-grid > a,
.landing-feature-grid > *,
.stat-panel-grid > * {
  animation: stagger-in var(--motion-duration-entry) var(--motion-ease-enter) backwards;
}
@keyframes stagger-in {
  from { opacity: 0; transform: translateY(12px) scale(0.985); }
  to { opacity: 1; transform: none; }
}
.trip-grid > a:nth-child(1), .dash-car-grid > a:nth-child(1), .stat-panel-grid > *:nth-child(1) { animation-delay: 0ms; }
.trip-grid > a:nth-child(2), .dash-car-grid > a:nth-child(2), .stat-panel-grid > *:nth-child(2) { animation-delay: 45ms; }
.trip-grid > a:nth-child(3), .dash-car-grid > a:nth-child(3), .stat-panel-grid > *:nth-child(3) { animation-delay: 90ms; }
.trip-grid > a:nth-child(4), .dash-car-grid > a:nth-child(4), .stat-panel-grid > *:nth-child(4) { animation-delay: 135ms; }
.trip-grid > a:nth-child(5), .dash-car-grid > a:nth-child(5), .stat-panel-grid > *:nth-child(5) { animation-delay: 180ms; }
.trip-grid > a:nth-child(6), .dash-car-grid > a:nth-child(6), .stat-panel-grid > *:nth-child(6) { animation-delay: 225ms; }
.trip-grid > a:nth-child(n + 7), .dash-car-grid > a:nth-child(n + 7), .stat-panel-grid > *:nth-child(n + 7) { animation-delay: 270ms; }

/* KPI numbers count in with a short rise; the row itself is already framed. */
.kpi-hairline-item { animation: stagger-in var(--motion-duration-entry) var(--motion-ease-enter) backwards; }
.kpi-hairline-item:nth-child(2) { animation-delay: 40ms; }
.kpi-hairline-item:nth-child(3) { animation-delay: 80ms; }
.kpi-hairline-item:nth-child(4) { animation-delay: 120ms; }
.kpi-hairline-item:nth-child(5) { animation-delay: 160ms; }

/* Table rows fade in on first paint of a page, capped so a 200-row table
   doesn't animate for six seconds. */
.table tbody tr { animation: row-in var(--motion-duration-medium) var(--motion-ease-enter) backwards; }
.table tbody tr:nth-child(1) { animation-delay: 0ms; }
.table tbody tr:nth-child(2) { animation-delay: 30ms; }
.table tbody tr:nth-child(3) { animation-delay: 60ms; }
.table tbody tr:nth-child(4) { animation-delay: 90ms; }
.table tbody tr:nth-child(5) { animation-delay: 120ms; }
.table tbody tr:nth-child(n + 6) { animation-delay: 150ms; }
@keyframes row-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* ---- QR / share surface -------------------------------------------------- */
.qr-box {
  display: grid;
  place-items: center;
  gap: 0.75rem;
  padding: 1.25rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--inset);
}
.qr-box canvas, .qr-box img {
  border-radius: var(--radius-sm);
  background: #fff;
  padding: 0.6rem;
  box-shadow: var(--shadow-2);
}

/* ---- Theme toggle -------------------------------------------------------- */
.theme-toggle .icon { transition: transform var(--motion-duration-bump) var(--motion-ease-spring-bump); }
.theme-toggle:hover .icon { transform: rotate(-18deg) scale(1.1); }

/* ---- The reduced-motion contract ----------------------------------------
   Durations are already zeroed in tokens.css. This removes the *movement*
   itself for anything that translates or scales, leaving opacity changes —
   which stay legible and cause no vestibular discomfort. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .btn:hover, .card:hover, a > .card:hover,
  .trip-grid > a:hover .trip-card,
  .dash-car-grid > a:hover .dash-car-card,
  .landing-feature-card:hover,
  .stat-panel:hover {
    transform: none;
  }
}

/* Smooth in-page anchor scrolling for the landing page's section links. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Print: drop the chrome, keep the data. */
/* Print / "Save as PDF" (#117): the page on white paper — header, stats, route
   map (when its canvas renders), charts and tables; no chrome or controls. The
   trip page switches the app to the light theme while printing so the
   canvas-drawn charts follow. */
@media print {
  @page { margin: 12mm; }
  html, body { background: #fff !important; color: #111 !important; }
  .sidebar, .mobile-topbar, .nav-backdrop, .connectivity-banner, .trip-detail-actions,
  .skip-link, .notif-bell, .notif-panel, .notif-backdrop,
  .replay-bar, .traffic-toolbar, .ai-toolbar-actions, .map-legend-actions,
  .telemetry-toolbar, .telemetry-cat-scroll, .trip-meta-form, .export-menu,
  .chat-layout, .chat-composer, .invite-banner, .trips-select-bar,
  .maplibregl-ctrl, button, .btn { display: none !important; }
  .app-shell { display: block; }
  .main { padding: 0; }
  .page-view { max-width: none; }
  .card, .kpi-hairline-row, .trip-card, .stat-panel, .telemetry-panel {
    box-shadow: none;
    border-color: #ccc;
    background: #fff !important;
    break-inside: avoid;
  }
  .map { height: 320px; box-shadow: none; break-inside: avoid; }
  .chart { break-inside: avoid; }
  a { color: inherit; text-decoration: none; }
  body::before { display: none; }
}

/* --- Ask your data (chat) ------------------------------------------------ */

.chat-setup-notice {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 1rem 1.125rem;
  border-left: 3px solid var(--color-warning);
}

.chat-setup-notice p {
  margin: 0.125rem 0 0;
  font-size: var(--text-sm);
}

.chat-setup-notice .btn {
  margin-left: auto;
  flex-shrink: 0;
}

.chat-layout {
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}

.chat-rail {
  position: sticky;
  top: 1rem;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-lg);
  padding: 0.875rem;
}

.chat-rail-title {
  margin: 0 0 0.625rem;
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-fg-faint);
}

.chat-rail-empty {
  margin: 0;
  font-size: var(--text-sm);
}

.chat-rail-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
}

.chat-rail-list li {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  border-radius: var(--radius-sm);
}

.chat-rail-list li:hover {
  background: var(--color-bg-inset);
}

.chat-rail-list a {
  flex: 1;
  min-width: 0;
  padding: 0.4rem 0.5rem;
  font-size: var(--text-sm);
  color: var(--color-fg-body);
  text-decoration: none;
  /* Titles are the user's own first question, so they run long. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-rail-list li .icon-btn {
  opacity: 0;
  flex-shrink: 0;
}

.chat-rail-list li:hover .icon-btn,
.chat-rail-list li .icon-btn:focus-visible {
  opacity: 1;
}

.chat-rail-active {
  background: var(--color-accent-softer);
}

.chat-rail-active a {
  color: var(--color-accent);
  font-weight: var(--font-weight-body-medium);
}

.chat-main {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  min-height: 60vh;
}

.chat-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  padding: 3rem 1rem 2rem;
}

.chat-empty h2 {
  margin: 0.5rem 0 0;
  font-size: var(--text-xl);
}

.chat-empty p {
  margin: 0;
  max-width: 34rem;
}

.chat-suggestions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 0.5rem;
  margin-top: 1.25rem;
  width: 100%;
  max-width: 44rem;
}

.chat-suggestion {
  padding: 0.75rem 0.875rem;
  text-align: left;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--color-fg-body);
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-md);
  cursor: pointer;
}

.chat-suggestion:hover {
  border-color: var(--color-border-accent);
  background: var(--color-bg-surface-raised);
}

.chat-thread {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.chat-msg {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  max-width: 52rem;
}

.chat-msg-user {
  align-self: flex-end;
  align-items: flex-end;
  max-width: 40rem;
}

.chat-role {
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-fg-faint);
}

.chat-body {
  font-size: var(--text-sm);
  line-height: 1.6;
  color: var(--color-fg-body);
}

.chat-msg-user .chat-body {
  padding: 0.625rem 0.875rem;
  background: var(--color-accent-softer);
  border-radius: var(--radius-md);
  white-space: pre-wrap;
}

.chat-body > :first-child { margin-top: 0; }
.chat-body > :last-child { margin-bottom: 0; }

.chat-body p { margin: 0 0 0.75rem; }
.chat-body ul,
.chat-body ol { margin: 0 0 0.75rem; padding-left: 1.25rem; }
.chat-body li { margin-bottom: 0.25rem; }

.chat-body h1,
.chat-body h2,
.chat-body h3 {
  margin: 1rem 0 0.5rem;
  font-size: var(--text-base);
  font-weight: var(--font-weight-body-semibold);
}

.chat-body code {
  font-family: var(--font-family-mono);
  font-size: 0.9em;
  padding: 0.1em 0.35em;
  background: var(--color-bg-inset);
  border-radius: var(--radius-xs);
}

.chat-body pre {
  padding: 0.75rem;
  background: var(--color-bg-inset);
  border-radius: var(--radius-sm);
  overflow-x: auto;
}

.chat-body pre code { padding: 0; background: none; }

.chat-body table {
  border-collapse: collapse;
  margin: 0 0 0.75rem;
  font-size: var(--text-xs);
  /* Model-authored tables can be wide; scroll them rather than the page. */
  display: block;
  overflow-x: auto;
  max-width: 100%;
}

.chat-body th,
.chat-body td {
  padding: 0.375rem 0.625rem;
  border: 1px solid var(--color-border-default);
  text-align: left;
  white-space: nowrap;
}

.chat-body th {
  background: var(--color-bg-inset);
  font-weight: var(--font-weight-body-semibold);
}

.chat-tools {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin: 0;
  font-size: var(--text-2xs);
  color: var(--color-fg-faint);
}

.chat-error {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-danger);
}

.chat-spinner {
  width: 0.6rem;
  height: 0.6rem;
  border: 2px solid var(--color-border-strong);
  border-top-color: var(--color-accent);
  border-radius: 50%;
  animation: chat-spin 0.7s linear infinite;
}

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

@media (prefers-reduced-motion: reduce) {
  .chat-spinner { animation: none; }
}

.chat-composer {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  padding: 0.625rem;
  margin-top: auto;
  background: var(--color-bg-surface);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-lg);
}

.chat-focus {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: var(--text-2xs);
  color: var(--color-fg-faint);
}

.chat-input {
  flex: 1;
  min-width: 0;
  resize: none;
  padding: 0.5rem;
  font: inherit;
  font-size: var(--text-sm);
  color: var(--color-fg-body);
  background: transparent;
  border: none;
}

.chat-input:focus { outline: none; }

.chat-composer .btn { flex-shrink: 0; }

@media (max-width: 900px) {
  .chat-layout { grid-template-columns: minmax(0, 1fr); }
  .chat-rail { position: static; }
  .chat-msg, .chat-msg-user { max-width: 100%; }
}

/* ---- Trips: purpose, tags, selection, paging (#121 #89 #93) --------------- */
.trips-range {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.trips-range-field {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  color: var(--muted);
}
.trips-range-field input { width: auto; min-height: 36px; padding: 0.35rem 0.6rem; }
.trips-tag-filter .trips-search-input { max-width: 9rem; }

.trips-select-bar {
  position: sticky;
  top: 0.5rem;
  z-index: 5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  margin-bottom: 1rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius);
  background: var(--gradient-surface), var(--panel-2);
  box-shadow: var(--shadow-2);
}
.trips-select-count { font-weight: var(--font-weight-body-bold); color: var(--text); }
.trips-select-hint { font-size: var(--text-sm); }
.trips-select-actions { display: flex; gap: 0.5rem; margin-left: auto; flex-wrap: wrap; }
.trip-card.is-selected {
  border-color: var(--color-border-accent);
  box-shadow: var(--shadow-2), inset 0 0 0 1px var(--color-border-accent);
}
.trip-select-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  color: var(--muted);
  font-size: var(--text-sm);
  cursor: pointer;
}

.pill-purpose { color: var(--color-accent-2); border-color: color-mix(in srgb, var(--color-accent-2) 30%, transparent); }
.pill-purpose.is-business { color: var(--color-info); background: var(--color-info-subtle); border-color: var(--color-border-accent); }
.pill-purpose.is-personal { color: var(--color-success); background: var(--color-success-subtle); border-color: color-mix(in srgb, var(--color-success) 26%, transparent); }

.trip-tags { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
.tag-chip {
  appearance: none;
  display: inline-flex;
  align-items: center;
  padding: 0.14rem 0.55rem;
  border-radius: var(--radius-chip);
  border: 1px solid var(--border);
  background: var(--inset);
  color: var(--muted);
  font: inherit;
  font-size: var(--text-xs);
  font-family: var(--font-family-mono);
  line-height: 1.4;
}
button.tag-chip { cursor: pointer; transition: color var(--t-fast), border-color var(--t-fast); }
button.tag-chip:hover { color: var(--accent); border-color: var(--color-border-accent); }

.trips-load-more { display: flex; justify-content: center; margin-top: 1.25rem; }

.trip-meta-card { margin-top: 1.25rem; }
.trip-meta-form { margin-top: 0.75rem; }
.trip-meta-form textarea { min-height: 72px; }
.trip-meta-readonly { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.6rem; }
.trip-meta-notes { margin: 0; white-space: pre-wrap; color: var(--body); }

/* ---- Garage: maintenance, odometer, fuel & charging (#113 #114 #115) ------- */
.garage-card { margin-top: 1.25rem; }
.garage-head { flex-wrap: wrap; margin-bottom: 0.75rem; }
.garage-panel { display: flex; flex-direction: column; gap: 0.75rem; }
.garage-subtitle {
  margin: 0.75rem 0 0;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-bold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--muted);
}
.garage-odo {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 0.75rem 1.25rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--inset);
}
.garage-inline-form { display: flex; gap: 0.5rem; align-items: center; }
.garage-inline-form input { width: 11rem; min-height: 36px; }
.garage-due-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.garage-due-item {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) 2fr auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}
.garage-due-name { color: var(--text); font-weight: var(--font-weight-body-medium); }
.garage-due-detail { font-size: var(--text-sm); }
.table-scroll { width: 100%; overflow-x: auto; }
.garage-table td { vertical-align: top; }
.garage-note { font-size: var(--text-xs); margin-top: 0.15rem; }
.garage-row-actions { display: flex; gap: 0.35rem; justify-content: flex-end; flex-wrap: wrap; }
.garage-form {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.85rem 0.95rem;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
}
.garage-form .btn { align-self: flex-start; }
.garage-form-title { font-weight: var(--font-weight-body-bold); color: var(--text); }
.garage-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.6rem 0.75rem;
}
.garage-field { margin: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.garage-field span { color: var(--muted); font-size: var(--text-xs); }
.garage-field-wide { grid-column: 1 / -1; }
.garage-check { display: flex; align-items: center; gap: 0.5rem; margin: 0; align-self: end; min-height: 42px; }
.garage-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
  gap: 0.5rem;
}
.dash-car-due { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.4rem; }
@media (max-width: 640px) {
  .garage-due-item { grid-template-columns: 1fr auto; }
  .garage-due-detail { grid-column: 1 / -1; grid-row: 2; }
  .garage-inline-form input { width: 100%; }
}

/* ---- Live positions (#108) ------------------------------------------------ */
.live-card { margin-top: 1.25rem; }
.live-card .map { margin-top: 0.75rem; }
.live-map { height: 320px; }
.live-marker {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  cursor: default;
}
.live-marker-dot {
  position: relative;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--color-bg-surface);
  border: 2px solid var(--accent);
  box-shadow: var(--shadow-2);
}
.live-marker-arrow {
  display: none;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 11px solid var(--accent);
  transform-origin: 50% 60%;
}
.live-marker.has-heading .live-marker-arrow { display: block; }
.live-marker:not(.has-heading) .live-marker-dot::after {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
}
.live-marker.is-driving .live-marker-dot {
  border-color: var(--color-info);
  animation: live-ring var(--motion-duration-ambient-pulse) var(--motion-ease-ambient) infinite;
}
@keyframes live-ring {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--color-info) 55%, transparent), var(--shadow-2); }
  50% { box-shadow: 0 0 0 8px transparent, var(--shadow-2); }
}
@media (prefers-reduced-motion: reduce) {
  .live-marker.is-driving .live-marker-dot { animation: none; }
}
.live-marker-label {
  padding: 0.1rem 0.45rem;
  border-radius: var(--radius-chip);
  background: var(--color-bg-surface);
  color: var(--text);
  font-size: var(--text-2xs);
  font-weight: var(--font-weight-body-bold);
  white-space: nowrap;
  box-shadow: var(--shadow-1);
}
.live-list { list-style: none; margin: 0.75rem 0 0; padding: 0; display: grid; gap: 0.5rem; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
.live-item {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.65rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}
.live-item-main { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.live-item-name { color: var(--text); font-weight: var(--font-weight-body-bold); }
.live-item-meta { display: flex; flex-wrap: wrap; gap: 0.25rem 0.75rem; font-size: var(--text-sm); }
.live-sharing-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem 1rem;
  margin: 0.5rem 0 1rem;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--inset);
}
.live-sharing-title { display: flex; align-items: center; gap: 0.4rem; color: var(--text); font-weight: var(--font-weight-body-bold); }
.live-sharing-row .field-hint { margin-top: 0.2rem; }

/* ---- Trip export menu (#117) ---------------------------------------------- */
.export-menu { position: relative; }
.export-menu > summary { list-style: none; cursor: pointer; }
.export-menu > summary::-webkit-details-marker { display: none; }
.export-menu-list {
  position: absolute;
  right: 0;
  top: calc(100% + 0.35rem);
  z-index: 20;
  display: flex;
  flex-direction: column;
  min-width: 13rem;
  padding: 0.35rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--panel-3);
  box-shadow: var(--shadow-3);
}
.export-menu-item {
  appearance: none;
  display: block;
  width: 100%;
  padding: 0.5rem 0.65rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
}
.export-menu-item:hover:not(:disabled) { background: var(--color-accent-softer); color: var(--accent); }
.export-menu-item:disabled { opacity: 0.5; cursor: not-allowed; }
.export-menu-note { margin: 0.35rem 0.5rem 0.2rem; font-size: var(--text-xs); max-width: 13rem; }

/* ---- Settings: region, your data (#60 #118) ------------------------------- */
.settings-kv {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.85rem;
  margin: 0.5rem 0 1rem;
}
.settings-kv strong { color: var(--text); font-family: var(--font-family-mono); font-weight: var(--font-weight-mono-medium); }
.danger-zone {
  margin-top: 1.25rem;
  padding: 0.9rem 1rem;
  border: 1px solid color-mix(in srgb, var(--color-danger) 34%, transparent);
  border-radius: var(--radius-md);
  background: var(--color-danger-subtle);
}
.danger-zone-title {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.35rem;
  font-size: var(--text-md);
  color: var(--color-danger);
}
.danger-zone .field { margin-bottom: 0.75rem; }

/* ---- Statistics (#116) ------------------------------------------------------ */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: 1rem;
  margin-top: 1.25rem;
}
.stats-grid > .card { margin-top: 0; }
.stats-grid + .card { margin-top: 1.25rem; }
.stats-chart-card { padding-bottom: 0.5rem; }
.stats-chart-title {
  margin: 0 0 0.25rem;
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-bold);
  color: var(--muted);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}
.stats-chart-card .chart { height: 240px; }

/* ---- Trips map overlay & calendar (#120) ---------------------------------- */
.trips-overlay-card .map { margin-top: 0.75rem; height: 480px; }
.trips-overlay-card .map-legend-note { margin-top: 0.5rem; }
.geo-cursor {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--color-bg-surface);
  box-shadow: var(--shadow-2);
}

.cal-scroll { overflow-x: auto; margin-top: 0.75rem; padding-bottom: 0.25rem; }
.cal-grid {
  display: grid;
  grid-template-columns: 2rem auto;
  column-gap: 3px;
  row-gap: 4px;
  width: max-content;
}
.cal-months {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 2rem repeat(53, 12px);
  column-gap: 3px;
  font-size: var(--text-2xs);
  color: var(--muted);
}
.cal-month { white-space: nowrap; }
.cal-weekdays {
  display: grid;
  grid-template-rows: repeat(7, 12px);
  row-gap: 3px;
  font-size: 10px;
  line-height: 12px;
  color: var(--muted);
}
.cal-weeks { display: flex; gap: 3px; }
.cal-week { display: grid; grid-template-rows: repeat(7, 12px); row-gap: 3px; }
.cal-day {
  display: inline-block;
  width: 12px;
  height: 12px;
  padding: 0;
  border: 0;
  border-radius: 3px;
  background: var(--inset);
  box-shadow: inset 0 0 0 1px var(--border);
}
button.cal-day { cursor: pointer; }
button.cal-day:hover { box-shadow: inset 0 0 0 1px var(--text); }
.cal-day.is-future { visibility: hidden; }
.cal-l1 { background: color-mix(in srgb, var(--accent) 28%, var(--inset)); }
.cal-l2 { background: color-mix(in srgb, var(--accent) 50%, var(--inset)); }
.cal-l3 { background: color-mix(in srgb, var(--accent) 75%, var(--inset)); }
.cal-l4 { background: var(--accent); }
.cal-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 0.6rem;
  font-size: var(--text-xs);
}
.cal-legend-note { display: inline-flex; align-items: center; gap: 0.3rem; margin-left: auto; }

/* ---- Trip replay (#119) ---------------------------------------------------- */
.replay-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 0.9rem;
  margin: 0 0 0.75rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--inset);
}
.replay-seek {
  flex: 1 1 12rem;
  min-width: 8rem;
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  accent-color: var(--accent);
}
.replay-seek:focus { background: transparent; box-shadow: none; }
.replay-seek:focus-visible { box-shadow: var(--ring); }
.replay-clock {
  font-family: var(--font-family-mono);
  font-size: var(--text-sm);
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---- Compare trips (#122) -------------------------------------------------- */
.compare-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  margin-bottom: 1rem;
  font-size: var(--text-sm);
}
.compare-legend a { display: inline-flex; align-items: center; gap: 0.45rem; color: var(--text); }
.compare-legend a:hover { color: var(--accent); }
.compare-swatch { width: 22px; height: 4px; border-radius: 2px; }
.compare-a { background: var(--color-chart-series-1); }
.compare-b { background: var(--color-chart-series-2); }
.compare-table th[scope="row"] { color: var(--muted); font-weight: var(--font-weight-body-medium); text-align: left; }

/* ---- Share invitations ------------------------------------------------------ */
.sharing-card { margin-top: 1rem; }
.sharing-card .telemetry-section-head { margin-bottom: 0.5rem; }
.invite-banner { margin-bottom: 1.25rem; border-color: var(--color-border-accent); }
.invite-list { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.invite-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}
.invite-car { display: flex; align-items: center; gap: 0.4rem; color: var(--text); font-weight: var(--font-weight-body-bold); }
.invite-meta { font-size: var(--text-sm); margin-top: 0.15rem; }

/* ---- Notifications (#109 #112) --------------------------------------------- */
.brand { width: 100%; }
.brand-spacer { flex: 1; }
.notif-bell { position: relative; display: inline-flex; }
.notif-bell-btn { position: relative; }
.notif-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--radius-chip);
  background: var(--color-danger);
  color: #fff;
  font-family: var(--font-family-mono);
  font-size: 10px;
  font-weight: var(--font-weight-body-bold);
  line-height: 18px;
  text-align: center;
  box-shadow: 0 0 0 2px var(--panel);
}
.notif-backdrop { position: fixed; inset: 0; z-index: 60; }
.notif-panel {
  position: fixed;
  z-index: 61;
  top: 1rem;
  left: calc(264px + 0.75rem);
  width: min(380px, calc(100vw - 2rem));
  max-height: min(70vh, 560px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--panel-3);
  box-shadow: var(--shadow-3);
  overflow: hidden;
}
@media (max-width: 900px) {
  .notif-panel { left: auto; right: 1rem; top: 3.75rem; }
}
.notif-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 0.75rem;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  font-family: var(--font-family-body);
  font-size: var(--text-base);
  letter-spacing: normal;
}
.notif-list { list-style: none; margin: 0; padding: 0.3rem; overflow-y: auto; }
.notif-list-page { padding: 0; }
.notif-item {
  appearance: none;
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  width: 100%;
  padding: 0.55rem 0.6rem;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--body);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.notif-item:hover { background: var(--color-accent-softer); }
.notif-item.is-unread { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.notif-item.is-unread .notif-title::after {
  content: "";
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-left: 0.4rem;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: middle;
}
.notif-text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.notif-title { color: var(--text); font-weight: var(--font-weight-body-bold); font-size: var(--text-sm); }
.notif-body { font-size: var(--text-sm); overflow-wrap: anywhere; }
.notif-when { font-size: var(--text-xs); }
.notif-empty { padding: 1rem; margin: 0; }
.notif-all {
  display: block;
  padding: 0.6rem 0.75rem;
  border-top: 1px solid var(--border);
  font-size: var(--text-sm);
  text-align: center;
}

/* ---- Alert rules (#110) ------------------------------------------------------ */
.alerts-card { margin-top: 1.25rem; }
.alert-rules { list-style: none; margin: 0.75rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.45rem; }
.alert-rule {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) minmax(14rem, 1.4fr) auto;
  align-items: center;
  gap: 0.5rem 1rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}
.alert-rule.is-on { border-color: var(--color-border-accent); }
.alert-rule-toggle { display: flex; align-items: center; gap: 0.55rem; margin: 0; cursor: pointer; }
.alert-rule-title { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--text); font-weight: var(--font-weight-body-medium); }
.alert-rule-threshold { display: flex; align-items: center; gap: 0.5rem; }
.alert-rule-threshold label { margin: 0; font-size: var(--text-sm); white-space: nowrap; }
.alert-rule-threshold input { width: 6.5rem; min-height: 34px; padding: 0.3rem 0.5rem; }
.alert-rule-actions { display: flex; gap: 0.35rem; justify-content: flex-end; }
@media (max-width: 760px) {
  .alert-rule { grid-template-columns: 1fr auto; }
  .alert-rule-threshold { grid-column: 1 / -1; grid-row: 2; flex-wrap: wrap; }
}

/* ---- Places (#111) ----------------------------------------------------------- */
.places-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 1rem;
  align-items: start;
}
.places-layout > .card { margin-top: 0; }
@media (max-width: 1000px) { .places-layout { grid-template-columns: minmax(0, 1fr); } }
.places-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.9rem; margin-bottom: 0.75rem; }
.places-radius { display: flex; align-items: center; gap: 0.6rem; margin: 0; flex: 1 1 16rem; }
.places-radius input[type="range"] { flex: 1; min-height: 0; padding: 0; border: 0; background: transparent; box-shadow: none; accent-color: var(--accent); }
.places-radius-value { font-family: var(--font-family-mono); font-size: var(--text-sm); color: var(--text); min-width: 4.5rem; }
.areas-map { height: 440px; }
.places-form {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
  gap: 0.6rem 0.75rem;
  align-items: end;
  margin-top: 0.85rem;
}
.places-list { list-style: none; margin: 0.5rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.45rem; }
.place-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem 0.75rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
}
.place-main { display: flex; flex-direction: column; min-width: 0; }
.place-name { color: var(--text); font-weight: var(--font-weight-body-bold); }
.place-meta { font-size: var(--text-xs); }
.place-actions { display: flex; align-items: center; gap: 0.3rem; }
.place-events { list-style: none; margin: 0.3rem 0 0; padding: 0; width: 100%; display: flex; flex-direction: column; gap: 0.3rem; font-size: var(--text-sm); }
.place-events li { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.trip-card-places {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  margin-top: 0.3rem;
  color: var(--body);
  font-size: var(--text-sm);
  font-weight: var(--font-weight-body-medium);
}

/* ---- Driving score & speeding (#124 #125) ---------------------------------- */
.driving-card, .driving-score-card { margin-top: 1.25rem; }
.driving-grid {
  display: grid;
  grid-template-columns: minmax(14rem, 1fr) minmax(0, 1.6fr);
  gap: 1rem 1.5rem;
  margin-top: 0.75rem;
}
@media (max-width: 800px) { .driving-grid { grid-template-columns: minmax(0, 1fr); } }
.driving-speeding { display: flex; flex-direction: column; gap: 0.5rem; min-width: 0; }
.driving-speeding-head { display: flex; flex-direction: column; gap: 0.15rem; }
.driving-speeding-head strong { color: var(--text); }
.speeding-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; max-height: 16rem; overflow-y: auto; }
.speeding-item {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  color: var(--body);
  font: inherit;
  font-size: var(--text-sm);
  font-family: var(--font-family-mono);
  text-align: left;
  cursor: pointer;
}
.speeding-item:hover { border-color: color-mix(in srgb, var(--color-danger) 40%, transparent); color: var(--text); }

/* ---- Vehicle health (#126 #127 #128) --------------------------------------- */
.health-card { margin-top: 1.25rem; }
.health-flags { list-style: none; margin: 0.75rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.health-flag {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid color-mix(in srgb, var(--color-warning) 30%, transparent);
  border-radius: var(--radius-sm);
  background: var(--color-warning-subtle);
  color: var(--text);
  font-size: var(--text-sm);
}
.health-dtc-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.75rem; }
.health-dtc-head .garage-subtitle { margin: 0; }

/* ---- Agent (MCP) tokens ------------------------------------------------------- */
.mcp-issued { flex-wrap: wrap; align-items: center; margin-bottom: 1rem; }
.mcp-token-text { display: block; padding: 0.4rem 0.55rem; border-radius: var(--radius-sm); background: var(--inset); color: var(--text); overflow-wrap: anywhere; font-size: var(--text-sm); }
.mcp-form { margin-bottom: 0.75rem; }
.mcp-scope { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.75rem; display: flex; flex-flow: row wrap; gap: 0.4rem 1rem; }
.mcp-scope legend { padding: 0 0.3rem; color: var(--muted); font-size: var(--text-xs); }
.table tr.is-revoked td { opacity: 0.55; }

/* ---- Notification preferences ------------------------------------------------ */
.notif-prefs { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--border); }
.notif-mute { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0.5rem 0.75rem; margin: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 0.35rem 1rem; }
.notif-mute legend { padding: 0 0.3rem; color: var(--muted); font-size: var(--text-xs); }

/* ---- Raw data retention ---------------------------------------------------------- */
.retention-card { margin-top: 1rem; }
.retention-custom { display: inline-flex; align-items: center; gap: 0.4rem; margin: 0; }
.retention-custom input { width: 6rem; min-height: 34px; padding: 0.3rem 0.5rem; }
