/* core/variables.css */
/* ============================================================
   Design tokens: a 1960s motorist's manual

   Stock and ink
   - Night edition (dark, default): dark stock #1c1a16, cream ink
   - Day edition (html.light-mode): warm paper #f1e8d5, dark ink
   - Spot inks: faded navy (primary, driven), rust (danger,
     undriven), mustard (warning, routes); --manual-* holds the
     printed palette and the semantic tokens below draw from it

   Printing rules
   - Corners are square or nearly so (1-4px); circles only for dots
   - Shadows are flat offsets, never blurred; panels are opaque
   - Type: Source Serif 4 text, condensed Roboto Serif display,
     Libre Franklin labels (see Typography)

   Spacing: 4px grid (0.25rem - 4rem)
   ============================================================ */

:root {
  /* Categorical inks, mixed from the manual's spot colours so charts
     print in the same family. Mid-tones read on both editions.
     Chart order is fixed: cobalt, ochre, steel, coral, slate, purple. */
  --cat-cobalt: #5f82a0;
  --cat-cobalt-rgb: 95 130 160;
  --cat-slate: #857d6e;
  --cat-slate-rgb: 133 125 110;
  --cat-rose: #b5523f;
  --cat-rose-rgb: 181 82 63;
  --cat-steel: #7893a6;
  --cat-steel-rgb: 120 147 166;
  --cat-ochre: #c49d4c;
  --cat-ochre-rgb: 196 157 76;
  --cat-sky: #93acbf;
  --cat-sky-rgb: 147 172 191;
  --cat-amber: #b5824a;
  --cat-amber-rgb: 181 130 74;
  --cat-coral: #c26a4a;
  --cat-coral-rgb: 194 106 74;
  --cat-red-rgb: var(--cat-rose-rgb);
  --cat-purple: #8b6f8a;
  --cat-purple-rgb: 139 111 138;
  --cat-indigo: #5e6789;
  --cat-indigo-rgb: 94 103 137;

  /* Semantic colors */
  --primary: #8fa6b4;
  --primary-light: #a9bcc8;
  --primary-dark: #6f8795;
  --primary-rgb: 143 166 180;
  --secondary: var(--cat-slate);
  --secondary-rgb: var(--cat-slate-rgb);
  --success: var(--primary);
  --success-light: var(--primary-light);
  --success-dark: var(--primary-dark);
  --success-rgb: var(--primary-rgb);
  --warning: var(--cat-ochre);
  --warning-light: #d8b76a;
  --warning-dark: #9c7a33;
  --warning-rgb: var(--cat-ochre-rgb);
  --danger: var(--cat-rose);
  --danger-light: #cf735c;
  --danger-dark: #8f3d2d;
  --danger-rgb: var(--cat-rose-rgb);
  --info: var(--cat-steel);
  --info-light: #98b0c2;
  --info-dark: #4f6b80;
  --info-rgb: var(--cat-steel-rgb);

  /* UI actions are bone-on-ink in light mode and ink-on-bone in dark mode. */
  --action: #ece2cb;
  --action-hover: #f6eedc;
  --action-rgb: 236 226 203;
  --text-on-action: #1c1a16;
  --text-on-warning: #16150f;
  --backdrop-rgb: 0 0 0;
  --print-bg: #fff;
  --print-text: #000;
  --print-border: #ccc;

  /* Map inks. Streets you have driven print in navy, streets still to
     drive in rust, and planned routes in mustard, as on the home page
     plates. Trip paths are a brighter blue so they read over roads. */
  --map-trip-path: #7fb0cf;
  --map-trip-path-rgb: 127 176 207;
  --map-trip-path-selected: #e9dfc6;
  --map-driven: #8fb1c8;
  --map-undriven: #d27b58;
  --map-undriveable: #7d7568;
  --map-route: #dcb35a;
  --map-place: var(--map-driven);
  --map-place-outline: #6e93ad;

  /* Trip heat: how many trips used a road, from once (ember) to the most
     travelled roads (white-hot). Steps are logarithmic; see trip-heat.js. */
  --map-heat-0: #7a3024;
  --map-heat-1: #b2412a;
  --map-heat-2: #e06a2c;
  --map-heat-3: #f5a746;
  --map-heat-4: #fff0c8;

  /* Basemap inks (maps/manual-basemap.js recolours the Mapbox light and
     dark styles with these): dark stock, dim roads, and a dull mustard
     for highways, like a road atlas printed for night reading. */
  --basemap-paper: #1c1a16;
  --basemap-land: #201e19;
  --basemap-green: #23221b;
  --basemap-water: #161b1e;
  --basemap-water-line: #26323a;
  --basemap-building: #2a2721;
  --basemap-road: #39352d;
  --basemap-road-major: #5a4c2f;
  --basemap-casing: #11100d;
  --basemap-rail: #4a453b;
  --basemap-boundary: rgb(213 128 95 / 40%);
  --basemap-label: #b3a88f;
  --basemap-label-strong: #e1d6bd;
  --basemap-label-water: #7893a6;
  --basemap-halo: #1c1a16;

  /* Night edition: warm dark stock and cream ink */
  --surface-deep: #141210;
  --surface-0: #1c1a16;
  --surface-1: #22201b;
  --surface-2: #2a2721;
  --surface-3: #333029;
  --surface-4: #3d3931;
  --surface-elevated: #25221d;
  --surface-rgb: 34 32 27;
  --text-primary: rgb(236 226 203 / 96%);
  --text-secondary: rgb(214 204 182 / 84%);
  --text-tertiary: rgb(176 166 146 / 84%);
  --text-on-primary: #1c1a16;
  --text-on-dark: #1c1a16;
  --border-color: rgb(206 194 168 / 22%);
  --border-color-light: rgb(206 194 168 / 36%);
  --divider-color: rgb(206 194 168 / 12%);
  --border-rgb: 206 194 168;
  --text-rgb: 236 226 203;

  /* ---- Typography -------------------------------------------------
     Set like a 1960s printed manual. Source Serif 4 carries everything
     you read or operate; one condensed cut of Roboto Serif sets titles
     and headline figures; Libre Franklin sets the short uppercase
     labels on buttons, table heads, and running heads. Monospace is
     reserved for machine output (logs and raw payloads) and uses the
     platform face, so it costs nothing to load. Numbers the app
     measured use --font-numeric with tabular figures rather than a
     code face. */
  --font-family-text: "Source Serif 4", ui-serif, georgia, "Times New Roman", serif;
  --font-family-display: "Roboto Serif", var(--font-family-text);
  --font-family-label:
    "Libre Franklin", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-family-mono:
    ui-monospace, sfmono-regular, "SF Mono", menlo, consolas, "Liberation Mono", monospace;
  --font-family: var(--font-family-text);
  --font-numeric: var(--font-family-text);
  --font-numeric-display: var(--font-family-display);

  /* Type scale. Steps are fixed below the display sizes: when every
     step carried its own vw coefficient the hierarchy collapsed on
     wide screens (sm and md landed within 0.3px of each other) and
     shrank below the legibility floor on phones. Display sizes stay
     fluid because that is where the extra range actually reads. */
  --font-size-xs: 0.75rem; /* 12px — eyebrows, table heads, meta */
  --font-size-sm: 0.875rem; /* 14px — controls, dense UI, captions */
  --font-size-md: 1rem; /* 16px — body */
  --font-size-base: var(--font-size-md);
  --font-size-lg: 1.125rem; /* 18px — lead paragraphs, card titles */
  --font-size-xl: 1.3125rem; /* 21px — section headings */
  --font-size-2xl: clamp(1.5rem, 1.36rem + 0.7vw, 1.875rem); /* 24 → 30px */
  --font-size-3xl: clamp(1.875rem, 1.61rem + 1.32vw, 2.5rem); /* 30 → 40px */
  --font-size-4xl: clamp(2.25rem, 1.66rem + 2.95vw, 3.5rem); /* 36 → 56px */
  --font-size-5xl: clamp(2.75rem, 1.55rem + 5.4vw, 5.25rem); /* 44 → 84px */
  --font-weight-regular: 400;
  --font-weight-normal: var(--font-weight-regular);
  --font-weight-medium: 500;
  --font-weight-semibold: 600;
  --font-weight-bold: 700;
  --line-height-tight: 1.1; /* display type */
  --line-height-snug: 1.3; /* headings, card titles, wrapped labels */
  --line-height-normal: 1.5; /* UI default */
  --line-height-relaxed: 1.65; /* prose */

  /* Letter-spacing. Large type tightens; small uppercase labels open
     just enough to stay legible. Body text is never tracked — wide
     tracking on running text is what made the interface read as a
     machine readout instead of a record. */
  --tracking-tight: -0.02em;
  --tracking-snug: -0.01em;
  --tracking-normal: 0;
  --tracking-wide: 0.02em;
  --tracking-caps: 0.06em;
  --tracking-display: -0.035em; /* condensed display headlines */
  --tracking-label: 0.16em; /* printed-manual running labels */

  /* Motorist's manual (home page). A printed field guide: warm stock,
     dark ink, and three spot inks. Dark mode is the night edition,
     cream ink on dark stock; "solid" is the heaviest fill either way. */
  --manual-paper: #1c1a16;
  --manual-paper-rgb: 28 26 22;
  --manual-paper-shade: #25221c;
  --manual-ink: #ece2cb;
  --manual-ink-rgb: 236 226 203;
  --manual-ink-soft: #c2b79f;
  --manual-ink-faint: #9b917c;
  --manual-solid: #0f0e0b;
  --manual-solid-rgb: 15 14 11;
  --manual-navy: #8fa6b4;
  --manual-navy-rgb: 143 166 180;
  --manual-rust: #d5805f;
  --manual-rust-rgb: 213 128 95;
  --manual-rust-ink: #dd8d6c;
  --manual-mustard: #cfae5c;
  --manual-mustard-rgb: 207 174 92;
  --manual-rule: rgb(var(--manual-ink-rgb) / 42%);
  --manual-rule-faint: rgb(var(--manual-ink-rgb) / 22%);
  /* Squared survey paper behind small route drawings */
  --manual-grid:
    linear-gradient(rgb(var(--manual-ink-rgb) / 9%) 1px, transparent 1px),
    linear-gradient(90deg, rgb(var(--manual-ink-rgb) / 9%) 1px, transparent 1px);
  --manual-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .96 0 0 0 0 .86 0 0 0 .075 0'/%3E%3C/filter%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.012' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .96 0 0 0 0 .86 0 0 0 .05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");

  /* Comfortable measure for running text */
  --measure: 68ch;
  --measure-tight: 54ch;

  /* Spacing System (4px grid) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;

  /* Layout rhythm */
  --page-gutter: clamp(1rem, 2.6vw, 2.75rem);
  --page-gutter-tight: clamp(0.75rem, 2.1vw, 1.5rem);
  --section-gap: clamp(1.25rem, 2.4vw, 2.5rem);
  --card-padding: clamp(1rem, 1.6vw, 1.5rem);
  --card-padding-lg: clamp(1.25rem, 2.1vw, 2rem);

  /* Layout */

  /* Visual bar is 64px; on notched devices the header also covers the top
     safe-area inset so its content is not clipped under the status bar/notch.
     Every consumer that offsets content below the header references this var,
     so baking the inset in here keeps the whole app aligned in one place. */
  --header-bar-height: 64px;
  --header-height: calc(var(--header-bar-height) + env(safe-area-inset-top, 0px));
  --content-max-width: 1440px;

  /* Effects */
  --transition-fast: 180ms cubic-bezier(0.4, 0, 0.2, 1);
  --transition-normal: 260ms cubic-bezier(0.4, 0, 0.2, 1);
  /* Printed shadows: flat offsets, no blur */
  --shadow-xs: 0 1px 0 rgb(0 0 0 / 30%);
  --shadow-sm: 2px 2px 0 rgb(0 0 0 / 32%);
  --shadow-md: 3px 3px 0 rgb(0 0 0 / 38%);
  --shadow-lg: 4px 4px 0 rgb(0 0 0 / 42%);
  --shadow-xl: 6px 6px 0 rgb(0 0 0 / 45%);
  --shadow-inset: inset 0 1px 0 rgb(0 0 0 / 20%);


  /* Semantic street colors */
  --color-undriven: var(--map-undriven);
  --color-driven: var(--map-driven);
  --live: var(--primary);

  /* Toggle/switch */
  --toggle-knob: var(--surface-1);
  --toggle-track-off: rgb(var(--border-rgb) / 25%);
  --toggle-track-on: var(--primary);

  /* Border radius: printed corners, nearly square */
  --radius-xs: 1px;
  --radius-sm: 2px;
  --radius-md: 2px;
  --radius-lg: 3px;
  --radius-xl: 3px;
  --radius-2xl: 4px;
  --radius-full: 9999px; /* dots, knobs, and other true circles only */

  /* Focus */
  --focus-ring: 0 0 0 2px var(--manual-rust);
  --focus-ring-strong: 0 0 0 2px var(--manual-paper), 0 0 0 4px var(--manual-rust);
  --focus-outline: 2px solid var(--manual-rust);

  /* Touch targets */
  --touch-target: 44px;

  /* Z-Index */
  --z-base: 1;
  --z-dropdown: 1000;
  --z-fixed: 1030;
  --z-drawer: 1040;
  --z-modal-backdrop: 1050;
  --z-modal: 1055;
  --z-popover: 1060;
  --z-tooltip: 1070;
  --z-overlay: 1080;
  --z-loading-overlay: 9999;

  /* Scrollbar */
  --scrollbar-thumb-color: rgb(var(--border-rgb) / 45%);
  --scrollbar-track-color: transparent;
  --scrollbar-thumb-hover-color: rgb(var(--border-rgb) / 65%);

  /* Utility Aliases */
  --border-hover: var(--border-color-light);

  /* Bootstrap Bridge */
  --bs-body-font-family: var(--font-family);
  --bs-body-font-size: var(--font-size-md);
  --bs-body-bg: var(--surface-0);
  --bs-body-bg-rgb: var(--surface-rgb);
  --bs-body-color: var(--text-primary);
  --bs-secondary-color: var(--text-secondary);
  --bs-tertiary-color: var(--text-tertiary);
  --bs-secondary-bg: var(--surface-2);
  --bs-tertiary-bg: var(--surface-3);
  --bs-border-color: var(--border-color);
  --bs-border-radius: var(--radius-lg);
  --bs-border-radius-sm: var(--radius-md);
  --bs-border-radius-lg: var(--radius-xl);
  --bs-border-radius-xl: var(--radius-xl);
  --bs-border-radius-xxl: calc(var(--radius-xl) + 4px);
  --bs-border-radius-pill: var(--radius-sm);
  --bs-primary: var(--primary);
  --bs-primary-rgb: var(--primary-rgb);
  --bs-secondary: var(--secondary);
  --bs-secondary-rgb: var(--secondary-rgb);
  --bs-success: var(--success);
  --bs-success-rgb: var(--success-rgb);
  --bs-info: var(--info);
  --bs-info-rgb: var(--info-rgb);
  --bs-warning: var(--warning);
  --bs-warning-rgb: var(--warning-rgb);
  --bs-danger: var(--danger);
  --bs-danger-rgb: var(--danger-rgb);
  --bs-light: var(--surface-2);
  --bs-dark: var(--surface-4);
  --bs-link-color: var(--primary);
  --bs-link-hover-color: var(--primary-dark);
  --bs-box-shadow: var(--shadow-sm);
  --bs-focus-ring-color: rgb(var(--manual-ink-rgb) / 30%);
}

/* Light mode overrides — warm paper, like a printed street map */
html.light-mode,
html.light-mode body {
  --surface-deep: #f7f0e1;
  --surface-0: #f1e8d5;
  --surface-1: #f5eddd;
  --surface-2: #ebe1cb;
  --surface-3: #e2d6bd;
  --surface-4: #d5c7aa;
  --surface-elevated: #f8f2e5;
  --surface-rgb: 245 237 221;
  --text-primary: rgb(48 45 37 / 96%);
  --text-secondary: rgb(72 66 54 / 90%);
  --text-tertiary: rgb(92 85 70 / 92%);

  /* Motorist's manual, day edition */
  --manual-paper: #f1e8d5;
  --manual-paper-rgb: 241 232 213;
  --manual-paper-shade: #e7dbc1;
  --manual-ink: #302d25;
  --manual-ink-rgb: 48 45 37;
  --manual-ink-soft: #564f41;
  --manual-ink-faint: #6b6353;
  --manual-solid: #302d25;
  --manual-solid-rgb: 48 45 37;
  --manual-navy: #465b68;
  --manual-navy-rgb: 70 91 104;
  --manual-rust: #a6533d;
  --manual-rust-rgb: 166 83 61;
  --manual-rust-ink: #954632;
  --manual-mustard: #b39343;
  --manual-mustard-rgb: 179 147 67;
  --manual-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .19 0 0 0 0 .17 0 0 0 0 .13 0 0 0 .11 0'/%3E%3C/filter%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.012' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .45 0 0 0 0 .36 0 0 0 0 .2 0 0 0 .07 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E");

  /* Faded navy: links and primary actions clear AA on the paper. */
  --primary: #465b68;
  --primary-light: #5a7282;
  --primary-dark: #37495a;
  --primary-rgb: 70 91 104;
  --text-on-primary: #fbf7ee;
  --action: #302d25;
  --action-hover: #4a453a;
  --action-rgb: 48 45 37;
  --text-on-action: #f1e8d5;
  --border-color: rgb(48 45 37 / 20%);
  --border-color-light: rgb(48 45 37 / 32%);
  --divider-color: rgb(48 45 37 / 11%);
  --border-rgb: 48 45 37;
  --text-rgb: 48 45 37;
  --shadow-xs: 0 1px 0 rgb(48 45 37 / 10%);
  --shadow-sm: 2px 2px 0 rgb(48 45 37 / 10%);
  --shadow-md: 3px 3px 0 rgb(48 45 37 / 13%);
  --shadow-lg: 4px 4px 0 rgb(48 45 37 / 15%);
  --shadow-xl: 6px 6px 0 rgb(48 45 37 / 17%);
  --scrollbar-thumb-color: rgb(var(--border-rgb) / 28%);
  --scrollbar-track-color: rgb(var(--border-rgb) / 6%);
  --scrollbar-thumb-hover-color: rgb(var(--border-rgb) / 42%);

  --toggle-knob: var(--surface-0);
  --map-trip-path: #2f6f95;
  --map-trip-path-rgb: 47 111 149;
  --map-trip-path-selected: #302d25;
  --map-driven: #3f6782;
  --map-undriven: #b0573a;
  --map-undriveable: #8f8676;
  --map-route: #a88430;
  --map-place-outline: #2f5068;

  /* On paper the busiest roads print deepest, so heat runs from a pale
     terracotta to a dark garnet instead of towards white. */
  --map-heat-0: #d9a27c;
  --map-heat-1: #d0703f;
  --map-heat-2: #bf3f2a;
  --map-heat-3: #95192c;
  --map-heat-4: #5a0d26;
  --basemap-paper: #efe6d1;
  --basemap-land: #ebe1ca;
  --basemap-green: #e2dbbf;
  --basemap-water: #c3cfd2;
  --basemap-water-line: #9fb3bb;
  --basemap-building: #e0d4ba;
  --basemap-road: #faf5e8;
  --basemap-road-major: #eed9a0;
  --basemap-casing: rgb(48 45 37 / 30%);
  --basemap-rail: #8c8373;
  --basemap-boundary: rgb(166 83 61 / 45%);
  --basemap-label: #564f41;
  --basemap-label-strong: #302d25;
  --basemap-label-water: #4f6b80;
  --basemap-halo: #f1e8d5;


}

/* core/reset.css */
/* ============================
   Base Reset & Typography
   ============================ */

/* === Core Reset & Base Styles === */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent; /* Remove tap highlight on mobile */
}

/* The root keeps the user's browser font size. It previously set
   font-size to a rem-based token, which re-scaled the rem unit itself:
   every size and spacing token then compounded off a ~15px root and the
   whole interface rendered a step smaller than it was designed to. */
html {
  height: 100%;
  scroll-behavior: smooth;
  background-color: var(--surface-0);
}

body {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  background-color: var(--surface-0);
  color: var(--text-primary);
  font-family: var(--font-family);
  line-height: var(--line-height-normal);
  position: relative;
  z-index: 0;
  transition:
    background-color var(--transition-normal),
    color var(--transition-normal);
  overflow-x: hidden; /* Prevent horizontal scroll */
}

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

::-webkit-scrollbar-track {
  background: var(--scrollbar-track-color);
  border-radius: var(--radius-sm);
}

::-webkit-scrollbar-thumb {
  background-color: var(--scrollbar-thumb-color);
  border-radius: var(--radius-sm);
  border: 2px solid transparent; /* Creates padding around thumb */
  background-clip: content-box;
}

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

/* For Firefox */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
}

/* === Container layout === */
.container-fluid,
.container {
  width: 100%;
  padding-right: var(--page-gutter);
  padding-left: var(--page-gutter);
  margin-right: auto;
  margin-left: auto;
}

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

/* core/typography.css */
/* ============================================================
   Typography

   Set like a printed manual: Source Serif 4 for everything you read
   or operate, a condensed Roboto Serif for titles and headline
   figures, and Libre Franklin for short uppercase labels. Monospace
   appears only where the app is showing machine output verbatim.

   Rules of the system:
   - Size comes from the scale tokens, never from a literal.
   - Tracking comes from the tracking tokens. Body text is untracked.
   - Uppercase is for short labels only, set in the label face and tracked.
   - Measured numbers get tabular figures, not a code font.
   ============================================================ */

/* Thinning light-on-dark text keeps it from blooming. On warm paper the
   same setting makes ink look anemic, so light mode keeps the default. */
body {
  font-family: var(--font-family);
  font-size: var(--font-size-md);
  line-height: var(--line-height-normal);
  letter-spacing: var(--tracking-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

html.light-mode body {
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
}

/* === Headings ==============================================
   The UA heading scale is relative to the parent, so nested h5/h6
   ended up smaller than body text. These are absolute steps. h1 and
   h2 are set in the condensed display cut (it has one weight, made
   for large sizes); smaller headings use the text face in bold, which
   holds its spacing at body sizes. */
h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-family-display);
  font-weight: 800;
  line-height: var(--line-height-snug);
  letter-spacing: var(--tracking-snug);
  color: var(--text-primary);
  text-wrap: balance;
}

h1,
h2 {
  line-height: var(--line-height-tight);
}

h1 {
  font-size: var(--font-size-3xl);
  letter-spacing: var(--tracking-tight);
}

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

h3,
h4,
h5,
h6,
.h4,
.h5,
.h6 {
  font-family: var(--font-family-text);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-normal);
}

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

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

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

/* h6 carries real section titles in this app, so it stays a small heading
   rather than a label role. Pages that want an eyebrow use their own class. */
h6 {
  font-size: var(--font-size-sm);
}

/* === Prose ================================================= */
p {
  line-height: var(--line-height-relaxed);
  text-wrap: pretty;
}

.route-content p,
.route-content .text-muted,
.route-content .text-secondary {
  max-width: var(--measure);
}

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

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

a {
  text-underline-offset: 0.16em;
  text-decoration-thickness: from-font;
}

/* === Measured numbers ======================================
   The app used a code face for every value it measured, which is what
   gave the interface its terminal look. Values now stay in the text
   face and earn their alignment from tabular lining figures, so a
   column of numbers lines up without changing voice mid-sentence.
   Tracking is explicitly cleared: figures are already evenly spaced,
   and inherited tracking is what makes digits look mechanical. */
[data-numeric],
.counter,
.metric-value,
.stat-value,
.preview-stat-value,
.live-trip-hud-speed,
.nav-stat .value,
.meta-value,
.numeric,
.data-num {
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: var(--tracking-normal);
}

/* Hero figures are set in the display serif: at this size the serif
   reads as an engraved measurement rather than a dashboard counter. */
.figure-value,
.stat-value,
.preview-stat-value {
  font-family: var(--font-numeric-display);
}

/* === Machine output ======================================== */
code,
kbd,
samp,
pre {
  font-family: var(--font-family-mono);
  font-size: 0.9375em;
  font-variant-ligatures: none;
}


/* core/utilities.css */
/* ============================
   Utility Classes
   ============================ */

/* === Text Utilities === */
.text-primary {
  color: var(--primary);
}

.bg-body-secondary {
  background-color: var(--surface-2) !important;
}

.text-secondary {
  color: var(--text-secondary);
} /* Note: this is different from --secondary color */

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

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

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

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

/* Badges and chips are small printed stamps: Franklin caps in a rule. */
.badge {
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  font-family: var(--font-family-label);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 1.75rem;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  background: transparent;
  color: var(--manual-ink-soft);
  font-family: var(--font-numeric);
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
}

.badge--success,
.badge.bg-success,
.badge.bg-primary,
.badge.bg-info {
  background: rgb(var(--manual-navy-rgb) / 12%) !important;
  border-color: rgb(var(--manual-navy-rgb) / 60%);
  color: var(--manual-navy) !important;
}

.badge.bg-warning {
  background: rgb(var(--manual-mustard-rgb) / 18%) !important;
  border-color: var(--manual-mustard);
  color: var(--manual-ink) !important;
}

.badge.bg-danger {
  background: rgb(var(--danger-rgb) / 10%) !important;
  border-color: rgb(var(--danger-rgb) / 60%);
  color: var(--manual-rust-ink) !important;
}

.badge.bg-secondary,
.badge.bg-dark,
.badge.bg-light {
  background: transparent !important;
  border-color: var(--manual-rule);
  color: var(--manual-ink-soft) !important;
}

.rounded,
.rounded-3 {
  border-radius: var(--radius-xs) !important;
}

.rounded-pill {
  border-radius: var(--radius-sm) !important;
}

.text-dark {
  color: var(--text-primary);
} /* For darker text on light backgrounds */

.bg-primary {
  background-color: var(--primary);
  color: var(--text-on-primary);
}

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

/* Disable animated progress stripes */
.progress-bar-animated {
  animation: none;
}

/* === Visibility === */
.visually-hidden,
.visually-hidden-focusable:not(:focus, :active) {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* === Animation Classes === */
.fade-in {
  animation: fadeIn 0.3s ease forwards;
}

.spinner {
  animation: spin 0.8s linear infinite;
} /* Generic spinner class */

/* === Accessibility === */

body[data-viewer-mode="true"] .owner-only {
  display: none !important;
}

/* Focus visible for keyboard users, not for mouse users */
:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 2px;
  box-shadow: var(--focus-ring);
}

/* Remove default outline if :focus-visible is supported and not matched */
:focus:not(:focus-visible) {
  outline: none;
}

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

/* High contrast mode support - merged into single block below */

/* Status indicator dots */
.status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--text-tertiary);
}

.status-dot.active {
  background: var(--live);
}

.status-dot.warning {
  background: var(--warning);
}

.status-dot.error {
  background: var(--danger);
}

/* High contrast mode */
@media (prefers-contrast: high) {
  :root {
    --border-color: rgb(var(--border-rgb) / 50%);
    --divider-color: rgb(var(--border-rgb) / 40%);
  }

  .card,
  .control-panel,
  .widget,
  .modal-content,
  .notification {
    border: 2px solid currentcolor;
  }

  .btn {
    border-width: 2px;
    border-style: solid;
  }

  .form-control,
  .form-select {
    border-width: 2px;
    border-color: currentcolor;
  }

  .table th,
  .table td {
    border-bottom-width: 2px;
  }
}

/* Ensure sufficient touch targets */

/* Reduced motion preferences already defined in animations.css and utilities.css */

/* === Print Styles === */
@media print {
  body {
    background-color: var(--print-bg);
    color: var(--print-text);
    font-size: 12pt; /* Readable print size */
    line-height: 1.4;
  }

  .app-header,
  .mobile-nav-drawer,
  .tools-section,
  .menu-toggle-btn,
  .notification-container,
  .loading-overlay,
  .control-panel,
  .btn,
  #atlas-rail /* Hide the map's atlas rail when printing */ {
    display: none;
  }

  .main-content {
    padding-top: 0;
    margin-left: 0;
  }

  .card {
    box-shadow: none;
    border: 1px solid var(--print-border);
    break-inside: avoid;
  }

  .table,
  .table th,
  .table td {
    border-color: var(--print-border);
  }

  a {
    text-decoration: none;
    color: var(--print-text);
  }

  a[href^="http"]::after {
    content: " (" attr(href) ")"; /* Show URLs for external links */
    font-size: 90%;
  }

  #map {
    /* Ensure map takes up space if it's the primary content */
    position: static;
    height: auto; /* Or specific print height */
    width: 100%;
    break-inside: avoid;
  }

  .container,
  .container-fluid {
    max-width: 100%;
    padding: 0;
    margin: 0;
  }
}

/* layout/header.css */
/* ============================
   Header & Navigation
   ============================ */

/* === Layout Structure === */
.layout-wrapper {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  position: relative;
  z-index: 1;
}

/* === Header — solid editorial masthead bar === */
.app-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--header-height);
  background: var(--surface-0);
  border-bottom: 1px solid var(--border-color);
  z-index: var(--z-fixed);
  transition:
    box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1),
    border-color 200ms cubic-bezier(0.4, 0, 0.2, 1);
  contain: layout style;
  background-color: var(--manual-paper);
  border-bottom-color: transparent;
  box-shadow: none;
}

.app-header.scrolled {
  box-shadow: var(--shadow-xs);
  border-bottom-color: var(--border-color-light);
}

.header-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;

  /* Keep header content below the top safe-area inset (notch/status bar). */
  padding: env(safe-area-inset-top, 0) var(--page-gutter) 0;
  max-width: var(--content-max-width);
  margin: 0 auto;
  width: 100%;
  gap: var(--space-3);
  position: relative;
}

/* === Brand Section === */
.brand-section {
  display: flex;
  align-items: center;
}

.menu-toggle-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  border-radius: var(--radius-full);
  border: none;
  background: transparent;
  color: var(--text-secondary);
  margin-right: var(--space-3);
  cursor: pointer;
  transition:
    background-color 120ms cubic-bezier(0.4, 0, 0.2, 1),
    color 120ms cubic-bezier(0.4, 0, 0.2, 1);
}

.menu-toggle-btn:hover {
  background-color: var(--surface-3);
  color: var(--text-primary);
}

.brand-logo {
  display: flex;
  align-items: center;
  color: var(--manual-ink);
  text-decoration: none;
  gap: var(--space-3);
}

.brand-wordmark,
.brand-monogram {
  font-family: var(--font-family-display);
  font-weight: 800;
  font-size: var(--font-size-2xl);
  letter-spacing: var(--tracking-display);
  line-height: 1;
  color: var(--manual-ink);
  white-space: nowrap;
}

.brand-monogram {
  display: none;
}

/* === Main Navigation === */
.main-nav {
  height: 100%;
}

.nav-list {
  display: flex;
  align-items: center;
  height: 100%;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: var(--space-1);
}

.nav-item {
  height: 100%;
  position: relative;
  display: flex;
  align-items: center;
}

.nav-item a {
  display: flex;
  align-items: center;
  height: 100%;
  padding: 0 var(--space-3);
  color: var(--manual-ink-soft);
  text-decoration: none;
  transition: color 150ms cubic-bezier(0.4, 0, 0.2, 1);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-normal);
  background-color: transparent;
  position: relative;
  font-family: var(--font-family-text);
}

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

.nav-item.active a::after {
  content: "";
  position: absolute;
  bottom: 10px;
  left: var(--space-3);
  right: var(--space-3);
  height: 1.5px;
  background: var(--manual-ink);
}

/* Editorial nav is type-led: the "More" caret is the only glyph */
.nav-item .nav-caret {
  margin-left: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--manual-ink-soft);
  transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-item .dropdown-toggle::after {
  display: none;
}

.nav-item .dropdown-toggle[aria-expanded="true"] .nav-caret {
  transform: rotate(180deg);
}

/* === Dropdown Menus — solid panels, hairline borders === */
.dropdown-menu {
  background: var(--surface-1);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--space-2) 0;
  min-width: 220px;
  z-index: var(--z-dropdown);
  animation: dropdownReveal 180ms cubic-bezier(0, 0, 0.2, 1) both;
  transform-origin: top center;
}

@keyframes dropdownReveal {
  from {
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
  }

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

.dropdown-item {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-4);
  color: var(--text-secondary);
  font-size: var(--font-size-sm);
  transition:
    background-color 120ms cubic-bezier(0.4, 0, 0.2, 1),
    color 120ms cubic-bezier(0.4, 0, 0.2, 1);
}

.dropdown-item:hover,
.dropdown-item.active {
  background-color: var(--surface-2);
  color: var(--text-primary);
}

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

/* Dropdown Headers for Grouped Menus */
.dropdown-header {
  padding: var(--space-2) var(--space-4);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  cursor: default;
}

.dropdown-menu-grouped {
  min-width: 240px;
}

/* === Tools Section === */
.tools-section {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* === Theme Toggle — quiet icon button (checkbox under the hood) === */
.theme-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  cursor: pointer;
  border-radius: var(--radius-full);
  color: var(--text-secondary);
  transition:
    color 150ms cubic-bezier(0.4, 0, 0.2, 1),
    background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
}

.theme-toggle:hover {
  color: var(--text-primary);
  background-color: var(--surface-2);
}

.theme-toggle input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}

.theme-toggle input:focus-visible + .theme-slider {
  outline: var(--focus-outline);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.theme-slider {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-sm);
}

/* === Mobile Navigation Drawer === */
.mobile-nav-drawer {
  position: fixed;
  top: 0;
  left: 0;
  width: 85%;
  max-width: 320px;
  height: 100%;
  background: var(--manual-paper);
  border-right: 1.5px solid var(--manual-ink);
  z-index: var(--z-drawer);
  /* Closed, the drawer sits past its own offset shadow and is hidden
     from focus once it has slid away. */
  transform: translateX(calc(-100% - 8px));
  visibility: hidden;
  transition:
    transform 280ms cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 280ms;
  box-shadow: 4px 0 0 var(--manual-rule-faint);
  display: flex;
  flex-direction: column;
  contain: layout style paint; /* Performance hint */
}

.mobile-nav-drawer.open {
  transform: translateX(0);
  visibility: visible;
  transition: transform 280ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Ensure all links in mobile nav drawer are properly styled */
.mobile-nav-drawer a,
.mobile-nav-drawer a:link,
.mobile-nav-drawer a:visited {
  color: var(--manual-ink-soft);
  text-decoration: none;
  font-family: var(--font-family-text);
}

.mobile-nav-drawer a:hover,
.mobile-nav-drawer a:focus {
  color: var(--manual-ink);
  text-decoration: none;
  background-color: var(--manual-paper-shade);
}

/* Ensure all lists in mobile nav drawer have no bullets */
.mobile-nav-drawer ul,
.mobile-nav-drawer ol,
.mobile-nav-drawer li {
  list-style: none;
  padding-left: 0;
  margin-left: 0;
}

.drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4);
  border-bottom: 3px double var(--manual-ink);
}

.drawer-title {
  font-size: var(--font-size-2xl);
  font-weight: 800;
  font-family: var(--font-family-display);
  letter-spacing: var(--tracking-display);
  color: var(--manual-ink);
}

.drawer-close-btn {
  background: transparent;
  border: none;
  color: var(--manual-ink);
  font-size: var(--font-size-xl);
  cursor: pointer;
  padding: var(--space-2); /* Larger tap target */
  transition: color 120ms cubic-bezier(0.4, 0, 0.2, 1);
}

.drawer-close-btn:hover {
  color: var(--text-primary);
}

.drawer-nav {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-2) 0; /* Reduced top/bottom padding */
}

/* === Drawer Navigation Sections (Grouped) === */
.drawer-nav-section {
  border-bottom: 1px solid var(--divider-color);
  border-bottom-color: var(--manual-rule-faint);
}

.drawer-nav-section:last-child {
  border-bottom: none;
}

.drawer-nav-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: var(--space-3) var(--space-4);
  background: transparent;
  border: none;
  color: var(--manual-rust-ink);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  cursor: pointer;
  transition:
    color 120ms cubic-bezier(0.4, 0, 0.2, 1),
    background-color 120ms cubic-bezier(0.4, 0, 0.2, 1);
  font-family: var(--font-family-label);
}

.drawer-nav-section-header:hover {
  background-color: var(--manual-paper-shade);
  color: var(--manual-rust-ink);
}

.drawer-nav-section-title {
  flex: 1;
  text-align: left;
}

.drawer-nav-section-chevron {
  font-size: var(--font-size-xs);
  transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1);
}

.drawer-nav-section-header[aria-expanded="false"] .drawer-nav-section-chevron {
  transform: rotate(-90deg);
}

.mobile-nav-drawer .drawer-nav-section-list,
.drawer-nav-section-list,
.mobile-nav-drawer ul,
.drawer-nav ul {
  list-style: none;
  padding: 0;
  margin: 0;
  overflow: hidden auto;
  max-height: min(70vh, calc(100vh - var(--header-height, 4rem) - var(--space-8)));
  transition:
    max-height 280ms cubic-bezier(0.4, 0, 0.2, 1),
    opacity 200ms cubic-bezier(0.4, 0, 0.2, 1);
  opacity: 1;
}

.mobile-nav-drawer .drawer-nav-section-list li,
.drawer-nav-section-list li,
.mobile-nav-drawer ul li,
.drawer-nav ul li {
  list-style: none;
  margin: 0;
  padding: 0;
}

.drawer-nav-section-list.collapsed {
  max-height: 0;
  overflow: hidden;
  opacity: 0;
}

.mobile-nav-drawer .drawer-nav-section-list li a,
.drawer-nav-section-list li a {
  display: flex;
  align-items: center;
  padding: var(--space-2) var(--space-4) var(--space-2) var(--space-5);
  color: var(--text-secondary);
  text-decoration: none;
  font-size: var(--font-size-sm);
  transition:
    background-color 120ms cubic-bezier(0.4, 0, 0.2, 1),
    color 120ms cubic-bezier(0.4, 0, 0.2, 1);
  border-left: 3px solid transparent;
}

.mobile-nav-drawer .drawer-nav-section-list li a:link,
.mobile-nav-drawer .drawer-nav-section-list li a:visited,
.drawer-nav-section-list li a:link,
.drawer-nav-section-list li a:visited {
  color: var(--text-secondary);
  text-decoration: none;
}

.mobile-nav-drawer .drawer-nav-section-list li a:hover,
.drawer-nav-section-list li a:hover {
  background-color: var(--surface-2);
  color: var(--text-primary);
}

.mobile-nav-drawer .drawer-nav-section-list li a.active,
.drawer-nav-section-list li a.active {
  background-color: var(--surface-2);
  color: var(--text-primary);
  border-left-color: var(--action);
  font-weight: var(--font-weight-medium);
}

/* ===========================================
   Mobile Header Styles (Colocated from mobile.css)
   =========================================== */

@media (width <= 992px) {
  /* Tablet and smaller — nav labels stay; just tighten the rhythm */
  .nav-item a {
    padding: 0 var(--space-2);
    letter-spacing: var(--tracking-caps);
  }

  .header-container {
    padding: 0 var(--page-gutter-tight);
  }
}

@media (width <= 768px) {
  /* Mobile landscape and smaller */
  .header-container {
    padding: 0 var(--page-gutter-tight);
  }

  .brand-wordmark {
    /* Compact monogram replaces the wordmark */
    display: none;
  }

  .brand-monogram {
    display: inline;
  }

  .main-nav {
    /* Hide desktop nav, mobile drawer takes over */
    display: none;
  }

  .menu-toggle-btn {
    /* Ensure menu toggle is always visible */
    display: flex;
  }
}

@media (width <= 576px) {
  /* Mobile portrait - notification adjustments */
  .notification-container {
    left: var(--space-2);
    right: var(--space-2);
    top: var(--space-2);
    max-width: calc(100% - var(--space-4));
  }
}

.header-container::after {
  content: "";
  position: absolute;
  left: var(--page-gutter);
  right: var(--page-gutter);
  bottom: 0;
  border-bottom: 3px double var(--manual-ink);
}

.brand-logo::after {
  content: "";
  width: 46px;
  height: 22px;
  background-color: var(--manual-ink);
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 46 22' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 15l8-8 4 4 7-9 6 7 3-3 7 8' stroke-width='1.4'/%3E%3Cpath d='M17 21c3-4 9-5 10-8s-2-4 1-6' stroke-width='1.3'/%3E%3Cpath d='M24 21c2-3 7-4 7-7s-2-4 0-6' stroke-width='1'/%3E%3Cpath d='M36 20l2-6 2 6zM41 20l1.5-4.5L44 20z' stroke-width='1'/%3E%3C/svg%3E")
    center / contain no-repeat;
}

.nav-item a:hover,
.nav-item.active a {
  color: var(--manual-ink);
}

.notif-bell-btn,
.theme-toggle,
.menu-toggle-btn {
  color: var(--manual-ink-soft);
}

.notif-bell-btn:hover,
.theme-toggle:hover,
.menu-toggle-btn:hover {
  color: var(--manual-ink);
  background-color: var(--manual-paper-shade);
}

.app-header .dropdown-menu {
  padding: var(--space-2) 0;
  border: 1px solid var(--manual-ink);
  border-radius: 0;
  background: var(--manual-paper);
  box-shadow: 3px 3px 0 var(--manual-rule-faint);
}

.app-header .dropdown-header {
  padding: var(--space-3) var(--space-4) var(--space-1);
  font-family: var(--font-family-label);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-label);
  color: var(--manual-rust-ink);
}

.app-header .dropdown-menu .dropdown-item {
  padding: var(--space-2) var(--space-4);
  font-family: var(--font-family-text);
  font-size: var(--font-size-sm);
  color: var(--manual-ink-soft);
}

.app-header .dropdown-item:hover,
.app-header .dropdown-item:focus-visible {
  background-color: var(--manual-paper-shade);
  color: var(--manual-ink);
}

.app-header .dropdown-item.active {
  background-color: transparent;
  color: var(--manual-ink);
  box-shadow: inset 2px 0 0 var(--manual-rust);
}

.app-header .dropdown-divider {
  background-color: var(--manual-rule-faint);
}

.mobile-nav-drawer a.active {
  color: var(--manual-ink);
  box-shadow: inset 3px 0 0 var(--manual-rust);
}

.drawer-close-btn:focus-visible,
.menu-toggle-btn:focus-visible,
.notif-bell-btn:focus-visible,
.app-header .nav-item a:focus-visible {
  outline: 2px solid var(--manual-rust);
  outline-offset: 2px;
}

/* layout/layout.css */
/* ============================
   Layout Structure & Panels
   ============================ */

/* === Main Content === */
.main-content {
  flex-grow: 1;
  padding-top: var(--header-height);
  display: flex;
  flex-direction: column;
  position: relative;
  /* Clip without becoming a scroll container: the body scrolls, and
     sticky panels inside pages stay pinned to the viewport. */
  overflow: clip;
}

/* === Map Containers === */
.map-container-standard {
  width: 100%;
  height: 600px;
  border-radius: var(--radius-xl);
  background-color: var(--surface-1);
  overflow: hidden;
  position: relative;
}

@media (width <= 768px) {
  .map-container-standard {
    height: 400px;
  }
}

/* === Content Grid === */
.content-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--section-gap);
  align-items: stretch;
}

.content-grid > * {
  min-width: 0;
}

.grid-span-12 {
  grid-column: span 12;
}

.grid-span-8 {
  grid-column: span 8;
}

.grid-span-7 {
  grid-column: span 7;
}

.grid-span-6 {
  grid-column: span 6;
}

.grid-span-5 {
  grid-column: span 5;
}

.grid-span-4 {
  grid-column: span 4;
}

@media (width <= 1200px) {
  .content-grid {
    grid-template-columns: repeat(8, minmax(0, 1fr));
  }
}

@media (width <= 992px) {
  .content-grid {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

@media (width <= 768px) {
  .content-grid {
    grid-template-columns: 1fr;
    gap: var(--space-4);
  }

  .content-grid > * {
    grid-column: 1 / -1;
  }
}

.persistent-shell {
  display: none;
  flex: 1 1 auto;
  min-height: 0;
  position: relative;
  flex-direction: column;
  view-transition-name: route-shell;
}

.route-content {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--section-gap);
  padding: var(--space-6) 0 var(--space-8);
  transition:
    opacity 200ms cubic-bezier(0, 0, 0.2, 1),
    transform 200ms cubic-bezier(0, 0, 0.2, 1);
  view-transition-name: route-content;
  will-change: opacity, transform;
}

body[data-route="/map"] .persistent-shell {
  display: flex;
}

body[data-route="/map"] .route-content {
  display: none;
}

body[data-route="/coverage-route-planner"] .route-content,
body[data-route="/live-navigation"] .route-content,
body[data-route="/regional-coverage-explorer"] .route-content {
  padding: 0;
  gap: 0;
}

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

/* === Content Overlay (for mobile nav, side panels) === */
.content-overlay {
  position: fixed;
  inset: 0;
  background-color: rgb(0 0 0 / 45%);
  z-index: calc(var(--z-drawer) - 1); /* Below drawer/panel */
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 200ms cubic-bezier(0, 0, 0.2, 1),
    visibility 200ms cubic-bezier(0, 0, 0.2, 1);
  pointer-events: none;
}

.content-overlay.visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* === Stat Item (from coverage_management.html) === */
.stat-item {
  padding: var(--space-4);
  background: var(--surface-1);
  border-radius: var(--radius-lg);
  text-align: center;
  border: 1px solid var(--border-color);
}

.stat-item .stat-icon {
  /* Optional icon for stat items */
  font-size: var(--font-size-2xl);
  color: var(--primary);
  margin-bottom: var(--space-2);
}

.stat-item .stat-value {
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-bold);
  margin-bottom: var(--space-1);
  color: var(--text-primary);
}

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

/* ===========================================
   Responsive Layout Styles (Colocated from mobile.css)
   =========================================== */

@media (width <= 768px) {
  /* Mobile content adjustments */
  .main-content {
    padding-top: calc(var(--header-height) + var(--space-4));
    padding-bottom: calc(72px + var(--space-5) + env(safe-area-inset-bottom));
  }

  .route-content {
    padding: var(--space-4) 0 var(--space-6);
    gap: var(--space-5);
  }

  .table-responsive {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  .card-body,
  .card-header {
    padding: var(--card-padding);
  }
}

@media (width <= 576px) {
  /* Very small screen adjustments */
  :root {
    --font-size-md: 0.9375rem;
  }

  .btn-group {
    flex-direction: column;
    width: 100%;
  }

  .btn-group .btn {
    width: 100%;
    border-radius: var(--radius-md);
    margin-bottom: var(--space-2);
  }

  .btn-group .btn:last-child {
    margin-bottom: 0;
  }
}

body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: var(--manual-grain);
}

body[data-route="/map"]::after,
body[data-route="/live-navigation"]::after,
body[data-route="/coverage-route-planner"]::after,
body[data-route="/regional-coverage-explorer"]::after,
body[data-route="/memory-city"]::after {
  content: none;
}

/* layout/mobile.css */
/* ============================
   Global Mobile Detection Rules
   ============================

   Note: Most mobile-specific styles have been colocated to their
   respective component files:
   - Mobile search styles → search.css
   - Mobile header/nav styles → header.css
   - Mobile map UI (bottom sheet) → features/map/atlas-rail.css
   - Responsive layout utilities → layout.css

   This file only contains truly global mobile rules that don't
   belong to any specific component.
*/

/* Desktop: Hide mobile-only elements globally */
@media (width > 768px) {
  .mobile-fab-container,
  .mobile-sheet-handle,
  .mobile-sheet-backdrop {
    display: none;
  }
}

/* Very small devices: Root font size adjustment */
@media (width <= 576px) {
  :root {
    /* Adjust base font size for very small screens */
    --font-size-md: 0.9375rem; /* 15px */
  }
}

@media (width <= 768px) {
  body {
    overscroll-behavior-y: auto;
  }

  body[data-route="/map"] {
    overscroll-behavior-y: none;
    overflow-y: hidden;
  }

  .atlas-rail-body,
  .modal-body,
  .table-responsive,
  .drawer-nav {
    -webkit-overflow-scrolling: touch;
  }

  .btn,
  .nav-item a,
  .dropdown-item {
    min-height: var(--touch-target);
  }
}

/* Very small devices: FAB size adjustments */
@media (width <= 375px) {
  .mobile-fab {
    width: 50px;
    height: 50px;
    font-size: var(--font-size-lg);
  }

  .mobile-fab.secondary {
    width: 44px;
    height: 44px;
  }
}

/* layout/footer.css */
/* ============================
   Application Footer — colophon
   ============================ */

.app-footer {
  padding: var(--space-6) var(--page-gutter);
  margin-top: auto;
  border-top: 0;
  padding-top: var(--space-2);
}

.footer-content {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3) var(--space-6);
  flex-wrap: wrap;
  max-width: var(--content-max-width);
  margin: 0 auto;
  font-size: var(--font-size-xs);
  color: var(--manual-ink-soft);
  padding-top: var(--space-4);
  border-top: 3px double var(--manual-ink);
  font-family: var(--font-family-label);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.footer-colophon {
  font-family: var(--font-family-label);
  font-weight: var(--font-weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  display: flex;
  align-items: center;
  flex: 1 1 auto;
  gap: var(--space-4);
  color: var(--manual-ink);
}

.footer-meta {
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-normal);
}

/* Mobile adjustments */
@media (width <= 768px) {
  .app-footer {
    padding-bottom: calc(var(--space-6) + 65px); /* Account for bottom nav */
  }
}
.footer-colophon::after {
  content: "";
  flex: 1 1 auto;
  border-top: 1px solid var(--manual-rule);
}

/* components/buttons.css */
/* ============================================================
   Buttons: printed labels in a ruled box. Primary actions print in
   reverse (paper type on an ink block); everything else is ink on
   paper with a rule around it. Variants only set the --btn-* inks.
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  min-height: var(--touch-target);
  border-radius: var(--radius-xs);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
  transition:
    background-color var(--transition-fast),
    color var(--transition-fast),
    border-color var(--transition-fast);
  border: 1px solid transparent;
  font-size: var(--font-size-sm);
  line-height: var(--line-height-normal);
  text-decoration: none;
  position: relative;
  user-select: none;
  touch-action: manipulation;
  background-color: var(--btn-bg, transparent);
  color: var(--btn-color, var(--text-primary));
  border-color: var(--btn-border, transparent);
  box-shadow: var(--btn-shadow, none);

  --btn-loading-color: var(--btn-color, var(--text-primary));
  font-family: var(--font-family-label);
  letter-spacing: var(--tracking-wide);
}

.btn:disabled,
.btn.disabled {
  background-color: var(--btn-bg, transparent);
  color: var(--btn-color, var(--text-primary));
  border-color: var(--btn-border, transparent);
  opacity: 0.5;
  cursor: not-allowed;
}

.btn:hover:not(:disabled, .disabled) {
  background-color: var(--btn-bg-hover, var(--btn-bg, transparent));
  color: var(--btn-color-hover, var(--btn-color, var(--text-primary)));
  border-color: var(--btn-border-hover, var(--btn-border, transparent));
  box-shadow: var(--btn-shadow-hover, var(--btn-shadow, none));
}

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

.btn:active:not(:disabled, .disabled) {
  transform: translateY(1px);
  transition: transform 0.1s ease;
}

.btn i {
  font-size: 1.1em; /* Slightly larger icons in buttons */
}

.btn-primary {
  --btn-bg: var(--manual-ink);
  --btn-bg-hover: var(--manual-ink-soft);
  --btn-color: var(--manual-paper);
  --btn-color-hover: var(--manual-paper);
  --btn-border: var(--manual-ink);
  --btn-border-hover: var(--manual-ink-soft);
}

.btn-secondary,
.btn-outline,
.btn-outline-primary,
.btn-outline-light {
  --btn-bg: transparent;
  --btn-bg-hover: var(--manual-paper-shade);
  --btn-color: var(--manual-ink);
  --btn-border: var(--manual-rule);
  --btn-border-hover: var(--manual-ink);
}

.btn-secondary {
  --btn-bg: var(--manual-paper);
  --btn-border: var(--manual-ink);
  --btn-shadow: 2px 2px 0 var(--manual-rule-faint);
}

.btn-outline-secondary {
  --btn-color: var(--manual-ink-soft);
  --btn-color-hover: var(--manual-ink);
  --btn-border: var(--manual-rule-faint);
  --btn-border-hover: var(--manual-rule);
  --btn-bg-hover: var(--manual-paper-shade);
}

/* Coloured variants print in one spot ink: the rule and the type. */
.btn-success,
.btn-outline-success,
.btn-info,
.btn-outline-info {
  --btn-color: var(--manual-navy);
  --btn-border: rgb(var(--manual-navy-rgb) / 70%);
  --btn-border-hover: var(--manual-navy);
  --btn-bg-hover: rgb(var(--manual-navy-rgb) / 10%);
}

.btn-danger,
.btn-outline-danger {
  --btn-color: var(--manual-rust-ink);
  --btn-border: rgb(var(--danger-rgb) / 70%);
  --btn-border-hover: var(--manual-rust);
  --btn-bg-hover: rgb(var(--danger-rgb) / 10%);
}

.btn-danger {
  --btn-bg: rgb(var(--danger-rgb) / 8%);
}

.btn-warning,
.btn-outline-warning {
  --btn-color: var(--manual-ink);
  --btn-border: var(--manual-mustard);
  --btn-border-hover: var(--manual-mustard);
  --btn-bg-hover: rgb(var(--manual-mustard-rgb) / 18%);
}

.btn-warning {
  --btn-bg: rgb(var(--manual-mustard-rgb) / 12%);
}

/* === Ghost button — borderless tertiary action (icon rows, table actions) === */
.btn-ghost {
  --btn-bg: transparent;
  --btn-bg-hover: var(--manual-paper-shade);
  --btn-color: var(--text-secondary);
  --btn-color-hover: var(--text-primary);
  --btn-border: transparent;
  --btn-border-hover: transparent;
}

.btn-link {
  --btn-bg: transparent;
  --btn-bg-hover: transparent;
  --btn-border: transparent;
  --btn-color: var(--text-secondary);
  --btn-color-hover: var(--text-primary);

  text-decoration: none;
}

/* === Icon Button === */

.btn-icon {
  width: var(--touch-target);
  height: var(--touch-target);
  padding: 0;
}

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

.btn-lg {
  padding: var(--space-3) var(--space-6);
  font-size: var(--font-size-md);
}

/* === Button Group === */
.btn-group {
  position: relative;
  display: inline-flex;
  vertical-align: middle;
}

.btn-group > .btn {
  position: relative;
  flex: 1 1 auto;
}

.btn-group > .btn:not(:first-child) {
  margin-left: -1px;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

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


.btn-group > .btn:hover {
  z-index: 1; /* Bring hovered button to front */
}

/* components/cards.css */
/* ============================================================
   Cards and widgets: printed panels. A thin ink rule frames the
   panel, corners stay square, and nothing floats on a shadow until
   it can be picked up (linked cards).
   ============================================================ */

.card,
.widget {
  position: relative;
  overflow: hidden;
  background: var(--surface-1);
  border: 1px solid var(--manual-rule);
  border-radius: var(--radius-xs);
  box-shadow: none;
  transition:
    box-shadow var(--transition-normal),
    border-color var(--transition-fast);
}

.card {
  margin-bottom: var(--space-5);
}

.card[data-ripple]:hover,
a.card:hover,
button.card:hover {
  border-color: var(--manual-ink);
  box-shadow: var(--shadow-sm);
}

.card[data-ripple] {
  cursor: pointer;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--card-padding) var(--card-padding-lg);
  border-bottom: 1px solid var(--manual-rule);
  background-color: transparent;
}

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

.card-title {
  margin: 0;
  font-family: var(--font-family-text);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-snug);
}

/* Object cards are reserved for distinct nouns: vehicles, places, and areas. */
.card--object {
  background: var(--surface-1);
  border-color: var(--manual-rule);
}

.card--object .card-header {
  background: transparent;
  border-bottom-color: var(--manual-rule);
}

/* === Widget: card variant with built-in padding and flex layout === */
.widget {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--card-padding-lg);
}

.widget-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.widget-title {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--manual-rust-ink);
}

.widget-title i {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5em;
  height: 1.5em;
  background: transparent;
  color: var(--manual-ink-faint);
  box-shadow: none;
}

.widget-meta {
  font-size: var(--font-size-xs);
  font-style: italic;
  color: var(--text-tertiary);
}

.widget-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.widget.is-compact {
  padding: var(--card-padding);
}

.widget.is-compact .widget-title i {
  width: 1.5em;
  height: 1.5em;
}

.widget.is-muted {
  background: var(--surface-2);
}

/* components/manual.css */
/* ============================================================
   Manual components shared across pages.
   ============================================================ */

/* The shared SVG defs (hatches, the ink wobble) live in base.html. */
.manual-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* ============================================================
   Pen-and-ink plates (inline SVG from partials/plates, drawn by
   scripts/generate_landing_plates.py)
   ============================================================ */
.plate {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  color: var(--manual-ink);
}

.plate-ink {
  filter: url("#manual-wobble");
}

.manual-hatch-line {
  stroke: var(--manual-ink);
  stroke-width: 0.8;
}

.pl-line {
  fill: none;
  stroke: currentcolor;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.1;
}

.pl-body {
  stroke-width: 1.8;
}

.pl-med {
  stroke-width: 1.3;
}

.pl-thin {
  stroke-width: 0.8;
}

.pl-hair {
  stroke-width: 0.55;
}

.pl-paper,
.pl-road {
  fill: var(--manual-paper);
}

.pl-hatch {
  fill: url("#manual-hatch");
}

.pl-hatch-dense {
  fill: url("#manual-hatch-dense");
  opacity: 0.85;
}

.pl-tree {
  fill: var(--manual-solid);
  stroke: currentcolor;
  stroke-width: 0.5;
  stroke-linejoin: round;
}

.pl-tree-far {
  opacity: 0.85;
}

.pl-light {
  fill: none;
  stroke: var(--manual-paper);
  stroke-linecap: round;
  stroke-width: 0.8;
  opacity: 0.7;
}

.pl-dash {
  fill: none;
  stroke: var(--manual-mustard);
  stroke-width: 1.6;
  stroke-linecap: round;
}

.pl-solid {
  fill: var(--manual-solid);
}

/* Cast shadows print in the heaviest ink: dark by day, near-black by night. */
.pl-shadow {
  fill: var(--manual-solid);
  opacity: 0.55;
}

html.light-mode .pl-shadow {
  opacity: 0.14;
}

.pl-sign-board {
  fill: var(--manual-paper);
  stroke: currentcolor;
  stroke-width: 1.8;
}

.pl-sign-name {
  font-family: var(--font-family-label);
  font-size: var(--font-size-sm);
  font-weight: 800;
  letter-spacing: var(--tracking-label);
  fill: currentcolor;
}

.pl-sign-miles {
  font-family: var(--font-family-display);
  font-size: var(--font-size-lg);
  font-weight: 800;
  fill: var(--manual-rust);
}

.pl-map-face {
  fill: var(--manual-paper);
  stroke: currentcolor;
  stroke-width: 1.1;
  stroke-linejoin: round;
}

.pl-map-face-shade,
.pl-wood,
.pl-ferrule {
  fill: var(--manual-paper-shade);
}

.pl-water {
  fill: none;
  stroke: var(--manual-navy);
  stroke-width: 3.2;
  stroke-linecap: round;
  opacity: 0.75;
}

.pl-water-fill {
  fill: rgb(var(--manual-navy-rgb) / 35%);
  stroke: var(--manual-navy);
  stroke-width: 0.8;
}

.pl-hwy {
  fill: none;
  stroke: var(--manual-mustard);
  stroke-width: 3;
  stroke-linecap: round;
}

.pl-route {
  fill: none;
  stroke: var(--manual-rust);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 5 3.5;
}

.pl-route-solid {
  stroke-dasharray: none;
  stroke-width: 2.4;
}

.pl-route-end {
  fill: none;
  stroke: var(--manual-rust);
  stroke-width: 2;
  stroke-linecap: round;
}

.pl-route-start,
.pl-needle,
.pl-flag,
.pl-eraser {
  fill: var(--manual-rust);
}

.pl-pin {
  fill: var(--manual-rust);
  stroke: currentcolor;
  stroke-width: 0.8;
}

.pl-undriven {
  stroke-dasharray: 2.5 2.5;
  opacity: 0.7;
}

.pl-pencil {
  fill: var(--manual-mustard);
}

.pl-bubble {
  fill: rgb(var(--manual-navy-rgb) / 70%);
}

.pl-star {
  fill: var(--manual-paper);
}

.pl-map-cartouche {
  fill: var(--manual-paper);
  stroke: currentcolor;
  stroke-width: 0.8;
}

.pl-map-title {
  font-family: var(--font-family-text);
  font-size: var(--font-size-sm);
  font-style: italic;
  font-weight: var(--font-weight-semibold);
  fill: currentcolor;
}

.pl-compass-n,
.pl-pump-label {
  font-family: var(--font-family-label);
  font-size: 0.5em;
  font-weight: 800;
  fill: currentcolor;
}

.pl-pump-digits {
  font-family: var(--font-family-display);
  font-size: 0.5em;
  font-weight: 800;
  fill: var(--manual-paper);
}

/* The Murano, engraved (scripts/engrave_landing_car.py): alpha masks
   inked with the page colours. Paper under the car and ink lines by
   day, a solid ground and cream highlights by night, rust lamps. Only
   the active edition's line mask is downloaded. */
.car-engraving {
  position: relative;
  aspect-ratio: 600 / 408;
}

.car-engraving > span {
  position: absolute;
  inset: 0;
  mask-position: 0 0;
  mask-size: 100% 100%;
  mask-repeat: no-repeat;
}

.car-engraving-base {
  background-color: var(--manual-solid);
  mask-image: url("../images/landing/murano-silhouette.webp");
}

.car-engraving-ink {
  background-color: var(--manual-ink);
  mask-image: url("../images/landing/murano-highlight.webp");
}

.car-engraving-lamps {
  background-color: var(--manual-rust);
  mask-image: url("../images/landing/murano-lamps.webp");
}

html.light-mode .car-engraving-base {
  background-color: var(--manual-paper);
}

html.light-mode .car-engraving-ink {
  mask-image: url("../images/landing/murano-ink.webp");
}

/* A printed survey scale: square ends, 5% ticks, heavier quarter
   ticks, and diagonal hatching for the driven share. */
.survey-bar {
  position: relative;
  height: 1.05rem;
  border: 1.5px solid var(--manual-ink);
  background-color: var(--manual-paper);
  background-image:
    repeating-linear-gradient(
      to right,
      rgb(var(--manual-ink-rgb) / 70%) 0 1px,
      transparent 1px 25%
    ),
    repeating-linear-gradient(
      to right,
      rgb(var(--manual-ink-rgb) / 45%) 0 1px,
      transparent 1px 5%
    );
  background-size:
    100% 60%,
    100% 32%;
  background-position:
    0 100%,
    0 100%;
  background-repeat: no-repeat;
}

.survey-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background-color: rgb(var(--manual-navy-rgb) / 16%);
  background-image: repeating-linear-gradient(
    -52deg,
    var(--manual-navy) 0 1.3px,
    transparent 1.3px 4.2px
  );
  border-right: 1.5px solid var(--manual-ink);
  transition: width 900ms cubic-bezier(0.3, 0, 0.2, 1);
}

.survey-bar.is-working .survey-fill {
  animation: surveyWorking 1.4s linear infinite;
}

@keyframes surveyWorking {
  to {
    background-position: 22px 0;
  }
}

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

  .survey-bar.is-working .survey-fill {
    animation: none;
  }
}

/* components/masthead.css */
/* ============================================================
   Page masthead + figure band — shared editorial header system
   Extends the landing page's "Atlas" language to interior pages:
   type-led mastheads (eyebrow / display title / factual subline)
   and hairline-divided figure bands instead of boxed stat cards.
   ============================================================ */

.page-masthead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
  flex-wrap: wrap;
  margin-bottom: var(--section-gap);
}

.pm-lead {
  min-width: 0;
}

.pm-eyebrow {
  margin: 0 0 var(--space-2);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--manual-rust-ink);
  font-family: var(--font-family-label);
}

.pm-title {
  margin: 0;
  font-family: var(--font-family-display);
  font-size: var(--font-size-4xl);
  font-weight: 800;
  letter-spacing: var(--tracking-display);
  line-height: 0.98;
  color: var(--text-primary);
  text-wrap: balance;
}

.pm-sub {
  margin: var(--space-3) 0 0;
  max-width: var(--measure-tight);
  font-size: var(--font-size-lg);
  line-height: var(--line-height-relaxed);
  color: var(--text-secondary);
  text-wrap: pretty;
}

.pm-sub strong {
  color: var(--text-primary);
  font-weight: var(--font-weight-semibold);
}

.pm-aside {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-3);
  padding-bottom: var(--space-1);
}

/* A small pen-and-ink plate beside the title (partials/plates). It sits
   against the right edge, next to any actions, and bows out on phones
   where the title needs the room. */
.pm-plate {
  flex: 0 0 auto;
  width: var(--pm-plate-width, 6rem);
  margin-left: auto;
  color: var(--manual-ink);
  pointer-events: none;
}

.pm-plate--wide {
  --pm-plate-width: 11rem;
}

.pm-plate--car {
  --pm-plate-width: 10rem;
}

@media (width <= 640px) {
  .pm-plate {
    display: none;
  }
}

/* ---- Figure band: hairline-divided numerals, no boxes -------- */
.figure-band {
  display: flex;
  align-items: stretch;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  padding: var(--space-4) 0;
  border-top: 1px solid var(--border-color);
  border-bottom: 1px solid var(--border-color);
}

.figure-band .figure {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-2);
  flex: 1 1 0;
  min-width: 0;
}

.figure-label {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--text-tertiary);
  font-family: var(--font-family-label);
}

.figure-readout {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
}

/* Family and tabular figures come from core/typography.css. */
.figure-value {
  font-size: var(--font-size-3xl);
  font-weight: 800;
  line-height: 1;
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  font-family: var(--font-family-display);
}

.figure-value-sm {
  font-size: var(--font-size-2xl);
}

/* The unit annotates the figure, so it stays in the text face — a sans
   caption against a serif numeral reads as a legend, not a continuation. */
.figure-unit {
  font-family: var(--font-family);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--text-tertiary);
}

.figure-rule {
  width: 1px;
  align-self: stretch;
  background: var(--border-color);
  flex: 0 0 auto;
}

@media (width <= 720px) {
  .page-masthead {
    align-items: flex-start;
  }

  .pm-aside {
    align-items: flex-start;
    flex-flow: row wrap;
  }

  .figure-band {
    flex-wrap: wrap;
    gap: var(--space-4) var(--space-6);
  }

  .figure-band .figure {
    flex: 1 1 40%;
  }

  .figure-rule {
    display: none;
  }
}

/* components/forms.css */
/* ============================================================
   Forms: ruled entry boxes on the page stock. Labels are printed
   Franklin captions; focus is marked in rust.
   ============================================================ */

/* === Forms === */
.form-group {
  margin-bottom: var(--space-4);
}

.form-label {
  display: block;
  margin-bottom: var(--space-2);
  font-weight: var(--font-weight-semibold);
  color: var(--text-secondary);
  font-size: var(--font-size-sm);
  font-family: var(--font-family-label);
  letter-spacing: var(--tracking-wide);
}

.form-control,
.form-select {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  min-height: var(--touch-target);
  background: var(--surface-1);
  border: 1px solid var(--manual-rule);
  border-radius: var(--radius-xs);
  color: var(--text-primary);
  font-size: var(--font-size-md);
  line-height: var(--line-height-normal);
  transition:
    background-color var(--transition-fast),
    border-color var(--transition-fast),
    box-shadow var(--transition-fast);
}

.form-control:hover,
.form-select:hover {
  border-color: var(--manual-ink-soft);
}

.form-control:focus,
.form-select:focus {
  border-color: var(--manual-ink);
  outline: 0;
  background: var(--surface-1);
  box-shadow: 2px 2px 0 var(--manual-rust);
}

.form-control::placeholder {
  color: var(--text-tertiary);
  opacity: 1; /* Firefox fix */
}

.input-unit,
.input-group-text {
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  background: var(--manual-paper-shade);
  border-color: var(--manual-rule);
  color: var(--manual-ink-soft);
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-wide);
}

/* iOS Safari auto-zooms when a focused field's font-size is below 16px.
   Force at least 16px on touch viewports to keep typing zoom-free. The
   visual difference from the desktop size is negligible. */
@media (width <= 768px) {
  input:not([type="checkbox"], [type="radio"], [type="range"]),
  select,
  textarea,
  .form-control,
  .form-select {
    font-size: 16px;
  }
}

.form-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23c2b79f' stroke-linecap='square' stroke-width='1.6' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right var(--space-3) center;
  background-size: 16px 12px;
  padding-right: calc(var(--space-3) + 16px + var(--space-3));
}

html.light-mode body .form-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23564f41' stroke-linecap='square' stroke-width='1.6' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
}

.form-check {
  display: flex; /* Use flex for better alignment */
  align-items: center;
  margin-bottom: var(--space-2);
  min-height: calc(var(--font-size-sm) * var(--line-height-normal)); /* Ensure consistent height */
}

.form-check-input {
  width: 1.25em;
  height: 1.25em;
  margin-top: 0;
  margin-right: var(--space-2);
  background-color: var(--surface-1);
  border: 1.5px solid var(--manual-ink-soft);
  border-radius: 0;
  transition:
    background-color var(--transition-fast),
    border-color var(--transition-fast);
}

.form-check-input[type="radio"] {
  border-radius: 50%;
}

.form-check-input:checked {
  background-color: var(--manual-ink);
  border-color: var(--manual-ink);
}

/* The tick and the radio dot print in the paper colour on the ink. */
.form-check-input:checked[type="checkbox"] {
  --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%231c1a16' stroke-width='2.2' d='M3.5 8.2l3 3 6-6.4'/%3e%3c/svg%3e");
}

.form-check-input:checked[type="radio"] {
  --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%231c1a16'/%3e%3c/svg%3e");
}

html.light-mode body .form-check-input:checked[type="checkbox"] {
  --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23f1e8d5' stroke-width='2.2' d='M3.5 8.2l3 3 6-6.4'/%3e%3c/svg%3e");
}

html.light-mode body .form-check-input:checked[type="radio"] {
  --bs-form-check-bg-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23f1e8d5'/%3e%3c/svg%3e");
}

.form-check-input:focus {
  border-color: var(--manual-ink);
  outline: 0;
  box-shadow: var(--focus-ring);
}

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

/* A slide switch: a ruled slot with a square block that moves across. */
.form-switch .form-check-input {
  position: relative;
  width: 2.6em;
  background-image: none;
  border-radius: 0;
}

.form-switch .form-check-input::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0.16em;
  width: 0.95em;
  height: 0.95em;
  background-color: var(--manual-ink-soft);
  transform: translateY(-50%);
  transition:
    transform var(--transition-fast),
    background-color var(--transition-fast);
}

.form-switch .form-check-input:checked::before {
  background-color: var(--manual-paper);
  transform: translate(1.36em, -50%);
}

.form-text {
  margin-top: var(--space-1);
  font-size: var(--font-size-xs);
  font-style: italic;
  color: var(--text-tertiary);
}

.invalid-feedback {
  display: none;
  width: 100%;
  margin-top: var(--space-1);
  font-size: var(--font-size-xs);
  color: var(--danger);
  animation: shake 0.3s ease;
}

.form-control.is-invalid,
.form-select.is-invalid {
  border-color: var(--danger);
}

.form-control.is-invalid:focus,
.form-select.is-invalid:focus {
  box-shadow: 2px 2px 0 var(--danger);
}

.form-control.is-invalid ~ .invalid-feedback,
.form-select.is-invalid ~ .invalid-feedback {
  display: block;
}

/* components/navigation-controls.css */
/* Shared underline tabs. Page code may keep its JS hook classes alongside these. */
.atlas-tabs {
  display: flex;
  gap: var(--space-5);
  min-height: var(--touch-target);
  overflow-x: auto;
  border-bottom: 1px solid var(--border-color);
  scrollbar-width: none;
}

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

.atlas-tab {
  position: relative;
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  padding: 0 0 var(--space-2);
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  cursor: pointer;
}

.atlas-tab::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: -1px;
  left: 0;
  height: 2px;
  background: transparent;
}

.atlas-tab:hover,
.atlas-tab.active,
.atlas-tab.is-active,
.atlas-tab[aria-selected="true"] {
  color: var(--text-primary);
}

.atlas-tab.active::after,
.atlas-tab.is-active::after,
.atlas-tab[aria-selected="true"]::after {
  background: var(--action);
}

.segmented-control {
  display: inline-flex;
  max-width: 100%;
  padding: 2px;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-md);
  background: var(--surface-1);
}

.segmented-control > button,
.segment {
  min-height: calc(var(--touch-target) - 6px);
  padding: var(--space-1) var(--space-3);
  border: 0;
  border-radius: calc(var(--radius-md) - 2px);
  background: transparent;
  color: var(--text-secondary);
  font-size: var(--font-size-sm);
  cursor: pointer;
}

.segmented-control > button:hover,
.segment:hover {
  color: var(--text-primary);
}

.segmented-control > button.active,
.segmented-control > button.is-active,
.segmented-control > button[aria-pressed="true"],
.segment.active,
.segment.is-active,
.segment[aria-pressed="true"] {
  background: var(--action);
  color: var(--text-on-action);
}

.section-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--touch-target);
  padding: var(--space-3) 0;
  border: 0;
  border-top: 1px solid var(--border-color);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-family-text);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-semibold);
  text-align: left;
}

.section-toggle i,
.section-toggle .toggle-icon {
  color: var(--text-tertiary);
  transition: transform var(--transition-fast);
}

.section-toggle[aria-expanded="true"] i:last-child,
.section-toggle[aria-expanded="true"] .toggle-icon {
  transform: rotate(180deg);
}

@media (width >= 48rem) {
  .atlas-tabs {
    gap: var(--space-6);
  }
}

/* components/stepper.css */
/* One workflow language: 01 / 02 / 03 in printed labels. The current step
   is underlined in ink and a finished one is ticked in rust. */
.atlas-stepper {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(4.5rem, 1fr);
  gap: 0;
  width: 100%;
  overflow-x: auto;
  border-bottom: 1px solid var(--manual-rule);
}

.atlas-step {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3) var(--space-2) 0;
  color: var(--text-tertiary);
}

.atlas-step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 50%;
  right: var(--space-2);
  width: clamp(0.75rem, 3vw, 2.5rem);
  border-top: 1px solid var(--manual-rule);
}

.atlas-step-index {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2ch;
  color: inherit;
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-variant-numeric: tabular-nums;
  font-weight: var(--font-weight-bold);
}

.atlas-step-index::before {
  content: "0";
}

.atlas-step-label {
  padding-bottom: var(--space-1);
  border-bottom: 2px solid transparent;
  color: inherit;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  white-space: nowrap;
  font-family: var(--font-family-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.atlas-step.active,
.atlas-step.is-active,
.atlas-step[aria-current="step"] {
  color: var(--text-primary);
}

.atlas-step.active .atlas-step-label,
.atlas-step.is-active .atlas-step-label,
.atlas-step[aria-current="step"] .atlas-step-label {
  border-bottom-color: var(--manual-ink);
}

.atlas-step.completed,
.atlas-step.is-complete {
  color: var(--text-secondary);
}

.atlas-step.completed .atlas-step-index,
.atlas-step.is-complete .atlas-step-index {
  color: transparent;
}

.atlas-step.completed .atlas-step-index::after,
.atlas-step.is-complete .atlas-step-index::after {
  content: "✓";
  position: absolute;
  color: var(--manual-rust-ink);
  font-family: var(--font-numeric);
}

@media (width >= 48rem) {
  .atlas-step {
    padding-right: var(--space-5);
  }
}

/* components/status.css */
/* Shared empty states and single-hue progress language. */
.empty-state {
  display: grid;
  place-items: center;
  gap: var(--space-3);
  min-height: 10rem;
  padding: var(--space-8) var(--space-4);
  border: 1px dashed var(--manual-rule);
  border-radius: 0;
  background: transparent;
  color: var(--text-secondary);
  text-align: center;
}

.empty-state > i,
.empty-state-icon {
  color: var(--text-tertiary);
  font-size: var(--font-size-2xl);
}

.empty-state h2,
.empty-state h3,
.empty-state-title {
  margin: 0;
  color: var(--text-primary);
  font-family: var(--font-family-text);
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-bold);
}

.empty-state p,
.empty-state-body {
  max-width: 46ch;
  margin: 0;
  font-style: italic;
  color: var(--text-secondary);
}

/* components/app-select.css */
/* Universal custom select, backed by the native <select> for state and forms. */
.es-native-select {
  position: absolute !important;
  inline-size: 1px !important;
  block-size: 1px !important;
  margin: -1px !important;
  padding: 0 !important;
  overflow: hidden !important;
  opacity: 0 !important;
  pointer-events: none !important;
  clip-path: inset(50%) !important;
}

.es-select {
  position: relative;
  inline-size: 100%;
  min-inline-size: 0;
}

.es-select__button {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-2);
  inline-size: 100%;
  min-block-size: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--divider-color);
  border-radius: var(--radius-md);
  background: var(--surface-0);
  color: var(--text-primary);
  font: inherit;
  line-height: var(--line-height-normal);
  text-align: start;
  cursor: pointer;
  transition:
    border-color var(--transition-fast),
    background-color var(--transition-fast),
    box-shadow var(--transition-fast);
}

.es-select--sm .es-select__button {
  min-block-size: 2.35rem;
  padding-block: var(--space-1);
  font-size: var(--font-size-sm);
}

.es-select__button:hover {
  border-color: var(--border-color);
}

.es-select__button:focus-visible,
.es-select.is-open .es-select__button {
  outline: 0;
  border-color: var(--primary);
  background: var(--surface-0);
  box-shadow: var(--focus-ring);
}

.es-select.is-invalid .es-select__button {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgb(var(--danger-rgb) / 20%);
}

.es-select.is-disabled .es-select__button {
  cursor: not-allowed;
  opacity: 0.6;
}

.es-select__value {
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.es-select__value.is-placeholder {
  color: var(--text-tertiary);
}

.es-select__chevron {
  color: var(--text-tertiary);
  font-size: 0.76em;
  transition:
    transform var(--transition-fast),
    color var(--transition-fast);
}

.es-select.is-open .es-select__chevron {
  color: var(--text-secondary);
  transform: rotate(180deg);
}

.es-select__menu {
  position: absolute;
  inset-block-start: calc(100% + 0.35rem);
  inset-inline: 0;
  z-index: var(--z-dropdown);
  display: none;
  max-block-size: min(18rem, 45vh);
  overflow-y: auto;
  padding: var(--space-1);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--surface-elevated);
  box-shadow: var(--shadow-lg);
}

.es-select.is-open .es-select__menu {
  display: grid;
  gap: 1px;
}

.es-select__option {
  inline-size: 100%;
  min-block-size: 2.25rem;
  padding: var(--space-2) var(--space-3);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: var(--font-size-sm);
  line-height: 1.25;
  text-align: start;
  cursor: pointer;
}

.es-select__option:hover,
.es-select__option:focus-visible {
  outline: 0;
  background: rgb(var(--primary-rgb) / 14%);
  color: var(--text-primary);
}

.es-select__option[aria-selected="true"] {
  background: rgb(var(--primary-rgb) / 20%);
  color: var(--text-primary);
}

.es-select__option:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

html.light-mode body .es-select__menu,
html.light-mode .es-select__menu {
  background: var(--surface-elevated);
}

.coverage-route-planner .select-wrapper:has(.es-select)::after {
  content: none;
}

.memory-city-area-picker:has(.es-select) .memory-city-area-chevron {
  display: none;
}

/* components/tables.css */
/* ============================================================
   Tables: a printed register. Franklin caps over a heavy ink rule,
   light rules between rows, figures hung from the right.
   ============================================================ */

.table {
  width: 100%;
  border-collapse: collapse;
  background-color: transparent;
  color: var(--text-primary);
  font-size: var(--font-size-sm);
  line-height: 1.4;
}

.table th,
.table td {
  padding: var(--space-3) var(--space-4);
  text-align: left;
  border-bottom: 1px solid var(--manual-rule-faint);
  vertical-align: middle;
  transition: background-color var(--transition-fast);
}

.table thead th {
  background: var(--manual-paper);
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  font-size: var(--font-size-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  position: sticky;
  top: 0;
  z-index: 10;
  font-family: var(--font-family-label);
  border-bottom: 1.5px solid var(--manual-ink);
}

.table td {
  overflow-wrap: anywhere;
}

/* Tabular figures come from core/typography.css; the table only decides
   which edge the digits hang from. */
.table td[data-numeric],
.table .data-num,
.table .numeric {
  text-align: right;
}

.table-hover tbody tr:hover {
  background-color: var(--manual-paper-shade);
}

.table-striped tbody tr:nth-of-type(odd) {
  background-color: rgb(var(--manual-ink-rgb) / 3%);
}

/* components/notifications.css */
/* ============================
   Notification Components
   ============================ */

/* === Notifications: printed slips pinned under the header === */
.notification-container {
  position: fixed;
  top: calc(var(--header-height) + var(--space-3));
  right: var(--space-4);
  z-index: var(--z-tooltip);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  width: min(380px, calc(100vw - (var(--space-4) * 2)));
  max-width: calc(100vw - (var(--space-4) * 2));
  pointer-events: none;
}

.notification {
  min-height: 3.5rem;
  background: var(--manual-paper);
  color: var(--text-primary);
  border-radius: 0;
  padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4);
  box-shadow: 3px 3px 0 var(--manual-rule-faint);
  transform: translateX(120%);
  opacity: 0;
  transition:
    transform 320ms cubic-bezier(0.34, 1.56, 0.64, 1),
    opacity 200ms cubic-bezier(0, 0, 0.2, 1);
  pointer-events: auto;
  border: 1px solid var(--manual-ink);
  border-left: 4px solid var(--manual-ink);
  display: flex;
  align-items: flex-start;
  width: 100%;
}

.notification.show {
  transform: translateX(0);
  opacity: 1;
}

/* Notification enter animation with stagger */
.notification:nth-child(1).show {
  transition-delay: 0ms;
}

.notification:nth-child(2).show {
  transition-delay: 50ms;
}

.notification:nth-child(3).show {
  transition-delay: 100ms;
}

.notification-icon {
  font-size: var(--font-size-xl);
  margin-right: var(--space-3);
  display: flex;
  align-items: center;
  min-height: var(--touch-target);
  flex-shrink: 0; /* Prevent icon from shrinking */
}

.notification-content {
  flex: 1;
  min-width: 0; /* Allow content to shrink if needed */
  align-self: center;
}

.notification-message {
  font-size: var(--font-size-sm);
  color: var(--text-primary);
  line-height: var(--line-height-normal);
  overflow-wrap: anywhere;
}

.notification-close {
  display: inline-flex;
  flex: 0 0 var(--touch-target);
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  padding: 0;
  border: none;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  margin-left: var(--space-1);
  font-size: var(--font-size-lg);
  transition:
    color 120ms cubic-bezier(0.4, 0, 0.2, 1),
    background 120ms cubic-bezier(0.4, 0, 0.2, 1);
  align-self: flex-start; /* Align close button to top right */
}

.notification-close:hover {
  background: var(--manual-paper-shade);
  color: var(--text-primary);
}

.notification-close:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 1px;
}

/* Minimized coverage-job progress badge (global) */
.minimized-progress-badge {
  --minimized-progress: 0%;

  position: fixed;
  bottom: 20px;
  left: 20px;
  z-index: var(--z-drawer);
  overflow: hidden;
  background: var(--surface-elevated);
  color: var(--text-primary);
  padding: var(--space-2) var(--space-3) calc(var(--space-2) + 3px);
  border-radius: var(--radius-lg);
  box-shadow:
    var(--shadow-lg),
    0 0 0 1px rgb(var(--info-rgb) / 14%);
  border: 1px solid rgb(var(--info-rgb) / 30%);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  max-width: min(560px, calc(100vw - 40px));
  cursor: pointer;
  transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1);
  animation: slideInUp 250ms cubic-bezier(0, 0, 0.2, 1);
}

.minimized-progress-badge::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: var(--minimized-progress);
  height: 3px;
  background: var(--info);
  transition: width 240ms ease;
}

.minimized-progress-badge:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-xl);
  background: var(--surface-elevated);
}

.minimized-progress-icon {
  position: relative;
  z-index: 1;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  border-radius: var(--radius-md);
  background: rgb(var(--info-rgb) / 16%);
  color: var(--info-light, var(--info));
  box-shadow: inset 0 0 0 1px rgb(var(--info-rgb) / 22%);
}

.minimized-progress-icon i {
  animation: minimized-icon-pulse 1.6s ease-in-out infinite;
}

.minimized-progress-badge .minimized-location-name {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-width: 0;
  max-width: none;
  white-space: normal;
  overflow-wrap: anywhere;
  font-weight: 500;
  color: var(--text-primary);
}

.minimized-progress-badge .minimized-progress-percent {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  margin-left: var(--space-1);
  color: var(--info-light, var(--info)) !important;
  font-weight: var(--font-weight-semibold);
}

@keyframes minimized-icon-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 0.78;
  }

  50% {
    transform: scale(1.08);
    opacity: 1;
  }
}

/* Desktop-only: hide minimized coverage badge on tablet/mobile */
@media (width <= 991.98px) {
  .minimized-progress-badge {
    display: none !important;
  }
}

/* Notification variants */
.notification-success {
  border-left-color: var(--success);
}

.notification-success .notification-icon {
  color: var(--success);
  animation: icon-pop 0.35s ease-out;
}

.notification-check {
  display: inline-block;
  width: 14px;
  height: 8px;
  border-left: 2px solid currentcolor;
  border-bottom: 2px solid currentcolor;
  transform: rotate(-45deg);
  animation: checkmark-draw 0.4s ease-out;
}

@keyframes checkmark-draw {
  0% {
    width: 0;
    height: 0;
    opacity: 0;
  }

  50% {
    width: 14px;
    height: 0;
    opacity: 1;
  }

  100% {
    width: 14px;
    height: 8px;
    opacity: 1;
  }
}

.notification-error {
  border-left-color: var(--danger);
}

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

.notification.notification-error.show {
  animation: shake 0.35s ease-out;
}

.notification-warning {
  border-left-color: var(--warning);
}

.notification-warning .notification-icon {
  color: var(--warning);
}

.notification-info {
  border-left-color: var(--info);
}

.notification-info .notification-icon {
  color: var(--info);
}

/* === Alerts: a boxed note with a spot-ink bar down the margin === */
.alert {
  display: flex;
  align-items: flex-start;
  margin-bottom: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--manual-rule);
  border-left: 4px solid var(--alert-ink, var(--manual-ink));
  border-radius: 0;
  background-color: var(--manual-paper-shade);
  color: var(--text-primary);
}

.alert .btn-close {
  opacity: 0.7;
  transition: opacity var(--transition-fast);
  margin-left: auto; /* Push to the right */
  padding: var(--space-3); /* Easier to click */
}

.alert .btn-close:hover {
  opacity: 1;
}

.alert-success,
.alert-info {
  --alert-ink: var(--manual-navy);
}

.alert-danger {
  --alert-ink: var(--manual-rust);
}

.alert-warning {
  --alert-ink: var(--manual-mustard);
}

/* ==========================================================================
   Pipeline Tracker — multi-stage progress UI (global, used in base.html modal)
   ========================================================================== */

.pipeline-tracker {
  padding: 0.25rem 0;
}

.pipeline-header {
  margin-bottom: 1rem;
}

.pipeline-overall {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.pipeline-progress-bar {
  height: 6px;
  background: var(--surface-3);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.pipeline-progress-fill {
  height: 100%;
  background: var(--info);
  border-radius: var(--radius-sm);
  transition: width 0.4s ease;
}

.pipeline-progress-label {
  display: flex;
  justify-content: space-between;
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
}

.pipeline-pct {
  font-weight: 600;
  color: var(--info);
}

/* Stage list */
.pipeline-stages {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.pipeline-stage {
  display: flex;
  gap: 0.75rem;
  position: relative;
}

.pipeline-stage-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  width: 32px;
}

.pipeline-stage-dot {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-xs);
  transition: all 0.3s ease;
  flex-shrink: 0;
  z-index: 1;
}

.pipeline-stage-line {
  width: 2px;
  flex: 1;
  min-height: 8px;
  transition: background 0.3s ease;
}

/* Pending state */
.pipeline-stage.is-pending .pipeline-stage-dot {
  background: var(--surface-2);
  border: 2px solid var(--text-tertiary);
  color: var(--text-tertiary);
}

.pipeline-stage.is-pending .pipeline-stage-line {
  background: var(--surface-3);
}

.pipeline-stage.is-pending .pipeline-stage-content {
  opacity: 0.5;
}

/* Active state */
.pipeline-stage.is-active .pipeline-stage-dot {
  background: rgb(var(--info-rgb) / 15%);
  border: 2px solid var(--info);
  color: var(--info);
}

.pipeline-stage.is-active .pipeline-stage-line {
  background: var(--info);
}

.pipeline-stage.is-active .pipeline-stage-content {
  opacity: 1;
}

/* Completed state */
.pipeline-stage.is-completed .pipeline-stage-dot {
  background: rgb(var(--success-rgb) / 20%);
  border: 2px solid var(--success);
  color: var(--success);
}

.pipeline-stage.is-completed .pipeline-stage-line {
  background: var(--success);
}

.pipeline-stage.is-completed .pipeline-stage-content {
  opacity: 0.85;
}

/* Stage content */
.pipeline-stage-content {
  flex: 1;
  padding-bottom: 0.75rem;
  min-width: 0;
  transition: opacity 0.3s ease;
}

.pipeline-stage-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
}

.pipeline-stage-label {
  font-weight: 600;
  font-size: var(--font-size-sm);
  color: var(--text-primary);
}

.pipeline-stage-time {
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.pipeline-stage.is-active .pipeline-stage-time {
  color: var(--info);
}

.pipeline-stage.is-completed .pipeline-stage-time {
  color: var(--success);
}

.pipeline-stage-description {
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
  margin-top: 0.1rem;
}

/* Stage metrics chips */
.pipeline-stage-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.35rem;
  min-height: 0;
  transition: min-height 0.2s ease;
}

.pipeline-stage-metrics.has-data {
  min-height: 1.5rem;
}

.pipeline-metric {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.15rem 0.5rem;
  background: rgb(var(--border-rgb) / 10%);
  border-radius: var(--radius-sm);
  font-size: var(--font-size-xs);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  animation: metricFadeIn 0.3s ease;
}

.pipeline-metric i {
  font-size: var(--font-size-xs);
  opacity: 0.7;
}

@keyframes metricFadeIn {
  from {
    opacity: 0;
    transform: translateY(4px);
  }

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

/* Live message */
.pipeline-message {
  text-align: center;
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
  margin-top: 0.5rem;
  min-height: 1.25rem;
}

/* Pulse animation for active stage icon */
.pipeline-stage.is-active .pipeline-stage-dot i.fa-pulse {
  animation: stagePulse 1.5s ease-in-out infinite;
}

@keyframes stagePulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.4;
  }
}

/* ============================
   Notification Bell & History Panel
   ============================ */

/* --- Bell button --- */
.notif-bell-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.notif-bell-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  border-radius: var(--radius-full);
  border: none;
  background: transparent;
  cursor: pointer;
  position: relative;
  transition:
    background-color 120ms cubic-bezier(0.4, 0, 0.2, 1),
    color 120ms cubic-bezier(0.4, 0, 0.2, 1);
}

.notif-bell-btn[aria-expanded="true"] {
  background-color: var(--surface-3);
  color: var(--text-primary);
}

.notif-bell-btn .fa-bell {
  font-size: var(--font-size-md);
}

/* --- Unread count badge --- */
.notif-unread-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  min-width: 16px;
  height: 16px;
  padding: 0 3px;
  border-radius: var(--radius-full);
  background: var(--manual-rust);
  color: var(--text-on-primary);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  line-height: 16px;
  text-align: center;
  pointer-events: none;
  animation: badgePop 220ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

@keyframes badgePop {
  from {
    transform: scale(0);
    opacity: 0;
  }

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

/* --- History panel --- */
.notif-history-panel {
  position: absolute;
  top: calc(100% + var(--space-2));
  right: 0;
  width: min(360px, calc(100vw - var(--space-6, 24px)));
  max-height: 480px;
  background: var(--manual-paper);
  border: 1px solid var(--manual-ink);
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--manual-rule-faint);
  z-index: var(--z-dropdown);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: dropdownReveal 180ms cubic-bezier(0, 0, 0.2, 1) both;
  transform-origin: top right;
}

.notif-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 3px double var(--manual-ink);
  flex-shrink: 0;
}

.notif-panel-title {
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  color: var(--manual-rust-ink);
  letter-spacing: var(--tracking-label);
  font-family: var(--font-family-label);
  text-transform: uppercase;
}

.notif-clear-all-btn {
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--font-size-xs);
  color: var(--manual-ink-soft);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
  transition:
    color 120ms ease,
    background-color 120ms ease;
  font-family: var(--font-family-text);
}

.notif-clear-all-btn:hover {
  color: var(--text-secondary);
  background-color: var(--surface-3);
}

/* --- Scrollable list --- */
.notif-history-list {
  overflow-y: auto;
  flex: 1;
  min-height: 0;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--surface-3) transparent;
}

/* --- Single history item --- */
.notif-history-item {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--divider-color);
  transition: background-color 100ms ease;
}

.notif-history-item:last-child {
  border-bottom: none;
}

.notif-history-item:hover {
  background-color: rgb(var(--border-rgb) / 8%);
}

.notif-history-icon {
  margin-top: 2px;
  font-size: var(--font-size-sm);
  flex-shrink: 0;
  opacity: 0.85;
}

.notif-history-item--success .notif-history-icon {
  color: var(--success);
}

.notif-history-item--error .notif-history-icon {
  color: var(--danger);
}

.notif-history-item--warning .notif-history-icon {
  color: var(--warning);
}

.notif-history-item--info .notif-history-icon {
  color: var(--info);
}

.notif-history-body {
  flex: 1;
  min-width: 0;
}

.notif-history-message {
  font-size: var(--font-size-xs);
  color: var(--text-primary);
  margin: 0 0 var(--space-1);
  line-height: var(--line-height-normal);
  overflow-wrap: anywhere;
}

.notif-history-time {
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
  display: block;
}

.notif-history-remove {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--text-tertiary);
  padding: var(--space-1);
  border-radius: var(--radius-sm);
  opacity: 0;
  transition:
    opacity 120ms ease,
    color 120ms ease;
  flex-shrink: 0;
  font-size: var(--font-size-xs);
  line-height: 1;
}

.notif-history-item:hover .notif-history-remove {
  opacity: 1;
}

.notif-history-remove:hover {
  color: var(--text-secondary);
}

/* --- Empty state --- */
.notif-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-6, 24px) var(--space-4);
  color: var(--text-tertiary);
  font-size: var(--font-size-sm);
}

.notif-empty-state i {
  font-size: var(--font-size-2xl);
  opacity: 0.4;
}

/* --- Mobile: panel becomes bottom sheet --- */
@media (width <= 600px) {
  .notif-history-panel {
    position: fixed;
    top: auto;
    bottom: 0;
    inset-inline: 0;
    width: 100%;
    max-height: 70dvh;
    transform-origin: bottom center;
    animation: sheetReveal 220ms cubic-bezier(0.32, 0.72, 0, 1) both;
  }

  @keyframes sheetReveal {
    from {
      transform: translateY(100%);
      opacity: 0;
    }

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

/* components/modals.css */
/* ============================
   Modal & Tooltip Components
   ============================ */

/* === Modal z-index fix - ensure modals appear above all other content === */

/* These aggressive styles ensure modals escape any parent stacking contexts */
.modal {
  z-index: var(--z-modal, 1055);
  position: fixed;
  inset: 0;
  pointer-events: auto;
  isolation: isolate;
}

.modal-backdrop {
  z-index: var(--z-modal-backdrop, 1050);
  position: fixed;
  inset: 0;
  pointer-events: auto;
  background: rgb(var(--manual-solid-rgb) / 62%);
  transition: opacity 200ms cubic-bezier(0, 0, 0.2, 1);
}

/* Ensure modal dialog and content are interactive */
.modal-dialog {
  pointer-events: auto;
  position: relative;
}

.modal-content {
  pointer-events: auto;
  position: relative;
  background: var(--manual-paper);
  border: 1.5px solid var(--manual-ink);
  box-shadow: 4px 4px 0 var(--manual-rule-faint);
  border-radius: 0;
  animation: modalRise 220ms cubic-bezier(0, 0, 0.2, 1);
}

@keyframes modalRise {
  from {
    opacity: 0;
    transform: scale(0.97) translateY(6px);
  }

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

.modal.fade .modal-dialog {
  opacity: 0;
  transition: opacity 200ms cubic-bezier(0, 0, 0.2, 1);
}

.modal.show .modal-dialog {
  opacity: 1;
}

.modal-header {
  margin: 0 var(--space-4);
  padding: var(--space-4) 0 var(--space-3);
  border-bottom: 3px double var(--manual-ink);
}

.modal-title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  font-weight: 800;
  letter-spacing: var(--tracking-snug);
}

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

.modal-footer {
  margin: 0 var(--space-4);
  border-top: 1px solid var(--manual-rule);
  padding: var(--space-3) 0;
  display: flex;
  gap: var(--space-3);
  justify-content: flex-end;
}

.btn-close-white {
  /* Ensure close button is visible in dark mode */
  filter: invert(1) grayscale(100%) brightness(200%);
}

html.light-mode body .btn-close-white {
  filter: none;
}

/* === Tooltips - Minimal === */
.tooltip-inner {
  padding: var(--space-1) var(--space-2);
  background-color: var(--manual-ink);
  border: 0;
  border-radius: 0;
  box-shadow: none;
  color: var(--manual-paper);
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-wide);
}

.tooltip.show {
  opacity: 1;
}

.bs-tooltip-auto[data-popper-placement^="top"] .tooltip-arrow::before,
.bs-tooltip-top .tooltip-arrow::before {
  border-top-color: var(--manual-ink);
}

/* components/pagination.css */
.pagination-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--pagination-btn-gap, var(--space-2));
  min-height: var(--pagination-btn-min-height, 40px);
  padding: var(--pagination-btn-padding, var(--space-2) var(--space-4));
  border: var(--pagination-btn-border-width, 1px) solid
    var(--pagination-btn-border-color, var(--manual-rule));
  border-radius: var(--pagination-btn-radius, 0);
  background: var(--pagination-btn-bg, transparent);
  color: var(--pagination-btn-color, var(--manual-ink));
  font-family: var(--font-family-label);
  font-size: var(--pagination-btn-font-size, var(--font-size-xs));
  font-weight: var(--pagination-btn-font-weight, 600);
  letter-spacing: var(--tracking-wide);
  cursor: pointer;
  transition: all var(--transition-fast);
}

.pagination-btn:hover:not(:disabled) {
  background: var(--pagination-btn-hover-bg, var(--manual-paper-shade));
  border-color: var(--pagination-btn-hover-border-color, var(--manual-ink));
  color: var(--pagination-btn-hover-color, var(--manual-ink));
}

.pagination-btn:disabled {
  opacity: var(--pagination-btn-disabled-opacity, 0.45);
  cursor: not-allowed;
}

/* components/mapbox-overrides.css */
/* Hide Mapbox attribution and logo controls globally. */
.mapboxgl-ctrl-attrib,
.mapboxgl-ctrl-attrib-inner,
.mapboxgl-ctrl-logo {
  display: none !important;
}

/* Map controls on every map: a printed box of paper buttons with an ink
   rule, square corners, and the icons inked to match the theme. Pages
   load mapbox-gl.css after this file, so each rule is scoped under the map
   container to outrank the Mapbox rule it replaces. */
.mapboxgl-map .mapboxgl-ctrl-group {
  border: 1px solid var(--manual-ink);
  border-radius: 0;
  background: var(--manual-paper);
}

.mapboxgl-map .mapboxgl-ctrl-group:not(:empty) {
  box-shadow: 2px 2px 0 var(--manual-rule-faint);
}

.mapboxgl-map .mapboxgl-ctrl-group button:is(:first-child, :last-child) {
  border-radius: 0;
}

.mapboxgl-map .mapboxgl-ctrl-group button + button {
  border-top: 1px solid var(--manual-rule);
}

.mapboxgl-map .mapboxgl-ctrl button:not(:disabled):hover {
  background-color: var(--manual-paper-shade);
}

.mapboxgl-map .mapboxgl-ctrl-group button:focus:focus-visible {
  outline: var(--focus-outline);
  outline-offset: -3px;
  box-shadow: none;
}

/* The control icons are dark SVGs; the night edition reverses them. */
html:not(.light-mode) .mapboxgl-ctrl-icon {
  filter: invert(92%) sepia(12%) saturate(300%) hue-rotate(5deg);
}

/* Map page navigation lives above the mobile sheet and matches the atlas UI. */
body[data-route="/map"] .mapboxgl-ctrl-bottom-right {
  right: var(--space-3);
  bottom: var(--space-3);
}

body[data-route="/map"] .mapboxgl-ctrl-group button {
  width: 38px;
  height: 38px;
}

/* === Mobile: Enlarge Mapbox navigation controls for touch === */
@media (width <= 768px) {
  body[data-route="/map"] .mapboxgl-ctrl-bottom-right {
    bottom: calc(
      var(--map-sheet-visible-height, 0px) +
      env(safe-area-inset-bottom, 0px) +
      var(--space-3)
    );
  }

  body[data-route="/map"] .mapboxgl-ctrl-group button {
    width: var(--touch-target);
    height: var(--touch-target);
  }

  /* Scale up the SVG icons inside buttons */
  body[data-route="/map"] .mapboxgl-ctrl-group button .mapboxgl-ctrl-icon {
    transform: scale(1.15);
  }
}

/* components/immersive.css */
/* ============================
   Immersive UI Enhancements
   ============================ */

/* Navigation breadcrumb trail - base styles first */
.nav-breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-1) var(--page-gutter);
  background: var(--surface-0);
  border-bottom: 1px solid var(--divider-color);
  transition:
    opacity 180ms cubic-bezier(0, 0, 0.2, 1),
    transform 180ms cubic-bezier(0, 0, 0.2, 1);
}

.nav-breadcrumb[hidden],
.nav-breadcrumb.is-empty {
  display: none;
}

/* Glass surfaces */
.glass {
  background: var(--surface-1);
  border: 1px solid var(--border-color);
}

/* Ripple base */
.ripple-container {
  position: relative;
  overflow: hidden;
  transform: translateZ(0);
}

.es-ripple {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--primary-rgb) / 30%) 0%, transparent 70%);
  animation: ripple 500ms cubic-bezier(0, 0, 0.2, 1) forwards;
  pointer-events: none;
}

/* Staggered reveal helpers */
.stagger-item {
  opacity: 0;
  animation: fadeInUp 300ms cubic-bezier(0, 0, 0.2, 1) forwards;
}

.nav-trail {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--font-size-xs);
  color: var(--text-secondary);
  list-style: none;
  margin: 0;
  min-width: 0;
  padding: 0;
  animation: fadeIn 200ms cubic-bezier(0, 0, 0.2, 1) both;
}

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

.nav-trail-item {
  color: inherit;
  text-decoration: none;
  transition: color 120ms cubic-bezier(0.4, 0, 0.2, 1);
}

.nav-trail-item:hover {
  color: var(--manual-rust-ink);
}

.nav-trail-item.current {
  color: var(--manual-ink);
  font-weight: var(--font-weight-semibold);
}

.nav-trail-sep {
  color: var(--manual-rust);
}

body[data-route="/map"] .nav-breadcrumb {
  display: none;
}

body[data-route="/coverage-route-planner"] .nav-breadcrumb,
body[data-route="/live-navigation"] .nav-breadcrumb,
body[data-route="/regional-coverage-explorer"] .nav-breadcrumb {
  display: none;
}

/* Bottom navigation (mobile) */
.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: none;
  align-items: center;
  justify-content: space-around;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3) calc(var(--space-2) + env(safe-area-inset-bottom));
  background: var(--surface-1);
  border-top: 3px double var(--manual-ink);
  z-index: var(--z-fixed);
  transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1);
  background-color: var(--manual-paper);
}

.bottom-nav.hidden {
  transform: translateY(100%);
}

.bottom-nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  color: var(--text-secondary);
  text-decoration: none;
  background: none;
  border: none;
  font-size: var(--font-size-xs);
  min-height: var(--touch-target);
  padding: var(--space-1) var(--space-2);
  min-width: 64px;
  position: relative;
  font-family: var(--font-family-label);
  font-weight: var(--font-weight-semibold);
}

.bottom-nav-item i {
  font-size: var(--font-size-lg);
  color: var(--text-secondary);
  transition: color 120ms cubic-bezier(0.4, 0, 0.2, 1);
}

.bottom-nav-item.active,
.bottom-nav-item:focus-visible,
.bottom-nav-item:hover {
  color: var(--text-primary);
}

.bottom-nav-item.active i,
.bottom-nav-item:hover i {
  color: var(--text-primary);
}

.bottom-nav-item.active::after {
  content: "";
  position: absolute;
  bottom: 2px;
  left: 50%;
  width: 28px;
  height: 2px;
  transform: translateX(-50%);
  background: var(--action);
}

@media (width <= 768px) {
  .bottom-nav {
    display: flex;
  }

  body[data-route="/map"] .bottom-nav {
    display: none;
  }
}

/* Density adjustments */
body.density-compact {
  --space-1: 0.2rem;
  --space-2: 0.4rem;
  --space-3: 0.6rem;
  --space-4: 0.8rem;
  --space-5: 1rem;
  --space-6: 1.2rem;
}

body.density-spacious {
  --space-1: 0.3rem;
  --space-2: 0.6rem;
  --space-3: 0.9rem;
  --space-4: 1.2rem;
  --space-5: 1.5rem;
  --space-6: 1.8rem;
}

.bottom-nav-item,
.bottom-nav-item i {
  color: var(--manual-ink-soft);
}

.nav-trail-item,
.nav-trail-sep {
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--manual-ink-soft);
}

/* components/icons.css */
/* ============================
   Icon System
   ============================ */

i.fas,
i.far,
i.fab,
i.fa,
i.fa-solid,
i.fa-regular,
i.fa-brands,
.icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1em;
  height: 1em;
  line-height: 1;
}

/* components/setup-required.css */
/* ============================
   Setup Required Modal
   ============================ */

.setup-required-modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--space-6) var(--page-gutter);
}

.setup-required-backdrop {
  position: absolute;
  inset: 0;
  background: rgb(7 12 18 / 55%);
  z-index: var(--z-modal-backdrop);
}

.setup-required-dialog {
  position: relative;
  z-index: var(--z-modal);
  width: min(720px, 100%);
}

.setup-required-card {
  background: var(--surface-elevated);
  border: 1px solid var(--border-color);
  border-left: 4px solid var(--warning);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg);
  display: grid;
  gap: var(--space-4);
  padding: clamp(1rem, 2vw, 1.6rem);
  grid-template-columns: auto 1fr;
  align-items: start;
  position: relative;
}

.setup-required-icon {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  background: rgb(var(--warning-rgb) / 18%);
  color: rgb(var(--warning-rgb) / 95%);
  font-size: var(--font-size-md);
  box-shadow: inset 0 0 0 1px rgb(var(--warning-rgb) / 20%);
}

.setup-required-body {
  display: grid;
  gap: var(--space-2);
}

.setup-required-title {
  font-family: var(--font-family-text);
  font-size: var(--font-size-md);
  font-weight: var(--font-weight-bold);
  color: var(--text-primary);
  letter-spacing: var(--tracking-wide);
}

.setup-required-message {
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--font-size-sm);
}

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

.setup-required-item {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  font-size: var(--font-size-sm);
  color: var(--text-secondary);
}

.setup-required-item-title {
  font-weight: var(--font-weight-semibold);
  color: var(--text-primary);
}

.setup-required-item-detail {
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
}

.setup-required-item i {
  margin-top: 0.1rem;
  color: var(--warning);
}

.setup-required-item.is-complete {
  color: var(--text-tertiary);
}

.setup-required-item.is-complete i {
  color: var(--success);
}

.setup-required-actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  align-items: flex-start;
}

.setup-required-actions .btn {
  white-space: nowrap;
}

.setup-required-footnote {
  font-size: var(--font-size-xs);
  color: var(--text-tertiary);
}

.setup-required-toggle {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 32px;
  height: 32px;
  border-radius: 10px;
  border: 1px solid rgb(var(--warning-rgb) / 25%);
  background: rgb(var(--surface-rgb) / 55%);
  color: var(--text-tertiary);
  font-size: var(--font-size-lg);
  line-height: 1;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition:
    color var(--transition-fast),
    border-color var(--transition-fast);
}

.setup-required-toggle:hover {
  color: var(--text-primary);
  border-color: rgb(var(--warning-rgb) / 55%);
}

.setup-required-fab {
  position: fixed;
  right: var(--space-5);
  bottom: var(--space-5);
  z-index: var(--z-modal);
  background: rgb(var(--warning-rgb) / 18%);
  border: 1px solid rgb(var(--warning-rgb) / 45%);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  padding: 0.65rem 1rem;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  box-shadow: var(--shadow-sm);
  font-size: var(--font-size-sm);
}

.setup-required-fab:hover {
  border-color: rgb(var(--warning-rgb) / 65%);
}

@media (width >= 900px) {
  .setup-required-card {
    grid-template-columns: auto 1fr auto;
    align-items: center;
  }

  .setup-required-actions {
    align-items: flex-end;
  }
}

@media (width <= 899px) {
  .setup-required-card {
    grid-template-columns: auto 1fr;
  }

  .setup-required-actions {
    grid-column: 1 / -1;
    flex-flow: row wrap;
    justify-content: space-between;
    align-items: center;
  }

  .setup-required-actions .btn {
    flex: 1 1 auto;
  }
}

@media (width <= 600px) {
  .setup-required-card {
    grid-template-columns: 1fr;
  }

  .setup-required-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .setup-required-fab {
    right: var(--space-4);
    left: var(--space-4);
    justify-content: center;
  }
}

/* components/date-picker.css */
/* ============================
   Date range picker
   Compact preset menu with an on-demand Flatpickr range calendar.
   ============================ */

.date-picker-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.date-picker-trigger {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-width: 0;
  min-height: var(--touch-target);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--manual-ink);
  border-radius: 0;
  background: var(--manual-paper);
  color: var(--manual-ink);
  font-family: var(--font-family-text);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  white-space: nowrap;
  cursor: pointer;
  transition:
    color var(--transition-fast),
    border-color var(--transition-fast),
    background var(--transition-fast);
  box-shadow: 2px 2px 0 var(--manual-rule-faint);
}

.date-picker-trigger:hover {
  border-color: var(--border-color-light);
  background: var(--manual-paper-shade);
  color: var(--manual-ink);
}

.date-picker-trigger:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 2px;
}

.date-picker-trigger .trigger-text {
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.date-picker-trigger .trigger-calendar {
  display: inline-block;
  flex-shrink: 0;
  color: var(--manual-ink-soft);
  font-size: var(--font-size-sm);
}

.date-picker-trigger .trigger-chevron {
  flex-shrink: 0;
  margin-left: var(--space-1);
  color: var(--text-tertiary);
  font-size: var(--font-size-xs);
  transition: transform var(--transition-fast);
}

.date-picker-trigger[aria-expanded="true"] .trigger-chevron {
  transform: rotate(180deg);
}

/* A range other than today: the box gets a rust offset, like a
   pencilled mark in the margin. */
.date-picker-trigger.has-filter {
  border-color: var(--manual-ink);
  background: var(--manual-paper-shade);
  color: var(--manual-ink);
  box-shadow: 2px 2px 0 var(--manual-rust);
}

.date-picker-dropdown {
  --dp-drag-y: 0px;

  position: fixed;
  inset: auto 0 0;
  z-index: var(--z-overlay);
  display: flex;
  flex-direction: column;
  width: 100%;
  max-height: min(94dvh, 46rem);
  overflow: hidden;
  border: 1.5px solid var(--manual-ink);
  border-bottom: 0;
  border-radius: 0;
  background: var(--manual-paper);
  color: var(--manual-ink);
  box-shadow: 0 -3px 0 var(--manual-rule-faint);
  opacity: 0;
  visibility: hidden;
  transform: translateY(100%);
  transition:
    opacity var(--transition-fast),
    visibility var(--transition-fast),
    transform var(--transition-normal);
}

.date-picker-dropdown.open {
  opacity: 1;
  visibility: visible;
  transform: translateY(var(--dp-drag-y));
}

/* While a drag is in flight the sheet must track the finger exactly. */
.date-picker-dropdown.dragging {
  transition: none;
}

/* Grab handle doubles as the swipe-to-dismiss target, so it needs a
   real touch height rather than a decorative 4px bar. */
.dp-grabber {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  height: 1.5rem;
  touch-action: none;
  cursor: grab;
}

.dp-grabber-bar {
  width: 2.5rem;
  height: 0.25rem;
  border-radius: var(--radius-sm);
  background: var(--manual-rule);
}

.date-picker-dropdown.dragging .dp-grabber {
  cursor: grabbing;
}

body.date-picker-open {
  overflow: hidden;
}

/* iOS Safari ignores `overflow: hidden` on the document scroller, so the
   page behind the sheet keeps scrolling. Pinning the body is the only
   reliable lock; date-manager.js restores the offset on close. */
body.date-picker-scroll-locked {
  position: fixed;
  inset-inline: 0;
  width: 100%;
}

.dp-header {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 0 var(--space-4) var(--space-3);
  border-bottom: 3px double var(--manual-ink);
  touch-action: none;
}

.dp-title {
  display: block;
  font-family: var(--font-family-display);
  font-size: var(--font-size-xl);
  font-weight: 800;
  line-height: var(--line-height-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--manual-ink);
}

.dp-section-label,
.dp-range-label {
  color: var(--manual-rust-ink);
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.dp-close-btn {
  display: inline-flex;
  flex: 0 0 var(--touch-target);
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  padding: 0;
  border: 1px solid var(--manual-ink);
  border-radius: 0;
  background: transparent;
  color: var(--manual-ink);
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast);
}

.dp-close-btn:hover {
  border-color: var(--manual-ink);
  background: var(--manual-paper-shade);
  color: var(--manual-ink);
}

.dp-close-btn:focus-visible,
.preset-btn:focus-visible,
.dp-actions button:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 2px;
}

/* Single scroll container for the whole sheet. The footer lives outside it so
   the primary action can never be pushed below the fold. */
.dp-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb-color) transparent;
  -webkit-overflow-scrolling: touch;
}

.dp-section {
  padding: var(--space-4);
}

.dp-preset-section {
  flex: 0 0 auto;
  padding-block: var(--space-4) var(--space-3);
}

.dp-section-label {
  display: block;
  margin-bottom: var(--space-2);
}

.dp-presets {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  border-top: 1px solid var(--manual-rule);
  border-left: 1px solid var(--manual-rule);
}

.preset-btn {
  min-width: 0;
  min-height: var(--touch-target);
  padding: var(--space-2);
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--manual-ink);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  line-height: 1.25;
  text-align: center;
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast),
    transform var(--transition-fast);
  border-right: 1px solid var(--manual-rule);
  border-bottom: 1px solid var(--manual-rule);
  font-family: var(--font-family-text);
}

.preset-btn:hover {
  border-color: var(--manual-rule);
  background: var(--manual-paper-shade);
  color: var(--manual-ink);
}

.preset-btn:active {
  transform: scale(0.98);
}

.preset-btn.active {
  border-color: var(--manual-ink);
  background: var(--manual-ink);
  color: var(--manual-paper);
  box-shadow: inset 0 0 0 1px rgb(var(--primary-rgb) / 12%);
}

.preset-btn.btn-loading {
  opacity: 0.6;
  pointer-events: none;
}

.dp-custom-toggle {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--space-3);
  min-height: var(--touch-target);
  margin: 0 var(--space-4) var(--space-4);
  padding: var(--space-3);
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  background: transparent;
  color: var(--manual-ink);
  text-align: left;
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast);
}

.dp-custom-toggle:hover {
  border-color: var(--border-color-light);
  background: var(--surface-2);
  color: var(--text-primary);
}

.dp-custom-toggle:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 2px;
}

.dp-custom-toggle[aria-expanded="true"] {
  margin-bottom: 0;
  margin-inline: 0;
  border-color: transparent;
  border-bottom-color: var(--divider-color);
  border-radius: 0;
  background: var(--surface-2);
  color: var(--text-primary);
}

.dp-custom-copy {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
}

.dp-custom-copy strong {
  color: var(--manual-ink);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  font-family: var(--font-family-text);
}

.dp-custom-copy span {
  overflow: hidden;
  margin-top: 0.1rem;
  color: var(--text-tertiary);
  font-family: var(--font-numeric);
  font-size: var(--font-size-xs);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dp-custom-chevron {
  color: var(--text-tertiary);
  font-size: var(--font-size-xs);
  transition: transform var(--transition-fast);
}

.dp-custom-toggle[aria-expanded="true"] .dp-custom-chevron {
  transform: rotate(180deg);
}

/* Expanded, the summary line just repeats the start/end fields below it. */
.dp-custom-toggle[aria-expanded="true"] .dp-custom-copy span {
  display: none;
}

.dp-custom-panel {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-height: 0;
  padding: var(--space-3) var(--space-4) var(--space-4);
}

.dp-custom-panel[hidden] {
  display: none;
}

.date-picker-dropdown.custom-open .dp-preset-section {
  display: none;
}

.dp-range-hint {
  margin: 0 0 var(--space-3);
  color: var(--text-tertiary);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-normal);
}

.dp-range-summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: stretch;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  background: transparent;
}

.dp-range-endpoint {
  min-width: 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  background: transparent;
}

.dp-range-endpoint.is-awaiting {
  border-color: var(--manual-rust);
  background: var(--manual-paper-shade);
}

.dp-range-endpoint strong {
  display: block;
  margin-top: var(--space-1);
  color: var(--manual-ink);
  font-family: var(--font-family-display);
  font-size: var(--font-size-sm);
  font-weight: 800;
  line-height: 1.3;
  overflow-wrap: anywhere;
}

.dp-range-arrow {
  align-self: center;
  color: var(--manual-ink-faint);
  font-size: var(--font-size-xs);
}

/* flex-shrink must stay 0: the calendar is a fixed-height grid, so squeezing
   it just clips the last weeks of the month. Overflow scrolls in .dp-body. */
.dp-calendar-host {
  position: relative;
  flex: 0 0 auto;
  width: 100%;
  overflow: hidden;
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  background: transparent;
}

.dp-range-input {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
}

/* Pinned action bar: always visible, never inside the scroll region. */
.dp-actions {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4)
    max(var(--space-3), env(safe-area-inset-bottom));
  border-top: 3px double var(--manual-ink);
  background: var(--manual-paper);
}

.dp-actions[hidden] {
  display: none;
}

.dp-range-count {
  min-width: 0;
  overflow: hidden;
  color: var(--manual-ink-soft);
  font-family: var(--font-family-text);
  font-size: var(--font-size-xs);
  text-overflow: ellipsis;
  white-space: nowrap;
  font-style: italic;
}

.dp-actions .btn-apply {
  flex: 1 1 auto;
  min-height: var(--touch-target);
  min-width: 8rem;
  max-width: 14rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--manual-ink);
  border-radius: 0;
  background: var(--manual-ink);
  color: var(--manual-paper);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast),
    transform var(--transition-fast);
  font-family: var(--font-family-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.dp-actions .btn-apply:hover {
  background: var(--manual-ink-soft);
}

.dp-actions button:active {
  transform: scale(0.98);
}

.dp-actions .btn-apply:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.dp-actions .btn-apply.btn-loading {
  opacity: 0.65;
  pointer-events: none;
}

.date-picker-overlay {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-overlay) - 1);
  display: block;
  background: rgb(var(--backdrop-rgb) / 62%);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    opacity var(--transition-fast),
    visibility var(--transition-fast);
}

.date-picker-overlay.visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

@media (width >= 769px) {

  .date-picker-trigger .trigger-text {
    max-width: 15rem;
  }

  .date-picker-dropdown {
    position: absolute;
    inset: calc(100% + var(--space-2)) 0 auto auto;
    z-index: var(--z-dropdown);
    width: min(23rem, calc(100vw - var(--space-8)));
    max-height: calc(100dvh - var(--header-height) - var(--space-4));
    transform: translateY(-0.5rem) scale(0.985);
    transform-origin: top right;
  border-bottom: 1.5px solid var(--manual-ink);
  border-radius: 0;
  box-shadow: 4px 4px 0 var(--manual-rule-faint);
  }

  .dp-grabber {
    display: none;
  }

  .date-picker-dropdown.open {
    transform: translateY(0) scale(1);
  }

  .date-picker-dropdown.custom-open {
    width: min(44rem, calc(100vw - var(--space-8)));
  }

  .dp-header {
    padding: var(--space-3) var(--space-4);
    touch-action: auto;
  }

  .dp-preset-section {
    padding: var(--space-4);
  }

  .dp-presets {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .dp-custom-panel {
    padding-inline: var(--space-4);
  }

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

  .dp-actions .btn-apply {
    flex: 0 0 auto;
  }
}

/* Short viewports (most phones, and anything in landscape) — trade day-cell
   height for a month grid that fits without scrolling. */
@media (width <= 768px) and (height <= 740px) {
  .dp-calendar-host {
    --dp-day-size: 2.25rem;
  }

  body .dp-calendar-host .flatpickr-weekdays {
    height: 1.75rem;
  }

  .dp-range-endpoint strong {
    margin-top: 0;
  }

  .dp-range-hint {
    margin-bottom: var(--space-2);
  }

  .dp-custom-panel {
    padding-top: var(--space-2);
  }
}

/* Smallest phones: the standing instruction is redundant once the start/end
   fields spell out what is missing. */
@media (width <= 768px) and (height <= 640px) {
  .dp-calendar-host {
    --dp-day-size: 2.125rem;
  }

  .dp-range-hint {
    display: none;
  }
}

/* ============================
   Flatpickr theme — shared popovers and the embedded range calendar
   ============================ */

.datepicker,
.datepicker.flatpickr-input {
  border: 1px solid rgb(var(--border-rgb) / 34%);
  background: var(--surface-2);
  color: var(--text-primary);
  transition:
    border-color var(--transition-fast),
    box-shadow var(--transition-fast),
    background var(--transition-fast);
}

.datepicker::placeholder,
.datepicker.flatpickr-input::placeholder {
  color: var(--text-tertiary);
}

.datepicker:focus,
.datepicker.flatpickr-input:focus {
  border-color: rgb(var(--primary-rgb) / 55%);
  outline: none;
  background: var(--surface-2);
  box-shadow: var(--focus-ring);
}

body .flatpickr-calendar {
  overflow: hidden;
  border: 1px solid var(--manual-ink);
  border-radius: 0;
  background: var(--manual-paper);
  color: var(--text-primary);
  font-family: var(--font-family);
  box-shadow: 3px 3px 0 var(--manual-rule-faint);
  z-index: calc(var(--z-overlay) + 1) !important;
}

body .flatpickr-calendar.arrowTop::before {
  border-bottom-color: rgb(var(--border-rgb) / 35%);
}

body .flatpickr-calendar.arrowTop::after {
  border-bottom-color: var(--surface-elevated);
}

body .flatpickr-calendar.arrowBottom::before {
  border-top-color: rgb(var(--border-rgb) / 35%);
}

body .flatpickr-calendar.arrowBottom::after {
  border-top-color: var(--surface-elevated);
}

/* Flatpickr absolutely positions the month nav inside a 75%-wide box and lets
   the native month <select> size itself from its widest option. At the 16px
   font touch viewports force (forms.css), that select outgrows its box and
   shoves the year out of the clipped calendar — the month/year header ends up
   as one giant control with no year at all. Lay the row out with flexbox so
   the arrows, month and year always share the available width. */
body .flatpickr-calendar .flatpickr-months {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1);
  border-bottom: 1px solid var(--divider-color);
  background: var(--surface-elevated);
}

body .flatpickr-calendar .flatpickr-month {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  justify-content: center;
  min-width: 0;
  height: auto;
  min-height: var(--touch-target);
  color: var(--text-primary);
  fill: var(--text-primary);
}

body .flatpickr-calendar .flatpickr-current-month {
  position: static;
  display: flex;
  flex: 0 1 auto;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  width: auto;
  max-width: 100%;
  height: auto;
  padding: 0;
  color: var(--text-primary);
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-semibold);
  transform: none;
}

body .flatpickr-calendar .flatpickr-current-month .flatpickr-monthDropdown-months,
body .flatpickr-calendar .flatpickr-current-month input.cur-year {
  height: auto;
  min-height: 2.25rem;
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-weight: var(--font-weight-semibold);
  transition: background-color var(--transition-fast);
}

/* The month control is the one that overflows, so it gets an explicit
   shrinkable box and an app-drawn caret instead of the native menulist. */
body .flatpickr-calendar .flatpickr-current-month .flatpickr-monthDropdown-months {
  flex: 0 1 auto;
  width: auto;
  min-width: 0;
  max-width: 100%;
  margin: 0;
  padding: var(--space-1) calc(var(--space-4) + var(--space-3)) var(--space-1)
    var(--space-2);
  appearance: none;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background-color: var(--surface-2);
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23c2b79f' stroke-linecap='square' stroke-width='1.6' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right var(--space-2) center;
  background-size: 0.7rem 0.55rem;
  font-size: var(--font-size-sm);
  text-overflow: ellipsis;
}

html.light-mode
  body
  .flatpickr-calendar
  .flatpickr-current-month
  .flatpickr-monthDropdown-months {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23564f41' stroke-linecap='square' stroke-width='1.6' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
}

body .flatpickr-calendar .flatpickr-current-month .numInputWrapper {
  flex: 0 0 auto;
  width: 4.25rem;
}

/* Deliberately no font-size override on the year field: forms.css forces 16px
   on touch viewports so focusing it does not trigger iOS auto-zoom. */
body .flatpickr-calendar .flatpickr-current-month input.cur-year {
  padding: var(--space-1) 0 var(--space-1) var(--space-1);
}

/* `background-color`, not `background`: the shorthand would drop the caret. */
body .flatpickr-calendar .flatpickr-current-month .flatpickr-monthDropdown-months:hover,
body .flatpickr-calendar .flatpickr-current-month .flatpickr-monthDropdown-months:focus,
body .flatpickr-calendar .flatpickr-current-month input.cur-year:hover,
body .flatpickr-calendar .flatpickr-current-month input.cur-year:focus {
  background-color: rgb(var(--primary-rgb) / 12%);
}

body
  .flatpickr-calendar
  .flatpickr-current-month
  .flatpickr-monthDropdown-months
  option {
  background: var(--surface-2);
  color: var(--text-primary);
}

body .flatpickr-calendar .flatpickr-months .flatpickr-prev-month,
body .flatpickr-calendar .flatpickr-months .flatpickr-next-month {
  position: static;
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  padding: 0;
  border-radius: var(--radius-md);
  color: var(--manual-ink);
  fill: var(--manual-ink);
  transition:
    color var(--transition-fast),
    fill var(--transition-fast),
    background var(--transition-fast);
}

body .flatpickr-calendar .flatpickr-months .flatpickr-prev-month:hover,
body .flatpickr-calendar .flatpickr-months .flatpickr-next-month:hover,
body .flatpickr-calendar .flatpickr-months .flatpickr-prev-month:focus-visible,
body .flatpickr-calendar .flatpickr-months .flatpickr-next-month:focus-visible {
  background: rgb(var(--primary-rgb) / 14%);
  color: var(--text-primary);
  fill: var(--text-primary);
}

body .flatpickr-calendar .flatpickr-months .flatpickr-prev-month:hover svg,
body .flatpickr-calendar .flatpickr-months .flatpickr-next-month:hover svg,
body .flatpickr-calendar .flatpickr-months .flatpickr-prev-month:focus-visible svg,
body .flatpickr-calendar .flatpickr-months .flatpickr-next-month:focus-visible svg {
  fill: currentcolor;
}

body .flatpickr-calendar .flatpickr-weekdays {
  height: 2.5rem;
  border-bottom: 1px solid var(--divider-color);
  background: transparent;
}

body .flatpickr-calendar span.flatpickr-weekday {
  color: var(--manual-ink-faint);
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

/* Horizontal padding must stay 0: flatpickr hard-codes the day grid's width in
   inline styles, so side padding pushes the last column past the calendar's
   clipped edge (Saturdays lose ~6px). Vertical padding is safe. */
body .flatpickr-calendar .flatpickr-days {
  border: 0;
  padding: var(--space-2) 0;
}

body .flatpickr-calendar .flatpickr-day {
  border: 1px solid transparent;
  border-radius: 0;
  color: var(--manual-ink-soft);
  font-weight: var(--font-weight-medium);
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast),
    box-shadow var(--transition-fast);
  font-family: var(--font-family-text);
  font-variant-numeric: lining-nums tabular-nums;
}

body .flatpickr-calendar .flatpickr-day:hover,
body .flatpickr-calendar .flatpickr-day:focus {
  border-color: var(--manual-rule);
  background: var(--manual-paper-shade);
  color: var(--manual-ink);
}

body .flatpickr-calendar .flatpickr-day.today {
  border-color: var(--manual-rust);
  color: var(--manual-rust-ink);
}

body .flatpickr-calendar .flatpickr-day.today:hover,
body .flatpickr-calendar .flatpickr-day.today:focus {
  border-color: var(--manual-rust);
  background: var(--manual-paper-shade);
  color: var(--manual-ink);
}

/* Day cells tile edge to edge here, so flatpickr's ±5px box-shadow trick for
   bridging its default gaps only produces overlapping, blotchy corners. A
   square-cornered fill gives one continuous band instead. */
body .flatpickr-calendar .flatpickr-day.inRange,
body .flatpickr-calendar .flatpickr-day.prevMonthDay.inRange,
body .flatpickr-calendar .flatpickr-day.nextMonthDay.inRange {
  border-color: transparent;
  border-radius: 0;
  background: rgb(var(--primary-rgb) / 18%);
  color: var(--manual-ink);
  box-shadow: none;
  background-color: rgb(var(--manual-navy-rgb) / 14%);
  background-image: repeating-linear-gradient(
    -52deg,
    rgb(var(--manual-navy-rgb) / 38%) 0 1px,
    transparent 1px 5px
  );
}

body .flatpickr-calendar .flatpickr-day.selected,
body .flatpickr-calendar .flatpickr-day.startRange,
body .flatpickr-calendar .flatpickr-day.endRange,
body .flatpickr-calendar .flatpickr-day.selected.inRange,
body .flatpickr-calendar .flatpickr-day.startRange.inRange,
body .flatpickr-calendar .flatpickr-day.endRange.inRange {
  border-color: var(--manual-ink);
  background: var(--manual-ink);
  color: var(--manual-paper);
  box-shadow: none;
  background-image: none;
}

body .flatpickr-calendar .flatpickr-day.startRange:not(.endRange) {
  border-radius: var(--radius-md) 0 0 var(--radius-md);
}

body .flatpickr-calendar .flatpickr-day.endRange:not(.startRange) {
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

body .flatpickr-calendar .flatpickr-day.prevMonthDay,
body .flatpickr-calendar .flatpickr-day.nextMonthDay {
  color: var(--text-tertiary);
  opacity: 0.48;
}

body .flatpickr-calendar .flatpickr-day.flatpickr-disabled,
body .flatpickr-calendar .flatpickr-day.flatpickr-disabled:hover,
body .flatpickr-calendar .flatpickr-day.notAllowed,
body .flatpickr-calendar .flatpickr-day.notAllowed:hover {
  color: var(--text-tertiary);
  opacity: 0.28;
}

body .flatpickr-calendar .flatpickr-time {
  border-top: 1px solid var(--divider-color);
  background: var(--surface-2);
}

body .flatpickr-calendar .flatpickr-time input,
body .flatpickr-calendar .flatpickr-time .flatpickr-am-pm {
  color: var(--text-primary);
  font-weight: var(--font-weight-semibold);
}

body .flatpickr-calendar .flatpickr-time input:hover,
body .flatpickr-calendar .flatpickr-time .flatpickr-am-pm:hover,
body .flatpickr-calendar .flatpickr-time input:focus,
body .flatpickr-calendar .flatpickr-time .flatpickr-am-pm:focus {
  background: var(--surface-3);
}

/* Embedded calendar fills the picker instead of opening another popover. */
.dp-calendar-host .flatpickr-calendar.inline {
  position: relative;
  inset: auto;
  display: block;
  width: 100% !important;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  z-index: auto !important;
}

.dp-calendar-host .flatpickr-innerContainer,
.dp-calendar-host .flatpickr-rContainer,
.dp-calendar-host .flatpickr-days {
  width: 100%;
  max-width: none;
}

.dp-calendar-host .flatpickr-days {
  width: 100% !important;
  overflow: visible;
  padding: var(--space-1);
}

.dp-calendar-host .dayContainer {
  width: 100%;
  min-width: 100%;
  max-width: 100%;
}

.dp-calendar-host .flatpickr-day {
  flex-basis: 14.2857%;
  max-width: none;
  height: var(--dp-day-size, var(--touch-target));
  line-height: var(--dp-day-size, var(--touch-target));
}

/* Flatpickr's month nav is replaced by .dp-month-nav: its native <select>
   sits inside a translate3d'd element, which iOS Safari refuses to open. */
body .dp-calendar-host .flatpickr-months {
  display: none;
}

body .dp-calendar-host .flatpickr-weekdays {
  height: 2rem;
}

.dp-month-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1);
  padding: var(--space-1);
  border-bottom: 1px solid var(--divider-color);
}

.dp-month-step {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: var(--touch-target);
  height: var(--touch-target);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--manual-ink);
  font-size: var(--font-size-sm);
  cursor: pointer;
  transition:
    background var(--transition-fast),
    color var(--transition-fast);
}

.dp-month-step:hover:not(:disabled) {
  background: rgb(var(--primary-rgb) / 14%);
  color: var(--text-primary);
}

.dp-month-step:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.dp-month-label {
  display: inline-flex;
  flex: 0 1 auto;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-width: 0;
  min-height: 2.25rem;
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  background: transparent;
  color: var(--manual-ink);
  font-size: var(--font-size-sm);
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast);
  font-family: var(--font-family-display);
}

.dp-month-label:hover {
  border-color: var(--manual-ink);
  background: var(--manual-paper-shade);
}

.dp-month-caret {
  flex-shrink: 0;
  color: var(--text-tertiary);
  font-size: var(--font-size-xs);
  transition: transform var(--transition-fast);
}

.dp-month-label[aria-expanded="true"] .dp-month-caret {
  transform: rotate(180deg);
}

.dp-month-step:focus-visible,
.dp-month-label:focus-visible,
.dp-month-option:focus-visible {
  outline: var(--focus-outline);
  outline-offset: 2px;
}

.dp-month-grid {
  padding: var(--space-2);
  background: var(--surface-1);
}

.dp-month-grid[hidden] {
  display: none;
}

/* The month grid takes the day grid's place rather than pushing it down, so
   the sheet keeps its height and nothing scrolls out of reach. */
.dp-calendar-host.month-grid-open .flatpickr-calendar {
  display: none;
}

.dp-year-step {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}

.dp-year-value {
  font-size: var(--font-size-sm);
  font-weight: 800;
  font-family: var(--font-family-display);
  color: var(--manual-ink);
}

.dp-month-options {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
}

.dp-month-option {
  min-height: var(--touch-target);
  padding: var(--space-2);
  border: 1px solid var(--manual-rule);
  border-radius: 0;
  background: transparent;
  color: var(--manual-ink);
  font-size: var(--font-size-sm);
  cursor: pointer;
  transition:
    background var(--transition-fast),
    border-color var(--transition-fast),
    color var(--transition-fast);
  font-family: var(--font-family-text);
}

.dp-month-option:hover:not(:disabled) {
  border-color: var(--manual-ink);
  background: var(--manual-paper-shade);
  color: var(--manual-ink);
}

.dp-month-option.active {
  border-color: var(--manual-ink);
  background: var(--manual-ink);
  color: var(--manual-paper);
}

.dp-month-option:disabled {
  opacity: 0.32;
  cursor: not-allowed;
}

/* `.flatpickr-month` is intentionally excluded: it is a flex child of the nav
   row and has to share that row with the two arrow buttons. */
.dp-calendar-host .flatpickr-calendar.es-single-month,
.dp-calendar-host .flatpickr-calendar.es-single-month .flatpickr-months,
.dp-calendar-host .flatpickr-calendar.es-single-month .flatpickr-weekdays,
.dp-calendar-host .flatpickr-calendar.es-single-month .flatpickr-weekdaycontainer,
.dp-calendar-host .flatpickr-calendar.es-single-month .flatpickr-days,
.dp-calendar-host .flatpickr-calendar.es-single-month .dayContainer {
  flex: 0 0 100%;
  width: 100%;
  min-width: 100%;
  max-width: 100%;
}

.dp-calendar-host .flatpickr-calendar.multiMonth .dayContainer:nth-child(n + 1) {
  border-left: 1px solid var(--divider-color);
  box-shadow: none;
}

@media (width >= 769px) {
  .dp-calendar-host .flatpickr-day {
    height: 2.5rem;
    line-height: 2.5rem;
  }

  .dp-calendar-host .flatpickr-calendar.es-multi-month .dayContainer,
  .dp-calendar-host .flatpickr-calendar.es-multi-month .flatpickr-weekdaycontainer {
    flex: 0 0 50%;
    width: 50%;
    min-width: 50%;
    max-width: 50%;
  }

  /* Both month headers grow into whatever the arrow buttons leave behind. */
  .dp-calendar-host .flatpickr-calendar.es-multi-month .flatpickr-month {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
    max-width: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .date-picker-dropdown,
  .date-picker-overlay,
  .preset-btn,
  .dp-custom-toggle,
  .dp-actions button {
    transition: none;
  }
}

.dp-custom-toggle:hover,
.dp-custom-toggle[aria-expanded="true"] {
  border-color: var(--manual-ink);
  background: var(--manual-paper-shade);
}

.dp-custom-copy span,
.dp-range-hint {
  font-family: var(--font-family-text);
  font-style: italic;
  color: var(--manual-ink-faint);
}

.dp-range-endpoint.is-awaiting strong {
  color: var(--manual-ink-faint);
}

.dp-close-btn:focus-visible,
.preset-btn:focus-visible,
.dp-custom-toggle:focus-visible,
.dp-actions button:focus-visible,
.date-picker-trigger:focus-visible {
  outline: 2px solid var(--manual-rust);
  outline-offset: 2px;
}

.dp-calendar-host .flatpickr-calendar {
  border: 0;
  background: transparent;
  box-shadow: none;
}

body .flatpickr-calendar .flatpickr-current-month,
body .flatpickr-calendar .flatpickr-current-month .flatpickr-monthDropdown-months,
body .flatpickr-calendar .flatpickr-current-month input.cur-year {
  font-family: var(--font-family-display);
  font-weight: 800;
  color: var(--manual-ink);
}

body .flatpickr-calendar .flatpickr-day.startRange:not(.endRange),
body .flatpickr-calendar .flatpickr-day.endRange:not(.startRange) {
  border-radius: 0;
}

body .flatpickr-calendar .flatpickr-day.selected.startRange,
body .flatpickr-calendar .flatpickr-day.selected.endRange,
body .flatpickr-calendar .flatpickr-day.startRange.endRange {
  border-radius: 0;
}

/* core/animations.css */
/* ============================
   Animation Keyframes
   ============================ */

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

  to {
    opacity: 1;
  }
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(12px);
  }

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

@keyframes fadeInDown {
  from {
    opacity: 0;
    transform: translateY(-12px);
  }

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

@keyframes fadeInScale {
  from {
    opacity: 0;
    transform: scale(0.97);
  }

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

/* Stagger animation utility classes */
.stagger-container > * {
  opacity: 0;
  animation: fadeInUp 280ms cubic-bezier(0, 0, 0.2, 1) forwards;
}

.stagger-container > *:nth-child(1) {
  animation-delay: 30ms;
}

.stagger-container > *:nth-child(2) {
  animation-delay: 70ms;
}

.stagger-container > *:nth-child(3) {
  animation-delay: 110ms;
}

.stagger-container > *:nth-child(4) {
  animation-delay: 150ms;
}

.stagger-container > *:nth-child(5) {
  animation-delay: 185ms;
}

.stagger-container > *:nth-child(6) {
  animation-delay: 220ms;
}

.stagger-container > *:nth-child(7) {
  animation-delay: 250ms;
}

.stagger-container > *:nth-child(8) {
  animation-delay: 280ms;
}

@media (prefers-reduced-motion: reduce) {
  .stagger-container > * {
    animation: none;
    opacity: 1;
  }
}

/* === SPA View Transitions (content-only) === */

/* Outgoing page: quick, subtle fade + slight scale to create depth */
@keyframes spaExit {
  0% {
    opacity: 1;
    transform: scale(1) translateY(0);
    filter: blur(0);
  }

  40% {
    opacity: 0.6;
  }

  100% {
    opacity: 0;
    transform: scale(0.995) translateY(-4px);
    filter: blur(1px);
  }
}

/* Incoming page: crisp entrance with subtle upward settle */
@keyframes spaEnter {
  0% {
    opacity: 0;
    transform: translateY(6px);
  }

  60% {
    opacity: 1;
  }

  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Root transition: disable to prevent full-page flash */
html.swup-native::view-transition-old(root) {
  animation: none;
}

html.swup-native::view-transition-new(root) {
  animation: none;
}

/* Content container transitions */
html.swup-native::view-transition-old(route-content),
html.swup-native::view-transition-old(route-shell) {
  animation: spaExit 140ms cubic-bezier(0.4, 0, 1, 1) both;
}

html.swup-native::view-transition-new(route-content),
html.swup-native::view-transition-new(route-shell) {
  animation: spaEnter 220ms cubic-bezier(0, 0, 0.2, 1) 40ms both;
}

/* Stacking during transition — old page on top, fading out cleanly */
html.swup-native::view-transition-old(route-content) {
  z-index: 2;
}

html.swup-native::view-transition-new(route-content) {
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  html.swup-native::view-transition-old(route-content),
  html.swup-native::view-transition-old(route-shell),
  html.swup-native::view-transition-new(route-content),
  html.swup-native::view-transition-new(route-shell) {
    animation: none;
  }
}

/* === Slide Animations === */

/* slideUp and slideInUp are identical - use slideInUp */
@keyframes slideInUp {
  from {
    opacity: 0;
    transform: translateY(12px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* slideDown and slideInDown are identical - use slideInDown */
@keyframes slideInDown {
  from {
    opacity: 0;
    transform: translateY(-12px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

/* === Pulse Animations === */
@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.75;
  }
}

@keyframes loadingPulse {
  0%,
  100% {
    opacity: 0.8;
  }

  50% {
    opacity: 1;
  }
}

@keyframes icon-pop {
  0% {
    transform: scale(0.8);
    opacity: 0.4;
  }

  60% {
    transform: scale(1.06);
    opacity: 1;
  }

  100% {
    transform: scale(1);
  }
}

/* === Spin Animation (single definition) === */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* === Shake Animation === */
@keyframes shake {
  0%,
  100% {
    transform: translateX(0);
  }

  25% {
    transform: translateX(-3px);
  }

  75% {
    transform: translateX(3px);
  }
}

@keyframes value-flash {
  0% {
    background-color: var(--manual-paper-shade);
  }

  100% {
    background-color: transparent;
  }
}

.value-flash {
  animation: value-flash 600ms ease-out;
}

@keyframes ripple {
  0% {
    transform: scale(0);
    opacity: 0.3;
  }

  70% {
    opacity: 0.1;
  }

  100% {
    transform: scale(2.5);
    opacity: 0;
  }
}

/* Reduced motion support defined in core/utilities.css */

/* layout/navigation-experience.css */
.detail-drawer {
  position: fixed;
  inset: var(--header-height) 0 0 auto;
  margin: 0;
  width: min(1050px, 92vw);
  max-width: none;
  height: calc(100dvh - var(--header-height));
  max-height: none;
  padding: 0;
  border: 0;
  border-left: 1.5px solid var(--manual-ink);
  background: var(--manual-paper);
  color: var(--text-primary);
  overscroll-behavior: contain;
  view-transition-name: detail-drawer;
  box-shadow: -4px 0 0 var(--manual-rule-faint);
}

.detail-drawer::backdrop {
  background: rgb(var(--manual-solid-rgb) / 55%);
}

.detail-drawer-toolbar {
  position: sticky;
  top: 0;
  z-index: 10;
  padding: 12px 16px;
  background: var(--manual-paper);
  border-bottom: 1px solid var(--manual-rule);
}

.trip-detail {
  padding: clamp(20px, 4vw, 44px);
}

.trip-detail-journey {
  font-size: var(--font-size-lg);
  font-style: italic;
}

.trip-detail-metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  margin: 28px 0;
  border-top: 2px solid var(--manual-ink);
  border-bottom: 1px solid var(--manual-ink);
}

/* A ledger row: ruled cells, labels over headline figures. */
.trip-detail-metrics > div {
  padding: var(--space-4);
}

.trip-detail-metrics > div:first-child {
  padding-left: 0;
}

.trip-detail-metrics > div + div {
  border-left: 1px solid var(--manual-rule);
}

.trip-detail-metrics dt {
  font-size: var(--font-size-xs);
  color: var(--manual-ink);
  font-weight: var(--font-weight-bold);
  font-family: var(--font-family-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.trip-detail-metrics dd {
  font-size: var(--font-size-2xl);
  margin: 6px 0 0;
  font-family: var(--font-family-display);
  font-weight: 800;
  font-variant-numeric: tabular-nums lining-nums;
}

.trip-detail-map {
  min-height: 340px;
  height: 42dvh;
  border-radius: 0;
  border: 1px solid var(--manual-ink);
}

.trip-detail-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 24px;
}

body[data-background-route="/map"] .persistent-shell {
  display: flex;
}

body[data-background-route="/map"] .route-content {
  display: none;
}

.exploration-map-canvas {
  width: 100%;
  height: 100%;
}

@keyframes detailEnter {
  from {
    transform: translateX(45px);
    opacity: 0;
  }
}

@keyframes detailExit {
  to {
    transform: translateX(45px);
    opacity: 0;
  }
}

@keyframes routeForward {
  from {
    transform: translateX(18px);
    opacity: 0;
  }
}

@keyframes routeBack {
  from {
    transform: translateX(-18px);
    opacity: 0;
  }
}

@keyframes driveEnter {
  from {
    opacity: 0;
    transform: scale(1.015);
  }
}

html[data-navigation-motion="detail-open"]::view-transition-new(detail-drawer) {
  animation: detailEnter 240ms ease-out both;
}

html[data-navigation-motion="detail-close"]::view-transition-old(detail-drawer) {
  animation: detailExit 180ms ease-in both;
}

html[data-navigation-motion^="detail"]::view-transition-old(route-content),
html[data-navigation-motion^="detail"]::view-transition-new(route-content),
html[data-navigation-motion^="detail"]::view-transition-old(route-shell),
html[data-navigation-motion^="detail"]::view-transition-new(route-shell) {
  animation: none;
}

html[data-navigation-motion="forward"]::view-transition-new(route-content) {
  animation: routeForward 180ms ease-out both;
}

html[data-navigation-motion="back"]::view-transition-new(route-content) {
  animation: routeBack 180ms ease-out both;
}

html[data-navigation-motion="drive"]::view-transition-new(route-content) {
  animation: driveEnter 220ms ease-out both;
}

html[data-navigation-motion="explore"]::view-transition-new(route-content) {
  animation: fadeIn 120ms ease-out both;
}

html::view-transition-group(selected-record),
html::view-transition-group(page-heading) {
  animation-duration: 220ms;
  animation-timing-function: ease-out;
}

@media (width <= 640px) {
  .detail-drawer {
    width: 100%;
    border-left: 0;
  }

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

  .trip-detail-map {
    min-height: 260px;
  }
}

@media (prefers-reduced-motion: reduce) {
  html::view-transition-group(*),
  html::view-transition-old(*),
  html::view-transition-new(*) {
    animation: none !important;
  }
}

/* components/loading.css */
/* ============================
   Loading States & Overlays
   ============================ */

/* === Global Loading Overlay === */
.loading-overlay {
  position: fixed;
  inset: 0;
  background-color: rgb(var(--manual-solid-rgb) / 35%);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: var(--z-loading-overlay, 9999);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 180ms cubic-bezier(0, 0, 0.2, 1),
    visibility 180ms cubic-bezier(0, 0, 0.2, 1);
  pointer-events: auto;
}

/* === Swup Progress Bar === */
.swup-progress-bar {
  position: fixed;
  top: env(safe-area-inset-top, 0);
  left: 0;
  right: 0;
  height: 2px;
  background: var(--manual-rust);
  pointer-events: none;
  z-index: var(--z-loading-overlay, 9999);
}

.loading-overlay.non-blocking {
  background-color: transparent;
  pointer-events: none;
  justify-content: center;
  align-items: flex-end;
  padding: 16px;
  padding-bottom: 32px;
}

/* Map route: a compact cartographer's field note anchored to the map plate. */
body[data-route="/map"] .loading-overlay.non-blocking {
  display: block;
  padding: 0;
}

.loading-overlay.compact .loading-indicator {
  padding: 12px 14px;
  gap: 10px;
  box-shadow: var(--shadow-xs);
}

.loading-overlay.visible {
  opacity: 1;
  visibility: visible;
}

/* Light mode adjustments */
html.light-mode body .loading-overlay,
[data-bs-theme="light"] .loading-overlay {
  background-color: rgb(var(--surface-rgb) / 60%);
}

/* === Loading Indicator === */
.loading-indicator {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  background: var(--manual-paper);
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--manual-rule-faint);
  border: 1px solid var(--manual-ink);
  animation: fadeInScale 180ms cubic-bezier(0, 0, 0.2, 1) both;
  font-family: var(--font-family-text);
  font-style: italic;
}

body[data-route="/map"] .loading-overlay.non-blocking .loading-indicator {
  position: absolute;
  left: calc(clamp(300px, 24vw, 360px) + var(--space-3));
  bottom: calc(var(--space-3) + 30px);
  max-width: min(32rem, calc(100vw - clamp(300px, 24vw, 360px) - 6rem));
  min-height: 38px;
  gap: var(--space-2);
  padding: 7px 11px 7px 9px;
  overflow: hidden;
  contain: layout paint;
  background: var(--manual-paper);
  border: 1px solid var(--manual-rule-faint);
  border-left: 3px solid var(--manual-rust);
  border-radius: var(--radius-xs);
  box-shadow: var(--shadow-xs);
  animation: map-status-enter 180ms cubic-bezier(0, 0, 0.2, 1) both;
}

body[data-route="/map"]:has(.atlas-rail.is-collapsed)
  .loading-overlay.non-blocking
  .loading-indicator {
  left: var(--space-3);
  max-width: min(32rem, calc(100vw - 6rem));
}

body[data-route="/map"]
  .loading-overlay.non-blocking
  .loading-indicator
  .route-tracer__svg {
  width: 38px;
}

body[data-route="/map"]
  .loading-overlay.non-blocking
  .loading-indicator
  :is(.route-tracer__line, .route-tracer__dot) {
  filter: none;
}

body[data-route="/map"] .loading-overlay.non-blocking .loading-text {
  overflow: hidden;

  /* The counter ticks in place, so the digits must not reflow. */
  font-variant-numeric: tabular-nums;
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-medium);
  letter-spacing: var(--tracking-normal);
  line-height: 1.25;
  text-overflow: ellipsis;
}

@keyframes map-status-enter {
  from {
    opacity: 0;
    transform: translateY(5px);
  }

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

html.light-mode body .loading-indicator,
[data-bs-theme="light"] .loading-indicator {
  background: var(--surface-1);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-color);
}

/* === Spinner === */
.loading-spinner {
  width: 24px;
  height: 24px;
  border: 3px solid var(--manual-rule);
  border-top-color: var(--action);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

html.light-mode body .loading-spinner,
[data-bs-theme="light"] .loading-spinner {
  border-color: var(--manual-rule);
  border-top-color: var(--action);
}

/* === Loading Text === */
.loading-text {
  font-size: var(--font-size-sm);
  font-weight: 500;
  color: var(--text-primary);
  white-space: nowrap;
}

html.light-mode body .loading-text,
[data-bs-theme="light"] .loading-text {
  color: var(--text-primary);
}

/* Spin animation defined in animations.css as 'spin' */

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

.btn.btn-loading::after {
  content: "";
  position: absolute;
  width: 1em;
  height: 1em;
  top: 50%;
  left: 50%;
  margin: -0.5em 0 0 -0.5em;
  border: 2px solid var(--btn-loading-color, var(--text-primary));
  border-radius: 50%;
  border-top-color: transparent;
  animation: spin 0.6s linear infinite;
  opacity: 0.8;
}

/* Filled buttons need white spinner */
.btn-primary.btn-loading::after {
  border-color: var(--manual-rule);
  border-top-color: var(--text-primary);
}

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

  100% {
    background-position: -200% 0;
  }
}

/* === Reduced Motion Support === */
@media (prefers-reduced-motion: reduce) {
  .loading-spinner,
  .btn.btn-loading::after,
  .swup-progress-bar {
    animation: none;
  }

  .loading-spinner {
    border-color: var(--action);
    opacity: 0.7;
  }

  body[data-route="/map"] .loading-overlay.non-blocking .loading-indicator {
    animation: none;
  }
}

@media (width <= 768px) {
  body[data-route="/map"] .loading-overlay.non-blocking .loading-indicator,
  body[data-route="/map"]:has(.atlas-rail.is-collapsed)
    .loading-overlay.non-blocking
    .loading-indicator {
    left: var(--space-2);
    bottom: calc(
      var(--map-sheet-visible-height, 96px) +
      env(safe-area-inset-bottom, 0px) +
      var(--space-3)
    );
    max-width: calc(100vw - 5.5rem);
    min-height: 40px;
  }
}

/* === Mobile Adjustments === */
@media (width <= 576px) {
  .loading-indicator {
    padding: 12px 20px;
    gap: 10px;
  }

  .loading-spinner {
    width: 20px;
    height: 20px;
    border-width: 2px;
  }

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

/* Brief, non-blocking status line (loadingManager.pulse). */
.loading-toast {
  position: fixed;
  bottom: calc(var(--space-6) + env(safe-area-inset-bottom, 0px));
  left: 50%;
  z-index: var(--z-overlay);
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--manual-ink);
  background: var(--manual-paper);
  box-shadow: var(--shadow-sm);
  font-family: var(--font-family-label);
  font-size: var(--font-size-xs);
  font-weight: var(--font-weight-semibold);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--manual-ink);
  opacity: 0;
  transform: translate(-50%, 10px);
  transition:
    opacity 180ms cubic-bezier(0, 0, 0.2, 1),
    transform 180ms cubic-bezier(0, 0, 0.2, 1);
  pointer-events: none;
}

.loading-toast.is-visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* components/route-tracer.css */
/* Global route-drawing loader glyph. */

.route-tracer {
  display: flex;
  align-items: center;
  justify-content: center;
}

.route-tracer__svg {
  display: block;
  width: 60px;
  height: auto;
  aspect-ratio: 72 / 32;
  overflow: visible;
}

.route-tracer__road {
  fill: none;
  stroke: rgb(var(--text-rgb) / 13%);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.route-tracer__line {
  fill: none;
  stroke: var(--action);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  filter: drop-shadow(0 0 4px rgb(var(--action-rgb) / 55%));
  animation: route-tracer-draw 1.9s ease-in-out infinite;
}

.route-tracer__origin {
  fill: var(--action);
  opacity: 0.85;
}

.route-tracer__dest {
  fill: none;
  stroke: var(--action);
  stroke-width: 2;
  transform-box: fill-box;
  transform-origin: center;
  animation: route-tracer-dest 1.9s ease-in-out infinite;
}

.route-tracer__dot {
  fill: var(--action);
  filter: drop-shadow(0 0 4px rgb(var(--action-rgb) / 70%));
}

@keyframes route-tracer-draw {
  0% {
    stroke-dashoffset: 100;
    opacity: 0;
  }

  6% {
    opacity: 1;
  }

  74% {
    stroke-dashoffset: 0;
    opacity: 1;
  }

  90% {
    stroke-dashoffset: 0;
    opacity: 1;
  }

  100% {
    stroke-dashoffset: 0;
    opacity: 0;
  }
}

@keyframes route-tracer-dest {
  0%,
  64% {
    transform: scale(0.6);
    opacity: 0.25;
  }

  78% {
    transform: scale(1.3);
    opacity: 1;
  }

  100% {
    transform: scale(0.9);
    opacity: 0.45;
  }
}

.loading-overlay.compact .route-tracer__svg {
  width: 46px;
}

@media (prefers-reduced-motion: reduce) {
  .route-tracer__line {
    animation: none;
    stroke-dashoffset: 0;
    opacity: 0.9;
  }

  .route-tracer__dest {
    animation: none;
    transform: none;
    opacity: 0.8;
  }

  .route-tracer__dot {
    display: none;
  }
}

