/*
  Admin styling, on a Google Cloud Console footing: a full-width top bar, a left navigation rail of
  icon-and-label rows with a pill on the active one, and content as bordered cards on a grey plane.

  The density of the old sheet is kept deliberately. Dispatchers and HR read these screens for
  hours, and Google's own console is dense for the same reason — the Material influence here is in
  the surfaces, the elevation and the interaction states, not in padding everything out to twice the
  height. Colour still means something: it is reserved for state that changes a decision.
*/

:root {
    color-scheme: light;

    /* Google's neutral ramp. --bg is the plane the cards sit on, --surface the cards themselves;
       the console's whole look rests on that pair being different, which the previous grey-on-grey
       did not commit to. */
    --bg: #f2f4f6;
    --surface: #ffffff;
    --surface-2: #f5f7f9;
    --border: #e7e9ee;
    --border-soft: #eef1f4;
    --text: #1c2632;
    --text-2: #3a4553;
    --muted: #6b7482;
    --faint: #98a0ac;
    --navy: #1b2b4b;

    /* FieldOps teal (the console design): accent, its pressed step, and the wash behind a selected
       rail row or a hovered row in a list. */
    --accent: #0aa294;
    --accent-hover: #088a7e;
    --accent-press: #07766c;

    /* The wash behind a selected nav row and a hovered blue control. Not a tint of --accent
       computed at runtime: Google's is a specific step, and colour-mixing toward white lands
       somewhere greyer. */
    --accent-wash: #e4f7f4;
    --accent-wash-2: #c6efe9;
    --hover-wash: #f5f7f9;

    --ok-bg: #e7f6ec;
    --ok-fg: #12a150;
    --warn-bg: #fbeed4;
    --warn-fg: #b8770f;
    --danger-bg: #fdeaea;
    --danger-fg: #d64545;

    /* Field-duty states, one colour each wherever a person's state is drawn: pill, pin, bar. */
    --st-moving: #12a150;  --st-moving-bg: #e7f6ec;
    --st-idle: #d9911f;    --st-idle-bg: #fbeed4;
    --st-break: #3b73d6;   --st-break-bg: #e6eefb;
    --st-lost: #d64545;    --st-lost-bg: #fdeaea;
    --st-done: #8a8f9c;    --st-done-bg: #eef0f3;

    --font: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;

    /* Two radii, not one. Google uses a small radius on controls and a larger one on surfaces;
       a single value makes buttons look like cards or cards look like buttons. */
    --radius: 14px;
    --radius-sm: 9px;
    --radius-pill: 999px;

    /* Material elevation: a tight contact shadow plus a wider ambient one. A single blurred
       shadow reads as a drop shadow rather than as height. */
    --elev-1: 0 1px 2px 0 rgba(60, 64, 67, .3), 0 1px 3px 1px rgba(60, 64, 67, .15);
    --elev-2: 0 1px 2px 0 rgba(60, 64, 67, .3), 0 2px 6px 2px rgba(60, 64, 67, .15);

    --topbar-height: 57px;
    --sidebar-width: 224px;

    --ease: cubic-bezier(.2, 0, 0, 1);
    --fast: 120ms;
    --slow: 220ms;

    /* ---- Chart ink -------------------------------------------------------
       Kept apart from the chip tokens above. Those are text colours on a tinted pill; these are
       fills on a card, and a colour legible as 12px text is too dark as a 200px bar.

       Validated against these surfaces (#ffffff light, #292a2d dark), not eyeballed and not
       inherited from the old palette — the dark surface changed with this theme, so the whole set
       was re-run:

         light  good/warn/critical  CVD dE 21.5, normal-vision 25.5, all >= 3:1
         dark   good/warn/critical  CVD dE  8.1, normal-vision 17.7, all >= 3:1

       --viz-accent is Google blue on light. Its dark step is Blue 500 rather than the #8ab4f8 the
       UI chrome uses: that one measures L 0.766, well outside the legible band for a mark, even
       though it is correct for text and icons.

       --viz-warn is below 3:1 on the light surface. Amber has nowhere else to sit, and it carries
       an obligation: every chart using it ships a visible label AND a table view. Both are present
       on every panel in Dashboard.razor. Do not reuse this token where that is not true. */
    --viz-accent: #0aa294;
    --viz-good: #12a150;
    --viz-warn: #d9911f;
    --viz-critical: #d64545;
    --viz-grid: #eceef2;
    --viz-track: #f2f4f6;
}

/* The dark palette, applied when <html data-theme="dark"> is set. Which one is set is the viewer's
   Appearance choice (Profile), the same four the app offers: day and night, follow the device,
   always light, always dark — resolved by the script at the top of App.razor, before first paint,
   on every page including sign-in. */
:root[data-theme="dark"] {
    color-scheme: dark;

    --bg: #121a26;
    --surface: #1a2433;
    --surface-2: #223043;
    --border: #2c3a4f;
    --border-soft: #243246;
    --text: #e6ebf2;
    --text-2: #c3cddb;
    --muted: #93a0b3;
    --faint: #6f7c90;
    --navy: #e6ebf2;

    --accent: #2fc4b3;
    --accent-hover: #4dd3c3;
    --accent-press: #6fdfd1;
    --accent-wash: #123a37;
    --accent-wash-2: #17504b;
    --hover-wash: #223043;

    --ok-bg: #173826;
    --ok-fg: #4cc47f;
    --warn-bg: #3d2f17;
    --warn-fg: #f0b44c;
    --danger-bg: #3d1f22;
    --danger-fg: #f07a7a;

    --st-moving: #3fbf74;  --st-moving-bg: #173826;
    --st-idle: #f0a93b;    --st-idle-bg: #3d2f17;
    --st-break: #6d9cf0;   --st-break-bg: #1c2c4a;
    --st-lost: #f07a7a;    --st-lost-bg: #3d1f22;
    --st-done: #9aa3b2;    --st-done-bg: #28323f;

    /* Shadows do not read on a dark plane, so elevation switches channel: the card border
       lightens instead. Same job, different medium. */
    --elev-1: 0 1px 2px 0 rgba(0, 0, 0, .6), 0 1px 3px 1px rgba(0, 0, 0, .3);
    --elev-2: 0 1px 3px 0 rgba(0, 0, 0, .6), 0 4px 8px 3px rgba(0, 0, 0, .3);

    --viz-accent: #2fc4b3;
    --viz-good: #3fbf74;
    --viz-warn: #f0a93b;
    --viz-critical: #f07a7a;
    --viz-grid: #2c3a4f;
    --viz-track: #223043;
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);

    /* Google Sans if the machine happens to have it, Roboto next, then the platform UI face.
       Deliberately not a webfont link: this console runs on a test LAN with no route to
       fonts.googleapis.com, and a blocked font request costs a render delay and then falls back
       here anyway. */
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

/* ---- Top bar ------------------------------------------------------------
   The console design: white, one hairline below, the FieldOps mark and name with the organisation
   beside it after a rule, a "Live" pill on screens that refresh themselves, and the signed-in person
   on the right with Sign out as a teal link. */

.topbar {
    position: sticky; top: env(safe-area-inset-top, 0); z-index: 30;
    height: var(--topbar-height); flex-shrink: 0;
    display: flex; align-items: center; gap: 14px;
    padding: 0 20px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
}

.topbar-brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.brand-logo { width: 30px; height: 30px; flex-shrink: 0; display: block; }
.brand-name { font-weight: 600; font-size: 17px; color: var(--navy); letter-spacing: 0; }
.brand-name b { color: var(--accent); font-weight: 600; }
.brand-org {
    font-size: 11px; color: var(--muted);
    border-left: 1px solid var(--border); padding-left: 12px; margin-left: 2px;
}

/* Hidden until a screen that refreshes itself says so (window.fieldopsLive.mark in App.razor). */
.live-pill {
    margin-left: 20px;
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 12.5px; color: var(--muted);
    background: var(--surface-2); padding: 6px 11px; border-radius: var(--radius-pill);
}
.live-pill[hidden] { display: none; }
.live-pill b { color: var(--text-2); margin-left: 2px; font-weight: 600; font-variant-numeric: tabular-nums; }

.pulse {
    width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
    background: var(--st-moving);
    box-shadow: 0 0 0 0 rgba(18, 161, 80, .5);
    animation: pulse 2s infinite;
}

@keyframes pulse {
    70% { box-shadow: 0 0 0 7px rgba(18, 161, 80, 0); }
    100% { box-shadow: 0 0 0 0 rgba(18, 161, 80, 0); }
}

.topbar-spacer { flex: 1; }
.topbar-actions { display: flex; align-items: center; gap: 14px; color: var(--text-2); font-size: 13.5px; }

.topbar-user {
    display: flex; align-items: center; gap: 8px;
    font-size: 13.5px; color: var(--text-2);
    max-width: 40ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- Account menu ----
   The avatar (with the name beside it, on a wide screen) is the one account control; it opens a
   small menu with the person, Profile and Sign out. */

.account { position: relative; }
.account > summary { list-style: none; }
.account > summary::-webkit-details-marker { display: none; }

.account-trigger {
    display: flex; align-items: center; gap: 10px;
    padding: 4px 6px 4px 12px; border-radius: var(--radius-pill);
    cursor: pointer; user-select: none;
    transition: background var(--fast) var(--ease);
}
.account-trigger:hover, .account[open] > .account-trigger { background: var(--surface-2); }
.account-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.account-caret {
    fill: none; stroke: var(--muted); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
    transition: transform var(--fast) var(--ease);
}
.account[open] .account-caret { transform: rotate(180deg); }

.account-menu {
    position: absolute; right: 0; top: calc(100% + 8px); z-index: 50;
    width: 260px; padding: 6px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 16px 36px -14px rgba(16, 24, 40, .32);
    animation: fade-in var(--fast) var(--ease) both;
}

.account-head {
    display: flex; align-items: center; gap: 11px;
    padding: 10px 10px 12px; margin-bottom: 4px;
    border-bottom: 1px solid var(--border-soft);
}
.avatar-lg { width: 38px; height: 38px; font-size: 14px; }
.account-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.account-who strong { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-who span { font-size: 12px; color: var(--muted); }

.account-menu form { margin: 0; }

.content .account-item, .account-item {
    display: flex; align-items: center; gap: 11px; width: 100%;
    padding: 9px 10px; border: 0; border-radius: 8px;
    background: none; color: var(--text-2);
    font: inherit; font-size: 13.5px; font-weight: 500; text-align: left; text-decoration: none;
    cursor: pointer;
}
.account-item:hover { background: var(--surface-2); }
.account-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.account-item .nav-icon { color: var(--faint); }
.account-item.danger { color: var(--danger-fg); }
.account-item.danger .nav-icon { color: var(--danger-fg); }
.account-item.danger:hover { background: var(--danger-bg); }

/* The signed-in person's initials, as a round teal chip. */
.avatar {
    width: 30px; height: 30px; border-radius: var(--radius-pill);
    background: var(--accent-wash); color: var(--accent);
    display: grid; place-items: center;
    font-size: 12px; font-weight: 600; flex-shrink: 0;
    text-transform: uppercase;
}

/* ---- Shell --------------------------------------------------------------- */

.app { display: flex; flex-direction: column; min-height: 100vh; }
.shell { display: flex; flex: 1; min-height: 0; align-items: stretch; }

.sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    background: var(--surface);
    border-right: 1px solid var(--border);
    padding: 16px 12px;
    display: flex;
    flex-direction: column;

    position: sticky; top: var(--topbar-height); align-self: flex-start;
    height: calc(100vh - var(--topbar-height));
    overflow-y: auto;
}

.content { flex: 1; padding: 20px 24px 40px; min-width: 0; max-width: 1360px; overflow-x: auto; }

/* ---- Navigation ----------------------------------------------------------
   Grouped under small uppercase captions, no rules between groups. Every link is gated on its own
   permission, so a group whose items are all hidden hides its caption too — MainLayout decides. */

.nav-group-label {
    padding: 14px 10px 8px;
    font-size: 10.5px; font-weight: 600;
    text-transform: uppercase; letter-spacing: .12em;
    color: var(--faint);
}

.nav-link {
    display: flex; align-items: center; gap: 11px;
    padding: 8px 11px; margin-bottom: 1px;
    border-radius: var(--radius-sm);
    color: var(--text-2); text-decoration: none;
    font-size: 13.5px; font-weight: 500;
    transition: background var(--fast) var(--ease), color var(--fast) var(--ease);
}

.nav-link:hover:not(.active) { background: var(--surface-2); }

.nav-link.active { background: var(--accent-wash); color: var(--accent); }
.nav-link.active .nav-icon { color: var(--accent); }

.nav-link:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* Stroked, inheriting the row's colour so the active row recolours glyph and label together. */
.nav-icon {
    width: 16px; height: 16px; flex-shrink: 0;
    color: var(--faint);
    stroke: currentColor; fill: none;
    stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
    transition: color var(--fast) var(--ease);
}

/* Count of alerts nobody has marked seen. */
.nav-badge {
    margin-left: auto;
    font-size: 10px; font-weight: 700; line-height: 1.5;
    background: var(--st-lost); color: #fff;
    padding: 1px 6px; border-radius: var(--radius-pill);
}

/* ---- Type ---------------------------------------------------------------- */

h1 { font-size: 22px; font-weight: 600; margin: 0; letter-spacing: 0; }
h2 { font-size: 16px; font-weight: 500; margin: 0 0 12px; }
h3 { font-size: 11px; margin: 20px 0 8px; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; font-weight: 500; }
.subtitle { margin: 5px 0 0; color: var(--muted); font-size: 13.5px; max-width: 70ch; }
.muted { color: var(--muted); }
.small { font-size: 12px; }

.page-header {
    display: flex; justify-content: space-between; align-items: flex-end;
    gap: 10px; flex-wrap: wrap; margin-bottom: 16px;
}

/* ---- Cards --------------------------------------------------------------- */

.panel {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 20px; min-width: 260px;
    transition: box-shadow var(--slow) var(--ease), border-color var(--slow) var(--ease);
}

.panel.grow { flex: 1; }

/* Opt-in. A card that lifts on hover claims to be clickable, so only the ones that are — a page of
   reacting cards is noise. */
.panel-interactive:hover { box-shadow: var(--elev-1); border-color: transparent; }

.split { display: flex; gap: 20px; align-items: flex-start; flex-wrap: wrap; }

/* A page-header that follows content is a new section, not the top of the page, and needs to be
   separated from what it comes after. Without this the heading sits directly against the panel
   above it and reads as belonging to that panel rather than introducing the next one. */
.split + .page-header,
.panel + .page-header { margin-top: 28px; }

/* ---- Tables -------------------------------------------------------------- */

.grid {
    width: 100%; border-collapse: collapse; background: var(--surface);
    border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
}

.grid th, .grid td { padding: 12px 16px; text-align: left; border-bottom: 1px solid var(--border); vertical-align: top; }

.grid th {
    font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: .08em;
    color: var(--muted); background: var(--surface-2);
}

.grid tbody tr { transition: background var(--fast) var(--ease); }
.grid tbody tr:hover { background: var(--surface-2); }
.grid tbody tr:last-child td { border-bottom: none; }
.grid td.num, .grid th.num { text-align: right; font-variant-numeric: tabular-nums; }
.row-attention { background: color-mix(in srgb, var(--warn-bg) 55%, transparent); }

/* ---- Chips --------------------------------------------------------------- */

.chip {
    display: inline-flex; align-items: center; padding: 3px 10px;
    border-radius: var(--radius-pill);
    background: var(--surface-2); border: 1px solid var(--border);
    font-size: 12px; font-weight: 500; margin-right: 4px; white-space: nowrap;
}

.chip-ok, .chip-live { background: var(--ok-bg); color: var(--ok-fg); border-color: transparent; }
.chip-warn { background: var(--warn-bg); color: var(--warn-fg); border-color: transparent; }
.chip-danger, .chip-stale { background: var(--danger-bg); color: var(--danger-fg); border-color: transparent; }

/* ---- Buttons ------------------------------------------------------------
   Material proportions: 36px tall, 4px radius, medium weight, letter-spaced. The wash on hover is
   an overlay rather than a different background colour, which is what keeps a hovered outlined
   button and a hovered filled button feeling like the same gesture. */

.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    min-height: 36px; padding: 0 14px;
    border-radius: var(--radius-sm); border: 1px solid var(--border);
    background: var(--surface); color: var(--text-2);
    cursor: pointer; font: inherit; font-size: 13px; font-weight: 600;
    text-decoration: none;
    transition: background var(--fast) var(--ease), box-shadow var(--fast) var(--ease),
                border-color var(--fast) var(--ease);
}

.btn svg { flex-shrink: 0; }
.btn:hover { background: var(--surface-2); }
.btn:active:not(:disabled) { background: var(--accent-wash); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.btn-primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn-primary:active:not(:disabled) { background: var(--accent-press); }

/* Dark mode's teal is light enough that white on it fails contrast; the label takes the plane. */
:root[data-theme="dark"] .btn-primary { color: #0d1a1f; }

.btn:disabled, .btn-primary:disabled { opacity: .5; cursor: default; box-shadow: none; }

.btn-link {
    background: none; border: none; padding: 0; height: auto; cursor: pointer;
    color: var(--accent); font-size: 13px; font-weight: 500; text-align: left;
}

.btn-link:hover { background: none; text-decoration: underline; }

td.actions { white-space: nowrap; }
.actions-bar { display: flex; align-items: center; gap: 12px; margin-top: 20px; flex-wrap: wrap; }

/* ---- Lists --------------------------------------------------------------- */

.list { list-style: none; margin: 0; padding: 0; }

.list-item {
    /* align-items matters here: a column flexbox stretches its children to full width by default,
       which turned every chip in a list row into a full-width bar. They size to their content. */
    display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
    width: 100%; text-align: left;
    padding: 10px 12px; border: none; background: none; color: inherit;
    border-radius: var(--radius-sm); cursor: pointer; font: inherit;
    transition: background var(--fast) var(--ease);
}

.list-item:hover { background: var(--hover-wash); }
.list-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.list-item.selected { background: var(--accent-wash); color: var(--accent); font-weight: 500; }
.list-item.selected .muted { color: var(--accent); opacity: .8; }

.permission-grid { display: grid; gap: 6px; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.permission { display: flex; gap: 8px; align-items: flex-start; padding: 8px; border-radius: var(--radius-sm); }
.permission:hover { background: var(--hover-wash); }
.permission.sensitive { border-left: 3px solid var(--warn-fg); }
.permission code { display: block; font-size: 11px; color: var(--muted); }

/* ---- Notices ------------------------------------------------------------- */

.notice {
    background: var(--warn-bg); color: var(--warn-fg);
    padding: 12px 16px; border-radius: var(--radius-sm); margin: 0 0 16px;
    font-size: 13px;
}

.notice-error { background: var(--danger-bg); color: var(--danger-fg); }

/* ---- Forms --------------------------------------------------------------
   Declared on the elements so a form picks this up by existing, rather than by remembering a
   class. The focus ring is a doubled border rather than an outline, which is how Material marks
   an active field without shifting the layout by a pixel. */

input[type="text"], input[type="email"], input[type="tel"], input[type="search"],
input[type="number"], input[type="date"], input[type="time"], input[type="password"],
select, textarea, .date-input {
    padding: 9px 12px; border-radius: var(--radius-sm);
    border: 1px solid var(--border); background: var(--surface);
    color: var(--text); font: inherit; font-size: 14px;
    transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}

input:hover:not(:disabled), select:hover:not(:disabled), textarea:hover:not(:disabled) {
    border-color: var(--muted);
}

input:disabled, select:disabled, textarea:disabled {
    background: var(--surface-2); color: var(--muted); cursor: not-allowed;
}

input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--accent);
    box-shadow: inset 0 0 0 1px var(--accent);
}

/* A filter bar and a form row are both written as .filters, but they are not the same thing, and
   the difference is visible in the markup: a bar holds bare controls, a form row wraps each in a
   label. Keying on that lets the date bar keep its inline shape while a form row becomes a proper
   grid — caption above its control, which is what makes a form scannable in a column. */

.filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.filters:has(> label) { align-items: end; gap: 12px 16px; }

.filters > label {
    display: flex; flex-direction: column; gap: 6px;
    flex: 1 1 220px; min-width: 0;
    font-size: 12px; color: var(--muted); font-weight: 500;
}

.filters > label > input,
.filters > label > select,
.filters > label > textarea { width: 100%; }

.filters + .filters { margin-top: 12px; }

/* ---- Sign-in ------------------------------------------------------------
   Centred single-column card on a bare layout. No navigation, because nothing is reachable yet —
   a sidebar of links that all bounce back here is worse than no sidebar. */

.bare {
    min-height: 100vh; display: flex; align-items: center; justify-content: center;
    padding: 24px; background: var(--bg);
}

.signin {
    width: 100%; max-width: 400px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 40px;
    box-shadow: var(--elev-1);
}

.appearance { border: 0; padding: 0; margin: 0 0 14px; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.appearance legend { width: 100%; margin-bottom: 6px; font-size: 12px; font-weight: 500; color: var(--muted); }
.appearance label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }

.signin .brand { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }

/* Stacks "FieldOps" over "KeenMinds" beside the mark. Scoped to the sign-in card: the top bar
   sets its own name out on one line, and a global rule here would break that. */
.signin .brand > span { display: flex; flex-direction: column; line-height: 1.25; }
.signin h1 { margin: 16px 0 24px; font-size: 24px; font-weight: 400; }
.signin label { display: block; margin-bottom: 18px; font-size: 12px; color: var(--muted); font-weight: 500; }

.signin input[type="text"],
.signin input[type="password"] {
    display: block; width: 100%; margin-top: 6px; padding: 12px 14px; font-size: 15px;
}

.signin .btn { width: 100%; margin-top: 8px; height: 40px; font-size: 15px; }
.signin p.muted { margin-top: 20px; }
.sso-divider { display: flex; align-items: center; gap: 10px; margin: 18px 0 12px; color: var(--muted); font-size: 12px; }
.sso-divider::before, .sso-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.signin .sso-btn { display: flex; align-items: center; justify-content: center; width: 100%; margin-top: 8px; height: 40px; text-decoration: none; }

#blazor-error-ui {
    display: none; position: fixed; bottom: 0; left: 0; right: 0;
    background: var(--danger-bg); color: var(--danger-fg); padding: 14px 20px; z-index: 1000;
    box-shadow: var(--elev-2);
}

#blazor-error-ui .dismiss { cursor: pointer; float: right; }

/* ---- Trip route map ------------------------------------------------------ */

.row-map > td { padding: 0 0 14px; background: var(--surface-2); }

.trip-map-canvas {
    height: 420px; width: 100%;
    border: 1px solid var(--border); border-radius: var(--radius);
}

/* Mapbox draws into an absolutely positioned child; without an explicit height on an empty
   container the panel collapses and the map renders zero pixels tall. */
.trip-map-canvas:empty { background: var(--surface); }

.trip-map-key { display: flex; align-items: center; gap: 8px; margin: 8px 2px 0; }
.key-swatch { display: inline-block; width: 22px; height: 0; border-top-width: 3px; }
.key-swatch:not(:first-child) { margin-left: 14px; }
.key-route { border-top-style: solid; border-top-color: var(--viz-accent); }
.key-raw { border-top-style: dashed; border-top-color: var(--muted); }

/* ---- Live dispatch map --------------------------------------------------- */

.live-map { margin-bottom: 16px; }

.live-map-canvas {
    height: 460px; width: 100%;
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--surface);
}

.live-map-key {
    display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px;
    margin: 8px 2px 0; font-size: 13px; color: var(--muted);
}

/* A filled circle rather than a line: it matches the marker shape, and the trip map's key already
   uses lines for the two routes. Two keys on one console meaning different things by the same
   swatch is how a stale pin gets read as a matched route. */
.pin-swatch { display: inline-block; width: 10px; height: 10px; border-radius: var(--radius-pill); }
.pin-live { background: var(--ok-fg); }
.pin-stale { background: var(--warn-fg); }

.refresh-note { margin: 0 2px 12px; }

/* The engineer's name as a control. Styled to read as the name it already was rather than as a
   button — the row is a list of people, and turning one column into a toolbar would say the name
   matters less than the action. The affordance arrives on hover and focus instead. */
.btn-name {
    padding: 0; border: 0; background: none; font: inherit; color: inherit;
    cursor: pointer; text-align: left;

    /* Replaces the whitespace the markup used to carry between the name and the employee code.
       A button is an element, not a text node, so the space either side of it is collapsed away
       and the two run together as "Test EngineerENG001". */
    margin-right: 5px;
}

.btn-name:hover strong { text-decoration: underline; text-underline-offset: 2px; }
.btn-name:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* Ties the row to the trace currently on the map, so a dispatcher looking at a route can see whose
   it is without reading the note above the table. */
.row-selected > td { background: var(--surface-2); }

/* Summary beside timeline, because they are read together — "42 km over 3 hours" means little
   without the stops that account for the gap. Collapses to one column on a narrow window rather
   than squeezing two tables into half a screen each. */
.tracking-panel {
    display: grid; grid-template-columns: minmax(280px, 1fr) minmax(320px, 1.2fr);
    gap: 16px; margin: 0 0 16px;
}

@media (max-width: 1100px) {
    .tracking-panel { grid-template-columns: 1fr; }
}

.tracking-panel > div {
    border: 1px solid var(--border); border-radius: var(--radius);
    background: var(--surface); padding: 14px 16px;
}

.tracking-panel h3 { margin: 0 0 10px; }

/* The timeline can run long on a busy day; it scrolls inside its own panel rather than pushing
   the engineer table off the bottom of the page. */
.tracking-timeline { max-height: 420px; overflow-y: auto; }

.grid.compact td, .grid.compact th { padding: 5px 8px; font-size: 13px; }
.grid.compact td:first-child { color: var(--muted); }

/* Mapbox popups carry their own white background and dark text. Left alone they are unreadable in
   dark mode, and they are the only part of the console the theme does not otherwise reach.

   Qualified by the map container rather than written bare. The SDK's stylesheet is injected into
   <head> at runtime, which puts it *after* this file — a bare .mapboxgl-popup-content here has
   equal specificity and loses the cascade to whichever rule the CDN happens to ship. */
.live-map .mapboxgl-popup-content,
.trip-map .mapboxgl-popup-content {
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border); border-radius: var(--radius-sm);
    box-shadow: var(--elev-1); padding: 10px 12px;
}

.live-map .mapboxgl-popup-anchor-top .mapboxgl-popup-tip,
.trip-map .mapboxgl-popup-anchor-top .mapboxgl-popup-tip { border-bottom-color: var(--surface); }

.live-map .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip,
.trip-map .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip { border-top-color: var(--surface); }

.live-map .mapboxgl-popup-anchor-left .mapboxgl-popup-tip,
.trip-map .mapboxgl-popup-anchor-left .mapboxgl-popup-tip { border-right-color: var(--surface); }

.live-map .mapboxgl-popup-anchor-right .mapboxgl-popup-tip,
.trip-map .mapboxgl-popup-anchor-right .mapboxgl-popup-tip { border-left-color: var(--surface); }

.live-map .mapboxgl-popup-close-button,
.trip-map .mapboxgl-popup-close-button { color: var(--muted); }

.map-popup { display: flex; flex-direction: column; gap: 2px; font-size: 13px; line-height: 1.4; }
.map-popup span { color: var(--muted); }

/* ---- Claim route --------------------------------------------------------- */

.claim-route { padding: 14px 16px 0; }

.distance-strip {
    display: flex; flex-wrap: wrap; gap: 12px;
    margin-bottom: 12px;
}

.distance-figure {
    display: flex; flex-direction: column; gap: 2px;
    flex: 1 1 180px; min-width: 160px;
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 12px 14px;
}

.distance-figure strong { font-size: 20px; font-weight: 500; }

.distance-label {
    font-size: 11px; color: var(--muted);
    text-transform: uppercase; letter-spacing: .08em;
}

.text-danger { color: var(--danger-fg); }

.claim-route-flags {
    display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px;
    margin: 0 0 12px;
}

/* ---- Claim rejection ----------------------------------------------------- */

.reject-panel { padding: 12px 2px 16px; }
.reject-panel label { display: block; max-width: 560px; font-size: 12px; color: var(--muted); font-weight: 500; }
.reject-panel input { margin-top: 6px; }
.reject-panel .actions-bar { margin-top: 10px; }

/* ---- Dashboard -----------------------------------------------------------
   Auto-fit rather than a fixed column count, so the grid reflows on a laptop without a media query
   per breakpoint. */

.kpi-row {
    display: grid; gap: 16px; margin-bottom: 20px;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.stat-tile {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: var(--radius); padding: 20px;
    display: flex; flex-direction: column; gap: 4px;
    transition: box-shadow var(--slow) var(--ease), border-color var(--slow) var(--ease);
}

a.stat-tile { text-decoration: none; color: inherit; }
a.stat-tile:hover { box-shadow: var(--elev-1); border-color: transparent; }
a.stat-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.stat-label { font-size: 12px; color: var(--muted); font-weight: 500; }

/* Proportional figures, not tabular. Tabular gives every digit the width of a zero, which makes a
   short number like 121 look gappy at display sizes. The grids above turn it back on, because
   there the digits must line up. */
.stat-value { font-size: 32px; font-weight: 400; line-height: 1.2; letter-spacing: -.02em; }

.stat-foot { font-size: 12px; color: var(--muted); }
.stat-foot.is-critical { color: var(--danger-fg); }
.stat-foot.is-warn { color: var(--warn-fg); }

.dash-grid {
    display: grid; gap: 16px; align-items: start;
    grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
}

.panel-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 4px; }
.panel-head h2 { margin: 0; }
.panel-note { font-size: 12px; color: var(--muted); margin: 0 0 16px; }

/* ---- Charts -------------------------------------------------------------
   Hand-rolled SVG. No charting library and no CDN, so the console keeps working on an air-gapped
   LAN, and the marks inherit the tokens above — which is what makes dark mode free rather than a
   second palette to maintain. */

.chart { display: block; width: 100%; overflow: visible; }
.chart-grid-line { stroke: var(--viz-grid); stroke-width: 1; }
.chart-axis { stroke: var(--border); stroke-width: 1; }

/* Axis and value text wears ink tokens, never the series colour. A light amber is a legible bar
   and an illegible word. */
.chart-tick { fill: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart-label { fill: var(--text); font-size: 11px; font-weight: 500; }

.chart-line { fill: none; stroke: var(--viz-accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart-area { fill: var(--viz-accent); opacity: .10; }
.chart-dot { fill: var(--viz-accent); stroke: var(--surface); stroke-width: 2; }

/* The hit target, deliberately larger than the mark it covers. An 8px dot you must land on
   dead-centre is not a hover target. */
.chart-hit { fill: transparent; cursor: pointer; }
.chart-hit:hover + .chart-dot, .chart-hit:focus-visible + .chart-dot { r: 5.5; }

.chart-empty {
    display: grid; place-items: center; min-height: 120px;
    color: var(--muted); font-size: 13px; text-align: center; padding: 12px;
}

/* ---- Stacked status bar --------------------------------------------------
   The 2px gap is the separator, and it is the surface colour showing through rather than a stroke
   — a border around each segment would add ink that is not data, and at this bar height it would
   swallow a thin segment whole. */

.stack {
    display: flex; gap: 2px; height: 32px;
    border-radius: var(--radius-sm); overflow: hidden; background: var(--surface);
}

.stack-seg {
    flex-basis: 0; min-width: 3px;
    display: grid; place-items: center;
    transition: opacity var(--fast) var(--ease);
}

.stack-seg:hover { opacity: .82; }
.stack-seg:first-child { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.stack-seg:last-child { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.stack-seg:only-child { border-radius: var(--radius-sm); }

/* The one place text may sit on a data colour — and the colour is picked by the fill's luminance
   so it always clears contrast, rather than being white by default and unreadable on the amber. */
.stack-seg-label { font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; }
.seg-good .stack-seg-label, .seg-critical .stack-seg-label { color: #fff; }
.seg-warn .stack-seg-label { color: #202124; }

/* Segment tones are set as background, not fill: the stacked bar is built from divs rather than
   SVG so its labels can use real text layout. The legend keys reuse the same classes, which keeps
   a swatch and its segment the same colour by construction rather than by two rules agreeing. */
.seg-good { background: var(--viz-good); }
.seg-warn { background: var(--viz-warn); }
.seg-critical { background: var(--viz-critical); }
.seg-empty { background: var(--viz-track); }

/* ---- Legend & table view -------------------------------------------------
   Both are mandatory, not decorative. The legend is the identity channel for any chart with two or
   more series; the table is the accessible twin that makes every plotted value readable without
   relying on colour at all. */

.legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 14px; }
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.legend-key { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.legend-value { color: var(--text); font-variant-numeric: tabular-nums; font-weight: 500; }

.table-view { margin-top: 14px; }

.table-view summary {
    cursor: pointer; font-size: 12px; color: var(--accent); font-weight: 500;
    padding: 6px 8px; border-radius: var(--radius-sm); list-style-position: inside;
    transition: background var(--fast) var(--ease);
}

.table-view summary:hover { background: var(--accent-wash); }
.table-view summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.table-view .grid { margin-top: 8px; }
.table-view .grid th, .table-view .grid td { padding: 8px 12px; font-size: 12px; }
.table-view .grid td.num { font-variant-numeric: tabular-nums; }

/* ---- Loading ------------------------------------------------------------
   A shimmering block the shape of the content it replaces, so the page does not jump when the data
   lands. */

.skeleton {
    background: linear-gradient(90deg, var(--surface-2) 25%, var(--border) 50%, var(--surface-2) 75%);
    background-size: 200% 100%;
    animation: skeleton-slide 1.4s var(--ease) infinite;
    border-radius: var(--radius);
}

.skeleton-line { height: 12px; margin-bottom: 8px; }
.skeleton-tile { height: 104px; }
.skeleton-chart { height: 150px; }

@keyframes skeleton-slide {
    from { background-position: 200% 0; }
    to { background-position: -200% 0; }
}

/* Content arriving after a fetch fades rather than snapping in. */
.fade-in { animation: fade-in var(--slow) var(--ease) both; }

@keyframes fade-in {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: none; }
}

/* ---- Navigation drawer ---------------------------------------------------
   The state checkbox and the menu button. Both exist at every width; only the button and the
   scrim are hidden above the breakpoint, so the same markup serves a desk and a phone. */

.nav-state {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

.nav-toggle {
    display: none;
    width: 40px; height: 40px; flex-shrink: 0;
    align-items: center; justify-content: center;
    margin-right: 4px; border-radius: var(--radius-sm);
    color: var(--text); cursor: pointer;
}

.nav-toggle:hover { background: var(--surface-2); }

/* The focus ring belongs on the thing the eye sees, not on the hidden input carrying the state. */
.nav-state:focus-visible ~ .topbar .nav-toggle { outline: 2px solid var(--accent); outline-offset: 1px; }

.nav-scrim { display: none; }

/* ---- Narrow --------------------------------------------------------------
   Everything the console does at full width, it does here. Nothing is dropped for being on a
   phone: an administrator holding one is the same administrator, usually the one who had to leave
   the desk, and a console that answers half their questions sends them back to it. What changes is
   the shape — the rail becomes a drawer, tables scroll inside their own frame instead of taking
   the page with them, and anything laid out in columns stacks. */

@media (max-width: 900px) {
    .nav-toggle { display: flex; }

    /* Off canvas until asked for, rather than stacked above the content. Fourteen links laid out
       as a wrapping strip cost half a phone screen before a single figure is visible, and pushed
       the thing the administrator opened the page for below the fold on every route. */
    .sidebar {
        position: fixed; top: var(--topbar-height); bottom: 0; left: 0;
        z-index: 40; width: min(300px, 84vw); max-height: none; height: auto;
        padding: 8px 12px 24px;
        overflow-y: auto; overscroll-behavior: contain;
        box-shadow: var(--elev-2);
        transform: translateX(-102%);
        transition: transform var(--slow) var(--ease);
    }

    .nav-state:checked ~ .shell .sidebar { transform: none; }

    /* Dims and closes. Present but transparent so the drawer can slide over it rather than the
       page flashing dark the instant the button is pressed. */
    .nav-scrim {
        display: block; position: fixed; inset: var(--topbar-height) 0 0 0;
        z-index: 39; background: rgba(0, 0, 0, .42);
        opacity: 0; pointer-events: none;
        transition: opacity var(--slow) var(--ease);
    }

    .nav-state:checked ~ .shell .nav-scrim { opacity: 1; pointer-events: auto; }

    .brand-org, .live-pill { display: none; }

    /* Kept, not hidden. Who you are signed in as decides what every figure on the screen means,
       and it is the first thing anybody checks when a console shows them the wrong numbers. */
    .topbar-user { max-width: 26vw; }

    .content { padding: 16px; overflow-x: visible; }
    .kpi-row { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
    .topbar { padding: 0 12px; }
    .stat-tile { padding: 16px; }
    .stat-value { font-size: 26px; }
    .panel { padding: 16px; }

    /* Two panels side by side become two panels, one after the other. `.split` already wraps, but
       its children carry their own widths and would wrap to a column three-quarters of the screen
       wide with a strip of background beside it. */
    .split > * { flex: 1 1 100% !important; width: 100%; min-width: 0; }

    .page-header { flex-direction: column; align-items: stretch; gap: 12px; }
    .page-header h1 { font-size: 22px; }

    /* A filter squeezed to half its label's width is a filter nobody uses. Each control gets at
       least enough room for its own name, and the row fits as many as that allows — two on a
       tablet, one on a phone — rather than being told which by another breakpoint. */
    .filters:has(> label) {
        display: grid; gap: 12px;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    }
    .filters > label { max-width: none; }

    /* Thumb-sized. 44px is the figure both platforms publish, and a console used one-handed in a
       car park is exactly the case it was published for. */
    .btn, .filters input, .filters select, .filters textarea { min-height: 44px; }

    .actions-bar { gap: 8px; }
    .actions-bar .btn { flex: 1 1 auto; justify-content: center; }
}

/* ---- Tables on a small screen --------------------------------------------
   Scrolled inside their own frame rather than reflowed into cards.

   A card per row reads well for two or three columns and falls apart at eight, which is what the
   approval queue and the user list actually have — and every figure in this console is there to be
   compared down a column, which cards make impossible. So the table stays a table and gains a
   scroll of its own, with the first column pinned: scrolling right on a wide grid is only usable
   while you can still see whose row you are reading. */

@media (max-width: 760px) {
    .grid-scroll, .grid { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }

    .grid > thead, .grid > tbody, .grid > tfoot { display: table; width: 100%; min-width: max-content; }
    .grid > thead { position: sticky; top: 0; z-index: 2; }

    .grid th, .grid td { white-space: nowrap; padding: 10px 12px; }

    /* The wrapping ones are the ones that would otherwise force the whole table wide: a purpose,
       an address, a rejection reason. They get a bounded column and wrap inside it. */
    .grid td.wrap, .grid th.wrap { white-space: normal; min-width: 180px; }

    .grid > thead th:first-child,
    .grid > tbody td:first-child {
        position: sticky; left: 0; z-index: 1;
        background: var(--surface);
        box-shadow: 1px 0 0 var(--border);
    }

    .grid > thead th:first-child { background: var(--surface-2); z-index: 3; }
    .grid tbody tr:hover td:first-child { background: var(--surface-2); }

    /* A shadow at whichever edge still has table behind it, and none at the edges that do not.
       Four layers pinned two to the element and two to the content: the pair that scrolls slides
       out from under the pair that does not, which uncovers the shadow exactly when there is
       something to uncover. No wrapper element and no script — and, unlike a permanent "scroll
       sideways" line, it stops claiming there is more once there is not. */
    .grid {
        background:
            linear-gradient(to right, var(--surface) 30%, transparent),
            linear-gradient(to left, var(--surface) 30%, transparent),
            linear-gradient(to right, rgba(60, 64, 67, .22), transparent 14px),
            linear-gradient(to left, rgba(60, 64, 67, .22), transparent 14px);
        background-repeat: no-repeat;
        background-size: 34px 100%, 34px 100%, 14px 100%, 14px 100%;
        background-position: 0 0, 100% 0, 0 0, 100% 0;
        background-attachment: local, local, scroll, scroll;
    }
}

/* ---- Phone ---------------------------------------------------------------- */

@media (max-width: 480px) {
    .topbar { padding: 0 12px; gap: 6px; }
    .topbar-user { display: none; }
    .content { padding: 12px; }
    .kpi-row { grid-template-columns: 1fr 1fr; }
    .stat-value { font-size: 22px; }
    .subtitle { font-size: 13px; }

    /* The name is not dropped, only moved: at this width the top bar cannot hold it, so it heads
       the drawer instead — where it also answers "whose console is this" before any link is read. */
    .sidebar[data-user]:not([data-user=""])::before {
        content: attr(data-user);
        display: block; padding: 10px 11px 12px; margin-bottom: 4px;
        border-bottom: 1px solid var(--border);
        font-size: 13px; color: var(--muted);
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
}

/* ---- Motion preference ---------------------------------------------------
   One override rather than a guard on each rule. Vestibular disorders are the reason this exists;
   the interface still works, it simply stops moving. */

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Employee photograph on the Users page. */
.photo-row { display: flex; align-items: center; gap: 16px; margin-bottom: 8px; }
.photo-current {
    width: 72px; height: 72px; border-radius: 50%; object-fit: cover;
    border: 2px solid var(--border); flex: 0 0 auto;
}
.photo-none {
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-2); color: var(--muted); font-weight: 700; font-size: 22px;
}

/* ---- Employee photograph control ----------------------------------------- */

.avatar-card { display: flex; align-items: center; gap: 18px; margin: 4px 0 14px; }

.avatar-well { position: relative; width: 104px; height: 104px; flex: 0 0 auto; }

.avatar-img {
    width: 104px; height: 104px; border-radius: 50%; object-fit: cover;
    border: 4px solid var(--surface); box-shadow: 0 0 0 1px var(--border), var(--elev-1);
    display: block;
}

.avatar-empty {
    display: flex; align-items: center; justify-content: center;
    background: var(--surface-2); color: var(--muted); font-weight: 700; font-size: 30px;
}

/* Actions sit on the rim, where the reference puts them: close enough to read as belonging to the
   photograph, clear of the face itself. */
.avatar-actions {
    position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%);
    display: flex; gap: 10px;
}

.avatar-btn {
    width: 34px; height: 34px; border-radius: 50%; border: 2px solid var(--surface);
    background: var(--muted); color: #fff; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    box-shadow: var(--elev-1); padding: 0;
}

.avatar-btn:hover { filter: brightness(1.1); }
.avatar-btn:focus-within, .avatar-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.avatar-btn-danger { background: var(--danger-fg); }

.avatar-btn svg {
    width: 17px; height: 17px; fill: none; stroke: #fff; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round; pointer-events: none;
}

/* The file input is driven by its label. Hidden with opacity and zero size rather than
   display:none, because a display:none input cannot receive focus and the control would drop out
   of the tab order entirely. */
.avatar-btn input[type="file"] { position: absolute; width: 1px; height: 1px; opacity: 0; }

/* ---- Live field duty board ------------------------------------------------ */

/* The one dark screen in a light console, on purpose: this is the wall display, and it follows
   its reference — an ink ground, a slate map, teal streets, and the employee drawn riding the
   vehicle the office approved for them. Palette is local to the board so the rest of the console
   keeps its day tokens. */
.fd-app {
    --fd-navy: #1B2B4B; --fd-navy-2: #22355c; --fd-teal: #0DBFB0; --fd-ink: #0f1626;
    --fd-orange: #E8722C; --fd-text: #e9eef6; --fd-muted: #8ea0bd; --fd-panel: #131c30;
    --fd-line: rgba(255, 255, 255, .06);

    display: flex; flex-direction: column; gap: 16px;
    min-height: calc(100vh - var(--topbar-height));
    margin: -24px -28px; padding: 24px 16px 40px;
    background: var(--fd-ink); color: var(--fd-text);
}

.fd-top { display: flex; align-items: center; gap: 12px; width: 100%; max-width: 1200px; margin: 0 auto; }

.fd-brand {
    width: 34px; height: 34px; border-radius: 9px; flex: none;
    background: linear-gradient(135deg, var(--fd-navy), var(--fd-navy-2));
    display: grid; place-items: center; box-shadow: inset 0 0 0 1.5px rgba(13, 191, 176, .5);
}
.fd-brand span { width: 12px; height: 12px; border-radius: 50%; background: var(--fd-teal); }
.fd-top h1 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.01em; color: var(--fd-text); }
.fd-top p { margin: 1px 0 0; font-size: 12.5px; color: var(--fd-muted); }

.fd-count {
    margin-left: auto; display: inline-flex; align-items: center; gap: 7px;
    font-size: 12px; font-weight: 600; color: var(--fd-text);
    background: rgba(13, 191, 176, .12); border: 1px solid rgba(13, 191, 176, .35);
    padding: 5px 12px; border-radius: 999px;
}

/* The live dot is the one claim on this screen: it is live. Stops under reduced-motion. */
.fd-live {
    width: 8px; height: 8px; border-radius: 50%; background: var(--fd-teal); flex: none;
    box-shadow: 0 0 0 0 rgba(13, 191, 176, .6); animation: fd-live 1.8s ease-out infinite;
}
@keyframes fd-live { to { box-shadow: 0 0 0 8px rgba(13, 191, 176, 0); } }

.fd-body { display: flex; gap: 16px; width: 100%; max-width: 1200px; margin: 0 auto; flex: 1; min-height: 0; }

/* Roster. Not in the reference, which shows one rider; a board that shows everybody needs a way
   to pick who the HUD follows. Styled as the reference's panel. */
.fd-panel {
    width: 300px; flex: 0 0 300px; display: flex; flex-direction: column;
    background: var(--fd-panel); border: 1px solid var(--fd-line); border-radius: 16px; overflow: hidden;
}
.fd-panel-head { padding: 14px 16px 10px; }
.fd-panel-head h2 { margin: 0; font-size: 12px; font-weight: 600; color: #c6d2e6; }
.fd-panel-head .fd-sub { font-size: 11.5px; color: #7f90ad; margin-top: 3px; }

.fd-legend { display: flex; flex-wrap: wrap; gap: 6px 12px; padding: 0 16px 10px; font-size: 11px; color: var(--fd-muted); }
.fd-legend span { display: inline-flex; align-items: center; gap: 5px; }
.fd-legend i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }

.fd-list { flex: 1; overflow-y: auto; padding: 6px 8px 10px; }
.fd-list .muted { color: var(--fd-muted); font-size: 13px; line-height: 1.5; }

.fd-emp {
    display: flex; gap: 10px; align-items: center; padding: 9px 10px;
    border-radius: 11px; cursor: pointer; border: 1px solid transparent; transition: .16s;
}
.fd-emp:hover { border-color: rgba(13, 191, 176, .5); background: #1b263f; }
.fd-emp:focus-visible { outline: 2px solid var(--fd-teal); outline-offset: -2px; }
.fd-emp.sel {
    background: linear-gradient(135deg, var(--fd-navy), #294067); border-color: var(--fd-teal);
    box-shadow: 0 0 0 1px var(--fd-teal), 0 8px 20px -12px rgba(13, 191, 176, .7);
}

.fd-ava { position: relative; width: 38px; height: 38px; flex: 0 0 auto; }
.fd-ava img, .fd-initials {
    width: 38px; height: 38px; border-radius: 50%; object-fit: cover;
    border: 2px solid var(--fd-panel); box-shadow: 0 0 0 2px currentColor;
}
.fd-initials { display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 13px; }
.fd-ava .fd-st { position: absolute; bottom: -1px; right: -1px; width: 11px; height: 11px; border-radius: 50%; border: 2px solid var(--fd-panel); }

.fd-n { font-size: 13.5px; font-weight: 600; color: var(--fd-text); }
.fd-d, .fd-meta { font-size: 11.5px; color: var(--fd-muted); }
.fd-meta { font-size: 11px; margin-top: 1px; }
.fd-chip { display: inline-block; font-size: 10.5px; font-weight: 700; padding: 2px 8px; border-radius: 999px; color: #fff; white-space: nowrap; }

.fd-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 16px; }

/* The map card, as drawn: slate and rounded. The employee card that used to float in this
   corner now rides on the marker itself, above the vehicle it describes. */
.fd-map-wrap {
    position: relative; flex: 1; min-height: 430px; border-radius: 18px; overflow: hidden;
    background: radial-gradient(120% 100% at 70% 20%, #3A424B, #333a42);
    border: 1px solid var(--fd-line); box-shadow: 0 24px 60px -30px rgba(0, 0, 0, .8);
}

/* Qualified by the wrapper: the SDK's stylesheet is injected at runtime after this file, so a bare
   .fd-map ties with .mapboxgl-map { position: relative } and the map collapses to zero height. */
.fd-map-wrap > .fd-map { position: absolute; inset: 0; }

.fd-recenter {
    position: absolute; bottom: 18px; right: 18px; z-index: 10;
    width: 44px; height: 44px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, .09);
    background: rgba(15, 22, 38, .72); backdrop-filter: blur(10px); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
}
.fd-recenter svg { width: 22px; height: 22px; }

.fd-note { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; padding: 24px; }
.fd-card { max-width: 420px; background: var(--fd-panel); border: 1px solid var(--fd-line); border-radius: 16px; padding: 26px; text-align: center; }
.fd-ic { width: 52px; height: 52px; border-radius: 14px; background: #1b263f; display: flex; align-items: center; justify-content: center; margin: 0 auto 14px; font-size: 24px; }
.fd-card h3 { margin: 0 0 8px; font-size: 17px; color: var(--fd-text); }
.fd-card p { margin: 0; font-size: 13.5px; color: var(--fd-muted); line-height: 1.5; }

/* Approved vehicle type, as the reference shows it — but read, not chosen, here. The chips echo
   what Admin › Vehicle Types and the employee's default vehicle say; changing it is done there. */
.fd-vehicle { background: var(--fd-panel); border: 1px solid var(--fd-line); border-radius: 16px; padding: 16px 16px 18px; }
.fd-vehicle h2 { margin: 0; font-size: 12px; font-weight: 600; color: #c6d2e6; }
.fd-vehicle .fd-sub { font-size: 11.5px; color: #7f90ad; margin: 3px 0 13px; }
.fd-vehicle .fd-sub code { background: rgba(13, 191, 176, .12); color: var(--fd-teal); padding: 1px 6px; border-radius: 5px; font-size: 11px; }
.fd-vehicle .fd-sub a { color: var(--fd-teal); }
.fd-chips { display: flex; flex-wrap: wrap; gap: 9px; }
.fd-vchip {
    display: inline-flex; align-items: center; gap: 8px; background: #1b263f;
    border: 1px solid rgba(255, 255, 255, .08); color: #c6d2e6;
    font-size: 13px; font-weight: 500; padding: 8px 14px; border-radius: 11px; opacity: .55;
}
.fd-vchip.active {
    opacity: 1; background: linear-gradient(135deg, var(--fd-navy), #294067);
    border-color: var(--fd-teal); color: #fff;
    box-shadow: 0 0 0 1px var(--fd-teal), 0 8px 20px -12px rgba(13, 191, 176, .7);
}

/* ---- The employee marker -------------------------------------------------- */

/* The marker is a point: a box of no size pinned to the coordinate, with the whole stack standing on
   it. Read top to bottom — who (their photograph, full colour, never filtered), their name, the
   vehicle, and a pin whose tip is the fix — so the GPS position is exactly where the pin points, at
   every zoom and whatever the name's length. */
.fd-mk { width: 0; height: 0; cursor: pointer; z-index: 2; }
.fd-stack {
    position: absolute; left: 0; bottom: 0; transform: translateX(-50%); transform-origin: 50% 100%;
    display: flex; flex-direction: column; align-items: center;
    translate: var(--dx, 0px) 0; transition: translate .25s ease-out;
}

/* A marker spread sideways off a crowded spot keeps a dot on its real position. */
.fd-mk.fd-shifted::after {
    content: ""; position: absolute; left: -5px; top: -5px; width: 10px; height: 10px; box-sizing: border-box;
    border-radius: 50%; background: #1a2536; border: 2px solid #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .4);
}

/* The employee card. Shown for the person being followed, or under the pointer: one on every marker
   at once hid the map they were standing on. Click-through so the map drags from anywhere. */
.fd-tag {
    display: none; position: relative; margin-bottom: 8px;
    width: 178px; box-sizing: border-box; pointer-events: none;
    background: rgba(15, 22, 38, .88); backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, .09); border-radius: 13px; padding: 11px 13px;
    box-shadow: 0 12px 30px -14px rgba(0, 0, 0, .7); color: var(--fd-text);
}
.fd-mk.fd-selected .fd-tag, .fd-mk:hover .fd-tag { display: block; }
.fd-mk.fd-dismissed:not(.fd-selected) .fd-tag { display: none; }
.fd-mk.fd-selected, .fd-mk:hover { z-index: 5; }
.fd-tag-name { font-size: 14px; font-weight: 600; display: flex; align-items: center; gap: 7px; }

/* The one part of the card that takes a click: it closes the card and ends following. */
.fd-tag-close {
    pointer-events: auto; margin-left: auto; padding: 0 2px; border: 0; background: none;
    color: var(--fd-muted); font-size: 20px; line-height: 1; cursor: pointer;
}
.fd-tag-close:hover { color: #fff; }
.fd-tag-row { display: flex; justify-content: space-between; gap: 16px; margin-top: 9px; font-size: 12px; }
.fd-tag-row span { color: var(--fd-muted); }
.fd-tag-row b { font-weight: 600; }
.fd-tag-mode { margin-top: 10px; padding-top: 9px; border-top: 1px solid rgba(255, 255, 255, .08); font-size: 11px; color: var(--fd-muted); line-height: 1.5; }
.fd-tag-mode b { color: #dfe7f3; font-weight: 600; }

.fd-head {
    display: block; flex: none; width: 42px; height: 42px; box-sizing: border-box;
    border-radius: 50%; object-fit: cover; border: 3px solid var(--ring); background: #fff;
    box-shadow: 0 4px 10px rgba(0, 0, 0, .35);
}
.fd-head-ini { display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 14px; background: var(--ring); }

/* A long name is cut with an ellipsis rather than widening the marker; the card has it in full. */
.fd-label {
    margin-top: 4px; max-width: 140px; box-sizing: border-box; background: #fff; color: #1a2536;
    border-radius: 8px; padding: 3px 9px; box-shadow: 0 3px 10px rgba(0, 0, 0, .25);
    text-align: center; line-height: 1.25;
}
.fd-name { display: block; font-size: 12px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fd-state { display: none; margin: 2px auto 0; width: fit-content; white-space: nowrap; font-size: 10px; font-weight: 700; color: #fff; border-radius: 6px; padding: 1px 6px; }
.fd-stack.lost .fd-state { display: block; background: #64748b; }
.fd-stack.gpsoff .fd-state { display: block; background: #dc2626; }

/* The vehicle, whole and uncovered. Motion is gated on .moving, which the server sets from the ping
   speed: the wheels roll and the body bobs only then. It mirrors (.west) to face its way. */
.fd-vehbox { flex: none; width: 70px; height: 45px; margin-top: 4px; }
.fd-stack.moving .fd-vehbox { animation: fd-bob .34s ease-in-out infinite; }
.fd-veh { display: block; width: 70px; height: 45px; overflow: visible; filter: drop-shadow(0 4px 5px rgba(16, 26, 40, .4)); }
.fd-stack.west .fd-veh { transform: scaleX(-1); }
/* An uploaded picture sits in the same 76:49 box as the scene, whole and undistorted. */
.fd-veh-img { object-fit: contain; }
.fd-tag-vehicle { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.fd-vchip .vt-icon { margin: -3px 0; }
.fd-veh .spokes { transform-box: fill-box; transform-origin: center; }
.fd-stack.moving .spokes { animation: fd-roll var(--spin, .5s) linear infinite; }

/* The location pin. Its tip is the bottom of the stack, and so the fix. It pulses while the position
   is live; with no signal it turns grey — the pin, never the person. */
.fd-loc { position: relative; flex: none; width: 20px; height: 26px; margin-top: 2px; }
.fd-loc svg { display: block; width: 20px; height: 26px; fill: var(--ring); filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .35)); }
.fd-stack.lost .fd-loc svg, .fd-stack.gpsoff .fd-loc svg { fill: #94a3b8; }
.fd-loc::after {
    content: ""; position: absolute; left: 50%; bottom: -5px; width: 18px; height: 9px; margin-left: -9px;
    border-radius: 50%; background: var(--ring); opacity: 0; pointer-events: none;
}
.fd-stack.live .fd-loc::after { animation: fd-fix 1.8s ease-out infinite; }

/* START and END of a duty route: a label on a dot that stands on the first and last valid fix.
   Beneath the people, so a flag never covers the person who started there. */
.fd-flag { z-index: 1; pointer-events: none; display: flex; flex-direction: column; align-items: center; }
.fd-flag span {
    font-size: 10px; font-weight: 800; letter-spacing: .06em; color: #fff;
    border-radius: 6px; padding: 3px 7px; box-shadow: 0 3px 8px rgba(0, 0, 0, .35);
}
.fd-flag::after {
    content: ""; width: 12px; height: 12px; margin-top: 2px; box-sizing: border-box;
    border-radius: 50%; border: 2.5px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .4);
}
.fd-flag-start span, .fd-flag-start::after { background: #16a34a; }
.fd-flag-end span, .fd-flag-end::after { background: #111827; }

@keyframes fd-roll { to { transform: rotate(360deg); } }
@keyframes fd-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1.4px); } }
@keyframes fd-fix { 0% { opacity: .5; transform: scale(.4); } 80%, 100% { opacity: 0; transform: scale(1.8); } }

@media (max-width: 900px) {
    .fd-body { flex-direction: column; }
    .fd-panel { width: 100%; flex: none; max-height: 40vh; }
    .fd-map-wrap { min-height: 340px; }
    .fd-stack { scale: .85; }
    .fd-tag { width: 158px; }
}

@media (prefers-reduced-motion: reduce) {
    .fd-live, .fd-stack.moving .fd-vehbox, .fd-stack.moving .spokes, .fd-stack.live .fd-loc::after { animation: none !important; }
}

/* ---- Day replay: pause and endpoint badges standing on the route ------------------------------
   The live board's card material — the same glass, the same radius — shrunk to a label, because
   these annotate a line rather than introduce a person. Pointer events stay off: the badge is a
   caption, and a caption that swallows the pan gesture under it reads as a broken map. */
.fd-day-badge {
    pointer-events: none;
    display: flex; align-items: center; gap: 6px; white-space: nowrap;
    background: rgba(15, 22, 38, .82); backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, .09); border-radius: 10px; padding: 6px 10px;
    box-shadow: 0 10px 24px -12px rgba(0, 0, 0, .7);
    color: #e7ecf6; font-size: 12px; line-height: 1.25;
}
.fd-day-badge b { font-weight: 600; }

/* The playback marker: one dot walking the day, ringed so it reads against both the trail it has
   covered and the dimmed one ahead of it. Deliberately not the live board's photograph-and-vehicle
   stack — that says "this is where they are", and this is where they were. */
.fd-day-rider {
    width: 18px; height: 18px; border-radius: 50%;
    background: #0dbfb0; border: 3px solid #fff;
    box-shadow: 0 0 0 2px rgba(13, 191, 176, .45), 0 2px 6px rgba(0, 0, 0, .35);
}
.fd-day-badge .fd-day-sub { display: block; color: #9aa7bd; font-size: 11px; margin-left: 6px; }

.fd-day-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: #9aa7bd; }
.fd-day-badge.start .fd-day-dot { background: #16a34a; }
.fd-day-badge.end .fd-day-dot { background: #dc2626; }
.fd-day-badge.now .fd-day-dot { background: var(--fd-teal, #0dbfb0); }

/* The leading edge of today pulses like the live board's presence dot — same animation, so
   "this end is still moving" is said in a vocabulary the reader already knows. */
.fd-day-live { box-shadow: 0 0 0 0 rgba(13, 191, 176, .6); animation: fd-live 1.8s ease-out infinite; }

.fd-day-badge.break { border-left: 3px solid #f59e0b; }
.fd-day-badge.idle { border-left: 3px solid #64748b; }

/* Hosted inside the mobile app (see MainLayout): the app draws the top bar and the drawer, so
   the console shows only its content plane. */
/* Shown inside the FieldOps app, which draws its own navigation bar: the console's own top
   bar and rail would be a second copy of both. The class is set on <body> by App.razor,
   where the request's user agent is actually available. */
body.embedded .topbar,
body.embedded .sidebar,
body.embedded .nav-scrim { display: none !important; }
body.embedded .content { padding: 12px; }

/* A screen with nothing to show says why, in a card rather than a stray line of grey text
   that reads as a page that failed to load. */
.empty-state {
    max-width: 62ch; padding: 24px 28px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
}
.empty-state h2 { margin: 0 0 8px; font-size: 17px; }
.empty-state p { margin: 0 0 12px; color: var(--muted); }
.empty-state ul { margin: 0 0 12px; padding-left: 20px; color: var(--muted); }
.empty-state li { margin: 4px 0; }
.empty-state strong { color: var(--text); }

/* The claims queue's people list: wide enough for a name and a pending total, no wider. */
.claims-people { width: 260px; flex: none; }
@media (max-width: 900px) { .claims-people { width: 100%; } }

/* Password field with a show/hide eye inside its right edge. */
.password-field { position: relative; display: block; }
.password-field input { width: 100%; padding-right: 40px; }
.password-eye {
    position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
    width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
    border: none; background: none; color: var(--muted); border-radius: 50%; cursor: pointer;
}
.password-eye:hover { background: var(--hover-wash); color: var(--text); }
.password-eye:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.password-eye .password-eye-slash { display: none; }
.password-eye.shown .password-eye-slash { display: block; }

/* ---- Vehicle type pictures --------------------------------------------------------------------
   One frame for every vehicle picture in the console: a fixed 76:49 box, the whole vehicle shown
   (contain, never cropped or stretched), on the same quiet tile, at one of three sizes. */
.vt-icon {
    display: inline-flex; align-items: center; justify-content: center; flex: none; vertical-align: middle;
    aspect-ratio: 76 / 49; box-sizing: border-box; overflow: hidden;
    background: #f1f5f9; border: 1px solid rgba(15, 23, 42, .06); border-radius: 8px;
}
.vt-icon img { display: block; width: 100%; height: 100%; object-fit: contain; }
.vt-sm { width: 44px; padding: 2px 3px; border-radius: 6px; }
.vt-md { width: 68px; padding: 3px 5px; }
.vt-lg { width: 152px; padding: 6px 10px; border-radius: 12px; }

.vt-name { display: inline-flex; align-items: center; gap: 8px; }

.vt-picker { display: flex; flex-wrap: wrap; gap: 8px; }
.vt-option {
    display: inline-flex; align-items: center; gap: 9px; padding: 6px 12px 6px 6px; cursor: pointer;
    background: var(--surface, #fff); border: 1px solid var(--border, #e2e8f0); border-radius: 10px;
    font: inherit; color: inherit;
}
.vt-option:hover { border-color: var(--accent, #0dbfb0); }
.vt-option.selected { border-color: var(--accent, #0dbfb0); box-shadow: 0 0 0 1px var(--accent, #0dbfb0); }
.vt-picker.disabled .vt-option { cursor: default; opacity: .7; }

.vt-editor { display: flex; align-items: center; gap: 16px; margin: 6px 0 14px; }
/* A cut-out previewed on a checkerboard, so the removed background reads as removed. */
.vt-transparent { background: repeating-conic-gradient(#e2e8f0 0 25%, #fff 0 50%) 0 0 / 14px 14px; }
.vt-facing { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin: 2px 0 6px; font-size: 13px; }
.vt-facing label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
.vt-toggle { display: flex; align-items: center; gap: 8px; margin: 2px 0 6px; font-size: 13px; }
.vt-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 6px; }
.vt-actions label.btn { position: relative; cursor: pointer; }
.vt-actions input[type="file"] { position: absolute; inset: 0; width: 1px; height: 1px; opacity: 0; }

/* ---- Site editor map ---------------------------------------------------------------------------- */
.site-locate { margin: 6px 0 14px; }
.site-map { position: relative; height: 360px; border-radius: 12px; overflow: hidden; border: 1px solid var(--border); }

/* The map-view preview on Integrations: a swatch of the chosen basemap, sized so the difference
   between night, day and satellite is obvious at a glance without the panel growing a scrollbar. */
.fd-style-preview {
    height: 220px;
    margin-top: 12px;
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid var(--line, #e2e8f0);
    background: var(--surface-2, #f1f5f9);
}

/* ---- Sign-in page --------------------------------------------------------
   The ElectEmb Field Duty sign-in: a two-panel card, brand on the left and the form on the
   right, folding to one column on a phone. Every class and variable here carries an "lg-" prefix
   because the design's own names (.shell, .panel, .brand, .btn) are already taken by the console
   chrome above, and a shared name would style the wrong thing on one side or the other.
   Colours are the page's own tokens rather than the console's, so it reads as the design in both
   themes; the html element's data-theme (set before first paint in App.razor) picks the set. */

.lg-shell, .lg-overlay, .lg-contacts {
    --lg-navy: #1B2B4B;
    --lg-navy-800: #16233d;
    --lg-navy-900: #101a30;
    --lg-teal: #0DBFB0;
    --lg-teal-600: #0aa294;
    --lg-teal-100: #d6f5f1;
    --lg-ink: #14203a;
    --lg-muted: #5c6a85;
    --lg-line: #dfe4ee;
    --lg-field: #f4f6fb;
    --lg-surface: #ffffff;
    --lg-page: #eef1f7;
    --lg-danger: #e15b52;
    --lg-shadow: 0 24px 60px -28px rgba(16,26,48,.45);
    --lg-font: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --lg-note-bg: var(--lg-teal-100);
    --lg-note-fg: #0a6f66;
}

:root[data-theme="dark"] .lg-shell,
:root[data-theme="dark"] .lg-overlay,
:root[data-theme="dark"] .lg-contacts {
    --lg-ink: #eaf0fb;
    --lg-muted: #9aa8c4;
    --lg-line: #28324a;
    --lg-field: #182338;
    --lg-surface: #141d31;
    --lg-page: #0b1424;
    --lg-shadow: 0 24px 60px -28px rgba(0,0,0,.7);
    --lg-note-bg: rgba(13,191,176,.1);
    --lg-note-fg: #7fe4da;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .lg-shell,
    :root:not([data-theme="light"]) .lg-overlay,
    :root:not([data-theme="light"]) .lg-contacts {
        --lg-ink: #eaf0fb;
        --lg-muted: #9aa8c4;
        --lg-line: #28324a;
        --lg-field: #182338;
        --lg-surface: #141d31;
        --lg-page: #0b1424;
        --lg-shadow: 0 24px 60px -28px rgba(0,0,0,.7);
        --lg-note-bg: rgba(13,191,176,.1);
        --lg-note-fg: #7fe4da;
    }
}

/* The page behind the card, in the design's colours rather than the console's. */
.bare:has(> .lg-shell) { background: #eef1f7; padding: 24px 16px; }
:root[data-theme="dark"] .bare:has(> .lg-shell) { background: #0b1424; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .bare:has(> .lg-shell) { background: #0b1424; } }

.lg-shell, .lg-overlay { font-family: var(--lg-font); color: var(--lg-ink); -webkit-font-smoothing: antialiased; }
.lg-shell *, .lg-overlay * { box-sizing: border-box; }

.lg-shell {
    width: 100%;
    max-width: 940px;
    background: var(--lg-surface);
    border: 1px solid var(--lg-line);
    border-radius: 22px;
    box-shadow: var(--lg-shadow);
    overflow: hidden;
    display: grid;
    grid-template-columns: 1.05fr .95fr;
}

/* Brand panel */
.lg-brand {
    position: relative;
    background:
        radial-gradient(120% 90% at 12% 12%, rgba(13,191,176,.20), transparent 55%),
        linear-gradient(160deg, var(--lg-navy) 0%, var(--lg-navy-800) 55%, var(--lg-navy-900) 100%);
    color: #eef4ff;
    padding: 38px 36px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    min-height: 560px;
    overflow: hidden;
}
.lg-brand::after {
    /* ambient GPS ping */
    content: "";
    position: absolute;
    right: 56px; top: 44%;
    width: 14px; height: 14px; border-radius: 50%;
    background: var(--lg-teal);
    box-shadow: 0 0 0 0 rgba(13,191,176,.55);
    animation: lg-ping 2.8s ease-out infinite;
}
@keyframes lg-ping {
    0% { box-shadow: 0 0 0 0 rgba(13,191,176,.5); }
    70% { box-shadow: 0 0 0 26px rgba(13,191,176,0); }
    100% { box-shadow: 0 0 0 0 rgba(13,191,176,0); }
}
.lg-routemap { position: absolute; inset: 0; width: 100%; height: 100%; opacity: .9; }

.lg-brand-top { position: relative; z-index: 2; display: flex; align-items: center; gap: 12px; }
.lg-logo-mark { flex: none; display: block; }
.lg-logo-word { font-weight: 600; font-size: 20px; letter-spacing: .2px; line-height: 1; }
.lg-logo-word b { color: var(--lg-teal); font-weight: 600; }
.lg-logo-word span { display: block; font-size: 11px; font-weight: 400; letter-spacing: .14em; text-transform: uppercase; color: #9fb2d4; margin-top: 5px; }

.lg-brand-mid { position: relative; z-index: 2; }
.lg-eyebrow {
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
    color: #a9d9d3; font-weight: 500; margin-bottom: 16px;
}
.lg-eyebrow .lg-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--lg-teal); box-shadow: 0 0 10px var(--lg-teal); }
.lg-brand-mid h1 {
    font-size: 30px; line-height: 1.18; margin: 0; font-weight: 600; text-wrap: balance;
    max-width: 15ch; color: inherit;
}
.lg-brand-mid p { color: #b6c4de; font-size: 14px; line-height: 1.6; margin: 14px 0 0; max-width: 34ch; }

.lg-status-row { position: relative; z-index: 2; display: flex; flex-wrap: wrap; gap: 8px; }
.lg-pill {
    display: inline-flex; align-items: center; gap: 7px;
    background: rgba(255,255,255,.07);
    border: 1px solid rgba(255,255,255,.14);
    padding: 7px 12px; border-radius: 999px;
    font-size: 12px; font-weight: 500; color: #dbe6f7;
}
.lg-pill i { width: 7px; height: 7px; border-radius: 50%; display: inline-block; }
.lg-i-move { background: var(--lg-teal); }
.lg-i-idle { background: #f5c451; }
.lg-i-break { background: #7aa2ff; }

/* Form panel */
.lg-panel { padding: 44px 44px 38px; display: flex; flex-direction: column; justify-content: center; }
.lg-panel h2 { margin: 0; font-size: 23px; font-weight: 600; letter-spacing: -.2px; color: inherit; }
.lg-panel .lg-sub { margin: 8px 0 28px; color: var(--lg-muted); font-size: 14px; line-height: 1.5; }

.lg-error {
    margin: -12px 0 18px; padding: 11px 13px;
    border-radius: 11px; font-size: 13px; line-height: 1.45;
    background: rgba(225,91,82,.10); border: 1px solid rgba(225,91,82,.35); color: var(--lg-danger);
}

.lg-form { display: flex; flex-direction: column; gap: 18px; }
.lg-field label { display: block; font-size: 12.5px; font-weight: 500; color: var(--lg-ink); margin-bottom: 7px; letter-spacing: .01em; }
.lg-input-wrap { position: relative; display: flex; align-items: center; }
.lg-input-wrap > svg { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--lg-muted); pointer-events: none; }
.lg-field input {
    width: 100%;
    font-family: var(--lg-font); font-size: 14.5px;
    color: var(--lg-ink);
    background: var(--lg-field);
    border: 1.5px solid transparent;
    border-radius: 11px;
    padding: 13px 14px 13px 42px;
    transition: border-color .16s, background .16s, box-shadow .16s;
}
.lg-field input::placeholder { color: var(--lg-muted); opacity: .75; }
.lg-field input:focus {
    outline: none;
    background: var(--lg-surface);
    border-color: var(--lg-teal);
    box-shadow: 0 0 0 4px rgba(13,191,176,.16);
}
.lg-field #password { padding-right: 46px; }
.lg-toggle-pw {
    position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
    background: none; border: none; cursor: pointer;
    color: var(--lg-muted); padding: 6px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
}
.lg-toggle-pw:hover { color: var(--lg-ink); }
.lg-toggle-pw:focus-visible { outline: 2px solid var(--lg-teal); outline-offset: 1px; }
.lg-toggle-pw .lg-eye-off { display: none; }
.lg-toggle-pw.is-shown .lg-eye-open { display: none; }
.lg-toggle-pw.is-shown .lg-eye-off { display: block; }

.lg-row-between { display: flex; align-items: center; justify-content: space-between; margin-top: -4px; }
.lg-remember { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--lg-muted); cursor: pointer; user-select: none; }
.lg-remember input { width: 16px; height: 16px; accent-color: var(--lg-teal); cursor: pointer; margin: 0; }
.lg-link { color: var(--lg-teal-600); font-size: 13px; text-decoration: none; font-weight: 500; }
.lg-link:hover { text-decoration: underline; }

.lg-btn {
    margin-top: 6px;
    font-family: var(--lg-font); font-size: 15px; font-weight: 600;
    color: #fff;
    background: linear-gradient(135deg, var(--lg-teal) 0%, var(--lg-teal-600) 100%);
    border: none; border-radius: 11px;
    padding: 14px; cursor: pointer;
    display: flex; align-items: center; justify-content: center; gap: 9px;
    box-shadow: 0 12px 24px -12px rgba(13,191,176,.7);
    transition: transform .12s, box-shadow .12s, filter .12s;
}
.lg-btn:hover { filter: brightness(1.03); box-shadow: 0 16px 30px -12px rgba(13,191,176,.8); }
.lg-btn:active { transform: translateY(1px); }
.lg-btn:focus-visible { outline: 2px solid var(--lg-navy); outline-offset: 2px; }
.lg-btn[aria-busy="true"] { pointer-events: none; filter: saturate(.7); }
a.lg-btn { text-decoration: none; }

.lg-divider { display: flex; align-items: center; gap: 10px; margin: 18px 0 10px; color: var(--lg-muted); font-size: 12px; }
.lg-divider::before, .lg-divider::after { content: ""; flex: 1; height: 1px; background: var(--lg-line); }
.lg-sso {
    display: flex; align-items: center; justify-content: center;
    margin-top: 8px; padding: 12px; border-radius: 11px;
    border: 1.5px solid var(--lg-line); background: var(--lg-field);
    color: var(--lg-ink); font-size: 14px; font-weight: 500; text-decoration: none;
    transition: border-color .15s, background .15s;
}
.lg-sso:hover { border-color: var(--lg-teal); background: var(--lg-surface); }

.lg-gps-note {
    display: flex; align-items: flex-start; gap: 10px;
    margin-top: 20px; padding: 12px 14px;
    background: var(--lg-note-bg);
    border: 1px solid rgba(13,191,176,.35);
    border-radius: 11px;
    font-size: 12.5px; line-height: 1.5; color: var(--lg-note-fg);
}
.lg-gps-note svg { flex: none; color: var(--lg-teal-600); margin-top: 1px; }

.lg-foot { margin: 26px 0 0; font-size: 12.5px; color: var(--lg-muted); text-align: center; }
.lg-foot a { color: var(--lg-teal-600); text-decoration: none; }
.lg-foot a:hover { text-decoration: underline; }

@media (max-width: 760px) {
    .lg-shell { grid-template-columns: 1fr; max-width: 440px; }
    .lg-brand { min-height: auto; padding: 30px 28px; }
    .lg-brand-mid { margin: 26px 0; }
    .lg-brand-mid h1 { font-size: 24px; }
    .lg-panel { padding: 34px 28px 30px; }
    .lg-brand::after { top: 34px; right: 32px; }
}
@media (prefers-reduced-motion: reduce) {
    .lg-brand::after { animation: none; }
}

/* Dialogs */
.lg-overlay {
    position: fixed; inset: 0; z-index: 50;
    background: rgba(10,16,30,.55);
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
}
.lg-overlay[hidden] { display: none; }
.lg-modal {
    width: 100%; max-width: 400px;
    background: var(--lg-surface); color: var(--lg-ink);
    border: 1px solid var(--lg-line); border-radius: 16px;
    box-shadow: var(--lg-shadow);
    padding: 24px 22px;
}
.lg-modal h3 { margin: 0 0 6px; font-size: 18px; font-weight: 600; color: inherit; }
.lg-modal p { margin: 0 0 16px; font-size: 13.5px; line-height: 1.55; color: var(--lg-muted); }
.lg-contacts { display: flex; flex-direction: column; gap: 10px; margin-bottom: 6px; }
.lg-contact-row {
    display: flex; align-items: center; gap: 11px;
    padding: 11px 13px; border: 1px solid var(--lg-line); border-radius: 11px;
    background: var(--lg-field); text-decoration: none; color: var(--lg-ink);
    transition: border-color .15s, background .15s;
}
.lg-contact-row:hover { border-color: var(--lg-teal); background: var(--lg-surface); }
.lg-contact-row svg { flex: none; color: var(--lg-teal-600); }
.lg-contact-row .lg-c-label { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--lg-muted); }
.lg-contact-row .lg-c-val { font-size: 14px; font-weight: 500; }
.lg-modal-close {
    margin-top: 14px; width: 100%;
    font-family: var(--lg-font); font-size: 13.5px; font-weight: 500;
    color: var(--lg-muted); background: none; border: none; cursor: pointer; padding: 8px;
}
.lg-modal-close:hover { color: var(--lg-ink); }

/* Sign-in page: outcome notices and the dialog's own form. */
.lg-notice {
    margin: -12px 0 18px; padding: 11px 13px;
    border-radius: 11px; font-size: 13px; line-height: 1.45;
    background: var(--lg-note-bg); border: 1px solid rgba(13,191,176,.35); color: var(--lg-note-fg);
}
.lg-modal .lg-field { margin-bottom: 14px; }
.lg-modal .lg-btn { width: 100%; margin-top: 0; }
.lg-modal-note { margin: 12px 0 0; font-size: 12.5px; color: var(--lg-teal-600); text-align: center; }
.lg-modal-note.is-error { color: var(--lg-danger); }
.lg-modal .lg-error { margin: 0 0 14px; }
.lg-shell.lg-single { max-width: 480px; grid-template-columns: 1fr; }
.lg-shell.lg-single .lg-panel { padding: 40px 40px 34px; }
.lg-shell.lg-single .lg-brand-top { margin-bottom: 22px; }
.lg-shell.lg-single .lg-logo-word { color: var(--lg-ink); }
.lg-shell.lg-single .lg-logo-word span { color: var(--lg-muted); }
@media (max-width: 760px) { .lg-shell.lg-single .lg-panel { padding: 32px 26px 28px; } }

/* ---- Email settings page ------------------------------------------------- */

.em-presets { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 10px; }
.em-preset {
    display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
    padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--text); text-align: left; cursor: pointer;
    font: inherit; transition: border-color .15s, background .15s;
}
.em-preset:hover { border-color: var(--accent); }
.em-preset.is-on { border-color: var(--accent); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent); }
.em-preset small { color: var(--muted); font-size: 12px; }
.em-preset:disabled { opacity: .6; cursor: default; }
.em-h3 { margin: 22px 0 10px; font-size: 13px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase; color: var(--muted); }
.em-security { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.em-radio {
    display: flex; flex-direction: column; gap: 2px; padding: 10px 14px 10px 36px; position: relative;
    border: 1px solid var(--border); border-radius: var(--radius-sm); cursor: pointer; flex: 1 1 160px;
}
.em-radio input { position: absolute; left: 12px; top: 13px; accent-color: var(--accent); margin: 0; }
.em-radio.is-on { border-color: var(--accent); background: var(--accent-wash); }
.em-radio b { font-weight: 600; font-size: 13px; }
.em-radio small { color: var(--muted); font-size: 12px; }
.em-switch { display: inline-flex; align-items: center; gap: 10px; font-size: 14px; cursor: pointer; }
.em-switch input { width: 18px; height: 18px; accent-color: var(--accent); margin: 0; }
.filters > label > .password-field { position: relative; display: block; }
.filters > label > .password-field > input { width: 100%; padding-right: 40px; }

/* ---- Page building blocks ------------------------------------------------
   The pieces the configuration and reporting pages are assembled from, so each page is a
   composition of the same parts rather than its own arrangement of labels and grey text.
   Defined once here; a page that needs a new shape adds it here, not inline. */

/* Links in content wear the accent, visited or not. The browser's purple says "you have been
   here", which on a console of daily screens is always true and so says nothing. */
.content a:not(.btn):not(.nav-link):not(.stat-tile):not(.db-kpi):not(.lg-contact-row) { color: var(--accent); text-underline-offset: 2px; }
a.btn { text-decoration: none; }

.page-header h1 { font-size: 24px; font-weight: 500; }
.page-header .subtitle { margin-top: 2px; }

/* The page-level description some pages write without a header wrapper. */
.page-note { margin: 0 0 20px; color: var(--muted); max-width: 72ch; }

/* A heading that opens a new section of a long page. Separated from what came before by space
   and a rule, so it reads as a new topic rather than as a caption for the card above it. */
.section-head { margin: 32px 0 14px; padding-top: 20px; border-top: 1px solid var(--border); }
.section-head h2 { font-size: 18px; margin: 0 0 4px; }
.section-head .subtitle { font-size: 13px; }

.page-stack { display: grid; gap: 16px; align-content: start; }

/* Forms: caption above control, in a grid that fills the width it is given and drops to one
   column on a phone. */
.form-grid {
    display: grid; gap: 16px 18px;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.form-grid.one-col { grid-template-columns: 1fr; }
.form-grid + .form-grid, .form-grid + .field-hint { margin-top: 12px; }
.field {
    display: flex; flex-direction: column; gap: 6px; min-width: 0;
    font-size: 12px; font-weight: 500; color: var(--muted);
}
.field > input, .field > select, .field > textarea { width: 100%; }
.field.span-all { grid-column: 1 / -1; }
.field-hint { font-size: 12px; color: var(--muted); font-weight: 400; margin: 8px 0 0; line-height: 1.45; }

/* A number with its unit written inside the same box, so "45" is never read without "minutes". */
.input-unit {
    display: inline-flex; align-items: stretch; width: 100%;
    border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface);
    transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.input-unit:focus-within { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.input-unit > input { border: none; box-shadow: none !important; background: transparent; min-width: 0; flex: 1; }
.input-unit > span {
    display: flex; align-items: center; padding: 0 10px;
    color: var(--muted); font-size: 12px; white-space: nowrap;
    border-left: 1px solid var(--border); background: var(--surface-2);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

/* An on/off switch. Used where a checkbox answers "is this on", which is every checkbox on the
   configuration pages. */
input[type="checkbox"].toggle {
    appearance: none; -webkit-appearance: none; margin: 0; flex-shrink: 0;
    width: 36px; height: 20px; border-radius: var(--radius-pill);
    background: var(--border); position: relative; cursor: pointer;
    transition: background var(--fast) var(--ease);
}
input[type="checkbox"].toggle::before {
    content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
    border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0, 0, 0, .3);
    transition: transform var(--fast) var(--ease);
}
input[type="checkbox"].toggle:checked { background: var(--accent); }
input[type="checkbox"].toggle:checked::before { transform: translateX(16px); }
:root[data-theme="dark"] input[type="checkbox"].toggle:checked::before { background: #202124; }
input[type="checkbox"].toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
input[type="checkbox"].toggle:disabled { opacity: .5; cursor: default; }

.toggle-label { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); cursor: pointer; }

/* A setting as a row: switch, what it is, and its value. The shape Alerts and the check rows on
   Tracking policy share. */
.setting-list { display: flex; flex-direction: column; }
.setting-row {
    display: grid; grid-template-columns: auto 1fr minmax(120px, 180px);
    gap: 4px 16px; align-items: center;
    padding: 14px 0; border-top: 1px solid var(--border);
}
.setting-row:first-child { border-top: none; padding-top: 4px; }
.setting-row.no-value { grid-template-columns: auto 1fr; }
.setting-title { font-weight: 500; color: var(--text); }
.setting-desc { font-size: 12px; color: var(--muted); line-height: 1.45; }
.setting-row.is-off .setting-title { color: var(--muted); }

/* Day-of-week picks as pills, the way a calendar shows a recurring rule. */
.day-picks { display: flex; flex-wrap: wrap; gap: 8px; }
.day-pick { position: relative; cursor: pointer; }
.day-pick input { position: absolute; opacity: 0; pointer-events: none; }
.day-pick span {
    display: inline-flex; align-items: center; justify-content: center; min-width: 52px; height: 34px; padding: 0 12px;
    border: 1px solid var(--border); border-radius: var(--radius-pill);
    font-size: 13px; font-weight: 500; color: var(--muted); background: var(--surface);
    transition: background var(--fast) var(--ease), color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.day-pick input:checked + span { background: var(--accent-wash); color: var(--accent); border-color: var(--accent); }
.day-pick input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* A checkbox with a title and an explanation under it. */
.check-row { display: flex; gap: 12px; align-items: flex-start; padding: 10px 0; cursor: pointer; }
.check-row > input { margin-top: 2px; }
.check-row strong { display: block; font-weight: 500; }
.check-row .muted { font-size: 12px; }

/* Tables that can be wider than a phone scroll inside their own frame rather than dragging the
   whole page sideways. */
.table-scroll {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
}
.table-scroll > .grid { border: none; border-radius: 0; min-width: 560px; }
.panel > .table-scroll { margin-top: 4px; }
.grid .nowrap, .nowrap { white-space: nowrap; }
.grid a strong { font-weight: 500; }
.row-muted td { color: var(--muted); }

/* Figures above a table: the answer first, the breakdown after. */
.kpi-row.compact { gap: 12px; margin-bottom: 16px; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.kpi-row.compact .stat-tile { padding: 14px 16px; }
.kpi-row.compact .stat-value { font-size: 24px; }
.stat-value small { font-size: 14px; color: var(--muted); margin-left: 2px; letter-spacing: 0; }

/* A labelled date range in a page header. */
.range { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.range label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; font-weight: 500; color: var(--muted); }

/* The empty state inside a card: centred, quieter than the stand-alone one. */
.empty-inline {
    display: flex; flex-direction: column; align-items: center; text-align: center; gap: 6px;
    padding: 28px 16px; color: var(--muted); border: 1px dashed var(--border); border-radius: var(--radius);
}
.empty-inline strong { color: var(--text); font-weight: 500; font-size: 14px; }
.empty-inline svg { width: 28px; height: 28px; stroke: currentColor; fill: none; stroke-width: 1.6; opacity: .7; }

/* A list row with an initial, a name and a secondary line — Users and Roles. */
.list-item.person {
    flex-direction: row; align-items: center; gap: 12px;
}
.list-item.person .person-text { display: flex; flex-direction: column; min-width: 0; flex: 1; gap: 2px; }
.list-item.person .person-text > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-item.person .avatar { width: 32px; height: 32px; font-size: 13px; }
.list-item.person .chip { margin: 0; font-size: 11px; padding: 2px 8px; }
.list-item.selected .avatar { background: var(--accent); color: var(--surface); }

.split > aside.panel { width: 300px; flex: 0 0 300px; }

/* Sections inside a detail card. */
.detail-section + .detail-section { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border); }
.detail-section > h3:first-child { margin-top: 0; }

.permission-group { border: 1px solid var(--border); border-radius: var(--radius); padding: 6px 10px 10px; margin-top: 12px; }
.permission-group > h3 { margin: 8px 4px; }

/* The support desk editor: form beside a preview of what employees will see. */
.support-layout { display: grid; gap: 16px; grid-template-columns: minmax(280px, 520px) minmax(260px, 360px); align-items: start; }
.contact-preview { display: flex; flex-direction: column; gap: 8px; }
.contact-preview-row {
    display: flex; align-items: center; gap: 12px; padding: 12px 14px;
    border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2);
}
.contact-preview-row svg { width: 20px; height: 20px; flex-shrink: 0; color: var(--accent); }
.contact-preview-row .label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.contact-preview-row .value { font-weight: 500; }

@media (max-width: 900px) {
    .split > aside.panel { width: 100%; flex: 1 1 100%; }
    .support-layout { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
    .page-header h1 { font-size: 21px; }
    .setting-row { grid-template-columns: auto 1fr; }
    .setting-row > :last-child:not(:nth-child(2)) { grid-column: 2; margin-top: 6px; }
    .panel { padding: 16px; }
    .range { width: 100%; }
    .range label { flex: 1; }
    .range input { width: 100%; }
}

.chip-info { background: var(--accent-wash); color: var(--accent); border-color: transparent; }
.notice-ok { background: var(--ok-bg); color: var(--ok-fg); }

/* ==========================================================================
   Dashboard (Dashboard.razor) — the FieldOps dashboard design.
   Prefixed db- because .grid, .card and .kpi already mean something elsewhere in this sheet.
   ========================================================================== */

.db-actions { display: flex; gap: 9px; align-items: center; }
.db-actions .btn { min-height: 0; padding: 9px 14px; }
.db-actions .btn.is-open { background: var(--surface-2); }

.db-filter { position: relative; }
.db-filter-count {
    font-size: 10.5px; font-weight: 700; line-height: 1.5;
    background: var(--accent); color: #fff; padding: 0 6px; border-radius: var(--radius-pill);
}
.db-filter-pop {
    position: absolute; right: 0; top: calc(100% + 6px); z-index: 25;
    min-width: 220px; padding: 10px 12px 12px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
    box-shadow: 0 12px 28px -12px rgba(16, 24, 40, .28);
    display: flex; flex-direction: column; gap: 2px;
}
.db-filter-cap {
    font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
    color: var(--faint); font-weight: 600; padding: 2px 0 6px;
}
.db-filter-pop label {
    display: flex; align-items: center; gap: 9px; padding: 6px 4px;
    font-size: 13px; color: var(--text-2); cursor: pointer; border-radius: 7px;
}
.db-filter-pop label:hover { background: var(--surface-2); }
.db-filter-pop label i { width: 9px; height: 9px; border-radius: 50%; }
.db-filter-pop label .muted { margin-left: auto; font-variant-numeric: tabular-nums; }
.db-filter-pop input { accent-color: var(--accent); margin: 0; }
.db-filter-pop .btn-link { margin-top: 6px; padding: 4px; color: var(--accent); font-weight: 600; }

/* ---- KPIs ---- */

.db-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 13px; margin-bottom: 14px; }
.db-kpis .skeleton-tile { height: 104px; border-radius: 13px; }

.db-kpi {
    background: var(--surface); border: 1px solid var(--border); border-radius: 13px;
    padding: 15px 16px; color: inherit; text-decoration: none; display: block;
    transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.db-kpi:hover { border-color: var(--accent-wash-2); box-shadow: 0 6px 18px -14px rgba(16, 24, 40, .35); }
.db-kpi:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.db-kpi .k {
    font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
    color: var(--muted); font-weight: 600; display: flex; align-items: center; gap: 7px;
}
.db-kpi .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.db-kpi .v { font-size: 26px; font-weight: 700; margin-top: 9px; font-variant-numeric: tabular-nums; line-height: 1; }
.db-kpi .v small { font-size: 15px; color: var(--faint); font-weight: 600; }
.db-kpi .s { font-size: 12px; color: var(--muted); margin-top: 7px; }
.db-kpi .s.warn { color: var(--st-idle); }
.db-kpi .s.bad { color: var(--st-lost); }
.db-kpi .s.good { color: var(--st-moving); }

/* ---- Cards and grid ---- */

.db-grid { display: grid; grid-template-columns: 1.65fr 1fr; gap: 14px; margin-bottom: 14px; align-items: start; }
.db-grid.single { grid-template-columns: 1fr; }
.db-col { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

.db-card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; min-width: 0; overflow: hidden; }
.db-card .skeleton { margin: 16px; }

.db-cardhd {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 14px 16px; border-bottom: 1px solid var(--border);
}
.db-cardhd.flush { border: none; padding: 2px 0 6px; }
.db-cardhd h3 {
    margin: 0; font-size: 15px; font-weight: 600; color: var(--text);
    text-transform: none; letter-spacing: 0;
}
.db-cardhd .sub { font-size: 12px; color: var(--muted); }
.db-link { color: var(--accent); font-size: 12.5px; font-weight: 600; text-decoration: none; white-space: nowrap; }
.db-link:hover { text-decoration: underline; }
button.db-link { font-size: 12.5px; }

.db-empty { margin: 0; padding: 16px; color: var(--muted); font-size: 13px; }

/* ---- Map ---- */

.db-mapwrap { position: relative; }
.db-map { width: 100%; aspect-ratio: 16 / 9; min-height: 260px; background: #eef2f4; }
:root[data-theme="dark"] .db-map { background: #1c2533; }

.db-maplegend {
    position: absolute; left: 12px; bottom: 12px; z-index: 2;
    background: color-mix(in srgb, var(--surface) 94%, transparent);
    border: 1px solid var(--border); border-radius: 10px; padding: 9px 11px;
    display: flex; gap: 12px; flex-wrap: wrap;
    font-size: 11.5px; color: var(--text-2);
    box-shadow: 0 4px 14px -8px rgba(0, 0, 0, .3);
}
.db-maplegend span { display: inline-flex; align-items: center; gap: 6px; }
.db-maplegend i { width: 9px; height: 9px; border-radius: 50%; }

.db-refreshpill {
    position: absolute; right: 12px; top: 12px; z-index: 2;
    background: color-mix(in srgb, var(--surface) 94%, transparent);
    border: 1px solid var(--border); border-radius: var(--radius-pill);
    padding: 6px 12px; font-size: 12px; color: var(--muted);
    display: flex; align-items: center; gap: 7px;
}

.db-map-note {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 24px;
    text-align: center; color: var(--muted); font-size: 13px;
}

/* The pins drawn by dashboard-map.js: initials in the state's colour, a white ring, a pulse when
   moving, and a ring around whoever is selected. --c is set per pin. */
.db-pin {
    position: relative; width: 25px; height: 25px; padding: 0;
    border-radius: 50%; border: 2.5px solid #fff; background: var(--c);
    color: #fff; font: 700 9.5px/1 var(--font); letter-spacing: .02em;
    display: grid; place-items: center; cursor: pointer;
    box-shadow: 0 2px 6px rgba(0, 0, 0, .25);
}
.db-pin.sel { width: 30px; height: 30px; font-size: 10.5px; box-shadow: 0 0 0 2.5px #fff, 0 0 0 4.5px var(--c), 0 3px 8px rgba(0, 0, 0, .3); }
.db-pin.moving::before {
    content: ""; position: absolute; inset: -6px; border-radius: 50%;
    background: var(--c); opacity: .28; z-index: -1;
    animation: db-pin-pulse 2.2s infinite;
}
@keyframes db-pin-pulse {
    0% { transform: scale(.7); opacity: .3; }
    50% { transform: scale(1.35); opacity: 0; }
    100% { transform: scale(.7); opacity: 0; }
}

/* ---- On-duty list ---- */

.db-od {
    display: flex; align-items: center; gap: 12px;
    padding: 12px 16px; border-bottom: 1px solid var(--border-soft); cursor: pointer;
    transition: background var(--fast) var(--ease);
}
.db-od:last-child { border-bottom: none; }
.db-od:hover, .db-od.sel { background: var(--accent-wash); }
.db-od:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.db-od .ava {
    width: 34px; height: 34px; border-radius: 50%; flex: none;
    display: flex; align-items: center; justify-content: center;
    color: #fff; font-weight: 600; font-size: 12.5px;
}
.db-od .who { min-width: 0; }
.db-od .nm { font-weight: 600; line-height: 1.15; }
.db-od .meta { font-size: 11.5px; color: var(--muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.db-od .right { margin-left: auto; text-align: right; flex-shrink: 0; }
.db-od .seen { font-size: 11.5px; color: var(--muted); margin-top: 4px; white-space: nowrap; }
.db-od .seen.old { color: var(--st-lost); }

.db-pill {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 11.5px; font-weight: 600; padding: 3px 9px;
    border-radius: var(--radius-pill); white-space: nowrap;
}
.db-pill i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.st-moving { background: var(--st-moving-bg); color: var(--st-moving); }
.st-idle { background: var(--st-idle-bg); color: var(--st-idle); }
.st-break { background: var(--st-break-bg); color: var(--st-break); }
.st-lost { background: var(--st-lost-bg); color: var(--st-lost); }
.st-done { background: var(--st-done-bg); color: var(--st-done); }

/* ---- Freshness ---- */

.db-freshbar { display: flex; height: 34px; border-radius: 9px; overflow: hidden; margin: 16px 16px 12px; }
.db-freshbar div { display: flex; align-items: center; justify-content: center; color: #fff; font-weight: 600; font-size: 13px; min-width: 22px; }
.db-freshlegend { display: flex; gap: 16px; padding: 0 16px 14px; flex-wrap: wrap; font-size: 12.5px; color: var(--text-2); }
.db-freshlegend span { display: inline-flex; align-items: center; gap: 7px; }
.db-freshlegend i { width: 9px; height: 9px; border-radius: 2px; }

/* ---- Alerts ---- */

.db-alert { display: flex; gap: 11px; padding: 11px 16px; border-bottom: 1px solid var(--border-soft); }
.db-alert:last-child { border-bottom: none; }
.db-alert .ic { width: 30px; height: 30px; border-radius: 8px; flex: none; display: flex; align-items: center; justify-content: center; }
.db-alert .msg { font-size: 13px; line-height: 1.35; }
.db-alert .msg b { font-weight: 600; }
.db-alert .t { font-size: 11.5px; color: var(--faint); margin-top: 2px; }
.ic-lost { background: var(--st-lost-bg); color: var(--st-lost); }
.ic-ok { background: var(--st-moving-bg); color: var(--st-moving); }
.ic-idle { background: var(--st-idle-bg); color: var(--st-idle); }
.ic-break { background: var(--st-break-bg); color: var(--st-break); }
.ic-done { background: var(--st-done-bg); color: var(--st-done); }

/* ---- Adherence chart ---- */

.db-chartcard { padding: 14px 18px 8px; }
.db-chart { display: block; width: 100%; height: auto; overflow: visible; font-family: var(--font); }
.db-chart .grid-line { stroke: var(--viz-grid); stroke-width: 1; }
.db-chart .tick { fill: var(--muted); font-size: 10.5px; }
.db-chart .line { fill: none; stroke: var(--accent); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.db-chart .hit { fill: transparent; cursor: pointer; }
.db-chart .dot { fill: var(--surface); stroke: var(--accent); stroke-width: 2; pointer-events: none; transition: r var(--fast) var(--ease); }
.db-chart .pt:hover .dot, .db-chart .pt:focus .dot { r: 5; }
.db-chart .pt:focus { outline: none; }
.db-chart .tip { opacity: 0; pointer-events: none; transition: opacity .1s; }
.db-chart .pt:hover .tip, .db-chart .pt:focus .tip { opacity: 1; }
.db-chart .tip rect { fill: var(--navy); }
.db-chart .tip text { fill: #fff; font-size: 12px; }
:root[data-theme="dark"] .db-chart .tip rect { fill: #e6ebf2; }
:root[data-theme="dark"] .db-chart .tip text { fill: #121a26; }
.db-table { margin: 6px 0 12px; }

@media (max-width: 1080px) {
    .db-grid { grid-template-columns: 1fr; }
    .db-kpis { grid-template-columns: repeat(2, 1fr); }
    .db-od .meta { display: none; }
}

@media (max-width: 480px) {
    .db-kpis { grid-template-columns: 1fr 1fr; gap: 10px; }
    .db-kpi .v { font-size: 22px; }
    .db-maplegend { gap: 8px; font-size: 11px; padding: 7px 9px; }
    .db-cardhd { flex-wrap: wrap; }
}

/* The followed vehicle, as the reference navigation view draws it: a car from above, nose up, red
   tail lights, a soft glow. Centred on the fix (the marker element is a point), turned in script. */
.fd-navcar { display: none; position: absolute; left: -15px; top: -27px; width: 30px; height: 54px; pointer-events: none; transform-origin: 50% 50%; }
.fd-navsvg { display: block; width: 100%; height: 100%; overflow: visible;
    filter: drop-shadow(0 0 7px rgba(47, 140, 255, .75)) drop-shadow(0 3px 4px rgba(0, 0, 0, .45)); }
.fd-mk.fd-nav .fd-navcar { display: block; z-index: 1; }
.fd-mk.fd-nav .fd-head, .fd-mk.fd-nav .fd-label, .fd-mk.fd-nav .fd-vehbox, .fd-mk.fd-nav .fd-loc { display: none; }
.fd-mk.fd-nav .fd-stack { bottom: 36px; }
.fd-mk.fd-nav.fd-dismissed .fd-tag { display: none; }
.fd-navcar.fd-navbike { left: -10px; top: -30px; width: 20px; height: 60px; }
.fd-speedbadge { position: absolute; top: 14px; right: 56px; z-index: 3; width: 64px; height: 64px; border-radius: 50%; background: #0a0d12; color: #fff;
    display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1; box-shadow: 0 4px 14px rgba(0, 0, 0, .5); pointer-events: none; }
.fd-speedbadge[hidden] { display: none; }
.fd-speedbadge b { font-size: 24px; font-weight: 700; }
.fd-speedbadge span { font-size: 11px; margin-top: 3px; }

/* ==== Track (/track) =====================================================
   A full-bleed map with the roster panel on its right, as the tracking design has it. The page
   takes the whole content plane, so the content's padding and max width are dropped for it. */

.content:has(> .tk) { padding: 0; max-width: none; overflow: hidden; }

.tk {
    display: grid; grid-template-columns: minmax(0, 1fr) 380px;
    height: calc(100vh - var(--topbar-height)); min-height: 480px;
}
.tk-map-wrap { position: relative; min-width: 0; background: var(--surface-2); }
.tk-map-wrap > .tk-map { position: absolute; inset: 0; }

.tk-panel {
    display: flex; flex-direction: column; min-height: 0;
    background: var(--surface); border-left: 1px solid var(--border);
    box-shadow: -2px 0 8px rgba(0, 0, 0, .04);
}

.tk-icon-btn {
    display: inline-grid; place-items: center; width: 34px; height: 34px; flex: none;
    border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface);
    color: var(--text-2); cursor: pointer; transition: background var(--fast) var(--ease);
}
.tk-icon-btn:hover { background: var(--hover-wash); }
.tk-icon-btn:disabled { opacity: .6; cursor: default; }
.tk-icon-btn svg, .tk-search svg, .tk-date svg, .tk-stats svg {
    width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2;
    stroke-linecap: round; stroke-linejoin: round;
}
.tk-icon-btn.on { color: var(--accent); border-color: var(--accent); background: var(--accent-wash); }
.tk-spin { animation: tk-spin 1s linear infinite; }
@keyframes tk-spin { to { transform: rotate(360deg); } }

.tk-head {
    display: grid; grid-template-columns: 34px 1fr 34px; align-items: center;
    padding: 14px 16px 10px; border-bottom: 1px solid var(--border-soft);
}
.tk-head h1 { margin: 0; text-align: center; font-size: 18px; font-weight: 600; color: var(--navy); }
:root[data-theme="dark"] .tk-head h1 { color: var(--text); }

.tk-search { display: flex; gap: 8px; padding: 14px 16px 8px; }
.tk-search .tk-icon-btn { width: 42px; height: 42px; }
.tk-search-box {
    flex: 1; display: flex; align-items: center; gap: 8px; padding: 0 12px; height: 42px;
    border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2);
    color: var(--muted);
}
.tk-search-box:focus-within { border-color: var(--accent); background: var(--surface); }
.tk-search-box input {
    flex: 1; min-width: 0; border: 0; outline: 0; background: transparent;
    font: inherit; font-size: 14px; color: var(--text); padding: 0;
}

.tk-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 16px 8px; }
.tk-chip {
    display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px;
    border: 1px solid var(--border); border-radius: var(--radius-pill); background: var(--surface);
    font: inherit; font-size: 12px; color: var(--muted); cursor: pointer; opacity: .55;
}
.tk-chip.on { opacity: 1; color: var(--text); border-color: var(--c); }
.tk-chip-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c); }

.tk-tabs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 8px 16px 12px; border-bottom: 1px solid var(--border); }
.tk-tab {
    position: relative; height: 38px; border: 0; border-radius: var(--radius-pill);
    background: transparent; font: inherit; font-size: 14px; color: var(--muted); cursor: pointer;
}
.tk-tab:hover { background: var(--hover-wash); }
.tk-tab.on { background: var(--accent); color: #fff; font-weight: 600; }
.tk-tab-count {
    position: absolute; top: -7px; right: 6px; min-width: 22px; height: 22px; padding: 0 6px;
    display: inline-grid; place-items: center; border-radius: var(--radius-pill);
    background: var(--surface-2); color: var(--text-2); font-size: 11px; font-weight: 700;
    border: 2px solid var(--surface);
}
.tk-tab.on .tk-tab-count { background: #16b886; color: #fff; }

.tk-list { flex: 1; overflow-y: auto; }
.tk-empty { padding: 20px 16px; margin: 0; color: var(--muted); font-size: 13px; }

.tk-row {
    display: flex; align-items: flex-start; gap: 14px; width: 100%; padding: 12px 16px;
    border: 0; border-bottom: 1px solid var(--border-soft); background: transparent;
    font: inherit; text-align: left; color: var(--text); cursor: pointer;
    transition: background var(--fast) var(--ease);
}
.tk-row:hover { background: var(--accent-wash); }
.tk-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.tk-row-skel { cursor: default; align-items: center; }
.tk-row-skel:hover { background: transparent; }
.tk-row-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; padding-top: 2px; }
.tk-row-body strong { font-size: 14px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tk-status { font-size: 12.5px; color: var(--faint); }
.tk-status b { font-weight: 600; }
.tone-ok { color: var(--st-moving); }
.tone-in { color: #1ba3c6; }
.tone-out { color: var(--st-lost); }
.tone-off { color: var(--muted); }

.tk-state {
    flex: none; align-self: center; padding: 2px 8px; border-radius: var(--radius-pill);
    font-size: 11px; font-weight: 600; color: var(--c);
    background: color-mix(in srgb, var(--c) 12%, transparent);
}

.tk-ava-col { flex: none; display: flex; flex-direction: column; align-items: center; gap: 3px; }
.tk-ava {
    position: relative; width: 42px; height: 42px; border-radius: 50%;
    display: grid; place-items: center; background: var(--surface-2);
    box-shadow: 0 0 0 2px var(--surface), 0 0 0 3.5px var(--c);
    color: var(--c); font-weight: 700; font-size: 13px;
}
.tk-ava img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.tk-ava-lg { width: 52px; height: 52px; font-size: 15px; }
.tk-dot {
    position: absolute; top: -1px; right: -2px; width: 11px; height: 11px; border-radius: 50%;
    background: var(--faint); border: 2px solid var(--surface);
}
.tk-dot.on { background: var(--st-moving); }

.tk-batt {
    display: inline-flex; align-items: center; gap: 3px; padding: 0 4px;
    border: 1px solid var(--border); border-radius: 4px; background: var(--surface);
    font-size: 10px; font-weight: 600; line-height: 15px; color: var(--text-2);
}
.tk-batt i {
    position: relative; width: 14px; height: 7px; border: 1.2px solid currentColor; border-radius: 2px;
    background: linear-gradient(90deg, currentColor var(--p), transparent var(--p)) content-box; padding: 1px;
}
.tk-batt.low { color: var(--st-lost); border-color: var(--st-lost); }
.tk-batt.mid { color: var(--warn-fg); }
.tk-batt-sm { margin-left: auto; }

/* ---- Person ---- */

.tk-dhead {
    display: flex; align-items: flex-start; gap: 12px; padding: 14px 14px 12px;
    border-bottom: 1px solid var(--border-soft);
}
.tk-dhead > .tk-icon-btn { border: 0; margin-top: 8px; }
.tk-dhead-who { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; padding-top: 6px; }
.tk-dhead-who strong { font-size: 16px; font-weight: 600; }
.tk-dhead-actions { display: flex; gap: 6px; padding-top: 6px; }
.tk-dhead-actions .tk-icon-btn { width: 30px; height: 30px; }
.tk-ago { font-size: 10.5px; color: var(--faint); }
.tk-phone { font-size: 12px; }

.tk-date {
    display: flex; align-items: center; justify-content: center; gap: 4px;
    margin: 12px auto 10px; padding: 4px; width: max-content;
    border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface);
    box-shadow: var(--elev-1);
}
.tk-date > button {
    display: grid; place-items: center; width: 26px; height: 26px; border: 0; border-radius: 6px;
    background: transparent; color: var(--text-2); cursor: pointer;
}
.tk-date > button:hover:not(:disabled) { background: var(--hover-wash); }
.tk-date > button:disabled { opacity: .35; cursor: default; }
.tk-date-pick {
    position: relative; display: inline-flex; align-items: center; gap: 8px; padding: 0 10px;
    font-size: 13px; font-weight: 500; cursor: pointer;
}
.tk-date-pick input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.tk-date-pick input::-webkit-calendar-picker-indicator { position: absolute; inset: 0; width: auto; height: auto; cursor: pointer; }

.tk-stats { display: grid; grid-template-columns: repeat(3, 1fr); padding: 4px 12px 14px; border-bottom: 1px solid var(--border); text-align: center; }
.tk-stats > div { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.tk-stats svg { width: 26px; height: 26px; stroke-width: 1.7; }
.tk-stat-ic.red { color: var(--st-lost); }
.tk-stat-ic.green { color: var(--st-moving); }
.tk-stat-ic.blue { color: var(--st-break); }
.tk-stats b { font-size: 16px; font-weight: 600; }
.tk-stats span { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); }

.tk-timeline { flex: 1; overflow-y: auto; padding: 12px 0 20px; }
.tk-timeline > .skeleton-line { margin: 10px 16px; }

.tk-ev { display: grid; grid-template-columns: 74px 30px 1fr; gap: 0 10px; padding: 0 16px 0 12px; }
.tk-ev.clickable { cursor: pointer; }
.tk-ev.hl, .tk-ev.clickable:hover { background: var(--accent-wash); }
.tk-ev-time { display: flex; flex-direction: column; padding: 6px 0 18px; font-size: 12px; color: var(--muted); }
.tk-ev-time b { color: var(--text); font-weight: 600; font-size: 12.5px; }
.tk-ev-rail { position: relative; display: flex; justify-content: center; padding-top: 6px; }
.tk-ev-rail::before { content: ""; position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; margin-left: -1px; background: var(--border); }
.tk-ev:first-child .tk-ev-rail::before { top: 14px; }
.tk-ev:last-child .tk-ev-rail::before { bottom: auto; height: 14px; }
.tk-ev-ic {
    position: relative; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
    font-size: 10.5px; font-weight: 700; color: #fff; background: var(--ic);
    box-shadow: 0 0 0 3px var(--surface);
}
.tk-ev-body { padding: 6px 0 16px; min-width: 0; }
.tk-ev-title { display: flex; align-items: center; gap: 8px; }
.tk-ev-title b { font-size: 13.5px; font-weight: 600; color: var(--ic); }
.tk-ev-body p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--text-2); }
.tk-ev-body p.muted { color: var(--muted); }

.k-login { --ic: var(--st-moving); }
.k-wait { --ic: #ef7d22; }
.k-break { --ic: var(--st-break); }
.k-checkin { --ic: #1ba3c6; }
.k-nosignal { --ic: var(--st-done); }
.k-logout { --ic: var(--st-lost); }
.k-now { --ic: var(--accent); }

/* ---- Map markers (track-map.js) ---- */

.tk-pin {
    position: relative; width: 42px; height: 42px; padding: 0; border-radius: 50%;
    border: 3px solid var(--c); background: #e2e8f0; cursor: pointer;
    display: grid; place-items: center; color: #334155; font: 700 13px/1 var(--font);
    box-shadow: 0 0 0 2px #fff, 0 3px 10px rgba(0, 0, 0, .3);
}
.tk-pin img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; pointer-events: none; }
.tk-pin.online::after {
    content: ""; position: absolute; top: -3px; right: -3px; width: 11px; height: 11px;
    border-radius: 50%; background: #12a150; border: 2px solid #fff;
}
.tk-pin.sel { width: 50px; height: 50px; z-index: 3; }

.tk-badge {
    width: 24px; height: 24px; padding: 0; border-radius: 50%; border: 2px solid #fff;
    background: var(--ic); color: #fff; font: 700 11px/1 var(--font); cursor: pointer;
    display: grid; place-items: center; box-shadow: 0 2px 6px rgba(0, 0, 0, .3);
}
.tk-badge-wait { --ic: #ef7d22; }
.tk-badge-break { --ic: #3b73d6; }
.tk-badge-checkin { --ic: #1ba3c6; }

@media (max-width: 900px) {
    .tk { grid-template-columns: 1fr; grid-template-rows: 45vh auto; height: auto; }
    .tk-panel { border-left: 0; border-top: 1px solid var(--border); }
    .tk-list, .tk-timeline { overflow: visible; }
}
