﻿/*
    Summary: styling of the web application -- layout, panels, tables, map, help.
    Keywords: css, layout, dark mode, table, map panel, help panel, status colours, clickable rows.

    Rows and cards are clickable as a whole rather than through a small icon, and primary actions sit
    where they are reachable without scrolling.
*/

:root {
    --bg: #f4f6f8;
    --surface: #ffffff;
    --surface-2: #f8fafc;
    --border: #dbe2ea;
    --text: #16202a;
    --text-dim: #5b6b7c;
    --accent: #0b6ea8;
    --accent-dark: #08557f;

    /* Route colours from project.md 7.1: green done, orange to do, red deviation. */
    --done: #1c9c53;
    --open: #d98218;
    --deviation: #c8352b;
    --stale: #8794a3;

    --radius: 6px;
    --shadow: 0 1px 3px rgba(16, 30, 44, .1), 0 4px 14px rgba(16, 30, 44, .06);
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg: #10161d;
        --surface: #18212b;
        --surface-2: #1e2833;
        --border: #2b3846;
        --text: #e6edf4;
        --text-dim: #9aabbc;
        --accent: #3f9fd6;
        --accent-dark: #2b86ba;
        --shadow: 0 1px 3px rgba(0, 0, 0, .4);
    }
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    height: 100%;
    background: var(--bg);
    color: var(--text);
    font: 14px/1.45 "Segoe UI", system-ui, -apple-system, sans-serif;
}

body { display: flex; flex-direction: column; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* -- Top bar ---------------------------------------------------------------- */

.topbar {
    display: flex;
    align-items: center;
    gap: 24px;
    padding: 0 16px;
    height: 52px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    flex: 0 0 auto;
}

.brand { display: flex; align-items: center; gap: 9px; color: var(--text); font-weight: 600; }
.brand:hover { text-decoration: none; }

.brand-mark { display: block; width: 26px; height: 26px; }
.brand-wordmark { display: block; height: 28px; width: auto; }

.mainnav { display: flex; gap: 4px; margin-right: auto; }

.mainnav a {
    padding: 7px 12px;
    border-radius: var(--radius);
    color: var(--text-dim);
    font-weight: 500;
}

.mainnav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.mainnav a.active { background: var(--accent); color: #fff; }

.topbar-right { display: flex; align-items: center; gap: 12px; }
.tenant { color: var(--text-dim); font-size: 13px; }

/* Connection indicator: a planner must be able to see that the map is live. */
.conn { width: 9px; height: 9px; border-radius: 50%; background: var(--stale); }
.conn[data-state="connected"] { background: var(--done); }
.conn[data-state="connecting"] { background: var(--open); }
.conn[data-state="lost"] { background: var(--deviation); }

.usermenu { position: relative; }
.usermenu > summary { cursor: pointer; list-style: none; padding: 6px 10px; border-radius: var(--radius); }
.usermenu > summary::-webkit-details-marker { display: none; }
.usermenu > summary:hover { background: var(--surface-2); }

.usermenu-panel {
    /* Above Leaflet, which claims up to 1000 for its own panes and controls: at z-index 40 this panel was
       in the DOM, the right size, fully opaque -- and invisible, because the map drew over it. Same trap as
       the chat panel and the banner. */
    position: absolute; right: 0; top: 100%; z-index: 1500;
    min-width: 160px; padding: 10px;
    display: flex; flex-direction: column; gap: 8px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow);
}

.role { color: var(--text-dim); font-size: 12px; }

/* -- The user options menu: display choices, per user, in one place instead of scattered over buttons. */
.usermenu-panel { min-width: 220px; }

.usermenu-options[hidden] { display: none; }

.usermenu-options {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
}

.usermenu-heading,
.option-label {
    font-size: 11px;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.option-group { display: flex; flex-direction: column; gap: 4px; }

.option-line {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 3px 4px;
    border-radius: 6px;
    font-size: 13px;
    cursor: pointer;
}

.option-line:hover { background: var(--surface-2); }

.option-line input { margin: 0; width: auto; }

/* -- Icon actions. Compact on purpose: the panel is narrow, and these three are used constantly. */
.panel-actions {
    display: flex;
    gap: 8px;
    padding: 10px;
    border-top: 1px solid var(--border);
}

.iconbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 38px;
    padding: 0;
    color: var(--text);
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    cursor: pointer;
}

.iconbtn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }

.iconbtn:disabled { opacity: .45; cursor: not-allowed; }

/* Any disabled button, not just the icons: a button that cannot be pressed and looks pressable is a button
   the user tries three times. */
button:disabled, .btn:disabled { opacity: .45; cursor: not-allowed; }

/* The chat icon is the primary action of this panel, so it carries the accent. */
#chat-toggle:not(:disabled) { color: #fff; background: var(--accent); border-color: var(--accent); }

/* -- Page frame ------------------------------------------------------------- */

main.app { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
main.bare { flex: 1 1 auto; display: grid; place-items: center; padding: 24px; }

.page { padding: 18px 20px; overflow: auto; }
.page-head { display: flex; align-items: baseline; gap: 16px; margin-bottom: 14px; }
.page-head h1 { margin: 0; font-size: 19px; font-weight: 600; }
.page-head .spacer { margin-left: auto; }

/* -- Buttons and fields ----------------------------------------------------- */

button, .btn {
    font: inherit;
    padding: 7px 14px;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    background: var(--accent);
    color: #fff;
    cursor: pointer;
}

button:hover, .btn:hover { background: var(--accent-dark); text-decoration: none; }

button.secondary, .btn.secondary {
    background: var(--surface); color: var(--text); border-color: var(--border);
}
button.secondary:hover, .btn.secondary:hover { background: var(--surface-2); }

button.danger { background: var(--deviation); border-color: var(--deviation); }

button.ghost {
    background: transparent; border: 1px solid var(--border); color: var(--text-dim);
    width: 28px; height: 28px; padding: 0; border-radius: 50%; line-height: 1;
}
button.ghost:hover { background: var(--surface-2); color: var(--text); }

button.linklike {
    background: none; border: none; color: var(--accent); padding: 0; text-align: left;
}
button.linklike:hover { text-decoration: underline; background: none; }

label { display: block; margin-bottom: 12px; }
label > span { display: block; margin-bottom: 4px; color: var(--text-dim); font-size: 13px; }

input[type=text], input[type=password], input[type=email], input[type=search], select, textarea {
    font: inherit;
    width: 100%;
    padding: 7px 9px;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.checkline { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.checkline input { width: auto; }
.checkline label { margin: 0; }

/* -- Cards, tables ---------------------------------------------------------- */

.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 18px;
}

.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; }

table.data { width: 100%; border-collapse: collapse; background: var(--surface); }

table.data th {
    text-align: left; padding: 9px 12px;
    border-bottom: 2px solid var(--border);
    color: var(--text-dim); font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
}

table.data td { padding: 9px 12px; border-bottom: 1px solid var(--border); }

/* Whole row clickable, not a small pencil icon at the end. */
table.data tr.clickable { cursor: pointer; }
table.data tr.clickable:hover td { background: var(--surface-2); }

.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius); }

.pill {
    display: inline-block; padding: 2px 8px; border-radius: 10px;
    font-size: 12px; font-weight: 600;
}
.pill.done { background: color-mix(in srgb, var(--done) 18%, transparent); color: var(--done); }
.pill.open { background: color-mix(in srgb, var(--open) 18%, transparent); color: var(--open); }
.pill.deviation { background: color-mix(in srgb, var(--deviation) 18%, transparent); color: var(--deviation); }
.pill.stale { background: color-mix(in srgb, var(--stale) 18%, transparent); color: var(--stale); }

/* A stop the driver is standing at. Deliberately not a fourth "done-ish" colour: the question is done
   or not done, and busy is not done. */
.pill.busy { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); }

.muted { color: var(--text-dim); }
.empty { padding: 36px; text-align: center; color: var(--text-dim); }
.notice { padding: 10px 12px; border-radius: var(--radius); border: 1px solid var(--border); background: var(--surface-2); margin-bottom: 14px; }
.notice.error { border-color: var(--deviation); color: var(--deviation); }
.notice.ok { border-color: var(--done); color: var(--done); }

/* -- Map screen: vehicle panel left, map right ------------------------------ */

.fleet { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: 320px 1fr; }

.fleet-panel {
    border-right: 1px solid var(--border);
    background: var(--surface);
    display: flex; flex-direction: column; min-height: 0;
}

.fleet-search { padding: 10px; border-bottom: 1px solid var(--border); }
.fleet-list { overflow-y: auto; flex: 1 1 auto; }

.fleet-item {
    padding: 9px 12px;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    display: grid;

    /* Three columns: code, the envelope when there is one, and the status pill. Two columns pushed the
       pill onto its own line as soon as a row had mail. */
    grid-template-columns: 1fr auto auto;
    gap: 2px 8px;
    align-items: center;
}

.fleet-item:hover { background: var(--surface-2); }
.fleet-item.selected { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.fleet-item .code { font-weight: 600; }
.fleet-item .sub { grid-column: 1 / -1; color: var(--text-dim); font-size: 12px; }

#map { width: 100%; height: 100%; background: var(--surface-2); }

.map-wrap { position: relative; min-height: 0; }

.map-hint {
    position: absolute; left: 50%; top: 14px; transform: translateX(-50%);
    z-index: 500; padding: 7px 14px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 14px; box-shadow: var(--shadow); font-size: 13px;
}

/* Vehicle marker: a triangle that points where it is going. */
.veh-marker { width: 22px; height: 22px; }
.veh-marker svg { display: block; overflow: visible; }

.stop-marker {
    display: grid; place-items: center;
    width: 24px; height: 24px; border-radius: 50%;
    color: #fff; font-size: 11px; font-weight: 700;
    border: 2px solid rgba(255, 255, 255, .85);
    box-shadow: 0 1px 4px rgba(0, 0, 0, .4);
}
.stop-marker.done { background: var(--done); }
.stop-marker.open { background: var(--open); }
.stop-marker.deviation { background: var(--deviation); }

/* Context menu on a vehicle. */
.ctxmenu {
    position: fixed; z-index: 900; min-width: 190px; padding: 5px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: var(--shadow);
}
.ctxmenu button {
    display: block; width: 100%; text-align: left;
    background: none; border: none; color: var(--text); padding: 8px 10px; border-radius: 4px;
}
.ctxmenu button:hover { background: var(--surface-2); }
.ctxmenu .sep { height: 1px; background: var(--border); margin: 4px 0; }
.ctxmenu .head { padding: 6px 10px; color: var(--text-dim); font-size: 12px; }

/* -- Dialog ----------------------------------------------------------------- */

dialog {
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--surface); color: var(--text);
    box-shadow: var(--shadow); padding: 18px; min-width: 340px; max-width: 90vw;
}
dialog::backdrop { background: rgba(10, 16, 22, .45); }
dialog h2 { margin: 0 0 12px; font-size: 16px; }
.dialog-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 14px; }

/* -- F1 help ---------------------------------------------------------------- */

/* The hidden attribute sets display:none in the browser's own stylesheet, and an author rule with
   display:flex beats it. Without these two rules the panel is simply always on screen. */
.help-panel[hidden], .help-backdrop[hidden] { display: none; }

.help-panel {
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 1000;
    width: min(460px, 92vw);
    background: var(--surface); border-left: 1px solid var(--border);
    box-shadow: -6px 0 24px rgba(10, 16, 22, .18);
    display: flex; flex-direction: column;
}

.help-panel header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 12px 14px; border-bottom: 1px solid var(--border);
}

.help-body { padding: 14px 18px 28px; overflow-y: auto; }
.help-body h2 { font-size: 17px; margin: 4px 0 10px; }
.help-body h3 { font-size: 14px; margin: 18px 0 6px; }
.help-body code { background: var(--surface-2); padding: 1px 4px; border-radius: 3px; }
.help-body table { border-collapse: collapse; width: 100%; margin: 10px 0; }
.help-body th, .help-body td { border: 1px solid var(--border); padding: 5px 8px; text-align: left; }

.help-backdrop { position: fixed; inset: 0; z-index: 999; background: rgba(10, 16, 22, .25); }

/* -- Sign in ---------------------------------------------------------------- */

.signin { width: 340px; }
.signin .brand { justify-content: center; margin-bottom: 18px; font-size: 17px; }

/* -- Draft indicator -------------------------------------------------------- */

.draft-note { font-size: 12px; color: var(--text-dim); min-height: 16px; }

/* -- Trip detail ------------------------------------------------------------ */

.stoplist { list-style: none; margin: 0; padding: 0; }
.stoplist li {
    display: grid; grid-template-columns: 30px 1fr auto; gap: 10px;
    padding: 10px 0; border-bottom: 1px solid var(--border);
}
.seq {
    display: grid; place-items: center;
    width: 26px; height: 26px; border-radius: 50%;
    background: var(--surface-2); color: var(--text-dim);
    font-size: 12px; font-weight: 700;
}
.seq.done { background: var(--done); color: #fff; }
.seq.deviation { background: var(--deviation); color: #fff; }
.seq.open { background: var(--open); color: #fff; }
.seq.busy { background: var(--accent); color: #fff; }
.seq.stale { background: var(--stale); color: #fff; }

/* Briefly marks a row that just changed by itself, so a planner watching the screen sees what moved
   instead of wondering whether it was always like that. */
@keyframes live-flash {
    from { background: color-mix(in srgb, var(--accent) 24%, transparent); }
    to { background: transparent; }
}
.stoplist li.live-changed { animation: live-flash 1.6s ease-out; }

dl.kv { display: grid; grid-template-columns: max-content 1fr; gap: 5px 14px; margin: 0; }
dl.kv dt { color: var(--text-dim); }
dl.kv dd { margin: 0; }

/* -- Chat with a driver ------------------------------------------------------ */
/* Docked bottom right and not a modal: a planner reads a message while he keeps watching the map, and a
   dialog over the map would hide exactly the thing the message is about. */

.chat-panel {
    /* Above Leaflet: its own panes and controls go up to z-index 1000, so anything below that is
       painted over by the map and looks like it never appeared. */
    position: fixed; right: 16px; bottom: 16px; z-index: 1200;
    width: min(380px, calc(100vw - 32px)); max-height: min(520px, 70vh);
    display: flex; flex-direction: column;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); box-shadow: 0 12px 34px rgba(0,0,0,.32);
}
.chat-panel[hidden] { display: none; }

.chat-panel > header {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 10px 12px; border-bottom: 1px solid var(--border);
}
.chat-panel > header .muted { font-size: 12px; }

.chat-body { overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 8px; }

.chat-line { max-width: 85%; align-self: flex-end; }
.chat-line.from-driver { align-self: flex-start; }
.chat-line .meta { font-size: 11px; color: var(--text-dim); margin-bottom: 2px; }
.chat-line .text {
    padding: 7px 10px; border-radius: 10px;
    background: var(--surface-2); border: 1px solid var(--border);
    white-space: pre-wrap; word-break: break-word;
}
.chat-line.from-driver .text { border-color: var(--accent); }

.chat-send { display: flex; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--border); }
.chat-send input { flex: 1; }

/* -- The envelope on a vehicle ---------------------------------------------- */

.fleet-mail {
    background: none; border: 0; padding: 0 2px; cursor: pointer;
    color: var(--accent); display: inline-flex; align-items: center; gap: 3px;
    min-height: 0; height: auto;
}
.fleet-mail:hover { color: var(--text); }
.fleet-mail .count { font-size: 11px; font-weight: 700; }
.fleet-item.has-mail .code { font-weight: 700; }

/* -- The banner ------------------------------------------------------------- */
/* Slides in from the right so it registers in the corner of the eye, and stays clickable long enough to
   act on: fifteen seconds, because a planner is usually on the phone when it appears. */

.toast-host {
    position: fixed; right: 16px; bottom: 16px; z-index: 1300;
    display: flex; flex-direction: column; gap: 8px; pointer-events: none;
}
.chat-panel:not([hidden]) ~ .toast-host { bottom: calc(min(520px, 70vh) + 28px); }

.toast {
    position: relative; pointer-events: auto;
    width: min(340px, calc(100vw - 32px));
    padding: 10px 30px 10px 12px;
    background: var(--surface); border: 1px solid var(--accent);
    border-radius: var(--radius); box-shadow: 0 10px 28px rgba(0,0,0,.30);
    transform: translateX(calc(100% + 24px)); opacity: 0;
    transition: transform .25s ease-out, opacity .25s ease-out;
}
.toast.in { transform: translateX(0); opacity: 1; }
.toast.clickable { cursor: pointer; }
.toast-title { display: flex; align-items: center; gap: 6px; font-weight: 600; color: var(--accent); }
.toast-text { margin-top: 3px; white-space: pre-wrap; word-break: break-word; }
.toast-close {
    position: absolute; top: 4px; right: 6px;
    background: none; border: 0; color: var(--text-dim); font-size: 18px; line-height: 1;
    cursor: pointer; padding: 2px 4px; min-height: 0; height: auto;
}
.toast-close:hover { color: var(--text); }

/* -- Photos with a deviation ------------------------------------------------- */
/* Thumbnails, because a planner scanning a trip wants to see that there is evidence, not open it. */

.photostrip { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.photostrip img {
    width: 96px; height: 96px; object-fit: cover;
    border-radius: 6px; border: 1px solid var(--border);
    background: var(--surface-2);
}
.photostrip a:hover img { border-color: var(--accent); }

/* -- History: the time slider sits over the map, so it has to clear Leaflet's own panes (z-index 1000). */
.history-bar {
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: 16px;
    z-index: 1100;
    display: grid;
    gap: 6px;
    padding: 10px 14px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    box-shadow: 0 6px 20px rgb(0 0 0 / 35%);
}

.history-bar[hidden] { display: none; }

.history-moment { display: flex; gap: 10px; align-items: baseline; }

.history-bar input[type="range"] { width: 100%; }

.history-summary {
    display: grid;
    gap: 3px;
    padding: 10px;
    border-bottom: 1px solid var(--border);
}

/* -- Corrections per stop: folded away, because a planner reads a trip far more often than he corrects it. */
.stop-actions { margin-top: 8px; }

.stop-actions > summary {
    cursor: pointer;
    color: var(--muted);
    font-size: 12px;
}

.stop-actions form {
    display: grid;
    gap: 6px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--border);
    text-align: left;
}

/* -- The pin picker on a location. Fixed height: a map that grows with its card ends up either a strip
      or the whole page, and neither is usable for placing one pin. */
.location-map {
    height: 300px;
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
}

/* -- The proof dossier -------------------------------------------------------
   A document, not a screen: one column, room to breathe, and everything that belongs to the application
   rather than to the document disappears when it is printed. */

.dossier .sheet {
    max-width: 900px;
    padding: 26px 30px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.dossier .sheet-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 20px;
    padding-bottom: 14px;
    border-bottom: 2px solid var(--border);
}

.dossier .sheet-head h2 { margin: 0 0 4px; font-size: 20px; }
.dossier .sheet-id { text-align: right; font-size: 12px; }

.dossier section { margin-top: 20px; }
.dossier section h3 { margin: 0 0 8px; font-size: 14px; }

.dossier .outcome {
    margin: 16px 0 0;
    padding: 8px 12px;
    border-radius: var(--radius);
    font-weight: 600;
}

.dossier .outcome.ok { color: var(--done); background: color-mix(in srgb, var(--done) 14%, transparent); }
.dossier .outcome.warn { color: var(--deviation); background: color-mix(in srgb, var(--deviation) 14%, transparent); }

.dossier .warn { color: var(--deviation); }

.dossier .deviations { margin: 0; padding: 0; list-style: none; display: grid; gap: 12px; }

.dossier .deviations > li {
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--deviation);
    border-radius: var(--radius);
}

.dossier .note { margin-top: 4px; font-style: italic; }

.dossier .photogrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 12px;
}

.dossier .photogrid img {
    width: 100%;
    height: 150px;
    object-fit: cover;
    border: 1px solid var(--border);
    border-radius: var(--radius);
}

.dossier .photogrid figure { margin: 0; }
.dossier .photogrid figcaption { font-size: 11px; margin-top: 3px; }

.dossier .sheet-foot { margin-top: 24px; padding-top: 12px; border-top: 1px solid var(--border); font-size: 11px; }

@media print {
    /* On paper only the document is left: no navigation, no buttons, no dark background eating a cartridge. */
    .topbar, .no-print, .help-panel, .toast-host, .chat-panel { display: none !important; }

    body, .dossier .sheet { background: #fff !important; color: #111 !important; }

    .dossier .sheet { border: 0; max-width: none; padding: 0; }

    .dossier .muted, .dossier .sheet-id { color: #555 !important; }

    /* The tables keep the dark styling of the application otherwise: dark text on a dark fill, which is
       invisible on paper and eats a cartridge doing it. */
    .dossier table.data, .dossier table.data th, .dossier table.data td {
        background: #fff !important;
        color: #111 !important;
        border-color: #bbb !important;
    }

    .dossier table.data th { border-bottom: 1px solid #666 !important; }

    .dossier .deviations > li { border-color: #bbb !important; border-left-color: #c9432f !important; }

    .dossier .outcome.ok { background: #eef7f0 !important; color: #14663a !important; }
    .dossier .outcome.warn { background: #fdeeeb !important; color: #a3301f !important; }

    .dossier .warn { color: #a3301f !important; }

    a[href]::after { content: ""; }

    /* A deviation and its photos belong together on one page: split across a page break they read as two
       separate incidents. */
    .dossier section, .dossier .deviations > li, .dossier .photogrid figure { break-inside: avoid; }
}

/* -- Where a vehicle is, in words. Its own line under the plate and the driver: it is the answer to a
      different question than "who is driving this". */
.fleet-item .place {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--text-dim);
    font-size: 12px;
    min-height: 16px;
}
.fleet-item .place svg { flex: 0 0 auto; }
.fleet-item .place .no-position { color: var(--deviation); }

/* -- A signature is a document, so it keeps a white ground whatever the theme does: black ink on a dark
      panel is invisible, and on paper it would be a black block. */
.signature img, .signature-strip img {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 4px;
}

.signature { margin: 0 0 12px; }
.signature img { max-width: 320px; width: 100%; }
.signature figcaption { margin-top: 4px; font-size: 12px; }

.signature-strip {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    font-size: 12px;
}

.signature-strip img { width: 120px; }

/* -- The pin on the location picker. Drawn rather than an image: Leaflet's default icon is a PNG from its
      images folder, and we ship only the stylesheet and the script -- so the default pin was a broken image. */
.pin-marker {
    width: 22px;
    height: 22px;
    border-radius: 50% 50% 50% 0;
    transform: rotate(-45deg);
    background: var(--accent);
    border: 2px solid #fff;
    box-shadow: 0 2px 6px rgb(0 0 0 / 45%);
}

/* -- The install block: the QR keeps a white ground whatever the theme does, because a scanner needs the
      contrast the code was generated with. */
.install { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }

.install-qr {
    padding: 8px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 8px;
    line-height: 0;
}

.install-qr svg { width: 160px; height: 160px; }

.install p { margin: 0 0 6px; }

/* -- A list whose order is the setting: dragged by the grip or moved with the arrows. No sort numbers to
      type, because a planner should not have to work out which numbers are still free. */
.reorder { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.reorder-row {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface-2);
}

.reorder-row.dragging { opacity: 0.5; }

.reorder-row .grip { cursor: grab; color: var(--muted); font-size: 18px; line-height: 1.2; user-select: none; }

.reorder-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }

.reorder-title { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }

.reorder-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }

.reorder-actions form { margin: 0; }

button.icon { padding: 6px 10px; min-width: 38px; line-height: 1; }

/* -- A line that says what is wrong, inside a card rather than as a banner. */
.text-error { color: var(--deviation); }

/* -- Answers from a question path, at the stop where they were given. */
.answers { display: flex; flex-direction: column; gap: 2px; margin: 6px 0; }

.answer { display: flex; gap: 8px; flex-wrap: wrap; align-items: baseline; }

/* -- The question path drawing. Tiles are positioned absolutely from what the model says (CanvasX/CanvasY),
      the lines are drawn in one SVG underneath them. No library: this is a box with lines, and the map is
      already the only third party thing we ship. */
.pathcanvas {
    position: relative;
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: 8px;
    background:
        radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--muted) 35%, transparent) 1px, transparent 0);
    background-size: 20px 20px;
    min-height: 320px;
    touch-action: none;
}

.pathcanvas.wiring { cursor: crosshair; }

/* Het vlak waarop getekend wordt. Groeit met de tegels; het venster eromheen houdt zijn eigen maat en scrollt.
   Die scheiding is er omdat het tekenen anders de hoogte van het venster zette - en dan verspringt de hele
   pagina bij elke muisbeweging tijdens het slepen. */
.pathcanvas-surface { position: relative; min-width: 100%; min-height: 100%; }

.pathcanvas-lines { position: absolute; inset: 0; pointer-events: none; }

.pathcanvas .edge { fill: none; stroke: var(--accent); stroke-width: 2; }

.pathcanvas .edge.wiring { stroke-dasharray: 6 4; }

.pathcanvas .edge-arrow { fill: var(--accent); stroke: none; }

.pathcanvas .edge-label {
    fill: var(--text);
    font-size: 11px;
    paint-order: stroke;
    stroke: var(--surface);
    stroke-width: 3px;
}

.pathcanvas .tile {
    position: absolute;
    width: 240px;
    padding: 8px 10px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface-2);
    cursor: grab;
    user-select: none;
    z-index: 1;
}

.pathcanvas.readonly .tile { cursor: default; }

.pathcanvas .tile.dragging { opacity: 0.7; }

/* A tile with a blocking finding: the planner should not have to read the list to find out which one. */
.pathcanvas .tile.broken { border-color: var(--deviation); }

.pathcanvas .tile.start { border-color: var(--done); }
.pathcanvas .tile.end { border-color: var(--muted); }
.pathcanvas .tile.task { border-color: var(--accent); }

.pathcanvas .tile-head { display: flex; gap: 8px; align-items: baseline; justify-content: space-between; }

.pathcanvas .tile-prompt { margin-top: 4px; font-size: 13px; }

.pathcanvas .tile-options { margin-top: 2px; font-size: 12px; color: var(--muted); }

/* The plug you pull a line from. Deliberately large enough to hit with a finger. */
.pathcanvas .tile-plug {
    position: absolute;
    left: 50%;
    bottom: -9px;
    width: 18px;
    height: 18px;
    margin-left: -9px;
    border-radius: 50%;
    background: var(--accent);
    cursor: crosshair;
}

/* -- A document from a customer's own template. The template brings the content, this brings the layout: that
      is the whole reason a template is Markdown and not HTML. */
.document h1 { font-size: 22px; margin: 0 0 10px; }
.document h2 { font-size: 17px; margin: 18px 0 8px; }
.document h3 { font-size: 15px; margin: 14px 0 6px; }

.document p { margin: 0 0 8px; }

.document table { width: 100%; border-collapse: collapse; margin: 8px 0 14px; }

.document th,
.document td { text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--border); }

.document th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }

.document ul { margin: 0 0 10px; padding-left: 20px; }

.document img { max-width: 320px; max-height: 220px; border: 1px solid var(--border); border-radius: 6px; }

.document hr { border: 0; border-top: 1px solid var(--border); margin: 16px 0 8px; }

/* A template is text somebody types, so it is edited in a monospace box: alignment in a Markdown table only
   reads if the characters line up. */
textarea.code {
    font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
    font-size: 12px;
    line-height: 1.45;
    white-space: pre;
    overflow-wrap: normal;
    overflow-x: auto;
}

.reorder-row.selected { border-color: var(--accent); }

@media print {
    /* Same rule as the proof dossier: tables keep the dark theme otherwise and are unreadable on paper. */
    .document table,
    .document th,
    .document td { background: #fff !important; color: #111 !important; border-color: #ccc !important; }

    .document th { color: #555 !important; }
}

/* -- The two buttons halfway along a line: the condition, and removing it. Above the lines, below the tiles,
      so dragging a tile is never blocked by a button that happens to sit under the cursor. */
.pathcanvas-handles { position: absolute; inset: 0; pointer-events: none; }

.edge-handle {
    position: absolute;
    width: 16px;
    height: 16px;
    padding: 0;
    border: 0;
    border-radius: 4px;
    background: var(--surface);
    color: var(--muted);
    cursor: pointer;
    pointer-events: auto;
    display: grid;
    place-items: center;
    line-height: 0;
}

.edge-handle svg { width: 12px; height: 12px; fill: currentColor; }

.edge-handle:hover { color: var(--text); background: var(--surface-2); }

.edge-handle.bin:hover { color: var(--deviation); }

/* -- Tabbladen. Twee weergaven van hetzelfde, dus geen aparte pagina's: de keuze mag geen herlaadbeurt en geen
      nieuwe URL kosten. */
.tabs { display: flex; gap: 6px; align-items: center; margin-bottom: 12px; }

.tabs .tab {
    background: var(--surface);
    color: var(--muted);
    border: 1px solid var(--border);
    border-radius: 8px 8px 0 0;
    padding: 7px 14px;
    cursor: pointer;
    font-size: 13px;
}

.tabs .tab[aria-selected="true"] {
    color: var(--text);
    background: var(--surface-2);
    border-bottom-color: var(--surface-2);
}

/* Het tekenvlak is met de hoek te vergroten; de maat wordt bij de versie bewaard. */
.pathcanvas { resize: both; }

.pathcanvas.readonly { resize: none; }

/* -- Het contextmenu van de tekening. Op de pagina en niet in het canvas: binnen een vlak dat scrollt zou het
      meescrollen en aan de rand afgekapt worden. Boven 1000, want dat is de les van Leaflet. */
.canvasmenu {
    position: fixed;
    z-index: 1600;
    min-width: 200px;
    padding: 4px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 10px 30px rgb(0 0 0 / 45%);
    display: flex;
    flex-direction: column;
}

.canvasmenu button {
    background: none;
    border: 0;
    color: var(--text);
    text-align: left;
    padding: 7px 10px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
}

.canvasmenu button:hover { background: var(--surface); }

.canvasmenu button.danger:hover { color: var(--deviation); }

.canvasmenu-separator { height: 1px; background: var(--border); margin: 4px 6px; }

/* Een document dat ook naar papier gaat: wit met zwarte tekst, want dat is wat de PDF wordt en wat een klant
   in zijn mailbox ziet. Onze donkere opmaak eroverheen leggen zou betekenen dat het scherm iets anders toont
   dan het bestand dat je verstuurt - dezelfde fout die het bewijsdossier eerder maakte. */
.paper {
    background: #fff;
    color: #111;
    border-radius: var(--radius);
    padding: 24px 28px;
    box-shadow: var(--shadow);
    overflow-x: auto;
}

/* Expliciet zwart op alles binnen het vlak: de applicatie zet een lichte tekstkleur op body, en die erfde
   door in het document - lichtblauwe letters op wit, prima leesbaar op het scherm en vaag op papier. */
.paper, .paper p, .paper li, .paper td, .paper th, .paper h1, .paper h2, .paper h3, .paper em,
.paper strong, .paper pre { color: #111; }

.paper h1 { font-size: 22px; margin: 0 0 10px; }
.paper h2 { font-size: 16px; margin: 22px 0 8px; }
.paper h3 { font-size: 14px; margin: 16px 0 6px; }
.paper p { margin: 0 0 10px; max-width: 70ch; }
.paper code { background: #f2f2f2; color: #111; padding: 1px 4px; border-radius: 3px; }
.paper pre {
    background: #f7f7f7;
    border: 1px solid #ddd;
    border-radius: 4px;
    padding: 10px 12px;
    overflow-x: auto;
}
.paper table { width: 100%; border-collapse: collapse; margin: 0 0 14px; background: #fff; }
.paper th, .paper td { border: 1px solid #bbb; padding: 5px 8px; text-align: left; vertical-align: top; }
.paper th { background: #f0f0f0; color: #111; font-weight: 600; }
.paper .muted { color: #555; }

@media print {
    /* Alles wat niet in het document hoort valt weg, zodat Ctrl+P hetzelfde oplevert als de PDF-knop. */
    body > header, body > nav, .page-head, .help-panel, .help-backdrop,
    .no-print { display: none !important; }
    .paper { box-shadow: none; padding: 0; }
}

/* -- Proefloop: de telefoon ------------------------------------------------- */

/* Smal en donker met opzet: de vraag hoort te passen op een cabinescherm, en dat zie je niet in een tabel
   over de volle breedte. Dit is geen exacte kopie van de app - het gaat om de lengte van de tekst en de
   grootte van de knoppen. */
.phone {
    background: #0d1117;
    border: 10px solid #23262b;
    border-radius: 26px;
    overflow: hidden;
    box-shadow: var(--shadow);
}

.phone-bar {
    background: var(--accent);
    color: #fff;
    padding: 10px 14px;
    font-weight: 600;
    font-size: 13px;
}

.phone-body { padding: 16px 14px 6px; min-height: 260px; }

.phone-question { font-size: 17px; line-height: 1.35; margin: 4px 0 16px; color: #f2f4f7; }

.phone-button {
    display: block;
    width: 100%;
    margin: 0 0 10px;
    padding: 14px 12px;
    font-size: 16px;
    border: 0;
    border-radius: 10px;
    background: var(--accent);
    color: #fff;
    cursor: pointer;
}

.phone-button:hover { filter: brightness(1.08); }

.phone-skip {
    display: block;
    width: 100%;
    margin: 4px 0 10px;
    padding: 10px;
    font-size: 14px;
    background: transparent;
    color: var(--text-dim);
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
}

.phone-input {
    width: 100%;
    padding: 12px;
    font-size: 16px;
    margin: 0 0 12px;
    border-radius: 10px;
    border: 1px solid var(--border);
    background: #161b22;
    color: #f2f4f7;
}

.phone-hint { font-size: 12px; color: var(--text-dim); margin: 8px 0 0; }
.phone-none { color: var(--text-dim); font-size: 14px; }
.phone-done { color: var(--done, #3fb950); font-size: 15px; }
.phone-restart { padding: 8px 14px 14px; }

/* De stoplijst en de stop in de proefloop-telefoon. */
.phone-stop {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    margin: 0 0 8px;
    padding: 10px 12px;
    background: #161b22;
    color: #f2f4f7;
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
    font-size: 15px;
}

.phone-stop:hover { border-color: var(--accent); }
.phone-stop.settled { opacity: 0.6; }

.phone-stop-number {
    flex: 0 0 26px;
    height: 26px;
    line-height: 26px;
    text-align: center;
    border-radius: 50%;
    background: var(--accent);
    color: #fff;
    font-size: 13px;
}

.phone-stop-name { display: block; }
.phone-stop-name small { display: block; color: var(--text-dim); font-size: 12px; }

.phone-path { color: var(--text-dim); font-size: 12px; margin: 0 0 8px; text-transform: uppercase; }
.phone-status { color: var(--text-dim); font-size: 13px; margin: 0 0 8px; }
.phone-task { color: #f2f4f7; font-size: 14px; margin: 0 0 4px; }
.phone-task.done { color: var(--text-dim); text-decoration: line-through; }

/* Een weigering is geen foutmelding van de applicatie maar een antwoord van de app aan de chauffeur. */
.phone-refusal {
    background: rgba(210, 90, 90, 0.15);
    border: 1px solid rgba(210, 90, 90, 0.5);
    border-radius: 8px;
    padding: 8px 10px;
    font-size: 14px;
    color: #f2b8b8;
    margin: 0 0 12px;
}

/* App installeren (Apparaten) en de badgekaart (Chauffeurs): een QR heeft een witte rustzone nodig, ook in
   het donkere thema - anders leest een camera hem niet. */
.install { display: flex; gap: 18px; align-items: center; flex-wrap: wrap; }
.install-qr, .qr-box { background: #fff; padding: 10px; border-radius: var(--radius); line-height: 0; }
.install-qr svg, .qr-box svg { width: 200px; height: 200px; }
.install-info { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.install-info a { word-break: break-all; }
.install-version { font-size: 15px; font-weight: 600; }
.install-actions { display: flex; gap: 8px; flex-wrap: wrap; }
