/* ═══════════════════════════════════════════════════════════
   App Components — Component Library
   Light admin theme shared across all ops pages.
   New pages: <link rel="stylesheet" href="app-components.css"> before <style>
   ═══════════════════════════════════════════════════════════ */

/* ── 1. DESIGN TOKENS ── */
:root {
  --brand-primary:      #1a2744;
  --brand-accent:      #c8a951;
  --brand-white:     #ffffff;
  --brand-light:     #f4f5f7;
  --brand-border:    #dde1e6;
  --brand-text:      #1a2744;
  --brand-muted:     #6b7280;
  --brand-hover:     #f0f2f5;
  --brand-green:     #22c55e;
  --brand-red:       #ef4444;
  --brand-blue:      #3b82f6;
  --brand-yellow:    #eab308;
  --brand-orange:    #f97316;
  --brand-red-bg:    #fef2f2;
  --brand-green-bg:  #f0fdf4;
  --brand-blue-bg:   #eff6ff;
  --brand-yellow-bg: #fefce8;
  --topbar-h:     52px;

  /* Stacking ladder — use these tokens everywhere z-index is needed.
     Order (bottom → top): page content → sticky header → page banners
     → slideouts → modals → toasts. See CANON.md "Z-Index" for the rule. */
  --brand-z-sticky-header:    50;    /* topbar, sticky table thead */
  --brand-z-page-overlay:     100;   /* claim banners, test-mode banner */
  --brand-z-slideout-overlay: 500;   /* slideout / drawer backdrops */
  --brand-z-slideout:         501;   /* slideout / drawer panel */
  --brand-z-modal-overlay:    1000;  /* modal dialogs — always above slideouts */
  --brand-z-modal:            1001;  /* modal inner box */
  --brand-z-toast:            10000; /* toast notifications — always on top */

  /* Legacy aliases — light admin pages that reference un-prefixed vars will pick up
     the light admin values. Dark pages load app-glass.css (not this file) and
     define their own --navy / --gold with different values — unaffected. */
  --navy:  var(--brand-primary);
  --gold:  var(--brand-accent);
}

/* ── 2. BASE RESET ── */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--brand-light);
  color: var(--brand-text);
  min-height: 100vh;
}

/* ── Landscape safe-area gutter (iPhone Dynamic Island / notch) ──
   In landscape the island rotates to a SIDE edge, so page content must clear
   the left/right insets — top-only padding (the common case) doesn't help.
   Pad the body globally; viewport-fit=cover (every page) opts us into drawing
   edge-to-edge, so we own the insets. Driven purely by env(): a no-op on
   desktop / iPad / portrait where side-insets are 0, so no media query needed.
   The full-bleed topbar breaks back out via negative margins (topbar.js).
   NOT covered: position:fixed/absolute edge-anchored elements (FABs, slide-out
   panels, bottom sheets) — they anchor to the viewport, not the padded body,
   so each handles its own max(px, env(safe-area-inset-*)). See CANON §10. */
body {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* ── 3. PAGE LAYOUT ── */
/* canonical: wc-page / wc-page-header; aliases: page-wrap / page-header */
.wc-page, .page-wrap {
  max-width: 1100px;
  margin: 0 auto;
  padding: 28px 24px 60px;
}
.wc-page-header, .page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}
.wc-page-header h1, .page-header h1 { font-size: 1.4rem; }
/* Mobile: stack the title above its action buttons so they never collide /
   overlap the (wrapped) heading on narrow screens. Pure stack — no width
   changes — to stay safe across the ~20 pages that share this header. */
@media (max-width: 600px) {
  .wc-page-header, .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }
}

/* ── 4. BUTTONS ── */

/* Site-wide tactile press feedback (Emil Kowalski "Animations on the Web").
   Uses :where() to give zero specificity so any class-based :active rule
   (e.g. .btn-gold-3d's translateY, driver-app's custom scales) wins. New
   buttons get the press feel for free; old buttons with bespoke press
   effects keep theirs untouched. */
button:where(:active:not(:disabled)) {
  transform: scale(0.97);
  transition: transform 0.05s ease-out;
}
@media (prefers-reduced-motion: reduce) {
  button:where(:active:not(:disabled)) { transform: none; }
}

/* Generic in-button spinner — drop <span class="btn-spinner"></span> inside
   any button to show a loading state. Uses currentColor so it adapts to
   the button's text color (white on navy, navy on gold, etc.). */
.btn-spinner {
  display: inline-block;
  width: 12px;
  height: 12px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: btn-spin 0.7s linear infinite;
  vertical-align: -2px;
  margin-right: 6px;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn-spinner { animation: none; border-top-color: currentColor; opacity: 0.5; }
}

/* Primary — navy solid
   Canonical: .btn-primary
   Aliases:   .btn-user-add  .btn-save  .btn-add  .btn-modal-submit  .btn-send-memo */
.btn-primary,
.btn-user-add,
.btn-save,
.btn-add,
.btn-modal-submit,
.btn-send-memo {
  background: var(--brand-primary);
  color: var(--brand-text-on-primary, #fff);
  border: none;
  padding: 8px 18px;
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: opacity 0.15s, transform 0.05s ease-out;
  display: inline-block;
  line-height: 1.4;
  text-decoration: none;
}
.btn-primary:hover:not(:disabled),
.btn-user-add:hover:not(:disabled),
.btn-save:hover:not(:disabled),
.btn-add:hover:not(:disabled),
.btn-modal-submit:hover:not(:disabled),
.btn-send-memo:hover:not(:disabled) { opacity: 0.85; }

/* Secondary — light bordered
   Canonical: .btn-secondary
   Aliases:   .btn-modal-cancel */
.btn-secondary,
.btn-modal-cancel {
  background: var(--brand-light);
  color: var(--brand-text);
  border: 1px solid var(--brand-border);
  padding: 8px 16px;
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s, transform 0.05s ease-out;
  display: inline-block;
  line-height: 1.4;
  text-decoration: none;
}
.btn-secondary:hover, .btn-modal-cancel:hover { background: var(--brand-border); }

/* Ghost — no fill, bordered, gold hover
   Canonical: .btn-ghost
   Aliases:   .btn-user-action  .btn-user-edit */
.btn-ghost,
.btn-user-action,
.btn-user-edit {
  background: none;
  color: var(--brand-text);
  border: 1px solid var(--brand-border);
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.05s ease-out;
  display: inline-block;
  line-height: 1.6;
  text-decoration: none;
}
.btn-ghost:hover,
.btn-user-action:hover,
.btn-user-edit:hover {
  background: var(--brand-light);
  border-color: var(--brand-accent);
  color: var(--brand-text);
}

/* Danger — red text/border
   Canonical: .btn-danger
   Aliases:   .btn-user-delete */
.btn-danger,
.btn-user-delete {
  background: none;
  color: var(--brand-red);
  border: 1px solid var(--brand-border);
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s, border-color 0.15s, transform 0.05s ease-out;
  display: inline-block;
  line-height: 1.6;
  text-decoration: none;
}
.btn-danger:hover,
.btn-user-delete:hover { background: var(--brand-red-bg); border-color: var(--brand-red); }

/* Danger solid — red fill (modifier or .btn-user-action.danger) */
.btn-danger.solid,
.btn-user-action.danger,
.btn-danger.solid:hover,
.btn-user-action.danger:hover {
  background: var(--brand-red);
  color: #fff;
  border-color: var(--brand-red);
}
.btn-user-action.danger { color: var(--brand-red); background: none; border-color: var(--brand-border); }
.btn-user-action.danger:hover { background: var(--brand-red-bg); border-color: var(--brand-red); }

/* Gold CTA */
.btn-gold {
  background: var(--brand-accent);
  color: var(--brand-text-on-accent, var(--brand-primary));
  border: none;
  padding: 8px 18px;
  border-radius: 6px;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  font-family: inherit;
  transition: opacity 0.15s, transform 0.05s ease-out;
  display: inline-block;
  text-decoration: none;
}
.btn-gold:hover { opacity: 0.88; }

/* Size modifiers */
.btn-sm { padding: 3px 10px; font-size: 0.75rem; }
.btn-lg { padding: 11px 24px; font-size: 0.95rem; }

/* Mobile tap targets — iOS minimum is 44x44px. Desktop keeps compact look. */
@media (max-width: 600px) {
  /* Universal catch-all: any <button> is a tap target. Covers page-specific
     custom classes (.btn-nav, .filter-pill, etc.)
     that don't use the canonical .btn-* names. */
  button, input[type="button"], input[type="submit"], input[type="reset"] {
    min-height: 44px;
  }
  /* Canonical classes — explicit padding bump for breathing room */
  [class*="btn-"],
  .btn-primary, .btn-secondary, .btn-ghost, .btn-danger, .btn-gold,
  .btn-user-add, .btn-save, .btn-add, .btn-modal-submit, .btn-send-memo,
  .btn-modal-cancel, .btn-user-action, .btn-user-edit, .btn-user-delete {
    min-height: 44px;
    padding-top: 10px;
    padding-bottom: 10px;
  }
  /* .btn-sm used to keep 36px compact on mobile — Heath asked for full 44 everywhere */
  .btn-sm { min-height: 44px; padding-top: 8px; padding-bottom: 8px; }
  .btn-lg { min-height: 48px; }
  .wc-input, .wc-select, input[type="text"], input[type="email"],
  input[type="tel"], input[type="number"], input[type="password"],
  input[type="search"], input[type="date"], input[type="time"],
  textarea, select { min-height: 44px; }
  .wc-tab { min-height: 44px; }
  .wc-pill, .filter-pill { min-height: 44px; padding-top: 10px; padding-bottom: 10px; }
  .filter-tab, .picker-tab, .lp-chip { min-height: 44px; padding-top: 10px; padding-bottom: 10px; }
  .num-stepper .stepper-btn { min-width: 44px; min-height: 44px; }
  /* Pagination buttons — currently 32x44, bump width to meet iOS minimum */
  .wp-btn { min-width: 44px; padding-left: 10px; padding-right: 10px; }
  /* Close/× and small nav/icon buttons (cover the common patterns across pages) */
  button[class*="-close"],
  button.pn-x, button.btn-close-panel, button.iw-panel-close,
  button.blast-panel-close, button.init-panel-close, button.dqf-panel-close,
  button.manual-app-close, button.slideout-close, button.panel-close,
  button.dp-close, button.drawer-close-btn,
  button.btn-nav, button.date-nav-btn,
  button.itin-add-btn, button.itin-delete-btn {
    min-width: 44px; min-height: 44px;
  }
  /* Form checkboxes/radios — iOS minimum visual size */
  input[type="checkbox"], input[type="radio"] { width: 22px; height: 22px; }
  /* Clickable list alert cards (management) + collapsible group headers
     (trip-calculator) — nudge up 2-3px to clear 44 */
  .alert-item, .cost-group-header { min-height: 44px; }
  /* Collapsible section headers (trip-calculator street view, etc.) */
  .sv-header { min-height: 44px; padding-top: 12px; padding-bottom: 12px; }
  /* Back-arrow page links */
  .back-btn { min-height: 44px; display: inline-flex; align-items: center; }
  /* Wrapping labels that contain a radio/checkbox — the label IS the tap target */
  label.blast-cat, label.role-card, label.consent-label,
  label[class*="-option"], label[class*="-choice"] { min-height: 44px; display: inline-flex; align-items: center; }
  /* .lp-chip is already in the filter-tab rule above, but extra selector for icon-only active state */
  .lp-chip { min-width: 44px; }

  /* ── iOS zoom-on-focus fix ──
     iOS Safari auto-zooms the viewport whenever an input is focused at
     font-size < 16px, and frequently doesn't zoom back out on blur.
     Force 16px on every typed input on mobile. !important is intentional —
     this is enforcing a platform requirement, not a design preference, and
     it needs to beat any page-level inline font-size:13px/0.82rem. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="range"]):not([type="file"]),
  select, textarea { font-size: 16px !important; }

  /* ── Grid/flex overflow fix ──
     <input> has an implicit min-width that forces grid columns wider than
     their container. This is what made Customer Info (trip-calculator) and
     other 2-col forms overflow on 390px. Clamp it. */
  input, select, textarea { min-width: 0; }
}

/* Universal disabled state */
[class*="btn-"]:disabled,
[class*="btn-"][aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

/* ── 5. FORM ELEMENTS ── */
.wc-field { margin-bottom: 14px; }

.wc-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  margin-bottom: 5px;
  color: var(--brand-text);
}

.wc-input,
.wc-field input[type="text"],
.wc-field input[type="email"],
.wc-field input[type="tel"],
.wc-field input[type="number"],
.wc-field input[type="url"],
.wc-field input[type="date"],
.wc-field input[type="time"],
.wc-field select {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--brand-border);
  border-radius: 6px;
  font-size: 0.88rem;
  font-family: inherit;
  background: var(--brand-white);
  color: var(--brand-text);
  transition: border-color 0.15s;
}
.wc-input:focus,
.wc-field input:focus,
.wc-field select:focus {
  outline: none;
  border-color: var(--brand-accent);
}

.wc-textarea,
.wc-field textarea {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--brand-border);
  border-radius: 6px;
  font-size: 0.88rem;
  font-family: inherit;
  background: var(--brand-white);
  color: var(--brand-text);
  resize: vertical;
  min-height: 80px;
  line-height: 1.5;
}
.wc-textarea:focus, .wc-field textarea:focus {
  outline: none;
  border-color: var(--brand-accent);
}

.wc-select {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--brand-border);
  border-radius: 6px;
  font-size: 0.88rem;
  font-family: inherit;
  background: var(--brand-white);
  color: var(--brand-text);
  cursor: pointer;
}
.wc-select:focus { outline: none; border-color: var(--brand-accent); }

/* ════════════════════════════════════════════════════════════════════════
   STYLED SELECT — "Elevated" (site-wide dropdown restyle, 2026-05-28)
   Replaces the native browser <select> arrow (boxy/inconsistent across browsers,
   ugly in Firefox) with a custom chevron + soft elevation.

   The chevron longhands carry !important ON PURPOSE: several pages set their
   select bg with a `background:` SHORTHAND at higher specificity (e.g.
   `.wo-toolbar .filter-select { background: var(--fm-input-bg) }`, 0,2,0). Without
   !important that shorthand resets background-repeat to `repeat`, tiling the
   chevron into a zigzag (the bug from the first attempt). !important on just the
   chevron properties lets the design system win that one concern while the page's
   theme background-COLOR (also from its shorthand, non-important) is preserved.

   Theme-aware: fleet-maintenance ships <body class="theme-dark"> (always dark),
   so .theme-dark swaps to a light chevron + dark-adaptive fill. Light admin pages
   (no .theme-dark) get the navy chevron. Dark driver/mechanic apps load
   app-glass.css and keep their own select styling — unaffected.
   Verified on the live authed pages (crm light + fleet dark) before shipping.
   ════════════════════════════════════════════════════════════════════════ */
select,
.wc-select,
.wc-field select,
.modal-field select,
select.form-select,
select.filter-select,
select.cell-select {
  -webkit-appearance: none !important;
  -moz-appearance: none !important;
  appearance: none !important;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%231a2744' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 11px center !important;
  background-size: 12px !important;
  padding-right: 32px !important;
}
/* Elevated visual: bare/canonical/field/modal selects (white fill, hairline
   border, soft shadow). Theme-aware classed selects keep their own bg + border. */
select,
.wc-select,
.wc-field select,
.modal-field select {
  border: 1px solid #e4e8ee;
  border-radius: 8px;
  background-color: var(--brand-white);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
  transition: border-color 0.14s ease, box-shadow 0.14s ease;
}
select:hover,
.wc-select:hover,
.wc-field select:hover,
.modal-field select:hover {
  border-color: #cdd4dd;
  box-shadow: 0 2px 5px rgba(15, 23, 42, 0.09);
}
select:focus,
.wc-select:focus,
.wc-field select:focus,
.modal-field select:focus,
select.form-select:focus,
select.filter-select:focus,
select.cell-select:focus {
  outline: none;
  border-color: var(--brand-primary);
  box-shadow: 0 0 0 3px rgba(26, 39, 68, 0.12);
}
/* Dark theme (body.theme-dark — e.g. fleet-maintenance): light chevron + dark-
   adaptive fill for bare/canonical (classed selects keep their theme bg). */
.theme-dark select,
.theme-dark .wc-select,
.theme-dark .wc-field select,
.theme-dark .modal-field select,
.theme-dark select.form-select,
.theme-dark select.filter-select,
.theme-dark select.cell-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23c9d2de' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
}
.theme-dark select,
.theme-dark .wc-select,
.theme-dark .wc-field select,
.theme-dark .modal-field select {
  background-color: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.16);
  color: inherit;
}
.theme-dark select:focus,
.theme-dark .wc-select:focus,
.theme-dark select.form-select:focus,
.theme-dark select.filter-select:focus,
.theme-dark select.cell-select:focus {
  border-color: #6b7a92;
  box-shadow: 0 0 0 3px rgba(150, 170, 200, 0.22);
}

/* ── 6. MODAL ── */
/* Canonical: .wc-overlay / .wc-modal; Aliases: .modal-overlay / .modal
   Pages that need a custom centering model (e.g. absolute + translate, like
   crm.html) override these locally — opacity-based open/close still works
   either way as long as the .open class is the toggle. */
.wc-overlay,
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.45);
  z-index: var(--brand-z-modal-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms cubic-bezier(0.215,0.61,0.355,1);
}
.wc-overlay.open,
.modal-overlay.open {
  opacity: 1;
  pointer-events: auto;
}

.wc-modal,
.modal {
  background: var(--brand-white);
  border-radius: 10px;
  padding: 28px;
  width: 440px;
  max-width: 95vw;
  max-height: min(90dvh, 860px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
  box-shadow: 0 20px 60px rgba(0,0,0,0.2);
  opacity: 0;
  transform: scale(0.96);
  transition: opacity 180ms cubic-bezier(0.215,0.61,0.355,1),
              transform 180ms cubic-bezier(0.215,0.61,0.355,1);
}
.wc-overlay.open .wc-modal,
.wc-overlay.open .modal,
.modal-overlay.open .wc-modal,
.modal-overlay.open .modal {
  opacity: 1;
  transform: scale(1);
}
/* Pin the title — stays visible while the body scrolls */
.wc-modal > h3,
.modal > h3 {
  position: sticky;
  top: -28px;
  margin: -28px -28px 16px;
  padding: 24px 28px 12px;
  background: var(--brand-white);
  z-index: 2;
  font-size: 1.1rem;
}

/* Modal field — label + input row */
.modal-field {
  margin-bottom: 14px;
}
.modal-field label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  margin-bottom: 5px;
  color: var(--brand-text);
}
.modal-field input,
.modal-field select,
.modal-field textarea {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid var(--brand-border);
  border-radius: 6px;
  font-size: 0.88rem;
  font-family: inherit;
  background: var(--brand-white);
  color: var(--brand-text);
  box-sizing: border-box;
}
.modal-field textarea {
  resize: vertical;
  line-height: 1.45;
  min-height: 64px;
}
/* Inline checkbox + label — when a .modal-field label wraps a checkbox,
   treat it as an inline-flex row so the box and its caption read as one
   unit instead of a block label sitting above a 100%-width input. */
.modal-field label:has(> input[type="checkbox"]) {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 0;
  cursor: pointer;
  font-weight: 500;
}
.modal-field label:has(> input[type="checkbox"]) > input[type="checkbox"] {
  width: auto;
  padding: 0;
  margin: 0;
  flex: 0 0 auto;
}

.modal-field input:focus,
.modal-field select:focus,
.modal-field textarea:focus {
  outline: none;
  border-color: var(--brand-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-accent) 18%, transparent);
}
.modal-field-hint {
  display: block;
  font-size: 0.74rem;
  color: var(--brand-muted);
  margin-top: 4px;
  line-height: 1.4;
}

/* Modal actions row — sticky-pinned to the modal's bottom edge so Save is
   always reachable on tall forms without scrolling. */
.wc-modal > .wc-modal-actions,
.wc-modal > .modal-actions,
.modal > .wc-modal-actions,
.modal > .modal-actions {
  position: sticky;
  bottom: -28px;
  margin: 20px -28px -28px;
  padding: 14px 28px;
  background: var(--brand-white);
  border-top: 1px solid var(--brand-border);
  z-index: 2;
}
.wc-modal-actions,
.modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 20px;
}

/* ── 7. TABLE ── */
/* Canonical: .wc-table; Alias: .user-table (base styles only) */
.wc-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}
.wc-table th {
  text-align: left;
  padding: 10px 16px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--brand-muted);
  background: var(--brand-light);
  border-bottom: 1px solid var(--brand-border);
  white-space: nowrap;
}
.wc-table td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--brand-border);
  vertical-align: middle;
}
.wc-table tr:last-child td { border-bottom: none; }
/* Mobile wrapper — every data table should be inside <div class="wc-table-scroll">
   so columns that exceed viewport width scroll horizontally instead of clipping. */
.wc-table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.wc-table-scroll > .wc-table { min-width: max-content; }

/* ── List end-cap (wc-list-end) ───────────────────────────────────
   Terminal "you've reached the end" cue for long scrolling lists and
   tables. Solves two problems at once: (1) a clear end-of-list signal
   so the last item isn't ambiguous/forgettable, and (2) generous bottom
   padding so the final row clears the viewport edge and any floating UI
   (help bubble / FAB). Opt-in — append after a list, or as the last
   table row:
     <div class="wc-list-end">End of list · 90 items</div>
     <tr class="wc-list-end-row"><td colspan="N"><div class="wc-list-end">…</div></td></tr>
   Empty text auto-hides. Light-theme tokens; dark (app-glass) pages need
   their own muted/border colors. First shipped: Daily Schedule, 2026-05-28. */
.wc-list-end {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 16px 16px 96px;
  color: var(--brand-muted);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  user-select: none;
}
.wc-list-end::before,
.wc-list-end::after {
  content: "";
  height: 1px;
  width: 32px;
  background: var(--brand-border);
}
.wc-list-end:empty { display: none; }
/* Table variant: strip cell chrome so the cue reads as a footer, not a data row */
.wc-list-end-row td,
.wc-list-end-row:hover td { border: none !important; background: none !important; padding: 0 !important; }

/* Wrap-friendly modifier — opt-in for tables where multi-line cells are
   acceptable and horizontal scroll is undesirable (e.g. user-assignment
   matrices with comma-separated tag lists). Lifts the min-width:max-content
   override and lets cells wrap naturally on word boundaries. */
.wc-table-scroll > .wc-table.wc-table-wrap { min-width: 0; }
.wc-table.wc-table-wrap td {
  white-space: normal;
  word-break: break-word;
  vertical-align: top;
}
/* Small inline tag chip — used inside .wc-table-wrap cells to render
   comma-separated lists (operating companies, depots, etc.) as a
   wrap-friendly cluster instead of a long unbroken string. */
.wc-tag-cluster {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.wc-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  font-size: 0.78rem;
  font-weight: 500;
  background: var(--brand-light, #f4f5f7);
  color: var(--brand-text);
  border: 1px solid var(--brand-border);
  border-radius: 999px;
  line-height: 1.4;
  white-space: nowrap;
}
.wc-tag.wc-tag-primary {
  background: color-mix(in srgb, var(--brand-accent) 14%, transparent);
  border-color: color-mix(in srgb, var(--brand-accent) 32%, transparent);
}
.wc-tag-empty {
  font-size: 0.78rem;
  color: var(--brand-muted);
  font-style: italic;
}

/* Half-window safety net: at narrow widths (≤1100px), any non-canonical
   container that wraps a <table> gets horizontal scroll so wide tables
   don't blow past the viewport. Scoped to narrow widths to avoid disturbing
   full-width layouts that intentionally use overflow:hidden for rounded
   corners or sticky positioning. !important is intentional — many per-page
   wrappers set overflow:hidden for border-radius corner clipping; we need
   to win at narrow widths regardless. */
@media (max-width: 1100px) {
  :where(div, section, article, main):has(> table):not(.wc-table-scroll) {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch;
    max-width: 100%;
  }
}
.wc-table tbody tr:hover td { background: var(--brand-hover); }

/* ── 8. CARD ── */
.wc-card {
  background: var(--brand-white);
  border: 1px solid var(--brand-border);
  border-radius: 10px;
  padding: 20px 24px;
}

/* ── 9. BADGES ── */
.wc-badge {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 4px;
  line-height: 1;
  vertical-align: middle;
}
.wc-badge-green  { background: #dcfce7; color: #166534; }
.wc-badge-red    { background: var(--brand-red-bg); color: #991b1b; }
.wc-badge-yellow { background: var(--brand-yellow-bg); color: #854d0e; }
.wc-badge-blue   { background: var(--brand-blue-bg); color: #1e40af; }
.wc-badge-navy   { background: var(--brand-primary); color: var(--brand-text-on-primary, #fff); }
.wc-badge-muted  { background: var(--brand-light); color: var(--brand-muted); }
.wc-badge-orange { background: #fff7ed; color: #9a3412; }
.wc-badge-gold   { background: #fef3c7; color: #78350f; }
.wc-badge-purple { background: #ede9fe; color: #5b21b6; }

/* ── 10. PILLS ── */
.wc-pill-group { display: flex; flex-wrap: wrap; gap: 8px; }

.wc-pill {
  display: inline-block;
  padding: 5px 14px;
  border-radius: 20px;
  border: 1px solid var(--brand-border);
  background: var(--brand-white);
  color: var(--brand-muted);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
	  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  user-select: none;
}
.wc-pill:hover { border-color: var(--brand-accent); color: var(--brand-text); }
.wc-pill.active {
  background: var(--brand-primary);
  color: var(--brand-text-on-primary, #fff);
  border-color: var(--brand-primary);
}

/* ── 11. TABS ── */
.wc-tabs {
  display: flex;
  gap: 0;
  background: var(--brand-white);
  border: 1px solid var(--brand-border);
  border-radius: 8px 8px 0 0;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.wc-tabs::-webkit-scrollbar { display: none; }

/* Horizontal tab strips scroll on overflow but must never show the native
   grey scrollbar (it reads as a broken UI element under the tabs). Same
   treatment as .wc-tabs above — scroll kept, bar hidden, every browser. */
.tabbar, .vd-tabs {
  scrollbar-width: none;        /* Firefox */
  -ms-overflow-style: none;     /* IE / old Edge */
}
.tabbar::-webkit-scrollbar, .vd-tabs::-webkit-scrollbar { display: none; }  /* WebKit / Chrome / Safari */

.wc-tab {
  background: none;
  border: none;
  color: var(--brand-muted);
  font-size: 13px;
  font-weight: 600;
  padding: 12px 16px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  transition: color 0.15s, border-color 0.15s;
  font-family: inherit;
  flex-shrink: 0;
}
.wc-tab:hover { color: var(--brand-text); }
.wc-tab.active {
  color: var(--brand-primary);
  border-bottom-color: var(--brand-accent);
}

/* ── 12. EMPTY STATE ── */
.wc-empty,
.empty-section {
  padding: 40px 20px;
  text-align: center;
  color: var(--brand-muted);
  font-size: 0.9rem;
}

/* ── 12b. SKELETON LOADERS ── */
/* Drop-in placeholder shown while a section's data is still loading.
   Usage: <div class="wc-skel wc-skel-line"></div>
          <div class="wc-skel wc-skel-card"></div>
   Each element animates its own shimmer; grouping isn't required. */
.wc-skel {
  position: relative;
  overflow: hidden;
  background: #eef1f4;
  border-radius: 6px;
}
.wc-skel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255,255,255,0.55) 50%,
    transparent 100%
  );
  transform: translateX(-100%);
  animation: wc-skel-shimmer 1.2s ease-in-out infinite;
}
.wc-skel-line { height: 12px; margin: 6px 0; }
.wc-skel-line.sm { height: 10px; width: 60%; }
.wc-skel-line.lg { height: 18px; width: 40%; }
.wc-skel-card {
  height: 72px;
  margin: 8px 0;
  border: 1px solid var(--brand-border);
}
.wc-skel-stat {
  height: 84px;
  border: 1px solid var(--brand-border);
}
.wc-skel-row {
  height: 44px;
  border-bottom: 1px solid var(--brand-border);
  background: transparent;
}
.wc-skel-row::after {
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(0,0,0,0.04) 50%,
    transparent 100%
  );
}
@keyframes wc-skel-shimmer {
  to { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .wc-skel::after { animation: none; opacity: 0.4; transform: none; }
}

/* ── 12c. SPINNER (rod-and-ball star) ── */
/*
 * Inline busy indicator. Eight glossy rod-and-ball spokes from a white
 * center, alternating two colors. Whole arrangement rotates.
 *
 * COLORS — driven by CSS custom properties so the spinner auto-themes
 * to the active tenant's brand:
 *
 *   --spin-rod-a → cardinals (N, E, S, W)   defaults to var(--brand-primary)
 *   --spin-rod-b → diagonals (NE, SE, SW, NW) defaults to var(--brand-accent)
 *
 * For Werner (brand-primary=navy, brand-accent=gold) this naturally renders
 * as the official "W1 Werner Classic" scheme. For other tenants, it auto-
 * themes to their primary+accent. To force a specific palette regardless of
 * tenant brand, add one of the .scheme-* override classes (see below).
 *
 * MARKUP:
 *   <svg class="wc-spinner" viewBox="-50 -50 100 100" aria-hidden="true">
 *     <line class="rod-arm rod-a" x1="0" y1="0" x2="0"   y2="-32"/> ...8 lines
 *     <circle class="rod-ball rod-a" cx="0" cy="-32" r="6"/>       ...8 circles
 *     <circle class="rod-center" cx="0" cy="0" r="9"/>
 *   </svg>
 *
 * SIZES — default 18px (inline). Add .wc-spinner-lg for 44px badge,
 * or set inline width/height for any custom size. SVG viewBox handles
 * scaling — internal proportions stay correct at every size.
 */
.wc-spinner {
  /* Default colors — override via .scheme-* class or per-tenant CSS */
  --spin-rod-a: var(--brand-primary, #0B1D3A);
  --spin-rod-b: var(--brand-accent, #C6973F);

  display: inline-block;
  width: 18px;
  height: 18px;
  flex: none;
  animation: wc-spinner-rotate 1.5s linear infinite;
  transform-origin: center;
}
.wc-spinner-lg { width: 44px; height: 44px; }

.wc-spinner .rod-arm    { stroke-linecap: round; stroke-width: 6; fill: none; }
.wc-spinner .rod-ball   { stroke: rgba(0,0,0,.15); stroke-width: 0.5; }
.wc-spinner .rod-center { fill: #fff; stroke: rgba(0,0,0,.2); stroke-width: 0.5; }
.wc-spinner .rod-a      { stroke: var(--spin-rod-a); fill: var(--spin-rod-a); }
.wc-spinner .rod-b      { stroke: var(--spin-rod-b); fill: var(--spin-rod-b); }

/* ── Scheme overrides — saved palettes for tenants whose brand
 *    doesn't naturally fit the rod-and-ball ──
 *
 *   .scheme-werner  Werner Classic (navy + gold)        explicit/locked
 *   .scheme-tech    Cool Tech (cyan + magenta)          vibrant SaaS
 *   .scheme-earth   Earth Tones (sage + terracotta)     warm/organic
 *   .scheme-mono    Monochrome Premium (charcoal+silver) sophisticated
 *   .scheme-multi   Vibrant Multi (teal + orange)       playful original
 *
 * Werner does NOT need .scheme-werner — the default already produces it
 * because Werner's brand-primary/accent are navy/gold.
 */
.wc-spinner.scheme-werner { --spin-rod-a: #0B1D3A; --spin-rod-b: #C6973F; }
.wc-spinner.scheme-tech   { --spin-rod-a: #00bcd4; --spin-rod-b: #e91e63; }
.wc-spinner.scheme-earth  { --spin-rod-a: #6b8e6b; --spin-rod-b: #c66a3d; }
.wc-spinner.scheme-mono   { --spin-rod-a: #36404a; --spin-rod-b: #b0b8c0; }
.wc-spinner.scheme-multi  { --spin-rod-a: #1d6c8a; --spin-rod-b: #e8742a; }

/* ── Dark glass surfaces (driver/mechanic pages) ──
 * Brand-primary is typically dark (navy/black) which would disappear
 * against the dark glass backdrop. Lift the rod-a color so geometry
 * stays visible. Defaults swap to accent + white; named schemes that
 * are already light-on-dark (tech, earth, multi) don't need
 * adjustment. Werner-classic and mono get explicit lifts. */
.glass .wc-spinner,
.app-glass .wc-spinner {
  --spin-rod-a: var(--brand-accent, #d4a953);
  --spin-rod-b: #ffffff;
}
.glass .wc-spinner.scheme-werner,
.app-glass .wc-spinner.scheme-werner {
  --spin-rod-a: #6694d8;
  --spin-rod-b: #d4a953;
}
.glass .wc-spinner.scheme-mono,
.app-glass .wc-spinner.scheme-mono {
  --spin-rod-a: #b0b8c0;
  --spin-rod-b: #ffffff;
}

@keyframes wc-spinner-rotate { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .wc-spinner { animation: none; }
}

/* ── LOADING OVERLAY (appLoading.show / hide) ── */
.app-loading-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.18s ease, visibility 0s linear 0.18s;
}
.app-loading-overlay.app-loading-visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.18s ease, visibility 0s linear 0s;
}
.app-loading-card {
  background: var(--brand-surface, #fff);
  color: var(--brand-text, #1a2744);
  border-radius: 14px;
  padding: 32px 40px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.35), 0 4px 12px rgba(0,0,0,0.2);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  min-width: 280px;
  max-width: 420px;
  text-align: center;
  transform: scale(0.96);
  transition: transform 0.18s ease;
}
.app-loading-overlay.app-loading-visible .app-loading-card {
  transform: scale(1);
}
.app-loading-card .wc-spinner-lg { width: 56px; height: 56px; }
.app-loading-msg {
  font-size: 1rem;
  font-weight: 600;
  color: var(--brand-text, #1a2744);
  line-height: 1.4;
}
.app-loading-sub {
  font-size: 0.85rem;
  color: var(--brand-muted, #6b7280);
  line-height: 1.4;
  margin-top: -6px;
}
@media (max-width: 600px) {
  .app-loading-card { padding: 24px 28px; min-width: 0; width: 100%; max-width: 360px; }
  .app-loading-msg { font-size: 0.95rem; }
}

/* ── 12d. SAVE FLASH ──
   Pulse-back acknowledgement for inline saves. Add .saved on success,
   remove ~600ms later (or use appUtils.flashSaved(el) which handles
   the timing). Works on any inline/block element. */
.save-flash {
  border-radius: 4px;
  transition: background-color 220ms cubic-bezier(0.215,0.61,0.355,1);
}
.save-flash.saved {
  background-color: rgba(45,155,90,0.16);
}

/* ── 12e. REDUCED MOTION (site-wide) ──
   Flatten every animation/transition when the OS-level Reduce Motion
   preference is on. Individual sections may still scope their own
   rules; this is the universal safety net. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── 13. TOAST ── */
.toast-container {
  position: fixed;
  bottom: max(20px, env(safe-area-inset-bottom));
  right: max(20px, env(safe-area-inset-right));
  left: max(0px, env(safe-area-inset-left));
  z-index: var(--brand-z-toast);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
}
.toast-container > .toast { pointer-events: auto; }
.toast {
  background: var(--brand-primary);
  color: var(--brand-text-on-primary, #fff);
  padding: 12px 20px;
  border-radius: 8px;
  font-size: 0.85rem;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  animation: wc-slide-in 200ms cubic-bezier(0.215,0.61,0.355,1) both;
  max-width: 350px;
}
.toast.success { background: #166534; }
.toast.error   { background: #991b1b; }
.toast.warning { background: #854d0e; }
.toast.leaving { animation: wc-slide-out 160ms cubic-bezier(0.215,0.61,0.355,1) forwards; }

@keyframes wc-slide-in {
  from { transform: translateX(100px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}
@keyframes wc-slide-out {
  from { transform: none; opacity: 1; }
  to   { transform: translateY(8px); opacity: 0; }
}
/* Keep old keyframe name for pages that reference it directly */
@keyframes slideIn {
  from { transform: translateX(100px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .toast, .toast.leaving { animation: none; }
}

/* ── 13. NUMBER STEPPER ── */
/* Hide native spinners site-wide */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
input[type="number"] { -moz-appearance: textfield; }

/* Custom +/− stepper wrapper */
.num-stepper {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid var(--brand-border);
  border-radius: 6px;
  overflow: hidden;
  background: var(--brand-white);
  height: 38px;
}
.num-stepper .stepper-btn {
  width: 38px;
  background: var(--brand-light);
  border: none;
  color: var(--brand-text);
  font-size: 1.2rem;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, color 0.15s;
  user-select: none;
  -webkit-user-select: none;
  flex-shrink: 0;
}
.num-stepper .stepper-btn:hover { background: var(--brand-primary); color: var(--brand-text-on-primary, var(--brand-white)); }
.num-stepper .stepper-btn:active { background: #0f1a30; color: var(--brand-white); }
.num-stepper input[type="number"] {
  border: none;
  border-left: 1px solid var(--brand-border);
  border-right: 1px solid var(--brand-border);
  background: var(--brand-white);
  color: var(--brand-text);
  text-align: center;
  font-size: 0.92rem;
  font-family: inherit;
  font-variant-numeric: tabular-nums;
  padding: 0 4px;
  outline: none;
}
.num-stepper input[type="number"]:focus { background: var(--brand-blue-bg); }
.num-stepper.wide input[type="number"] { width: 80px; }
.num-stepper.narrow input[type="number"] { width: 54px; }

/* Digit-count input widths. Pick the smallest one that fits the max
   realistic value — gallons (3), quarts (3 incl. ".5"), odometer (6).
   These are independent of .wide / .narrow (which control button size
   and overall stepper height): combine .wide.digits-6 for tablet-sized
   tap targets with a 6-digit input, or .narrow.digits-3 for a compact
   inline qty field. flex:0 0 width pins the input width so a parent
   .wide override that uses flex:1 doesn't stretch it back to 100%. */
.num-stepper.digits-1 input[type="number"] { width: 40px;  flex: 0 0 40px;  }
.num-stepper.digits-2 input[type="number"] { width: 52px;  flex: 0 0 52px;  }
.num-stepper.digits-3 input[type="number"] { width: 64px;  flex: 0 0 64px;  }
.num-stepper.digits-4 input[type="number"] { width: 80px;  flex: 0 0 80px;  }
.num-stepper.digits-5 input[type="number"] { width: 96px;  flex: 0 0 96px;  }
.num-stepper.digits-6 input[type="number"] { width: 112px; flex: 0 0 112px; }
.num-stepper.digits-7 input[type="number"] { width: 128px; flex: 0 0 128px; }

/* Dark-theme baseline for steppers. Pages with class="theme-dark" on
   <body> get sensible dark colors automatically; they can still override
   with their own --fm-* / --ck-* tokens for tighter brand alignment. */
.theme-dark .num-stepper {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.14);
}
.theme-dark .num-stepper input[type="number"] {
  background: rgba(255,255,255,0.04);
  border-color: rgba(255,255,255,0.14);
  color: rgba(255,255,255,0.92);
}
.theme-dark .num-stepper input[type="number"]:focus {
  background: rgba(255,255,255,0.06);
}
.theme-dark .num-stepper .stepper-btn {
  background: rgba(255,255,255,0.06);
  color: rgba(255,255,255,0.92);
}
.theme-dark .num-stepper .stepper-btn:hover {
  background: var(--brand-accent);
  color: var(--brand-primary);
}
.theme-dark .num-stepper .stepper-btn:active {
  background: var(--brand-accent);
  color: var(--brand-primary);
  filter: brightness(0.9);
}

/* ── 14. NATIVE DATE / TIME PICKERS ──
   Tenant- and theme-aware styling for every native date/time/month/week
   input site-wide. No opt-in needed — applies wherever a native picker
   is used. Two CSS variables control color so light and dark surfaces
   adapt without per-page CSS:
     --wc-picker-glyph  : color of the calendar/clock indicator icon
     --wc-picker-scheme : color-scheme for the native popup (light/dark)
   The glyph SVG is masked, so background-color paints through it — that
   means each tenant's --brand-* tokens automatically theme the icon
   without us editing the SVG. */
:root {
  --wc-picker-glyph: var(--brand-primary);
  --wc-picker-scheme: light;
}

input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"],
input[type="week"] {
  color-scheme: var(--wc-picker-scheme);
}

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator,
input[type="month"]::-webkit-calendar-picker-indicator,
input[type="week"]::-webkit-calendar-picker-indicator {
  background-image: none;
  background-color: var(--wc-picker-glyph);
  -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'/%3E%3Cline x1='16' y1='2' x2='16' y2='6'/%3E%3Cline x1='8' y1='2' x2='8' y2='6'/%3E%3Cline x1='3' y1='10' x2='21' y2='10'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;
          mask-size: contain;
  filter: none;
  cursor: pointer;
  width: 22px;
  height: 22px;
  padding: 0;
  opacity: 1;
  transition: opacity 0.15s;
}
input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="time"]::-webkit-calendar-picker-indicator:hover,
input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover,
input[type="month"]::-webkit-calendar-picker-indicator:hover,
input[type="week"]::-webkit-calendar-picker-indicator:hover {
  opacity: 0.75;
}

/* Dark surfaces opt in by setting these two variables on a wrapper or
   <body>. Pages that should render with the dark popup + accent-color
   glyph add class="theme-dark" to <body>. */
.theme-dark {
  --wc-picker-glyph: var(--brand-accent);
  --wc-picker-scheme: dark;
}

/* ── Text — no clipping ──
   Project rule: never truncate text vertically or horizontally. Size
   containers (columns, cards, modals) to fit the longest real content
   and let text wrap naturally. Do NOT add -webkit-line-clamp, and do
   NOT use text-overflow:ellipsis in admin pages.
   The .truncate utility below is retained only for internal topbar/menu
   labels where horizontal scroll would break layout — do not apply it
   to business data (company names, trip details, user-entered text). */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Surcharge badges ──
   Shared chip for the three pricing_surcharges types. Used by
   trip-calculator.html (per-trip evaluation) and calendar.html (per-day
   active rules). Active = solid pastel + checkmark; inactive = white +
   dashed border + plus sign. */
.surcharge-badges {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.surcharge-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: 20px; font-size: 12px;
  font-weight: 700; font-family: 'JetBrains Mono', monospace;
	  border: 1.5px solid transparent; transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.surcharge-badge.calendar    { background: #FEF3C7; color: #92400E; border-color: #B45309; }
.surcharge-badge.day_of_week { background: #DBEAFE; color: #1E40AF; border-color: #1E40AF; }
.surcharge-badge.utilization { background: #FCE7F3; color: #9D174D; border-color: #9D174D; }
.surcharge-badge::before {
  content: '\2713'; font-weight: 800; font-size: 11px; opacity: 0.85;
}
.surcharge-badge.is-inactive {
  background: #fff; border-style: dashed; font-weight: 600; cursor: pointer;
}
.surcharge-badge.is-inactive::before { content: '+'; opacity: 1; }
.surcharge-badge.is-inactive.calendar    { color: #B45309; border-color: #FCD34D; }
.surcharge-badge.is-inactive.day_of_week { color: #1E40AF; border-color: #93C5FD; }
.surcharge-badge.is-inactive.utilization { color: #9D174D; border-color: #F9A8D4; }
.surcharge-badge.is-inactive:hover {
  border-style: solid; transform: translateY(-1px);
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}
.surcharge-badge.is-inactive.calendar:hover    { background: #FEF3C7; }
.surcharge-badge.is-inactive.day_of_week:hover { background: #DBEAFE; }
.surcharge-badge.is-inactive.utilization:hover { background: #FCE7F3; }
.surcharge-badge .badge-x {
  cursor: pointer; opacity: 0.55; margin-left: 1px; font-size: 14px; line-height: 1;
}
.surcharge-badge .badge-x:hover { opacity: 1; }
/* Compact pct-vs-flat suffix used inside the badge text */
.surcharge-badge .badge-kind { font-size: 10px; opacity: 0.7; font-weight: 600; }
