/* ============================================================
   Fleet Ops Tracker
   Dark operations console. Tokens, spacing and component anatomy
   follow the approved mockup; extended to cover the pages the
   mockup did not include (forms, reports, trailer tables).
   Inter is self-hosted and icons are inline SVG, so no CDN can
   take the interface down.
   ============================================================ */

@font-face { font-family:"Inter"; font-style:normal; font-weight:400; font-display:swap;
  src:url("fonts/inter-400.woff2") format("woff2"); }
@font-face { font-family:"Inter"; font-style:normal; font-weight:500; font-display:swap;
  src:url("fonts/inter-500.woff2") format("woff2"); }
@font-face { font-family:"Inter"; font-style:normal; font-weight:600; font-display:swap;
  src:url("fonts/inter-600.woff2") format("woff2"); }
@font-face { font-family:"Inter"; font-style:normal; font-weight:700; font-display:swap;
  src:url("fonts/inter-700.woff2") format("woff2"); }

:root {
  color-scheme: dark;
  --bg-primary: #0f1117;
  --bg-secondary: #181b21;
  --bg-tertiary: #1e2129;
  --bg-elevated: #252a33;
  --border: #2a2e3a;
  --border-light: #353a47;
  --text-primary: #e8eaf0;
  --text-secondary: #9ca3af;
  --text-muted: #6b7280;
  --accent: #3b82f6;
  --accent-hover: #2563eb;
  --danger: #ef4444;   --danger-bg: rgba(239, 68, 68, .12);
  --warning: #f59e0b;  --warning-bg: rgba(245, 158, 11, .12);
  --success: #22c55e;  --success-bg: rgba(34, 197, 94, .12);
  --info: #06b6d4;     --info-bg: rgba(6, 182, 212, .12);
  --purple: #a855f7;   --purple-bg: rgba(168, 85, 247, .12);
}

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

body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  background: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.5;
  min-height: 100vh;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

::selection { background: rgba(59, 130, 246, .35); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
svg { display: block; }
/* A sprite icon has no size of its own: <use> pulls in a symbol that carries a
   viewBox but no width, so an unstyled one stretches to fill whatever box it
   is in - which is how a 16px warning icon became half the page. Every context
   below sets its own size; this is the floor, so a context I forget degrades
   to "slightly wrong" rather than "enormous". Scoped to :has(> use) so it
   never touches Leaflet's own SVG layers on the map pages. */
svg:has(> use) { width: 16px; height: 16px; flex: none; }

/* ---------- Navbar ---------- */
.navbar {
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border);
  padding: 0 24px;
  position: sticky; top: 0; z-index: 100;
}
.navbar-inner {
  max-width: 1400px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between;
  height: 56px; gap: 16px;
}
.nav-brand {
  display: flex; align-items: center; gap: 10px;
  font-weight: 700; font-size: 16px; color: var(--text-primary); text-decoration: none;
  white-space: nowrap;
}
.nav-brand svg { width: 20px; height: 20px; color: var(--accent); }

.nav-links {
  display: flex; align-items: center; gap: 4px; list-style: none;
  overflow-x: auto; min-width: 0;
  /* The row scrolls when the window is narrow. The scrollbar it drew for
     that sat across the middle of the navbar, so it is hidden - the links
     still scroll, they just do it quietly. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.nav-links::-webkit-scrollbar { display: none; }
.nav-links a {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 14px; border-radius: 8px;
  color: var(--text-secondary); text-decoration: none;
  font-size: 13px; font-weight: 500; white-space: nowrap;
  transition: all .15s;
}
.nav-links a svg { width: 14px; height: 14px; }
.nav-links a:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.nav-links a.active { color: var(--accent); background: rgba(59, 130, 246, .1); }

.nav-user { display: flex; align-items: center; gap: 16px; flex: 0 0 auto; }
.nav-user a {
  display: flex; align-items: center; gap: 6px;
  color: var(--text-secondary); text-decoration: none;
  font-size: 13px; font-weight: 500; transition: color .15s; white-space: nowrap;
}
.nav-user a svg { width: 13px; height: 13px; }
.nav-user a:hover { color: var(--text-primary); }
.user-pill {
  display: flex; align-items: center; gap: 8px;
  font-family: inherit; cursor: pointer;
  padding: 6px 12px;
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 20px; font-size: 13px; font-weight: 500;
  color: var(--text-secondary); text-decoration: none; transition: all .15s;
}
.user-pill { cursor: pointer; }
.user-pill:hover { border-color: var(--border-light); color: var(--text-primary); }
.user-pill svg { width: 13px; height: 13px; }

/* ---------- Layout ---------- */
.container { max-width: 1400px; margin: 0 auto; padding: 24px; }

.page-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  margin-bottom: 24px; gap: 12px; flex-wrap: wrap;
}
.page-title {
  font-size: 26px; font-weight: 700; color: var(--text-primary);
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
.page-title svg { width: 26px; height: 26px; flex: none; }
.page-title .date-badge {
  font-size: 14px; font-weight: 500; color: var(--text-secondary);
  background: var(--bg-secondary); border: 1px solid var(--border);
  padding: 4px 12px; border-radius: 20px;
}
.header-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- Buttons ---------- */
.btn, button {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 16px; border-radius: 8px;
  font-size: 13px; font-weight: 600;
  font-family: inherit;
  border: 1px solid var(--border);
  background: var(--bg-secondary); color: var(--text-primary);
  cursor: pointer; transition: all .15s; text-decoration: none;
}
.btn:hover, button:hover { background: var(--bg-tertiary); border-color: var(--border-light); }
.btn svg, button svg { width: 13px; height: 13px; }
.btn-primary, button.primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.btn-primary:hover, button.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn.secondary, button.secondary { background: var(--bg-secondary); color: var(--text-primary); }

/* ---------- Priority alert ---------- */
.priority-alert {
  background: linear-gradient(135deg, rgba(239, 68, 68, .15), rgba(245, 158, 11, .1));
  border: 1px solid rgba(239, 68, 68, .3);
  border-radius: 12px; padding: 16px 20px;
  display: flex; align-items: center; gap: 16px;
  margin-bottom: 24px; flex-wrap: wrap;
}
.priority-alert .alert-icon {
  width: 40px; height: 40px; border-radius: 10px;
  background: var(--danger-bg);
  display: flex; align-items: center; justify-content: center;
  color: var(--danger); flex-shrink: 0;
}
.priority-alert .alert-icon svg { width: 21px; height: 21px; }
.priority-alert .alert-content { flex: 1; min-width: 12rem; }
.priority-alert .alert-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; color: var(--danger); margin-bottom: 2px;
}
.priority-alert .alert-title { font-size: 15px; font-weight: 600; color: var(--text-primary); }
.priority-alert .alert-title a { color: var(--accent); text-decoration: none; }
.priority-alert .alert-title a:hover { text-decoration: underline; }
.priority-alert .alert-meta { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }
.priority-alert .alert-action { flex-shrink: 0; }

/* ---------- Stats ---------- */
/* Six cards on All Trailers, five elsewhere, four on Reports - auto-fit so
   the row lays out for whatever a page has rather than a fixed count. */
.stats-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 24px; }
.stat-card {
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 10px; padding: 16px; transition: all .15s;
  text-decoration: none; color: inherit; display: block;
}
.stat-card:hover { border-color: var(--border-light); transform: translateY(-1px); }
.stat-card .stat-label {
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
  color: var(--text-muted); margin-bottom: 8px;
  display: flex; align-items: center; gap: 6px;
}
.stat-card .stat-label svg { width: 12px; height: 12px; }
.stat-card .stat-value { font-size: 22px; font-weight: 700; color: var(--text-primary); }
.stat-card .stat-value .of { font-size: 14px; color: var(--text-muted); }
.stat-card .stat-sub { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
.stat-card .stat-link { font-size: 12px; color: var(--accent); font-weight: 500; text-decoration: none; }

/* ---------- Section cards ---------- */
.section-card {
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 12px; margin-bottom: 20px; overflow: hidden;
}
.section-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px; border-bottom: 1px solid var(--border); gap: 12px;
}
.section-title {
  display: flex; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 700; color: var(--text-primary); flex-wrap: wrap;
}
.section-title .ico {
  width: 28px; height: 28px; border-radius: 8px; flex: 0 0 28px;
  display: flex; align-items: center; justify-content: center;
}
.section-title .ico svg { width: 16px; height: 16px; }
.icon-red { background: var(--danger-bg); color: var(--danger); }
.icon-amber { background: var(--warning-bg); color: var(--warning); }
.icon-blue { background: var(--info-bg); color: var(--info); }
.icon-green { background: var(--success-bg); color: var(--success); }
.icon-purple { background: var(--purple-bg); color: var(--purple); }
.section-count {
  background: var(--bg-tertiary); color: var(--text-secondary);
  font-size: 12px; font-weight: 700; padding: 2px 10px; border-radius: 10px;
  margin-left: 8px;
}
.section-note {
  font-size: 12px; font-weight: 500; color: var(--text-muted);
}
.section-action {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--accent); text-decoration: none; font-weight: 600;
  white-space: nowrap;
}
.section-action:hover { text-decoration: underline; }
.section-action svg { width: 10px; height: 10px; }
.section-intro {
  padding: 16px 20px; color: var(--text-secondary); font-size: 13px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: flex-start; gap: 8px;
}
.section-intro svg { width: 14px; height: 14px; color: var(--accent); flex: 0 0 14px; margin-top: 3px; }
.section-body { padding: 20px; }

/* A fact and its value, stacked down a card. Label on the left in the quiet
   colour, value on the right where the eye lands when scanning for one. */
.kv {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; padding: 7px 0; border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.kv:last-child { border-bottom: 0; }
.kv > span:first-child {
  color: var(--text-muted); font-size: 12px; font-weight: 500;
  white-space: nowrap;
}
.kv > :last-child { color: var(--text-primary); text-align: right; }

/* One line of controls that reads as a single action. */
.add-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ---------- Tables ---------- */
.table-scroll { overflow-x: auto; }

/* What a visit is to cost its driver. A row of labelled fields that wraps,
   rather than inputs stacked full-width down the card - the first attempt put
   this in the header's button row and it burst out of the header. */
.charge-card { margin-bottom: 14px; }
.charge-card.is-owed { border-color: var(--warning); }
.charge-body { padding: 14px 20px 16px; }
.charge-summary { margin: 0 0 12px; font-size: 13px; color: var(--text-secondary); }
.charge-form {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end;
}
.charge-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.charge-field label {
  font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .4px; color: var(--text-muted);
}
.charge-field input {
  padding: 8px 12px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--bg-primary); color: var(--text-primary);
  font-size: 13px; font-family: inherit; min-width: 0;
}
.charge-field input:focus { outline: none; border-color: var(--accent); }
.charge-money { flex: 0 0 150px; }
/* The dollar sign sits inside the box, so the number lines up with the label
   rather than being pushed along by a floating character beside it. */
.charge-input-money { position: relative; display: flex; align-items: center; }
.charge-input-money span {
  position: absolute; left: 12px; color: var(--text-muted); font-size: 13px;
  pointer-events: none;
}
.charge-input-money input { padding-left: 26px; width: 100%; }
.charge-field.charge-grow { flex: 1 1 220px; }
.charge-actions { display: flex; gap: 8px; align-items: flex-end; }
.charge-hint { margin: 10px 0 0; }
@media (max-width: 700px) {
  /* Side by side stops helping once each field is a line of its own. */
  .charge-form { flex-direction: column; align-items: stretch; }
  .charge-money, .charge-field.charge-grow { flex: 1 1 auto; }
}
/* A list long enough to bury the rest of the page scrolls inside itself
   instead. 284 weeks and 86 drivers both did that. The header stays put while
   the rows move under it - a column of bare numbers with the heading scrolled
   off the top is not a table you can read.

   z-index 20 puts the header above the sticky actions column, and leaves it
   under an open row menu (60) and the site header (100). */
.table-scroll.table-capped { max-height: 55vh; overflow-y: auto; }
.table-scroll.table-capped thead th { position: sticky; top: 0; z-index: 20; }
.table-scroll.table-capped thead .col-actions { z-index: 25; }
.data-table, table { width: 100%; border-collapse: collapse; font-size: 13px; }
.data-table th, table th {
  text-align: left; padding: 12px 20px;
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .5px;
  color: var(--text-muted); background: var(--bg-tertiary);
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
.data-table td, table td {
  padding: 14px 20px; border-bottom: 1px solid var(--border);
  color: var(--text-primary); vertical-align: middle;
}
.data-table tr:last-child td, table tr:last-child td { border-bottom: none; }
.data-table tbody tr, table tbody tr { transition: background .1s; }
.data-table tbody tr:hover, table tbody tr:hover { background: rgba(255,255,255,.02); }

.col-num { width: 50px; color: var(--text-muted); font-weight: 600; font-size: 12px; }
.col-unit { display: flex; align-items: center; gap: 8px; }
.unit-icon {
  width: 28px; height: 28px; border-radius: 6px; flex: 0 0 28px;
  background: var(--bg-elevated);
  display: flex; align-items: center; justify-content: center;
  color: var(--text-secondary);
}
.unit-icon svg { width: 16px; height: 16px; }
.unit-num { font-weight: 600; color: var(--text-primary); }
.col-issue { font-weight: 500; }
.col-due { color: var(--text-secondary); white-space: nowrap; }
.col-due svg { width: 10px; height: 10px; display: inline-block; vertical-align: -1px; margin-right: 4px; }
.col-due.overdue { color: var(--danger); font-weight: 600; }
.col-shop { color: var(--text-secondary); }
.col-more { color: var(--text-muted); text-decoration: none; }
.col-more svg { width: 13px; height: 13px; }

/* ---------- Badges ---------- */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 6px;
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.badge-dot { width: 6px; height: 6px; border-radius: 50%; flex: 0 0 6px; }
.badge-warning { background: var(--warning-bg); color: var(--warning); }
.badge-warning .badge-dot { background: var(--warning); }
.badge-purple { background: var(--purple-bg); color: var(--purple); }
.badge-purple .badge-dot { background: var(--purple); }
.badge-info { background: var(--info-bg); color: var(--info); }
.badge-info .badge-dot { background: var(--info); }
.badge-danger { background: var(--danger-bg); color: var(--danger); }
.badge-danger .badge-dot { background: var(--danger); }
.badge-success { background: var(--success-bg); color: var(--success); }
.badge-success .badge-dot { background: var(--success); }
.badge-accent { background: rgba(59,130,246,.12); color: var(--accent); }
.badge-accent .badge-dot { background: var(--accent); }
.badge-muted { background: var(--bg-tertiary); color: var(--text-secondary); }
.badge-muted .badge-dot { background: var(--text-muted); }

/* ---------- Two column ---------- */
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px; }
/* Faults are a short list; the task table carries costs and controls, so it
   gets the larger share. fr units rather than percentages, so the gap does
   not push the columns past 100%. */
.two-col--aside { grid-template-columns: 35fr 65fr; }
.two-col > .section-card { margin-bottom: 0; }
/* The narrow column holds more than one card, stacked with the same gap the
   grid uses between columns. */
.col-stack { display: flex; flex-direction: column; gap: 20px; min-width: 0; height: 100%; }
.col-stack > .section-card { margin-bottom: 0; }
/* The task table grows as tasks are added. The last card in this column
   stretches to match it, so the column ends level instead of leaving a gap
   under it. */
.col-stack > .section-card:last-child { flex: 1 1 auto; }

/* ---------- Activity feed ---------- */
.activity-list { padding: 8px 0; }
.activity-item { display: flex; gap: 14px; padding: 12px 20px; position: relative; }
.activity-item:not(:last-child)::before {
  content: ""; position: absolute; left: 33px; top: 46px; bottom: -6px;
  width: 2px; background: var(--border);
}
.activity-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex: 0 0 28px; flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(135deg, var(--accent), #8b5cf6);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: #fff; z-index: 1;
}
.activity-content { flex: 1; min-width: 0; }
.activity-line { font-size: 13px; color: var(--text-primary); line-height: 1.5; }
.activity-line .who { color: var(--accent); font-weight: 600; }
.activity-line .action-label { color: var(--text-secondary); }
.activity-line .what { font-weight: 600; }
.activity-meta { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.activity-issue { flex-shrink: 0; }
.activity-issue a, .activity-issue span {
  font-size: 12px; color: var(--accent); text-decoration: none; font-weight: 600;
  background: rgba(59,130,246,.1); padding: 4px 10px; border-radius: 6px; white-space: nowrap;
}
.activity-issue a:hover { background: rgba(59,130,246,.2); }

.footer-note {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  text-align: center; font-size: 12px; color: var(--text-muted); padding: 16px;
}
.footer-note svg { width: 12px; height: 12px; }

.empty-state { padding: 40px 20px; text-align: center; color: var(--text-muted); }
.empty-state svg { width: 32px; height: 32px; margin: 0 auto 12px; opacity: .4; }
.empty-state p { font-size: 14px; }

/* ---------- Forms ---------- */
.field-row { margin-bottom: 16px; max-width: 30rem; }
.field-row label {
  display: block; font-size: 12px; font-weight: 600; color: var(--text-secondary);
  margin-bottom: 6px;
}
.field-row input, .field-row textarea, .field-row select, select, input[type="date"], input[type="text"],
input[type="password"], input[type="number"] {
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: 8px;
  font: inherit; font-size: 13px;
  background: var(--bg-tertiary); color: var(--text-primary);
}
select { width: auto; min-width: 10rem; cursor: pointer; }
.field-row input:focus, .field-row select:focus, select:focus, .field-row textarea:focus, input:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(59,130,246,.18);
}
.filters {
  display: flex; gap: 12px; align-items: end; flex-wrap: wrap;
  margin-bottom: 20px;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 12px; padding: 16px 20px;
}
.filters .field-row { margin-bottom: 0; max-width: 14rem; }
.actions { margin-top: 20px; display: flex; gap: 8px; flex-wrap: wrap; }

.flashes {
  list-style: none; margin-bottom: 20px; padding: 12px 16px;
  background: var(--info-bg); border: 1px solid rgba(6,182,212,.3);
  border-radius: 10px; font-size: 13px; color: var(--text-primary);
  /* A refused action redirects to #flash so the sentence refusing it is
     what you land on. The navbar is sticky and 56px tall, so without this
     the browser parks the message exactly underneath it - which is the
     same as not showing it, and not showing it is the bug this exists to
     fix. */
  scroll-margin-top: 76px;
}

pre.report {
  white-space: pre-wrap;
  font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12.5px; line-height: 1.6;
  background: var(--bg-secondary); border: 1px solid var(--border);
  padding: 20px; border-radius: 12px; color: var(--text-primary);
  overflow-x: auto;
}
.report-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 20px; }
.hint, .muted { font-size: 12px; color: var(--text-muted); }
a { color: var(--accent); }

/* ---------- Logged-out door ---------- */
.door { max-width: 24rem; margin: 12vh auto; text-align: center; }
.door .mark {
  width: 52px; height: 52px; margin: 0 auto 16px; border-radius: 14px;
  background: rgba(59,130,246,.12); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
}
.door .mark svg { width: 24px; height: 24px; }
.door h1 { font-size: 24px; font-weight: 700; margin-bottom: 6px; }
.door-sub { color: var(--text-secondary); font-size: 14px; margin-bottom: 28px; }
.door-actions { margin-bottom: 28px; }
.door-contact { font-size: 12px; color: var(--text-muted); }

/* ---------- Task typeahead ---------- */
.typeahead { position: relative; }
.suggest {
  position: absolute; z-index: 30; left: 0; right: 0; top: 100%;
  margin: 4px 0 0; padding: 4px; list-style: none;
  background: var(--bg-elevated);
  border: 1px solid var(--border-light);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
  max-height: 15rem; overflow-y: auto;
}
.suggest-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 10px; border-radius: 6px;
  font-size: 13px; color: var(--text-primary); cursor: pointer;
}
.suggest-item:hover, .suggest-item.is-active { background: rgba(59,130,246,.16); }
.suggest-sys {
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
  color: var(--text-muted); background: var(--bg-tertiary);
  padding: 2px 7px; border-radius: 10px; flex: 0 0 auto;
}

/* The add-task row spans the card; the field-row default max-width is for
   narrow forms, not a full-width bar. */
.task-add { border-bottom: 1px solid var(--border); }
.task-add .field-row { max-width: none; margin-bottom: 0; }
.task-add .hint { margin-top: 8px; }

/* A single-glyph action inside a table row: the archive box here, and
   whatever else earns a place in a row's action cell later. Big enough to
   hit on a telephone, quiet enough not to compete with the data. */
.icon-btn {
  width: 30px; height: 30px; border-radius: 7px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid transparent;
  color: var(--text-muted); cursor: pointer; transition: all .15s;
}
.icon-btn svg { width: 15px; height: 15px; }
.icon-btn:hover {
  background: var(--bg-tertiary); border-color: var(--border);
  color: var(--text-primary);
}
.icon-btn.is-danger:hover { background: var(--danger-bg); color: var(--danger); }

/* Active / Archived. Two views of one list, so they sit together as one
   control rather than as two loose links. */
.seg-toggle {
  display: inline-flex; background: var(--bg-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 2px; gap: 2px;
}
.seg-toggle a {
  padding: 5px 12px; border-radius: 6px; font-size: 12px; font-weight: 600;
  color: var(--text-muted); text-decoration: none; transition: all .15s;
  white-space: nowrap;
}
.seg-toggle a:hover:not(.on) { color: var(--text-secondary); }
.seg-toggle a.on { background: var(--bg-elevated); color: var(--text-primary); }
.seg-toggle .n { opacity: .65; margin-left: 5px; font-variant-numeric: tabular-nums; }

/* An archived row is still readable, but it is plainly not in service. */
tr.is-archived td { opacity: .62; }
tr.is-archived:hover td { opacity: 1; }

/* A totals list is two columns of short text. Left to fill the card it puts
   half a metre between the label and the figure. */
.totals { padding: 16px 20px; }
.totals table { max-width: 26rem; border: none; box-shadow: none; background: transparent; }
.totals td { padding: 7px 0; border-bottom: 1px solid var(--border); }
.totals tr:last-child td { border-bottom: none; padding-top: 12px; }

/* ---------- Centred form ---------- */
.form-page { max-width: 44rem; margin: 0 auto; }
.form-head { justify-content: center; text-align: center; }
.form-page .field-row { max-width: none; }
.form-actions { justify-content: center; }

/* Unit numbers are the thing being read here, so they are set larger than
   ordinary form text. */
.unit-input {
  font-size: 20px !important;
  font-weight: 600;
  letter-spacing: .01em;
  padding: 11px 14px !important;
}
.form-page .suggest-item { font-size: 16px; padding: 10px 12px; }

.attach-bar { border-top: 1px solid var(--border); }
.attach-bar .field-row { max-width: 32rem; margin-bottom: 0; }
.attach-bar select { width: 100%; }

/* ---------- Media gallery ---------- */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 12px; padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.shot { margin: 0; }
.shot img, .shot video {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  background: var(--bg-tertiary);
  border: 1px solid var(--border); border-radius: 10px;
  display: block;
}
.shot img:hover { border-color: var(--accent); }
.shot figcaption {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 6px; font-size: 11px;
}

/* ---------- Inline editing ---------- */
.inline-edit {
  width: 100%; min-width: 5.5rem;
  padding: 5px 8px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-primary);
  font: inherit; font-size: 13px;
}
.inline-edit:hover { border-color: var(--border); background: var(--bg-tertiary); }
.inline-edit:focus {
  outline: none; background: var(--bg-tertiary);
  border-color: var(--accent); box-shadow: 0 0 0 3px rgba(59,130,246,.18);
}
.cost-edit { font-weight: 600; }
/* An automatic figure sits in the placeholder, so it reads as a value while
   still showing that nobody typed it. */
.cost-edit::placeholder { color: var(--text-primary); opacity: .75; font-weight: 600; }
.cost-edit:focus::placeholder { opacity: .35; }
.inline-edit.is-saving { opacity: .5; }

/* ---------- Small dialog ---------- */
.modal {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(6, 8, 12, .72);
  padding: 20px;
}
.modal[hidden] { display: none; }
.modal-card {
  width: 100%; max-width: 27rem;
  background: var(--bg-secondary);
  border: 1px solid var(--border-light);
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(0,0,0,.55);
  padding: 22px;
}
.modal-card h2 { font-size: 17px; margin-bottom: 6px; }
.modal-choices {
  display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 4px;
}
.modal-choices .btn { flex: 1 1 7rem; justify-content: center; }
.modal-foot { display: flex; justify-content: flex-end; margin-top: 14px; }

/* ---------- Responsive ---------- */
@media (max-width: 1200px) {
  .stats-row { grid-template-columns: repeat(3, 1fr); }
  .two-col, .two-col--aside { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
  .nav-links { display: none; }
  .stats-row { grid-template-columns: repeat(2, 1fr); }
  .page-header { flex-direction: column; gap: 12px; }
  .data-table, table { font-size: 12px; }
  .data-table th, .data-table td, table th, table td { padding: 10px 12px; }
}
@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* ---------------------------------------------------------------------
   Issues page: filter bar, dense table, row actions, pagination.
   The filter bar is a real form, so a view survives a reload and can be
   linked to. The search box beside it is the only client-side part.
   --------------------------------------------------------------------- */
.filter-bar {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 20px;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.filter-group {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
}
.filter-group label { font-size: 12px; color: var(--text-muted); font-weight: 500; }
.filter-group input {
  background: transparent; border: none; color: var(--text-primary);
  font-size: 13px; width: 118px; outline: none; font-family: inherit;
}
.filter-group svg { width: 12px; height: 12px; color: var(--text-muted); flex: 0 0 12px; }
.filter-divider { width: 1px; height: 24px; background: var(--border); }
.filter-pill {
  padding: 6px 14px; border-radius: 8px; font-size: 13px; font-weight: 600;
  cursor: pointer; transition: all .15s; border: 1px solid transparent;
  background: transparent; color: var(--text-secondary);
  text-decoration: none; display: inline-flex; align-items: center;
  font-family: inherit;
}
.filter-pill:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.filter-pill.active {
  background: rgba(59,130,246,.12); color: var(--accent);
  border-color: rgba(59,130,246,.25);
}
.filter-search {
  display: flex; align-items: center; gap: 6px;
  background: var(--bg-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 12px; margin-left: auto;
}
.filter-search input {
  background: transparent; border: none; color: var(--text-primary);
  font-size: 13px; width: 170px; outline: none; font-family: inherit;
}
.filter-search svg { width: 12px; height: 12px; color: var(--text-muted); flex: 0 0 12px; }

/* Table cells specific to the issue list */
.col-unit { display: flex; align-items: center; gap: 8px; }
.unit-num { font-weight: 600; color: var(--text-primary); }
.unit-meta { font-size: 11px; color: var(--text-muted); }
.col-issue { font-weight: 500; }
.col-issue a { color: inherit; text-decoration: none; }
.col-issue a:hover { color: var(--accent); }
.col-issue-meta { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.col-owner { display: flex; align-items: center; gap: 8px; }
.owner-avatar {
  width: 24px; height: 24px; border-radius: 50%; background: var(--bg-elevated);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700; color: var(--text-secondary); flex: 0 0 24px;
}
.col-due { color: var(--text-secondary); white-space: nowrap; }
.col-due svg { width: 10px; height: 10px; margin-right: 4px; vertical-align: -1px; }
.col-due.overdue { color: var(--danger); font-weight: 600; }
.col-due.today { color: var(--warning); font-weight: 600; }
.due-sub { font-size: 11px; margin-top: 2px; font-weight: 400; }
.due-sub.overdue { color: var(--danger); opacity: .8; }
.due-sub.today { color: var(--warning); opacity: .8; }
.col-shop { color: var(--text-secondary); }

/* Row actions stay hidden until the row is hovered, so a long list reads as
   data rather than as a wall of buttons. Keyboard focus reveals them too. */
.row-actions {
  display: flex; align-items: center; gap: 4px;
  justify-content: flex-end;
  /* Visible at rest, not revealed on hover. Hiding them meant the row had
     no visible way to act on it until the mouse happened to be over it,
     and they appeared to flicker on the way past. */
  opacity: .5;
  transition: opacity .15s;
}
.data-table tbody tr:hover .row-actions,
.row-actions:focus-within { opacity: 1; }

/* The actions stay reachable while the rest of a wide table scrolls under
   them. The background is opaque on purpose: the columns pass behind. */
.table-scroll .col-actions {
  position: sticky;
  right: 0;
  text-align: right;
  background: var(--bg-secondary, #14171f);
  box-shadow: -8px 0 12px -8px rgba(0,0,0,.6);
}
/* While its menu is open, this cell paints above the rows below it. Without
   it the sticky cells further down the table cover the panel, which is what
   made an open menu look cut in half. Kept under the header's own 100. */
.table-scroll .col-actions.menu-open,
.data-table td.menu-open { z-index: 60; }
.table-scroll thead .col-actions { background: var(--bg-tertiary, #1a1e28); }
.data-table tbody tr:hover .col-actions { background: var(--bg-tertiary, #1a1e28); }
.row-action-btn {
  width: 28px; height: 28px; border-radius: 6px; display: flex;
  align-items: center; justify-content: center; background: transparent;
  border: none; color: var(--text-secondary); cursor: pointer;
  transition: all .15s; padding: 0;
}
.row-action-btn svg { width: 12px; height: 12px; }
.row-action-btn:hover { background: var(--bg-elevated); color: var(--text-primary); }
.row-action-btn.done:hover { color: var(--success); }

/* The "..." menu holds the status changes that used to be an inline select
   sitting in every single row. */
.row-menu-wrap { position: relative; }
.row-menu {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 1000;
  min-width: 210px; padding: 6px;
  background: var(--bg-elevated); border: 1px solid var(--border-light);
  border-radius: 10px; box-shadow: 0 12px 32px rgba(0,0,0,.45);
  text-align: left;
}
.row-menu[hidden] { display: none; }
/* A long list still has to fit the window once the script has placed it. */
.row-menu { overflow-y: auto; overscroll-behavior: contain; }
.row-menu .menu-label {
  font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .5px; color: var(--text-muted); padding: 6px 10px 4px;
}
.row-menu button {
  display: block; width: 100%; text-align: left; padding: 7px 10px;
  background: transparent; border: none; border-radius: 6px;
  color: var(--text-secondary); font-size: 12.5px; font-weight: 500;
  font-family: inherit; cursor: pointer;
}
.row-menu button:hover { background: var(--bg-tertiary); color: var(--text-primary); }
/* Links sit in these menus too, and have to match the buttons beside them. */
.row-menu a {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 7px 10px; border-radius: 6px; text-decoration: none;
  color: var(--text-secondary); font-size: 12.5px; font-weight: 500;
}
.row-menu a svg { width: 13px; height: 13px; flex: 0 0 auto; }
.row-menu a:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.user-menu { min-width: 180px; }
/* A line of explanation under a choice that deserves one. */
.row-menu .menu-note {
  padding: 6px 10px 4px; margin-top: 4px; border-top: 1px solid var(--border);
  font-size: 11px; line-height: 1.45; color: var(--text-muted);
  max-width: 240px;
}

/* Pagination */
.pagination {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 20px; border-top: 1px solid var(--border);
}
.pagination-info { font-size: 12px; color: var(--text-muted); }
.pagination-btns { display: flex; align-items: center; gap: 6px; }
.pagination-btn {
  padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--border); background: var(--bg-tertiary);
  color: var(--text-secondary); cursor: pointer; transition: all .15s;
  text-decoration: none; display: inline-flex; align-items: center;
  font-family: inherit;
}
.pagination-btn:hover { background: var(--bg-elevated); color: var(--text-primary); }
.pagination-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; }
.pagination-btn.is-disabled { opacity: .4; pointer-events: none; }

/* List / grid switch */
.view-toggle {
  display: flex; align-items: center; gap: 2px; background: var(--bg-primary);
  border: 1px solid var(--border); border-radius: 8px; padding: 2px;
}
.view-toggle button {
  width: 28px; height: 28px; border-radius: 6px; display: flex;
  align-items: center; justify-content: center; background: transparent;
  border: none; color: var(--text-muted); cursor: pointer;
  transition: all .15s; padding: 0;
}
.view-toggle button svg { width: 12px; height: 12px; }
.view-toggle button.active { background: var(--bg-elevated); color: var(--text-primary); }
.view-toggle button:hover:not(.active) { color: var(--text-secondary); }

/* Grid view: the same rows as cards, for scanning by unit rather than by date */
.issue-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px; padding: 16px 20px;
}
.issue-card {
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 10px; padding: 14px; transition: all .15s;
}
.issue-card:hover { border-color: var(--border-light); transform: translateY(-1px); }
.issue-card-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 10px;
}
.issue-card-task { font-size: 13.5px; font-weight: 600; margin-bottom: 10px; }
.issue-card-meta {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11.5px; color: var(--text-muted);
}
.is-hidden { display: none !important; }

@media (max-width: 900px) {
  .filter-bar { flex-direction: column; align-items: stretch; }
  .filter-search { margin-left: 0; }
  .filter-divider { display: none; }
  .row-actions { opacity: 1; }
}

/* ---------------------------------------------------------------------
   Components for the Reports, PTI, Trailers, All Trailers and Damages
   pages. Collected from the five approved designs and deduplicated: the
   shared pieces (cards, tables, stat rows, badges, filter bars) already
   live above, so only what is genuinely new is here - 14 KB rather than
   the 68 KB the five files carry between them.
   --------------------------------------------------------------------- */
.sub-tabs { display: flex; align-items: center; gap: 4px; margin-bottom: 20px; }
.sub-tab { padding: 6px 14px; border-radius: 8px; font-size: 14px; font-weight: 600; color: var(--text-secondary); text-decoration: none; transition: all 0.15s; }
.sub-tab:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.sub-tab.active { color: var(--accent); background: rgba(59, 130, 246, 0.1); }
.map-layout { display: grid; grid-template-columns: 320px 1fr; gap: 20px; height: calc(100vh - 320px); min-height: 500px; }
.trailer-sidebar { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; display: flex; flex-direction: column; }
.sidebar-header { padding: 14px 16px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; }
.sidebar-header h3 { font-size: 14px; font-weight: 700; color: var(--text-primary); display: flex; align-items: center; gap: 8px; }
.sidebar-header h3 i { color: var(--accent); }
.sidebar-count { font-size: 12px; color: var(--text-muted); font-weight: 600; }
.trailer-list { overflow-y: auto; flex: 1; }
.trailer-list::-webkit-scrollbar { width: 6px; }
.trailer-list::-webkit-scrollbar-track { background: transparent; }
.trailer-list::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
.trailer-item { padding: 14px 16px; border-bottom: 1px solid var(--border); cursor: pointer; transition: all 0.15s; position: relative; }
.trailer-item:last-child { border-bottom: none; }
.trailer-item:hover { background: rgba(255,255,255,0.02); }
.trailer-item.active { background: rgba(59, 130, 246, 0.06); border-left: 3px solid var(--accent); padding-left: 13px; }
.trailer-item.active::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--accent); border-radius: 0 2px 2px 0; }
.trailer-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.trailer-num { font-size: 15px; font-weight: 700; color: var(--text-primary); }
.trailer-location { font-size: 12px; color: var(--text-secondary); display: flex; align-items: center; gap: 4px; margin-bottom: 6px; }
.trailer-location i { font-size: 10px; color: var(--text-muted); }
.trailer-meta { display: flex; align-items: center; gap: 8px; }
.trailer-hook { font-size: 11px; color: var(--text-muted); display: flex; align-items: center; gap: 4px; }
.trailer-hook i { font-size: 9px; }
.trailer-hook.unhooked { color: var(--warning); }
.trailer-hook.hooked { color: var(--success); }
.badge-loaded { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
.badge-empty { background: var(--purple-bg); color: var(--purple); }
.badge-idle { background: var(--warning-bg); color: var(--warning); }
.map-wrap { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; position: relative; }
.map-overlay { position: absolute; top: 12px; right: 12px; z-index: 500; display: flex; flex-direction: column; gap: 6px; }
.map-overlay-btn { width: 32px; height: 32px; border-radius: 8px; background: var(--bg-secondary); border: 1px solid var(--border); color: var(--text-secondary); display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 12px; transition: all 0.15s; }
.map-overlay-btn:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.map-legend { position: absolute; bottom: 12px; left: 12px; z-index: 500; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 10px; padding: 10px 14px; display: flex; align-items: center; gap: 16px; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--text-secondary); font-weight: 500; }
.legend-dot { width: 8px; height: 8px; border-radius: 50%; }
.btn-success { background: var(--success); border-color: var(--success); color: white; }
.btn-success:hover { background: #16a34a; border-color: #16a34a; }
.btn-danger { background: var(--danger-bg); border-color: rgba(239, 68, 68, 0.3); color: var(--danger); }
.btn-danger:hover { background: rgba(239, 68, 68, 0.2); }
.btn-sm { padding: 6px 12px; font-size: 12px; }
.add-damage-card { background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin-bottom: 24px; }
.add-damage-header { font-size: 14px; font-weight: 700; color: var(--text-primary); margin-bottom: 16px; display: flex; align-items: center; gap: 8px; }
.add-damage-header i { color: var(--accent); }
.add-damage-form { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.form-field { display: flex; flex-direction: column; gap: 6px; }
.form-field label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-muted); }
.form-field input, .form-field select, .form-field textarea { padding: 8px 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-primary); font-size: 13px; font-family: inherit; outline: none; transition: border-color 0.15s; }
.form-field input:focus, .form-field select:focus, .form-field textarea:focus { border-color: var(--accent); }
.form-field input { width: 120px; }
.form-field select { width: 140px; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; padding-right: 28px; }
.form-field textarea { width: 320px; min-height: 36px; resize: vertical; }
.form-field input[type="date"] { width: 150px; }
.unit-type { font-size: 11px; color: var(--text-muted); }
.col-desc { color: var(--text-primary); line-height: 1.6; max-width: 500px; }
.col-reporter { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.reporter-avatar { width: 24px; height: 24px; border-radius: 50%; background: linear-gradient(135deg, var(--accent), #8b5cf6); display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 700; color: white; flex-shrink: 0; }
.col-date { color: var(--text-secondary); font-size: 12px; white-space: nowrap; }
.col-deadline { white-space: nowrap; }
.deadline-overdue { color: var(--danger); font-weight: 600; }
.deadline-ok { color: var(--success); font-weight: 600; }
.deadline-soon { color: var(--warning); font-weight: 600; }
.deadline-sub { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.badge-open { background: var(--danger-bg); color: var(--danger); }
.badge-fixed { background: var(--success-bg); color: var(--success); }
.row-action-btn.fix:hover { background: var(--success-bg); color: var(--success); border-color: rgba(34,197,94,0.3); }
.row-action-btn.delete:hover { background: var(--danger-bg); color: var(--danger); border-color: rgba(239,68,68,0.3); }
.page-subtitle { font-size: 14px; color: var(--text-secondary); margin-top: 4px; }
.page-subtitle a { color: var(--accent); text-decoration: none; font-weight: 600; }
.page-subtitle a:hover { text-decoration: underline; }
.week-selector { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.week-nav { display: flex; align-items: center; gap: 2px; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 10px; padding: 3px; }
.week-nav button { width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; background: transparent; border: none; color: var(--text-secondary); cursor: pointer; transition: all 0.15s; font-size: 12px; }
.week-nav button:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.week-current { padding: 6px 16px; font-size: 14px; font-weight: 600; color: var(--text-primary); }
.col-truck { font-weight: 700; color: var(--text-primary); font-size: 14px; width: 80px; }
.col-driver { font-weight: 500; color: var(--text-primary); }
.col-missing { color: var(--text-muted); font-style: italic; }
.col-missing.has-parts { color: var(--danger); font-style: normal; font-weight: 600; }
.badge-pending { background: var(--warning-bg); color: var(--warning); }
.badge-review { background: var(--info-bg); color: var(--info); }
.badge-done { background: var(--success-bg); color: var(--success); }
.badge-missing { background: var(--danger-bg); color: var(--danger); }
.driver-cell { display: flex; align-items: center; gap: 10px; }
.driver-avatar { width: 28px; height: 28px; border-radius: 50%; background: linear-gradient(135deg, var(--accent), #8b5cf6); display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; color: white; flex-shrink: 0; }
.page-title .emoji { font-size: 28px; }
.report-tab { padding: 8px 16px; border-radius: 8px; font-size: 14px; font-weight: 600; color: var(--text-secondary); text-decoration: none; transition: all 0.15s; border: 1px solid transparent; }
.report-tab:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.report-tab.active { color: var(--accent); background: rgba(59, 130, 246, 0.1); border-color: rgba(59, 130, 246, 0.2); }
.filter-field { display: flex; flex-direction: column; gap: 6px; }
.filter-field label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-muted); }
.filter-select { padding: 8px 32px 8px 12px; border-radius: 8px; border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-primary); font-size: 13px; font-weight: 500; font-family: inherit; cursor: pointer; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; min-width: 180px; }
.filter-select:focus { outline: none; border-color: var(--accent); }
.summary-banner { background: linear-gradient(135deg, rgba(59, 130, 246, 0.08), rgba(168, 85, 247, 0.05)); border: 1px solid rgba(59, 130, 246, 0.15); border-radius: 12px; padding: 16px 20px; margin-bottom: 24px; display: flex; align-items: center; gap: 12px; }
.summary-banner i { font-size: 18px; color: var(--accent); }
.summary-banner-text { font-size: 14px; color: var(--text-secondary); }
.summary-banner-text strong { color: var(--text-primary); font-weight: 700; }
.summary-banner-text .amount { color: var(--success); font-weight: 700; }
.breakdown-list { padding: 4px 0; }
.breakdown-item { display: flex; align-items: center; gap: 14px; padding: 14px 20px; border-bottom: 1px solid var(--border); transition: background 0.1s; }
.breakdown-item:last-child { border-bottom: none; }
.breakdown-item:hover { background: rgba(255,255,255,0.02); }
.breakdown-icon { width: 32px; height: 32px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 14px; flex-shrink: 0; }
.breakdown-info { flex: 1; min-width: 0; }
.breakdown-name { font-size: 14px; font-weight: 600; color: var(--text-primary); display: flex; align-items: center; gap: 8px; }
.breakdown-bar-wrap { margin-top: 8px; height: 6px; background: var(--bg-elevated); border-radius: 3px; overflow: hidden; }
.breakdown-bar { height: 100%; border-radius: 3px; transition: width 0.6s ease; }
.breakdown-meta { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
.breakdown-amount { font-size: 15px; font-weight: 700; color: var(--text-primary); text-align: right; white-space: nowrap; }
.breakdown-pct { font-size: 12px; color: var(--text-muted); text-align: right; margin-top: 2px; }
.color-tires { background: var(--danger-bg); color: var(--danger); }
.bar-tires { background: var(--danger); }
.color-brakes { background: var(--warning-bg); color: var(--warning); }
.bar-brakes { background: var(--warning); }
.color-electrical { background: var(--info-bg); color: var(--info); }
.bar-electrical { background: var(--info); }
.color-other-sys { background: var(--purple-bg); color: var(--purple); }
.bar-other-sys { background: var(--purple); }
.color-parts { background: var(--success-bg); color: var(--success); }
.bar-parts { background: var(--success); }
.color-other-cat { background: var(--purple-bg); color: var(--purple); }
.bar-other-cat { background: var(--purple); }
.color-labor { background: var(--accent-bg, rgba(59,130,246,0.12)); color: var(--accent); }
.bar-labor { background: var(--accent); }
.color-diagnostics { background: var(--info-bg); color: var(--info); }
.bar-diagnostics { background: var(--info); }
.col-trailer { font-weight: 700; color: var(--text-primary); font-size: 14px; white-space: nowrap; }
.col-truck { font-weight: 600; color: var(--text-secondary); white-space: nowrap; }
.col-location { color: var(--text-secondary); max-width: 220px; line-height: 1.5; }
.col-gps { color: var(--text-secondary); white-space: nowrap; }
.col-gps .gps-time { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.col-reporter { display: flex; align-items: center; gap: 8px; }
.col-note { color: var(--text-muted); font-style: italic; }
.col-updated { color: var(--text-secondary); font-size: 12px; white-space: nowrap; }
.badge-moving { background: var(--success-bg); color: var(--success); }
.badge-dropped { background: var(--warning-bg); color: var(--warning); }
.badge-hooked { background: var(--success-bg); color: var(--success); }
.cargo-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.cargo-empty { background: var(--purple-bg); color: var(--purple); }
.cargo-loaded { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
.last-status { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.3px; padding: 3px 8px; border-radius: 4px; display: inline-block; }
.last-status-loaded { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }
.last-status-empty { background: var(--purple-bg); color: var(--purple); }

/* Damages: the report-new card and its header icon */
.add-damage-header svg { width: 15px; height: 15px; color: var(--accent); }
.sort-select {
  background: var(--bg-primary); border: 1px solid var(--border);
  border-radius: 6px; padding: 4px 24px 4px 8px; color: var(--text-primary);
  font-size: 12px; font-family: inherit; appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='3'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center;
}
.sort-wrap { display: flex; align-items: center; gap: 8px; }
.sort-wrap .sort-label { font-size: 12px; color: var(--text-muted); }

/* The map fills its half of .map-layout. The design set this on #map; ours is
   #all-trailers-map, and an element with no height collapses to nothing. */
#all-trailers-map { width: 100%; height: 100%; min-height: 500px; background: var(--bg-tertiary); }
.trailer-pin { background: none; border: none; }
.leaflet-popup-content-wrapper { background: var(--bg-elevated); color: var(--text-primary); border-radius: 10px; }
.leaflet-popup-tip { background: var(--bg-elevated); }
.leaflet-container { font-family: inherit; }
@media (max-width: 900px) {
  .map-layout { grid-template-columns: 1fr; height: auto; }
  .trailer-list { max-height: 320px; }
  #all-trailers-map { min-height: 380px; }
}

/* Buckets the design did not name.
   The four systems and four categories in the mockup have their own colours
   above. Anything else - a system the extractor starts reporting, a category
   added later - picks one of these deterministically from its key, so a new
   bucket is visually its own thing instead of looking identical to "Other". */
.color-b1 { background: rgba(236, 72, 153, .12); color: #ec4899; }  .bar-b1 { background: #ec4899; }
.color-b2 { background: rgba(20, 184, 166, .12); color: #14b8a6; }  .bar-b2 { background: #14b8a6; }
.color-b3 { background: rgba(234, 179, 8, .12);  color: #eab308; }  .bar-b3 { background: #eab308; }
.color-b4 { background: rgba(139, 92, 246, .12); color: #8b5cf6; }  .bar-b4 { background: #8b5cf6; }
.color-b5 { background: rgba(249, 115, 22, .12); color: #f97316; }  .bar-b5 { background: #f97316; }
.color-b6 { background: rgba(6, 182, 212, .12);  color: #06b6d4; }  .bar-b6 { background: #06b6d4; }
.color-b7 { background: rgba(132, 204, 22, .12); color: #84cc16; }  .bar-b7 { background: #84cc16; }
.color-b8 { background: rgba(244, 63, 94, .12);  color: #f43f5e; }  .bar-b8 { background: #f43f5e; }
.color-b9  { background: rgba(168, 162, 158, .14); color: #a8a29e; }  .bar-b9  { background: #a8a29e; }
.color-b10 { background: rgba(217, 70, 239, .12);  color: #d946ef; }  .bar-b10 { background: #d946ef; }
.color-b11 { background: rgba(45, 212, 191, .12);  color: #2dd4bf; }  .bar-b11 { background: #2dd4bf; }
.color-b12 { background: rgba(251, 146, 60, .12);  color: #fb923c; }  .bar-b12 { background: #fb923c; }
.color-b13 { background: rgba(129, 140, 248, .12); color: #818cf8; }  .bar-b13 { background: #818cf8; }
.color-b14 { background: rgba(74, 222, 128, .12);  color: #4ade80; }  .bar-b14 { background: #4ade80; }

/* The parts and labor behind one service task, nested under its row. */
.task-items-row > td { padding-top: 0; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
.task-items { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.task-items td { padding: 4px 8px; border: none; color: var(--text-secondary); }
.task-items tr + tr td { border-top: 1px solid rgba(255,255,255,.04); }
.ti-kind { width: 78px; }
.ti-kind .badge { font-size: 10px; padding: 2px 7px; }
.badge-parts { background: var(--success-bg); color: var(--success); }
.badge-labor { background: rgba(59,130,246,.12); color: var(--accent); }
.ti-desc { color: var(--text-primary); }
.ti-brand { color: var(--text-muted); margin-left: 6px; font-size: 11px; }
.ti-qty { width: 90px; color: var(--text-muted); text-align: right; }
.ti-amount { width: 90px; text-align: right; font-weight: 600; color: var(--text-primary); }

/* Editing what was read off the invoice.
   These look like text until you point at them, so a work order still reads
   as a record rather than as a form full of boxes. */
.ti-kind { width: 112px; }
.ti-edit-kind { width: 100%; font-size: 11px; padding: 2px 4px; }
.ti-desc .inline-edit { width: 100%; }
.ti-amount .inline-edit { width: 84px; text-align: right; }
.ti-del { width: 34px; text-align: right; }
.ti-del form { margin: 0; }

/* The add-a-line row sits quiet until it is used. */
.ti-add td { opacity: .55; }
.ti-add:hover td,
.ti-add:focus-within td { opacity: 1; }

/* A service name is editable in place; it should still read as a heading. */
.task-rename { margin: 0; }
.name-edit {
  width: 100%;
  font-weight: 500;
  color: var(--text-primary);
}
.task-rename .suggest { min-width: 260px; }

/* Folding the parts away under a service. */
.col-toggle { width: 34px; }
.disclose {
  background: none;
  border: none;
  padding: 2px;
  cursor: pointer;
  color: var(--text-muted);
  line-height: 0;
  border-radius: 4px;
}
.disclose:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.disclose svg { transition: transform .12s ease; }
.disclose[aria-expanded="false"] svg { transform: rotate(-90deg); }
/* A table row needs telling: the UA rule for [hidden] loses to anything
   that sets display on the row itself. */
.task-items-row[hidden] { display: none; }

/* The line an invoice sent you to. A work order can carry nineteen lines
   that read almost the same, so arriving at one has to say which. It stays
   marked rather than fading: the point is to still be able to see it after
   reading down the table looking for the mistake. */
.task-items tr.is-targeted td { background: var(--info-bg); }
/* The bar marks the row, so it belongs on the row's edge - put on every cell
   it draws five of them, one down each column. */
.task-items tr.is-targeted td:first-child { box-shadow: inset 2px 0 0 var(--info); }

/* While a service edit is saving in the background. */
.section-card.is-busy { opacity: .6; pointer-events: none; }

/* A filter that takes several values at once. Built on <details>, so it
   opens, closes and takes the keyboard without a line of script. */
.multi-select { position: relative; }
.multi-select > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.multi-select > summary::-webkit-details-marker { display: none; }
.multi-select > summary::after {
  content: "";
  width: 7px; height: 7px;
  margin-left: 8px;
  border-right: 2px solid var(--text-muted);
  border-bottom: 2px solid var(--text-muted);
  transform: rotate(45deg) translate(-2px, -2px);
}
.multi-select[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.multi-menu {
  position: absolute;
  z-index: 40;
  top: calc(100% + 4px);
  left: 0;
  min-width: 100%;
  white-space: nowrap;
  padding: 4px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-light);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
  max-height: 18rem;
  overflow-y: auto;
}
.multi-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
}
.multi-option:hover { background: rgba(59,130,246,.16); }
.multi-option input { margin: 0; accent-color: var(--accent, #3b82f6); }
.multi-text { flex: 1; }


/* The invoice document itself, shown on the page rather than opened elsewhere. */
.doc-view { padding: 16px 20px; }
.doc-view iframe { width: 100%; height: 78vh; min-height: 460px; border: 1px solid var(--border); border-radius: 10px; background: #fff; }
.doc-view img { max-width: 100%; border: 1px solid var(--border); border-radius: 10px; display: block; }

/* Acting on several invoices at once */
.bulk-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 20px; border-bottom: 1px solid var(--border);
  background: rgba(59,130,246,.06);
}
.bulk-bar[hidden] { display: none; }
.bulk-count { font-size: 13px; color: var(--text-secondary); margin-right: 4px; }
.bulk-count strong { color: var(--accent); font-size: 15px; }

/* Picking the trucks to remind on the PTI week page. The bar stays on show
   even at nothing selected - it is how somebody finds out the checkboxes are
   there at all - but it keeps quiet until something is ticked. Scoped by id,
   because the invoices page uses .bulk-bar too and hides it outright. */
#pti-bulk-bar:not(.is-active) { background: transparent; }
#pti-bulk-bar button[disabled] { opacity: .45; cursor: not-allowed; }
.col-pick { width: 34px; text-align: center; }
.col-pick input { width: 15px; height: 15px; cursor: pointer; accent-color: var(--accent); }
.data-table tr.is-picked { background: rgba(59,130,246,.07); }
.btn.is-danger { border-color: rgba(239,68,68,.35); color: var(--danger); }
.btn.is-danger:hover { background: var(--danger-bg); }
.pagination-gap { color: var(--text-muted); padding: 0 4px; }
.filter-bar .filter-field label { display: block; font-size: 11px; color: var(--text-muted); margin-bottom: 4px; }
/* .filter-bar sets a display, which beats the browser's own rule for
   [hidden] - so the map page showed the truck bar and the trailer bar at the
   same time, stacked. Only one belongs on screen at once. */
.filter-bar[hidden] { display: none; }
/* On Both, the pills belong to one fleet each and the search does not, so
   the pills step aside and the box takes the bar. */
/* A row the layer switch has put away. Separate from .is-hidden, which is
   the search and the pills - a row can be excluded by either, and both have
   to let go before it comes back. */
.trailer-item.fleet-off { display: none; }
/* Which fleet a row is, at a glance, now that they share one list. */
.trailer-num .unit-icon { width: 12px; height: 12px; opacity: .5; margin-right: 2px; }
.legend-dot.legend-truck { border-radius: 3px; }


/* ---------------------------------------------------------------------
   The filter panel.
   Search gets its own line and the full width; the filters below share a
   grid so every label starts on the same line and every control is the
   same height. A flex row of mixed labelled and unlabelled controls could
   not line up, which is what this replaced.
   --------------------------------------------------------------------- */
.filter-panel {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px 20px;
  margin-bottom: 20px;
}
.filter-row-search { display: flex; gap: 10px; align-items: stretch; margin-bottom: 14px; }
.filter-row-search .filter-search { flex: 1 1 auto; margin-left: 0; height: 38px; position: relative; }
.filter-row-search .filter-search input { width: 100%; font-size: 14px; }
.filter-row-search .btn { height: 38px; flex: 0 0 auto; }
.filter-clear-x {
  color: var(--text-muted); text-decoration: none; font-size: 18px; line-height: 1;
  padding: 0 2px;
}
.filter-clear-x:hover { color: var(--text-primary); }

.filter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  align-items: end;          /* labels differ in length; controls still line up */
}
.filter-grid .filter-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.filter-grid .filter-field label {
  font-size: 11px; font-weight: 600; letter-spacing: .3px;
  text-transform: uppercase; color: var(--text-muted); margin: 0;
}
.filter-grid .filter-select {
  height: 36px; width: 100%; min-width: 0; box-sizing: border-box;
  padding: 0 30px 0 10px; font-size: 13px;
}
.filter-grid input.filter-select { padding-right: 10px; background-image: none; }
.filter-buttons { display: flex; gap: 8px; }
.filter-buttons .btn { height: 36px; flex: 1 1 auto; justify-content: center; }

/* What is being filtered on, each removable on its own */
.filter-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 14px; }
.chip-label { font-size: 11px; text-transform: uppercase; letter-spacing: .3px; color: var(--text-muted); }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(59,130,246,.12); color: var(--accent);
  border: 1px solid rgba(59,130,246,.25); border-radius: 20px;
  padding: 3px 10px; font-size: 12px; font-weight: 600; text-decoration: none;
}
.chip:hover { background: rgba(59,130,246,.2); }
.chip-x { font-size: 14px; line-height: 1; opacity: .7; }

@media (max-width: 700px) {
  .filter-row-search { flex-direction: column; }
  .filter-grid { grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
}

/* The seven work order statuses. Colour carries the stage: grey while it is
   only planned, blue once it is moving, amber when it is waiting on somebody
   else, green when the work is done, and settled once it is paid. */
.status-pills { gap: 6px; padding: 10px 14px; margin-bottom: 14px; }
.status-pills .filter-pill { font-size: 12.5px; padding: 6px 12px; }
.pill-count { opacity: .65; font-size: 11px; margin-left: 2px; }

.wo-planning      { background: var(--bg-elevated); color: var(--text-secondary); }
.wo-planning .badge-dot { background: var(--text-muted); }
.wo-assigned      { background: var(--purple-bg); color: var(--purple); }
.wo-assigned .badge-dot { background: var(--purple); }
.wo-open          { background: rgba(59,130,246,.12); color: var(--accent); }
.wo-open .badge-dot { background: var(--accent); }
.wo-pending_parts { background: var(--warning-bg); color: var(--warning); }
.wo-pending_parts .badge-dot { background: var(--warning); }
.wo-progress      { background: var(--info-bg); color: var(--info); }
.wo-progress .badge-dot { background: var(--info); }
.wo-completed     { background: var(--success-bg); color: var(--success); }
.wo-completed .badge-dot { background: var(--success); }
.wo-closed        { background: var(--bg-elevated); color: var(--text-secondary); }
.wo-closed .badge-dot { background: var(--success); }

/* Dropping an invoice onto a work order */
.dropzone {
  display: flex; align-items: center; gap: 14px; cursor: pointer;
  border: 1.5px dashed var(--border-light); border-radius: 12px;
  padding: 18px 20px; transition: all .15s; background: var(--bg-primary);
}
.dropzone:hover, .dropzone.is-over { border-color: var(--accent); background: rgba(59,130,246,.06); }
.dropzone.has-file { border-style: solid; border-color: var(--success); }
.dropzone svg { width: 22px; height: 22px; color: var(--text-muted); flex: none; }
.dropzone.is-over svg, .dropzone.has-file svg { color: var(--accent); }
.dropzone-text { display: flex; flex-direction: column; gap: 2px; }
.dropzone-text strong { font-size: 13.5px; color: var(--text-primary); }
.dropzone-text span { font-size: 12px; color: var(--text-muted); }
.dropzone-name { margin-left: auto; font-size: 12px; color: var(--success); font-weight: 600; }
.dropzone-actions { display: flex; gap: 8px; margin-top: 10px; }
.dropzone-actions[hidden] { display: none; }
/* Waiting for an invoice to be read. The dot is the whole point: a still
   line of text looks like a page that has given up, and the answer to that
   is always to press refresh. */
.unit-meta.reading { color: var(--accent); display: flex; align-items: center; gap: 6px; }
.reading-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  animation: reading-pulse 1.1s ease-in-out infinite;
  flex: none;
}
@keyframes reading-pulse {
  0%, 100% { opacity: .25; transform: scale(.8); }
  50%      { opacity: 1;   transform: scale(1.15); }
}
@media (prefers-reduced-motion: reduce) {
  .reading-dot { animation: none; opacity: .9; }
}


/* Picking units for a schedule: seventy trucks read as a grid, not a column. */
.check-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 2px;
  max-height: 22rem;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-tertiary);
}
.check-grid .multi-option { padding: 6px 8px; }
.check-grid input:disabled + .multi-text { opacity: .5; }
.check-grid .multi-option[hidden] { display: none; }

/* The unit picker's heading line: the label, All/None, and the filter that
   decides what All/None apply to. It wraps rather than squeezing the box on
   a narrow screen. */
/* Which carrier is being worked in. Deliberately not styled like the account
   pill next to it: this one is about the DATA on screen, not about you, and
   somebody in two companies needs to catch it without looking for it. */
/* The carriers screen: a handover card that is read once and written down,
   and a table where the numbers line up. */
/* Billing. The banner appears only when there is something to say, so it can
   afford to be noticed; the lapsed page is calm on purpose - somebody is
   there because they cannot work. */
.sub-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px;
  font-size: 13px;
  color: var(--warning);
  background: var(--warning-bg, rgba(234, 179, 8, .12));
  border-bottom: 1px solid var(--border);
}
.sub-banner svg { width: 15px; height: 15px; flex: none; }
.sub-banner span { flex: 1; }
.sub-banner strong { font-weight: 600; }
.sub-banner a { color: inherit; font-weight: 600; text-decoration: underline; }

.lapsed { border-color: var(--warning); }
.lapsed-safe {
  padding: 13px 15px;
  font-size: 13.5px;
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  border-radius: 7px;
}
.lapsed-safe strong { color: var(--text-primary); }

.sub-form { display: flex; gap: 5px; align-items: center; flex-wrap: wrap; }
.sub-form select,
.sub-form input {
  font-size: 11.5px;
  padding: 3px 6px;
  color: var(--text-primary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border);
  border-radius: 4px;
}
.sub-form input[type="text"] { width: 70px; }

.handover { border-color: var(--success); }
.handover-list { margin: 12px 0 0; display: grid; gap: 10px; }
.handover-list > div { display: grid; grid-template-columns: 150px 1fr; gap: 12px; }
.handover-list dt { font-size: 12px; color: var(--text-secondary); }
.handover-list dd { margin: 0; font-size: 13px; }
.handover-secret {
  font-size: 15px;
  letter-spacing: .04em;
  padding: 3px 8px;
  background: var(--bg-tertiary);
  border-radius: 4px;
  user-select: all;
}
.handover-warn {
  margin: 14px 0 0;
  font-size: 12.5px;
  color: var(--warning);
}
.carrier-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
  align-items: end;
  margin-top: 12px;
}
.carrier-form label { display: grid; gap: 5px; font-size: 12px; color: var(--text-secondary); }
.carrier-form label em { font-style: normal; opacity: .7; }
.carrier-form .picker-filter { max-width: none; width: 100%; }
.cell-sub { font-size: 11px; color: var(--text-secondary); }
td.num { text-align: right; font-variant-numeric: tabular-nums; }

.nav-company { margin-left: auto; }
.company-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 11px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent, #3b82f6);
  background: rgba(59, 130, 246, .12);
  border: 1px solid rgba(59, 130, 246, .35);
  border-radius: 999px;
  cursor: pointer;
}
.company-pill:hover { background: rgba(59, 130, 246, .2); }
.company-pill svg { width: 13px; height: 13px; }
.row-menu form { margin: 0; }
.row-menu form button { width: 100%; text-align: left; }
.row-menu button.is-here { font-weight: 600; }
.here-mark {
  float: right;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-secondary);
}

.picker-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 16px 0 6px;
  font-size: 14px;
}
.picker-btn { padding: 2px 8px; font-size: 11px; }
.picker-filter {
  flex: 1 1 190px;
  max-width: 280px;
  padding: 4px 9px;
  font-size: 12px;
  font-weight: 400;
  color: var(--text-primary);
  background: var(--bg-tertiary);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.picker-filter:focus {
  outline: none;
  border-color: var(--accent, #3b82f6);
}
.picker-count {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-secondary);
}
/* The integrations page: one credential per block, with room for the
   provider's own answer under the Test button. */
.integration-row {
  padding: 14px 0;
  border-top: 1px solid var(--border);
}
.integration-row:first-of-type { border-top: none; }
.integration-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 4px;
}
.integration-value {
  font-size: 11.5px;
  color: var(--text-secondary);
  background: var(--bg-tertiary);
  padding: 2px 6px;
  border-radius: 4px;
}
.integration-fallback {
  font-size: 12px;
  color: var(--text-secondary);
}
/* An office that is deactivated stays in the list, so it can be reactivated -
   dimmed, but its buttons are not. */
.data-table tr.is-off td { opacity: .6; }
.data-table tr.is-off td:last-child { opacity: 1; }
.integration-help {
  margin: 2px 0 8px;
  font-size: 12px;
  color: var(--text-secondary);
  max-width: 68ch;
}
.integration-form {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.integration-input { flex: 1 1 260px; max-width: 420px; }
.integration-result {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--text-secondary);
  max-width: 68ch;
}
.integration-result.is-good { color: var(--success); }
.integration-result.is-bad { color: var(--danger); }

.picker-empty {
  margin: 6px 2px 0;
  font-size: 12px;
  color: var(--text-secondary);
}
/* The owner, under the number: enough to pick by, never enough to crowd
   out the number itself. */
.unit-owner {
  display: block;
  font-size: 10.5px;
  line-height: 1.3;
  color: var(--text-muted, var(--text-secondary));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* The three ways a schedule can repeat. They wrap instead of running off the
   right-hand edge, and each keeps its number box wide enough to read. */
.interval-grid { flex-wrap: wrap; gap: 18px; }
.interval-grid .filter-field {
  flex: 1 1 220px;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.interval-grid .multi-option { padding: 0; background: none; }
.interval-grid .multi-option:hover { background: none; }
.interval-grid .hint { margin: 0; }


/* Posting an update from a row: wider than a menu of buttons, because it
   holds a message box and a choice of destination. */
.post-menu {
  width: 300px;
  padding: 10px;
  right: 0;
  left: auto;
}
.post-menu textarea {
  width: 100%;
  resize: vertical;
  font-family: inherit;
  font-size: 13px;
}
.post-menu .multi-option { padding: 5px 6px; }
.post-menu .menu-label { padding: 0 0 4px; }


/* The truck's PM, inside the scheduled maintenance card. A strip rather than
   another table: it is one row about one thing, and a second table made the
   card read as two cards stacked. */
.pm-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: rgba(139, 92, 246, .06);
}
.pm-label { font-weight: 600; font-size: 13px; color: var(--text-primary); }
.pm-meta { display: block; font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }
.pm-right { display: flex; align-items: center; gap: 10px; }
.pm-right form { margin: 0; }


/* A shop is judged on more than a name: the yard, the rating, and what the
   last few people said. A table row cannot carry that, so the Google results
   are cards. */
.shop-cards { display: flex; flex-direction: column; gap: 10px; padding: 12px 16px 16px; }
.shop-card {
  display: flex;
  gap: 14px;
  background: var(--bg-tertiary);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
.shop-photo {
  width: 150px;
  min-width: 150px;
  object-fit: cover;
  background: var(--bg-elevated);
  align-self: stretch;
}
.shop-photo--none {
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); min-height: 110px;
}
.shop-photo--none svg { width: 30px; height: 30px; }
.shop-body { flex: 1; padding: 12px 14px 12px 0; min-width: 0; }
.shop-head { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.shop-name { font-weight: 600; font-size: 14px; }
.shop-meta { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.shop-stats { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.shop-rating { color: var(--warning); font-weight: 700; }
.shop-reviews { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.shop-review { font-size: 12px; line-height: 1.45; }
.shop-review-head { color: var(--text-muted); margin-right: 6px; }
.shop-review-text { color: var(--text-secondary); }
.shop-actions { margin-top: 12px; display: flex; gap: 8px; align-items: center; }
.shop-actions form { margin: 0; }

@media (max-width: 640px) {
  .shop-card { flex-direction: column; }
  .shop-photo { width: 100%; min-width: 0; height: 140px; }
  .shop-body { padding: 0 14px 14px; }
}


/* Find a shop: list and map side by side, the way the job is done. The panel
   replaces the list rather than sitting under it, so the map never scrolls
   out of view while you are deciding. */
.shop-split {
  display: grid;
  grid-template-columns: minmax(320px, 420px) 1fr;
  gap: 14px;
  align-items: stretch;
  margin-bottom: 16px;
}
.shop-pane {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  max-height: 560px;
  overflow: hidden;
}
.shop-pane-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 14px; border-bottom: 1px solid var(--border);
  font-size: 13px; font-weight: 600;
}
.shop-list, .shop-detail { overflow-y: auto; flex: 1; }

.shop-row {
  display: flex; justify-content: space-between; gap: 12px; align-items: center;
  padding: 11px 14px; border-bottom: 1px solid var(--border);
  cursor: pointer;
}
.shop-row:hover, .shop-row:focus { background: var(--bg-tertiary); outline: none; }
.shop-row-name { display: block; font-weight: 600; font-size: 13px; }
.shop-row-meta {
  display: block; font-size: 11.5px; color: var(--text-muted); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 250px;
}
.shop-row-side { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.shop-rating { color: var(--warning); font-weight: 700; font-size: 12.5px; }

.shop-detail-photo { width: 100%; height: 180px; object-fit: cover; display: block; }
.shop-detail-body { padding: 14px; }
.shop-detail-name { font-size: 16px; font-weight: 700; }
.shop-detail-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 8px 0 10px; }
.shop-detail-line { font-size: 12.5px; color: var(--text-secondary); margin-bottom: 3px; }
.shop-detail-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0 4px; }
.shop-detail-sub {
  margin-top: 16px; font-size: 11px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-muted);
}
.shop-detail-reviews { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.shop-review { font-size: 12.5px; line-height: 1.5; }
.shop-review-head { display: block; color: var(--text-muted); margin-bottom: 2px; }
.shop-review-text { color: var(--text-secondary); }

/* The map carries its own furniture now, so the wrapper is the positioning
   context and the map itself simply fills it. */
.shop-map-wrap { position: relative; display: flex; }
.shop-map { flex: 1; min-height: 560px; border-radius: 10px; border: 1px solid var(--border); }
.search-here {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  z-index: 1001;               /* clear of Leaflet's own controls */
  white-space: nowrap;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
}
/* .btn sets a display, which beats the browser's own rule for [hidden]. */
.search-here[hidden] { display: none; }
/* Leaflet gives div icons a white box and a border of their own; the pin is
   the whole graphic, so both have to go. */
/* The unit's own details, above the search. Reads as one line on a desktop
   and wraps into a stack on a telephone, which is where somebody standing
   next to the truck will read it. */
.unit-line {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  margin: 0 0 8px; font-size: 12px; color: var(--text-secondary);
}
.unit-badge {
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 6px; padding: 2px 8px; font-weight: 600; color: var(--text-primary);
}
.unit-spec { font-weight: 500; color: var(--text-primary); }
.unit-vin code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; letter-spacing: .04em;
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 5px; padding: 1px 6px; user-select: all;
}

/* ---- equipment search ----
   Sits between the links and the user pill, and gives way first when the
   window narrows: on a small screen the navigation matters more than a
   search box nobody can see the results of. */
.equip-search {
  position: relative; display: flex; align-items: center; gap: 7px;
  background: var(--bg-primary); border: 1px solid var(--border);
  border-radius: 8px; padding: 0 10px; height: 34px;
  flex: 0 1 250px; min-width: 150px;
  transition: border-color .15s, box-shadow .15s;
}
.equip-search:focus-within {
  border-color: var(--accent, #3b82f6);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, .12);
}
.equip-search > svg { width: 14px; height: 14px; color: var(--text-muted); flex: 0 0 auto; }
.equip-search input {
  flex: 1 1 auto; min-width: 0; background: none; border: 0; outline: none;
  color: var(--text-primary); font-size: 13px; font-family: inherit; padding: 0;
}
.equip-search input::placeholder { color: var(--text-muted); }
.equip-search input::-webkit-search-cancel-button { display: none; }
.equip-search kbd {
  flex: 0 0 auto; font-family: ui-monospace, monospace; font-size: 10px;
  color: var(--text-muted); border: 1px solid var(--border);
  border-radius: 4px; padding: 1px 5px; line-height: 1.4;
}
.equip-search:focus-within kbd { display: none; }

.equip-results {
  position: absolute; top: calc(100% + 6px); right: 0; width: 380px; max-width: 92vw;
  max-height: 60vh; overflow-y: auto; z-index: 1100;
  background: var(--bg-elevated); border: 1px solid var(--border-light);
  border-radius: 10px; box-shadow: 0 14px 38px rgba(0, 0, 0, .5); padding: 5px;
}
.equip-results[hidden] { display: none; }
.equip-hit {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px;
  border-radius: 7px; text-decoration: none; color: var(--text-secondary);
}
.equip-hit > svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--text-muted); }
.equip-hit.is-active { background: var(--bg-tertiary); }
.equip-hit.is-active .equip-name { color: var(--text-primary); }
.equip-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.equip-name {
  font-weight: 600; font-size: 13px; color: var(--text-primary);
  display: flex; align-items: center; gap: 6px;
}
.equip-sub {
  font-size: 11.5px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.equip-why {
  flex: 0 0 auto; font-family: ui-monospace, monospace; font-size: 10px;
  text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 999px; padding: 2px 7px;
}
.equip-tag {
  font-size: 9.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); border: 1px solid var(--border);
  border-radius: 999px; padding: 1px 6px; font-weight: 500;
}
.equip-empty { padding: 14px 12px; font-size: 12.5px; color: var(--text-muted); }

@media (max-width: 1180px) { .equip-search { display: none; } }

/* Which fleet the map is showing. Over the map rather than above it, so it
   reads as a control on the picture and not another page filter. */
.map-layout { position: relative; }
.layer-switch {
  position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  z-index: 600; display: flex; gap: 2px; padding: 3px;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 9px; box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
}
.layer-switch button {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 12px; border: 0; border-radius: 6px; cursor: pointer;
  background: transparent; color: var(--text-muted);
  font-family: inherit; font-size: 12px; font-weight: 600; white-space: nowrap;
  transition: background .15s, color .15s;
}
.layer-switch button:hover:not(.on) { color: var(--text-secondary); }
.layer-switch button.on { background: var(--bg-elevated); color: var(--text-primary); }
.layer-switch .n {
  font-variant-numeric: tabular-nums; opacity: .6; font-weight: 500;
}
@media (max-width: 720px) {
  .layer-switch { left: 12px; transform: none; }
}

.shop-pin { background: none; border: 0; }
.shop-pin svg {
  width: 22px; height: 22px; display: block;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .45));
}
.hidden-form { display: none; }

@media (max-width: 900px) {
  .shop-split { grid-template-columns: 1fr; }
  .shop-map-wrap { order: -1; }
  .shop-map { min-height: 320px; }
  .shop-pane { max-height: 460px; }
}


/* Five reviews is all Google's API will part with; the rest are on its own
   page, and this says so rather than implying the list is complete. */
.shop-more-reviews {
  display: inline-block;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--accent, #3b82f6);
}

/* ---------------------------------------------------------- the unit page --
   A unit page answers two questions and they want different room: where is
   it, and what has been done to it. The map takes the page and the panel
   takes the side, with a switch at the top of the panel deciding which of
   the two you are asking. */
.unit-layout { height: calc(100vh - 260px); min-height: 520px; }
.unit-head { margin-bottom: 12px; }
.unit-panel { padding: 0; }

.unit-switch {
  display: flex; gap: 2px; padding: 4px; margin: 10px 10px 0;
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 9px;
}
.unit-switch button {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 7px 10px; border: 0; border-radius: 6px; cursor: pointer;
  background: transparent; color: var(--text-muted);
  font-family: inherit; font-size: 12px; font-weight: 600;
  transition: background .15s, color .15s;
}
.unit-switch button:hover:not(.on) { color: var(--text-secondary); }
.unit-switch-panes { display: flex; gap: 2px; flex: 1; min-width: 0; }
/* The unit this visit was attached to: present, but plainly secondary to
   the one that is actually broken. */
.hooked-badge { opacity: .75; font-weight: 500; }

/* ---------- Hookups that cannot both be true ----------
   A <details> that folds away: it sits above the board somebody came here
   to read, and four conflicts push that off the screen. One grid for every
   row rather than a table per conflict, so the trailer, the status and the
   place line up down the whole card. */
.hook-conflicts { padding: 0; }
.hook-conflicts > summary {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 14px 16px; cursor: pointer; list-style: none;
}
.hook-conflicts > summary::-webkit-details-marker { display: none; }
.hook-conflicts > summary:hover { background: var(--bg-tertiary); }
.hook-conflicts .hc-title { font-weight: 600; font-size: 14px; }
.hook-conflicts .hc-sub {
  font-size: 12px; color: var(--text-muted);
  /* Pushed away from the count so the two are not read as one phrase. */
  margin-left: 4px;
}
.hook-conflicts .hc-chevron {
  width: 14px; height: 14px; margin-left: auto; color: var(--text-muted);
  transition: transform .15s;
}
.hook-conflicts[open] .hc-chevron { transform: rotate(180deg); }

.hook-conflicts .hc-body { padding: 0 16px 14px; }
.hook-conflicts .hc-claim {
  margin: 14px 0 6px; font-size: 13px; color: var(--text-secondary);
}
.hook-conflicts .hc-claim:first-child { margin-top: 4px; }
/* Fixed columns, so every row in the card lines up regardless of which
   conflict it belongs to - the thing four separate tables could not do. */
.hook-conflicts .hc-row {
  display: grid; align-items: center; gap: 12px;
  grid-template-columns: 110px 78px 1fr 92px auto;
  padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--bg-tertiary);
  margin-bottom: 6px;
}
.hook-conflicts .hc-trailer {
  font-weight: 600; color: var(--text-primary); text-decoration: none;
}
.hook-conflicts .hc-trailer:hover { color: var(--accent); text-decoration: underline; }
.hook-conflicts .hc-where {
  font-size: 12px; color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hook-conflicts .hc-when {
  font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.hook-conflicts .hc-foot { margin: 12px 0 0; font-size: 12px; color: var(--text-muted); }

/* On a phone the grid becomes a stack: five columns at 380px is five
   columns nobody can read. */
@media (max-width: 720px) {
  .hook-conflicts .hc-row { grid-template-columns: 1fr auto; row-gap: 6px; }
  .hook-conflicts .hc-where { grid-column: 1 / -1; white-space: normal; }
  .hook-conflicts .hc-sub { flex: 1 0 100%; margin-left: 0; }
}
/* Moving events to the right truck: the action sits under the list it acts
   on, so what is ticked and what happens to it are read together. */
.move-bar {
  display: flex; flex-wrap: wrap; align-items: end; gap: 12px;
  padding: 14px; border-top: 1px solid var(--border);
}
.move-bar label { display: flex; flex-direction: column; gap: 4px; font-size: 12px;
                  color: var(--text-muted); }
.move-bar input[type="text"] {
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-secondary); color: var(--text-primary); font-size: 14px;
}
.move-bar .hint { flex: 1 0 100%; margin: 0; }
/* Not a third tab: it leaves the page, so it does not stretch to a third of
   the bar and it carries an icon the two panes do not. */
.unit-switch-link {
  flex: 0 0 auto; display: flex; align-items: center; gap: 5px;
  padding: 7px 11px; border-radius: 6px; text-decoration: none;
  color: var(--text-muted); font-size: 12px; font-weight: 600;
  transition: background .15s, color .15s;
}
.unit-switch-link:hover { background: var(--bg-elevated); color: var(--accent); }
.unit-switch-link svg { width: 13px; height: 13px; }
.unit-switch button.on { background: var(--bg-elevated); color: var(--text-primary); }
.unit-switch .n {
  padding: 0 5px; border-radius: 8px; background: var(--danger);
  color: #fff; font-size: 10px; font-variant-numeric: tabular-nums;
}

/* The panes carry a display, so hiding them needs a rule that outranks the
   browser's [hidden] - the same fix six other components here needed. */
.unit-pane { flex: 1; overflow-y: auto; padding: 14px 14px 18px; display: block; }
.unit-pane[hidden] { display: none; }

.unit-figures { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.unit-figures .figure {
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--bg-tertiary);
}
.unit-figures .k {
  display: block; font-size: 11px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em;
}
.unit-figures .v {
  display: block; margin-top: 3px; font-size: 20px; font-weight: 700;
  color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.unit-figures .v em { font-style: normal; font-size: 12px; font-weight: 500;
  color: var(--text-muted); margin-left: 3px; }

.unit-note { margin: 8px 0 0; font-size: 11px; color: var(--text-muted); }
.unit-sub {
  margin: 16px 0 6px; font-size: 11px; font-weight: 700; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .05em;
}

.unit-facts { margin: 14px 0 0; display: grid; grid-template-columns: 84px 1fr; gap: 7px 10px; }
.unit-facts dt { font-size: 12px; color: var(--text-muted); }
.unit-facts dd { margin: 0; font-size: 13px; color: var(--text-primary); word-break: break-word; }
.unit-facts dd .hint { display: block; font-size: 11px; }
.unit-facts code { font-size: 11.5px; letter-spacing: .02em; }

.unit-counts {
  display: flex; gap: 14px; margin-top: 16px; padding-top: 12px;
  border-top: 1px solid var(--border); font-size: 12px; color: var(--text-muted);
}
.unit-counts strong { color: var(--text-primary); font-size: 14px; }
.unit-counts .is-bad strong { color: var(--danger); }

.unit-issue, .unit-line {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  padding: 8px 10px; margin-bottom: 5px; border-radius: 8px;
  background: var(--bg-tertiary); border: 1px solid var(--border);
  font-size: 12.5px; color: var(--text-primary); text-decoration: none;
}
a.unit-issue:hover, a.unit-line:hover { border-color: var(--accent); }
.unit-issue-task { font-weight: 600; }
.unit-line .is-bad { color: var(--danger); font-weight: 600; }
.unit-full { display: block; margin-top: 14px; text-align: center; }

#unit-map { width: 100%; height: 100%; min-height: 520px;
  border-radius: 12px; background: var(--bg-tertiary); }
.unit-pin { background: none; border: 0; }
.unit-dot {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%; color: #06121f;
  border: 2px solid rgba(255, 255, 255, .85);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .5);
  font-size: 10px; font-weight: 800;
}
.unit-nomap {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 30px; text-align: center;
  border: 1px dashed var(--border); border-radius: 12px;
  background: var(--bg-secondary); color: var(--text-muted);
}
.unit-nomap svg { width: 34px; height: 34px; opacity: .5; }
.unit-nomap p { max-width: 420px; font-size: 13px; }

@media (max-width: 900px) {
  .unit-layout { height: auto; }
  .unit-pane { max-height: 340px; }
  #unit-map { min-height: 360px; }
}

/* Google's info bubble is white with black text, which on a dark page reads
   like a hole punched in it. The wrapper is theirs, so it is reached by their
   class names; the arrow underneath needs colouring separately or it stays
   white against the recoloured box. */
.gm-style .gm-style-iw-c {
  background: var(--bg-elevated); color: var(--text-primary);
  border-radius: 10px; box-shadow: 0 6px 20px rgba(0, 0, 0, .5);
  /* Room on the right for the close button, which now floats in the corner
     rather than sitting in a row of its own. */
  padding: 11px 30px 11px 13px !important;
}
.gm-style .gm-style-iw-d {
  overflow: hidden !important; background: transparent;
  padding: 0 !important; max-height: none !important;
}
.gm-style .gm-style-iw-tc::after { background: var(--bg-elevated); }
.gm-style .gm-style-iw-c .hint { color: var(--text-muted); font-size: 11px; }

/*  Google reserves a header row inside every bubble whether or not there is
    a header to put in it, and ours have none - which drew a blank band above
    the text the height of the close button. The row is flattened and the
    button floated into the corner instead.

    Two generations of class names are covered: -ch/-chr are the current
    ones, and older builds put the button straight in -c. A rule that matches
    nothing costs nothing, and a map that quietly grows a blank band after a
    Google update costs an afternoon.  */
.gm-style .gm-style-iw-ch { padding: 0 !important; display: block !important; }
.gm-style .gm-style-iw-chr {
  position: absolute !important; top: 0; right: 0; z-index: 2;
  height: auto !important; width: auto !important;
  padding: 0 !important; margin: 0 !important;
}
.gm-style .gm-style-iw-chr .gm-style-iw-ch { display: none !important; }
.gm-style .gm-ui-hover-effect {
  width: 26px !important; height: 26px !important;
  top: 0 !important; right: 0 !important; opacity: .55;
}
.gm-style .gm-ui-hover-effect:hover { opacity: 1; }
.gm-style .gm-ui-hover-effect > span {
  background-color: var(--text-muted);
  width: 13px !important; height: 13px !important; margin: 6px !important;
}
.map-warn {
  grid-column: 2; margin-bottom: 8px; padding: 9px 12px; border-radius: 9px;
  background: rgba(234, 179, 8, .12); border: 1px solid rgba(234, 179, 8, .4);
  color: var(--warning); font-size: 12.5px;
}

/* Every pin on every map is an SVG in a bare box: the same markup Leaflet
   drops into a div and Google takes as a picture, so a marker looks the same
   whichever engine drew it. */
.fleet-pin { background: none; border: 0; }
.fleet-pin svg { display: block; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .45)); }

/* ============================================================ map pages ==
   The fleet map and the shop finder are the same page in two costumes: the
   map takes the whole window and the list floats over it on the left. Both
   used to be a two-column grid with the map in one half, which left a strip
   of empty page under the shorter column and made the map smaller than the
   thing it is for.

   The page must not scroll - the panel scrolls inside itself instead. Get
   that wrong and either the map is a letterbox or the reviews are
   unreachable. */
body.map-body { overflow: hidden; }

/*  The equipment explorer, full-bleed.
 *
 *  Same shape as `map-full` below, and deliberately a separate class rather
 *  than a reuse of it: the two pages want different things of the strip above
 *  the canvas, and one class serving both is how a change made for the map
 *  quietly resizes the 3D view.
 *
 *  The height is 57px short of the window, not 56: `.navbar-inner` is 56px
 *  tall and `.navbar` adds a 1px bottom border, so the navbar occupies 57.
 *  Subtracting 56 leaves the document one pixel taller than the viewport, and
 *  since `overflow: hidden` on BODY does not propagate to the viewport - only
 *  the one on `html` does - the page scrolls by that pixel. On a page whose
 *  whole design is that it does not scroll, a 1px nudge moves the cards off
 *  the model. Measured in a browser: nav 57px, container 844px, document 901
 *  against a 900px window. `map-full` below still carries the old 56 and the
 *  same one pixel; it is left alone here rather than changed blind, because
 *  that is a different page than this one.
 *
 *  Everything INSIDE the explorer lives in equipment/equipment.css, which
 *  touches nothing outside `.equipment-explorer` and has a test saying so.
 *  These are the page rather than the feature, which is why they are here.
 */
.container.eq-full {
  max-width: none; padding: 0;
  height: calc(100vh - 57px);        /* 56px of navbar plus its 1px border */
  display: flex; flex-direction: column;
}
.container.eq-full .flashes { margin: 8px 14px 0; flex: 0 0 auto; }

.eq-bar {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 12px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-secondary);
}
.eq-bar-title {
  margin: 0; font-size: 15px; font-weight: 600;
  display: flex; align-items: center; gap: 8px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.eq-bar-title .emoji { font-size: 17px; }
.eq-bar-actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }

/*  Below this the cards come off the model and the page scrolls again, so the
    body has to be released - there is content underneath that nobody could
    otherwise reach. Same breakpoint as equipment.css. */
@media (max-width: 1180px) {
  body.map-body { overflow: auto; }
  .container.eq-full { height: auto; display: block; padding: 0 0 24px; }
  .eq-bar { position: sticky; top: 57px; z-index: 20; }
}

/*  On a phone the strip was the worst thing on the page: one flex row with
    nowrap, so "Back to trucks" was squeezed to 95px and broke over FOUR
    lines, the whole bar stood 160px tall - a fifth of the screen, above a
    model 453px tall - and the unit's name was clipped to 49px of the 116 it
    needs, leaving "Tr". The name of the truck being looked at is the one
    thing on this bar that cannot be guessed from context.

    So the row is allowed to wrap and the buttons are not: the labels keep
    their own width and the bar gives them a second line when they need one,
    which is the opposite of what squeezing them does. Measured at 375px. */
@media (max-width: 640px) {
  .eq-bar { flex-wrap: wrap; row-gap: 8px; }
  .eq-bar > .btn { white-space: nowrap; }
  .eq-bar-title { flex: 1 1 auto; min-width: 0; }
  .eq-bar-actions { margin-left: 0; flex: 1 0 100%; }
  .eq-bar-actions .btn { white-space: nowrap; flex: 1 1 auto; justify-content: center; }
}

.container.map-full {
  max-width: none; padding: 0;
  height: calc(100vh - 56px);        /* the navbar is 56px and sticky */
  display: flex; flex-direction: column;
}
.container.map-full .sub-tabs { padding: 10px 16px; margin: 0; flex: 0 0 auto; }
.container.map-full .flashes { margin: 0 16px 8px; flex: 0 0 auto; }

.map-page { position: relative; flex: 1; min-height: 0; }
.map-page > .map-canvas { position: absolute; inset: 0; }
.map-page > .map-canvas > div { width: 100%; height: 100%; }

/* The list, over the map rather than beside it. */
.map-panel {
  position: absolute; z-index: 500; top: 12px; left: 12px; bottom: 12px;
  width: 380px; display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: 0 10px 34px rgba(0, 0, 0, .5);
  transition: transform .18s ease;
}
.map-panel-head {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 11px 13px; border-bottom: 1px solid var(--border);
}
.map-panel-title {
  font-size: 14px; font-weight: 700; display: flex; align-items: center; gap: 7px;
  min-width: 0;
}
.map-panel-title svg { width: 15px; height: 15px; flex: 0 0 auto; }
.map-panel-title span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-panel-actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.map-panel-fixed { flex: 0 0 auto; }
.map-panel-scroll { flex: 1; min-height: 0; overflow-y: auto; }
.map-panel-foot {
  flex: 0 0 auto; padding: 8px 12px; border-top: 1px solid var(--border);
  background: var(--bg-secondary);
}
.icon-btn {
  width: 28px; height: 28px; display: inline-flex; align-items: center;
  justify-content: center; border-radius: 7px; cursor: pointer;
  background: var(--bg-tertiary); border: 1px solid var(--border);
  color: var(--text-secondary);
}
.icon-btn:hover { color: var(--text-primary); border-color: var(--border-light); }
.icon-btn svg { width: 14px; height: 14px; }

/* Push the list out of the way and the map is the whole window. */
.panel-tab {
  position: absolute; z-index: 501; top: 50%; left: 392px;
  transform: translateY(-50%);
  width: 20px; height: 46px; padding: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-secondary); border: 1px solid var(--border);
  border-left: 0; border-radius: 0 8px 8px 0;
  color: var(--text-muted); font-size: 12px;
  box-shadow: 3px 0 12px rgba(0, 0, 0, .35);
  transition: left .18s ease;
}
.panel-tab:hover { color: var(--text-primary); }
.map-page.panel-away .map-panel { transform: translateX(calc(-100% - 20px)); }
.map-page.panel-away .panel-tab { left: 0; border-radius: 0 8px 8px 0; }

/* Furniture that floats on the map. Left is the panel's, so everything else
   keeps to the middle and the right. */
.map-page .layer-switch { left: calc(50% + 190px); }
.map-page .search-here { left: calc(50% + 190px); }
.map-page.panel-away .layer-switch,
.map-page.panel-away .search-here { left: 50%; }
.map-page .map-overlay { top: 12px; right: 12px; }

.map-stats {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
  background: var(--border); border-bottom: 1px solid var(--border);
}
.map-stat { background: var(--bg-secondary); padding: 7px 9px; }
.map-stat .v { display: block; font-size: 15px; font-weight: 700; line-height: 1.2; }
.map-stat .k { display: block; font-size: 10px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em; }

/* On a telephone an overlay panel would cover the map it is describing, so
   the two stack and the page scrolls the ordinary way. */
@media (max-width: 900px) {
  body.map-body { overflow: auto; }
  .container.map-full { height: auto; padding-bottom: 16px; }
  .map-page { height: auto; display: flex; flex-direction: column; }
  .map-page > .map-canvas { position: relative; inset: auto; height: 52vh; min-height: 300px; }
  .map-panel {
    position: relative; inset: auto; width: auto; margin: 10px 12px 0;
    max-height: 60vh; transform: none !important;
  }
  .panel-tab { display: none; }
  .map-page .layer-switch, .map-page .search-here { left: 50%; }
}

/* ---- what the panel holds on the fleet map ---- */

/* The filter bar was a card across the page; inside the panel it is just the
   pills, with the search box on its own line above them. */
.map-panel .filter-bar {
  border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  padding: 9px 11px; margin: 0; gap: 5px; background: var(--bg-secondary);
}
.map-panel .filter-search {
  order: -1; width: 100%; margin: 0 0 7px; padding: 6px 10px;
  background: var(--bg-tertiary);
}
.map-panel .filter-search input { width: 100%; font-size: 12.5px; }
.map-panel .filter-pill { padding: 3px 9px; font-size: 11.5px; }

/* The fleet switch, in the panel rather than floating: the same segmented
   control the unit page uses, so the two read as one idea. */
.map-panel .layer-switch {
  position: static; transform: none; box-shadow: none;
  border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  padding: 8px 11px; gap: 4px; background: var(--bg-secondary);
}
.map-panel .layer-switch button {
  flex: 1; justify-content: center;
  background: var(--bg-tertiary); border: 1px solid var(--border);
}
.map-panel .layer-switch button.on {
  background: var(--bg-elevated); border-color: var(--border-light);
  color: var(--text-primary);
}

.map-panel .sidebar-count { font-size: 11px; white-space: nowrap; }
.map-panel .trailer-list { flex: none; overflow: visible; }

.panel-form { border-bottom: 1px solid var(--border); padding: 10px 12px; }
.panel-form .section-header { margin-bottom: 8px; }
.panel-form .add-damage-form { display: flex; flex-direction: column; gap: 8px; }
.panel-form .add-damage-form .btn { width: 100%; justify-content: center; }

.map-legend-inline {
  display: flex; flex-wrap: wrap; gap: 4px 12px;
  font-size: 10.5px; color: var(--text-muted);
}
.map-legend-inline span { display: inline-flex; align-items: center; gap: 5px; }
.map-legend-inline i {
  width: 9px; height: 9px; display: inline-block;
  border-radius: 50% 50% 50% 0; transform: rotate(-45deg);
}
.map-legend-inline i.round { border-radius: 50%; transform: none; }

/* ---- what the panel holds on the shop finder ---- */

/* The context card and the search form were full-width cards; in the panel
   they are sections divided by a line, not boxes inside a box. */
.panel-section {
  padding: 10px 12px; border-bottom: 1px solid var(--border);
  font-size: 12.5px;
}
.panel-section .section-title { font-size: 13px; margin-bottom: 5px; }
.panel-section .hint { font-size: 11.5px; }
.panel-section .unit-line { gap: 4px 8px; margin: 4px 0; }
.panel-search .filter-grid { display: flex; flex-direction: column; gap: 8px; }
.panel-search .filter-field { flex: none !important; width: 100%; }
.panel-search .filter-field label { font-size: 11px; }
.panel-search .btn { width: 100%; justify-content: center; }
.panel-note { margin: 0; border-radius: 0; font-size: 11.5px; padding: 9px 12px; }

/* Inside the panel the list and the detail are page flow: the panel itself
   is the thing that scrolls, and two scrollbars inside one card is how you
   lose half a list without noticing. */
.map-panel .shop-list,
.map-panel .shop-detail { overflow: visible; flex: none; }
.map-panel .shop-row-meta { max-width: 210px; }
.map-panel .shop-detail-photo { height: 150px; }
.map-panel .shop-detail-actions .btn { flex: 1; justify-content: center; min-width: 96px; }

/* The map fills whatever is left of the window. */
#shop-map { background: var(--bg-tertiary); }
.map-canvas .unit-nomap { height: 100%; border: 0; border-radius: 0; }

/* ---- what the panel holds on a unit page ---- */

/* The Details/Records switch is fixed under the panel head; the panel below
   it is what scrolls, so the toggle never leaves the screen. */
.map-panel .unit-switch { margin: 0; border-radius: 0; border: 0;
  border-bottom: 1px solid var(--border); background: var(--bg-secondary); }
.map-panel .unit-pane { overflow: visible; flex: none; padding: 12px 12px 18px; }
.map-panel .unit-figures .v { font-size: 18px; }

/* A record is a row, not a table cell: the same facts stacked, because a
   panel is 380px wide and a work order has seven columns. */
.unit-rec {
  display: block; padding: 8px 10px; margin-bottom: 5px; border-radius: 8px;
  background: var(--bg-tertiary); border: 1px solid var(--border);
  color: var(--text-primary); text-decoration: none; font-size: 12.5px;
}
a.unit-rec:hover { border-color: var(--accent); }
.unit-rec-top {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
}
.unit-rec-name { font-weight: 600; }
.unit-rec-what {
  display: block; color: var(--text-secondary); margin: 2px 0 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.unit-rec .hint { display: block; font-size: 11px; }
.unit-rec .is-bad { color: var(--danger); font-weight: 600; }

.unit-sub { display: flex; align-items: baseline; gap: 7px; }
.unit-sub b { color: var(--text-secondary); font-weight: 700; }
.unit-sub-link {
  margin-left: auto; text-transform: none; letter-spacing: 0;
  font-size: 11px; font-weight: 500; color: var(--accent); text-decoration: none;
}
.unit-sub-link:hover { text-decoration: underline; }

/* The work order list says what was done, not who it was sent to and how
   urgent somebody once said it was. The shop keeps its place as a second
   line: it is context for the work, not the headline. */
.col-service { max-width: 420px; }
.wo-tasks {
  display: block; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wo-tasks.hint { color: var(--text-muted); }
.wo-shop {
  display: block; font-size: 11.5px; color: var(--text-muted); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wo-asked {
  display: inline-block; margin-top: 2px; padding: 0 5px; border-radius: 4px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  background: var(--bg-elevated); color: var(--text-muted);
}

/* ==================================================== trailer history ====
   The hook and drop record is one thing after another, so it is drawn as a
   line with the events hanging off it rather than as paragraphs of emoji. */
.hist-summary {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px; background: var(--border); padding: 0; overflow: hidden;
  margin-bottom: 16px;
}
.hist-figure { background: var(--bg-secondary); padding: 12px 14px; }
.hist-figure .k {
  display: block; font-size: 11px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em; margin-bottom: 5px;
}
.hist-figure .v { display: block; font-size: 17px; font-weight: 700; }
.hist-figure .v.small { font-size: 13px; font-weight: 600; line-height: 1.35; }
.hist-figure .hint { display: block; margin-top: 3px; font-size: 11px; }
.hist-none { padding: 4px 20px 18px; color: var(--text-muted); font-size: 13px; }

.note-add { padding: 14px 20px; border-bottom: 1px solid var(--border); }
.note-add form { display: flex; gap: 8px; }
.note-add input { flex: 1; }
.note-list { list-style: none; margin: 0; padding: 0; }
.note-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  padding: 11px 20px; border-bottom: 1px solid var(--border);
}
.note-row:last-child { border-bottom: 0; }
.note-text { font-size: 13px; }
.note-meta { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }

.timeline { list-style: none; margin: 0; padding: 6px 20px 18px; position: relative; }
.tl-item { position: relative; padding: 0 0 14px 34px; }
/* The line runs between the dots, not past the last one. */
.tl-item::before {
  content: ""; position: absolute; left: 12px; top: 24px; bottom: 0;
  width: 2px; background: var(--border);
}
.tl-item:last-child { padding-bottom: 2px; }
.tl-item:last-child::before { display: none; }
.tl-dot {
  position: absolute; left: 0; top: 2px;
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); background: var(--bg-tertiary);
}
.tl-dot svg { width: 12px; height: 12px; }
.tl-hook { color: var(--success); border-color: rgba(34, 197, 94, .45); }
.tl-drop { color: var(--info); border-color: rgba(14, 165, 233, .45); }
.tl-bad .tl-dot { color: var(--danger); border-color: rgba(239, 68, 68, .5); }

.tl-card {
  background: var(--bg-tertiary); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 12px;
}
.tl-bad .tl-card { border-color: rgba(239, 68, 68, .35); }
.tl-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.tl-kind { font-size: 13.5px; font-weight: 700; }
.tl-when {
  margin-left: auto; font-size: 11.5px; color: var(--text-muted); white-space: nowrap;
}
.tl-where {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-top: 6px; font-size: 12.5px; color: var(--text-secondary);
}
.tl-where svg { width: 12px; height: 12px; color: var(--text-muted); flex: 0 0 12px; }
.tl-where a { color: var(--text-secondary); text-decoration: none; border-bottom: 1px dotted var(--border-light); }
.tl-where a:hover { color: var(--text-primary); }

.tl-checks { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.chk {
  font-size: 10.5px; font-weight: 600; padding: 2px 7px; border-radius: 5px;
  background: var(--bg-elevated); color: var(--text-muted);
}
.chk-ok { color: var(--text-secondary); }
.chk-bad { background: rgba(239, 68, 68, .16); color: var(--danger); }
.chk-none { opacity: .6; }

.tl-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-top: 8px;
  font-size: 11.5px;
}
.tl-foot svg { width: 11px; height: 11px; vertical-align: -1px; margin-right: 3px; }
.tl-flag { color: var(--warning); font-weight: 600; }
.tl-ok { color: var(--success); font-weight: 600; }

@media (max-width: 640px) {
  .tl-when { margin-left: 0; width: 100%; }
}

/* ================================================ arranging the board ====
   The board is grouped by a status order somebody chose, and rows can be
   dragged inside their group. Two orderings, because they answer different
   questions: the group order keeps applying as trailers change status, the
   row order is a hand arrangement within one group. */
.arrange-card { margin-bottom: 16px; }
.arrange-hint { padding: 0 20px; margin: 0 0 10px; font-size: 12.5px; color: var(--text-muted); }
.status-order {
  list-style: none; display: flex; flex-wrap: wrap; gap: 7px;
  margin: 0; padding: 0 20px 16px;
}
.status-chip {
  display: flex; align-items: center; gap: 7px; cursor: grab;
  padding: 6px 12px; border-radius: 8px; font-size: 12.5px; font-weight: 600;
  background: var(--bg-tertiary); border: 1px solid var(--border);
  user-select: none;
}
.status-chip:active { cursor: grabbing; }
.status-chip.dragging { opacity: .45; border-color: var(--accent); }
.status-chip .grip, .row-grip { color: var(--text-muted); font-size: 12px; letter-spacing: -1px; }

.row-grip {
  display: inline-block; margin-right: 7px; cursor: grab;
  padding: 2px 1px; touch-action: none;      /* or the page scrolls instead */
}
.row-grip:active { cursor: grabbing; }
tbody.is-dragging { cursor: grabbing; }
tbody.is-dragging tr { user-select: none; }
tr.dragging td { background: var(--bg-elevated); }
tr.dragging { outline: 1px solid var(--accent); }

/* A group heading inside the table: the status, and how many are in it. */
.group-row td {
  padding: 9px 16px 6px; background: var(--bg-primary);
  border-bottom: 1px solid var(--border);
}
.group-name {
  font-size: 11px; font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-secondary);
}
.group-count {
  margin-left: 7px; padding: 1px 7px; border-radius: 9px;
  background: var(--bg-elevated); color: var(--text-muted);
  font-size: 10.5px; font-weight: 700;
}

.arrange-blocked {
  margin: 0; padding: 10px 20px; font-size: 12.5px; color: var(--warning);
  border-top: 1px solid var(--border);
}
.arrange-blocked[hidden] { display: none; }

/* Saved, or not. A row that says it moved when the server never heard is
   worse than no feedback at all. */
.just-saved { animation: saved-flash .7s ease; }
.save-failed { outline: 1px solid var(--danger) !important; }
@keyframes saved-flash {
  0% { background: rgba(34, 197, 94, .22); }
  100% { background: transparent; }
}

/* The road the search followed, named above the results. Amber when the line
   is our straight-line stand-in rather than the real road, because the
   distances then mean something weaker and the page should say so. */
.route-note {
  padding: 9px 12px; border-bottom: 1px solid var(--border);
  background: rgba(59, 130, 246, .08);
}
.route-note.is-rough { background: rgba(234, 179, 8, .1); }
.route-line { display: flex; align-items: center; gap: 7px; font-size: 12.5px; }
.route-line svg { width: 13px; height: 13px; color: var(--accent); flex: 0 0 13px; }
.route-note.is-rough .route-line svg { color: var(--warning); }
.route-note .hint { display: block; margin-top: 3px; font-size: 11px; line-height: 1.45; }
/* The mileage a shop asks for, next to the VIN. Dated, because a reading
   nobody can place gets quoted against as though it were today's. */
.unit-odo {
  display: inline-flex; align-items: baseline; gap: 5px;
  font-size: 12px; font-weight: 600; color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.unit-odo em { font-style: normal; font-size: 10.5px; font-weight: 500; color: var(--text-muted); }
.empty-actions { display: flex; gap: 8px; justify-content: center; margin-top: 10px; }

/* ---------- Component suggestions on a work order ----------
   A suggestion has to look like a suggestion. These sit on a work order
   beside the money, and nothing in them is part of the unit's history until
   somebody presses Confirm - so a confirmed one changes colour and loses its
   buttons rather than staying an editable-looking row that is now a fact. */
.proposal {
  border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 10px; padding: 12px 14px; margin-bottom: 12px;
  background: var(--bg-tertiary);
}
.proposal.is-confirmed { border-left-color: var(--success, #2f9e57); opacity: .92; }
.proposal-head { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.proposal-evidence { list-style: none; margin: 8px 0; padding: 0; }
.proposal-evidence li {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 4px 0; font-size: 13px; border-bottom: 1px dashed var(--border);
}
.proposal-evidence .money { white-space: nowrap; color: var(--text-secondary); }
.proposal .field-grid {
  display: grid; gap: 10px; margin: 10px 0;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
.proposal .field-grid label,
.proposal-manual .field-grid label {
  display: flex; flex-direction: column; gap: 4px;
  font-size: 11px; color: var(--text-muted);
}
.proposal-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
.proposal .warn-note {
  margin: 8px 0; padding: 8px 10px; border-radius: 8px; font-size: 12px;
  background: rgba(224, 138, 30, .12); border: 1px solid var(--border);
}
.pill.warn { background: rgba(224, 138, 30, .18); }
.pill.ok { background: rgba(47, 158, 87, .18); }
.proposal-manual { margin-top: 6px; }
.proposal-manual summary { cursor: pointer; font-size: 13px; }
.proposal-manual .field-grid {
  display: grid; gap: 10px; margin: 10px 0;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}

/* ---------- Visit timeline: the daily actions panel ----------
   A <details> rather than a dialog, so opening it is one click, closing it
   is one click, and it works with JavaScript off. The normal path is two
   clicks total: open the panel, press Confirm. */
.wo-panel { margin: 0 0 10px; }
.wo-panel > summary { list-style: none; cursor: pointer; }
.wo-panel > summary::-webkit-details-marker { display: none; }
.wo-panel-body {
  margin-top: 10px; padding: 12px; border: 1px solid var(--border);
  border-radius: 10px; background: var(--surface-2, rgba(127,127,127,.06));
  display: flex; flex-direction: column; gap: 12px;
}
.wo-field { display: flex; flex-direction: column; gap: 4px; border: 0; padding: 0; margin: 0; }
.wo-field > span:first-child, .wo-field > legend {
  font-size: 12px; color: var(--text-muted); padding: 0;
}
.wo-field input[type="text"], .wo-field input[type="date"],
.wo-field input[type="time"], .wo-field select {
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); color: var(--text); font-size: 14px;
}
.wo-check {
  display: flex; align-items: center; gap: 8px; font-size: 14px;
  padding: 3px 0; cursor: pointer;
}
.wo-check input { flex: none; }
.wo-when { display: flex; gap: 10px; flex-wrap: wrap; }
.wo-when > label { display: flex; flex-direction: column; gap: 4px; flex: 1 1 120px; }
.wo-when-note { flex: 1 0 100%; margin: 0; }
.wo-when input { width: 100%; }
.wo-when input[type="date"], .wo-when input[type="time"] {
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-secondary); color: var(--text-primary); font-size: 14px;
}

/* ---------- The split button that records an event ----------
   Ninety per cent of the control is the answer people give ninety per cent
   of the time - it happened NOW - and pressing it posts, full stop. The
   caret is the other ten: a <details>, so it opens with one click, closes
   with one click, and still opens with JavaScript off. The panel is
   positioned against .wo-go rather than the caret so it drops the full
   width of the card instead of a thumb-wide sliver. */
.wo-go { position: relative; margin-top: 12px; }
.wo-go + .wo-go { margin-top: 8px; }
.wo-go-bar { display: flex; gap: 4px; align-items: stretch; }
.wo-go-main { flex: 1 1 auto; min-width: 0; justify-content: center; }
.wo-go-drop { flex: 0 0 auto; position: static; display: flex; }
.wo-go-more {
  list-style: none; cursor: pointer; display: flex; align-items: center;
  justify-content: center; width: 34px; padding-left: 0; padding-right: 0;
}
.wo-go-more::-webkit-details-marker { display: none; }
.wo-go-more svg { width: 14px; height: 14px; transition: transform .15s; }
.wo-go-drop[open] .wo-go-more svg { transform: rotate(180deg); }
.wo-go-note { font-size: 11.5px; color: var(--text-muted); margin: 0 0 6px; line-height: 1.45; }
.wo-go-panel {
  position: absolute; z-index: 40; left: 0; top: calc(100% + 6px);
  /* Wider than the card it hangs off, on purpose. A stat card is about
     250px and a day, a time, a mileage and a fault list do not fit in
     that - they wrap into something nobody can read. */
  width: 300px; max-width: calc(100vw - 32px);
  padding: 12px; border-radius: 10px;
  border: 1px solid var(--border-light); background: var(--bg-secondary);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .45);
  display: flex; flex-direction: column; gap: 12px;
}
/* A tick and its explanation are two lines, not one run-on sentence. */
.wo-go-panel .wo-check { flex-wrap: wrap; }
.wo-go-panel .wo-check .hint { flex: 1 0 100%; padding-left: 24px; }
.wo-go-panel legend .hint { display: block; }
/* The card holds controls now, so it must not lift away under the cursor
   while somebody is reaching for one. */
.stat-card--metric:hover { transform: none; }
/* The two metric cards are half again as tall as a card holding one fact,
   and a stretched grid row makes SHOP into a tall empty box beside them.
   Cards size to their own content on this page. */
/* One row, one height. The cards were sized to their own content for a
   while, which left a ragged row of six different boxes - the grid
   stretches them again, and the action is pushed to the BOTTOM of its card
   so the two buttons line up with each other rather than floating at
   whatever height their card's text happened to end at. */
.stat-card--metric { display: flex; flex-direction: column; }
.stat-card--metric .wo-go { margin-top: auto; padding-top: 12px; }
/* Below the two-column breakpoint a metric card is about 150px wide and
   "Repairs done now" wraps onto three lines beside a caret. The two cards
   carrying an action take the full width instead - they are the reason
   somebody opened the page on a phone. */
@media (max-width: 768px) {
  .stat-card--metric { grid-column: 1 / -1; }
}

/* On a phone the quick choices stack rather than wrapping into an unreadable
   row, and the inputs take the full width so they can actually be tapped. */
@media (max-width: 560px) {
  .wo-when { flex-direction: column; gap: 8px; }
  .wo-field input, .wo-field select { width: 100%; }
  .wo-panel > summary { display: block; width: 100%; text-align: center; }
  /* A dropdown pinned to a 300px card is a dropdown nobody can fill in on
     a phone, so at this width it spans the card and the panel scrolls. */
  .wo-go-panel { width: calc(100vw - 32px); max-height: 70vh; overflow-y: auto; }
}

/* The two duration columns on the work-order list. Narrow, but never
   hidden on a phone: a column that disappears at 560px is a metric the
   person on the yard floor never sees. They fold under the row instead. */
/* width:1% in a table means "as narrow as the content allows" - these two
   hold "3d 7h" and want none of the room the service column needs. */
.col-time { white-space: nowrap; font-variant-numeric: tabular-nums; width: 1%; }
/* A row that opens something says so before it is clicked. */
tr[data-open] { cursor: pointer; }
tr[data-open]:hover { background: var(--bg-tertiary); }
/* The work-order number, which is now the link into the row. */
.wo-open { color: var(--text-primary); text-decoration: none; font-weight: 600; }
.wo-open:hover { color: var(--accent); text-decoration: underline; }
@media (max-width: 760px) {
  .col-time { white-space: normal; }
}

/*  A scheduled service that is due on this unit and NOT on this work order.
    Loud on purpose: the means to attach it was a dropdown at the foot of the
    page, and twelve overdue services were closed around it.  */
.wo-maint-warn {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 0 16px 14px;
  padding: 12px 14px;
  border: 1px solid var(--warning);
  border-radius: 10px;
  background: var(--bg-tertiary);
}
.wo-maint-warn .ico { flex: 0 0 auto; }
.wo-maint-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.wo-maint-list li {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
@media (max-width: 720px) {
  .wo-maint-warn { flex-direction: column; }
}

/* ---------- Office board ----------
   Reasons are chips, and a reason with a page behind it is a link. A warning is
   the same chip drawn quieter - dashed and muted - because it is something
   that would block the truck at home and does not where it is. */
.office-tabs { flex-wrap: wrap; }
.icon-muted { background: var(--bg-tertiary); color: var(--text-muted); }
.reason-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.reason-chip {
  display: inline-block; padding: 2px 9px; border-radius: 12px;
  font-size: 12px; font-weight: 500; text-decoration: none;
  color: var(--text-primary); background: var(--bg-tertiary);
  border: 1px solid var(--border-light);
}
a.reason-chip:hover { border-color: var(--accent); color: var(--accent); }
.reason-chip.is-hold { background: var(--warning-bg); border-color: var(--warning); color: var(--warning); }
.reason-chip.is-warning {
  background: transparent; border-style: dashed; border-color: var(--border);
  color: var(--text-muted); font-weight: 400;
}
.hold-form { display: flex; gap: 6px; align-items: center; margin: 0; }
.hold-form .picker-filter { flex: 0 1 12rem; min-width: 8rem; }
