/* =========================================================================
   FVST Express — Driver app mockup stylesheet
   Static, presentation-only. Shared across every page in /mockup-driver.
   Mobile-width surface. Reuses the admin mockup's color system (/mockup)
   for cross-app visual consistency — see queue item on this.
   ========================================================================= */

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

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

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

  --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;
  --phone-width: 390px;
  --topbar-height: 52px;
  --bottomnav-height: 58px;
}

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

/* Custom scrollbar, global — every scrollable element in this app, not just
   .app-content, gets the same thin unobtrusive thumb with NO up/down arrow
   buttons. Those arrow buttons are a mouse-era affordance nobody can tap on
   a phone; a real mobile scroll indicator never has them. One shared rule
   here instead of redefining this per scrollable container each time. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--color-border-strong) transparent;
}
*::-webkit-scrollbar { width: 6px; height: 6px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: 999px; }
*::-webkit-scrollbar-thumb:hover { background: var(--color-text-faint); }
/* A bare ::-webkit-scrollbar-button rule alone doesn't reliably beat the
   browser's own default button pseudo-elements in every Chromium build —
   those are matched with more specific pseudo-classes, so those need
   targeting explicitly too, not just the unqualified pseudo-element. */
*::-webkit-scrollbar-button,
*::-webkit-scrollbar-button:single-button,
*::-webkit-scrollbar-button:vertical:start,
*::-webkit-scrollbar-button:vertical:end,
*::-webkit-scrollbar-button:horizontal:start,
*::-webkit-scrollbar-button:horizontal:end {
  display: none;
  width: 0;
  height: 0;
}

body {
  font-family: var(--font);
  background: #14161d;
  color: var(--color-text);
  font-size: 14.5px;
  line-height: 1.4;
  -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 4px; font-weight: 600; }
h1 { font-size: 1.2rem; }
h2 { font-size: 1.05rem; }
h3 { font-size: 0.95rem; }
p { margin: 0 0 8px; color: var(--color-text-muted); }

/* =========================================================================
   Phone frame — centers a fixed mobile-width surface in the browser
   ========================================================================= */

.phone-frame-wrap {
  min-height: 100vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 28px 12px;
  background:
    radial-gradient(circle at 20% 10%, #202432 0%, #14161d 55%);
}

.phone-frame {
  width: var(--phone-width);
  max-width: 100%;
  height: 780px;
  background: var(--color-bg);
  border-radius: 32px;
  border: 6px solid #000;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: relative;
}

.app-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.app-content {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px;
}

/* =========================================================================
   Top bar
   ========================================================================= */

.driver-topbar {
  /* min-height, not height — env(safe-area-inset-top) is 0px today (no
     viewport-fit=cover yet), so this renders identically to before. If this
     ever runs full-bleed under the notch/status bar (installed as a
     home-screen PWA, or viewport-fit=cover added), the bar grows downward
     by the inset instead of squeezing its own icons/toggle into less room —
     min-height + top padding, not a fixed height eating into that padding. */
  min-height: var(--topbar-height);
  padding-top: env(safe-area-inset-top, 0px);
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-left: 14px;
  padding-right: 14px;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
}

.topbar-icon-btn {
  background: none;
  border: none;
  color: var(--color-text);
  font-size: 18px;
  line-height: 1;
  padding: 6px;
  cursor: pointer;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
}
.topbar-icon-btn:hover { background: var(--color-surface-alt); }
.topbar-icon-btn svg { width: 19px; height: 19px; }

/* Connectivity icon — green/yellow/red reflects how many of the 4 checks
   (Internet, both HQ Servers, GPS) are currently down. Color lives on the
   icon itself (stroke), not the button background, so it reads at a glance
   without looking like an alert badge. */
.network-status-icon { color: var(--color-success); }
.network-status-btn.is-warn .network-status-icon { color: var(--color-warning); }
.network-status-btn.is-down .network-status-icon { color: var(--color-danger); }

.network-status-rows { display: flex; flex-direction: column; }
.network-status-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 13px;
}
.network-status-meta {
  font-size: 11.5px;
  color: var(--color-text-faint);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--color-border);
}
.network-status-value { font-weight: 700; color: var(--color-success); }
.network-status-value.is-down { color: var(--color-danger); }
.network-report { border-top: 1px solid var(--color-border); margin-top: 14px; padding-top: 14px; }
.network-status-user { font-size: 12px; color: var(--color-text-faint); margin: -4px 0 8px; }

/* Messages — unread count badge on the topbar icon. */
.messages-btn { position: relative; }
.messages-badge {
  position: absolute;
  top: 2px; right: 2px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  border-radius: 999px;
  background: var(--color-danger);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  line-height: 15px;
  text-align: center;
}
.messages-badge[hidden] { display: none; }

/* Messages inbox — a screen, not a modal: slides in over the whole frame
   like the nav drawer (positioned against .phone-frame), with its own mini
   topbar rather than sitting in a centered card. */
.messages-overlay {
  position: absolute;
  inset: 0;
  z-index: 52;
  background: var(--color-bg);
  transform: translateX(100%);
  transition: transform 220ms ease;
  display: flex;
  flex-direction: column;
}
.messages-overlay[hidden] { display: none; }
.messages-overlay.open { transform: translateX(0); }
.messages-header {
  flex-shrink: 0;
  height: var(--topbar-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 8px;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
}
.messages-title { font-size: 1.02rem; font-weight: 700; }
.messages-list { flex: 1; overflow-y: auto; }

/* Rows only — no per-message card/panel (that's a second layer of padding
   on top of the list's own), just a flat row with a single divider line
   between messages, same as any inbox. */
.message-row { border-bottom: 1px solid var(--color-border); }
.message-row-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  cursor: pointer;
}
/* Unread = bold + a faint tint, same as a real inbox; read = plain text, no
   background — the tint IS the affordance, no extra dot/badge needed. */
.message-row[data-read="false"] { background: var(--color-accent-soft); }
.message-row[data-read="false"] .message-row-order,
.message-row[data-read="false"] .message-row-subject { font-weight: 700; }
.message-row-main { min-width: 0; }
.message-row-order { font-size: 13px; color: var(--color-text); }
.message-row-subject { font-size: 12.5px; color: var(--color-text-muted); margin-top: 1px; }
.message-row-side { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.message-row-time { font-size: 11px; color: var(--color-text-faint); flex-shrink: 0; white-space: nowrap; }
.message-star-btn {
  flex-shrink: 0;
  display: flex;
  background: none;
  border: none;
  padding: 2px;
  cursor: pointer;
  color: var(--color-text-faint);
}
.message-star-btn svg { width: 17px; height: 17px; fill: none; }
.message-star-btn.is-starred { color: var(--color-warning); }
.message-star-btn.is-starred svg { fill: var(--color-warning); }
/* Header filter toggle — same star, lit up (filled) while active so it
   reads as a pressed filter, not just another icon button. */
.messages-star-filter svg { fill: none; }
.messages-star-filter.is-active { color: var(--color-warning); }
.messages-star-filter.is-active svg { fill: var(--color-warning); }
/* Expands in place under the row it belongs to — not a popup — so reading
   a message never loses your place in the list. */
.message-row-detail {
  padding: 0 14px 14px;
  font-size: 13px;
  color: var(--color-text-muted);
  line-height: 1.5;
}
.message-row-detail[hidden] { display: none; }
.message-row-goto {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--color-accent-hover);
}
.message-row-goto svg { width: 14px; height: 14px; }

/* Deliberately red/attention-grabbing, not the same soft-accent tint as an
   unread inbox row — this sits on the order's own page as a flag ("there's
   something you need to know about THIS stop"), not just a restated log
   entry, so it needs to stand out more than a normal message would. */
.order-message {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  background: var(--color-danger-soft);
  border-left: 3px solid var(--color-danger);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  margin-top: 8px;
  font-size: 12.5px;
  color: var(--color-text);
  line-height: 1.4;
}
.order-message-icon { flex-shrink: 0; color: var(--color-danger); }
.order-message-text strong { color: var(--color-danger); }

.topbar-title { font-size: 1.02rem; font-weight: 700; margin: 0; }

/* Left/right topbar sections given equal flex share so a lone centered item
   (the online toggle) stays truly centered regardless of how many icons sit
   on either side. */
.topbar-side { flex: 1; display: flex; align-items: center; gap: 4px; }
.topbar-side-right { justify-content: flex-end; }

/* Nav drawer — slides in from the left over the whole frame (a scrim +
   panel), the standard mobile-app pattern for a hamburger menu. Positioned
   against .phone-frame (the nearest positioned ancestor) so it covers the
   topbar and bottom nav too, and stays clipped to the frame's rounded corners. */
.sidebar-overlay {
  position: absolute;
  inset: 0;
  z-index: 50;
  background: rgba(0, 0, 0, 0);
  transition: background 180ms ease;
}
.sidebar-overlay[hidden] { display: none; }
.sidebar-overlay.open { background: rgba(0, 0, 0, 0.5); }
.sidebar-drawer {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 78%;
  max-width: 300px;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border-right: 1px solid var(--color-border-strong);
  box-shadow: var(--shadow-lg);
  transform: translateX(-100%);
  transition: transform 220ms ease;
}
.sidebar-overlay.open .sidebar-drawer { transform: translateX(0); }
.sidebar-drawer-header {
  flex-shrink: 0;
  height: var(--topbar-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 8px 0 16px;
  border-bottom: 1px solid var(--color-border);
}
.sidebar-drawer-title { font-size: 14px; font-weight: 700; }
.sidebar-drawer-nav { display: flex; flex-direction: column; padding: 6px; }
.sidebar-drawer-nav a,
.sidebar-drawer-nav button {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 10px;
  font-size: 14px;
  font-weight: 600;
  color: var(--color-text);
  border-radius: var(--radius-sm);
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.sidebar-drawer-nav a svg,
.sidebar-drawer-nav button svg { width: 19px; height: 19px; flex-shrink: 0; }
.sidebar-drawer-nav a:hover,
.sidebar-drawer-nav button:hover { background: var(--color-surface-alt); }
.sidebar-drawer-divider { height: 1px; background: var(--color-border); margin: 6px 4px; }
.sidebar-drawer-danger { color: var(--color-danger); }
.sidebar-drawer-danger:hover { background: var(--color-danger-soft); }

/* Map pin detail sheet — same scrim + sliding-panel shape as the nav drawer
   above (positioned against .phone-frame so it covers the whole frame, not
   just the map's iframe), but a bottom sheet instead of a side drawer. */
.map-pin-sheet-overlay {
  position: absolute;
  inset: 0;
  z-index: 55;
  background: rgba(0, 0, 0, 0);
  transition: background 180ms ease;
  display: flex;
  align-items: flex-end;
}
.map-pin-sheet-overlay[hidden] { display: none; }
.map-pin-sheet-overlay.open { background: rgba(0, 0, 0, 0.5); display: flex; }
.map-pin-sheet {
  width: 100%;
  max-height: 80%;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border-strong);
  border-radius: 16px 16px 0 0;
  box-shadow: var(--shadow-lg);
  padding: 14px;
  transform: translateY(100%);
  transition: transform 220ms ease;
}
.map-pin-sheet-overlay.open .map-pin-sheet { transform: translateY(0); }
.map-pin-sheet-top { flex-shrink: 0; display: flex; align-items: center; gap: 8px; }
.map-pin-sheet-order { flex: 1; font-size: 14px; font-weight: 700; color: var(--color-text); }
.map-pin-sheet-addr { flex-shrink: 0; font-size: 13px; color: var(--color-text-muted); margin: 6px 0 14px; }

/* Multi-order stop table — same columns/shape as the admin app's
   task-panel-table (Order Name / Recipient / …), scrollable within the
   sheet instead of pushing "View details" off-screen on a 12-order pickup. */
.map-pin-orders-wrap {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  margin-bottom: 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}
.map-pin-orders-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.map-pin-orders-table th {
  position: sticky; top: 0;
  background: var(--color-surface-alt);
  color: var(--color-text-faint);
  text-align: left;
  font-weight: 700;
  padding: 6px 8px;
  border-bottom: 1px solid var(--color-border-strong);
}
.map-pin-orders-table td { padding: 6px 8px; border-bottom: 1px solid var(--color-border); color: var(--color-text); }
.map-pin-orders-table tr:last-child td { border-bottom: none; }

.online-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--color-text);
  cursor: pointer;
  user-select: none;
}
.online-toggle .switch {
  width: 34px;
  height: 19px;
  border-radius: 999px;
  background: var(--color-border-strong);
  position: relative;
  transition: background 0.15s;
}
.online-toggle .switch::after {
  content: "";
  position: absolute;
  top: 2px; left: 2px;
  width: 15px; height: 15px;
  border-radius: 50%;
  background: #fff;
  transition: left 0.15s;
}
.online-toggle.is-online .switch { background: var(--color-success); }
.online-toggle.is-online .switch::after { left: 17px; }
.online-toggle.is-online .online-toggle-label::before { content: "Online"; }
.online-toggle:not(.is-online) .online-toggle-label::before { content: "Offline"; }

/* =========================================================================
   Segmented control (Today / All / Unassigned)
   ========================================================================= */

/* Edge-to-edge tab bar — flush against the topbar above and the screen's
   left/right edges, no outer margin, same space-saving treatment as the
   task list below it. */
.segmented {
  display: flex;
  background: var(--color-surface-alt);
  border-bottom: 1px solid var(--color-border);
  margin: 0;
}
.segmented[hidden] { display: none; }
.segmented button {
  flex: 1;
  background: none;
  border: none;
  color: var(--color-text);
  font-size: 12.5px;
  font-weight: 600;
  padding: 3px 4px;
  cursor: pointer;
}
.segmented button.active {
  background: var(--color-accent);
  color: #fff;
}

/* =========================================================================
   Task list / task cards
   ========================================================================= */

/* Edge-to-edge list: cancels .app-content's own side padding so rows run the
   full width of the frame, with a line separator between rows instead of a
   gap + bordered card per row — much less vertical space per row. */
/* Cancels .app-content's own padding on every side — not just left/right —
   so the list itself stays edge-to-edge without changing that shared padding
   for other pages/panels that still rely on it (stat boxes, form fields, etc).
   The top cancel only applies when the list opens its panel (Today, Completed):
   the "All" tab's intro paragraph still needs its own top clearance, so its
   list keeps normal top spacing instead of tucking under that text. */
.task-list { display: flex; flex-direction: column; margin: 0 -14px; }
[data-segment-panel] > .task-list-date-header:first-child,
[data-segment-panel] > .task-list:first-child { margin-top: -14px; }
[data-segment-panel] > .task-list:last-child { margin-bottom: -14px; }

/* Date-group divider in the "All" tab — the negative side margins match
   .task-list so the label lines up flush with the cards below it. */
.task-list-date-header {
  margin: 16px -14px 6px;
  padding: 0 14px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-faint);
}

.task-card {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
}
.task-list .task-card:last-child { border-bottom: none; }
.task-card:hover { background: var(--color-surface-alt); }

/* Leg tag, order name and the chevron/action share one row; address, contact
   and the footer are full-width rows underneath, flush with the card's own
   left edge — not indented under wherever the top row's text happens to start. */
.task-card-top { display: flex; align-items: center; gap: 6px; }
.task-card-order { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 700; color: var(--color-text); }

/* Pickup/dropoff leg tag — identical chip to the dispatch board's roster stops
   (.kc-leg-tag / .kc-leg-pickup / .kc-leg-dropoff there), same glyphs (⮝/⮟). */
.kc-leg-tag {
  display: inline-block;
  flex-shrink: 0;
  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); }

/* Urgency is a red flag, not a chip — same .urgency-flag treatment as the
   dispatch board. */
.urgency-flag {
  display: inline-block;
  flex-shrink: 0;
  color: var(--color-danger);
  font-size: 13px;
  line-height: 1;
}

.task-card-biz { font-size: 12px; color: var(--color-text-muted); margin-top: 1px; }
.task-card-addr { font-size: 13px; font-weight: 700; color: var(--color-text); margin-top: 2px; }
.task-card-sub { font-size: 12px; font-weight: 400; color: var(--color-text-muted); }
.task-card-time { font-size: 11.5px; color: var(--color-text); flex: 0 0 auto; }
.task-card-chevron { flex-shrink: 0; color: var(--color-text-faint); font-size: 16px; }

/* Time window + day-progress bar, same pairing as the dispatch board's roster
   stops (.stop-row-body .task-row-window-line + .day-graph-bar there). */
.task-card-footer { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.day-graph-bar {
  position: relative;
  flex: 1 1 auto;
  height: 6px;
  min-width: 40px;
  border-radius: 2px;
  background: repeating-linear-gradient(to right, #05070c 0, #05070c calc(100%/24 - 1px), transparent calc(100%/24 - 1px), transparent calc(100%/24));
  overflow: hidden;
}
.dgb-window { position: absolute; top: 0; bottom: 0; background: #858ea3; }
.dgb-now { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: #fff; }

/* =========================================================================
   Map placeholder
   ========================================================================= */

.driver-map-placeholder {
  position: relative;
  margin-top: 10px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background:
    linear-gradient(135deg, #1c2130 0%, #14171f 100%);
  height: 460px;
  overflow: hidden;
}
/* Map tab fills the frame flush to all 4 edges — cancel .app-content's own
   14px padding (same trick .task-list uses) and size to exactly fill the
   space that padding freed, so the iframe never overflows into its own
   scrollbar. */
[data-view-panel="map"] {
  margin: -14px;
  height: calc(100% + 28px);
}
.driver-map-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: none;
  /* The iframe's OWN scrollbar is a separate browser-chrome scrollbar that
     no ::-webkit-scrollbar rule (from either document) can restyle — if
     route-map.html's content is even 1px taller than the frame, this shows
     a native scrollbar with arrows no CSS here can touch. Force it off. */
  overflow: hidden;
}
.driver-map-caption {
  position: absolute;
  bottom: 10px; left: 10px; right: 10px;
  text-align: center;
  font-size: 11.5px;
  color: var(--color-text-faint);
  background: rgba(10,12,18,0.7);
  border-radius: var(--radius-sm);
  padding: 8px;
}
.map-pin-driver {
  position: absolute;
  display: block;
  width: 14px; height: 14px;
  border-radius: 50% 50% 50% 0;
  transform: translate(-50%, -100%) rotate(-45deg);
  border: 2px solid #0a0c12;
  cursor: pointer;
}
.map-pin-driver.pickup { background: var(--color-accent); }
.map-pin-driver.dropoff { background: var(--color-purple); }
.map-pin-driver.unassigned { background: var(--color-text-faint); cursor: default; }

/* =========================================================================
   Bottom tab nav
   ========================================================================= */

.bottom-nav {
  flex-shrink: 0;
  height: var(--bottomnav-height);
  display: flex;
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
}
.bottom-nav a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  color: var(--color-text);
  font-size: 10.5px;
  font-weight: 700;
}
/* Monochrome icons — outline SVGs that inherit the link's own color (currentColor),
   so the active tab's blue applies to the icon too instead of a fixed-color emoji. */
.bottom-nav a .nav-icon { display: flex; }
.bottom-nav a .nav-icon svg { width: 19px; height: 19px; }
.bottom-nav a.active { color: var(--color-accent); }

/* =========================================================================
   Task detail — header, info cards, status stepper
   ========================================================================= */

.detail-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 14px;
}
.detail-header .back-btn {
  background: none; border: none; color: var(--color-text);
  font-size: 20px; cursor: pointer; padding: 4px;
}
.detail-header-title { flex: 1; min-width: 0; }
.detail-header-title h1 { font-size: 1.05rem; margin: 0; }
.detail-header-order { font-size: 13px; color: var(--color-text); }
/* Order id emphasized like the page's own h1 — same size/weight — when a
   page wants it to read as a second title rather than just another value. */
.order-name-big { font-size: 1.05rem; font-weight: 700; color: var(--color-text); }
/* Tappable variant — opens the full order list, so it needs to look and act
   like plain text/a link, not a button, while still being one. */
button.detail-header-order {
  display: block;
  background: none;
  border: none;
  padding: 0;
  text-align: left;
  cursor: pointer;
}

/* Flat sections separated by a line, not boxed panels — .app-content's own
   14px side padding is the only horizontal inset (a card padding on top of
   it was a second, redundant layer), and the border-bottom is the section
   break instead of a margin gap between separate boxes. */
.info-card {
  padding: 10px 0;
  border-bottom: 1px solid var(--color-border);
  margin-top: 0;
}
.info-card h3 { margin-bottom: 8px; }
.info-row { display: flex; justify-content: space-between; gap: 10px; font-size: 12.5px; padding: 4px 0; }
/* Value sits right next to the label instead of pushed to the far right. */
.info-row-start { justify-content: flex-start; flex-wrap: nowrap; }
.info-row-start .info-label { flex-shrink: 0; }
.info-row-start .info-value { text-align: left; white-space: nowrap; }
.info-row .info-label { color: var(--color-text-faint); }
.info-row .info-value { text-align: right; color: var(--color-text); }
.info-contact-btn {
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: middle;
  width: 24px; height: 24px;
  margin-left: 4px;
  border-radius: 50%;
  background: var(--color-surface-alt);
  border: none;
  color: var(--color-text);
  cursor: pointer;
}
.info-contact-btn svg { width: 14px; height: 14px; }

/* Contact picker — a multi-order pickup can have a dozen orders' worth of
   senders/recipients to choose from, so (like the other tall modals here,
   e.g. [data-pickup-orders-overlay]) the modal itself caps at 80% of the
   frame and only the list inside scrolls, instead of the list forcing the
   whole modal past the frame's own height. */
[data-contact-picker-overlay] .confirm-modal { max-height: 80%; display: flex; flex-direction: column; }
.contact-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  margin: 0 -18px;
}
/* The divider belongs between orders, not between an order's own Sender and
   Recipient rows — so the border lives on the order label (which starts a
   new order), not on every row. */
.contact-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 18px;
}
.contact-order-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text-faint);
  padding: 10px 18px 2px;
  margin-top: 6px;
  border-top: 1px solid var(--color-border);
}
.contact-order-label:first-child { padding-top: 0; margin-top: 0; border-top: none; }
.contact-name { font-size: 12.5px; color: var(--color-text); }
.contact-role { color: var(--color-text-faint); font-weight: 400; }
.contact-actions { display: flex; gap: 6px; flex-shrink: 0; }
.contact-call-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text);
  text-decoration: none;
  font-size: 14px;
}

.status-stepper { display: flex; flex-direction: column; gap: 0; margin-top: 4px; }
.step {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  position: relative;
  padding-bottom: 10px;
}
.step:last-child { padding-bottom: 0; }
.step-dot {
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--color-surface-alt);
  border: 2px solid var(--color-border-strong);
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px;
  z-index: 1;
}
.step.done .step-dot { background: var(--color-success); border-color: var(--color-success); color: #06210f; }
.step.current .step-dot { background: var(--color-accent); border-color: var(--color-accent); color: #fff; }
.step-dot svg { width: 12px; height: 12px; }
.step:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 9px; top: 20px; bottom: 0;
  width: 2px;
  background: var(--color-border-strong);
}
.step.done:not(:last-child)::before { background: var(--color-success); }
.step-label { font-size: 12.5px; font-weight: 600; padding-top: 1px; }
.step-time { font-size: inherit; font-weight: 400; color: var(--color-text-faint); margin-left: 6px; }
.step-meta { font-size: 11px; color: var(--color-text-faint); }

.action-row { display: flex; gap: 8px; margin-top: 12px; }
.action-row[hidden] { display: none; }
.action-row .btn { flex: 1; }
/* Deliberately the small one — reverting a status is the exception, not the
   primary action sharing this row. ".action-row .status-undo-btn" (two
   classes) so it actually outweighs ".action-row .btn" above, not just
   ties with it. */
.action-row .status-undo-btn { flex: 0 0 25%; }
/* .btn sets its own display (inline-flex), which otherwise beats [hidden]'s
   UA default — same fix as .action-row[hidden] needed earlier. */
.status-undo-btn[hidden] { display: none; }

.pickup-checklist {
  margin-top: 14px;
  border-top: 1px solid var(--color-border);
  padding-top: 6px;
  max-height: 320px;
  overflow-y: auto;
}
.pickup-checklist-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 4px;
  min-height: 32px;
  cursor: pointer;
}
.pickup-checklist-row.is-checked { opacity: 0.55; }
/* Round, not the browser's square default — appearance:none clears the
   native box entirely so the checkmark below is drawn by hand. */
.pickup-checklist-row input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 18px; height: 18px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid var(--color-border-strong);
  background: var(--color-surface-alt);
  position: relative;
  cursor: pointer;
}
.pickup-checklist-row input[type="checkbox"]:checked {
  background: var(--color-accent);
  border-color: var(--color-accent);
}
.pickup-checklist-row input[type="checkbox"]:checked::after {
  content: "";
  position: absolute;
  left: 5px; top: 1px;
  width: 4px; height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.pickup-checklist-name { font-size: 13px; font-weight: 600; flex: 1; }
/* Both open order details (same as the ⓘ), not the row's own checkbox
   toggle — plain buttons styled to read as inline text/icon, each its own
   tap target so its click can be stopped before it reaches the enclosing
   <label> and toggles the box instead. */
.pickup-checklist-count,
.pickup-checklist-info {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 4px 6px;
  line-height: 1;
  cursor: pointer;
}
.pickup-checklist-count { font-size: 11.5px; color: var(--color-text-faint); font-family: inherit; margin: -4px 0; }
.pickup-checklist-info { font-size: 15px; color: var(--color-text-faint); margin: -4px -6px -4px 0; }

/* =========================================================================
   Confirm modal (pickup checklist gate)
   ========================================================================= */

.confirm-overlay {
  position: absolute;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  background: rgba(0, 0, 0, 0.55);
}
.confirm-overlay[hidden] { display: none; }
.confirm-modal {
  position: relative;
  width: 100%;
  max-width: 360px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 18px;
}
.confirm-modal h3 { margin: 0 24px 8px 0; font-size: 15px; }
/* Injected by app.js into every .confirm-modal — one close affordance
   shared by all of them, instead of hand-adding it to each modal's markup. */
.confirm-modal-x {
  position: absolute;
  top: 12px;
  right: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: none;
  border: none;
  color: var(--color-text-faint);
  cursor: pointer;
}
.confirm-modal-x svg { width: 16px; height: 16px; }
.confirm-modal p { margin: 0 0 16px; font-size: 13px; color: var(--color-text-muted); line-height: 1.5; }
.confirm-modal-actions { display: flex; gap: 8px; }
.confirm-modal-actions .btn { flex: 1; }
/* Stacked, full-width — side by side wrapped "Unmark Picked Up" onto two
   lines in a modal this narrow. */
[data-order-info-overlay] .confirm-modal-actions { flex-direction: column; }

/* Per-order Restart/Fully Fail decision for the pickup-confirm modal — one
   row per order left unchecked, scrollable so a long list doesn't blow out
   the modal's height. */
/* This modal runs taller (75% of the frame) so the note field and the
   unchecked-orders list both have real room — flex column lets the list grow
   to fill that height instead of a small fixed max-height. */
[data-pickup-confirm-overlay] .confirm-modal { max-height: 75%; display: flex; flex-direction: column; }
[data-pickup-confirm-overlay] .form-group { flex-shrink: 0; }
.pickup-confirm-unchecked-hint { font-size: 12.5px; color: var(--color-text-muted); margin: 0 0 8px; }
.pickup-confirm-unchecked-hint strong { color: var(--color-text); }
.pickup-confirm-unchecked-list {
  flex: 1;
  min-height: 80px;
  overflow-y: auto;
  margin: 0 -18px 16px;
}
.pickup-confirm-unchecked-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 18px;
  border-bottom: 1px solid var(--color-border);
}
.pickup-confirm-unchecked-row:last-child { border-bottom: none; }
.pickup-confirm-unchecked-info { display: flex; align-items: baseline; gap: 6px; font-size: 13px; }
.pickup-confirm-unchecked-info span:first-child { font-weight: 600; }
.pickup-confirm-unchecked-info span:last-child { color: var(--color-text-faint); }
.restart-fail-toggle {
  flex-shrink: 0;
  padding: 6px 12px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-accent);
  background: var(--color-accent-soft);
  color: var(--color-accent-hover);
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.restart-fail-toggle.is-fail {
  border-color: var(--color-danger);
  background: var(--color-danger-soft);
  color: var(--color-danger);
}

.pickup-summary-section { margin-bottom: 12px; }
.pickup-summary-section:last-child { margin-bottom: 0; }
.pickup-summary-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 4px; }
.pickup-summary-title.is-success { color: var(--color-success); }
.pickup-summary-title.is-restart { color: var(--color-accent); }
.pickup-summary-title.is-fail { color: var(--color-danger); }
.pickup-summary-item { font-size: 13px; padding: 3px 0; }
/* Picked Up orders link straight to their delivery stop — the only outcome
   here with somewhere to actually go. The arrow is its own button (a real
   40x40 tap target), not the whole row, and rows get real spacing between
   them — on a phone screen, a full-row link (or buttons packed edge to
   edge) is too easy to fat-finger into the wrong order's delivery page. */
.pickup-summary-item-linked {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 10px;
  margin-bottom: 6px;
}
.pickup-summary-item-linked:last-child { margin-bottom: 0; }
.pickup-summary-goto-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text);
  text-decoration: none;
}
.pickup-summary-goto-btn svg { width: 16px; height: 16px; }

.order-info-rows { margin-bottom: 16px; }
/* The full-pickup list can run to a dozen+ rows — scrolls within the modal
   instead of pushing it taller than the frame, same swipe-only scrollbar
   treatment used elsewhere. */
/* Policy: a scrollbar sits flush against the container's own edge, never
   inset by the container's padding — that padding moves onto the items
   inside instead (cancel it here with a negative margin matching
   .confirm-modal's own padding, since this list runs edge-to-edge within it). */
/* This modal runs taller than the others (70% of the frame) so the list has
   real room to breathe — flex column lets the list itself grow to fill that
   height, with Close pinned below it, rather than a fixed max-height. */
[data-pickup-orders-overlay] .confirm-modal { max-height: 70%; display: flex; flex-direction: column; }
[data-pickup-orders-list] {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  margin: 0 -18px;
}
.pickup-orders-item { padding: 7px 18px; border-bottom: 1px solid var(--color-border); }
.pickup-orders-item:last-child { border-bottom: none; }
.pickup-orders-item-header { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; }
.pickup-orders-item-header span:first-child { font-weight: 600; }
.pickup-orders-item-header span:last-child { color: var(--color-text-faint); flex-shrink: 0; }
.pickup-orders-item-meta { font-size: 13px; color: var(--color-text-faint); margin-top: 2px; }
.order-info-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 13px;
}
.order-info-row:last-child { border-bottom: none; }
.order-info-row span:first-child { color: var(--color-text-faint); }
.order-info-row span:last-child { font-weight: 600; text-align: right; }

/* =========================================================================
   Buttons / badges (subset of admin system, reused verbatim)
   ========================================================================= */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 14px;
  border-radius: var(--radius-md);
  font-size: 13px;
  font-weight: 600;
  border: 1px solid var(--color-border-strong);
  background: var(--color-surface-alt);
  color: var(--color-text);
  cursor: pointer;
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; pointer-events: 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-alt); }
.btn-secondary:hover { background: var(--color-neutral-soft); }
.btn-danger { background: var(--color-danger-soft); border-color: var(--color-danger); color: var(--color-danger); }
.btn-danger:hover { background: var(--color-danger); color: #fff; }
.btn-block { width: 100%; }
.btn-sm { padding: 5px 10px; font-size: 11.5px; }
/* Delivered is a completed, positive state — full-strength green, not a
   washed-out disabled button (the default :disabled treatment reads as
   "unavailable", which is wrong once the order is actually done). */
.btn-success { background: var(--color-success); border-color: var(--color-success); color: #06210f; }
.btn-success:disabled { opacity: 1; }

.badge {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.badge-accent { background: var(--color-accent-soft); color: var(--color-accent-hover); }
.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); }

.text-faint { color: var(--color-text-faint); }
.text-muted { color: var(--color-text-muted); }
.mt-0 { margin-top: 0; }

/* =========================================================================
   Forms (photo capture, failure reason, etc.)
   ========================================================================= */

.form-group { margin-bottom: 12px; }
.form-group label { display: block; font-size: 11.5px; font-weight: 600; color: var(--color-text-muted); margin-bottom: 4px; }
.pickup-confirm-note-label { font-size: 13px !important; color: var(--color-text) !important; }
.form-group select, .form-group textarea, .form-group input[type="text"] {
  width: 100%;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: 13px;
  font-family: var(--font);
}
.form-group textarea { min-height: 70px; resize: vertical; }
.form-help { font-size: 11px; color: var(--color-text-faint); margin: 4px 0 0; }

.toggle-group { display: flex; gap: 6px; }
.toggle-group button {
  flex: 1;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-muted);
  padding: 8px;
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.toggle-group button.active { background: var(--color-accent); border-color: var(--color-accent); color: #fff; }

/* Once Delivered is confirmed, the whole proof-of-delivery form is a
   read-only record, not something to keep editing — photos can't be
   removed, text fields stop looking (and behaving) like textboxes, and
   only the chosen "Customer contacted?" option still shows. Undo is the
   only way back to an editable state. */
[data-proof-of-delivery].is-locked .photo-upload-row,
[data-proof-of-delivery].is-locked .offline-note,
[data-proof-of-delivery].is-locked .remove-photo,
[data-proof-of-delivery].is-locked h3 .badge-danger {
  display: none;
}
[data-proof-of-delivery].is-locked .form-group input[type="text"] {
  background: transparent;
  border-color: transparent;
  padding: 0;
  color: var(--color-text);
}
[data-proof-of-delivery].is-locked .toggle-group button:not(.active) { display: none; }
[data-proof-of-delivery].is-locked .toggle-group button.active {
  flex: 0 0 auto;
  background: transparent;
  border-color: transparent;
  color: var(--color-text);
  padding: 0;
  cursor: default;
  pointer-events: none;
}

.photo-upload-row { display: flex; gap: 8px; margin-bottom: 10px; }
.photo-upload-row .btn { flex: 1; }

.photo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 10px; }
.photo-thumb {
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  background: var(--color-surface-alt);
  border: 1px dashed var(--color-border-strong);
  display: flex; align-items: center; justify-content: center;
  font-size: 18px;
  color: var(--color-text-faint);
  position: relative;
}
.photo-thumb.filled { border-style: solid; background: var(--color-neutral-soft); }
/* Stand-in for the actual captured photo (a mockup has no real camera
   output to show) — a plain image-placeholder glyph, not the camera emoji
   used before taking the shot. */
.photo-thumb-icon { width: 46%; height: 46%; color: var(--color-text-faint); }
.photo-thumb .remove-photo {
  position: absolute; top: 2px; right: 2px;
  background: var(--color-danger);
  border: none; color: #fff; border-radius: 50%;
  width: 18px; height: 18px; font-size: 11px; line-height: 1;
  cursor: pointer;
}

.offline-note {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--color-warning);
  background: var(--color-warning-soft);
  padding: 6px 8px; border-radius: var(--radius-sm);
  margin-bottom: 10px;
}

/* =========================================================================
   Fake camera screen (task-camera.html)
   ========================================================================= */

.camera-view {
  flex: 1;
  position: relative;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.camera-close {
  position: absolute;
  top: calc(14px + env(safe-area-inset-top, 0px));
  left: 14px;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
}
.camera-close svg { width: 18px; height: 18px; }
.camera-hint {
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.75);
  line-height: 1.5;
}
.camera-hint .text-faint { font-size: 11px; font-weight: 400; color: rgba(255, 255, 255, 0.4); }
/* Burned-in time/location — the whole reason this is its own camera screen
   instead of a plain file picker: it's what proves a photo was taken here,
   now, not pulled from the Gallery. */
.camera-stamp {
  position: absolute;
  left: 12px;
  bottom: 12px;
  font-family: ui-monospace, monospace;
  font-size: 11px;
  line-height: 1.6;
  color: #ffe07a;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}
.camera-controls {
  flex-shrink: 0;
  height: 110px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #000;
}
.camera-shutter {
  width: 66px; height: 66px;
  border-radius: 50%;
  background: #fff;
  border: 4px solid rgba(255, 255, 255, 0.4);
  cursor: pointer;
}
.camera-shutter:active { background: #d8d8d8; }

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

/* =========================================================================
   Login
   ========================================================================= */

.login-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 24px;
}
.login-brand { text-align: center; margin-bottom: 28px; }
.login-brand .brand-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 14px;
  background: var(--color-accent); color: #fff; font-weight: 800; font-size: 18px;
  margin-bottom: 10px;
}

/* =========================================================================
   Stat row (profile / working hours)
   ========================================================================= */

.stat-row { display: flex; gap: 8px; margin-top: 10px; }
.stat-box {
  flex: 1;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 12px;
  text-align: center;
}
.stat-box .stat-value { font-size: 1.3rem; font-weight: 700; }
.stat-box .stat-label { font-size: 10.5px; color: var(--color-text-faint); text-transform: uppercase; letter-spacing: 0.03em; margin-top: 2px; }

.placeholder-block {
  margin-top: 60px;
  text-align: center;
  color: var(--color-text-faint);
  font-size: 12.5px;
}
.placeholder-block .placeholder-icon { font-size: 34px; margin-bottom: 10px; display: block; }

/* Mockup-only reset button — floats top-left of the browser window, outside the phone frame. */
.mockup-reset-btn {
  position: fixed; top: 10px; left: 10px; z-index: 9999;
  padding: 6px 12px; font: 600 12px var(--font);
  color: #fff; background: rgba(255,255,255,0.12);
  border: 1px solid rgba(255,255,255,0.3); border-radius: 999px; cursor: pointer;
}
.mockup-reset-btn:hover { background: rgba(255,255,255,0.22); }

/* Address + round navigate icon — the whole thing is one tappable maps link. */
.addr-nav-link { color: inherit; text-decoration: none; }
.addr-nav-link:hover { text-decoration: none; }
.addr-nav-circle {
  display: inline-flex; align-items: center; justify-content: center;
  vertical-align: middle; width: 24px; height: 24px; margin-left: 6px;
  border-radius: 50%; background: var(--color-accent); color: #fff;
}
.addr-nav-circle svg { width: 13px; height: 13px; }
.addr-nav-link:hover .addr-nav-circle { background: var(--color-accent-hover); }
