/*
 * Bodyshop design system — global tokens, self-hosted fonts, base typography.
 * Bootstrap 5 is imported before this (in app.js); these rules layer the brand on top.
 * Page-specific layout lives in its own file (e.g. auth.css).
 */

@font-face {
    font-family: 'Bebas Neue';
    src: url("../fonts/bebas-neue-400-kCS-Go6.woff2") format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Archivo';
    src: url("../fonts/archivo-400-6zzj1o8.woff2") format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Archivo';
    src: url("../fonts/archivo-600-som1JOa.woff2") format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: 'Archivo';
    src: url("../fonts/archivo-700-NpNxM9d.woff2") format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}

:root {
    /* Workshop palette */
    --bs-ink: #15171a;          /* tyre black / backdrop */
    --bs-ink-2: #0e0f11;        /* deepest */
    --bs-steel: #21252b;        /* raised panel */
    --bs-steel-2: #2b3037;
    --bs-hi-vis: #00de91;       /* signature accent */
    --bs-hi-vis-press: #00bd7b;
    --bs-paper: #fcfbf9;        /* card */
    --table-scroll-cover: #fff; /* solid edge-mask for the wide-table scroll shadow; must match the panel bg behind the table */
    --bs-line: #c9ced6;         /* hairline */
    --bs-muted: #6b7280;
    --bs-text: #1d2126;
    --due-amber: #9a6700;       /* deadline urgency: 2-3 days out */
    --due-red: #b3261e;         /* deadline urgency: 1 day / due today / overdue */

    --bs-font-display: 'Bebas Neue', 'Arial Narrow', system-ui, sans-serif;
    --bs-font-ui: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
    --bs-font-mono: ui-monospace, 'SFMono-Regular', 'Cascadia Code', 'JetBrains Mono', monospace;

    --bs-body-font-family: var(--bs-font-ui);
}

body {
    font-family: var(--bs-font-ui);
    color: var(--bs-text);
}

/* A reusable workshop micro-label: monospace, uppercase, tracked — the WIP/reg-number voice. */
.eyebrow {
    font-family: var(--bs-font-mono);
    text-transform: uppercase;
    letter-spacing: 0.18em;
    font-size: 0.72rem;
    color: var(--bs-muted);
}

/* ---- Authenticated app shell ---- */
.shell { display: flex; min-height: 100vh; }
.shell__main { flex: 1; min-width: 0; }

.sidebar {
    width: 248px;
    flex-shrink: 0;
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100vh;
    background: var(--bs-ink);
    color: #eef1f5;
    border-inline-end: 3px solid var(--bs-hi-vis);
    display: flex;
    flex-direction: column;
}

.sidebar__brand {
    font-family: var(--bs-font-display);
    font-size: 1.7rem;
    line-height: 1;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #fff;
    text-decoration: none;
    padding: 1.15rem 1.35rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.sidebar__logo { display: block; height: 48px; width: auto; }
.appbar__logo { display: block; height: 30px; width: auto; }
@media (max-width: 860px) { .sidebar__logo { height: 40px; } }

/* Site scope switcher (group managers only): a compact disclosure below the brand. Native <details>
   so it works without JS; the summary shows the current scope, the menu lists sites + "All sites". */
.site-switch { border-bottom: 1px solid rgba(255, 255, 255, 0.08); }
.site-switch__current {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0.7rem 1.35rem;
    cursor: pointer;
    list-style: none;
    color: #eef1f5;
}
.site-switch__current::-webkit-details-marker { display: none; }
.site-switch__current::after {
    content: "";
    position: absolute;
    inset-inline-end: 1.2rem;
    width: 0.5rem;
    height: 0.5rem;
    margin-top: 0.55rem;
    border-inline-end: 2px solid #aeb6c2;
    border-bottom: 2px solid #aeb6c2;
    transform: rotate(45deg);
}
.site-switch { position: relative; }
.site-switch[open] .site-switch__current::after { transform: rotate(-135deg); margin-top: 0.75rem; }
.site-switch__eyebrow {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: #8b93a1;
}
.site-switch__value { font-weight: 600; font-size: 0.95rem; }
.site-switch__menu { padding: 0.25rem 0 0.55rem; }
.site-switch__menu form { margin: 0; }
.site-switch__opt {
    display: block;
    width: 100%;
    padding: 0.45rem 1.35rem;
    font: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    text-align: start;
    color: #aeb6c2;
    background: none;
    border: none;
    border-inline-start: 3px solid transparent;
    cursor: pointer;
}
.site-switch__opt:hover { color: #fff; background: rgba(255, 255, 255, 0.04); }
.site-switch__opt.is-active { color: #fff; border-inline-start-color: var(--bs-hi-vis); background: rgba(0, 222, 145, 0.10); }

.sidebar__nav { flex: 1; overflow-y: auto; padding: 0.5rem 0; }
.sidebar__group { padding: 0.35rem 0; }
.sidebar__group + .sidebar__group { border-top: 1px solid rgba(255, 255, 255, 0.05); }
/* Nav rows — plain links (Dashboard, Reports, Help) and collapsible group headings
   (buttons) share ONE look; the chevron is the only differentiator on expandable groups. */
.sidebar__nav a,
.sidebar__nav button.sidebar__label {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.5rem 1.35rem;
    font-family: inherit;
    font-size: 0.92rem;
    font-weight: 600;
    color: #aeb6c2;
    text-decoration: none;
    text-align: start;
    background: none;
    border: none;
    border-inline-start: 3px solid transparent;
    cursor: pointer;
}
.sidebar__nav a:hover,
.sidebar__nav button.sidebar__label:hover { color: #fff; background: rgba(255, 255, 255, 0.04); }
.sidebar__nav a.is-active { color: #fff; border-inline-start-color: var(--bs-hi-vis); background: rgba(0, 222, 145, 0.10); }
.sidebar__nav button.sidebar__label:focus-visible { outline: 2px solid var(--bs-hi-vis); outline-offset: -2px; }

/* Expanded child items get a leading dot to distinguish them from top-level rows. */
.sidebar__submenu a::before {
    content: "";
    flex-shrink: 0;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.55;
}

/* Chevron: the only differentiator on an expandable heading. Points right, rotates down when open. */
.sidebar__chevron {
    width: 0;
    height: 0;
    flex-shrink: 0;
    margin-inline-start: auto;
    border-top: 3.5px solid transparent;
    border-bottom: 3.5px solid transparent;
    border-inline-start: 4px solid currentColor;
    transition: transform 0.18s ease;
}
.sidebar__group.is-open .sidebar__chevron { transform: rotate(90deg); }

/* Collapse only applies once the controller marks the nav JS-enhanced, so no-JS renders open. */
.sidebar-nav--js .sidebar__submenu {
    overflow: hidden;
    max-height: 0;
    transition: max-height 0.22s ease;
}
.sidebar-nav--js .sidebar__group.is-open .sidebar__submenu { max-height: 40rem; }

/* The current section's heading text goes hi-vis: the group of the active page, or a dropdown you
   click open — but NOT one merely restored open from memory on a group-less page (e.g. Dashboard). */
.sidebar__group.is-current > button.sidebar__label { color: var(--bs-hi-vis); }

.sidebar__foot {
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    padding: 0.9rem 1.35rem;
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
}
.sidebar__bell {
    display: inline-flex; align-items: center; gap: 0.4rem;
    font-size: 0.8rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;
    color: #aeb6c2; text-decoration: none;
}
.sidebar__bell:hover, .sidebar__bell.is-active { color: #fff; }
.sidebar__badge {
    background: var(--bs-hi-vis); color: var(--bs-ink-2);
    font-family: var(--bs-font-mono); font-size: 0.66rem; font-weight: 700;
    border-radius: 999px; padding: 0.05rem 0.4rem; line-height: 1.4;
}
.sidebar__email { font-family: var(--bs-font-mono); font-size: 0.72rem; letter-spacing: 0.05em; color: #7e879a; word-break: break-all; }
.sidebar__signout {
    align-self: flex-start;
    font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--bs-hi-vis); text-decoration: none;
    border: 1.5px solid rgba(0, 222, 145, 0.45); border-radius: 8px; padding: 0.3rem 0.65rem;
}
.sidebar__signout:hover { background: rgba(0, 222, 145, 0.12); }

@media (max-width: 860px) {
    .shell { flex-direction: column; }
    .sidebar {
        width: auto; height: auto; position: static;
        flex-direction: row; align-items: center; flex-wrap: wrap;
        border-inline-end: none; border-bottom: 3px solid var(--bs-hi-vis);
        padding: 0 0.5rem;
    }
    .sidebar__brand { border-bottom: none; padding: 0.8rem 1rem; }
    .sidebar__nav { display: flex; flex: 1 1 100%; order: 3; overflow-x: auto; padding: 0; }
    .sidebar__group { display: flex; align-items: center; padding: 0; }
    .sidebar__group + .sidebar__group { border-top: none; }
    .sidebar__label, button.sidebar__label { display: none; }
    /* Submenu wrapper collapses structurally so its links flow inline like before. */
    .sidebar__submenu { display: contents; }
    .sidebar-nav--js .sidebar__submenu { max-height: none; overflow: visible; }
    .sidebar__submenu a::before { display: none; }
    .sidebar__nav a { width: auto; border-inline-start: none; border-bottom: 2px solid transparent; padding: 0.6rem 0.7rem; white-space: nowrap; }
    .sidebar__nav a.is-active { border-inline-start: none; background: transparent; border-bottom-color: var(--bs-hi-vis); }
    .sidebar__foot { border-top: none; flex-direction: row; align-items: center; gap: 0.7rem; margin-inline-start: auto; padding: 0.5rem 0.75rem; }
    .sidebar__email { display: none; }
    .theme-toggle { flex-direction: row; align-items: center; gap: 0.4rem; }
    .theme-toggle__label { display: none; }
}

/* Notifications list */
.notif-list { list-style: none; margin: 0; padding: 0; }
.notif { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.85rem 1rem; border-bottom: 1px solid #eef0f3; }
.notif:last-child { border-bottom: none; }
.notif--unread { background: #fffaf0; }
.notif__main { display: flex; align-items: center; gap: 0.7rem; }
.notif__when { font-family: var(--bs-font-mono); font-size: 0.66rem; letter-spacing: 0.06em; color: var(--bs-muted); white-space: nowrap; }

.app__main {
    max-width: 1200px;
    margin: 0 auto;
    padding: 2.25rem 2rem;
}

.page-title {
    font-weight: 700;
    font-size: 1.7rem;
    letter-spacing: -0.01em;
    margin: 0.25rem 0 1.25rem;
}

/* App surface (auth/marketing pages cover this with their own backgrounds) */
body { background: #f5f6f8; }

/* Toolbar: title on the left, actions on the right */
.toolbar { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; flex-wrap: wrap; }
.toolbar .page-title { margin: 0.25rem 0 0; }

/* Buttons */
.btn {
    display: inline-block;
    font-family: var(--bs-font-ui);
    font-weight: 600;
    font-size: 0.9rem;
    text-decoration: none;
    border: 1.5px solid transparent;
    border-radius: 9px;
    padding: 0.55rem 0.9rem;
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease, transform 0.04s ease;
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--bs-hi-vis); color: var(--bs-ink-2); }
.btn--primary:hover { background: var(--bs-hi-vis-press); }
/* Secondary main action (brand blue, white text): a real action that sits alongside the primary
   button, distinct from white ghost buttons used for Cancel / navigation. */
.btn--secondary { background: #02b3fe; border-color: #02b3fe; color: #fff; }
.btn--secondary:hover { background: #0299d6; border-color: #0299d6; }
.btn--ghost { background: #fff; border-color: var(--bs-line); color: var(--bs-text); }
.btn--ghost:hover { border-color: #9aa2b0; }
/* CRM claim action (exact brand cyan #00b3ff): the "New Claim" trigger and "Save & Proceed To
   Estimate". Distinct from .btn--secondary (#02b3fe) — the ticket specifies this precise hex. */
.btn--claim { background: #00b3ff; border-color: #00b3ff; color: #fff; }
.btn--claim:hover { background: #0098d6; border-color: #0098d6; }
.btn--claim:focus-visible { outline: 3px solid rgba(0,179,255,0.4); outline-offset: 2px; }
/* Import Estimate (exact #0211FF): a deep blue for the API/AI-PDF import entry point (currently a stub). */
.btn--import { background: #0211FF; border-color: #0211FF; color: #fff; }
.btn--import:hover { background: #020ecc; border-color: #020ecc; }
.btn--import:focus-visible { outline: 3px solid rgba(2,17,255,0.4); outline-offset: 2px; }
.btn--danger { background: #fff; border-color: #f0b4b4; color: #b3261e; }
.btn--danger:hover { background: #fdecec; }
.btn--sm { padding: 0.4rem 0.65rem; font-size: 0.82rem; }

/* Native <dialog> modal (see modal_controller.js). Used for the on-card New Claim form. */
.modal { border: none; border-radius: 14px; padding: 0; max-width: 720px; width: calc(100% - 2rem); box-shadow: 0 20px 50px rgba(16,24,40,0.25); background: #fff; color: var(--bs-text); }
.modal::backdrop { background: rgba(16,24,40,0.45); }
.modal__panel { padding: 1.25rem 1.4rem 1.4rem; }
.modal__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; }
.modal__close { background: none; border: none; font-size: 1.6rem; line-height: 1; cursor: pointer; color: var(--bs-text-secondary, #667085); padding: 0 0.25rem; }
.modal__close:hover { color: var(--bs-text); }

/* Panel / card */
.panel { background: #fff; border: 1px solid var(--bs-line); border-radius: 14px; box-shadow: 0 1px 2px rgba(16,24,40,0.04); }

/* Data table */
/* Horizontal-scroll container for wide tables: a data-dense table stays usable on a phone by
   scrolling sideways inside its panel instead of widening the whole page. The inset shadows hint
   that there's more table to the side; they fade as you reach each edge. */
.table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    background:
        linear-gradient(to right, var(--table-scroll-cover) 30%, transparent) left center / 28px 100% no-repeat,
        linear-gradient(to left, var(--table-scroll-cover) 30%, transparent) right center / 28px 100% no-repeat,
        radial-gradient(farthest-side at 0 50%, rgba(16,24,40,0.10), rgba(0,0,0,0)) left center / 12px 100% no-repeat,
        radial-gradient(farthest-side at 100% 50%, rgba(16,24,40,0.10), rgba(0,0,0,0)) right center / 12px 100% no-repeat;
    background-attachment: local, local, scroll, scroll;
}
/* Only force the table to its natural (unwrapped) width — and thus sideways scrolling — on
   tablet-and-smaller. Above this, the table returns to width:100% and shows every column in the
   panel with no scroll. (860px is the app's primary breakpoint — see the sidebar/two-col rules.) */
@media (max-width: 860px) {
    .table-scroll .data-table { min-width: max-content; }
}

.data-table { width: 100%; border-collapse: collapse; }
.data-table thead th {
    text-align: start;
    font-family: var(--bs-font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bs-muted);
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--bs-line);
}
.data-table tbody td { padding: 0.85rem 1rem; border-bottom: 1px solid #eef0f3; vertical-align: middle; }
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: #fafbfc; }
.data-table__reg { font-family: var(--bs-font-mono); font-weight: 600; letter-spacing: 0.03em; }
/* Keep the actions cell a real table-cell (not display:flex, which detaches it from the row and
   staggers the row divider) and lay its buttons out in a right-aligned inline row instead. */
.data-table__actions { text-align: end; white-space: nowrap; }
.data-table__actions > * { display: inline-flex; vertical-align: middle; }
.data-table__actions > * + * { margin-inline-start: 0.4rem; }
/* Inline table-cell inputs (e.g. a part's editable expected-delivery date): match the app's
   text-field styling at a size that fits a table row. */
.inline-form input[type="date"],
.inline-form input[type="text"],
.inline-form select {
    font-family: var(--bs-font-ui);
    font-size: 0.9rem;
    padding: 0.4rem 0.55rem;
    border: 1.5px solid var(--bs-line);
    border-radius: 8px;
    background: #fff;
    color: var(--bs-text);
}
.inline-form input:focus,
.inline-form select:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 3px rgba(0, 222, 145, 0.18);
}

/* Empty state */
.empty-state { padding: 3rem 1.5rem; text-align: center; color: var(--bs-muted); }

/* Board tiles (live work situation) */
.board-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.board-tile {
    display: block;
    text-decoration: none;
    color: inherit;
    background: #fff;
    border: 1px solid var(--bs-line);
    border-radius: 14px;
    padding: 1.25rem 1.3rem;
    transition: border-color 0.12s ease, transform 0.04s ease, box-shadow 0.12s ease;
}
.board-tile:hover { border-color: var(--bs-hi-vis); box-shadow: 0 6px 18px -10px rgba(16,24,40,0.2); }
.board-tile__count { font-family: var(--bs-font-display); font-size: 2.6rem; line-height: 1; color: var(--bs-ink); }
.board-tile__count--zero { color: #c2c8d0; }
.board-tile__label { font-weight: 600; margin-top: 0.35rem; }
.board-tile__hint { font-family: var(--bs-font-mono); font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--bs-muted); margin-top: 0.5rem; }
/* Compact per-status pipeline tiles. Red-RAG statuses (e.g. Awaiting Parts) flag in red. */
.board-tile--status { padding: 0.85rem 1rem; }
.board-tile--status .board-tile__count { font-size: 1.9rem; }
.board-tile--status .board-tile__label { font-size: 0.9rem; margin-top: 0.2rem; }
.board-tile--red .board-tile__count,
.board-tile--red .board-tile__label { color: #b3261e; }
@media (max-width: 860px) { .board-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .board-grid { grid-template-columns: 1fr; } }

/* ---- Board card view: compact per-vehicle cards (RSPH-3) ---- */
.view-toggle { display: inline-flex; gap: 0.35rem; }
.vehicle-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
    gap: 0.55rem;
}
.vehicle-card {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    background: #fff;
    border: 1px solid var(--bs-line);
    border-radius: 12px;
    overflow: hidden;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.vehicle-card:hover { border-color: var(--bs-hi-vis); box-shadow: 0 6px 18px -10px rgba(16,24,40,0.2); }
/* A Total Loss job reads as 'dead' — greyed and faded so it recedes from the live board. The whole
   card (image included) fades; hover/focus lifts it back so it stays readable and openable. */
.vehicle-card--dead { opacity: 0.4; filter: grayscale(1); }
.vehicle-card--dead:hover,
.vehicle-card--dead:focus-visible { opacity: 0.82; filter: grayscale(0.35); }
/* Same 'dead' treatment for the jobs table: the Total Loss row's text/badges/emblem dim and
   desaturate. Actions column keeps its Open button usable (only the content cells fade). */
.data-table tbody tr.is-total-loss td { opacity: 0.45; }
.data-table tbody tr.is-total-loss td.data-table__actions { opacity: 1; }
.data-table tbody tr.is-total-loss .badge-flag,
.data-table tbody tr.is-total-loss .make-emblem { filter: grayscale(1); }
/* Deadline urgency (mirrors the Workshop TV board) on the Live Job Status page. Cards view: the card
   border recolours amber 2-3 days from the requested completion date, red at 1 day / due today /
   overdue with a slow pulse. The double class + inset ring reads as a 2px border without a layout
   shift and holds over the hover border colour. */
.vehicle-card.vehicle-card--due-amber { border-color: var(--due-amber); box-shadow: inset 0 0 0 1px var(--due-amber); }
.vehicle-card.vehicle-card--due-red {
    border-color: var(--due-red);
    box-shadow: inset 0 0 0 1px var(--due-red);
    animation: cardDuePulse 1.3s ease-in-out infinite;
}
@keyframes cardDuePulse {
    0%, 100% { border-color: var(--due-red); box-shadow: inset 0 0 0 1px var(--due-red); }
    50% { border-color: var(--bs-line); box-shadow: inset 0 0 0 1px transparent; }
}
/* Table view: the WIP number is the affected field — same amber/red, red pulsing between the alarm
   colour and the normal text colour so it stays legible in either theme. */
.wip--due-amber { color: var(--due-amber); font-weight: 700; }
.wip--due-red {
    color: var(--due-red);
    font-weight: 700;
    animation: wipDuePulse 1.3s ease-in-out infinite;
}
@keyframes wipDuePulse {
    0%, 100% { color: var(--due-red); }
    50% { color: var(--bs-text); }
}
@media (prefers-reduced-motion: reduce) {
    .vehicle-card--due-red, .wip--due-red { animation: none; }
}
.vehicle-card__photo {
    position: relative;
    flex: 0 0 auto;
    aspect-ratio: 11 / 5;
    overflow: hidden;
    background: #f4f6f8;
    display: flex;
    align-items: center;
    justify-content: center;
}
.vehicle-card__photo img { width: 100%; height: 100%; object-fit: contain; max-width: 100%; }
/* Dark-mode brand emblems: a make with a published dark variant carries the URL inline as
   --emblem-dark; in dark theme we swap the <img>'s rendered image to it (white/light logo for the
   dark surface). Makes without a variant never get the .themed-emblem class, so they keep the
   standard logo. One element, no layout change, alt text preserved. */
[data-bs-theme="dark"] .themed-emblem { content: var(--emblem-dark); }
/* A real stock photo fills the wide slot (cover); brand emblems stay contained. The photo is taken
   out of flow so its intrinsic height can't stretch the slot past the 11/5 aspect ratio. */
.vehicle-card__photo--cover { background: #0d0f12; }
.vehicle-card__photo--cover img { position: absolute; inset: 0; object-fit: cover; }
.vehicle-card__photo--empty { background: linear-gradient(135deg, #eef1f4, #e2e7ec); }
.vehicle-card__initial { font-family: var(--bs-font-display); font-size: 1.5rem; color: #9aa4b0; }
.vehicle-card__body { padding: 0.4rem 0.5rem 0.5rem; display: flex; flex-direction: column; gap: 0.05rem; }
.vehicle-card__reg { font-family: var(--bs-font-mono); font-weight: 700; letter-spacing: 0.03em; font-size: 0.82rem; color: var(--bs-ink); }
.vehicle-card__wip { font-size: 0.68rem; color: var(--bs-muted); }
.vehicle-card__model { font-size: 0.76rem; font-weight: 600; }
.vehicle-card__loc { font-size: 0.66rem; color: var(--bs-muted); }
/* RSPH-3: a card can carry more than one badge (current status + Awaiting Parts progress). */
.vehicle-card__badges { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-top: 0.3rem; }
.vehicle-card__badges .badge-flag { align-self: flex-start; font-size: 0.62rem; padding: 0.12rem 0.4rem; }
@media (max-width: 480px) { .vehicle-card-grid { grid-template-columns: 1fr 1fr; } }

/* RSPH-3: view switcher — the active view's button reads as pressed (filled). */
.view-toggle .btn[aria-pressed="true"] {
    background: var(--bs-ink);
    color: #fff;
    border-color: var(--bs-ink);
}

/* ---- RSPH-3 Live Job Status board: card grid + sections rail + drag-drop ---- */
/* The board is width-hungry (grid + rail), so this page gets more room than the default column. */
.app__main--board { max-width: 1600px; }
.board { display: flex; gap: 1.25rem; align-items: flex-start; }
.board__main { flex: 1; min-width: 0; }

/* Status filter pills (card view) — the quick section filter above the grid. Sticks to the top on
   scroll (like the sections rail) so the filters are always in reach; the opaque background occludes
   cards passing underneath. */
.board-pills {
    display: flex; flex-wrap: wrap; gap: 0.4rem;
    position: sticky; top: 0; z-index: 5;
    margin: 0 0 0.85rem; padding: 0.5rem 0;
    background: #f5f6f8;
    box-shadow: 0 1px 0 var(--bs-line);
}
.pill {
    font: inherit; font-size: 0.78rem; font-weight: 600; cursor: pointer;
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.35rem 0.7rem; border-radius: 999px;
    border: 1px solid var(--bs-line); background: #fff; color: var(--bs-text);
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.pill:hover { border-color: #9aa4b0; }
.pill[aria-pressed="true"] { background: var(--bs-ink); border-color: var(--bs-ink); color: #fff; }
.pill__n { font-family: var(--bs-font-mono); font-size: 0.7rem; color: var(--bs-muted); }
.pill[aria-pressed="true"] .pill__n { color: rgba(255,255,255,0.7); }
.pill__dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: #9aa4b0; }
.pill__dot--green { background: #1a7f3c; }
.pill__dot--amber { background: #c98a00; }
.pill__dot--red { background: #b3261e; }
.pill__dot--neutral { background: #9aa4b0; }

.vehicle-card__tech {
    margin-top: 0.3rem;
    padding-top: 0.3rem;
    border-top: 1px dashed var(--bs-line);
    font-size: 0.68rem;
    color: var(--bs-text);
}
.vehicle-card__tech.is-awaiting { color: #9a6700; font-weight: 600; }

.vehicle-card[draggable="true"] { cursor: grab; }
.vehicle-card.is-dragging { opacity: 0.4; cursor: grabbing; }

/* ── Technician Status tiles (RSPH-66) ──────────────────────────────────────────────
   The shop-floor version of the vehicle card: a technician ID badge with a portrait, a name, and a
   state-coloured "status light". Each state maps to one accent colour, carried by the tile's top bar
   and the status pill's dot; the on-job light pulses to signal a running clock. */
.tech-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 0.55rem;
}
.tech-card {
    --tech-accent: #9aa4b0;
    position: relative;
    display: flex;
    flex-direction: column;
    background: #fff;
    border: 1px solid var(--bs-line);
    border-radius: 12px;
    overflow: hidden;
    /* The status light: a hairline accent across the top edge. */
    box-shadow: inset 0 3px 0 0 var(--tech-accent);
}
.tech-card--on_job  { --tech-accent: #1a7f3c; }
.tech-card--idle    { --tech-accent: #c98a00; }
.tech-card--holiday { --tech-accent: #2563eb; }
.tech-card--unpaid,
.tech-card--other   { --tech-accent: #6b7280; }
.tech-card--sick    { --tech-accent: #b3261e; }
.tech-card--off     { --tech-accent: #9aa4b0; }
/* Off the clock recedes, like a total-loss vehicle does on the jobs board — but stays readable. */
.tech-card--off { opacity: 0.72; }
.tech-card__photo {
    position: relative;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    background: #f4f6f8;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Headshots are portrait; anchor the cover-crop to the top so heads aren't cut off in the square tile. */
.tech-card__photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.tech-card__photo--empty { background: linear-gradient(135deg, #eef1f4, #e2e7ec); }
.tech-card__initial {
    font-family: var(--bs-font-display);
    font-size: 2rem;
    font-weight: 700;
    color: #9aa4b0;
}
.tech-card__body { padding: 0.45rem 0.55rem 0.55rem; display: flex; flex-direction: column; gap: 0.28rem; }
.tech-card__name {
    font-weight: 700;
    font-size: 0.82rem;
    line-height: 1.15;
    color: var(--bs-ink);
}
.tech-card__badges { display: flex; flex-wrap: wrap; gap: 0.25rem; }
.tech-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.32rem;
    font-size: 0.64rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    padding: 0.14rem 0.44rem;
    border-radius: 999px;
    color: var(--tech-accent);
    background: color-mix(in srgb, var(--tech-accent) 14%, transparent);
}
.tech-badge::before {
    content: "";
    width: 0.42rem;
    height: 0.42rem;
    border-radius: 50%;
    background: var(--tech-accent);
    flex: 0 0 auto;
}
/* The running-clock light: the on-job dot pulses, echoing "clock running". */
.tech-card--on_job .tech-badge::before { animation: techClockPulse 1.6s ease-in-out infinite; }
@keyframes techClockPulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--tech-accent) 60%, transparent); }
    50%      { opacity: 0.55; box-shadow: 0 0 0 3px transparent; }
}
@media (prefers-reduced-motion: reduce) {
    .tech-card--on_job .tech-badge::before { animation: none; }
}
.tech-card__job {
    font-family: var(--bs-font-mono);
    font-weight: 700;
    font-size: 0.72rem;
    letter-spacing: 0.03em;
    color: var(--bs-ink);
    text-decoration: none;
}
.tech-card__job:hover { color: var(--tech-accent); text-decoration: underline; }
.tech-card__since { font-size: 0.66rem; color: var(--bs-muted); }
.tech-card__actions { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.15rem; }
.tech-card__actions .btn { font-size: 0.66rem; padding: 0.16rem 0.45rem; }
/* "Put on a job" trigger + overlay modal. The trigger is the small ghost button on the tile; the
   overlay (a plain fixed div, not a native <dialog>) lists the technician's assigned work as
   selectable rows plus a search for any other active job. */
.tech-card__start { margin-top: 0.3rem; }
.tech-card__start > .btn { font-size: 0.66rem; padding: 0.16rem 0.45rem; }
.tech-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1000;
    align-items: flex-start;
    justify-content: center;
    padding: 6vh 1rem 1rem;
    background: rgba(16, 24, 40, 0.45);
    overflow-y: auto;
}
.tech-modal.is-open { display: flex; }
.tech-modal__panel .field { margin-bottom: 1rem; }
.tech-modal__panel .field label { display: block; margin-bottom: 0.35rem; font-weight: 600; }
.tech-modal__panel {
    width: 100%;
    max-width: 560px;
    background: #fff;
    color: var(--bs-text);
    border-radius: 14px;
    box-shadow: 0 20px 50px rgba(16, 24, 40, 0.25);
    padding: 1.25rem 1.4rem 1.4rem;
}
.tech-start__subhead { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--bs-muted); margin: 0 0 0.4rem; }
.tech-start__jobs { display: flex; flex-direction: column; gap: 0.35rem; max-height: 34vh; overflow: auto; }
.tech-start__job {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    text-align: left;
    padding: 0.5rem 0.65rem;
    background: #fff;
    border: 1.5px solid var(--bs-line);
    border-radius: 9px;
    cursor: pointer;
}
.tech-start__job:hover { border-color: #9aa2b0; }
.tech-start__job[aria-pressed="true"] { border-color: var(--bs-hi-vis); box-shadow: inset 0 0 0 1px var(--bs-hi-vis); }
.tech-start__wip { font-family: var(--bs-font-mono); font-weight: 700; letter-spacing: 0.02em; }
.tech-start__veh { font-size: 0.8rem; color: var(--bs-muted); }
.tech-start__or { font-size: 0.8rem; color: var(--bs-muted); margin: 0.8rem 0 0.4rem; }
/* Search results dropdown for the modal's job typeahead. */
.tech-start__job + .tech-start__job { margin-top: 0; }
.typeahead__option { display: block; width: 100%; text-align: left; padding: 0.4rem 0.6rem; background: none; border: none; cursor: pointer; font-size: 0.85rem; color: var(--bs-text); }
.typeahead__option:hover { background: #f1f3f5; }
@media (max-width: 480px) { .tech-card-grid { grid-template-columns: 1fr 1fr; } }

/* Technician photo field on the user edit form: a round preview beside the file input. */
.photo-field { display: flex; gap: 1rem; align-items: flex-start; margin-top: 0.5rem; }
.photo-field__preview {
    flex: 0 0 auto;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    overflow: hidden;
    border: 1px solid var(--bs-line);
    display: flex;
    align-items: center;
    justify-content: center;
    background: #f4f6f8;
}
.photo-field__preview img { width: 100%; height: 100%; object-fit: cover; }
.photo-field__preview--empty { background: linear-gradient(135deg, #eef1f4, #e2e7ec); }
.photo-field__preview span { font-family: var(--bs-font-display); font-size: 1.75rem; font-weight: 700; color: #9aa4b0; }
.photo-field__controls { flex: 1 1 auto; display: flex; flex-direction: column; gap: 0.5rem; }

/* Compact drag image: just the number plate, so it lines up with a section. */
.drag-chip {
    position: fixed; top: -200px; left: 0;
    font-family: var(--bs-font-mono); font-weight: 700; font-size: 1rem; letter-spacing: 0.08em;
    color: #fff; background: var(--bs-ink);
    padding: 0.5rem 0.85rem; border-radius: 8px;
    border: 2px solid var(--bs-hi-vis);
    box-shadow: 0 10px 24px rgba(0,0,0,0.4);
    white-space: nowrap; pointer-events: none;
}

.board-rail {
    width: 250px; flex: 0 0 250px;
    position: sticky; top: 1rem; align-self: flex-start;
    max-height: calc(100vh - 2rem); overflow: auto;
    background: var(--bs-ink); border-radius: 14px; padding: 0.9rem; color: #e9ecf1;
}
.board-rail__head { font-family: var(--bs-font-display); font-size: 1.25rem; letter-spacing: 0.04em; color: #fff; }
.board-rail__hint {
    font-family: var(--bs-font-mono); font-size: 0.62rem; letter-spacing: 0.06em; text-transform: uppercase;
    color: #7e879a; margin: 0.2rem 0 0.75rem;
}
.board-rail__item {
    width: 100%; font: inherit; text-align: left; cursor: pointer;
    display: flex; align-items: center; gap: 0.65rem;
    padding: 0.7rem 0.75rem; border-radius: 11px;
    border: 1.5px dashed rgba(255,255,255,0.16); background: var(--bs-steel); color: #e9ecf1;
    transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease, box-shadow 0.12s ease;
}
.board-rail__item + .board-rail__item { margin-top: 0.5rem; }
.board-rail__item:hover { background: #262b32; border-color: rgba(255,255,255,0.3); }
.board-rail__item.is-drop {
    border-color: var(--bs-hi-vis); background: rgba(0, 222, 145, 0.16);
    transform: translateY(-1px); box-shadow: 0 10px 22px -12px rgba(0,222,145,0.6), inset 0 0 0 1px rgba(0,222,145,0.3);
}
.board-rail__bar { width: 4px; align-self: stretch; border-radius: 3px; flex: 0 0 auto; background: #9aa4b0; }
.board-rail__bar--green { background: #1a7f3c; }
.board-rail__bar--amber { background: #c98a00; }
.board-rail__bar--red { background: #b3261e; }
.board-rail__bar--neutral { background: #9aa4b0; }
.board-rail__label { flex: 1; font-size: 0.84rem; font-weight: 600; }
.board-rail__n { font-family: var(--bs-font-mono); font-size: 0.82rem; font-weight: 700; }

/* Assignment modal */
.board-modal {
    position: fixed; inset: 0; z-index: 50; background: rgba(14,15,17,0.55);
    display: flex; align-items: center; justify-content: center; padding: 1rem;
}
.board-modal[hidden] { display: none; }
.board-modal__card {
    width: 100%; max-width: 420px; background: var(--bs-paper); color: var(--bs-text);
    border-radius: 16px; box-shadow: 0 30px 70px rgba(0,0,0,0.4); overflow: hidden;
}
.board-modal__head { padding: 1.1rem 1.25rem 0.9rem; border-bottom: 1px solid var(--bs-line); }
.board-modal__eyebrow {
    font-family: var(--bs-font-mono); font-size: 0.64rem; letter-spacing: 0.14em; text-transform: uppercase;
    color: var(--bs-muted); margin: 0 0 0.3rem;
}
.board-modal__title { font-family: var(--bs-font-display); font-size: 1.6rem; letter-spacing: 0.03em; margin: 0; }
.board-modal__sub { margin: 0.35rem 0 0; font-family: var(--bs-font-mono); font-weight: 700; }
.board-modal__list { list-style: none; margin: 0; padding: 0.6rem; max-height: 46vh; overflow: auto; }
.board-modal__tech {
    width: 100%; font: inherit; text-align: left; cursor: pointer;
    padding: 0.55rem 0.65rem; border-radius: 10px; border: 1px solid transparent; background: transparent;
}
.board-modal__tech:hover { background: #f1f3f5; }
.board-modal__tech.is-selected { background: rgba(0,222,145,0.1); border-color: rgba(0,222,145,0.45); font-weight: 600; }
.board-modal__actions { display: flex; align-items: center; gap: 0.6rem; padding: 0.85rem 1.25rem 1.1rem; border-top: 1px solid var(--bs-line); }
.board-modal__spacer { flex: 1; }

/* Move confirmation toast */
.board-toast {
    position: fixed; left: 50%; bottom: 1.5rem; transform: translateX(-50%); z-index: 60;
    background: var(--bs-ink); color: #fff; font-size: 0.85rem; font-weight: 600;
    padding: 0.7rem 1.1rem; border-radius: 10px; box-shadow: 0 14px 34px rgba(0,0,0,0.35);
}
.board-toast[hidden] { display: none; }

@media (max-width: 900px) {
    .board { flex-direction: column; }
    .board-rail { position: static; width: auto; flex: none; max-height: none; order: -1; }
}

/* Work-stream brand emblem (RSPH-50): a small coloured make logo inline before the vehicle in board
   and pipeline rows. Unknown makes fall back to a neutral initial chip — never a broken image. */
.make-emblem {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    margin-right: 0.45rem;
    vertical-align: middle;
    object-fit: contain;
    border-radius: 5px;
    flex: 0 0 auto;
}
.make-emblem--empty {
    background: linear-gradient(135deg, #eef1f4, #e2e7ec);
    color: #9aa4b0;
    font-family: var(--bs-font-display);
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1;
}
/* On the Live Job Status table the emblem stands alone in its own Make column rather than sitting
   inline beside text, so give it more room than the 22px inline badge. */
.job-cell-make .make-emblem {
    width: 40px;
    height: 40px;
    margin-right: 0;
    border-radius: 7px;
}

/* ---- Dashboard: LIVE WORK SITUATION ---- */
.kpi-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 0.85rem;
    margin-bottom: 1.1rem;
}
.kpi-stat {
    background: #fff;
    border: 1px solid var(--bs-line);
    border-radius: 14px;
    padding: 1.05rem 1.2rem;
}
.kpi-stat--hero { background: var(--bs-ink); border-color: var(--bs-ink); }
.kpi-stat--hero .kpi-stat__n { color: var(--bs-hi-vis); }
.kpi-stat--hero .kpi-stat__label { color: #aeb6c2; }
.kpi-stat__n {
    font-family: var(--bs-font-display);
    font-size: 2.9rem;
    line-height: 0.95;
    letter-spacing: 0.01em;
    color: var(--bs-ink);
}
.kpi-stat__n--green { color: #1a7f3c; }
.kpi-stat__n--amber { color: #e8a400; }
.kpi-stat__n--red { color: #b3261e; }
.kpi-stat__n--neutral { color: var(--bs-muted); }
.kpi-stat__n--value { font-size: 2.2rem; }
.kpi-stat__label {
    font-family: var(--bs-font-mono);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    font-size: 0.64rem;
    color: var(--bs-muted);
    margin-top: 0.4rem;
}

/* Revenue strip (page-load only; never broadcast) */
.kpi-revenue { display: flex; align-items: baseline; gap: 0.6rem; margin: 0 0 1.1rem; }
.kpi-revenue__n { font-family: var(--bs-font-display); font-size: 2.1rem; line-height: 1; color: var(--bs-ink); }
.kpi-revenue__l { font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.64rem; color: var(--bs-muted); }

/* Signature: the proportional status board (hazard-tape RAG split) */
.kpi-board {
    display: flex;
    height: 16px;
    border-radius: 999px;
    overflow: hidden;
    margin-bottom: 1.6rem;
    background: #eef0f3;
    box-shadow: inset 0 0 0 1px var(--bs-line);
}
.kpi-board__seg { height: 100%; }
.kpi-board__seg--green { background: #1a7f3c; }
.kpi-board__seg--amber { background: #ffb81c; }
.kpi-board__seg--red { background: #b3261e; }
.kpi-board__seg--neutral { background: #98a2b3; }
.kpi-board__seg--empty { background: #eef0f3; }

/* Board grid sits between the KPI headline and the team panels — give it room to read as its own band. */
.board-grid-section { margin: 1.4rem 0; }
.board-grid-section > .section-heading { margin-bottom: 0.75rem; }
/* Heading beside an inline control (e.g. the closing-soon window toggle) — wraps on narrow screens. */
.section-head-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.section-head-row > .section-heading { margin-bottom: 0; }

/* The remaining KPI panels, full width beneath the board grid: two compact team mixes and a wider
   leaders table. Collapses to two-up then one-up, with the table spanning full width once wrapped. */
.kpi-teams { display: grid; grid-template-columns: 1fr 1fr 1.4fr; gap: 1.1rem; align-items: start; margin-top: 1.1rem; }
.kpi-panel { padding: 1.25rem 1.4rem; }
.kpi-empty { color: var(--bs-muted); font-size: 0.9rem; margin: 0; }

.kpi-pipeline { list-style: none; margin: 0; padding: 0; }
.kpi-pipeline__row {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    padding: 0.6rem 0;
    border-bottom: 1px solid #eef0f3;
}
.kpi-pipeline__row:last-child { border-bottom: none; }
/* RAG indicator: colour only — the status label is carried on title/aria-label, not shown. */
.kpi-pipeline__rag { flex: 0 0 auto; width: 0.85rem; height: 0.85rem; border-radius: 50%; }
.kpi-pipeline__rag--green { background: #1a7f3c; }
.kpi-pipeline__rag--amber { background: #9a6700; }
.kpi-pipeline__rag--red { background: #b3261e; }
.kpi-pipeline__rag--neutral { background: #4b5563; }
.kpi-pipeline__label { flex: 1; font-weight: 600; }
.kpi-pipeline__count {
    font-family: var(--bs-font-display);
    font-size: 1.5rem;
    line-height: 1;
    color: var(--bs-ink);
    min-width: 1.5ch;
    text-align: end;
}

.kpi-mix { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.75rem; }
.kpi-mix__cell { text-align: center; border: 1px solid var(--bs-line); border-radius: 10px; padding: 0.75rem 0.5rem; }
.kpi-mix__n { font-family: var(--bs-font-display); font-size: 2rem; line-height: 1; color: var(--bs-ink); }
.kpi-mix__l { font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.6rem; color: var(--bs-muted); margin-top: 0.3rem; }

.kpi-leaders { margin-top: 0.25rem; }
.kpi-leaders thead th { padding: 0.5rem 0.6rem; }
.kpi-leaders tbody td { padding: 0.55rem 0.6rem; }

@media (max-width: 980px) {
    .kpi-teams { grid-template-columns: 1fr 1fr; }
    .kpi-panel--leaders { grid-column: 1 / -1; }
}
@media (max-width: 560px) { .kpi-teams { grid-template-columns: 1fr; } }

/* Status badges */
.badge-flag {
    display: inline-block;
    font-family: var(--bs-font-mono);
    font-size: 0.64rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0.2rem 0.45rem;
    border-radius: 6px;
    margin-inline-end: 0.3rem;
}
.badge-flag--stop { background: #fdecec; color: #b3261e; border: 1px solid #f3b4b4; }
.badge-flag--credit { background: #fff4e0; color: #9a6700; border: 1px solid #f3d9a8; }
.badge-flag--ok { background: #e9f6ee; color: #1a7f3c; border: 1px solid #b7e0c4; }
.badge-flag--pending { background: #fff4e0; color: #9a6700; border: 1px solid #f3d9a8; }
.badge-flag--authorised { background: #e9f6ee; color: #1a7f3c; border: 1px solid #b7e0c4; }
.badge-flag--declined { background: #fdecec; color: #b3261e; border: 1px solid #f3b4b4; }
/* RAG status colours */
.badge-flag--green { background: #e9f6ee; color: #1a7f3c; border: 1px solid #b7e0c4; }
.badge-flag--amber { background: #fff4e0; color: #9a6700; border: 1px solid #f3d9a8; }
.badge-flag--red { background: #fdecec; color: #b3261e; border: 1px solid #f3b4b4; }
.badge-flag--neutral { background: #eef0f3; color: #4b5563; border: 1px solid #d7dbe0; }

/* Status pill (larger, for headers) */
.status-pill {
    display: inline-block;
    font-weight: 700;
    font-size: 0.82rem;
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
}
.status-pill--green { background: #1a7f3c; color: #fff; }
.status-pill--amber { background: #ffb81c; color: var(--bs-ink-2); }
.status-pill--red { background: #b3261e; color: #fff; }
.status-pill--neutral { background: #4b5563; color: #fff; }

/* In the job header, the status pill and the due-date flag share one shape: the
   rounded-rectangle of the flag (6px), keeping each its own colour. */
.job-status-block .status-pill { border-radius: 6px; }

/* Detail header + grid */
.detail-head { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.4rem; }
.detail-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem 1.5rem; margin: 0; }
.detail-grid dt { font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.64rem; color: var(--bs-muted); }
.detail-grid dd { margin: 0.15rem 0 0; font-size: 0.98rem; }
.two-col { display: grid; grid-template-columns: 1.4fr 1fr; gap: 1.25rem; align-items: start; }
@media (max-width: 860px) { .two-col { grid-template-columns: 1fr; } .detail-grid { grid-template-columns: 1fr 1fr; } }

/* Estimate detail: the lines and their supplements share the main (left) column while the
   summary sits in a sidebar spanning both rows — so supplements sit directly under the lines
   instead of being pushed below the (often taller) summary. min-width:0 lets wide line tables
   scroll inside their column rather than stretching the grid track. */
.estimate-detail { display: grid; grid-template-columns: 1.4fr 1fr; gap: 1.25rem; align-items: start; }
.estimate-detail__lines { grid-column: 1; grid-row: 1; min-width: 0; }
.estimate-detail__supplements { grid-column: 1; grid-row: 2; min-width: 0; }
.estimate-detail__summary { grid-column: 2; grid-row: 1 / span 2; }
@media (max-width: 860px) {
    .estimate-detail { grid-template-columns: 1fr; }
    .estimate-detail__lines,
    .estimate-detail__supplements,
    .estimate-detail__summary { grid-column: 1; grid-row: auto; }
}

/* Send-for-approval split button: a primary action plus a caret that reveals delivery channels
   (email insurer/customer, download PDF) via a native <details> menu — no JS, CSRF kept per form.
   The two halves must read as one control: align-items:stretch + flex wrappers make the caret take
   the main button's exact height, and hovering either half lights up both. */
.send-split { position: relative; display: inline-flex; align-items: stretch; }
.send-split > form { display: flex; }
.send-split__more { display: flex; }
.send-split__main { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.send-split__caret {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0 0.6rem; font-size: 0.7rem; line-height: 1;
    border-top-left-radius: 0; border-bottom-left-radius: 0;
    border-left: 1.5px solid rgba(0,0,0,0.14);
    list-style: none; cursor: pointer;
}
.send-split__caret::-webkit-details-marker { display: none; }
.send-split:hover .send-split__main,
.send-split:hover .send-split__caret,
.send-split__more[open] .send-split__caret { background: var(--bs-hi-vis-press); }
.send-split__panel {
    position: absolute; top: calc(100% + 6px); right: 0; z-index: 20;
    min-width: 190px; padding: 0.35rem;
    background: #fff; border: 1px solid var(--bs-line); border-radius: 10px;
    box-shadow: 0 8px 24px rgba(16,24,40,0.14);
}
.send-split__panel form { margin: 0; }
.send-split__item {
    display: block; width: 100%; text-align: left;
    padding: 0.5rem 0.65rem; border: none; border-radius: 7px;
    background: transparent; color: var(--bs-text); font: inherit; cursor: pointer;
    text-decoration: none;
}
.send-split__item:hover { background: var(--bs-surface-2, #f3f5f8); }

/* Estimate rate setters (agreed labour rate, paint & materials rate) in the summary panel: a
   labelled field with a Save button. The label sits on its own row so the input can grow and the
   button never wraps onto a second line. */
.rate-form { display: grid; grid-template-columns: 1fr auto; gap: 0.4rem 0.6rem; align-items: center; margin-bottom: 1rem; }
.rate-form label { grid-column: 1 / -1; font-size: 0.85rem; font-weight: 600; color: var(--bs-text); }
.rate-form input {
    width: 100%;
    box-sizing: border-box;
    font-family: var(--bs-font-ui);
    font-size: 0.9rem;
    padding: 0.45rem 0.6rem;
    border: 1.5px solid var(--bs-line);
    border-radius: 8px;
    background: #fff;
    color: var(--bs-text);
}
.rate-form input:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 3px rgba(0, 222, 145, 0.18);
}
.rate-form .btn { white-space: nowrap; }

/* Paint & materials per-hour / fixed mode toggle (estimate summary). Native inline radios on one
   row; the active input group (label + field) spans full width. .hidden state must still win. */
.rate-form__label { grid-column: 1 / -1; font-size: 0.85rem; font-weight: 600; color: var(--bs-text); }
.rate-form .pm-modes { grid-column: 1 / -1; display: flex; gap: 1.1rem; }
.rate-form .radio-inline { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.85rem; font-weight: 500; color: var(--bs-text); cursor: pointer; }
.rate-form .radio-inline input[type="radio"] { width: auto; margin: 0; padding: 0; border: 0; background: none; box-shadow: none; accent-color: var(--bs-hi-vis); }
.rate-form [data-paint-materials-mode-target="perhour"],
.rate-form [data-paint-materials-mode-target="fixed"] { grid-column: 1 / -1; display: grid; gap: 0.35rem; }
.rate-form [data-paint-materials-mode-target][hidden] { display: none; }

/* Status-change form (inline) */
.status-form { display: flex; flex-direction: column; gap: 0.6rem; }
.status-form select, .status-form input, .status-form textarea {
    width: 100%; font-family: var(--bs-font-ui); font-size: 0.92rem; padding: 0.55rem 0.7rem;
    border: 1.5px solid var(--bs-line); border-radius: 9px; background: #fff;
}

/* RSPH-55: co-located clocking controls — trade, technician and status sit side by side,
   wrapping on narrow screens, with the action buttons on their own row below. */
.clock-panel { flex-direction: row; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem; }
.clock-panel__field { display: flex; flex-direction: column; gap: 0.3rem; flex: 1 1 9rem; min-width: 0; margin: 0; }
.clock-panel__label { font-size: 0.72rem; font-weight: 600; color: var(--bs-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.clock-panel__actions { display: flex; flex-wrap: wrap; gap: 0.5rem; flex: 1 1 100%; }

/* Timeline */
.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { position: relative; padding: 0 0 1.1rem; padding-inline-start: 1.4rem; border-inline-start: 2px solid var(--bs-line); }
.timeline li:last-child { border-inline-start-color: transparent; padding-bottom: 0; }
.timeline li::before {
    content: ''; position: absolute; inset-inline-start: -6px; top: 3px; width: 10px; height: 10px;
    border-radius: 50%; background: var(--bs-hi-vis); box-shadow: 0 0 0 3px rgba(0,222,145,0.18);
}
.timeline__when { font-family: var(--bs-font-mono); font-size: 0.66rem; letter-spacing: 0.08em; color: var(--bs-muted); }
.timeline__what { font-size: 0.95rem; margin-top: 0.15rem; }
.timeline__note { color: var(--bs-muted); font-size: 0.88rem; }

/* Checkbox row */
.check-row { display: flex; align-items: center; gap: 0.5rem; }
.check-row input { width: auto; }
.check-row label { font-family: var(--bs-font-ui); text-transform: none; letter-spacing: 0; font-size: 0.92rem; color: var(--bs-text); }
label.check-row { font-family: var(--bs-font-ui); text-transform: none; letter-spacing: 0; font-size: 0.92rem; color: var(--bs-text); cursor: pointer; padding: 0.2rem 0; }

/* Access-group form */
.section-heading { font-size: 1rem; font-weight: 700; margin: 0 0 0.75rem; color: var(--bs-text); }
.section-intro { margin: 0; color: var(--bs-muted); font-size: 0.9rem; }
.toolbar--section { margin-top: 2rem; }
.data-table__num { text-align: end; font-variant-numeric: tabular-nums; }
.status-link { text-decoration: none; }

/* Client-side table search + sort (table_controller.js) */
.table-tools {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}
.table-tools__search {
    width: min(420px, 100%);
    font-family: var(--bs-font-ui);
    font-size: 0.92rem;
    color: var(--bs-text);
    padding: 0.6rem 0.9rem 0.6rem 2.4rem;
    border: 1.5px solid var(--bs-line);
    border-radius: 10px;
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%239aa1ab' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='5'/%3E%3Cline x1='10.5' y1='10.5' x2='15' y2='15'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 0.8rem center;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.table-tools__search::placeholder { color: #aab0bb; }
.table-tools__search:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 4px rgba(0, 222, 145, 0.18);
}
/* Search box + any column facet dropdowns share one left-aligned row; the count sits opposite. */
.table-tools__controls {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}
.table-tools__filter {
    font-family: var(--bs-font-ui);
    font-size: 0.9rem;
    color: var(--bs-text);
    padding: 0.55rem 2.1rem 0.55rem 0.85rem;
    border: 1.5px solid var(--bs-line);
    border-radius: 10px;
    background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%239aa1ab' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='2,4 6,8 10,4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    appearance: none;
    cursor: pointer;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.table-tools__filter:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 4px rgba(0, 222, 145, 0.18);
}
.table-tools__count {
    font-family: var(--bs-font-mono);
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--bs-muted);
    white-space: nowrap;
}
.data-table th.is-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.data-table th.is-sortable::after { content: '↕'; opacity: 0.35; margin-inline-start: 0.4em; font-size: 0.85em; }
.data-table th.is-sorted-asc::after { content: '↑'; opacity: 0.9; }
.data-table th.is-sorted-desc::after { content: '↓'; opacity: 0.9; }
.perm-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1.75rem; }
.perm-area { border: 1px solid var(--bs-line); border-radius: 10px; padding: 0.75rem 0.9rem; margin: 0; min-width: 0; }
.perm-area legend {
    font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em;
    font-size: 0.66rem; color: var(--bs-muted); padding: 0 0.35rem;
}
.member-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.4rem 1rem; margin-bottom: 0.5rem; }

@media (max-width: 720px) { .perm-grid { grid-template-columns: 1fr 1fr; } .member-grid { grid-template-columns: 1fr; } }
@media (max-width: 480px) { .perm-grid { grid-template-columns: 1fr; } }

/* Forms */
.form-card { max-width: 720px; padding: 1.75rem; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.form-grid .field--full { grid-column: 1 / -1; }
.form-grid label { font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.68rem; color: var(--bs-muted); }
.form-grid input, .form-grid textarea, .form-grid select,
.tech-modal__panel input, .tech-modal__panel textarea, .tech-modal__panel select {
    width: 100%;
    font-family: var(--bs-font-ui);
    font-size: 0.95rem;
    padding: 0.6rem 0.7rem;
    border: 1.5px solid var(--bs-line);
    border-radius: 9px;
    background: #fff;
    color: var(--bs-text);
}
.form-grid input:focus, .form-grid textarea:focus, .form-grid select:focus,
.tech-modal__panel input:focus, .tech-modal__panel textarea:focus, .tech-modal__panel select:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 4px rgba(0,222,145,0.18);
}
/* Checkboxes and radios are not text fields: undo the full-width / bordered text-input sizing above
   so they render at their native size and sit inline with their labels (see .checkbox-field and
   .radio-list__item, which lay out the row). */
.form-grid input[type="checkbox"], .form-grid input[type="radio"] {
    width: auto;
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}
/* Prefixed input: a prefix addon (e.g. a currency symbol) joined to the start of a text input.
   Named to avoid Bootstrap's own .input-group (which sets flex-wrap: wrap and would wrap the field). */
.prefixed-input { display: flex; flex-wrap: nowrap; align-items: stretch; }
.prefixed-input__prefix {
    display: inline-flex;
    align-items: center;
    padding: 0 0.7rem;
    font-family: var(--bs-font-ui);
    font-size: 0.95rem;
    color: var(--bs-muted);
    background: #f4f6f8;
    border: 1.5px solid var(--bs-line);
    border-right: 0;
    border-radius: 9px 0 0 9px;
    white-space: nowrap;
}
.form-grid .prefixed-input input { flex: 1 1 auto; min-width: 0; border-radius: 0 9px 9px 0; }
/* Reset native select chrome so dropdowns match the text inputs, then draw our own chevron. */
.form-grid select,
.tech-modal__panel select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 2.2rem;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 0.7rem;
}
.form-grid select:disabled {
    background-color: #f4f6f8;
    color: var(--bs-muted);
    cursor: not-allowed;
}

/* Address blocks (main / billing / delivery): the fieldset is a plain grid cell, and its
   "Same as main address" toggle is a left-aligned checkbox + label row — overriding both the
   uppercase field-label styling and the width:100% input rule that would otherwise stretch and
   centre the checkbox. */
.form-grid .address-block { border: 0; margin: 0; padding: 0; min-width: 0; }
.form-grid .checkbox-field {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--bs-font-ui);
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.92rem;
    color: var(--bs-text);
    cursor: pointer;
    margin-bottom: 0.9rem;
}
.form-grid .checkbox-field input[type="checkbox"] {
    width: auto;
    flex: 0 0 auto;
    margin: 0;
    padding: 0;
}

/* Select2 (searchable dropdowns) restyled to match the form inputs. */
.form-grid .select2-container { width: 100% !important; }
.select2-container--default .select2-selection--single {
    height: auto;
    min-height: calc(1.4em + 1.2rem + 3px);
    display: flex;
    align-items: center;
    padding: 0.1rem 2rem 0.1rem 0.7rem;
    border: 1.5px solid var(--bs-line);
    border-radius: 9px;
    background: #fff;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
    width: 100%;
    padding: 0;
    margin: 0;
    line-height: 1.4;
    color: var(--bs-text);
    font-family: var(--bs-font-ui);
    font-size: 0.95rem;
}
.select2-container--default .select2-selection--single .select2-selection__placeholder { color: #aab0bb; }
.select2-container--default .select2-selection--single .select2-selection__arrow {
    position: absolute;
    top: 0;
    right: 0.6rem;
    height: 100%;
    display: flex;
    align-items: center;
}
.select2-container--disabled .select2-selection--single { background-color: #f4f6f8; cursor: not-allowed; }
.select2-container--default.select2-container--focus .select2-selection--single,
.select2-container--default.select2-container--open .select2-selection--single {
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 4px rgba(0, 222, 145, 0.18);
}
.select2-dropdown {
    border: 1.5px solid var(--bs-line);
    border-radius: 9px;
    font-family: var(--bs-font-ui);
    font-size: 0.92rem;
}
.select2-search--dropdown .select2-search__field {
    border: 1.5px solid var(--bs-line);
    border-radius: 7px;
    padding: 0.45rem 0.6rem;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
    background: var(--bs-hi-vis);
    color: var(--bs-ink-2);
}
.select2-container--default .select2-results__option--selected { background: #eef0f3; }
.form-actions { display: flex; gap: 0.6rem; margin-top: 1.4rem; }
.form-error {
    margin: 0 0 1.1rem;
    padding: 0.7rem 0.9rem;
    border-radius: 9px;
    background: #fdecec;
    border: 1px solid #f3b4b4;
    color: #8f1d1d;
    font-size: 0.9rem;
}

.form-success {
    margin: 0 0 1.1rem;
    padding: 0.7rem 0.9rem;
    border-radius: 9px;
    background: #e8f8f1;
    border: 1px solid #9fe3c7;
    color: #0f6b48;
    font-size: 0.9rem;
}

@media (max-width: 620px) { .form-grid { grid-template-columns: 1fr; } }

/* DataTables (vehicles list) — align the generated search box, info and pagination with the
 * app theme on the white panel. DataTables 2.x emits dt-* class names. */
.dt-container { margin-top: 0.1rem; }
.dt-container .dt-layout-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap; }
.dt-container .dt-search { margin-bottom: 0.75rem; margin-inline-start: auto; }
.dt-container .dt-search label { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--bs-muted); font-size: 0.85rem; }
.dt-container .dt-search input {
    border: 1px solid var(--bs-line);
    border-radius: 8px;
    padding: 0.45rem 0.7rem;
    font: inherit;
    color: var(--bs-text);
}
.dt-container .dt-search input:focus {
    outline: none;
    border-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 3px rgba(0, 222, 145, 0.18);
}
.dt-container .dt-info { color: var(--bs-muted); font-size: 0.85rem; padding-top: 0.85rem; }
.dt-container .dt-paging { padding-top: 0.6rem; }
.dt-container .dt-paging .dt-paging-button {
    padding: 0.35rem 0.7rem;
    border-radius: 8px;
    border: 1px solid transparent;
    color: var(--bs-text);
}
.dt-container .dt-paging .dt-paging-button.current,
.dt-container .dt-paging .dt-paging-button.current:hover {
    background: var(--bs-hi-vis);
    border-color: var(--bs-hi-vis);
    color: var(--bs-ink-2);
}
.dt-container .dt-paging .dt-paging-button:hover:not(.current):not(.disabled) {
    background: #f2f4f7;
    border-color: var(--bs-line);
}
.dt-container .dt-paging .dt-paging-button.disabled { color: var(--bs-muted); opacity: 0.5; }

/* Real-time new-message toasts (bottom-right), Mercure-appended into #toasts. */
.toasts { position: fixed; inset-block-end: 1rem; inset-inline-end: 1rem; display: flex; flex-direction: column; gap: 0.5rem; z-index: 1080; max-width: 340px; }
.toast {
    display: flex; align-items: flex-start; gap: 0.5rem;
    background: #15171a; color: #fff; border-radius: 12px; padding: 0.7rem 0.85rem;
    box-shadow: 0 8px 24px rgba(16, 24, 40, 0.18);
    opacity: 0; transform: translateY(8px); transition: opacity .2s ease, transform .2s ease;
}
.toast--in { opacity: 1; transform: translateY(0); }
.toast--out { opacity: 0; transform: translateY(8px); }
.toast__body { display: flex; flex-direction: column; gap: 0.15rem; color: #fff; text-decoration: none; flex: 1; }
.toast__title { font-size: 0.85rem; font-weight: 600; }
.toast__meta { font-size: 0.78rem; color: #b9c0c9; }
.toast__close { background: none; border: 0; color: #b9c0c9; font-size: 1.15rem; line-height: 1; cursor: pointer; padding: 0 0.15rem; }
.toast__close:hover { color: #fff; }

/* Message view + crew quick-message buttons */
.message-body { white-space: pre-wrap; margin: 0.5rem 0 0; }
.message-photo { max-width: 100%; height: auto; border-radius: 10px; border: 1px solid var(--bs-line); margin-top: 0.5rem; }
.crew-message-list { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.notif__chip { font-size: 0.7rem; color: var(--bs-muted); }

/* Filter bar (Jobs / Vehicles list filters) */
.filter-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1rem; margin-bottom: 1rem; }
.filter-bar__field { display: flex; flex-direction: column; gap: 0.25rem; }
.filter-bar__field label {
    font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em;
    font-size: 0.66rem; color: var(--bs-muted);
}
.filter-bar__field select, .filter-bar__field input {
    font-family: var(--bs-font-ui); font-size: 0.9rem; color: var(--bs-text);
    padding: 0.5rem 0.65rem; border: 1.5px solid var(--bs-line); border-radius: 10px;
    background-color: #fff; min-width: 9.5rem;
}
.filter-bar__field select:focus, .filter-bar__field input:focus { outline: none; border-color: var(--bs-hi-vis); box-shadow: 0 0 0 4px rgba(0, 222, 145, 0.18); }
.filter-bar__actions { display: flex; gap: 0.5rem; margin-inline-start: auto; align-self: flex-end; }
@media (max-width: 720px) { .filter-bar__actions { margin-inline-start: 0; } }

/* Padded settings card that spans wider than the default 720px form — e.g. the Manufacturers grid,
   which needs the room for its two-column list of makes. */
.form-card--wide { max-width: 960px; }
/* Full-bleed card that keeps the form-card padding but drops the width cap, filling the content
   column (up to .app__main's 1200px) — for wide data tables like the Parts list, which needs the
   room to show every column without cramping. */
.form-card--full { max-width: 100%; }

/* Inline filter/search control living in a .toolbar (e.g. Manufacturers settings): matches the
   look of the list filter-bar inputs and grows to fill the row. */
.toolbar--filter { align-items: center; gap: 0.5rem; }
.toolbar-search {
    flex: 1 1 12rem;
    font-family: var(--bs-font-ui); font-size: 0.9rem; color: var(--bs-text);
    padding: 0.5rem 0.65rem; border: 1.5px solid var(--bs-line); border-radius: 10px;
    background-color: #fff;
}
.toolbar-search::placeholder { color: #6f7886; }
.toolbar-search:focus { outline: none; border-color: var(--bs-hi-vis); box-shadow: 0 0 0 4px rgba(0, 222, 145, 0.18); }

/* Countdown widget — per-phase remaining time ticker */
.countdown__time { font-size: 1.5rem; font-weight: 600; }
.countdown--over { color: var(--bs-danger); }

/* ---- My Queue: the technician's personal work queue ----
   A priority-ordered stack of job cards. The card being actively worked lights up with the hi-vis
   accent and its clocked/remaining figures tick live (see queue_timer_controller). */
.queue { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.85rem; }
.queue-card {
    background: #fff;
    border: 1px solid var(--bs-line);
    border-left: 4px solid var(--bs-line);
    border-radius: 14px;
    padding: 1.15rem 1.3rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
/* Active = on the clock. Accent rail + soft hi-vis glow, so a tech spots the live job at a glance. */
.queue-card--active {
    border-left-color: var(--bs-hi-vis);
    box-shadow: 0 0 0 1px var(--bs-hi-vis), 0 8px 22px -14px rgba(0,222,145,0.65);
}
.queue-card__head { display: flex; align-items: flex-start; gap: 1.25rem; min-width: 0; }
.queue-card__id { min-width: 0; }
.queue-card__vehicle { font-family: var(--bs-font-display); font-size: 1.9rem; line-height: 1; letter-spacing: 0.02em; margin: 0.3rem 0 0; color: var(--bs-ink); }
.queue-card__model { color: var(--bs-muted); font-size: 0.9rem; margin: 0.25rem 0 0; }
.queue-card__status { display: flex; flex-direction: column; align-items: flex-end; gap: 0.4rem; }

/* The signature: side-by-side live timers reading up (clocked) and down (remaining). */
.queue-card__timers { display: flex; align-items: center; gap: 1.75rem; margin-left: auto; }
.queue-timer { display: flex; flex-direction: column; gap: 0.2rem; text-align: right; }
.queue-timer__label { font-family: var(--bs-font-mono); font-size: 0.6rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--bs-muted); }
.queue-timer__value { font-family: var(--bs-font-display); font-size: 2rem; line-height: 1; color: var(--bs-ink); font-variant-numeric: tabular-nums; }
.queue-timer--remaining .queue-timer__value { color: var(--bs-hi-vis-press); }
.queue-timer__value--over { color: var(--bs-danger) !important; }
.queue-timer__value--muted { font-family: var(--bs-font-ui); font-size: 0.9rem; font-weight: 600; color: var(--bs-muted) !important; }

/* "On the clock" live tag — a quiet pulsing dot beside the pill on the active card. */
.queue-live { display: inline-flex; align-items: center; gap: 0.4rem; font-family: var(--bs-font-mono); font-size: 0.6rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--bs-hi-vis-press); font-weight: 700; }
.queue-live::before { content: ""; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--bs-hi-vis); animation: queue-pulse 1.6s ease-in-out infinite; }
@keyframes queue-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .queue-live::before { animation: none; } }

.queue-card__open { font-family: var(--bs-font-mono); font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--bs-muted); text-decoration: none; white-space: nowrap; }
.queue-card__open:hover { color: var(--bs-hi-vis-press); }

@media (max-width: 720px) {
    .queue-card { align-items: flex-start; gap: 1rem; }
    .queue-card__timers { margin-left: 0; width: 100%; justify-content: space-between; gap: 1rem; }
    .queue-timer { text-align: left; }
}

/* ---- Mobile spacing: reclaim horizontal room on small screens ---- */
@media (max-width: 720px) {
    .app__main { padding: 1.25rem 1rem; }
    /* Full-width primary actions read better than a stranded button on a phone. */
    .toolbar { align-items: stretch; }
}
@media (max-width: 480px) {
    .app__main { padding: 1rem 0.85rem; }
}

/* Wizard vehicle picker — a vertical list of selectable rows (estimate/job step 2). */
.radio-list { display: flex; flex-direction: column; gap: 0.5rem; margin-top: 0.35rem; }
.radio-list__item {
    display: flex; align-items: center; gap: 0.6rem;
    padding: 0.6rem 0.8rem; border: 1px solid var(--bs-line); border-radius: 9px; cursor: pointer;
}
.radio-list__item:hover { border-color: var(--bs-hi-vis); background: #fafbfc; }

/* Customer typeahead (estimate/job wizard step 1) — native fetch-driven results list. */
.typeahead { position: relative; }
.typeahead__results {
    position: absolute; z-index: 30; inset-inline: 0; top: calc(100% + 2px);
    margin: 0; padding: 0.25rem; list-style: none;
    background: #fff; border: 1px solid var(--bs-line); border-radius: 9px;
    box-shadow: 0 6px 18px rgba(16, 24, 40, 0.10); max-height: 16rem; overflow-y: auto;
}
.typeahead__item { padding: 0.5rem 0.7rem; border-radius: 6px; cursor: pointer; }
.typeahead__item:hover { background: rgba(0, 222, 145, 0.10); }

/* Customer document drag-and-drop uploader. Degrades to a normal file input + button without JS. */
.dropzone { border: 2px dashed var(--bs-line, #ccc); border-radius: 8px; padding: 1.25rem; text-align: center; margin-top: 1rem; }
.dropzone--over { border-color: var(--bs-primary, #2b6cb0); background: rgba(43, 108, 176, 0.06); }
.dropzone__prompt { margin: 0 0 0.75rem; color: var(--bs-secondary, #555); }
.dropzone__fallback { margin-top: 0.75rem; }
.dropzone__bar { height: 8px; background: #eee; border-radius: 4px; overflow: hidden; }
.dropzone__bar > span { display: block; height: 100%; width: 0; background: var(--bs-primary, #2b6cb0); transition: width 0.15s; }
.dropzone__error { color: var(--bs-danger, #c0392b); }

/* ---- Workforce: HR calendar ---- */
.wf-calendar-nav { display: flex; align-items: center; gap: 0.6rem; }
.wf-calendar-nav a {
    font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.08em;
    font-size: 0.7rem; color: var(--bs-text); text-decoration: none;
    padding: 0.55rem 0.9rem; border: 1px solid var(--bs-line); border-radius: 8px;
}
.wf-calendar-nav a:hover { border-color: var(--bs-ink); }
.wf-calendar-nav a:focus-visible { outline: 2px solid var(--bs-hi-vis); outline-offset: 2px; border-color: var(--bs-hi-vis); }

/* State legend: each swatch reuses the exact .wf-cell--* treatment used in the grid, with the same
   short marker letter, so the legend and the grid are visibly the same vocabulary. */
.wf-legend { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem; margin: 0 0 1.25rem; padding: 0; font-size: 0.82rem; color: var(--bs-text); }
.wf-legend__item { display: flex; align-items: center; gap: 0.45rem; }
.wf-legend__swatch {
    width: 1.4rem; height: 1.4rem; flex: 0 0 auto; border-radius: 6px;
    display: flex; align-items: center; justify-content: center;
    font-family: var(--bs-font-mono); font-size: 0.6rem; font-weight: 700;
}

/* Horizontally-scrolling grid: staff name is a sticky first column; the header row stays visible
   as the panel scrolls vertically on long staff lists. Always scrolls (unlike .table-scroll, which
   only forces scroll below the tablet breakpoint) because a month of columns never fits any viewport. */
.wf-calendar-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; border: 1px solid var(--bs-line); border-radius: 10px; }
.wf-calendar-table { border-collapse: collapse; width: max-content; min-width: 100%; }
.wf-calendar-table th, .wf-calendar-table td {
    border-bottom: 1px solid #eef0f3; border-right: 1px solid #f4f5f7;
    padding: 0.3rem; text-align: center; vertical-align: middle;
}
.wf-calendar-table thead th {
    position: sticky; top: 0; z-index: 2; background: #fff;
    font-family: var(--bs-font-mono); font-weight: 600; color: var(--bs-muted);
    border-bottom: 1px solid var(--bs-line);
}
.wf-calendar-table th.is-weekend, .wf-calendar-table td.is-weekend { background: #f7f8fa; }
.wf-calendar__daynum { display: block; font-size: 0.78rem; color: var(--bs-text); }
.wf-calendar__dow { display: block; font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.06em; }
.wf-calendar-table .wf-calendar__name {
    position: sticky; left: 0; z-index: 1; background: #fff;
    text-align: left; white-space: nowrap; min-width: 11rem;
    padding-inline: 0.9rem; font-weight: 600; font-size: 0.85rem;
    border-right: 1px solid var(--bs-line); box-shadow: 2px 0 4px rgba(16, 24, 40, 0.04);
}
.wf-calendar-table thead th.wf-calendar__name { z-index: 3; }
.wf-calendar-group-heading td {
    position: sticky; left: 0; text-align: left; background: var(--bs-ink); color: #fff;
    font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em;
    font-size: 0.68rem; padding: 0.55rem 0.9rem; border: none;
}
.wf-calendar__empty { text-align: left; color: var(--bs-muted); font-style: italic; padding-inline-start: 0.9rem; }

/* Each day cell is a fixed-size chip: a background/border pair per state plus a short marker
   letter, so the state never depends on color alone. */
.wf-cell {
    display: flex; align-items: center; justify-content: center;
    width: 1.9rem; height: 1.9rem; margin: 0 auto; border-radius: 6px;
    border: 1px solid transparent;
}
.wf-cell__marker { font-family: var(--bs-font-mono); font-size: 0.62rem; font-weight: 700; letter-spacing: 0.01em; }
.wf-cell--present { background: transparent; }
.wf-cell--present .wf-cell__marker { color: #c7ccd3; }
.wf-cell--off { background: #f1f2f4; border-color: #e7e9ec; }
.wf-cell--off .wf-cell__marker { color: #9aa1ab; }
.wf-cell--public_holiday { background: #fff4e0; border-color: #f3d9a8; color: #9a6700; }
.wf-cell--closure { background: var(--bs-ink); border-color: var(--bs-ink); color: #fff; }
.wf-cell--absence_holiday { background: #e9f6ee; border-color: #b7e0c4; color: #1a7f3c; }
.wf-cell--absence_sick { background: #fdecec; border-color: #f3b4b4; color: #b3261e; }
.wf-cell--absence_unpaid { background: #e6f6fd; border-color: #a8dcf3; color: #026e9e; }
.wf-cell--absence_other { background: #eef0f3; border-color: #d7dbe0; color: #4b5563; }
.wf-cell--absence_pending {
    color: #9a6700; border: 1px dashed #e8b23d;
    background-image: repeating-linear-gradient(45deg, #fff4e0, #fff4e0 4px, #ffe9c2 4px, #ffe9c2 8px);
}
@media (max-width: 480px) {
    .wf-calendar-table .wf-calendar__name { min-width: 8.5rem; }
}

/* ---- Dark-mode switch (RSPH-28) ----
   A two-option segmented control in the sidebar foot. The sidebar is dark in both themes, so this
   control keeps one look regardless of the active theme. The chosen option lights up hi-vis. */
.theme-toggle { display: flex; flex-direction: column; gap: 0.4rem; }
.theme-toggle__label {
    font-family: var(--bs-font-mono); text-transform: uppercase; letter-spacing: 0.1em;
    font-size: 0.6rem; color: #7e879a;
}
.theme-toggle__opts {
    display: inline-flex; padding: 2px; border-radius: 8px;
    background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.08);
}
.theme-toggle__opt {
    flex: 1; font-family: var(--bs-font-ui); font-size: 0.72rem; font-weight: 600;
    letter-spacing: 0.02em; color: #aeb6c2; background: none; border: none; border-radius: 6px;
    padding: 0.3rem 0.6rem; cursor: pointer;
    transition: background-color 0.12s ease, color 0.12s ease;
}
.theme-toggle__opt:hover { color: #fff; }
.theme-toggle__opt.is-active { background: var(--bs-hi-vis); color: var(--bs-ink-2); }
.theme-toggle__opt:focus-visible { outline: 2px solid var(--bs-hi-vis); outline-offset: 1px; }

/* ==========================================================================
   Dark mode (RSPH-28)
   Bootstrap 5.3 flips its own components under [data-bs-theme="dark"]; this block re-tokenises the
   bespoke brand layer under the same scope. Per the ticket only neutrals (backgrounds / text / lines)
   change — the hi-vis accent, RAG status colours and coloured badges are kept as they are. The
   sidebar, auth panel and marketing site are already dark, so most of the work is the app content.
   Overriding the shared tokens (--bs-paper / --bs-line / --bs-muted / --bs-text) cascades through
   every rule already built on them; the explicit rules below cover surfaces that hardcoded a light
   value (mostly #fff panels) or that use the near-black --bs-ink token as *text*.
   ========================================================================== */
[data-bs-theme="dark"] {
    --bs-paper: #1c1f24;
    --table-scroll-cover: #1c1f24;  /* match the dark panel bg so the edge mask stops smearing light */
    --bs-line: #333a43;
    --bs-muted: #98a2b0;
    --bs-text: #e6e9ee;
    --due-amber: #ffcf4d;    /* readable amber/red on the dark surface (match badge-flag) */
    --due-red: #ff8a80;

    --surface: #1c1f24;      /* raised cards / panels / inputs */
    --surface-2: #14161a;    /* page background */
    --surface-3: #23272e;    /* subtle fill: hovers, insets, chips */
    --heading: #e9ecf1;      /* big display figures that use --bs-ink as text in light mode */
}

[data-bs-theme="dark"] body { background: var(--surface-2); color: var(--bs-text); }

/* Raised surfaces: cards, panels, tiles, modals, menus, dropdowns. */
[data-bs-theme="dark"] .panel,
[data-bs-theme="dark"] .board-tile,
[data-bs-theme="dark"] .kpi-stat,
[data-bs-theme="dark"] .kpi-mix__cell,
[data-bs-theme="dark"] .vehicle-card,
[data-bs-theme="dark"] .queue-card,
[data-bs-theme="dark"] .radio-list__item,
[data-bs-theme="dark"] .perm-area,
[data-bs-theme="dark"] .modal,
[data-bs-theme="dark"] .send-split__panel,
[data-bs-theme="dark"] .typeahead__results,
[data-bs-theme="dark"] .select2-dropdown {
    background: var(--surface);
    border-color: var(--bs-line);
    color: var(--bs-text);
}

/* Big display figures coloured with the near-black ink token must go light on a dark surface. */
[data-bs-theme="dark"] .board-tile__count,
[data-bs-theme="dark"] .kpi-stat__n,
[data-bs-theme="dark"] .kpi-revenue__n,
[data-bs-theme="dark"] .kpi-pipeline__count,
[data-bs-theme="dark"] .kpi-mix__n,
[data-bs-theme="dark"] .queue-card__vehicle,
[data-bs-theme="dark"] .queue-timer__value,
[data-bs-theme="dark"] .vehicle-card__reg {
    color: var(--heading);
}

/* Hero KPI card stays ink but gains a faint accent edge so it separates from the dark page. */
[data-bs-theme="dark"] .kpi-stat--hero { border-color: rgba(0, 222, 145, 0.35); }

/* Form controls & search inputs that hardcoded a white face. */
[data-bs-theme="dark"] .form-grid input,
[data-bs-theme="dark"] .form-grid textarea,
[data-bs-theme="dark"] .form-grid select,
[data-bs-theme="dark"] .tech-modal__panel input,
[data-bs-theme="dark"] .tech-modal__panel textarea,
[data-bs-theme="dark"] .tech-modal__panel select,
[data-bs-theme="dark"] .rate-form input,
[data-bs-theme="dark"] .status-form select,
[data-bs-theme="dark"] .status-form input,
[data-bs-theme="dark"] .status-form textarea,
[data-bs-theme="dark"] .inline-form input[type="date"],
[data-bs-theme="dark"] .inline-form input[type="text"],
[data-bs-theme="dark"] .inline-form select,
[data-bs-theme="dark"] .field input,
[data-bs-theme="dark"] .table-tools__search,
[data-bs-theme="dark"] .table-tools__filter,
[data-bs-theme="dark"] .filter-bar__field select,
[data-bs-theme="dark"] .filter-bar__field input,
[data-bs-theme="dark"] .toolbar-search,
[data-bs-theme="dark"] .dt-container .dt-search input,
[data-bs-theme="dark"] .select2-container--default .select2-selection--single {
    background: var(--surface-3);
    color: var(--bs-text);
    border-color: var(--bs-line);
}
[data-bs-theme="dark"] .select2-container--default .select2-selection--single .select2-selection__rendered { color: var(--bs-text); }

/* Neutral "face" buttons that assumed white. */
[data-bs-theme="dark"] .btn--ghost { background: var(--surface-3); color: var(--bs-text); }
[data-bs-theme="dark"] .btn--ghost:hover { border-color: var(--bs-muted); }

/* RSPH-3: filter pills & modal rows share the ghost-control face in dark mode (were hardcoded white). */
[data-bs-theme="dark"] .board-pills { background: var(--surface-2); box-shadow: 0 1px 0 var(--bs-line); }
[data-bs-theme="dark"] .pill { background: var(--surface-3); border-color: var(--bs-line); color: var(--bs-text); }
[data-bs-theme="dark"] .pill:hover { border-color: var(--bs-muted); }
[data-bs-theme="dark"] .pill[aria-pressed="true"] { background: var(--bs-hi-vis); border-color: var(--bs-hi-vis); color: var(--bs-ink-2); }
[data-bs-theme="dark"] .pill[aria-pressed="true"] .pill__n { color: rgba(14,15,17,0.65); }
[data-bs-theme="dark"] .board-modal__tech:hover { background: var(--surface-3); }
[data-bs-theme="dark"] .board-modal__tech.is-selected { background: rgba(0, 222, 145, 0.14); }
[data-bs-theme="dark"] .btn--danger { background: var(--surface-3); color: #ff9d97; border-color: #6d2b2b; }
[data-bs-theme="dark"] .btn--danger:hover { background: #3a2626; }

/* Disabled fields & prefix chips. */
[data-bs-theme="dark"] .form-grid select:disabled,
[data-bs-theme="dark"] .prefixed-input__prefix,
[data-bs-theme="dark"] .select2-container--disabled .select2-selection--single { background: var(--surface-2); color: var(--bs-muted); }

/* Tables: row dividers and hover. */
[data-bs-theme="dark"] .data-table tbody td { border-bottom-color: var(--bs-line); }
[data-bs-theme="dark"] .data-table tbody tr:hover { background: var(--surface-3); }

/* Dashboard neutral fills. */
[data-bs-theme="dark"] .kpi-board { background: var(--surface-3); box-shadow: inset 0 0 0 1px var(--bs-line); }
[data-bs-theme="dark"] .kpi-board__seg--empty { background: var(--surface-3); }
[data-bs-theme="dark"] .kpi-pipeline__row { border-bottom-color: var(--bs-line); }

/* Notifications. */
[data-bs-theme="dark"] .notif { border-bottom-color: var(--bs-line); }
[data-bs-theme="dark"] .notif--unread { background: rgba(255, 184, 28, 0.08); }

/* Vehicle-card photo well. */
[data-bs-theme="dark"] .vehicle-card__photo { background: var(--surface-3); }
[data-bs-theme="dark"] .vehicle-card__photo--empty { background: linear-gradient(135deg, #23272e, #1a1d22); }

/* Technician tiles on the dark surface: same dark card shell as the vehicle cards; the accent tokens
   already read well on dark, and color-mix keeps the pill tint subtle. */
[data-bs-theme="dark"] .tech-card { background: var(--surface); border-color: var(--bs-line); }
[data-bs-theme="dark"] .tech-card--on_job  { --tech-accent: #4ade80; }
[data-bs-theme="dark"] .tech-card--idle    { --tech-accent: #ffcf4d; }
[data-bs-theme="dark"] .tech-card--holiday { --tech-accent: #7aa2ff; }
[data-bs-theme="dark"] .tech-card--sick    { --tech-accent: #ff8a80; }
[data-bs-theme="dark"] .tech-card__name { color: var(--bs-text); }
[data-bs-theme="dark"] .tech-card__job { color: var(--bs-text); }
[data-bs-theme="dark"] .tech-card__photo { background: var(--surface-3); }
[data-bs-theme="dark"] .tech-card__photo--empty { background: linear-gradient(135deg, #23272e, #1a1d22); }
[data-bs-theme="dark"] .photo-field__preview { background: var(--surface-3); border-color: var(--bs-line); }
[data-bs-theme="dark"] .photo-field__preview--empty { background: linear-gradient(135deg, #23272e, #1a1d22); }
[data-bs-theme="dark"] .tech-modal__panel { background: var(--surface); }
[data-bs-theme="dark"] .tech-start__job { background: var(--surface-3); border-color: var(--bs-line); }
[data-bs-theme="dark"] .typeahead__option { color: var(--bs-text); }
[data-bs-theme="dark"] .typeahead__option:hover { background: var(--surface-3); }

/* Near-white hovers / selected rows. */
[data-bs-theme="dark"] .radio-list__item:hover { background: var(--surface-3); }
[data-bs-theme="dark"] .select2-container--default .select2-results__option--selected { background: var(--surface-3); }
[data-bs-theme="dark"] .dt-container .dt-paging .dt-paging-button:hover:not(.current):not(.disabled) { background: var(--surface-3); border-color: var(--bs-line); }

/* Workforce HR calendar surfaces (sticky header + name column hardcoded #fff). */
[data-bs-theme="dark"] .wf-calendar-table thead th,
[data-bs-theme="dark"] .wf-calendar-table .wf-calendar__name { background: var(--surface); }
[data-bs-theme="dark"] .wf-calendar-table th,
[data-bs-theme="dark"] .wf-calendar-table td { border-bottom-color: var(--bs-line); border-right-color: rgba(255, 255, 255, 0.05); }
[data-bs-theme="dark"] .wf-calendar-table th.is-weekend,
[data-bs-theme="dark"] .wf-calendar-table td.is-weekend { background: var(--surface-3); }
[data-bs-theme="dark"] .wf-cell--off { background: var(--surface-3); border-color: var(--bs-line); }

/* Secondary editorial accent — dark mode only. A magenta highlight on the labelling elements
   (subsection headings, eyebrow kickers) adds a second colour to the dark theme without touching the
   green, which stays reserved for interactive state (nav, links, focus, CTAs). #9c009f reads well as a
   solid accent bar; the eyebrow uses a lightened tint of the same hue so the small uppercase text keeps
   AA contrast on the dark surfaces. */
[data-bs-theme="dark"] {
    --accent-magenta: #9c009f;
}
[data-bs-theme="dark"] .section-heading {
    position: relative;
    padding-inline-start: 0.7rem;
}
[data-bs-theme="dark"] .section-heading::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    top: 0.15em;
    bottom: 0.15em;
    width: 3px;
    border-radius: 2px;
    background: var(--accent-magenta);
}
[data-bs-theme="dark"] .eyebrow { color: #cf63d1; }

/* Toast lifts a touch above the page. */
[data-bs-theme="dark"] .toast { background: #23272e; }

/* Neon status badges — dark mode only. In light mode the coloured badges are pale-tint chips on a
   white page; dropped onto the dark surface that same tint reads flat and washed-out. Re-tone them
   as glowing chips instead: a translucent fill of the hue, a saturated edge, bright text, and one
   restrained outer glow — the single bold move. Neutral stays quiet (no glow) so the accent hues
   carry the signal. Covers the RAG variants and their semantic aliases. */
[data-bs-theme="dark"] .badge-flag { font-weight: 600; }
[data-bs-theme="dark"] .badge-flag--green,
[data-bs-theme="dark"] .badge-flag--ok,
[data-bs-theme="dark"] .badge-flag--authorised {
    background: rgba(0, 222, 145, 0.14);
    color: #3ff5b8;
    border-color: rgba(0, 222, 145, 0.55);
    box-shadow: 0 0 10px rgba(0, 222, 145, 0.25);
}
[data-bs-theme="dark"] .badge-flag--amber,
[data-bs-theme="dark"] .badge-flag--credit,
[data-bs-theme="dark"] .badge-flag--pending {
    background: rgba(255, 184, 28, 0.14);
    color: #ffcf4d;
    border-color: rgba(255, 184, 28, 0.6);
    box-shadow: 0 0 10px rgba(255, 184, 28, 0.25);
}
[data-bs-theme="dark"] .badge-flag--red,
[data-bs-theme="dark"] .badge-flag--stop,
[data-bs-theme="dark"] .badge-flag--declined {
    background: rgba(255, 76, 62, 0.15);
    color: #ff8a80;
    border-color: rgba(255, 90, 76, 0.6);
    box-shadow: 0 0 10px rgba(255, 76, 62, 0.28);
}
[data-bs-theme="dark"] .badge-flag--neutral {
    background: rgba(255, 255, 255, 0.07);
    color: #c4cdda;
    border-color: rgba(255, 255, 255, 0.22);
}

/* ============================================================================
   Workshop TV "Live View" (RSPH-64)
   A wall-mounted, full-screen board: the curated workshop stages as tiles, each
   auto-scrolling its vehicles, pulsing when one moves. Ported from the signed-off
   demo. Everything is scoped under `.workshop-tv` and its own tokens (incl.
   --rag-*). The board defaults to the dark palette below and follows the portal's
   theme selection: a `[data-bs-theme="light"]` block further down re-tokenises it
   to a light palette (the shared theme-init script stamps the choice on <html>).
   ============================================================================ */
.workshop-tv {
    --bs-ink: #15171a;
    --bs-ink-2: #0e0f11;
    --bs-steel: #21252b;
    --bs-steel-2: #2b3037;
    --bs-hi-vis: #00de91;
    --bs-line: #333a43;
    --bs-muted: #98a2b0;
    --rag-green: #2ec77e;
    --rag-amber: #f0b429;
    --rag-red: #f2685f;
    /* Neutral-stage row accents read as the board's signature green rather than a dead grey. */
    --rag-neutral: var(--bs-hi-vis);

    position: fixed;
    inset: 0;
    z-index: 1;
    overflow: hidden;
    background: radial-gradient(120% 120% at 50% 0%, #1a1d22 0%, var(--bs-ink-2) 70%);
    color: #e9ecf1;
    font-family: var(--bs-font-ui);
    -webkit-font-smoothing: antialiased;
    display: flex;
    flex-direction: column;
}

/* Header ------------------------------------------------------------------ */
.workshop-tv .tv-head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: clamp(0.5rem, 1.2vh, 1rem) clamp(1rem, 2vw, 2rem);
    border-bottom: 3px solid var(--bs-hi-vis);
}
.workshop-tv .tv-brand { display: flex; align-items: baseline; gap: 0.8rem; }
.workshop-tv .tv-brand__logo {
    height: clamp(1.6rem, 2.8vw, 2.6rem);
    width: auto;
    display: block;
}
.workshop-tv .tv-brand__site {
    font-family: var(--bs-font-mono);
    font-size: clamp(0.6rem, 0.95vw, 0.85rem);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--bs-muted);
}
.workshop-tv .tv-head__right { display: flex; align-items: center; gap: clamp(1rem, 2.2vw, 2.2rem); }
.workshop-tv .tv-live {
    display: flex; align-items: center; gap: 0.5rem;
    font-family: var(--bs-font-mono);
    font-size: clamp(0.62rem, 1vw, 0.9rem);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--bs-hi-vis);
}
.workshop-tv .tv-live__dot {
    width: 0.7em; height: 0.7em; border-radius: 50%;
    background: var(--bs-hi-vis);
    box-shadow: 0 0 0 0 rgba(0, 222, 145, 0.6);
    animation: wtv-live-pulse 2s ease-out infinite;
}
@keyframes wtv-live-pulse {
    0% { box-shadow: 0 0 0 0 rgba(0, 222, 145, 0.55); }
    70% { box-shadow: 0 0 0 0.7em rgba(0, 222, 145, 0); }
    100% { box-shadow: 0 0 0 0 rgba(0, 222, 145, 0); }
}
.workshop-tv .tv-clock {
    font-family: var(--bs-font-display);
    font-size: clamp(1.6rem, 3vw, 2.8rem);
    letter-spacing: 0.04em;
    line-height: 1;
    color: #fff;
    font-variant-numeric: tabular-nums;
}
.workshop-tv .tv-clock small {
    display: block;
    font-family: var(--bs-font-mono);
    font-size: 0.32em;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--bs-muted);
    text-align: right;
}
.workshop-tv .tv-btn {
    font: inherit; cursor: pointer; text-decoration: none;
    background: var(--bs-steel); color: #e9ecf1;
    border: 1px solid var(--bs-line); border-radius: 8px;
    padding: 0.45rem 0.75rem; font-size: 0.85rem; font-weight: 600;
    display: inline-flex; align-items: center; gap: 0.4rem;
    transition: border-color 0.15s, background 0.15s;
}
.workshop-tv .tv-btn:hover { border-color: var(--bs-hi-vis); background: var(--bs-steel-2); }

/* Stage grid -------------------------------------------------------------- */
.workshop-tv .tv-grid {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: 1fr;
    gap: clamp(0.4rem, 0.9vw, 0.9rem);
    padding: clamp(0.4rem, 0.9vw, 0.9rem);
}
.workshop-tv .tile {
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: var(--bs-steel);
    border: 1.5px solid var(--bs-line);
    border-radius: 12px;
    overflow: hidden;
    position: relative;
}
.workshop-tv .tile__head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: clamp(0.35rem, 0.9vh, 0.6rem) clamp(0.5rem, 0.9vw, 0.85rem);
    border-bottom: 1px solid var(--bs-line);
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), transparent);
}
.workshop-tv .tile__name {
    font-family: var(--bs-font-display);
    font-size: clamp(1rem, 1.5vw, 1.7rem);
    letter-spacing: 0.03em;
    line-height: 1;
    color: #02b3fe;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.workshop-tv .tile__count {
    flex: 0 0 auto;
    font-family: var(--bs-font-mono);
    font-size: clamp(0.7rem, 1.1vw, 1rem);
    font-weight: 700;
    color: var(--bs-hi-vis);
    background: rgba(0, 222, 145, 0.12);
    border-radius: 999px;
    padding: 0.1rem 0.55rem;
    min-width: 1.8em;
    text-align: center;
}
/* Scrollable so a person on a computer can wheel/drag through a busy stage (the JS auto-scroll pauses
   on interaction and resumes after 15s). The scrollbar is hidden so the TV board still looks clean;
   overscroll-behavior keeps a wheel scroll inside the tile from scrolling the page behind it. */
.workshop-tv .tile__list { flex: 1 1 auto; min-height: 0; overflow-y: auto; position: relative; overscroll-behavior: contain; scrollbar-width: none; }
.workshop-tv .tile__list::-webkit-scrollbar { width: 0; height: 0; }
.workshop-tv .tile__scroll { display: flex; flex-direction: column; gap: 0.3rem; padding: 0.35rem; }
.workshop-tv .tile__empty {
    height: 100%;
    display: flex; align-items: center; justify-content: center;
    color: #5b6470;
    font-family: var(--bs-font-mono);
    font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
}

/* Vehicle card ------------------------------------------------------------ */
.workshop-tv .veh {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 0.5rem;
    padding: 0.35rem 0.45rem;
    border-radius: 9px;
    background: var(--bs-ink);
    border-left: 4px solid var(--rag, var(--rag-neutral));
}
/* Quality Control rows get a royal-blue left accent (its stage RAG is amber, shared with Awaiting
   Loading, so override the row colour directly rather than the tile's --rag token). */
.workshop-tv .tile[data-code="quality_control"] .veh { border-left-color: #4169e1; }
/* Deadline urgency recolours the row's RAG accent (the left bar) rather than the whole row — it
   overrides the stage colour, incl. Quality Control's blue: amber 2-3 days from the requested
   completion date, red at 1 day away / due today / overdue. Only the red accent flashes; the row
   itself stays put. Specificity matches the QC rule and sits after it, so it wins. */
.workshop-tv .tile .veh.veh--due-amber { border-left-color: var(--rag-amber); }
.workshop-tv .tile .veh.veh--due-red {
    border-left-color: var(--rag-red);
    animation: tvDueAccentFlash 1.3s ease-in-out infinite;
}
@keyframes tvDueAccentFlash {
    0%, 100% { border-left-color: #f2685f; }
    50% { border-left-color: #000; }
}
@media (prefers-reduced-motion: reduce) {
    .workshop-tv .veh--due-red { animation: none; }
}
.workshop-tv .veh__emblem {
    width: clamp(24px, 2vw, 34px);
    height: clamp(24px, 2vw, 34px);
    object-fit: contain;
    border-radius: 6px;
    /* Dark grey to match the Live Job Status card emblem slot (--surface-3 in dark theme); the
       always-dark TV scope uses the literal since --surface-3 is only defined under data-bs-theme. */
    background: #23272e;
    padding: 2px;
    flex: 0 0 auto;
}
.workshop-tv .veh__emblem--empty {
    display: inline-flex; align-items: center; justify-content: center;
    background: linear-gradient(135deg, #2b3037, #21252b);
    color: #8a94a2;
    font-family: var(--bs-font-display);
    font-size: clamp(0.8rem, 1.1vw, 1.1rem);
}
.workshop-tv .veh__id { min-width: 0; }
.workshop-tv .veh__reg {
    font-family: var(--bs-font-mono);
    font-weight: 700;
    letter-spacing: 0.05em;
    font-size: clamp(0.85rem, 1.25vw, 1.4rem);
    color: #fff;
    line-height: 1.05;
    white-space: nowrap;
}
.workshop-tv .veh__model {
    font-size: clamp(0.62rem, 0.9vw, 0.9rem);
    color: var(--bs-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.workshop-tv .veh__meta {
    flex: 0 0 auto;
    display: flex; flex-direction: column; align-items: flex-end;
    gap: 0.12rem; min-width: 0; text-align: right;
}
.workshop-tv .veh__parts {
    font-family: var(--bs-font-mono);
    font-size: clamp(0.58rem, 0.8vw, 0.8rem);
    font-weight: 700;
    color: var(--rag-amber);
    background: rgba(240, 180, 41, 0.14);
    border: 1px solid rgba(240, 180, 41, 0.35);
    border-radius: 999px;
    padding: 0.02rem 0.45rem;
    white-space: nowrap;
}
.workshop-tv .veh__parts--none {
    color: #fff;
    background: var(--rag-red);
    border-color: var(--rag-red);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    box-shadow: 0 0 10px 1px rgba(242, 104, 95, 0.5);
}
.workshop-tv .veh__tech {
    font-size: clamp(0.62rem, 0.9vw, 0.9rem);
    font-weight: 600;
    color: #e9ecf1;
    white-space: nowrap;
}
.workshop-tv .veh__loc {
    display: inline-flex; align-items: center; gap: 0.2rem;
    font-size: clamp(0.56rem, 0.8vw, 0.8rem);
    color: var(--bs-hi-vis);
    font-weight: 600;
    white-space: nowrap;
}
.workshop-tv .veh__pin { width: 0.85em; height: 0.85em; fill: currentColor; flex: 0 0 auto; opacity: 0.85; }

/* Pulse on update --------------------------------------------------------- */
.workshop-tv .tile.is-updated {
    animation: wtv-tile-pulse 1.15s ease-out;
    border-color: var(--bs-hi-vis);
    z-index: 2;
}
@keyframes wtv-tile-pulse {
    0% { box-shadow: 0 0 0 0 rgba(0, 222, 145, 0); }
    18% { box-shadow: 0 0 0 3px rgba(0, 222, 145, 0.9), 0 0 34px 4px rgba(0, 222, 145, 0.45); }
    100% { box-shadow: 0 0 0 0 rgba(0, 222, 145, 0); }
}

@media (max-width: 1100px) { .workshop-tv .tv-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px) { .workshop-tv .tv-grid { grid-template-columns: repeat(2, 1fr); } }
@media (prefers-reduced-motion: reduce) {
    .workshop-tv .tv-live__dot, .workshop-tv .tile.is-updated { animation: none; }
}

/* Light theme -------------------------------------------------------------
   The board follows the portal's theme selection (data-bs-theme on <html>, set
   by the shared theme-init script from the same 'rsph-theme' preference). In
   light mode we re-tokenise to a white-surface palette and override the handful
   of literal near-white text/surfaces the dark board hard-codes. The green is
   darkened so it stays legible as text/accent on white; RAG amber/red, the QC
   blue and the deadline flash already read on both. */
[data-bs-theme="light"] .workshop-tv {
    --bs-ink: #f2f5f8;        /* vehicle row fill */
    --bs-ink-2: #e6ebf0;
    --bs-steel: #ffffff;      /* tile / button surface */
    --bs-steel-2: #eef1f5;
    --bs-hi-vis: #0a9d68;     /* darker green: legible as text + fine as accent on white */
    --bs-line: #d7dde4;
    --bs-muted: #5b6675;
    background: radial-gradient(120% 120% at 50% 0%, #ffffff 0%, #e9edf2 70%);
    color: #1a1f26;
}
[data-bs-theme="light"] .workshop-tv .tv-btn { color: #2b3440; }
[data-bs-theme="light"] .workshop-tv .tv-clock,
[data-bs-theme="light"] .workshop-tv .veh__reg { color: #12161b; }
[data-bs-theme="light"] .workshop-tv .veh__tech { color: #2b3440; }
[data-bs-theme="light"] .workshop-tv .tile__name { color: #0a6fb0; }
[data-bs-theme="light"] .workshop-tv .tile__empty { color: #9aa4b0; }
[data-bs-theme="light"] .workshop-tv .veh__emblem { background: #eef1f5; }
[data-bs-theme="light"] .workshop-tv .veh__emblem--empty {
    background: linear-gradient(135deg, #eef1f4, #e2e7ec);
    color: #6b7683;
}
/* Swap the header logo to the dark mark on the light board (default board is dark → white mark). */
.workshop-tv .tv-brand__logo--for-light { display: none; }
[data-bs-theme="light"] .workshop-tv .tv-brand__logo--for-dark { display: none; }
[data-bs-theme="light"] .workshop-tv .tv-brand__logo--for-light { display: block; }

/* ── Cover-photo picker (Job View → Documents tab) ──────────────────────────────
   A row of selectable image thumbnails that mirror the Live Job Status card's photo
   slot (wide cover-fit on a near-black backdrop). The chosen tile carries the
   signature hi-vis ring + check; a "No cover" tile clears it. Selection is driven off
   the real checked radio via :has(), so it stays right even before the form re-renders. */
.cover-picker__hint { color: var(--bs-muted); font-size: 0.8rem; margin: 0 0 0.7rem; }
.cover-picker { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: stretch; }
.cover-option {
    position: relative;
    flex: 0 0 auto;
    width: 132px;
    aspect-ratio: 11 / 5;
    border: 1px solid var(--bs-line);
    border-radius: 10px;
    overflow: hidden;
    cursor: pointer;
    background: #0d0f12;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.cover-option input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.cover-option img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cover-option:hover { border-color: var(--bs-hi-vis); }
.cover-option:has(input:checked) {
    border-color: var(--bs-hi-vis);
    box-shadow: inset 0 0 0 2px var(--bs-hi-vis);
}
.cover-option:has(input:focus-visible) { outline: 2px solid var(--bs-hi-vis); outline-offset: 2px; }
/* Check badge, top-end corner, only on the selected tile. */
.cover-option__check {
    position: absolute;
    inset-block-start: 4px;
    inset-inline-end: 4px;
    width: 18px;
    height: 18px;
    display: none;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bs-hi-vis);
    color: var(--bs-ink-2);
    font-size: 0.7rem;
    line-height: 1;
}
.cover-option:has(input:checked) .cover-option__check { display: flex; }
/* The "No cover" tile is a quiet dashed placeholder rather than a photo. */
.cover-option--none {
    background: #fff;
    border-style: dashed;
    display: flex;
    align-items: center;
    justify-content: center;
}
.cover-option__none { color: var(--bs-muted); font-size: 0.74rem; font-weight: 600; }
