/* ===============================================
   AUTHEON — Production styles
   =============================================== */

:root {
  /* Client Farbgebung §3 — brand tokens (see docs/design/brand-tokens.md) */
  --brand-accent: #000000;
  --brand-text: #111111;
  --brand-text-secondary: #6e6e73;
  --brand-canvas: #f5f5f7;
  --brand-surface: #ffffff;
  --brand-border: #e5e5ea;

  --primary: var(--brand-accent);
  --primary-rgb: 0, 0, 0;
  --primary-ink: #1c1c1e;
  --cta: #ea580c;
  --cta-rgb: 234, 88, 12;
  --destructive: #dc2626;
  --destructive-rgb: 220, 38, 38;
  --danger-ink: #b91c1c;
  --on-accent: #ffffff;
  --on-destructive: #ffffff;
  --on-cta: #ffffff;
  --canvas: var(--brand-canvas);
  --paper: var(--brand-surface);
  --paper-2: #f1f5f9;
  /* Neutral hover/selected wash — solid so Theme Editor can edit it */
  --paper-3: #f4f4f5;
  --ink: var(--brand-text);
  --ink-2: var(--brand-text-secondary);
  --ink-3: #8e8e93;

  /* Lines */
  --line: var(--brand-border);
  --line-2: #c7c7cc;
  --line-3: var(--brand-text);
  --line-dash: #c7c7cc;

  /* Text */
  --text: var(--brand-text);
  --muted: var(--brand-text-secondary);
  --muted-2: #8e8e93;

  /* Status — logistics semantics (NOT brand accent) */
  --st-draft: #64748b;
  --st-published: #2563eb;
  --st-assigned: #c2410c;
  --st-accepted: #059669;
  --st-accepted-rgb: 5, 150, 105;
  --st-empty-run: #9333ea;
  --st-performed: #0f172a;
  --st-cancelled: #dc2626;
  --st-warn: #ea580c;

  --st-draft-bg: #f1efea;
  --st-published-bg: #eff6ff;
  --st-assigned-bg: #fff7ed;
  --st-accepted-bg: #ecfdf5;
  --st-empty-run-bg: #f5f3ff;
  --st-cancelled-bg: #fef2f2;
  --st-warn-bg: #ffedd5;

  /* Success mark — the standalone gradient checkmark, sampled from the approved
     reference: deepest at the vertex, lightest at the long arm's tip, over a
     soft radial bloom. Narrowly scoped to that one glyph on purpose — the
     reference green is lighter than `--st-accepted`, which stays the status /
     badge / label green and is NOT re-toned by these. */
  --success-mark-from: #54b765;
  --success-mark-mid: #6bc67b;
  --success-mark-to: #8fde9c;
  --success-glow: rgba(87, 221, 132, 0.18);
  --success-glow-fade: rgba(87, 221, 132, 0);

  /* Diff / master-data compare */
  --diff-added: #065f46;
  --diff-added-bright: #6ee7b7;
  --diff-removed-bright: #fca5a5;

  /* Document card icon chip */
  --doc-icon-bg: #e5e7eb;
  --doc-icon-fg: #4b5563;

  /* Device chrome (phone frame) */
  --phone-bezel: #1a1a1a;
  --phone-notch: #0b0b0c;

  /* Slide-to-confirm thumb */
  --slide-thumb-bg: #ffffff;
  --slide-thumb-fg: #4b5563;
  --slide-thumb-fg-active: #1f2937;

  /* Overlays / shadows / attention */
  --scrim-ink: #0f172a;
  --shadow-ink: #0f172a;
  --shadow-ink-rgb: 15, 23, 42;
  --highlight: #ffd255;
  --highlight-soft: #ffe6a5;
  --neutral-fill: #7f7f7f;

  /* Spacing scale (4pt) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 40px;
  --space-9: 48px;

  --r-1: 4px;
  --r-2: 8px;
  --r-3: 12px;
  --r-4: 16px;
  --r-pill: 999px;

  --sh-1: 0 1px 2px color-mix(in srgb, var(--shadow-ink) 6%, transparent);
  --sh-2:
    0 8px 24px color-mix(in srgb, var(--shadow-ink) 7%, transparent),
    0 1px 2px color-mix(in srgb, var(--shadow-ink) 5%, transparent);
  --sh-3:
    0 24px 64px color-mix(in srgb, var(--shadow-ink) 16%, transparent),
    0 2px 8px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
  --sh-inset: inset 0 0 0 1px var(--line);

  /* Design Direction Board (07/2026): Inter Tight is the client's primary UI
     font. JetBrains Mono stays as an internal data-identifier font only. */
  --font-sans: "Inter Tight", system-ui, -apple-system, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Type scale — 7 sizes, rem-based (plan §4.2). Mono is reserved for data
     identifiers (tour no., PLZ, VIN, timestamps, money) — never UI chrome. */
  --text-display: clamp(1.75rem, 1.2rem + 1.2vw, 2.25rem);
  --text-title: 1.25rem;
  --text-heading: 1.0625rem;
  --text-body: 1rem;
  --text-body-sm: 0.875rem;
  --text-caption: 0.8125rem;
  --text-overline: 0.6875rem;
  /* legacy alias — retire with W2 sweep */
  --text-micro: var(--text-caption);

  /* z-index scale (plan §4.3) */
  --z-sticky: 10;
  --z-popover: 20;
  --z-tabbar: 30;
  --z-sheet: 40;
  --z-dialog: 50;
  --z-toast: 60;

  /* Prototype shell chrome — fixed dark bar (never flip with --brand-text) */
  --chrome-header-bg: #111111;
  --chrome-header-fg: #ffffff;
  --chrome-header-muted: color-mix(
    in srgb,
    var(--chrome-header-fg) 70%,
    transparent
  );
  --chrome-header-border: color-mix(
    in srgb,
    var(--chrome-header-fg) 8%,
    transparent
  );
  --chrome-header-wash: color-mix(
    in srgb,
    var(--chrome-header-fg) 6%,
    transparent
  );
  --chrome-header-wash-strong: color-mix(
    in srgb,
    var(--chrome-header-fg) 12%,
    transparent
  );
  --chrome-header-ring: color-mix(
    in srgb,
    var(--chrome-header-fg) 18%,
    transparent
  );
  --chrome-header-ring-strong: color-mix(
    in srgb,
    var(--chrome-header-fg) 28%,
    transparent
  );
}

[data-theme="dark"] {
  --brand-accent: #8f5bff;
  --brand-text: #ffffff;
  --brand-text-secondary: #aeaeb2;
  --brand-canvas: #1c1c1e;
  --brand-surface: #2c2c2e;
  --brand-border: #38383a;

  --primary: var(--brand-accent);
  --primary-rgb: 143, 91, 255;
  --primary-ink: #a375ff;
  --cta: #ea580c;
  --cta-rgb: 234, 88, 12;
  --destructive: #dc2626;
  --destructive-rgb: 220, 38, 38;
  --danger-ink: #f87171;
  --on-accent: #ffffff;
  --on-destructive: #ffffff;
  --on-cta: #ffffff;
  --canvas: var(--brand-canvas);
  --paper: var(--brand-surface);
  --paper-2: #1c1c1e;
  --paper-3: #3a3a3c;
  --ink: var(--brand-text);
  --ink-2: var(--brand-text-secondary);
  --ink-3: #8e8e93;
  --line: var(--brand-border);
  --line-2: #48484a;
  --line-3: var(--brand-text);
  --line-dash: #48484a;
  --text: var(--brand-text);
  --muted: var(--brand-text-secondary);
  --muted-2: #aeaeb2; /* ≥4.5:1 on --paper */
  --st-draft-bg: #2a2a2c;
  --st-published-bg: #172554;
  --st-assigned-bg: #3a2210;
  --st-accepted-bg: #092a24;
  --st-empty-run-bg: #2c1f50;
  --st-cancelled-bg: #3e1520;
  --st-warn-bg: #4a2b12;
  /* The mark's own greens carry over unchanged — they are mid-greens that read
     on `--paper` #2c2c2e as well as on white. Only the bloom is re-tuned: a
     tint that is a soft lift on white needs slightly more presence to register
     against a dark panel at all. */
  --success-glow: rgba(87, 221, 132, 0.22);
  --diff-added: #6ee7b7;
  --diff-added-bright: #6ee7b7;
  --diff-removed-bright: #fca5a5;
  --doc-icon-bg: #374151;
  --doc-icon-fg: #d1d5db;
  --phone-bezel: #1a1a1a;
  --phone-notch: #0b0b0c;
  --slide-thumb-bg: #ffffff;
  --slide-thumb-fg: #4b5563;
  --slide-thumb-fg-active: #1f2937;
  --scrim-ink: #0b0b0c;
  --shadow-ink: #020617;
  --shadow-ink-rgb: 2, 6, 23;
  --highlight: #ffd250;
  --highlight-soft: #ffe6a5;
  --neutral-fill: #7f7f7f;
  --sh-1: 0 1px 2px color-mix(in srgb, var(--shadow-ink) 45%, transparent);
  --sh-2:
    0 14px 30px color-mix(in srgb, var(--shadow-ink) 48%, transparent),
    0 1px 2px color-mix(in srgb, var(--shadow-ink) 35%, transparent);
  --sh-3:
    0 26px 60px color-mix(in srgb, var(--shadow-ink) 66%, transparent),
    0 2px 10px color-mix(in srgb, var(--shadow-ink) 40%, transparent);

  --chrome-header-bg: #0b0b0c;
  --chrome-header-fg: #ffffff;
  --chrome-header-muted: color-mix(
    in srgb,
    var(--chrome-header-fg) 72%,
    transparent
  );
  --chrome-header-border: color-mix(
    in srgb,
    var(--chrome-header-fg) 10%,
    transparent
  );
  --chrome-header-wash: color-mix(
    in srgb,
    var(--chrome-header-fg) 6%,
    transparent
  );
  --chrome-header-wash-strong: color-mix(
    in srgb,
    var(--chrome-header-fg) 12%,
    transparent
  );
  --chrome-header-ring: color-mix(
    in srgb,
    var(--chrome-header-fg) 18%,
    transparent
  );
  --chrome-header-ring-strong: color-mix(
    in srgb,
    var(--chrome-header-fg) 28%,
    transparent
  );
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* List entrance — matches autheon-mobile.nxt-app.pages.dev portalCardEnter
   (Demo Login → Portal): opacity 0→1, translateY(8px)→0, 320ms,
   cubic-bezier(0.16, 1, 0.3, 1), delay index*40ms, first 4 items only. */
@keyframes list-enter {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.list-enter {
  opacity: 0;
  animation: list-enter 320ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
  animation-delay: calc(var(--list-enter-i, 0) * 40ms);
}
@media (prefers-reduced-motion: reduce) {
  .list-enter {
    opacity: 1;
    animation: none;
    transform: none;
  }
}

* {
  box-sizing: border-box;
}
html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
}
body {
  font-family: var(--font-sans);
  color: var(--text);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "ss01", "cv11";
  overflow: auto;
  min-height: 100%;
}
button,
input,
select,
textarea {
  font-family: inherit;
  color: inherit;
}
button {
  cursor: pointer;
}
a {
  color: inherit;
}

/* ===============================================
   APP SHELL
   =============================================== */
.app {
  display: grid;
  grid-template-rows: 52px 1fr;
  /* Fixed-height app shell: the header row stays put and each surface
     (driver phone-shell / admin .admin-content) scrolls internally.
     Using min-height here let the whole document scroll instead, which
     broke sticky positioning inside .admin-content. */
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  overflow: hidden;
}
.app-header {
  background: var(--chrome-header-bg);
  color: var(--chrome-header-fg);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
  border-bottom: 1px solid var(--chrome-header-border);
}
.app-header .brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: 0.18em;
  font-size: 13px;
}
.app-header .brand-mark,
.admin-nav .nav-brand .brand-mark {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  display: block;
  border-radius: 5px;
}
.app-header .switcher {
  display: inline-flex;
  background: var(--chrome-header-wash);
  border-radius: var(--r-pill);
  padding: 3px;
  font-size: 13px;
}
.app-header .app-controls {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.app-header .pwa-entry {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--chrome-header-ring);
  color: var(--chrome-header-fg);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
  background: var(--chrome-header-wash);
}
.app-header .pwa-entry:hover {
  background: var(--chrome-header-wash-strong);
  border-color: var(--chrome-header-ring-strong);
}
.app-header .theme-editor-entry {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--chrome-header-ring);
  color: var(--chrome-header-muted);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  white-space: nowrap;
  background: var(--chrome-header-wash);
  cursor: pointer;
}
.app-header .theme-editor-entry:hover {
  background: var(--chrome-header-wash-strong);
  border-color: var(--chrome-header-ring-strong);
  color: var(--chrome-header-fg);
}
.app-header .theme-editor-entry.on {
  background: var(--primary);
  border-color: transparent;
  color: var(--chrome-header-fg);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
}
.app-header .theme-editor-entry:focus-visible {
  outline: 2px solid var(--chrome-header-fg);
  outline-offset: 2px;
}
.app-header .switcher button {
  background: transparent;
  color: var(--chrome-header-muted);
  border: 0;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.app-header .switcher button.on {
  background: var(--primary);
  color: var(--chrome-header-fg);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
}
.app-header .right {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  color: var(--chrome-header-muted);
}
.app-header .right .demo-tag {
  border: 1px solid var(--chrome-header-ring);
  padding: 4px 10px;
  border-radius: var(--r-pill);
  text-transform: uppercase;
}
.banner {
  margin: 6px 14px 0;
  padding: 10px 12px;
  border-radius: var(--r-2);
  border: 1px solid var(--line);
  font-size: 13px;
}
.banner-warn {
  background: var(--st-warn-bg);
}
.app-stage {
  position: relative;
  overflow: hidden;
  background: var(--canvas);
}

/* ===============================================
   ATOMS
   =============================================== */
.label,
.lbl {
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
  font-weight: 500;
}
.label-ink {
  color: var(--text);
}
.mono {
  font-family: var(--font-mono);
  font-feature-settings:
    "tnum" on,
    "lnum" on;
}
.tnum {
  font-variant-numeric: tabular-nums;
}

hr.dash {
  border: 0;
  border-top: 1px dashed var(--line-dash);
  margin: 0;
}
hr.line {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 0;
}

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--paper);
  color: var(--text);
  /* Secondary = white surface + fine gray outline (board §I) */
  border: 1px solid var(--line-2);
  border-radius: var(--r-2);
  padding: 11px 18px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
  transition:
    background 0.14s ease,
    transform 0.04s,
    box-shadow 0.14s;
  white-space: nowrap;
}
.btn:hover {
  background: var(--paper-3);
}
.btn:active {
  transform: translateY(1px);
}
.btn.primary {
  background: var(--primary);
  color: var(--on-accent);
  border-color: var(--primary);
}
.btn.primary:hover {
  background: var(--primary-ink);
  border-color: var(--primary-ink);
}
.btn.cta {
  background: var(--cta);
  color: var(--on-cta);
  border-color: var(--cta);
}
.btn.cta:hover {
  filter: brightness(1.05);
}
.btn.ghost {
  border-color: transparent;
  background: transparent;
}
.btn.ghost:hover {
  background: var(--paper-3);
}
.btn.danger {
  color: var(--st-cancelled);
  border-color: var(--line);
}
.btn.danger:hover {
  background: var(--st-cancelled-bg);
}
/* Solid destructive action (e.g. "Delete all") — same structural pattern as
   .btn.primary, just on --destructive instead of --primary. .btn.danger
   above stays the subtler outlined/text style for lower-stakes actions. */
.btn.destructive {
  background: var(--destructive);
  color: var(--on-accent);
  border-color: var(--destructive);
}
.btn.destructive:hover {
  filter: brightness(1.08);
}
.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}
/* Small button. NOTE: `--r-1` (4px) is sharper than the `--r-2` every other
   button uses, and sharper than the documented "moderate button rounding
   (--r-2/--r-3)" rule — so `.btn.sm` must not be used for a card-level or
   dialog-level primary action, where it reads as a different button family.
   Reach for the full-size `.btn` there. (Tightening `--r-1` → `--r-2` globally
   is a separate, wider visual change: recorded, not taken here.) */
.btn.sm {
  padding: 7px 12px;
  font-size: 13px;
  border-radius: var(--r-1);
}
.btn.xs {
  padding: 5px 10px;
  font-size: 12px;
  border-radius: var(--r-1);
}
.btn.block {
  width: 100%;
}
.btn.icon {
  padding: 0;
  width: 44px;
  height: 44px;
}
/* Compact icon-only button for dense table rows (admin notification feed
   row actions) — .btn.icon above is touch-target sized (44px) for the
   driver-facing surfaces; this is the desktop-density equivalent. */
.btn.icon-only {
  padding: 0;
  width: 28px;
  height: 28px;
}
.btn.icon.sm {
  width: 40px;
  height: 40px;
}
.touch-target {
  min-width: 44px;
  min-height: 44px;
}

/* Inputs */
.input {
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: var(--r-2);
  padding: 10px 12px;
  font-size: 14px;
  color: var(--text);
  outline: none;
  transition:
    border-color 0.12s,
    box-shadow 0.12s;
}
.input::placeholder {
  color: var(--muted-2);
}
.input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 20%, transparent);
}
textarea.input {
  min-height: 92px;
  resize: vertical;
}
/* Custom select chevron — replaces the native arrow, which macOS draws
   flush against the border; keep it 14px off the right edge. */
select.input {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6e73' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 16px 16px;
  padding-right: 42px;
  cursor: pointer;
}
[data-theme="dark"] select.input {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aeaeb2' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
@supports (-webkit-touch-callout: none) {
  @media (hover: none) and (pointer: coarse) {
    input[type="date"].input {
      -webkit-appearance: none;
      appearance: none;
      min-width: 0;
      max-width: 100%;
      min-height: 40px;
    }
  }
}
.field-label {
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
  font-weight: 500;
  margin-bottom: 6px;
  display: block;
}

/* Pills */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* Sentence-case sans label (board §D: no default uppercase; mono is for
     data identifiers only). Text label is always present — never color-only. */
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  padding: 3px 9px 3px 8px;
  border-radius: var(--r-pill);
  background: var(--paper-3);
  color: var(--text);
  font-weight: 500;
  white-space: nowrap;
  line-height: 1.4;
  border: 1px solid transparent;
}
.pill::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  display: inline-block;
}
.pill.no-dot::before {
  display: none;
}
.pill.draft {
  background: var(--st-draft-bg);
  color: var(--st-draft);
}
.pill.published {
  background: var(--st-published-bg);
  color: var(--st-published);
}
.pill.assigned {
  background: var(--st-assigned-bg);
  color: var(--st-assigned);
}
.pill.accepted {
  background: var(--st-accepted-bg);
  color: var(--st-accepted);
}
.pill.performed {
  /* Tinted bg + dark text — the solid near-black chip was the one heavy
     status fill (board §C: restrained status colors). */
  background: rgba(15, 23, 42, 0.08);
  color: var(--st-performed);
}
[data-theme="dark"] .pill.performed {
  background: rgba(248, 250, 252, 0.14);
  color: #e2e8f0;
}
.pill.empty_run {
  background: var(--st-empty-run-bg);
  color: var(--st-empty-run);
}
.pill.cancelled {
  background: var(--st-cancelled-bg);
  color: var(--st-cancelled);
}
.pill.warn {
  background: var(--st-warn-bg);
  color: var(--st-warn);
}
.pill.outline {
  background: transparent;
  border-color: var(--line-2);
  color: var(--text);
}

/* Chips */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  padding: 7px 14px;
  font-size: 13px;
  white-space: nowrap;
  user-select: none;
  transition:
    background 0.12s,
    border-color 0.12s;
}
.chip.actionable {
  min-height: 44px;
  padding: 10px 14px;
}
.chip:hover {
  background: var(--paper-3);
  border-color: var(--line-3);
}
.chip.on {
  background: var(--primary);
  color: var(--on-accent);
  border-color: var(--primary);
}
.chip.mono {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.02em;
}
.chip .x {
  margin-left: 2px;
  width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  opacity: 0.7;
}
.chip:hover .x {
  opacity: 1;
}

/* Cards */
.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--sh-1);
}
.card.flat {
  box-shadow: none;
}
.card.elev {
  box-shadow: var(--sh-2);
}

/* ===============================================
   AUTH SCREENS — Login (driver + admin)
   Shared form chrome; each screen supplies its own outer layout
   (phone-frame for driver, centered card on muted canvas for admin) —
   see driver.jsx DriverLoginScreen / admin.jsx AdminLoginScreen.
   =============================================== */
.auth-screen {
  display: flex;
  flex-direction: column;
  gap: 28px;
}
.auth-logo-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 14px;
  color: var(--text);
}
.auth-heading-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.auth-heading {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 24px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--text);
}
.auth-subheading {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--muted);
}
.auth-form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.auth-field-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.auth-password-wrap {
  position: relative;
}
.auth-password-wrap .input {
  padding-right: 44px;
}
.auth-password-toggle {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: var(--r-1);
  background: transparent;
  color: var(--muted-2);
  cursor: pointer;
}
.auth-password-toggle:hover {
  color: var(--text);
}
.auth-password-toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.auth-field-error {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--st-cancelled);
}
.auth-root-error {
  font-size: 13px;
}
.auth-form-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding-top: 4px;
}
.auth-forgot-link {
  border: 0;
  background: transparent;
  font-family: var(--font-sans);
  color: var(--text);
  font-size: 14px;
  cursor: pointer;
  padding: 4px;
}
.auth-forgot-link:hover {
  text-decoration: underline;
}
.auth-forgot-link:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--r-1);
}
.auth-forgot-link[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Forgot-password flow: per-step back button + segmented OTP entry */
.auth-back-row {
  display: flex;
  margin-bottom: -8px;
}
.auth-otp-row {
  position: relative;
  display: flex;
  gap: 8px;
}
.auth-otp-hidden-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  border: 0;
  padding: 0;
  cursor: text;
}
.auth-otp-cell {
  flex: 1;
  min-width: 0;
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-2);
  border-radius: var(--r-2);
  background: var(--paper);
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 500;
  color: var(--text);
}
.auth-otp-cell.active {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 20%, transparent);
}

/* Admin login — centered card on muted canvas (autheon-fe CenteredCardLayout) */
.auth-shell-admin {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 16px;
  background: var(--paper-2);
  overflow-y: auto;
}
.auth-card-admin {
  width: 100%;
  max-width: 400px;
  padding: 32px;
  display: flex;
  flex-direction: column;
  gap: 28px;
}

/* Auth top chrome — language + theme controls on every auth screen
   (autheon-fe parity: AuthTopChrome). In-flow, right-aligned row rather
   than an absolute overlay — simpler to keep correct across the phone-mock,
   standalone /pwa, and admin centered-card contexts alike. */
.auth-top-chrome {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
}
.auth-locale-select {
  appearance: none;
  -webkit-appearance: none;
  height: 44px;
  background: var(--paper);
  color: var(--text);
  border: 0;
  border-radius: var(--r-3);
  padding: 0 34px 0 14px;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 14px;
  box-shadow: var(--sh-1);
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6e73' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 14px 14px;
}
[data-theme="dark"] .auth-locale-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23aeaeb2' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.auth-locale-select:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.auth-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--r-3);
  background: var(--paper);
  color: var(--text);
  box-shadow: var(--sh-1);
  cursor: pointer;
}
.auth-theme-toggle:hover {
  background: var(--paper-3);
}
.auth-theme-toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Job overview — “What do statuses mean?” (readability) */
.status-explain {
  padding: 20px 22px 24px;
  margin-bottom: 16px;
}
.status-explain-summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  letter-spacing: -0.02em;
  line-height: 1.45;
  padding: 2px 0 6px;
  list-style-position: outside;
}
.status-explain-body {
  margin-top: 0;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 24px;
  max-width: 68ch;
}
.status-explain-intro {
  margin: 0;
  font-size: 14px;
  line-height: 1.75;
  color: var(--ink-2);
  letter-spacing: 0.01em;
}
.status-explain-note {
  margin: 0;
  padding: 16px 18px;
  font-size: 13px;
  line-height: 1.65;
  color: var(--muted);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  box-shadow: var(--sh-inset);
}
.status-explain-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.status-explain-list > li {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}
.status-explain-pill {
  flex-shrink: 0;
  margin-top: 2px;
}
.status-explain-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.7;
  color: var(--ink-2);
  letter-spacing: 0.01em;
}

/* Segmented */
.seg {
  display: inline-grid;
  background: var(--paper-3);
  border-radius: var(--r-2);
  padding: 3px;
  gap: 0;
}
.seg button {
  background: transparent;
  border: 0;
  padding: 8px 14px;
  font-size: 13px;
  border-radius: var(--r-1);
  color: var(--muted);
  font-weight: 500;
}
.seg button.on {
  background: var(--paper);
  color: var(--text);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--shadow-ink) 6%, transparent);
}
.seg.full {
  width: 100%;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
}

/* Route stack */
.route {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 0 14px;
}
.route .rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 8px;
}
.route .rail .dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 1.5px solid var(--ink);
  background: var(--paper);
}
.route .rail .dot.filled {
  background: var(--ink);
}
.route .rail .line {
  flex: 1;
  width: 1.5px;
  background: var(--ink);
  margin: 4px 0;
  min-height: 22px;
  background-image: linear-gradient(to bottom, var(--ink) 60%, transparent 0);
  background-size: 1.5px 5px;
  background-color: transparent;
}
.route .end {
  margin-top: 16px;
}
.route .city {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.05;
}
.route .meta {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--muted);
  margin-top: 4px;
}

/* ===============================================
   DRIVER PWA — inherits :root Farbgebung tokens
   Layout-only overrides below (no duplicate color blocks)
   =============================================== */
.phone-shell {
  /* Driver uses same brand tokens as :root */
}

/* Job card — client reference layout (Design Direction Board §5, p.5–6):
   route text line "City → City" with PLZ beneath, two-column pickup/delivery
   legs, footer with vehicle · important-info tags · axle chip · price right. */
.phone-shell .jobcard {
  border-radius: var(--r-4); /* moderate rounding (board §E) */
}
/* Vertical route timeline — client-confirmed layout (2026-08-03): pickup
   stop above delivery stop, joined by a dashed connector, distance shown
   between them. Replaces the earlier horizontal "City → City" line.
   Each row is a 2-col grid (rail | content); the rail cell stretches to
   match that row's own content height (CSS Grid default), so the dashed
   line always meets the dot centers exactly instead of guessed offsets —
   fixes the earlier version where the line ran through/behind the pins. */
.phone-shell .jobcard-route-timeline {
  margin-top: 2px;
}
.phone-shell .route-leg {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 10px;
}
.phone-shell .route-rail {
  position: relative;
}
/* Pin badge — reuses Ic.Map (same glyph as lucide MapPin) per client reference. */
.phone-shell .route-dot {
  position: relative;
  z-index: 1;
  display: flex;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
}
/* Pin center sits at y=11px (1px top margin + half of the 20px badge), so the
   segments meet it exactly; .route-dot's z-index hides the overlap. */
.phone-shell .route-connector {
  position: absolute;
  left: 50%;
  top: 11px;
  bottom: 0;
  border-left: 1px dashed var(--line);
  transform: translateX(-50%);
}
.phone-shell .route-connector-above {
  top: 0;
  bottom: auto;
  height: 11px;
}
/* Distance row — no rail wrapper: the dashed line spans the row's full
   height at the pin's center-x. The label sits flush-left (same x as the
   pin badges, matching the client reference) and is vertically centered in
   the row, i.e. centered between the pickup and delivery pins — not
   centered horizontally across the card. */
.phone-shell .route-distance-row {
  position: relative;
  height: 64px;
  display: flex;
  align-items: center;
}
/* Denser variant for detail cards, which carry more sections per screen. */
.phone-shell .route-distance-row.compact {
  height: 40px;
}
.phone-shell .route-connector-full {
  position: absolute;
  left: 10px;
  top: 0;
  bottom: 0;
  border-left: 1px dashed var(--line);
}
.phone-shell .route-leg-main {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  min-width: 0;
}
.phone-shell .route-leg-place {
  min-width: 0;
}
.phone-shell .route-city-name {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.phone-shell .route-city-plz {
  font-size: var(--text-caption);
  color: var(--muted);
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.phone-shell .route-leg-meta {
  flex-shrink: 0;
  text-align: right;
}
.phone-shell .route-pill {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(var(--primary-rgb), 0.12);
  color: var(--primary);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
.phone-shell .route-leg-when {
  margin-top: 4px;
  font-size: var(--text-caption);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.phone-shell .route-distance-note {
  margin-left: 6px;
}
.phone-shell .route-distance {
  position: relative;
  z-index: 1;
  white-space: nowrap;
  padding-right: 8px;
  background: var(--paper);
  font-size: 13px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.phone-shell .jobcard-divider {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 14px 0 12px;
}
.phone-shell .jobcard-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.phone-shell .jobcard-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  row-gap: 6px;
  min-width: 0;
}
.phone-shell .vehicle-meta {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
}
.phone-shell .vehicle-meta svg {
  color: var(--text);
  flex-shrink: 0;
}
/* Important vehicle info tag (Registered / Deregistered / E-vehicle / Red
   plates) — chip treatment so rows wrap cleanly on narrow cards; text label
   always present, the icon supports it. */
.phone-shell .vehicle-flag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  background: var(--canvas);
  border-radius: var(--r-2);
  padding: 4px 9px;
  white-space: nowrap;
}
.phone-shell .vehicle-flag svg {
  flex-shrink: 0;
  color: var(--muted);
}
.phone-shell .vehicle-flag.electric svg {
  color: var(--primary); /* restrained accent per client reference card */
}
/* DERIVED "Red licence plates required" notice (deregistered + own axle).
   Reuses the EXISTING semantic warning tokens (--st-warn / --st-warn-bg) that
   already carry attention meaning across the app — no isolated warning style
   and no new token was introduced. Compact tag variant for dense tag rows. */
.phone-shell .vehicle-flag.red-plates-required {
  background: var(--st-warn-bg);
  color: var(--st-warn);
  font-weight: 600;
  /* Long translations ("Rote Kennzeichen erforderlich") must wrap instead of
     overflowing a narrow card, unlike the other single-word flags. */
  white-space: normal;
}
.phone-shell .vehicle-flag.red-plates-required svg {
  color: var(--st-warn);
}
/* Banner variant — marketplace preview, booking dialog, complete order view. */
.phone-shell .red-plates-banner {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px solid var(--st-warn);
  border-radius: var(--r-2);
  background: var(--st-warn-bg);
  color: var(--text);
}
.phone-shell .red-plates-banner-head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--st-warn);
}
.phone-shell .red-plates-banner-head svg {
  flex-shrink: 0;
  color: var(--st-warn);
}
.phone-shell .red-plates-banner-detail {
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted);
}
.phone-shell .axle-chip {
  display: inline-flex;
  align-items: center;
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  background: var(--canvas);
  border-radius: var(--r-2);
  padding: 4px 9px;
  white-space: nowrap;
}
/* Wrapping tag row under the card footer (flags + axle) */
.phone-shell .jobcard-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
.phone-shell .jobcard-tags:empty {
  display: none;
}
/* Ordered vehicle-info block in the detail card: label line, tags beneath */
.phone-shell .detail-flag-block .label {
  font-size: 14px;
  color: var(--muted);
}
.phone-shell .detail-flag-block .jobcard-tags {
  margin-top: 8px;
}
/* German red transfer plate (§16 FZV) — literal plate rendering; the text
   label ("Red plate no.") always accompanies it */
.phone-shell .plate-badge.plate-red {
  color: var(--danger-ink);
  border-color: var(--danger-ink);
}
.phone-shell .jobcard-price {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
}

/* Header KPI row — reduced dashboard character (board §4) */
.phone-shell .kpi-row {
  display: flex;
  gap: 8px;
}
.phone-shell .kpi-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  background: var(--canvas);
  border-radius: 10px;
  padding: 6px 10px;
  font-size: 12px;
  color: var(--muted);
  white-space: nowrap;
  min-width: 0;
}
.phone-shell .kpi-chip .kpi-num {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.phone-shell .kpi-chip .kpi-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Tabbar Redesign Styles */
.phone-shell .tabbar-container {
  padding: 0 16px max(20px, calc(8px + env(safe-area-inset-bottom, 0px)));
  /* Transparent ground — list content peeks around the floating capsule */
  background: transparent;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  pointer-events: none;
}
/* Board §H: frosted nav surface, fine border, subtle shadow; active/inactive
   through black/gray contrast — dominant purple navigation is prohibited.
   Floating vs fixed geometry remains an open client decision (kept floating). */
.phone-shell .tabbar-capsule {
  display: flex;
  align-items: stretch;
  pointer-events: auto;
  background: color-mix(in srgb, var(--paper) 85%, transparent);
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: 6px 8px;
  box-shadow:
    0 6px 20px color-mix(in srgb, var(--shadow-ink) 8%, transparent),
    0 1px 2px color-mix(in srgb, var(--shadow-ink) 5%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
@supports not (
  (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))
) {
  .phone-shell .tabbar-capsule {
    background: var(--paper);
  }
}
[data-theme="dark"] .phone-shell .tabbar-capsule {
  background: color-mix(in srgb, var(--paper) 78%, transparent);
  border-color: var(--line);
  box-shadow: var(--sh-2);
}
.phone-shell .tabbar-item {
  background: transparent;
  border: 0;
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  color: var(--muted);
  padding: 8px 4px;
  border-radius: 18px;
  transition:
    background 0.22s cubic-bezier(0.2, 0.8, 0.2, 1),
    color 0.22s cubic-bezier(0.2, 0.8, 0.2, 1);
  cursor: pointer;
  min-height: 44px;
  font: inherit;
}
.phone-shell .tabbar-item.active {
  background: var(--canvas);
  color: var(--text);
  font-weight: 600;
}
[data-theme="dark"] .phone-shell .tabbar-item.active {
  background: color-mix(in srgb, var(--on-accent) 9%, transparent);
}
.phone-shell .tabbar-icon-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
}
.phone-shell .tabbar-badge {
  position: absolute;
  top: -5px;
  right: -9px;
  background: var(--destructive);
  color: var(--on-accent);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  border-radius: 9999px;
  min-width: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
  border: 1.5px solid var(--paper);
  line-height: 1;
}
[data-theme="dark"] .phone-shell .tabbar-badge {
  border-color: var(--paper);
}
.phone-shell .tabbar-label {
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  line-height: 1.1;
  text-align: center;
}
.phone-shell .tabbar-item.active .tabbar-label {
  font-weight: 600;
  color: var(--text);
}

/* Animated Autheon mark for the active Marketplace tab — the white ribbons
   draw themselves on, hold, and re-trace endlessly while the tab is active. */
.phone-shell .tabbar-anim-mark path {
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
  stroke-dasharray: 1;
  animation: autheonTrace 3.6s ease-in-out infinite both;
}
.phone-shell .tabbar-anim-mark path:nth-of-type(1) {
  animation-delay: 0s;
}
.phone-shell .tabbar-anim-mark path:nth-of-type(2) {
  animation-delay: 0.13s;
}
.phone-shell .tabbar-anim-mark path:nth-of-type(3) {
  animation-delay: 0.26s;
}
.phone-shell .tabbar-anim-mark path:nth-of-type(4) {
  animation-delay: 0.39s;
}
@keyframes autheonTrace {
  0%,
  100% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
    stroke-opacity: 0;
  } /* filled logo — visible most of the cycle */
  56% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
    stroke-opacity: 0;
  } /* hold */
  64% {
    stroke-dashoffset: 0;
    fill-opacity: 0;
    stroke-opacity: 0.9;
  } /* unfill to a thin line */
  74% {
    stroke-dashoffset: 1;
    fill-opacity: 0;
    stroke-opacity: 0.9;
  } /* retract the line */
  88% {
    stroke-dashoffset: 0;
    fill-opacity: 0;
    stroke-opacity: 0.9;
  } /* re-trace the line */
  96% {
    stroke-dashoffset: 0;
    fill-opacity: 1;
    stroke-opacity: 0.2;
  } /* fill back in */
}
@media (prefers-reduced-motion: reduce) {
  .phone-shell .tabbar-anim-mark path {
    animation: none;
    fill-opacity: 1;
    stroke-opacity: 0;
    stroke-dashoffset: 0;
  }
}

/* Header Redesign Styles
   ------------------------------------------------------------------------
   Client decision 2026-07-26: all four primary driver screens share ONE
   header (`.pwa-screen-header`, see the shared-header block further down).
   The Marketplace-only greeting block (.pwa-header / .header-top-row /
   .driver-welcome / .driver-avatar / .welcome-*) was removed with it — do not
   reintroduce a per-screen header wrapper. */
.phone-shell .header-title {
  margin: 0;
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
  line-height: 1.2;
}
.phone-shell .header-subtitle {
  font-size: 14px;
  color: var(--muted);
  line-height: 1.3;
  margin-top: 2px;
}
.phone-shell .header-controls {
  display: flex;
  gap: 8px;
  align-items: center;
}
/* Canonical header icon-button treatment — the SINGLE definition of border,
   radius, size, surface and shadow for sort, filter AND the notification bell
   (client requirement 2026-07-26: the bell must have exactly the same border as
   the sorting/filter controls). Never re-declare these values per button. */
.phone-shell .header-btn {
  width: 40px;
  height: 40px;
  border-radius: var(--r-3);
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  /* Scoped, not `all`: `all` also transitioned outline-width/color, so the
     focus-visible ring faded in instead of appearing immediately. */
  transition:
    border-color 0.15s ease,
    background 0.15s ease,
    color 0.15s ease;
  box-shadow: var(--sh-1);
}
.phone-shell .header-btn:hover {
  border-color: var(--line-3);
  background: var(--paper-2);
}
.phone-shell .header-btn:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.phone-shell .header-btn.active {
  background: var(--primary);
  color: var(--on-accent);
  border-color: var(--primary);
}
/* Bell and filter add ONLY a badge anchor on top of .header-btn. */
.phone-shell .header-bell-btn,
.phone-shell .header-filter-btn {
  position: relative;
}
/* ONE anchored-count-badge rule, shared by the notification bell (unread
   count) and the Marketplace filter button (applied-filter count). It only
   POSITIONS the shared `.ui-badge` primitive — colour, radius, weight and the
   99+ cap all stay in `.ui-badge` / `.ui-badge-destructive`, so there is no
   duplicated badge styling. `pointer-events: none` keeps the whole button one
   click/touch target; the badge is never a separate hit area or focus stop. */
.phone-shell .header-btn > .header-btn-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  font-size: 10px;
  border: 1.5px solid var(--paper);
  pointer-events: none;
}
/* Applied state fills the button with --primary; keep the badge ring reading
   against that surface instead of the page surface. */
.phone-shell .header-btn.active > .header-btn-badge {
  border-color: var(--primary);
}
.phone-shell .header-chips-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

/* Job Details Redesign Styles */
.phone-shell .pwa-detail-header {
  padding: 12px 16px;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}
.phone-shell .detail-back-btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--canvas);
  border: 0;
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--sh-1);
}
.phone-shell .detail-header-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  text-align: center;
  flex: 1;
}
.phone-shell .pwa-detail-body {
  padding: 16px 16px 24px;
  background: var(--canvas); /* client canvas #F5F5F7 (board §E) */
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.phone-shell .detail-card {
  background: var(--paper);
  border-radius: 16px;
  padding: 16px;
  border: 1px solid var(--line);
  box-shadow: var(--sh-1);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.phone-shell .detail-card.info-card {
  background: var(--st-published-bg);
  border-color: var(--line);
}
.phone-shell .detail-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
/* The marketplace-preview Route card no longer uses a horizontal
   "city — dash — distance — dash — city" row: the client confirmed the
   VERTICAL timeline (2026-08-03), so JobLocked now renders the same shared
   <RouteTimeline> as the job cards. Its styles live with the timeline block
   above; the old .detail-route-row/-city/-dash/-info rules were removed with
   the markup they styled. */
.phone-shell .detail-card-divider {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 0;
}
/* Stacked full-width rows — the old 50/50 columns wrapped time
   ranges mid-value ("09:00–" / "12:00"), plan §7.3 */
.phone-shell .detail-route-times {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.phone-shell .detail-route-times > div {
  display: block;
  text-align: left !important;
}
.phone-shell .detail-route-times .time-label {
  font-size: var(--text-caption);
  color: var(--muted);
  font-weight: 500;
  margin-bottom: 2px;
  text-transform: none;
  letter-spacing: 0;
}
.phone-shell .detail-route-times .time-val {
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
  font-size: var(--text-caption);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.phone-shell .detail-kv-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.phone-shell .detail-kv-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.phone-shell .detail-kv-row .label {
  font-size: 14px;
  color: var(--muted);
}
.phone-shell .detail-kv-row .value {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.phone-shell .detail-check-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.phone-shell .detail-check-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--text);
}
.phone-shell .detail-check-list .check-icon {
  color: var(--primary);
  font-weight: 600;
}
.phone-shell .pwa-detail-bottom {
  padding: 16px 20px 24px;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--paper);
  flex-shrink: 0;
}
.phone-shell .bottom-price-info {
  display: flex;
  flex-direction: column;
}
.phone-shell .bottom-price-info .label {
  font-size: 12px;
  color: var(--muted);
  font-weight: 500;
}
.phone-shell .bottom-price-info .price {
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
}
.phone-shell .lg-cta {
  padding: 12px 32px;
  border-radius: var(--r-3); /* moderate — no pill buttons (board §I) */
  font-size: 16px;
  font-weight: 600;
  min-width: 140px;
}

/* JobUnlocked Redesign Styles */
.phone-shell .customer-card {
  padding: 12px 16px;
}
.phone-shell .customer-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.phone-shell .customer-title {
  font-size: 14px;
  color: var(--muted);
}
.phone-shell .customer-name {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
/* Unlocked My Jobs detail: street / stop / schedule / map under RouteTimeline
   (FE MarketplaceJobUnlockedView parity). Old custom vertical timeline removed. */
.phone-shell .detail-unlocked-stops {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.phone-shell .detail-unlocked-stop .time-label {
  font-size: var(--text-caption);
  color: var(--muted);
  font-weight: 500;
  margin-bottom: 2px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.phone-shell .detail-unlocked-stop .city-location-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.35;
  overflow-wrap: anywhere;
  margin-top: 2px;
}
.phone-shell .detail-unlocked-stop .city-address {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  overflow-wrap: anywhere;
  margin-top: 2px;
}
.phone-shell .detail-unlocked-stop .time-val {
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  margin-top: 2px;
}
.phone-shell .detail-unlocked-stop .map-link {
  font-size: 12px;
  font-weight: 600;
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  gap: 4px;
  text-decoration: none;
  padding: 4px 8px;
  border-radius: 8px;
  background: var(--canvas);
  margin-top: 8px;
  width: fit-content;
}
.phone-shell .plate-badge {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 13px;
  color: var(--text);
  background: var(--canvas);
  border: 1.5px solid var(--line-2);
  border-radius: 6px;
  padding: 4px 10px;
}
.phone-shell .detail-contacts-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.phone-shell .contact-column {
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--canvas);
  padding: 12px;
  border-radius: 12px;
}
.phone-shell .contact-role {
  font-size: 12px;
  color: var(--muted);
  font-weight: 500;
}
.phone-shell .contact-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin: 2px 0 4px;
}
.phone-shell .contact-actions {
  display: flex;
  gap: 8px;
}
.phone-shell .contact-action-btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  transition: all 0.15s ease;
}
.phone-shell .detail-pdf-card {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--canvas);
  padding: 12px;
  border-radius: 12px;
}
.phone-shell .pdf-icon-wrap {
  color: var(--primary);
  flex-shrink: 0;
}
.phone-shell .pdf-name {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text);
  font-weight: 600;
  word-break: break-all;
}
.phone-shell .pdf-meta {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}
.phone-shell .pdf-actions {
  display: flex;
  gap: 6px;
}
.phone-shell .pdf-btn {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--paper);
  border: 1px solid var(--line);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

/* Tour document rows — same visual language as detail-pdf-card */
.phone-shell .detail-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.phone-shell .tour-doc-section-hint {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}
.phone-shell .tour-doc-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.phone-shell .tour-doc-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  background: var(--canvas);
  padding: 12px;
  border-radius: 12px;
}
.phone-shell .tour-doc-row-icon {
  color: var(--primary);
  flex-shrink: 0;
  margin-top: 1px;
}
.phone-shell .tour-doc-row-name {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  word-break: break-all;
}
.phone-shell .tour-doc-row-meta-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
  flex-wrap: wrap;
}
.phone-shell .tour-doc-row-meta {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.4;
}
.phone-shell .tour-doc-row-status {
  flex-shrink: 0;
}
.phone-shell .tour-doc-row-rejection {
  margin: 6px 0 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--st-cancelled);
}
.phone-shell .tour-doc-row-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.phone-shell .tour-doc-upload-btn {
  align-self: flex-start;
}
.phone-shell .tour-doc-empty {
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px dashed var(--line-dash);
  background: var(--paper-2);
  text-align: center;
}
.phone-shell .tour-doc-empty-title {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.phone-shell .tour-doc-empty-desc {
  margin: 6px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}

.phone-shell .price-summary-card {
  padding: 16px;
}
.phone-shell .price-summary-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.phone-shell .price-label {
  font-size: 12px;
  color: var(--muted);
  font-weight: 500;
}
.phone-shell .price-meta {
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
  font-family: var(--font-mono);
}
.phone-shell .price-val {
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
}
.phone-shell .pwa-unlocked-bottom {
  padding: 16px 20px 24px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--paper);
  flex-shrink: 0;
}

.phone-shell .btn.primary:hover {
  background: var(--primary-ink);
  border-color: var(--primary-ink);
}

/* Sheet (Filters) Redesign Styles */
.phone-shell .sheet {
  border-top-left-radius: 24px;
  border-top-right-radius: 24px;
  border: 1px solid var(--line);
  border-bottom: 0;
  box-shadow: 0 -10px 30px
    color-mix(in srgb, var(--shadow-ink) 15%, transparent);
}
.phone-shell .sheet .grabber {
  width: 38px;
  height: 4px;
  background: var(--line-2);
  border-radius: 2px;
  margin: 0;
  pointer-events: none;
}
.phone-shell .sheet .grabber-hit {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding-top: 10px;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.phone-shell .sheet .grabber-hit:active {
  cursor: grabbing;
}
.phone-shell .sheet .grabber-hit--hidden {
  min-height: 12px;
  padding-top: 0;
}
.phone-shell .sheet-head {
  padding: 16px 20px 12px;
  border-bottom: 0;
  background: var(--paper);
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.phone-shell .sheet-head:active {
  cursor: grabbing;
}
.phone-shell .sheet-head h2 {
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
}
.phone-shell .sheet-body {
  padding: 0 20px 24px;
}
.phone-shell .sheet-foot {
  padding: 16px 20px 24px;
  border-top: 1px solid var(--line);
  background: var(--paper);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  gap: 12px;
}
.phone-shell .sheet-body .field-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin-top: 20px;
  margin-bottom: 8px;
}
.phone-shell .sheet-body .input {
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--canvas);
  padding: 12px 14px;
  font-size: 14px;
  color: var(--text);
  width: 100%;
  transition: border-color 0.15s ease;
}
.phone-shell .sheet-body .input:focus {
  border-color: var(--primary);
  outline: none;
}
.phone-shell .sheet-body .chip.actionable {
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 8px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  transition: all 0.15s ease;
  cursor: pointer;
}
.phone-shell .sheet-body .chip.actionable.on {
  background: var(--primary);
  color: var(--on-accent);
  border-color: var(--primary);
}
.phone-shell .sheet-body .seg.full {
  display: flex;
  gap: 6px;
  background: var(--canvas);
  padding: 4px;
  border-radius: 14px;
  border: 1px solid var(--line);
}
.phone-shell .sheet-body .seg.full button {
  flex: 1;
  border: 0;
  background: transparent;
  padding: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.15s ease;
}
.phone-shell .sheet-body .seg.full button.on {
  background: var(--paper);
  color: var(--text);
  box-shadow: var(--sh-1);
}

/* ===============================================
   PHONE FRAME
   =============================================== */
.phone-shell {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 24px 16px 36px;
  overflow: auto;
}
.phone-shell .pwa-tag {
  position: absolute;
  top: 16px;
  left: 24px;
  z-index: 5;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  max-width: min(280px, calc(100vw - 48px));
  line-height: 1.35;
  pointer-events: none;
}
.phone {
  width: min(392px, calc(100vw - 32px));
  height: min(800px, calc(100vh - 120px));
  max-height: calc(100vh - 80px);
  background: var(--paper);
  border-radius: 44px;
  border: 1px solid var(--phone-bezel);
  position: relative;
  overflow: hidden;
  box-shadow:
    0 0 0 8px var(--phone-bezel),
    0 28px 52px color-mix(in srgb, var(--shadow-ink) 24%, transparent),
    inset 0 0 0 1px color-mix(in srgb, var(--on-accent) 3%, transparent),
    0 4px 12px color-mix(in srgb, var(--shadow-ink) 10%, transparent);
}
.phone .notch {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  width: 110px;
  height: 30px;
  background: var(--phone-notch);
  border-radius: 18px;
  z-index: 30;
}
.phone-screen {
  width: 100%;
  height: 100%;
  background: var(--paper);
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  font-family: var(--font-sans);
  /* Status bar + device safe areas (used by full-screen overlays) */
  --phone-chrome-top: calc(44px + env(safe-area-inset-top, 0px));
  --phone-chrome-bottom: env(safe-area-inset-bottom, 0px);
  --phone-chrome-left: env(safe-area-inset-left, 0px);
  --phone-chrome-right: env(safe-area-inset-right, 0px);
}
.statusbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 28px 6px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  flex-shrink: 0;
  position: relative;
  z-index: 20;
}
.statusbar .right {
  display: inline-flex;
  gap: 5px;
  align-items: center;
}
.statusbar .signal {
  display: inline-flex;
  gap: 2px;
  align-items: flex-end;
}
.statusbar .signal i {
  display: inline-block;
  width: 3px;
  background: var(--ink);
  border-radius: 1px;
}
.statusbar .battery {
  width: 24px;
  height: 12px;
  border: 1.2px solid var(--ink);
  border-radius: 3px;
  position: relative;
  display: inline-block;
}
.statusbar .battery::after {
  content: "";
  position: absolute;
  right: -3px;
  top: 3px;
  width: 2px;
  height: 4px;
  background: var(--ink);
  border-radius: 0 1px 1px 0;
}
.statusbar .battery::before {
  content: "";
  position: absolute;
  inset: 1px;
  width: calc(100% - 10px);
  background: var(--ink);
  border-radius: 1px;
}
.scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.scroll::-webkit-scrollbar {
  width: 6px;
}
.scroll::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--shadow-ink) 12%, transparent);
  border-radius: 3px;
}

/* Draggable paged tab views (see SwipeViews in driver.jsx) */
.swipe-viewport {
  position: relative;
  overflow: hidden;
  /* Let the browser own vertical panning; we handle horizontal drags. */
  touch-action: pan-y;
}
.swipe-track {
  display: flex;
  height: 100%;
  width: 100%;
  will-change: transform;
}
.swipe-pane {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.swipe-pane::-webkit-scrollbar {
  width: 6px;
}
.swipe-pane::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.12);
  border-radius: 3px;
}
/* A pane's inner content fills the pane height so its background never
   leaves a gap under short lists. */
.swipe-pane-body {
  min-height: 100%;
}

/* Legacy .tabbar (pre-capsule nav) removed — use .tabbar-container / .tabbar-capsule */

/* Job card (driver) */
.jobcard {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: 16px;
  margin-bottom: 12px;
  cursor: pointer;
  transition:
    transform 0.12s ease,
    box-shadow 0.14s ease,
    border-color 0.14s;
  position: relative;
}
.jobcard:hover {
  box-shadow: var(--sh-2);
  border-color: var(--line-2);
  transform: translateY(-1px);
}
.jobcard:active {
  transform: translateY(0);
}
.jobcard .driver-offer {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.015em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.jobcard .mono {
  color: var(--muted-2);
}

.dash-area {
  border: 1px dashed var(--line-dash);
  background-image: repeating-linear-gradient(
    135deg,
    transparent 0 8px,
    color-mix(in srgb, var(--shadow-ink) 4%, transparent) 8px 9px
  );
  border-radius: var(--r-2);
  padding: 14px;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  line-height: 1.5;
}

/* Sheets */
.sheet-backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--scrim-ink) 45%, transparent);
  backdrop-filter: blur(2px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  z-index: 50;
  animation: fade 0.18s ease;
}
.sheet-backdrop.center {
  justify-content: center;
  padding: 0 16px;
}
@keyframes fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
.sheet {
  background: var(--paper);
  border-top-left-radius: 24px;
  border-top-right-radius: 24px;
  border: 1px solid var(--line);
  border-bottom: 0;
  display: flex;
  flex-direction: column;
  animation: sheetIn 0.26s cubic-bezier(0.2, 0.8, 0.25, 1);
  max-height: 90%;
  overflow: hidden;
}
.sheet.modal {
  border-radius: var(--r-4);
  border: 1px solid var(--line);
  animation: modalIn 0.22s cubic-bezier(0.2, 0.8, 0.25, 1);
}
/* Phone-shell bottom-sheet rules must not clip centered modals (top-only radius). */
.phone-shell .sheet.modal {
  border-radius: var(--r-4);
  border: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--sh-3);
}
@keyframes sheetIn {
  from {
    transform: translateY(20px);
  }
  to {
    transform: translateY(0);
  }
}
@keyframes modalIn {
  from {
    transform: scale(0.96);
    opacity: 0;
  }
  to {
    transform: scale(1);
    opacity: 1;
  }
}
.sheet .grabber {
  width: 38px;
  height: 4px;
  background: var(--line-3);
  border-radius: 2px;
  margin: 0;
  opacity: 0.65;
  pointer-events: none;
}
.sheet .grabber-hit {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding-top: 10px;
  cursor: grab;
  touch-action: none;
  user-select: none;
}
.sheet .grabber-hit:active {
  cursor: grabbing;
}
.sheet .grabber-hit--hidden {
  min-height: 12px;
  padding-top: 0;
}
.sheet-head {
  padding: 14px 22px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, var(--paper) 0%, var(--paper-2) 100%);
}
.sheet-head h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.sheet-body {
  padding: 20px 22px;
  overflow-y: auto;
}
.sheet-foot {
  padding: 14px 22px 22px;
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  gap: 10px;
  background: var(--paper);
}
/* Footer actions are stretched grid items, so a bare `1fr` (= minmax(auto, 1fr))
   lets each button's nowrap min-content floor its column: at 320px the DE label
   "Abbrechen" widened Cancel to 105px and squeezed Confirm to 137px — a 1:1.3
   ratio instead of the canonical 1:1.6. minmax(0, …) makes the declared ratio
   authoritative; min-width:0 plus tighter inline padding keeps long labels
   unclipped inside the narrower column. The label stays centred in the stretched
   column, so the reduced padding is visually inert. min-height meets the 44px
   touch-target floor (buttons previously rendered 41px tall). */
.sheet-foot > .btn {
  min-width: 0;
  min-height: 44px;
  padding-inline: 12px;
}
/* Success / single-action sheets: one primary spans the Cancel|Primary grid. */
.sheet-foot > .btn:only-child {
  grid-column: 1 / -1;
}

/* =========================================================================
   DIALOG STANDARD — reference: the driver "Accept tour" dialog
   (`AcceptanceModal`, driver.jsx). One contract for every dialog on both
   surfaces, so proportions, spacing, corner treatment, content hierarchy and
   action placement stop drifting per dialog.

   Structure, top to bottom:
     .dialog-eyebrow?   small uppercase context label   (optional)
     .dialog-title      the purpose, one type step up, CENTERED
     .dialog-desc       consequence / decision / outcome, muted, CENTERED
     .dialog-content    summaries, forms, warnings, legal — LEFT aligned and
                        scrollable, so long content never clips the actions
     .dialog-actions    consistent sizing, spacing and alignment

   Title and description are centered BY DEFAULT. `.dialog-content` is
   deliberately left-aligned: it carries running prose, key/value summaries,
   legal text and form fields, which are unreadable centered. That is the one
   content-driven alignment exception, and it is structural rather than a
   per-dialog opt-out, so no dialog has to decide for itself.
   ========================================================================= */
.dialog-backdrop {
  /* Console dialogs cover the whole viewport. */
  position: fixed;
  inset: 0;
  background: color-mix(in srgb, var(--scrim-ink) 45%, transparent);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Guarantees the panel can never touch the viewport edge, so actions stay
     reachable on small screens. */
  padding: 24px;
  z-index: 102;
  animation: fade 0.18s ease;
}
/* Inside the driver surface a dialog belongs to the DEVICE, not the browser
   window: `position: absolute` scopes it to `.phone-screen` so the framed
   client preview keeps the dialog inside the phone mock instead of centring it
   on the whole page. Same containment `.sheet-backdrop` has always used — the
   16px gutter and the full-width panel below reproduce `.sheet-backdrop.center`. */
.phone-shell .dialog-backdrop {
  position: absolute;
  padding: 0 16px;
  z-index: 50;
}
.dialog-panel {
  background: var(--paper);
  border: 1px solid var(--line);
  /* Same outer rounding as the reference dialog (`.sheet.modal`). */
  border-radius: var(--r-4);
  box-shadow: var(--sh-3);
  width: 100%;
  max-width: 480px;
  /* Bounded height + an internally scrolling `.dialog-content` is what keeps
     the action row on screen for long content instead of pushing it out. */
  max-height: min(90vh, 760px);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  padding: 24px;
  animation: modalIn 0.22s cubic-bezier(0.2, 0.8, 0.25, 1);
}
/* Two documented widths beyond the default: forms and operational summaries
   need more room. Replaces the ad-hoc 480 / 520 / 560 inline maxWidths. */
.dialog-panel--md {
  max-width: 560px;
}
.dialog-panel--lg {
  max-width: 720px;
}
/* On the phone the device width IS the constraint — a dialog fills it (minus the
   backdrop gutter) rather than sitting at a desktop max-width inside it. */
.phone-shell .dialog-panel {
  max-width: 100%;
  max-height: 90%;
}
.dialog-eyebrow {
  display: block;
  margin: 0 0 6px;
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted-2);
}
/* Status disc. Present ONLY when the icon carries meaning — success, warning,
   error, destructive. Same 52px disc treatment as the remove-document dialog,
   so meaningful dialog icons look like one family. Tone comes from the
   `--st-*` families via a modifier; there is no default colour, because a
   dialog with no status has no icon. */
.dialog-icon {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  margin: 2px auto 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper-2);
  color: var(--muted);
}
.dialog-icon--success {
  background: var(--st-accepted-bg);
  color: var(--st-accepted);
}
.dialog-icon--warning {
  background: var(--st-assigned-bg);
  color: var(--st-assigned);
}
.dialog-icon--danger {
  background: var(--st-cancelled-bg);
  color: var(--st-cancelled);
}
.dialog-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.3;
  color: var(--text);
  text-align: center;
}
/* The phone surface steps the title up, exactly as `.phone-shell .sheet-head h2`
   already does — one type step, rendered at the size each surface needs. */
.phone-shell .dialog-title {
  font-size: 22px;
}
.dialog-desc {
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
  text-align: center;
}
.dialog-content {
  margin-top: 18px;
  text-align: left;
  overflow-y: auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.dialog-content:empty {
  display: none;
}
/* Panels not composed through the `Dialog` primitive (converted in place) get
   the same spacing rhythm below the header without a wrapper element. */
.dialog-panel > .dialog-body {
  margin-top: 18px;
  overflow-y: auto;
  min-height: 0;
  display: grid;
  gap: 12px;
}
.dialog-meta {
  font-size: 12px;
  color: var(--muted);
}
.dialog-hint {
  margin: 8px 0 0;
  font-size: 11.5px;
  line-height: 1.45;
}
.dialog-error {
  margin: 0;
  font-size: 13px;
  color: var(--st-cancelled);
}
.dialog-banner {
  font-size: 13px;
}
/* Success / short-message dialogs read better narrower than the 480px default. */
.dialog-panel--narrow {
  max-width: 360px;
}
/* The `Dialog` primitive renders one status disc; the tone modifier is applied
   on the panel so a caller does not have to reach inside. Success is the one
   tone that is NOT a disc — see "SUCCESS MARK" below. */
.dialog-icon-warning > .dialog-icon {
  background: var(--st-assigned-bg);
  color: var(--st-assigned);
}
.dialog-icon-danger > .dialog-icon {
  background: var(--st-cancelled-bg);
  color: var(--st-cancelled);
}
/* =========================================================================
   SUCCESS MARK — a standalone gradient checkmark, no disc.
   Success is the one status tone that drops the 52px disc. Once the glyph grew
   and took a gradient it carried the status on its own, and the container was
   just a ring around it. Warning and danger keep their discs deliberately: a
   small `!` or `×` reads as an alert only inside one, so the disc is still
   load-bearing there and this is a success-only deviation, not the disc
   standard being retired.
   The box is larger than the glyph because it hosts the bloom as its own
   background. That is why the bloom is a background and not a pseudo-element:
   `.performed-success-scroll` is an `overflow-y: auto` container, so anything
   painted outside the box would be clipped at the scroll edge and could add a
   scrollbar. A background is bounded by the box and cannot.
   The bloom is a diffuse radial fade with no edge — it reads as light behind
   the mark, not as the disc that was removed.
   ========================================================================= */
.dialog-icon-success > .dialog-icon,
.phone-shell .performed-success-check {
  width: 80px;
  height: 80px;
  border-radius: 0;
  box-shadow: none;
  background: radial-gradient(
    circle at 50% 50%,
    var(--success-glow) 0%,
    var(--success-glow-fade) 75%
  );
}
/* Trim the surrounding margin as the box grows, so the mark gets bigger without
   the gap to the title growing with it. */
.dialog-icon-success > .dialog-icon {
  margin: 0 auto 6px;
}
.phone-shell .performed-success-check {
  margin: 0 auto 8px;
}
/* Gradient stops are tokens applied through CSS, because `var()` is not
   resolved inside an SVG presentation attribute. Theming the mark therefore
   means changing the tokens only — never the JSX. */
.success-mark-from {
  stop-color: var(--success-mark-from);
}
.success-mark-mid {
  stop-color: var(--success-mark-mid);
}
.success-mark-to {
  stop-color: var(--success-mark-to);
}
/* Reference-dialog tour summary — was an inline style object on the one dialog
   every other dialog is measured against. */
.accept-tour-summary {
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  padding: 14px;
  background: var(--paper-2);
}
/* Action grammar is the canonical Cancel | Primary 1:1.6 grid already used by
   `.sheet-foot`, so the two never disagree. A single action spans the row —
   wide and centered. */
.dialog-actions {
  margin-top: 20px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
  gap: 12px;
  flex-shrink: 0;
}
.dialog-actions > .btn {
  min-width: 0;
  min-height: 44px;
  padding-inline: 12px;
}
.dialog-actions > .btn:only-child {
  grid-column: 1 / -1;
}
/* Three actions (e.g. save / discard / keep editing) stack full width rather
   than squeezing three columns below the touch-target floor. */
.dialog-actions.dialog-actions--stack {
  grid-template-columns: 1fr;
}
/* Three or more actions: a wrapping row instead of a squeezed grid, with the
   same gap, the same 44px floor and the primary last. */
.dialog-actions.dialog-actions--row {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.dialog-actions.dialog-actions--row > .btn {
  flex: 0 1 auto;
}
@media (max-width: 420px) {
  .dialog-backdrop {
    padding: 16px;
  }
  .dialog-actions {
    grid-template-columns: 1fr;
  }
}

/* Dialogs composed from the shared `Sheet` primitive get the same centered
   hierarchy. Bottom sheets keep their left-aligned, draggable header — the
   grabber and the drag affordance belong on the leading edge. */
.sheet.modal .sheet-head {
  justify-content: center;
  text-align: center;
  border-bottom: 0;
  background: var(--paper);
  cursor: default;
}
.phone-shell .sheet.modal .sheet-head {
  justify-content: center;
  text-align: center;
  cursor: default;
}
.sheet.modal .sheet-body > p:first-child:last-child {
  text-align: center;
}

/* Driver subpage drill-down back control: the shared .detail-back-btn is 40px,
   below the documented ≥44×44 floor (design-system.md §Button,
   ui-ux-production-plan §"Touch: ≥44×44px … default on all interactive
   styles"). It is the primary escape from every driver subpage (Profile
   sections, Infopoint message detail), so it is raised here. Scoped to the
   subpage header so the job-detail chrome is untouched; the same 40px gap
   exists there and is worth a follow-up. */
.phone-shell .driver-subpage-header .detail-back-btn {
  width: 44px;
  height: 44px;
}
/* Mirror the 44px control so the centred title stays optically centred. */
.phone-shell .driver-subpage-header .w-40-spacer {
  width: 44px;
}
/* The heading receives focus on entry (tabIndex -1) purely to announce the new
   view; it is not an interactive control, so it must not paint a focus ring. */
.phone-shell .driver-subpage-header .detail-header-title:focus {
  outline: none;
}

/* Slide-to-confirm */
.slide-confirm {
  position: relative;
  height: 56px;
  background: var(--paper-3);
  border: 1px solid var(--line-2);
  border-radius: 9999px;
  overflow: hidden;
  user-select: none;
  touch-action: none;
  transition:
    background 0.3s ease,
    border-color 0.3s ease;
}
.slide-confirm .track-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-left: 52px;
  font-family: var(--font-sans);
  font-size: 15px;
  letter-spacing: 0.01em;
  color: var(--muted);
  font-weight: 500;
  pointer-events: none;
}
/* Circular sliding handle — stays white in both states; the track fills
   with brand purple on confirm and the arrow morphs into a check. */
.slide-confirm .thumb {
  position: absolute;
  top: 5px;
  left: 5px;
  bottom: 5px;
  width: 46px;
  background: var(--slide-thumb-bg);
  color: var(--slide-thumb-fg);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  border-radius: 9999px;
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--shadow-ink) 14%, transparent),
    0 4px 10px -4px color-mix(in srgb, var(--shadow-ink) 20%, transparent);
  will-change: transform;
}
.slide-confirm .thumb:active {
  cursor: grabbing;
}
.slide-handle-icon {
  width: 20px;
  height: 20px;
  display: block;
}
.slide-confirm.done {
  background: var(--primary);
  border-color: var(--primary);
}
.slide-confirm.done .thumb {
  color: var(--slide-thumb-fg-active);
}
.slide-confirm.done .track-text {
  color: var(--on-accent);
  font-weight: 600;
  padding-left: 0;
  padding-right: 52px;
}

/* Progressive fill: a purple bar that grows from the left as the handle
   advances (width is set inline to the drag distance). The white-text layer
   is clipped to the same width so the label stays legible over the fill. */
.slide-confirm .track-text {
  z-index: 1;
}
.slide-confirm .slide-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  background: var(--primary);
  border-radius: 9999px 0 0 9999px;
  z-index: 2;
  pointer-events: none;
}
.slide-confirm .track-text-fill {
  z-index: 3;
  color: var(--on-accent);
  -webkit-text-fill-color: var(--on-accent);
}
.slide-confirm .thumb {
  z-index: 4;
}

.slide-confirm-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.slide-char-count {
  margin-left: 8px;
  font-variant-numeric: tabular-nums;
}
.slide-char-count.need-more {
  color: var(--st-cancelled);
  font-weight: 600;
}
.slide-char-count.ok {
  color: var(--st-accepted);
  font-weight: 600;
}
.slide-confirm-hint {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted);
  padding: 0 2px;
}

.slide-confirm.disabled {
  opacity: 1;
  background: var(--paper-2);
  border: 1px dashed var(--line-dash);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--line-2) 12%, transparent);
  filter: grayscale(0.35);
}
.slide-confirm.disabled .track-text {
  color: var(--muted);
  font-size: 12px;
  letter-spacing: 0.01em;
  padding: 0 12px 0 100px;
  text-align: left;
  justify-content: flex-start;
}
.slide-confirm.disabled .thumb {
  background: var(--paper-2);
  color: var(--muted);
  cursor: not-allowed;
  pointer-events: none;
  box-shadow: none;
  transform: none !important;
}
.slide-confirm.disabled .thumb:active {
  cursor: not-allowed;
}

/* ---- Slide-to-confirm: animation upgrade ---------------------------------
   Adds spring physics on fill/release, an idle "drag me" invitation
   (shimmering label + nudging chevrons + breathing thumb) and a success pop.
   Brand colours (--primary / --cta) are unchanged. */

/* Glide the handle as it springs back or settles, but track the finger 1:1
   while actively dragging (the .dragging class removes the transition). */
.slide-confirm .thumb {
  transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
}
.slide-confirm.dragging .thumb {
  transition: none;
}

/* Idle invitation, only while the control is ready (not done / disabled /
   dragging): the arrow nudges rightward and the label shimmers purple. */
.slide-confirm:not(.done):not(.disabled):not(.dragging) .slide-handle-icon {
  animation: slideArrowNudge 1.5s ease-in-out infinite;
}
.slide-confirm:not(.done):not(.disabled):not(.dragging)
  .track-text:not(.track-text-fill) {
  background: linear-gradient(
    100deg,
    var(--muted) 0%,
    var(--muted) 40%,
    color-mix(in srgb, var(--primary) 95%, transparent) 50%,
    var(--muted) 60%,
    var(--muted) 100%
  );
  background-size: 250% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: slideShimmer 2.8s linear infinite;
}

/* Success moment: the check pops in and the label lands. */
.slide-confirm.done .slide-handle-icon {
  animation: slideCheckPop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.slide-confirm.done .track-text {
  animation: slideDonePop 0.42s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes slideArrowNudge {
  0%,
  100% {
    transform: translateX(0);
    opacity: 0.65;
  }
  50% {
    transform: translateX(3px);
    opacity: 1;
  }
}
@keyframes slideShimmer {
  0% {
    background-position: 130% 0;
  }
  100% {
    background-position: -130% 0;
  }
}
@keyframes slideCheckPop {
  0% {
    transform: scale(0.4);
    opacity: 0;
  }
  60% {
    transform: scale(1.15);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}
@keyframes slideDonePop {
  0% {
    transform: scale(0.92);
    opacity: 0.4;
  }
  60% {
    transform: scale(1.05);
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .slide-handle-icon,
  .slide-confirm .track-text,
  .slide-confirm .thumb {
    animation: none !important;
  }
}

/* Radio cards */
.radio-card {
  cursor: pointer;
  display: grid;
  grid-template-columns: 26px 1fr;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-2);
  background: var(--paper);
  align-items: start;
  transition:
    background 0.12s,
    border-color 0.12s;
}
.radio-card:hover {
  background: var(--paper-3);
}
.radio-card.on {
  border-color: var(--primary);
  background: var(--paper-3);
}
.radio-card .ring {
  width: 18px;
  height: 18px;
  border: 1.5px solid var(--ink);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: 2px;
}
.radio-card.on .ring::after {
  content: "";
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ink);
}
.radio-card .t {
  font-weight: 600;
  font-size: 14px;
}
.radio-card .s {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 2px;
  line-height: 1.5;
}

/* ===============================================
   ADMIN BACKEND
   =============================================== */
.admin {
  display: grid;
  grid-template-columns: 248px 1fr;
  /* Bound the single row to the shell height so .admin-main (and its
     .admin-content) inherit a definite height and scroll internally
     instead of growing the document. */
  grid-template-rows: minmax(0, 1fr);
  height: 100%;
  min-height: 0;
  background: var(--canvas); /* client canvas #F5F5F7 (board §E) */
  font-family: var(--font-sans);
}
.admin-nav {
  background: var(--paper);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
}
.admin-nav .nav-head {
  padding: 22px 22px 22px;
  border-bottom: 1px solid var(--line);
}
/* Retained uppercase meta markers (board §D sparing-use list — pending
   client confirmation, see design-direction-board-audit.md) */
.admin-nav .nav-eyebrow {
  font-family: var(--font-sans);
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.admin-nav .nav-brand {
  font-weight: 600;
  font-size: 19px;
  letter-spacing: 0.04em;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.admin-nav .nav-list {
  padding: 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.admin-nav .nav-section {
  font-family: var(--font-sans);
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 12px 10px 8px;
}
.nav-item {
  appearance: none;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 9px 12px;
  border-radius: var(--r-2);
  font-size: 14px;
  color: var(--text);
  transition: background 0.12s;
  text-align: left;
  width: 100%;
  border: 0;
  font-family: inherit;
  line-height: 1.3;
}
.nav-item:hover {
  background: var(--paper-3);
}
/* Board §H: no dominant purple navigation — active sidebar item uses a
   neutral fill + darker text instead of a purple capsule. */
.nav-item.on {
  background: var(--paper-2);
  color: var(--text);
  font-weight: 600;
}
.nav-item .ic {
  width: 16px;
  height: 16px;
  margin-right: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.nav-item .count {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
}
.nav-item.on .count {
  color: var(--muted);
}
/* Nav badge pulse — only ever applied to the notifications count while it
   has open (unprocessed) alerts, so it stops on its own once the backlog is
   cleared instead of needing a separate "seen" flag. */
.nav-item .count.count-pulse {
  color: var(--destructive);
  font-weight: 700;
  animation: navBadgePulse 1.6s ease-in-out infinite;
}
@keyframes navBadgePulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}

/* Notification feed badge — a colored square carrying an icon (never color
   alone: the row's own title text sits beside it, and the severity word is
   still exposed to assistive tech via aria-label/title on the square).
   Reuses the same semantic tokens as job/document status pills (already
   theme-safe in light + dark). */
.notif-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: var(--r-2, 8px);
}
.notif-badge svg {
  width: 20px;
  height: 20px;
}
/* Every row reserves the same height whether or not its third (read-by)
   line is present, so unread and read rows never visibly differ in size. */
.notif-row-detail {
  min-height: 54px;
}
.notif-badge.sev-red {
  color: var(--destructive);
  background: color-mix(in srgb, var(--destructive) 14%, transparent);
}
.notif-badge.sev-orange {
  color: var(--st-warn);
  background: var(--st-warn-bg);
}
.notif-badge.sev-gray {
  color: var(--st-draft);
  background: var(--st-draft-bg);
}
/* Source bubble — a neutral pill, deliberately not severity-colored (the
   badge already owns color; this column is a category, not an urgency
   signal, so giving it its own color would compete with the badge). */
.notif-source-chip {
  display: inline-block;
  font-size: 12px;
  color: var(--muted);
  background: var(--paper-3);
  border-radius: var(--r-pill);
  padding: 3px 10px;
  white-space: nowrap;
}
/* Unread marker — a plain dot beside the title, distinct from the badge's
   severity color so read state and urgency never get confused for the same
   signal. */
.notif-unread-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--primary);
  flex-shrink: 0;
}
.admin-nav .nav-foot {
  margin-top: auto;
  padding: 14px 18px;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 10px;
}
[data-theme="dark"] .admin-nav {
  background: var(--paper-2);
}
[data-theme="dark"] .admin-top,
[data-theme="dark"] .admin-foot {
  background: var(--paper);
}
[data-theme="dark"] .nav-item:hover {
  background: var(--paper-3);
}
[data-theme="dark"] .nav-item.on {
  background: color-mix(in srgb, var(--on-accent) 9%, transparent);
  color: var(--text);
}
[data-theme="dark"] .nav-item .count {
  color: var(--muted);
}
[data-theme="dark"] .nav-item.on .count {
  color: var(--muted);
}
.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--paper-3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  border: 1px solid var(--line);
  flex-shrink: 0;
}
.admin-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--paper-2);
}
.admin-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
  padding: 14px 28px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  flex-shrink: 0;
}
/* Single page title lives in chrome — content panes must not repeat it */
.admin-top .admin-page-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--text);
  line-height: 1.25;
}
.admin-top .crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0;
  min-width: 0;
  color: var(--muted);
  font-size: 13px;
  letter-spacing: 0.01em;
}
.admin-top .crumbs .crumb-link {
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.admin-top .crumbs .crumb-link:hover {
  color: var(--text);
}
.admin-top .crumbs .admin-page-title {
  font-size: 18px;
}
.admin-top .crumbs .sep {
  margin: 0 8px;
  opacity: 0.5;
}
.admin-top-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
/* Supporting copy under chrome title (not a second heading) */
.pane-lead {
  margin: 0 0 18px;
  max-width: 720px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}
.pane-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 18px;
}
.pane-toolbar .pane-lead {
  margin-bottom: 0;
}
.admin-content {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 28px 32px 32px;
}
.admin-foot {
  border-top: 1px solid var(--line);
  padding: 14px 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--paper);
  flex-shrink: 0;
}

/* Status grid */
.statgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 12px;
  margin-bottom: 28px;
}
.stat {
  text-align: left;
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: 16px;
  cursor: pointer;
  transition:
    background 0.12s,
    border-color 0.12s,
    transform 0.08s;
}
.stat:focus-visible,
.nav-item:focus-visible,
.tbl tr.row:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}
.stat:hover {
  background: var(--paper-3);
}
.stat.on {
  border-color: var(--primary);
  background: var(--paper);
  box-shadow: var(--sh-1);
}
.stat.on .num {
  color: var(--text);
}
.stat .num {
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  margin: 12px 0 8px;
}
.stat .sub {
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted);
}
.stat .pill {
  font-size: 10px;
  padding: 3px 8px;
}

/* Table */
.tbl {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  overflow: hidden;
}
.tbl th {
  text-align: left;
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
  font-weight: 500;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--paper-3);
  white-space: nowrap;
  position: sticky;
  top: 0;
  z-index: 1;
}
.tbl td {
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
.tbl tr:nth-child(even) td {
  background: color-mix(in srgb, var(--paper) 88%, var(--paper-3));
}
.tbl td.num,
.tbl td.date {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.tbl.dense td {
  padding: 10px 14px;
}
.tbl.dense th {
  padding: 10px 14px;
}
.tbl tr:last-child td {
  border-bottom: 0;
}
.tbl tr.row {
  cursor: pointer;
  transition: background 0.1s;
}
.table-wrap {
  overflow-x: auto;
  border-radius: var(--r-3);
}
.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-bottom: 22px;
}
.page-title {
  margin: 0;
  font-size: var(--text-display);
  font-weight: 600;
  letter-spacing: -0.02em;
}
.toolbar {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.toolbar .density-toggle {
  margin-left: auto;
  grid-auto-flow: column;
}

.stack-18 {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.grid-main-aside {
  display: grid;
  grid-template-columns: 1fr 280px;
  gap: 24px;
  align-items: flex-start;
}
.grid-form-layout {
  display: grid;
  grid-template-columns: 180px 1fr 280px;
  gap: 24px;
  align-items: start;
}
/* Create-job sidebars: left form-section nav + right live summary.
   They stick to the top of the scrolling .admin-content while the central
   form scrolls. If a sidebar is taller than the space between the top bar
   and the footer, it scrolls independently instead of overlapping them. */
.grid-form-layout > aside {
  position: sticky;
  top: 0;
  max-height: calc(100dvh - 172px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* Not enough horizontal room for three columns → stack and drop sticky so
   the sidebars never overlap the form or force a horizontal scrollbar.
   Tablet/mobile are reviewed separately; this only removes the desktop
   sticky behaviour, it does not restyle those layouts. */
@media (max-width: 1200px) {
  .grid-form-layout {
    grid-template-columns: minmax(0, 1fr);
  }
  .grid-form-layout > aside {
    position: static;
    max-height: none;
    overflow: visible;
  }
}
.tbl tr.row:hover td {
  background: var(--paper-3);
}
.tbl tr.row.fresh td {
  background: color-mix(in srgb, var(--highlight-soft) 18%, transparent);
  animation: freshFade 4s ease 1;
}
@keyframes freshFade {
  from {
    background: color-mix(in srgb, var(--highlight) 32%, transparent);
  }
  to {
    background: color-mix(in srgb, var(--highlight-soft) 18%, transparent);
  }
}
.tbl .tour {
  font-family: var(--font-mono);
  font-weight: 600;
}
.tbl .new-tag {
  /* Tiny "New" marker — retained uppercase meta label (board §D sparing use) */
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 10px;
  letter-spacing: 0.12em;
  margin-top: 4px;
  color: var(--st-warn);
  text-transform: uppercase;
  font-weight: 600;
}

/* Toast */
.toast {
  position: absolute;
  bottom: 72px;
  right: 28px;
  /* Neutral dark surface — purple is not a feedback-surface color (board §B) */
  background: var(--chrome-header-bg);
  color: var(--on-accent);
  padding: 14px 18px;
  border-radius: var(--r-3);
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 13px;
  z-index: 60;
  box-shadow: var(--sh-3);
  animation: toastIn 0.26s ease;
  min-width: 360px;
}
@keyframes toastIn {
  from {
    transform: translateY(8px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}
.toast .check {
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--paper);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
}
.toast .sub {
  font-family: var(--font-sans);
  font-size: 12px;
  color: color-mix(in srgb, var(--on-accent) 65%, transparent);
  margin-top: 3px;
}

/* Validation bar */
.bar {
  height: 6px;
  background: var(--paper-3);
  border-radius: 3px;
  overflow: hidden;
  border: 1px solid var(--line);
}
.bar > span {
  display: block;
  height: 100%;
  background: var(--primary);
  transition: width 0.25s ease;
}

/* Section heads inside form / detail */
.sec-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 4px;
}
.sec-head h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.sec-head h3 .num {
  font-family: var(--font-mono);
  color: var(--muted);
  font-weight: 500;
  margin-right: 6px;
}

/* Misc */
.list-end {
  text-align: center;
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  color: var(--muted);
  padding: 22px 0 14px;
}

.kbd {
  font-family: var(--font-mono);
  font-size: 11px;
  background: var(--paper-3);
  border: 1px solid var(--line);
  padding: 2px 6px;
  border-radius: 3px;
  color: var(--muted);
}

/* Search input with icon */
.search {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: 1;
  max-width: 360px;
}
.search input {
  padding-left: 36px;
}
.search .ic {
  position: absolute;
  left: 12px;
  width: 14px;
  height: 14px;
  color: var(--muted);
  pointer-events: none;
}

/* Tabs (simple) */
.tabs {
  display: flex;
  gap: 28px;
  border-bottom: 1px solid var(--line);
}
.tabs button {
  background: none;
  border: 0;
  padding: 12px 0;
  font-size: 14px;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  font-weight: 500;
  margin-bottom: -1px;
}
.tabs button.on {
  color: var(--text);
  font-weight: 600;
  border-bottom-color: var(--primary);
}
.tabs button .count {
  font-family: var(--font-mono);
  font-size: 11px;
  margin-left: 6px;
  color: var(--muted);
}

/* Admin Settings — folder tabs (mirrors the Autheon admin console). The
   prototype's existing underline .tabs style above stays where it is (the
   real console also uses two tab presentations); these folder tabs are drawn
   entirely with prototype CSS tokens, not ported Tailwind. */
.settings-tabs {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 4px;
}
.settings-tab {
  appearance: none;
  background: transparent;
  color: var(--muted);
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--r-2) var(--r-2) 0 0;
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
  cursor: pointer;
  margin-bottom: -1px;
  position: relative;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease;
}
.settings-tab:hover {
  color: var(--text);
}
.settings-tab.on,
.settings-tab[aria-selected="true"] {
  background: var(--paper);
  color: var(--text);
  border-color: var(--line);
  border-bottom: 0;
  z-index: 1;
}
.settings-tab:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
/* Square top edge so the selected tab joins the bordered panel below; the
   panel's top border shows through under the unselected tabs and is erased
   by the selected tab's paper-coloured bottom overlap, giving the folder look. */
.settings-tabpanel {
  border: 1px solid var(--line);
  border-radius: 0 0 var(--r-3) var(--r-3);
  background: var(--paper);
  padding: 24px;
}
.settings-lead {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}
/* User settings language + appearance rows (label + hint on the left, control
   on the right, separated by hairlines — same cadence as the console). */
.settings-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.settings-row:last-of-type {
  border-bottom: 0;
}
.settings-row-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.settings-row-hint {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}
/* Account sections (Change email · Change password) — same hairline cadence as
   the rows above, but stacked: heading, description, then the form. */
.settings-section {
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.settings-form {
  display: grid;
  gap: 14px;
  margin-top: 14px;
}
.settings-form .input {
  margin-top: 6px;
}
.settings-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
/* Single-icon appearance toggle (console ThemeToggle shape) — .btn.icon gives
   the 44×44 footprint and the hairline border; this adds the focus ring. */
.appearance-toggle:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Billing UI separation */
.finance-snapshot-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-top: 18px;
  padding: 14px 16px;
  background: var(--paper-3);
  border-radius: var(--r-2);
}
.finance-snapshot-banner {
  padding: 12px 14px;
  background: var(--paper-3);
  border-radius: var(--r-2);
  border-left: 3px solid var(--st-warn);
}
.fin-row-highlight {
  animation: fin-row-highlight-fade 3.2s ease-out;
}
@keyframes fin-row-highlight-fade {
  0% {
    background: var(--st-published-bg);
  }
  70% {
    background: var(--st-published-bg);
  }
  100% {
    background: transparent;
  }
}
.billing-filter-chip {
  cursor: pointer;
  font-size: 12.5px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-2);
  background: var(--paper-3);
  color: var(--text);
  font-family: var(--font-sans);
  transition:
    background 0.12s,
    border-color 0.12s;
}
.billing-filter-chip:hover {
  background: var(--paper);
  border-color: var(--line-3);
}
.label.pill-muted {
  font-size: 12px;
  color: var(--muted);
}
.tbl.compact th,
.tbl.compact td {
  padding: 8px 10px;
  font-size: 12.5px;
}

/* Master-data / change-request surfaces (generic — not feature-prefixed) */
.profile-status-banner {
  margin-top: 12px;
  padding: 12px 14px;
  border-radius: var(--r-2);
  border: 1px solid color-mix(in srgb, var(--primary) 28%, transparent);
  background: color-mix(in srgb, var(--primary) 6%, transparent);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text);
}
.profile-status-banner strong {
  display: block;
  font-size: 13.5px;
  margin-bottom: 4px;
}
.profile-field-list {
  margin-top: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  overflow: hidden;
  background: var(--paper);
}
.profile-field-row {
  display: grid;
  grid-template-columns: 108px 1fr;
  gap: 12px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  align-items: start;
}
.profile-field-row:last-child {
  border-bottom: none;
}
.profile-field-row.is-changed {
  background: color-mix(in srgb, var(--primary) 4%, transparent);
}
.profile-field-label {
  font-size: 12px;
  color: var(--muted);
  padding-top: 3px;
  font-weight: 500;
  margin-bottom: 0;
}
.profile-field-body {
  min-width: 0;
}
.profile-field-value {
  font-size: 13px;
  line-height: 1.45;
  word-break: break-word;
}
.profile-field-value.is-new {
  font-weight: 600;
  color: var(--primary-ink);
}
.profile-field-old {
  font-size: 12px;
  color: var(--muted);
  text-decoration: line-through;
  margin-top: 4px;
  line-height: 1.4;
  word-break: break-word;
}
.profile-field-badge {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--st-warn-bg);
  color: var(--st-warn);
  margin-left: 8px;
  vertical-align: middle;
}
.profile-actions {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.profile-actions .btn.primary {
  flex: 1;
  min-width: 140px;
}

.compare-table {
  margin-top: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  overflow: hidden;
  background: var(--paper);
}
.compare-table-header,
.compare-table-row {
  display: grid;
  grid-template-columns: minmax(0, 110px) minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  padding: 10px 14px;
  align-items: start;
  border-bottom: 1px solid var(--line);
}
.compare-table-header {
  background: var(--paper-2);
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
}
.compare-table-row:last-child {
  border-bottom: none;
}
.compare-table-row.is-changed {
  background: color-mix(in srgb, var(--primary) 5%, transparent);
}
.compare-table-cell {
  font-size: 12.5px;
  line-height: 1.45;
  word-break: break-word;
  min-width: 0;
}
.compare-table-cell.after {
  font-weight: 600;
  color: var(--primary-ink);
}
.compare-table-cell.before {
  color: var(--muted);
}

.queue-detail-actions {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
/* Single column until a request is selected; two columns from 1280px (admin
   shell + review form need room). min-width:0 so panes shrink instead of
   widening the page. */
.queue-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
  align-items: start;
}
@media (min-width: 1280px) {
  .queue-split.two {
    grid-template-columns: minmax(20rem, 1fr) minmax(28rem, 1.1fr);
  }
}
.queue-split > * {
  min-width: 0;
}
.queue-list-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}
.queue-list-changes {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}
.queue-list-chip {
  font-size: 10.5px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: var(--r-pill);
  background: var(--paper-3);
  border: 1px solid var(--line-2);
  color: var(--muted);
}
.queue-list-chip.on {
  background: color-mix(in srgb, var(--primary) 8%, transparent);
  border-color: color-mix(in srgb, var(--primary) 25%, transparent);
  color: var(--primary-ink);
}

/* ===============================================
   REQUIREMENT SURFACES — v1.8 UX polish
   =============================================== */
.banner-info {
  background: var(--st-published-bg);
  border-color: color-mix(in srgb, var(--primary) 22%, transparent);
  color: var(--primary-ink);
}
.banner-success {
  background: var(--st-accepted-bg);
  border-color: color-mix(in srgb, var(--st-accepted) 25%, transparent);
  color: var(--diff-added);
}
.banner-error {
  background: var(--st-cancelled-bg);
  border-color: color-mix(in srgb, var(--destructive) 22%, transparent);
  color: var(--st-cancelled);
}
[data-theme="dark"] .banner-success {
  color: var(--diff-added-bright);
}
[data-theme="dark"] .banner-error {
  color: var(--diff-removed-bright);
}

.req-panel {
  margin-top: 16px;
  padding: 16px;
  border-radius: var(--r-3);
  border: 1px solid var(--line);
  background: var(--paper-2);
  box-shadow: var(--sh-1);
}
.req-panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}
.req-panel-head h4 {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.req-panel-desc {
  margin: 0 0 14px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--muted);
}
.req-panel-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.inline-alert {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: var(--r-2);
  border: 1px solid var(--line);
  font-size: 12.5px;
  line-height: 1.45;
}
.inline-alert-error {
  background: var(--st-cancelled-bg);
  border-color: color-mix(in srgb, var(--destructive) 20%, transparent);
  color: var(--st-cancelled);
}
.inline-alert-success {
  background: var(--st-accepted-bg);
  border-color: color-mix(in srgb, var(--st-accepted) 22%, transparent);
  color: var(--diff-added);
}
.inline-alert-info {
  background: var(--st-published-bg);
  border-color: color-mix(in srgb, var(--primary) 18%, transparent);
  color: var(--primary-ink);
}
.inline-alert-warn {
  background: var(--st-warn-bg);
  border-color: color-mix(in srgb, var(--cta) 25%, transparent);
  color: var(--st-warn);
}
.inline-alert-dismiss {
  flex-shrink: 0;
  border: 0;
  background: transparent;
  color: inherit;
  opacity: 0.7;
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
  min-width: 28px;
  min-height: 28px;
}
.inline-alert-dismiss:hover {
  opacity: 1;
}

.empty-state {
  margin-top: 14px;
  padding: 18px 16px;
  border: 1px dashed var(--line-2);
  border-radius: var(--r-2);
  background: var(--paper);
  text-align: center;
}
.empty-state-title {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.empty-state-desc {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}
.empty-state .btn {
  margin-top: 12px;
}

.doc-card-list {
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.doc-card {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: var(--paper);
  font-size: 12.5px;
}
.doc-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 10px;
}
.doc-card-meta {
  font-size: 11px;
  margin-top: 4px;
  color: var(--muted);
}
.doc-card-actions {
  margin-top: 10px;
}

/* Spacing comes from `.pwa-detail-body` gap — no extra margin, so cancelled
   chrome aligns with the in-execution banner and detail cards. */
.cancellation-card {
  margin: 0;
  padding: 14px 16px;
  border-radius: var(--r-3);
  border: 1px solid color-mix(in srgb, var(--destructive) 22%, transparent);
  background: var(--st-cancelled-bg);
  font-size: 13px;
  line-height: 1.55;
}
.cancellation-card-title {
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 600;
  color: var(--st-cancelled);
}
.cancellation-card-reason {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid color-mix(in srgb, var(--destructive) 15%, transparent);
  font-weight: 600;
}
.cancellation-card-message {
  margin-top: 6px;
  color: var(--text);
}

/* Mark performed — success modal with document upload (Figma 07/2026) */
/* Padding comes from `.dialog-panel`; this stage centres its own body because
   it is a success confirmation, not a content dialog. */
.phone-shell .performed-success-modal {
  text-align: center;
}
.phone-shell .performed-success-scroll {
  overflow-y: auto;
  min-height: 0;
}
/* Box, bloom and margin come from the shared "SUCCESS MARK" block above, which
   this stage now renders through the same `DialogSuccessIcon` as the success
   dialogs. Only the centring is local. */
.phone-shell .performed-success-check {
  display: flex;
  align-items: center;
  justify-content: center;
}
.phone-shell .performed-success-title {
  margin: 0 0 8px;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.015em;
}
.phone-shell .performed-success-body {
  margin: 0 0 16px;
  font-size: 13.5px;
  color: var(--muted);
  line-height: 1.55;
}
.phone-shell .performed-upload-drop {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 20px 14px;
  border: 1px dashed var(--line-dash);
  border-radius: var(--r-3);
  background: var(--paper);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.phone-shell .performed-upload-drop:hover {
  background: var(--paper-2);
}
.phone-shell .performed-upload-icn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--canvas);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
}
.phone-shell .performed-upload-cta {
  font-size: 14px;
  font-weight: 600;
}
.phone-shell .performed-upload-hint {
  font-size: 11.5px;
  color: var(--muted-2);
}
.phone-shell .performed-success-list {
  text-align: left;
  margin-top: 12px;
}

/* Performed tour detail — tab pills (Figma 8:2387). Active/inactive via
   ink/paper contrast per Design Direction Board §H (no purple nav). */
.phone-shell .detail-tabs-row {
  display: flex;
  gap: 10px;
  padding: 8px 16px 10px;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
  /* Long DE labels ("Auftragsdetails" + "Meine Dokumente") may exceed
     narrow widths — degrade to horizontal scroll, never clip */
  overflow-x: auto;
  scrollbar-width: none;
}
.phone-shell .detail-tabs-row::-webkit-scrollbar {
  display: none;
}
.phone-shell .detail-tab-pill {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  white-space: nowrap;
  flex-shrink: 0;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--text);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  box-shadow: 0 1px 1px color-mix(in srgb, var(--shadow-ink) 5%, transparent);
  transition:
    background 0.12s,
    color 0.12s;
}
.phone-shell .detail-tab-pill.active {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--on-accent);
}
.phone-shell .detail-tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 12px;
  line-height: 16px;
  background: var(--canvas);
  color: var(--muted);
}
.phone-shell .detail-tab-pill.active .detail-tab-count {
  background: color-mix(in srgb, var(--on-accent) 25%, transparent);
  color: var(--on-accent);
}

/* My documents rows (Figma 8:2387) */
.phone-shell .mydocs-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.phone-shell .mydoc-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 16px;
  box-shadow: var(--sh-1);
}
.phone-shell .mydoc-row-mainline {
  display: flex;
  align-items: center;
  gap: 14px;
}
.phone-shell .mydoc-actions {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}
.phone-shell .mydoc-rejection {
  margin: 0;
  padding-top: 2px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--st-cancelled);
}
.phone-shell .doc-file-badge {
  position: relative;
  width: 40px;
  height: 48px;
  flex-shrink: 0;
  border-radius: 6px;
  background: var(--muted-2);
  color: var(--on-accent);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 9px;
  overflow: hidden;
}
.phone-shell .doc-file-badge::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  width: 12px;
  height: 12px;
  background: color-mix(in srgb, var(--shadow-ink) 12%, transparent);
  border-bottom-left-radius: 4px;
}
.phone-shell .mydoc-main {
  flex: 1;
  min-width: 0;
}
.phone-shell .mydoc-name {
  font-size: 14px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.phone-shell .mydoc-size {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}
.phone-shell .mydoc-side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
  max-width: 45%;
}
.phone-shell .mydoc-type {
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  text-align: right;
}
.phone-shell .mydoc-remove {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  border-radius: 50%;
  cursor: pointer;
  flex-shrink: 0;
  margin: 0 -6px 0 -4px;
}
.phone-shell .mydoc-remove:hover {
  color: var(--text);
  background: var(--canvas);
}

/* My documents tab — fixed bottom upload bar (Figma 8:2387) */
.phone-shell .mydocs-upload-bar {
  gap: 8px;
}
/* Button geometry follows the design-system .btn rules (radius --r-2,
   board §I) — only sizing matches the sibling detail bottom-bar buttons. */
.phone-shell .mydocs-upload-bar .btn.primary {
  padding: 12px 24px;
  font-size: 15px;
  font-weight: 600;
}
.phone-shell .mydocs-upload-hint {
  margin: 0;
  text-align: center;
  font-size: 12px;
  color: var(--muted);
}

/* Remove document confirmation (Figma 8:2545) */
/* Padding and alignment now come from `.dialog-panel`; this keeps only what is
   specific to the dialog — a positioning context for its close button. */
.phone-shell .remove-doc-modal {
  position: relative;
}
.phone-shell .remove-doc-close {
  position: absolute;
  top: 6px;
  right: 6px;
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted-2);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* `.confirm-sheet` / `.confirm-sheet-actions` / `.confirm-sheet-panel` are
   gone: ConfirmSheet renders through the `Dialog` primitive now, so the title,
   message and action row are governed by the DIALOG STANDARD above. The
   overrides here fought that standard (a 20px title against `.dialog-title`'s
   18px), and `-panel` / `-actions` had no markup applying them at all. */

/* Operational policies — two columns, matching the console's
   `grid gap-4 sm:grid-cols-2`. Switches and the action row span both. */
.policy-grid {
  margin-top: 16px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  max-width: 680px;
}
.policy-grid-full {
  grid-column: 1 / -1;
}
@media (max-width: 720px) {
  .policy-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
.policy-field {
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: var(--paper);
}
.policy-field .field-label {
  margin-bottom: 8px;
}
.policy-field .input {
  max-width: 140px;
}
/* Pill switch rows for the three cancellation policies. The console renders a
   `role="switch"` button next to its label; the prototype's pill treatment is
   an input+slider, so the label wraps both and no aria-labelledby is needed. */
.policy-switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  padding: 0 2px;
  cursor: pointer;
}
.policy-switch-label {
  font-size: 14px;
  color: var(--text);
  flex: 1;
}
.policy-switch {
  position: relative;
  width: 44px;
  height: 24px;
  flex-shrink: 0;
}
.policy-switch-input {
  opacity: 0;
  width: 0;
  height: 0;
}
.policy-switch-slider {
  position: absolute;
  inset: 0;
  background-color: var(--line-2);
  border-radius: 24px;
  transition: background-color 0.25s ease;
}
.policy-switch-slider::before {
  position: absolute;
  content: "";
  height: 18px;
  width: 18px;
  left: 3px;
  bottom: 3px;
  background-color: white;
  border-radius: 50%;
  transition: transform 0.25s ease;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--shadow-ink) 15%, transparent);
}
.policy-switch-input:checked + .policy-switch-slider {
  background-color: var(--primary);
}
.policy-switch-input:checked + .policy-switch-slider::before {
  transform: translateX(20px);
}
.policy-switch-input:focus-visible + .policy-switch-slider {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Compact binary access toggles (operationalAccess / accountAccess). Same
   switch grammar as .policy-switch; sized for table cells and profile rows. */
.access-control {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.access-switch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
  cursor: pointer;
}
.access-switch-input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute;
}
.access-switch-slider {
  position: absolute;
  inset: 0;
  background-color: var(--line-2);
  border-radius: 22px;
  transition: background-color 0.2s ease;
}
.access-switch-slider::before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 3px;
  bottom: 3px;
  background-color: white;
  border-radius: 50%;
  transition: transform 0.2s ease;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--shadow-ink) 15%, transparent);
}
.access-switch-input:checked + .access-switch-slider {
  background-color: var(--primary);
}
.access-switch-input:checked + .access-switch-slider::before {
  transform: translateX(18px);
}
.access-switch-input:focus-visible + .access-switch-slider {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Save + Discard, side by side across the full grid width. */
.policy-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

/* System settings — one unified Help contacts card with three channels. */
.help-contacts-form {
  margin-top: 16px;
}
.help-contacts-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  overflow: hidden;
}
.help-contact-group {
  display: grid;
  grid-template-columns: minmax(180px, 0.72fr) minmax(0, 1.28fr);
  align-items: start;
  gap: 24px;
  min-width: 0;
  margin: 0;
  padding: 20px 18px;
  border-bottom: 1px solid var(--line);
}
.help-contact-group:last-child {
  border-bottom: 0;
}
.help-contact-group-copy {
  min-width: 0;
}
.help-contact-group-copy h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 650;
  color: var(--text);
}
.help-contact-group-copy p {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}
.help-contact-fields {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
}
.help-contact-field {
  min-width: 0;
}
.help-contact-field .field-label {
  margin-bottom: 7px;
}
.help-contact-field .input {
  width: 100%;
  max-width: none;
}
.help-contacts-actions {
  margin-top: 16px;
}
@media (max-width: 720px) {
  .help-contact-group {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
    padding: 18px 16px;
  }
  .help-contact-fields {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* System settings — driver upload limits card (two MB fields + hints). */
.upload-limits-form {
  margin-top: 16px;
}
.upload-limits-hint {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}
.upload-limits-actions {
  margin-top: 16px;
}

.field-counter {
  margin-top: 4px;
  font-size: 11px;
  color: var(--muted);
}
.field-counter.invalid {
  color: var(--st-cancelled);
  font-weight: 600;
}
.field-counter.valid {
  color: var(--st-accepted);
}

/* Figma File Type Selection Redesign */
.phone-shell .category-picker {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 14px;
}
.phone-shell .category-group-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 4px;
  margin-left: 4px;
}
.phone-shell .category-group {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--shadow-ink) 2%, transparent);
}
.phone-shell .category-group-item {
  display: flex;
  width: 100%;
  padding: 14px 16px;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
  outline: none;
}
.phone-shell .category-group-item:last-child {
  border-bottom: none;
}
.phone-shell .category-group-item:hover {
  background: var(--canvas);
}
.phone-shell .category-picker-desc {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.45;
  margin: 6px 4px 0;
}

/* Upload-source action sheet — "Foto aufnehmen" vs. "Datei auswählen".
   Bottom sheet so it reads as a source choice, not a form; the camera only
   opens once the driver picks the photo action. Reuses the .sheet surface,
   .category-group row rhythm and the paper/line/muted semantic tokens. */
.phone-shell .upload-source-sheet {
  padding-bottom: var(--phone-chrome-bottom);
}
.phone-shell .upload-source-body {
  padding: 4px 20px 20px;
  overflow-y: auto;
  /* The tour-completion modal centres its text; the sheet must read the
     same from every entry point. */
  text-align: left;
}
.phone-shell .upload-source-title {
  margin: 14px 4px 12px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.phone-shell .upload-source-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.phone-shell .upload-source-action {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 16px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    background 0.15s ease,
    border-color 0.15s ease;
}
.phone-shell .upload-source-action:hover {
  background: var(--canvas);
}
/* Focus ring comes from the global :focus-visible rule (--primary). */
.phone-shell .upload-source-icn {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--canvas);
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
}
.phone-shell .upload-source-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.phone-shell .upload-source-label {
  font-size: 14px;
  font-weight: 600;
}
.phone-shell .upload-source-desc {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.4;
}

/* Document-details amount walk — invoice / fuel / toll receipts after the
   staged review. Uses the shared bottom Sheet chrome; these rules only set
   the form rhythm so three amount fields stay usable on a 320–390px column. */
.phone-shell .tour-doc-amount-sheet .sheet-body {
  text-align: left;
}
.phone-shell .tour-doc-amount-walk-progress {
  margin: 0 0 4px;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.4;
}
.phone-shell .tour-doc-amount-field .field-label {
  margin-top: 14px;
  margin-bottom: 6px;
}
.phone-shell
  .tour-doc-amount-sheet
  .sheet-body
  > .tour-doc-amount-field:first-child
  .field-label,
.phone-shell
  .tour-doc-amount-sheet
  .sheet-body
  > .tour-doc-amount-walk-progress
  + .tour-doc-amount-field
  .field-label {
  margin-top: 0;
}
.phone-shell .tour-doc-amount-period,
.phone-shell .tour-doc-amount-figures {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.phone-shell .tour-doc-amount-figures .tour-doc-amount-gross {
  grid-column: 1 / -1;
}
.phone-shell .tour-doc-amount-period .field-label,
.phone-shell .tour-doc-amount-figures .field-label {
  margin-top: 14px;
}
.phone-shell .tour-doc-amount-err {
  margin: 12px 0 0;
  color: var(--destructive);
  font-size: 12.5px;
  line-height: 1.4;
}

/* Staged multi-select review — between the file picker and the upload.
   Allowance figure lives here only; row marks name the oversize file. */
.phone-shell .staged-upload-sheet .sheet-body {
  text-align: left;
}
.phone-shell .staged-upload-category {
  margin: 0;
  font-size: 12.5px;
  color: var(--muted);
}
.phone-shell .staged-upload-usage {
  margin: 6px 0 0;
  font-size: 13.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.phone-shell .staged-upload-list {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.phone-shell .staged-upload-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--canvas);
}
.phone-shell .staged-upload-row-main {
  min-width: 0;
  flex: 1;
}
.phone-shell .staged-upload-name {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.phone-shell .staged-upload-size {
  margin: 2px 0 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
/* Semantic tokens, not literals: --st-warn / --destructive are the same pair
   the evidence rows and every inline form error already use, and they are
   re-toned for dark mode. A hardcoded hex here would not be. */
.phone-shell .staged-upload-warn {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--st-warn);
}
.phone-shell .staged-upload-fail {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--destructive);
}
/* Upload phases. Two displays, never one bar that changes label: the
   determinate track is REPLACED by an indeterminate one at 100%, because a
   bar parked full is the exact thing this work removes. Tokens only, as
   above — they are re-toned for dark mode and a hardcoded hex would not be. */
.phone-shell .staged-upload-progress {
  margin: 8px 0 0;
}
.phone-shell .staged-upload-progress-counter {
  margin: 0 0 6px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.phone-shell .staged-upload-progress-track {
  position: relative;
  width: 100%;
  height: 6px;
  overflow: hidden;
  border-radius: 99px;
  border: 1px solid var(--line);
  background: var(--paper-2);
}
.phone-shell .staged-upload-progress-bar {
  height: 100%;
  border-radius: 99px;
  background: var(--primary);
  transition: width 0.12s linear;
}
.phone-shell
  .staged-upload-progress-track.is-indeterminate
  .staged-upload-progress-bar {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 40%;
  transition: none;
  animation: staged-upload-indeterminate 1.1s ease-in-out infinite;
}
@keyframes staged-upload-indeterminate {
  from {
    left: -40%;
  }
  to {
    left: 100%;
  }
}
.phone-shell .staged-upload-progress-meta {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin: 6px 0 0;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.phone-shell .staged-upload-processing {
  margin: 6px 0 0;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
}
.phone-shell .staged-upload-processing-hint {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.35;
  color: var(--muted);
}
/* Reduced motion still needs "something is happening"; a static half-tone
   fill says that without the sweep. */
@media (prefers-reduced-motion: reduce) {
  .phone-shell
    .staged-upload-progress-track.is-indeterminate
    .staged-upload-progress-bar {
    position: static;
    width: 100%;
    opacity: 0.5;
    animation: none;
  }
}
.phone-shell .staged-upload-remove {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  color: var(--text);
  cursor: pointer;
}
.phone-shell .staged-upload-remove:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.phone-shell .staged-upload-sheet .inline-alert {
  margin-top: 12px;
}
.phone-shell .staged-upload-offline {
  margin: 12px 0 0;
  text-align: center;
  font-size: 12px;
  color: var(--muted);
}

.limit-meter {
  margin-top: 12px;
}
.limit-meter-track {
  height: 8px;
  border-radius: 4px;
  background: var(--paper-3);
  border: 1px solid var(--line);
  overflow: hidden;
}
.limit-meter-fill {
  display: block;
  height: 100%;
  background: var(--primary);
  transition: width 0.25s ease;
}
.limit-meter-fill.at-limit {
  background: var(--st-warn);
}
.limit-meter-meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  margin-top: 8px;
  font-size: 12px;
  color: var(--muted);
}
.limit-meter-count {
  font-weight: 600;
  font-size: 15px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* =========================================================================
   DRIVER PWA VISUAL OVERHAUL EXTRA STYLES
   ========================================================================= */

/* My Jobs Search & Tabs */
.phone-shell .myjobs-search-row {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 12px 20px 16px;
  background: var(--paper);
}
.phone-shell .myjobs-search-input-wrap {
  position: relative;
  flex: 1;
}
.phone-shell .myjobs-search-input-wrap svg {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  width: 16px;
  height: 16px;
  pointer-events: none;
}
.phone-shell .myjobs-search-input-wrap input {
  width: 100%;
  padding: 10px 12px 10px 36px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--canvas);
  color: var(--text);
  font-size: 14px;
  outline: none;
  transition: all 0.15s ease;
}
.phone-shell .myjobs-search-input-wrap input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent);
}

.phone-shell .myjobs-tabs-slider {
  display: flex;
  justify-content: space-between;
  padding: 0 16px;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.phone-shell .myjobs-tabs-slider::-webkit-scrollbar {
  display: none;
}
.phone-shell .myjobs-tab-pill {
  display: inline-flex;
  align-items: center;
  padding: 12px 0 10px;
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  position: relative;
  transition: all 0.15s ease;
  outline: none;
}
.phone-shell .myjobs-tab-pill.active {
  color: var(--primary);
}
.phone-shell .myjobs-tab-pill::after {
  content: "";
  position: absolute;
  bottom: -1px;
  left: 0;
  right: 0;
  height: 2px;
  background: transparent;
  transition: background-color 0.15s ease;
}
.phone-shell .myjobs-tab-pill.active::after {
  background: var(--primary);
}
.phone-shell .myjobs-tab-pill .pill-badge {
  font-size: 10px;
  padding: 1px 5px;
  border-radius: 10px;
  background: var(--canvas);
  color: var(--muted);
  font-weight: 600;
  margin-left: 4px;
}
.phone-shell .myjobs-tab-pill.active .pill-badge {
  background: var(--paper-3);
  color: var(--primary);
}
[data-theme="dark"] .phone-shell .myjobs-tab-pill.active .pill-badge {
  background: color-mix(in srgb, var(--primary) 20%, transparent);
  color: var(--primary-ink);
}

/* Assigned Job Card Banner */
.phone-shell .jobcard-banner-assigned {
  background: var(--st-assigned-bg);
  color: var(--st-assigned);
  font-size: var(--text-caption);
  font-weight: 600;
  padding: 10px 16px;
  border-radius: 16px 16px 0 0;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -16px -16px 16px -16px;
  border-bottom: 1px solid var(--line);
}
/* dark: root --st-assigned tokens adapt — no override needed */

/* Profile Form styling */
.phone-shell .input,
.phone-shell select.input {
  border-radius: 12px;
  border: 1px solid var(--line);
  /* background-color, not the shorthand — select.input carries the
     custom chevron as a background-image */
  background-color: var(--paper);
  color: var(--text);
  padding: 10px 14px;
  font-size: 14px;
  outline: none;
  transition: all 0.15s ease;
  width: 100%;
}
.phone-shell .input:focus,
.phone-shell select.input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent);
}
.phone-shell select.input {
  cursor: pointer;
  padding-right: 42px;
}

/* Toggle segment selectors */
.phone-shell .seg {
  display: flex;
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
  background: var(--canvas);
  margin-top: 6px;
}
.phone-shell .seg button {
  flex: 1;
  padding: 10px;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
}
.phone-shell .seg button.on {
  background: var(--paper);
  color: var(--text);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--shadow-ink) 5%, transparent);
}
[data-theme="dark"] .phone-shell .seg button.on {
  box-shadow: 0 2px 6px color-mix(in srgb, var(--shadow-ink) 20%, transparent);
}

/* My Documents / Uploaded Document Cards */
.phone-shell .doc-card {
  padding: 16px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--shadow-ink) 2%, transparent);
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: box-shadow 0.2s ease;
}
.phone-shell .doc-card:hover {
  box-shadow: 0 4px 12px color-mix(in srgb, var(--shadow-ink) 4%, transparent);
}
.phone-shell .doc-card-layout {
  display: flex;
  align-items: center;
  gap: 14px;
}
.phone-shell .doc-card-icon-container {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: var(--doc-icon-bg);
  color: var(--doc-icon-fg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 10px;
  flex-shrink: 0;
}
.phone-shell .doc-card-details {
  flex: 1;
  min-width: 0;
}
.phone-shell .doc-card-filename {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.phone-shell .doc-card-size {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}
.phone-shell .doc-card-category-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  background: var(--canvas);
  padding: 4px 10px;
  border-radius: 8px;
  white-space: nowrap;
}
.phone-shell .doc-card-close-btn {
  background: transparent;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: 6px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s ease;
}
.phone-shell .doc-card-close-btn:hover {
  background: var(--canvas);
  color: var(--text);
}

/* Infopoint news & documents cards */
.phone-shell .infopoint-card {
  padding: 16px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--paper);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--shadow-ink) 2%, transparent);
  margin-top: 14px;
}
.phone-shell .infopoint-doc-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.phone-shell .infopoint-doc-row:last-child {
  border-bottom: none;
}
.phone-shell .infopoint-news-row {
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.phone-shell .infopoint-news-row:last-child {
  border-bottom: none;
}

/* My Jobs Card Header Row styling */
.phone-shell .jobcard-header-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  margin-top: 2px;
}
.phone-shell .jobcard-tour-num {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}
.phone-shell .jobcard-header-row .pill {
  font-size: 11px;
  padding: 3px 8px;
  font-weight: 500;
  border-radius: var(--r-pill);
}
.phone-shell .jobcard-header-row .chip.correction-required {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: var(--r-pill);
}

/* Floating Notifications Dropdown Popover */
/* Notifications — full-height page panel (plan §7.6; replaces the
   desktop-style anchored popover, which is the wrong pattern on mobile) */
.phone-shell .notifications-dropdown-backdrop {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: color-mix(in srgb, var(--scrim-ink) 20%, transparent);
  z-index: var(--z-sheet);
}
.phone-shell .notifications-dropdown {
  position: absolute;
  top: var(--phone-chrome-top);
  right: var(--phone-chrome-right);
  bottom: var(--phone-chrome-bottom);
  left: var(--phone-chrome-left);
  width: auto;
  max-height: none;
  background: var(--canvas);
  border: none;
  border-radius: 0;
  box-shadow: none;
  z-index: var(--z-sheet);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: slideInRight 0.2s cubic-bezier(0.32, 0.72, 0, 1);
}
@keyframes slideInRight {
  from {
    transform: translateX(24px);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}
@keyframes fadeInDown {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.phone-shell .notifications-dropdown-header {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px max(20px, var(--phone-chrome-right)) 14px
    max(20px, var(--phone-chrome-left));
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.phone-shell .notifications-pane-head-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.phone-shell .notifications-pane-head-row h3 {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
.phone-shell .notifications-pane-sub-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px 12px;
  flex-wrap: wrap;
}
.phone-shell .notifications-pane-sub-row .label {
  flex: 1 1 160px;
  min-width: 0;
}
.phone-shell .notifications-dropdown-header h3 {
  margin: 0;
  font-size: var(--text-title);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.phone-shell .notifications-dropdown-header .label {
  margin-top: 4px;
}
.phone-shell .notifications-mark-all-btn svg {
  flex-shrink: 0;
  display: block;
}
.phone-shell .notifications-mark-all-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 40px;
  padding: 8px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--paper-2);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition:
    background 0.15s ease,
    border-color 0.15s ease,
    color 0.15s ease,
    box-shadow 0.15s ease;
}
.phone-shell .notifications-mark-all-btn:hover {
  background: color-mix(in srgb, var(--primary) 8%, transparent);
  border-color: var(--primary);
  color: var(--primary);
}
.phone-shell .notifications-mark-all-btn:active {
  transform: translateY(1px);
}
.phone-shell .notifications-mark-all-btn:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.phone-shell .notifications-mark-all-label {
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
.phone-shell .notifications-all-read-hint {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}
.phone-shell .notifications-close-btn {
  flex-shrink: 0;
}
.phone-shell .notifications-close-btn:hover {
  background: var(--paper-2);
  border-color: var(--line-3);
}
.phone-shell .notifications-dropdown-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px max(20px, var(--phone-chrome-right))
    calc(24px + var(--phone-chrome-bottom)) max(20px, var(--phone-chrome-left));
}

/* In-app document viewer — full-height page inside the phone frame */
.phone-shell .docview-panel {
  position: absolute;
  top: var(--phone-chrome-top);
  right: var(--phone-chrome-right);
  bottom: var(--phone-chrome-bottom);
  left: var(--phone-chrome-left);
  background: var(--canvas);
  z-index: var(--z-sheet);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: slideInRight 0.2s cubic-bezier(0.32, 0.72, 0, 1);
}
.phone-shell .docview-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.phone-shell .docview-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.phone-shell .docview-filename {
  font-size: var(--text-caption);
  color: var(--muted);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.phone-shell .docview-body {
  flex: 1;
  min-height: 0;
  background: var(--paper-2);
}
.phone-shell .docview-pages {
  height: 100%;
  overflow-y: auto;
  padding: 12px;
}
.phone-shell .docview-pages .docview-page {
  display: block;
  margin: 0 auto 12px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: var(--sh-1);
  max-width: 100%;
}
.phone-shell .docview-loading {
  padding: 8px 4px;
}
/* Admin-side A4 preview of a generated transport order. The frame carries the
   real 210 mm-wide document and scrolls inside the dialog's content area, so
   the approved layout is inspected at true proportions. */
.admin-a4-preview {
  display: block;
  width: 100%;
  height: min(62vh, 720px);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: #fff;
}

/* Generated transport-order document (Task 17). The frame is a full 210×297 mm
   A4 page; scaling it down with a transform preserves the approved layout
   exactly, whereas letting it reflow to the phone width would not. The wrapper
   reserves the SCALED height so the scroll container measures correctly. */
.phone-shell .docview-a4-scaler {
  --a4-scale: 0.42;
  width: calc(210mm * var(--a4-scale));
  height: calc(297mm * var(--a4-scale));
  margin: 0 auto;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 4px;
  box-shadow: var(--sh-1);
  overflow: hidden;
}
.phone-shell .docview-a4 {
  display: block;
  width: 210mm;
  height: 297mm;
  border: 0;
  background: #fff;
  transform: scale(var(--a4-scale));
  transform-origin: top left;
}
.phone-shell .docview-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--paper);
}
.phone-shell .docview-actions {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  padding: 8px 0 calc(8px + var(--phone-chrome-bottom));
  background: var(--paper);
  border-top: 1px solid var(--line);
  flex-shrink: 0;
}
.phone-shell .docview-action {
  position: relative;
  display: flex;
  min-width: 0;
  min-height: 58px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 6px 8px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition:
    background 0.14s ease,
    transform 0.04s ease;
}
.phone-shell .docview-action:hover {
  background: var(--paper-3);
}
.phone-shell .docview-action:active {
  transform: translateY(1px);
}
.phone-shell .docview-action + .docview-action::before {
  content: "";
  position: absolute;
  left: 0;
  top: 10px;
  bottom: 10px;
  width: 1px;
  background: var(--line);
}
.phone-shell .docview-action-icon {
  display: flex;
  width: 24px;
  height: 24px;
  align-items: center;
  justify-content: center;
  color: var(--text);
}
.phone-shell .docview-action-icon svg {
  width: 22px;
  height: 22px;
}
.phone-shell .docview-action-label {
  max-width: 100%;
  overflow: hidden;
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.15;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Profile Redesign & Switch Toggles */
.phone-shell .profile-verified-badge {
  display: inline-flex;
  align-items: center;
  color: var(--primary);
  margin-left: 6px;
}

/* Daily Limits Progress Meter */
.phone-shell .limit-progress-track {
  width: 100%;
  height: 8px;
  background: var(--paper-2);
  border-radius: 99px;
  overflow: hidden;
  margin-top: 8px;
  margin-bottom: 4px;
  border: 1px solid var(--line);
}
.phone-shell .limit-progress-bar {
  height: 100%;
  background: var(--primary);
  border-radius: 99px;
  transition: width 0.3s ease;
}

/* Premium iOS Switch Toggle */
.phone-shell .switch-toggle-wrap {
  position: relative;
  width: 44px;
  height: 24px;
  flex-shrink: 0;
}
.phone-shell .switch-toggle-input {
  opacity: 0;
  width: 0;
  height: 0;
}
.phone-shell .switch-slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--line-2);
  transition: 0.25s ease;
  border-radius: 24px;
}
.phone-shell .switch-slider::before {
  position: absolute;
  content: "";
  height: 18px;
  width: 18px;
  left: 3px;
  bottom: 3px;
  background-color: white;
  transition: 0.25s ease;
  border-radius: 50%;
  box-shadow: 0 1px 3px color-mix(in srgb, var(--shadow-ink) 15%, transparent);
}
.phone-shell .switch-toggle-input:checked + .switch-slider {
  background-color: var(--primary);
}
.phone-shell .switch-toggle-input:checked + .switch-slider::before {
  transform: translateX(20px);
}

/* Postal Chip Tags Input */
.phone-shell .postal-chip-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  min-height: 44px;
  align-items: center;
}
.phone-shell .postal-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 4px 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  line-height: 1;
}
.phone-shell .postal-chip-delete {
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--muted-2);
  font-size: 14px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.phone-shell .postal-chip-delete:hover {
  color: var(--st-cancelled);
}
.phone-shell .postal-chip-input {
  border: none;
  outline: none;
  background: transparent;
  font-size: 13px;
  color: var(--text);
  padding: 4px 0;
  flex: 1;
  min-width: 60px;
}

/* Marketplace filter — multi-select PLZ area pills (00xxx) */
.phone-shell .filter-plz-block {
  margin-top: 10px;
}
.phone-shell .filter-plz-block > .field-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  margin-bottom: 6px;
}
.phone-shell .filter-plz-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.phone-shell .filter-plz-row .input {
  flex: 1;
  min-width: 0;
}
.phone-shell .filter-plz-add {
  flex-shrink: 0;
  border-radius: 999px;
  padding: 8px 14px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  white-space: nowrap;
}
.phone-shell .filter-plz-add:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.phone-shell .filter-plz-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.phone-shell .filter-plz-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  color: var(--text);
  border-radius: 999px;
  padding: 6px 10px 6px 12px;
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
[data-theme="dark"] .phone-shell .filter-plz-pill {
  background: var(--paper-3);
}
.phone-shell .filter-plz-pill-x {
  background: transparent;
  border: none;
  color: var(--muted-2);
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0 2px;
  opacity: 0.85;
}
.phone-shell .filter-plz-pill-x:hover {
  opacity: 1;
}
/* iOS Safari auto-zooms the viewport when a focused form control has a
   computed font-size below 16px, which jerks the whole phone-shell (a
   sudden zoom + scroll-into-view "jump") on every tap. Scope a 16px floor
   to coarse pointers so real touch devices never trigger the zoom, while
   the desktop phone-frame preview keeps its designed 13–14px density. */
@media (pointer: coarse) {
  .phone-shell input,
  .phone-shell textarea,
  .phone-shell select,
  .phone-shell .input,
  .phone-shell select.input,
  .phone-shell .postal-chip-input,
  .phone-shell .myjobs-search-input-wrap input {
    font-size: 16px;
  }
}
[data-theme="dark"] .phone-shell .postal-chip-container {
  background: var(--paper-2);
}
[data-theme="dark"] .phone-shell .postal-chip {
  background: var(--paper-3);
}

/* ===============================================
   TOKEN UTILITIES (plan §4 — the only sanctioned
   typography/spacing vocabulary for JSX; replaces
   inline style={{ fontSize, marginTop, ... }})
   =============================================== */
.text-display {
  font-size: var(--text-display);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.015em;
}
.text-title {
  font-size: var(--text-title);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.text-heading {
  font-size: var(--text-heading);
  font-weight: 600;
  line-height: 1.3;
}
.text-body {
  font-size: var(--text-body);
  line-height: 1.5;
}
.text-body-sm {
  font-size: var(--text-body-sm);
  line-height: 1.5;
}
.text-caption {
  font-size: var(--text-caption);
  font-weight: 500;
  line-height: 1.45;
  color: var(--muted);
}
.text-overline {
  font-size: var(--text-overline);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.text-strong {
  font-weight: 600;
  color: var(--text);
}
.text-muted {
  color: var(--muted);
}
/* data identifiers only (tour no., PLZ, VIN, timestamps, money) */
.data-mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* 4-pt spacing stack (plan §4.3) */
.stack-4 {
  margin-top: 4px;
}
.stack-8 {
  margin-top: 8px;
}
.stack-12 {
  margin-top: 12px;
}
.stack-16 {
  margin-top: 16px;
}
.stack-20 {
  margin-top: 20px;
}
.stack-24 {
  margin-top: 24px;
}
.row-8 {
  display: flex;
  align-items: center;
  gap: 8px;
}
.row-12 {
  display: flex;
  align-items: center;
  gap: 12px;
}
.row-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* ===============================================
   DRIVER PWA — SECTION CARD SYSTEM (plan §5/§7)
   One card grammar for every profile/infopoint section.
   =============================================== */
.phone-shell .section-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-4);
  padding: 16px;
  margin-top: 12px;
}
.phone-shell .section-card .section-title {
  margin: 0;
  font-size: var(--text-heading);
  font-weight: 600;
  line-height: 1.3;
  color: var(--text);
}
.phone-shell .section-card .section-hint {
  margin: 6px 0 0;
  font-size: var(--text-caption);
  color: var(--muted);
  line-height: 1.45;
}
/* Empty states / placeholder areas read as content, not code (plan §6.3) */
.phone-shell .dash-area {
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.5;
}
.phone-shell .dash-area .btn {
  font-family: var(--font-sans);
  letter-spacing: 0;
}

/* Form labels: caption-size sentence case sans (plan §4.2 —
   uppercase micro-mono was flattening hierarchy everywhere) */
.phone-shell .field-label,
.phone-shell .label {
  font-family: var(--font-sans);
  font-size: var(--text-caption);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 600;
  color: var(--text);
}

/* Profile master-data list — stacked on phone (plan §7.7.3) */
.phone-shell .profile-field-row {
  grid-template-columns: 1fr;
  gap: 3px;
  padding: 12px 16px;
}
.phone-shell .profile-field-row.is-changed {
  background: color-mix(in srgb, var(--st-accepted) 4%, transparent);
  border-left: 3px solid var(--st-accepted);
  padding-left: 13px;
}
.phone-shell .profile-field-label {
  font-size: var(--text-caption);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
  color: var(--muted);
  padding-top: 0;
}
.phone-shell .profile-field-value {
  font-size: var(--text-body-sm);
  font-weight: 500;
  color: var(--text);
  overflow-wrap: anywhere;
}
.phone-shell .profile-field-value.is-new {
  color: var(--st-accepted);
  font-weight: 600;
}
.phone-shell .profile-field-old {
  text-decoration: line-through;
  color: var(--muted-2);
  font-size: 12px;
  margin-top: 2px;
}
.phone-shell .profile-field-badge {
  background: var(--st-accepted-bg);
  color: var(--st-accepted);
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 6px;
  font-weight: 600;
}

.phone-shell .profile-identity {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 4px 2px 14px;
}
.phone-shell .profile-identity .avatar {
  width: 56px;
  height: 56px;
  font-size: var(--text-body);
  background: color-mix(in srgb, var(--primary) 10%, transparent);
  color: var(--primary);
  border: none;
}
.phone-shell .profile-identity-name {
  font-size: var(--text-heading);
  font-weight: 600;
  color: var(--text);
  display: flex;
  align-items: center;
  gap: 4px;
}
.phone-shell .profile-identity-code {
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--muted);
  margin-top: 3px;
}
/* Account & sign-in — driver-owned credential card (Task 1) */
.phone-shell .account-signin-title {
  display: flex;
  align-items: center;
  gap: 8px;
}
.phone-shell .account-signin-key {
  font-size: 15px;
  line-height: 1;
}
.phone-shell .account-email-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px 0 2px;
}
.phone-shell .account-email-value {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.phone-shell .account-email-address {
  font-size: var(--text-body-sm);
  font-weight: 500;
  color: var(--text);
  overflow-wrap: anywhere;
}
.phone-shell .account-email-verified {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-caption);
  font-weight: 600;
  color: var(--diff-added);
  white-space: nowrap;
}
.phone-shell .account-email-verified .dot {
  font-size: 9px;
  line-height: 1;
}
.phone-shell .account-email-badge {
  flex-shrink: 0;
}
/* Change-email sheet */
.phone-shell .change-email-current {
  font-size: var(--text-body-sm);
  color: var(--muted);
}
.phone-shell .code-input-row {
  display: flex;
  gap: 8px;
  justify-content: space-between;
}
.phone-shell .code-input-box {
  flex: 1;
  min-width: 0;
  height: 52px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 600;
  color: var(--text);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-2);
}
.phone-shell .code-input-box:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.15);
}
.phone-shell .change-email-resend-row {
  min-height: 24px;
  display: flex;
  align-items: center;
}
/* Tertiary text links under the OTP row (Resend / Change address).
   Matches Report-problem terms-link treatment: primary tint + underline,
   not a filled/outline button that would compete with Confirm change. */
.phone-shell .change-email-aux-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  flex-wrap: wrap;
}
.phone-shell .change-email-resend-wait {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.phone-shell .change-email-text-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: var(--text-body-sm);
  font-weight: 500;
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.phone-shell .change-email-text-link:hover {
  color: var(--primary-ink);
}
.phone-shell .change-email-text-link:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--r-1);
}
.phone-shell .change-email-success-check {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  background: rgba(var(--primary-rgb), 0.12);
  color: var(--primary);
}
.phone-shell .switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  cursor: pointer;
}
.phone-shell .switch-row-text {
  font-size: var(--text-body-sm);
  font-weight: 500;
  color: var(--text);
  flex: 1;
}
.phone-shell .contact-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  min-height: 48px;
  text-decoration: none;
  border-bottom: 1px solid var(--line);
}
.phone-shell .contact-row:last-child {
  border-bottom: none;
}
.phone-shell .contact-row-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--r-2);
  background: color-mix(in srgb, var(--primary) 8%, transparent);
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.phone-shell .contact-row-value {
  font-family: var(--font-mono);
  font-size: var(--text-body-sm);
  font-weight: 600;
  color: var(--text);
}
.phone-shell .contact-row-sub {
  font-size: var(--text-caption);
  color: var(--muted);
  margin-top: 2px;
}

/* ---------------------------------------------------------------------------
   Profile: navigation-list / drill-down layout
   (identity card, summary card, grouped nav rows, app-version)
   --------------------------------------------------------------------------- */
.phone-shell .profile-identity-card {
  display: flex;
  align-items: center;
  gap: 14px;
}
.phone-shell .profile-identity-card .avatar {
  width: 56px;
  height: 56px;
  font-size: var(--text-body);
  background: rgba(var(--primary-rgb), 0.1);
  color: var(--primary);
  border: none;
  flex-shrink: 0;
}
.phone-shell .profile-identity-partner {
  font-size: var(--text-body-sm);
  color: var(--muted);
  margin-top: 4px;
  overflow-wrap: anywhere;
}

/* Summary card — rows with dividers; only the log-out row is actionable */
.phone-shell .profile-summary-card {
  padding: 0;
  overflow: hidden;
}
.phone-shell .profile-summary-row {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 56px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  text-align: left;
}
.phone-shell .profile-summary-row:last-child {
  border-bottom: none;
}
.phone-shell button.profile-summary-action {
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-top: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.phone-shell button.profile-summary-action:last-child {
  border-bottom: none;
}
.phone-shell .profile-summary-action:focus-visible,
.phone-shell .profile-nav-row:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: -2px;
}
.phone-shell .profile-summary-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  flex-shrink: 0;
  color: var(--text);
}
.phone-shell .profile-summary-icon.is-status {
  color: var(--st-accepted);
}
.phone-shell .profile-summary-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.phone-shell .profile-summary-label {
  font-size: var(--text-body-sm);
  color: var(--muted);
}
.phone-shell .profile-summary-value {
  font-size: var(--text-body-sm);
  font-weight: 600;
  color: var(--text);
  margin-top: 2px;
  overflow-wrap: anywhere;
}
.phone-shell .profile-summary-value.is-active {
  color: var(--st-accepted);
}
.phone-shell .profile-summary-action-label {
  font-size: var(--text-body-sm);
  font-weight: 600;
  color: var(--text);
}

/* Grouped navigation */
.phone-shell .profile-group {
  margin-top: 22px;
}
.phone-shell .profile-group-label {
  margin: 0 0 8px;
  padding: 0 4px;
  font-size: var(--text-caption);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.phone-shell .section-card.profile-nav-card {
  margin-top: 0;
  padding: 0;
  overflow: hidden;
}
.phone-shell .profile-nav-row {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 56px;
  padding: 15px 16px;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.phone-shell .profile-nav-row:last-child {
  border-bottom: none;
}
.phone-shell .profile-nav-row-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  flex-shrink: 0;
  color: var(--text);
}
.phone-shell .profile-nav-row-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.phone-shell .profile-nav-row-label {
  font-size: var(--text-body-sm);
  font-weight: 600;
  color: var(--text);
  overflow-wrap: anywhere;
}
.phone-shell .profile-nav-row-sub {
  font-size: var(--text-caption);
  color: var(--muted);
  margin-top: 2px;
  overflow-wrap: anywhere;
}
.phone-shell .profile-nav-row-chevron {
  display: inline-flex;
  align-items: center;
  color: var(--muted-2);
  flex-shrink: 0;
}
.phone-shell .profile-mailto-row {
  text-decoration: none;
}
.phone-shell .profile-mailto-row .profile-nav-row-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--r-2);
  background: color-mix(in srgb, var(--primary) 8%, transparent);
  color: var(--primary);
}
.phone-shell .profile-mailto-row-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 8%, transparent);
  flex-shrink: 0;
}
.phone-shell .profile-mailto-row:hover {
  background: color-mix(in srgb, var(--primary) 4%, transparent);
}
.phone-shell .profile-version {
  text-align: center;
  font-size: var(--text-caption);
  color: var(--muted-2);
  margin: 22px 0 4px;
}
.phone-shell .btn.destructive-outline {
  border: 1px solid var(--st-cancelled);
  color: var(--st-cancelled);
  background: transparent;
  transition:
    background 0.14s ease,
    border-color 0.14s ease,
    color 0.14s ease,
    transform 0.04s ease;
}
.phone-shell .btn.destructive-outline:hover {
  background: var(--st-cancelled-bg);
  border-color: var(--st-cancelled);
  color: var(--st-cancelled);
}
.phone-shell .btn.destructive-outline:active {
  transform: translateY(1px);
}

/* interactive baseline (plan §4.3 touch + §8 a11y) */
.tappable {
  min-width: 44px;
  min-height: 44px;
}
:where(button, [role="button"], a):focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--r-1);
}

/* ===============================================
   UI PRIMITIVES (driver-ui.jsx)
   =============================================== */
.ui-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-pill);
  font-size: var(--text-overline);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.ui-badge-primary {
  background: var(--primary);
  color: var(--on-accent);
}
.ui-badge-destructive {
  background: var(--destructive);
  color: var(--on-destructive);
}
.ui-badge-dot {
  width: 8px;
  height: 8px;
  min-width: 8px;
  padding: 0;
  border-radius: 50%;
}

.skeleton-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-4) 0;
}
.skeleton-jobcard {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.skeleton-line {
  height: 12px;
  border-radius: var(--r-1);
  background: linear-gradient(
    90deg,
    var(--paper-2) 25%,
    var(--paper-3) 50%,
    var(--paper-2) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.2s ease-in-out infinite;
}
.skeleton-line-lg {
  width: 70%;
  height: 16px;
}
.skeleton-line-md {
  width: 50%;
}
.skeleton-line-sm {
  width: 35%;
}
@keyframes skeleton-shimmer {
  0% {
    background-position: 100% 0;
  }
  100% {
    background-position: -100% 0;
  }
}

/* SortSelect — header trigger + portaled dropdown menu */
.phone-shell .sort-trigger {
  flex-shrink: 0;
  padding: 0;
}

.phone-shell .sort-dropdown-backdrop {
  position: absolute;
  inset: 0;
  z-index: var(--z-sheet);
  background: color-mix(in srgb, var(--scrim-ink) 28%, transparent);
  backdrop-filter: blur(1px);
  animation: fade 0.16s ease;
}

.phone-shell .sort-dropdown-panel {
  position: absolute;
  z-index: calc(var(--z-sheet) + 1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow:
    0 16px 40px color-mix(in srgb, var(--shadow-ink) 16%, transparent),
    0 2px 8px color-mix(in srgb, var(--shadow-ink) 8%, transparent);
  animation: fadeInDown 0.18s cubic-bezier(0.2, 0.8, 0.25, 1);
}

.phone-shell .sort-dropdown-head {
  flex-shrink: 0;
  padding: 12px 14px 8px;
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  border-bottom: 1px solid var(--line);
  background: var(--paper-2);
}

.phone-shell .sort-menu {
  list-style: none;
  margin: 0;
  padding: 6px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.phone-shell .sort-menu-item {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 12px;
  min-height: 44px;
  border: none;
  border-radius: 10px;
  background: transparent;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition:
    background 0.12s ease,
    color 0.12s ease;
}

.phone-shell .sort-menu-item:hover {
  background: var(--paper-2);
}

.phone-shell .sort-menu-item.on {
  background: color-mix(in srgb, var(--primary) 10%, transparent);
  color: var(--primary);
  font-weight: 600;
}

.phone-shell .sort-menu-label {
  flex: 1;
  min-width: 0;
}

.phone-shell .sort-menu-check {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  color: var(--primary);
}

.phone-shell .sort-menu-check--empty {
  visibility: hidden;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Shared primary-screen header (Marketplace / My orders / Infopoint / Profile)
   ------------------------------------------------------------------------
   Rendered by `DriverScreenHeader` in driver.jsx. One padding definition here
   is what makes all four screen titles start at the same visual height —
   never add per-screen top margins. Status bar / safe-area / notch offset is
   owned by `.phone-screen` (see pwa.css), i.e. above this element. */
.pwa-screen-header {
  padding: 16px 20px 14px;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}
.pwa-screen-header .header-title {
  margin: 0;
  letter-spacing: -0.015em;
}
/* Title/subtitle left, screen actions (incl. the notification bell) right.
   `flex-start` + `min-width: 0` keep long translated titles from being pushed
   into the actions and keep the title baseline fixed regardless of how many
   actions a screen contributes. */
.pwa-screen-header .screen-header-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.pwa-screen-header .screen-header-titles {
  min-width: 0;
  flex: 1;
}
.pwa-screen-header .header-controls {
  flex-shrink: 0;
}
/* Infopoint sub-tabs: a white band directly UNDER the header divider, not header
   children. The header therefore ends at the same height on all four primary
   screens (that shared grey line is the one the client aligns against) and this
   band contributes the second divider, under the tabs. Base treatment —
   `background: var(--paper)` + `border-bottom` — comes from
   `.phone-shell .myjobs-tabs-slider`; only the alignment differs. The left pad
   matches the header's 20px so the first tab lines up with the title. */
.phone-shell .infopoint-tabs-slider {
  justify-content: flex-start;
  gap: 20px;
  padding: 0 20px;
}
.scroll-body {
  /* Extra bottom pad clears the absolute floating tab capsule */
  padding: 16px 18px calc(24px + 72px + env(safe-area-inset-bottom, 0px));
  background: var(--canvas); /* client canvas #F5F5F7 (board §E) */
  flex: 1;
}

.portal-refresh-hint {
  text-align: center;
  margin-bottom: 10px;
}
/* Marketplace results area: "N results" left, sort + filter right (client-agreed
   Marketplace structure 2026-07-26 — the controls moved out of the header so the
   header is title/subtitle + bell only, identical to the other primary screens). */
.portal-results-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.chip-row-wrap {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.header-controls {
  display: flex;
  gap: 10px;
  align-items: center;
}

.jobcard-btn {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-3);
  padding: var(--space-4);
  margin-bottom: var(--space-3);
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition:
    transform 0.12s ease,
    box-shadow 0.14s ease,
    border-color 0.14s;
}
.jobcard-btn:hover {
  box-shadow: var(--sh-2);
  border-color: var(--line-2);
}
.jobcard-btn:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

.chip-btn {
  appearance: none;
  font: inherit;
  cursor: pointer;
}

.notification-day-header {
  font-size: var(--text-caption);
  font-weight: 600;
  color: var(--muted);
  margin: var(--space-4) 0 var(--space-2);
  text-transform: capitalize;
}
/* Notification card = the row (always present) plus, for tour notifications,
   an inline expandable preview panel. The card owns the border, background and
   unread treatment so the row and the panel read as one surface; the row keeps
   its own layout and stays the only focusable element. */
.notification-card {
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: var(--paper);
  overflow: hidden;
}
.notification-card.unread {
  background: var(--paper-2);
}
.notification-card.expanded {
  border-color: var(--primary);
}
.notification-row {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 0;
  border-radius: 0;
  background: transparent;
  text-align: left;
  width: 100%;
  cursor: pointer;
  font: inherit;
  color: inherit;
  align-items: flex-start;
}
.notification-card.unread > .notification-row {
  font-weight: 600;
}
.notification-row-static {
  cursor: default;
}
/* Chevron: right-hand affordance for both interaction models — it rotates for
   the tour accordion and points forward for a deep link. */
.notification-row-chevron {
  display: flex;
  align-items: center;
  align-self: center;
  flex-shrink: 0;
  color: var(--muted-2);
  transition: transform 0.15s ease;
}
.notification-row-chevron.open {
  transform: rotate(180deg);
}
/* NOTE: `.notification-row-cat` (the category chip) was removed on 2026-08-04
   when the client dropped visible notification categories. The card now starts
   at `.notification-row-title`, so there is no chip rule and no empty container
   left behind — the heading's own line-height owns the top of the text block. */
.notification-card-panel {
  padding: 0 var(--space-3) var(--space-3);
  border-top: 1px solid var(--line);
  margin-top: 0;
}
.notification-card-panel[hidden] {
  display: none;
}
.notification-card-actions {
  display: flex;
  flex-wrap: wrap;
  /* Same 12px action gap the dialog standard uses. */
  gap: 12px;
  margin-top: 12px;
}
/* Full-size `.btn`, deliberately NOT `.btn.sm`: the small variant drops the
   radius to `--r-1` (4px), which read as a sharper corner than every other
   button in the app, and it sits below the 44px touch floor. */
.notification-card-actions .btn {
  flex: 1 1 auto;
  justify-content: center;
  min-height: 44px;
}
.notification-preview {
  padding-top: var(--space-3);
}
/* Ride id alone since 2026-08-04 — the status pill that used to sit opposite it
   was dropped with the rest of the metadata the expansion no longer shows. */
.notification-preview-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.notification-preview-tour {
  font-size: 11px;
  color: var(--muted-2);
}
.notification-preview-list {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.notification-preview-row {
  display: grid;
  grid-template-columns: 88px 1fr;
  gap: 8px;
  align-items: start;
}
.notification-preview-row dt {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
}
.notification-preview-row dd {
  margin: 0;
  font-size: 12px;
  font-weight: 500;
  color: var(--text);
  min-width: 0;
  overflow-wrap: anywhere;
}
/* `.notification-preview-sub` (the muted second line under each preview value)
   and `.notification-preview-hint` (the "visible after you accept" note) were
   removed on 2026-08-04: the ride expansion is now five single-value rows, and
   because the projection is identical before and after acceptance there is no
   longer anything the hint could promise. */
.notification-unavailable {
  font-size: 11px;
  line-height: 1.45;
  color: var(--muted);
  margin: 10px 0 0;
}
/* `--danger-ink` is the defined light/dark danger text token — do not reach for
   an undefined status token here (cf. the DDB audit finding on `--st-ok`). */
.notification-unavailable {
  color: var(--danger-ink);
  padding: 0 var(--space-3) var(--space-3);
  margin: 0;
}
.notification-card-panel .notification-unavailable {
  padding: var(--space-3) 0 0;
}
/* Narrow phones: the label column would squeeze the value to a few
   characters, so the preview stacks. */
@media (max-width: 359px) {
  .notification-preview-row {
    grid-template-columns: 1fr;
    gap: 2px;
  }
  .notification-card-actions .btn {
    flex-basis: 100%;
  }
}
.notification-row-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary);
  flex-shrink: 0;
  margin-top: 6px;
}
.notification-row-body {
  flex: 1;
  min-width: 0;
}
.notification-row-title {
  display: block;
  font-weight: 600;
  font-size: 13px;
}
/* Collapsed preview text is capped at two lines so every card in the list has
   a predictable height and the date/tour meta line never gets pushed away. */
.notification-row-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 12px;
  color: var(--muted);
  margin-top: 4px;
  white-space: pre-line;
}
.notification-row-meta {
  display: block;
  font-size: var(--text-caption);
  color: var(--muted-2);
  margin-top: 4px;
}
.notification-row-dot-spacer {
  width: 8px;
  flex-shrink: 0;
}
.notifications-grouped-list {
  margin-top: 12px;
}
.notifications-day-rows {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.notifications-pane-sheet {
  display: flex;
  flex-direction: column;
  max-height: 85%;
}
.notifications-pane-head {
  padding: 16px 20px 12px;
}
.notifications-pane-head-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  gap: 12px;
}
.notifications-pane-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}
.notifications-pane-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.notifications-pane-body {
  padding: 0 20px 24px;
  flex: 1;
}

/* Semantic button resets (plan W2 — div role=button → real buttons) */
button.radio-card {
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  appearance: none;
  -webkit-appearance: none;
}
button.infopoint-news-row {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  background: transparent;
  border: none;
  cursor: pointer;
  outline: none;
}
button.infopoint-news-row:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
button.notifications-dropdown-backdrop {
  appearance: none;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  font: inherit;
}

.infopoint-news-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  position: relative;
}
.infopoint-news-icon.unread {
  background: color-mix(in srgb, var(--primary) 8%, transparent);
  color: var(--primary);
}
.infopoint-news-icon.read {
  background: var(--paper-2);
  color: var(--muted-2);
}
/* Message list row: title + date only, so it is a navigation row rather than a
   disclosure. Scoped to `.phone-shell` to match — and beat — the neighbouring
   `button.infopoint-news-row` rule that top-aligns the accordion layout. */
.phone-shell .infopoint-news-row {
  align-items: center;
  gap: 12px;
}
.phone-shell .infopoint-news-title {
  font-size: 14px;
  line-height: 1.35;
  color: var(--text);
}
.phone-shell .infopoint-news-unread-dot {
  position: absolute;
  top: -2px;
  right: -2px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--primary);
  border: 1.5px solid var(--paper);
}
/* Unread badge only. A read row carries no badge — three rows all labelled
   "Read" is noise, not information — and the state stays explicit in the row's
   accessible name either way. Words plus the dot mean unread never depends on
   colour alone. */
.phone-shell .infopoint-news-state {
  flex-shrink: 0;
  /* Aligned with the title's first line rather than the row's centre, so a
     two-line title does not leave the badge floating beside the wrap. */
  align-self: flex-start;
  margin-top: 1px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 10%, transparent);
  border-radius: 999px;
  padding: 2px 8px;
}
.phone-shell .infopoint-news-chev {
  display: flex;
  align-items: center;
  align-self: center;
  flex-shrink: 0;
  color: var(--muted-2);
}

/* Message detail page — replaces the whole Infopoint screen so a long
   announcement (AGB, client instructions) gets the full viewport. */
.infopoint-message-page {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  /* Reserves the horizontal axis for the left-edge swipe-back while leaving
     vertical scrolling of a long message to the browser. This — not
     preventDefault — is what stops the gesture fighting the scroller. */
  touch-action: pan-y;
  /* Follows the finger during the swipe and snaps home if the gesture is
     abandoned. Transform-only. */
  transition: transform 0.18s ease;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .infopoint-message-page {
    transition: none;
  }
}
.infopoint-message-card {
  gap: 8px;
}
.infopoint-message-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
  overflow-wrap: anywhere;
}
.infopoint-message-date {
  margin: 0;
}
/* Infopoint date metadata — message list, message detail, document list.
   One step below `--text-body-sm` (14px), because the full `DD.MM.YYYY + HH:MM`
   stamp is a longer string than the bare `DD.MM. HH:MM` it replaced and 14px
   put it level with the 14px row title it sits under. Dropping it to 12.5px
   restores the hierarchy and buys the width back without wrapping. `.mono` on
   the element supplies the tabular figures, so the stamps stay column-aligned
   down the list. */
.infopoint-meta-datetime {
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--muted);
}
.infopoint-message-body {
  margin: 8px 0 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
  /* Full text, never clamped; `pre-line` keeps the paragraph breaks admins
     type into the message body. */
  white-space: pre-line;
  overflow-wrap: anywhere;
}

.infopoint-empty-hint {
  font-size: var(--text-body-sm);
  color: var(--muted);
  margin-top: 10px;
  line-height: 1.5;
}
.sheet-head-warn {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
}
.sheet-head-warn-icon {
  color: var(--st-warn);
}
.text-muted-sm {
  font-size: var(--text-body-sm);
  color: var(--muted);
}
.text-strong-lg {
  font-weight: 600;
  font-size: var(--text-body);
}
.mono-strong {
  font-weight: 600;
  font-size: var(--text-body);
}
.para-intro {
  margin: 16px 0 14px;
  font-size: var(--text-body-sm);
  line-height: 1.55;
}
.para-muted-xs {
  font-size: var(--text-caption);
  color: var(--muted);
  margin-bottom: 18px;
}
.doc-row-icon {
  color: var(--primary-ink);
  flex-shrink: 0;
}
.doc-grid {
  display: grid;
  gap: 10px;
  margin-top: 4px;
}
.doc-row-card {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-2);
  background: var(--paper);
}
.profile-header-block {
  padding: 24px 22px;
  background: var(--paper-2);
}
.profile-header-title {
  margin: 0;
  font-size: var(--text-title);
  font-weight: 600;
}

/* Layout utilities (replace inline flex/grid/margin in driver.jsx) */
.flex-1-min-0 {
  flex: 1;
  min-width: 0;
}
/* minmax(0, ...) not `1fr`: a bare `1fr` is `minmax(auto, 1fr)`, whose auto
   minimum is the item's content size. Native date fields have a large intrinsic
   width, which blows the tracks past the container and eats the gap. */
.grid-2-col-10 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px;
}
.flex-col-gap-10 {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.flex-gap-8-wrap {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.mt-field {
  margin-top: 18px;
}
.mt-16 {
  margin-top: 16px;
}
.mt-20 {
  margin-top: 20px;
}
.text-right {
  text-align: right;
}
.w-40-spacer {
  width: 40px;
  flex-shrink: 0;
}
.hidden {
  display: none !important;
}
/* DEMO ONLY — excluded from production design contract */
.statusbar,
.phone .notch,
.phone-shell .pwa-tag {
  /* presentation chrome for prototype demo frame only */
}
