/* Self-hosted fonts — SIL Open Font License 1.1, see /fonts/OFL.txt.
   Served from this origin so the app makes zero third-party font requests
   (no Google Fonts connection). Latin subset only. */
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("../fonts/manrope-latin.woff2") format("woff2");
}
@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/dmmono-400-latin.woff2") format("woff2");
}
@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/dmmono-500-latin.woff2") format("woff2");
}

:root {
  /* SiteStock editorial palette — blue / orange / brown on warm paper.
     Variable names are kept from the original stylesheet (--navy, --bg,
     --card, …) so every existing rule and every class/id the JS touches
     keeps working; only the values changed. */
  --navy: #12344a;
  --navy-light: #17607f;
  --orange: #f26a2e;
  /* --orange-dark is the text/UI-safe orange: ~5:1 with white, ~4.4:1 as a
     focus outline on the light backgrounds. Bright --orange only clears
     ~3:1 on white, so it is kept for decorative fills and hover tints
     only — see the contrast block at the end of this file. */
  --orange-dark: #bd4c14;
  /* bg/card/border/text/text-muted below are the landing page's own
     neutral tokens (--landing-paper/-white/-line/-ink/-muted in
     landing.css) — matched 2026-09-14 so the logged-in app reads as the
     same design system as the marketing homepage, not just a sibling with
     the same accent colours. Every accent below (navy/orange/brown/sand)
     already matched landing.css byte-for-byte before this change; only
     the neutrals were still the older, warmer palette. Dark mode further
     down is deliberately NOT re-matched to landing — landing has no dark
     variant to copy, so dark mode keeps its own pre-existing warm-dark
     tokens rather than guessing at an unreviewed palette. */
  --bg: #f3f2eb;
  --card: #ffffff;
  --border: rgba(17, 19, 16, 0.16);
  --text: #111310;
  --text-muted: #696c65;
  --green: #2e7d46;
  --red: #b23524;
  --radius: 0;

  --blue: #12344a;
  --brown: #65412e;
  --brown-dark: #3f291f;
  --sand: #d8c2ae;
  --paper: #f3f2eb;
  --sink: #ece9e0;

  /* Fixed "always dark navy panel with light writing on it" tokens (topbar,
     filled buttons, badges, the skip link) — deliberately NEVER redefined
     for dark mode below. --navy/--orange-dark themselves ARE redefined
     (they're used as ordinary foreground text/link/outline color dozens of
     times, which must lighten against a dark page background), but a
     handful of call sites pair the SAME variable with a hardcoded white/
     var(--paper) text color expecting it to stay put — redefining --navy
     there too would silently turn "white text on dark navy" into "white
     text on light navy" mid-theme-switch. These three exist so those call
     sites have a genuinely constant color to point at instead. */
  --navy-surface: #12344a;
  --on-navy-surface: #fffaf5;
  --orange-surface: #bd4c14;

  --sans: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "DM Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* --- Dark mode --------------------------------------------------------
   Simplified to a genuine black/white swap 2026-09-14, per explicit
   direction after the earlier warm-brown-inverted palette ("I don't like
   the dark mode that much"): page/card surfaces go to true black, text to
   true white, --navy (the heading/emphasis accent) also goes to white
   rather than a tinted blue. Two things are DELIBERATELY untouched here,
   both because they were already on fixed tokens that never vary by theme
   even before this change: the topbar (--navy-surface/--on-navy-surface)
   and every filled orange button (--orange-surface) — see those tokens'
   own comment further up. --orange/--orange-dark (hover tints, focus
   rings, non-button accents) are also left exactly as they were. White on
   black is the maximum possible contrast (21:1), so every text colour
   below clears WCAG AAA by a wide margin without needing a fresh
   per-token contrast check the way the previous palette did. Two ways in:
   the OS/browser's own dark-mode setting (automatic, matches "the one on
   my phone" with no action needed) or an explicit choice from the footer
   toggle (public/js/theme.js), which always wins over the system setting
   in either direction. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --navy: #ffffff;
    --navy-light: #6dd3c8;
    --orange: #ff8a52;
    --orange-dark: #ff7a33;
    --bg: #000000;
    --card: #000000;
    --border: rgba(255, 255, 255, 0.18);
    --text: #ffffff;
    --text-muted: #a8a8a8;
    --green: #4caf6e;
    --red: #e57468;

    --blue: #ffffff;
    --brown: #c9ad93;
    --brown-dark: #f2e8dc;
    --sand: #d8c2ae;
    --paper: #000000;
    --sink: #141414;
  }
}
:root[data-theme="dark"] {
  --navy: #ffffff;
  --navy-light: #6dd3c8;
  --orange: #ff8a52;
  --orange-dark: #ff7a33;
  --bg: #000000;
  --card: #000000;
  --border: rgba(255, 255, 255, 0.18);
  --text: #ffffff;
  --text-muted: #a8a8a8;
  --green: #4caf6e;
  --red: #e57468;

  --blue: #ffffff;
  --brown: #c9ad93;
  --brown-dark: #f2e8dc;
  --sand: #d8c2ae;
  --paper: #000000;
  --sink: #141414;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

.topbar[hidden] { display: none; }
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  background: var(--navy-surface);
  color: white;
  padding: 14px 20px;
  /* Positioning context for .notif-panel: it is anchored here (full viewport
     width) rather than to .notif-wrap, so the dropdown can be clamped inside
     the viewport gutters regardless of where .notif-wrap lands when the
     topbar wraps onto multiple rows. */
  position: relative;
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.brand-mark {
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.brand-sub {
  font-size: 0.85rem;
  color: #d8c2ae;
}

.role-btn {
  background: transparent;
  border: 1px solid rgba(255,255,255,0.3);
  color: white;
  padding: 8px 14px;
  border-radius: 0;
  font-size: 0.9rem;
  cursor: pointer;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.pill-btn {
  background: var(--navy-light);
  border: 2px solid rgba(255,255,255,0.25);
  color: white;
  height: 40px;
  padding: 0 18px;
  border-radius: 0;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.pill-btn:hover {
  border-color: rgba(255,255,255,0.7);
}

.pill-btn[hidden] {
  display: none;
}

.session-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.session-bar[hidden] {
  display: none;
}

.session-label {
  font-size: 0.9rem;
  font-weight: 600;
  color: white;
}

.session-actions {
  display: flex;
  gap: 8px;
}

.circle-btn {
  width: 40px;
  height: 40px;
  border-radius: 0;
  border: 2px solid rgba(255,255,255,0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  font-weight: 700;
  color: white;
  cursor: pointer;
}

.circle-btn:hover {
  border-color: rgba(255,255,255,0.7);
}

.circle-btn-community {
  background: var(--navy-light);
}

.circle-btn-account {
  width: auto;
  min-width: 76px;
  height: 40px;
  border-radius: 0;
  padding: 0 18px;
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  background: var(--orange);
  border-color: rgba(255,255,255,0.4);
}

.account-menu-wrap {
  position: relative;
}

.account-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 160px;
  z-index: 10;
}

.account-menu[hidden] {
  display: none;
}

.account-menu-item {
  background: none;
  border: none;
  text-align: left;
  padding: 9px 10px;
  border-radius: 0;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
}

.account-menu-item:hover {
  background: var(--bg);
}

.notif-wrap {
  /* Deliberately NOT a positioning context — see .notif-panel / .topbar. */
  position: static;
}

.notif-wrap[hidden] {
  display: none;
}

.circle-btn-notif {
  background: var(--navy-light);
  width: auto;
  padding: 0 16px;
  font-family: var(--mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  /* Anchor .notif-badge (a child of this button) to the button itself, now
     that .notif-wrap is no longer a positioning context. */
  position: relative;
}

/* Icon slots are text-only now — any that render empty collapse so they
   don't leave a phantom gap in their flex row. */
.activity-icon:empty,
.notif-row-icon:empty,
.role-select-icon:empty,
.product-preview-icon:empty,
.owner-product-icon:empty,
.variant-option-arrow:empty,
.route-arrow:empty,
.modal-icon:empty { display: none; }

.notif-badge {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 0;
  background: var(--red);
  color: white;
  font-size: 0.68rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  border: 2px solid var(--navy-surface);
}

.notif-badge[hidden] {
  display: none;
}

.notif-panel {
  /* Anchored to .topbar, not .notif-wrap (see .topbar). left + right are both
     pinned to the topbar's own horizontal padding (20px), so the panel's
     available band is always the full viewport minus those gutters; max-width
     then caps it at 340px and margin-left:auto pushes it to the right gutter.
     Result: panelLeft >= 20 and panelRight <= viewportWidth - 20 at every
     width, with no 100vw math and no overflow hacks. */
  position: absolute;
  top: calc(100% + 8px);
  left: 20px;
  right: 20px;
  width: auto;
  max-width: 340px;
  margin-left: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 0;
  z-index: 10;
  overflow: hidden;
}

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

.notif-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}

.notif-panel-header strong {
  font-size: 0.92rem;
  color: var(--text);
}

.notif-list {
  max-height: 360px;
  overflow-y: auto;
}

.notif-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}

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

.list-show-more {
  display: block;
  width: 100%;
  padding: 10px 14px;
  text-align: center;
  font-size: 0.85rem;
}

.delivery-shortfalls {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 4px 0 8px;
}

.shortfall-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
}

.shortfall-note {
  margin-left: 26px;
}

/* --- Order message threads (migration 0037) --- */
.msg-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 320px;
  overflow-y: auto;
  margin-bottom: 10px;
}

.msg-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border-radius: 0;
  background: var(--sink);
  font-size: 0.9rem;
}

.msg-row-mine {
  background: var(--sink);
}

.msg-meta {
  font-size: 0.75rem;
  color: var(--text-muted);
}

.msg-body {
  white-space: pre-wrap;
  word-break: break-word;
}

.msg-compose {
  display: flex;
  gap: 6px;
}

.msg-compose .msg-input {
  flex: 1;
}

.order-card-links {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

/* --- Delivery photos (migration 0039) --- */
.photo-strip {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: 6px 0;
}

.photo-thumb {
  display: block;
  width: 84px;
  height: 84px;
  border-radius: 0;
  overflow: hidden;
  background: var(--sink);
}

.photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.photo-upload-btn {
  display: inline-block;
  cursor: pointer;
}

/* --- Two-factor enrollment QR --- */
.mfa-qr {
  width: 180px;
  max-width: 100%;
  margin: 8px 0;
  background: #fff;
  padding: 8px;
  border-radius: 0;
}

.mfa-qr svg {
  display: block;
  width: 100%;
  height: auto;
}

.notif-row-unread {
  background: var(--sink);
}

.notif-row-icon {
  font-size: 1.1rem;
  flex-shrink: 0;
  margin-top: 2px;
}

.notif-row-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: left;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.notif-row-body strong {
  font-size: 0.85rem;
}

.notif-row-body span {
  font-size: 0.8rem;
  color: var(--text-muted);
  /* Some messages carry an explicit second line, e.g. a suspension/removal
     "\nReason: …" (migration 0023) — render it as a real line break. */
  white-space: pre-line;
}

.notif-row-time {
  font-size: 0.72rem !important;
  color: var(--text-muted);
}

.notif-row-toggle {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--orange);
  flex-shrink: 0;
  padding: 2px 4px;
}

.notif-row-delete {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  color: var(--text-muted);
  flex-shrink: 0;
  padding: 2px 4px;
}

.notif-row-delete:hover {
  color: var(--text);
}

.notif-panel-footer {
  padding: 10px 14px;
  border-top: 1px solid var(--border);
  text-align: center;
}

.order-card-highlight {
  outline: 3px solid var(--orange);
  outline-offset: 2px;
}

main#app {
  max-width: 720px;
  margin: 0 auto;
  padding: 20px 16px 60px;
}

/* The landing page is a full-bleed marketing layout, not a centered panel -
   main.js's showOnly() toggles this only while landing-view is active. */
main#app.app-full-bleed {
  max-width: none;
  margin: 0;
  padding: 0;
}

.view { display: none; }
.view.active { display: block; }

.panel {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 18px;
}

.settings-subhead {
  font-size: 0.95rem;
  margin: 22px 0 8px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

/* Multi-item orders (migration 0030) */
.order-items-list {
  list-style: none;
  margin: 6px 0;
  padding: 0;
}
.order-items-list li {
  padding: 4px 0;
  font-size: 0.9rem;
  border-bottom: 1px solid var(--border);
}
.order-items-list li:last-child { border-bottom: none; }
.edit-items-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.edit-item-qty { width: 70px; }
.edit-item-unit { color: var(--text-muted); font-size: 0.85rem; }
.cart-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 12px;
  margin-bottom: 12px;
  background: var(--navy-light, #eef2ff);
  border-radius: var(--radius);
  font-size: 0.9rem;
}
.cart-bar-actions { display: flex; align-items: center; gap: 10px; }
.settings-subhead:first-of-type {
  margin-top: 10px;
  padding-top: 0;
  border-top: none;
}

h1 { font-size: 1.4rem; margin: 0 0 6px; }
h2 { font-size: 1.15rem; margin: 0 0 4px; }

.hint { color: var(--text-muted); font-size: 0.9rem; margin: 0 0 14px; }

.search-input, .text-input {
  width: 100%;
  padding: 12px 14px;
  font-size: 1rem;
  border: 1px solid var(--text-muted);
  border-radius: 0;
  background: var(--sink);
  margin-bottom: 12px;
}

.search-input:focus, .text-input:focus {
  outline: none;
  border-color: var(--orange-dark);
}

/* Replaces two inline style="" attributes removed for the Content-Security-Policy. */
.text-input-upper { text-transform: uppercase; }
.settings-subhead-inline { display: inline; }

.text-input[readonly] {
  background: var(--bg);
  color: var(--text);
  cursor: default;
}

.text-input[readonly]:focus {
  border-color: var(--border);
}

.field-label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 6px;
}

.results-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.result-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  width: 100%;
  text-align: left;
  background: var(--sink);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 12px 14px;
  cursor: pointer;
  font-size: 0.95rem;
}

.result-card:hover {
  border-color: var(--orange);
  background: var(--sink);
}

.result-name { font-weight: 600; }
.result-meta { font-size: 0.8rem; color: var(--text-muted); }

.empty-hint { color: var(--text-muted); font-size: 0.9rem; }

.link-btn {
  background: none;
  border: none;
  color: var(--navy-light);
  font-size: 0.9rem;
  cursor: pointer;
  padding: 0 0 12px;
}

.variant-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.variant-option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: var(--sink);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 13px 16px;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.variant-option-radio {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  border-radius: 0;
  border: 2px solid var(--border);
  background: var(--card);
}

.variant-option-label {
  flex: 1 1 auto;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
  white-space: normal;
  overflow-wrap: anywhere;
}

.variant-option-arrow {
  flex: 0 0 auto;
  color: var(--text-muted);
  font-size: 1rem;
}

.variant-option:hover {
  border-color: var(--orange);
  background: var(--sink);
}

.variant-option:hover .variant-option-radio {
  border-color: var(--orange);
}

.variant-option:hover .variant-option-arrow {
  color: var(--orange-dark);
}

.variant-option-custom {
  border-style: dashed;
  background: transparent;
}

.variant-option-custom .variant-option-radio {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text-muted);
  border-style: dashed;
}

.variant-option-custom .variant-option-label {
  color: var(--text-muted);
  font-weight: 600;
}

.source-option .variant-option-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.source-name {
  font-weight: 700;
}

.source-meta {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-muted);
}

.source-distance {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
}

.source-availability {
  font-size: 0.78rem;
  font-weight: 700;
  margin-top: 2px;
}

.availability-today { color: var(--text); }
.availability-hours { color: var(--text); }
.availability-tomorrow { color: var(--text-muted); }

.availability-badge {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 0;
  white-space: nowrap;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
}

.product-preview {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--sink);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 16px;
}

.product-preview-icon {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.8rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 0;
}

.product-preview-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.product-preview-info span {
  font-size: 0.85rem;
  color: var(--text-muted);
}

.confirm-source-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.confirm-source-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.confirm-source-card .link-btn {
  padding: 8px 0 0;
}

.inline-link-btn {
  padding: 0;
  font-weight: 600;
  text-decoration: underline;
}

.small-hint {
  font-size: 0.78rem;
  margin: 0;
}

.variant-option-custom:hover .variant-option-radio {
  color: var(--orange-dark);
}

.custom-size-form {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.btn {
  border: none;
  border-radius: 0;
  padding: 12px 16px;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}

.btn-primary { background: var(--orange); color: white; }
.btn-primary:hover { background: var(--orange-dark); }

.btn-secondary { background: var(--navy-light); color: white; }

.btn-block { width: 100%; margin-top: 6px; }

.form-status { min-height: 1.2em; font-size: 0.88rem; margin-top: 8px; }
.form-status.error { color: var(--red); }
.form-status.success { color: var(--green); }

.checkbox-field {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.95rem;
  cursor: pointer;
  margin-bottom: 4px;
}

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

.hold-confirm-btn {
  position: relative;
  overflow: hidden;
  user-select: none;
  touch-action: none;
}

.hold-confirm-fill {
  position: absolute;
  inset: 0;
  width: 0%;
  background: var(--orange-surface);
  z-index: 0;
}

.hold-confirm-label {
  position: relative;
  z-index: 1;
}

.orders-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.order-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 12px 14px;
  background: var(--sink);
  flex-wrap: wrap;
}

.order-card-main {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.9rem;
}

.order-card-main span {
  color: var(--text-muted);
  font-size: 0.82rem;
}

.request-header {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}

.order-detail-link {
  margin-left: auto;
  white-space: nowrap;
  padding: 4px 0;
}

.requester-badge {
  flex: 0 0 auto;
  width: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-align: center;
}

.requester-avatar {
  width: 40px;
  height: 40px;
  border-radius: 0;
  background: var(--navy-surface);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  font-weight: 700;
  flex-shrink: 0;
}

.requester-name {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
  line-height: 1.15;
  word-break: break-word;
}

.order-price {
  font-weight: 700;
  color: var(--text) !important;
}

.product-preview-price {
  font-weight: 600;
  color: var(--orange-dark) !important;
}

/* Status badges: one austere outline treatment for every state, no fills
   or per-state colours. Only two exceptions carry meaning — a solid ink
   badge marks a finished order, a red outline marks a problem state. */
.status-badge {
  font-size: 0.75rem;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 0;
  white-space: nowrap;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--text-muted);
}

.status-delivered.status-badge,
.status-granted.status-badge {
  background: var(--navy-surface);
  color: var(--on-navy-surface);
  border-color: var(--navy-surface);
}

.status-rejected.status-badge,
.status-suspended.status-badge,
.status-cancelled.status-badge {
  color: var(--red);
  border-color: var(--red);
}

.driver-header-panel {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: flex-end;
  justify-content: space-between;
}

.driver-id { display: flex; flex-direction: column; gap: 6px; }
.driver-id label { font-size: 0.85rem; font-weight: 600; color: var(--text-muted); }
.driver-id input { padding: 8px 10px; border: 1px solid var(--border); border-radius: 0; }

.driver-location { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }

.location-status { font-size: 0.85rem; color: var(--text-muted); }
.location-status.ok { color: var(--green); }
.location-status.error { color: var(--red); }

.worker-header-panel {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.worker-header-panel label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-muted);
}

.worker-header-panel input {
  max-width: 320px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 0;
  font: inherit;
}

.owner-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
}

.owner-actions .btn {
  flex: 1;
}

.owner-product-icon {
  font-size: 1.1rem;
  margin-right: 2px;
}

.reject-form {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

/* Small explanatory line, e.g. above the Team suspend/remove reason field
   and under a suspended member's badge. */
.field-hint {
  display: block;
  font-size: 0.82rem;
  color: var(--text-muted, #5a6b7d);
  margin: 2px 0 6px;
  line-height: 1.35;
}

.btn-danger { background: var(--red); color: white; }

.link-btn-danger { color: var(--red); }

.reject-form-actions {
  display: flex;
  gap: 10px;
  margin-top: 8px;
}

.reject-form-actions .btn {
  flex: 1;
}

.rejection-reason {
  font-size: 0.82rem;
  color: var(--red);
  margin: 8px 0 0;
}

.btn-small {
  padding: 8px 12px;
  font-size: 0.85rem;
}

.revert-section {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.revert-countdown {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-muted);
}

.revert-note {
  font-size: 0.8rem;
  margin: 10px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.revert-final {
  color: var(--green);
  font-weight: 600;
}

.revert-expired {
  color: var(--text-muted);
}

.community-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.community-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 12px 14px;
  background: var(--sink);
  flex-wrap: wrap;
}

.community-card-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.community-card-info span {
  font-size: 0.8rem;
  color: var(--text-muted);
}

.role-select-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 6px;
}

.role-select-card {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  background: var(--sink);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.role-select-card:hover {
  border-color: var(--orange);
  background: var(--sink);
}

.role-select-icon {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 0;
}

.role-toggle-group {
  display: flex;
  gap: 8px;
  margin-bottom: 6px;
  flex-wrap: wrap;
}

.role-toggle-btn {
  flex: 1 1 0;
  min-width: 100px;
  background: var(--sink);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 12px 10px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  text-align: center;
}

.role-toggle-btn:hover {
  border-color: var(--orange);
  background: var(--sink);
}

.role-toggle-btn.active {
  border-color: var(--orange);
  background: var(--sink);
  box-shadow: inset 0 0 0 1px var(--orange);
}

/* Roadmap Step 2 — "Needed by" quick-choice control (Worker order create
   and edit). Layout deliberately mirrors .role-toggle-group/-btn above
   (flex-wrap row, min-width, orange active state) rather than introducing
   a new visual language, per the "reuse existing component styles"
   convention documented in CLAUDE.md. */
.needed-by-group {
  display: flex;
  gap: 8px;
  margin: 4px 0 10px;
  flex-wrap: wrap;
}

.needed-by-btn {
  flex: 1 1 0;
  min-width: 84px;
  min-height: 44px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  background: var(--sink);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 10px 8px;
  font: inherit;
  cursor: pointer;
  text-align: center;
}

.needed-by-btn:hover {
  border-color: var(--orange);
  background: var(--sink);
}

.needed-by-btn.active {
  border-color: var(--orange);
  background: var(--sink);
  box-shadow: inset 0 0 0 1px var(--orange);
}

.needed-by-btn-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}

.needed-by-btn-time {
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--text-muted);
}

.needed-by-custom {
  margin-bottom: 10px;
}

.needed-by-custom .text-input {
  width: 100%;
}

.order-needed-by {
  font-size: 0.8rem;
  color: var(--text-muted);
  font-weight: 500;
}

/* Roadmap Step 4 — order operations & status clarity. */

.order-next-action {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--navy-light);
}

/* Applied alongside .order-needed-by as a modifier — subtle emphasis only,
   matching the brief's "no huge warning banners" instruction. 'future' and
   'none' urgency keys deliberately have no class at all (deadline.js's
   urgencyLabel returns null for them), leaving the existing plain styling
   untouched for the common case. */
.urgency-overdue { color: var(--red); font-weight: 700; }
.urgency-asap { color: var(--orange-dark); font-weight: 700; }
.urgency-today { color: var(--orange-dark); font-weight: 600; }
.urgency-tomorrow { color: var(--navy-light); font-weight: 600; }

/* The Worker's inline expandable order history — reuses .link-btn's
   existing color/hover behavior via a shared class on the button, this
   class only adds the 44px tap target .link-btn doesn't itself guarantee
   (same convention as .needed-by-btn's own min-height, Roadmap Step 2). */
.order-history-toggle {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 0 4px;
}

.order-history {
  margin-top: 4px;
  padding-top: 6px;
  border-top: 1px solid var(--border);
}

.role-select-info {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.role-select-info span {
  font-size: 0.82rem;
  color: var(--text-muted);
}

.community-status-pending,
.community-status-declined,
.community-status-suspended {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--border);
  padding: 4px 10px;
  border-radius: 0;
  white-space: nowrap;
}

.community-status-declined {
  color: var(--red);
  border-color: var(--red);
}

/* One bordered block split by hairlines - not gapped cards. Collapsed
   borders (negative margin) so there's no leftover cell after the last
   tile. */
.dashboard-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 0;
  margin-top: 12px;
  border-top: 1px solid var(--border);
  border-left: 1px solid var(--border);
}

.stat-tile {
  background: var(--card);
  border: 1px solid var(--border);
  border-top: none;
  border-left: none;
  border-radius: 0;
  padding: 14px 12px;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.stat-tile-highlight {
  background: var(--sink);
}

.stat-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--navy);
}

.stat-label {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.activity-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.activity-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 4px;
  border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
}

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

.activity-icon {
  flex: 0 0 auto;
  font-size: 1rem;
}

.activity-text {
  flex: 1 1 auto;
  color: var(--text);
}

.activity-time {
  flex: 0 0 auto;
  font-size: 0.75rem;
  color: var(--text-muted);
  white-space: nowrap;
}

#account-status-btn {
  display: inline-block;
  margin: 2px 0 16px;
}

.profile-details {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 8px;
}

.profile-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.profile-label {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.profile-value {
  font-size: 1rem;
  color: var(--text);
}

.profile-communities {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.profile-data-list {
  margin: 4px 0;
  padding-left: 1.2em;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.92rem;
  color: var(--text-muted);
}

.profile-data-list li { line-height: 1.45; }

.profile-community-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 10px 12px;
  background: var(--sink);
}

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(31, 20, 15, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 100;
}

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

.modal-box {
  background: var(--card);
  border-radius: var(--radius);
  padding: 28px 24px;
  max-width: 380px;
  width: 100%;
  text-align: center;
}

.modal-icon {
  font-size: 2.4rem;
  display: block;
  margin-bottom: 8px;
}

.modal-box h2 {
  margin: 0 0 8px;
  font-size: 1.2rem;
}

.modal-box .hint {
  margin-bottom: 18px;
}

.notif-prefs-list {
  text-align: left;
  margin-bottom: 16px;
}

.notif-prefs-sub {
  margin: 0 0 4px 28px;
  display: flex;
  flex-direction: column;
}

.checkbox-field-sub {
  font-size: 0.88rem;
  margin-bottom: 2px;
}

.manual-postcode { display: flex; gap: 8px; margin-top: 8px; }
.manual-postcode .text-input { margin: 0; width: 180px; }

.driver-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}

/* A plain class rule of equal specificity beats the UA [hidden] rule — so
   #auth-tabs.hidden (password recovery / 2FA / confirm-your-email screens)
   needs this or it stays on screen. */
.driver-tabs[hidden] { display: none; }

.tab-btn {
  background: none;
  border: none;
  padding: 10px 14px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
}

.tab-btn.active {
  color: var(--navy);
  border-bottom-color: var(--orange);
  /* Weight change so the selected tab is distinguishable without relying
     on colour alone (WCAG 1.4.1). Pairs with aria-current="true", which
     the view modules set alongside .active. */
  font-weight: 800;
}

.driver-card {
  flex-direction: column;
  align-items: stretch;
}

.driver-route {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 10px 0;
  flex-wrap: wrap;
}

.route-step {
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 8px 12px;
  flex: 1;
  min-width: 160px;
}

.route-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  font-weight: 700;
}

.route-value { font-size: 0.9rem; font-weight: 600; }
.route-sub { font-size: 0.78rem; color: var(--text-muted); }
.route-pickup-estimate { color: var(--green); font-weight: 700; }
.route-dist { font-size: 0.78rem; color: var(--orange-dark); font-weight: 600; }
.route-maps-link { display: inline-block; margin-top: 4px; font-size: 0.8rem; color: var(--navy-light); text-decoration: none; min-height: 44px; line-height: 44px; }

.route-arrow {
  color: var(--text-muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.route-sub b {
  font-family: var(--mono);
  font-weight: 500;
  text-transform: uppercase;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
}

@media (max-width: 480px) {
  .driver-route { flex-direction: column; align-items: stretch; }
  .route-arrow { display: none; }
}

/* Roadmap Step 5 — Company Setup & Onboarding. */

.invite-link-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

.invite-link-row .text-input {
  margin: 0;
  flex: 1 1 auto;
  min-width: 0;
}

/* Checklist rows reuse .activity-item/.activity-text verbatim (both already
   flex:1 1 auto-friendly — see the shared history/activity list this
   already serves) — only the done/not-done state and the trailing CTA
   button are new here. */
.checklist-item-done .activity-text {
  color: var(--text-muted);
}

.site-assign-group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 14px;
  margin: 8px 0;
  padding: 8px;
  background: var(--bg);
  border-radius: 0;
}

.site-assign-group .field-label {
  flex: 1 0 100%;
  margin: 0 0 2px;
}

/* Compact inline variant of .checkbox-field for the site-assignment list —
   same 18px checkbox target, just tighter row spacing since several sit
   side by side rather than one per line. */
.checkbox-field-inline {
  margin-bottom: 0;
  font-size: 0.85rem;
}

/* .link-btn already has adequate horizontal padding; the checklist/people
   panel CTAs additionally need a real 44px tap target since they sit
   inline in an otherwise-dense list row (matching Roadmap Step 2/4's own
   .needed-by-btn/.order-history-toggle convention). */
#owner-setup-checklist-list .link-btn,
#owner-people-list .link-btn {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 0 4px;
}

@media (max-width: 480px) {
  .invite-link-row { flex-direction: column; align-items: stretch; }
  .site-assign-group { flex-direction: column; align-items: flex-start; }
}

/* ============================================================================
   EDITORIAL REDESIGN LAYER
   A single override block, kept at the end of the file so it wins on
   specificity ties without touching the feature-ordered rules above. It
   restyles the shared primitives — type scale, mono micro-labels, buttons,
   topbar, panels, cards, tabs, badges — to the SiteStock landing-page design
   language (Manrope + DM Mono, blue/orange/brown on warm paper, tight
   display headings). No class name or id changes; purely visual.

   Shape language (updated 2026-09-14 to match the actual, now-finished
   public/css/landing.css byte-for-byte, not just the general idea of it):
   structural containers — panels, cards, list rows, inputs, modals — stay
   perfectly square (var(--radius), always 0), exactly like landing.css's
   own .product-shell/.workflow-section/.site-layer-panel. Buttons, pills,
   toggle chips and status/availability badges get landing's soft 4px
   corner (its .button/.role-tag/.page-nav-button/.site-chip are all 4px).
   Round icon badges (avatar initials, role/product icon tiles, the notif
   count bubble) are true circles (50%), matching landing's .avatar/
   .role-letter/.crosshair. Never introduce a fourth radius value without
   updating this note — the whole point is these three are the only ones
   landing.css itself ever uses. */

/* --- Display headings: Manrope, heavy, tight tracking, blue ink --- */
h1, h2, h3,
#dashboard-title,
.modal-box h2 {
  font-family: var(--sans);
  color: var(--navy);
  letter-spacing: -0.02em;
  line-height: 1.12;
}
h1 { font-size: 1.55rem; font-weight: 800; letter-spacing: -0.035em; margin: 0 0 8px; }
h2 { font-size: 1.16rem; font-weight: 700; margin: 0 0 5px; }
h3 { font-size: 1rem; font-weight: 700; }

.hint { line-height: 1.5; }

/* --- Mono micro-labels: uppercase, tracked, small --- */
.brand-sub,
.session-label,
.field-label,
.profile-label,
.stat-label,
.route-label,
.notif-panel-header strong,
.settings-subhead,
.driver-id label,
.worker-header-panel label {
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 500;
}
.field-label,
.profile-label,
.stat-label,
.route-label,
.driver-id label,
.worker-header-panel label { font-size: 0.68rem; color: var(--text-muted); }
.settings-subhead {
  font-size: 0.72rem;
  color: var(--navy);
  letter-spacing: 0.12em;
}
.brand-sub { font-size: 0.62rem; letter-spacing: 0.14em; }
.session-label { font-size: 0.7rem; letter-spacing: 0.08em; }
.notif-panel-header strong { font-size: 0.7rem; letter-spacing: 0.12em; color: var(--navy); }

/* Numeric / timestamp fragments read better in mono too */
.activity-time,
.notif-row-time,
.revert-countdown,
.order-needed-by,
.order-next-action,
.route-dist,
.source-distance { font-family: var(--mono); letter-spacing: 0.01em; }

/* --- Topbar: flat dark blue field --- */
.topbar {
  background: var(--navy-surface);
  border-bottom: 1px solid rgba(216, 194, 174, 0.28);
}
.brand-mark {
  font-family: var(--sans);
  font-weight: 800;
  letter-spacing: -0.03em;
}

/* --- Buttons: mono caps, square, instant hover --- */
.btn,
.pill-btn,
.role-btn,
.circle-btn-account,
.tab-btn {
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 500;
}
.btn {
  border-radius: 4px;
  font-size: 0.82rem;
  padding: 13px 18px;
}
.btn-primary { box-shadow: none; }
.btn-primary:hover { background: var(--orange-dark); }
/* Disabled (e.g. "Create account" before the Terms box is ticked, or any
   button mid-request): clearly not pressable, and no hover lift. */
.btn:disabled,
.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}
.btn:disabled:hover,
.btn[disabled]:hover { transform: none; }
.btn-secondary {
  background: transparent;
  color: var(--navy);
  box-shadow: inset 0 0 0 1px var(--navy);
}
.btn-secondary:hover { background: var(--navy-surface); color: var(--on-navy-surface); }
.btn-danger:hover { background: #8f2b1d; }
.btn-small, .btn-block { font-size: 0.78rem; }
/* Mono caps + tracking widen labels — keep row-buttons from wrapping mid-word
   next to their input (the .invite-link-row pattern stacks on mobile anyway). */
.invite-link-row .btn { white-space: nowrap; flex: 0 0 auto; }

.pill-btn {
  border-radius: 4px;
  font-size: 0.72rem;
  background: rgba(255, 255, 255, 0.06);
  border-width: 1px;
}
.pill-btn:hover { background: rgba(255, 255, 255, 0.16); }
.circle-btn-account {
  border-radius: 4px;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
}
.circle-btn { border-width: 1px; border-radius: 4px; }
.circle-btn-community, .circle-btn-notif { background: rgba(255, 255, 255, 0.06); }

.link-btn { color: var(--navy-light); font-weight: 600; }
.link-btn:hover { color: var(--orange-dark); }

/* --- Tabs: mono caps, underline-select --- */
.driver-tabs { gap: 2px; border-bottom-width: 1px; }
.tab-btn {
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  padding: 11px 13px;
  border-bottom-width: 2px;
}
.tab-btn.active { color: var(--navy); border-bottom-color: var(--orange); }

/* --- Panels & cards: flat, 1px grid, sharp (structural containers stay
   square, matching landing.css's own product-shell/workflow-section/
   site-layer-panel etc — landing only rounds buttons/pills/badges/icon
   badges, never a card or panel) --- */
.panel {
  border-radius: var(--radius);
  box-shadow: none;
}
.result-card,
.variant-option,
.role-select-card,
.community-card,
.order-card,
.profile-community-row,
.stat-tile,
.product-preview,
.confirm-source-card {
  border-radius: 0;
}
.stat-value { font-weight: 800; letter-spacing: -0.02em; color: var(--navy); }
.stat-tile-highlight { border-color: var(--navy); }

/* --- Toggle chips + icon badges: landing's soft 4px / circle treatment
   (its .role-tag/.row-action/.button = 4px, its .avatar/.role-letter/
   .crosshair = 50%) — these read as buttons/badges, not cards, so they
   don't belong in the "stay square" group above. */
.role-toggle-btn,
.needed-by-btn {
  border-radius: 4px;
}
.role-select-icon,
.product-preview-icon,
.requester-avatar,
.notif-badge {
  border-radius: 50%;
}

/* Inputs: warm fill, square, orange focus ring. color is explicit here
   because form controls don't inherit body's color from the UA stylesheet
   (a real bug found live 2026-09-14: in dark mode the background went
   dark via --sink but the text stayed at the browser's own default input
   color, rendering password/email fields as invisible black-on-black). */
.search-input, .text-input,
.driver-id input,
.worker-header-panel input {
  border-radius: 0;
  background: var(--sink);
  color: var(--text);
}
.search-input:focus, .text-input:focus {
  border-color: var(--orange);
}

/* Cart bar (had a now-dark var fallback) — warm tint, not solid blue */
.cart-bar {
  background: var(--sink);
  border: 1px solid var(--border);
  color: var(--text);
}
.cart-bar strong { color: var(--navy); }

/* --- Status / availability chips: mono caps micro-type --- */
.status-badge,
.availability-badge,
.community-status-pending,
.community-status-declined,
.community-status-suspended {
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 500;
  font-size: 0.64rem;
  border-radius: 4px;
  padding: 4px 8px;
}

/* --- Modal: sharp card, heavier shadow --- */
.modal-box { border-radius: var(--radius); }

/* --- Focus visibility, palette-consistent --- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--orange-dark);
  outline-offset: 2px;
}

/* --- Contrast (WCAG 2.1 AA) ---------------------------------------------
   Bright --orange (#f26a2e) is ~3:1 on white — fine for a decorative fill
   or a hover tint, not for text, a focus ring, or a persistent selected
   state. Those all use --orange-dark (#bd4c14): ~5:1 with white, ~4.4:1
   as a UI outline on the light grounds. Everything else in the palette
   was checked and passes (body text ~16.6:1, muted text ~4.8:1 against
   --bg / ~5.3:1 against --card — both re-verified after the 2026-09-14
   neutral-token swap to landing.css's ink/paper/muted values, since that
   changed --text/--text-muted/--bg/--card together — links ~6.2:1, every
   status chip >5:1). */
.btn-primary { background: var(--orange-surface); }
.btn-primary:hover { background: #9a3d0e; }
.circle-btn-account { background: var(--orange-surface); }
.tab-btn.active { border-bottom-color: var(--orange-dark); }
.search-input:focus,
.text-input:focus,
.driver-id input:focus,
.worker-header-panel input:focus { border-color: var(--orange-dark); }
.notif-row-toggle { color: var(--orange-dark); }
.order-card-highlight { outline-color: var(--orange-dark); }
.role-toggle-btn.active,
.needed-by-btn.active {
  border-color: var(--orange-dark);
  box-shadow: inset 0 0 0 1px var(--orange-dark);
}

/* --- Bootstrap holding screen --- */
#bootstrap-loading .panel { text-align: left; }

/* --- View-transition loading veil (main.js beginViewLoading) ---
   Sits above the content and the account/notification dropdowns (z 10) but
   below the modal overlay (z 100) and the skip link (z 200). */
#view-loading {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 22vh;
  background: rgba(247, 239, 230, 0.72);
  /* Purely a visual cue - never intercept clicks, so a stuck transition
     (hung backend) can't lock the user out of the topbar. */
  pointer-events: none;
}
#view-loading[hidden] { display: none; }
.view-loading-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 18px;
  background: var(--card);
  border: 1px solid var(--border);
  font: 500 0.8rem var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.view-loading-spinner {
  width: 13px;
  height: 13px;
  border: 2px solid var(--border);
  border-top-color: var(--orange);
  border-radius: 50%;
  animation: view-loading-spin 0.7s linear infinite;
}
@keyframes view-loading-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .view-loading-spinner { animation: none; border-top-color: var(--orange); }
  /* WCAG 2.3.3 / honour a reduced-motion preference everywhere: kill every
     transition/animation and force any programmatic smooth scroll
     (element.scrollIntoView, window.scrollTo) to jump instead. */
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto !important; }
}

/* --- Screen-reader-only text -----------------------------------------
   Visually removed but still in the accessibility tree - for labels,
   state ("completed" / "opens in a new tab") and the route-change
   announcement that would be visual clutter on screen. Standard clip
   pattern. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Programmatic focus target for the SPA route change and the skip link -
   the outline would flash on every navigation and adds nothing (the
   heading/announcement already convey the move). Keyboard focus rings on
   real controls are untouched - they use :focus-visible. */
#app:focus,
.view:focus { outline: none; }

/* --- "Email confirmed" acknowledgement bar (main.js showConfirmBanner) ---
   In normal flow at the very top of the page (pushes the topbar down while
   shown, no space when hidden) rather than a fixed overlay, so it never
   covers the topbar. */
#confirm-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 10px 16px;
  background: var(--green);
  color: #fff;
  font-size: 0.9rem;
  text-align: center;
}
#confirm-banner[hidden] { display: none; }
#confirm-banner button {
  flex: none;
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.5);
  color: #fff;
  font-size: 1rem;
  line-height: 1;
  padding: 2px 9px;
  cursor: pointer;
  border-radius: 4px;
}
#confirm-banner button:hover { background: rgba(255, 255, 255, 0.15); }

/* --- Sticky mobile CTA (authView.js) ---
   Off on desktop; on a narrow screen it shows only when authView.js clears
   [hidden] (register form visible), and never while the cookie notice is up. */
#sticky-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 110;
  display: none;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--card);
  border-top: 1px solid var(--border);
  box-shadow: 0 -2px 10px rgba(63, 41, 31, 0.12);
}
#sticky-cta .btn { margin: 0; }
@media (max-width: 640px) {
  #sticky-cta:not([hidden]) { display: block; }
  /* room to scroll past the real button without the sticky bar covering it */
  body.sticky-cta-open #register-form { padding-bottom: 72px; }
}
body.cookie-choice-pending #sticky-cta { display: none; }

/* --- Cookie / storage consent notice (cookieConsent.js) --- */
#cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 130;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px));
  background: var(--card);
  border-top: 2px solid var(--navy);
  box-shadow: 0 -3px 16px rgba(63, 41, 31, 0.18);
}
.cookie-banner-text {
  flex: 1 1 320px;
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text);
}
.cookie-banner-link { color: var(--navy-light); font-weight: 600; white-space: nowrap; }
.cookie-banner-actions {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.cookie-banner-actions .btn { margin: 0; }
@media (max-width: 560px) {
  .cookie-banner-actions { width: 100%; }
  .cookie-banner-actions .btn { flex: 1 1 auto; }
}

/* --- "Install app" prompt (pwaInstall.js) - same shape as #cookie-banner,
   deliberately, so the two never look like different UI systems even though
   they never actually show at the same time. --- */
#pwa-install-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 130;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px));
  background: var(--card);
  border-top: 2px solid var(--orange);
  box-shadow: 0 -3px 16px rgba(63, 41, 31, 0.18);
}
.pwa-install-text { flex: 1 1 320px; margin: 0; font-size: 0.85rem; line-height: 1.5; color: var(--text); }
.pwa-install-actions { flex: 0 0 auto; display: flex; flex-wrap: wrap; gap: 8px; }
.pwa-install-actions .btn { margin: 0; }
@media (max-width: 560px) {
  .pwa-install-actions { width: 100%; }
  .pwa-install-actions .btn { flex: 1 1 auto; }
}
/* Footer re-open control, injected by cookieConsent.js into .app-footer-links
   (uppercase mono) or .legal-footer (plain) - inherit so it matches either. */
.cookie-settings-btn {
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  background: none;
  border: none;
  padding: 0;
  color: var(--navy-light);
  font-weight: 600;
  cursor: pointer;
}
.cookie-settings-btn:hover { color: var(--orange-dark); }

/* Footer dark-mode switch + Save button, injected by theme.js. A real
   sliding switch (not this app's usual plain checkbox) since that's the
   familiar "phone settings" shape being matched here - softly rounded
   (4px) to match the landing-page shape language used elsewhere for
   interactive controls, not the typical fully-rounded stadium pill.
   Moving the switch only changes its own visual state; nothing is applied
   or persisted until Save is pressed (theme.js enables/disables Save based
   on whether the switch currently disagrees with what's actually applied). */
.theme-toggle-group {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 2px;
  min-height: 24px;
}
.theme-switch-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  color: inherit;
  cursor: pointer;
}
.theme-switch-label input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.theme-switch-track {
  position: relative;
  flex-shrink: 0;
  width: 40px;
  height: 22px;
  background: var(--sink);
  border: 1px solid var(--text-muted);
  border-radius: 4px;
}
.theme-switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: var(--text-muted);
  border-radius: 3px;
  transition: transform 0.15s ease, background-color 0.15s ease;
}
.theme-switch-label input:checked ~ .theme-switch-track .theme-switch-thumb {
  transform: translateX(18px);
  background: var(--on-navy-surface);
}
.theme-switch-label input:checked ~ .theme-switch-track {
  background: var(--navy-surface);
  border-color: var(--navy-surface);
}
.theme-switch-label input:focus-visible ~ .theme-switch-track {
  outline: 2px solid var(--orange-dark);
  outline-offset: 2px;
}
.theme-save-btn {
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  background: none;
  border: 1px solid var(--navy-light);
  padding: 3px 10px;
  min-height: 24px;
  color: var(--navy-light);
  font-weight: 600;
  cursor: pointer;
}
.theme-save-btn:hover:not(:disabled) { color: var(--orange-dark); border-color: var(--orange-dark); }
.theme-save-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.theme-save-status { font-weight: 600; color: var(--green); }

/* "Create an account" link sits inline in the auth intro sentence - drop
   .link-btn's standalone bottom padding so it doesn't push the line box. */
#auth-intro-register-btn { padding: 0; font-size: inherit; }

/* --- Global kill switch / maintenance screen (migration 0042) --- */
#kill-switch-panel {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--bg);
}
#kill-switch-panel[hidden] { display: none; }
#kill-switch-panel .panel { max-width: 32rem; text-align: left; }

/* --- Skip link (keyboard: first Tab reveals it) --- */
.skip-link {
  position: fixed;
  left: 12px;
  top: -60px;
  z-index: 200;
  background: var(--navy-surface);
  color: #fff;
  padding: 10px 16px;
  border-radius: 0;
  font: 500 0.85rem var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-decoration: none;
  transition: top 0.15s ease;
}
.skip-link:focus { top: 12px; }

/* --- App footer: operator identity + legal links (e-commerce regs) --- */
.app-footer {
  max-width: 720px;
  margin: 0 auto;
  padding: 22px 16px 48px;
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.8rem;
  line-height: 1.5;
}
.app-footer p { margin: 0 0 6px; }
.app-footer a { color: var(--navy-light); font-weight: 600; }
.app-footer a:hover { color: var(--orange-dark); }
.app-footer-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 14px;
  margin: 8px 0;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.72rem;
}
/* Give each footer legal link a real tap target (WCAG 2.5.8, 24px min) -
   they sit in a flex row, not a sentence, so the inline exception does
   not apply. Vertical padding + row-gap keeps 24px circles clear. */
.app-footer-links a,
.app-footer-links .cookie-settings-btn {
  display: inline-block;
  padding: 6px 2px;
  min-height: 24px;
}
.app-footer-a11y { margin-top: 12px; max-width: 62ch; }
.app-footer-a11y-label {
  display: block;
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.7rem;
  color: var(--text);
  margin-bottom: 3px;
}
.app-footer-note { font-size: 0.75rem; margin-top: 10px; }
.app-footer-feedback { font-size: 0.8rem; margin-top: 12px; }
.app-footer-feedback .link-btn { font-size: 0.8rem; }

/* Feedback modal */
#feedback-modal .modal-box { max-width: 460px; text-align: left; }
#feedback-input { min-height: 110px; resize: vertical; margin-bottom: 4px; font-family: inherit; }
#feedback-count { font-variant-numeric: tabular-nums; }

@media (max-width: 480px) {
  .tab-btn { font-size: 0.68rem; padding: 10px 9px; letter-spacing: 0.05em; }
  h1 { font-size: 1.35rem; }
}

/* ============================================================================
   LEGAL PAGES  (terms.html, privacy.html)
   Standalone documents — not part of the SPA. They pull in this same
   stylesheet for the palette/fonts/panel, and add the long-form reading
   styles below. No JS.
   ========================================================================= */
.legal-page { padding-top: 28px; }

.legal-doc {
  padding: 32px 30px 40px;
  line-height: 1.62;
}
.legal-doc > .link-btn { margin-bottom: 18px; }

.legal-kicker {
  font-family: var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.66rem;
  color: var(--orange-dark);
  margin: 0 0 6px;
}
.legal-doc h1 { font-size: 1.7rem; margin: 0 0 6px; }
.legal-meta {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--text-muted);
  letter-spacing: 0.02em;
  margin: 0 0 22px;
}

.legal-note {
  border: 1px solid var(--navy);
  background: transparent;
  border-radius: 0;
  padding: 12px 14px;
  font-size: 0.9rem;
  margin: 0 0 26px;
}
.legal-note strong { color: var(--navy); }

.legal-doc h2 {
  font-size: 1.02rem;
  margin: 28px 0 8px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
.legal-doc h2:first-of-type { border-top: none; padding-top: 0; }
.legal-doc h3 { font-size: 0.92rem; margin: 16px 0 4px; }

.legal-doc p { margin: 0 0 12px; }
.legal-doc ul, .legal-doc ol { margin: 0 0 12px; padding-left: 22px; }
.legal-doc li { margin-bottom: 6px; }
.legal-doc a { color: var(--navy-light); font-weight: 600; }
.legal-doc a:hover { color: var(--orange-dark); }

.legal-doc dl { margin: 0 0 12px; }
.legal-doc dt { font-weight: 700; color: var(--navy); margin-top: 10px; }
.legal-doc dd { margin: 2px 0 0; }

.legal-doc .data-table-wrap { overflow-x: auto; margin: 0 0 16px; }
.legal-doc table {
  border-collapse: collapse;
  width: 100%;
  min-width: 34rem;
  font-size: 0.86rem;
}
.legal-doc th,
.legal-doc td {
  border: 1px solid var(--border);
  padding: 7px 10px;
  text-align: left;
  vertical-align: top;
}
.legal-doc th { background: var(--sink); font-weight: 700; color: var(--navy); }

.legal-footer {
  margin-top: 30px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 0.85rem;
  color: var(--text-muted);
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

/* Signup agreement checkbox (index.html #register-form) */
#register-terms-field { align-items: flex-start; margin: 4px 0 12px; font-size: 0.9rem; }
#register-terms-field input[type="checkbox"] { margin-top: 2px; }
#auth-legal-links {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
  text-align: center;
}

/* The app otherwise uses .link-btn buttons, not anchors — give the few real
   <a>s in body copy (agreement line, legal-page cross-links, hint text) the
   palette treatment instead of the browser default blue. */
.hint a,
#register-terms-field a,
#auth-legal-links a,
.profile-value a {
  color: var(--navy-light);
  font-weight: 600;
  text-decoration: underline;
}
.hint a:hover,
#register-terms-field a:hover,
#auth-legal-links a:hover { color: var(--orange-dark); }

/* --- Password show/hide toggle (authView.js decorates every password
   field in #auth-view with one of these) --- */
.pw-field { position: relative; margin-bottom: 12px; }
.pw-field > .text-input { margin-bottom: 0; padding-right: 62px; }
.pw-toggle {
  position: absolute;
  top: 1px;
  right: 1px;
  bottom: 1px;
  width: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  border-left: 1px solid var(--border);
  border-radius: 0;
  color: var(--text-muted);
  cursor: pointer;
  font-family: var(--mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.pw-toggle:hover { color: var(--navy); }

/* --- Live password requirements (register form, authView.js) ---
   Neutral grey until a rule is met, then green; only the breach rule ever
   goes red. Shown from first render so the requirements are visible before
   the user starts typing. */
.pw-checklist {
  list-style: none;
  margin: 6px 0 10px;
  padding: 0;
  font-size: 0.8rem;
  color: var(--text-muted);
}
.pw-rule {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 2px 0;
}
.pw-rule-mark {
  flex: none;
  width: 1em;
  text-align: center;
  font-weight: 700;
  color: var(--text-muted);
}
.pw-rule-mark::before { content: "\25CB"; } /* ○ */
.pw-rule.met { color: var(--green); }
.pw-rule.met .pw-rule-mark { color: var(--green); }
.pw-rule.met .pw-rule-mark::before { content: "\2713"; } /* ✓ */
.pw-rule.fail { color: var(--red); }
.pw-rule.fail .pw-rule-mark { color: var(--red); }
.pw-rule.fail .pw-rule-mark::before { content: "\2715"; } /* ✕ */
.pw-rule.checking .pw-rule-mark::before { content: "\2026"; } /* … */

/* Cloudflare Turnstile CAPTCHA holder on the login / register / reset forms.
   Empty (and so invisible) unless window.SITESTOCK_TURNSTILE_KEY is set and
   authView.js renders a widget into it. */
.captcha-slot { margin: 12px 0 4px; min-height: 0; }
.captcha-slot:empty { display: none; }

/* Social sign-in block (#oauth-block). Hidden entirely unless a provider is
   enabled - see authView.js / env.js. */
#oauth-block { margin: 4px 0 18px; }
#oauth-block[hidden] { display: none; }
.oauth-buttons { display: flex; flex-direction: column; gap: 8px; }
.btn-oauth {
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--text-muted);
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.btn-oauth[hidden] { display: none; }
.oauth-icon { width: 18px; height: 18px; flex: none; }
.btn-oauth:hover:not(:disabled) { border-color: var(--navy); color: var(--navy); }
.btn-oauth:disabled { opacity: 0.5; cursor: not-allowed; }
.auth-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 14px 0 2px;
  font-family: var(--mono);
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.auth-divider::before,
.auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* --- "Confirm your email" screen shown after signup (#check-email-panel) --- */
.checklist-state {
  flex: 0 0 auto;
  font-family: var(--mono);
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}
.checklist-item-done .checklist-state { color: var(--navy); }

.check-email-steps {
  margin: 0 0 14px;
  padding-left: 20px;
  line-height: 1.55;
}
.check-email-steps li { margin-bottom: 6px; }
#check-email-panel .btn-block { margin-top: 8px; }
#check-email-panel .link-btn { display: block; margin: 10px auto 0; }
