/* ==========================================================================
   Northfleet Driver Portal — mobile-first (brand: BrandGuidelines V2.2)
   ========================================================================== */
:root{
  --blue:#2552A4;--blue-d:#1b3d7a;--orange:#F58A2A;--yellow:#FCD911;--red:#F23C00;
  --ink:#221F20;--bg:#eef1f6;--line:#e0e5ee;--muted:#6b7280;--muted-2:#9aa3b2;--ok:#1f9d55;
  --font:'Raleway',-apple-system,BlinkMacSystemFont,'Segoe UI',Arial,sans-serif;
  --bar:64px;--tabs:66px;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0}
/* column layout so the version line is pushed to the bottom of the screen even
   when a screen's content is short (main takes up the slack) */
body{font-family:var(--font);background:var(--bg);color:var(--ink);font-weight:600;padding-bottom:var(--tabs);
  display:flex;flex-direction:column;min-height:100vh;min-height:100dvh}
/* clear the tab bar at its real height — the bar grows by the home-indicator
   inset, so content reserving only --tabs ends up under it (0px in a tab) */
body{padding-bottom:calc(var(--tabs) + env(safe-area-inset-bottom))}
#dview{flex:1 0 auto}
h1,h2,h3{margin:0;font-weight:900}
button{font-family:var(--font);cursor:pointer}
select,input{font-family:var(--font)}

/* top bar */
/* min-height, not height: the account column is pill + driver select + vehicle
   line, and on a narrow phone with the sync pill showing that's three rows
   against 64px — the vehicle line used to spill out below the bar and render
   over the page, which looked like clipped text under the header. The bar now
   grows instead, and --bar-h (set from driver.js) carries its real height to
   everything that has to sit below or budget around it. */
.dbar{position:sticky;top:0;z-index:30;min-height:var(--bar);background:var(--ink);color:#fff;display:flex;align-items:center;justify-content:space-between;padding:6px 16px;gap:12px}
.dbar__brand{display:flex;align-items:center;gap:10px}
.dbar__mark{width:38px}
.dbar__word{font-weight:900;font-size:17px;line-height:1}
.dbar__word b{color:#fff} .dbar__word i{color:var(--orange);font-style:normal}
.dbar__sub{font-size:10px;font-weight:800;letter-spacing:2px;text-transform:uppercase;color:var(--muted-2)}
/* Two rows, always: the driver select, then the vehicle line — or the sync pill
   in its place while that's up. min-height holds the second row's space open
   whichever is in it, and whether the pill lands beside the select (a tablet,
   where there's width) or above it (a phone, where there isn't). Without that
   the bar's height changed with the pill, and the pinned header below it moved
   every time a change was saved. */
.dbar__acct{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:2px 8px;text-align:right;min-height:54px;min-width:0}
.dbar__acct select{order:2;background:#2c2829;color:#fff;border:1px solid #3a3738;border-radius:8px;padding:7px 10px;font-weight:800;font-size:13px;max-width:150px}
.dbar__veh{order:3;flex-basis:100%;min-width:0;max-width:100%;height:18px;line-height:18px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font-size:11px;font-weight:700;color:var(--muted-2)}
/* While the pill is up it takes the vehicle line's slot rather than adding a
   row: the bar's height then stays the same whether syncing or not, so the
   pinned header below it doesn't jump every time a change is saved. The pill
   precedes the vehicle line in the DOM, hence the sibling selector. The plate
   is always on the Truck tab, and a synced pill clears itself after 2.6s. */
.dsync:not([hidden]) ~ .dbar__veh{display:none}

/* PWA sync / offline status pill (shown only when a backend is configured) */
.dsync{display:inline-flex;align-items:center;gap:6px;height:18px;padding:0 9px;border-radius:999px;background:#2c2829;color:var(--muted-2);font-size:10.5px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;line-height:1}
.dsync[hidden]{display:none}
.dsync__dot{width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}
.dsync.is-synced{color:#8fe0b0;background:rgba(31,157,85,.18)}
.dsync.is-pending{color:#ffc98a;background:rgba(245,138,42,.18)}
.dsync.is-pending .dsync__dot{animation:dsync-pulse 1s ease-in-out infinite}
.dsync.is-offline{color:#ffb2a2;background:rgba(242,60,0,.20)}
/* Offline is normal out on a run; blocked is not — the office has to intervene.
   Solid red rather than a tint, and free to wrap, because it names a job. */
.dsync.is-blocked{color:#fff;background:var(--red);height:auto;min-height:18px;
  padding:3px 9px;text-transform:none;letter-spacing:0;font-size:11px;
  max-width:62vw;white-space:normal;text-align:left;line-height:1.25}
@keyframes dsync-pulse{0%,100%{opacity:1}50%{opacity:.25}}
@media (prefers-reduced-motion:reduce){.dsync.is-pending .dsync__dot{animation:none}}

/* install / add-to-home-screen banner */
.dinstall{display:flex;align-items:center;gap:12px;padding:10px 14px;background:#fff;border-bottom:1px solid var(--line)}
.dinstall[hidden]{display:none}
.dinstall__ico{width:34px;height:34px;border-radius:8px;flex:none}
.dinstall__txt{flex:1;min-width:0;line-height:1.25}
.dinstall__txt b{display:block;font-size:14px;font-weight:900;color:var(--ink)}
.dinstall__txt span{font-size:11px;font-weight:700;color:var(--muted)}
.dinstall__go{border:none;border-radius:9px;padding:9px 16px;font-weight:900;font-size:13px;background:var(--blue);color:#fff;flex:none}
.dinstall__x{border:none;background:none;color:var(--muted);font-size:15px;font-weight:800;padding:6px;line-height:1;flex:none}

/* installed (standalone) — keep the top bar clear of the notch. The bottom
   inset is handled unconditionally on .dtabs/body instead of here: Safari
   reports a bottom inset once its toolbar collapses too, so gating it on
   standalone left the tab bar under the home indicator in a browser tab. */
@media (display-mode:standalone),(display-mode:fullscreen){
  .dbar{min-height:calc(var(--bar) + env(safe-area-inset-top));padding-top:calc(6px + env(safe-area-inset-top))}
}

main{padding:16px 14px 24px;max-width:640px;margin:0 auto}

/* Section headers — pinned just under the top bar, so which screen you're on
   and whose run it is stay visible while the job list scrolls. The bar is
   itself sticky at 0 and grows by the notch inset when installed, so the offset
   has to include that (0px in a browser tab). Needs its own background or the
   cards would scroll through it, and a z-index below the bar's 30. The negative
   top margin cancels the padding so the resting position is unchanged. */
/* align-items:center, not baseline: the run sheet's header carries a 44px
   Refresh button, and a baseline-aligned one hangs below the heading. */
.dhead{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:2px 0 14px;
  position:sticky;top:var(--bar-h,calc(var(--bar) + env(safe-area-inset-top)));z-index:20;
  background:var(--bg);padding:8px 0 8px;margin-top:-6px;border-bottom:1px solid var(--line)}
.dhead h2{font-size:22px}
.dhead .sub{color:var(--muted);font-weight:700;font-size:13px}
.dhead>div{min-width:0}                       /* the heading column shrinks; the button doesn't */
.dhead__r{display:flex;align-items:center;gap:10px;flex:0 0 auto}
.dhead__r .sub{text-align:right}

/* How fresh the sheet is, and a way to ask again. Out of range the app is
   showing the last document the office sent; the driver has to be able to see
   that, and to pull the new one the moment they're back in signal. */
.dfresh{display:block;font-weight:700;font-size:12px;color:var(--muted)}
.dfresh.is-stale{color:var(--red)}
.drefresh{flex:0 0 44px;width:44px;height:44px;border:1px solid var(--line);background:#fff;
  border-radius:12px;font-family:inherit;font-size:21px;line-height:1;color:var(--blue);
  cursor:pointer;display:flex;align-items:center;justify-content:center}
.drefresh:disabled{opacity:.6;cursor:default}
.drefresh.is-busy{animation:drefresh-spin 1s linear infinite}
@keyframes drefresh-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){ .drefresh.is-busy{animation:none} }

/* chips / summary */
/* Today / Tomorrow switch on the run sheet. 48px tall so it's a comfortable
   thumb target in a cab without eating the space the job cards need. */
.drunday{display:flex;gap:8px;margin-bottom:14px}
.drunday button{flex:1;min-height:48px;border:1px solid var(--line);background:#fff;border-radius:12px;
  font-family:inherit;font-weight:800;font-size:15px;color:var(--muted);cursor:pointer;
  display:flex;align-items:center;justify-content:center;gap:8px}
.drunday button span{background:rgba(0,0,0,.08);border-radius:11px;padding:1px 8px;font-size:13px}
.drunday button.is-active{background:var(--blue);border-color:var(--blue);color:#fff}
.drunday button.is-active span{background:rgba(255,255,255,.25)}
.dchips{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:16px}
.dchip{background:#fff;border:1px solid var(--line);border-radius:12px;padding:9px 14px;font-weight:800}
.dchip b{display:block;font-size:19px;color:var(--blue)}

/* job cards */
.jcard{background:#fff;border:1px solid var(--line);border-radius:16px;padding:16px;margin-bottom:14px;box-shadow:0 1px 3px rgba(34,31,32,.06)}
.jcard.is-next{border-color:var(--orange);box-shadow:0 0 0 2px rgba(245,138,42,.25)}
.jcard.is-done{opacity:.6}
/* Preload / backload: on the board but not a job — no connote, nothing to
   capture. Flatter and dashed so it can't be mistaken for a stop with actions,
   but still in the day's order so the sheet matches the dispatcher's line. */
.jsupport{background:#fbfcfe;border:1px dashed var(--line);border-radius:14px;padding:12px 14px;margin-bottom:14px}
.jsupport__hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:14px;color:var(--ink)}
.jsupport__ico{font-size:15px;color:var(--muted)}
.jsupport__tag{margin-left:auto;font-size:10px;font-weight:900;letter-spacing:1px;text-transform:uppercase;color:var(--muted-2);border:1px solid var(--line);border-radius:20px;padding:2px 8px;background:#fff}
.jsupport__route{margin-top:4px;font-size:12.5px;font-weight:700;color:var(--muted)}
.jsupport__meta{margin-top:5px;font-size:12px;font-weight:700;color:var(--muted-2)}
.jcard__top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}
.jseq{width:30px;height:30px;border-radius:9px;background:var(--ink);color:#fff;display:grid;place-items:center;font-weight:900;flex-shrink:0}
.jcard.is-next .jseq{background:var(--orange)}
.jroute{font-weight:900;font-size:17px;line-height:1.2}
.jconnote{font-weight:800;font-size:12px;letter-spacing:.4px;color:var(--orange);margin-top:2px}
.jleg{display:flex;align-items:center;gap:8px;margin:8px 0;font-weight:700}
.jleg .dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.jleg .dot--p{background:var(--blue)} .jleg .dot--d{background:var(--ok)}
.jmeta{color:var(--muted);font-weight:700;font-size:13px;margin:2px 0}
.jgoods{font-weight:700;font-size:14px;margin-top:6px}
.jinstr{background:#fff6ef;border:1px solid #f6d3ab;border-radius:10px;padding:9px 12px;font-weight:700;font-size:13px;margin-top:10px}
.jrelay{background:#e8effb;border:1px solid #c5d6f2;border-radius:10px;padding:8px 11px;margin:8px 0 2px;
  font-size:12.5px;font-weight:700;color:#2b4470;line-height:1.35}
.jrelay b{display:block;font-weight:900;color:var(--blue)}
.jrelay.is-wait{background:#fff6ef;border-color:#f6d3ab;color:#7a4a12}
.jrelay.is-wait b{color:#c96a12}
.jrelay__tr{display:inline-block;margin-top:3px;font-size:11px;font-weight:800;color:var(--muted)}
.jinstr b{color:#c96a12}
/* The rig (#247) — what is hooked up behind the truck. Reads as a fact about
   the unit rather than an instruction, so it borrows the muted meta styling
   rather than the orange site-note panel. */
.jrig{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin:4px 0 2px}
.jrig b{font-weight:900;font-size:14px;letter-spacing:.2px}
.jrig__n{color:var(--muted);font-weight:800;font-size:11.5px}
/* route / run reference material (#171) — read-only, one-tap open */
.jref{margin-top:10px;display:flex;flex-direction:column;gap:6px}
.jref__hd{font-weight:900;font-size:11px;letter-spacing:.4px;text-transform:uppercase;color:var(--muted-2)}
.jref__item{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:#eef4ff;border:1px solid #c5d6f2;border-radius:10px;padding:11px 12px;font-family:inherit;font-weight:800;font-size:14px;color:var(--blue);cursor:pointer;min-height:48px}
.jref__item:active{background:#e0ebff}
.jref__ico{font-size:16px;flex:none}
.jref__t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.jref__go{font-size:11px;font-weight:800;color:var(--muted);flex:none}
/* the same on the Drive screen — compact, still a full touch target */
.drv-refs{display:flex;flex-direction:column;gap:8px}
.drv-ref{justify-content:flex-start;gap:8px;font-size:15px;min-height:48px}
.jactions{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:14px}
.jactions .full{grid-column:1 / -1}

/* badges */
.badge{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:800;padding:5px 11px;border-radius:999px;white-space:nowrap}
.badge::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.badge--blue{background:#e8effb;color:var(--blue)}
.badge--orange{background:#fdefe0;color:#c96a12}
.badge--green{background:#e4f6ec;color:var(--ok)}
.badge--red{background:#fde6df;color:var(--red)}
.badge--grey{background:#eef1f6;color:var(--muted)}

/* buttons */
.dbtn{border:none;border-radius:12px;padding:14px 16px;font-weight:800;font-size:15px;min-height:50px;display:flex;align-items:center;justify-content:center;gap:8px}
.dbtn--primary{background:var(--blue);color:#fff}
.dbtn--orange{background:var(--orange);color:#fff}
.dbtn--green{background:var(--ok);color:#fff}
.dbtn--ghost{background:#eef1f6;color:var(--ink)}
.dbtn--danger{background:#fde6df;color:var(--red)}
.dbtn--block{width:100%}
a.dbtn{text-decoration:none}

/* pre-start checklist */
.chk-item{display:flex;align-items:center;justify-content:space-between;gap:10px;background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px 14px;margin-bottom:10px}
.chk-item__l{font-weight:800;font-size:15px}
.chk-toggle{display:flex;gap:6px}
.chk-toggle button{border:1px solid var(--line);background:#f4f6fa;border-radius:9px;padding:8px 14px;font-weight:800;font-size:13px;color:var(--muted)}
.chk-toggle button.ok.is-on{background:var(--ok);color:#fff;border-color:var(--ok)}
.chk-toggle button.bad.is-on{background:var(--red);color:#fff;border-color:var(--red)}
.chk-defect{margin-top:8px}
.chk-defect input{width:100%;padding:10px 12px;border:1px solid var(--red);border-radius:9px;font-weight:600}
.chk-done{background:#e4f6ec;border:1px solid #b6e4c8;border-radius:14px;padding:18px;text-align:center;font-weight:800;color:var(--ok)}

/* fatigue */
.fat-status{background:var(--ink);color:#fff;border-radius:16px;padding:18px;margin-bottom:16px}
.fat-status .big{font-size:30px;font-weight:900}

/* ==========================================================================
   Drive page — the in-cab display. Designed around a tablet mounted landscape
   in the truck: three columns that fit the screen without scrolling, big
   glanceable numbers, and touch targets a driver can hit at arm's length.
   Falls back to a single stacked column on a phone (map last).
   ========================================================================== */
.drv{display:grid;grid-template-columns:1fr;gap:12px}
.drv-col{display:flex;flex-direction:column;gap:12px;min-width:0}
.drv-col--map{order:3}                       /* portrait: actions before the map */
.drv-col .card{margin-bottom:0}
/* speed */
.drv-speed{background:var(--ink);color:#fff;border-radius:18px;padding:20px 16px;text-align:center;transition:background .2s;display:flex;flex-direction:column;justify-content:center}
.drv-speed.is-ok{background:#123b23}
.drv-speed.is-over{background:var(--red);animation:drvflash 1s steps(2,jump-none) infinite}
@keyframes drvflash{50%{background:#9e2800}}
@media (prefers-reduced-motion:reduce){.drv-speed.is-over{animation:none}}
.drv-speed__val{display:flex;align-items:baseline;justify-content:center;gap:8px;line-height:1}
.drv-speed__val #drv-speed-num{font-size:clamp(72px,16vh,150px);font-weight:900;letter-spacing:-3px;font-variant-numeric:tabular-nums}
/* no fix yet — a 150px dash reads as a glitch, so shrink the placeholder */
.drv-speed.is-wait #drv-speed-num{font-size:clamp(38px,7vh,64px);letter-spacing:0;color:var(--muted-2)}
.drv-speed__val small{font-size:20px;font-weight:800;color:var(--muted-2)}
.drv-speed.is-ok .drv-speed__val small,.drv-speed.is-over .drv-speed__val small{color:rgba(255,255,255,.8)}
.drv-speed__msg{margin-top:10px;font-weight:800;font-size:15px;min-height:22px}
.drv-lim-row{display:flex;align-items:center;justify-content:center;gap:6px;margin-top:14px;flex-wrap:wrap}
.drv-lim-lbl{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:1px;color:var(--muted-2);margin-right:2px}
.drv-lim-src{text-transform:none;letter-spacing:0;font-weight:800;color:rgba(255,255,255,.7)}
.drv-lim{border:none;border-radius:10px;padding:10px 14px;min-height:48px;min-width:54px;font-weight:900;font-size:16px;background:rgba(255,255,255,.14);color:#fff}
.drv-lim.is-on{background:var(--yellow);color:var(--ink)}
/* break countdown */
.drv-brk__top{display:flex;justify-content:space-between;align-items:center;font-size:15px}
.drv-brk__top span{font-weight:900;font-size:20px;font-variant-numeric:tabular-nums}
.drv-brk__bar{height:16px;border-radius:999px;background:#e7ebf2;overflow:hidden;margin:12px 0 6px}
.drv-brk__fill{height:100%;width:0;background:var(--ok);border-radius:999px;transition:width .5s linear}
.drv-brk__fill.is-warn{background:var(--orange)}
.drv-brk__fill.is-due{background:var(--red)}
.drv-brk__sub{font-size:12px;color:var(--muted);font-weight:700}
.drv-brk__nums{display:flex;gap:10px;margin-top:12px}
.drv-brk__nums>div{flex:1;background:#f4f6fa;border-radius:10px;padding:9px 6px;text-align:center}
.drv-brk__nums b{display:block;font-size:19px;font-weight:900;font-variant-numeric:tabular-nums}
.drv-brk__nums span{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;color:var(--muted-2)}
.drv-brk .dbtn{margin-top:12px}
/* live map */
.drv-map{position:relative;border-radius:14px;overflow:hidden;border:1px solid var(--line);height:230px;background:#dfe4ec}
.drv-map #drv-map{position:absolute;inset:0}
.drv-map__note{position:absolute;left:8px;top:8px;z-index:500;background:rgba(34,31,32,.85);color:#fff;font-size:11.5px;font-weight:800;padding:6px 10px;border-radius:8px}
.drv-map__note[hidden]{display:none}
.drv-mapbtn{position:absolute;right:8px;bottom:8px;z-index:500;border:none;background:#fff;color:var(--ink);font-weight:900;font-size:14px;min-height:48px;padding:12px 16px;border-radius:11px;box-shadow:0 2px 10px rgba(0,0,0,.28)}
.drv-mapbtn.is-on{background:var(--blue);color:#fff}   /* showing the leg / panned away */
.drv-mapbtn[hidden]{display:none}
.drv-me{border-radius:50%;background:var(--blue);border:3px solid #fff;box-shadow:0 0 0 6px rgba(37,82,164,.25)}
.drv-pin{border-radius:50%;background:var(--orange);border:3px solid #fff;box-shadow:0 1px 5px rgba(0,0,0,.4)}
/* distance / ETA */
.drv-eta{background:#fff;border:1px solid var(--line);border-radius:14px;padding:12px 14px;text-align:center}
.drv-eta__d{font-size:38px;font-weight:900;line-height:1;font-variant-numeric:tabular-nums}
.drv-eta__d small{font-size:16px;font-weight:800;color:var(--muted);margin-left:4px}
.drv-eta__t{font-weight:900;font-size:17px;color:var(--blue);margin-top:3px}
.drv-eta__s{font-size:11.5px;font-weight:700;color:var(--muted-2);margin-top:3px}
/* next stop + actions */
.drv-alert{display:block;width:100%;text-align:left;border:none;border-radius:12px;background:var(--yellow);color:var(--ink);font-family:inherit;font-weight:900;font-size:15px;line-height:1.25;padding:14px 16px;min-height:60px}
.drv-alert small{display:block;font-size:12px;font-weight:800;opacity:.7;margin-top:2px}
.drv-stop{padding:14px 16px}
.drv-stop__tag{font-size:11px;font-weight:900;letter-spacing:1.2px;color:var(--orange)}
.drv-stop b{display:block;font-size:21px;line-height:1.2;margin-top:3px}
.drv-stop__pl{font-weight:700;font-size:13.5px;color:var(--muted);margin-top:4px}
/* a stop that isn't today's reads as a heads-up, not as the job in front of them */
.drv-stop__rig{font-weight:900;font-size:13.5px;margin-top:5px;letter-spacing:.2px}
.drv-stop--ahead{opacity:.9;border-left:4px solid var(--muted)}
.drv-stop--ahead .drv-stop__tag{color:var(--muted)}
.drv-row{display:flex;gap:10px}
.drv-row .dbtn{flex:1;padding:14px 8px}
/* the actions column sits on the page background, so ghost buttons need an edge */
.drv-col--act .dbtn--ghost{background:#fff;border:2px solid var(--line)}
.drv-big{min-height:64px;font-size:17px}
.dbtn.is-locked{opacity:.45}
.drv-lock{font-size:12px;font-weight:800;color:var(--muted);text-align:center}
.drv-lock[hidden]{display:none}

/* Landscape tablet — the mounted-in-the-cab case: three columns, one screen,
   no page scroll, and slimmer chrome to give the display the height. */
@media (orientation:landscape) and (min-width:820px){
  body.is-drive{--bar:54px;--tabs:60px;overflow:hidden}
  body.is-drive .dinstall,body.is-drive .dver{display:none}   /* don't steal cab height */
  body.is-drive main{max-width:none;padding:10px 12px}
  /* The chrome this subtracts grows by the safe-area insets when installed, and
     this screen must fit with no page scroll — so take those off too (both 0px
     in a browser tab, where the viewport already excludes the insets). */
  body.is-drive .drv{grid-template-columns:1fr 1.15fr 1fr;height:calc(100vh - var(--bar) - var(--tabs) - 20px)}
  body.is-drive .drv{height:calc(100dvh - var(--bar) - var(--tabs) - 20px)}
  body.is-drive .drv{height:calc(100dvh - var(--bar-h,var(--bar)) - var(--tabs) - 20px
    - env(safe-area-inset-bottom))}
  body.is-drive .drv-col--map{order:0}
  body.is-drive .drv-speed{flex:1}
  body.is-drive .drv-lim-row{margin-top:auto;padding-top:16px}   /* chips to the bottom edge */
  body.is-drive .drv-map{flex:1;height:auto}
  body.is-drive .drv-col--act{overflow-y:auto}
  body.is-drive .drv-stop b{font-size:23px}
  body.is-drive .dtab{font-size:11.5px}
  /* toasts drop to the top — at the bottom they'd cover the ETA readout */
  body.is-drive .dtoast{top:10px;bottom:auto;transform:translateX(-50%) translateY(-220%)}
  body.is-drive .dtoast.is-show{transform:translateX(-50%) translateY(0)}
}

/* Geofence driver advisory (#83) — high-contrast banner + persistent voice mute.
   The banner is position:fixed so it overlays the Drive screen without adding any
   layout height — the in-cab display must still fit one screen with no scroll. */
.drv-adv{position:fixed;left:12px;right:12px;top:calc(var(--bar-h,60px) + 10px);z-index:1200;
  box-sizing:border-box;max-width:960px;margin:0 auto;
  display:flex;align-items:center;gap:14px;padding:16px;border-radius:16px;
  background:var(--blue);color:#fff;box-shadow:0 10px 34px rgba(0,0,0,.4);animation:advin .18s ease-out}
.drv-adv--warning{background:var(--orange);color:var(--ink)}
.drv-adv--critical{background:var(--red);color:#fff;animation:advin .18s ease-out, drvflash 1s steps(2,jump-none) infinite}
@media (prefers-reduced-motion:reduce){.drv-adv--critical{animation:advin .18s ease-out}}
@keyframes advin{from{transform:translateY(-16px);opacity:0}to{transform:translateY(0);opacity:1}}
.drv-adv__ico{font-size:36px;line-height:1;flex:none}
.drv-adv__body{flex:1;min-width:0}
.drv-adv__msg{font-size:24px;font-weight:900;line-height:1.15}
.drv-adv__where{font-size:12.5px;font-weight:800;opacity:.82;margin-top:4px;text-transform:uppercase;letter-spacing:.6px}
.drv-adv__x{flex:none;width:64px;height:64px;border:none;border-radius:14px;font-size:26px;font-weight:900;
  background:rgba(255,255,255,.22);color:inherit;cursor:pointer;font-family:inherit}
.drv-adv--warning .drv-adv__x{background:rgba(0,0,0,.14)}

.drv-mute{position:absolute;left:8px;bottom:8px;z-index:500;border:none;width:64px;height:64px;border-radius:14px;
  background:#fff;color:var(--ink);font-size:26px;box-shadow:0 2px 10px rgba(0,0,0,.28);cursor:pointer;font-family:inherit}
.drv-mute.is-muted{background:var(--ink);color:#fff}

/* ==========================================================================
   IN-CAB TABLET (#250) — prefix `cab-`, verified unused in driver.css and
   driver.js before it was added.

   The device belongs to the TRUCK: "one tablet per truck… with a stand and a
   hard cover, because they're going to drop it down on mine sites". Everything
   here is drawn only when this device has been assigned to one — an unassigned
   phone renders none of it, which is what keeps the pre-#250 behaviour intact.

   Sizing rule throughout: 44px is the floor and the primary controls are 52px+,
   because these get hit at arm's length, in gloves, in full sun, in a truck
   that may be idling. Nothing here is position:fixed — the Drive screen has to
   fit one screen with no scroll, and .drv-adv already owns the fixed overlay.
   ========================================================================== */

/* --- top bar ---
   The truck's identity goes in the brand's own sub-line, because that is the
   one part of the bar the sync pill never takes over (the vehicle line is
   display:none while the pill is up). Ellipsised and width-capped: a rego is
   longer than the word "Driver" it replaces, and the bar must not start
   scrolling sideways on a phone. */
.dbar__brand{min-width:0}
.dbar__brand>div{min-width:0}
.dbar__sub.cab-bar{color:var(--orange);letter-spacing:.6px;font-size:11px;
  max-width:38vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* The driver switcher is a phone control. On a truck's tablet the driver signs
   ON and OFF, so it is swapped for the sign-on button — the select stays in the
   DOM and stays functional, it is just not the affordance here. */
body.cab-bound #drv-sel{display:none}
.cab-who{order:2;display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:1px;
  min-height:44px;max-width:170px;padding:4px 12px;border:1px solid #3a3738;border-radius:10px;
  background:#2c2829;color:#fff;font-family:inherit;cursor:pointer;text-align:right}
.cab-who[hidden]{display:none}
.cab-who__n{font-weight:900;font-size:14px;line-height:1.1;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cab-who__s{font-size:9.5px;font-weight:800;letter-spacing:1px;text-transform:uppercase;color:var(--muted-2);line-height:1}

/* --- the honesty line ---
   Used everywhere a name or an hours figure is shown: a selection is not
   authentication (SSO is #66) and this app is not an approved work diary. Same
   refusal the compliance register and the speed screen make. */
.cab-note{display:block;margin-top:8px;font-size:11px;font-weight:700;line-height:1.45;color:var(--muted-2)}

/* --- device identity card (Truck tab + modal) --- */
.cab-idcard{display:flex;align-items:center;gap:12px;background:#f4f6fa;border:1px solid var(--line);
  border-radius:14px;padding:12px 14px}
.cab-idcard--none{background:#fbfcfe;border-style:dashed}
.cab-idcard__ico{font-size:26px;line-height:1;flex:none}
.cab-idcard__b{min-width:0}
.cab-idcard__b b{display:block;font-size:17px;font-weight:900;line-height:1.2}
.cab-idcard__b small{display:block;font-size:12px;font-weight:700;color:var(--muted);margin-top:2px;line-height:1.35}
/* Truck tab: one row, tappable, opens the device modal. */
.cab-devrow{display:flex;align-items:center;gap:12px;width:100%;text-align:left;min-height:60px;
  background:#f4f6fa;border:1px solid var(--line);border-radius:14px;padding:10px 14px;
  font-family:inherit;color:var(--ink);cursor:pointer}

/* --- run sheet: which truck this is and who is on it --- */
.cab-strip{background:#fff;border:1px solid var(--line);border-left:5px solid var(--orange);
  border-radius:14px;padding:12px 14px;margin-bottom:12px}
.cab-strip__hd{display:flex;align-items:center;gap:10px}
.cab-strip__ico{font-size:22px;line-height:1;flex:none}
.cab-strip__t{min-width:0}
.cab-strip__t b{display:block;font-size:17px;font-weight:900;line-height:1.2}
.cab-strip__t small{display:block;font-size:11px;font-weight:800;letter-spacing:.4px;text-transform:uppercase;color:var(--muted-2)}
.cab-strip__who{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;margin-top:10px;
  padding-top:10px;border-top:1px solid var(--line)}
.cab-strip__who b{font-size:16px;font-weight:900}
.cab-strip__who span{font-size:12px;font-weight:700;color:var(--muted)}
.cab-strip__note{margin-top:8px;background:#fff6ef;border:1px solid #f6d3ab;border-radius:10px;
  padding:9px 12px;font-size:13px;font-weight:700;color:#7a4a12;line-height:1.4}
.cab-strip__row{display:flex;gap:8px;margin-top:10px}
.cab-btn{flex:1;min-height:52px;font-size:15px}

/* --- unsynced work ---
   Never a quiet line. This is the one thing that can lose a driver's capture at
   a handover, so it is red, it names what is outstanding, and it says in as many
   words that signing off deletes nothing. */
.cab-warn{margin-top:10px;background:#fff6f2;border:2px solid var(--red);border-radius:12px;padding:12px 14px}
.cab-warn b{display:block;color:var(--red);font-size:14.5px;font-weight:900;line-height:1.3}
.cab-warn p{margin:6px 0 0;font-size:13px;font-weight:700;color:#8a2b12;line-height:1.5}
.cab-warn__keep{color:var(--ink) !important}
.cab-warnhost[hidden]{display:none}

/* --- pickers (driver, truck) --- */
.cab-list{display:flex;flex-direction:column;gap:8px;margin-top:12px}
.cab-opt{display:flex;align-items:center;gap:10px;width:100%;text-align:left;min-height:56px;
  background:#fff;border:1px solid var(--line);border-radius:12px;padding:10px 14px;
  font-family:inherit;color:var(--ink);cursor:pointer}
.cab-opt.is-on{border-color:var(--blue);background:#eef4ff;box-shadow:0 0 0 1px var(--blue) inset}
.cab-opt__b{flex:1;min-width:0}
.cab-opt__b b{display:block;font-size:15.5px;font-weight:900;line-height:1.25}
.cab-opt__b small{display:block;font-size:12px;font-weight:700;color:var(--muted);margin-top:2px;line-height:1.35}
.cab-opt__go{flex:none;font-size:12px;font-weight:900;color:var(--blue)}

/* --- fatigue on glass ---
   "get that warning that you have with that green bar, you are coming up to
   your five hour break". Green while there is room, amber on the adapter's
   warning, red on its breach — the thresholds are NF.EWD's, never a second copy
   in the driver app. */
.cab-fat{background:#fff;border:1px solid var(--line);border-left:5px solid var(--ok);
  border-radius:14px;padding:12px 14px;margin-bottom:14px}
.cab-fat__top{display:flex;align-items:center;justify-content:space-between;gap:10px}
.cab-fat__top b{font-size:15px;font-weight:900}
.cab-fat__rem{font-size:22px;font-weight:900;font-variant-numeric:tabular-nums;color:var(--ok)}
.cab-fat__bar{height:14px;border-radius:999px;background:#e7ebf2;overflow:hidden;margin:10px 0 8px}
.cab-fat__bar span{display:block;height:100%;width:0;border-radius:999px;background:var(--ok);transition:width .5s linear}
.cab-fat__msg{font-size:13.5px;font-weight:700;line-height:1.45}
.cab-fat__row{display:flex;gap:8px;margin-top:10px}
.cab-fat--soon{border-left-color:var(--orange);background:#fff9f3}
.cab-fat--soon .cab-fat__rem{color:#c96a12}
.cab-fat--soon .cab-fat__bar span{background:var(--orange)}
.cab-fat--due{border-left-color:var(--red);background:#fff6f2}
.cab-fat--due .cab-fat__rem{color:var(--red)}
.cab-fat--due .cab-fat__bar span{background:var(--red)}
.cab-fat--due .cab-fat__msg{color:#8a2b12;font-weight:800}
.cab-fat--rest{border-left-color:var(--blue)}
.cab-fat--rest .cab-fat__rem{color:var(--blue)}

/* the same states on the Drive screen's break card, which already carries the
   countdown — colouring the card it is in beats adding a second panel to a
   layout that must fit one screen */
.cab-brkmsg{display:block;font-size:13.5px;font-weight:800;line-height:1.4;color:var(--ink)}
.cab-brk--soon{border-color:var(--orange);background:#fff9f3}
.cab-brk--soon .cab-brkmsg{color:#c96a12}
.cab-brk--due{border-color:var(--red);background:#fff6f2}
.cab-brk--due .cab-brkmsg{color:var(--red);font-size:15px;font-weight:900}

/* --- sign-on screen (the login gate on a truck tablet) --- */
.cab-lgtruck{display:flex;align-items:center;gap:11px;background:#f4f6fa;border:1px solid var(--line);
  border-radius:12px;padding:11px 13px;margin-bottom:6px}
.cab-lgtruck[hidden]{display:none}
.cab-lgtruck__ico{font-size:24px;line-height:1;flex:none}
.cab-lgtruck__b{min-width:0}
.cab-lgtruck__b b{display:block;font-size:16px;font-weight:900;line-height:1.2}
.cab-lgtruck__b small{display:block;font-size:11.5px;font-weight:700;color:var(--muted);margin-top:2px;line-height:1.3}
.login__hint .cab-note{margin-top:6px;text-align:center}

/* HQ messages */
.dmsg-btn{position:relative;margin-left:auto;background:rgba(255,255,255,.12);border:none;color:#fff;width:40px;height:40px;border-radius:11px;font-size:19px;flex:none;display:flex;align-items:center;justify-content:center}
.dmsg-badge{position:absolute;top:-4px;right:-4px;background:var(--red);color:#fff;font-size:10px;font-weight:900;min-width:17px;height:17px;border-radius:9px;display:inline-flex;align-items:center;justify-content:center;padding:0 4px}
.dmsg-badge[hidden]{display:none}      /* the display rule above beats the attribute */
.msg-body{display:flex;flex-direction:column;gap:10px;background:#f2f4f8}
.dmsg{max-width:82%;padding:9px 12px;border-radius:14px}
.dmsg__t{font-size:14px;line-height:1.35}
.dmsg__m{font-size:11px;font-weight:700;color:var(--muted-2);margin-top:3px}
.dmsg--in{align-self:flex-start;background:#fff;border:1px solid var(--line);border-bottom-left-radius:4px}
.dmsg--out{align-self:flex-end;background:var(--blue);color:#fff;border-bottom-right-radius:4px}
.dmsg--out .dmsg__m{color:rgba(255,255,255,.72)}
.dmsg-empty{margin:auto;color:var(--muted);font-weight:700}
#drv-msg-input{padding:11px 14px;border:1px solid var(--line);border-radius:10px;font-size:15px;font-family:inherit}
/* incident severity selector */
.inc-sev{display:flex;gap:8px}
.inc-sev button{flex:1;border:1px solid var(--line);background:#fff;border-radius:9px;padding:11px;font-weight:800;color:var(--muted);font-family:inherit}
.inc-sev button.is-on[data-sev="low"]{background:var(--ok);color:#fff;border-color:var(--ok)}
.inc-sev button.is-on[data-sev="medium"]{background:var(--orange);color:#fff;border-color:var(--orange)}
.inc-sev button.is-on[data-sev="high"]{background:var(--red);color:#fff;border-color:var(--red)}
/* asset documents */
.dd-row{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:none;border:none;border-bottom:1px solid var(--line);padding:11px 2px;font-family:inherit}
.dd-row:last-child{border-bottom:none}
.dd-ico{font-size:17px;width:24px;text-align:center;color:var(--muted-2);flex:none}
.dd-b{flex:1;min-width:0}
.dd-b b{display:block;font-size:14px;font-weight:800}
.dd-b small{color:var(--muted);font-weight:700;font-size:12px}
.dd-pill{font-size:11px;font-weight:900;padding:2px 8px;border-radius:999px;white-space:nowrap;flex:none}
.dd--ok{background:#e3f5ea;color:var(--ok)}
.dd--soon{background:#fdecd8;color:#c96a12}
.dd--exp{background:#fde6df;color:var(--red)}
/* load & dimension check */
.lc-sec{font-size:11px;font-weight:900;text-transform:uppercase;letter-spacing:1px;color:var(--muted-2);margin:16px 0 8px}
.lc-dims{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.lc-flag{margin-top:12px;padding:10px 12px;border-radius:10px;font-weight:800;font-size:13px}
.lc-flag.is-ok{background:#e3f5ea;color:var(--ok)}
.lc-flag.is-over{background:#fde6df;color:var(--red)}
/* hours & breaks guide (see NF.EWD — this app is not the diary of record) */
.ewd-notice{background:#fff6ef;border:1px solid #f6d3ab;border-radius:12px;padding:11px 13px;margin-bottom:14px;font-weight:700;font-size:13px;line-height:1.35;color:#7a4a12}
.ewd-notice b{display:block;font-weight:900;color:#c96a12;margin-bottom:2px}
/* a certified provider is connected — informational, not a warning */
.ewd-notice.is-provider{background:#e8effb;border-color:#c5d6f2;color:#2b4470}
.ewd-notice.is-provider b{color:var(--blue)}
.ewd{margin-bottom:16px}
.ewd-nums{display:flex;justify-content:space-between;text-align:center;margin-bottom:14px}
.ewd-nums b{display:block;font-size:20px;font-weight:900}
.ewd-nums span{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.5px;color:var(--muted-2)}
.ewd-lbl{font-size:12px;font-weight:800;color:var(--muted);margin:10px 0 5px}
.ewd-bar{height:14px;border-radius:999px;background:#e7ebf2;overflow:hidden}
.ewd-fill{height:100%;width:0;background:var(--ok);border-radius:999px;transition:width .4s}
.ewd-fill.is-amber{background:var(--orange)}
.ewd-fill.is-red{background:var(--red)}
.ewd-alert{margin-top:12px;padding:10px 12px;border-radius:10px;background:#fde6df;color:var(--red);font-weight:800;font-size:13px}
/* docket job forms */
.dock-form{display:flex;align-items:center;gap:10px;width:100%;text-align:left;background:#fff7ee;border:1px solid #f5d9b8;border-radius:10px;padding:10px 12px;margin-bottom:6px;font-family:inherit;color:var(--ink)}
.dock-form.is-done{background:#eef8f1;border-color:#c6e6d2}
.dock-form>span:first-child{font-size:17px}
/* docket documents & permits */
.dock-doc{display:flex;align-items:center;gap:10px;text-decoration:none;color:var(--ink);background:#f7f9fc;border:1px solid var(--line);border-radius:10px;padding:10px 12px;margin-bottom:6px}
.dock-doc__b{flex:1;min-width:0}
.dock-doc__b b{display:block;font-size:14px}
.dock-doc__b small{color:var(--muted);font-weight:700;font-size:12px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dock-doc__go{color:var(--blue);font-weight:800;font-size:12px;white-space:nowrap;flex:none}
.fat-hint{background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px 14px;font-weight:700;font-size:13px;color:var(--muted);margin-bottom:14px}
.fat-log{background:#fff;border:1px solid var(--line);border-radius:12px;padding:6px 14px}
.fat-row{display:flex;justify-content:space-between;padding:10px 0;border-bottom:1px solid var(--line);font-weight:700;font-size:14px}
.fat-row:last-child{border-bottom:none}

/* truck / profile */
.card{background:#fff;border:1px solid var(--line);border-radius:16px;padding:18px;margin-bottom:14px}
.kv{display:grid;grid-template-columns:auto 1fr;gap:9px 16px}
.kv dt{color:var(--muted);font-weight:700;font-size:13px}
.kv dd{margin:0;font-weight:800;text-align:right}
.sec-title{font-size:12px;text-transform:uppercase;letter-spacing:1px;color:var(--muted);font-weight:800;margin:0 0 12px}

/* fields */
.dfld{display:block;margin-bottom:14px}
.dfld span{display:block;font-weight:800;font-size:13px;margin-bottom:6px}
.dfld input,.dfld select{width:100%;padding:13px 14px;border:1px solid var(--line);border-radius:11px;font-size:16px;font-weight:600;background:#fff}
.dchk{display:flex;align-items:center;gap:10px;font-weight:700;font-size:14px;margin-top:4px}
.dchk input{width:20px;height:20px}

/* build version stamp */
/* The padding moves onto the link so the version is a usable tap target in a
   cab; the totals are unchanged (4+6 top, 6+8 bottom), which keeps the stamp
   flush above the tab bar the way drive-screen.js asserts. */
.dver{flex:none;text-align:center;padding:4px 14px 8px;font-size:11.5px;font-weight:700;letter-spacing:.3px;color:var(--muted-2)}
.dver__link{display:inline-block;padding:6px 10px;color:var(--muted-2);
  text-decoration:underline;text-underline-offset:2px}
.dver__link:active{color:var(--blue)}

/* bottom tabs */
/* The bar has to cover the home-indicator strip and still keep its full height
   for the labels. box-sizing is border-box app-wide, so padding-bottom alone
   comes OUT of the declared height instead of adding to it — on an iPhone that
   left the labels crammed into the top half with a dead white band under them.
   The height carries the inset as well. Plain declaration first: env() is 0px
   in a browser tab (so nothing changes there) and a browser without env() at
   all drops only the second line rather than losing the bar's height. */
.dtabs{position:fixed;bottom:0;left:0;right:0;height:var(--tabs);background:#fff;border-top:1px solid var(--line);display:flex;z-index:30}
.dtabs{height:calc(var(--tabs) + env(safe-area-inset-bottom));padding-bottom:env(safe-area-inset-bottom)}
.dtab{flex:1;border:none;background:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;font-weight:800;font-size:11px;color:var(--muted)}
.dtab__ico{font-size:18px}
.dtab.is-active{color:var(--blue)}
.dtab.is-active .dtab__ico{transform:translateY(-1px)}

/* modal */
.dmodal{position:fixed;inset:0;background:rgba(34,31,32,.55);display:none;align-items:flex-end;justify-content:center;z-index:100}
.dmodal.is-open{display:flex}
/* 94vh leaves 6vh of scrim above a sheet — less than the notch inset on a short
   phone, which would put the sheet's own header (and its close button) under the
   status bar. Take the inset off the cap so a sheet always stops clear of it. */
.dmodal__card{background:#fff;border-radius:20px 20px 0 0;width:100%;max-width:640px;
  max-height:calc(94vh - env(safe-area-inset-top));overflow:auto}
.dmodal__head{display:flex;align-items:center;justify-content:space-between;padding:18px 20px;border-bottom:1px solid var(--line);position:sticky;top:0;background:#fff;z-index:10}
.dmodal__head h2{font-size:19px}
/* 44px, not 38 — the iOS minimum, and it matches .fr-back so the runner's
   header is symmetrical. This is the only way out of a form. */
.dmodal__x{border:none;background:#eef1f6;width:44px;height:44px;border-radius:50%;font-size:17px;flex-shrink:0}
.dmodal__body{padding:18px 20px}
.dmodal__foot{display:flex;gap:10px;padding:14px 20px;border-top:1px solid var(--line);position:sticky;bottom:0;background:#fff;z-index:10}
.dmodal__foot .dbtn{flex:1}
.dmodal__foot #pod-mode{flex:1.3}
.pod-meta{background:#f4f6fa;border:1px solid var(--line);border-radius:11px;padding:12px 14px;font-weight:700;font-size:14px;margin-bottom:16px}
.pod-meta b{color:var(--blue)}
.pod-pad-wrap{position:relative;border:2px solid var(--blue);border-radius:12px;overflow:hidden;margin-bottom:14px}
.pod-pad-lbl{position:absolute;top:8px;left:12px;font-size:11px;font-weight:800;text-transform:uppercase;color:var(--muted-2);pointer-events:none}
.pod-pad{display:block;width:100%;height:200px;touch-action:none}
.pod-photo{margin-top:14px}
.pod-thumbs{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.pod-thumbs .pt{position:relative}
.pod-thumbs img{height:84px;border-radius:10px;border:1px solid var(--line);display:block}
.pod-thumbs .pt-x{position:absolute;top:-7px;right:-7px;width:24px;height:24px;border-radius:50%;border:none;background:var(--red);color:#fff;font-weight:800;font-size:12px;cursor:pointer}
.geo-stamp{margin-top:14px;font-size:12px;font-weight:700;color:var(--muted);background:#f4f6fa;border:1px solid var(--line);border-radius:9px;padding:8px 12px}
.geo-stamp.is-ok{color:var(--ok)}
.dmodal__card.is-fail .dmodal__head h2{color:var(--red)}

/* toast */
/* Hidden with opacity + visibility, not by translating it far enough away: the
   transform only moves the toast by a multiple of its own height, which for an
   empty single-line pill (28px) didn't clear this app's 82px offset — it sat
   visible on the tab bar and swallowed taps on the centre tab. pointer-events
   stays off regardless; a toast is never interactive. */
.dtoast{position:fixed;bottom:calc(var(--tabs) + 16px);bottom:calc(var(--tabs) + env(safe-area-inset-bottom) + 16px);left:50%;transform:translateX(-50%) translateY(60%);background:var(--ink);color:#fff;padding:14px 22px;border-radius:12px;font-weight:800;z-index:200;transition:.35s;box-shadow:0 10px 30px rgba(0,0,0,.3);max-width:90vw;text-align:center;pointer-events:none;opacity:0;visibility:hidden}
.dtoast.is-show{transform:translateX(-50%) translateY(0);opacity:1;visibility:visible}
.dtoast--ok{background:var(--ok)} .dtoast--err{background:var(--red)}

.empty{background:#fff;border:1px dashed var(--line);border-radius:14px;padding:30px;text-align:center;color:var(--muted);font-weight:700}

/* digital docket */
.dock-hd{border:2px solid var(--ink);border-radius:12px;padding:12px 14px;margin-bottom:14px}
.dock-hd__no{font-weight:900;font-size:20px;color:var(--blue)}
.dock-hd__cust{font-weight:800}
.dock-hd__ref{color:var(--muted);font-weight:700;font-size:13px}
.dock-party{border:1px solid var(--line);border-radius:11px;padding:10px 12px;margin-bottom:10px;font-weight:700;position:relative;font-size:14px}
.dock-party b{display:block}
.dock-party div{color:var(--muted);font-weight:600;font-size:13px}
.dock-tag{display:inline-block;background:#111;color:#fff;font-size:9px;font-weight:800;padding:2px 8px;border-radius:3px;margin-bottom:5px}
.dock-contact{margin-top:6px;font-weight:700;font-size:13px;color:var(--muted)}
.dock-contact a{color:var(--blue);font-weight:800;text-decoration:none}
/* ---- #280 who did which component, read from the cab ----------------------
   Prefix `dhov-`, verified unused across driver/driver.css, css/app.css and
   portal/portal.css first. Read-only: the driver hands the trailer over through
   the existing .dock-hand step, and there is deliberately no writer here.
   "Nothing captured yet" is drawn HATCHED, the same refusal .dcmp-chip--indet
   makes -- it is neither done nor not-due, and it is the fact the dispatcher's
   hand-over refusal turns on. */
.dhov{display:flex;flex-direction:column;gap:8px}
.dhov-c{border:1px solid var(--line);border-left:5px solid var(--muted-2);border-radius:12px;
  background:#fff;padding:10px 12px}
.dhov-c--done{border-left-color:var(--ok)}
.dhov-c--doing{border-left-color:var(--orange)}
.dhov-c--blocked{border-left-color:var(--yellow)}
.dhov-c--mine{background:#f4f8ff}
.dhov-c__hd{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;font-size:15px;font-weight:800}
.dhov-c__n{flex:none;font-size:11px;font-weight:900;letter-spacing:.5px;color:#fff;background:var(--ink);
  border-radius:7px;padding:3px 7px}
.dhov-c__you{font-size:10.5px;font-weight:900;letter-spacing:.5px;text-transform:uppercase;color:#fff;
  background:var(--blue);border-radius:6px;padding:2px 6px}
.dhov-c__state{margin-left:auto;font-size:11px;font-weight:900;letter-spacing:.5px;text-transform:uppercase;color:var(--muted)}
.dhov-c__rt{font-size:13px;font-weight:700;color:var(--muted);margin-top:3px}
.dhov-c__caps{display:flex;flex-direction:column;gap:2px;margin-top:6px}
.dhov-c__st{font-size:13.5px;font-weight:700}
.dhov-c__st b{color:var(--blue)}
.dhov-c__none{display:inline-block;font-size:13px;font-weight:800;color:var(--muted);padding:3px 8px;border-radius:7px;
  background-image:repeating-linear-gradient(45deg,#eef0f4 0 5px,#f8f9fb 5px 10px);border:1px solid var(--line)}
.dock-sec{font-size:12px;text-transform:uppercase;letter-spacing:1px;color:var(--muted);font-weight:800;margin:16px 0 8px}
.dock-items{width:100%;border-collapse:collapse}
.dock-items td{border:1px solid var(--line);padding:7px 9px;font-weight:700;font-size:13px}
.dock-items td:first-child{width:44px;text-align:center}
.dock-time{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--line)}
.dock-time:last-of-type{border-bottom:none}
.dock-time__l{flex:1}
.dock-time__l b{display:block;font-size:14px}
.dock-time__l small{color:var(--muted);font-weight:700;font-size:11px}
.dock-tin{width:112px;padding:9px 10px;border:1px solid var(--line);border-radius:9px;font-family:var(--font);font-weight:700;font-size:15px}
.dock-now{min-height:40px;padding:8px 14px}
/* guided job flow */
.fstep{display:flex;align-items:center;gap:12px;padding:10px 0;position:relative}
.fstep::before{content:"";position:absolute;left:15px;top:42px;bottom:-10px;width:2px;background:var(--line)}
.fstep:last-of-type::before{display:none}
.fstep__n{width:32px;height:32px;border-radius:50%;background:#e4e9f2;color:var(--muted);display:grid;place-items:center;font-weight:900;flex-shrink:0;z-index:1}
.fstep__b{flex:1;min-width:0}
.fstep__b b{display:block;font-size:14.5px}
.fstep__b small{color:var(--muted);font-weight:700;font-size:11.5px}
.fstep__c{flex-shrink:0}
.fstep--done .fstep__n{background:var(--ok);color:#fff}
.fstep--done::before{background:var(--ok)}
.fstep--active{background:#fff6ef;border:2px solid var(--orange);border-radius:14px;padding:12px 10px;margin:6px -4px}
.fstep--active .fstep__n{background:var(--orange);color:#fff}
.fstep--todo{opacity:.45}
.flow-btn{min-height:48px;padding:10px 16px;font-size:14px;white-space:nowrap}
@media(max-width:480px){
  .fstep--active{flex-wrap:wrap}
  .fstep--active .fstep__c{width:100%;margin-top:8px}
  .fstep--active .flow-btn{width:100%}
}

/* login gate */
.login{position:fixed;inset:0;background:linear-gradient(135deg,#1b3d7a 0%,#221F20 90%);display:grid;place-items:center;z-index:500;padding:20px}
.login.is-hidden{display:none}
.login__card{background:#fff;border-radius:18px;padding:30px 26px;width:min(360px,100%);display:flex;flex-direction:column;box-shadow:0 30px 80px rgba(0,0,0,.45)}
.login__mark{width:74px;margin:0 auto}
.login__word{text-align:center;font-weight:900;font-size:24px;margin-top:8px}
.login__word b{color:var(--ink)} .login__word i{color:var(--orange);font-style:normal}
.login__app{text-align:center;font-weight:800;font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--muted);margin-bottom:16px}
.login__lbl{font-weight:800;font-size:13px;margin:12px 0 5px}
.login select,.login input{padding:13px 14px;border:1px solid var(--line);border-radius:11px;font-family:var(--font);font-weight:600;font-size:16px;background:#fff}
.login .dbtn{margin-top:18px}
.login__err{color:var(--red);font-weight:800;font-size:13px;min-height:16px;margin-top:8px}
.login__hint{color:var(--muted-2);font-weight:700;font-size:12px;margin-top:16px;text-align:center;line-height:1.5}

/* ===================================================================
   FORM RUNNER  (L&D checks and any other NF.formTemplates form)
   ==========================================================================
   Built for a driver standing at a loaded trailer: full screen, one section at
   a time, 64px+ targets, high contrast for direct sun, and the primary action
   pinned to the same spot on every screen so it can be hit without looking.
   -------------------------------------------------------------------------- */
.dmodal--full{align-items:stretch}
.fr-card{border-radius:0;max-width:720px;max-height:100%;height:100%;display:flex;flex-direction:column;overflow:hidden}
/* The runner is the one full-screen overlay, and the page is viewport-fit=cover
   — so on an installed iPhone this header owns the notch strip. Without the top
   inset the close button is drawn under the status bar, where iOS swallows the
   tap for its own scroll-to-top: the X is visible but dead, and rotating to
   landscape (no top inset) was the only way to hit it. Unconditional, not
   inside the display-mode block, for the same reason the tab bar's bottom inset
   is: the manifest's display_override lists minimal-ui, which that query does
   not match, and where the inset is 0 this changes nothing. */
.fr-head{display:flex;align-items:center;gap:10px;
  padding:calc(14px + env(safe-area-inset-top)) 16px 14px;
  border-bottom:1px solid var(--line);flex-shrink:0}
.fr-head__t{flex:1;min-width:0;text-align:center}
.fr-head__t b{display:block;font-size:17px;font-weight:900;line-height:1.2}
.fr-head__t small{display:block;color:var(--muted);font-weight:700;font-size:12px;margin-top:2px}
.fr-back{border:none;background:#eef1f6;width:44px;height:44px;border-radius:50%;font-size:26px;line-height:1;font-weight:800;color:var(--ink);flex-shrink:0}
.fr-bar{height:5px;background:#eef1f6;flex-shrink:0}
.fr-bar span{display:block;height:100%;background:var(--orange);transition:width .2s;border-radius:0 3px 3px 0}
.fr-body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:16px}
.fr-foot{padding:12px 16px calc(12px + env(safe-area-inset-bottom));border-top:1px solid var(--line);background:#fff;flex-shrink:0}
.dbtn--xl{min-height:64px;font-size:18px;border-radius:14px}

.fr-intro{background:#f4f6fb;border-radius:14px;padding:14px 16px;margin-bottom:18px}
.fr-intro b{font-size:15px}
.fr-intro p{color:var(--muted);font-weight:700;font-size:13px;line-height:1.5;margin:6px 0 0}
.fr-intro__ctx{margin-top:10px;font-weight:900;font-size:13px;color:var(--blue)}
.fr-sec__t{font-size:13px;font-weight:900;letter-spacing:1.2px;text-transform:uppercase;color:var(--muted-2);margin:22px 0 12px}
.fr-sec__t:first-child{margin-top:0}

.fr-q{border:2px solid var(--line);border-radius:14px;padding:14px;margin-bottom:14px;background:#fff}
.fr-q.is-answered{border-color:#d7e6d9;background:#fbfdfb}
.fr-q.is-bad{border-color:var(--red);background:#fff6f2}
.fr-q__l{display:flex;align-items:flex-start;gap:10px;font-weight:800;font-size:16px;line-height:1.4}
.fr-q__l span{flex:1;min-width:0}
.fr-req{flex-shrink:0;margin-top:2px;font-style:normal;font-size:10px;font-weight:900;letter-spacing:.6px;text-transform:uppercase;color:var(--orange);margin-left:8px}
.fr-help{color:var(--muted);font-weight:600;font-size:13px;line-height:1.5;margin:6px 0 0}
.fr-note{background:#fff8e6;border-left:4px solid var(--yellow);border-radius:10px;padding:13px 14px;font-weight:700;font-size:14px;line-height:1.55;margin-bottom:14px}

/* YES / NO — the most-tapped control in the app, so it's the biggest */
.fr-yn{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:12px}
.fr-yn__b{border:2px solid var(--line);background:#fff;border-radius:14px;min-height:64px;font-family:var(--font);font-weight:900;font-size:20px;letter-spacing:1px;color:var(--muted)}
.fr-yn__yes.is-on{background:var(--ok);border-color:var(--ok);color:#fff}
.fr-yn__no.is-on{background:var(--red);border-color:var(--red);color:#fff}

.fr-opts{display:flex;flex-direction:column;gap:8px;margin-top:12px}
.fr-opt{border:2px solid var(--line);background:#fff;border-radius:12px;min-height:58px;padding:10px 14px;text-align:left;font-family:var(--font);font-weight:800;font-size:15px;color:var(--ink)}
.fr-opt.is-on{border-color:var(--blue);background:#eef2fb;color:var(--blue)}

.fr-in{width:100%;padding:15px 14px;border:2px solid var(--line);border-radius:12px;font-family:var(--font);font-weight:700;font-size:17px;background:#fff;margin-top:12px}
.fr-in--big{font-size:20px;font-weight:900;letter-spacing:.5px;min-height:60px}
.fr-ta{font-size:16px;font-weight:600;line-height:1.5}

/* Photo tiles — tap anywhere on the tile, thumbnails big enough to check */
.fr-shots{display:flex;flex-wrap:wrap;gap:10px;margin-top:12px}
.fr-cam{border:2px dashed var(--blue);background:#f4f7fd;border-radius:14px;min-height:96px;min-width:120px;flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-family:var(--font);font-weight:800;font-size:14px;color:var(--blue);padding:12px}
.fr-cam__i{font-size:26px}
.fr-shot{position:relative;width:96px;height:96px;border-radius:12px;overflow:hidden;background:#eef1f6;flex-shrink:0}
.fr-shot img{width:100%;height:100%;object-fit:cover;display:block}
.fr-shot__x{position:absolute;top:3px;right:3px;border:none;background:rgba(34,31,32,.72);color:#fff;width:30px;height:30px;border-radius:50%;font-size:14px;font-weight:800}

/* STOP panel — deliberately loud; it's a legal stop, not a warning.
   `.dock-stop` is the docket's counterpart, shown under the blocked flow step:
   the form's panel only exists while the form is open, but the load is still
   held afterwards and the driver still has a call to make. Same styling on
   purpose — a stop should look identical wherever it appears. */
.fr-stop,.dock-stop{margin-top:14px;background:#fff6f2;border:2px solid var(--red);border-radius:14px;padding:14px}
.fr-stop b,.dock-stop b{display:block;color:var(--red);font-size:17px;font-weight:900;letter-spacing:.5px}
.fr-stop p,.dock-stop p{color:#8a2b12;font-weight:700;font-size:13px;line-height:1.55;margin:6px 0 0}
.fr-stop--sum{margin:0 0 16px}
.fr-stop__call,.dock-stop__call{display:flex;align-items:center;justify-content:center;min-height:56px;margin-top:12px;background:var(--red);color:#fff;border-radius:12px;font-weight:900;font-size:16px;text-align:center;padding:8px 12px;line-height:1.2;text-decoration:none}
.fr-stop__lbl{display:block;font-weight:800;font-size:13px;margin-top:14px}
.dock-stop{margin:2px 0 12px}
.dock-stop__ref{font-style:normal;opacity:.9}

/* Review screen */
.fr-warn{background:#fff8e6;border-left:4px solid var(--orange);border-radius:10px;padding:13px 14px;font-weight:800;font-size:14px;margin-bottom:16px}
.fr-ok{background:#eaf7ee;border-left:4px solid var(--ok);border-radius:10px;padding:13px 14px;font-weight:800;font-size:14px;color:#166534;margin-bottom:16px}
.fr-rev{display:flex;align-items:center;gap:10px;width:100%;text-align:left;border:1px solid var(--line);border-radius:12px;background:#fff;padding:12px 14px;margin-bottom:8px;min-height:56px;font-family:var(--font)}
.fr-rev__l{flex:1;font-weight:700;font-size:14px;line-height:1.4}
.fr-rev__v{font-weight:900;font-size:14px;color:var(--ink);white-space:nowrap}
.fr-rev__go{font-weight:800;font-size:11px;text-transform:uppercase;letter-spacing:.6px;color:var(--blue);white-space:nowrap}
.fr-rev.is-miss{border-color:var(--orange);background:#fffaf3}
.fr-rev.is-miss .fr-rev__v{color:var(--orange)}
.fr-rev.is-bad{border-color:var(--red);background:#fff6f2}
.fr-rev.is-bad .fr-rev__v{color:var(--red)}
.fr-sig{color:var(--muted-2);font-weight:700;font-size:12px;line-height:1.55;margin-top:16px}

/* Landscape phone: keep the action reachable, shrink the chrome */
@media(max-height:520px){
  .fr-head{padding:calc(8px + env(safe-area-inset-top)) 12px 8px}
  .fr-head__t b{font-size:15px}
  .dbtn--xl{min-height:54px;font-size:16px}
  .fr-yn__b{min-height:54px}
}

/* Quick-pick chips (trailers at this depot) — saves typing a plate one-handed */
.fr-chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px}
.fr-chip{border:2px solid var(--line);background:#fff;border-radius:11px;padding:9px 12px;min-height:52px;font-family:var(--font);font-weight:900;font-size:15px;color:var(--ink);text-align:left;display:flex;flex-direction:column;justify-content:center}
.fr-chip small{display:block;font-weight:700;font-size:11px;color:var(--muted-2);margin-top:2px}
.fr-chip.is-on{border-color:var(--blue);background:#eef2fb;color:var(--blue)}
/* ---- Visible keyboard focus ----------------------------------------------
   :focus-visible only shows the ring for keyboard users, so mouse and touch
   look unchanged. Without this, tabbing through a dialog gives no clue where
   you are — the browser default ring is invisible against the brand blues. */
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,
textarea:focus-visible,[tabindex]:focus-visible{
  outline:3px solid var(--yellow);outline-offset:2px;border-radius:6px}
.modal.is-open .modal__card:focus-visible,.dmodal.is-open .dmodal__card:focus-visible{outline:none}

/* ---- Daily checks launcher (prestart / fitness for work / trailer) ---- */
.dwarn{display:block;width:100%;text-align:left;background:#fff8e6;border:2px solid var(--orange);border-radius:12px;padding:13px 14px;margin-bottom:10px;font-family:var(--font);font-weight:700;font-size:14px;line-height:1.5;color:var(--ink)}
.dwarn b{font-weight:900}
.dcheck{display:flex;align-items:center;gap:12px;width:100%;text-align:left;background:#fff;border:2px solid var(--line);border-radius:14px;padding:14px;margin-bottom:10px;min-height:76px;font-family:var(--font)}
.dcheck.is-done{border-color:#d7e6d9;background:#fbfdfb}
.dcheck.is-bad{border-color:var(--red);background:#fff6f2}
.dcheck__i{font-size:26px;width:34px;text-align:center;flex-shrink:0}
.dcheck__b{flex:1;min-width:0}
.dcheck__b b{display:block;font-size:16px;font-weight:900}
.dcheck__b small{display:block;color:var(--muted);font-weight:700;font-size:12px;line-height:1.45;margin-top:3px}
.dcheck__go{font-weight:800;font-size:12px;color:var(--blue);white-space:nowrap;flex-shrink:0}
.dcheck__note{color:var(--muted-2);font-weight:700;font-size:12px;line-height:1.5;margin-top:14px}

/* ---- Form runner: checklist, repeat groups, signature ---- */
.fr-checks{display:flex;flex-direction:column;gap:8px;margin-top:12px}
.fr-check{display:flex;align-items:center;gap:12px;border:2px solid var(--line);background:#fff;border-radius:12px;padding:10px 12px;min-height:58px;font-family:var(--font);font-weight:800;font-size:15px;text-align:left;color:var(--ink)}
.fr-check__box{width:30px;height:30px;border:2px solid var(--line);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:17px;color:#fff;flex-shrink:0}
.fr-check.is-on{border-color:var(--ok);background:#f4fbf6}
.fr-check.is-on .fr-check__box{background:var(--ok);border-color:var(--ok)}
.fr-all{width:100%;margin-top:10px;border:2px dashed var(--blue);background:#f4f7fd;color:var(--blue);border-radius:12px;min-height:52px;font-family:var(--font);font-weight:800;font-size:14px}
.fr-all.is-on{border-style:solid;background:var(--ok);border-color:var(--ok);color:#fff}
.fr-unit{border:2px solid var(--line);border-radius:12px;padding:12px;margin-top:12px;background:#fbfcfe}
.fr-unit__hd{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.fr-unit__hd b{font-size:14px;font-weight:900;text-transform:uppercase;letter-spacing:.6px;color:var(--muted)}
.fr-unit__x{border:none;background:#fde6df;color:var(--red);border-radius:9px;padding:7px 12px;font-family:var(--font);font-weight:800;font-size:12px;min-height:38px}
.fr-sub{margin-bottom:12px}
.fr-sub:last-child{margin-bottom:0}
.fr-sub__l{font-weight:800;font-size:14px;line-height:1.4}
.fr-sub .fr-opt{min-height:50px;font-size:14px}
.fr-sub .fr-yn__b{min-height:54px;font-size:17px}
.fr-sub .fr-in{margin-top:8px;padding:12px}
.fr-add{width:100%;margin-top:12px;border:2px dashed var(--blue);background:#f4f7fd;color:var(--blue);border-radius:12px;min-height:56px;font-family:var(--font);font-weight:800;font-size:15px}
.fr-opt--bad.is-on{border-color:var(--red);background:#fff1eb;color:var(--red)}
.fr-q.is-flagged,.fr-sub.is-flagged{border-color:var(--red)}
.fr-defect{margin-top:10px;background:#fff6f2;border-left:4px solid var(--red);border-radius:9px;padding:10px 12px;font-weight:700;font-size:13px;line-height:1.5;color:#8a2b12}
.fr-warn--defect ul{margin:8px 0 0;padding-left:18px;font-weight:700;font-size:13px;line-height:1.6}
.fr-warn--defect li{list-style:disc}
.fr-pad-wrap{position:relative;border:2px solid var(--blue);border-radius:12px;overflow:hidden;margin-top:12px;background:#fff}
.fr-pad-lbl{position:absolute;top:8px;left:12px;font-size:11px;font-weight:800;text-transform:uppercase;color:var(--muted-2);pointer-events:none}
.fr-pad{display:block;width:100%;height:180px;touch-action:none}
.fr-pad-btns{display:flex;gap:10px;margin-top:10px}
.fr-pad-btns button{flex:1;border:none;border-radius:12px;min-height:52px;font-family:var(--font);font-weight:800;font-size:15px}
.fr-pad-clear{background:#eef1f6;color:var(--ink)}
.fr-pad-ok{background:var(--blue);color:#fff}
.fr-signed{margin-top:12px;border:2px solid #d7e6d9;border-radius:12px;background:#fbfdfb;padding:10px;text-align:center}
.fr-signed img{max-width:100%;height:110px;object-fit:contain;display:block;margin:0 auto}
.fr-resign{margin-top:8px;border:none;background:#eef1f6;color:var(--ink);border-radius:10px;padding:9px 14px;font-family:var(--font);font-weight:800;font-size:13px;min-height:42px}

/* ==========================================================================
   TICKETS — licences / inductions / medicals (LMS v2 #230). Own `dcmp-`
   namespace, verified unused before adding. Touch targets ≥44px: this is used
   one-handed, in glare, often wearing gloves.
   ========================================================================== */
.dcmp-lead{margin:0 0 12px;color:var(--muted);font-weight:700;font-size:13.5px;line-height:1.55}
.dcmp-sec{margin:16px 0 8px;font-weight:900;font-size:12px;text-transform:uppercase;letter-spacing:.7px;color:var(--muted)}
.dcmp-row{margin-bottom:10px}
.dcmp-row__hd{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:4px}
.dcmp-row__hd b{font-size:15px;line-height:1.3}
.dcmp-row__why{margin:0 0 6px;color:var(--muted);font-weight:700;font-size:13px;line-height:1.5}
.dcmp-row__meta{color:var(--muted-2);font-weight:800;font-size:12px;margin-bottom:10px}
.dcmp-days{color:#b3200a;margin-left:6px}
.dcmp-add,.dcmp-row .dbtn{min-height:44px}
/* Status chips. `indeterminate` is NOT green: telling a driver they're current
   when nobody can confirm it is the one mistake that could put them on the road
   out of ticket. */
.dcmp-chip{flex:none;font-size:11.5px;font-weight:800;padding:4px 10px;border-radius:20px;white-space:nowrap}
.dcmp-chip--compliant{background:#e4f5ea;color:#1f7a44}
.dcmp-chip--expiring{background:#fdefe0;color:#b4650f}
.dcmp-chip--grace{background:#fdf0e4;color:#9a4d00}
.dcmp-chip--waived{background:#eef2fb;color:#2552A4}
.dcmp-chip--unverified{background:#f2f0fb;color:#5b46b8}
.dcmp-chip--rejected,.dcmp-chip--expired{background:#fde6df;color:#b3200a}
.dcmp-chip--missing{background:#eceff4;color:#5b6472}
.dcmp-chip--indet{background:repeating-linear-gradient(135deg,#f4f2ea,#f4f2ea 5px,#eae6d8 5px,#eae6d8 10px);color:#7a6520;border:1px dashed #c9b877}
.dcmp-note{margin:0 0 12px;color:var(--muted);font-weight:700;font-size:13px;line-height:1.5}
.dcmp-fld{display:block;margin-bottom:12px}
.dcmp-fld span{display:block;font-weight:800;font-size:12.5px;color:var(--muted);margin-bottom:5px}
.dcmp-fld input{width:100%;min-height:48px;box-sizing:border-box;padding:10px 12px;border:1px solid var(--line);border-radius:11px;font-family:inherit;font-size:16px;font-weight:700}
.dcmp-shots{display:flex;flex-wrap:wrap;gap:9px;margin-bottom:14px}
.dcmp-shot{position:relative;width:88px;height:88px;border-radius:11px;overflow:hidden;border:1px solid var(--line)}
.dcmp-shot img{width:100%;height:100%;object-fit:cover;display:block}
.dcmp-shot__x{position:absolute;top:2px;right:2px;width:30px;height:30px;border:none;border-radius:50%;background:rgba(0,0,0,.62);color:#fff;font-size:14px;font-weight:900;cursor:pointer}
.dcmp-shot__add{width:88px;height:88px;border:2px dashed var(--line);border-radius:11px;background:none;font-family:inherit;font-weight:800;font-size:13px;color:var(--muted);cursor:pointer}

/* ==========================================================================
   ASSESSMENTS (#238) — the driver's quiz runner. The QUESTIONS themselves reuse
   the existing form-runner CSS (`.fr-q`, `.fr-opts`, `.fr-opt`, `.fr-yn`,
   `.fr-in`) because a quiz IS a form template with marking — there is no second
   renderer. Only the things a form has no equivalent for live here: the start
   card, the score, and the two result panels.

   `qz-` verified unused in driver/driver.css, css/app.css, driver/driver.js and
   js/app.js before it was added.

   Every tappable thing below is >= 44px, and the two result panels are visually
   DIFFERENT from each other AND from "not assessed": a fail and a not-yet-sat
   are different facts about a driver and must never read the same.
   ========================================================================== */
.qz-chip{flex:none;font-size:11px;font-weight:800;padding:3px 9px;border-radius:20px;white-space:nowrap}
.qz-chip--passed{background:#e4f5ea;color:#1f7a44}
.qz-chip--failed{background:#fde6df;color:#b3200a}
.qz-chip--exhausted{background:#fde6df;color:#8a1f00;border:1px solid #b3200a}
.qz-chip--not-assessed{background:#eceff4;color:#5b6472}
.qz-intro{background:#f4f6fb;border-radius:14px;padding:14px 16px;margin:14px 0}
.qz-intro>b{display:block;font-size:15px;font-weight:900}
.qz-intro p{color:var(--muted);font-weight:700;font-size:13px;line-height:1.5;margin:6px 0 0}
.qz-count{margin:0 0 14px;color:var(--muted);font-weight:800;font-size:13px}
.qz-score{display:flex;align-items:baseline;gap:10px;margin:2px 0 12px}
.qz-score b{font-size:34px;font-weight:900;line-height:1}
.qz-score span{color:var(--muted);font-weight:800;font-size:13px}
/* The heading carries its own class rather than being styled as `.qz-res b`.
   A bare `b` selector made every EMPHASIS inside the paragraph a block as well,
   so "This has <b>not</b> been recorded as complete" broke across three lines —
   and it is the sentence that tells a driver their course is still outstanding,
   which is the one sentence on the panel that has to read cleanly. */
.qz-res{border-radius:14px;padding:16px;margin-bottom:14px}
.qz-res__t{display:block;font-size:18px;font-weight:900;letter-spacing:.4px}
.qz-res p{font-weight:700;font-size:13.5px;line-height:1.55;margin:6px 0 0}
.qz-res--pass{background:#eaf7ef;border:2px solid var(--ok)}
.qz-res--pass .qz-res__t{color:#166b35}
.qz-res--pass p{color:#1f5c37}
.qz-res--fail{background:#fff6f2;border:2px solid var(--red)}
.qz-res--fail .qz-res__t{color:var(--red)}
.qz-res--fail p{color:#8a2b12}
.qz-wrong{border:2px solid var(--line);border-left:5px solid var(--red);border-radius:12px;padding:12px 14px;margin-bottom:10px;background:#fff}
.qz-wrong__q{font-weight:800;font-size:14.5px;line-height:1.4}
.qz-wrong__fb{color:var(--muted);font-weight:700;font-size:13px;line-height:1.5;margin:6px 0 0}
.qz-rem{background:#fff8e6;border-left:4px solid var(--yellow);border-radius:10px;padding:13px 14px;
  font-weight:700;font-size:13.5px;line-height:1.55;margin-bottom:12px}
.qz-call{display:flex;align-items:center;justify-content:center;min-height:56px;background:var(--red);color:#fff;
  border-radius:12px;font-weight:900;font-size:16px;text-decoration:none;padding:8px 12px;text-align:center}

/* ==========================================================================
   SESSIONS I WAS AT (LMS2-E, #235) — confirming attendance at a toolbox talk,
   pre-start briefing or VOC, in a crib room with no signal.
   `dses-` verified unused in driver/driver.css, css/app.css and all three apps'
   JS before it was added. The pad itself reuses the form runner's `.fr-pad*`
   rules deliberately — one signature pad, one set of touch targets — and only
   the things below are new.
   ========================================================================== */
.dses-card{margin-bottom:10px}
/* THE attestation chip. `--none` is HATCHED, exactly as .dcmp-chip--indet is and
   for the same reason: "nobody has confirmed you were in the room" is neither
   present nor absent, and a green tick there would tell a driver their attendance
   is on record when it is not. */
.dses-chip{flex:none;font-size:11px;font-weight:800;padding:3px 9px;border-radius:20px;white-space:nowrap}
.dses-chip--ok{background:rgba(31,157,85,.15);color:#146c3a}
.dses-chip--none{background:repeating-linear-gradient(135deg,#f4f2ea,#f4f2ea 5px,#eae6d8 5px,#eae6d8 10px);
  color:#7a6520;border:1px dashed #c9b877}
/* Three findings, three appearances. A recorded "not yet competent" is an
   assessment that did not pass and the driver has to be able to read it — it is a
   different fact from nobody having assessed them, which is blank. */
.dses-out{flex:none;font-size:11px;font-weight:800;padding:3px 9px;border-radius:20px;white-space:nowrap;color:var(--muted)}
.dses-out--competent{background:rgba(31,157,85,.15);color:#146c3a}
.dses-out--not-yet-competent{background:rgba(245,138,42,.18);color:#8a4a06}
.dses-out--attended{background:#eef1f6;color:var(--blue)}
.dses-done{margin-top:9px;padding:9px 11px;border-radius:10px;background:#f2f6fb;
  color:var(--muted);font-weight:700;font-size:12.5px;line-height:1.5}
.dses-err{margin-top:9px;padding:9px 11px;border-radius:10px;background:rgba(242,60,0,.08);
  border:1px solid rgba(242,60,0,.35);color:#a32900;font-weight:800;font-size:13px;line-height:1.5}
/* The pad and its buttons borrow .fr-pad / .fr-pad-btns; these only re-declare
   what the form runner's own wrapper classes would otherwise supply, because the
   card here is not inside a form step. */
.dses-pad-wrap{position:relative;border:2px solid var(--blue);border-radius:12px;overflow:hidden;
  margin-top:12px;background:#fff}
.dses-pad-lbl{position:absolute;top:8px;left:12px;font-size:11px;font-weight:800;text-transform:uppercase;
  color:var(--muted-2);pointer-events:none}
.dses-pad-btns{display:flex;gap:10px;margin-top:10px}
.dses-pad-btns .dbtn{flex:1}
/* "Recorded" and "recorded AND uploaded" are different claims, and the driver is
   the one person who can act on the second. Amber, never red: nothing is lost. */
.dses-held{margin-top:8px;padding:9px 11px;border-radius:10px;background:rgba(245,138,42,.12);
  color:#8a4a06;font-weight:800;font-size:12.5px;line-height:1.5}
