* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

/* ---- Stats overlay: Remaining / Delivered / Failed, floating on the map
   itself (not a reserved full-width bar) so their whole former height goes
   back to the map. Positioned top-center, same pill visual language as the
   other map-overlay-badge elements (GPS/Plan Route/Import/Admin/Logout). */

#stats-overlay {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 900;
  display: flex;
  gap: 10px;
  padding: 6px 14px;
  padding-top: max(6px, env(safe-area-inset-top));
}

.stat-chip {
  font-size: 0.72rem;
  font-weight: 700;
}

.stat-chip b {
  font-size: 0.85rem;
  font-weight: 800;
  margin-right: 2px;
}

.stat-remaining b {
  color: #ffb300;
}

.stat-delivered b {
  color: #81c784;
}

.stat-failed b {
  color: #ff8a80;
}

/* ---- Map area: the map plus floating overlays on top of it ---- */

#map-area {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
}

#map {
  width: 100%;
  height: 100%;
}

.map-overlay-badge {
  z-index: 900;
  background-color: rgba(26, 26, 26, 0.85);
  color: #ffffff;
  padding: 7px 14px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  text-decoration: none;
}

/* Buttons styled as a .map-overlay-badge (e.g. #logout-btn) need their
   native button chrome reset — an <a> badge doesn't. */
.map-overlay-btn {
  border: none;
  cursor: pointer;
  font-family: inherit;
}

#gps-badge.gps-active {
  color: #a5d6a7;
}

#gps-badge.gps-searching {
  color: #ffcc80;
}

#gps-badge.gps-error {
  color: #ef9a9a;
}

.map-overlay-stack {
  position: absolute;
  top: 10px;
  z-index: 900;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.map-overlay-top-left {
  left: 10px;
  align-items: flex-start;
}

.map-overlay-top-right {
  right: 10px;
  align-items: flex-end;
}

#logout-btn,
#plan-route-btn,
#admin-link,
#delivery-history-link,
#pickup-link,
#home-link {
  color: #90caf9;
}

/* Highlighted (amber, not the usual badge blue) whenever there's at least
   one assigned-but-not-yet-picked-up package — see
   app.js's refreshPickupAwareness(), the ask being "the driver should
   still be able to see the count somewhere" for packages the delivery map
   deliberately hides until they're scanned. */
#pickup-link.pickup-link-awaiting {
  color: #ffb300;
  font-weight: 800;
}

.fab {
  position: absolute;
  right: 14px;
  bottom: 14px;
  z-index: 900;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: none;
  background-color: #ffffff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}

.fab:active {
  background-color: #eeeeee;
}

.fab svg {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: #1565c0;
  stroke-width: 2;
  stroke-linecap: round;
}

/* ---- Bottom delivery card ---- */

#bottom-card {
  flex: 0 0 auto;
  z-index: 1000;
  background-color: #ffffff;
  padding: 10px 16px;
  padding-bottom: max(10px, env(safe-area-inset-bottom));
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.2);
  border-top-left-radius: 18px;
  border-top-right-radius: 18px;
}

.next-stop-label {
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: #e65100;
  margin-bottom: 3px;
}

/* Same purple as app.js's own INFO_CHANGED_MARKER_STYLE — an admin/
   dispatcher edited this parcel's info while it was already out for
   delivery (see Package.info_changed_at's own docstring); this app has no
   real-time push, so this banner is only ever seen after the driver's own
   next page load/refresh, not instantly. */
.next-stop-warning {
  background-color: #f3e5f5;
  color: #4a148c;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 8px 10px;
  border-radius: 8px;
  margin-bottom: 8px;
}

.next-stop-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.9rem;
  padding: 2px 0;
}

.next-stop-key {
  color: #666666;
  font-weight: 600;
}

#next-stop-tracking,
#next-stop-address,
#next-stop-distance,
#next-stop-eta {
  text-align: right;
}

.next-stop-phone-link {
  text-align: right;
  color: #1565c0;
  font-weight: 600;
  text-decoration: none;
}

.next-stop-phone-link:not([href]) {
  cursor: default;
}

#next-stop-message {
  font-size: 1rem;
  font-weight: 600;
  color: #555555;
  text-align: center;
  padding: 10px 0;
}

#retry-btn {
  width: 100%;
  margin-top: 4px;
}

#next-stop-message[hidden],
#next-stop-panel[hidden],
#next-stop-eta-row[hidden] {
  display: none;
}

.button-row {
  display: flex;
  gap: 10px;
  margin-top: 8px;
}

.action-btn {
  flex: 1;
  min-height: 46px;
  padding: 10px 10px;
  font-size: 0.95rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1.15;
  color: #ffffff;
  border: none;
  border-radius: 12px;
  cursor: pointer;
}

.action-btn-primary {
  background-color: #1565c0;
}

.action-btn-primary:active {
  background-color: #0d47a1;
}

.action-btn-complete {
  background-color: #2e7d32;
}

.action-btn-complete:active {
  background-color: #1b5e20;
}

.action-btn-navigate {
  background-color: #283593;
}

.action-btn-navigate:active {
  background-color: #1a237e;
}

.action-btn-fail {
  background-color: #c62828;
}

.action-btn-fail:active {
  background-color: #8e0000;
}

.action-btn-secondary {
  background-color: #eeeeee;
  color: #333333;
}

.action-btn-secondary:active {
  background-color: #dddddd;
}

.action-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

#failure-reason-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 2000;
}

#failure-reason-overlay[hidden] {
  display: none;
}

#failure-reason-modal {
  width: 100%;
  max-width: 480px;
  background: #ffffff;
  border-radius: 16px 16px 0 0;
  padding: 20px;
  box-sizing: border-box;
}

#failure-reason-modal h2 {
  margin: 0 0 12px;
  font-size: 1.1rem;
}

#failure-reason-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.failure-reason-btn {
  min-height: 44px;
  text-align: left;
  padding-left: 16px;
}

.failure-reason-btn.failure-reason-selected {
  background-color: #1565c0;
  color: #ffffff;
}

#failure-reason-note {
  width: 100%;
  box-sizing: border-box;
  margin-top: 10px;
  min-height: 70px;
  border-radius: 10px;
  border: 1px solid #cccccc;
  padding: 8px 10px;
  font-size: 0.95rem;
  resize: vertical;
}

#failure-reason-note[hidden] {
  display: none;
}

#signature-pad-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 2000;
}

#signature-pad-overlay[hidden] {
  display: none;
}

#signature-pad-modal {
  width: 100%;
  max-width: 480px;
  background: #ffffff;
  border-radius: 16px 16px 0 0;
  padding: 20px;
  box-sizing: border-box;
}

#signature-pad-modal h2 {
  margin: 0 0 8px;
  font-size: 1.1rem;
}

#signature-pad-instructions {
  margin: 0 0 12px;
  font-size: 0.85rem;
  color: #555555;
}

#signature-pad-canvas {
  width: 100%;
  height: 180px;
  border: 1px solid #cccccc;
  border-radius: 10px;
  background-color: #fafafa;
  /* Signature drawing is touch/pen input, not a page-scroll gesture — this
     stops a driver's first stroke from also scrolling the page underneath
     the modal on a touchscreen. */
  touch-action: none;
  display: block;
}

#signature-pad-modal label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: #444444;
  margin-top: 12px;
  margin-bottom: 6px;
}

#signature-received-by {
  width: 100%;
  box-sizing: border-box;
  padding: 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  font-size: 0.95rem;
  font-family: inherit;
}

#failure-reason-note-error {
  color: #c62828;
  font-size: 0.85rem;
  margin-top: 6px;
}

#failure-reason-note-error[hidden] {
  display: none;
}

/* Compact icon button sharing #complete-btn's row — fixed width instead of
   the default flex:1, so it doesn't compete for the primary button's
   space. photo-btn-attached (set once an upload succeeds) swaps to a
   green background as a lightweight "attached" confirmation. */
.photo-btn {
  flex: none;
  width: 52px;
  font-size: 1.3rem;
  padding: 10px 0;
}

.photo-btn-attached {
  background-color: #2e7d32;
}

#toast {
  position: fixed;
  left: 50%;
  top: calc(env(safe-area-inset-top) + 64px);
  transform: translateX(-50%);
  z-index: 2000;
  background-color: #212121;
  color: #ffffff;
  padding: 10px 20px;
  border-radius: 999px;
  font-size: 0.9rem;
  font-weight: 700;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

#toast.toast-visible {
  opacity: 1;
}

.btn-feedback {
  display: inline-block;
  margin-left: 8px;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  vertical-align: middle;
}

.btn-feedback-success {
  color: #2e7d32;
}

.btn-feedback-error {
  color: #c62828;
}

.package-popup {
  font-size: 0.95rem;
  line-height: 1.6;
  min-width: 210px;
}

.package-popup strong {
  display: inline-block;
  min-width: 100px;
}

.package-popup .package-status {
  text-transform: capitalize;
  font-weight: 600;
  color: #d84315;
}

/* Same purple as .next-stop-warning/INFO_CHANGED_MARKER_STYLE — see
   buildPackagePopupHtml()'s own comment. */
.popup-info-changed-warning {
  background-color: #f3e5f5;
  color: #4a148c;
  font-weight: 700;
  padding: 6px 8px;
  border-radius: 6px;
  margin-bottom: 8px;
  line-height: 1.3;
}

/* Set by the customer at order creation (see Package.signature_required)
   — a distinct blue rather than the purple info-changed-warning above, so
   the two conditions (a routine notice vs. this delivery's own condition)
   don't read as the same kind of alert. */
.popup-signature-required,
.next-stop-signature-required {
  background-color: #e3f2fd;
  color: #0d47a1;
  font-weight: 700;
  padding: 6px 8px;
  border-radius: 6px;
  margin-bottom: 8px;
  line-height: 1.3;
}

.next-stop-signature-required[hidden] {
  display: none;
}

.popup-photo-delete {
  color: #c62828;
  font-weight: 700;
  text-decoration: none;
}

/* Lets the driver change a marker's delivery status directly from its
   popup (see buildPackagePopupHtml()/handlePopupAction() in app.js), not
   just whichever package the bottom panel currently recommends. Smaller
   than .action-btn since these sit inside a Leaflet popup, not the
   full-width bottom card. */
.package-popup .popup-actions {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}

.popup-btn {
  flex: 1;
  min-height: 36px;
  padding: 6px 4px;
  font-size: 0.8rem;
  font-weight: 700;
  color: #ffffff;
  border: none;
  border-radius: 8px;
  cursor: pointer;
}

.popup-btn-complete {
  background-color: #2e7d32;
}

.popup-btn-fail {
  background-color: #c62828;
}

.popup-btn-secondary {
  background-color: #eeeeee;
  color: #333333;
}

.popup-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Distance-order number shown on each eligible package marker (see
   renumberPackageMarkers() in app.js) — a plain number sitting on the pin,
   not Leaflet's default boxed/arrowed tooltip look. Chained with
   .leaflet-tooltip so this specificity (0,2,0) beats leaflet.css's own
   .leaflet-tooltip rule (0,1,0) without needing !important. */
.leaflet-tooltip.package-number-label {
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 0;
  margin: 0;
  color: #ffffff;
  font-weight: 800;
  font-size: 0.7rem;
  line-height: 1;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.7);
  pointer-events: none;
}

.import-body {
  overflow-y: auto;
  height: auto;
}

#import-header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background-color: #1a1a1a;
  color: #ffffff;
  padding: 14px 16px;
  padding-top: max(14px, env(safe-area-inset-top));
  font-size: 1.1rem;
  font-weight: 700;
}

#back-link {
  color: #90caf9;
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

/* Admin has no map to go "back" to (an admin account has no packages of
   its own — see app.main's "/" route, which redirects admins straight to
   /admin instead), so its header bar gets a real logout action instead of
   #back-link's "Back to map". */
.admin-header-btn {
  background: none;
  border: none;
  color: #90caf9;
  font-size: 0.9rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  padding: 0;
}

.import-intro {
  font-size: 0.95rem;
  line-height: 1.5;
  color: #333333;
}

.import-intro code {
  background-color: #eeeeee;
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 0.85em;
}

/* Customer Portal bulk-import page: a small "screenshot" of what the
   downloadable CSV template looks like opened in a spreadsheet program,
   standing in for a real product screenshot since none exists to embed. */
.import-template-card {
  margin: 14px 0 20px;
  border: 1px solid #e0e0e0;
  border-radius: 10px;
  background-color: #ffffff;
  overflow: hidden;
}

.import-template-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background-color: #f5f5f5;
  border-bottom: 1px solid #e0e0e0;
}

.import-template-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.import-template-dot-red {
  background-color: #ff5f57;
}

.import-template-dot-yellow {
  background-color: #febc2e;
}

.import-template-dot-green {
  background-color: #28c840;
}

.import-template-toolbar-title {
  margin-left: 6px;
  font-size: 0.78rem;
  color: #777777;
}

.import-template-table-wrap {
  overflow-x: auto;
}

.import-template-table {
  border-collapse: collapse;
  font-size: 0.8rem;
  white-space: nowrap;
}

.import-template-table th,
.import-template-table td {
  padding: 7px 10px;
  border: 1px solid #eeeeee;
  text-align: left;
}

.import-template-table th {
  background-color: #fafafa;
  color: #666666;
  font-weight: 700;
}

.import-template-table th.import-template-required {
  background-color: #eef0fb;
  color: #283593;
}

.import-template-table tbody tr:nth-child(even) {
  background-color: #fafafa;
}

.import-template-caption {
  margin: 0;
  padding: 8px 12px 0;
  font-size: 0.78rem;
  color: #666666;
}

.import-template-legend-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: 3px;
}

.import-template-legend-required {
  background-color: #283593;
}

.import-template-legend-optional {
  background-color: #cccccc;
}

.import-template-links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 10px 12px 12px;
}

.import-download-link {
  display: inline-block;
  max-width: 220px;
}

/* ---- Driver-facing Delivery Records page (below Logout on the map) ---- */

#delivery-history-page {
  max-width: 640px;
  margin: 0 auto;
  padding: 20px 16px 48px;
}

#delivery-history-status {
  margin-bottom: 16px;
  padding: 10px 14px;
  border-radius: 8px;
  background-color: #e8f5e9;
  color: #2e7d32;
  font-weight: 600;
}

#delivery-history-status.import-status-error {
  background-color: #ffebee;
  color: #c62828;
}

.delivery-history-card {
  border: 1px solid #eeeeee;
  border-radius: 12px;
  padding: 14px 16px;
  margin-bottom: 12px;
}

.delivery-history-tracking {
  font-weight: 800;
  font-size: 1rem;
  margin-bottom: 2px;
}

.delivery-history-address {
  color: #555555;
  font-size: 0.9rem;
  margin-bottom: 10px;
}

.delivery-history-meta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-top: 1px solid #f0f0f0;
  padding-top: 8px;
}

.delivery-history-meta-row {
  display: flex;
  justify-content: space-between;
  font-size: 0.85rem;
}

.delivery-history-meta-row span:first-child {
  color: #888888;
  font-weight: 600;
}

.delivery-history-meta-row span:last-child {
  font-weight: 700;
  color: #1a1a1a;
}

.delivery-history-no-gps {
  color: #999999 !important;
  font-weight: 600 !important;
  font-style: italic;
}

#delivery-history-empty-state {
  padding: 40px 0;
  text-align: center;
  color: #777777;
  font-size: 0.95rem;
}

@media (max-width: 480px) {
  .package-popup {
    font-size: 0.9rem;
    min-width: 150px;
  }
}

/* ---- "Next stop" marker: a pulsing halo so it's unmistakable among all
   the other parcel pins, layered under the restyled (bigger, amber)
   circleMarker rather than replacing it — see applyNextStopHighlight() in
   app.js. Uses a plain L.divIcon (not the SVG circleMarkers used for every
   other pin) because SVG circleMarkers can't run CSS keyframe animations. */

.next-stop-pulse-icon {
  position: relative;
}

.next-stop-pulse-icon .pulse-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  margin: -22px 0 0 -22px;
  border-radius: 50%;
  background-color: rgba(255, 179, 0, 0.55);
  animation: next-stop-pulse 1.6s ease-out infinite;
}

@keyframes next-stop-pulse {
  0% {
    transform: scale(0.4);
    opacity: 0.9;
  }
  100% {
    transform: scale(1.9);
    opacity: 0;
  }
}

/* ---- Login page ---- */

.login-body {
  overflow-y: auto;
  height: auto;
  align-items: center;
  justify-content: center;
  background-color: #f2f2f2;
  padding: 24px 16px;
  padding-top: max(24px, env(safe-area-inset-top));
  padding-bottom: max(24px, env(safe-area-inset-bottom));
}

#login-card {
  width: 100%;
  max-width: 360px;
  background-color: #ffffff;
  border-radius: 16px;
  padding: 28px 24px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}

#login-title {
  font-size: 1.3rem;
  font-weight: 800;
  margin: 0 0 2px;
  text-align: center;
}

#login-subtitle {
  font-size: 0.9rem;
  color: #666666;
  margin: 0 0 24px;
  text-align: center;
}

#login-form {
  display: flex;
  flex-direction: column;
}

.login-label {
  font-size: 0.85rem;
  font-weight: 700;
  color: #444444;
  margin-bottom: 6px;
  margin-top: 14px;
}

.login-label:first-of-type {
  margin-top: 0;
}

.login-input {
  padding: 14px;
  font-size: 1rem;
  border: 1px solid #cccccc;
  border-radius: 10px;
  background-color: #fafafa;
}

.login-input:focus {
  outline: 2px solid #283593;
  outline-offset: -1px;
}

#login-error {
  margin-top: 16px;
  padding: 10px 14px;
  border-radius: 8px;
  background-color: #ffebee;
  color: #c62828;
  font-size: 0.9rem;
  font-weight: 600;
  text-align: center;
}

#login-submit-btn {
  margin-top: 22px;
  width: 100%;
}

/* ---- Admin dispatch page ---- */

#admin-page {
  max-width: 1180px;
  margin: 0 auto;
  padding: 20px 16px 48px;
  width: 100%;
  /* NOT overflow-x:hidden here (unlike before the sidebar existed) — that
     would make this element the sticky containing block for #admin-tabs
     below (per the CSS overflow spec, overflow-x:hidden on one axis forces
     the other to a used value of auto, turning this into a scroll
     container even though it never actually shows a scrollbar), which
     broke the sidebar's position:sticky (verified in a real browser: it
     scrolled away with the page instead of staying put). See #admin-
     content for where the actual "clip a wide non-wrapping descendant"
     job now lives instead — everything wide (tables) is inside it, never
     inside the sidebar, so moving the clip one level down loses nothing.
  */
}

.admin-filters-bar {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.admin-filters-bar input[type="search"] {
  flex: 1 1 220px;
  padding: 10px 12px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #fafafa;
  font-size: 0.95rem;
}

.admin-filters-bar select {
  padding: 10px 12px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #fafafa;
  font-size: 0.95rem;
}

.admin-filters-bar .action-btn {
  flex: none;
  min-height: auto;
  padding: 10px 16px;
}

.admin-date-filter-group {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #fafafa;
}

.admin-date-filter-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: #666666;
  white-space: nowrap;
}

.admin-date-filter-sep {
  color: #999999;
}

.admin-date-filter-group input[type="date"] {
  border: none;
  background: none;
  font-size: 0.85rem;
  padding: 2px 0;
  color: #333333;
  max-width: 130px;
}

#admin-status {
  margin-bottom: 16px;
  padding: 10px 14px;
  border-radius: 8px;
  background-color: #e8f5e9;
  color: #2e7d32;
  font-weight: 600;
}

#admin-status.import-status-error {
  background-color: #ffebee;
  color: #c62828;
}

.admin-table-scroll {
  overflow-x: auto;
}

#admin-packages-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

#admin-packages-table th,
#admin-packages-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #eeeeee;
  white-space: nowrap;
}

#admin-packages-table th {
  color: #666666;
  font-weight: 700;
}

.admin-status-cell {
  text-transform: capitalize;
  font-weight: 700;
}

.admin-status-pending {
  color: #e65100;
}

.admin-status-delivered {
  color: #2e7d32;
}

.admin-status-failed {
  color: #c62828;
}

/* CLOSED (lost/damaged) reuses the failed red — both are a bad terminal
   outcome; RETURNED_TO_CUSTOMER reuses the neutral "unassigned" grey — it's
   terminal but not a failure. cancelled has no color rule either (plain
   bold text) — same minimal-effort precedent this follows. */
.admin-status-closed {
  color: #c62828;
}

.admin-status-returned_to_customer {
  color: #616161;
}

.admin-pickup-unassigned {
  color: #757575;
}

.admin-pickup-awaiting_pickup {
  color: #e65100;
}

.admin-pickup-picked_up {
  color: #2e7d32;
}

.admin-pickup-returned {
  color: var(--status-exception);
}

.admin-driver-select {
  padding: 6px 8px;
  border: 1px solid #cccccc;
  border-radius: 6px;
  background-color: #fafafa;
  font-size: 0.85rem;
  max-width: 220px;
}

.admin-reassign-btn {
  min-height: auto;
  padding: 8px 14px;
  font-size: 0.85rem;
  flex: none;
}

.admin-package-actions-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}

.admin-label-action-link {
  font-size: 0.8rem;
  color: #1565c0;
  text-decoration: none;
  white-space: nowrap;
}

.admin-label-action-link:hover {
  text-decoration: underline;
}

/* Print Label tab's own bulk bar — same visual language as #admin-bulk-bar
   and the Customer Portal's #orders-bulk-bar (see static/style.css's own
   comment on that rule). */
#print-label-bulk-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin-bottom: 16px;
  padding: 14px 16px;
  background-color: #eef2ff;
  border-radius: 10px;
}

#print-label-selected-count {
  font-weight: 700;
  font-size: 0.9rem;
  color: #283593;
}

#print-label-bulk-bar .action-btn {
  flex: none;
  min-height: auto;
  padding: 10px 16px;
}

#admin-empty-state {
  padding: 24px 0;
  text-align: center;
  color: #777777;
  font-size: 0.95rem;
}

/* ---- Assignment tab: suburb group header rows ----
   One of these precedes each area's packages in #admin-packages-table —
   a distinct background + no cell borders (only the whole group row gets
   one) sets it apart from an ordinary package row. */

.suburb-group-row {
  background-color: #eef2ff;
}

.suburb-group-row td {
  border-bottom: 1px solid #dde3fb !important;
}

.suburb-group-cell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  white-space: normal !important;
  padding: 10px 10px !important;
}

.suburb-group-label {
  font-weight: 700;
  font-size: 0.85rem;
  color: #283593;
}

.suburb-group-controls {
  display: flex;
  align-items: center;
  gap: 8px;
}

.suburb-group-select {
  padding: 6px 8px;
  border: 1px solid #cccccc;
  border-radius: 6px;
  background-color: #ffffff;
  font-size: 0.85rem;
  max-width: 200px;
}

/* ---- Admin page layout: a left sidebar nav + content column on wide
   screens, falling back to today's horizontal scrollable tab strip below
   admin-narrow-breakpoint (a sidebar has nowhere to go at phone width). ---- */

#admin-layout {
  display: flex;
  align-items: flex-start;
  gap: 28px;
}

#admin-content {
  flex: 1 1 auto;
  /* Without this, a flex item's automatic min-width is its content's
     intrinsic width — a wide table inside would push #admin-content (and
     the whole sidebar layout with it) wider instead of letting that
     table's own .admin-table-scroll wrapper scroll internally. Safe to
     also set overflow-x:hidden here (unlike on #admin-page, see its own
     comment) — #admin-tabs is this element's sibling, not its descendant,
     so this can't touch the sidebar's position:sticky. width:100% is
     required too, not just min-width:0/overflow-x:hidden — verified in a
     real browser that without it, this box measured wider than its own
     flex container on mobile (where #admin-layout switches to column
     direction, see the media query below): stretch alone did not reliably
     clamp a cross-axis flex item's width to its container the way a
     definite width does. */
  min-width: 0;
  width: 100%;
  overflow-x: hidden;
}

#admin-tabs {
  display: flex;
  flex-direction: column;
  flex: 0 0 190px;
  gap: 2px;
  /* Light-blue card background — makes the sidebar read as its own panel
     rather than bare buttons floating next to the content column. The
     active tab (below) gets a white background instead, so it "lifts off"
     this backdrop rather than blending into it. */
  background-color: #eaf1fb;
  padding: 12px;
  border-radius: 12px;
  /* Stays in view while a long tab (e.g. Shipment Centre's full package
     history) scrolls past it — 20px matches #admin-page's own top padding
     so the sidebar's top edge lines up with the content column's. */
  position: sticky;
  top: 20px;
}

/* Groups the sidebar's buttons into collapsible Operations/Management/
   Settings sections (see initTabGroups() in admin.js) — the label itself
   carries no data-tab and switchTab() never looks at it, only at the
   .admin-tab-btn buttons inside each group's .admin-tab-group-items. */
.admin-tab-group + .admin-tab-group {
  margin-top: 6px;
}

.admin-tab-group-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  border: none;
  background: none;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #8896ac;
  padding: 8px 12px;
  cursor: pointer;
  border-radius: 8px;
}

.admin-tab-group-label:hover {
  background-color: rgba(40, 53, 147, 0.06);
}

.admin-tab-group-chevron {
  display: inline-block;
  width: 0;
  height: 0;
  /* Right-pointing = collapsed; rotated 90deg (below) to point down once
     the group's own aria-expanded flips to true. */
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 5px solid #8896ac;
  transition: transform 0.15s ease;
}

.admin-tab-group-label[aria-expanded="true"] .admin-tab-group-chevron {
  transform: rotate(90deg);
}

.admin-tab-group-items {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 2px;
}

/* Same "an unconditional display:flex beats the browser's own
   [hidden]{display:none}" gotcha this codebase has hit (and worked around)
   many times before — see e.g. #next-stop-panel/#admin-customer-import's
   own history. Needed here so a collapsed group (items container carrying
   the `hidden` attribute, set by initTabGroups()/switchTab() in admin.js)
   actually disappears instead of the flex rule above silently keeping it
   visible. */
.admin-tab-group-items[hidden] {
  display: none;
}

.admin-tab-btn {
  border: none;
  background: none;
  padding: 10px 12px;
  font-size: 0.9rem;
  font-weight: 700;
  color: #5a6a85;
  cursor: pointer;
  text-align: left;
  border-radius: 8px;
  border-left: 3px solid transparent;
}

.admin-tab-btn-active {
  color: #1a1a1a;
  background-color: #ffffff;
  border-left-color: #283593;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.admin-tab-panel[hidden] {
  display: none;
}

/* Phone-width fallback: the sidebar has no room to sit beside the content,
   so it goes back to being a horizontal, edge-to-edge scrollable strip
   above it — the exact layout this app used before the sidebar existed. */
@media (max-width: 720px) {
  #admin-layout {
    flex-direction: column;
    gap: 0;
  }

  #admin-tabs {
    flex-direction: row;
    flex: none;
    width: 100%;
    /* Same flex-item-won't-shrink-below-content-size trap #admin-content's
       own min-width:0 comment above describes, just on the cross axis of
       this column-direction #admin-layout instead of the main axis — this
       row of nowrap tab buttons would otherwise push #admin-tabs (and the
       whole page) wider instead of scrolling internally within its own
       overflow-x:auto (verified in a real browser: without this, body.
       scrollWidth exceeded the viewport). */
    min-width: 0;
    gap: 8px;
    /* The light-blue card look is a sidebar-only treatment — at this width
       #admin-tabs is back to being an edge-to-edge strip, not a panel. */
    background-color: transparent;
    padding: 0;
    border-radius: 0;
    margin-bottom: 16px;
    padding-bottom: 8px;
    border-bottom: 1px solid #eeeeee;
    overflow-x: auto;
    position: static;
  }

  /* A section label/chevron makes sense above a vertical column of
     buttons, not inline in a horizontal scrolling strip — hidden here
     rather than trying to reflow it into the row. */
  .admin-tab-group-label {
    display: none;
  }

  /* The collapse/expand affordance doesn't fit a horizontal strip either
     (no room for a per-group toggle, and the toggle button itself is
     hidden immediately above) — flatten every group and its items
     container with display:contents so every .admin-tab-btn becomes a
     direct flex item of #admin-tabs again, exactly the pre-accordion flat
     button row. A collapsed group's items container still carries the
     `hidden` attribute (initTabGroups()/switchTab() in admin.js don't know
     or care about viewport width), so this needs the [hidden] variant
     specifically, at matching specificity to the desktop
     .admin-tab-group-items[hidden]{display:none} rule above — same
     specificity plus later source order is what lets this win here rather
     than that one, the reverse of that rule's own reasoning. */
  .admin-tab-group,
  .admin-tab-group-items,
  .admin-tab-group-items[hidden] {
    display: contents;
  }

  .admin-tab-btn {
    padding: 10px 4px;
    white-space: nowrap;
    border-left: none;
    border-bottom: 3px solid transparent;
    border-radius: 0;
  }

  .admin-tab-btn-active {
    background-color: transparent;
    border-left-color: transparent;
    border-bottom-color: #283593;
    box-shadow: none;
  }
}

/* ---- Overview tab: fleet-wide summary (donut + stat tiles) plus a
   per-driver delivery-progress dashboard below it ----
   Segment colors intentionally reuse the app's existing status scale
   (same hexes as .admin-status-pending/delivered/failed) — delivered/
   pending/failed is a state, not a series identity, so it takes the
   status color job rather than a categorical palette. This tab alone gets
   a shaded surface + card treatment (the other tabs keep their existing
   plain-page look) so the summary numbers and per-driver bars read as a
   dashboard rather than another data table. */

:root {
  --status-delivered: #2e7d32;
  --status-pending: #e65100;
  --status-failed: #c62828;
  --status-unassigned: #616161;
  --status-exception: #ad1457;
}

#admin-tab-overview {
  background-color: #f4f5f7;
  margin: -20px -16px 0;
  padding: 20px 16px 28px;
  border-radius: 0 0 16px 16px;
}

.overview-card {
  background-color: #ffffff;
  border-radius: 14px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.08);
  padding: 20px;
}

#overview-summary-card {
  display: flex;
  align-items: center;
  gap: 28px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

#overview-donut-wrap {
  position: relative;
  flex: none;
  width: 88px;
  height: 88px;
}

#overview-donut {
  width: 88px;
  height: 88px;
}

#overview-donut-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

#overview-donut-percent {
  font-size: 1.15rem;
  font-weight: 800;
  color: #1a1a1a;
  line-height: 1.1;
}

#overview-donut-caption {
  font-size: 0.6rem;
  color: #777777;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

#overview-stats {
  flex: 1 1 260px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 14px;
}

.overview-stat-tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.overview-stat-value {
  font-size: 1.6rem;
  font-weight: 800;
  color: #1a1a1a;
  line-height: 1.1;
}

.overview-stat-label {
  font-size: 0.75rem;
  color: #777777;
  font-weight: 600;
}

.overview-stat-delivered .overview-stat-value {
  color: var(--status-delivered);
}

.overview-stat-pending .overview-stat-value {
  color: var(--status-pending);
}

.overview-stat-failed .overview-stat-value {
  color: var(--status-failed);
}

.overview-stat-unassigned .overview-stat-value {
  color: var(--status-unassigned);
}

.overview-stat-tile-clickable {
  cursor: pointer;
  border-radius: 8px;
  padding: 4px 6px;
  margin: -4px -6px;
  transition: background-color 0.12s ease;
}

.overview-stat-tile-clickable:hover,
.overview-stat-tile-clickable:focus-visible {
  background-color: #f0f2ff;
  outline: none;
}

/* Company Management tab's "Company Overview" card — plain #overview-card
   has no layout of its own (its only other user, #overview-summary-card,
   supplies its own flex layout), so without this the 5 stat tiles here
   used to stack full-width instead of sitting in a grid like every other
   stat-tile group in this app (#overview-stats, #lifecycle-funnel). */
#company-info-card {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 18px 24px;
}

/* The company name reads better as the card's title than as just another
   stat tile sized/colored the same as a driver count. */
.company-info-tile-name .overview-stat-value {
  font-size: 1.3rem;
}

/* Service Status pill — same green/red as .admin-status-delivered/failed
   and .customer-status-delivered/failed, this app's existing "state, not
   series" active/inactive convention, just in the pill shape
   .customer-status-badge already established for a summary-card context. */
#company-info-status {
  display: inline-block;
  padding: 3px 12px;
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 700;
}

#company-info-status.company-status-active {
  background-color: #e8f5e9;
  color: #2e7d32;
}

#company-info-status.company-status-paused {
  background-color: #ffebee;
  color: #c62828;
}

#live-ops-table th,
#live-ops-table td {
  white-space: nowrap;
}

.live-ops-warning-row td {
  background-color: #fdecea;
}

.live-ops-warning-icon {
  color: var(--status-exception);
  margin-left: 4px;
}

#lifecycle-funnel {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 10px;
  margin-top: 8px;
}

.lifecycle-tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  border-radius: 10px;
  background-color: #f4f5f7;
}

.lifecycle-tile-value {
  font-size: 1.3rem;
  font-weight: 800;
  color: #1a1a1a;
}

.lifecycle-tile-label {
  font-size: 0.72rem;
  color: #777777;
  font-weight: 600;
}

#new-api-key-scopes {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  border: 1px solid #e0e0e0;
  border-radius: 10px;
  padding: 10px 14px;
  margin: 10px 0;
  font-size: 0.85rem;
}

#new-api-key-scopes legend {
  font-size: 0.75rem;
  color: #777777;
  font-weight: 600;
  padding: 0 4px;
}

#new-api-key-reveal {
  background-color: #e8f5e9;
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 16px;
}

#new-api-key-reveal[hidden] {
  display: none;
}

#new-api-key-raw-value {
  display: block;
  background-color: #ffffff;
  border-radius: 8px;
  padding: 8px 10px;
  margin: 8px 0;
  font-size: 0.9rem;
  word-break: break-all;
  user-select: all;
}

#admin-map {
  height: 65vh;
  min-height: 360px;
  border-radius: 12px;
  overflow: hidden;
}

#admin-map-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 16px;
  margin-bottom: 10px;
  font-size: 0.8rem;
  color: #444444;
}

.admin-map-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.admin-map-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

.overview-section-title {
  font-size: 0.95rem;
  font-weight: 700;
  color: #444444;
  margin: 4px 0 12px;
}

#progress-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  font-size: 0.85rem;
  color: #555555;
}

.progress-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.progress-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  font-style: normal;
}

.progress-swatch-delivered {
  background-color: var(--status-delivered);
}

.progress-swatch-pending {
  background-color: var(--status-pending);
}

.progress-swatch-failed {
  background-color: var(--status-failed);
}

.driver-progress-row {
  background-color: #ffffff;
  border-radius: 14px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.08);
  padding: 16px 18px;
  margin-bottom: 14px;
}

.driver-progress-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}

.driver-progress-name {
  font-weight: 700;
  font-size: 0.95rem;
}

.driver-progress-inactive-badge {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 999px;
  background-color: #ffebee;
  color: #c62828;
  font-size: 0.7rem;
  font-weight: 700;
  vertical-align: middle;
}

.driver-progress-summary {
  font-size: 0.85rem;
  font-weight: 700;
  color: #444444;
  white-space: nowrap;
}

/* Bar: <=24px thick, 4px rounded ends on the whole track only (not between
   segments — overflow:hidden clips flex children to the rounded shape).
   A 2px gap (the track's own background color showing through) separates
   touching segments instead of a border. */
.driver-progress-track {
  display: flex;
  gap: 2px;
  height: 20px;
  border-radius: 4px;
  overflow: hidden;
  background-color: #ffffff;
}

.driver-progress-track-empty {
  background-color: #eeeeee;
}

.driver-progress-segment {
  min-width: 2px;
}

.progress-segment-delivered {
  background-color: var(--status-delivered);
}

.progress-segment-pending {
  background-color: var(--status-pending);
}

.progress-segment-failed {
  background-color: var(--status-failed);
}

.driver-progress-counts {
  margin-top: 8px;
  font-size: 0.8rem;
  color: #666666;
}

.driver-progress-pickup {
  margin-top: 4px;
  font-size: 0.78rem;
  font-weight: 700;
  color: #e65100;
}

/* ---- Overview tab: Delivery Trend (admin-adjustable date range, default
   last 7 days — one delivered/failed summary tile + a per-day chart) ---- */

#trend-range-controls {
  margin-bottom: 12px;
}

#trend-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 260px));
  gap: 12px;
  margin-bottom: 16px;
}

.trend-tile {
  background-color: #ffffff;
  border-radius: 14px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.08);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.trend-tile-label {
  font-size: 0.75rem;
  font-weight: 700;
  color: #777777;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.trend-tile-numbers {
  display: flex;
  gap: 14px;
  font-size: 0.85rem;
  font-weight: 600;
  color: #555555;
}

.trend-tile-numbers b {
  font-size: 1.1rem;
  font-weight: 800;
  margin-right: 3px;
}

.trend-tile-delivered b {
  color: var(--status-delivered);
}

.trend-tile-failed b {
  color: var(--status-failed);
}

#trend-chart-card {
  margin-bottom: 20px;
}

#trend-chart-legend {
  display: flex;
  gap: 16px;
  margin-bottom: 8px;
  font-size: 0.85rem;
  color: #555555;
}

#trend-chart {
  width: 100%;
  height: auto;
  display: block;
}

.trend-bar-total-label {
  font-size: 9px;
  font-weight: 700;
  fill: #444444;
}

.trend-bar-day-label {
  font-size: 9px;
  font-weight: 600;
  fill: #888888;
}

#trend-chart-empty-state {
  padding: 20px 0;
  text-align: center;
  color: #777777;
  font-size: 0.9rem;
}

#driver-progress-empty-state {
  padding: 24px 0;
  text-align: center;
  color: #777777;
  font-size: 0.95rem;
}

/* ---- Driver management tab ---- */

.admin-inline-form {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

/* .admin-inline-form's own display:flex beats the browser's native
   [hidden]{display:none} at equal specificity — same class of bug this
   app has already hit for #admin-map-city-controls etc.; fixed the same
   way here for #create-pricing-tier-form, hidden while viewing a specific
   customer's own prices (see updatePricingCustomerFilterUI()). */
#create-pricing-tier-form[hidden] {
  display: none;
}

.admin-inline-form input {
  flex: 1 1 160px;
  padding: 10px 12px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #fafafa;
  font-size: 0.9rem;
}

.admin-inline-form button {
  flex: none;
  min-height: auto;
  padding: 10px 16px;
}

/* Create Orders tab's single-order form and bulk-import customer picker —
   same stacked label-above-field layout as #customer-order-form (the
   Customer Portal's own order-creation form), as a reusable class instead
   of an id since admin.html has two separate forms that both need it
   (the order form and the import form's customer <select>). */
.admin-order-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 480px;
  margin-bottom: 24px;
}

.admin-order-form label {
  font-size: 0.85rem;
  font-weight: 600;
  color: #444444;
  margin-bottom: -8px;
}

.admin-order-form input,
.admin-order-form select,
.admin-order-form textarea {
  padding: 12px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #fafafa;
  font-size: 0.95rem;
  font-family: inherit;
}

/* ---- Pricing tab ---- */

#pricing-customer-filter-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 8px;
  font-size: 0.9rem;
}

#pricing-customer-filter-bar select {
  padding: 6px 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #ffffff;
}

.pricing-tier-card {
  border: 1px solid #e0e0e0;
  border-radius: 10px;
  padding: 16px;
  margin-bottom: 16px;
  background-color: #fafafa;
}

.pricing-tier-header {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

.pricing-tier-name {
  font-size: 1.05rem;
  font-weight: 700;
}

.pricing-tier-section {
  margin-top: 14px;
}

.pricing-tier-section h4 {
  margin: 0 0 8px;
  font-size: 0.9rem;
  color: #666666;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* The Areas section (see buildPricingTierCard()) is a <details> element,
   collapsed by default — a bulk-assigned tier can carry hundreds of areas
   (e.g. "Assign entire city" on Auckland is 794 at once), so the chip
   list only renders when expanded rather than always inflating the card. */
.pricing-tier-section summary {
  margin: 0 0 8px;
  font-size: 0.9rem;
  color: #666666;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
}

.pricing-area-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.pricing-area-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background-color: #e3f2fd;
  color: #0d47a1;
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 0.85rem;
}

.pricing-area-chip-remove {
  color: #0d47a1;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
}

.pricing-empty-note {
  color: #888888;
  font-size: 0.85rem;
  font-style: italic;
}

.pricing-inline-form {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.pricing-inline-form input,
.pricing-inline-form select {
  padding: 8px 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #ffffff;
  font-size: 0.85rem;
}

.pricing-bands-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  margin-bottom: 10px;
}

.pricing-bands-table th,
.pricing-bands-table td {
  text-align: left;
  padding: 6px 10px;
  border-bottom: 1px solid #eeeeee;
}

.pricing-bands-table th {
  color: #666666;
  font-weight: 700;
}

.pricing-band-edit-cell {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  padding: 6px 10px;
}

.pricing-band-edit-cell input {
  padding: 8px 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  font-size: 0.85rem;
  max-width: 140px;
}

/* ---- Map tab's Color-by control ---- */

#admin-map-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
  font-size: 0.9rem;
}

#admin-map-controls select {
  padding: 6px 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #ffffff;
}

#admin-map-city-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

#admin-map-city-controls[hidden] {
  display: none;
}

#admin-map-selection-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
  padding: 8px 10px;
  background-color: #fff3e0;
  border: 1px solid #ffcc80;
  border-radius: 8px;
  font-size: 0.9rem;
}

#admin-map-selection-bar[hidden] {
  display: none;
}

#admin-map-selection-count {
  font-weight: 700;
  color: #e65100;
}

#admin-map-selection-bar select {
  padding: 6px 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #ffffff;
}

.suburb-popup {
  font-size: 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 160px;
}

.suburb-popup select {
  padding: 6px 8px;
  border: 1px solid #cccccc;
  border-radius: 6px;
}

.suburb-popup-actions {
  display: flex;
  gap: 6px;
}

.suburb-popup-actions button {
  flex: 1;
}

#drivers-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

#drivers-table th,
#drivers-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #eeeeee;
}

#drivers-table th {
  color: #666666;
  font-weight: 700;
}

#companies-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

#companies-table th,
#companies-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #eeeeee;
}

#companies-table th {
  color: #666666;
  font-weight: 700;
}

#customers-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

#customers-table th,
#customers-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #eeeeee;
}

#customers-table th {
  color: #666666;
  font-weight: 700;
}

#companies-table tbody tr:not(.records-detail-row) {
  cursor: default;
}

/* Company usage summary (super admin's Companies tab, expandable row) —
   same small-stat-tile visual language as .trend-tile/.overview-stat-tile
   elsewhere in this app, just for 4 coarse counts instead of a delivered/
   failed pair. */
.company-usage-summary-title {
  font-size: 0.85rem;
  font-weight: 700;
  color: #444444;
  margin: 0 0 10px;
}

.company-usage-summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
  margin-bottom: 18px;
}

.company-usage-summary-tile {
  background-color: #ffffff;
  border: 1px solid #eeeeee;
  border-radius: 10px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.company-usage-summary-value {
  font-size: 1.3rem;
  font-weight: 800;
  color: #1a1a1a;
}

.company-usage-summary-label {
  font-size: 0.72rem;
  color: #777777;
  font-weight: 600;
}

/* ---- Companies tab: "Monthly order volume" trend chart, inside the same
   expandable usage-summary panel as the tiles above. Single accent color
   (not STATUS_COLOR) — see renderCompanyMonthlyVolumeSection()'s own
   comment on why this is a magnitude series, not a delivered/pending/failed
   state. */
.company-monthly-volume-section {
  margin-bottom: 12px;
}

.company-monthly-volume-title {
  font-size: 0.85rem;
  font-weight: 700;
  color: #444444;
  margin: 0 0 8px;
}

.company-monthly-volume-chart {
  width: 100%;
  max-width: 300px;
  height: auto;
  display: block;
}

.company-monthly-volume-bar-label {
  font-size: 9px;
  font-weight: 700;
  fill: #444444;
}

.company-monthly-volume-month-label {
  font-size: 9px;
  font-weight: 600;
  fill: #888888;
}

.company-monthly-volume-empty-state {
  padding: 12px 0;
  color: #777777;
  font-size: 0.85rem;
}

.company-admins-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}

.company-admin-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}

.company-admin-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}

.company-add-admin-form {
  margin: 0;
}

.company-add-admin-form input {
  flex: 1 1 140px;
}

.admin-driver-actions-cell {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
  white-space: normal;
}

.admin-inline-password-input {
  padding: 6px 8px;
  border: 1px solid #cccccc;
  border-radius: 6px;
  background-color: #fafafa;
  font-size: 0.85rem;
  min-width: 160px;
}

/* ---- Super Admin: per-company shipping-label template editor + live
   preview (see renderCompanyLabelTemplatePanel()/renderLabelTemplatePreview()
   in admin.js). The preview is a compact, non-print reference — not a
   true-to-scale 4x6"/A4 rendering — with a real scannable barcode/QR so a
   super admin can actually verify a logo/brand/tagline reads correctly. */
.label-template-editor {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  align-items: flex-start;
}

.label-template-form {
  flex: 1 1 240px;
  min-width: 220px;
}

.label-template-logo-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.label-template-logo-thumb {
  width: 44px;
  height: 44px;
  object-fit: contain;
  border: 1px solid #dddddd;
  border-radius: 6px;
  background-color: #ffffff;
  padding: 3px;
}

.label-template-preview-wrap {
  flex: 0 0 auto;
  display: flex;
  justify-content: center;
}

.label-preview {
  /* Was 240x360 before the Items/Date/Weight/Volume info strip was added,
     then 280x420 once that row shipped (same 4:6 aspect ratio kept
     exactly each time) — bumped again for the SGN/ATL signature-
     indicator line added below FROM, which the 280x420 card clipped at
     its own bottom edge (confirmed via a real Playwright screenshot
     before this change, same "not enough room" failure mode as the
     first bump). */
  width: 300px;
  height: 450px;
  aspect-ratio: 4 / 6;
  background-color: #ffffff;
  color: #000000;
  border: 2px solid #000000;
  border-radius: 3px;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  font-family: ui-sans-serif, "IBM Plex Sans", sans-serif;
  box-shadow: 0 8px 20px -10px rgba(20, 18, 12, 0.4);
  overflow: hidden;
}

.label-preview.label-preview-a4 {
  aspect-ratio: 210 / 297;
  /* Same -20px-vs-base relationship every earlier size bump has kept
     (240x360 → 340; 280x420 → 400; now 300x450 → 430) — not a literal
     true-A4-ratio height (this preview already only approximates that,
     since `width` isn't adjusted for A4's own aspect ratio either), just
     enough shorter than the thermal-label preview to read as "a bigger
     sheet of paper," while still fitting the full card content (Items/
     Date/Weight/Volume row, SGN/ATL line) without crushing the QR code —
     confirmed via a real Playwright screenshot in both label-size modes. */
  height: 430px;
}

.label-preview-brand-row {
  flex: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
  border-bottom: 2px solid #000000;
  padding-bottom: 4px;
}

.label-preview-brand-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.label-preview-brand-name {
  font-weight: 800;
  font-size: 0.8rem;
  line-height: 1.1;
  overflow-wrap: break-word;
}

.label-preview-tagline {
  font-size: 0.46rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #333333;
}

.label-preview-logo-slot {
  flex: none;
  width: 26px;
  height: 26px;
}

.label-preview-logo {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.label-preview-logo-placeholder {
  border: 1px dashed #999999;
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.4rem;
  font-weight: 700;
  color: #999999;
  letter-spacing: 0.02em;
}

.label-preview-barcode-band {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
}

.label-preview-barcode {
  /* Deliberately NO width/height here — see renderCode128Barcode()'s own
     comment in static/admin.js. That function computes a module width so
     the barcode's own generated SVG attributes are already the exact final
     size; any CSS resize here (even a "proportional" one) would force the
     browser to rasterize bar edges at fractional pixel positions, which
     can make an otherwise-valid Code128 barcode fail on a real scanner
     even though it still looks fine on screen. The svg renders at its own
     natural size and is centered by .label-preview-barcode-band's
     align-items: center above. */
  display: block;
}

.label-preview-tracking-text {
  text-align: center;
  font-family: ui-monospace, "IBM Plex Mono", monospace;
  font-weight: 700;
  font-size: 0.56rem;
  letter-spacing: 0.03em;
}

.label-preview-rule {
  flex: none;
  width: 100%;
  border: none;
  border-top: 2px solid #000000;
  margin: 0;
}

.label-preview-body {
  flex: 1;
  display: flex;
  flex-direction: row;
  gap: 6px;
  font-size: 0.5rem;
  line-height: 1.25;
  min-height: 0;
  overflow: hidden;
}

.label-preview-col-left,
.label-preview-col-right {
  flex: 1 1 0;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.label-preview-col-right {
  gap: 3px;
}

.label-preview-field-label {
  display: inline-block;
  background-color: #000000;
  color: #ffffff;
  font-weight: 700;
  font-size: 0.42rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 1px 4px;
  border-radius: 2px;
  margin-bottom: 2px;
}

.label-preview-cjk {
  font-weight: 700;
  opacity: 0.85;
}

.label-preview-name {
  font-weight: 600;
  font-size: 0.54rem;
  margin-bottom: 1px;
}

.label-preview-address {
  margin-bottom: 2px;
}

.label-preview-phone {
  font-family: ui-monospace, "IBM Plex Mono", monospace;
}

.label-preview-divider {
  border: none;
  border-top: 1px solid #000000;
  margin: 4px 0;
}

.label-preview-signature-indicator {
  /* SGN/ATL — scaled-down mirror of templates/label.html's own
     .label-signature-indicator (2.3rem in the real 4in-wide label; this
     card is ~280px vs. the real ~384px @96dpi, so scaled proportionally). */
  margin-top: auto;
  font-family: Georgia, "Times New Roman", serif;
  font-weight: 700;
  font-size: 1.3rem;
  line-height: 1;
}

.label-preview-mini-box {
  flex: none;
  border: 1px solid #000000;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.label-preview-mini-header {
  flex: none;
  background-color: #000000;
  color: #ffffff;
  font-weight: 700;
  font-size: 0.38rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 1px 4px;
  display: flex;
  justify-content: space-between;
  gap: 4px;
}

.label-preview-mini-body {
  padding: 2px 4px;
  font-size: 0.46rem;
  line-height: 1.2;
}

.label-preview-id-number {
  font-family: ui-monospace, "IBM Plex Mono", monospace;
  font-weight: 700;
  font-size: 0.95rem;
  text-align: center;
  padding: 1px 0 2px;
}

.label-preview-qr-box {
  flex: 1 1 0;
  min-height: 0;
}

.label-preview-qr-wrap {
  flex: 1;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
}

.label-preview-qr-wrap img,
.label-preview-qr-wrap canvas,
.label-preview-qr-wrap table {
  width: auto !important;
  height: auto !important;
  max-width: 100%;
  max-height: 100%;
}

.label-preview-info-table {
  flex: none;
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.label-preview-info-table th,
.label-preview-info-table td {
  border: 1px solid #000000;
  padding: 2px 3px;
  text-align: left;
  vertical-align: top;
  overflow: hidden;
}

.label-preview-info-table th {
  font-size: 0.34rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.label-preview-info-table td {
  font-size: 0.44rem;
  font-weight: 700;
}

.label-preview-info-sub {
  display: block;
  font-size: 0.32rem;
  font-weight: 400;
  color: #444444;
}

.label-preview-footer {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  border-top: 2px solid #000000;
  padding-top: 4px;
  font-size: 0.36rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.admin-inline-wide-input {
  min-width: 240px;
}

#drivers-empty-state {
  padding: 24px 0;
  text-align: center;
  color: #777777;
  font-size: 0.95rem;
}

/* ---- Generic admin modal (currently just the package-edit form) — a
   centered dialog rather than driver-side #failure-reason-overlay's
   bottom sheet, since the admin UI is desktop-first, but still constrained
   to fit a phone-width viewport (max-height + its own scroll). ---- */
.admin-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 16px;
}

.admin-modal-overlay[hidden] {
  display: none;
}

.admin-modal {
  width: 100%;
  max-width: 420px;
  max-height: 90vh;
  overflow-y: auto;
  background: #ffffff;
  border-radius: 16px;
  padding: 20px;
  box-sizing: border-box;
}

.admin-modal h2 {
  margin: 0 0 12px;
  font-size: 1.1rem;
}

.admin-modal-field {
  display: block;
  margin-bottom: 14px;
}

.admin-modal-field span {
  display: block;
  font-size: 0.8rem;
  font-weight: 700;
  color: #555555;
  margin-bottom: 4px;
}

.admin-modal-field input,
.admin-modal-field textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  font-size: 0.95rem;
  box-sizing: border-box;
  font-family: inherit;
}

.admin-modal-field textarea {
  min-height: 60px;
  resize: vertical;
}

.admin-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 4px;
}

/* ---- Assignment tab: bulk action bar + row checkboxes ---- */

/* One row per action (assign/unassign share a row; return-to-warehouse,
   return-to-customer, and close each get their own) instead of every
   control from every action crammed into a single wrapping line — that's
   what made this bar hard to scan once it grew past three actions. A
   labeled row reads like a small form: label column, then that action's
   own inputs, then its button. */
#admin-bulk-bar {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
  padding: 14px 16px;
  background-color: #eef2ff;
  border-radius: 10px;
}

#admin-bulk-bar[hidden] {
  display: none;
}

#admin-bulk-bar-header {
  display: flex;
  align-items: center;
}

#admin-selected-count {
  font-weight: 700;
  font-size: 0.9rem;
  color: #283593;
}

.admin-bulk-action-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 10px;
}

.admin-bulk-action-label {
  flex: 0 0 170px;
  font-size: 0.8rem;
  font-weight: 700;
  color: #444444;
}

/* Separates the two everyday dispatch actions above (assign/unassign,
   return to warehouse — a parcel keeps working afterward) from the two
   terminal ones below (return to customer, close — a parcel's story ends
   there). The terminal actions also get their own red styling (see
   .action-btn-bulk-danger) and a confirm() prompt before they run — this
   divider is the grouping cue that motivates both. */
.admin-bulk-action-divider {
  border-top: 1px solid #c5cae9;
  margin: 2px 0;
}

.admin-bulk-action-row input[type="text"],
.admin-bulk-action-row select {
  padding: 8px 10px;
  border: 1px solid #cccccc;
  border-radius: 6px;
  background-color: #ffffff;
  font-size: 0.85rem;
  flex: 1 1 180px;
  min-width: 120px;
}

/* .action-btn's own defaults (flex:1, min-height:46px) are sized for the
   driver app's full-width mobile buttons — every button in this bar needs
   its own compact size instead, same reasoning as .admin-filters-bar
   .action-btn above. */
#admin-bulk-bar .action-btn {
  flex: none;
  min-height: auto;
  padding: 10px 16px;
}

/* Same solid-fill, white-text format as .action-btn-primary (Assign
   Selected), and the same dark-blue family too — these two read as one
   consistent group with Assign, distinguished only by their label text,
   since both are reversible, everyday dispatch actions (unassigning, or
   sending a parcel back to the warehouse pool, doesn't end its story —
   see .admin-bulk-action-divider's own comment). Scoped to this bar, not
   a redefinition of .action-btn-secondary itself — every other
   "Cancel"/"Reset Password" use elsewhere in the admin UI is untouched.
   #0d47a1 is .action-btn-primary's own :active shade reused here as a
   slightly darker resting color, so Assign still reads as the one
   primary action while Unassign/Return stay clearly blue, not grey.
   Return to Client / Close Selected do NOT use this class — see
   .action-btn-bulk-danger below, they're deliberately styled apart from
   this group. */
.action-btn-bulk-secondary,
.action-btn-warehouse-return {
  background-color: #0d47a1;
  color: #ffffff;
}

.action-btn-bulk-secondary:active,
.action-btn-warehouse-return:active {
  background-color: #08306b;
}

/* Return to Client / Close Selected — the two terminal, hard-to-reverse
   bulk actions below .admin-bulk-action-divider. Deliberately broken out
   of the shared blue family above: these end a parcel's story rather than
   just moving it around, so a click here should look, and (see
   handleBulkReturnToCustomer()/handleBulkClose() in admin.js, both now
   gated behind a confirm() prompt) behave, as a different kind of action
   than Assign/Unassign/Return to Warehouse. Reuses the same red this tab
   already uses for Failed/Closed status text (.admin-status-failed/
   .admin-status-closed) rather than introducing a new color. */
.action-btn-bulk-danger {
  background-color: #c62828;
  color: #ffffff;
}

.action-btn-bulk-danger:active {
  background-color: #8e1c1c;
}

/* ---- Delivery records tab ---- */

#records-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

#records-table th,
#records-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #eeeeee;
  white-space: nowrap;
}

#records-table th {
  color: #666666;
  font-weight: 700;
}

#records-table tbody tr:not(.records-detail-row) {
  cursor: pointer;
}

.records-toggle-btn {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 0.9rem;
  padding: 0 4px;
  color: #283593;
}

.records-detail-row[hidden] {
  display: none;
}

.records-detail-content {
  padding: 10px 14px;
  background-color: #fafafa;
  border-radius: 8px;
  font-size: 0.8rem;
  color: #444444;
  white-space: normal;
}

.records-event-list {
  margin: 0;
  padding-left: 18px;
}

.records-event-list li {
  margin-bottom: 4px;
}

#records-empty-state {
  padding: 24px 0;
  text-align: center;
  color: #777777;
  font-size: 0.95rem;
}

/* ---- Pickup scanning page ---- */

#pickup-page {
  max-width: 480px;
  margin: 0 auto;
  padding: 20px 16px 48px;
}

#pickup-progress-bar {
  display: flex;
  justify-content: space-between;
  background-color: #1a1a1a;
  border-radius: 14px;
  padding: 16px 10px;
  margin-bottom: 20px;
}

.pickup-stat {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.pickup-stat-value {
  font-size: 1.6rem;
  font-weight: 800;
  color: #ffffff;
}

.pickup-stat-label {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #aaaaaa;
  text-transform: uppercase;
}

#pickup-scanner-area {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 20px;
}

#qr-reader {
  width: 100%;
  min-height: 250px;
  border-radius: 14px;
  overflow: hidden;
  background-color: #000000;
}

/* html5-qrcode injects its own <video>/<canvas> — force them to fill this
   container rather than keep the library's own inline sizing, which can
   otherwise render narrower than #qr-reader on some mobile browsers. */
#qr-reader video,
#qr-reader canvas {
  width: 100% !important;
}

#pickup-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 22px 16px;
  border-radius: 14px;
  margin-bottom: 20px;
  text-align: center;
  transition: background-color 0.15s ease;
}

#pickup-result-icon {
  font-size: 2.4rem;
  line-height: 1;
}

#pickup-result-title {
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}

#pickup-result-tracking {
  font-size: 0.95rem;
  font-weight: 700;
}

#pickup-result-address {
  font-size: 0.85rem;
  color: #555555;
}

#pickup-result-reason {
  font-size: 0.85rem;
  font-weight: 700;
  margin-top: 4px;
}

#pickup-result-reason:empty {
  display: none;
}

.pickup-result-idle {
  background-color: #f2f2f2;
  color: #666666;
}

.pickup-result-success {
  background-color: #e8f5e9;
  color: #1b5e20;
}

.pickup-result-success #pickup-result-address {
  color: #2e7d32;
}

.pickup-result-warning {
  background-color: #fff8e1;
  color: #e65100;
}

.pickup-result-warning #pickup-result-address {
  color: #ef6c00;
}

.pickup-result-error {
  background-color: #ffebee;
  color: #b71c1c;
}

.pickup-result-error #pickup-result-address {
  color: #c62828;
}

#pickup-manual-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

#pickup-manual-form .login-label {
  margin-top: 0;
}

#pickup-manual-submit-btn {
  width: 100%;
}

/* ---- Driver home page: the two main entry points (Pickup / Delivery) ---- */

.home-body {
  background-color: #f2f2f2;
  overflow-y: auto;
  height: auto;
}

#home-page {
  max-width: 420px;
  margin: 0 auto;
  min-height: 100%;
  display: flex;
  flex-direction: column;
  padding: 0 16px 32px;
}

#home-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 20px 0;
  padding-top: max(20px, env(safe-area-inset-top));
}

#home-title {
  font-size: 1.2rem;
  font-weight: 800;
  color: #1a1a1a;
}

#home-cards {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: 12px;
}

.home-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 36px 20px;
  border-radius: 20px;
  text-decoration: none;
  color: #ffffff;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15);
}

.home-card:active {
  transform: scale(0.98);
}

.home-card-pickup {
  background: linear-gradient(135deg, #1565c0, #283593);
}

.home-card-delivery {
  background: linear-gradient(135deg, #2e7d32, #1b5e20);
}

.home-card-icon {
  font-size: 2.6rem;
  line-height: 1;
}

.home-card-title {
  font-size: 1.3rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.home-card-count {
  font-size: 0.95rem;
  font-weight: 600;
  opacity: 0.9;
}

#home-records-link {
  display: block;
  text-align: center;
  margin-top: 28px;
  color: #1565c0;
  font-weight: 600;
  font-size: 0.9rem;
  text-decoration: none;
}

/* ---- Customer Portal ----------------------------------------------------
   Deliberately reuses the admin dispatch tool's plain, light "back-office"
   look (.import-body/#import-header-bar/.action-btn/.admin-table-scroll
   etc, all already defined above) rather than the driver map's dark
   status-bar aesthetic — see CLAUDE.md's Customer Portal section: "Do not
   make Customer Portal look like the Driver map UI." Only genuinely new
   pieces (the nav bar, stat tiles, and the 6-way status badge palette) get
   their own rules here. */

#customer-nav {
  display: flex;
  gap: 4px;
  padding: 10px 16px;
  background-color: #ffffff;
  border-bottom: 1px solid #eeeeee;
  overflow-x: auto;
}

.customer-nav-link {
  padding: 8px 12px;
  border-radius: 8px;
  color: #555555;
  font-weight: 600;
  font-size: 0.85rem;
  text-decoration: none;
  white-space: nowrap;
}

.customer-nav-link-active {
  background-color: #eef0fb;
  color: #283593;
}

#customer-page {
  max-width: 900px;
  width: 100%;
  margin: 0 auto;
  padding: 16px;
  padding-bottom: 40px;
  overflow-x: hidden;
}

/* Dashboard summary: a donut chart (order-status breakdown) beside the
   existing stat-tile grid, in one card — same "donut + tiles" shape as the
   admin Overview tab's own summary (see #overview-donut-wrap/#overview-
   stats in this file), kept as separate customer-* rules rather than
   reused directly since the two pages are otherwise deliberately styled
   independently (see this section's own top-of-file note). Segment/tile
   colors reuse .customer-status-*'s own hexes exactly — a state, not a
   series identity, so it takes the status-color job (same reasoning as
   the admin donut). */
/* Amount statistics ("金额统计") — the sum of Package.quoted_price across
   this customer's orders in the currently-selected date range (see
   crud.get_customer_status_counts()'s total_quoted_amount/priced_order_
   count/unpriced_order_count). Deliberately its own card, not squeezed
   into .customer-stat-grid below — a currency total reads as a different
   kind of number from a plain order count, and giving it its own visual
   weight makes it scannable at a glance rather than one tile among many. */
.customer-amount-card {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 16px;
  background-color: #eef7f0;
  border: 1px solid #cfe8d4;
  border-radius: 14px;
  padding: 16px 18px;
  margin-bottom: 16px;
}

.customer-amount-main {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.customer-amount-value {
  font-size: 1.9rem;
  font-weight: 800;
  color: #2e7d32;
}

.customer-amount-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: #4a4a4a;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.customer-amount-note {
  font-size: 0.8rem;
  color: #666666;
}

.customer-order-price-pending {
  color: #e65100;
  font-style: italic;
}

.customer-summary-card {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
  background-color: #ffffff;
  border: 1px solid #eeeeee;
  border-radius: 14px;
  padding: 18px;
  margin-bottom: 20px;
}

#customer-donut-wrap {
  position: relative;
  flex: none;
  width: 96px;
  height: 96px;
}

#customer-donut {
  width: 96px;
  height: 96px;
}

#customer-donut-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

#customer-donut-percent {
  font-size: 1.25rem;
  font-weight: 800;
  color: #1a1a1a;
  line-height: 1.1;
}

#customer-donut-caption {
  font-size: 0.62rem;
  color: #777777;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.customer-stat-grid {
  flex: 1 1 260px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.customer-stat-tile-pending .customer-stat-value {
  color: #e65100;
}

.customer-stat-tile-assigned .customer-stat-value {
  color: #1565c0;
}

.customer-stat-tile-picked-up .customer-stat-value {
  color: #5e35b1;
}

.customer-stat-tile-delivered .customer-stat-value {
  color: #2e7d32;
}

.customer-stat-tile-failed .customer-stat-value {
  color: #c62828;
}

.customer-stat-tile-cancelled .customer-stat-value {
  color: #757575;
}

@media (min-width: 560px) {
  .customer-stat-grid {
    grid-template-columns: repeat(6, 1fr);
  }
}

.customer-stat-tile {
  background-color: #ffffff;
  border: 1px solid #eeeeee;
  border-radius: 10px;
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.customer-stat-tile-clickable {
  cursor: pointer;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

.customer-stat-tile-clickable:hover,
.customer-stat-tile-clickable:focus-visible {
  background-color: #f0f2ff;
  border-color: #c5cbff;
  outline: none;
}

.customer-stat-value {
  font-size: 1.5rem;
  font-weight: 800;
}

.customer-stat-label {
  font-size: 0.75rem;
  color: #666666;
  text-align: center;
}

/* One color per customer-facing status — a STATE (what's happening to
   this order right now), not a series-identity palette, so each key below
   reuses this app's existing status-color convention where one already
   exists (delivered/failed match admin-status-delivered/failed exactly)
   and picks a clearly distinct hue for the three in-progress states. */
.customer-status-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  white-space: nowrap;
}

.customer-status-awaiting_dispatch {
  background-color: #fff3e0;
  color: #e65100;
}

.customer-status-assigned {
  background-color: #e3f2fd;
  color: #1565c0;
}

.customer-status-out_for_delivery {
  background-color: #ede7f6;
  color: #5e35b1;
}

.customer-status-delivered {
  background-color: #e8f5e9;
  color: #2e7d32;
}

.customer-status-failed {
  background-color: #ffebee;
  color: #c62828;
}

.customer-status-cancelled {
  background-color: #f5f5f5;
  color: #757575;
}

/* Same visual language as #admin-bulk-bar (light-indigo card, bold count,
   the shared .action-btn-bulk-secondary blue) — see that rule's own
   comment for why this shade family is used for routine, reversible bulk
   actions like these two. */
#orders-bulk-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 14px;
  margin-bottom: 16px;
  padding: 14px 16px;
  background-color: #eef2ff;
  border-radius: 10px;
}

#orders-selected-count {
  font-weight: 700;
  font-size: 0.9rem;
  color: #283593;
}

#orders-bulk-bar .action-btn {
  flex: none;
  min-height: auto;
  padding: 10px 16px;
}

#customer-orders-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

#customer-orders-table th,
#customer-orders-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid #eeeeee;
}

#customer-orders-table th {
  color: #666666;
  font-weight: 700;
}

.customer-order-detail-row[hidden] {
  display: none;
}

.customer-order-detail-content {
  padding: 10px 14px;
  background-color: #fafafa;
  border-radius: 8px;
  font-size: 0.85rem;
  color: #444444;
}

.customer-timeline {
  margin: 0 0 10px 0;
  padding-left: 18px;
}

.customer-timeline li {
  margin-bottom: 4px;
}

.customer-pod-photos {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.customer-pod-photos img {
  width: 84px;
  height: 84px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid #dddddd;
}

#customer-order-form,
#customer-profile-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 480px;
}

#customer-order-form label,
#customer-profile-form label {
  font-size: 0.85rem;
  font-weight: 600;
  color: #444444;
  margin-bottom: -8px;
}

#customer-order-form input,
#customer-order-form textarea,
#customer-profile-form input,
#customer-profile-form textarea {
  padding: 12px;
  border: 1px solid #cccccc;
  border-radius: 8px;
  background-color: #fafafa;
  font-size: 0.95rem;
  font-family: inherit;
}

/* Overrides the generic "#customer-order-form label" rule above (bold,
   negative margin to hug the field below it) — a checkbox label sits
   inline with its own control instead of stacked above a separate input. */
.order-checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 0 !important;
  font-weight: 500 !important;
}

.order-checkbox-label input[type="checkbox"] {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

/* Live price preview on the order-creation form (POST /api/customer/quote)
   — deliberately a plain, always-visible box rather than a modal/tooltip,
   since it updates automatically as the customer types (see
   scheduleQuotePreview() in customer-order-new.js), not on demand. */
.order-quote-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background-color: #f4f5f7;
  border: 1px solid #e0e0e0;
  border-radius: 10px;
  padding: 12px 14px;
  margin: 4px 0 16px 0;
}

#order-quote-label {
  font-weight: 700;
  font-size: 0.85rem;
  color: #444444;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

#order-quote-value {
  font-weight: 700;
  font-size: 1.1rem;
  color: #555555;
  text-align: right;
}

#order-quote-value.order-quote-value-priced {
  color: #2e7d32;
  font-size: 1.3rem;
}

#order-quote-value.order-quote-value-pending {
  color: #e65100;
  font-size: 0.85rem;
  font-weight: 500;
}

#order-quote-value.order-quote-value-error {
  color: #c62828;
  font-size: 0.85rem;
  font-weight: 500;
}

#customer-import-summary {
  margin-top: 16px;
}

.customer-import-summary-row {
  display: flex;
  gap: 16px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.customer-import-summary-stat {
  font-size: 0.9rem;
}

.customer-import-summary-stat b {
  font-size: 1.1rem;
}

.customer-cta-link {
  display: block;
  text-align: center;
  text-decoration: none;
  max-width: 260px;
}

#customer-import-form {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 12px;
}

#customer-import-errors-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

#customer-import-errors-table th,
#customer-import-errors-table td {
  text-align: left;
  padding: 6px 10px;
  border-bottom: 1px solid #eeeeee;
}

#customer-import-errors-table th {
  color: #666666;
  font-weight: 700;
}

/* Admin/dispatcher Create Orders tab's own bulk-import summary — same
   rules as #customer-import-summary/#customer-import-errors-table above,
   just under this tab's own element ids. */
#admin-import-summary {
  margin-top: 16px;
}

#admin-import-errors-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

#admin-import-errors-table th,
#admin-import-errors-table td {
  text-align: left;
  padding: 6px 10px;
  border-bottom: 1px solid #eeeeee;
}

#admin-import-errors-table th {
  color: #666666;
  font-weight: 700;
}
