/* ==========================================================================
   DriverHub Design System — colour tokens (UI/UX Refinement)
   --------------------------------------------------------------------------
   Single source of truth for every colour in the app. Three layers, in
   order of increasing priority:
     1. :root            — light values (the default/fallback)
     2. prefers-color-scheme: dark, guarded by :not([data-theme="light"])
                          — system dark mode, unless the driver explicitly
                            chose Light
     3. :root[data-theme="dark"] — explicit driver choice, wins regardless
                                    of system preference
   public/theme.js sets data-theme="light"|"dark" on <html> from the
   driver's stored Appearance choice, or removes it entirely for "System".
   Every screen (Login, Home, Schedule, Operations/timer.html, Finance,
   Dashboard, all panels/modals) shares this one stylesheet and these same
   tokens — there is no separate dark stylesheet anywhere.
   ========================================================================== */

:root {
  --bg: #f5f6f8;
  --surface: #ffffff;
  --surface-secondary: #f3f4f6;
  --surface-secondary-strong: #1f2937;
  --surface-elevated: #f9fafb;

  --text-primary: #111827;
  --text-secondary: #374151;
  --text-muted: #6b7280;
  --text-faint: #9ca3af;

  --border: #d1d5db;
  --border-subtle: #e5e7eb;

  /* Deliberately dark decorative surfaces used for emphasis (header,
     primary buttons, active nav) — dark even in Light mode today; becomes
     the accent blue in Dark mode so primary actions still pop against an
     already-dark page (matches the supplied reference's "blue primary
     accent"). */
  --emphasis-bg: #111827;
  --emphasis-text: #ffffff;

  --accent: #2563eb;
  --accent-strong: #1d4ed8;
  --accent-bg: #eff6ff;
  --accent-bg-strong: #e0e7ff;
  --accent-border: #93c5fd;

  --success: #16a34a;
  --success-strong: #065f46;
  --success-bg: #ecfdf5;
  --success-border: #a7f3d0;

  --warning: #d97706;
  --warning-strong: #92400e;
  --warning-bg: #fef3c7;
  --warning-border: #fcd34d;

  --danger: #b91c1c;
  --danger-strong: #dc2626;
  --danger-bg: #fef2f2;
  --danger-border: #fecaca;

  /* Job Type category accents — Arrival/Departure reuse accent/warning
     above; Transfer/Hourly Disposal/Ride-Hailing get their own hue. */
  --cat-violet: #7c3aed;
  --cat-violet-bg: #ede9fe;
  --cat-violet-text: #5b21b6;
  --cat-teal: #0d9488;
  --cat-teal-bg: #ccfbf1;
  --cat-teal-text: #115e59;
  --cat-pink: #db2777;
  --cat-pink-bg: #fce7f3;
  --cat-pink-text: #9d174d;

  --radius: 12px;
  --radius-sm: 10px;
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.08);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0b0f19;
    --surface: #131a2b;
    --surface-secondary: #1c2438;
    --surface-secondary-strong: #1e40af;
    --surface-elevated: #1a2236;

    --text-primary: #f3f4f6;
    --text-secondary: #cbd5e1;
    --text-muted: #94a3b8;
    --text-faint: #64748b;

    --border: #2a3348;
    --border-subtle: #232c40;

    --emphasis-bg: #2563eb;
    --emphasis-text: #ffffff;

    --accent: #3b82f6;
    --accent-strong: #60a5fa;
    --accent-bg: #16213a;
    --accent-bg-strong: #1c2c4d;
    --accent-border: #2f4a7a;

    --success: #22c55e;
    --success-strong: #4ade80;
    --success-bg: #0f2a1c;
    --success-border: #1f5c3a;

    --warning: #f59e0b;
    --warning-strong: #fbbf24;
    --warning-bg: #2c2008;
    --warning-border: #5a4413;

    --danger: #ef4444;
    --danger-strong: #f87171;
    --danger-bg: #2c1414;
    --danger-border: #5c2626;

    --cat-violet: #a78bfa;
    --cat-violet-bg: #241b42;
    --cat-violet-text: #c4b5fd;
    --cat-teal: #2dd4bf;
    --cat-teal-bg: #0f2a28;
    --cat-teal-text: #5eead4;
    --cat-pink: #f472b6;
    --cat-pink-bg: #2e1826;
    --cat-pink-text: #f9a8d4;

    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4);
  }
}

:root[data-theme="dark"] {
  --bg: #0b0f19;
  --surface: #131a2b;
  --surface-secondary: #1c2438;
  --surface-secondary-strong: #1e40af;
  --surface-elevated: #1a2236;

  --text-primary: #f3f4f6;
  --text-secondary: #cbd5e1;
  --text-muted: #94a3b8;
  --text-faint: #64748b;

  --border: #2a3348;
  --border-subtle: #232c40;

  --emphasis-bg: #2563eb;
  --emphasis-text: #ffffff;

  --accent: #3b82f6;
  --accent-strong: #60a5fa;
  --accent-bg: #16213a;
  --accent-bg-strong: #1c2c4d;
  --accent-border: #2f4a7a;

  --success: #22c55e;
  --success-strong: #4ade80;
  --success-bg: #0f2a1c;
  --success-border: #1f5c3a;

  --warning: #f59e0b;
  --warning-strong: #fbbf24;
  --warning-bg: #2c2008;
  --warning-border: #5a4413;

  --danger: #ef4444;
  --danger-strong: #f87171;
  --danger-bg: #2c1414;
  --danger-border: #5c2626;

  --cat-violet: #a78bfa;
  --cat-violet-bg: #241b42;
  --cat-violet-text: #c4b5fd;
  --cat-teal: #2dd4bf;
  --cat-teal-bg: #0f2a28;
  --cat-teal-text: #5eead4;
  --cat-pink: #f472b6;
  --cat-pink-bg: #2e1826;
  --cat-pink-text: #f9a8d4;

  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4);
}

html {
  color-scheme: light dark;
}
/* Mobile-first base styles for Driver App MVP */

* {
  box-sizing: border-box;
}

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

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text-primary);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.app-header {
  background: var(--emphasis-bg);
  color: #ffffff;
  padding: 16px;
  text-align: center;
}

/* Home visual refinement — Home hides the shared blue header bar, the
   Sign out/driver-name row, and the standalone footer text so it reads as
   its own screen rather than "the previous application"; Home gets its
   own compact wordmark instead (see .home-brand), and Sign Out remains
   reachable via More, unchanged. Every other view (Login, Schedule,
   Finance, Dashboard) keeps these elements exactly as before — this is
   scoped to body.home-active only, toggled in switchToHome()/the other
   switchTo*() functions in app.js. */
body.home-active .app-header,
body.home-active .schedule-header,
body.home-active .app-footer,
body.schedule-active .app-header,
body.schedule-active .schedule-header,
body.payments-active .app-header,
body.payments-active .schedule-header,
body.payments-active .app-footer,
body.dashboard-active .app-header,
body.dashboard-active .schedule-header,
body.dashboard-active .app-footer,
body.login-active .app-header,
body.login-active .app-footer {
  display: none;
}

/* Schedule visual refinement — plain page heading replacing the blue
   banner, same treatment as Home's own compact brand block conceptually,
   but simple text (no wordmark repeat) since "DriverHub" branding
   already lives on Home. */
.schedule-page-heading {
  margin: 2px 0 14px;
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--text-primary);
}

.app-header h1 {
  margin: 0;
  font-size: 1.25rem;
}

.app-main {
  flex: 1;
  padding: 16px;
  max-width: 560px;
  width: 100%;
  margin: 0 auto;
}

.hidden {
  display: none !important;
}

.card {
  background: var(--surface);
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.card h2 {
  margin-top: 0;
  font-size: 1.1rem;
}

.hint {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin-top: -8px;
}

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

.app-footer {
  text-align: center;
  padding: 12px;
  color: var(--text-faint);
  font-size: 0.8rem;
}

/* Sign-in */

#sign-in-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 12px;
}

.field-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin-top: 10px;
}

.text-input {
  width: 100%;
  min-height: 52px;
  border: 2px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  font-size: 1.05rem;
  background: var(--surface);
  color: var(--text-primary);
}

.text-input:focus {
  outline: none;
  border-color: var(--emphasis-bg);
}

/* Job Type selector — deliberately more prominent than every other job
   form field, so it's the first thing a driver notices when the form
   opens. Same #job-type-select element is reused for both Add and Edit
   Job (see public/app.js), so this automatically applies to both. No
   other field gets this treatment. */
#job-type-select {
  background: var(--warning-bg);
  color: var(--text-primary);
  font-weight: 700;
  border: 2px solid var(--warning);
}

#job-type-select:focus {
  border-color: var(--warning-strong);
}

.primary-button {
  width: 100%;
  min-height: 56px;
  border: none;
  background: var(--emphasis-bg);
  color: #ffffff;
  border-radius: 12px;
  font-size: 1.05rem;
  font-weight: 700;
  cursor: pointer;
  margin-top: 16px;
}

.primary-button:active {
  background: var(--surface-secondary-strong);
}

.primary-button:disabled {
  background: var(--text-faint);
  cursor: not-allowed;
}

.form-error {
  margin-top: 14px;
  margin-bottom: 0;
  color: var(--danger);
  font-size: 0.9rem;
}

/* Optional Job image attachment field (Phase D-E) — appended after every
   other Add/Edit field (see renderJobAttachmentField in app.js), never
   rendered at all for Ride-Hailing. Deliberately not styled as prominently
   as #job-type-select above — this field is optional and secondary. */
.job-attachment-field {
  margin-top: 14px;
}

.job-attachment-field-body {
  margin-top: 6px;
}

.job-attachment-file-input {
  width: 100%;
  font-size: 0.9rem;
  color: var(--text-secondary);
}

.job-attachment-field-error {
  margin: 6px 0 0;
  color: var(--danger);
  font-size: 0.85rem;
}

/* Local preview only — this image never leaves the browser (object URL,
   see URL.createObjectURL in renderJobAttachmentField) until the driver
   saves the form, at which point the actual file is uploaded separately. */
.job-attachment-preview {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border: 1px solid var(--border-subtle);
  border-radius: 10px;
  background: var(--surface-secondary);
}

.job-attachment-preview-image {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 8px;
  flex-shrink: 0;
}

.job-attachment-preview-meta {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.85rem;
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

.job-attachment-existing-status {
  margin: 0 0 4px;
  font-size: 0.9rem;
  color: var(--text-secondary);
}

.job-attachment-existing-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.job-attachment-remove-prompt {
  margin: 0 0 4px;
  font-size: 0.9rem;
  color: var(--text-primary);
  font-weight: 600;
}

.job-attachment-remove-pending {
  margin: 0;
  font-size: 0.85rem;
  color: var(--warning-strong);
}

/* Schedule */

.schedule-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
  gap: 8px;
}

.current-driver-name {
  font-weight: 700;
  font-size: 1.05rem;
}

.link-button {
  background: none;
  border: none;
  color: var(--accent);
  font-size: 0.95rem;
  padding: 8px 4px;
  cursor: pointer;
  min-height: 44px;
}

/* Destructive text-button variant (Remove Attachment) — same shape as
   .link-button, just the existing danger color instead of accent. */
.link-button-danger {
  color: var(--danger);
}

/* Top-level Schedule/Dashboard switcher (Phase 2.1) — same look as the
   admin My Schedule/All Drivers toggle below, reusing .view-toggle-button
   for the buttons themselves. */

.main-nav-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

/* Admin only — "My Schedule" / "All Drivers" toggle */

.admin-view-toggle {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

/* Phase 2.3 UI Refinement: compact single-<select> replacement for the
   two-button row above. The old .admin-view-toggle rule is kept, unused,
   for rollback (see index.html's #admin-view-toggle comment). */
.admin-view-toggle-compact {
  margin-bottom: 12px;
}

.admin-view-select-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

.view-mode-select {
  min-height: 44px;
  padding: 8px 12px;
  font-size: 0.9rem;
  font-weight: 700;
}

.view-toggle-button {
  flex: 1;
  min-height: 48px;
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  border-radius: 10px;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
}

.view-toggle-button.view-toggle-active {
  background: var(--emphasis-bg);
  color: #ffffff;
  border-color: var(--emphasis-bg);
}

.view-toggle-button:active {
  background: var(--surface-secondary);
}

.view-toggle-button.view-toggle-active:active {
  background: var(--surface-secondary-strong);
}

/* Shown on each card in "All Drivers" — must be prominent since jobs from
   multiple drivers are mixed together there. */
.job-driver-name {
  display: inline-block;
  background: var(--emphasis-bg);
  color: #ffffff;
  font-weight: 700;
  font-size: 0.85rem;
  padding: 4px 10px;
  border-radius: 999px;
  margin-bottom: 10px;
}

.date-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--surface);
  border-radius: 12px;
  padding: 8px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.nav-button {
  min-width: 48px;
  min-height: 48px;
  font-size: 1.5rem;
  border: none;
  background: var(--surface-secondary);
  border-radius: 10px;
  color: var(--text-primary);
  cursor: pointer;
}

.nav-button:active {
  background: var(--border-subtle);
}

.date-nav-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  text-align: center;
  flex: 1;
}

.date-label {
  font-weight: 700;
  font-size: 1rem;
}

.today-pill {
  background: var(--success);
  color: #ffffff;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 10px;
  border-radius: 999px;
}

.jump-today {
  display: block;
  margin: 6px auto 0;
}

.add-job-button {
  margin-top: 14px;
}

/* Phase 2.3 — Schedule Focus home: compact weekly date-strip, the Today/
   Yesterday/Custom Date sheet, and the fixed bottom nav. The existing
   .date-nav/.jump-today/.add-job-button rules above stay untouched for
   rollback safety; these are small overrides for the new positions. */

.date-strip-section {
  margin-bottom: 8px;
}

.date-strip-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  margin-bottom: 6px;
}

/* Compact prev/next-day arrows, now flanking the month label directly
   (previously a separate bordered .date-nav card below the strip) — same
   #prev-day/#next-day ids; commitDateTrackStep(-1/1) plays the same
   one-slot settle animation the swipe gesture uses, then calls the same
   navigateDay(delta) either path uses. */
.date-strip-arrow {
  flex-shrink: 0;
  min-width: 40px;
  min-height: 40px;
  border: none;
  background: var(--surface-secondary);
  border-radius: 10px;
  font-size: 1.2rem;
  color: var(--text-primary);
  cursor: pointer;
}

.date-strip-arrow:active {
  background: var(--border-subtle);
}

/* Replaces the old bulky bordered .date-nav card — one compact line
   directly under the strip. #today-pill/#jump-today keep their existing
   mutual-exclusivity toggle (app.js), just relocated here. */
.date-strip-selected-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-size: 0.9rem;
}

.date-strip-selected-row .date-label {
  font-weight: 700;
  font-size: 0.95rem;
}

.date-strip-selected-row .jump-today {
  margin: 0;
  min-height: auto;
  padding: 2px 4px;
}

/* UI refinement: the standalone calendar-icon button is gone — the
   Month/Year heading itself now opens the date-picker sheet. Reset to a
   plain button, keeping the exact same text styling as before, with just
   a subtle dashed underline as the "this is tappable" cue. */
.date-strip-month-label {
  appearance: none;
  border: none;
  border-bottom: 1px dashed var(--text-faint);
  background: none;
  padding: 4px 2px;
  font-weight: 700;
  font-size: 0.95rem;
  font-family: inherit;
  color: var(--text-secondary);
  flex: 1;
  text-align: center;
  cursor: pointer;
}

.date-strip-month-label:active {
  color: var(--text-primary);
  border-bottom-color: var(--text-muted);
}

/* Schedule V3 refinement — continuous date-track carousel (see
   initDateTrackDrag/commitDateTrackStep/renderDateStrip in app.js).
   #date-strip now renders more dates than are visible (a few buffer days
   on each side) and is moved by translate3d as one continuous row; this
   wrapper clips it to exactly 7 visible slots so the Schedule page itself
   can never scroll horizontally, regardless of how far a drag or settle
   animation moves the row. */
.date-strip-viewport {
  overflow: hidden;
}

.date-strip {
  display: flex;
  gap: 6px;
  padding-bottom: 2px;
  will-change: transform;
  /* Let the browser handle vertical page scrolling natively over the strip;
     JS claims the gesture only once a drag is confirmed horizontal, so a
     vertical or diagonal touch never fights the page scroll. */
  touch-action: pan-y;
}

/* Width is fixed rather than flexible now — the continuous track needs a
   precise, known slot width to translate by; app.js sets it inline on every
   render from the viewport's own measured width, this 42px is only the
   pre-first-render fallback. */
.date-strip-pill {
  position: relative;
  flex: 0 0 42px;
  width: 42px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 8px 4px;
  border-radius: 10px;
  border: 1px solid transparent;
  background: var(--surface-secondary);
  cursor: pointer;
}

.date-strip-pill:active {
  background: var(--border-subtle);
}

.date-strip-weekday {
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
}

.date-strip-daynum {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--text-primary);
}

.date-strip-pill-selected {
  background: var(--emphasis-bg);
  border-color: var(--emphasis-bg);
}

.date-strip-pill-selected .date-strip-weekday,
.date-strip-pill-selected .date-strip-daynum {
  color: #ffffff;
}

.date-strip-pill-today:not(.date-strip-pill-selected) {
  border: 2px solid var(--success);
  background: var(--surface);
}

/* Phase 2.3 UI Refinement: job-indicator dot — one or more jobs scheduled
   on that operational date (Pending or Completed both count; the count
   itself doesn't change the dot). A single, one-meaning green dot, kept
   deliberately separate from the "today" signal above (a border, not a
   dot) so the two are never visually conflated. Still shown even when the
   pill is selected/dark, per spec. */
.date-strip-job-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--success);
}

/* Singapore Public Holidays layer — a small violet corner dot, absolutely
   positioned so it never adds height to the pill or competes with the
   green job-dot's meaning below. Deliberately a different color and a
   different position (top corner vs. bottom-center) from .date-strip-job-dot
   so the two can never read as the same signal when a date has both a
   holiday and jobs. Color alone isn't the only cue — see the pill's own
   aria-label and this marker's title, set in renderDateStrip(). */
.date-strip-holiday-marker {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--cat-violet);
}

.date-picker-sheet {
  margin-bottom: 14px;
}

.date-picker-shortcuts {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.date-picker-shortcuts .secondary-button {
  margin-top: 0;
}

.date-picker-cancel-button {
  margin-top: 10px;
}

.home-bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  gap: 8px;
  padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-top: 1px solid var(--border-subtle);
  box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.06);
  max-width: 560px;
  margin: 0 auto;
  z-index: 20;
}

.bottom-nav-button {
  flex: 1;
  min-height: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border-radius: 12px;
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  font-weight: 700;
  text-decoration: none; /* Operations is an <a>, the rest are <button> */
  cursor: pointer;
  margin-top: 0; /* overrides .add-job-button's margin-top:14px in this flex context */
}

.bottom-nav-icon {
  display: flex;
  line-height: 1;
}

.bottom-nav-icon svg {
  width: 20px;
  height: 20px;
}

.bottom-nav-label {
  font-size: 0.75rem;
  line-height: 1;
}

.bottom-nav-button:active {
  background: var(--surface-secondary);
}

.bottom-nav-primary {
  background: var(--emphasis-bg);
  color: #ffffff;
  border-color: var(--emphasis-bg);
}

.bottom-nav-primary:active {
  background: var(--surface-secondary-strong);
}

/* Operations V2 — the current-page indicator for the bottom nav, used only
   by timer.html's own (non-interactive) Operations item, since this page
   has no other view to switch to. New class, additive only: the shared
   .bottom-nav-button base style and every other page's bottom nav are
   completely unaffected. */
.bottom-nav-active {
  background: var(--accent-bg);
  color: var(--accent-strong);
  border-color: var(--accent-border);
  cursor: default;
}

body.has-bottom-nav {
  padding-bottom: calc(84px + env(safe-area-inset-bottom, 0px));
}

/* Phase 2.3 UI Refinement */

/* Home V2 — approved as the one remaining Schedule change: the previous
   success-tinted (green) treatment read as a status signal it wasn't
   ("6 Jobs" isn't good/bad news); it now uses the same neutral surface as
   the rest of Schedule's chrome. Schedule is otherwise locked. */
.schedule-summary-line {
  margin-top: 14px;
  padding: 10px 14px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: 12px;
  color: var(--text-secondary);
  font-weight: 600;
  font-size: 0.9rem;
  line-height: 1.4;
}

/* Singapore Public Holidays layer — compact, read-only, informational
   banner shown only when the selected Schedule date is a holiday (see
   renderHolidayBanner in app.js; hidden and empty otherwise, so a normal
   day reserves no space and looks exactly as before). Uses the existing
   violet category tokens for a clean, non-alarming "this is a tag, not a
   warning" treatment — deliberately not the red/amber danger/warning
   tokens, and not styled like a job card (no action buttons belong here). */
.holiday-banner {
  margin-top: 10px;
  padding: 8px 14px;
  background: var(--cat-violet-bg);
  border: 1px solid var(--cat-violet-bg);
  border-radius: 12px;
  color: var(--cat-violet-text);
}

.holiday-banner-line {
  font-weight: 600;
  font-size: 0.85rem;
  line-height: 1.4;
}

/* Preserves the "Subject to confirmation" status supplied for Hari Raya
   Puasa — visually secondary (smaller, neutral-muted) but still clearly
   readable text, never conveyed by color alone. */
.holiday-banner-qualifier {
  margin-top: 2px;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
}

.home-link {
  margin-bottom: 10px;
  padding-left: 0;
}

/* Daily summary — Total/Pending/Completed job counts + Total Revenue
   (Completed jobs only) for the selected date only; no cost/expense or
   profit figures belong here (deferred). A 2x2 grid keeps four stats
   readable and compact on a narrow screen, rather than squeezing them
   into one row. */

.revenue-summary {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 12px;
  margin-top: 14px;
  padding: 12px 16px;
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  border-radius: 12px;
}

.revenue-stat {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.revenue-stat-label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--success-strong);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.revenue-stat-value {
  margin-top: 2px;
  font-size: 1.2rem;
  font-weight: 800;
  color: var(--success-strong);
}

/* Job list */

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

.job-card {
  background: var(--surface);
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  border-left: 6px solid var(--text-faint);
  position: relative;
}

.job-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.job-card-header-left {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.job-type-badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--surface-secondary);
  color: var(--text-secondary);
}

.status-badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 4px 10px;
  border-radius: 999px;
}

.status-pending {
  background: var(--warning-bg);
  color: var(--warning-strong);
}

.status-completed {
  background: var(--success-bg);
  color: var(--success-strong);
}

/* Compact outlined badge for Completed + Paid jobs — deliberately not a
   filled pill like .status-completed, so "Paid" reads as an additional,
   distinct signal rather than a second status. Padding is 1px tighter than
   the filled badges to offset the added border, keeping the same overall
   pill height. */
.paid-badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--surface);
  border: 1.5px solid var(--success);
  color: var(--success-strong);
}

.job-id {
  font-size: 0.8rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

.job-fields {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 12px;
  row-gap: 6px;
  margin: 0;
}

.job-fields dt {
  color: var(--text-muted);
  font-size: 0.85rem;
  white-space: nowrap;
}

.job-fields dd {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 500;
  word-break: break-word;
}

/* Every job card starts collapsed and the whole header/summary/meta area is
   itself the tap target (.job-card-toggle) — no separate full-width "View
   Details" button. .job-card-details (the expanded content) is appended as
   a sibling after the toggle and shown/hidden via .hidden; its own
   contents/behaviour are untouched. */

.job-card-details {
  margin-top: 12px;
}

/* Expanded Job Card refinement — avoids repeating information the grouped
   detail sections below already show. The collapsed appearance (no
   .is-expanded class) is completely unaffected — every meta line and the
   price both still show exactly as before when the card is collapsed. */
.job-card.is-expanded .job-collapsed-meta-line-redundant,
.job-card.is-expanded .job-collapsed-price {
  display: none;
}

.job-detail-groups {
  display: flex;
  flex-direction: column;
}

.job-detail-section {
  padding-top: 10px;
  margin-top: 10px;
  border-top: 1px solid var(--border-subtle);
}

.job-detail-section:first-child {
  padding-top: 0;
  margin-top: 0;
  border-top: none;
}

.job-detail-section-heading {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 6px;
}

.job-detail-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.job-detail-row:last-child {
  margin-bottom: 0;
}

.job-detail-row-icon-type .job-detail-row-value {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-primary);
}

.job-detail-row-label-type {
  font-size: 0.85rem;
}

.job-detail-row-label-type .job-detail-row-label {
  color: var(--text-muted);
  min-width: 92px;
}

.job-detail-row-label-type .job-detail-row-value {
  color: var(--text-secondary);
  font-weight: 500;
  word-break: break-word;
}

/* Presentation-only fallback for an absent Pax Mobile (section 6 of the
   refinement spec) — "Mobile not provided" instead of a bare "—", styled
   distinctly muted/italic so it reads as an absence, not a real value.
   Never written back; the underlying empty passengerContact is untouched. */
.job-detail-row-value-muted {
  color: var(--text-faint) !important;
  font-style: italic;
  font-weight: 500 !important;
}

.job-detail-notes-text {
  margin: 0;
  font-size: 0.9rem;
  color: var(--text-secondary);
  white-space: pre-wrap;
  word-break: break-word;
}

/* Calendar export + Message Passenger, grouped into one secondary-action
   row so they read as a single area distinct from .job-action-bar's
   primary job-management actions below. */
.job-detail-secondary-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 12px 0 4px;
}

.job-detail-secondary-actions .calendar-export-button,
.job-detail-secondary-actions .whatsapp-message-button {
  margin: 0;
  flex: 1 1 auto;
  justify-content: center;
}

/* Optional Job image attachment (Phase D-E) — only ever rendered for an
   eligible Job that actually has one (see renderJobCard); deliberately the
   same visually-secondary tier as .job-detail-secondary-actions above, not
   grouped into the primary .job-action-bar below. The image itself is
   never here — only the button that lazy-loads it on tap. */
.job-attachment-section {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 12px 0 4px;
}

.job-attachment-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary);
}

/* Same visual weight as .calendar-export-button/.whatsapp-message-button —
   a secondary, accent-tinted action, not a primary button. */
.job-attachment-view-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: auto;
  min-height: 40px;
  padding: 8px 14px;
  border: 1.5px solid var(--accent-border);
  border-radius: 10px;
  background: var(--accent-bg);
  color: var(--accent-strong);
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.job-attachment-view-button:active {
  background: var(--accent-bg-strong);
}

.job-attachment-view-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.job-attachment-status {
  width: 100%;
  font-size: 0.85rem;
  color: var(--text-muted);
}

.job-attachment-status-error {
  color: var(--danger);
}

.job-attachment-retry {
  margin-left: 4px;
  font-size: 0.85rem;
  min-height: auto;
  padding: 2px 4px;
}

.job-card-toggle {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  font: inherit;
}

.job-card-toggle:active {
  opacity: 0.85;
}

/* Room on the right for the chevron so it never overlaps the badges/time/
   price/meta text it sits beside. */
.job-card-toggle .job-card-header,
.job-card-toggle .job-card-collapsed-summary,
.job-card-toggle .job-collapsed-meta {
  padding-right: 20px;
}

.job-card-chevron {
  position: absolute;
  top: 14px;
  right: 14px;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-faint);
  transition: transform 0.15s ease;
}

.job-card-toggle[aria-expanded="true"] .job-card-chevron {
  transform: rotate(90deg);
}

.job-card-collapsed-summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 4px;
}

/* Time leads the hierarchy (section 12: TIME first); price stays visible
   but deliberately smaller/lighter so it doesn't compete with it. */
.job-collapsed-time {
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.job-collapsed-price {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-secondary);
}

/* Dense per-type identifying info (flight/terminal, passenger, locations —
   see collapsedMetaLines in app.js). Values only, compact and muted so the
   time/price/badges above still lead visually. */
.job-collapsed-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 2px;
}

.job-collapsed-meta-line {
  font-size: 0.85rem;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Job type color coding */

.job-type-arrival {
  border-left-color: var(--accent);
}
.job-type-arrival .job-type-badge {
  background: var(--accent-bg);
  color: var(--accent-strong);
}

.job-type-departure {
  border-left-color: var(--warning);
}
.job-type-departure .job-type-badge {
  background: var(--warning-bg);
  color: var(--warning-strong);
}

.job-type-transfer {
  border-left-color: var(--cat-violet);
}
.job-type-transfer .job-type-badge {
  background: var(--cat-violet-bg);
  color: var(--cat-violet-text);
}

.job-type-hourly {
  border-left-color: var(--cat-teal);
}
.job-type-hourly .job-type-badge {
  background: var(--cat-teal-bg);
  color: var(--cat-teal-text);
}

.job-type-ridehailing {
  border-left-color: var(--cat-pink);
}
.job-type-ridehailing .job-type-badge {
  background: var(--cat-pink-bg);
  color: var(--cat-pink-text);
}

.edit-job-button {
  width: 100%;
  min-height: 48px;
  margin-top: 10px;
  border: 2px solid var(--emphasis-bg);
  background: var(--surface);
  color: var(--text-primary);
  border-radius: 10px;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
}

.edit-job-button:active {
  background: var(--emphasis-bg);
  color: #ffffff;
}

/* Job status action */

.status-action {
  margin-top: 12px;
}

.status-action-button {
  width: 100%;
  min-height: 52px;
  border: none;
  border-radius: 10px;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
}

.status-action-complete {
  background: var(--success);
  color: #ffffff;
}

.status-action-complete:active {
  background: var(--success-strong);
}

.status-action-reopen {
  background: var(--surface-secondary);
  color: var(--warning-strong);
  border: 2px solid var(--warning-border);
}

.status-action-reopen:active {
  background: var(--warning-bg);
}

.status-confirm-prompt {
  margin: 0 0 8px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-secondary);
}

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

.status-confirm-cancel,
.status-confirm-yes {
  flex: 1;
  min-height: 48px;
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.status-confirm-cancel {
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
}

.status-confirm-cancel:active {
  background: var(--surface-secondary);
}

.status-confirm-yes {
  border: none;
  background: var(--emphasis-bg);
  color: #ffffff;
}

.status-confirm-yes:active {
  background: var(--surface-secondary-strong);
}

.status-confirm-cancel:disabled,
.status-confirm-yes:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Job cancellation — deliberately quieter than the status action, since
   it's destructive and secondary to Edit/status */

.cancel-action {
  margin-top: 10px;
}

.cancel-job-button {
  width: 100%;
  min-height: 44px;
  border: 2px solid var(--danger-border);
  background: var(--surface);
  color: var(--danger);
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.cancel-job-button:active {
  background: var(--danger-bg);
}

.cancel-confirm-prompt {
  margin: 0 0 8px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--danger);
}

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

.cancel-confirm-keep,
.cancel-confirm-yes {
  flex: 1;
  min-height: 48px;
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.cancel-confirm-keep {
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
}

.cancel-confirm-keep:active {
  background: var(--surface-secondary);
}

.cancel-confirm-yes {
  border: none;
  background: var(--danger-strong);
  color: #ffffff;
}

.cancel-confirm-yes:active {
  background: var(--danger);
}

.cancel-confirm-keep:disabled,
.cancel-confirm-yes:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.error-banner {
  margin-top: 16px;
  color: var(--danger);
  background: var(--danger-bg);
  border: 1px solid var(--danger-border);
}

/* Add / edit job form */

#job-form {
  display: flex;
  flex-direction: column;
  margin-top: 12px;
}

#job-form-fields {
  display: flex;
  flex-direction: column;
}

#job-form-fields textarea.text-input {
  min-height: 80px;
  resize: vertical;
  font-family: inherit;
}

/* Caller field: existing picker + inline "add/edit/remove caller" flows */

.caller-buttons-row {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.add-caller-button,
.edit-caller-button {
  flex: 1;
  min-height: 44px;
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.add-caller-button {
  border: 2px solid var(--accent-border);
  background: var(--surface);
  color: var(--accent-strong);
}

.add-caller-button:active {
  background: var(--accent-bg);
}

.edit-caller-button {
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
}

.edit-caller-button:active {
  background: var(--surface-secondary);
}

.edit-caller-button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.remove-caller-button {
  width: 100%;
  min-height: 44px;
  margin-top: 8px;
  border: 2px solid var(--danger-border);
  background: var(--surface);
  color: var(--danger);
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.remove-caller-button:active {
  background: var(--danger-bg);
}

.remove-caller-confirm {
  margin-top: 8px;
}

.add-caller-form {
  margin-top: 8px;
  padding: 12px;
  border: 1px solid var(--accent-bg);
  background: var(--accent-bg);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

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

.add-caller-cancel-button,
.add-caller-save-button {
  flex: 1;
  min-height: 48px;
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.add-caller-cancel-button {
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
}

.add-caller-cancel-button:active {
  background: var(--surface-secondary);
}

.add-caller-save-button {
  border: none;
  background: var(--accent-strong);
  color: #ffffff;
}

.add-caller-save-button:active {
  background: var(--accent-strong);
}

.add-caller-cancel-button:disabled,
.add-caller-save-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.secondary-button {
  width: 100%;
  min-height: 56px;
  border: 2px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  border-radius: 12px;
  font-size: 1.05rem;
  font-weight: 700;
  cursor: pointer;
  margin-top: 16px;
}

.secondary-button:active {
  background: var(--surface-secondary);
}

.job-form-actions {
  display: flex;
  flex-direction: column-reverse;
  gap: 10px;
}

.job-form-actions .primary-button,
.job-form-actions .secondary-button {
  margin-top: 0;
}

@media (min-width: 480px) {
  .job-form-actions {
    flex-direction: row-reverse;
  }
}

/* Comfortable touch targets on larger screens too */
@media (min-width: 600px) {
  .app-main {
    padding: 32px 16px;
  }
}

/* Phase 2.1 — Driver Dashboard & Reports */

#dashboard-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.dashboard-breakdown {
  margin-top: 14px;
}

.dashboard-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 8px;
  font-size: 0.9rem;
}

.dashboard-table th,
.dashboard-table td {
  text-align: left;
  padding: 8px 4px;
  border-bottom: 1px solid var(--border-subtle);
}

.dashboard-table th {
  color: var(--text-muted);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.dashboard-table td:not(:first-child),
.dashboard-table th:not(:first-child) {
  text-align: right;
}

/* Job Mix type accents — a small dot, not a badge, using the exact same
   colour tokens Schedule's job-type-* classes already use for their
   border-left/badge colour. Purely a visual link back to that language;
   the table itself stays flat and quiet. */
.dashboard-jobtype-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}

.dashboard-jobtype-dot {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text-faint);
}

.dashboard-jobtype-dot.job-type-arrival {
  background: var(--accent);
}

.dashboard-jobtype-dot.job-type-departure {
  background: var(--warning);
}

.dashboard-jobtype-dot.job-type-transfer {
  background: var(--cat-violet);
}

.dashboard-jobtype-dot.job-type-hourly {
  background: var(--cat-teal);
}

.dashboard-jobtype-dot.job-type-ridehailing {
  background: var(--cat-pink);
}

/* Dashboard V2 — Completed Jobs (Caller-specific reconciliation list).
   Compact audit-list style, not a card per Job ID: each Job Type is one
   row, collapsed by default, same tap-target/chevron-rotation language as
   Schedule's .job-card-toggle and Finance's .expense-card-toggle. */
.dashboard-completed-jobs-card {
  padding: 4px 16px;
}

.dashboard-jobtype-group {
  position: relative;
  border-bottom: 1px solid var(--border-subtle);
}

.dashboard-jobtype-group:last-child {
  border-bottom: none;
}

.dashboard-jobtype-group-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 12px 20px 12px 0;
  border: none;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  font: inherit;
}

.dashboard-jobtype-group-toggle:active {
  opacity: 0.85;
}

.dashboard-jobtype-group-label {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  font-size: 0.92rem;
}

.dashboard-jobtype-group-count {
  color: var(--text-muted);
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
}

.dashboard-jobtype-group-chevron {
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-faint);
  transition: transform 0.15s ease;
}

.dashboard-jobtype-group-toggle[aria-expanded="true"] .dashboard-jobtype-group-chevron {
  transform: translateY(-50%) rotate(90deg);
}

.dashboard-jobtype-group-list {
  padding: 0 0 12px 16px;
}

/* Job ID + Date refinement — one compact row per job (wraps only if the
   viewport genuinely can't fit both, e.g. 320px with a long id), Job ID
   kept visually stronger than the muted Date, a centered dot between them
   via ::before rather than an extra DOM node. */
.dashboard-jobtype-group-jobrow {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px;
  padding: 4px 0;
  font-size: 0.88rem;
}

.dashboard-jobtype-group-jobid {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--text-secondary);
}

.dashboard-jobtype-group-jobdate {
  color: var(--text-muted);
}

.dashboard-jobtype-group-jobdate::before {
  content: "· ";
}

/* Phase 2.2 — Payment Tracking */

#payments-filter-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.payment-status-badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 4px 10px;
  border-radius: 999px;
}

.payment-status-unpaid {
  background: var(--warning-bg);
  color: var(--warning-strong);
}

.payment-status-paid {
  background: var(--success-bg);
  color: var(--success-strong);
}

.payments-item-header {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 10px;
}

.payments-item-checkbox {
  min-width: 24px;
  min-height: 24px;
  width: 22px;
  height: 22px;
  margin-top: 2px;
  cursor: pointer;
}

.payments-item-header-main {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

/* Finance V2 refinement — compact, quiet action instead of a full-width
   bright-green bar, so the card's amount stays the visually dominant
   element. Right-aligned via .finance-item-actions below; same subtle
   surface/border/text treatment as .status-completed's success badge
   (--success-bg/--success-strong), not the solid --success fill. */
.finance-item-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 8px;
}

.mark-paid-button {
  width: auto;
  min-height: 40px;
  min-width: 108px;
  padding: 0 16px;
  border: 1.5px solid var(--success-border);
  border-radius: 10px;
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
  background: var(--success-bg);
  color: var(--success-strong);
  margin-top: 0;
}

.mark-paid-button:active {
  background: var(--success-border);
}

/* Finance V2 refinement — same compact, right-aligned treatment as
   .mark-paid-button (via the shared .finance-item-actions wrapper), so a
   Paid card doesn't visually outweigh an Outstanding one. Kept neutral
   (border/surface, not the success-green of Mark Paid) since reverting
   isn't a "success" action — same colour language the old full-width
   version already used, just resized. */
.revert-payment-button {
  width: auto;
  min-height: 40px;
  min-width: 140px;
  padding: 0 16px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  border-radius: 10px;
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
  margin-top: 0;
}

.revert-payment-button:active {
  background: var(--surface-secondary);
}

.payments-bulk-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  background: var(--accent-bg);
  border: 1px solid var(--accent-border);
  border-radius: 12px;
  padding: 12px 14px;
  margin-top: 14px;
  flex-wrap: wrap;
}

.payments-bulk-bar span {
  font-weight: 700;
  color: var(--accent-strong);
  font-size: 0.9rem;
}

.payments-bulk-pay-button {
  width: auto;
  min-height: 44px;
  margin-top: 0;
  padding: 0 16px;
}

.payments-item-disabled {
  opacity: 0.45;
}

/* --- Finance V2 --- */

.finance-tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}

.finance-tab-button {
  flex: 1;
  min-height: 44px;
  border: 1px solid var(--border-subtle);
  background: var(--surface);
  color: var(--text-secondary);
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
}

.finance-tab-button.finance-tab-active {
  background: var(--accent-bg);
  color: var(--accent-strong);
  border-color: var(--accent-border);
}

.finance-tab-button:active {
  background: var(--surface-secondary);
}

.finance-subtabs {
  display: flex;
  gap: 8px;
  margin: 14px 0 10px;
}

.finance-subtab-button {
  flex: 1;
  min-height: 40px;
  border: 1px solid var(--border-subtle);
  background: var(--surface);
  color: var(--text-secondary);
  border-radius: 10px;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.finance-subtab-button.finance-subtab-active {
  background: var(--surface-secondary-strong);
  color: var(--text-primary);
  border-color: var(--border);
}

.finance-subtab-button:active {
  background: var(--surface-secondary);
}

/* Money-first summary — Outstanding/Paid side by side (or Total Expenses
   alone), always visible above the sub-tabs/list. Semantic colour pairs
   with each half's status badge: Outstanding ~ amber Unpaid badge, Paid ~
   green Paid badge. */
.finance-money-row {
  display: flex;
  gap: 10px;
  margin-bottom: 4px;
}

.finance-money-card {
  flex: 1;
  min-width: 0;
}

.finance-money-card-inner {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
}

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

.finance-money-amount {
  font-size: 1.3rem;
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.finance-money-count {
  font-size: 0.78rem;
  color: var(--text-muted);
}

.finance-money-outstanding .finance-money-card-inner {
  border-color: var(--warning-border);
  background: var(--warning-bg);
}

.finance-money-outstanding .finance-money-label,
.finance-money-outstanding .finance-money-amount {
  color: var(--warning-strong);
}

.finance-money-paid .finance-money-card-inner {
  border-color: var(--success-border);
  background: var(--success-bg);
}

.finance-money-paid .finance-money-label,
.finance-money-paid .finance-money-amount {
  color: var(--success-strong);
}

/* Compact filter summary — replaces the permanently-open From/To/Caller
   (or Month/From/To) form; tapping reveals the exact same form in
   .finance-filter-sheet below it. */
.finance-filter-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  margin: 10px 0;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: 10px;
  color: var(--text-secondary);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}

.finance-filter-summary-action {
  color: var(--accent-strong);
  font-weight: 700;
}

.finance-filter-sheet {
  margin-bottom: 10px;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: 12px;
}

.finance-filter-sheet form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* "Payment tracking not activated" — a genuine current configuration
   state, presented as calm information rather than an error. */
.finance-notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 12px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: 10px;
  font-size: 0.82rem;
}

.finance-notice-icon {
  flex-shrink: 0;
  display: flex;
  margin-top: 1px;
  color: var(--text-muted);
}

.finance-notice-icon svg {
  width: 17px;
  height: 17px;
}

.finance-notice-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  color: var(--text-secondary);
}

.finance-notice-text strong {
  color: var(--text-primary);
  font-size: 0.85rem;
}

/* Outstanding/Paid item cards — DATE · TYPE / AMOUNT, then status + Job ID
   · Caller, then Passenger where available, then the action button. Left
   border colour mirrors the status badge (amber Unpaid / green Paid);
   .finance-item-selected adds a full accent outline for bulk-selection
   clarity without changing the left border's semantic colour. */
.finance-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  background: var(--surface);
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  border: 1px solid transparent;
  border-left: 5px solid var(--warning);
}

.finance-item-paid {
  border-left-color: var(--success);
}

.finance-item-selected {
  border-color: var(--accent-border);
  background: var(--accent-bg);
}

.finance-item .payments-item-checkbox {
  margin-top: 2px;
  flex-shrink: 0;
}

.finance-item-body {
  flex: 1;
  min-width: 0;
}

.finance-item-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.finance-item-meta {
  flex: 1;
  min-width: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-muted);
}

.finance-item-amount {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.finance-item-sub {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 6px;
}

.finance-item-idcaller {
  font-size: 0.85rem;
  color: var(--text-secondary);
  word-break: break-word;
}

.finance-item-passenger {
  margin-top: 4px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-primary);
}

.finance-item-payment-info {
  margin-top: 6px;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* Finance V2 polish — a compact intentional treatment for "nothing here"
   states (empty Outstanding/Paid/Expenses for the current filter). Same
   message text as before; just an icon and tidier spacing instead of a
   bare line, and no invented content filling the remaining space. */
.finance-empty-state {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 18px 16px;
  border-radius: var(--radius);
  border: 1px dashed var(--border);
  color: var(--text-muted);
}

.finance-empty-state-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--text-faint);
}

.finance-empty-state-icon svg {
  width: 22px;
  height: 22px;
}

.finance-empty-state-text {
  margin: 0;
  font-size: 0.9rem;
}

/* Phase 2.4A — Expense Tracking (inside Payments -> Expenses) */

#expenses-filter-form,
#expense-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.add-expense-button {
  margin-top: 14px;
}

.expense-card {
  position: relative;
  background: var(--surface);
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  border-left: 6px solid var(--text-faint);
}

/* Finance V2 refinement — collapsed-by-default expense card, same tap-
   target/chevron technique as Schedule's .job-card-toggle/.job-card-chevron
   (see there for the shared rotation rule). The whole collapsed summary
   (description, amount, date) is the tap target; Edit/Delete only exist
   inside .expense-card-details below. */
.expense-card-toggle {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  font: inherit;
}

.expense-card-toggle:active {
  opacity: 0.85;
}

.expense-card-main {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding-right: 20px;
}

.expense-description {
  font-weight: 700;
  font-size: 1rem;
  word-break: break-word;
}

.expense-amount {
  font-weight: 800;
  font-size: 1.05rem;
  white-space: nowrap;
}

.expense-date {
  margin-top: 2px;
  font-size: 0.85rem;
  color: var(--text-muted);
  padding-right: 20px;
}

.expense-card-chevron {
  position: absolute;
  top: 14px;
  right: 14px;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-faint);
  transition: transform 0.15s ease;
}

.expense-card-toggle[aria-expanded="true"] .expense-card-chevron {
  transform: rotate(90deg);
}

.expense-card-details {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-subtle);
}

/* Deliberately understated and compact — Edit/Delete must be reachable but
   must not dominate the row (the description + amount are what a driver
   scans). Centered, auto-width buttons rather than a stretched full-width
   bar; flex-wrap keeps both comfortably tappable at 320px if they can't sit
   side by side. */
.expense-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

.expense-edit-button,
.expense-delete-button {
  flex: 0 1 auto;
  min-width: 96px;
  min-height: 40px;
  padding: 0 16px;
  border-radius: 10px;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  background: var(--surface);
}

.expense-edit-button {
  border: 1px solid var(--border);
  color: var(--text-secondary);
}

.expense-edit-button:active {
  background: var(--surface-secondary);
}

.expense-delete-button {
  border: 1px solid var(--danger-border);
  color: var(--danger);
}

.expense-delete-button:active {
  background: var(--danger-bg);
}

.expense-confirm-prompt {
  margin: 10px 0 8px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-secondary);
}

/* Dashboard V2 — same section-heading treatment used elsewhere (Finance's
   money-card labels, Home's overview title): small muted caps. Replaces
   the old collapsible-header buttons — sections are always shown once
   their data is available, no per-section toggle state. */
.dashboard-section-heading {
  margin: 18px 0 8px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

#dashboard-performance-section .dashboard-section-heading {
  margin-top: 4px;
}

/* Filter row: From/To share a line, Caller spans full width beneath. */
.dashboard-filter-row {
  display: flex;
  gap: 10px;
}

.dashboard-filter-field {
  flex: 1;
  min-width: 0; /* lets the date inputs shrink instead of overflowing */
  display: flex;
  flex-direction: column;
}

.dashboard-filter-field .text-input {
  font-size: 0.95rem;
  padding: 10px;
}

/* Performance — Scheduled/Completed as a small counts row (.quick-overview-
   counts), then Completion Rate (.dashboard-completion-rate), then Revenue
   and Average/Job each on their own full-width, progressively larger row
   (.quick-overview-money) — three explicit groups rather than a plain
   2x2/4-across grid, so layout doesn't depend on child position/order.
   Same buildQuickStat() calls, same data — only the layout changed.
   Neutral surface (counts aren't "good/bad news", so no success tint here
   — that's reserved for Financial Summary's figures). */
.quick-overview {
  display: flex;
  flex-direction: column;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: 12px;
}

.quick-overview-counts {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 14px;
}

.quick-stat {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Completion Rate — between the counts and the money figures, on its own
   divider-separated row (same visual weight as the Revenue divider used
   to have at this position). */
.dashboard-completion-rate {
  margin: 10px 0 8px;
  padding-top: 10px;
  border-top: 1px dashed var(--border-subtle);
}

.dashboard-completion-track {
  height: 6px;
  border-radius: 999px;
  background: var(--surface-secondary);
  overflow: hidden;
}

.dashboard-completion-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--success);
  transition: width 0.2s ease;
}

.dashboard-completion-caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.dashboard-completion-pct {
  font-weight: 700;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.quick-overview-money {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--border-subtle);
}

.quick-overview-money .quick-stat-value {
  font-size: 1.7rem;
}

.quick-overview-money .quick-stat:last-child .quick-stat-value {
  font-size: 1.05rem;
  color: var(--text-secondary);
}

.quick-stat-label {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.quick-stat-value {
  margin-top: 2px;
  font-size: 1.05rem;
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

/* Collapsible sections (Financial Summary / Job Type / Expenses) — the
   .collapsible-* rules below are now orphaned (Dashboard V2 replaced the
   toggle buttons with plain .dashboard-section-heading text), left in
   place harmlessly per this codebase's rollback convention. */

.collapsible-section {
  margin-top: 14px;
  padding: 0;
  overflow: hidden;
}

.collapsible-header {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 52px;
  padding: 14px 18px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-primary);
  text-align: left;
  cursor: pointer;
}

.collapsible-header:active {
  background: var(--surface-elevated);
}

.collapsible-arrow {
  color: var(--text-muted);
  font-size: 0.8rem;
  transition: transform 0.15s ease;
}

.collapsible-header[aria-expanded="false"] .collapsible-arrow {
  transform: rotate(-90deg);
}

.collapsible-body {
  padding: 0 18px 18px;
}

/* Three financial cards. Type scales down a step at very narrow widths so
   a long negative figure like -$2,683.32 never clips or wraps mid-number;
   the approved 3-card structure is preserved at every width. */
.financial-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.financial-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  padding: 10px 6px;
  border-radius: 10px;
  background: var(--surface-elevated);
  border: 1px solid var(--border-subtle);
  text-align: center;
}

.financial-card-label {
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--text-muted);
  line-height: 1.25;
}

/* nowrap is deliberate: an amount must never break mid-number
   ("-$2,683.3 / 2"). Type is sized down instead so even a long negative
   like -$12,345.67 stays on one line inside a ~97px card at 375px. */
.financial-card-value {
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.financial-card-expense {
  color: var(--danger);
}

/* Net Earnings stays the visually strongest figure. */
.financial-card-net {
  background: var(--success-bg);
  border-color: var(--success-border);
}

.financial-card-value-net {
  font-size: 0.92rem;
  color: var(--success-strong);
}

.financial-card-net.financial-negative-card {
  background: var(--danger-bg);
  border-color: var(--danger-border);
}

.financial-card-value-net.financial-negative {
  color: var(--danger);
}

@media (min-width: 400px) {
  .financial-card {
    padding: 10px 8px;
  }
  .financial-card-label {
    font-size: 0.7rem;
  }
  .financial-card-value {
    font-size: 0.95rem;
  }
  .financial-card-value-net {
    font-size: 1.15rem;
  }
}

.financial-note {
  margin-top: 14px;
  margin-bottom: 0;
  line-height: 1.45;
}

/* Dashboard V2 Financial Summary — Revenue/Expenses reuse Finance V2's own
   .finance-money-row/-card (same component, same styling as Payments'
   money summary); Expenses gets a red tint via this modifier since it's
   money going out, distinct from Payments' neutral card treatment. Net
   Earnings gets its own full-width prominent row below, mirroring the
   approved mockup. */
.finance-money-card-inner-expense {
  border-color: var(--danger-border);
  background: var(--danger-bg);
}

.finance-money-card-inner-expense .finance-money-label,
.finance-money-card-inner-expense .finance-money-amount {
  color: var(--danger);
}

.dashboard-net-card {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-top: 10px;
  padding: 14px 16px;
  background: var(--success-bg);
  border: 1px solid var(--success-border);
  border-radius: 12px;
}

.dashboard-net-label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--success-strong);
}

.dashboard-net-value {
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--success-strong);
  font-variant-numeric: tabular-nums;
}

.dashboard-net-card.financial-negative-card {
  background: var(--danger-bg);
  border-color: var(--danger-border);
}

.dashboard-net-card.financial-negative-card .dashboard-net-label {
  color: var(--danger);
}

.dashboard-net-value.financial-negative {
  color: var(--danger);
}

/* Job Mix / Expense Breakdown tables — a compact card wrapper (less
   padding than the base .card) instead of the old collapsible-section
   card, so the table reads as a defined surface without excess whitespace
   around it. */
.dashboard-table-card {
  padding: 14px 16px;
  border: 1px solid var(--border-subtle);
}

/* Searchable Caller picker (Add/Edit Job) */

.caller-picker {
  position: relative;
}

.caller-picker-input {
  width: 100%;
}

.caller-picker-results {
  position: absolute;
  z-index: 30;
  left: 0;
  right: 0;
  top: calc(100% + 4px);
  max-height: 240px;
  overflow-y: auto;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}

.caller-picker-option {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  border: none;
  border-bottom: 1px solid var(--surface-secondary);
  background: var(--surface);
  color: var(--text-primary);
  font-family: inherit;
  font-size: 1rem;
  text-align: left;
  cursor: pointer;
}

.caller-picker-option:last-child {
  border-bottom: none;
}

.caller-picker-option:active {
  background: var(--surface-secondary);
}

.caller-picker-option-selected {
  background: var(--success-bg);
  font-weight: 700;
}

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

/* Success variant of the shared banner (e.g. "4 jobs created successfully.") */
.error-banner.banner-success {
  color: var(--success-strong);
  background: var(--success-bg);
  border-color: var(--success-border);
}

/* Duplicate Job panel */

.duplicate-job-button {
  width: 100%;
  min-height: 48px;
  margin-top: 10px;
  border: 2px solid var(--accent-border);
  background: var(--accent-bg);
  color: var(--accent-strong);
  border-radius: 10px;
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
}

.duplicate-job-button:active {
  background: var(--accent-bg);
}

.duplicate-add-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}

.duplicate-add-row .text-input {
  flex: 1;
  min-width: 0;
}

.duplicate-add-button {
  width: auto;
  margin-top: 0;
  padding: 0 18px;
  min-height: 52px;
}

.duplicate-selected-dates {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}

.duplicate-date-chip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  background: var(--surface-secondary);
  border-radius: 10px;
  font-size: 0.95rem;
  font-weight: 600;
}

.duplicate-date-remove {
  min-width: 36px;
  min-height: 36px;
  border: none;
  background: none;
  color: var(--danger);
  font-size: 1rem;
  cursor: pointer;
}

/* ==========================================================================
   Horizontal job action bar (Scheduler UI refinement)
   --------------------------------------------------------------------------
   Presentation only. The original vertical rules for .status-action,
   .status-action-button, .edit-job-button, .duplicate-job-button,
   .cancel-action and .cancel-job-button are left INTACT above; everything
   here is scoped to `.job-action-bar >` so it only applies inside the new
   row. To roll back to the vertical stack: delete this whole block and
   revert the `.job-action-bar` wrapper in public/app.js#renderJobCard.
   ========================================================================== */

.job-action-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 6px;
  margin-top: 12px;
}

/* Each of the four actions takes an equal quarter. min-width:0 is what
   lets them actually shrink to fit instead of overflowing the card. */
.job-action-bar > .status-action,
.job-action-bar > .cancel-action,
.job-action-bar > .edit-job-button,
.job-action-bar > .duplicate-job-button {
  flex: 1 1 0;
  min-width: 0;
  margin-top: 0;
}

/* Shared button shape inside the bar — overrides the width:100% and taller
   min-heights of the original standalone rules. */
.job-action-bar .status-action-button,
.job-action-bar .edit-job-button,
.job-action-bar .duplicate-job-button,
.job-action-bar .cancel-job-button {
  width: 100%;
  min-height: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 6px 2px;
  border-radius: 10px;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.1;
}

/* Icons stay small and secondary to the label. */
.job-action-icon {
  font-size: 0.85rem;
  line-height: 1;
  opacity: 0.85;
}

/* nowrap is the guarantee that "Duplicate" never breaks onto two lines. */
.job-action-label {
  white-space: nowrap;
}

/* While a confirm prompt is showing, that container takes the full card
   width on its own row rather than being squeezed into a quarter column. */
.job-action-bar > .action-confirming {
  flex: 1 0 100%;
}

/* Very narrow phones (~320px): tighten type/padding a step so four labels
   still fit on one row without clipping. */
@media (max-width: 359px) {
  .job-action-bar {
    gap: 3px;
  }
  .job-action-bar .status-action-button,
  .job-action-bar .edit-job-button,
  .job-action-bar .duplicate-job-button,
  .job-action-bar .cancel-job-button {
    font-size: 0.58rem;
    padding: 6px 1px;
  }
  .job-action-icon {
    font-size: 0.72rem;
  }
}

/* Roomier phones get slightly larger type. */
@media (min-width: 400px) {
  .job-action-bar .status-action-button,
  .job-action-bar .edit-job-button,
  .job-action-bar .duplicate-job-button,
  .job-action-bar .cancel-job-button {
    font-size: 0.78rem;
  }
}

/* ==========================================================================
   Phase 3A — Live OTS & Waiting Countdown (public/timer.html + timer.js)
   --------------------------------------------------------------------------
   Fully isolated: every rule below is scoped to classes unique to the
   Live Timer page or its Schedule-home entry link. To roll back, delete
   this block, delete public/timer.html and public/timer.js, and remove the
   #live-timer-link markup from index.html — nothing else references these
   classes.
   ========================================================================== */

.live-timer-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  margin-bottom: 12px;
  border: 2px solid var(--emphasis-bg);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text-primary);
  font-weight: 700;
  font-size: 0.95rem;
  text-decoration: none;
}

.live-timer-link:active {
  background: var(--surface-secondary);
}

/* Operations V2 — compact page-level notices, replacing the old
   multi-paragraph .timer-intro-card. Each row: a small muted icon, a bold
   one-line heading, and at most one line of supporting text — deliberately
   not a "card" in its own right, just quiet context above the timer(s). */
.operations-subtitle {
  margin: -10px 0 14px;
  color: var(--text-muted);
  font-size: 0.9rem;
}

/* Operations V2 final polish — a single compact strip above the timer
   (down from three stacked cards); the reference/notification info moved
   to .operations-secondary, below the timer(s). */
.operations-notice-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: 10px;
  font-size: 0.82rem;
}

.operations-notice-compact {
  margin-bottom: 14px;
}

.operations-notice-icon {
  flex-shrink: 0;
  display: flex;
  margin-top: 1px;
  color: var(--text-muted);
}

.operations-notice-icon svg {
  width: 17px;
  height: 17px;
}

.operations-notice-text {
  display: flex;
  flex-direction: column;
  gap: 1px;
  color: var(--text-secondary);
}

.operations-notice-text strong {
  color: var(--text-primary);
  font-size: 0.85rem;
}

.operations-notice-action {
  margin: 4px 0 0;
  font-size: 0.82rem;
  font-weight: 700;
}

/* Reference-timer + notification status — one quiet card below the
   timer(s), never gating access to them. */
.operations-secondary {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 10px;
  margin-top: 14px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: 10px;
  font-size: 0.78rem;
}

.operations-secondary-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: var(--text-muted);
}

.operations-alert-status-line {
  color: var(--text-muted);
}

.timer-toast-area {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}

/* Compact operational notification, not a primary action — neutral
   surface with a small icon and a subtle semantic accent border, never a
   flooded saturated fill. */
.timer-toast {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-primary);
}

.timer-toast-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--accent-strong);
}

.timer-toast-icon svg {
  width: 15px;
  height: 15px;
}

.timer-toast-sd {
  border-left-color: var(--danger);
}

.timer-toast-sd .timer-toast-icon {
  color: var(--danger);
}

/* Operations V2 — clean intentional empty state, replacing the old bare
   "No jobs are due for OTS in the next hour." line. */
.timer-empty-state {
  padding: 22px 18px;
  border-radius: var(--radius);
  border: 1px dashed var(--border);
  text-align: center;
  margin-bottom: 14px;
}

.timer-empty-title {
  margin: 0 0 4px;
  font-size: 1rem;
  font-weight: 800;
  color: var(--text-primary);
}

.timer-empty-text {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.9rem;
}

.timer-empty-hint {
  margin: 6px 0 0;
  color: var(--text-muted);
  font-size: 0.82rem;
}

.timer-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* The timer card itself — job identity header, then the stage hero
   (countdown), then the exact OTS/SD clock times, matching the same
   surface/border-radius/shadow language as the locked Schedule job cards.
   Stage colour is carried by the left border + .timer-stage-label text +
   .timer-hero-value, never a flooded background (section 12). */
.timer-card {
  position: relative;
  background: var(--surface);
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
  border-left: 5px solid var(--text-faint);
}

.timer-stage-approaching {
  border-left-color: var(--accent);
}

.timer-stage-waiting {
  border-left-color: var(--warning);
}

.timer-stage-overdue {
  border-left-color: var(--danger);
}

.timer-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}

.timer-job-id {
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

.timer-card-flight {
  font-size: 0.9rem;
  color: var(--text-muted);
  margin-bottom: 2px;
}

.timer-card-passenger {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-primary);
  margin-bottom: 4px;
}

.timer-card-passenger .field-row-icon {
  color: var(--text-muted);
}

/* The hero — substantially larger than every other element on the card
   (section 9). Centred, tabular-nums so the digits don't jitter width
   tick to tick. */
.timer-hero {
  text-align: center;
  padding: 12px 0;
  margin: 8px 0;
  border-top: 1px dashed var(--border-subtle);
  border-bottom: 1px dashed var(--border-subtle);
}

.timer-stage-label {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
  color: var(--accent-strong);
}

.timer-stage-waiting .timer-stage-label {
  color: var(--warning-strong);
}

.timer-stage-overdue .timer-stage-label {
  color: var(--danger);
}

.timer-hero-value {
  font-size: 2.4rem;
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.timer-stage-overdue .timer-hero-value {
  color: var(--danger);
}

.timer-hero-caption {
  margin-top: 2px;
  font-size: 0.8rem;
  color: var(--text-muted);
}

/* Exact clock times — always visible alongside the countdown (section 13),
   never the countdown's replacement. */
.timer-exact-times {
  display: flex;
  gap: 8px;
}

.timer-exact-time {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 0;
  background: var(--surface-secondary);
  border-radius: 8px;
}

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

.timer-exact-time-value {
  font-size: 1.05rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}

.timer-eta-note {
  margin: 10px 0 0;
  font-size: 0.78rem;
  color: var(--text-muted);
}

.timer-update-eta-button {
  width: 100%;
  min-height: 40px;
  margin-top: 8px;
  font-size: 0.85rem;
}

@media (max-width: 359px) {
  .timer-hero-value {
    font-size: 2rem;
  }
}

/* ==========================================================================
   Calendar Integration 3.1A — driver-controlled "Add to Calendar"
   --------------------------------------------------------------------------
   Fully isolated: every rule below is scoped to .calendar-export-* classes
   that exist nowhere else. To roll back, delete this block and remove the
   buildCalendarExportButton() call site in public/app.js#renderJobCard —
   nothing else references these classes.
   ========================================================================== */

.calendar-export-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: auto;
  min-height: 40px;
  margin: 10px 0 4px;
  padding: 8px 14px;
  border: 1.5px solid var(--accent-border);
  border-radius: 10px;
  background: var(--accent-bg);
  color: var(--accent-strong);
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.calendar-export-button:active {
  background: var(--accent-bg-strong);
}

.calendar-export-icon {
  display: inline-flex;
  flex-shrink: 0;
}

.calendar-export-label {
  white-space: nowrap;
}

/* Very narrow phones: a compact secondary button already fits comfortably,
   but a touch is taken off the horizontal padding to keep generous margin
   either side. */
@media (max-width: 359px) {
  .calendar-export-button {
    padding: 8px 10px;
    font-size: 0.8rem;
  }
}

/* ==========================================================================
   Phase 4A — Passenger WhatsApp Messaging Automation
   --------------------------------------------------------------------------
   Fully isolated: every rule below is scoped to .whatsapp-message-* and
   #message-passenger-* classes that exist nowhere else. To roll back,
   delete this block, remove the buildMessagePassengerButton() call site in
   public/app.js#renderJobCard, and remove the #message-passenger-section
   markup from index.html.
   ========================================================================== */

.whatsapp-message-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: auto;
  min-height: 40px;
  margin: 6px 0 4px;
  padding: 8px 14px;
  border: 1.5px solid var(--success-border);
  border-radius: 10px;
  background: var(--success-bg);
  color: var(--success-strong);
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.whatsapp-message-button:active {
  background: var(--success-bg);
}

/* Missing/unnormalizable Pax Mobile — same button, same tap target, same
   click handler (still opens the existing explanatory panel, never
   WhatsApp), just neutral instead of green so it doesn't read as fully
   available when it can't actually send anything. */
.whatsapp-message-button-muted {
  border-color: var(--border-subtle);
  background: var(--surface-secondary);
  color: var(--text-muted);
}

.whatsapp-message-button-muted:active {
  background: var(--surface-secondary);
}

.whatsapp-message-icon {
  display: inline-flex;
  flex-shrink: 0;
}

.whatsapp-message-label {
  white-space: nowrap;
}

@media (max-width: 359px) {
  .whatsapp-message-button {
    padding: 8px 10px;
    font-size: 0.8rem;
  }
}

.message-passenger-info {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 4px 0 12px;
}

.message-passenger-textarea {
  min-height: 120px;
  resize: vertical;
  font-family: inherit;
  line-height: 1.4;
}

#message-pickup-point-field {
  margin-bottom: 10px;
}

/* ==========================================================================
   UI/UX Refinement — Login redesign, Home hub, bottom nav restructure,
   More sheet, Appearance selector.
   --------------------------------------------------------------------------
   Presentation/navigation only — every rule below is scoped to classes
   unique to this refinement. To roll back the navigation restructure
   specifically: restore the previous #home-bottom-nav markup/#nav-*
   handlers in index.html/app.js; this CSS block can stay (unused classes
   are harmless) or be deleted together with it.
   ========================================================================== */

/* --- Login --- */

/* Login V2 — the card is centered with a comfortable max-width even on
   wide/desktop viewports, matching DriverHub's mobile-centered
   architecture rather than stretching the form full-width. */
.login-card {
  max-width: 400px;
  margin: 64px auto 0;
  padding: 28px 24px;
  border: 1px solid var(--border-subtle);
}

/* Same two-tone wordmark treatment as Home's .home-brand (Driver in the
   primary text colour, Hub in the accent blue) — reused here instead of
   the old blue banner/"DH" tile so Login reads as the same product as
   every other V2 screen. Centered and sized up slightly since it's the
   only branding on the page. */
.login-wordmark {
  text-align: center;
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  margin-bottom: 22px;
}

.login-wordmark-driver {
  color: var(--text-primary);
}

.login-wordmark-hub {
  color: var(--accent);
}

.login-brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 4px;
  margin-bottom: 20px;
}

.login-welcome {
  margin: 0;
  font-size: 1.3rem;
}

.login-subtitle {
  margin: 0;
}

/* PIN show/hide toggle — sits inside the right edge of the PIN field.
   Right padding on the input keeps typed digits clear of the button. */
.pin-field-wrap {
  position: relative;
}

.pin-input {
  padding-right: 48px;
}

.pin-toggle-button {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 48px;
  min-width: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
}

.pin-toggle-button svg {
  width: 22px;
  height: 22px;
}

.pin-toggle-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-radius: var(--radius-sm);
}

.pin-toggle-button:active {
  color: var(--text-secondary);
}

/* --- Home --- */

/* Home-only wordmark — replaces the shared blue .app-header while Home is
   active (see body.home-active below). "Driver" in the primary text
   colour, "Hub" in the accent blue — a compact two-tone mark rather than a
   full-width bar. */
.home-brand {
  margin: 2px 0 18px;
  font-size: 1.1rem;
  font-weight: 800;
  letter-spacing: 0.01em;
}

.home-brand-driver {
  color: var(--text-primary);
}

.home-brand-hub {
  color: var(--accent);
}

.home-greeting {
  margin-bottom: 16px;
}

.home-greeting-text {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.25;
  color: var(--text-primary);
}

.home-date-text {
  margin: 3px 0 0;
  color: var(--text-muted);
  font-size: 0.9rem;
}

/* --- Home V2 — Today Overview --- */

.home-overview-card {
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  padding: 14px 16px 16px;
  margin-bottom: 12px;
}

.home-overview-title {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 10px;
}

.home-overview-stats {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

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

.home-overview-stat-value {
  font-size: 1.8rem;
  font-weight: 800;
  line-height: 1.1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.home-overview-stat-value-accent {
  color: var(--success-strong);
}

.home-overview-stat-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  font-weight: 600;
}

.home-overview-progress-track {
  height: 8px;
  border-radius: 999px;
  background: var(--surface-secondary);
  overflow: hidden;
  margin-bottom: 6px;
}

.home-overview-progress-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--success);
  transition: width 0.2s ease;
}

.home-overview-progress-caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.home-overview-progress-pct {
  font-weight: 700;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* --- Home V2 — Next Job hero --- */

.home-next-job-empty {
  padding: 16px;
  border-radius: var(--radius);
  border: 1px dashed var(--border);
  color: var(--text-muted);
  text-align: center;
  margin-bottom: 14px;
  font-size: 0.9rem;
}

.home-next-job-card {
  position: relative;
  background: var(--surface);
  border-left: 5px solid var(--text-faint);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 14px 34px 14px 16px;
  margin-bottom: 14px;
  cursor: pointer;
}

.home-next-job-card:active {
  background: var(--surface-secondary);
}

.home-next-job-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.home-next-job-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-right: 2px;
}

.home-next-job-id {
  margin-left: auto;
}

.home-next-job-time {
  font-size: 1.6rem;
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}

.home-next-job-subline {
  font-size: 0.9rem;
  color: var(--text-muted);
  margin-top: 1px;
}

/* Home V2 polish — who/where fields read via icon instead of a field label
   ("[person icon] Mr Duy" rather than "Pax Name  Mr Duy"); secondary
   metadata (Reporting/Service Type/Pax Mobile) stays as a short labeled
   row underneath, visually quieter than the icon rows above it. */
.home-next-job-rows {
  margin: 12px 0 0;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.home-next-job-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.home-next-job-row-icon-type .home-next-job-row-value {
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--text-primary);
}

/* Shared icon wrapper (buildFieldIcon in app.js) — used by both the Home
   V2 Next Job hero and the Schedule expanded job card's icon rows. */
.field-row-icon {
  flex-shrink: 0;
  display: flex;
  color: var(--text-muted);
}

.field-row-icon svg {
  width: 16px;
  height: 16px;
}

.home-next-job-row-label-type {
  font-size: 0.85rem;
}

.home-next-job-row-label-type .home-next-job-row-label {
  color: var(--text-muted);
  min-width: 92px;
}

.home-next-job-row-label-type .home-next-job-row-value {
  color: var(--text-secondary);
  font-weight: 500;
  word-break: break-word;
}

/* Price kept out of the who/where rows entirely — its own quiet line, a
   short label plus the value, deliberately lighter than the time headline. */
.home-next-job-price-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-subtle);
}

.home-next-job-price-label {
  font-size: 0.78rem;
  color: var(--text-muted);
}

.home-next-job-price-value {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-secondary);
}

.home-next-job-actions {
  margin-top: 12px;
}

.home-next-job-actions .whatsapp-message-button {
  width: 100%;
  justify-content: center;
  margin: 0;
}

.home-next-job-chevron {
  position: absolute;
  top: 14px;
  right: 14px;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text-faint);
}

/* Two-class selectors so these reliably win over the single-class
   .job-type-* border-left rules earlier in this file regardless of source
   order (both set the same border-left-color property). */
.home-next-job-card.job-type-arrival {
  border-left-color: var(--accent);
}
.home-next-job-card.job-type-departure {
  border-left-color: var(--warning);
}
.home-next-job-card.job-type-transfer {
  border-left-color: var(--cat-violet);
}
.home-next-job-card.job-type-hourly {
  border-left-color: var(--cat-teal);
}
.home-next-job-card.job-type-ridehailing {
  border-left-color: var(--cat-pink);
}

/* --- Home Planning Overview — filter row, search, JOBS categories --- */

.home-filter-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.home-filter-row .finance-filter-summary {
  flex: 1;
  margin: 10px 0;
}

.home-filter-clear {
  margin: 0;
  font-size: 0.85rem;
  white-space: nowrap;
}

.home-search-field {
  margin-bottom: 10px;
}

.home-search-field .text-input {
  min-height: 44px;
  padding: 10px 14px;
  font-size: 0.95rem;
}

.home-overview-subtitle {
  margin: -6px 0 10px;
  font-size: 0.82rem;
  color: var(--text-secondary);
  font-weight: 600;
}

.home-jobs-section {
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  padding: 4px 16px;
  margin-bottom: 14px;
}

.home-jobs-header {
  padding: 12px 0 8px;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.home-jobs-empty {
  padding: 4px 0 14px;
  font-size: 0.88rem;
}

/* Each expanded-category row — same Job ID/date styling as Dashboard's
   .dashboard-jobtype-group-jobrow (see .dashboard-jobtype-group-jobid/
   -jobdate), but a tappable full-width button (Home rows open the Job in
   Schedule) with a status badge pushed to the right instead of a plain
   static row. */
.home-jobrow {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 0;
  border: none;
  background: transparent;
  color: inherit;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.home-jobrow:active {
  opacity: 0.85;
}

.home-jobrow-status {
  margin-left: auto;
  flex-shrink: 0;
}

.home-nav-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 8px;
}

/* Vertical-balance polish: a modest height/padding bump (not a redesign)
   so the empty-state Home doesn't leave as much bare space above the
   bottom nav — still governed entirely by content, so a real Next Job
   card continues to consume however much space it naturally needs. */
.home-nav-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 20px 16px;
  min-height: 150px;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius);
  color: var(--text-primary);
  text-decoration: none;
  cursor: pointer;
}

.home-nav-card:active {
  background: var(--surface-secondary);
}

/* Subtle accent-tinted badge behind each icon, rather than a bare emoji —
   one consistent container across all four cards (size, radius, colour). */
.home-nav-card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  margin-bottom: 6px;
  border-radius: 11px;
  background: var(--accent-bg);
  color: var(--accent);
}

.home-nav-card-icon svg {
  width: 20px;
  height: 20px;
}

.home-nav-card-title {
  font-weight: 800;
  font-size: 1rem;
}

.home-nav-card-desc {
  font-size: 0.8rem;
  line-height: 1.3;
  color: var(--text-muted);
  text-align: left;
}

/* --- More sheet --- */

.more-sheet-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 29;
}

.more-sheet {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(96px + env(safe-area-inset-bottom, 0px));
  max-width: 536px;
  margin: 0 auto;
  z-index: 30;
  padding: 16px;
}

.more-sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.more-sheet-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

.more-sheet-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 10px 6px;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: 0.98rem;
  font-weight: 700;
  text-align: left;
  cursor: pointer;
  border-radius: var(--radius-sm);
}

.more-sheet-item:active {
  background: var(--surface-secondary);
}

.more-sheet-item-danger {
  color: var(--danger);
}

.more-sheet-divider {
  height: 1px;
  background: var(--border-subtle);
  margin: 8px 0;
}

/* Optional Job image attachment viewer (Phase D-E) — same fixed
   backdrop+centered-panel pattern as .more-sheet-backdrop/.more-sheet
   above, just centered vertically instead of bottom-anchored, since it
   needs to comfortably fit a tall portrait screenshot too. A higher
   z-index than the more-sheet's so it can never end up underneath it. */
.attachment-viewer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 39;
}

.attachment-viewer {
  position: fixed;
  left: 12px;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  max-width: 536px;
  max-height: 85vh;
  margin: 0 auto;
  z-index: 40;
  padding: 16px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.attachment-viewer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
  flex-shrink: 0;
}

.attachment-viewer-header h2 {
  margin: 0;
  font-size: 1.05rem;
}

/* object-fit: contain preserves aspect ratio for both portrait and
   landscape screenshots alike; max-width/max-height keep it inside the
   panel (itself already width- and height-capped above) so it can never
   overflow the viewport in either direction. */
.attachment-viewer-image {
  display: block;
  margin: 0 auto;
  max-width: 100%;
  max-height: 70vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 8px;
}

.more-appearance-label {
  margin: 4px 0 8px;
}

.appearance-selector {
  display: flex;
  gap: 6px;
  margin-bottom: 4px;
}

.appearance-option {
  flex: 1;
  min-height: 40px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--text-secondary);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
}

.appearance-option-active {
  background: var(--emphasis-bg);
  color: var(--emphasis-text);
  border-color: var(--emphasis-bg);
}

/* --- Finance heading (Payments view relabelled as Finance) --- */

.finance-heading {
  margin: 0 0 12px;
  font-size: 1.1rem;
}
