/* =========================================================================
   FVST Express — Admin (dispatch back-office) mockup stylesheet
   Static, presentation-only. Shared across every page in /mockup.
   Compact density — spacing scale ported from temp/backend-min.
   ========================================================================= */

:root {
  --color-bg: #10131a;
  --color-surface: #1a1e28;
  --color-surface-alt: #212633;
  --color-border: #2b3140;
  --color-border-strong: #3a4152;
  --color-text: #ffffff;
  --color-text-muted: #d6ddeb;
  --color-text-faint: #a8b0c2;

  --color-accent: #5b8bf5;
  --color-accent-hover: #7ba0f7;
  --color-accent-soft: #1e2c4d;

  --color-success: #3ec97a;
  --color-success-soft: #16301f;
  --color-warning: #e0a63e;
  --color-warning-soft: #3a2c11;
  --color-danger: #f0685c;
  --color-danger-soft: #3d1f1c;
  --color-neutral-soft: #262c3a;
  --color-purple: #b299f5;
  --color-purple-soft: #2a2545;
  --color-route-5: #35b8c2;
  --color-route-5-soft: #123338;
  --color-route-6: #e668c9;
  --color-route-7: #f2994a;
  --color-route-8: #4bd8d8;
  --color-route-9: #c9d94a;
  --color-route-10: #8c7ae6;
  --color-route-11: #e0729c;
  --color-route-12: #c9975c;
  --color-route-13: #5ce0a8;
  --color-route-14: #e0b45c;
  --color-route-15: #5ca8e0;
  --color-route-16: #cf8ee0;
  --color-route-17: #9ecf5c;
  --color-route-18: #e05c72;
  --color-route-19: #8e72e0;

  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.55);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --sidebar-width: 165px;
  --topbar-height: 44px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
}

body {
  font-family: var(--font);
  background: var(--color-bg);
  color: var(--color-text);
  font-size: 13.5px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4 { line-height: 1.25; margin: 0 0 6px; font-weight: 600; }
h1 { font-size: 1.35rem; }
h2 { font-size: 1.1rem; }
h3 { font-size: 0.95rem; }
p { margin: 0 0 8px; color: var(--color-text-muted); }

/* =========================================================================
   Buttons
   ========================================================================= */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  line-height: 1.3;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.btn:hover { text-decoration: none; }

.btn-primary {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
.btn-primary:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); }

.btn-secondary {
  background: var(--color-surface);
  border-color: var(--color-border-strong);
  color: var(--color-text);
}
.btn-secondary:hover { background: var(--color-neutral-soft); }

.btn-outline {
  background: transparent;
  border-color: var(--color-accent);
  color: var(--color-accent);
}
.btn-outline:hover { background: var(--color-accent-soft); }

.btn-danger {
  background: var(--color-surface);
  border-color: var(--color-danger);
  color: var(--color-danger);
}
.btn-danger:hover { background: var(--color-danger-soft); }

.btn-block { width: 100%; }
.btn-sm { padding: 2px 8px; font-size: 11.5px; border-radius: var(--radius-sm); }

.btn-group { display: flex; gap: 6px; flex-wrap: wrap; }

/* =========================================================================
   Forms
   ========================================================================= */

.form-group { margin-bottom: 12px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.form-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
@media (max-width: 640px) { .form-row, .form-row-3 { grid-template-columns: 1fr; } }

label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 4px;
  color: var(--color-text);
}
.label-hint { font-weight: 400; color: var(--color-text-faint); }

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="search"],
input[type="date"],
input[type="time"],
select,
textarea {
  width: 100%;
  font-family: inherit;
  font-size: 13px;
  color: var(--color-text);
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 5px 10px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-accent-soft);
}
textarea { resize: vertical; min-height: 64px; }

.checkbox-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--color-text);
}
.checkbox-row input { width: auto; }
.checkbox-row label { margin: 0; font-weight: 400; }

.form-help { font-size: 11.5px; color: var(--color-text-faint); margin-top: 4px; }

.form-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 6px;
}

.field-static {
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  background: var(--color-surface-alt);
  border: 1px dashed var(--color-border-strong);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  color: var(--color-text-muted);
  word-break: break-all;
}

fieldset { border: none; padding: 0; margin: 0 0 16px; }
fieldset legend {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-faint);
  padding: 0 0 6px;
  width: 100%;
  border-bottom: 1px solid var(--color-border);
  margin-bottom: 10px;
}

/* =========================================================================
   Cards
   ========================================================================= */

.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.card-header {
  padding: 8px 14px;
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.card-header h2, .card-header h3 { margin: 0; }
.card-header p { margin: 2px 0 0; }
.card-header-title { display: flex; align-items: center; gap: 8px; }
.card-collapse-toggle {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-faint);
  font-size: 13px;
  line-height: 1;
  padding: 2px 4px;
  transition: transform 0.15s ease;
}
.card-collapse-toggle:hover { color: var(--color-text); }
.card.collapsed .card-body { display: none; }
.card.collapsed .card-collapse-toggle { transform: rotate(-90deg); }
.card-body { padding: 14px; }
.card-footer {
  padding: 8px 14px;
  border-top: 1px solid var(--color-border);
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.card-stack { display: flex; flex-direction: column; gap: 12px; }
.card-stack[hidden] { display: none; }

/* =========================================================================
   Auth (centered card) layout — login
   ========================================================================= */

.auth-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
}

.auth-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 18px;
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--color-text);
}
.auth-brand-mark {
  width: 30px;
  height: 30px;
  border-radius: 7px;
  background: var(--color-accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
}
.auth-brand small {
  display: block;
  font-weight: 400;
  font-size: 10.5px;
  color: var(--color-text-faint);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 22px;
}
.auth-card h1 { font-size: 1.15rem; margin-bottom: 4px; }
.auth-card .auth-subtitle { margin-bottom: 16px; }

.auth-links {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  text-align: center;
}

.auth-links-inline {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  margin-top: -6px;
  margin-bottom: 12px;
}

.auth-footer-link {
  margin-top: 16px;
  font-size: 12px;
  color: var(--color-text-faint);
}

/* =========================================================================
   App shell — sidebar + topbar
   ========================================================================= */

.admin-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: var(--sidebar-width);
  flex-shrink: 0;
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
  padding: 0 8px 14px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
/* Positioned inside the sidebar's own box, not straddling the border — overflow-y:auto
   above implicitly makes overflow-x auto too, which would clip a handle hanging outside. */
.sidebar-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  width: 6px;
  height: 100%;
  cursor: col-resize;
  z-index: 10;
}
.sidebar-resize-handle:hover, .sidebar-resize-handle.dragging { background: var(--color-accent-soft); }
.sidebar.collapsed .sidebar-resize-handle { display: none; }
.sidebar-brand-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  padding: 10px 6px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--color-border);
}
.sidebar .brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  color: var(--color-text);
  font-size: 13px;
  min-width: 0;
}
.sidebar-collapse-toggle {
  flex-shrink: 0;
  width: 20px; height: 20px;
  background: none;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text-faint);
  font-size: 11px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.sidebar-collapse-toggle:hover { color: var(--color-text); border-color: var(--color-accent); }

/* Collapsed = a narrow rail with just the brand mark + toggle; every label and nav
   item hides, but the sidebar stays a flex child so it doesn't overlap admin-main. */
.sidebar.collapsed { width: 40px; padding: 0 4px 14px; }
.sidebar.collapsed .sidebar-brand-row { flex-direction: column; gap: 8px; border-bottom: none; padding: 10px 0 0; }
.sidebar.collapsed .brand-text,
.sidebar.collapsed .sidebar-section-label,
.sidebar.collapsed .sidebar-nav { display: none; }
.sidebar .brand-mark {
  width: 24px; height: 24px;
  border-radius: 6px;
  background: var(--color-accent);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700;
}
.sidebar-section-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  padding: 10px 6px 3px;
}
.sidebar-nav { display: flex; flex-direction: column; gap: 1px; }
.sidebar-nav a {
  display: flex;
  align-items: center;
  padding: 5px 6px 5px 14px;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  font-weight: 500;
  font-size: 12.5px;
}
.sidebar-nav a:hover { background: var(--color-neutral-soft); text-decoration: none; color: var(--color-text); }
.sidebar-nav a.active { background: var(--color-accent-soft); color: var(--color-accent); font-weight: 600; }

.admin-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* Opt-in: lets a page's .page-wrap stretch to fill the remaining viewport
   height below the topbar (instead of shrink-wrapping its content), so a
   flex:1 child further down (e.g. dashboard.html's map row) can grow into
   whatever vertical space the page actually has. */
.page-wrap-fill { flex: 1; width: 100%; display: flex; flex-direction: column; min-height: 0; }

.admin-topbar {
  height: var(--topbar-height);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 14px;
  position: sticky;
  top: 0;
  z-index: 20;
}
.admin-topbar h1 { font-size: 0.92rem; margin: 0; }

.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  cursor: pointer;
  color: var(--color-text);
}

/* Topbar alerts bell — links out to alerts.html; badge count is a static mockup
   number (no shared backend/localStorage to keep it live across pages). */
.topbar-alert-btn {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-size: 15px;
  text-decoration: none;
}
.topbar-alert-btn:hover { background: var(--color-neutral-soft); text-decoration: none; }
.topbar-alert-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  background: var(--color-danger);
  color: #fff;
  font-size: 9.5px;
  font-weight: 700;
  min-width: 15px;
  height: 15px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  border: 2px solid var(--color-surface);
}

/* User account dropdown */
.user-menu { position: relative; }
.user-menu-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 3px 8px;
  cursor: pointer;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--color-text);
}
.user-menu-btn:hover { background: var(--color-neutral-soft); }
.avatar {
  width: 23px; height: 23px;
  border-radius: 50%;
  background: var(--color-accent-soft);
  color: var(--color-accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 700;
  flex-shrink: 0;
}
.user-menu-dropdown {
  display: none;
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 190px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 4px;
  z-index: 30;
}
.user-menu.open .user-menu-dropdown { display: block; }
.user-menu-dropdown .menu-label {
  padding: 6px 10px 3px;
  font-size: 10.5px;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.user-menu-dropdown a {
  display: block;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-size: 12.5px;
  font-weight: 500;
}
.user-menu-dropdown a:hover { background: var(--color-neutral-soft); text-decoration: none; }
.user-menu-dropdown .divider { height: 1px; background: var(--color-border); margin: 4px 4px; }
.user-menu-dropdown a.danger { color: var(--color-danger); }

.page-wrap {
  /* Fills available width (viewport minus sidebar) up to a generous cap — was a flat
     1280px regardless of screen size, leaving a large dead zone on anything wider than
     a laptop (e.g. a 1920px monitor). 1800px still stops it from stretching absurdly
     wide on ultrawide displays. */
  width: 100%;
  max-width: 1800px;
  margin: 0 auto;
  padding: 16px 24px 32px;
  box-sizing: border-box;
}
.page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.page-header p { margin: 2px 0 0; }
.info-toggle {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  width: 18px;
  height: 18px;
  line-height: 1;
  font-size: 11px;
  color: var(--color-text-faint);
  cursor: pointer;
  vertical-align: middle;
  margin-left: 4px;
}
.info-toggle:hover, .info-toggle[aria-expanded="true"] { color: var(--color-accent); border-color: var(--color-accent); }
.page-info-text { max-width: 640px; }

/* =========================================================================
   Stats / summary cards
   ========================================================================= */

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
  margin-bottom: 14px;
}
.stat-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 12px;
}
.stat-card .stat-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-text-faint);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.stat-card .stat-value {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--color-text);
}
.stat-card .stat-sub {
  font-size: 11px;
  color: var(--color-text-faint);
  margin-top: 2px;
}
a.stat-card:hover { border-color: var(--color-accent); box-shadow: var(--shadow-md); }
.stat-grid-compact { gap: 8px; }
.stat-grid-compact .stat-card {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 12px;
  white-space: nowrap;
}
.stat-grid-compact .stat-label { margin-bottom: 0; font-size: 10px; line-height: 1; flex-shrink: 0; }
.stat-grid-compact .stat-value { font-size: 1.05rem; line-height: 1; flex-shrink: 0; }
.stat-grid-compact .stat-sub { margin-top: 0; margin-left: auto; font-size: 10px; line-height: 1; flex-shrink: 0; }
@media (max-width: 700px) {
  .stat-grid-compact .stat-card { flex-wrap: wrap; }
  .stat-grid-compact .stat-sub { margin-left: 0; }
}

/* =========================================================================
   Tables
   ========================================================================= */

.table-wrap {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow-x: auto;
}
table { width: 100%; border-collapse: collapse; font-size: 12.5px; min-width: 640px; }
table.table-tight { min-width: 0; }
.tier-window-input { max-width: 90px; display: inline-block; }
.tier-window-hint { margin-left: 6px; font-size: 11px; color: var(--color-text-faint); }
thead th {
  text-align: left;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-faint);
  padding: 3px 8px;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface-alt);
  white-space: nowrap;
}
tbody td {
  padding: 3px 8px;
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text);
  vertical-align: middle;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--color-surface-alt); }
.cell-muted { color: var(--color-text-faint); }
.shift-cell { display: flex; flex-direction: column; gap: 2px; padding: 4px 10px; }
.shift-chip {
  font-size: 11px;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: var(--radius-sm);
  background: var(--color-accent-soft);
  color: var(--color-accent);
  white-space: nowrap;
  width: fit-content;
}
/* In the week-grid (driver-shifts.html), each chip is its own clickable shift — style it
   to match the plain single-shift cells next to it (accent color there reads as a stray
   "selected/primary" cue, not "click me"), same hover affordance as td[data-shift]. */
.shift-cell .shift-chip { background: var(--color-neutral-soft); color: var(--color-text); }
.shift-cell .shift-chip[data-shift]:hover { background: var(--color-surface-alt); }
.cell-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11.5px; }
.row-actions { display: flex; gap: 4px; flex-wrap: wrap; }

/* Click-to-edit $ cells (pricing-grid.html) */
td[data-editable-cell] { cursor: pointer; border-radius: var(--radius-sm); }
td[data-editable-cell]:hover { background: var(--color-accent-soft); }
td[data-editable-cell].editing { padding: 3px 4px; cursor: default; }
td[data-editable-cell].editing:hover { background: none; }
.editable-cell-input {
  width: 64px;
  font-size: 12.5px;
  padding: 2px 5px;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-text);
}

/* =========================================================================
   Badges / status pills
   ========================================================================= */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.badge-success { background: var(--color-success-soft); color: var(--color-success); }
.badge-warning { background: var(--color-warning-soft); color: var(--color-warning); }
.badge-danger { background: var(--color-danger-soft); color: var(--color-danger); }
.badge-neutral { background: var(--color-neutral-soft); color: var(--color-text-muted); }
.badge-accent { background: var(--color-accent-soft); color: var(--color-accent); }
.badge-purple { background: var(--color-purple-soft); color: var(--color-purple); }
.badge-outline { background: transparent; border: 1px solid var(--color-border-strong); color: var(--color-text-faint); }

/* Order status badge helpers (canonical OrderStatus enum, §3.1) */
.badge-status-received { background: var(--color-accent-soft); color: var(--color-accent); }
.badge-status-pending { background: var(--color-neutral-soft); color: var(--color-text-muted); }
.badge-status-assigned { background: var(--color-neutral-soft); color: var(--color-text-muted); }
.badge-status-pickingup { background: var(--color-purple-soft); color: var(--color-purple); }
.badge-status-pickedup { background: var(--color-accent-soft); color: var(--color-accent-hover); }
.badge-status-intransit { background: var(--color-accent-soft); color: var(--color-accent); }
.badge-status-delivered { background: var(--color-success-soft); color: var(--color-success); }
.badge-status-failed { background: var(--color-danger-soft); color: var(--color-danger); }
.badge-status-cancelled { background: transparent; border: 1px solid var(--color-border-strong); color: var(--color-text-faint); }

/* =========================================================================
   Pagination
   ========================================================================= */

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 10px;
  border-top: 1px solid var(--color-border);
}
.pagination a, .pagination span {
  min-width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: 600;
  color: var(--color-text-muted);
}
.pagination a:hover { background: var(--color-neutral-soft); text-decoration: none; }
.pagination .current { background: var(--color-accent); color: #fff; }
.pagination .disabled { color: var(--color-text-faint); opacity: 0.5; }

/* Real (functional) pagination — see initPagination() in app.js. A row hidden by
   this class is windowed out of the current page; a row hidden by the filter's
   own inline display:none is excluded from the filtered set entirely. Both can
   apply to the same table without conflicting since they use different mechanisms. */
.pg-hidden { display: none !important; }
.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 4px;
  border-top: 1px solid var(--color-border);
  flex-wrap: wrap;
}
.pagination-bar .inline-field { flex-shrink: 0; }

/* =========================================================================
   Alerts / neutral confirmation banners
   ========================================================================= */

.alert {
  border-radius: var(--radius-md);
  padding: 8px 12px;
  font-size: 12.5px;
  margin-bottom: 12px;
  border: 1px solid transparent;
}
.alert-info { background: var(--color-accent-soft); color: var(--color-accent-hover); border-color: var(--color-accent-soft); }
.alert-success { background: var(--color-success-soft); color: var(--color-success); }
.alert-warning { background: var(--color-warning-soft); color: var(--color-warning); }
.alert-danger { background: var(--color-danger-soft); color: var(--color-danger); }

/* =========================================================================
   Filter bar
   ========================================================================= */

.filter-bar {
  display: grid;
  grid-template-columns: repeat(4, 1fr) auto;
  gap: 8px;
  align-items: end;
  margin-bottom: 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 8px 10px;
  box-shadow: var(--shadow-sm);
}
.filter-bar .form-group { margin-bottom: 0; }
@media (max-width: 900px) {
  .filter-bar { grid-template-columns: 1fr 1fr; }
}

/* =========================================================================
   Sortable columns + inline filter row (generic table sort/filter)
   ========================================================================= */

/* Clickable sortable headers, with a chevron showing the current sort state */
thead th[data-sort-key] {
  cursor: pointer;
  user-select: none;
  padding-right: 18px;
  position: relative;
}
thead th[data-sort-key]:hover { color: var(--color-text-muted); }
thead th[data-sort-key]:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
thead th[data-sort-key]::after {
  content: "\2195"; /* ↕ — unsorted */
  position: absolute;
  right: 5px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 9px;
  line-height: 1;
  opacity: 0.3;
}
thead th[data-sort-key][aria-sort="ascending"]::after { content: "\25B2"; opacity: 1; color: var(--color-accent); }
thead th[data-sort-key][aria-sort="descending"]::after { content: "\25BC"; opacity: 1; color: var(--color-accent); }

/* Second <tr> inside <thead> holding one compact filter control per column */
thead tr.filter-row th {
  padding: 3px 8px;
  background: var(--color-surface);
  border-bottom: 2px solid var(--color-border-strong);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  vertical-align: middle;
}
thead tr.filter-row input,
thead tr.filter-row select {
  width: 100%;
  min-width: 0;
  font-size: 11.5px;
  padding: 3px 6px;
  border-radius: var(--radius-sm);
}
thead tr.filter-row input::placeholder { color: var(--color-text-faint); }

/* Slim toolbar above a table, for controls that don't map to a single column
   (date ranges, report period selectors) */
.table-toolbar {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 8px 10px;
  box-shadow: var(--shadow-sm);
}
.table-toolbar .form-group { margin-bottom: 0; }
.table-toolbar .toolbar-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-faint);
  align-self: center;
}
.table-toolbar .spacer { margin-left: auto; }
/* Label beside its input instead of stacked above it — for toolbar fields (like a
   From/To date pair) where the block-label layout wastes vertical space. */
.inline-field { display: flex; align-items: center; gap: 6px; }
.inline-field label { margin: 0; font-size: 12px; font-weight: 400; color: var(--color-text-faint); white-space: nowrap; }

/* Empty-state row shown when the active filters match nothing */
tr.table-empty-row td {
  text-align: center;
  color: var(--color-text-faint);
  padding: 18px 10px;
}

/* Soft-deleted / archived row — record retained, visually de-emphasized */
tr.row-archived { opacity: 0.55; }
tr.row-archived td:not(.row-actions) { font-style: italic; }

/* Briefly highlights a row that was just scrolled to via a #fragment link (e.g. a
   recurring-rule row reached from an All Shifts "↻ Recurring" link). The transition lives
   on the row itself (not just .row-flash) so removing the class fades smoothly back out. */
.table-wrap tbody tr { transition: background 1.4s ease; }
tr.row-flash { background: var(--color-accent-soft); }

/* =========================================================================
   Config sections
   ========================================================================= */

.config-section {
  margin-bottom: 14px;
}
.config-section .card-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.config-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.config-field .config-field-text { max-width: 60%; }
.config-field .config-field-text label { margin-bottom: 2px; }
.config-field .config-field-text p { margin: 0; font-size: 11.5px; }
.config-field .config-field-control { width: 200px; flex-shrink: 0; }
.config-field .config-field-control input,
.config-field .config-field-control select { width: 100%; }
@media (max-width: 700px) {
  .config-field { flex-direction: column; align-items: stretch; }
  .config-field .config-field-text { max-width: none; }
  .config-field .config-field-control { width: 100%; }
}

/* Toggle switch (fake checkbox) */
.switch {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
  flex-shrink: 0;
}
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background: var(--color-border-strong);
  border-radius: 999px;
  transition: background 0.15s ease;
}
.switch .slider::before {
  content: "";
  position: absolute;
  width: 14px; height: 14px;
  left: 3px; top: 3px;
  background: #fff;
  border-radius: 50%;
  transition: transform 0.15s ease;
  box-shadow: var(--shadow-sm);
}
.switch input:checked + .slider { background: var(--color-accent); }
.switch input:checked + .slider::before { transform: translateX(16px); }

/* =========================================================================
   Map / live tracking widgets
   ========================================================================= */

.map-placeholder {
  position: relative;
  height: 320px;
  border-radius: var(--radius-lg);
  border: 1px dashed var(--color-border-strong);
  /* Real street-map crop (Vancouver/Burnaby/New West/Richmond/Surrey — the same 5
     cities as DELIVERY_ZONES) standing in for actual map tiles. It's one fixed
     image, not a real pannable/zoomable layer, so the existing pin/zone percentage
     coordinates don't correspond to true lat/lng on it — good enough for a mockup,
     but don't treat pin placement against it as geographically exact. */
  background-image: url("../img/map-reference.png");
  background-size: cover;
  background-position: center;
  background-color: var(--color-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-faint);
  font-size: 12.5px;
  overflow: hidden;
}
.map-placeholder .map-caption {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 6px 12px;
  box-shadow: var(--shadow-sm);
  text-align: center;
}
.map-pin {
  position: absolute;
  width: 12px; height: 12px;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  border: 2px solid var(--color-surface);
  box-shadow: var(--shadow-sm);
}
.map-pin.pin-green { background: #1f8a4c; }
.map-pin.pin-blue { background: #3457d5; }
.map-pin.pin-purple { background: #7444c0; }
.map-pin.pin-red { background: #c0392b; }
.map-pin.pin-grey { background: #9aa1ac; }

.map-legend-overlay {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  width: auto;
  max-width: 220px;
}
.map-legend-overlay .card-header { padding: 6px 10px; }
.map-legend-overlay .card-header h3 { font-size: 12.5px; }
.map-legend-overlay .card-body { padding: 8px 10px; }
.map-legend-overlay .legend { flex-direction: column; gap: 6px; }
/* The app-wide ▾/rotate-to-▸ collapse toggle reads ambiguously (as a "+") at this
   card's small size/contrast — an explicit +/− is clearer here, even though it
   diverges from the rest of the app's toggle style. */
.card.map-legend-overlay .card-collapse-toggle {
  font-size: 0;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}
.card.map-legend-overlay .card-collapse-toggle:hover { border-color: var(--color-accent); }
.card.map-legend-overlay .card-collapse-toggle::before {
  content: "−";
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
}
.card.collapsed.map-legend-overlay .card-collapse-toggle { transform: none; }
.card.collapsed.map-legend-overlay .card-collapse-toggle::before { content: "+"; }

.map-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.map-toolbar .day-select { min-width: 170px; }
.pin-count-badges { display: flex; gap: 8px; flex-wrap: wrap; }
.pin-count-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

.legend { display: flex; flex-wrap: wrap; gap: 8px 14px; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--color-text-muted); }
.legend-item.disabled { opacity: 0.5; }
/* Legend entries that double as on/off toggles for that driver's pins/marker. */
button.legend-toggle {
  background: none;
  border: none;
  padding: 2px 4px;
  margin: -2px -4px;
  font: inherit;
  cursor: pointer;
  border-radius: var(--radius-sm);
}
button.legend-toggle:hover { background: var(--color-neutral-soft); }
button.legend-toggle[aria-pressed="false"] { opacity: 0.45; text-decoration: line-through; }
.legend-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.legend-dot.green { background: #1f8a4c; }
.legend-dot.blue { background: #3457d5; }
.legend-dot.purple { background: #7444c0; }
.legend-dot.yellow { background: #d8ab1f; }
.legend-dot.red { background: #c0392b; }
.legend-dot.grey { background: #9aa1ac; }

.status-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; display: inline-block; }
.status-dot.online { background: var(--color-success); }
.status-dot.offline { background: #9aa1ac; }

.driver-list { display: flex; flex-direction: column; }
.driver-list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 12.5px;
}
.driver-list-item:last-child { border-bottom: none; }
.driver-list-item .driver-name { display: flex; align-items: center; gap: 6px; font-weight: 600; }
.driver-list-item .driver-meta { color: var(--color-text-faint); font-size: 11.5px; }

/* Route Map roster & zone list: clicking a row slides in a panel (see .driver-slide-panel
   below) instead of expanding in place — scoped so it doesn't affect the plain
   driver-list-item rows used on Dashboard / Roles / Service Areas. */
[data-driver-roster] .driver-row-head, [data-zone-roster] .driver-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  cursor: pointer;
}
[data-driver-roster] .driver-row-head:hover, [data-zone-roster] .driver-row-head:hover { background: var(--color-neutral-soft); margin: 0 -6px; padding: 0 6px; border-radius: var(--radius-sm); }
[data-driver-roster] .driver-chevron, [data-zone-roster] .driver-chevron { display: inline-block; margin-left: 4px; font-size: 13px; color: var(--color-text-faint); }
[data-driver-roster] .driver-list-item.panel-open .driver-row-head, [data-zone-roster] .driver-list-item.panel-open .driver-row-head { background: var(--color-accent-soft); margin: 0 -6px; padding: 0 6px; border-radius: var(--radius-sm); }

/* Dropping an unallocated order onto a driver row */
[data-driver-roster] .driver-list-item.drag-over { box-shadow: inset 0 0 0 2px var(--color-accent); background: var(--color-accent-soft); border-radius: var(--radius-sm); }
[data-driver-roster] .driver-list-item.drag-invalid { box-shadow: inset 0 0 0 2px var(--color-danger); background: var(--color-danger-soft); border-radius: var(--radius-sm); }
/* Dropping an unallocated order directly onto the open driver panel (now a
   persistent column, so it's a direct drop target too, not just the roster row). */
.driver-slide-panel.drag-over { box-shadow: inset 0 0 0 2px var(--color-accent); }

/* The driver/zone panel — a real 2nd grid column in .mapview-layout (see
   .mapview-layout.panel-open above) when open, not an overlay; hidden entirely
   (display:none, out of grid flow) when closed. align-self:stretch matches its
   height to the row's tallest column (the map) since the grid's own
   align-items:start otherwise only sizes columns to their natural content. */
.driver-slide-panel {
  display: none;
  width: 300px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 14px;
}
.driver-slide-panel.open {
  display: flex;
  flex-direction: column;
  align-self: stretch;
}
/* Header/meta never scroll — only the stop list itself does (flex:1 + its own
   overflow-y below). A position:sticky header inside a single scrolling panel
   turned out fragile in practice (its containing block for stickiness could end
   up being an ancestor other than this panel depending on how tall the panel's
   content grew, so the header ended up stuck mid-list instead of at the true
   top) — this structural fix has no such ambiguity: the close button is simply
   never inside the part that scrolls. */
.driver-slide-panel .dsp-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 4px;
  flex-shrink: 0;
}
.driver-slide-panel .dsp-header h3 { margin: 0; }
.driver-slide-panel .dsp-meta { font-size: 11.5px; color: var(--color-text-faint); margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--color-border); flex-shrink: 0; }
.driver-slide-panel .driver-orders-list { display: flex; flex-direction: column; gap: 4px; flex: 1; overflow-y: auto; min-height: 0; }

.driver-order-row {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  cursor: pointer;
  color: var(--color-text-muted);
  padding: 3px 4px;
  border-radius: var(--radius-sm);
}
.driver-order-row:hover { background: var(--color-neutral-soft); color: var(--color-text); }
.driver-order-row.ro-hover-sibling {
  background: var(--color-accent-soft);
  color: var(--color-text);
  box-shadow: inset 3px 0 0 var(--color-accent), inset 0 0 0 1px var(--color-accent);
  font-weight: 600;
}
.driver-order-row .cell-mono { font-size: 11px; }
.driver-order-row[draggable="true"] { cursor: grab; }
.driver-order-row.dragging { opacity: 0.4; }
.driver-order-row.drag-over { box-shadow: inset 0 0 0 2px var(--color-accent); background: var(--color-accent-soft); }
.ro-drag-handle { cursor: grab; color: var(--color-text-faint); flex-shrink: 0; }
/* Restyled to the shared kanban-card look (queue item) — .driver-order-row stays
   on the element purely for its JS hooks/hover-sibling/drag-state classes above;
   this overrides the box-model properties it would otherwise still contribute
   (flex row / small padding / muted color) so the combined element renders as a
   proper kanban card, not a hybrid of the two styles. */
.kanban-card.driver-order-row {
  display: block;
  cursor: grab;
  color: var(--color-text);
  padding: 7px 9px;
  border-radius: var(--radius-md);
}
.kanban-card.driver-order-row:hover { background: var(--color-neutral-soft); }
.kanban-card.driver-order-row .ro-actions { display: flex; align-items: center; justify-content: space-between; margin-top: 6px; }
.driver-orders-empty { font-size: 11.5px; color: var(--color-text-faint); padding: 2px 4px; }

/* Briefly flashes on a stop row just dropped onto this driver from the unallocated
   pool, so it's easy to spot where it landed in the (possibly long) list. */
.driver-order-row.ro-new-drop {
  animation: ro-new-drop-flash 2s ease-out;
}
@keyframes ro-new-drop-flash {
  0%, 40% { background: var(--color-accent-soft); box-shadow: inset 0 0 0 1px var(--color-accent); }
  100% { background: transparent; box-shadow: none; }
}

/* Zone panel — one row per order that touches the selected zone, click jumps to its
   pickup popover the same way a roster stop row does. */
.zone-order-row { padding: 6px 4px; border-radius: var(--radius-sm); cursor: pointer; }
.zone-order-row:hover { background: var(--color-neutral-soft); }
.zor-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 3px; }
.zor-alloc { margin-bottom: 4px; }
.zor-id-check { display: flex; align-items: center; cursor: pointer; }
.zor-check { width: auto; flex-shrink: 0; margin: 0 5px 0 0; }
.dsp-bulk-allocate { flex-shrink: 0; }
.dsp-bulk-allocate .divider { margin: 10px 0; }
.zone-order-row .kc-legs { font-size: 11px; }
.zone-order-row .zor-leg-out { opacity: 0.5; }
.zor-other-zone { font-style: italic; }
.map-pin.pin-zone-full { outline: 2px solid var(--color-success); outline-offset: 1px; }
.map-pin.pin-zone-partial { outline: 2px dashed var(--color-warning); outline-offset: 1px; }

/* Weekday-pattern picker + "ends never/on date" radio pair — shared by the recurring
   shift builder (shift-recurring-new.html) and the recurring rule edit modal
   (driver-shifts-recurring.html). */
.day-chips { display: flex; gap: 6px; margin-bottom: 12px; }
.day-chip {
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text-muted);
  font-size: 11.5px;
  font-weight: 700;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.day-chip:hover { border-color: var(--color-accent); }
.day-chip.active { background: var(--color-accent); border-color: var(--color-accent); color: #fff; }

.ends-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.ends-row input[type="radio"] { width: auto; flex: none; }
.ends-row label { margin: 0; font-weight: 400; flex-shrink: 0; }
.ends-row input[type="date"], .ends-row input[type="number"] { max-width: 160px; }
.ends-row.is-disabled input:not([type="radio"]) { opacity: 0.45; }

/* Shift day view (driver-shifts-day.html) — Google-Calendar-style single day, one column
   per driver, shift blocks positioned/sized to scale by JS from minutes-of-day. The empty
   space in a column IS the coverage gap — no separate encoding needed for it. */
.daycal-toolbar { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.daycal-toolbar input[type="date"] { max-width: 160px; }
.day-cal { min-width: 680px; }
.day-cal-header { display: flex; }
.day-cal-header .dc-corner { width: 52px; flex-shrink: 0; }
.day-cal-header .dc-driver-head {
  flex: 1;
  min-width: 120px;
  text-align: center;
  font-size: 11.5px;
  font-weight: 600;
  padding: 0 6px 8px;
  border-left: 1px solid var(--color-border);
}
.day-cal-header .dc-driver-head .dc-driver-meta { display: block; font-weight: 400; color: var(--color-text-faint); font-size: 10.5px; margin-top: 1px; }
.day-cal-rows { display: flex; }
.day-cal-time-col { width: 52px; flex-shrink: 0; position: relative; }
.day-cal-time-col .dc-hour-label {
  position: absolute;
  right: 8px;
  left: 0;
  text-align: right;
  font-size: 10px;
  color: var(--color-text-faint);
  transform: translateY(-50%);
}
.day-cal-body { flex: 1; display: flex; position: relative; }
.day-cal-driver-col { flex: 1; min-width: 120px; position: relative; border-left: 1px solid var(--color-border); }
.shift-block {
  position: absolute;
  left: 4px;
  right: 4px;
  border-radius: var(--radius-sm);
  background: var(--color-accent-soft);
  border-left: 3px solid var(--color-accent);
  padding: 3px 6px;
  font-size: 10.5px;
  line-height: 1.3;
  overflow: hidden;
  color: var(--color-text);
}
.shift-block.sb-one-off { background: var(--color-warning-soft); border-left-color: var(--color-warning); }
.shift-block .sb-time { font-weight: 700; display: block; }
.day-cal-empty-note {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  text-align: center;
  font-size: 10.5px;
  color: var(--color-text-faint);
}
.ro-seq {
  flex-shrink: 0;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: var(--color-neutral-soft);
  color: var(--color-text-muted);
  font-size: 9.5px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.ro-unalloc-btn {
  flex-shrink: 0;
  width: 18px; height: 18px;
  font-size: 10px;
  line-height: 1;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-danger);
  border-radius: 3px;
  cursor: pointer;
  padding: 0;
}
.ro-unalloc-btn:hover { background: var(--color-danger-soft); border-color: var(--color-danger); }
.ro-move { flex-shrink: 0; display: flex; flex-direction: column; gap: 1px; }
.ro-move-btn {
  width: 16px; height: 13px;
  font-size: 8px;
  line-height: 1;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text-muted);
  border-radius: 3px;
  cursor: pointer;
  padding: 0;
}
.ro-move-btn:hover:not(:disabled) { background: var(--color-neutral-soft); color: var(--color-text); }
.ro-move-btn:disabled { opacity: 0.3; cursor: not-allowed; }

/* =========================================================================
   Kanban dispatch board
   ========================================================================= */

.kanban-board {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 6px;
}
.kanban-col {
  flex: 1 1 230px;
  max-width: 340px;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  /* No max-height: columns stretch to match whichever column has the longest queue
     (the board's default flex align-items:stretch does this automatically), instead
     of capping at a fixed height and scrolling internally. */
}
.kanban-col-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
  padding: 8px 10px 6px;
  border-bottom: 1px solid var(--color-border);
}
.kanban-col-header .kc-title { font-weight: 700; font-size: 12.5px; display: flex; align-items: center; justify-content: space-between; }
.kanban-col-header .kc-sub { font-size: 11px; color: var(--color-text-faint); margin-top: 1px; }
.kc-lock-toggle {
  flex-shrink: 0;
  width: 22px; height: 22px;
  background: none;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  color: var(--color-text-faint);
  font-size: 12px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.kc-lock-toggle:hover { color: var(--color-text); border-color: var(--color-accent); }
.kc-lock-toggle[aria-pressed="true"] { background: var(--color-accent-soft); color: var(--color-accent); border-color: var(--color-accent); }

/* Locked = pinned to the left edge of the scrolling board; other columns scroll
   underneath/past it. left offset is computed in JS (see initKanbanLock) so multiple
   locked columns stack correctly instead of overlapping at left:0. */
.kanban-col.locked { position: sticky; z-index: 5; box-shadow: var(--shadow-lg); }
.kanban-col-body {
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.kanban-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 7px 9px;
  box-shadow: var(--shadow-sm);
  cursor: grab;
  transition: opacity 0.12s ease;
}
.kanban-card:active { cursor: grabbing; }
.kanban-card.dragging { opacity: 0.4; }
.kanban-card.kc-terminal { cursor: default; opacity: 0.7; }
.kanban-col-body[data-drop-allowed="false"] { cursor: not-allowed; }
.kanban-card .kc-order { font-weight: 700; font-size: 12px; display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.kanban-card .kc-addr { font-size: 11.5px; color: var(--color-text-muted); margin-top: 2px; }
.kanban-card .kc-cust { font-size: 11px; color: var(--color-text-faint); margin-top: 1px; }
.kanban-empty {
  border: 1px dashed var(--color-border-strong);
  border-radius: var(--radius-md);
  padding: 12px 8px;
  text-align: center;
  color: var(--color-text-faint);
  font-size: 11.5px;
}
.workload-strip {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.workload-chip {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 5px 10px;
  box-shadow: var(--shadow-sm);
  font-size: 11.5px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.workload-chip strong { font-size: 12.5px; }

.board-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.segmented {
  display: inline-flex;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.seg-btn {
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--color-text-muted);
  background: var(--color-surface);
  border: none;
  padding: 5px 10px;
  cursor: pointer;
  border-right: 1px solid var(--color-border-strong);
}
.seg-btn:last-child { border-right: none; }
.seg-btn:hover { background: var(--color-neutral-soft); }
.seg-btn.active { background: var(--color-accent); color: #fff; }

.kc-vehicle {
  font-size: 11px;
  color: var(--color-text-faint);
  margin-top: 4px;
  padding-top: 4px;
  border-top: 1px dashed var(--color-border);
}

/* Dropoff-only: the delivery deadline, right under the address, so a dispatcher can
   eyeball it against the driver's shift end time without opening the order. */
.kc-deadline { font-size: 11px; color: var(--color-text-faint); margin-top: 2px; }
.kc-deadline.at-risk { color: var(--color-warning); font-weight: 600; }

/* =========================================================================
   Status timeline (order detail)
   ========================================================================= */

.timeline { display: flex; flex-direction: column; }
.timeline-step {
  display: flex;
  gap: 10px;
  position: relative;
  padding-bottom: 14px;
}
.timeline-step:last-child { padding-bottom: 0; }
.timeline-step .ts-marker {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--color-neutral-soft);
  border: 2px solid var(--color-border-strong);
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 9.5px;
  color: var(--color-text-faint);
  z-index: 1;
}
.timeline-step .ts-line {
  position: absolute;
  left: 8px; top: 18px; bottom: -14px;
  width: 2px;
  background: var(--color-border-strong);
}
.timeline-step:last-child .ts-line { display: none; }
.timeline-step .ts-content { padding-top: 0; }
.timeline-step .ts-title { font-weight: 600; font-size: 12.5px; }
.timeline-step .ts-meta { font-size: 11px; color: var(--color-text-faint); margin-top: 1px; }
.timeline-step.done .ts-marker { background: var(--color-success); border-color: var(--color-success); color: #fff; }
.timeline-step.done .ts-line { background: var(--color-success); }
.timeline-step.current .ts-marker { background: var(--color-accent); border-color: var(--color-accent); color: #fff; }
.timeline-step.current .ts-title { color: var(--color-accent); }
.timeline-step.branch .ts-marker { background: var(--color-danger); border-color: var(--color-danger); color: #fff; }
.timeline-step.branch .ts-title { color: var(--color-danger); }
.timeline-step.note .ts-marker { background: var(--color-purple); border-color: var(--color-purple); color: #fff; font-size: 10px; }
.timeline-step.note .ts-title { color: var(--color-purple); }

/* Internal notes card: existing note list + inline add-note form (order-detail-*.html) */
.note-list { display: flex; flex-direction: column; gap: 10px; }
.note-item { font-size: 13.5px; }
.note-item .note-meta { font-size: 11px; color: var(--color-text-faint); margin-bottom: 2px; }
.note-item .note-text { margin: 0; }
.note-list:not(:empty) + .notes-form-wrap { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--color-border); }

/* =========================================================================
   Definition / detail lists
   ========================================================================= */

.dl-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 20px;
}
@media (max-width: 700px) { .dl-grid { grid-template-columns: 1fr; } }
.dl-item .dl-label {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-faint);
  margin-bottom: 2px;
}
.dl-item .dl-value { font-size: 13px; color: var(--color-text); }
.dl-item .dl-value.muted { color: var(--color-text-faint); }

.photo-placeholder {
  width: 100%;
  height: 120px;
  border-radius: var(--radius-md);
  border: 1px dashed var(--color-border-strong);
  background: var(--color-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-faint);
  font-size: 12px;
}

/* =========================================================================
   Section / two-column layout
   ========================================================================= */

.two-col {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 12px;
  align-items: start;
}
@media (max-width: 960px) { .two-col { grid-template-columns: 1fr; } }

/* Dashboard live-map column: stretches to match the "Needs attention"/"Drivers"
   column's height instead of shrink-wrapping the map's own fixed height. */
.dash-two-col { grid-template-columns: 1fr 300px; align-items: stretch; flex: 1; min-height: 0; }
.dash-two-col .card-stack:first-child { display: flex; flex-direction: column; }
.dash-map-card { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.dash-map-body { display: flex; flex-direction: column; flex: 1; min-height: 0; position: relative; }
.dash-map-placeholder { flex: 1; height: auto; min-height: 900px; }

/* Pin content wrapper — pickup/dropoff icon + stop-number badge, counter-rotated so
   it reads upright despite the pin's own -45deg tilt. Reused by any bigger-pin view
   (dashboard live map, route map) that needs an icon + number on its pins; a plain
   .pin-icon nested in here is NOT separately rotated (see .map-pin > .pin-icon). */
.map-pin .pin-face {
  position: absolute;
  inset: 0;
  transform: rotate(45deg);
  display: flex;
  align-items: center;
  justify-content: center;
}
.map-pin .pin-num {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 2px;
  border-radius: 50%;
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  box-shadow: var(--shadow-sm);
  font-size: 10px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Dropoff leg marked with a dashed ring so it's distinguishable even when pins are
   colored by driver (i.e. the icon/dash are the only leg cue in that color scheme). */
.map-pin.pin-type-dropoff { border-style: dashed; }

/* Dashboard live-map pins: bigger than the default .map-pin (~3.5x) so the
   pickup/dropoff icon + stop number inside are legible at a glance. */
.dash-map-placeholder .map-pin { width: 42px; height: 42px; border-width: 4px; }
.dash-map-placeholder .map-pin .pin-icon { font-size: 17px; line-height: 1; }
/* Bigger pins need a bit more clearance so the hover card doesn't overlap them. */
.dash-map-placeholder .pin-info-card { transform: translate(-50%, calc(-100% - 22px)); }
.pin-info-card .pic-response { font-size: 11px; color: var(--color-text-muted); margin-bottom: 8px; }

/* =========================================================================
   Permission matrix (roles)
   ========================================================================= */

.perm-matrix td, .perm-matrix th { text-align: center; }
.perm-matrix td:first-child, .perm-matrix th:first-child { text-align: left; }
.perm-cell-yes { color: var(--color-success); font-weight: 700; }
.perm-cell-no { color: var(--color-text-faint); }

/* =========================================================================
   Utility
   ========================================================================= */

.text-muted { color: var(--color-text-muted); }
.text-faint { color: var(--color-text-faint); }
.text-danger { color: var(--color-danger); }
.text-success { color: var(--color-success); }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.gap-8 { gap: 8px; }
.section-intro { max-width: 680px; margin-bottom: 14px; }
.divider { height: 1px; background: var(--color-border); margin: 14px 0; }
.inline-form { display: inline; }

/* =========================================================================
   Route map / service areas — two-pane map views
   ========================================================================= */

.mapview-layout {
  display: grid;
  grid-template-columns: 300px 1fr;
  gap: 12px;
  align-items: start;
  position: relative;
}
/* The driver/zone slide panel becomes a real 2nd grid column when open (a
   persistent column, not an overlay floating on top of the map) — so the map
   reflows to make room for it and unallocated orders can be dragged straight
   into it, same as any other in-flow panel. */
.mapview-layout.panel-open { grid-template-columns: 300px 300px 1fr; }
.mapview-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.mapview-panel .card-body { max-height: 320px; overflow-y: auto; }
.mapview-main { min-width: 0; }
.mapview-main .map-placeholder { position: relative; }

.map-placeholder-tall { height: 640px; }

.map-svg-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.map-svg-overlay[hidden] { display: none; }
/* non-scaling-stroke keeps this a true, constant 2px regardless of the SVG's
   non-uniform viewBox scaling (viewBox 0 0 100 100 with preserveAspectRatio="none"
   scales x/y independently) — without it, a plain stroke-width in user-space units
   renders at inconsistent apparent thickness depending on a line's angle, which is
   what made lines look unevenly thick before. */
.route-line { fill: none; stroke-width: 2px; vector-effect: non-scaling-stroke; opacity: 1; }
.zone-polygon {
  fill-opacity: 0.2;
  stroke-width: 0.5;
  pointer-events: auto;
  cursor: pointer;
  transition: fill-opacity 0.15s ease, stroke-width 0.15s ease;
}
.zone-polygon:hover { fill-opacity: 0.3; }
.zone-polygon.selected { fill-opacity: 0.42; stroke-width: 1; }
.zone-label {
  position: absolute;
  transform: translate(-50%, -50%);
  font-size: 11.5px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85), 0 0 8px rgba(0, 0, 0, 0.6);
  cursor: pointer;
  white-space: nowrap;
  padding: 2px 4px;
  border-radius: var(--radius-sm);
  transition: background 0.15s ease;
}
.zone-label:hover { background: rgba(0, 0, 0, 0.25); }
.zone-label.selected { background: rgba(0, 0, 0, 0.4); text-decoration: underline; }

/* Driver-identity route colors (distinct from the dashboard task-state pin colors) */
.map-pin.pin-route-1 { background: var(--color-accent); }
.map-pin.pin-route-2 { background: var(--color-success); }
.map-pin.pin-route-3 { background: var(--color-purple); }
.map-pin.pin-route-4 { background: var(--color-warning); }
.map-pin.pin-route-5 { background: var(--color-route-5); }
.map-pin.pin-route-6 { background: var(--color-route-6); }
.map-pin.pin-route-7 { background: var(--color-route-7); }
.map-pin.pin-route-8 { background: var(--color-route-8); }
.map-pin.pin-route-9 { background: var(--color-route-9); }
.map-pin.pin-route-10 { background: var(--color-route-10); }
.map-pin.pin-route-11 { background: var(--color-route-11); }
.map-pin.pin-route-12 { background: var(--color-route-12); }
.map-pin.pin-route-13 { background: var(--color-route-13); }
.map-pin.pin-route-14 { background: var(--color-route-14); }
.map-pin.pin-route-15 { background: var(--color-route-15); }
.map-pin.pin-route-16 { background: var(--color-route-16); }
.map-pin.pin-route-17 { background: var(--color-route-17); }
.map-pin.pin-route-18 { background: var(--color-route-18); }
.map-pin.pin-route-19 { background: var(--color-route-19); }
.map-pin.pin-dim { opacity: 0.55; }
/* Toggled off via the dashboard's pin-legend on/off buttons. */
.map-pin.pin-driver-hidden { display: none; }
.map-pin.pin-selected { outline: 2px solid #fff; outline-offset: 1px; }
/* The paired pickup/dropoff pin for whatever's selected/hovered — the correlation cue for
   when the two legs of one order aren't numbered consecutively. */
.map-pin.pin-sibling { outline: 2px dashed #fff; outline-offset: 2px; }
.map-pin.pin-hover-sibling {
  outline: 3px solid #fff;
  outline-offset: 3px;
  box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.35), var(--shadow-md);
  transform: rotate(-45deg) scale(1.4);
  z-index: 5;
  animation: pin-pulse 0.9s ease-in-out infinite;
}
@keyframes pin-pulse {
  0%, 100% { outline-color: #fff; box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.35), var(--shadow-md); }
  50% { outline-color: var(--color-accent); box-shadow: 0 0 0 6px rgba(91, 139, 245, 0.45), var(--shadow-md); }
}

.map-pin.pin-unassigned {
  background: var(--color-neutral-soft);
  border: 2px dashed var(--color-text-faint);
}
.map-pin .pin-badge {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: rotate(45deg);
  font-size: 8px;
  font-weight: 800;
  color: var(--color-text-faint);
}
.map-pin { cursor: pointer; }

.driver-marker {
  position: absolute;
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  border: 2px solid var(--color-surface);
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  font-size: 9px;
  font-weight: 800;
  color: #fff;
  transform: translate(-50%, -50%);
  cursor: default;
  transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
}
.driver-marker.dim { opacity: 0.55; }
/* Toggled off via the map's pin-legend on/off buttons. */
.driver-marker.dm-hidden { display: none; }
button.driver-marker { cursor: pointer; }
button.driver-marker:hover { filter: brightness(1.15); }
button.driver-marker:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Hovering a driver row in the left roster (Route Map page) glows their marker and
   dims the rest, so it's easy to spot which vehicle on the map is theirs. Skipped for
   markers already showing the "offline/last known position" dim look (.dim) so the
   two dimmed states don't stack into a different, unintended opacity. */
.driver-marker.dm-hover-glow {
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.45), var(--shadow-md);
  transform: translate(-50%, -50%) scale(1.2);
  z-index: 6;
}
.driver-marker.dm-hover-dim { opacity: 0.8; }
/* Same dim treatment extends to that driver's own waypoint/stop pins, so hovering
   a roster row visually isolates their whole route (marker + pins), not just the
   marker. */
.map-pin.dm-hover-dim { opacity: 0.8; }

/* A driver with an active/unresolved route exception (breakdown, collision, etc.)
   blinks a red ring + border on the map so it's impossible to miss. The marker's
   own fill color comes from an inline style (per-driver), which always wins over
   a stylesheet animation — and !important is ignored inside @keyframes anyway —
   so this animates box-shadow/border-color instead of fighting the inline
   background, rather than trying to recolor the marker itself. */
.driver-marker.dm-alert { animation: dm-alert-blink 1.1s ease-in-out infinite; z-index: 8; }
@keyframes dm-alert-blink {
  0%, 100% { box-shadow: 0 0 0 6px rgba(240, 104, 92, 0.75), var(--shadow-sm); border-color: var(--color-danger); }
  50% { box-shadow: 0 0 0 0 rgba(240, 104, 92, 0), var(--shadow-sm); border-color: var(--color-surface); }
}

.tracking-layout { display: grid; grid-template-columns: 1fr 280px; gap: 12px; align-items: start; }
@media (max-width: 900px) { .tracking-layout { grid-template-columns: 1fr; } }
/* Default both sides to a taller ~860px instead of the map's fixed 320px, with the
   driver-status widget's own body scrolling internally if its content overflows
   rather than growing the card past 860px. */
.tracking-layout > .card:first-child { height: 860px; display: flex; flex-direction: column; }
.tracking-layout > .card:first-child > .card-body { flex: 1; display: flex; flex-direction: column; min-height: 0; position: relative; }
.tracking-layout > .card:first-child .map-placeholder { flex: 1; height: auto; }
.tracking-layout [data-driver-widget] { height: 860px; display: flex; flex-direction: column; }
.tracking-layout [data-driver-widget] [data-widget-body] { flex: 1; overflow-y: auto; min-height: 0; }

/* tracking.html's live map now shares dispatch-map.html's exact pin/driver-marker
   styling via the same [data-route-map] attribute on its .map-placeholder (see
   that ruleset) instead of keeping a separate, only-similar-looking size/style
   override here — so the two pages' maps genuinely match, not just resemble
   each other. */

/* Icon glyph centered in a pin (pickup vs. dropoff), counter-rotated the same way
   as .pin-badge/.pin-seq so it reads upright despite the pin's own -45deg tilt.
   Direct-child selector only: pins that wrap their content in .pin-face (dashboard,
   route map) get their counter-rotation from .pin-face instead, so a plain nested
   .pin-icon there isn't rotated a second time. */
.map-pin > .pin-icon {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: rotate(45deg);
  font-size: 7px;
  line-height: 1;
}

/* Instant hover tooltip for the live-tracking map's pins — replaces the native
   title-attribute tooltip (which has a slow, browser-controlled show delay) with
   one that appears immediately on mouseenter. */
.tracking-tooltip {
  position: absolute;
  z-index: 14;
  max-width: 220px;
  pointer-events: none;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 6px 9px;
  transform: translate(-50%, calc(-100% - 16px));
  display: none;
}
.tracking-tooltip.open { display: block; }
.tracking-tooltip .tt-order { font-weight: 700; color: var(--color-text); font-size: 11.5px; }
.tracking-tooltip .tt-leg { font-size: 10.5px; color: var(--color-text-faint); margin: 1px 0 2px; }
.tracking-tooltip .tt-addr { font-size: 11px; color: var(--color-text-muted); }

.route-swatch {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-block;
  border: 1px solid rgba(255, 255, 255, 0.15);
}

.map-popover {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 230px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 10px;
  z-index: 15;
  display: none;
}
.map-popover.open { display: block; }
.map-popover h4 { margin: 0 0 4px; font-size: 12.5px; padding-right: 16px; }
.map-popover .popover-addr { font-size: 11.5px; color: var(--color-text-muted); margin-bottom: 6px; }
.map-popover .popover-driver { font-size: 11px; color: var(--color-text-faint); margin-bottom: 8px; }

/* Small info popup shown when hovering a driver row in the Route Map's roster
   widget — positioned via JS against the hovered row's live bounding rect (the
   roster list scrolls internally, so a plain CSS-only position wouldn't track it). */
.roster-tooltip {
  position: absolute;
  width: 210px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 10px;
  z-index: 30;
}
.roster-tooltip[hidden] { display: none; }
.roster-tooltip .rt-name { font-weight: 700; font-size: 12.5px; margin-bottom: 4px; }
.roster-tooltip .rt-row { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--color-text-muted); margin-bottom: 3px; }
.roster-tooltip .rt-actions { display: flex; gap: 6px; margin-top: 8px; }
.roster-tooltip .rt-actions .btn { flex: 1; }
.map-popover .popover-close {
  position: absolute;
  top: 4px;
  right: 6px;
  background: none;
  border: none;
  color: var(--color-text-faint);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 2px;
}
.map-popover .popover-close:hover { color: var(--color-text); }

.order-pin-card { cursor: pointer; }
.order-pin-card.active { border-color: var(--color-accent); box-shadow: 0 0 0 1px var(--color-accent); }
.order-pin-card[draggable="true"]:active { cursor: grabbing; }

.pkg-count { font-weight: 700; color: var(--color-text); }

/* =========================================================================
   Scrollbars — thin, dark-theme-matched (Firefox + WebKit/Chromium)
   ========================================================================= */

* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border-strong) transparent;
}
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--color-border-strong);
  border-radius: 999px;
  border: 2px solid var(--color-bg);
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--color-text-faint); background-clip: padding-box; }
::-webkit-scrollbar-corner { background: transparent; }

.sidebar::-webkit-scrollbar-thumb {
  border-color: var(--color-surface);
}
.kanban-col-body::-webkit-scrollbar-thumb {
  border-color: var(--color-surface-alt);
}

/* =========================================================================
   Order consolidation — multi-order stops (§3.3)
   A single stop (pickup or dropoff) can carry several orders. These style the
   consolidated stop card on the dispatch board and the multi-order map pin.
   ========================================================================= */

.kanban-card.kc-stop { border-left: 3px solid var(--color-accent); }
.kc-stop-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.kc-stop-loc { font-weight: 700; font-size: 12px; }
.kc-order-list {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.kc-order-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  font-size: 11.5px;
}

/* Multi-order stop count badge on a route-map pin */
.pin-stop-count {
  position: absolute;
  top: -7px;
  right: -7px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
  font-size: 9px;
  font-weight: 800;
  line-height: 13px;
  text-align: center;
  transform: rotate(45deg);
}

/* Multi-order list inside the route-map reassignment popover */
.map-popover .popover-stop { font-size: 11.5px; margin-bottom: 8px; }
.map-popover .popover-stop .ps-head { font-weight: 700; margin-bottom: 3px; }
.map-popover .popover-stop .ps-order {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 2px 0;
}

/* Consolidation callout line on order-detail pages */
.consolidation-note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 12.5px;
}

/* =========================================================================
   Route map — two-waypoint model: sequence badges, leg colors, hover tooltip,
   pickup/dropoff color scheme, and the reusable consolidation modal (Phase 3).
   ========================================================================= */

.map-toolbar-controls {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

/* Pins are generated into this layer so a re-render never clobbers the popover/markers */
.pin-layer { position: absolute; inset: 0; pointer-events: none; }
.pin-layer .map-pin { pointer-events: auto; }

/* Dark, fully-opaque visit-order line, regardless of the active color scheme — a
   semi-transparent white line was nearly invisible against the light real-world
   map image's roads/land, so this uses a solid dark stroke instead. */
.route-line-dark { stroke: #12141c; stroke-linejoin: round; }
/* Toggled off via a pin legend's per-driver on/off buttons (tracking.html). */
.route-line.route-line-hidden { display: none; }

/* Route Map pins: sized for this page's denser layout (many pins, some stacked at
   one address), with a thinner border than the dashboard live-map's version and the
   visual hierarchy flipped — the stop sequence number is the dominant element, the
   pickup/dropoff icon is a small side accent (dashboard live map keeps its own
   icon-first look; this override only applies here). */
[data-route-map] .map-pin { width: 28px; height: 28px; border-width: 2px; }
[data-route-map] .map-pin .pin-num {
  position: static;
  min-width: 0;
  height: auto;
  padding: 0;
  border: none;
  box-shadow: none;
  background: none;
  font-size: 13px;
}
/* No background/border chrome behind the icon — it's a bigger, bold black glyph
   sitting directly on the pin, tucked in tighter to the corner than before. */
[data-route-map] .map-pin .pin-icon {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 0;
  height: auto;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
  font-size: 13px;
  line-height: 1;
  color: #000;
  font-weight: 900;
}
/* Selecting/hovering a pin already gets a clear highlighted outline + pulse
   animation (.pin-hover-sibling, shared base rule) — the extra size-bump it also
   applies is unnecessary noise on this page's denser pin layout, so cancel it here
   without touching that rule for other pages (e.g. driver-day-timeline.html) that
   reuse it and still want the bigger hover state. */
[data-route-map] .map-pin.pin-hover-sibling { transform: rotate(-45deg) scale(1); }

/* Bigger driver markers than the app default, reshaped into the exact same
   teardrop (border-radius + rotate) that .map-pin already uses, instead of a
   plain circle with a separate pointed-tail hack bolted on — that hack's own
   square shape visually clipped across the circle's border and looked broken.
   Using the real pin recipe means the shape's own geometry IS the pointed tail,
   same as every other pin on this page. A black circle badge (not the driver's
   own color) sits inside holding the initials in white, in a counter-rotated
   .dm-face wrapper so it reads upright, exactly like .map-pin's own .pin-face
   pattern. */
[data-route-map] .driver-marker {
  width: 32px;
  height: 32px;
  font-size: 11px;
  border-radius: 50% 50% 50% 0;
  transform: translate(-50%, -50%) rotate(-45deg);
}
[data-route-map] .driver-marker .dm-face {
  position: absolute;
  inset: 0;
  transform: rotate(45deg);
  display: flex;
  align-items: center;
  justify-content: center;
}
[data-route-map] .driver-marker .dm-initials {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #12141c;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  box-shadow: var(--shadow-sm);
}

/* Dashboard live-map pin hover card — business, client, leg type, address, and a
   link through to the order record. Scoped to the dashboard's static pins only. */
.pin-info-card {
  position: absolute;
  z-index: 14;
  width: 220px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 10px;
  transform: translate(-50%, calc(-100% - 14px));
  display: none;
}
.pin-info-card.open { display: block; }
.pin-info-card .pic-header { display: flex; align-items: center; gap: 6px; font-weight: 700; font-size: 12px; margin-bottom: 6px; }
.pin-info-card .pic-avatar {
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--color-accent-soft);
  color: var(--color-accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 800;
  flex-shrink: 0;
}
.pin-info-card .pic-client { font-size: 11.5px; color: var(--color-text-muted); margin-bottom: 4px; }
.pin-info-card .pic-type { font-size: 11px; color: var(--color-text-faint); margin-bottom: 4px; }
.pin-info-card .pic-addr { font-size: 11px; color: var(--color-text-muted); margin-bottom: 8px; }

/* Lightweight hover tooltip */
.map-tooltip {
  position: absolute;
  z-index: 14;
  max-width: 210px;
  pointer-events: none;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: 6px 9px;
  transform: translate(-50%, calc(-100% - 12px));
  display: none;
}
.map-tooltip.open { display: block; }
.map-tooltip .mt-order { font-weight: 700; color: var(--color-text); font-size: 11.5px; }
.map-tooltip .mt-leg { font-size: 10.5px; color: var(--color-text-faint); margin: 1px 0 2px; }
.map-tooltip .mt-addr { font-size: 11px; color: var(--color-text-muted); }

/* Both-legs block inside the reassignment popover */
.popover-legs { margin-bottom: 8px; }
.popover-leg {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 11.5px;
  color: var(--color-text-muted);
  padding: 2px 0;
}
.popover-leg.active { color: var(--color-text); font-weight: 600; }
.popover-leg .pl-tag {
  flex-shrink: 0;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 999px;
  color: #fff;
  background: var(--color-text-faint);
}
.popover-leg .pl-pickup { background: var(--color-warning); }
.popover-leg .pl-dropoff { background: var(--color-accent); }

/* Pickup/Dropoff tags on the unallocated order cards */
.kc-legs { font-size: 11.5px; color: var(--color-text-muted); margin-top: 2px; }
.kc-leg-tag {
  display: inline-block;
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 1px 5px;
  border-radius: 999px;
  color: #fff;
  vertical-align: middle;
}
.kc-leg-pickup { background: var(--color-warning); }
.kc-leg-dropoff { background: var(--color-accent); }

/* Reusable confirm modal (dark card overlay) */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  padding: 20px;
}
.modal-overlay[hidden] { display: none; }
.modal {
  position: relative;
  width: 100%;
  max-width: 380px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 18px 18px 16px;
}
.modal-title { margin: 0 24px 8px 0; font-size: 15px; }
.modal-body { font-size: 13px; color: var(--color-text-muted); line-height: 1.5; margin-bottom: 16px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; }
.modal-close {
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: none;
  color: var(--color-text-faint);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 2px;
}
.modal-close:hover { color: var(--color-text); }

/* =========================================================================
   Global topbar search — sits between the page title and the user menu on
   every page. Submitting GETs the full results page; typing opens a
   type-ahead dropdown (initGlobalSearch() in app.js) backed by a real query
   (AdminSearchController::quick) across Orders/Customers/Drivers.
   ========================================================================= */

.topbar-search {
  position: relative;
  flex: 1 1 auto;
  max-width: 360px;
  margin: 0 auto;
  display: flex;
  align-items: center;
}
.topbar-search .topbar-search-icon {
  position: absolute;
  left: 9px;
  font-size: 11px;
  line-height: 1;
  color: var(--color-text-faint);
  pointer-events: none;
}
.topbar-search input[type="search"] {
  width: 100%;
  padding: 4px 10px 4px 28px;
  font-size: 12.5px;
  background: var(--color-bg);
  border: 1px solid var(--color-border-strong);
  border-radius: 999px;
}
@media (max-width: 640px) { .topbar-search { display: none; } }

.global-search-results {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  max-height: 320px;
  overflow-y: auto;
  z-index: 50;
  padding: 4px;
}
.global-search-results[hidden] { display: none; }
.gsr-group-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-faint);
  padding: 6px 8px 2px;
}
.gsr-item {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 5px 8px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  color: var(--color-text);
}
.gsr-item:hover, .gsr-item.active { background: var(--color-surface-alt); }
.gsr-item-label { font-size: 12.5px; font-weight: 600; }
.gsr-item-sub { font-size: 11px; color: var(--color-text-faint); }
.gsr-empty { padding: 10px 8px; font-size: 12px; color: var(--color-text-faint); }
.gsr-footer {
  padding: 6px 8px 3px;
  font-size: 10.5px;
  color: var(--color-text-faint);
  border-top: 1px solid var(--color-border);
  margin-top: 4px;
}

/* =========================================================================
   Searchable select (initSearchableSelect) — type-ahead front end for any
   [data-searchable-select] <select> that has too many options for a plain
   dropdown to be usable (customer pickers). The <select> itself stays in the
   DOM as the real source of truth, just visually hidden.
   ========================================================================= */

.searchable-select { position: relative; }
.searchable-select-native { display: none; }
.searchable-select-results {
  position: absolute;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  max-height: 220px;
  overflow-y: auto;
  z-index: 40;
  padding: 4px;
}
.searchable-select-results[hidden] { display: none; }
.ss-item { padding: 5px 8px; font-size: 12.5px; cursor: pointer; border-radius: var(--radius-sm); }
.ss-item:hover, .ss-item.active { background: var(--color-surface-alt); }
.ss-empty { padding: 8px; font-size: 12px; color: var(--color-text-faint); }

/* =========================================================================
   Dashboard "Needs attention" panel (D3) — compact list of linked action items
   ========================================================================= */

.attention-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--color-border);
  color: var(--color-text);
  font-size: 12.5px;
  font-weight: 500;
}
.attention-item:last-child { border-bottom: none; }
.attention-item:hover { background: var(--color-surface-alt); text-decoration: none; }
.attention-item .attention-count { flex-shrink: 0; }
.attention-item .attention-text { flex: 1; }
.attention-item .attention-arrow { color: var(--color-text-faint); font-size: 15px; line-height: 1; }

/* =========================================================================
   Dispatch board — right-click context menu + per-column "Reassign all" (§4.2)
   ========================================================================= */

.context-menu {
  position: fixed;
  z-index: 60;
  min-width: 160px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  padding: 4px;
}
.context-menu[hidden] { display: none; }
.context-item {
  display: block;
  width: 100%;
  text-align: left;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--color-text);
  background: none;
  border: none;
  border-radius: var(--radius-sm);
  padding: 6px 10px;
  cursor: pointer;
}
.context-item:hover { background: var(--color-neutral-soft); }
.context-item.context-danger { color: var(--color-danger); }

.reassign-all { margin-top: 6px; }
.reassign-picker {
  display: flex;
  gap: 4px;
  margin-top: 5px;
}
.reassign-picker[hidden] { display: none; }
.reassign-picker .reassign-select { font-size: 11.5px; padding: 3px 6px; }

/* =========================================================================
   Shift conflict summary (shift-new / shift-recurring-new) + occurrence prompt
   ========================================================================= */

.conflict-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.recur-preview {
  margin-top: 8px;
  font-size: 12px;
  color: var(--color-text-muted);
}
.recur-preview .rp-label { color: var(--color-text-faint); }
.recur-preview ul { margin: 4px 0 0; padding-left: 18px; }
.recur-preview li { margin-bottom: 1px; }

.occurrence-choice { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 4px; }
.occurrence-choice label {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-weight: 400;
  margin: 0;
  padding: 8px 10px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.occurrence-choice input { width: auto; margin-top: 2px; }

/* Clickable shift cells on the schedule grid */
td[data-shift] { cursor: pointer; }
td[data-shift]:hover { background: var(--color-surface-alt); }
.shift-chip[data-shift] { cursor: pointer; }
.shift-recurring-mark {
  display: inline-block;
  margin-left: 4px;
  font-size: 9px;
  color: var(--color-text-faint);
  vertical-align: middle;
}

/* Week-grid "+" — one per cell (Off days included), shown on hover/focus so it doesn't
   clutter a grid that's mostly populated already. */
.shift-grid-cell { position: relative; padding-right: 20px; }
.cell-add-btn {
  position: absolute;
  top: 3px; right: 3px;
  width: 15px; height: 15px;
  border-radius: 50%;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface);
  color: var(--color-text-faint);
  font-size: 10px;
  line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.shift-grid-cell:hover .cell-add-btn, .cell-add-btn:focus { opacity: 1; }
.cell-add-btn:hover { color: var(--color-text); border-color: var(--color-accent); }

/* =========================================================================
   Simple CSS bar chart (reports.html order-volume trend) — no chart library
   ========================================================================= */

.bar-chart {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  height: 160px;
  padding: 8px 4px 0;
}
.bar-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 5px;
  height: 100%;
  min-width: 0;
}
.bar-col .bar {
  width: 100%;
  max-width: 46px;
  background: linear-gradient(180deg, var(--color-accent-hover), var(--color-accent));
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  min-height: 3px;
}
.bar-col .bar-value { font-size: 11px; font-weight: 700; color: var(--color-text); }
.bar-col .bar-label { font-size: 10.5px; color: var(--color-text-faint); white-space: nowrap; }

/* =========================================================================
   Shared read-only zone-boundary map on Pricing — colored zones, no
   interactivity beyond the shared-map framing.
   ========================================================================= */

.zone-static-label {
  position: absolute;
  transform: translate(-50%, -50%);
  font-size: 11.5px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85), 0 0 8px rgba(0, 0, 0, 0.6);
  white-space: nowrap;
  pointer-events: none;
}
.zone-static-label small { display: block; font-weight: 600; font-size: 10px; opacity: 0.9; }

/* Disabled look applied to buttons after a one-shot inline action fires */
.btn.is-disabled { opacity: 0.55; pointer-events: none; }

/* =========================================================================
   Responsive: sidebar collapses on narrow screens
   ========================================================================= */

@media (max-width: 860px) {
  .nav-toggle { display: inline-flex; align-items: center; justify-content: center; }
  .admin-shell { flex-direction: column; }
  .sidebar {
    position: fixed;
    left: 0; top: 0; bottom: 0;
    z-index: 40;
    transform: translateX(-100%);
    transition: transform 0.18s ease;
    box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }
  .filter-bar { grid-template-columns: 1fr; }
  .two-col { grid-template-columns: 1fr; }
  .mapview-layout, .mapview-layout.panel-open { grid-template-columns: 1fr; }
}
