:root {
  --bg: #f4f4f5;            /* neutral grey — used behind the photo fallback */
  --bg-page: #eceef1;       /* light grey page bg for internal pages (not white) */
  --card: #ffffff;
  --ink: #1f2733;
  /* Grey for labels / secondary text. #5d6470 (was #6b7280): the old grey was
     4.16:1 on the grey page background, under WCAG AA's 4.5:1; this is 5.13:1,
     and still 4.72:1 under the SafConnect watermark at its 5% ceiling. */
  --muted: #5d6470;
  --accent: #8B1E2D;        /* Safgri red — primary accent, app-wide */
  --accent-dark: #731825;   /* hover/darken */
  --border: #e3e6ea;        /* grey borders */
  --ok: #1f9d55;
  --bad: #d64545;
  /* Aliases kept for the login page and any explicit brand use. */
  --safgri-red: #8B1E2D;
  --safgri-red-dark: #731825;
  /* Unified button system — one shape/size across all three variants. */
  --btn-radius: 8px;
  --btn-pad: 0.55rem 0.95rem;
  --btn-font: 0.92rem;
  --safgri-red-tint: #f7e4e6;   /* secondary hover fill */
  --danger-bg: #fdeaea;         /* destructive fill (muted pink) */
  --danger-fg: #a01f2b;         /* destructive text (darker red) */
  --danger-border: #eebcbc;
  /* ---- Type scale — one size per role (see typography audit). Phase 1 wires the
     headings; --fs-meta/--fs-micro land in phase 2, --fs-body (opt-in for
     currently-unstyled text) in phase 3. ---- */
  --fs-page-title: 1.5rem;    /* page <h1> */
  --fs-section:    1.1rem;    /* section headings ("Recent slips", "Diesel Overview") */
  --fs-card-title: 1.05rem;   /* card / row titles */
  --fs-body:       0.95rem;   /* opt-in size for currently-unstyled content (phase 3) */
  --fs-meta:       0.82rem;   /* labels, captions, timestamps (phase 2) */
  --fs-micro:      0.72rem;   /* badges, pills (phase 2) */
  --fs-eyebrow:    0.78rem;   /* checklist category eyebrow — a distinct role, kept */
  /* ---- Elevation scale (see shadow/elevation audit). Level 0 = flat (no shadow).
     One value per level so look-alike surfaces lift by the same amount;
     --elev-2-accent is the single consolidated brand-red hover tint. ---- */
  --elev-1: 0 1px 2px rgba(31, 39, 51, 0.06);           /* resting cards / rows */
  --elev-2: 0 4px 12px rgba(31, 39, 51, 0.12);          /* interactive / hover (neutral) */
  --elev-2-accent: 0 4px 12px rgba(139, 30, 45, 0.16);  /* interactive / hover (brand red) */
  --elev-3: 0 10px 28px rgba(31, 39, 51, 0.18);         /* overlays: dropdowns, popovers, menus */
  --elev-4: 0 16px 40px rgba(31, 39, 51, 0.22);         /* modal-scale surfaces */
  /* ---- Corner radii. Pills (999px), circles (50%) and small feature insets stay
     literal; buttons/inputs keep --btn-radius (== --radius-control). ---- */
  --radius-card: 12px;      /* every resting card + overlay */
  --radius-control: 8px;    /* buttons / inputs */
  --radius-chip: 6px;       /* small chips / insets */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg-page);   /* internal pages: light grey (home/login use the photo) */
  color: var(--ink);
}

/* Top bar — back (left) · logo (center) · log out (right) */
/* One header treatment everywhere: the home screen's frosted-glass bar, applied
   to internal pages too (over their tint instead of the photo). */
.topbar {
  position: relative;   /* anchor for the notification status toast + Menu panel */
  z-index: 1000;        /* lift the banner (and its dropdowns) above ALL page
                           content — incl. the frosted-glass subcontractor tiles,
                           whose own backdrop-filter composited layers would
                           otherwise out-stack a lower banner z-index */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem 1rem;
  /* Guaranteed-light base (reads light with no/weak/dark backdrop-filter); the
     blur is a progressive enhancement, not what creates the lightness. */
  background: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(139, 30, 45, 0.14);   /* faint Safgri-red rule, visible on tint + photo */
}
.topbar-side { flex: 1 1 0; display: flex; align-items: center; min-width: 0; }
.topbar-left { gap: 1rem; }   /* space Back and Log out on driver sub-pages */
/* Logo lives on the RIGHT: the left controls flex-grow and push .brand to the
   right edge (shared header for home + internal pages). */
/* Right side of the banner: Refresh button + logo, kept together so the refresh
   sits by the logo without crowding the left (Back / Log out) controls. */
.topbar-right { display: flex; align-items: center; gap: 0.5rem; flex: 0 0 auto; }
.brand { display: flex; align-items: center; flex: 0 0 auto; }
.topbar-refresh {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;   /* comfortable mobile tap target */
  flex: 0 0 auto;
  color: var(--muted); text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s, background 0.15s, transform 0.3s;
}
.topbar-refresh:hover, .topbar-refresh:focus-visible {
  color: var(--safgri-red); background: rgba(139, 30, 45, 0.09);
}
.topbar-refresh:active { transform: rotate(-180deg); }   /* spin feedback on tap */
.topbar-refresh svg { display: block; }
/* Readable over the photo backdrop (same treatment as Log out). */
body.home-bg .topbar-refresh { color: var(--ink); }
/* Tap accent: a brief Safgri-red colour pulse at the START of the spin, easing
   back to the resting colour as the rotation completes. The missing 100% keyframe
   is synthesised from the element's base colour, so it returns to whichever applies
   (muted on internal pages, ink over the photo home banner). Runs alongside the
   :active spin; the animation overrides the transition/:hover colour while active. */
.topbar-refresh.is-pulsing { animation: refresh-pulse 0.35s ease-out; }
@keyframes refresh-pulse { 0% { color: var(--safgri-red); } }
@media (prefers-reduced-motion: reduce) {
  .topbar-refresh.is-pulsing { animation: none; }
}

/* Pending driver-request badge in the topbar (every page, admins). */
.topbar-requests {
  display: inline-flex; align-items: center; gap: 0.3rem;
  background: var(--bad); color: #fff;
  border-radius: 999px; padding: 0.22rem 0.55rem;
  font-size: var(--fs-micro); font-weight: 800; line-height: 1;
  text-decoration: none; box-shadow: 0 1px 3px rgba(214, 69, 69, 0.4);
}
.topbar-requests:hover, .topbar-requests:focus-visible { background: #c23b3b; }
.topbar-requests svg { display: block; }
.topbar-requests-count { line-height: 1; }

/* Account Settings gear in the topbar — same icon-button treatment as the
   refresh button beside it; reads clearly on both the tinted and photo banners. */
.topbar-settings {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;   /* comfortable mobile tap target */
  flex: 0 0 auto;
  color: var(--muted); text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s, background 0.15s, transform 0.15s;
}
.topbar-settings:hover, .topbar-settings:focus-visible {
  color: var(--safgri-red); background: rgba(139, 30, 45, 0.09); outline: none;
}
.topbar-settings:active { transform: scale(0.92); }
.topbar-settings svg { display: block; }
body.home-bg .topbar-settings { color: var(--ink); }   /* readable over the photo */
/* Active/open state: while ON the Account Settings page the gear is the "close"
   toggle and shows red (matching the Menu hamburger's open state). */
.topbar-settings.is-open,
body.home-bg .topbar-settings.is-open { color: var(--safgri-red); }
/* Tap animation — same spin + colour-accent pattern as the refresh icon: the gear
   turns while the icon briefly flashes Safgri red, then settles back to its resting
   colour (the missing 100% colour keyframe is synthesised from the base colour, so
   it returns to muted / ink / red-when-open as applicable). Direction reinforces
   the toggle: clockwise to OPEN, anticlockwise to CLOSE. */
.topbar-settings.is-spinning-open,
.topbar-settings.is-spinning-close { animation: gear-pulse 0.4s ease-out; }
.topbar-settings.is-spinning-open svg { animation: gear-turn-cw 0.4s ease-out; }
.topbar-settings.is-spinning-close svg { animation: gear-turn-ccw 0.4s ease-out; }
@keyframes gear-pulse { 0% { color: var(--safgri-red); } }
@keyframes gear-turn-cw { from { transform: rotate(0); } to { transform: rotate(180deg); } }
@keyframes gear-turn-ccw { from { transform: rotate(0); } to { transform: rotate(-180deg); } }
@media (prefers-reduced-motion: reduce) {
  .topbar-settings.is-spinning-open, .topbar-settings.is-spinning-close,
  .topbar-settings.is-spinning-open svg, .topbar-settings.is-spinning-close svg {
    animation: none;
  }
}
.logout {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
}
.logout:hover { color: var(--safgri-red); }
/* Current user shown subtly just above Log out on the home screen. */
.logout-stack { display: flex; flex-direction: column; align-items: flex-start; gap: 0.1rem; min-width: 0; }
.logged-in-as { color: var(--muted); font-size: var(--fs-micro); font-weight: 500; line-height: 1.1; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.content { max-width: 960px; margin: 0 auto; padding: 1.5rem 1.25rem; }
h1 { margin: 0 0 0.25rem; }
.page-title { margin: 0 0 0.25rem; font-size: var(--fs-page-title); }
/* Trucks-list heading with the subcontractor logo: prominent but page-heading
   sized, with a "Trucks" label beside it. */
.page-title-logo { display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap; }
.page-heading-logo {
  height: 2.4rem; max-height: 2.4rem; width: auto; max-width: 220px;
  object-fit: contain; display: block;
}
.page-heading-suffix {
  font-size: var(--fs-section); font-weight: 600; color: var(--muted);
}
@media (max-width: 520px) {
  .page-heading-logo { height: 2rem; max-width: 60vw; }
}
.subtitle { color: var(--muted); margin: 0 0 1.5rem; font-size: var(--fs-body); }

/* Truck detail header: registration heading on the left, the page's action
   buttons on the right; on narrow/mobile screens the buttons wrap below the
   heading (left-aligned). */
.truck-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 0.25rem;
}
.truck-header .page-title { margin: 0; }
/* Truck sections: four primary icon buttons — a single row on desktop, a tidy
   2x2 grid on phones. Solid Safgri-red (primary) with a clear hover/tap state. */
.truck-nav {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin: 0.7rem 0 1.3rem;
}
.truck-nav-btn {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  min-height: 48px;                      /* comfortable tap target on mobile */
  padding: 0.6rem 0.8rem;
  background: var(--safgri-red); color: #fff;
  border: 1px solid var(--safgri-red);
  border-radius: 10px;
  font-weight: 600; font-size: 0.92rem; line-height: 1.15;
  text-align: center; text-decoration: none;
  box-shadow: 0 1px 2px rgba(31, 39, 51, 0.12);
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.05s;
}
.truck-nav-btn:hover, .truck-nav-btn:focus-visible {
  background: var(--safgri-red-dark); border-color: var(--safgri-red-dark);
  color: #fff;
  box-shadow: var(--elev-2-accent);
}
.truck-nav-btn:active {
  transform: translateY(1px);
  box-shadow: 0 1px 2px rgba(31, 39, 51, 0.12);
}
.truck-nav-icon { width: 18px; height: 18px; flex: 0 0 auto; }
@media (max-width: 620px) {
  .truck-nav { grid-template-columns: 1fr 1fr; }   /* 2x2 on phones */
}

/* Export Truck Record — a full-width secondary action under the nav. Outlined
   (not solid red) so it reads as a distinct "download the whole record" action. */
.export-record-btn {
  display: flex; align-items: center; justify-content: center; gap: 0.55rem;
  width: 100%; min-height: 46px; margin: 0 0 1.3rem;
  padding: 0.65rem 0.9rem;
  background: var(--card); color: var(--safgri-red);
  border: 1.5px solid var(--safgri-red); border-radius: 10px;
  font-weight: 700; font-size: 0.92rem; text-decoration: none;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s, transform 0.05s;
}
.export-record-btn:hover, .export-record-btn:focus-visible {
  background: var(--safgri-red); color: #fff;
  box-shadow: var(--elev-2-accent);
}
.export-record-btn:active { transform: translateY(1px); }
.export-record-icon { width: 18px; height: 18px; flex: 0 0 auto; }

/* Ctrack telemetry panel — last known GPS location + delta-based tracked distance,
   shown under the truck details once the periodic sync has stored a reading. */
.ctrack-panel {
  display: flex; flex-direction: column; gap: 0.75rem;
  margin: 0 0 1.3rem; padding: 0.85rem 1rem;
  background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--safgri-red); border-radius: 10px;
}
.ctrack-row { display: flex; align-items: flex-start; gap: 0.65rem; }
.ctrack-icon { width: 20px; height: 20px; flex: 0 0 auto; color: var(--safgri-red);
  margin-top: 2px; }
.ctrack-label { display: block; font-size: var(--fs-meta); font-weight: 700;
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.02em; }
.ctrack-value { display: block; font-size: 1rem; font-weight: 600; color: var(--ink);
  margin: 1px 0; }
.ctrack-meta { display: block; font-size: var(--fs-meta); color: var(--muted); }
/* Ignition state on the last-known-location row. Colour is a reinforcement, never
   the only signal — the word "on"/"off" is always present for accessibility. */
.ctrack-ignition { font-weight: 700; }
.ctrack-ignition.is-on { color: var(--ok, #1a7f37); }
.ctrack-ignition.is-off { color: var(--muted); }
.ctrack-map-link { font-size: var(--fs-meta); font-weight: 600; margin-left: 0.35rem; }
/* Live location map. Fixed height so the card doesn't collapse before the Maps
   script resolves, and doesn't reflow the page when it does. */
.truck-map-wrap { margin: 0 0 1rem; }
.truck-map { width: 100%; height: 320px; border-radius: var(--radius, 10px);
  border: 1px solid var(--line, #e3e3e3); background: var(--surface-2, #f2f2f2); }
.truck-map-error { margin-top: 0.5rem; }
.truck-map-info { font-size: var(--fs-meta); line-height: 1.4; color: #202020; }
.truck-map-info strong { font-size: 1rem; }
.truck-map-info-meta { color: #666; margin-top: 2px; }
.truck-map-empty { display: flex; gap: 0.6rem; align-items: flex-start;
  padding: 1rem; margin: 0 0 1rem; border-radius: var(--radius, 10px);
  border: 1px dashed var(--line, #e3e3e3); background: var(--surface-2, #fafafa); }
.ctrack-badge { display: inline-block; margin-left: 0.4rem; padding: 1px 7px;
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: 0;
  text-transform: none; color: var(--safgri-red-dark); background: var(--safgri-red-tint);
  border-radius: 999px; vertical-align: middle; }

/* Home screen: a fixed full-screen background image with frosted-glass chrome
   on top (matches the login page's visual language). Scoped to body.home-bg so
   only the home screen is affected. */
body.home-bg::before {
  content: "";
  position: fixed;
  inset: 0; top: 0; right: 0; bottom: 0; left: 0;   /* explicit offsets: inset fallback */
  z-index: -2;
  /* Default Safgri photo; a subscriber with an uploaded home-screen background sets
     --home-bg-image on <body> (see base.html) to brand their own post-login home. */
  background: var(--bg) var(--home-bg-image, url("login-4.jpg")) center / cover no-repeat;
}
/* Frost the top bar so the image shows through while Log out stays legible. */
body.home-bg .logout { color: var(--ink); }
body.home-bg .logged-in-as { color: var(--ink); opacity: 0.72; }

/* Home — subcontractor grid with tap-to-open dropdowns */
.sub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 1rem;
  margin-top: 1.5rem;
}
.sub { position: relative; }         /* anchor for the dropdown menu */
.sub-card {                          /* the <summary> — a frosted-glass card */
  display: flex;
  align-items: center;
  justify-content: center;
  height: 104px;                     /* FIXED: every tile (logo or text) is identical */
  padding: 1rem;
  text-align: center;
  /* HOME-SCREEN ONLY frosted glass: strongly transparent white (~45%) + a
     stronger blur so the background photo genuinely shows through like frosted
     glass rather than a solid tinted card. The heavier blur (+ slight saturate)
     softens the busy photo enough that dark text/logos stay legible at this low
     opacity; a faint white text-halo below is the extra legibility scrim.
     Deliberately distinct from the solid white cards / tinted surfaces used on
     internal pages — .sub-card is not matched by the app-wide button/theme
     rules, so it keeps this look. */
  background: rgba(255, 255, 255, 0.45);
  -webkit-backdrop-filter: blur(15px) saturate(1.3);
  backdrop-filter: blur(15px) saturate(1.3);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: var(--radius-card);
  color: var(--ink);
  font-weight: 700;
  font-size: var(--fs-card-title);
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.55);
  cursor: pointer;
  list-style: none;                  /* hide the default disclosure triangle */
  box-shadow: var(--elev-1);
  transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.sub-card::-webkit-details-marker { display: none; }
.sub-card::marker { content: ""; }
.sub-card:hover,
.sub[open] > .sub-card {
  background: var(--safgri-red);
  border-color: var(--safgri-red);
  color: #fff;
  text-shadow: none;                 /* crisp white text on the solid red hover */
  box-shadow: var(--elev-2-accent);
}

/* Tabs with a logo: show ONLY the logo, sized to fill the card cleanly. Both are
   capped to the same height so neither looks larger, and max-width/max-height +
   object-fit: contain keep their aspect ratio (no stretch/crop). (Driver grid.) */
.sub-card-logo { padding: 0.9rem; }
.sub-logo {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 62px;
  object-fit: contain;
}

/* Home grid logo tile: show ONLY the logo (no name), centred in a fixed ~80px
   box so any aspect ratio renders undistorted (object-fit: contain). The box +
   trimmed padding fit the tile's normal height, so logo and text-only tiles
   stay the same size in the grid. */
.sub-card-img { height: auto; min-height: 104px; padding: 0.6rem; }
.tile-logo {
  height: 80px;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.tile-logo img { width: 100%; height: 100%; object-fit: contain; display: block; }
@media (max-width: 560px) { .sub-card-img { min-height: 88px; } }

/* Locked subcontractor tab — visible but not usable (no access): the same
   frosted card, greyed out. */
.sub-card.sub-locked {
  cursor: pointer;               /* tappable — reveals the "no access" message */
  position: relative;
  opacity: 0.5;
  filter: grayscale(0.6);        /* clearly greyed vs the full-colour accessible tiles */
  color: var(--ink);
}
.sub-card.sub-locked:hover {   /* cancel the normal red hover, stay frosted */
  background: rgba(255, 255, 255, 0.45);
  border-color: rgba(255, 255, 255, 0.6);
  color: var(--ink);
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.55);
  box-shadow: var(--elev-1);
}
/* Lock badge pinned to the corner so it sits over a logo or a name tile alike. */
.sub-lock {
  position: absolute; top: 0.45rem; right: 0.55rem;
  font-size: 0.95rem; opacity: 0.9; line-height: 1;
}
/* On-screen "you don't have access" panel revealed on tap. */
.sub-locked-msg {
  margin: 0; padding: 0.9rem 1rem;
  font-weight: 600; color: var(--bad);
}

/* Manage Users */
.user-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1rem 1.1rem;
  margin-bottom: 0.9rem;
  box-shadow: var(--elev-1);
}
.user-head { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.user-delete { margin-left: auto; }

/* Manage Users — grouped, collapsible cards. Collapsed shows a compact summary
   (name + role + one-line / subcontractor pills); expanding reveals the editor. */
.user-section-head { display: flex; align-items: baseline; gap: 0.5rem; margin-top: 1.7rem; }
.user-count {
  font-size: var(--fs-micro); font-weight: 700; color: var(--muted);
  background: #eef2f8; border-radius: 999px; padding: 0.05rem 0.5rem;
}
.user-card-collapsible { padding: 0; overflow: hidden; }   /* summary/body own their padding */
.user-summary {
  position: relative; display: flex; align-items: center; gap: 0.55rem;
  flex-wrap: wrap; padding: 0.8rem 2.3rem 0.8rem 1.05rem; cursor: pointer;
  list-style: none; -webkit-tap-highlight-color: transparent;
}
.user-summary::-webkit-details-marker { display: none; }
.user-summary::marker { content: ""; }
.user-summary:hover .user-name { color: var(--safgri-red); }
.user-summary-id { display: inline-flex; align-items: baseline; gap: 0.4rem; min-width: 0; }
.user-username { color: var(--muted); font-size: var(--fs-meta); font-weight: 500; }
.user-oneline { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 0.3rem; min-width: 0; }
.user-oneline-muted { color: var(--muted); font-size: var(--fs-meta); }
.user-pill {
  display: inline-block; font-size: var(--fs-micro); font-weight: 600;
  color: var(--safgri-red); background: var(--safgri-red-tint);
  border-radius: 999px; padding: 0.1rem 0.5rem; white-space: nowrap;
}
.user-caret {
  position: absolute; right: 1.05rem; top: 0.95rem;
  color: var(--muted); font-size: 0.9rem; transition: transform 0.15s;
}
.user-card-collapsible[open] .user-caret { transform: rotate(180deg); }
.user-body {
  padding: 0.9rem 1.05rem 1rem; border-top: 1px solid var(--border);
}
.user-body .user-edit { margin-top: 0; }
.user-body .user-delete { margin: 0.9rem 0 0; }
/* Collapsible username/password editor on each user card. */
.user-edit { margin: 0 0 0.6rem; }
.user-edit > summary { cursor: pointer; color: var(--safgri-red); font-weight: 600; font-size: var(--fs-meta); width: max-content; }
.user-edit-form { display: flex; flex-direction: column; gap: 0.5rem; max-width: 22rem; margin-top: 0.6rem; }
.user-name { font-weight: 700; font-size: var(--fs-card-title); }
.user-meta { color: var(--muted); font-size: 0.9rem; }
.user-access-all { margin: 0; color: var(--muted); font-size: var(--fs-body); }
.access-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.4rem 0.75rem;
  margin: 0.5rem 0 0.9rem;
}
.access-item { display: flex; align-items: center; gap: 0.4rem; font-size: 0.9rem; }
.access-perm { margin: 0.2rem 0 0.9rem; font-weight: 600; }

/* Edit-date link on a load row */
/* Load-row controls: Edit = secondary, Delete = destructive (styled above). */
.load-delete-form { display: inline; margin: 0; }
.confirm-move { margin: 0 0 0.75rem; font-size: 1rem; }

/* Driver upload confirmation (Layer 2) — key fields + Confirm/Re-upload. */
.confirm-fields { list-style: none; padding: 0; margin: 0 0 1rem; }
.confirm-fields li {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: 0.5rem 0; border-bottom: 1px solid var(--border);
}
.confirm-fields li:last-child { border-bottom: none; }
.cf-label { color: var(--muted); font-size: var(--fs-meta); }
.cf-value { font-weight: 700; color: var(--ink); text-align: right; }
.confirm-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.confirm-actions form { margin: 0; flex: 1 1 auto; }
.confirm-actions button { width: 100%; }

.confirm-warn { margin: 0.5rem 0; }

/* Dropdown menu — overlays content below the card so the grid doesn't shift. */
.sub-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  min-width: 220px;                  /* room for icons + labels even on small tiles */
  z-index: 20;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  box-shadow: var(--elev-3);
  overflow: hidden;
  transform-origin: top center;
}
/* Container reveal: a gentle downward EXPAND + fade-in on open (grows from the top
   edge — transform-origin is top center — so it opens downward, not a snap). The
   staggered item cascade below plays inside this. */
.sub[open] > .sub-menu { animation: subMenuIn 185ms ease-out; }
@keyframes subMenuIn {
  from { opacity: 0; transform: translateY(-6px) scaleY(0.9); }
  to   { opacity: 1; transform: translateY(0) scaleY(1); }
}
/* Staggered cascade: each item (header + links) fades/slides in just after the
   container, ~30ms apart, so they reveal one-after-another. `backwards` keeps each
   hidden through its delay. Whole cascade lands within ~380ms — snappy. */
.sub[open] > .sub-menu > * { animation: subItemIn 150ms ease-out backwards; }
.sub[open] > .sub-menu > *:nth-child(1)  { animation-delay: 0.02s; }
.sub[open] > .sub-menu > *:nth-child(2)  { animation-delay: 0.05s; }
.sub[open] > .sub-menu > *:nth-child(3)  { animation-delay: 0.08s; }
.sub[open] > .sub-menu > *:nth-child(4)  { animation-delay: 0.11s; }
.sub[open] > .sub-menu > *:nth-child(5)  { animation-delay: 0.14s; }
.sub[open] > .sub-menu > *:nth-child(6)  { animation-delay: 0.17s; }
.sub[open] > .sub-menu > *:nth-child(7)  { animation-delay: 0.20s; }
.sub[open] > .sub-menu > *:nth-child(8)  { animation-delay: 0.23s; }
.sub[open] > .sub-menu > *:nth-child(9)  { animation-delay: 0.26s; }
.sub[open] > .sub-menu > *:nth-child(10) { animation-delay: 0.29s; }
@keyframes subItemIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* Reverse on close: a quick collapse-upward + fade-out (JS holds the menu open just
   long enough to play it, then collapses the <details>). Mirrors subMenuIn. */
.sub.sub-closing > .sub-menu { animation: subMenuOut 150ms ease-in forwards; }
@keyframes subMenuOut {
  from { opacity: 1; transform: translateY(0) scaleY(1); }
  to   { opacity: 0; transform: translateY(-6px) scaleY(0.9); }
}
@media (prefers-reduced-motion: reduce) {
  .sub[open] > .sub-menu,
  .sub[open] > .sub-menu > *,
  .sub.sub-closing > .sub-menu { animation: none; }
}
/* Header: current subcontractor name (+ small logo for Safgri/SCM/FCS/EML). */
.sub-menu-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.9rem;
  background: #faf6f6;
  border-bottom: 1px solid var(--border);
}
.sub-menu-logo {
  height: 22px; width: auto; max-width: 84px;
  object-fit: contain; display: block;
}
.sub-menu-name {
  font-weight: 700; font-size: 0.9rem; color: var(--ink);
  letter-spacing: 0.01em;
}
.sub-menu a {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.7rem 0.9rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.95rem;
  border-bottom: 1px solid var(--border);
}
.sub-menu a:last-child { border-bottom: none; }
.sub-menu a:hover,
.sub-menu a:active { background: var(--safgri-red); color: #fff; }
/* Menu icons: lucide-style strokes, red accent, turning white on the red row. */
.menu-icon {
  width: 18px; height: 18px; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--safgri-red);
}
.sub-menu a:hover .menu-icon,
.sub-menu a:active .menu-icon { color: #fff; }
/* Mobile: one tile per row so each dropdown is full-width and roomy (no cramped
   labels, no sideways overflow). */
@media (max-width: 560px) {
  .sub-grid { grid-template-columns: 1fr; }
  .sub-card { height: 88px; }        /* uniform, a touch shorter on phones */
  .sub-menu { min-width: 0; }        /* full-width tile already gives enough room */
}

.home-links { margin-top: 1.75rem; display: flex; flex-direction: column; align-items: flex-start; gap: 0.6rem; }

/* Notification bell toggle (owner/admin). Outline+muted when off, filled+red
   when on; a quick ring-wiggle + bounce on every tap. */
/* Minimal icon — no border, box or background: just the bell, grey when muted and
   filled red when subscribed. Sits directly in the banner beside refresh/settings.
   The width/height is an invisible tap target, not a visible button. */
.notif-bell {
  position: relative;   /* anchor for the "ding" burst overlay */
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; flex: 0 0 auto; cursor: pointer;
  /* Neutralise the app-wide button chrome in EVERY state. The global
     button:hover / button:focus-visible red background (specificity 0,1,1) and
     the base button box-shadow would otherwise repaint a red box behind the icon
     the moment it's tapped (tap -> focus). Reset background + box-shadow here and
     in each interactive state below so only the icon glyph ever shows colour. */
  background: none; border: none; box-shadow: none; color: var(--muted);
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s, transform 0.15s;
}
.notif-bell:hover, .notif-bell:focus-visible {
  color: var(--ink); background: none; box-shadow: none; border: none; outline: none;
}
.notif-bell:active { transform: scale(0.92); background: none; box-shadow: none; }
.notif-bell:disabled { opacity: 0.5; cursor: not-allowed; background: none; box-shadow: none; }
.notif-bell svg {
  width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; transform-origin: 50% 15%;
}
/* Subscribed: the bell fills red (clapper stays a red stroke) — still no box. */
.notif-bell.is-on { color: var(--safgri-red); background: none; box-shadow: none; }
.notif-bell.is-on:hover, .notif-bell.is-on:focus-visible {
  color: var(--safgri-red-dark); background: none; box-shadow: none;
}
.notif-bell.is-on .bell-body { fill: currentColor; }
.notif-bell.animate svg { animation: bell-ring 0.6s ease; }
@keyframes bell-ring {
  0%, 100% { transform: rotate(0) scale(1); }
  15%      { transform: rotate(15deg) scale(1.12); }
  30%      { transform: rotate(-12deg) scale(1.08); }
  45%      { transform: rotate(9deg); }
  60%      { transform: rotate(-6deg); }
  75%      { transform: rotate(3deg); }
}
@media (prefers-reduced-motion: reduce) { .notif-bell.animate svg { animation: none; } }
/* "Ding!" burst — layered on top of the ring-wiggle ONLY when turning notifications
   ON (JS adds .dinging). Radiating spokes + a faint ring expand outward from the
   bell and fade in ~280ms; hidden (opacity 0) at rest. */
.notif-ding {
  position: absolute; left: 50%; top: 50%; width: 44px; height: 44px;
  margin: -22px 0 0 -22px; color: var(--safgri-red);
  opacity: 0; pointer-events: none;
}
.notif-ding svg { width: 100%; height: 100%; display: block; fill: none; stroke: currentColor; }
.notif-bell.dinging .notif-ding { animation: notif-ding 280ms ease-out; }
@keyframes notif-ding {
  0%   { opacity: 0;    transform: scale(0.5); }
  25%  { opacity: 0.95; }
  100% { opacity: 0;    transform: scale(1.4); }
}
@media (prefers-reduced-motion: reduce) { .notif-bell.dinging .notif-ding { animation: none; } }
/* Bell in the top banner: icon sized to sit cleanly beside the refresh/gear icons. */
.topbar-bell { width: 40px; height: 40px; }
.topbar-bell svg { width: 20px; height: 20px; }
body.home-bg .notif-bell:not(.is-on) { color: var(--ink); }   /* readable over the photo */
/* Notification status text — a small toast under the banner, right-aligned near
   the bell; absolutely positioned so it never disturbs the banner row, and hidden
   entirely when there's no message. */
.topbar-notif-msg {
  position: absolute; top: calc(100% + 6px); right: 12px; z-index: 60;
  font-size: var(--fs-meta); color: var(--ink); line-height: 1.3;
  background: rgba(255, 255, 255, 0.97); border: 1px solid var(--border);
  border-radius: 8px; padding: 0.3rem 0.6rem; max-width: min(80vw, 20rem);
  box-shadow: var(--elev-3);
}
.topbar-notif-msg:empty { display: none; }
.home-menu { position: relative; display: inline-block; }
/* Owner Menu as a plain hamburger icon — no background/border, matching the bell
   and settings-gear icon style. (A <summary>, not a <button>, so no button chrome
   to override.) */
.home-menu-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: none;
  list-style: none; -webkit-tap-highlight-color: transparent;
  transition: color 0.15s;
}
.home-menu-toggle::-webkit-details-marker { display: none; }
.home-menu-toggle::marker { content: ""; }
.home-menu-toggle:hover, .home-menu-toggle:focus-visible { color: var(--ink); outline: none; }
.home-menu-toggle svg {
  width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; display: block;
}
.home-menu[open] .home-menu-toggle { color: var(--safgri-red); }
body.home-bg .home-menu-toggle { color: var(--ink); }   /* readable over the photo */
body.home-bg .home-menu[open] .home-menu-toggle { color: var(--safgri-red); }
/* Owner Menu hamburger living in the top banner: right-anchor its dropdown to the
   banner (not the icon) so it never runs off a narrow screen, and let it overlay
   the page. (.topbar carries a z-index below so this escaping panel sits above the
   page content.) */
.topbar-menu.home-menu { position: static; }
.topbar .home-menu-panel {
  top: calc(100% + 6px); right: 12px; z-index: 100;
  /* Promote to its own composited layer so it reliably paints ABOVE the
     backdrop-filter tiles (which are themselves composited); a bare z-index isn't
     always honoured against a backdrop-filter layer without this. */
  will-change: transform;
}
.home-menu-panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 30;
  min-width: 250px; max-width: 340px; max-width: min(340px, 90vw);   /* plain px = min() fallback */
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--elev-3);
  overflow: hidden;
}
.home-menu[open] .home-menu-panel { animation: subMenuIn 160ms ease-out; }
@media (prefers-reduced-motion: reduce) {
  .home-menu[open] .home-menu-panel { animation: none; }
}
.home-menu-panel a {
  display: flex; align-items: center;
  min-height: 48px; padding: 0.8rem 1.15rem;   /* generous tap targets */
  color: var(--ink); text-decoration: none; font-weight: 600; font-size: 0.95rem;
  line-height: 1.25; border-bottom: 1px solid var(--border);
  transition: background 0.12s, color 0.12s;
}
.home-menu-panel a:last-child { border-bottom: none; }
.home-menu-panel a:hover,
.home-menu-panel a:active,
.home-menu-panel a:focus-visible {
  background: var(--safgri-red-tint); color: var(--safgri-red); outline: none;
}

/* Driver dashboard: two big, clearly-separate destination tiles (Upload
   Documents / New Checklist). Stack on narrow phones, side-by-side when wider. */
.driver-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.9rem;
  margin: 1.25rem 0 0.5rem;
}
.driver-tile {
  display: flex; flex-direction: column; justify-content: center; gap: 0.3rem;
  min-height: 104px; padding: 1.1rem 1.2rem; text-decoration: none;
  background: var(--card); border: 1px solid var(--border);
  border-left: 4px solid var(--safgri-red); border-radius: var(--radius-card);
  box-shadow: var(--elev-1);
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.05s;
}
.driver-tile:hover, .driver-tile:focus-visible {
  border-color: var(--safgri-red);
  box-shadow: var(--elev-2-accent);
}
.driver-tile:active { transform: translateY(1px); }
.driver-tile-label { font-weight: 700; font-size: var(--fs-card-title); color: var(--safgri-red); }
.driver-tile-caption { font-size: 0.88rem; color: var(--muted); }

/* Driver: five explicit document-upload buttons. Full-width, big tap targets,
   flowing to as many per row as fit (one per row on narrow phones). Each wraps a
   hidden file input that auto-submits on pick. */
/* Driver document uploads: the PROVEN visible-input pattern (reverted from the
   red-tile/label overlay, which Samsung/Chrome resolved to file-browser-only).
   Each type is a bordered .slip-upload card with a heading, a visible native
   file input (.photo-input), and a submit button. */
.driver-upload-list {
  display: flex; flex-direction: column; gap: 0.9rem;
  margin: 0.6rem 0 0.25rem;
}
.driver-upload-label { font-weight: 700; color: var(--ink); font-size: 0.95rem; }
.driver-upload-caption { font-weight: 400; color: var(--muted); font-size: var(--fs-meta); }
/* Optional odometer (km) field on loading/offloading uploads. */
.odo-field { display: flex; flex-direction: column; gap: 0.3rem; }
.odo-field-label { font-size: var(--fs-meta); color: var(--muted); font-weight: 600; }
.odo-input {
  padding: 0.55rem 0.6rem; border: 1px solid var(--border);
  border-radius: 8px; background: #fff; width: 100%; font-size: 1rem;
}
.doc-odo-input { flex: 1 1 8rem; min-width: 0; font-size: 0.85rem; padding: 0.4rem; }

/* Owner-only Safgri Diesel debug view: one card per captured read. */
.debug-list { list-style: none; margin: 1.25rem 0; padding: 0; }
.debug-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 0.9rem 1.1rem; margin-bottom: 0.7rem;
  box-shadow: var(--elev-1);
}
.debug-head { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem 0.75rem; }
.debug-truck { font-weight: 700; color: var(--ink); }
.debug-when { color: var(--muted); font-size: var(--fs-meta); margin-left: auto; }
.debug-reason { color: var(--safgri-red); font-size: var(--fs-meta); margin: 0.5rem 0 0; }
.debug-fields {
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem;
  margin-top: 0.6rem; font-size: 0.9rem; color: var(--ink);
}
.debug-fields b { color: var(--muted); font-weight: 600; font-size: var(--fs-micro);
  text-transform: uppercase; letter-spacing: 0.03em; margin-right: 0.25rem; }
.debug-raw { margin-top: 0.6rem; }
.debug-raw summary { cursor: pointer; color: var(--safgri-red); font-size: var(--fs-meta); font-weight: 600; }
.debug-raw pre {
  margin: 0.5rem 0 0; padding: 0.7rem 0.85rem; background: #f6f8fa;
  border: 1px solid var(--border); border-radius: 8px;
  font-size: 0.8rem; white-space: pre-wrap; word-break: break-word; overflow-x: auto;
}

/* Per-subcontractor Drivers page: one row per driver account (name + ID + truck). */
.driver-acct {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 0.6rem 0.9rem;
  padding: 0.85rem 1rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--elev-1);
}
.driver-acct-info { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.driver-acct-truck { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-left: auto; }
.truck-tag {
  font-weight: 700; font-size: var(--fs-micro); color: var(--safgri-red);
  background: var(--safgri-red-tint); border-radius: 8px; padding: 0.25rem 0.6rem;
  white-space: nowrap;
}
.truck-tag-none { color: var(--muted); background: #eef2f8; font-weight: 600; }

/* Truck list (per subcontractor) */
.truck-list { list-style: none; padding: 0; margin: 1.25rem 0 0; }
.truck-list li { margin-bottom: 0.6rem; }
.truck-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  padding: 0.85rem 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);                 /* match the Recent-slips cards */
  text-decoration: none;
  box-shadow: var(--elev-1);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.truck-row:hover {
  border-color: var(--safgri-red);
  box-shadow: var(--elev-2-accent);
}
.truck-reg { font-weight: 700; color: var(--ink); }
/* A real, approved driver reads with weight; "Unassigned"/no-driver is muted +
   italic so trucks lacking a driver are obvious at a glance. */
.truck-driver {
  color: var(--ink); font-weight: 600; font-size: 0.9rem;
  text-align: right; min-width: 0;
}
.truck-driver-none { color: var(--muted); font-weight: 400; font-style: italic; }

/* Per-truck attention badge: coloured dot + count (red critical/expired, amber
   needs-review/expiring-soon) or a subtle green tick when clear. Summary only. */
.attn-badge {
  display: inline-flex; align-items: center; gap: 0.28rem;
  font-size: var(--fs-micro); font-weight: 700; line-height: 1;
  padding: 0.2rem 0.42rem; border-radius: 999px; flex: none;
}
.attn-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; flex: none; }
.attn-red   { background: #fdeaea; color: var(--bad); }
.attn-red   .attn-dot { background: var(--bad); }
.attn-amber { background: #fff1e0; color: #b5651d; }
.attn-amber .attn-dot { background: #d9822b; }
.attn-clear { background: transparent; color: var(--ok); padding: 0.2rem 0.1rem; font-size: 0.9rem; }
/* When the badge has items it becomes a button opening the attention popover. */
.attn-badge[role="button"] { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.attn-badge[role="button"]:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.truck-item { position: relative; }

/* Attention popover — a small dropdown listing a truck's flagged items, each a
   link to where it's resolved. JS positions it with position:fixed (viewport-
   clamped) so it can't be clipped by the list or run off-screen on phones. */
.attn-pop {
  position: fixed; z-index: 1001; max-width: 320px; width: max-content;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--elev-3); overflow: hidden;
}
.attn-pop[hidden] { display: none; }
.attn-pop-head {
  font-size: var(--fs-micro); font-weight: 800; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.04em;
  padding: 0.55rem 0.7rem 0.4rem; border-bottom: 1px solid var(--border);
}
.attn-pop-body { max-height: 60vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.attn-pop-msg { margin: 0; padding: 0.7rem; font-size: var(--fs-meta); color: var(--muted); }
.attn-pop-list { list-style: none; margin: 0; padding: 0; }
.attn-pop-item {
  display: flex; flex-direction: column; gap: 0.12rem;
  padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--border);
  text-decoration: none; color: inherit;
}
.attn-pop-list li:last-child .attn-pop-item { border-bottom: 0; }
.attn-pop-item:hover, .attn-pop-item:focus { background: var(--bg-page); }
.attn-pop-title { font-size: var(--fs-meta); font-weight: 700; color: var(--ink); }
.attn-pop-why { font-size: var(--fs-micro); color: var(--muted); }

/* Truck details (per-truck page) */
.truck-details {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.75rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.1rem;
  margin-bottom: 0.5rem;
}
.detail { display: flex; flex-direction: column; gap: 0.15rem; }
.detail-label {
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
}
.detail-value { color: var(--ink); font-weight: 600; }
/* "Previously registered as …" — a truck's old/alternate plates, for transparency. */
.detail-note { color: var(--muted); font-size: var(--fs-meta); font-weight: 400; margin-top: 0.1rem; }

/* Per-truck registration management (Manage Trucks). */
.reg-manage-summary { cursor: pointer; color: var(--safgri-red); font-size: var(--fs-meta); margin-top: 0.25rem; }
.reg-manage-body { margin-top: 0.5rem; display: flex; flex-direction: column; gap: 0.5rem; }
.reg-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.reg-add { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.reg-add input[type="text"] { flex: 1 1 auto; min-width: 11rem; }
.reg-add-current { display: flex; align-items: center; gap: 0.3rem; font-size: var(--fs-meta); color: var(--muted); }
.reg-manage-body form { margin: 0; }

/* Truck detail page heading: prominent subcontractor logo (or name) + a small
   "Vehicle Overview" subtitle. The logo's hard size cap lives INLINE on the img
   (cache-proof); this just handles layout/spacing. */
.truck-heading { margin: 0 0 0.7rem; }
.truck-heading-logo { display: block; }   /* left-aligned block, capped inline */
.truck-heading-name { margin: 0; }
.truck-heading-sub { margin: 0.2rem 0 0; }

/* Truck detail page — subtle card polish (CSS only). A thin Safgri-red accent
   bar across the top, and light-grey dividers between fields via the gap-as-
   divider technique: the card background is the divider colour and each field
   sits on card-white with 1px gaps, so the gaps read as clean thin lines (no
   fragile per-cell borders, no empty-cell artifacts with the 6 even fields).
   Scoped so the driver dashboard's plain .truck-details card is unaffected. */
.truck-details-accent {
  grid-template-columns: 1fr 1fr;            /* fixed 2-col: 6 fields -> 3 full rows */
  gap: 1px;
  background: var(--border);                 /* shows through the gaps as lines */
  border-top: 3px solid var(--safgri-red);   /* branded red accent bar */
  padding: 0;                                /* cells carry their own padding */
  overflow: hidden;                          /* clip cells to the rounded corners */
}
.truck-details-accent .detail {
  background: var(--card);
  padding: 0.7rem 0.95rem;
}
/* "Unassigned" driver: muted grey + italic, vs the solid name of a real driver. */
.truck-details-accent .detail-value.is-unassigned {
  color: var(--muted); font-weight: 500; font-style: italic;
}
@media (max-width: 560px) {
  .truck-details-accent { grid-template-columns: 1fr; }   /* single column on phones */
}

/* Driver dashboard: plain grey backdrop, white cards, generous separation
   between sections so it never feels cramped on a phone. */
.driver-dash .section-head { margin-top: 2.4rem; }
.driver-dash .truck-details { margin-bottom: 0; }
.driver-dash .slip-upload { margin-bottom: 0.25rem; }
.driver-dash .hint { margin-top: 0.9rem; }

/* Inspections shown as a tappable row list (matches "Recent load papers"),
   so it reads cleanly on mobile instead of a table that scrolls sideways. */
.insp-list { padding-top: 0.2rem; }
.insp-row { gap: 0.35rem 0.75rem; }
a.insp-link {
  flex: 0 0 auto; color: var(--safgri-red); font-weight: 700;
  font-size: 0.92rem; text-decoration: none;
}
a.insp-link:hover, a.insp-link:focus-visible { text-decoration: underline; }
.insp-meta { flex: 1 1 auto; color: var(--muted); font-size: var(--fs-meta); }
.insp-row .overall-badge { flex: 0 0 auto; margin-left: auto; }

/* Monthly load log (truck page) */
.load-month {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 0.9rem 1.1rem;
  margin-bottom: 0.8rem;
  box-shadow: var(--elev-1);
}
.load-month-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--border);
}
.load-month-name { font-weight: 700; font-size: var(--fs-card-title); }
/* Diesel Pours cards: a comfortable VERTICAL layout. Each pour carries more than a
   single Load Log line (an info line, a status/reconciliation line, and the Edit
   form), so stack them in a column with clear, consistent gaps rather than cramming
   one wrapping flex row (which made the badges collide and the rhythm uneven). The
   delete × is pinned to the card's top-right corner. Scoped to .pour-row so the
   shared .load-row (Load Log) is untouched. */
/* Diesel Pours cards: ONE clean horizontal line per entry — date/time · litres ·
   slip · supplier · load, then the status + reconciliation badges — with Edit pushed
   to the far right. Wraps gracefully on narrow screens; the open Edit form spans the
   full card width (like the Load Log's inline edit). Scoped to .pour-row so the
   shared .load-row (Load Log) is untouched. */
.pour-row {
  display: flex; flex-direction: row; flex-wrap: wrap; align-items: center;
  gap: 0.3rem 0.7rem;
  padding: 0.5rem 0;
}
.pour-row .load-mass { flex: 0 1 auto; }              /* pack left; shrink if needed */
/* Status + reconciliation badges kept together with a clear gap between them. */
.pour-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.pour-row .load-actions { margin-left: auto; }        /* Edit to the far right */
/* Open Edit form drops to full card width so the field grid isn't crushed on the
   right (degrades to a right-side panel on browsers without :has). */
.pour-row .inline-edit[open] { flex-basis: 100%; }
.pour-row .load-actions:has(> .inline-edit[open]) { flex-basis: 100%; margin-left: 0; }
.pour-row > .slip-reason { flex-basis: 100%; margin-top: 0.1rem; }
/* Confirm & save + Delete side by side inside the expanded Edit form. */
.inline-edit-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
/* Orphan vendor-invoice warning on the Diesel timeline — a vendor invoiced diesel
   we hold NO captured slip for. Prominent RED, distinct from the normal pour cards,
   and the whole card links to the Reconciliation History record. */
.pour-orphan-row { list-style: none; }
.pour-orphan-link {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.7rem;
  text-decoration: none; color: #991b1b;
  background: #fef2f2; border: 1px solid #fca5a5; border-left: 4px solid #dc2626;
  border-radius: 8px; padding: 0.5rem 0.7rem; margin: 0.3rem 0;
}
.pour-orphan-link:hover { background: #fee2e2; border-color: #f87171; }
.pour-orphan-link .load-date { color: #991b1b; font-weight: 700; }
.pour-orphan-link .load-mass { flex: 0 1 auto; color: #b91c1c; }
.pour-orphan-badge {
  margin-left: auto; font-size: var(--fs-micro); font-weight: 700; white-space: nowrap;
  color: #fff; background: #dc2626; padding: 0.15rem 0.6rem; border-radius: 999px;
}
/* Highlight the Reconciliation History row a red orphan card deep-links to. */
.slip-table tr:target > td { background: #fff3cd; }
/* Bulk vendor diesel-invoice upload — drag-and-drop zone. */
.bulk-drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.4rem; text-align: center; cursor: pointer;
  min-height: 8rem; padding: 1.5rem 1rem; margin: 0.5rem 0 0.9rem;
  border: 2px dashed var(--border); border-radius: var(--radius-card);
  background: var(--card); color: var(--muted);
}
.bulk-drop:hover, .bulk-drop-over { border-color: #2563eb; background: #eff6ff; color: var(--ink); }
.bulk-drop-text { font-weight: 600; }
.bulk-drop-count { font-size: var(--fs-meta); color: var(--ink); font-weight: 600; }
/* Reconciliation status pill on each pour card. */
.pour-recon, .pour-unrecon {
  font-size: var(--fs-micro); font-weight: 600;
  padding: 0.15rem 0.55rem; border-radius: 999px;
  max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pour-recon { color: #166534; background: #dcfce7; }        /* reconciled — green */
.pour-unrecon { color: var(--muted); background: #eef2f8; } /* not yet — muted */
/* Roomier spacing between the inline-edit form's field labels. */
.inline-edit .field-grid { gap: 0.85rem 1rem; }
.load-month-stats { color: var(--muted); font-size: 0.88rem; }
.load-list { list-style: none; margin: 0; padding: 0.4rem 0 0; }
.load-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;                 /* wrap rather than overflow on narrow screens */
  gap: 0.5rem 0.75rem;
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--border);
}
.load-row:last-child { border-bottom: none; }
.load-date { flex: 0 0 auto; font-weight: 600; font-size: 0.9rem; }
.load-mass { flex: 1 1 auto; color: var(--muted); font-size: 0.9rem; }
/* Action buttons group: inline on the right on desktop. */
.load-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-left: auto;               /* push to the right end of the single row */
}
/* Mobile: stack — date + tonnage (and badge) on top, then the action buttons on
   their OWN full-width row that grows/wraps to fit the viewport, so they're never
   cut off, never overflow, and never need horizontal scroll. */
@media (max-width: 560px) {
  .load-row { align-items: baseline; }
  .load-actions {
    flex-basis: 100%;              /* forces the buttons onto their own row */
    margin-left: 0;
    margin-top: 0.25rem;
  }
  /* Buttons share the row and grow to fill it; a flex item won't shrink below its
     text (min-width: auto), so they wrap to a new line instead of clipping. */
  .load-actions > .load-edit,
  .load-actions > .load-delete-form { flex: 1 1 auto; }
  .load-actions .load-delete-form { display: flex; }
  .load-actions .load-delete { width: 100%; }   /* fill the (grown) delete form */
}
/* Inline (accordion) load edit — expands the form IN PLACE on the row (native
   <details>), no page navigation. Collapsed: the "Edit" summary is a chip in the
   actions group. Open: the panel spans the full row width (:has lets the actions
   group grow; degrades to a right-side panel on browsers without :has). */
/* The collapsed "Edit" trigger matches the Diesel Pours Edit chip exactly — small,
   grey, subtle — overriding the .load-edit red-secondary button styling on this
   summary only (the sibling "Complete load" .load-edit link is untouched). */
.load-edit-inline > summary {
  display: inline-block; cursor: pointer; list-style: none;
  padding: 0.28rem 0.6rem; font-size: 0.8rem; font-weight: 600; line-height: 1.2;
  border: 1px solid var(--border); border-radius: 8px;
  color: var(--ink); background: transparent;
}
.load-edit-inline > summary:hover,
.load-edit-inline > summary:focus-visible {
  color: var(--ink); background: transparent; border-color: var(--border);
}
.load-edit-inline > summary::-webkit-details-marker { display: none; }
.load-edit-inline[open] { flex-basis: 100%; }
.load-actions:has(> .load-edit-inline[open]) { flex-basis: 100%; margin-left: 0; }
.load-edit-panel {
  display: flex; flex-direction: column; gap: 0.6rem;
  margin-top: 0.6rem; padding: 0.85rem;
  border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--card);
  max-width: 460px;
}
.load-edit-field {
  display: flex; flex-direction: column; gap: 0.25rem;
  font-size: var(--fs-meta); color: var(--muted); font-weight: 600;
}
.load-edit-field input, .load-edit-field select {
  padding: 0.5rem 0.6rem; border: 1px solid var(--border); border-radius: 8px;
  font-size: 0.95rem; color: var(--ink); font-weight: 400;
}
.load-edit-panel-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.load-badge {
  flex: 0 0 auto;
  font-size: var(--fs-micro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  white-space: nowrap;
}
.load-complete   { background: #e8f7ee; color: var(--ok); }
.load-in_transit { background: #fff1e0; color: #b5651d; }
.load-overdue    { background: #fdeaea; color: var(--safgri-red); }
/* Low-confidence proximity pairing awaiting confirmation — not yet counted. */
.load-awaiting_confirmation { background: #eef4ff; color: #1c4fbf; }
/* Offloading entered by hand via "Complete load" (vs read from a slip). */
.load-manual     { background: #ede7fb; color: #5b3fb0; cursor: help; }

/* ------------------------------------------------------------------ *
 * Driver "My Loads" — per-load document cards (mobile-first).
 * ------------------------------------------------------------------ */
.new-load-form { margin: 1rem 0 1.4rem; }
.load-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--card);
  padding: 0.9rem 1rem;
  margin-bottom: 1rem;
  box-shadow: var(--elev-1);
}
.load-card-done { border-color: var(--ok); background: #f3fbf6; }
.load-card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.6rem; margin-bottom: 0.6rem;
}
.load-card-date { font-weight: 700; color: var(--ink); font-size: var(--fs-card-title); }
.load-complete-banner {
  background: #e8f7ee; color: var(--ok); font-weight: 700; font-size: 0.85rem;
  padding: 0.35rem 0.6rem; border-radius: 8px; margin-bottom: 0.6rem;
}
.doc-check { list-style: none; padding: 0; margin: 0 0 0.7rem; }
.doc-check-item {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.45rem 0; border-top: 1px solid var(--border);
}
.doc-check-item:first-child { border-top: 0; }
.doc-mark {
  flex: 0 0 1.4rem; width: 1.4rem; height: 1.4rem; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.8rem; font-weight: 800;
}
.doc-ok .doc-mark      { background: #e8f7ee; color: var(--ok); }
.doc-missing .doc-mark { background: #fdeaea; color: var(--safgri-red); }
.doc-label { flex: 1 1 auto; font-size: 0.95rem; }
.doc-missing .doc-label { color: var(--muted); }
.doc-state { flex: 0 0 auto; font-size: var(--fs-meta); color: var(--muted); }
/* Per-card missing-type upload: a visible native input + submit button (same
   proven pattern as the main buttons), dropped onto its own full-width line
   under the checklist label so the file input is real and laid-out. */
.doc-upload {
  flex: 1 1 100%; margin: 0.25rem 0 0.1rem;
  display: flex; gap: 0.5rem; align-items: center;
}
.doc-photo-input { flex: 1 1 auto; min-width: 0; padding: 0.4rem; }
.load-complete-form { margin: 0; }

/* "Reading…" indicator while a background read is in progress. */
.reading-hint { font-weight: 600; color: var(--muted); margin-top: 0.4rem; }

/* "Needs attention" — flagged uploads that couldn't be auto-filed (read-only). */
.attention-block { margin: 0.4rem 0 1.4rem; }
.attention-head { color: #b5651d; margin-top: 1.2rem; }
.attention-card {
  border: 1px solid #f0c78a;
  border-left: 4px solid #d98a1f;
  background: #fff8ef;
  border-radius: var(--radius-card);
  padding: 0.7rem 0.9rem;
  margin-bottom: 0.7rem;
}
.attention-card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem; margin-bottom: 0.35rem;
}
.attention-doc { font-weight: 700; color: var(--ink); }
.attention-reason { margin: 0.1rem 0; font-size: 0.9rem; color: var(--ink); }
.attention-date { margin: 0.2rem 0 0; font-size: var(--fs-meta); color: var(--muted); }
/* Status badges reused on the attention cards (match the slip-table palette). */
.status-processing   { background: #eef2f8; color: var(--muted); }
.status-needs_review { background: #fff1e0; color: #b5651d; }
.status-duplicate    { background: #fdeaea; color: var(--bad); }

/* ------------------------------------------------------------------ *
 * Digital checklist (driver inspections) — mobile-first.
 * ------------------------------------------------------------------ */
/* Overall status + per-item status badges (color-coded). */
.overall-badge, .status-badge {
  display: inline-block; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em;
  padding: 0.2rem 0.55rem; border-radius: 999px; white-space: nowrap;
}
.overall-pass, .status-pass       { background: #e8f7ee; color: var(--ok); }
.overall-minor, .status-minor     { background: #fff4e0; color: #b5651d; }
.overall-critical, .status-critical { background: #fdeaea; color: var(--safgri-red); }
.status-na                        { background: #eef2f8; color: var(--muted); }
/* Inspection-type tag in the merged history (Checklist / Daily / Weekly). */
.insp-type-tag {
  display: inline-block; font-size: var(--fs-micro); font-weight: 700;
  padding: 0.2rem 0.55rem; border-radius: 999px; white-space: nowrap;
  background: var(--safgri-red-tint); color: var(--safgri-red-dark);
}
/* Tyre-inspection detail: embedded photo thumbnails + section notes. */
.insp-photo { display: block; max-width: 120px; max-height: 120px; width: auto;
  height: auto; border-radius: 8px; border: 1px solid var(--border); }
.insp-photo-link { display: inline-block; }
.insp-section-note { margin: 0 0 1rem; padding: 0.75rem 1rem;
  background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--safgri-red); border-radius: 8px; }
.insp-section-note p { margin: 0 0 0.5rem; }

/* Odometer / location card + fields. */
.cl-intro-card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 1rem 1.1rem; margin: 1rem 0 1.25rem;
  box-shadow: var(--elev-1);
}
.cl-fields { display: flex; flex-wrap: wrap; gap: 0.85rem; margin: 0; }
.cl-fields .natis-field { flex: 1 1 150px; }
.cl-fields input, #cl-form textarea {
  padding: 0.6rem 0.7rem; border: 1px solid var(--border);
  border-radius: 8px; font-size: 1rem; color: var(--ink); background: #fff; width: 100%;
}
#cl-form textarea { margin-top: 0.2rem; }

/* Sticky progress bar so it stays visible while stepping through items. */
.cl-progress-wrap {
  position: sticky; top: 0; z-index: 5; background: var(--bg-page);
  padding: 0.6rem 0 0.7rem; margin-bottom: 0.5rem;
}
.cl-progress-label { font-size: var(--fs-meta); font-weight: 600; color: var(--muted); margin-bottom: 0.35rem; }
.cl-progress { height: 10px; background: #e3e6ea; border-radius: 999px; overflow: hidden; }
.cl-progress-bar { height: 100%; width: 0; background: var(--safgri-red); transition: width 0.2s; }

/* Category grouping heading — spaced, with a red accent bar. */
.cl-cat-title {
  font-size: var(--fs-eyebrow); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--muted);
  margin: 1.75rem 0 0.75rem; padding-left: 0.6rem;
  border-left: 3px solid var(--safgri-red);
}

/* Each checklist item is its own card. */
.cl-item {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  padding: 1rem 1.05rem; margin-bottom: 0.85rem;
  box-shadow: var(--elev-1);
}
.cl-item-head { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.6rem; margin-bottom: 0.7rem; }
.cl-item-name { font-weight: 700; font-size: 1rem; }
.cl-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.5rem; }
/* Small distinct badges for Priority / Photo required (form + detail). Padding +
   gaps are generous enough that two badges never run together or crowd the card. */
.cl-badge, .cl-crit {
  display: inline-block; font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; padding: 0.22rem 0.55rem; border-radius: 999px; white-space: nowrap;
  line-height: 1.2;
}
.cl-badge-crit, .cl-crit { background: #fdeaea; color: var(--safgri-red); }
.cl-badge-photo { background: #eef4ff; color: #1c4fbf; }
.cl-crit { margin-left: 0.35rem; vertical-align: middle; }

/* Status choice: radios as a 3-up segmented button control (Pass / Minor /
   Critical — big, equal tap targets). Three equal columns so all three fit the
   card cleanly on any width; min-width:0 lets each column shrink instead of
   overflowing on the narrowest phones. */
.cl-status { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.cl-opt { position: relative; min-width: 0; }
.cl-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.cl-opt span {
  display: block; text-align: center; padding: 0.65rem 0.3rem;
  border: 1.5px solid var(--border); border-radius: 9px; font-size: 0.85rem;
  font-weight: 700; color: var(--ink); cursor: pointer; user-select: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.cl-opt input:focus-visible + span { outline: 2px solid var(--safgri-red); outline-offset: 1px; }
.cl-opt-pass input:checked + span     { background: var(--ok); border-color: var(--ok); color: #fff; }
.cl-opt-minor input:checked + span    { background: #b5651d; border-color: #b5651d; color: #fff; }
.cl-opt-critical input:checked + span { background: var(--safgri-red); border-color: var(--safgri-red); color: #fff; }
.cl-opt-na input:checked + span       { background: var(--muted); border-color: var(--muted); color: #fff; }

/* Photo capture: dashed tap box (hides the raw file input). */
.cl-photo { display: block; margin-top: 0.75rem; cursor: pointer; }
.cl-photo-input { position: absolute; opacity: 0; width: 0; height: 0; }
.cl-photo-box {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  border: 2px dashed var(--border); border-radius: 10px; padding: 0.85rem;
  color: var(--muted); font-weight: 600; font-size: 0.85rem; text-align: center;
  background: #fafbfc; transition: border-color 0.12s, color 0.12s, background 0.12s;
}
.cl-photo:hover .cl-photo-box,
.cl-photo-input:focus-visible + .cl-photo-box { border-color: var(--safgri-red); color: var(--safgri-red); }
.cl-photo.has-photo .cl-photo-box { border-style: solid; border-color: var(--ok); color: var(--ok); background: #f0fbf4; }
/* Item marked Minor/Critical but no photo yet — a photo is mandatory to submit. */
.cl-photo.photo-needed .cl-photo-box { border-color: var(--safgri-red); color: var(--safgri-red); background: #fdeaea; }
.cl-cam { width: 20px; height: 20px; flex: 0 0 auto; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* Unresolved-issue type badges — visually distinct per type: Critical = red,
   Minor = orange, GIT = blue, other = neutral. Mirrors the checklist palette. */
.issue-badge {
  display: inline-block; padding: 0.08rem 0.5rem; border-radius: 999px;
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.02em; vertical-align: middle;
}
.issue-badge-critical { background: #fdeaea; color: var(--safgri-red); }
.issue-badge-minor    { background: #fff4e0; color: #b5651d; }
.issue-badge-git      { background: #eef4ff; color: #1c4fbf; }
.issue-badge-other    { background: #eef2f8; color: var(--muted); }
.issue-links { display: block; margin-top: 0.2rem; font-size: 0.82rem; }
.issue-links a { color: var(--accent); text-decoration: none; margin-right: 0.9rem; }

/* Revenue / Profit view */
.profit-pos { color: var(--ok); font-weight: 700; }
.profit-neg { color: var(--safgri-red); font-weight: 700; }
.rev-month { border: 1px solid var(--border); border-radius: 12px; padding: 0.4rem 0.9rem; margin-bottom: 0.8rem; background: var(--card); }
.rev-month-summary { cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 0.9rem; }
.rev-month-name { font-weight: 800; }
.rev-month-totals { font-size: var(--fs-meta); color: var(--muted); font-weight: 600; }
.rev-fleet-line { font-size: 0.9rem; font-weight: 700; margin: 0.4rem 0 0.8rem; }
.rev-incomplete { color: var(--safgri-red); }
.rev-sub-head { font-size: 0.98rem; margin: 0.9rem 0 0.35rem; display: flex; justify-content: space-between; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.rev-sub-profit { font-size: var(--fs-meta); font-weight: 600; color: var(--muted); }
.rev-table .rev-subtotal td { font-weight: 700; border-top: 2px solid var(--border); background: #f6f8fb; }

.cl-review { font-weight: 700; display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.75rem; }
.cl-submit-btn { width: 100%; margin-top: 0.9rem; padding-top: 0.7rem; padding-bottom: 0.7rem; }

/* Inspection detail (read-only results). */
.cl-cat-head { font-size: 0.95rem; margin: 1rem 0 0.4rem; color: var(--muted); }
.cl-result {
  background: var(--card); border: 1px solid var(--border); border-radius: 10px;
  padding: 0.6rem 0.85rem; margin-bottom: 0.5rem;
}
.cl-result-main { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.cl-result-name { font-weight: 600; }
.cl-photo-thumb { display: block; max-width: 160px; max-height: 160px; border-radius: 8px; margin-top: 0.5rem; }

/* Checklist-template editor rows. */
.cl-tmpl-item, .cl-tmpl-add {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  margin: 0.5rem 0; padding-top: 0.5rem; border-top: 1px solid var(--border);
}
.cl-tmpl-item .driver-add-field, .cl-tmpl-add .driver-add-field { flex: 1 1 140px; }
.user-role-form { margin: 0.4rem 0 0.6rem; max-width: 14rem; }

/* NATIS documents (per truck) */
.natis-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1rem 1.1rem;
  margin-bottom: 0.9rem;
  box-shadow: var(--elev-1);
}
.natis-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.natis-vehicle { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap; }
.natis-role { font-weight: 700; font-size: var(--fs-card-title); }
.natis-reg { color: var(--muted); font-weight: 600; }
.natis-meta { margin: 0.6rem 0 0; font-size: 0.9rem; color: var(--muted); }
.natis-meta a { color: var(--safgri-red); text-decoration: none; font-weight: 600; }
.natis-meta a:hover { text-decoration: underline; }
.natis-none { margin: 0.6rem 0 0; color: var(--muted); font-style: italic; font-size: var(--fs-body); }

.natis-upload {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
}
.natis-field { display: flex; flex-direction: column; gap: 0.3rem; font-size: var(--fs-meta); color: var(--muted); }
.natis-field input,
.natis-field select {
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 0.9rem;
  color: var(--ink);
  background: #fff;
}
/* Login-history user filter: keep the select a sensible width. */
.login-history-filter { margin-bottom: 1rem; }
.login-history-filter .natis-field { max-width: 20rem; }
/* Login history: the two lists (Driver / Admin+Subcontractor) sit side by side on
   desktop & tablet, collapsing to a single stacked column on narrow phones. */
.lh-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem 2rem; align-items: start; }
.lh-col { min-width: 0; }   /* let each table-scroll shrink within its column, not force it wide */
@media (max-width: 720px) { .lh-columns { grid-template-columns: 1fr; } }
.natis-upload button { align-self: flex-end; }

/* NATIS / expiry status badges */
.natis-badge {
  flex: 0 0 auto;
  font-size: var(--fs-micro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  white-space: nowrap;
}
.natis-valid       { background: #e8f7ee; color: var(--ok); }
.natis-expiring_1m { background: #fff4e0; color: #b5651d; }
.natis-expiring_2w { background: #ffe7d1; color: #c2410c; }
.natis-expired     { background: #fdeaea; color: var(--safgri-red); }
.natis-processing  { background: #eef2f8; color: var(--muted); }
.natis-needs_review{ background: #fff1e0; color: #b5651d; }
/* ESTIMATE (issue date + 1 month) — deliberately a DIFFERENT colour + a dashed
   outline from every confirmed-expiry badge, so a fallback estimate can never be
   mistaken for a certain expiry date. */
.natis-estimated { background: #eef0fb; color: #5b53c6; border: 1px dashed #a9a2e6; }
.natis-estimate { color: #5b53c6; font-style: italic; }
.natis-flag { color: var(--bad); }

/* Two document slots (COR / LCO) inside one vehicle card */
.natis-slot {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
}
.natis-slot:first-of-type { margin-top: 0.6rem; }
.natis-slot-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}
.natis-slot-label {
  font-weight: 700;
  font-size: 0.9rem;
  letter-spacing: 0.03em;
  color: var(--ink);
}

/* Boarding document category list */
.cat-list { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 1.25rem; }
.cat-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.95rem 1.1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  text-decoration: none;
  color: var(--ink);
  font-weight: 700;
  box-shadow: var(--elev-1);
  transition: border-color 0.15s, box-shadow 0.15s, color 0.15s;
}
.cat-card:hover { border-color: var(--safgri-red); color: var(--safgri-red);
                  box-shadow: var(--elev-2-accent); }
.cat-go { color: var(--safgri-red); font-weight: 700; }

/* Inline delete inside a document meta line (button uses the Destructive style). */
.inline-delete { display: inline-block; margin-left: 0.5rem; }

/* Alerts list */
.alert-list { list-style: none; padding: 0; margin: 1.25rem 0 0; }
.alert-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  border-radius: var(--radius-card);
  margin-bottom: 0.6rem;
}
.alert-row.alert-expired     { border-left-color: var(--safgri-red); }
.alert-row.alert-expiring_2w { border-left-color: #c2410c; }
.alert-row.alert-expiring_1m { border-left-color: #b5651d; }
.alert-main { flex: 1 1 auto; min-width: 0; }
.alert-reg { display: block; font-weight: 700; }
.alert-role { color: var(--muted); font-weight: 500; font-size: 0.9rem; }
.alert-expiry { display: block; color: var(--muted); font-size: var(--fs-meta); margin-top: 0.15rem; }
.alert-sub { color: var(--muted); font-size: var(--fs-meta); margin-top: 0.15rem; }
.alert-open { flex: 0 0 auto; color: var(--safgri-red); text-decoration: none; font-weight: 600; font-size: 0.9rem; }
.alert-open:hover { text-decoration: underline; }

/* Drivers */
.driver-add {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 1.25rem 0 1.5rem;
}
.driver-add-field {
  flex: 1 1 160px;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 9px;
  font-size: 0.95rem;
  color: var(--ink);
  background: #fff;
}
.driver-list { list-style: none; padding: 0; margin: 0; }
.driver-list li { margin-bottom: 0.6rem; }
.driver-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  text-decoration: none;
  box-shadow: var(--elev-1);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.driver-row:hover {
  border-color: var(--safgri-red);
  box-shadow: var(--elev-2-accent);
}
.driver-name { font-weight: 700; color: var(--ink); }
.driver-id { color: var(--muted); font-size: 0.9rem; }
.driver-remove { margin-top: 1.5rem; }

/* Driver 'other' documents list */
.other-list { list-style: none; margin: 0.4rem 0 0; padding: 0; }
.other-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border);
}
.other-row:last-child { border-bottom: none; }
.other-label { font-weight: 600; }
.other-links a { color: var(--safgri-red); text-decoration: none; font-weight: 600; font-size: 0.9rem; }
.other-links a:hover { text-decoration: underline; }
.natis-filename { color: var(--muted); font-size: var(--fs-meta); }

/* Diesel status badges + summary */
.diesel-link { margin: 0.5rem 0 0; }
/* .diesel-tab is styled as a Secondary button in the unified button system. */
.diesel-done        { background: #e8f7ee; color: var(--ok); }
.diesel-processing  { background: #eef2f8; color: var(--muted); }
.diesel-needs_review{ background: #fff1e0; color: #b5651d; }
.diesel-duplicate   { background: #fdeaea; color: var(--bad); }
.diesel-unallocated { background: #eef4ff; color: #1c4fbf; }
/* Invoice reconciliation result badges (Reconciliation History). */
.diesel-matched         { background: #e8f7ee; color: var(--ok); }
.diesel-litres_mismatch { background: #fdeaea; color: var(--bad); }
.diesel-no_slip         { background: #fff1e0; color: #b5651d; }
.diesel-ambiguous_date  { background: #fff1e0; color: #b5651d; }
.diesel-wrong_truck     { background: #fdeaea; color: var(--bad); }
.diesel-reason-row td { border-bottom: 1px solid var(--border); }
.diesel-reason { color: var(--bad); font-size: var(--fs-meta); padding-top: 0 !important; }

/* Excel import preview summary */
.import-summary {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.6rem;
  margin: 1.25rem 0 1.5rem;
}
.import-stat {
  background: var(--card);
  border: 1px solid var(--border);
  border-left: 4px solid var(--border);
  border-radius: var(--radius-card);
  padding: 0.7rem 0.9rem;
  font-size: 0.9rem;
  color: var(--muted);
  box-shadow: var(--elev-1);
}
.import-num { display: block; font-size: 1.4rem; font-weight: 800; color: var(--ink); }
.import-stat.import-ok { border-left-color: var(--ok); }
.import-stat.import-warn { border-left-color: var(--safgri-red); }

/* Placeholder ("coming soon") pages */
.placeholder {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 2rem 1.5rem;
  text-align: center;
  box-shadow: var(--elev-1);
}
.placeholder-title {
  margin: 0 0 0.35rem;
  font-size: var(--fs-card-title);
  font-weight: 700;
  color: var(--safgri-red);
}
.placeholder-text { margin: 0; color: var(--muted); font-size: var(--fs-body); }

/* Flash messages — styled by category (info/success are not errors). */
.flash {
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 0.5rem 0.9rem;
  margin-bottom: 1rem;
}
.flash p { margin: 0.15rem 0; }
.flash-error   { background: #fff4f4; border-color: #f3c9c9; color: var(--bad); }
.flash-info    { background: #eef4ff; border-color: #cddbf7; color: #1c4fbf; }
.flash-success { background: #e8f7ee; border-color: #bfe6cd; color: var(--ok); }

/* Role badges */
.role-badge {
  display: inline-block;
  font-size: var(--fs-micro);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: #eef2f8;
  color: var(--muted);
}
.role-owner { background: #e7f0ff; color: #1c4fbf; }
.role-admin { background: #fff1e0; color: #b5651d; }
.role-field { background: #e8f7ee; color: #1f7a48; }
.role-subcon { background: var(--safgri-red-tint); color: var(--safgri-red); }
.role-workshop { background: #e5eef7; color: #1c4fbf; }
.role-demo { background: #fde7e4; color: #d92d20; }

/* Demo "view as driver" preview banner + home picker. */
.preview-banner {
  position: sticky; top: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  background: #d92d20; color: #fff;
  padding: 0.5rem 1rem; font-size: 0.9rem;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}
.preview-banner-text { display: inline-flex; align-items: center; gap: 0.45rem; }
.preview-banner-tag {
  background: rgba(255, 255, 255, 0.22); border-radius: 999px;
  padding: 0.05rem 0.5rem; font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.03em;
}
.preview-banner form { margin: 0; }
.preview-banner-exit {
  background: #fff; color: #d92d20; border: 0; border-radius: 6px;
  padding: 0.35rem 0.85rem; font-weight: 700; cursor: pointer; white-space: nowrap;
}
.preview-banner-exit:hover { background: #ffe9e6; }

.demo-preview { margin-top: 1.5rem; }
.demo-preview-form {
  display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-top: 0.5rem;
}
.demo-preview-form select { flex: 1 1 220px; padding: 0.5rem; border-radius: 8px; }

/* Manage Subscriptions */
.sub-summary { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0.5rem 0 1.5rem; }
.sub-summary span {
  display: flex; flex-direction: column; gap: 0.15rem;
  font-size: 0.8rem; color: var(--muted);
  background: var(--card, #f6f6f8); border-radius: 10px; padding: 0.5rem 0.9rem;
}
.sub-summary strong { font-size: 1.05rem; color: var(--text, #222); }
.sub-card { margin-bottom: 1.75rem; }
.sub-card-head { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.sub-rate-form { display: inline-flex; align-items: center; gap: 0.4rem; }
.sub-rate-form input { width: 8rem; padding: 0.35rem 0.5rem; border-radius: 8px; }
.sub-rand { color: var(--muted); }
.sub-live { color: var(--muted); font-size: 0.72rem; margin-left: 0.35rem; }
.sub-history-summary { cursor: pointer; font-weight: 600; margin-top: 0.6rem; }

/* Per-driver documents page */
.driver-doc-slot { margin-bottom: 1.75rem; }
.driver-doc-current {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.85rem;
  margin-bottom: 0.6rem;
}
.driver-doc-badge { display: inline-flex; align-items: center; gap: 0.35rem; }
.driver-doc-badge-label { font-weight: 600; font-size: 0.85rem; }
.driver-doc-other-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.85rem;
}

/* My Documents (driver-facing): each stored doc stacks a large inline preview,
   its meta/badges, then its actions. Distinct from the admin flex-row above. */
.mydoc-current {
  display: block;
  margin-bottom: 0.9rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--border, #e2e6eb);
}
.mydoc-preview {
  display: block;
  width: 100%;
  max-width: 640px;
  max-height: 72vh;
  border: 1px solid var(--border, #d9dee5);
  border-radius: 8px;
  background: #fff;
  object-fit: contain;
}
.mydoc-preview-pdf { height: 72vh; }
.mydoc-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.85rem;
  margin: 0.5rem 0;
}
.mydoc-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; }

/* Subcontractor capability checkboxes (Manage Users). */
.cap-list { display: flex; flex-direction: column; gap: 0.25rem; margin: 0.6rem 0 0.9rem; }
.cap-item { align-items: flex-start; }
.cap-text { display: flex; flex-direction: column; gap: 0.1rem; }
.cap-desc { font-weight: 400; font-size: var(--fs-meta); color: var(--muted); }

/* Login — single username + password form, Safgri brand palette */

/* Full-screen crossfading image slideshow behind the login card (pure CSS).
   Four fixed layers cover the viewport; each shows for 7s then hands over with a
   slow ~2.8s ease-in-out crossfade, looping continuously (28s cycle). Each layer
   also carries a
   gentle, continuous Ken Burns zoom (scale 1 -> 1.06 over its visible window) for
   a calmer, premium feel. Both animations are GPU-composited (opacity + transform
   only, no layout) so they stay smooth on mobile. The card legibility is a
   separate concern — the frosted card and the .login-scrim sit on higher z-index
   layers and are unaffected by scaling these background slides. */
.login-slideshow {
  position: fixed;
  inset: 0; top: 0; right: 0; bottom: 0; left: 0;   /* explicit offsets: inset fallback */
  z-index: -2;
  overflow: hidden;
  background: var(--bg);          /* shown until the first image paints */
  pointer-events: none;
}
.login-slide {
  position: absolute;
  inset: 0; top: 0; right: 0; bottom: 0; left: 0;   /* explicit offsets: inset fallback */
  background-size: cover;
  background-position: center;
  opacity: 0;
  transform: scale(1);
  /* One delay drives BOTH animations (fade + zoom) so they stay in sync. The fade
     is eased (ease-in-out) for a gradual, gentle crossfade; the zoom keeps its
     default even easing, unchanged. */
  animation: loginSlideFade 28s ease-in-out infinite, loginKenBurns 28s infinite;
  will-change: opacity, transform;
  backface-visibility: hidden;    /* nudge onto its own compositor layer */
}
/* Staggered by 7s; the -2s offset makes image 1 already faded-in on load. */
.login-slide-1 { animation-delay: -2s; }
.login-slide-2 { animation-delay: 5s; }
.login-slide-3 { animation-delay: 12s; }
.login-slide-4 { animation-delay: 19s; }
@keyframes loginSlideFade {
  0%   { opacity: 0; }
  10%  { opacity: 1; }   /* faded in over 2.8s (eased) */
  25%  { opacity: 1; }   /* held through 7s */
  35%  { opacity: 0; }   /* faded out over 2.8s — the slower, gentler crossfade */
  100% { opacity: 0; }
}
@keyframes loginKenBurns {
  0%      { transform: scale(1); }
  32.143% { transform: scale(1.06); }  /* slow zoom across the visible window */
  40%     { transform: scale(1); }     /* reset while invisible (opacity 0) */
  100%    { transform: scale(1); }
}
/* A branded login with a single uploaded background: hold it still (a gentle,
   non-fading image) rather than crossfading to a blank frame. */
.login-slide-static { opacity: 1; animation: loginKenBurns 28s infinite; }
@media (prefers-reduced-motion: reduce) {
  .login-slide { animation: none; transform: none; }  /* no fade, no zoom */
  .login-slide-1, .login-slide-static { opacity: 1; }   /* hold a single, still image */
}

/* Soft dark scrim centred behind the card only (not the whole screen), so the
   frosted card and its text stay legible over both dark and bright images. */
.login-scrim {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(560px, 92vw);
  height: min(560px, 92vh);
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse at center,
              rgba(0, 0, 0, 0.34) 0%, rgba(0, 0, 0, 0.20) 42%, rgba(0, 0, 0, 0) 72%);
}
.login-page {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: calc(100vh - 3rem);
  padding: 2.5rem 0 3rem;
}
/* Idle fade: after 5s of no interaction the login card + its scrim fade out so the
   photo slideshow shows unobstructed (JS toggles body.login-idle; see login.html).
   They fade straight back on any interaction. pointer-events off while faded so a
   click can't hit the invisible form — a mousemove reveals it first anyway; keyboard
   focus is unaffected, so resuming typing brings it back without losing a keystroke. */
.login-page, .login-scrim { transition: opacity 0.6s ease; }
body.login-idle .login-page { opacity: 0; pointer-events: none; }
body.login-idle .login-scrim { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .login-page, .login-scrim { transition-duration: 0.15s; }
}
.login-box {
  width: 100%;
  max-width: 380px;
  /* Frosted glass: white with a strong blur so the slideshow shows through. The
     inputs (solid white), the Log in button (solid red) and flash messages
     (solid) carry their own backgrounds; the labels, title and links sit on the
     glass, and 65% white keeps them at WCAG AA over every login-1..4.jpg photo
     with room for the zoom and crossfade (the old 33% did not; 60% only just).
     Where backdrop-filter is unsupported the @supports block falls back to a
     near-opaque light card. */
  background: rgba(255, 255, 255, 0.65);
  -webkit-backdrop-filter: blur(17px) saturate(1.3);
  backdrop-filter: blur(17px) saturate(1.3);
  border: 1px solid rgba(255, 255, 255, 0.6);
  border-radius: var(--radius-card);
  box-shadow: var(--elev-4);
  padding: 2rem 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
}
/* Fallback: some older Android/Samsung browsers don't render backdrop-filter, so
   the blur (which makes the transparent card readable) would be absent — serve a
   near-opaque light card there so the login form is never an unreadable
   see-through panel. Modern iPhone/Android that DO support it get the glass. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .login-box { background: rgba(255, 255, 255, 0.9); }
}
.login-logo { text-align: center; margin-bottom: 0.5rem; }
/* Subscriber brand name shown when a branded login has no logo image (dark text
   on the light frosted card). */
.login-brand-name {
  display: block; text-align: center;
  font-size: 1.6rem; font-weight: 800; color: #1f2733; line-height: 1.2;
}
/* Public subscriber selector (login-select) — a grid of logos inside the card. */
.login-select-box { max-width: 560px; }
.login-select-title { text-align: center; margin: 0 0 0.25rem; font-size: 1.3rem; }
.login-select-sub { text-align: center; margin: 0 0 1rem; color: #2b3543;
  font-size: var(--fs-meta); text-shadow: 0 1px 2px rgba(255, 255, 255, 0.75); }
.login-select-grid { margin: 0.5rem 0 0.25rem; }
.login-select-grid .sub-card { cursor: pointer; text-decoration: none; }
.login-select-link { text-align: center; margin-top: 1rem; }
.login-select-link a { font-weight: 600; }
/* Native "Install app" button — pinned to the TOP-RIGHT corner of the login
   screen (default + branded), clear of the centred card and other elements.
   Fixed to the viewport (not in the card's flow) and inset by the device safe
   area so it never sits under a notch/rounded corner on mobile. Hidden until the
   browser signals installability (and only when not already installed) — the
   `hidden` attribute must always win, hence the explicit rule. */
.login-install {
  position: fixed;
  top: max(0.85rem, env(safe-area-inset-top, 0px));
  right: max(0.85rem, env(safe-area-inset-right, 0px));
  z-index: 10;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;   /* button, and the manual hint below it, hug the corner */
}
.login-install[hidden] { display: none; }
/* Manual "Add to Home Screen" hint for iOS Safari / Firefox (revealed on tap). */
.login-install-hint {
  margin: 0.4rem 0 0;
  max-width: 230px;
  padding: 0.45rem 0.6rem;
  font-size: var(--fs-meta); font-weight: 600; line-height: 1.3;
  color: #1f2733;
  background: rgba(255, 255, 255, 0.95);
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
  text-align: right;
}
.login-install-hint[hidden] { display: none; }
.login-install-btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.6rem 1.15rem;
  font-size: var(--fs-body); font-weight: 700; cursor: pointer;
  color: #1f2733;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: 999px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.login-install-btn:hover { background: #fff; }
.login-install-btn:active { transform: translateY(1px); }
.login-install-btn svg { width: 18px; height: 18px; flex: none; }
/* Phones: collapse to a small icon-only circle tucked in the corner, so it's
   significantly more compact and can't crowd or overlap the login card. The label
   is hidden visually but kept for screen readers via the button's aria-label. */
@media (max-width: 480px) {
  .login-install {
    top: max(0.6rem, env(safe-area-inset-top, 0px));
    right: max(0.6rem, env(safe-area-inset-right, 0px));
  }
  .login-install-label { display: none; }
  .login-install-btn {
    gap: 0;
    padding: 0.5rem;          /* equal padding + circle => a tidy 36px icon button */
    border-radius: 50%;
  }
  .login-install-btn svg { width: 20px; height: 20px; }
  .login-install-hint { max-width: min(200px, 62vw); font-size: var(--fs-meta); }
}
/* Admin: managing a subscriber's uploaded login backgrounds (thumbnails + remove). */
.brand-bg-manage { margin: 0.5rem 0 1.25rem; }
.brand-bg-company {
  font-size: var(--fs-body); margin: 0.6rem 0 0.4rem;
  display: flex; gap: 0.75rem; align-items: baseline; flex-wrap: wrap;
}
.brand-bg-thumbs { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.brand-bg-thumb { width: 160px; }
.brand-bg-thumb img {
  display: block; width: 100%; height: 96px; object-fit: cover;
  border-radius: 6px; border: 1px solid var(--border, #d9dee5);
  margin-bottom: 0.35rem; background: #fff;
}
/* Admin: per-subscriber brand accent colour (swatch + hex + re-extract). */
.brand-color-list { list-style: none; margin: 0.5rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.5rem; }
.brand-color-row { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.brand-swatch {
  width: 26px; height: 26px; border-radius: 6px; flex: none;
  border: 1px solid rgba(0, 0, 0, 0.15); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.4);
}
.brand-color-name { font-weight: 600; }

/* ---- Workshop landing + Parts/Tool inventories ---- */
.wk-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0.5rem 0 1rem; }
.wk-action {
  flex: 1 1 220px; display: flex; flex-direction: column; gap: 0.2rem;
  padding: 0.9rem 1.1rem; text-decoration: none;
  background: var(--card); border: 1px solid var(--border, #d9dee5);
  border-radius: var(--radius-card, 12px); box-shadow: var(--elev-1, 0 1px 3px rgba(0,0,0,0.1));
}
.wk-action:hover { border-color: var(--safgri-red); }
.wk-action-label { font-weight: 700; color: var(--safgri-red); }
.wk-action-caption { font-size: var(--fs-meta); color: var(--muted); }
.wk-truck-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.wk-issues { min-width: 0; }
.wk-issues > summary { list-style: none; cursor: pointer; display: inline-flex; }
.wk-issues > summary::-webkit-details-marker { display: none; }
.wk-issue-list { list-style: none; margin: 0.4rem 0 0; padding: 0.5rem 0.7rem;
  background: var(--card); border: 1px solid var(--border, #d9dee5); border-radius: 8px;
  display: flex; flex-direction: column; gap: 0.35rem; }
.wk-issue-list li { display: flex; flex-direction: column; }
.wk-issue-label { font-weight: 600; font-size: var(--fs-meta); }
.wk-issue-detail { font-size: var(--fs-micro, 0.75rem); color: var(--muted); }

.low-stock-alert {
  margin: 0.5rem 0 1rem; padding: 0.7rem 0.9rem;
  background: var(--safgri-red-tint, #f7e4e6); color: var(--safgri-red-dark, #731825);
  border: 1px solid var(--safgri-red, #8B1E2D); border-radius: 8px;
}
.part-list { list-style: none; margin: 0.5rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.7rem; }
.part-card { padding: 0.8rem 0.95rem; background: var(--card);
  border: 1px solid var(--border, #d9dee5); border-radius: var(--radius-card, 12px); }
.part-card.part-low { border-color: var(--safgri-red); }
.part-head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.part-name { font-weight: 700; font-size: var(--fs-body); }
.part-qty { font-size: var(--fs-meta); color: var(--muted); }
.part-low-badge { margin-left: 0.4rem; font-weight: 700; color: #fff;
  background: var(--safgri-red); border-radius: 999px; padding: 0.1rem 0.5rem; font-size: var(--fs-micro, 0.72rem); }
.part-use-form, .part-edit form {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem 0.75rem; margin-top: 0.6rem; }
.part-use-form .natis-field, .part-edit .natis-field { flex: 1 1 130px; margin: 0; }
.part-edit { margin-top: 0.5rem; }
.part-edit > summary { cursor: pointer; color: var(--safgri-red); font-weight: 600;
  font-size: var(--fs-meta); width: max-content; }

/* ---- Invoicing (universal draft + live integrations) ---- */
.invoice-month-list, .integration-list { list-style: none; margin: 0.5rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.5rem; }
.invoice-month-row, .integration-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  flex-wrap: wrap; padding: 0.6rem 0.8rem; background: var(--card);
  border: 1px solid var(--border, #d9dee5); border-radius: 10px; }
.invoice-month-label, .integration-name { font-weight: 700; }
.invoice-month-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.invoice-month-actions form { margin: 0; }
.integration-status { font-size: var(--fs-meta); color: var(--muted); margin-left: auto; }
.integration-connected { color: var(--good, #157a41); font-weight: 600; }
.integration-row form { margin: 0; }

/* Per-load invoicing: date range, running summary, grouped selectable loads. */
/* Invoicing relationship toggle (Safgri → Vendor vs Subcontractor → Safgri). */
.invoice-rel-toggle { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.25rem 0 0.75rem; }
.invoice-rel-toggle .btn-small { text-decoration: none; }
.invoice-rel-toggle .invoice-rel-active {
  background: var(--safgri-red); color: #fff; border-color: var(--safgri-red); }
.invoice-range { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem 0.75rem; margin: 0.5rem 0 0.75rem; }
.invoice-range .natis-field { flex: 0 1 150px; margin: 0; }
.invoice-summary-bar {
  position: sticky; top: 0.5rem; z-index: 3;
  padding: 0.55rem 0.85rem; margin: 0 0 0.9rem;
  background: var(--safgri-red); color: #fff; font-weight: 700;
  border-radius: 999px; box-shadow: 0 2px 8px rgba(0,0,0,0.25); text-align: center;
}
/* The running net, under the selection bar. Normal state is deliberately quiet
   — it is a figure to glance at, not a warning. It only turns red when the
   deductions exceed the loads, because that is the one state worth stopping on:
   a legitimate outcome (the subcontractor owes Safgri) that looks identical to a
   mis-tick. Not sticky: two stacked sticky bars eat the top of a long list. */
/* Reissue confirmation: what comes back, and what cannot. Quiet by default —
   it is information, not a warning — with the "not everything restores" line
   carrying the same weight as the other refusals on this page. */
.reuse-restore { margin: 0 0 0.9rem; padding: 0.6rem 0.85rem;
  border: 1px solid var(--border, #d9dee5); border-radius: 10px;
  background: var(--card, #fff); font-size: var(--fs-meta, 0.85rem); }
.reuse-restore p { margin: 0 0 0.4rem; }
.reuse-restore p:last-child { margin-bottom: 0; }
.reuse-legacy { color: var(--safgri-red, #b91c1c); font-weight: 600; }

/* POD cell on a remittance load row. Quiet: it is a fact about the row, not a
   call to action — except the missing state, which is the one worth noticing. */
.rem-pod { display: inline-flex; align-items: center; gap: 0.35rem;
  flex-wrap: wrap; font-size: var(--fs-meta, 0.85rem); width: 100%; }
.rem-pod-num { color: var(--muted, #6b7280); }
.rem-pod-none { color: var(--safgri-red, #b91c1c); font-weight: 600; }
.rem-pod-entry { display: inline-flex; align-items: center; gap: 0.3rem; }
.rem-pod-input { max-width: 9rem; padding: 0.15rem 0.4rem;
  border: 1px solid var(--border, #d9dee5); border-radius: 6px; }
.rem-pod-err { color: var(--safgri-red, #b91c1c); font-weight: 600; }

.rem-net-bar {
  position: static; background: var(--card, #fff); color: var(--text, #1f2937);
  border: 1px solid var(--border, #d9dee5); font-weight: 600;
  box-shadow: none; border-radius: 10px; font-size: var(--fs-meta, 0.85rem);
}
.rem-net-bar.rem-net-negative {
  background: #fef2f2; border-color: var(--safgri-red, #b91c1c);
  color: var(--safgri-red, #b91c1c); font-weight: 800;
}
.diesel-added-row { display: flex; align-items: center; gap: 0.5rem 0.7rem;
  flex-wrap: wrap; padding: 0.25rem 0; }
#diesel-results { margin: 0.4rem 0 0; padding: 0; }
#diesel-results .load-row { padding: 0.3rem 0; border-top: 1px solid var(--border, #d9dee5); }

.invoice-truck { margin-bottom: 0.6rem; border: 1px solid var(--border, #d9dee5);
  border-radius: 10px; overflow: hidden; background: var(--card); }
.invoice-truck-head { cursor: pointer; padding: 0.6rem 0.85rem; display: flex;
  justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; font-weight: 700; }
.invoice-truck-stats { font-weight: 400; font-size: var(--fs-meta); color: var(--muted); }
.invoice-load-list { margin: 0; padding: 0 0.5rem 0.4rem; }
.invoice-load-row { display: flex; align-items: center; gap: 0.5rem 0.7rem; flex-wrap: wrap; }
.invoice-load-row.is-invoiced { opacity: 0.72; }
.invoice-load-row.is-invoiced.is-reinvoicing { opacity: 1; }
.load-check { flex: none; width: 18px; height: 18px; }
.load-check-label { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 0.85rem;
  flex: 1 1 auto; cursor: pointer; }
.load-check-label .load-date { font-weight: 600; }
.load-check-label .load-amount { margin-left: auto; font-weight: 700; }
.invoiced-badge { font-size: var(--fs-micro, 0.72rem); font-weight: 800; color: #fff;
  background: var(--muted, #6b7280); border-radius: 999px; padding: 0.1rem 0.5rem; }
/* Live Xero/Sage status colours. */
.invoiced-badge.invoiced-submitted, .invoiced-badge.invoiced-approved,
.invoiced-badge.invoiced-sent { background: var(--warn, #b25c00); }
.invoiced-badge.invoiced-paid { background: var(--good, #157a41); }
/* Undefined 7-day (non-Kitso) terms — due date must be set by hand. */
.invoiced-badge.invoiced-review { background: var(--warn, #b25c00); }
/* Gone or unconfirmed in the accounting system: still invoiced here until a
   release (invoicerelease) — red so it stands out from a live draft. */
.invoiced-badge.invoiced-voided, .invoiced-badge.invoiced-deleted,
.invoiced-badge.invoiced-missing { background: var(--bad, #b42318); }
.reinvoice-warn { flex-basis: 100%; margin: 0.25rem 0 0; font-size: var(--fs-meta);
  color: var(--bad, #b42318); }
.reinvoice-reason { border: 1px solid var(--bad, #b42318); border-radius: var(--radius-chip, 8px);
  padding: 0.6rem 0.9rem; margin: 0.75rem 0; }
.reinvoice-reason p { margin: 0 0 0.4rem; color: var(--bad, #b42318); }
.invoice-check-link { font-size: var(--fs-micro, 0.72rem); font-weight: 600; color: var(--accent);
  text-decoration: underline; white-space: nowrap; margin-left: 0.35rem; }
/* "Check and release" — one invoice's live status and its loads. */
.release-verdict { border: 1px solid var(--border, #d0d5dd); border-radius: var(--radius-chip, 8px);
  padding: 0.75rem 1rem; margin: 0.75rem 0; }
.release-verdict.is-auto { border-color: var(--good, #157a41); }
.release-verdict.is-manual { border-color: var(--warn, #b25c00); }
.release-verdict.is-none { border-color: var(--bad, #b42318); }
.release-facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.25rem 1rem;
  margin: 0.5rem 0 1rem; }
.release-facts dt { font-weight: 700; }
.release-facts dd { margin: 0; overflow-wrap: anywhere; }
/* Fleet Health Score (Safgri pilot) — per-truck badge + fleet-average banner.
   Reuses the attention-popover mechanism; only the badge visual differs. */
.health-badge { display: inline-flex; align-items: center; gap: 0.25rem;
  font-size: var(--fs-micro, 0.7rem); font-weight: 800; color: #fff;
  border-radius: 999px; padding: 0.05rem 0.45rem; cursor: pointer;
  vertical-align: middle; }
.health-badge .health-grade { font-weight: 900; opacity: 0.95; }
.health-good { background: var(--good, #157a41); }
.health-warn { background: var(--warn, #b25c00); }
.health-bad  { background: var(--safgri-red, #8B1E2D); }
.health-none { background: var(--muted, #6b7280); }
.fleet-health-banner { display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.4rem 0.75rem; padding: 0.7rem 0.9rem; border-radius: 12px; color: #fff;
  margin: 0.25rem 0 0.9rem; }
.fleet-health-banner.health-good { background: var(--good, #157a41); }
.fleet-health-banner.health-warn { background: var(--warn, #b25c00); }
.fleet-health-banner.health-bad  { background: var(--safgri-red, #8B1E2D); }
.fleet-health-label { font-weight: 700; opacity: 0.95; }
.fleet-health-score { font-size: 1.5rem; font-weight: 900; line-height: 1; }
.fleet-health-max { font-size: 0.85rem; font-weight: 700; opacity: 0.85; }
.fleet-health-grade { font-weight: 800; }
.fleet-health-sub { font-size: var(--fs-meta); opacity: 0.92; flex-basis: 100%; }
/* SCM Trucks list — top-right Truck Status button (moved off the Menu). */
.trucks-topbar { display: flex; justify-content: flex-end; margin: 0 0 0.25rem; }
.trucks-status-btn { display: inline-block; text-decoration: none; font-weight: 800;
  background: var(--safgri-red, #8B1E2D); color: #fff; border-radius: 999px;
  padding: 0.4rem 0.9rem; }
.trucks-status-btn:hover, .trucks-status-btn:focus { filter: brightness(1.08); }
/* SCM Truck Status — inline service-scheduled Yes/No toggle + responsibility field. */
.service-toggle { margin: 0; }
.svc-btn { border: 1px solid; border-radius: 999px; padding: 0.15rem 0.7rem;
  font-weight: 800; cursor: pointer; }
.svc-btn.svc-yes { background: var(--good, #157a41); border-color: var(--good, #157a41); color: #fff; }
.svc-btn.svc-no { background: #e7ebf0; border-color: #b9c0cc; color: #6b7280; }
.truck-status-table td { vertical-align: middle; }
.issue-responsible { display: inline-flex; align-items: center; gap: 0.35rem;
  margin: 0.35rem 0 0; }
.issue-responsible-label { display: inline-flex; flex-direction: column;
  font-size: var(--fs-meta); }
/* Issue photo viewer — the photo framed in a page so Back is always reachable. */
.issue-photo-head { display: flex; align-items: center; gap: 0.5rem;
  margin-top: 0.75rem; }
.issue-photo-full { display: block; width: 100%; max-width: 720px;
  height: auto; border-radius: 10px; margin: 0.75rem 0 1rem;
  border: 1px solid var(--hair, #d9d9d9); }
.issue-photo-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
/* SCM Truck Dashboard — status tiles. */
.truck-dash-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.75rem; margin: 0.75rem 0 1rem; }
.dash-tile { display: flex; flex-direction: column; gap: 0.3rem; padding: 1rem;
  border-radius: 12px; text-decoration: none; border: 1px solid var(--hair, #d9d9d9);
  color: #fff; min-height: 78px; }
.dash-tile-label { font-size: var(--fs-meta); font-weight: 700; opacity: 0.95; }
.dash-tile-status { font-size: 1.05rem; font-weight: 800; }
.dash-tile.dash-ok { background: var(--good, #157a41); border-color: transparent; }
.dash-tile.dash-warn { background: var(--warn, #b25c00); border-color: transparent; }
.dash-tile.dash-loaded { background: #1d4e89; border-color: transparent; }
.dash-tile.dash-empty { background: var(--muted, #6b7280); border-color: transparent; }
.dash-tile.dash-danger { background: var(--safgri-red, #8B1E2D); border-color: transparent; }
.dash-breakdown-form { margin: 0.5rem 0 1rem; }
/* Inactivity auto-logout warning — small fixed notice near the bottom. */
/* IN-APP PUSH TOASTS — shown when a push arrives while this tab is visible,
   instead of the OS notification (see static/sw.js). Built on the same
   vocabulary as .attn-pop: card background, hairline border, elev-3 shadow —
   so it reads as part of the app rather than a foreign overlay. Anchored TOP,
   unlike .idle-warning, because it is news arriving rather than a countdown. */
.app-toasts { position: fixed; top: 1rem; left: 50%; transform: translateX(-50%);
  z-index: 1002; display: flex; flex-direction: column; gap: 0.5rem;
  width: min(92vw, 440px); pointer-events: none; }
.app-toast { pointer-events: auto; display: flex; align-items: flex-start;
  gap: 0.6rem; padding: 0.7rem 0.85rem;
  background: var(--card, #fff); border: 1px solid var(--border, #d9dee5);
  border-radius: 12px; box-shadow: var(--elev-3, 0 6px 24px rgba(0,0,0,0.18));
  /* Start state for the entry transition; .is-in releases it. */
  opacity: 0; transform: translateY(-8px);
  transition: opacity 180ms ease, transform 180ms ease; }
.app-toast.is-in { opacity: 1; transform: translateY(0); }
.app-toast.is-leaving { opacity: 0; transform: translateY(-8px); }
.app-toast.is-link { cursor: pointer; }
.app-toast-dot { flex: none; width: 8px; height: 8px; margin-top: 0.42rem;
  border-radius: 50%; background: var(--safgri-red, #b91c1c); }
.app-toast-text { display: flex; flex-direction: column; gap: 0.1rem; flex: 1 1 auto;
  min-width: 0; }
.app-toast-title { font-weight: 700; }
.app-toast-body { font-size: var(--fs-meta, 0.85rem); color: var(--muted, #6b7280); }
.app-toast-close { flex: none; border: 0; background: none; cursor: pointer;
  font-size: 1.05rem; line-height: 1; padding: 0.1rem 0.2rem;
  color: var(--muted, #6b7280); }
.app-toast-close:hover { color: var(--text, #1f2937); }
/* Same guard every other animation in this file carries. */
@media (prefers-reduced-motion: reduce) {
  .app-toast { transition: none; opacity: 1; transform: none; }
  .app-toast.is-leaving { opacity: 0; }
}

.idle-warning { position: fixed; left: 50%; bottom: 1rem; transform: translateX(-50%);
  z-index: 1000; max-width: min(92vw, 440px); display: flex; flex-wrap: wrap;
  align-items: center; gap: 0.5rem 0.75rem; padding: 0.7rem 0.9rem; border-radius: 12px;
  background: var(--warn, #b25c00); color: #fff; font-size: var(--fs-meta);
  box-shadow: 0 6px 24px rgba(0,0,0,0.25); }
.idle-warning[hidden] { display: none; }
.idle-warning .btn-small { background: #fff; color: var(--warn, #b25c00);
  border-color: #fff; font-weight: 800; }
/* Login History — collapsible "older logins" dropdown. */
.lh-older { margin-top: 0.5rem; }
.lh-older > summary { cursor: pointer; list-style: revert; }
/* Tool check-in/out + assignment (SCM pilot). */
.tool-check-list { list-style: none; margin: 0.75rem 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.5rem; }
.tool-check-item { display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; padding: 0.6rem 0.75rem; border: 1px solid var(--hair, #d9d9d9);
  border-radius: 10px; }
.tool-check-name { font-weight: 700; }
.tool-check-photo input[type="file"] { display: none; }
.tool-check-btn { display: inline-block; padding: 0.4rem 0.7rem; border-radius: 8px;
  background: var(--muted, #6b7280); color: #fff; font-weight: 700; cursor: pointer; }
.tool-check-photo.has-photo .tool-check-btn { background: var(--good, #157a41); }
.tool-check-photo.has-photo .tool-check-btn::after { content: " ✓"; }
.tool-killswitch { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
  justify-content: space-between; padding: 0.75rem; border-radius: 10px; margin: 0.5rem 0;
  border: 1px solid var(--hair, #d9d9d9); }
.tool-killswitch.on { background: rgba(21,122,65,0.1); }
.tool-assign-list { list-style: none; margin: 0.5rem 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.4rem; }
.tool-assign-row { display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; }
/* Weekly Inspection — inline "add a photo for…" pre-submit message + section gap. */
.insp-section { margin-bottom: 1.5rem; }
.insp-missing { color: var(--safgri-red, #8B1E2D); font-weight: 700; }
.insp-missing[hidden] { display: none; }
/* Photo-only tyre inspection (SCM) — "photo attached" confirmation on the button. */
.tyre-slot-photo .tyre-photo { display: inline-flex; margin-top: 0.25rem; }
.tyre-photo.has-photo .tyre-photo-btn { background: var(--good, #157a41); color: #fff; }
.tyre-photo.has-photo .tyre-photo-btn::after { content: " ✓"; }
/* Relief / temporary driver marker (SCM pilot) — small amber "TEMP" pill. */
.temp-badge { display: inline-block; font-size: var(--fs-micro, 0.68rem);
  font-weight: 800; letter-spacing: 0.03em; color: #fff;
  background: var(--warn, #b25c00); border-radius: 999px; padding: 0.05rem 0.4rem;
  vertical-align: middle; }
.relief-toggle { display: inline; margin: 0 0 0 0.5rem; }
/* Outstanding-documents quick upload rows. */
.doc-missing { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem;
  margin: 0 0 0.5rem; }
.doc-upload { display: inline-flex; align-items: center; gap: 0.35rem; margin: 0; }
.doc-upload input[type="file"] { max-width: 190px; font-size: var(--fs-meta); }

/* Per-load document slots: a labelled row per document (loading/offloading/POD),
   present ones with View/Download, missing ones with the inline uploader. Used on the
   Outstanding page (one slot per line) and mirrored in the per-load panel. */
.doc-slot { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.6rem;
  margin: 0 0 0.4rem; padding: 0.1rem 0; }
.doc-slot-label { min-width: 8.5rem; font-weight: 600; }
.doc-slot.doc-present .doc-slot-label { color: var(--ink); }
.doc-slot.doc-missing .doc-slot-label { color: var(--muted); }
.doc-slot a.home-link { margin: 0; }

/* Outstanding for Invoicing — one CARD per load, its documents in a GRID.
   The grid is the point: every card puts Loading / Offloading / POD / Diesel in the
   same order at the same position, so scanning DOWN a column shows the pattern of
   what is missing without reading a single label. The previous stacked list forced
   a read of every row to learn the same thing. */
/* A driver from another company, eligible here but not on one of these trucks.
   Muted rather than alarming — it is a normal arrangement, just not this
   company's own roster. */
.rem-badge-draft     { background: var(--card); color: var(--muted); }
.rem-badge-submitted { background: #e8eefc; color: #24448c; }
.rem-badge-approved  { background: #e6f4ea; color: #1e7b34; }
.rem-badge-disputed  { background: #fdeaea; color: var(--safgri-red); }
.doc-card.rem-status-disputed { border-color: var(--safgri-red); }
.rem-card-meta { margin: 0 0 0.35rem; font-size: var(--fs-meta); color: var(--muted); }
.rem-card-actions { margin: 0 0 0.5rem; }
.rem-events { list-style: none; margin: 0 0 0.6rem; padding: 0.5rem 0.6rem;
  border-left: 2px solid var(--border); font-size: var(--fs-meta);
  color: var(--muted); }
.rem-events li { margin-bottom: 0.2rem; }
.rem-event-note { font-style: italic; }
.rem-respond { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; }
.rem-respond form { display: inline-flex; align-items: center; gap: 0.35rem; margin: 0; }
.rem-dispute-form input { flex: 1 1 14rem; padding: 0.35rem 0.45rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip);
  font-size: var(--fs-meta); }

.affil-badge { display: inline-block; margin-left: 0.35rem; padding: 0.05rem 0.4rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip);
  background: var(--card); color: var(--muted);
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: 0.03em;
  vertical-align: middle; }
.driver-acct.is-affiliated { background: var(--card); }
.driver-acct.is-affiliated .driver-name { color: var(--muted); }

.pin-state { margin: 0 0 0.6rem; padding: 0.5rem 0.65rem;
  border: 1px solid var(--accent); border-radius: var(--radius-chip);
  background: var(--safgri-red-tint, rgba(0,0,0,0.03)); font-size: var(--fs-meta); }

.pod-link-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem;
  margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--border); }
.pod-link-label { display: flex; flex-direction: column; gap: 0.2rem;
  font-size: var(--fs-meta); font-weight: 600; flex: 1 1 20rem; }
.pod-link-label select { font-weight: 400; padding: 0.35rem 0.45rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip); max-width: 100%; }

.doc-cards { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.doc-card { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-chip); padding: 0.65rem 0.75rem; }
.doc-card-head { display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.35rem 0.7rem; margin-bottom: 0.55rem; }
.doc-card-date { font-weight: 700; }
.doc-card-truck { font-weight: 600; }
.doc-card-mine { color: var(--muted); font-size: var(--fs-meta); }
.doc-card-count { margin-left: auto; }

/* auto-fit rather than a fixed four: on a phone the tiles become one column and
   stay readable instead of being squeezed to four unreadable slivers. */
.doc-grid { display: grid; gap: 0.5rem;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
.doc-tile { display: flex; flex-direction: column; gap: 0.3rem;
  padding: 0.5rem 0.55rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); background: #fff; }
.doc-tile.is-missing { border-color: var(--safgri-red);
  background: var(--safgri-red-tint, rgba(0,0,0,0.02)); }
.doc-tile-head { display: flex; align-items: center; gap: 0.35rem; }
/* The mark carries the state on its own — colour is never the only signal, so it
   still reads for anyone who cannot separate the green from the red. */
.doc-tile-mark { display: inline-flex; align-items: center; justify-content: center;
  width: 1.15rem; height: 1.15rem; border-radius: 50%; flex: 0 0 auto;
  font-size: 0.72rem; font-weight: 700; line-height: 1; }
.doc-tile.is-present .doc-tile-mark { background: #e6f4ea; color: #1e7b34; }
.doc-tile.is-missing .doc-tile-mark { background: #fdeaea; color: var(--safgri-red); }
.doc-tile-label { font-weight: 600; font-size: var(--fs-meta); }
.doc-tile.is-missing .doc-tile-label { color: var(--muted); }
.doc-tile-note { color: var(--muted); font-size: var(--fs-meta); }
.doc-tile-actions { display: inline-flex; gap: 0.6rem; }
.doc-tile-actions a.home-link { margin: 0; }
.doc-tile .doc-upload { flex-wrap: wrap; gap: 0.3rem; }
.doc-tile .doc-upload input[type="file"] { max-width: 100%; }

.doc-panel { list-style: none; margin: 0.4rem 0 1rem; padding: 0; max-width: 34rem; }
.doc-panel-row { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 0.4rem 0.8rem; padding: 0.6rem 0.7rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip);
  margin-bottom: 0.4rem; background: #fff; }
.doc-panel-row.doc-missing { background: var(--safgri-red-tint, rgba(0,0,0,0.03)); }
.doc-panel-label { font-weight: 700; }
.doc-panel-actions { display: inline-flex; gap: 0.7rem; }
.doc-panel-actions a.home-link { margin: 0; }
.doc-panel-status { color: var(--muted); font-style: italic; font-size: var(--fs-meta); }
.doc-panel-note { color: var(--muted); font-weight: 400; font-size: var(--fs-meta); }

.load-docs-link { margin-left: 0.5rem; font-size: var(--fs-meta); white-space: nowrap; }
.reinvoice { font-size: var(--fs-meta); color: var(--safgri-red); display: inline-flex;
  align-items: center; gap: 0.25rem; cursor: pointer; }
.invoice-generate-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 1rem 0 0.4rem; }
.invoice-gen-btn { cursor: pointer; max-width: 100%; white-space: normal; }   /* long labels wrap on phones */
.invoice-bulk { display: flex; gap: 0.5rem; margin: 0 0 0.6rem; }
.invoice-truck-bulk { display: flex; gap: 0.5rem; padding: 0.4rem 0.5rem 0; }

/* Remittance Creator: the Load Log / Diesel Pours collapsible (.recent-slips) used
   for one truck group at a time. Those are page-level sections with room around
   them; these stack as cards inside the form, so the section margin and the
   summary's own rounding are dropped and the header sits flush in the card. */
.invoice-truck.recent-slips { margin: 0 0 0.6rem; }
.invoice-truck.recent-slips > .recent-slips-summary {
  padding: 0.5rem 0.7rem; border-radius: 0;
}
/* The selected tally sits beside the load count, not in place of it. Hidden at
   zero — an unselected truck should read as quiet, not as "0 selected". */
/* Truck registration on a deduction line — a tag, so it reads as an attribution
   rather than as part of the description it sits beside. */
.rem-reg-tag { flex: none; font-weight: 700; font-size: var(--fs-meta);
  color: var(--muted); border: 1px solid var(--border, #d9dee5);
  border-radius: 6px; padding: 0 0.35rem; }
.rem-seq-form { display: flex; align-items: center; gap: 0.4rem; margin: 0; }
.rem-seq-form input { width: 6.5rem; }

/* PDF link and Delete sit on one line in the issued-remittances table. */
.rem-actions { display: flex; align-items: center; gap: 0.75rem; white-space: nowrap; }
.rem-actions form { margin: 0; }
.rem-group-picked { margin-left: 0.6rem; font-weight: 700; color: var(--accent); }
.rem-group-picked[hidden] { display: none; }

/* Format Library */
.format-list { list-style: none; margin: 0.5rem 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.6rem; }
.format-row { display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap;
  padding: 0.6rem 0.8rem; background: var(--card);
  border: 1px solid var(--border, #d9dee5); border-radius: 10px; }
.format-thumb { flex: none; display: block; }
.format-thumb img { width: 68px; height: 68px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--border, #d9dee5); background: #fff; display: block; }
.format-meta { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.format-name { font-weight: 700; }
.format-actions { display: flex; align-items: center; gap: 0.75rem; margin-left: auto; }
.format-actions form { margin: 0; }
.format-detail { display: flex; flex-wrap: wrap; gap: 1.25rem; align-items: flex-start; }
.format-detail-img { flex: 1 1 320px; }
.format-detail-img img { width: 100%; max-width: 480px; border-radius: 10px;
  border: 1px solid var(--border, #d9dee5); background: #fff; }
.format-detail-notes { flex: 1 1 340px; }
.format-notes-field { width: 100%; font-family: inherit; font-size: var(--fs-body);
  line-height: 1.4; padding: 0.6rem; border-radius: 8px;
  border: 1px solid var(--border, #d9dee5); resize: vertical; }
.login-logo-img {
  display: block;
  width: 200px;
  max-width: 70%;
  height: auto;
  margin: 0 auto;
  /* Soft halo so the transparent logo stays legible over lighter video frames. */
  filter: drop-shadow(0 1px 6px rgba(255, 255, 255, 0.7));
}
.login-field { display: flex; flex-direction: column; gap: 0.35rem; }
.login-label { font-size: var(--fs-meta); font-weight: 700; color: #2b3543;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.75); }
.login-field input {
  width: 100%;
  padding: 0.65rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 9px;
  font-size: 1rem;
  color: var(--ink);
  background: #fff;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.login-field input:focus {
  outline: none;
  border-color: var(--safgri-red);
  box-shadow: 0 0 0 3px rgba(139, 30, 45, 0.15);
}
/* Password field with a show/hide eye toggle inside the input. */
.login-pw-wrap { position: relative; display: block; }
.login-pw-wrap input { padding-right: 3rem; }   /* room for the eye button */
.login-pw-toggle {
  position: absolute; top: 50%; right: 5px; transform: translateY(-50%);
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0;         /* generous tap target on phones */
  background: transparent; border: none; border-radius: 8px;
  color: var(--muted); cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.login-pw-toggle:hover { color: var(--safgri-red); }
.login-pw-toggle:focus-visible {
  outline: none; color: var(--safgri-red);
  box-shadow: 0 0 0 3px rgba(139, 30, 45, 0.15);
}
.login-pw-toggle:active { background: rgba(139, 30, 45, 0.08); }
.login-pw-toggle svg {
  width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
/* Only one icon (eye / eye-off) shows at a time — the hidden attribute isn't
   reliably applied to inline SVG, so hide it explicitly. */
.login-pw-toggle svg[hidden] { display: none; }
/* Login CTA: a full-width Primary button (inherits the unified primary style). */
.login-btn { margin-top: 0.4rem; width: 100%; }
.login-box a { color: var(--safgri-red-dark); }   /* the dark red: AA on the frosted glass */
/* ------------------------------------------------------------------ *
 * Unified buttons — exactly three variants, one shape/size for all.
 *   Primary   : solid red, white text, shadow (main actions; the default
 *               for every <button>).
 *   Secondary : outlined red on white, fills to a light-red tint on hover
 *               (nav / lesser actions).
 *   Destructive: muted pink + darker-red text + red border, fills solid
 *               red on hover (deletes / irreversible — always confirmed).
 * Same radius + padding + height across all three, on <button> and <a>.
 * ------------------------------------------------------------------ */
button,
.btn-primary,
.btn-secondary, .backlink, .home-link, .diesel-tab, .load-edit,
.btn-danger, .btn-delete, .load-delete {
  display: inline-block;
  border-radius: var(--btn-radius);
  padding: var(--btn-pad);
  font-size: var(--btn-font);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  border: 1.5px solid transparent;
  transition: background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
}
/* Primary */
button,
.btn-primary {
  background: var(--safgri-red);
  color: #fff;
  border-color: var(--safgri-red);
  box-shadow: 0 1px 2px rgba(31, 39, 51, 0.12);
}
/* Hover / focus / TAP (:active) feedback for the app-wide red button. Keep the
   label WHITE whenever this red feedback shows, so any button briefly repainted red
   on press stays legible (the base red bg here otherwise leaves a button's own
   dark/coloured text on dark red — e.g. the amber status buttons or the grey tabs). */
button:hover,
.btn-primary:hover,
button:focus-visible,
.btn-primary:focus-visible,
button:active,
.btn-primary:active {
  background: var(--safgri-red-dark);
  border-color: var(--safgri-red-dark);
  color: #fff;
  filter: none;
}
/* Secondary (incl. legacy nav-link classes) */
.btn-secondary, .backlink, .home-link, .diesel-tab, .load-edit {
  background: #fff;
  color: var(--safgri-red);
  border-color: var(--safgri-red);
  box-shadow: none;
}
.btn-secondary:hover, .btn-secondary:focus-visible,
.backlink:hover, .backlink:focus-visible,
.home-link:hover, .home-link:focus-visible,
.diesel-tab:hover, .diesel-tab:focus-visible, .diesel-tab:focus,
.load-edit:hover, .load-edit:focus-visible {
  background: var(--safgri-red-tint);
  color: var(--safgri-red-dark);
  border-color: var(--safgri-red-dark);
  text-decoration: none;
}

/* Back button — pill-shaped secondary (outlined red), arrow icon + "Back", with a
   quick leftward swoosh streak on tap. Inherits the secondary colours above. */
.backlink {
  display: inline-flex; align-items: center; gap: 0.35rem;
  border-radius: 999px;              /* pill */
  padding: 0.4rem 0.9rem;
  -webkit-tap-highlight-color: transparent;
}
.backlink-arrow { position: relative; display: inline-flex; align-items: center; }
.backlink-arrow svg {
  width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2;
  stroke-linecap: round; stroke-linejoin: round; display: block;
}
.backlink-label { line-height: 1; }
/* The swoosh streak — a short line just left of the arrow (the direction it points),
   hidden until a tap triggers the animation. */
.backlink-swoosh {
  position: absolute; left: -4px; top: 50%; margin-top: -1px;
  width: 14px; height: 2px; border-radius: 2px; background: currentColor;
  opacity: 0; transform: translateX(0); pointer-events: none;
}
.backlink.is-swooshing .backlink-swoosh { animation: back-swoosh 260ms ease-out; }
.backlink.is-swooshing .backlink-arrow svg { animation: back-nudge 260ms ease-out; }
@keyframes back-swoosh {
  0%   { opacity: 0.85; transform: translateX(4px) scaleX(0.4); }
  100% { opacity: 0;    transform: translateX(-12px) scaleX(1.25); }
}
@keyframes back-nudge {
  0%, 100% { transform: translateX(0); }
  45%      { transform: translateX(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .backlink.is-swooshing .backlink-swoosh,
  .backlink.is-swooshing .backlink-arrow svg { animation: none; }
}
/* Destructive (incl. legacy delete classes) */
.btn-danger, .btn-delete, .load-delete {
  background: var(--danger-bg);
  color: var(--danger-fg);
  border-color: var(--danger-border);
  box-shadow: none;
}
.btn-danger:hover, .btn-danger:focus-visible,
.btn-delete:hover, .btn-delete:focus-visible,
.load-delete:hover, .load-delete:focus-visible {
  background: var(--bad);
  color: #fff;
  border-color: var(--bad);
}

/* Dashboard */
.status-row { margin-bottom: 1.25rem; }
.status-pill {
  display: inline-block;
  font-size: var(--fs-micro);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
}
.status-pill.ok { background: #e8f7ee; color: var(--ok); }
.status-pill.bad { background: #fdeaea; color: var(--bad); }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}
.tile {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.1rem;
}
.tile h2 { margin: 0 0 0.4rem; font-size: var(--fs-card-title); }
.tile p { margin: 0; color: var(--muted); font-size: 0.9rem; }
a.tile { text-decoration: none; color: inherit; transition: border-color 0.15s; }
a.tile:hover { border-color: var(--accent); }
.hint { color: var(--muted); font-size: var(--fs-meta); margin-top: 1.5rem; }
.hint-inline { color: var(--muted); font-size: var(--fs-meta); font-weight: 400; }

/* Compact document-completion indicator (Boarding / Supplier). A small ring +
   percentage + label, colour-coded red <50 / amber 50–99 / green 100. */
.doc-score {
  display: inline-flex; align-items: center; gap: 0.65rem;
  padding: 0.5rem 0.85rem; margin: 0.25rem 0 1.25rem;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--elev-1);
}
.doc-ring { width: 42px; height: 42px; flex: 0 0 auto; transform: rotate(-90deg); }
.doc-ring-bg { fill: none; stroke: #e3e6ea; stroke-width: 3.6; }
.doc-ring-fg {
  fill: none; stroke-width: 3.6; stroke-linecap: round;
  transition: stroke-dasharray 0.4s ease;
}
.doc-score-red   .doc-ring-fg { stroke: var(--bad); }
.doc-score-amber .doc-ring-fg { stroke: #b5651d; }
.doc-score-green .doc-ring-fg { stroke: var(--ok); }
.doc-score-text { display: flex; flex-direction: column; line-height: 1.15; }
.doc-score-pct { font-weight: 800; font-size: 1.05rem; color: var(--ink); }
.doc-score-red   .doc-score-pct { color: var(--bad); }
.doc-score-amber .doc-score-pct { color: #b5651d; }
.doc-score-green .doc-score-pct { color: var(--ok); }
.doc-score-label { font-size: var(--fs-meta); color: var(--muted); }

/* Notification settings: one card row per alert type + an on/off toggle. */
.notif-list { list-style: none; margin: 1.25rem 0 1.5rem; padding: 0; }
.notif-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.9rem 1.1rem; margin-bottom: 0.6rem;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--elev-1);
}
.notif-text { display: flex; flex-direction: column; gap: 0.2rem; min-width: 0; }
.notif-label { font-weight: 700; color: var(--ink); }
.notif-desc { font-size: var(--fs-meta); color: var(--muted); }

/* Your Devices — subscribed push devices, each removable. */
.device-list { list-style: none; margin: 0.75rem 0 1rem; padding: 0; }
.device-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.8rem 1.1rem; margin-bottom: 0.55rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--elev-1);
}
.device-info { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.device-name { font-weight: 700; color: var(--ink); }
.device-meta { font-size: var(--fs-meta); color: var(--muted); }
/* Accessible toggle switch (a styled checkbox). */
.switch { position: relative; display: inline-block; width: 46px; height: 26px; flex: 0 0 auto; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-slider {
  position: absolute; inset: 0; top: 0; right: 0; bottom: 0; left: 0; cursor: pointer; background: #cbd2da;
  border-radius: 999px; transition: background 0.15s;
}
.switch-slider::before {
  content: ""; position: absolute; height: 20px; width: 20px; left: 3px; top: 3px;
  background: #fff; border-radius: 50%; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
  transition: transform 0.15s;
}
.switch input:checked + .switch-slider { background: var(--safgri-red); }
.switch input:checked + .switch-slider::before { transform: translateX(20px); }
.switch input:focus-visible + .switch-slider { outline: 2px solid var(--safgri-red); outline-offset: 2px; }

/* Nav links */
a.brand { text-decoration: none; color: inherit; }
.navlink {
  color: var(--ink);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
}
.navlink:hover { color: var(--accent); }

.section-head { font-size: var(--fs-section); margin: 1.75rem 0 0.75rem; }

/* Collapsible "Recent slips" — native <details>, collapsed by default. */
.recent-slips { margin: 1.75rem 0 0.75rem; }
/* One aligned header bar: heading (left) · status badges (middle) · toggle (right). */
.recent-slips > .recent-slips-summary {
  margin: 0;
  cursor: pointer;
  list-style: none;                 /* hide the default disclosure triangle */
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.4rem 0.7rem;
  padding: 0.3rem 0.4rem;
  border-radius: 10px;
  user-select: none;
}
.recent-slips > .recent-slips-summary::-webkit-details-marker { display: none; }
.recent-slips > .recent-slips-summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Heading — bolder / slightly larger, with a small slip icon in Safgri red. */
.rs-heading {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: var(--fs-section); font-weight: 700; letter-spacing: -0.01em;
  color: var(--ink);
}
.rs-icon { width: 1.15rem; height: 1.15rem; color: var(--accent); flex: none; }

/* Badges take the space between heading and toggle. */
.rs-stats { flex: 1 1 auto; }

/* Expand/collapse control — a subtle rounded button pinned to the right. */
.rs-toggle {
  flex: 0 0 auto; margin-left: auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem;
  border: 1px solid var(--border); border-radius: 9px;
  background: var(--card); color: var(--muted);
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.recent-slips > .recent-slips-summary:hover .rs-toggle {
  background: var(--safgri-red-tint);
  border-color: var(--accent);
  color: var(--accent);
}
.recent-slips-chevron {
  display: inline-block;
  width: 0.5rem; height: 0.5rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-1px) rotate(-45deg);   /* points right, collapsed */
  transition: transform 0.28s cubic-bezier(0.34, 1.3, 0.5, 1);  /* smooth, slight overshoot */
  flex: none;
}
.recent-slips[open] > .recent-slips-summary .recent-slips-chevron {
  transform: translateY(-2px) rotate(45deg);     /* points down, expanded */
}

/* Mobile: keep heading + toggle on line 1; badges wrap to their own line below. */
@media (max-width: 520px) {
  .rs-heading { order: 0; }   /* size comes from --fs-section — no mobile shrink */
  .rs-toggle  { order: 1; }
  .rs-stats   { order: 2; flex-basis: 100%; margin-top: 0.1rem; }
}

/* At-a-glance status breakdown shown while collapsed. Colour-coded to match the
   status badges (green Done / amber Needs Review / red Duplicate / grey Processing). */
.rs-stats {
  display: inline-flex; flex-wrap: wrap; align-items: center;
  gap: 0.3rem 0.7rem;
  font-size: var(--fs-meta); font-weight: 600; color: var(--muted);
}
.rs-stat { display: inline-flex; align-items: center; gap: 0.32rem; white-space: nowrap; }
.rs-dot { width: 0.55rem; height: 0.55rem; border-radius: 50%; flex: none; }
.rs-stat-done   { color: var(--ok); }
.rs-stat-review { color: #b5651d; }
.rs-stat-dup    { color: var(--bad); }
.rs-stat-proc   { color: var(--muted); }
.rs-stat-done   .rs-dot { background: var(--ok); }
.rs-stat-review .rs-dot { background: #d9822b; }
.rs-stat-dup    .rs-dot { background: var(--bad); }
.rs-stat-proc   .rs-dot { background: var(--muted); }

/* Direction accent per slip row — a distinct colour axis from the status palette
   (blue = loading, true yellow = offloading — a bright lemon/gold kept clear of the
   amber/red status badges) so direction and status read separately
   and the load->offload rhythm is scannable down the left edge. */
/* (the direction-coloured left border is set on .slip-row.slip-dir-* below, with
   a compound selector so it always beats the card's base border) */
.slip-dir-tag { font-weight: 700; }
.slip-dir-loading    .slip-dir-tag::before { content: "\2191\00a0"; color: #2563eb; }  /* ↑ loading (blue) */
.slip-dir-offloading .slip-dir-tag::before { content: "\2193\00a0"; color: #f4c430; }  /* ↓ offloading (yellow) */
.slip-dir-none       .slip-dir-tag::before { content: "\2022\00a0"; color: var(--muted); } /* • pending */
.count {
  font-size: var(--fs-meta); color: var(--muted); font-weight: 600;
  background: #eef2f8; border-radius: 999px; padding: 0.05rem 0.5rem;
}
.back { margin: 0 0 0.5rem; font-size: 0.9rem; }
.back a { color: var(--accent); text-decoration: none; }

/* Slip upload form */
.slip-upload {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 480px;
  box-shadow: var(--elev-1);   /* subtle card lift */
}
/* Admin truck-page typed uploads — compact 2×2 tile grid (one per document type).
   Two per row on desktop/tablet; single column only on narrow phones where two
   tiles wouldn't fit comfortably. */
.truck-upload-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}
@media (max-width: 480px) {
  .truck-upload-grid { grid-template-columns: 1fr; }
}
/* Compact tiles — tighter padding/spacing than the standalone .slip-upload card,
   so they read as efficient upload tiles rather than large blocks. */
.truck-upload-grid .slip-upload { max-width: none; gap: 0.45rem; padding: 0.7rem 0.8rem; }
.truck-upload-grid .dropzone { min-height: 54px; padding: 0.55rem 0.5rem; gap: 0.2rem; }
.truck-upload-grid .dropzone-text { font-size: 0.8rem; }
.truck-upload-grid .upload-hint-icon { width: 20px; height: 20px; }
.truck-upload-grid button { padding: 0.45rem 0.6rem; }
.truck-upload-head { display: flex; flex-direction: column; gap: 0.05rem; }
.truck-upload-label { font-weight: 700; font-size: 0.95rem; line-height: 1.2; }
.truck-upload-caption { font-size: var(--fs-meta); color: var(--muted); line-height: 1.2; }
.direction-toggle { border: none; margin: 0; padding: 0; }
.direction-toggle legend { font-weight: 600; padding: 0; margin-bottom: 0.5rem; }
.direction-toggle label {
  display: inline-flex; align-items: center; gap: 0.4rem;
  margin-right: 1.25rem; cursor: pointer;
}
/* Upload drop-zone hint: a minimal line-art cloud-with-up-arrow icon centered
   ABOVE a "Tap to upload" label, above the file picker. The icon is a thin
   outline (not filled), neutral GREY (red is reserved for buttons), and an
   INLINE SVG whose size is fixed EXPLICITLY to 28px — never an <img>, so it can
   never render oversized. */
/* Single consolidated upload drop zone: a styled label wrapping a transparent,
   full-size native file input. Tapping anywhere opens the picker; dropping a
   file lands on the input. There is NO separate "Choose File" button — the
   native input is transparent (opacity:0) over the label, so the icon + text
   are the only visible control. Camera works via the android/allowCamera token. */
.dropzone {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.35rem;
  width: 100%; min-height: 96px; padding: 1.3rem 1rem;
  border: 2px dashed var(--border); border-radius: 10px;
  background: #fafbfc; color: var(--muted);
  font-weight: 600; font-size: 0.85rem; text-align: center;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.dropzone:hover, .dropzone:focus-within, .dropzone.is-dragover {
  border-color: var(--safgri-red); background: var(--safgri-red-tint); color: var(--safgri-red);
}
.dropzone-input {
  position: absolute; inset: 0; top: 0; right: 0; bottom: 0; left: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; font-size: 0;
}
.dropzone-text { line-height: 1.2; }
.upload-hint-icon {
  width: 28px; height: 28px; flex: 0 0 auto;   /* small, fixed — never larger */
  fill: none; stroke: var(--muted); stroke-width: 1.75;
  stroke-linecap: round; stroke-linejoin: round;
}

/* File picker styled as a touch-friendly dashed "drop zone" box (keeps the
   VISIBLE native input so the mobile camera/gallery chooser still works — the
   hidden-input pattern is deliberately avoided). The native control shows the
   chosen filename; .has-file (set by JS on change) confirms a selection. */
.photo-input {
  width: 100%;
  padding: 1.1rem 1rem;
  border: 2px dashed var(--border);
  border-radius: 10px;
  background: #fafbfc;
  color: var(--muted);
  font-size: 0.9rem;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.photo-input:hover, .photo-input:focus-visible {
  border-color: var(--safgri-red);
  background: var(--safgri-red-tint);
  color: var(--safgri-red);
  outline: none;
}
/* The native "Choose file" button, styled to match (both modern + WebKit). */
.photo-input::file-selector-button,
.photo-input::-webkit-file-upload-button {
  margin-right: 0.85rem;
  padding: 0.5rem 0.9rem;
  border: 1px solid var(--safgri-red);
  border-radius: 8px;
  background: #fff;
  color: var(--safgri-red);
  font-weight: 700;
  font-size: 0.85rem;
  cursor: pointer;
  -webkit-appearance: none; appearance: none;
}
.photo-input:hover::file-selector-button { background: var(--safgri-red); color: #fff; }
/* A file is chosen: solid green border confirms the selection (like the
   checklist's captured-photo state). */
.photo-input.has-file {
  border-style: solid; border-color: var(--ok);
  background: #f0fbf4; color: var(--ink); font-weight: 600;
}
/* ------------------------------------------------------------------
 * Busy state — ONE spinner, one button treatment, one slow-page bar,
 * driven by the busy-state script in base.html for every POST form.
 * .rem-spinner and .invoice-progress-spinner are the same ring under
 * their old names, so the remittance and invoicing pages match it.
 * ------------------------------------------------------------------ */
.spinner, .rem-spinner, .invoice-progress-spinner {
  display: inline-block; flex: 0 0 auto; box-sizing: border-box;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--safgri-red-tint); border-top-color: var(--safgri-red);
  animation: spin 0.8s linear infinite;
}
.spinner-lg, .rem-spinner { width: 26px; height: 26px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }
/* Slowed, not stopped: a still ring reads as "stuck", which is the opposite of
   the one thing it is there to say. */
@media (prefers-reduced-motion: reduce) {
  .spinner, .rem-spinner, .invoice-progress-spinner { animation-duration: 2s; }
}

/* The clicked button. The ring takes the button's own text colour, so it is white
   on a red primary and red on an outlined secondary without a variant per style. */
button.is-busy, input.is-busy, .btn-primary.is-busy { cursor: progress; opacity: 0.85; }
.is-busy .spinner {
  width: 1em; height: 1em; margin-right: 0.45em; vertical-align: -0.15em;
  border-color: rgba(255, 255, 255, 0.35);
  border-color: color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor;
}
/* The form's OTHER submit buttons: visibly off, but not greyed like an error. */
form[aria-busy="true"] button:disabled:not(.is-busy),
form[aria-busy="true"] input[type="submit"]:disabled:not(.is-busy) {
  opacity: 0.55; cursor: progress;
}

/* Slow-page bar: a 3px brand-red sweep across the top, only once a navigation
   has taken longer than 300ms (base.html), so fast pages never flash it. */
.page-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 2000;
  overflow: hidden; pointer-events: none; opacity: 0; transition: opacity 0.15s;
}
.page-progress.is-active { opacity: 1; }
.page-progress::before {
  content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 40%;
  background: var(--safgri-red);
}
.page-progress.is-active::before { animation: page-progress 1.1s ease-in-out infinite; }
@keyframes page-progress { from { transform: translateX(-100%); } to { transform: translateX(250%); } }
@media (prefers-reduced-motion: reduce) {
  .page-progress.is-active::before { animation: none; width: 100%; opacity: 0.6; }
}
/* Drag-and-drop: highlight the drop zone while a file is dragged over it. */
.photo-input.is-dragover,
.natis-upload input[type="file"].is-dragover {
  border-color: var(--safgri-red);
  background: var(--safgri-red-tint);
  color: var(--safgri-red);
}

/* Selected-file preview thumbnails (before upload). CRITICAL: fixed 72px cells
   with object-fit:cover, so a large photo is always cropped to the small box and
   can NEVER render near its native resolution. */
.upload-previews {
  display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.6rem;
}
.upload-thumb {
  position: relative;
  width: 72px; height: 72px; flex: 0 0 auto;
  border: 1px solid var(--border); border-radius: 8px;
  overflow: hidden; background: #fff;
}
.upload-thumb-img {
  width: 72px; height: 72px; object-fit: cover; display: block;   /* fixed + cropped */
}
.upload-thumb-file {
  width: 72px; height: 72px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0.2rem; color: var(--muted); background: #fafbfc;
}
.upload-thumb-file svg {
  width: 26px; height: 26px; fill: none; stroke: currentColor;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}
.upload-thumb-ext { font-size: 0.58rem; font-weight: 800; letter-spacing: 0.03em; }
.upload-thumb-x {
  position: absolute; top: 3px; right: 3px;
  width: 20px; height: 20px; min-width: 0; padding: 0;
  border: none; border-radius: 50%;
  background: rgba(15, 21, 29, 0.62); color: #fff;
  font-size: 0.95rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: none;
}
.upload-thumb-x:hover, .upload-thumb-x:focus-visible {
  background: var(--safgri-red); filter: none;
}
/* Per-card inline "Upload" inputs stay compact (they live in the load-history
   rows, not as a full drop zone). Declared after .photo-input to win on padding. */
.doc-photo-input { padding: 0.5rem 0.6rem; font-size: 0.82rem; border-width: 1px; }

/* Slip list */
/* Recent-slips list reads as an activity feed of clean cards, evenly spaced. */
.slip-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 0.6rem;
}
.slip-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 0.9rem;
  background: var(--card);
  border: 1px solid var(--border);
  border-left-width: 4px;                 /* space reserved for the direction accent */
  border-radius: var(--radius-card);
  padding: 0.85rem 1rem;
  box-shadow: var(--elev-1);
  transition: box-shadow 0.15s ease;
}
.slip-row:hover { box-shadow: var(--elev-2); }
/* Direction accent — compound selectors (0,2,0) so they always beat the card's
   own 1px border regardless of source order. */
.slip-row.slip-dir-loading    { border-left-color: #2563eb; }
.slip-row.slip-dir-offloading { border-left-color: #f4c430; }
.slip-row.slip-dir-none       { border-left-color: var(--border); }
@media (max-width: 520px) {
  .slip-row { padding: 0.75rem 0.85rem; gap: 0.6rem; border-radius: 10px; }
}
.slip-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.4rem;
  flex-shrink: 0;
}
.slip-reg { font-weight: 600; }
.slip-reg a { color: var(--accent); text-decoration: none; }

/* Load-pairing review actions (Confirm / Not a match / Dismiss) side by side. */
.review-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.5rem; }
.review-actions form { margin: 0; }

/* Delete button — subtle until hovered; destructive, owner only. */
/* .btn-delete is styled as a Destructive button in the unified button system. */
.review-delete { margin-top: 0.75rem; }

/* Direction override control */
.dir-control { display: inline-flex; align-items: center; gap: 0.3rem; margin: 0; }
.dir-control select {
  padding: 0.2rem 0.4rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.78rem;
  color: var(--ink);
  background: #fff;
}
.btn-small {
  padding: 0.2rem 0.5rem;
  font-size: 0.78rem;
  border-radius: 6px;
}
.row-actions { display: flex; align-items: center; gap: 0.5rem; }

/* Manage Trucks: subcontractor selector tabs + deactivated-row dimming */
.manage-truck-subs {
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
}
.manage-truck-subs .access-item {
  justify-content: center;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border, #d9e0ea);
  border-radius: 8px;
  text-decoration: none;
  color: var(--text, inherit);
  background: #f6f8fb;
  font-weight: 600;
}
.manage-truck-subs .access-item-on {
  background: var(--safgri-red, #c8102e);
  border-color: var(--safgri-red, #c8102e);
  color: #fff;
}
.truck-row-inactive td { opacity: 0.55; }
/* Deactivated truck in the shared trucks_list (anchor rows): dim the reg/driver
   text but keep the "Inactive" badge at full strength so it stays legible. The
   badge is a sibling of .truck-reg inside .truck-reg-wrap, so dimming .truck-reg
   alone (not the wrap) leaves the badge untouched. */
.truck-reg-wrap { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }

/* Driver truck-request list: registration on top, live current-driver line under
   it (left-aligned, unlike the right-aligned .truck-driver in the admin list). */
.truck-request-lines { display: flex; flex-direction: column; gap: 0.15rem; }
.truck-request-lines .truck-reg { display: block; }
.truck-current-driver { color: var(--muted); font-size: var(--fs-meta); }
.truck-current-driver.truck-driver-free { font-style: italic; }
a.truck-row-inactive .truck-reg,
a.truck-row-inactive .truck-driver { opacity: 0.5; }
.review-quickfix {
  display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap;
  margin: 0.75rem 0;
}
.quickfix-label { font-size: var(--fs-meta); color: var(--muted); text-transform: capitalize; }
.slip-meta { color: var(--muted); font-size: var(--fs-meta); margin-top: 0.15rem; text-transform: capitalize; }
.slip-reason { color: var(--bad); font-size: var(--fs-meta); margin-top: 0.3rem; }

/* "Did you mean …?" close-misread confirm — an amber suggestion strip on a
   flagged slip, with a Confirm and a Keep-flagged action. */
.didyoumean {
  margin-top: 0.4rem;
  padding: 0.5rem 0.6rem;
  background: #fff1e0;
  border: 1px solid #f0d3a8;
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.6rem;
}
.didyoumean-text { color: #8a5a1d; font-size: var(--fs-meta); }
.didyoumean-text strong { color: #6d4514; }
.didyoumean-actions { display: flex; gap: 0.4rem; margin-left: auto; }
.didyoumean-actions form { margin: 0; }
.didyoumean-yes {
  background: #b5651d; color: #fff; border-color: #b5651d;
}
.didyoumean-yes:hover { background: #9c561a; border-color: #9c561a; }
.didyoumean-keep { background: none; color: #8a5a1d; border-color: #d9b483; }

/* Recent Diesel cards — reuse the slip-row card; each fill can carry a Diesel and
   a Safgri Diesel line, paired into one card. No direction accent (diesel has none). */
.diesel-card .slip-main { width: 100%; }
.diesel-card-head { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem; }
.diesel-pair-tag {
  font-size: var(--fs-micro); font-weight: 700; color: var(--accent);
  background: var(--safgri-red-tint); border-radius: 999px; padding: 0.1rem 0.45rem;
}
.diesel-line {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.3rem 0.5rem;
  padding: 0.35rem 0; border-top: 1px solid var(--border);
}
.diesel-line:first-of-type { border-top: none; }
.diesel-line-type {
  font-weight: 700; font-size: var(--fs-meta); color: var(--ink);
  min-width: 4.5rem;
}
.diesel-line-type-safgri { color: var(--accent); }
.diesel-line-meta { flex: 1 1 auto; color: var(--muted); font-size: var(--fs-meta); min-width: 0; }
.diesel-line-actions { display: inline-flex; align-items: center; gap: 0.35rem; flex: 0 0 auto; }
.diesel-line-actions form { display: inline; }


/* Status badges */
.badge {
  flex-shrink: 0;
  display: inline-block;
  font-size: var(--fs-micro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  white-space: nowrap;
}
.badge-processing   { background: #eef2f8; color: var(--muted); }
.badge-done         { background: #e8f7ee; color: var(--ok); }
.badge-needs_review { background: #fff1e0; color: #b5651d; }
.badge-duplicate    { background: #fdeaea; color: var(--bad); }

/* Review tray */
.review-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  padding: 0.9rem 1.1rem;
  margin-bottom: 0.8rem;
}
.review-card summary { cursor: pointer; font-weight: 600; }
.review-reg { margin-right: 0.5rem; }
.review-why { color: var(--bad); font-weight: 400; font-size: var(--fs-meta); }
.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.75rem;
  margin: 1rem 0;
}
.field { display: flex; flex-direction: column; gap: 0.3rem; font-size: var(--fs-meta); color: var(--muted); }
.field input, .field select {
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 0.95rem;
  color: var(--ink);
}

/* Truck slip tables */
.table-scroll { overflow-x: auto; }
.slip-table { border-collapse: collapse; width: 100%; font-size: 0.85rem; background: var(--card); }
.slip-table th, .slip-table td {
  text-align: left; padding: 0.5rem 0.7rem; border-bottom: 1px solid var(--border); white-space: nowrap;
}
.slip-table th { color: var(--muted); font-weight: 600; }

/* Action column (e.g. diesel "Edit"): pinned to the right edge of the scroll
   area so it's ALWAYS fully in view — never scrolled off or clipped — even when
   the wide table overflows horizontally on a phone. The opaque background +
   left shadow keep it readable over the columns sliding underneath. */
.slip-table th.col-edit,
.slip-table td.col-edit,
.slip-table th.col-del,
.slip-table td.col-del {
  position: sticky;
  right: 0;
  z-index: 1;
  text-align: center;
  background: var(--card);
  box-shadow: -8px 0 8px -6px rgba(31, 39, 51, 0.14);
}
/* Compact button so the pinned action stays narrow inside the dense table. */
.btn-compact { padding: 0.28rem 0.6rem; font-size: 0.8rem; border-width: 1px; }
/* Small square "×" delete button pinned top-right of a dense-table row. */
.col-del { padding-left: 0.35rem; padding-right: 0.35rem; }
.btn-del-x {
  padding: 0; width: 1.9rem; height: 1.9rem; line-height: 1;
  font-size: 1.15rem; font-weight: 700; border-width: 1px; border-radius: 6px;
}

/* Inline consolidated edit (Diesel / POD summary) — one expandable form per row
   (all fields, single Confirm), native <details>, collapsed by default. The
   collapsed state is a compact "Edit" chip that replaces the old per-field links;
   opening reveals the same field-grid used by the Needs Review form. */
.inline-edit { margin: 0.4rem 0 0.2rem; }
.inline-edit > summary {
  cursor: pointer; display: inline-block; list-style: none;
  padding: 0.28rem 0.6rem; font-size: 0.8rem; font-weight: 600;
  border: 1px solid var(--border); border-radius: 8px; color: var(--ink);
}
.inline-edit > summary::-webkit-details-marker { display: none; }
.inline-edit[open] > summary { margin-bottom: 0.2rem; }
.inline-edit .field-grid { margin: 0.6rem 0 0.8rem; }
/* Recent Slips inline Edit: the form drops onto its own full-width line UNDER the
   row (mirroring the POD table's full-width inline-edit row) so the 200px-min field
   grid isn't crushed into the narrow right-hand .slip-actions column. */
.slip-row { flex-wrap: wrap; }
.slip-row > .inline-edit { flex-basis: 100%; margin-top: 0.5rem; }
/* Full-width edit row inside the pours/POD tables: let the form wrap (table
   cells default to nowrap, which would break the grid). */
.slip-table td.inline-edit-cell { white-space: normal; }

/* ------------------------------------------------------------------ *
 * Tyre Inspection (owner-only testing) — top-down schematic          *
 * ------------------------------------------------------------------ */
.tyre-controls { margin: 1rem 0; max-width: 340px; }
.tyre-legend { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; margin: 0.6rem 0 0.2rem; }
.tyre-legend-item { display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: var(--fs-meta); color: var(--muted); font-weight: 600; }
.tyre-swatch { width: 0.85rem; height: 0.85rem; border-radius: 4px; border: 2px solid; flex: none; }

/* Wrapper lets the (now roomier) schematic scroll sideways on the narrowest
   phones instead of squashing the per-position controls. */
.tyre-diagram-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tyre-diagram {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
  width: max-content; min-width: 100%; margin: 1rem auto 1.5rem; padding: 1rem 0.5rem;
}
/* Central vertical spine running the length of the rig (front top -> rear bottom). */
.tyre-diagram::before {
  content: ""; position: absolute; top: 0.5rem; bottom: 0.5rem; left: 50%;
  width: 3px; transform: translateX(-50%); background: var(--border);
  border-radius: 2px; z-index: 0;
}
.tyre-section {
  position: relative; z-index: 1; width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 0.55rem;
  padding: 0.35rem 0;
}
.tyre-section-label {
  font-size: var(--fs-meta); font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.05em;
  background: var(--bg-page); padding: 0 0.5rem;   /* break the spine behind it */
}
.tyre-axle { width: 100%; display: flex; flex-direction: column; align-items: center; gap: 0.2rem; }
.tyre-axle-name { font-size: var(--fs-micro); color: var(--muted); font-weight: 600; }
/* Slots are now tall stacks (tyre + mm + photo), so align them at the top and run
   the axle bar / hub through the TYRE buttons (their vertical centre ≈ 1.5rem). */
.tyre-axle-row { position: relative; display: flex; align-items: flex-start; justify-content: center; gap: 0.6rem; }
.tyre-axle-row::before {   /* the axle bar behind the tyres, across the spine */
  content: ""; position: absolute; top: 1.5rem; left: 10%; right: 10%; height: 3px;
  background: var(--border); transform: translateY(-50%); z-index: -1;
}
.tyre-group { display: flex; gap: 0.4rem; z-index: 1; }
.tyre-hub { width: 0.7rem; height: 0.7rem; background: #9aa3b2; border-radius: 3px;
  flex: none; z-index: 1; align-self: flex-start; margin-top: 1.15rem; }

/* Each position is a vertical stack: the tyre button, the mm input, then (only
   when Needs Replacement) the photo control — with room to breathe. */
/* Slots now stack status + tread depth (+ photo when Needs Replacement), so give
   them a touch more width and breathing room than the status-only slot needed. */
.tyre-slot { display: inline-flex; flex-direction: column; align-items: center; gap: 0.5rem; width: 4.7rem; }
/* Tread-depth field inside a tyre slot: a small caption over the mm input. */
.tyre-tread { display: inline-flex; flex-direction: column; align-items: center; gap: 0.12rem; }
.tyre-tread-lbl { font-size: 0.6rem; font-weight: 700; letter-spacing: 0.02em; color: var(--muted); text-transform: uppercase; }
.tyre-mm { display: inline-flex; align-items: center; gap: 0.2rem; }
.tyre-mm-input {
  width: 2.4rem; padding: 0.28rem 0.2rem; font-size: 0.78rem; text-align: center;
  border: 1.5px solid var(--border); border-radius: 6px; color: var(--ink);
  -moz-appearance: textfield; appearance: textfield;
}
.tyre-mm-input::-webkit-outer-spin-button,
.tyre-mm-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.tyre-mm-unit { font-size: 0.72rem; color: var(--muted); font-weight: 600; }
.tyre-photo { position: relative; display: inline-flex; cursor: pointer; }
.tyre-photo[hidden] { display: none; }
.tyre-photo-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.tyre-photo-btn {
  font-size: 0.66rem; font-weight: 800; line-height: 1.1; text-align: center;
  padding: 0.28rem 0.4rem; border-radius: 6px; white-space: nowrap;
  background: #fdeaea; color: var(--bad); border: 1px dashed var(--bad);
}
.tyre-photo.has-photo .tyre-photo-btn {
  background: #e8f7ee; color: var(--ok); border-style: solid; border-color: var(--ok);
}
.tyre {
  width: 2.5rem; height: 3rem; border-radius: 7px; border: 2px solid;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.58rem; font-weight: 800; letter-spacing: 0.02em;
  cursor: pointer; padding: 0; -webkit-tap-highlight-color: transparent;
  transition: background 0.1s ease, border-color 0.1s ease, transform 0.05s ease;
}
.tyre:active { transform: scale(0.94); }
.tyre-label { pointer-events: none; }
/* Status colours. Compound selectors (.tyre.tyre-*) — specificity (0,2,0) — so they
   OUTRANK the app-wide button:hover / button:focus-visible red (0,1,1). Without this
   a tapped <button> keeps :focus on mobile and gets repainted the button-hover red
   regardless of its real status (the same specificity trap as the Recent-slips
   direction border). The legend swatches (.tyre-swatch.tyre-*) reuse the colours. */
/* Active states use SOLID fills with contrast-checked text (all >= 4.5:1 for this
   small bold label): white on the green/red fills; near-black on amber (white is
   illegible on amber). Unset stays a neutral grey chip. */
.tyre.tyre-unset,   .tyre-swatch.tyre-unset   { background: #e7ebf0; border-color: #b9c0cc; color: #6b7280; }
.tyre.tyre-good,    .tyre-swatch.tyre-good     { background: #177a3e; border-color: #136535; color: #fff; }
.tyre.tyre-ok,      .tyre-swatch.tyre-ok       { background: #e3a500; border-color: #c68f00; color: #231900; }
.tyre.tyre-replace, .tyre-swatch.tyre-replace  { background: #c62222; border-color: #a81b1b; color: #fff; }
/* And neutralise the button-hover/focus box-shadow/filter on tyres so no red halo. */
.tyre:hover, .tyre:focus, .tyre:focus-visible { box-shadow: none; filter: none; }

/* LIGHT positions — a distinct ROUND marker with a lightbulb icon (vs the
   rounded-rect tyre). Reuses the .tyre.tyre-* status colours + tap-to-cycle. */
.tyre-slot-light { width: 3.2rem; gap: 0.25rem; }
.tyre-light { width: 2.2rem; height: 2.2rem; border-radius: 50%; }
.tyre-light-icon { width: 1.15rem; height: 1.15rem; pointer-events: none; }
/* A light row sits at a point on the rig, not on an axle — no axle bar, and the
   hub is just an invisible spacer keeping the left/right pair centred on the spine. */
.tyre-lightrow .tyre-axle-row::before { display: none; }
.tyre-lightrow .tyre-hub { visibility: hidden; }
/* Left/Right caption under a grouped-section light marker. */
.lt-side {
  font-size: 0.58rem; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.02em;
}
/* Tiny shape swatches in the hint so tyre (square) vs light (round) is obvious. */
.tyre-inline-square, .tyre-inline-circle {
  display: inline-block; width: 0.7rem; height: 0.7rem; vertical-align: -1px;
  border: 1.5px solid var(--muted); background: var(--card);
}
.tyre-inline-square { border-radius: 2px; }
.tyre-inline-circle { border-radius: 50%; }

/* ---- Light Inspection: vehicle-level header row + per-section cards ---- */
/* Vehicle-level lights (Orange Light, Reverse Hooter) — standalone, no L/R. */
.lt-vehicle {
  margin: 0.5rem 0 1.1rem; padding: 0.8rem 0.9rem;
  border: 1.5px solid var(--border); border-radius: var(--radius-card);
  background: var(--card); box-shadow: var(--elev-1);
}
.lt-vehicle-title {
  font-size: var(--fs-meta); font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.6rem;
}
.lt-vehicle-row { display: flex; flex-wrap: wrap; gap: 1.4rem; justify-content: center; }
.lt-slot-named { width: auto; min-width: 4.5rem; }
.lt-name {
  font-size: 0.66rem; font-weight: 700; color: var(--ink);
  text-align: center; max-width: 6rem; line-height: 1.15;
}

/* Each grouped section is a card: spine diagram on the left, one Comments field +
   one Photo on the right (a general note/evidence for that section's lights). */
.lt-section-card {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 1.1rem;
  align-items: start; margin: 0 0 1rem; padding: 0.85rem 0.9rem;
  border: 1.5px solid var(--border); border-radius: var(--radius-card);
  background: var(--card); box-shadow: var(--elev-1);
}
.lt-section-diagram { min-width: 0; }
.lt-section-diagram .tyre-diagram { margin: 0.4rem auto 0.2rem; padding: 0.6rem 0.5rem; }
/* Break the spine behind the section label with the CARD's background, not the page. */
.lt-section-card .tyre-section-label { background: var(--card); }
.lt-section-notes { display: flex; flex-direction: column; gap: 0.7rem; }
.lt-comments {
  display: flex; flex-direction: column; gap: 0.3rem;
  font-size: var(--fs-meta); font-weight: 700; color: var(--muted);
}
.lt-comments textarea {
  font: inherit; font-weight: 400; color: var(--ink); width: 100%; resize: vertical;
  min-height: 3.5rem; padding: 0.5rem 0.6rem; border: 1.5px solid var(--border);
  border-radius: 8px; background: var(--bg-page);
}
.lt-photo { position: relative; display: inline-flex; align-self: flex-start; cursor: pointer; }
.lt-photo-input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; }
.lt-photo-btn {
  font-size: 0.72rem; font-weight: 800; line-height: 1.1; text-align: center;
  padding: 0.4rem 0.7rem; border-radius: 8px; white-space: nowrap;
  background: var(--bg-page); color: var(--muted); border: 1px dashed var(--border);
}
.lt-photo.has-photo .lt-photo-btn {
  background: #e8f7ee; color: var(--ok); border-style: solid; border-color: var(--ok);
}
/* Narrow screens: stack the diagram above its comments/photo. */
@media (max-width: 640px) {
  .lt-section-card { grid-template-columns: 1fr; }
}

.tyre-save { margin-top: 0.5rem; }

/* Tabs splitting the one inspection into Tyre / Light / Brake Pad sections.
   All three panels stay in the single form; only one is visible at a time. */
.tyre-tabs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.9rem 0 0.2rem; }
.tyre-tab {
  padding: 0.5rem 0.9rem; border: 1.5px solid var(--border); border-radius: 8px;
  background: var(--card); color: var(--muted); font-weight: 700;
  font-size: var(--fs-meta); cursor: pointer;
}
.tyre-tab.active { background: var(--ink); color: var(--bg-page); border-color: var(--ink); }
/* Neutralise the app-wide button hover/focus red halo on the tabs. */
.tyre-tab:hover, .tyre-tab:focus, .tyre-tab:focus-visible { box-shadow: none; filter: none; }
.tyre-panel { display: none; }
.tyre-panel.active { display: block; }

/* Measurement cell (Weekly tab): the wheel's position label above its mm input. */
.tyre-slot-mm { justify-content: flex-start; }
.tyre-mm-pos {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.2rem; height: 1.5rem; padding: 0 0.35rem;
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.02em;
  color: var(--muted); background: var(--card);
  border: 1.5px solid var(--border); border-radius: 6px;
}
/* Calculated wear percentage shown live under its mm input (brake 21mm=100%,
   tread 11mm=100%). Colour-coded by health, matching the tyre severity swatches:
   green healthy, amber approaching the threshold, red at/below the auto-escalation
   threshold. Base grey applies only to the empty/no-reading state. */
.bp-pct {
  min-height: 0.9rem; font-size: 0.72rem; font-weight: 800;
  letter-spacing: 0.01em; color: var(--muted);
}
/* The % is coloured text on the white card, so it uses darker shades than the
   solid button fills for clear contrast on white (all >= 4.5:1). */
.bp-pct-good { color: #157a41; }          /* healthy — green */
.bp-pct-warn { color: #8a6400; }          /* approaching — amber */
.bp-pct-low  { color: #c62222; }          /* at/below threshold — red */

/* Weekly measurement cell: the position label, then the stacked Brake + Tread
   fields (each = caption + mm input + calculated %). */
.tyre-slot-meas { justify-content: flex-start; gap: 0.3rem; width: auto; min-width: 4.4rem; }
.meas-field { display: inline-flex; flex-direction: column; align-items: center; gap: 0.1rem; }
.meas-lbl {
  font-size: 0.55rem; font-weight: 800; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted);
}
/* Weekly section items — an extensible list, each item its own titled block. */
.wk-item { margin: 0.25rem 0 1.5rem; }
.wk-item-title { font-size: 0.95rem; font-weight: 800; color: var(--ink); margin: 0.5rem 0 0.15rem; }

/* Effective-dated history (Mine Rates / Vendor Diesel Prices) — one grouped list
   per mine/vendor, each row showing its value and calculated effective range. */
.eff-history { list-style: none; margin: 0.1rem 0 1.1rem; padding: 0; }
.eff-history-row { display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.35rem 0.75rem; padding: 0.55rem 0.7rem; margin-bottom: 0.4rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip);
  background: var(--card); }
.eff-history-current { border-color: var(--accent);
  background: var(--safgri-red-tint); }
.eff-history-text { flex: 1 1 auto; color: var(--ink); }
.eff-history-meta { color: var(--muted); font-size: var(--fs-meta); }
.eff-current-badge { color: var(--accent); font-weight: 700; }

/* Monthly Break-Even. */
.month-picker { margin: 0.5rem 0 0.5rem; }
.month-picker input { padding: 0.35rem 0.5rem; border: 1px solid var(--border);
  border-radius: var(--radius-control); background: var(--card); color: var(--ink); }
.be-summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.6rem;
  margin: 1rem 0; }
.be-metric { padding: 0.7rem 0.8rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card); }
.be-metric-label { display: block; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.02em; color: var(--muted); }
.be-metric-value { display: block; font-size: 1.2rem; font-weight: 800; color: var(--ink); }
.be-pos { color: #157a41; }
.be-neg { color: var(--safgri-red); }
.be-progress-text { font-size: var(--fs-body); margin: 0.5rem 0 1rem; }
.be-total-row td { font-weight: 800; border-top: 2px solid var(--border); }
@media (max-width: 620px) { .be-summary { grid-template-columns: 1fr 1fr; } }

/* The climb bar: 0% = opening deficit, centre marker = break-even, 100% = profit. */
.be-climb { margin: 0.6rem 0 0.2rem; }
.be-climb-track { position: relative; height: 18px; border-radius: 999px;
  background: linear-gradient(to right, #fdeaea 0 50%, #e8f7ee 50% 100%);
  border: 1px solid var(--border); overflow: hidden; }
.be-climb-fill { position: absolute; left: 0; top: 0; bottom: 0;
  background: var(--safgri-red); opacity: 0.85; transition: width 0.3s; }
.be-climb-fill.be-climb-profit { background: #157a41; }
.be-climb-marker { position: absolute; left: 50%; top: -2px; bottom: -2px;
  width: 2px; background: var(--ink); transform: translateX(-1px); }
.be-climb-mini { height: 12px; margin: 0.3rem 0; }
.be-climb-legend { display: flex; justify-content: space-between;
  font-size: var(--fs-micro); color: var(--muted); margin-top: 0.25rem; }
.be-climb-be { font-weight: 700; }
.be-focus-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; }

/* Per-truck break-even cards. */
.be-truck-list { display: flex; flex-direction: column; gap: 0.55rem;
  margin: 0.6rem 0 1.2rem; }
.be-truck-card { display: block; padding: 0.7rem 0.9rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  text-decoration: none; color: var(--ink); box-shadow: var(--elev-1);
  transition: border-color 0.15s, box-shadow 0.15s; }
.be-truck-card:hover { border-color: var(--safgri-red); box-shadow: var(--elev-2-accent); }
.be-truck-focus { border-color: var(--safgri-red); border-width: 1.5px; }
.be-truck-head { display: flex; align-items: center; justify-content: space-between;
  gap: 0.6rem; }
.be-truck-reg { font-weight: 800; }
.be-truck-nums { font-size: var(--fs-meta); color: var(--muted); margin-top: 0.2rem; }
.be-badge { font-size: var(--fs-micro); font-weight: 700; padding: 1px 8px;
  border-radius: 999px; background: var(--safgri-red-tint); color: var(--safgri-red-dark);
  white-space: nowrap; }
.be-badge-profit { background: #e8f7ee; color: #157a41; }
.be-badge-muted { background: var(--bg-page); color: var(--muted); }

/* Fixed-costs entry grid. */
.fixed-costs-grid th, .fixed-costs-grid td { white-space: nowrap; }
.fixed-costs-grid .fc-truck { font-weight: 700; }
.fc-input { width: 6.5rem; padding: 0.3rem 0.4rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); text-align: right; }
.fc-eff-picker { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 1rem;
  margin: 0.4rem 0 0.9rem; }
.fc-eff-picker label { font-weight: 700; }
.fc-eff-picker input { margin-left: 0.4rem; }
.fc-eff-picker .hint { flex: 1 1 16rem; margin: 0; }
.fc-history-truck { margin: 0.6rem 0 1.2rem; }
.fc-history-reg { font-size: 1.05rem; margin: 0.8rem 0 0.35rem; }
.fc-history-cat { margin: 0 0 0.5rem; }
.fc-history-cat-name { font-weight: 700; color: var(--muted);
  font-size: var(--fs-meta); text-transform: uppercase; letter-spacing: 0.03em;
  margin: 0 0 0.15rem; }

/* Cost-category list. */
.cat-list { list-style: none; margin: 0.5rem 0 1rem; padding: 0; }
.cat-row { display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 0.6rem 0.9rem; margin-bottom: 0.4rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card); }
.cat-name { font-weight: 700; color: var(--ink); }

/* Driver Safety Scorecards (admin) — two separate metrics per driver. */
.scorecard-list { display: flex; flex-direction: column; gap: 0.7rem;
  margin: 1rem 0 1.5rem; }
.scorecard { padding: 0.9rem 1.1rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--elev-1); }
.scorecard-head { display: flex; flex-direction: column; gap: 0.1rem;
  margin-bottom: 0.6rem; }
.scorecard-name { font-weight: 800; color: var(--ink); }
.scorecard-sub { font-size: var(--fs-meta); color: var(--muted); }
.scorecard-metrics { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; }
.scorecard-metric { display: flex; flex-direction: column; gap: 0.15rem;
  padding: 0.55rem 0.7rem; background: var(--bg-page); border-radius: 8px; }
.scorecard-metric-label { font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.02em; color: var(--muted); }
.scorecard-metric-value { font-size: 1.4rem; font-weight: 800; color: var(--ink); }
.scorecard-metric-detail { font-size: var(--fs-meta); color: var(--muted); }
.scorecard-na { font-size: 0.95rem; font-weight: 600; color: var(--muted); }
.score-good { color: #157a41; }
.score-warn { color: #b25c00; }
.score-bad  { color: var(--safgri-red); }
@media (max-width: 480px) { .scorecard-metrics { grid-template-columns: 1fr; } }

/* Driver dashboard — positive inspection-streak card. */
.streak-card { display: flex; align-items: center; gap: 0.8rem;
  margin: 0 0 1.2rem; padding: 0.85rem 1.1rem;
  background: var(--safgri-red-tint); border: 1px solid var(--danger-border);
  border-radius: var(--radius-card); }
.streak-flame { font-size: 1.9rem; line-height: 1; flex: 0 0 auto; }
.streak-headline { display: block; font-weight: 800; color: var(--safgri-red-dark);
  font-size: 1.05rem; }
.streak-sub { display: block; font-size: var(--fs-meta); color: var(--ink); }

/* Per-mine Revenue tonnage-basis control on Manage Mine Rates. */
.mine-basis { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem;
  margin: 0.1rem 0 0.6rem; }
.mine-basis-label { font-size: var(--fs-meta); color: var(--muted); font-weight: 600; }
.mine-terms { display: inline-flex; align-items: center; gap: 0.35rem; margin: 0; }
.mine-basis select { padding: 0.3rem 0.5rem; border: 1px solid var(--border);
  border-radius: var(--radius-control); background: var(--card); color: var(--ink);
  font-size: 0.9rem; }
.mine-basis-default { font-size: var(--fs-micro); font-weight: 700; letter-spacing: 0;
  padding: 1px 7px; border-radius: 999px; color: var(--muted);
  background: var(--bg-page); }

/* ---- Daily Inspection: a flat single-column checklist of grouped items ---- */
.di-list { display: flex; flex-direction: column; gap: 0.75rem; margin: 0.75rem 0 0.5rem; }
.di-group {
  display: flex; flex-direction: column; gap: 0.4rem;
  padding: 0.5rem; border: 1.5px solid var(--border);
  border-radius: var(--radius-card); background: var(--card); box-shadow: var(--elev-1);
}
/* Sub-headed blocks (Prop Shaft / General Inspection): a bold uppercase heading
   that stays visually distinct without an underline. */
.di-group-headed { padding-top: 0.35rem; }
.di-heading {
  margin: 0.15rem 0 0.35rem;
  font-size: 0.82rem; font-weight: 800; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink);
}
/* One checklist row: icon + text on the left, colored toggle on the right; an
   optional comment field spans the full width below. */
.di-item {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 0.4rem 0.75rem; padding: 0.4rem 0.35rem;
  border-top: 1px solid var(--border);
}
.di-group > .di-item:first-of-type { border-top: 0; }
.di-main { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.di-ico {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: 8px;
  background: var(--bg-page); color: var(--muted); border: 1px solid var(--border);
}
.di-icon { width: 1.2rem; height: 1.2rem; }
.di-text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.di-label { font-weight: 700; font-size: 0.92rem; color: var(--ink); }
.di-hint { font-size: 0.72rem; color: var(--muted); font-style: italic; }

/* The toggle button: a pill that reuses the tyre status palette. Fixed min-width
   so the label switching between states doesn't jump the layout. */
.di-btn {
  min-width: 7.5rem; padding: 0.5rem 0.7rem; border-radius: 8px; border: 2px solid;
  font-weight: 800; font-size: 0.78rem; letter-spacing: 0.01em; cursor: pointer;
  text-align: center; -webkit-tap-highlight-color: transparent;
  transition: background 0.1s ease, border-color 0.1s ease, transform 0.05s ease;
}
.di-btn:active { transform: scale(0.97); }
.di-btn:hover, .di-btn:focus, .di-btn:focus-visible { box-shadow: none; filter: none; }
/* State colours mirror the tyre swatches: green (pass/good), amber (ok),
   red (fail/attention), grey (unset). */
/* Solid fills + contrast-checked text, matching the tyre status buttons (white on
   green/red; near-black on amber). COMPOUND selectors (.di-btn.di-*) — specificity
   (0,2,0) — so they OUTRANK the app-wide button:hover / :active red (0,1,1) and the
   status colour never flashes to red on tap (the amber's dark label especially). */
.di-btn.di-unset            { background: #e7ebf0; border-color: #b9c0cc; color: #6b7280; }
.di-btn.di-pass, .di-btn.di-good   { background: #177a3e; border-color: #136535; color: #fff; }
.di-btn.di-ok               { background: #e3a500; border-color: #c68f00; color: #231900; }
.di-btn.di-fail, .di-btn.di-attention { background: #c62222; border-color: #a81b1b; color: #fff; }
/* Yes/No items (SCM spare-wheel): Yes = green (present/good), No = amber (attention). */
.di-btn.di-yes              { background: #177a3e; border-color: #136535; color: #fff; }
.di-btn.di-no               { background: #e3a500; border-color: #c68f00; color: #231900; }

/* Comment field on the two commentable items — full width under the row. */
.di-comment {
  grid-column: 1 / -1; display: flex; flex-direction: column; gap: 0.25rem;
  font-size: 0.72rem; font-weight: 700; color: var(--muted);
}
.di-comment input {
  font: inherit; font-weight: 400; color: var(--ink);
  padding: 0.45rem 0.6rem; border: 1.5px solid var(--border);
  border-radius: 8px; background: var(--bg-page);
}

.di-control { display: inline-flex; align-items: center; gap: 0.5rem; justify-self: end; }
/* Mandatory evidence photo on a daily item (Fail / Needs Attention). Spans the full
   row below the toggle; reuses the .tyre-photo overlay + red-dashed "Add photo" chip. */
.di-photo { grid-column: 1 / -1; align-self: start; }
.di-photo.tyre-photo { display: inline-flex; }
.di-photo[hidden] { display: none; }

/* The embedded Light Inspection step: a REQUIRED, expandable block within the
   Daily checklist. The <summary> is the row (icon + label + progress badge); the
   body holds the full 22-position light interface (reused as-is). */
.di-lights-step { display: block; padding: 0; }
.di-lights-summary {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  padding: 0.55rem 0.35rem; cursor: pointer; list-style: none;
}
.di-lights-summary::-webkit-details-marker { display: none; }
.di-lights-summary::marker { content: ""; }
.di-lights-step[open] > .di-lights-summary { border-bottom: 1px solid var(--border); }
.di-required {
  display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.42rem;
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--bad); background: #fdeaea; border: 1px solid var(--bad);
  border-radius: 999px; vertical-align: 1px;
}
.di-lights-body { padding: 0.4rem 0.15rem 0.3rem; }

/* Progress badge on the Lights step: n/22 → green Done ✓ once every position is set. */
.di-lights-badge {
  flex: none; font-size: 0.72rem; font-weight: 800; color: var(--muted);
  padding: 0.25rem 0.5rem; border-radius: 999px; background: #e7ebf0; white-space: nowrap;
}
.di-lights-badge.di-done { background: #e8f7ee; color: var(--ok); }

@media (max-width: 480px) {
  .di-item { grid-template-columns: 1fr; }
  .di-control { justify-self: stretch; }
  .di-btn { width: 100%; }
}

/* ------------------------------------------------------------------ *
 * Notifications feature: Account Settings button, owner→driver
 * messaging, driver messages + tile badges.
 * ------------------------------------------------------------------ */
/* Shared empty-state card (Account Settings, messaging, driver messages). */
.empty-card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 1.25rem 1.4rem; margin: 1.25rem 0;
}
.empty-card p { margin: 0.35rem 0; }
.empty-card p:first-child { font-weight: 600; color: var(--ink); }

/* ---- Owner: message-drivers composer ---- */
.msg-form { margin: 1.25rem 0 2rem; }
.msg-compose { position: relative; }
.msg-field-label {
  display: block; font-weight: 700; color: var(--ink);
  font-size: var(--fs-meta); margin-bottom: 0.4rem;
}
.msg-compose textarea {
  width: 100%; resize: vertical; min-height: 5.5rem;
  border: 1.5px solid var(--border); border-radius: 10px;
  padding: 0.7rem 0.8rem; font: inherit; color: var(--ink);
  background: var(--card);
}
.msg-compose textarea:focus-visible {
  outline: none; border-color: var(--safgri-red);
}
.msg-count {
  display: block; text-align: right; margin-top: 0.25rem;
  font-size: var(--fs-micro); color: var(--muted);
}
.msg-recipients-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem; margin-top: 1.25rem; flex-wrap: wrap;
}
.msg-recipients-head .section-head { margin: 0; }
.msg-selectall {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: var(--fs-meta); font-weight: 600; color: var(--safgri-red);
  cursor: pointer;
}
.msg-selectall input { width: 1.05rem; height: 1.05rem; accent-color: var(--safgri-red); }
.msg-driver-list { list-style: none; margin: 0.9rem 0 1.5rem; padding: 0;
  display: flex; flex-direction: column; gap: 0.5rem; }
.msg-driver-row { margin: 0; }
.msg-driver {
  display: flex; align-items: center; gap: 0.7rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 0.65rem 0.85rem; cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.msg-driver:hover { border-color: var(--safgri-red); }
.msg-driver input {
  width: 1.15rem; height: 1.15rem; flex: 0 0 auto;
  accent-color: var(--safgri-red);
}
.msg-driver input:checked ~ .msg-driver-info .msg-driver-name { color: var(--safgri-red); }
.msg-driver-info { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.msg-driver-name { font-weight: 700; color: var(--ink); }
.msg-driver-meta { font-size: var(--fs-meta); color: var(--muted); }
.msg-send { margin-top: 0.25rem; }

/* ---- Driver: message history ---- */
.dmsg-list { list-style: none; margin: 1.25rem 0; padding: 0;
  display: flex; flex-direction: column; gap: 0.7rem; }
.dmsg-card {
  background: var(--card); border: 1px solid var(--border);
  border-left: 4px solid var(--border); border-radius: var(--radius-card);
  padding: 0.85rem 1rem;
}
.dmsg-card.dmsg-unread {
  border-left-color: var(--safgri-red); background: var(--safgri-red-tint);
}
.dmsg-text { margin: 0 0 0.4rem; color: var(--ink); white-space: pre-wrap;
  word-break: break-word; line-height: 1.4; }
.dmsg-time { font-size: var(--fs-meta); color: var(--muted); }

/* ---- Badges: unread messages on the driver home ---- */
.driver-tile-badge, .driver-msg-badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.35rem; height: 1.35rem; padding: 0 0.4rem;
  margin-left: 0.35rem; border-radius: 999px;
  background: var(--safgri-red); color: #fff;
  font-size: var(--fs-micro); font-weight: 700; line-height: 1;
  vertical-align: middle;
}
.driver-home-actions { display: flex; justify-content: flex-end; margin: 0 0 1rem; }
.driver-msg-link { display: inline-flex; align-items: center; }
/* A heading that sits straight on the home photo (the driver's "Choose your
   truck"): a subtle dark frosted panel with white text, so it meets WCAG AA over
   any part of the photo. Only on the photo. */
body.home-bg .photo-heading {
  display: inline-block;
  max-width: 100%;
  margin: 0 0 1.25rem;
  padding: 0.7rem 1rem;
  border-radius: var(--radius-card);
  background: rgba(12, 15, 20, 0.62);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
body.home-bg .photo-heading .page-title { color: #fff; }
body.home-bg .photo-heading .subtitle { color: rgba(255, 255, 255, 0.92); margin: 0; }
body.home-bg .driver-msg-link {           /* readable on the photo backdrop */
  background: rgba(255, 255, 255, 0.92);
}

/* ------------------------------------------------------------------ *
 * Remittance Advice import — preview (header + classified row lists).
 * ------------------------------------------------------------------ */
.rem-header {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.5rem 1.25rem; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 0.9rem 1.1rem; margin: 0 0 1.25rem;
}
.rem-list { list-style: none; margin: 0.6rem 0 1.4rem; padding: 0;
  display: flex; flex-direction: column; gap: 0.4rem; }
.rem-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  background: var(--card); border: 1px solid var(--border);
  border-left: 4px solid var(--border); border-radius: var(--radius-card); padding: 0.6rem 0.85rem;
}
.rem-row.rem-new { border-left-color: var(--ok); }
.rem-row.rem-backfill { border-left-color: #2f7ec4; }
.rem-row.rem-matched { border-left-color: var(--border); }
.rem-row.rem-adjustment { border-left-color: #b58a1d; }
.rem-row-main { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.rem-reg { font-weight: 700; color: var(--ink); }
.rem-inherit { font-weight: 400; color: var(--muted); font-size: var(--fs-meta); }
.rem-meta { font-size: var(--fs-meta); color: var(--muted); word-break: break-word; }
.rem-badge {
  flex: 0 0 auto; font-size: var(--fs-micro); font-weight: 700; line-height: 1;
  border-radius: 999px; padding: 0.25rem 0.55rem; white-space: nowrap; text-align: right;
  background: #eef2f8; color: var(--muted);
}
.rem-badge-new { background: #e8f7ee; color: var(--ok); }
.rem-badge-backfill { background: #e7f0ff; color: #1c4fbf; }
.rem-badge-adjustment { background: #fbf1d8; color: #8a6a12; }

/* Remittance preview — processing (background read) state. */
.rem-processing {
  display: flex; align-items: center; gap: 0.9rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 1rem 1.1rem; margin: 0.5rem 0 1rem;
}
.rem-processing-title { margin: 0 0 0.2rem; font-weight: 700; color: var(--ink); }
/* .rem-spinner is the large .spinner — see the busy-state section. */
.rem-warnings { margin: 0.4rem 0 0; padding-left: 1.15rem; font-size: var(--fs-meta); }
.rem-warnings li { margin: 0.1rem 0; }

/* Remittance history — cards with an embedded first-page PDF preview that opens
   the full document on tap. */
.rem-hist-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.9rem; margin: 0.9rem 0 1.5rem;
}
.rem-hist-item { position: relative; display: flex; }
.rem-hist-item > .rem-hist-card { flex: 1 1 auto; width: 100%; }
.rem-hist-card {
  display: flex; flex-direction: column; text-decoration: none;
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  overflow: hidden; transition: border-color 0.15s, box-shadow 0.15s, transform 0.1s;
}
.rem-hist-card:hover, .rem-hist-card:focus-visible {
  border-color: var(--safgri-red); box-shadow: var(--elev-2);
  outline: none;
}
.rem-hist-card:active { transform: translateY(1px); }
.rem-hist-preview {
  position: relative; display: block; width: 100%; aspect-ratio: 3 / 4;
  background: #f4f5f7; border-bottom: 1px solid var(--border); overflow: hidden;
}
/* First-page PNG thumbnail — a plain <img>, so it renders on every device. */
.rem-hist-thumb {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: top center; display: block;
}
/* Delete (×) — top-right corner of each history card. */
.rem-hist-del { position: absolute; top: 5px; right: 5px; z-index: 3; margin: 0; }
.rem-hist-del-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0; border-radius: 50%;
  background: rgba(255, 255, 255, 0.94); color: var(--muted);
  border: 1px solid var(--border); box-shadow: 0 1px 3px rgba(31, 39, 51, 0.2);
  font-size: 1.05rem; line-height: 1; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.rem-hist-del-btn:hover, .rem-hist-del-btn:focus-visible {
  background: var(--danger-bg); color: var(--danger-fg);
  border-color: var(--danger-border); outline: none;
}
/* "Open PDF" affordance — always visible on touch, emphasised on hover. */
.rem-hist-open {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 0.3rem 0.5rem; font-size: var(--fs-micro); font-weight: 700;
  color: #fff; background: rgba(139, 30, 45, 0.86); text-align: center;
  opacity: 0.92; transition: opacity 0.15s;
}
.rem-hist-card:hover .rem-hist-open { opacity: 1; }
.rem-hist-meta { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.55rem 0.7rem; }
.rem-hist-doc { font-weight: 700; color: var(--ink); font-size: var(--fs-meta);
  word-break: break-word; }
.rem-hist-date { font-size: var(--fs-micro); color: var(--muted); }

/* Remittance history — placeholder for imports done before PDF storage existed. */
.rem-hist-card-nopdf { cursor: default; }
.rem-hist-preview-empty {
  display: flex; align-items: center; justify-content: center;
  background: repeating-linear-gradient(-45deg, #f0f1f4, #f0f1f4 8px, #e9ebef 8px, #e9ebef 16px);
}
.rem-hist-nopdf-mark {
  font-size: var(--fs-micro); font-weight: 700; color: var(--muted);
  background: rgba(255, 255, 255, 0.9); border: 1px solid var(--border);
  border-radius: 6px; padding: 0.2rem 0.5rem; text-align: center;
}

/* Remittance preview — confirm a flagged transposition typo as a real truck. */
.rem-confirm {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  flex-wrap: wrap;
  background: #fff7ea; border: 1px solid #f0d9a8; border-left: 4px solid #b58a1d;
  border-radius: var(--radius-card); padding: 0.6rem 0.85rem; margin: 0 0 0.6rem;
}
.rem-confirm-text { font-size: var(--fs-meta); color: var(--ink); min-width: 0; }
.rem-confirm form { margin: 0; flex: 0 0 auto; }

/* Remittance in-app PDF viewer — pages as images, with explicit Back controls. */
.rem-view-actions { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; margin: 0.4rem 0 1.1rem; }
.rem-view-pages { display: flex; flex-direction: column; gap: 1rem; align-items: center; }
.rem-view-page {
  max-width: 100%; width: 820px; height: auto; display: block; background: #fff;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  box-shadow: var(--elev-1);
}

/* Inspection detail: Back + Delete on one row. */
.inspection-detail-actions { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-top: 1.75rem; }
.inspection-detail-actions form { margin: 0; }
/* Inline delete forms inside inspection tables shouldn't add block spacing. */
.slip-table td form { margin: 0; display: inline; }

/* ------------------------------------------------------------------ *
 * Data Health dashboard — owner-only diagnostics.
 * ------------------------------------------------------------------ */
.dh-section {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-card);
  margin: 0 0 0.7rem; overflow: hidden;
}
/* The offloading-before-loading violation is always a real error — call it out. */
.dh-alert {
  background: var(--danger-bg); color: var(--danger-fg);
  border: 1px solid var(--danger-fg); border-radius: var(--radius-card);
  padding: 0.8rem 1.05rem; margin: 0 0 0.9rem; line-height: 1.4;
}
.dh-alert a { color: inherit; font-weight: 700; white-space: nowrap; }
.dh-section-critical { border-color: var(--danger-fg); border-width: 2px; }
.dh-section-critical .dh-title { color: var(--danger-fg); }
.dh-summary {
  display: flex; align-items: center; gap: 0.6rem; cursor: pointer;
  padding: 0.85rem 1.05rem; list-style: none; -webkit-tap-highlight-color: transparent;
}
.dh-summary::-webkit-details-marker { display: none; }
.dh-summary::marker { content: ""; }
.dh-title { font-weight: 700; color: var(--ink); flex: 1 1 auto; min-width: 0; }
.dh-count {
  flex: 0 0 auto; min-width: 1.6rem; text-align: center;
  font-size: var(--fs-micro); font-weight: 800; line-height: 1;
  border-radius: 999px; padding: 0.22rem 0.5rem;
}
.dh-count-ok   { background: #e8f7ee; color: var(--ok); }
.dh-count-flag { background: var(--danger-bg); color: var(--danger-fg); }
.dh-caret { flex: 0 0 auto; color: var(--muted); font-size: 0.85rem; transition: transform 0.15s; }
.dh-section[open] .dh-caret { transform: rotate(180deg); }
.dh-body { padding: 0 1.05rem 0.9rem; border-top: 1px solid var(--border); }
.dh-desc { margin: 0.7rem 0 0.6rem; }
.dh-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.dh-item {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  background: var(--bg-page); border: 1px solid var(--border); border-radius: 8px;
  padding: 0.5rem 0.7rem;
}
.dh-item-main { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.dh-item-title { font-weight: 600; color: var(--ink); font-size: var(--fs-meta); word-break: break-word; }
.dh-item-detail { font-size: var(--fs-micro); color: var(--muted); }
.dh-item-link {
  flex: 0 0 auto; color: var(--safgri-red); font-weight: 700; font-size: var(--fs-meta);
  text-decoration: none;
}
.dh-item-link:hover, .dh-item-link:focus-visible { color: var(--safgri-red-dark); }
.dh-clear { margin: 0.4rem 0 0.2rem; color: var(--ok); font-weight: 600; font-size: var(--fs-meta); }

/* Predictive-wear table row for a position flagged as an alignment/pressure fault. */
.wear-align { background: #fdeaea; }

/* --------------------------------------------------------------------------- */
/* Print stylesheet — clean, report-only output when a page is printed directly */
/* from the browser (NOT the dedicated reportlab PDF exports, which never touch  */
/* this CSS). Hides all chrome/controls and shows only the data, with a branded  */
/* header. Applies globally; the report-style pages (Load Log, Diesel Pours,     */
/* Break-Even, Invoicing/detail, etc.) benefit most.                            */
/* --------------------------------------------------------------------------- */
.print-only { display: none; }              /* hidden on screen; shown in print */

@media print {
  @page { margin: 14mm; }

  /* Ink-true colours (status badges, table shading) + a clean white page. */
  html, body {
    background: #fff !important; color: #000 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact;
    font-size: 11pt;
  }
  body.home-bg, body { background-image: none !important; }

  /* --- Hide all navigation / chrome / transient UI --- */
  .topbar, .preview-banner, .idle-warning, #idle-warning, .home-menu, .notif-bell,
  .topbar-notif-msg, .flash, .login-install, .login-history-filter, .no-print,
  .attn-badge, .health-badge, .attn-pop, .trucks-status-btn, .fleet-health-sub {
    display: none !important;
  }

  /* --- Hide interactive controls (buttons, edit/delete, toggles, filters) --- */
  button, input, select, textarea,
  .btn-danger, .btn-small, .backlink, .home-link, .export-record-btn,
  .invoice-gen-btn, .tyre-save, .svc-btn, .service-toggle, .relief-toggle,
  .dash-breakdown-form, .reinvoice, .mine-terms, .invoice-range, .invoice-bulk,
  .invoice-truck-bulk, .doc-upload, .tool-check-form, form.natis-upload {
    display: none !important;
  }

  /* --- Branded print header at the top of the report --- */
  .print-header.print-only {
    display: flex; align-items: center; gap: 0.6rem;
    border-bottom: 2px solid #8B1E2D; padding: 0 0 8px; margin: 0 0 14px;
  }
  .print-header .print-logo { max-height: 46px; width: auto; }
  .print-header .print-title { font-size: 15pt; font-weight: 800; color: #000; }

  /* --- Content fills the page --- */
  .content { max-width: none !important; margin: 0 !important; padding: 0 !important; }
  .table-scroll { overflow: visible !important; }
  * { box-shadow: none !important; text-shadow: none !important; }
  a { color: inherit !important; text-decoration: none !important; }

  /* --- Typography --- */
  .page-title { font-size: 17pt; margin: 0 0 0.3rem; }
  .section-head { font-size: 12.5pt; margin: 0.9rem 0 0.35rem; }
  .subtitle, .hint { color: #333 !important; }

  /* --- Tables print full-width with visible rules + repeated headers --- */
  table, .slip-table { width: 100% !important; border-collapse: collapse !important; }
  .slip-table th, .slip-table td, table th, table td {
    border: 1px solid #999 !important; padding: 4px 6px !important;
  }
  thead { display: table-header-group; }     /* repeat header on each printed page */
  tr, td, th, img { page-break-inside: avoid; }

  /* --- Keep report blocks/cards intact across page breaks --- */
  .be-truck-card, .truck-item, .wk-item, .insp-section, .be-summary, .streak-card,
  .fleet-health-banner, .ctrack-panel, .truck-dash-tiles {
    page-break-inside: avoid;
  }

  /* --- Collapsible <details> print fully expanded (so nothing is hidden). --- */
  details[open] > summary, details > summary { list-style: none; }
  details:not([open]) > :not(summary) { display: block !important; }
}

/* --------------------------------------------------------------------------- */
/* Empty-state component (_empty.html) — one consistent pattern: small icon +   */
/* friendly one-line message + optional CTA. neutral (grey) vs positive (green). */
/* --------------------------------------------------------------------------- */
.empty-state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 0.5rem; padding: 1.75rem 1.25rem; margin: 1.25rem 0;
  border: 1px dashed var(--border, #d9d9d9); border-radius: var(--radius-card, 12px);
  background: var(--card, #fafbfc);
}
.empty-state-icon { width: 34px; height: 34px; color: var(--muted, #6b7280); opacity: 0.75; }
.empty-state-msg { margin: 0; font-weight: 600; color: var(--ink, #333); }
.empty-state-sub { font-size: var(--fs-meta, 0.85rem); color: var(--muted, #6b7280); max-width: 40ch; }
.empty-state-cta { font-weight: 700; color: var(--safgri-red, #8B1E2D); text-decoration: none; }
.empty-state-cta:hover, .empty-state-cta:focus { text-decoration: underline; }
.empty-state-positive {
  border-color: rgba(21, 122, 65, 0.35); background: rgba(21, 122, 65, 0.06);
}
.empty-state-positive .empty-state-icon { color: var(--good, #157a41); opacity: 1; }
.empty-state-positive .empty-state-msg { color: var(--good, #157a41); }

/* ------------------------------------------------------------------------- */
/* Route Profitability Calculator (Safgri-only planning tool).               */
/* ------------------------------------------------------------------------- */
.rc-testing-tag { display: inline-block; margin-left: 0.4rem; padding: 0.05rem 0.45rem;
  font-size: var(--fs-meta); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: #fff; background: var(--muted); border-radius: 999px;
  vertical-align: middle; }
.rc-setup { margin: 0.6rem 0 1rem; }
.rc-setup-steps { margin: 0.5rem 0; padding-left: 1.2rem; }
.rc-setup-steps li { margin: 0.2rem 0; }
.rc-setup code { background: rgba(0,0,0,0.06); padding: 0.05rem 0.3rem; border-radius: 4px; }

.rc-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 1.2rem; align-items: start; }
@media (max-width: 860px) { .rc-grid { grid-template-columns: 1fr; } }

.rc-endpoints { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 0.6rem; }
.rc-field { display: flex; flex-direction: column; gap: 0.2rem; font-weight: 600; }
.rc-field input { font-weight: 400; padding: 0.4rem 0.5rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); }
.rc-field-note { font-weight: 400; color: var(--muted); font-size: var(--fs-meta); }
.rc-clickmode { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.8rem;
  font-size: var(--fs-meta); }
.rc-clickmode-label { color: var(--muted); font-weight: 700; }
.rc-clickmode label { display: inline-flex; align-items: center; gap: 0.25rem; }
.rc-map-actions { margin-left: auto; display: inline-flex; flex-wrap: wrap; gap: 0.4rem; }
.rc-map-actions button[disabled] { opacity: 0.45; cursor: not-allowed; }
#rc-undo { font-weight: 700; }
/* Edit-route toggle (touch only): clearly shows locked vs unlocked state. */
.rc-edit-btn { font-weight: 700; }
.rc-edit-btn.rc-edit-on { background: var(--good, #157a41); border-color: var(--good, #157a41);
  color: #fff; }

/* Pinned-waypoints list: numbered, each individually removable. */
.rc-pins { margin: 0.5rem 0 0.2rem; }
.rc-pins-head { font-size: var(--fs-meta); color: var(--muted); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 0.3rem; }
.rc-pins-list { list-style: none; margin: 0; padding: 0; display: flex;
  flex-direction: column; gap: 0.3rem; }
.rc-pin-row { display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem; padding: 0.35rem 0.5rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); background: #fff; }
.rc-pin-label { font-size: 0.9rem; }
.rc-pin-remove { flex: 0 0 auto; }

.rc-map { width: 100%; height: 440px; border: 1px solid var(--border);
  border-radius: var(--radius-card, 10px); overflow: hidden; background: #eef0f2;
  position: relative; }   /* anchors .rc-map-error over the map */
@media (max-width: 860px) { .rc-map { height: 320px; } }
.rc-map-placeholder { display: flex; align-items: center; justify-content: center;
  height: 100%; color: var(--muted); font-style: italic; text-align: center; padding: 1rem; }

/* Shown in place of the map when Google rejects the key or the script is
   blocked, so the failure is readable on the device that hit it. */
.rc-map-error { position: absolute; inset: 0; z-index: 3; overflow-y: auto;
  display: flex; flex-direction: column; justify-content: center;
  gap: 0.55rem; padding: 1.1rem 1.25rem; text-align: left;
  background: var(--danger-bg); color: var(--danger-fg); }
.rc-map-error[hidden] { display: none; }
.rc-map-error-title { font-weight: 700; font-size: 1.05rem; }
.rc-map-error-body { margin: 0; font-size: 0.92rem; line-height: 1.45; }
.rc-map-error-meta { display: grid; grid-template-columns: max-content 1fr;
  gap: 0.2rem 0.7rem; margin: 0.2rem 0 0; font-size: 0.85rem; }
.rc-map-error-meta dt { color: var(--danger-fg); opacity: 0.75; }
.rc-map-error-meta dd { margin: 0; font-family: ui-monospace, SFMono-Regular,
  Menlo, Consolas, monospace; word-break: break-all; }
.rc-map-error-hint { margin: 0.35rem 0 0; font-size: 0.8rem; opacity: 0.8; }
@media (max-width: 860px) {
  .rc-map-error { padding: 0.9rem 1rem; gap: 0.45rem; }
  .rc-map-error-title { font-size: 0.98rem; }
  .rc-map-error-body { font-size: 0.87rem; }
  .rc-map-error-meta { grid-template-columns: 1fr; gap: 0 0; }
  .rc-map-error-meta dt { margin-top: 0.3rem; }
}
.rc-drag-hint { margin-top: 0.35rem; }

.rc-inputs-col { display: flex; flex-direction: column; gap: 0.7rem; }
.rc-input-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.rc-toggle { display: flex; gap: 0.5rem; align-items: flex-start; font-size: 0.92rem;
  padding: 0.5rem 0.6rem; background: var(--safgri-red-tint, rgba(0,0,0,0.03));
  border-radius: var(--radius-chip); }
.rc-toggle input { margin-top: 0.15rem; }

.rc-results { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem;
  margin: 0.4rem 0 0.2rem; }
.rc-result { display: flex; flex-direction: column; gap: 0.1rem; padding: 0.5rem 0.6rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip); background: #fff; }
.rc-result-label { font-size: var(--fs-meta); color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.03em; }
.rc-result-value { font-size: 1.05rem; font-weight: 700; }
.rc-result-key { border-color: var(--accent); background: var(--safgri-red-tint, rgba(0,0,0,0.03)); }
.rc-result-key .rc-result-value { color: var(--accent-dark, var(--accent)); }

.reuse-blocked { margin: 0 0 0.8rem; padding: 0.6rem 0.7rem;
  border: 1px solid var(--safgri-red); border-radius: var(--radius-chip);
  background: #fdeaea; font-size: var(--fs-meta); }

.reuse-pending { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
  margin: 0.5rem 0; padding: 0.5rem 0.65rem;
  border: 1px solid var(--accent); border-radius: var(--radius-chip);
  background: var(--safgri-red-tint, rgba(0,0,0,0.03)); font-size: var(--fs-meta); }
.reuse-pending-form { display: inline; margin: 0; }

.reuse-warn { border: 1px solid var(--accent); border-radius: var(--radius-chip);
  background: var(--safgri-red-tint, rgba(0,0,0,0.03));
  padding: 0.8rem 0.9rem; margin: 0.6rem 0 1rem; }
.reuse-lead { margin: 0 0 0.5rem; font-size: 1.02rem; }
.reuse-assume { margin: 0; font-size: var(--fs-meta); }
.reuse-longgap { margin: 0.5rem 0 0; font-weight: 700;
  color: var(--accent-dark, var(--accent)); font-size: var(--fs-meta); }
.reuse-actions { display: flex; align-items: center; gap: 0.9rem; margin-top: 0.8rem; }

.rem-preview-head { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0.6rem 0; }
.rem-preview-fact { flex: 1 1 10rem; padding: 0.55rem 0.7rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-chip); }
.rem-preview-label { display: block; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.rem-preview-value { display: block; font-size: 1.1rem; font-weight: 800; }
.rem-preview-totals { max-width: 26rem; margin-left: auto; }
.rem-row-deduction { color: var(--muted); }
.slip-table td.num, .slip-table th.num { text-align: right; white-space: nowrap; }
.rem-preview-actions { display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.8rem; margin: 1rem 0 0.4rem; }
.rem-preview-actions form { margin: 0; }

.rem-nopod-warn { margin: 0.5rem 0; padding: 0.55rem 0.7rem;
  border: 1px solid var(--accent); border-radius: var(--radius-chip);
  background: var(--safgri-red-tint, rgba(0,0,0,0.03));
  font-size: var(--fs-meta); }

/* Diesel bonus payouts */
.pay-buildup-tight { margin-bottom: 0.5rem; }
.pay-line.is-note { color: var(--muted); font-size: var(--fs-meta); }
.pay-note-warn { color: var(--accent-dark, var(--accent)); font-weight: 600; }
.dl-entry.is-voided { opacity: 0.6; text-decoration: line-through; }
.dl-entry.is-voided .badge, .dl-entry.is-voided .dl-entry-meta { text-decoration: none; }
.dl-entry-action { display: flex; gap: 0.4rem; align-items: center; margin-top: 0.3rem; }
.dl-entry-action input { flex: 1 1 8rem; padding: 0.3rem 0.4rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip);
  font-size: var(--fs-meta); }
.sal-part-note { display: block; font-size: var(--fs-meta); color: var(--muted);
  margin-top: 0.15rem; }
.sal-paid { border: 1px solid var(--border); border-radius: var(--radius-chip);
  background: var(--safgri-red-tint, rgba(0,0,0,0.03));
  padding: 0.6rem 0.7rem; margin: 0.6rem 0; }
.sal-paid-head { margin: 0 0 0.35rem; font-weight: 700; font-size: 0.95rem; }
.sal-paid-list { margin: 0; padding-left: 1.1rem; }
.sal-paid-list li { margin-bottom: 0.2rem; }
.sal-paid-foot { margin: 0.45rem 0 0; font-size: var(--fs-meta); color: var(--muted); }

.load-credit { flex: 1 1 100%; display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 0.5rem; margin-top: 0.3rem; }
.load-credit-who { font-size: var(--fs-meta); color: var(--muted); }

/* "Change driver" correction control — shared by the Salaries detail view and the
   Load Log. Collapsed by default so a per-load table is not buried in forms. */
.credit-fix { margin-top: 0.25rem; }
.credit-fix-toggle { cursor: pointer; font-size: var(--fs-meta); color: var(--muted);
  text-decoration: underline; list-style: none; }
.credit-fix-toggle::-webkit-details-marker { display: none; }
.credit-fix[open] .credit-fix-toggle { color: var(--accent-dark, var(--accent)); }
.credit-fix-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem;
  margin-top: 0.4rem; padding: 0.55rem 0.6rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); background: var(--safgri-red-tint, rgba(0,0,0,0.03)); }
.credit-fix-field { display: flex; flex-direction: column; gap: 0.2rem;
  font-size: var(--fs-meta); font-weight: 600; flex: 1 1 12rem; }
.credit-fix-field select, .credit-fix-field input { font-weight: 400;
  padding: 0.35rem 0.45rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); }
.credit-fix-opt { font-weight: 400; color: var(--muted); }
.credit-fix-warn { flex: 1 1 100%; margin: 0; font-size: var(--fs-meta);
  color: var(--accent-dark, var(--accent)); }
.credit-fix-log { margin: 0.4rem 0 0; padding-left: 1rem; font-size: var(--fs-meta);
  color: var(--muted); }
.credit-fix-log li { margin-bottom: 0.15rem; }
.credit-fix-note { font-style: italic; }

/* ETA — a time, not money, so it sits apart from the .rc-results grid and reads
   as one line per answer rather than a tile. */
.rc-eta { border: 1px solid var(--accent); border-radius: var(--radius-chip);
  background: var(--safgri-red-tint, rgba(0,0,0,0.03));
  padding: 0.55rem 0.6rem; margin: 0.2rem 0 0.4rem; }
.rc-eta-line { display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.6rem; }
.rc-eta-line + .rc-eta-line { margin-top: 0.35rem; padding-top: 0.35rem;
  border-top: 1px solid var(--border); }
.rc-eta-value { font-size: 1.05rem; font-weight: 700;
  color: var(--accent-dark, var(--accent)); white-space: nowrap; }
.rc-eta-secondary .rc-eta-value { font-size: 0.95rem; font-weight: 600;
  color: var(--text, inherit); }
.rc-eta-note { margin: 0.35rem 0 0; font-size: var(--fs-meta); color: var(--muted); }

.rc-save { display: flex; align-items: flex-end; gap: 0.6rem; margin-top: 0.4rem; }
.rc-save .rc-field { flex: 1 1 auto; }
.rc-save-btn { white-space: nowrap; }

.rc-saved-table th, .rc-saved-table td { white-space: nowrap; vertical-align: top; }
.rc-cell-name { font-weight: 700; }
.rc-cell-meta { display: block; font-weight: 400; font-size: var(--fs-meta); color: var(--muted); }
.rc-cell-route { white-space: normal; min-width: 12rem; }
.rc-cell-actions { display: flex; gap: 0.35rem; align-items: center; }
.rc-cell-actions form { margin: 0; }

/* ------------------------------------------------------------------------- */
/* Weekly Inspection photo review + status override (SCM).                   */
/* ------------------------------------------------------------------------- */
.insp-row-actions { display: flex; gap: 0.4rem; align-items: center; justify-content: flex-end; }
.insp-row-actions form { margin: 0; }

.ir-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 0.8rem; margin: 0.6rem 0 1rem; }
.ir-pos { border: 1px solid var(--border); border-radius: var(--radius-card, 10px);
  padding: 0.6rem; background: #fff; }
.ir-pos-label { font-weight: 700; margin-bottom: 0.4rem; }
.ir-aspect { display: flex; flex-direction: column; gap: 0.35rem; padding: 0.4rem 0;
  border-top: 1px dashed var(--border); }
.ir-aspect:first-of-type { border-top: none; }
.ir-aspect-head { font-size: var(--fs-meta); text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--muted); font-weight: 700; }
.ir-photo { display: block; }
.ir-photo img { width: 100%; height: 130px; object-fit: cover;
  border-radius: var(--radius-chip); border: 1px solid var(--border); }
.ir-photo-none { height: 130px; display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-style: italic; font-size: var(--fs-meta);
  border: 1px dashed var(--border); border-radius: var(--radius-chip);
  background: rgba(0,0,0,0.02); }
.ir-status { display: flex; flex-direction: column; gap: 0.15rem; font-size: var(--fs-meta);
  font-weight: 600; color: var(--muted); }
.ir-status-sel { padding: 0.3rem 0.4rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); font-weight: 600; }
.ir-status-sel.ir-status-replace { border-color: var(--bad, #c0392b);
  color: var(--bad, #c0392b); background: #fff4f4; }

.ir-save-bar { position: sticky; bottom: 0; padding: 0.6rem 0; background: var(--bg, #fff);
  border-top: 1px solid var(--border); }

.ir-audit { list-style: none; margin: 0.3rem 0 1rem; padding: 0; }
.ir-audit-row { display: flex; flex-wrap: wrap; justify-content: space-between;
  gap: 0.3rem 0.8rem; padding: 0.4rem 0.5rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); margin-bottom: 0.3rem; }
.ir-audit-aspect { color: var(--muted); font-size: var(--fs-meta); }
.ir-audit-meta { color: var(--muted); font-size: var(--fs-meta); }

/* Bulk diesel preview: possible-duplicate notice. Informational, not a blocker —
   the document still commits if it's a genuine second fuelling that day. Amber
   rather than red: this is "check me", not "this is wrong". */
.dup-warn { color: #8a5a00; background: #fff8e6; border: 1px solid #f0dca8;
  border-radius: 6px; padding: 4px 8px; margin-top: 4px; }

/* Manage Trucks — inline trailer edit. Mirrors .reg-manage above it so the two
   inline controls in a row look like one idiom rather than two. */
.trailer-current { display: block; }
.trailer-edit { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-end; }
.trailer-field { display: flex; flex-direction: column; font-size: var(--fs-meta);
  color: var(--muted); gap: 2px; }
.trailer-field input { min-width: 9rem; }

/* Manage Trucks — "Remove…" for a phantom entry. Deliberately quieter than the
   Deactivate button: Deactivate is the right action for almost every truck, and
   removal is a narrow escape hatch for a mistaken entry with no records. */
.truck-remove { margin-top: 0.35rem; }
.btn-link-danger { background: none; border: 0; padding: 0; cursor: pointer;
  font-size: var(--fs-meta); font-weight: 600; color: var(--bad);
  text-decoration: underline; }

/* Invoicing: temporary manual contact override. Collapsed by default — the
   account-code split is the intended path; this is an escape hatch. */
.invoice-contact-override { margin: 0.75rem 0; padding: 0.6rem 0.8rem;
  border: 1px dashed var(--line, #e3e3e3); border-radius: var(--radius, 10px);
  background: var(--surface-2, #fafafa); }
.invoice-contact-override > summary { cursor: pointer; font-size: var(--fs-meta);
  font-weight: 600; color: var(--muted); }
.invoice-contact-override input { width: 100%; max-width: 28rem; }

/* Invoicing: batch-generation progress. Shown on submit to a live provider, since
   pacing + any rate-limit pause can make a batch take 15-30s and a frozen-looking
   page invites a re-submit (which would create duplicate drafts). */
/* Author `display` beats the UA sheet's [hidden]{display:none}, so the box needs
   its own [hidden] rule or it is permanently on screen showing the template's
   placeholder "0" — which reads as "0 loads were selected". */
.invoice-progress[hidden] { display: none; }
.invoice-progress { display: flex; gap: 0.6rem; align-items: flex-start;
  margin: 0.75rem 0; padding: 0.7rem 0.9rem; border-radius: var(--radius, 10px);
  border: 1px solid var(--line, #e3e3e3); background: var(--surface-2, #fafafa);
  font-size: var(--fs-meta); }
/* .invoice-progress-spinner is .spinner — see the busy-state section. */
.invoice-progress-spinner { margin-top: 2px; }

/* Manage Companies: the up/down order controls sit as a tight pair in their cell. */
.company-order { display: flex; gap: 0.25rem; }
.company-order button { padding: 0.15rem 0.45rem; line-height: 1; }
.company-order button[disabled] { opacity: 0.35; cursor: default; }

/* --------------------------------------------------------------------------
   Driver Financial Ledger — food money + personal loans.
   This screen shows personal financial information about employees, so it is
   deliberately quiet: plenty of whitespace, one accent colour, and outstanding
   vs deducted separated by weight and tone rather than by loud colour.
   -------------------------------------------------------------------------- */
.dl-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0.6rem; margin: 1rem 0 1.4rem; }
.dl-stat { padding: 0.85rem 0.95rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card); }
.dl-stat-label { display: block; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
  margin-bottom: 0.3rem; }
.dl-stat-value { display: block; font-size: 1.35rem; font-weight: 800; color: var(--ink); }
.dl-stat-value.is-owing { color: var(--accent); }
.dl-stat-value.is-clear { color: var(--ok); }
.dl-stat-note { display: block; font-size: var(--fs-micro); color: var(--muted);
  margin-top: 0.2rem; }

/* Driver picker rows */
.dl-drivers { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.dl-driver { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); }
.dl-driver a { display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 0.8rem 1rem; text-decoration: none; color: inherit; }
.dl-driver a:hover { background: var(--safgri-red-tint); }
.dl-driver-name { font-weight: 700; }
.dl-driver-meta { display: block; font-size: var(--fs-micro); color: var(--muted);
  margin-top: 0.15rem; }
.dl-driver-amount { text-align: right; font-weight: 800; white-space: nowrap; }
.dl-driver-amount.is-owing { color: var(--accent); }
.dl-driver-amount.is-clear { color: var(--muted); font-weight: 600; }

/* Entry rows — outstanding carries the accent edge, deducted is settled/quiet */
.dl-entries { list-style: none; margin: 0.4rem 0 0; padding: 0; display: grid;
  gap: 0.45rem; }
.dl-entry { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.9rem;
  padding: 0.7rem 0.9rem; background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: var(--radius-card); }
.dl-entry.is-deducted { border-left-color: var(--ok); background: #fbfbfc; }
.dl-entry-date { font-variant-numeric: tabular-nums; color: var(--muted);
  min-width: 6.2rem; font-size: 0.9rem; }
.dl-entry-amount { font-weight: 800; font-variant-numeric: tabular-nums;
  min-width: 6rem; }
.dl-entry-running { font-size: var(--fs-micro); color: var(--muted);
  font-variant-numeric: tabular-nums; }
.dl-entry-note { flex: 1 1 12rem; color: var(--muted); font-size: 0.9rem; }
.dl-entry-actions { margin-left: auto; display: flex; gap: 0.35rem; align-items: center; }
.dl-entry-actions form { display: flex; gap: 0.3rem; align-items: center; margin: 0; }
.dl-entry-actions input[type="date"] { padding: 0.25rem 0.4rem; font-size: 0.85rem;
  border: 1px solid var(--border); border-radius: var(--radius-control);
  background: var(--card); color: var(--ink); }
.badge-outstanding { background: var(--safgri-red-tint); color: var(--danger-fg); }
.badge-deducted    { background: #e8f7ee; color: var(--ok); }

/* The add-entry form: a single quiet card, fields on one line where there's room */
.dl-form { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: flex-end;
  padding: 0.9rem 1rem; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); }
.dl-form .natis-field { margin: 0; flex: 1 1 9rem; }
.dl-form button { flex: 0 0 auto; }

/* --------------------------------------------------------------------------
   My Salary (driver-facing). Read on a phone, often in poor light, by someone
   who wants one number. So: the total is the biggest thing on the page, the
   split sits under it, and each load shows its own arithmetic.
   -------------------------------------------------------------------------- */
.sal-total { padding: 1.1rem 1rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card);
  text-align: center; margin: 0.6rem 0 0.6rem; }
.sal-total-label { display: block; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.sal-total-value { display: block; font-size: 2.1rem; font-weight: 800;
  color: var(--accent); line-height: 1.2; margin-top: 0.25rem; }
.sal-split { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem;
  margin-bottom: 1.2rem; }
.sal-part { padding: 0.75rem 0.85rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card); }
.sal-part-label { display: block; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.sal-part-value { display: block; font-size: 1.15rem; font-weight: 800;
  color: var(--ink); margin-top: 0.2rem; }

.sal-loads { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.sal-load { padding: 0.8rem 0.9rem; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--radius-card); }
.sal-load-head { display: flex; justify-content: space-between; gap: 0.8rem;
  align-items: baseline; }
.sal-load-route { font-weight: 700; }
.sal-load-total { font-weight: 800; white-space: nowrap; }
.sal-load-meta { display: flex; flex-wrap: wrap; gap: 0.6rem; color: var(--muted);
  font-size: var(--fs-micro); margin-top: 0.2rem; }
.sal-load-lines { display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem;
  margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--border);
  font-size: 0.9rem; }
.sal-line { color: var(--muted); }
.sal-line strong { color: var(--ink); }

/* Admin earnings view — denser, and every override is visible as a correction */
.ea-driver { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); margin-bottom: 0.6rem; }
.ea-driver > summary { padding: 0.8rem 1rem; cursor: pointer; font-weight: 700;
  display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.ea-driver-total { font-weight: 800; white-space: nowrap; }
.ea-body { padding: 0 1rem 0.9rem; }
.ea-override { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; }
.ea-override input[type="text"] { width: 7rem; padding: 0.25rem 0.4rem;
  font-size: 0.85rem; border: 1px solid var(--border);
  border-radius: var(--radius-control); background: var(--card); color: var(--ink); }
.ea-overridden { color: var(--accent); font-weight: 700; }
.badge-flagged { background: #fff1e0; color: #b5651d; }

/* Diesel bonus review — one card per load, so the admin reads a slip's details
   and acts on them in the same place. */
.rev-card, .rev-route { margin-bottom: 0.8rem; }
.rev-head { display: flex; flex-wrap: wrap; justify-content: space-between;
  gap: 0.5rem 1rem; align-items: baseline; }
.rev-head .detail-note { display: block; }

/* Review backlog at a glance — one row per month with something waiting. */
.rev-months { list-style: none; margin: 0 0 1.2rem; padding: 0; display: flex;
  flex-wrap: wrap; gap: 0.4rem; }
.rev-month a { display: flex; align-items: baseline; gap: 0.45rem;
  padding: 0.45rem 0.7rem; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); text-decoration: none; color: inherit; }
.rev-month a:hover { background: var(--safgri-red-tint); }
.rev-month.is-current a { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.rev-month-label { font-weight: 700; }
.rev-month-count { font-weight: 800; color: var(--accent); }

/* Driver Pay build-up — the net as a visible sum, never an opaque number. */
.pay-buildup { list-style: none; margin: 0.6rem 0 1.4rem; padding: 0.4rem 0.9rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); }
.pay-line { display: flex; justify-content: space-between; gap: 1rem;
  padding: 0.4rem 0; font-variant-numeric: tabular-nums; }
.pay-line + .pay-line { border-top: 1px solid var(--border); }
.pay-line .detail-note { display: block; }
.pay-line.is-minus > span:last-child { color: var(--accent); }
.pay-line.is-subtotal { font-weight: 700; }
.pay-line.is-total { font-weight: 800; font-size: 1.1rem;
  border-top: 2px solid var(--ink); }

/* Driver Pay — the "add an advance" card. This is the one thing an admin opens
   this page to DO, so it reads as an input area rather than another panel of
   figures: a solid card with the accent edge used elsewhere for live/actionable
   rows, an explicit title, and a full-size primary button (not btn-small). */
.pay-action { margin: 0.5rem 0 1.1rem; padding: 0.9rem 1rem 1rem;
  background: var(--card); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: var(--radius-card);
  box-shadow: 0 1px 3px rgba(31, 39, 51, 0.06); }
.pay-action-title { margin: 0 0 0.15rem; font-size: 1.02rem; font-weight: 800;
  color: var(--ink); }
.pay-action-note { margin: 0 0 0.7rem; font-size: var(--fs-micro);
  color: var(--muted); }
/* The form sits INSIDE the card, so it drops its own border and padding. */
.pay-action .dl-form { padding: 0; background: none; border: 0; border-radius: 0; }
.pay-action-btn { padding: 0.6rem 1.2rem; font-weight: 700; }

/* The outstanding total, beside its heading, so its weight is visible at a glance. */
.pay-owing-total { font-size: 0.95rem; font-weight: 800; color: var(--accent);
  background: var(--safgri-red-tint); padding: 0.15rem 0.55rem;
  border-radius: 999px; vertical-align: middle; margin-left: 0.4rem; }

/* --------------------------------------------------------------------------
   Driver Pay list — one expandable card per driver, in the same shell the Load
   Log month cards use (.load-month), so the two feeds read as the same kind of
   thing. A dense table made every figure equally loud; only four matter at a
   glance, so the head carries those and the build-up lives inside.
   -------------------------------------------------------------------------- */
.dp-card { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); padding: 0.9rem 1.1rem;
  margin-bottom: 0.8rem; box-shadow: var(--elev-1); }
.dp-card > .dp-card-head {
  margin: 0; cursor: pointer; user-select: none;
  list-style: none;                     /* hide the default disclosure triangle */
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.4rem 0.9rem;
}
.dp-card > .dp-card-head::-webkit-details-marker { display: none; }
.dp-card > .dp-card-head:focus-visible { outline: 2px solid var(--accent);
  outline-offset: 3px; border-radius: 8px; }
.dp-card-name { flex: 1 1 10rem; font-weight: 700; font-size: var(--fs-card-title); }
.dp-card-stats { flex: 0 0 auto; color: var(--muted); font-size: 0.88rem; }

/* The two figures that matter at a glance, right-aligned and tabular so the
   column of numbers scans down the page. */
.dp-card-figures { flex: 0 0 auto; display: flex; gap: 1.2rem; align-items: baseline; }
.dp-fig { display: flex; flex-direction: column; align-items: flex-end; }
.dp-fig-label { font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.dp-fig-value { font-weight: 800; font-variant-numeric: tabular-nums; }
.dp-fig.is-net .dp-fig-value { font-size: 1.1rem; }

/* Chevron, rotating on open — the only cue that a card expands. */
.dp-toggle { flex: 0 0 auto; width: 0.55rem; height: 0.55rem; margin-left: auto;
  border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg); transition: transform 0.15s; }
.dp-card[open] > .dp-card-head .dp-toggle { transform: rotate(-135deg); }

/* The build-up reuses .load-list / .load-row rhythm, with a money column. */
.dp-breakdown { margin-top: 0.7rem; border-top: 1px solid var(--border); }
.dp-breakdown .load-row { justify-content: space-between; }
.dp-line-label { color: var(--muted); font-size: 0.9rem; }
.dp-line-label .detail-note { display: block; }
.dp-line-value { font-weight: 600; font-variant-numeric: tabular-nums; }
.dp-breakdown .is-minus .dp-line-value { color: var(--accent); }
/* A line shown for information and added to nothing (food allowance used). */
.dp-breakdown .is-note .dp-line-value { color: var(--muted); font-weight: 500; }
.dp-breakdown .is-subtotal .dp-line-label,
.dp-breakdown .is-subtotal .dp-line-value { font-weight: 800; color: var(--ink); }
.dp-breakdown .is-total { border-top: 2px solid var(--ink); border-bottom: none; }
.dp-breakdown .is-total .dp-line-label,
.dp-breakdown .is-total .dp-line-value { font-weight: 800; font-size: 1.05rem;
  color: var(--ink); }
.dp-card-actions { margin: 0.7rem 0 0; }

/* --------------------------------------------------------------------------
   Banner menu groups + Admin Hub. Both render from menus.BANNER_MENU.
   -------------------------------------------------------------------------- */
.menu-group-head { display: block; padding: 0.55rem 0.4rem 0.15rem;
  font-size: var(--fs-micro); font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--muted); }
.menu-group-head:first-of-type { padding-top: 0.2rem; }
.menu-hub-link { font-weight: 700; }

.hub-head { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.1rem; }
.hub-head-count { font-size: var(--fs-micro); font-weight: 700; color: var(--muted);
  background: var(--bg-page); border: 1px solid var(--border);
  border-radius: 999px; padding: 0.05rem 0.45rem; }
.hub-caption { margin: 0 0 0.5rem; }
.hub-tiles { margin-bottom: 1.4rem; }

/* Booking wizard — a text input with a "choose…" select beside it. The pair
   reads as one control: the input is the value, the select is the way in. Wraps
   on a phone rather than squeezing both onto one line, because the input is the
   half that matters and a 90px-wide registration field is unusable. */
.pick-row {
  display: flex;
  gap: .6rem;
  align-items: flex-end;
  flex-wrap: wrap;
}
.pick-row > .natis-field { flex: 1 1 14rem; margin-bottom: 0; }
.pick-row > .pick-choose { flex: 0 1 12rem; }
.pick-row > .pick-choose select { width: 100%; }
@media (max-width: 480px) {
  .pick-row > .natis-field,
  .pick-row > .pick-choose { flex: 1 1 100%; }
}

/* ==========================================================================
   Booking Creator — the tile grid.
   Built on the app's own tokens (--accent, --elev-*, --radius-card, --fs-*)
   rather than fresh values, so this page belongs to the app rather than
   looking like a page from somewhere else. #8B1E2D is the app's red; the
   Excel sheet's #8C1C2B differs by a digit and is imperceptible side by side,
   so the token wins and the two stay in step if the brand ever moves.
   ========================================================================== */

/* ---- Header: progress ring + title ------------------------------------- */
.bk-header {
  display: flex; align-items: center; gap: 1.1rem;
  flex-wrap: wrap; margin-bottom: .4rem;
}
.bk-header-text { flex: 1 1 18rem; min-width: 0; }
.bk-title { margin: 0 0 .15rem; }
.bk-sub { margin: 0 0 .7rem; }

.bk-ring { width: 84px; height: 84px; flex: 0 0 auto; }
.bk-ring circle {
  fill: none; stroke-width: 7; cx: 42; cy: 42;
  /* Start the arc at 12 o'clock and run clockwise. */
  transform: rotate(-90deg); transform-origin: 50% 50%;
}
.bk-ring-track { stroke: var(--border); }
.bk-ring-fill {
  stroke: var(--accent); stroke-linecap: round;
  stroke-dasharray: 226.19;
  transition: stroke-dashoffset .55s cubic-bezier(.22,.8,.3,1), stroke .35s ease;
}
.bk-ring.is-complete .bk-ring-fill { stroke: var(--ok); }
.bk-ring-num {
  text-anchor: middle; font-size: 1.35rem; font-weight: 700; fill: var(--ink);
}
.bk-ring-den {
  text-anchor: middle; font-size: .7rem; font-weight: 600; fill: var(--muted);
}

/* ---- Company headings --------------------------------------------------- */
.bk-section { display: flex; align-items: center; gap: .5rem; }
.bk-company {
  display: flex; align-items: center; gap: .55rem;
  margin: 1.15rem 0 .5rem;
  padding-bottom: .4rem;
  border-bottom: 1px solid var(--border);
}
.bk-company-logo {
  width: 26px; height: 26px; flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
}
.bk-company-logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
.bk-company-name {
  margin: 0; font-size: var(--fs-card-title); font-weight: 700;
  letter-spacing: -.01em; color: var(--ink);
}
.bk-pill {
  font-size: var(--fs-micro); font-weight: 700; line-height: 1;
  padding: .28rem .5rem; border-radius: 999px;
  background: var(--safgri-red-tint); color: var(--accent-dark);
}
.bk-pill-ok { background: #e7f6ed; color: #14683a; }
.bk-empty { margin: .3rem 0 1rem; }

/* ---- Tiles -------------------------------------------------------------- */
.truck-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
  gap: .7rem;
  margin: 0 0 1.3rem;
}
.truck-tile {
  position: relative;
  display: flex; flex-direction: column; gap: .1rem;
  padding: .85rem .9rem;
  min-height: 4.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--card);
  box-shadow: var(--elev-1);
  text-decoration: none;
  color: inherit;
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.truck-tile:hover, .truck-tile:focus-visible {
  transform: translateY(-2px);
  box-shadow: var(--elev-2-accent);
  border-color: var(--accent);
  text-decoration: none;
}
.truck-tile:active { transform: translateY(0); box-shadow: var(--elev-1); }
.bk-tile-icon {
  width: 20px; height: 20px; margin-bottom: .25rem;
  color: var(--muted);
  transition: color .16s ease;
}
.truck-tile:hover .bk-tile-icon { color: var(--accent); }
.truck-tile-reg {
  font-weight: 700; font-size: var(--fs-card-title);
  letter-spacing: .01em; color: var(--ink);
}
.truck-tile-driver {
  font-size: var(--fs-meta); color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Booked: a green edge and a tick, so the two sections are told apart at a
   glance and not by reading their headings. */
.truck-tile.is-booked { border-left: 3px solid var(--ok); }
.truck-tile.is-booked:hover { border-color: var(--ok); }
.bk-tick {
  position: absolute; top: .6rem; right: .6rem;
  width: 20px; height: 20px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--ok); color: #fff;
}
.bk-tick svg { width: 12px; height: 12px; fill: none; stroke: currentColor; }

/* The one-shot "just booked" moment. Fires only on the tile the save came
   from, once, then it is an ordinary booked tile like the rest. */
@keyframes bk-land {
  0%   { transform: scale(.94); box-shadow: 0 0 0 0 rgba(31,157,85,.45); }
  55%  { transform: scale(1.02); box-shadow: 0 0 0 10px rgba(31,157,85,0); }
  100% { transform: scale(1);    box-shadow: var(--elev-1); }
}
.truck-tile.just-booked { animation: bk-land .6s cubic-bezier(.22,.8,.3,1); }

@media (prefers-reduced-motion: reduce) {
  .truck-tile, .bk-ring-fill, .bk-tile-icon { transition: none; }
  .truck-tile.just-booked { animation: none; }
  .truck-tile:hover { transform: none; }
}

/* Booking Creator start page. The two selectors sit side by side on a wide
   screen and stack on a phone; the button is separated from them by the hint so
   the page reads "choose, then go" rather than as one undifferentiated form. */
.booking-start-fields {
  display: flex;
  gap: .75rem 1rem;
  flex-wrap: wrap;
  align-items: flex-end;
}
.booking-start-fields > .natis-field,
.booking-start-fields > label.natis-field { flex: 1 1 15rem; margin-bottom: 0; }
/* The mine picker's "Other" box is a block that must sit under its own select,
   not squeeze in beside it. */
.booking-start-fields > div { flex: 1 1 100%; }
.booking-start-hint { margin: .7rem 0 .9rem; }
.booking-start-go { display: flex; }

/* Actions on a row, with room around them — the old markup put a bare link here
   and it read as body text rather than something to press. */
.booking-actions { display: flex; gap: .6rem; flex-wrap: wrap; margin: .8rem 0 0; }
.booking-resume .booking-actions { margin-bottom: .35rem; }
.booking-meta-sep { opacity: .45; padding: 0 .15rem; }

/* ==========================================================================
   Driver-Truck History — a timeline, not a table.
   Built on the app's tokens (--accent, --elev-*, --radius-card, --fs-*) so it
   belongs to this app. Reading spans off rows meant holding four dates in your
   head to notice an overlap; a bar shows it.
   ========================================================================== */
/* ONE TRUCK = ONE CARD. Seven of these are scanned in a column, so the gap
   BETWEEN cards is deliberately larger than any gap inside one — that ratio is
   what makes a block read as a unit without needing a divider line. */
.dh-truck {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--elev-1);
  padding: 1.15rem 1.35rem 1.25rem; margin-bottom: 1.5rem;
  position: relative;                     /* see the stacking note below */
}
/* STACKING. An open period's panel is absolutely positioned inside its band,
   and .dh-undated carries z-index:1 — so a panel opened on one card was painted
   UNDER the next card's undated band, which cut a dashed rule straight through
   its Delete row. z-index inside a card cannot fix that: the two bands are in
   different stacking contexts, one per card.
   So the CARD holding something open is lifted above its siblings. That is the
   level the comparison actually happens at. */
.dh-truck:has(.dh-period[open]) { z-index: 60; }
/* The accent edge says "this one needs work" from the far left, before any
   badge is read.
   An INSET SHADOW, not border-left: a border adds to the box, so flagged cards
   sat 4px right of clean ones and the column of registrations came out ragged —
   which is exactly the scanning this edge exists to help. */
.dh-truck-needs {
  box-shadow: inset 4px 0 0 var(--accent), var(--elev-1);
}

.dh-truck-head {
  display: flex; align-items: center; gap: .55rem 1rem; flex-wrap: wrap;
  padding-bottom: .9rem; margin-bottom: 1.05rem;
  border-bottom: 1px solid var(--border);
}
/* PRIMARY. The registration is what someone is looking for when they scan. */
.dh-truck-reg {
  margin: 0; font-size: 1.25rem; font-weight: 800; letter-spacing: -.02em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
/* SECONDARY, and labelled — "Senzo Mazibuko" alone beside a registration did
   not say what it was. Smaller, lighter, with an uppercase eyebrow. */
.dh-current {
  display: inline-flex; align-items: baseline; gap: .4rem;
  font-size: var(--fs-body); font-weight: 600; color: var(--ink);
}
.dh-current::before {
  content: "driving now"; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
}
.dh-current.dh-muted { font-weight: 500; }
.dh-current.dh-muted::before { content: "driver"; }
.dh-muted { color: var(--muted); }

.dh-pills { display: flex; gap: .4rem; flex-wrap: wrap; margin-left: auto; }
/* SEVERITY IS A COLOUR, not a sentence. Across seven trucks the badges are read
   as a block of colour first and words second, so "needs a decision" and "just
   so you know" must not look alike — they did, both being the same pale red. */
.dh-pill {
  font-size: var(--fs-micro); font-weight: 700; line-height: 1;
  padding: .4rem .62rem; border-radius: 999px; white-space: nowrap;
  border: 1px solid transparent;
}
/* URGENT — a human has to decide something. Solid, the only filled red here. */
.dh-pill-urgent {
  background: var(--danger-bg); color: var(--danger-fg);
  border-color: var(--danger-border);
}
.dh-pill-urgent::before { content: "! "; font-weight: 900; }
/* MISSING — data absent but nobody has to judge anything. Amber. */
.dh-pill-gap {
  background: #fdf3e0; color: #8a5a12; border-color: #f0dcb4;
}
/* INFORMATIONAL — "start backfilled", the period count. Grey, and quiet. */
.dh-pill-info  { background: #eef1f5; color: #56607a; border-color: #e0e5ec; }
.dh-pill-quiet { background: transparent; color: var(--muted);
                 border-color: var(--border); font-weight: 600; }
/* kept: the in-popover pills still use it */
.dh-pill-warn  { background: #fdf3e0; color: #8a5a12; border-color: #f0dcb4; }
.dh-pill-main  { background: #e7edf7; color: #2c4a7c; }
.dh-pill-help  { background: #eef1f5; color: #46536b; }
.dh-pill-approved { background: #e7f6ed; color: #14683a; }
.dh-pill-ended    { background: #eef1f5; color: #56607a; }
.dh-pill-rejected { background: var(--danger-bg); color: var(--danger-fg); }

/* ---- the axis + lanes ---- */
/* The lane label column and the gap after it. ONE definition, used by both the
   label and the axis offset — they must be identical or the ticks stop lining
   up with the bars, and two hardcoded numbers in different rules is exactly how
   that drifts. Wide enough for the longest label, which is UNDATED. */
.dh-timeline {
  position: relative; margin: .2rem 0 .3rem;
  --dh-label-w: 4.8rem;
  --dh-gap: .5rem;
}
.dh-axis {
  position: static; height: 1.35rem;
  margin-left: calc(var(--dh-label-w) + var(--dh-gap));
  border-bottom: 1px solid var(--border);
}
.dh-tick {
  position: absolute; top: 0; transform: translateX(-50%);
  font-size: var(--fs-micro); color: var(--muted); white-space: nowrap;
}
/* WHERE a tick (or the today line) goes. Its percentage (--p) is of the TRACK
   the bars live in, but it is positioned against the whole .dh-timeline — the
   axis stays position:static so the today line can run the full height of the
   lanes. So the label column and gap are added back, and --p applies to what
   is left. It used to be a plain left:%, which measured from the label column's
   left edge and across its width: every tick sat left of its date, by up to
   ~80px at the start of the axis. */
.dh-axis > .dh-tick, .dh-axis > .dh-today {
  left: calc(var(--dh-label-w) + var(--dh-gap)
             + (100% - var(--dh-label-w) - var(--dh-gap)) * var(--p, 0) / 100);
}
/* The today marker used to be `bottom: -100vh` — a 1px element a hundred
   viewport-heights tall, painting straight down over the undated strip, the
   help card and anything else beneath. It now spans the TIMELINE only, which
   is the only place a date position means anything. */
.dh-today {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: var(--accent); opacity: .35; pointer-events: none;
}
.dh-lane { display: flex; align-items: center; gap: var(--dh-gap);
  margin-top: .55rem; }
/* THE FOURTH CAUSE. This was `width: 3.1rem; flex: 0 0 auto` — but a flex item
   has min-width:auto, so it never shrinks below its CONTENT. "UNDATED" is seven
   bold uppercase characters at 0.72rem with letter-spacing: about 61px against
   a 49.6px box. So the undated row's label silently grew, pushing its own row
   out of step with the lanes above it while MAIN and HELP (four characters)
   fitted and did not.
   Fixed basis, and overflow handling as a backstop so no future label can push
   a row again. */
.dh-lane-label {
  flex: 0 0 var(--dh-label-w); max-width: var(--dh-label-w);
  text-align: right; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted);
}
/* Bars are absolutely positioned, so they contribute NO height — the track is
   only ever as tall as this. That is fine while every bar is closed, and it is
   why an OPEN one used to spill its card over the strip below (see .dh-pop). */
.dh-lane-track { position: relative; flex: 1 1 auto; min-height: 2rem; }

/* ---- a period ---- */
.dh-period { position: absolute; top: 0; min-width: 2.2rem; }
/* An open period must sit above its neighbours AND above the strip below. */
.dh-period[open] { z-index: 30; }
/* Taller than it was: these are the page's main touch target, and 1.7rem is
   below the ~44px a thumb wants. The name is stepped up with it — a bar is read
   as a NAME first and a span second. */
.dh-period > summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; gap: .25rem;
  height: 2.4rem; padding: 0 .7rem;
  border-radius: var(--radius-chip);
  background: var(--accent); color: #fff;
  font-size: var(--fs-meta); font-weight: 700; letter-spacing: -.005em;
  overflow: hidden; white-space: nowrap;
  box-shadow: var(--elev-1);
  transition: transform .14s ease, box-shadow .14s ease, filter .14s ease;
}
.dh-period > summary::-webkit-details-marker { display: none; }
/* PRIMARY vs SECONDARY on the bar. The driver's name holds full weight and
   never shrinks; the dates ride behind it at lower contrast and are the first
   thing to go when the bar is too narrow to hold both. */
.dh-bar-name { flex: 0 0 auto; font-weight: 700; }
.dh-bar-facts {
  flex: 0 1 auto; min-width: 0; overflow: hidden;
  font-size: var(--fs-micro); font-weight: 500; letter-spacing: 0;
  opacity: .78; font-variant-numeric: tabular-nums;
  /* Fades out instead of stopping mid-character, so a clipped date reads as
     "there is more here" rather than as a rendering fault. */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 1.1rem), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - 1.1rem), transparent);
}
.dh-bar-open { flex: 0 0 auto; margin-left: auto; opacity: .8; }
.dh-period > summary:hover {
  transform: translateY(-1px); box-shadow: var(--elev-2-accent); filter: brightness(1.08);
}
.dh-bar-name { overflow: hidden; text-overflow: ellipsis; }
.dh-bar-open { margin-left: auto; opacity: .8; }
/* Help reads as a second, quieter voice — present, not competing. */
.dh-role-help > summary { background: #5b6b86; }
/* Ended is history: same shape, less ink. */
.dh-ended > summary { background: #97a2b5; }
/* Refused never ran: hatched, so it is visibly not a span. */
.dh-rejected > summary {
  background: repeating-linear-gradient(45deg, #c9ced8 0 6px, #dde1e8 6px 12px);
  color: #46536b;
}

/* ---- undated: cannot be placed, and must not pretend to be ---- */
/* Its own band, separated by a real rule rather than by a few pixels of
   margin — the label sits directly under the lanes and had nothing keeping the
   bars above off it. */
.dh-undated {
  position: relative; z-index: 1;
  /* Inherits --dh-label-w from .dh-timeline only when nested inside it; this
     block is a SIBLING, so it needs its own copy or its label falls back to the
     bare initial value and the column widths disagree again. */
  --dh-label-w: 4.8rem; --dh-gap: .5rem;
  display: flex; align-items: flex-start; gap: var(--dh-gap);
  margin-top: 1.15rem; padding-top: 1rem;
  border-top: 1px dashed var(--border);
}
.dh-undated-bars { display: flex; gap: .4rem; flex-wrap: wrap; flex: 1 1 auto; }
.dh-undated .dh-period { position: static; }
.dh-undated .dh-lane-label { padding-top: .25rem; }
.dh-undated .dh-period > summary {
  background: repeating-linear-gradient(45deg,
              var(--safgri-red-tint) 0 7px, #fff 7px 14px);
  color: var(--accent-dark);
  border: 1px dashed var(--accent);
}

/* ---- the expanded detail ---- */
/* ABSOLUTE, not relative. As a relative box this card added its own height to
   an absolutely-positioned bar that the lane could not account for, so opening
   a period pushed a floating panel down across the undated strip. Out of flow,
   it overlays cleanly and the lanes below never move. */
.dh-pop {
  position: absolute; top: 100%; left: 0; z-index: 40; margin-top: .5rem;
  /* Never clipped by the card it hangs out of. */
  max-width: min(30rem, 92vw);
  min-width: 25rem; padding: 1.1rem 1.2rem 1.15rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius-card); box-shadow: var(--elev-3);
}
/* The driver's NAME is what identifies this period; the pills qualify it. So
   the name is stepped up and the pills sit under it rather than beside it at
   the same visual weight. */
.dh-pop-head {
  margin: 0 0 .15rem; display: flex; gap: .45rem;
  align-items: center; flex-wrap: wrap;
  font-size: var(--fs-card-title);
}
.dh-pop-head strong { font-size: 1.1rem; font-weight: 800; letter-spacing: -.01em; }
.dh-pop-dates {
  margin: 0 0 1rem; padding-bottom: .9rem;
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-meta); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.dh-edit { display: flex; flex-direction: column; gap: .9rem; }
.dh-edit-row { display: flex; gap: .7rem; align-items: flex-end; flex-wrap: wrap; }
.dh-edit-alt { padding-top: .9rem; border-top: 1px dashed var(--border); }
.dh-field { display: flex; flex-direction: column; gap: .3rem;
  font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted); }
.dh-field input, .dh-field select {
  font-size: var(--fs-body); text-transform: none; letter-spacing: 0;
  font-weight: 400; color: var(--ink); min-height: 2.5rem;
}
.dh-note { margin: .2rem 0 0; }
/* Removal is not a sibling of the corrections above it. Pushed to the end,
   behind a rule, with the consequence written next to it. */
.dh-edit-destroy {
  margin-top: .3rem; padding-top: .8rem;
  border-top: 1px solid var(--border);
  align-items: baseline; gap: .55rem;
}
.dh-destroy-note { font-size: var(--fs-micro); color: var(--muted); }

/* ---- "Record a period": two questions, asked separately ---- */
.dh-form-grid {
  display: grid; gap: 1.1rem;
  grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
  margin-bottom: 1.1rem;
}
.dh-fieldset {
  margin: 0; padding: 1rem 1.1rem 1.1rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip);
  background: var(--bg-page);
  display: flex; flex-wrap: wrap; gap: .85rem;
}
.dh-fieldset legend {
  padding: 0 .4rem; font-size: var(--fs-micro); font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
}
.dh-fieldset .dh-field { flex: 1 1 8.5rem; }
.dh-field-note { flex: 1 1 100%; margin: 0; }
.dh-form-actions { display: flex; }

/* The "resolved" moment. Once, on the row that just changed — a permanent
   marker would be noise by the third correction. */
@keyframes dh-fixed {
  0%   { box-shadow: 0 0 0 0 rgba(31,157,85,.5); filter: brightness(1.3); }
  70%  { box-shadow: 0 0 0 9px rgba(31,157,85,0); }
  100% { box-shadow: var(--elev-1); filter: none; }
}
.dh-just-fixed > summary { animation: dh-fixed .9s cubic-bezier(.22,.8,.3,1); }

/* ---- help earnings: its own card, visibly outside the record above ---- */
.dh-help {
  margin-top: .7rem; padding: .55rem .7rem;
  background: var(--bg-page); border-radius: var(--radius-chip);
}
.dh-help > summary { display: flex; align-items: center; gap: .45rem;
  cursor: pointer; }
.dh-help-title { font-size: var(--fs-meta); font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.dh-help-total { margin-left: auto; font-weight: 700; font-size: var(--fs-meta); }
.dh-help-list { list-style: none; padding: 0; margin: .4rem 0; }
.dh-help-list li { padding: .18rem 0; font-size: var(--fs-meta); }
.dh-inline { display: inline; }
.dh-inline button { padding: 0 .3rem; }

@media (prefers-reduced-motion: reduce) {
  .dh-period > summary { transition: none; }
  .dh-period > summary:hover { transform: none; }
  .dh-just-fixed > summary { animation: none; }
}
@media (max-width: 560px) {
  .dh-timeline, .dh-undated { --dh-label-w: 3.4rem; }
  .dh-pop { min-width: 0; max-width: 100%; }
  .dh-truck { padding: .95rem 1rem 1.05rem; margin-bottom: 1.1rem; }
  /* The badges stop being pushed to the right edge — at this width `margin-left:
     auto` shoved them off the end of the row, so the second and third were half
     out of view. Full-width under the name instead, still in severity order. */
  .dh-pills { margin-left: 0; flex-basis: 100%; }
  .dh-truck-head { gap: .5rem .7rem; }
  .dh-truck-reg { font-size: 1.12rem; }
  /* The axis is a fixed span of months; below this width it cannot fit, so it
     SCROLLS rather than being silently cut off at the card edge. */
  .dh-lane-track, .dh-axis { min-width: 0; }
  .dh-timeline { overflow-x: auto; overflow-y: visible; padding-bottom: .2rem; }
  .dh-fieldset { padding: .85rem .9rem .95rem; }
}

/* The tools row on the Salaries list page. One tile today, so it is held to a
   readable width rather than stretched across the page — a lone card spanning
   1200px reads as a banner, not as something to click. */
.dp-tools { margin: .3rem 0 1.1rem; }
.dp-tools .wk-action { flex: 0 1 26rem; }

/* A POD whose number was typed on the Load Log with no document behind it.
   Deliberately neither green nor red: the number is real and invoices on it,
   but no paper exists, so it must not read as a resolved upload OR as a gap. */
.doc-tile.is-manual { border-color: color-mix(in srgb, var(--accent) 28%, transparent); }
.doc-tile.is-manual .doc-tile-mark { color: var(--accent); }

/* Divider between the load and diesel bulk controls on the Remittance Creator.
   They act on opposite things — what gets paid vs what gets deducted — so the
   four buttons must not read as one undifferentiated row. */
.invoice-bulk-sep {
  width: 1px; align-self: stretch; min-height: 1.4rem;
  background: var(--border, rgba(0,0,0,.15)); margin: 0 .15rem;
}
/* The per-group diesel tally. Sits beside the load tally, never merged into it:
   a group header that quietly netted diesel off its load total would misstate
   both numbers. */
.rem-group-diesel {
  font-size: var(--fs-xs, .78rem); color: var(--accent);
  white-space: nowrap; margin-left: .45rem;
}

/* Remittance Creator draft: the resume notice and the autosave indicator. */
.rem-draft-note { display: flex; flex-wrap: wrap; align-items: center;
                  gap: .6rem 1rem; justify-content: space-between; }
.rem-draft-note p { margin: 0; }
.rem-draft-discard { margin: 0; }
.rem-draft-status { display: block; min-height: 1.1rem; margin: 0 0 .4rem;
                    font-size: var(--fs-xs, .78rem); color: var(--muted, #6b6b6b); }

/* Booking wizard: which driver the fields were defaulted to. Never silent —
   "last booked" and "officially assigned" must not look the same. */
.booking-driver-source { display: flex; flex-wrap: wrap; align-items: center;
                         gap: .4rem .6rem; margin: 0 0 .6rem; }

/* Manage Vendor Diesel Prices: which rate a history group is. Shown on EVERY
   group — an absent badge reads as "not checked yet", not as "the default". */
.vendor-rate-tag { display: inline-block; margin-left: .5rem; padding: .05rem .4rem;
  border-radius: var(--radius-pill, 999px); font-size: var(--fs-xs, .78rem);
  font-weight: 600; background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent); }
.vendor-rate-tag.vendor-rate-any { background: transparent; color: var(--muted, #6b6b6b);
  border: 1px solid var(--border, rgba(0,0,0,.15)); font-weight: 500; }

/* Manage Diesel Depots. */
.depot-unmatched { flex-wrap: wrap; gap: .4rem .8rem; }
.depot-attach { display: flex; align-items: flex-end; gap: .5rem; margin: 0; }
.depot-attach .natis-field { margin: 0; }
.depot-card.depot-inactive { opacity: .68; }

/* The by-month view of assignment history. Reuses .dh-truck / .dh-pill so the
   two pages read as one thing; only the row layout is its own. */
.dhm-nav { display: flex; align-items: center; gap: .8rem; margin: 0 0 1.2rem; }
.dhm-current { font-weight: 700; font-size: var(--fs-card-title); }
.dhm-disabled { opacity: .4; pointer-events: none; }
.dhm-list { list-style: none; padding: 0; margin: 0; }
.dhm-row {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .5rem .85rem;
  padding: .7rem 0; border-bottom: 1px solid var(--border);
}
.dhm-row:last-child { border-bottom: 0; padding-bottom: 0; }
/* Primary: who. Everything else qualifies it. */
.dhm-driver { font-size: var(--fs-card-title); font-weight: 700; }
.dhm-dates { font-variant-numeric: tabular-nums; font-weight: 600; }
.dhm-days  { font-size: var(--fs-meta); color: var(--muted);
             font-variant-numeric: tabular-nums; }
.dhm-context { font-size: var(--fs-meta); color: var(--muted); margin-left: auto; }
.dhm-role-help .dhm-driver { font-weight: 600; color: #46536b; }

/* ---- LoadCon Creator ------------------------------------------------------
   The tiles reuse .truck-tile wholesale (geometry, hover lift, focus ring), so
   only what genuinely differs is set here: a logo box on the company picker, and
   the selected/confirmed states on the load picker. */
.lc-company-tiles { grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); }
.lc-company-tile { align-items: center; text-align: center; min-height: 8.5rem; }
.lc-tile-logo {
  display: flex; align-items: center; justify-content: center;
  height: 3.4rem; width: 100%; margin-bottom: .45rem;
}
.lc-tile-logo img { max-height: 3.4rem; max-width: 100%; object-fit: contain; }
/* No logo on file: the company's initials in the accent, so a tile without an
   image is still a tile and not a gap in the grid. */
.lc-tile-initial {
  font-size: 1.5rem; font-weight: 700; letter-spacing: .04em;
  color: var(--accent); opacity: .55;
}
.lc-tile-name { font-size: var(--fs-card-title); }
.lc-tile-count { font-size: var(--fs-meta); color: var(--muted); }

.lc-range-form { align-items: flex-end; }
/* The one warning block on the page, so it carries the accent edge rather than
   looking like another card. */
.lc-warn { border-left: 3px solid var(--accent); }

.lc-load-tiles { grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); }
.lc-load-tile { cursor: pointer; min-height: 5.4rem; }
.lc-load-date { font-size: var(--fs-card-title); }
.lc-load-meta { color: var(--muted); }

/* Visually hidden, NOT display:none — the checkbox still has to be reachable by
   keyboard and still has to post. The tile is the label, so the hit area is the
   whole card. */
.lc-load-check {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.lc-tile-tick { opacity: 0; transform: scale(.7); transition: opacity .14s ease, transform .14s ease; }
.lc-load-tile:has(.lc-load-check:checked) {
  border-color: var(--accent);
  box-shadow: var(--elev-2-accent);
  background: var(--safgri-red-tint);
}
.lc-load-tile:has(.lc-load-check:checked) .lc-tile-tick {
  opacity: 1; transform: scale(1); background: var(--accent);
}
/* Focus must be visible on the CARD, since the input it belongs to is hidden. */
.lc-load-tile:focus-within { border-color: var(--accent); box-shadow: var(--elev-2-accent); }

.lc-load-tile.is-confirmed {
  cursor: default; opacity: .62; background: var(--bg-page);
  box-shadow: none; border-style: dashed;
}
.lc-load-tile.is-confirmed:hover { transform: none; box-shadow: none; border-color: var(--border); }
.lc-load-done { color: var(--ok); font-weight: 600; }

/* Sticky action bar: the count and Generate stay reachable while working down a
   long list, which is the whole task on this page. */
.lc-bar {
  position: sticky; top: .5rem; z-index: 5;
  display: flex; flex-wrap: wrap; gap: .6rem;
  align-items: center; justify-content: space-between;
  padding: .6rem .85rem; margin: 0 0 1rem;
  border: 1px solid var(--border); border-radius: var(--radius-card);
  background: var(--card); box-shadow: var(--elev-2);
}
.lc-bar-count { font-size: var(--fs-card-title); }
.lc-bar-actions { display: flex; flex-wrap: wrap; gap: .45rem; align-items: center; }
.lc-bar-actions button[disabled] { opacity: .5; cursor: not-allowed; }

@media (prefers-reduced-motion: reduce) {
  .lc-tile-tick { transition: none; }
}

/* LoadCon — the page a scanned QR opens. A definition list rather than a table:
   this is read on a phone at a gate, and a two-column table at 360px either
   scrolls sideways or squeezes the value into three words a line. */
.lc-view-card { margin-bottom: .9rem; }
.lc-dl { display: grid; grid-template-columns: 9.5rem 1fr; gap: .3rem .9rem; margin: 0; }
.lc-dl dt { color: var(--muted); font-size: var(--fs-meta); }
.lc-dl dd { margin: 0; font-weight: 600; }
.lc-view-pair { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem; }
.lc-terms { margin: .4rem 0 0; padding-left: 1.2rem; color: var(--muted); font-size: var(--fs-meta); }
.lc-terms li { margin-bottom: .35rem; }

@media (max-width: 34rem) {
  /* Stacked, and the label above its value rather than beside it — 9.5rem of
     label leaves nothing for a registration on a narrow phone. */
  .lc-view-pair { grid-template-columns: 1fr; }
  .lc-dl { grid-template-columns: 1fr; gap: 0; }
  .lc-dl dd { margin-bottom: .55rem; }
}

/* LoadCon — history filter and the edit form. */
.lc-filter { display: flex; flex-wrap: wrap; gap: .4rem; }
/* The active filter is filled rather than outlined, so which one is on is
   readable without comparing every chip to its neighbours. */
.lc-filter .is-on {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.lc-filter .is-on:hover { background: var(--accent-dark); border-color: var(--accent-dark); }
.lc-edit-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: .7rem; margin-bottom: .6rem;
}

/* LoadCon edit — the derived total, sitting between the two fields it comes from.
   Styled as a read-only statement rather than a disabled input, so it never looks
   like a field somebody failed to fill in. */
.lc-total-line {
  margin: .2rem 0 .6rem; padding: .5rem .7rem;
  background: var(--bg-page); border-radius: var(--btn-radius);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem;
}
.lc-total-line strong { font-size: var(--fs-card-title); }

/* ---- Quick navigation search (banner) -------------------------------------
   The toggle is a clone of .topbar-settings so the two sit as a matched pair:
   same 40px tap target, same muted-to-red hover, same readability over the photo
   backdrop. Only the pressed feedback differs — the gear turns, this one does
   not, because there is nothing rotational about a magnifier. */
.topbar-search > summary.topbar-search-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;
  flex: 0 0 auto; cursor: pointer;
  color: var(--muted);
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s, background 0.15s, transform 0.15s;
  list-style: none;
}
/* The default disclosure triangle, removed in both engines. */
.topbar-search > summary::-webkit-details-marker { display: none; }
.topbar-search > summary::marker { content: ""; }
.topbar-search > summary:hover,
.topbar-search > summary:focus-visible {
  color: var(--safgri-red); background: rgba(139, 30, 45, 0.09); outline: none;
}
.topbar-search > summary:active { transform: scale(0.92); }
.topbar-search > summary svg { display: block; }
body.home-bg .topbar-search > summary { color: var(--ink); }
.topbar-search[open] > summary { color: var(--safgri-red); }

/* The panel reuses .home-menu-panel wholesale (position, elevation, the open
   animation); only what a search adds is set here. */
.qs-panel { min-width: 300px; max-width: min(380px, 92vw); }
.qs-field { padding: 0.6rem 0.7rem 0.5rem; border-bottom: 1px solid var(--border); }
.qs-input {
  width: 100%; box-sizing: border-box;
  padding: 0.5rem 0.65rem;
  font-size: var(--fs-body);
  border: 1px solid var(--border); border-radius: var(--btn-radius);
  background: var(--card); color: var(--ink);
}
.qs-input:focus { outline: none; border-color: var(--accent); }
/* Cap the list and scroll it: an owner sees 33 entries, which unbounded would
   run off the bottom of a laptop screen. */
.qs-results { max-height: min(60vh, 26rem); overflow-y: auto; }
.qs-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0 0.6rem;
  padding: 0.5rem 0.75rem;
  text-decoration: none; color: inherit;
  border-bottom: 1px solid var(--border);
}
.qs-row:last-child { border-bottom: 0; }
.qs-row-label { font-weight: 600; font-size: var(--fs-meta); color: var(--ink); }
/* The group, right-aligned: it is context for the label, not a second heading. */
.qs-row-meta {
  font-size: var(--fs-micro); color: var(--muted);
  white-space: nowrap; align-self: center;
}
.qs-row-caption {
  grid-column: 1 / -1;
  font-size: var(--fs-micro); color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Hover and keyboard selection share one treatment, so moving with the arrows
   and moving with the mouse look like the same act. */
.qs-row:hover, .qs-row:focus-visible, .qs-row.is-active {
  background: var(--safgri-red-tint); outline: none;
}
.qs-row:hover .qs-row-label, .qs-row.is-active .qs-row-label { color: var(--accent); }
.qs-empty { margin: 0; padding: 0.85rem 0.75rem; font-size: var(--fs-meta); color: var(--muted); }

/* ---- Booking review -------------------------------------------------------
   The screen was a bare card, a raw table and an unstyled <button>. It reuses
   the grid's header ring (same booking, same shape) and the card vocabulary
   used across the app; only what a review adds is defined here. */
.rv-facts { display: flex; flex-wrap: wrap; gap: .4rem; margin: .35rem 0 .7rem; }
.rv-pill {
  display: inline-flex; align-items: center;
  padding: .12rem .55rem; border-radius: 999px;
  background: var(--safgri-red-tint); color: var(--accent);
  font-size: var(--fs-micro); font-weight: 600;
}
/* "follows today" is a statement of fact, not a warning — grey, so it does not
   compete with the date beside it. */
.rv-pill-quiet { background: var(--bg-page); color: var(--muted); font-weight: 500; }

.rv-card { margin-bottom: .9rem; }
.rv-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: .7rem; margin-bottom: .7rem;
}
.rv-form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: .7rem; }

/* Registrations, IDs and cell numbers are read character by character against a
   vehicle or a licence. Tabular figures keep the columns aligned and stop 1/7
   and 0/O drifting in width. */
.rv-reg { font-variant-numeric: tabular-nums; letter-spacing: .01em; }
.rv-no { color: var(--muted); font-variant-numeric: tabular-nums; }
.rv-table th { white-space: nowrap; }
.rv-none { margin: 0; }

/* The one irreversible act on the page gets its own edge, so it cannot be
   mistaken for the Update button in the card above it. */
.rv-commit { border-left: 3px solid var(--accent); }
.rv-commit-btn { font-weight: 600; }

/* ---- Correcting a finalised booking --------------------------------------- */
/* What cannot change is stated first, and quietly — it is context for the edit,
   not a warning about it. */
.be-locked { border-left: 3px solid var(--border); }
.be-truck {
  padding: .7rem 0; border-bottom: 1px solid var(--border);
}
.be-truck:last-of-type { border-bottom: 0; }
.be-truck-head { display: flex; align-items: baseline; gap: .55rem; margin-bottom: .45rem; }
.be-truck-no {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.5rem; height: 1.5rem; padding: 0 .35rem; border-radius: 999px;
  background: var(--bg-page); color: var(--muted);
  font-size: var(--fs-micro); font-variant-numeric: tabular-nums;
}
/* Narrower than the review grid: these are short codes, and wide boxes for a
   registration make a long form look longer than it is. */
.be-fields { grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); margin-bottom: 0; }

/* Re-plated trucks (see slips.SQL_SIBLING_KEYS). A truck keeps ONE group, headed
   by its current plate, but the loads inside it may have been captured under an
   earlier registration — and that earlier plate is what their invoice, remittance
   and LoadCon print. Both markers below exist so the picker never shows a plate
   the resulting document contradicts. Deliberately quiet: this is a factual note
   on a normal load, not a warning about a problem. */
.load-plate,
.invoice-truck-prior {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: #92400e;
  background: #fef3c7;
  border: 1px solid #fde68a;
  border-radius: 4px;
  padding: 1px 6px;
  white-space: nowrap;
}
.invoice-truck-prior { margin-left: 8px; text-transform: none; }
.load-check-label .load-plate { flex: 0 0 auto; }

/* ---- Booking grid: the truck modal ----------------------------------------
   THESE RULES DID NOT EXIST. .truck-modal was an unstyled div sitting in normal
   document flow after the grid, so "opening" a tile revealed a block BELOW the
   page content — reachable only by scrolling the page. That is also why focusing
   a field inside it used to drag the page to the bottom: the field genuinely was
   down there. focus({preventScroll:true}) in booking_grid.html treated the
   symptom; this treats the cause.

   The page behind is frozen with overflow:hidden, NOT with position:fixed. That
   distinction is load-bearing: a position-fixed body lock zeroes window.scrollY,
   and booking_grid.html's anchor restore measures tiles as
   getBoundingClientRect().top + window.scrollY. Locking with overflow alone
   leaves the scroll position and every rect untouched, so "keep your place after
   booking" is completely unaffected by this change. */
.truck-modal {
  position: fixed;
  inset: 0;
  z-index: 1100;              /* over the topbar (1000) and its dropdowns (1002) */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: calc(14px + env(safe-area-inset-top, 0px)) 14px
           calc(14px + env(safe-area-inset-bottom, 0px));
}
/* display:flex above would otherwise out-specify the [hidden] attribute. */
.truck-modal[hidden] { display: none; }

.truck-modal-backdrop { position: absolute; inset: 0; background: rgba(15,23,42,.55); }

.truck-modal-panel {
  position: relative;         /* over the backdrop without a second z-index */
  display: flex;
  flex-direction: column;     /* fixed head, scrolling body */
  width: min(38rem, 100%);
  /* dvh follows mobile browser chrome as it hides and shows; vh is the fallback
     for anything that does not know dvh. */
  max-height: 88vh;
  max-height: 88dvh;
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 24px 60px rgba(15,23,42,.35);
  overflow: hidden;           /* keeps the corners rounded over the scrolling body */
}

.truck-modal-head {
  flex: 0 0 auto;             /* the title and ✕ never scroll away */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--line, #e5e7eb);
}

#truck-modal-body {
  flex: 1 1 auto;
  overflow-y: auto;           /* ALL modal content reachable, whatever its height */
  /* Stops a scroll that reaches the end of the modal from chaining through to
     the page behind — the other half of "the page never moves". */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 16px 18px calc(18px + env(safe-area-inset-bottom, 0px));
}

/* The frozen page. Set on <html> AND <body>: either one alone leaves the other
   scrollable, depending on which carries the scrollport. */
html.modal-open, body.modal-open { overflow: hidden; }


/* ------------------------------------------------------------------
 * Rotations (SCM pilot) — the .dh-* timeline, with one colour rule:
 * RED means an off-duty period nobody is covering yet, and nothing
 * else is red. On duty is navy, a past off week grey, a closure hatched.
 * ------------------------------------------------------------------ */
.rt-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1rem;
  margin: .5rem 0 .9rem; }
.rt-nav { display: inline-flex; align-items: center; gap: .5rem; }
.rt-window { font-weight: 700; color: var(--ink); min-width: 9rem; text-align: center; }
.rt-views { display: inline-flex; gap: .3rem; }
.rt-actions { display: inline-flex; gap: .5rem; margin-left: auto; flex-wrap: wrap; }
.rt-legend { display: flex; flex-wrap: wrap; gap: .4rem 1rem; margin: 0 0 1rem;
  font-size: var(--fs-micro); color: var(--muted); }
.rt-key { display: inline-flex; align-items: center; gap: .35rem; }
.rt-key::before { content: ""; width: .95rem; height: .7rem; border-radius: 3px;
  display: inline-block; }
.rt-key-on::before { background: #2c4a7c; }
.rt-key-needs::before { background: var(--danger-fg); }
.rt-key-emergency::before {
  background: repeating-linear-gradient(45deg, var(--danger-fg) 0 3px, #7a1720 3px 6px); }
.rt-key-off::before { background: #97a2b5; }
.rt-key-closure::before {
  background: repeating-linear-gradient(45deg, #c9ced8 0 3px, #eef0f4 3px 6px);
  box-shadow: inset 0 0 0 1px #b8bfcc; }
.rt-regular::before { content: "regular driver"; }
.dh-truck-reg a { color: inherit; text-decoration: none; }
.dh-truck-reg a:hover { text-decoration: underline; }
.rt-timeline .dh-lane-track { min-height: 2.4rem; }
/* Ticks: placed by the shared .dh-axis > .dh-tick rule (--p of the track). The
   rotation's today line lives INSIDE the track, so a plain left:% is right. */
.rt-today { z-index: 2; opacity: .9; width: 2px; background: var(--ink); }
/* No minimum width: .dh-period's 2.2rem pushed a short bar at the right edge
   past the end of the track. A narrow bar shows its colour, not its text. */
.rt-period { min-width: 0; }
.rt-narrow > summary { padding: 0; }
.rt-narrow .dh-bar-name, .rt-narrow .dh-bar-facts,
.rt-narrow .rt-more, .rt-narrow .dh-bar-open { display: none; }
.rt-views a[aria-current="page"] { background: var(--safgri-red); color: #fff;
  border-color: var(--safgri-red); }
.rt-segment { border-left-color: var(--border); }
.rt-tick-start { transform: none; }
.rt-tick-end { transform: translateX(-100%); }
.rt-period > summary { gap: .35rem; }
.rt-on > summary { background: #2c4a7c; }
.rt-off > summary { background: #97a2b5; }
.rt-emergency_off > summary { background: #97a2b5; }
.rt-needs > summary { background: var(--danger-fg); }
.rt-emergency_off.rt-needs > summary {
  background: repeating-linear-gradient(45deg, var(--danger-fg) 0 8px, #7a1720 8px 16px); }
.rt-closure > summary {
  background: repeating-linear-gradient(45deg, #c9ced8 0 6px, #eef0f4 6px 12px);
  color: #46536b; box-shadow: inset 0 0 0 1px #b8bfcc; }
.rt-more { flex: 0 0 auto; opacity: .8; }
.rt-closure-note { margin: 0 0 .8rem; }
.rt-periods .rt-row-needs td:first-child { color: var(--danger-fg); font-weight: 700; }
.rt-periods .rt-row-closure td:first-child { color: var(--muted); }
.rt-periods .rt-row-current { background: #f5f7fb; }
@media (max-width: 640px) {
  .rt-actions { margin-left: 0; }
  .rt-period .dh-bar-facts { display: none; }
}

/* ---- Stage 4: relief ---- */
.rt-key-covered::before { background: #1f7a6a; }
.rt-key-stale::before {
  background: repeating-linear-gradient(45deg, #b7791f 0 3px, #f3e2bf 3px 6px); }
.rt-covered > summary { background: #1f7a6a; }
.rt-covered.rt-flagged > summary { box-shadow: inset 0 -3px 0 #e0a43a, var(--elev-1); }
.rt-stale > summary {
  background: repeating-linear-gradient(45deg, #b7791f 0 8px, #9a6414 8px 16px); }
.rt-stale-lane { margin-top: .35rem; }
.rt-relief-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .4rem;
  margin-top: .45rem; }
.rt-relief-form select { max-width: 14rem; }
.rt-relief-who { margin: .3rem 0; }
.rt-flags { margin: .25rem 0 .35rem; padding-left: 1rem; color: #8a5a12;
  font-size: var(--fs-meta); }
.rt-none { color: var(--muted); }
.rt-stale-text { color: #8a5a12; }
.rt-relief-stale { border-left-color: #b7791f; }
.rt-relief-row.is-cancelled { opacity: .6; }

/* ---- Stage 5: handover / return ---- */
.rt-key-inprogress::before { background: #0c4a40; box-shadow: inset 0 -3px 0 #3cc49a; }
.rt-key-completed::before { background: #7fa39a; }
.rt-rel-in_progress > summary { background: #0c4a40; box-shadow: inset 0 -3px 0 #3cc49a, var(--elev-1); }
.rt-rel-completed > summary { background: #7fa39a; }
.rt-status-assigned { background: #e4f3ef; color: #1f7a6a; }
.rt-status-in_progress { background: #d6efe7; color: #0c4a40; border-color: #3cc49a; }
.rt-status-completed { background: #eef1f5; color: #46536b; }
.rt-status-cancelled { background: #f3f4f6; color: var(--muted); }
.rt-timing { color: var(--muted); }
.rt-recredit { flex-basis: 100%; margin-top: .5rem; padding: .6rem .75rem;
  border: 1px solid #f0dcb4; background: #fdf8ee; border-radius: var(--radius-chip); }
.rt-recredit-head { margin: 0 0 .35rem; font-size: var(--fs-meta); color: #6b4a10; }
.rt-recredit-list { margin: 0; padding-left: 1rem; font-size: var(--fs-meta); }
/* Schedule shifts (relief.shift_schedule): a mark on the moved off period, a
   note saying by how much and who, and the uncovered days a shift can leave. */
.rt-shift-mark { font-weight: 700; }
.rt-stale-reason { font-size: var(--fs-meta); color: #6b4a10; }
.rt-shift-note { margin: .35rem 0; font-size: var(--fs-meta); color: var(--muted); }
.rt-shift-row { flex-basis: 100%; margin-top: .35rem; }
.rt-shift-form { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.rt-shift-opt { margin: .35rem 0; }
.rt-portion + .rt-portion { margin-top: .5rem; padding-top: .5rem; border-top: 1px solid var(--border, #ddd); }
.rt-gap { margin-top: .5rem; padding: .5rem .6rem; border-radius: 6px;
  border: 1px solid var(--danger-fg); background: color-mix(in srgb, var(--danger-fg) 8%, transparent); }
.rt-gap-head { margin: 0 0 .35rem; font-size: var(--fs-meta); color: var(--danger-fg); }
.rt-recredit-list li { margin: .25rem 0; }
.rt-inline-form { display: inline-flex; margin-left: .4rem; }

/* ---- Stage 6: relief food money ---- */
.rt-food { flex-basis: 100%; margin-top: .45rem; padding: .55rem .75rem;
  border: 1px solid var(--border); background: #f7faf9; border-radius: var(--radius-chip); }
.rt-food-head { margin: 0 0 .25rem; font-size: var(--fs-meta); }
.rt-food-weeks { margin: 0 0 .2rem; padding-left: 1rem; font-size: var(--fs-meta); color: var(--muted); }

/* ---- WhatsApp (stage 1) ---- */
.wa-setup-list { display: grid; grid-template-columns: max-content 1fr; gap: .25rem .9rem;
  margin: .5rem 0; font-size: var(--fs-meta); }
.wa-setup-list dt { color: var(--muted); }
.wa-setup-list dd { margin: 0; overflow-wrap: anywhere; }
.wa-filter { display: flex; gap: .75rem; flex-wrap: wrap; margin-bottom: .5rem; }
.wa-templates { margin-top: .5rem; font-size: var(--fs-meta); }
.wa-number-form { display: flex; gap: .35rem; align-items: center; }
.wa-number-form input { width: 9.5rem; min-width: 0; }
.wa-problem { display: block; margin-top: .2rem; font-size: var(--fs-micro); color: var(--danger-fg); }
.wa-withdraw-form { display: inline; margin-left: .35rem; }
.wa-consent-form { margin-top: .6rem; }
.wa-setup .dh-pill { white-space: normal; line-height: 1.3; display: inline-block; margin: 0 .25rem .3rem 0; }
/* On a phone each driver becomes a stacked row — tick | name, number, consent —
   so the consent status isn't hidden off the side of a scrolling table. */
@media (max-width: 600px) {
  .wa-drivers thead { display: none; }
  .wa-drivers tr { display: grid; grid-template-columns: 2rem 1fr; padding: .5rem 0;
    border-bottom: 1px solid var(--border); }
  .wa-drivers { width: 100%; table-layout: fixed; }
  .wa-drivers td { display: block; border: 0; padding: .15rem .25rem; min-width: 0;
    white-space: normal; overflow-wrap: anywhere; }
  .wa-drivers td .hint { display: block; }
  .wa-drivers td:first-child { grid-row: 1 / span 3; }
  .wa-drivers td:nth-child(n+2) { grid-column: 2; }
  .wa-drivers td:nth-child(2) { font-weight: 700; }
}

/* ---- WhatsApp stage 3: driver replies on a relief ---- */
.rt-reports { list-style: none; margin: .35rem 0; padding: 0; font-size: var(--fs-meta); }
.rt-report { margin: .15rem 0; }
.rt-report .dh-pill { margin-right: .3rem; }
.rt-reports-row { flex-basis: 100%; }
.rt-report-confirm { margin-bottom: .2rem; }
/* A bar in the right half opens its card leftwards, so a period at the end of
   the month doesn't hang its card (and its Confirm buttons) off the screen. */
.rt-period.rt-pop-end > .dh-pop { left: auto; right: 0; }
/* On a phone a rotation bar is often a few percent of a 7-month axis, and the
   card (max-width: 100% of its bar under 560px) became a sliver one word wide,
   with the handover / assign / shift controls unusable. There it opens as a
   sheet along the bottom of the screen instead, whatever the bar's width. */
@media (max-width: 560px) {
  .rt-period > .dh-pop, .rt-period.rt-pop-end > .dh-pop {
    position: fixed; left: .75rem; right: .75rem; bottom: .75rem; top: auto;
    margin: 0; min-width: 0; max-width: none; max-height: 75vh; overflow-y: auto;
    z-index: 60;
  }
}

/* ---- Driver app: WhatsApp messages card ---- */
.wa-driver-card { margin: 1rem 0; }
.wa-driver-head { margin: 0 0 .2rem; font-size: 1.05rem; }
.wa-driver-card p { margin: .35rem 0; }
.wa-driver-form { margin-top: .5rem; }

/* ---- Driver licence & PrDP panel ---- */
.licence-panel { margin: .5rem 0 .8rem; padding: .7rem .85rem; border: 1px solid var(--border);
  border-radius: var(--radius-chip); background: var(--card); }
.licence-facts { display: grid; grid-template-columns: max-content 1fr; gap: .3rem .9rem;
  margin: 0 0 .4rem; font-size: var(--fs-meta); }
.licence-facts dt { color: var(--muted); }
.licence-facts dd { margin: 0; display: flex; flex-wrap: wrap; gap: .35rem; align-items: center; }
.licence-state { margin: .3rem 0; display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.licence-edit summary { cursor: pointer; font-weight: 600; margin: .3rem 0; }
.licence-card-view img, .licence-card-view iframe { max-width: 100%; max-height: 22rem;
  border: 1px solid var(--border); border-radius: var(--radius-chip); margin: .3rem 0; }
.licence-card-view iframe { width: 100%; height: 22rem; }
.licence-cats { border: 0; padding: 0; margin: .2rem 0; display: flex; flex-wrap: wrap; gap: .4rem .9rem; }
.licence-cats legend { font-size: var(--fs-meta); color: var(--muted); padding: 0; }

/* ---- Driver licences (stage 2) ---- */
.lic-date { font-weight: 600; padding: .05rem .35rem; border-radius: 4px; }
.lic-expired { background: var(--danger-bg); color: var(--danger-fg); }
.lic-due_30 { background: #fdf3e0; color: #8a5a12; }
.lic-due_60 { background: #eef1f5; color: #46536b; }
.lic-key { font-size: var(--fs-micro); font-weight: 700; padding: .1rem .4rem; border-radius: 4px; margin-left: .3rem; }
.lic-counts { display: flex; flex-wrap: wrap; gap: .4rem; margin: .5rem 0; }
.lic-row-expired td:first-child { border-left: 3px solid var(--danger-fg); }
.lic-row-due_30 td:first-child { border-left: 3px solid #d59a32; }
.lic-list { margin: .3rem 0 1rem; padding-left: 1.1rem; }
.lic-list li { margin: .2rem 0; }
.lic-chip { display: inline-block; margin-top: .3rem; font-size: var(--fs-micro); font-weight: 700;
  padding: .2rem .5rem; border-radius: 999px; border: 1px solid var(--border); text-decoration: none;
  color: var(--muted); background: transparent; }
.lic-chip-expired { background: var(--danger-bg); color: var(--danger-fg); border-color: var(--danger-border); }
.lic-chip-due_30 { background: #fdf3e0; color: #8a5a12; border-color: #f0dcb4; }
.lic-chip-due_60 { background: #eef1f5; color: #46536b; border-color: #e0e5ec; }
.lic-chip-ok { background: #e7f6ed; color: #14683a; border-color: #c9ead6; }
.lic-table td { line-height: 1.45; }
.lic-table .dh-pill { display: inline-block; margin-top: .3rem; }
.flash-warning { background: #fdf3e0; border-color: #f0dcb4; color: #8a5a12; }
.licence-warn { margin: .4rem 0; padding: .45rem .65rem; border-radius: var(--radius-chip);
  background: #fdf3e0; border: 1px solid #f0dcb4; color: #8a5a12; font-size: var(--fs-meta); }
.licence-warn p { margin: .1rem 0; }
.licence-warn-chip { display: inline-block; margin-top: .2rem; font-size: var(--fs-micro); font-weight: 700;
  color: #8a5a12; }
/* A select's width follows its longest option (a driver name plus a licence
   note can be long); never let it push a form wider than the screen. */
.natis-field { min-width: 0; max-width: 100%; }
.natis-field select { max-width: 100%; }

/* ---- Payroll lock panel (Salaries) ---- */
.payroll-panel { margin: .6rem 0 1rem; padding: .7rem .9rem; border: 1px solid var(--border);
  border-radius: var(--radius-card); background: var(--card); }
.payroll-panel.is-locked { border-color: #c9ead6; background: #f6fcf8; }
.payroll-state { margin: 0 0 .4rem; display: flex; flex-wrap: wrap; gap: .4rem; align-items: baseline; }
.payroll-lock-form { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; }
.payroll-unlock summary, .payroll-history summary { cursor: pointer; font-weight: 600; margin: .3rem 0; }
.payroll-history ul { margin: .3rem 0; padding-left: 1.1rem; font-size: var(--fs-meta); }
.payroll-changes, .payroll-adjust { margin: .6rem 0 0; }
.payroll-changes table, .payroll-adjust table { font-size: var(--fs-meta); }
.pay-delta-pos { color: var(--ok); } .pay-delta-neg { color: var(--bad); }
/* The panel sits in a flex column: without min-width 0 it grows to its widest
   table instead of letting that table scroll inside it on a phone. */
.payroll-panel, .payroll-changes, .payroll-adjust { min-width: 0; max-width: 100%; }
.payroll-panel .table-scroll { max-width: 100%; }
/* A driver card's "Open <name> — loads, advances & salary →" wraps on a phone
   instead of pushing the page wider (it didn't wrap before this either). */
.dp-card-actions .home-link { white-space: normal; max-width: 100%; }

/* Expense categories + Xero account mapping: small one-line forms inside a table
   cell, wrapping on a phone rather than widening the table. */
.inline-form { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin: 0; }
.inline-form input[type="text"], .inline-form select { min-width: 0; flex: 1 1 10rem; }
.cat-edit { display: inline-block; margin-left: 0.4rem; }
.cat-edit[open] { display: flex; flex-direction: column; gap: 0.4rem; margin: 0.4rem 0 0; }
.cat-edit form { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0; }
/* The category -> account tables stack to one column on a phone: name, then its
   dropdown full width, rather than a dropdown cut off at the screen edge. */
@media (max-width: 600px) {
  .cat-map thead { display: none; }
  .cat-map td { display: block; white-space: normal; border-bottom: none; padding: 0.3rem 0.7rem; }
  .cat-map tr { display: block; border-bottom: 1px solid var(--border); padding: 0.3rem 0; }
  .cat-map select { width: 100%; }
}

/* Expenses to review: on a phone each inbox row becomes a small card — document,
   then the read fields with their labels, then the actions — instead of a table
   whose Review / Discard buttons sit off the right edge of the screen. */
@media (max-width: 600px) {
  .expense-inbox thead { display: none; }
  .expense-inbox tr { display: block; border-bottom: 1px solid var(--border); padding: 0.4rem 0; }
  .expense-inbox td { display: block; border-bottom: none; padding: 0.15rem 0.7rem;
                      white-space: normal; text-align: left; }
  .expense-inbox td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
}

/* Expense review card (stage 4): the document beside the answers on a wide
   screen, folded above them on a phone. */
.review-card { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.25rem; align-items: start; }
.review-doc { position: sticky; top: 1rem; background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 0.6rem; }
.review-doc > summary { font-weight: 600; cursor: pointer; }
.review-doc-frame { width: 100%; height: 75vh; border: 0; }
.review-doc-img { width: 100%; height: auto; display: block; }
.review-form { display: flex; flex-direction: column; gap: 0.9rem; min-width: 0; }
.review-q { border: 1px solid var(--border); border-radius: 10px; padding: 0.7rem 0.9rem; background: var(--card); margin: 0; min-width: 0; }
.review-q legend, .review-parts > summary { font-weight: 700; padding: 0 0.3rem; }
.review-q select, .review-q input[type="text"] { max-width: 100%; }
.review-opt { display: flex; align-items: center; gap: 0.5rem; margin: 0.35rem 0; }
.review-sub { margin: 0 0 0.4rem 1.6rem; }
.truck-ticks { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: 0.2rem 0.8rem; }
.truck-ticks label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.review-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: 0.6rem 0.9rem; }
.review-grid label { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.85rem; color: var(--muted); }
.review-grid input, .review-grid select { width: 100%; }
.reg-list { list-style: none; margin: 0; padding: 0; }
.reg-item { padding: 0.35rem 0; border-bottom: 1px solid var(--border); }
.reg-item:last-child { border-bottom: none; }
.reg-evidence ul { margin: 0.2rem 0 0; padding-left: 1.1rem; font-size: 0.82rem; }
/* Each allocation choice's own control shows only while that choice is picked —
   45 truck ticks are noise unless "Several trucks" is chosen. Browsers without
   :has() simply show both, as before. */
@supports selector(:has(a)) {
  .review-q select[name="truck_id"], .review-q .truck-ticks { display: none; }
  .review-q:has(input[name="allocation"][value="truck"]:checked) select[name="truck_id"] { display: block; }
  .review-q:has(input[name="allocation"][value="several"]:checked) .truck-ticks { display: grid; }
}
@media (max-width: 800px) {
  .review-card { grid-template-columns: minmax(0, 1fr); }
  .review-doc { position: static; }
  .review-doc-frame { height: 60vh; }
}

/* Expense reports: the filter bar wraps; on a phone each report row becomes a
   labelled card, like the review inbox. */
.report-filters { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
                  gap: 0.6rem 0.9rem; align-items: end; margin: 0.5rem 0 1rem; }
.report-filters label { display: flex; flex-direction: column; gap: 0.2rem; font-size: 0.85rem; color: var(--muted); }
.report-filters input, .report-filters select { width: 100%; }
.report-filter-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
@media (max-width: 600px) {
  .expense-report thead { display: none; }
  .expense-report tr { display: block; border-bottom: 1px solid var(--border); padding: 0.4rem 0; }
  .expense-report td { display: block; border-bottom: none; padding: 0.15rem 0.7rem;
                       white-space: normal; text-align: left; }
  .expense-report td[data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
}

/* Drivers page: correcting a driver's ID number in place. */
.id-edit { margin: 0.2rem 0; }
.id-edit-form { display: flex; flex-wrap: wrap; gap: 0.4rem 0.8rem; align-items: end; margin-top: 0.4rem; }
.id-edit-form label { display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.85rem; color: var(--muted); }
.id-edit-form .id-edit-foreign { flex-direction: row; align-items: flex-start; gap: 0.35rem; color: var(--ink); }
.id-edit-form .id-edit-error { flex-basis: 100%; margin: 0; }

/* The one-time WhatsApp prompt: a full-screen backdrop with a centred card. It has
   no close control; the two steps (ask / number) swap via data-step. */
body.wa-prompt-open { overflow: hidden; }
.wa-prompt-backdrop { position: fixed; inset: 0; z-index: 10000; background: rgba(20, 24, 31, 0.6);
                      display: flex; align-items: center; justify-content: center; padding: 16px; }
.wa-prompt-card { background: var(--card, #fff); border-radius: 14px; max-width: 28rem; width: 100%;
                  padding: 1.2rem 1.25rem; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.25);
                  max-height: calc(100vh - 32px); overflow: auto; }
.wa-prompt-card h2 { margin: 0 0 0.6rem; font-size: 1.2rem; }
.wa-prompt-step { display: none; }
.wa-prompt-backdrop[data-step="ask"] [data-step-ask],
.wa-prompt-backdrop[data-step="number"] [data-step-number] { display: block; }
.wa-prompt-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.8rem; }
.wa-prompt-actions form { margin: 0; }
.wa-prompt-card .natis-field input { width: 100%; }

/* Page tabs — one page, several views as plain links (the Invoicing page's
   "Ready to invoice" / "Missing paperwork"). Pills that wrap rather than scroll,
   so they never push a phone screen sideways. */
.page-tabs { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.75rem 0 1.25rem; }
.page-tab { display: inline-flex; align-items: center; gap: 0.4rem; min-height: 40px;
            padding: 0.4rem 0.95rem; border: 1px solid var(--border); border-radius: 999px;
            text-decoration: none; color: var(--ink); background: var(--card); font-weight: 600; }
.page-tab:hover { border-color: var(--safgri-red); color: var(--safgri-red-dark); }
.page-tab.is-current { border-color: var(--safgri-red); background: var(--safgri-red);
                       color: #fff; }
.page-tab-count { min-width: 1.5em; padding: 0 0.4em; border-radius: 999px; text-align: center;
                  font-size: var(--fs-micro); font-weight: 700; line-height: 1.6;
                  background: var(--safgri-red-tint); color: var(--safgri-red-dark); }
.page-tab.is-current .page-tab-count { background: #fff; color: var(--safgri-red-dark); }
@media (max-width: 480px) {      /* both tabs side by side on a phone */
  .page-tabs { gap: 0.4rem; }
  .page-tab { padding: 0.35rem 0.7rem; font-size: 0.9rem; }
}

/* WhatsApp office inbox: tabs, the conversation list, and a conversation shown as
   bubbles — theirs on the left, ours on the right. */
.wa-inbox-tabs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.6rem 0 1rem; }
.wa-inbox-tab { padding: 0.35rem 0.75rem; border: 1px solid var(--border); border-radius: 999px;
                text-decoration: none; color: var(--ink); background: var(--card); }
.wa-inbox-tab.is-current { border-color: var(--safgri-red); color: var(--safgri-red); font-weight: 700; }
.wa-thread-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.wa-thread-row { display: flex; flex-direction: column; gap: 0.15rem; padding: 0.7rem 0.9rem;
                 background: var(--card); border: 1px solid var(--border); border-radius: 10px;
                 text-decoration: none; color: var(--ink); }
.wa-thread-row.needs-reply { border-left: 4px solid var(--safgri-red); }
.wa-thread-last { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wa-conversation { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.wa-msg { display: flex; flex-direction: column; max-width: 80%; }
.wa-msg-in { align-self: flex-start; }
.wa-msg-out { align-self: flex-end; align-items: flex-end; }
.wa-bubble { padding: 0.55rem 0.8rem; border-radius: 12px; white-space: pre-wrap; overflow-wrap: anywhere;
             background: var(--card); border: 1px solid var(--border); }
.wa-msg-out .wa-bubble { background: #e7f6ec; border-color: #c5e8d1; }
.wa-reply textarea { width: 100%; }
.wa-status-form { margin-top: 0.6rem; }
/* Assistant shadow drafts (never sent) */
.wa-job { list-style: none; border-left: 3px dashed var(--border); padding-left: 0.7rem; }
.wa-job-head { margin: 0 0 0.3rem; }
.wa-would-reply { font-style: italic; background: transparent; }
.wa-drafts { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 0.6rem; }
.wa-draft { background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 0.6rem 0.75rem; min-width: 0; }
.wa-draft-head { margin: 0 0 0.4rem; font-size: 0.95rem; display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
.wa-draft .wa-bubble { background: #f4f6f8; }
.wa-rate-form { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.4rem; }
.wa-rate-form input[type="text"] { flex: 1 1 8rem; min-width: 0; }
.wa-live { margin-top: 1rem; border-top: 1px solid var(--border); padding-top: 0.6rem; }
.wa-live-state { padding: 0.55rem 0.75rem; border-radius: 8px; margin: 0.3rem 0 0.5rem; }
.wa-live-on { background: #e7f6ed; color: #14683a; border: 1px solid #b9e2c8; }
.wa-live-off { background: #f4f6f8; color: var(--ink); border: 1px solid var(--border); }
.wa-live-list { width: 100%; margin: 0.4rem 0; }
@media (max-width: 600px) {
  .wa-live-list thead { display: none; }
  .wa-live-list, .wa-live-list tbody, .wa-live-list tr, .wa-live-list td { display: block; width: 100%; }
  .wa-live-list tr { padding: 0.5rem 0; border-bottom: 1px solid var(--border); }
  .wa-live-list td { border: 0; padding: 0.1rem 0; overflow-wrap: anywhere; }
}
.wa-own-setup { display: block; margin-top: 0.2rem; font-size: var(--fs-meta); }
.wa-live-add { margin-top: 0.5rem; display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-end; }
.wa-live-add .natis-field { flex: 0 1 22rem; min-width: 0; }
.wa-live-add select { width: 100%; flex: 0 0 auto; }
.wa-job-sent { margin: 0 0 0.3rem; color: #14683a; font-weight: 600; }
.wa-draft-sent { border-color: #7cc49a; box-shadow: 0 0 0 1px #7cc49a inset; }
.wa-pin-form { margin-top: 0.6rem; display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem; }
.wa-pin-form .natis-field { flex: 0 1 20rem; min-width: 0; }
.wa-pin-form select { width: 100%; flex: 0 0 auto; }
/* Knowledge base */
.kb-topic-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem; }
.kb-article-list { list-style: none; margin: 0 0 0.6rem; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.kb-safety { color: var(--bad, #b42318); }
.kb-article-form textarea { width: 100%; }
.kb-body { white-space: pre-wrap; overflow-wrap: anywhere; margin: 0.3rem 0 0; font-family: inherit; }

/* --------------------------------------------------------------------------- */
/* SafConnect branding: the banner lockup, the login lockup and the page       */
/* watermark. One logo file, static/brand/safconnect-logo.svg — an exact copy   */
/* of the marketing site's.                                                     */
/* --------------------------------------------------------------------------- */
.brand { gap: 0.55rem; text-decoration: none; }
.brand-safconnect { display: inline-flex; align-items: center; gap: 0.4rem; }
.brand-mark { width: 28px; height: 28px; display: block; flex: none; }
.brand-word {
  font-weight: 800; font-size: 1.05rem; letter-spacing: -0.02em;
  color: var(--ink); white-space: nowrap;
}
.brand-word em { font-style: normal; color: #8B1E2D; }
/* Phones: the banner is full (Back + up to six controls for an admin with the
   bell and a request badge), so the wordmark goes and the mark carries the
   brand. */
@media (max-width: 600px) {
  .brand-word { display: none; }
  .brand-mark { width: 26px; height: 26px; }
  /* Controls go to 36px (still well above the 24px minimum tap target) and
     pack without a gap; the banner's side padding tightens. */
  .topbar { padding-left: 0.75rem; padding-right: 0.75rem; gap: 0.5rem; }
  .topbar-right { gap: 0; }
  .topbar-refresh, .topbar-settings, .topbar-bell, .topbar .home-menu-toggle,
  .topbar-search > summary.topbar-search-toggle {
    width: 36px; height: 36px;
  }
}

/* Login page: the SafConnect logo in the bottom-right corner — the corner
   watermark's lockup and size, fully visible, on a white pill (the photos
   behind it are dark). */
.login-corner {
  position: fixed; z-index: 5;
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; gap: 7px;
  padding: 6px 12px 6px 6px;
  background: #fff; border-radius: 999px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
  pointer-events: none; user-select: none;
}
.login-corner img { width: 26px; height: 26px; display: block; flex: none; }
.login-corner-word {
  font-weight: 800; font-size: 19px; letter-spacing: -0.02em; line-height: 1;
  color: #1f2733; white-space: nowrap;
}
.login-corner-word em { font-style: normal; color: #8B1E2D; }
/* Keep the card clear of the corner: the page reserves the logo's height
   (plus its margin) at the bottom, and the card is centred in what is left. */
.login-page { padding-bottom: calc(3rem + 40px); }
@media (max-width: 600px) {
  .login-corner { gap: 5px; padding: 5px 10px 5px 5px;
    right: calc(12px + env(safe-area-inset-right, 0px));
    bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .login-corner img { width: 18px; height: 18px; }
  .login-corner-word { font-size: 13px; }
  .login-page { padding-bottom: calc(2.5rem + 30px); }
}
/* A short screen (a small phone, or one turned sideways) cannot hold the card
   and a fixed corner logo apart, so the logo joins the page flow below the
   card, still at the right. */
@media (max-height: 620px) {
  .login-corner { position: static; width: max-content; margin: 0 0 16px auto; }
  .login-page { padding-bottom: 1.5rem; }
}

/* The watermark: a small SafConnect logo fixed in the bottom-right corner,
   behind every in-flow element (z-index -1; the home photo sits further back
   at -2), so buttons, bars, cards and text always paint over it. Never
   clickable, never printed. 6% opacity: faint, and even its darkest pixel
   keeps muted grey text that scrolls over it at 4.59:1 (AA is 4.5:1).
   Clears the phone's home indicator via the safe-area inset. */
.app-watermark {
  position: fixed; z-index: -1;
  right: calc(16px + env(safe-area-inset-right, 0px));
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  display: flex; align-items: center; gap: 7px;
  opacity: 0.06;
  pointer-events: none; user-select: none;
}
.app-watermark img { width: 26px; height: 26px; display: block; flex: none; }
.app-watermark-word {
  font-weight: 800; font-size: 19px; letter-spacing: -0.02em; line-height: 1;
  color: #1f2733; white-space: nowrap;
}
.app-watermark-word em { font-style: normal; color: #8B1E2D; }
/* Room at the foot of every page, so the last button or line can always be
   scrolled clear of the corner logo. */
.app-watermark ~ .content { padding-bottom: calc(1.5rem + 56px); }
@media (max-width: 600px) {
  .app-watermark { gap: 5px;
    right: calc(12px + env(safe-area-inset-right, 0px));
    bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .app-watermark img { width: 18px; height: 18px; }
  .app-watermark-word { font-size: 13px; }
  .app-watermark ~ .content { padding-bottom: calc(1.5rem + 40px); }
}
@media print {
  .app-watermark { display: none !important; }
}
