/*
 * Themes. Light is the default; dark applies when <html data-theme="dark"> (set by theme.js from the user's choice:
 * light, dark, or the same as the device). Each theme has a fixed set of colours, inputs included: every field,
 * dropdown, checkbox, radio, slider and button takes its colours from the --input-*, --check-* and --button-* tokens.
 */
:root {
  --paper: #F2EFE9;
  --surface: #FBF9F5;
  --surface-2: #EEEAE3;
  --ink: #221F1B;
  --muted: #69645B;
  --line: #E3DDD3;
  --select: #1F5F8F;
  --select-tint: #E5ECF0;
  --menu-bg: #EEEAE3;
  --menu-line: #D3CBBE;
  --menu-hover: #E1DACE;
  --banner: #FFF4D6;
  --banner-ink: #6B4E00;

  --moving: #1F9D63;
  --idle: #C98A0B;
  --parked: #5B7A90;
  --offline: #A3B1BA;
  --alarm: #C2412D;
  --graph: #1F5F8F; /* the replay graph's lines (checked against --surface in both themes) */
  /* The graph's values, in this order (history-graph.js); validated as a set against --surface, both themes. */
  --g1: #2A78D6; --g2: #EB6834; --g3: #1BAF7A; --g4: #EDA100; --g5: #E87BA4; --g6: #008300; --g7: #6250D6; --g8: #E34948;

  /* inputs: text, number, date and time fields, text areas, dropdowns */
  --input-bg: #FFFDF9;
  --input-ink: #221F1B;
  --input-placeholder: #8C867B;
  --input-border: #CDC5B8;
  --input-border-hover: #9D9487;
  --input-focus: #1F5F8F;
  --input-ring: rgba(31, 95, 143, .22);
  --input-disabled-bg: #EEEAE3;
  --input-disabled-ink: #9D9487;
  --input-invalid: #C2412D;
  /* checkboxes, radios, sliders */
  --check-on: #1F5F8F;
  --check-mark: #FFFFFF;
  --check-off-bg: #FFFDF9;
  /* buttons: main and secondary */
  --button-bg: #1F5F8F;
  --button-ink: #FFFFFF;
  --button-hover: #184D74;
  --button-2-bg: #E9E4DB;
  --button-2-ink: #221F1B;
  --button-2-hover: #DDD6CA;

  --radius: 6px;
  --font: "Inter", system-ui, "Segoe UI", sans-serif;
  /* Sizes (Manage > Style can change them): text scale, the space above and below a control's text, corner rounding */
  --text-scale: 1;
  --cpy: 4px;
  --control-lh: calc(20px * var(--text-scale));
  --control-h: calc(var(--control-lh) + 2 * var(--cpy)); /* inputs, dropdowns and buttons: one height everywhere */
  --control-sm-h: var(--control-h); /* ...the compact set (class "compact"): the same size */
  color-scheme: light;
}

:root[data-theme="dark"] {
  --graph: #3987E5;
  --g1: #3987E5; --g2: #D95926; --g3: #199E70; --g4: #C98500; --g5: #D55181; --g6: #008300; --g7: #9085E9; --g8: #E66767;
  --paper: #121B21;
  --surface: #18232B;
  --surface-2: #213039;
  --ink: #E4EBEF;
  --muted: #93A5B0;
  --line: #2A3A44;
  --select: #6FB0E0;
  --select-tint: #1D3343;
  --menu-bg: #213039;
  --menu-line: #34495A;
  --menu-hover: #2C3F4B;
  --offline: #5E6E78;
  --banner: #3A3016;
  --banner-ink: #F2D58A;

  --input-bg: #0F181E;
  --input-ink: #E4EBEF;
  --input-placeholder: #6D808B;
  --input-border: #3A4D59;
  --input-border-hover: #5A7383;
  --input-focus: #6FB0E0;
  --input-ring: rgba(111, 176, 224, .28);
  --input-disabled-bg: #1B262D;
  --input-disabled-ink: #5E6E78;
  --input-invalid: #F07A66;
  --check-on: #6FB0E0;
  --check-mark: #0F181E;
  --check-off-bg: #0F181E;
  --button-bg: #6FB0E0;
  --button-ink: #0C1419;
  --button-hover: #8CC2EA;
  --button-2-bg: #2A3B46;
  --button-2-ink: #E4EBEF;
  --button-2-hover: #354A57;
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body { background: var(--paper); color: var(--ink); font: calc(14px * var(--text-scale))/1.45 var(--font); }
b, strong, h1, h2, h3, h4, th { font-weight: 600; } /* the font is loaded up to 600: nothing heavier */
button, input, select, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--select); outline-offset: 2px; }

button {
  background: var(--button-bg); color: var(--button-ink); border: 0; border-radius: var(--radius);
  padding: var(--cpy) 12px; font-size: calc(13px * var(--text-scale)); line-height: var(--control-lh); cursor: pointer; font-weight: 400;
}
:where(button:not(:disabled)):hover { background: var(--button-hover); } /* low specificity: any button class wins */
button:disabled { opacity: .6; cursor: default; }
button.secondary { background: var(--button-2-bg); color: var(--button-2-ink); }
button.secondary:hover:not(:disabled) { background: var(--button-2-hover); }
button.small { padding: var(--cpy) 10px; } /* as high as the rest; only narrower */
/* The compact set: inputs, dropdowns and buttons a size smaller, for toolbars (28px high) */
button.compact { height: var(--control-sm-h); padding: calc(var(--cpy) - 1px) 8px; font-size: calc(13px * var(--text-scale)); line-height: var(--control-lh); border: 1px solid var(--line); }
input.compact:not([type=checkbox], [type=radio], [type=range], [type=color], [type=file]), select.compact { height: var(--control-sm-h); padding: calc(var(--cpy) - 1px) 8px; font-size: calc(13px * var(--text-scale)); line-height: var(--control-lh); }
button.link { background: none; color: var(--muted); padding: 4px 6px; font-weight: 400; }
button.link:hover { color: var(--ink); }
button.icon { background: none; color: var(--muted); padding: 4px 8px; font-weight: 400; }
button.danger-link { background: none; color: var(--alarm); padding: 8px 4px; font-weight: 400; }
input, select, textarea {
  background: var(--input-bg); color: var(--input-ink); border: 1px solid var(--input-border); border-radius: var(--radius);
  padding: calc(var(--cpy) - 1px) 8px; font-size: calc(13px * var(--text-scale)); line-height: var(--control-lh); width: 100%;
}
input:not([type=checkbox], [type=radio], [type=range], [type=color], [type=file]), select { height: var(--control-h); }
input:hover:not(:disabled, :focus), select:hover:not(:disabled, :focus), textarea:hover:not(:disabled, :focus) { border-color: var(--input-border-hover); }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--input-focus); box-shadow: 0 0 0 3px var(--input-ring); }
input:disabled, select:disabled, textarea:disabled { background: var(--input-disabled-bg); color: var(--input-disabled-ink); cursor: not-allowed; }
textarea { padding: 5px 8px; }
input:user-invalid, textarea:user-invalid { border-color: var(--input-invalid); }
::placeholder { color: var(--input-placeholder); opacity: 1; }
/* Checkboxes and radios drawn the same in every browser, from the theme's colours. */
input[type=checkbox], input[type=radio] {
  appearance: none; flex: none; width: 18px; height: 18px; padding: 0; margin: 0; display: inline-grid; place-content: center;
  background: var(--check-off-bg); border: 1.5px solid var(--input-border); border-radius: 4px; cursor: pointer; vertical-align: -4px;
}
input[type=radio] { border-radius: 50%; }
input[type=checkbox]:checked, input[type=radio]:checked { background: var(--check-on); border-color: var(--check-on); }
input[type=checkbox]:checked::before { content: ""; width: 5px; height: 10px; margin-top: -2px; border: solid var(--check-mark); border-width: 0 2px 2px 0; transform: rotate(45deg); }
input[type=radio]:checked::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--check-mark); }
input[type=checkbox]:focus-visible, input[type=radio]:focus-visible { box-shadow: 0 0 0 3px var(--input-ring); }
input[type=checkbox]:disabled, input[type=radio]:disabled { opacity: .5; cursor: not-allowed; }
input[type=range] { accent-color: var(--check-on); background: none; border: 0; padding: 0; box-shadow: none; }
input[type=color] { padding: 2px; cursor: pointer; }
label { display: grid; gap: 4px; font-size: calc(13px * var(--text-scale)); color: var(--muted); }
label.check { display: flex; align-items: center; gap: 8px; font-size: calc(14px * var(--text-scale)); color: var(--ink); }
label.check input:not([type=checkbox], [type=radio]) { width: auto; margin: 0; }
.hint { color: var(--muted); font-size: calc(14px * var(--text-scale)); margin: 0; }
small.hint { font-size: calc(12px * var(--text-scale)); }
.form-error { color: var(--alarm); margin: 0; min-height: 1.2em; font-size: calc(14px * var(--text-scale)); }
.spacer { flex: 1; }

/* Sign-in and password forms */
.card-form {
  width: min(360px, calc(100% - 32px)); margin: 16vh auto 0; display: grid; gap: 14px;
  background: var(--surface); padding: 28px; border-radius: 10px; border: 1px solid var(--line);
}
.card-form h1 { margin: 0 0 4px; font-size: calc(26px * var(--text-scale)); letter-spacing: -0.02em; }

/* Shell */
.app { height: 100vh; display: flex; flex-direction: column; }
.topbar {
  flex: 0 0 48px; display: flex; align-items: center; gap: 12px; padding: 0 16px;
  background: var(--surface); border-bottom: 1px solid var(--line);
}
.brand { font-weight: 600; font-size: calc(18px * var(--text-scale)); letter-spacing: -0.01em; }
.account-name { color: var(--muted); padding-left: 12px; border-left: 1px solid var(--line); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 24ch; }
.mainnav { display: flex; gap: 2px; margin-left: 8px; }
.mainnav a { color: var(--muted); text-decoration: none; padding: 13px 10px 11px; border-bottom: 2px solid transparent; }
.mainnav a:hover { color: var(--ink); }
.mainnav a[aria-current] { color: var(--ink); border-bottom-color: var(--select); }
.live { width: 8px; height: 8px; border-radius: 50%; background: var(--offline); }
.live.on { background: var(--moving); }
/* The user menu: the username opens it */
.user-menu { position: relative; }
.user-button { display: flex; align-items: center; gap: 6px; background: none; color: var(--ink); font-weight: 400; font-size: calc(14px * var(--text-scale)); padding: 6px 8px; }
.user-button:hover:not(:disabled), .user-button[aria-expanded="true"] { background: var(--surface-2); }
.user-chevron { color: var(--muted); transition: transform .15s; }
.user-button[aria-expanded="true"] .user-chevron { transform: rotate(180deg); }
.menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 3000; min-width: 210px; padding: 6px; display: grid;
  background: var(--menu-bg); color: var(--ink); border: 1px solid var(--menu-line); border-radius: 8px; box-shadow: 0 10px 32px rgba(10, 20, 28, .22);
}
.menu[hidden] { display: none; }
.menu [role^=menuitem] { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; background: none; color: var(--ink); font-weight: 400; font-size: calc(13px * var(--text-scale)); padding: 5px 10px; border-radius: 5px; }
.menu [role^=menuitem]:hover, .menu [role^=menuitem]:focus-visible { background: var(--menu-hover); outline: none; }
.menu-label { margin: 2px 10px 4px; font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.menu-themes, .menu-languages { display: grid; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.login-language { justify-self: center; }
.login-language select { width: auto; border: 0; background: none; color: var(--muted); padding: 4px 8px; }
/* A theme option: a radio dot that fills when it is the current choice. */
.menu [role=menuitemradio]::before { content: ""; flex: none; width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--input-border); background: var(--check-off-bg); box-sizing: border-box; }
.menu [role=menuitemradio][aria-checked="true"]::before { border: 4px solid var(--check-on); background: var(--check-mark); }
.menu-sep { border: 0; border-top: 1px solid var(--line); margin: 6px 4px; }
.acting-banner {
  display: flex; align-items: center; gap: 12px; padding: 6px 16px; font-size: calc(14px * var(--text-scale));
  background: var(--banner); color: var(--banner-ink); border-bottom: 1px solid var(--line);
}
.acting-banner .link { color: var(--banner-ink); text-decoration: underline; }
.view { flex: 1; min-height: 0; }

/* Map view */
.view-map { display: grid; grid-template-columns: var(--board-width, 360px) 1fr; position: relative; }
.map { min-height: 0; }
/* Shown over the map while offline vehicles are hidden (map options); clicking shows them again. */
.hidden-note {
  position: absolute; left: 50%; bottom: 34px; transform: translateX(-50%); z-index: 2;
  padding: 7px 14px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface); color: var(--ink); font-size: calc(13px * var(--text-scale)); white-space: nowrap;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .18); cursor: pointer;
}
.hidden-note:hover { border-color: var(--select); color: var(--select); }
.hidden-note[hidden] { display: none; }
.board { display: flex; flex-direction: column; min-height: 0; background: var(--surface); border-right: 1px solid var(--line); position: relative; }
.board-tools { padding: 12px; display: grid; gap: 10px; border-bottom: 1px solid var(--line); }
.filters { display: flex; flex-wrap: wrap; gap: 4px; }
.filters button { background: none; color: var(--muted); font-weight: 400; padding: 3px 8px; font-size: calc(13px * var(--text-scale)); border: 1px solid transparent; }
.filters button[aria-pressed="true"] { color: var(--ink); border-color: var(--line); background: var(--surface-2); }
.filters span { font-variant-numeric: tabular-nums; opacity: .7; }
.rows { list-style: none; margin: 0; padding: 0; overflow: auto; flex: 1; }
.row {
  /* name and status | one column per chosen field | ignition | speed. The list sets --row-cols (the same for every row, so
     columns line up) and --row-min (below which it scrolls sideways rather than squeezing the columns). */
  display: grid; grid-template-columns: var(--row-cols, minmax(96px, 1fr) 18px 52px); align-items: center; gap: 2px 12px;
  min-width: var(--row-min, 0);
  padding: 7px 14px 7px 16px; border-bottom: 1px solid var(--line); cursor: pointer;
  border-left: 5px solid var(--status);
}
.row:hover { background: var(--surface-2); }
.row[aria-selected="true"] { background: var(--select-tint); }
.row-name { grid-column: 1; grid-row: 1; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-name small { font-weight: 400; color: var(--muted); }
.row-meta { grid-column: 1; grid-row: 2; font-size: calc(13px * var(--text-scale)); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-speed { grid-row: 1 / 3; grid-column: -2 / -1; text-align: right; font-variant-numeric: tabular-nums; line-height: 1; }
.row-speed b { display: block; font-size: calc(20px * var(--text-scale)); letter-spacing: -0.02em; color: var(--status); }
.row-speed small { font-size: calc(11px * var(--text-scale)); color: var(--muted); }
/* The ignition key: green on, red off, grey when the vehicle has no mapped ignition */
.row-ign { grid-row: 1 / 3; grid-column: -3 / -2; display: flex; justify-content: center; color: var(--offline); }
.row-ign.on { color: var(--moving); }
.row-ign.off { color: var(--alarm); }
.list-head button[data-sort="ignition"] { text-align: center; }
.list-head button[data-sort="ignition"] svg { vertical-align: -2px; }
.list-head button[data-sort="ignition"] .sort-chevron { display: none; } /* no room: the highlight shows it is sorted */
/* Rows carry their status colour inline (--status, from STATUSES in vehicle-layer.js). */
.st-noData { border-left-style: dashed; }
.status-dot { display: inline-block; width: 8px; height: 8px; margin-right: 5px; border-radius: 50%; background: var(--status); vertical-align: 0; }
.rows-empty { padding: 24px 16px; color: var(--muted); }
/* Resizing the list: a handle on its right edge */
.board-resizer { position: absolute; top: 0; right: -4px; bottom: 0; width: 8px; cursor: col-resize; z-index: 4; touch-action: none; }
.board-resizer:hover, .board-resizer:focus-visible, .board-resizer.dragging { background: linear-gradient(90deg, transparent 3px, var(--select) 3px, var(--select) 5px, transparent 5px); outline: none; }
body.resizing { cursor: col-resize; user-select: none; }

/* Sort and the fields picker */
/* Status dropdown, fields picker and search on one row, all in the compact size */
.list-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; } /* the search box goes under the buttons when there is no room */
.list-tools > button, .status-pick { flex: none; }
.list-tools #search { flex: 1 1 150px; min-width: 0; }
.status-pick { position: relative; }
#status-button { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
#status-button .status-dot { margin-right: 1px; }
#status-button span { font-variant-numeric: tabular-nums; opacity: .7; }
#status-button svg { opacity: .7; margin-right: -2px; }
.status-menu {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 20; min-width: 170px;
  flex-direction: column; flex-wrap: nowrap; gap: 2px; padding: 4px;
  background: var(--menu-bg); border: 1px solid var(--menu-line); border-radius: var(--radius); box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
}
.status-menu button { display: flex; align-items: center; width: 100%; text-align: left; color: var(--ink); }
.status-menu button:hover { background: var(--menu-hover); }
.status-menu button span { margin-left: auto; padding-left: 12px; }
.fields-panel { display: grid; gap: 6px; padding: 10px 12px; background: var(--surface-2); border-radius: var(--radius); max-height: 260px; overflow-y: auto; }
.fields-panel .hint { font-size: calc(12px * var(--text-scale)); }
.fields-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 2px 10px; }
.fields-list .check { gap: 7px; min-height: 22px; font-size: calc(12.5px * var(--text-scale)); line-height: 1.2; }
.fields-list input[type=checkbox] { width: 15px; height: 15px; }
.fields-list input[type=checkbox]:checked::before { width: 4px; height: 8px; }
/* Field columns and their header (sticky; click a header to sort by it) */
.cell { grid-row: 1 / 3; font-size: calc(13px * var(--text-scale)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.cell.num { text-align: right; }
.cell.no-value { color: var(--muted); }
.cell .dot { display: inline-block; width: 7px; height: 7px; margin-right: 5px; border-radius: 50%; background: var(--offline); vertical-align: 1px; }
.cell .dot.on { background: var(--moving); }
.list-head {
  position: sticky; top: 0; z-index: 1; display: grid; grid-template-columns: var(--row-cols); gap: 0 12px; min-width: var(--row-min, 0);
  padding: 6px 14px 6px 21px; background: var(--surface); border-bottom: 1px solid var(--line); align-items: end;
}
.list-head button {
  all: unset; cursor: pointer; font-size: calc(12px * var(--text-scale)); line-height: 1.25; color: var(--muted); border-radius: 3px; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; /* long names wrap, at most two lines */
}
.list-head button.num { text-align: right; }
.list-head button:hover { color: var(--ink); }
.list-head button[aria-pressed="true"] { color: var(--ink); font-weight: 600; }
.list-head .sort-chevron { margin-left: 3px; vertical-align: -1px; }
.head-first { display: flex; flex-wrap: wrap; gap: 2px 12px; min-width: 0; }
.head-first button { flex: none; }
.list-head button:focus-visible { outline: 2px solid var(--select); outline-offset: 1px; }
/* A field column's header, with a handle on its right edge (in the gap) to drag its width */
.head-cell { position: relative; min-width: 0; display: flex; align-items: flex-end; }
.head-cell > button { flex: 1; min-width: 0; }
.col-resize { position: absolute; top: -6px; bottom: -6px; right: -9px; width: 6px; cursor: col-resize; touch-action: none; z-index: 1; border-radius: 2px; }
.col-resize:hover, .col-resize:focus-visible, .col-resize.dragging { background: linear-gradient(90deg, transparent 2px, var(--select) 2px, var(--select) 4px, transparent 4px); outline: none; }
/* The group filter: the chosen group's name, cut short */
#group-button { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; max-width: 160px; }
#group-button .group-name { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
#group-button.on { border-color: var(--select); }
#group-button > span:not(.group-name) { font-variant-numeric: tabular-nums; opacity: .7; }
#group-button svg { flex: none; opacity: .7; }
#group-filters { max-height: 320px; overflow-y: auto; }

/* The board's two lists: vehicles and places */
.board-tabs { display: flex; gap: 2px; padding: 4px 12px 0; border-bottom: 1px solid var(--line); }
.board-tabs button { background: none; color: var(--muted); font-weight: 400; border-radius: 0; padding: 8px 10px; border-bottom: 2px solid transparent; }
.board-tabs button[aria-selected="true"] { color: var(--ink); font-weight: 600; border-bottom-color: var(--select); }
.board-pane { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.board-pane[hidden] { display: none; }

/* Places list. Each place carries its colour as --place. */
.place-add { display: flex; flex-wrap: wrap; gap: 6px; }
.place-add[hidden] { display: none; }
.place-row {
  display: grid; grid-template-columns: 16px minmax(0, 1fr) auto; align-items: center; gap: 2px 12px;
  padding: 10px 14px 10px 16px; border-bottom: 1px solid var(--line); cursor: pointer;
}
.place-row:hover { background: var(--surface-2); }
.place-row[aria-selected="true"] { background: var(--select-tint); }
.place-row:focus-visible { outline: 2px solid var(--select); outline-offset: -2px; }
.place-mark {
  grid-row: 1 / 3; width: 16px; height: 16px; border: 2px solid var(--place); border-radius: 3px;
  background: color-mix(in srgb, var(--place) 22%, transparent);
}
.place-mark.is-circle { border-radius: 50%; }
.place-mark.is-path { height: 4px; margin: 6px 0; border: 0; border-radius: 2px; background: var(--place); }
.place-mark.is-poi { width: 12px; height: 12px; margin: 2px; border: 2px solid #fff; border-radius: 50%; background: var(--place); box-shadow: 0 0 0 1px var(--place); }
.place-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.place-meta { grid-column: 2; font-size: calc(13px * var(--text-scale)); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.place-count { grid-column: 3; grid-row: 1 / 3; text-align: right; line-height: 1; font-variant-numeric: tabular-nums; }
.place-count b { display: block; font-size: calc(22px * var(--text-scale)); color: var(--place); }
.place-count small { font-size: calc(11px * var(--text-scale)); color: var(--muted); }
.place-count.none b { color: var(--muted); font-weight: 400; }
.place-row.off-map .place-name, .place-row.off-map .place-mark { opacity: .55; }
.place-mark.has-icon { width: 18px; height: 18px; margin: 0; border: 0; box-shadow: none; display: grid; place-items: center; color: #fff; }
.place-mark.has-icon svg { display: block; }
/* A group's POI icon, in its header and panel; and choosing it in the group's form */
.group-icon { display: inline-grid; place-items: center; color: var(--muted); }
.icon-choice { display: grid; gap: 6px; }
.icon-choice .hint { margin: 0; font-size: calc(13px * var(--text-scale)); }
.icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(34px, 1fr)); gap: 4px; }
.icon-grid label { position: relative; display: grid; place-items: center; height: 34px; border: 1px solid var(--line); border-radius: 6px; cursor: pointer; color: var(--ink); }
.icon-grid label:hover { background: var(--surface-2); }
.icon-grid input { position: absolute; opacity: 0; pointer-events: none; }
.icon-grid label:has(input:checked) { border-color: var(--select); box-shadow: inset 0 0 0 1px var(--select); background: var(--select-tint); color: var(--select); }
.icon-grid label:has(input:focus-visible) { outline: 2px solid var(--select); outline-offset: 1px; }
.icon-grid .dot-choice { width: 12px; height: 12px; border-radius: 50%; background: #C2410C; border: 2px solid #fff; box-shadow: 0 0 0 1px #C2410C; }
/* A geofence group's header in the list */
.group-row {
  display: flex; align-items: center; gap: 6px; padding: 6px 10px 6px 8px; min-height: 36px;
  background: var(--surface-2); border-bottom: 1px solid var(--line); font-size: calc(14px * var(--text-scale));
}
.group-fold { flex: none; width: 24px; height: 24px; padding: 0; display: grid; place-items: center; background: none; color: var(--muted); }
.group-fold .caret { width: 0; height: 0; border: 5px solid transparent; border-top-color: currentColor; margin-top: 5px; transition: transform .15s; }
.group-fold[aria-expanded="false"] .caret { transform: rotate(-90deg) translateX(3px); }
.group-name { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group-name.link { padding: 0; color: var(--ink); text-align: left; background: none; }
.group-name.link:hover { color: var(--select); text-decoration: underline; }
.group-count { color: var(--muted); font-variant-numeric: tabular-nums; }
.group-state { font-size: calc(12px * var(--text-scale)); color: var(--muted); margin-left: auto; }
.group-eye { flex: none; width: 30px; height: 28px; padding: 0; display: grid; place-items: center; background: none; color: var(--muted); border-radius: var(--radius); }
.group-state + .group-eye { margin-left: 0; }
.group-count + .group-eye { margin-left: auto; }
.group-eye svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.group-eye svg .fill { fill: currentColor; }
.group-eye.is-always { color: var(--select); }
:where(button.group-eye):hover { background: var(--line); color: var(--ink); }
.group-empty { padding: 10px 16px 12px 40px; font-size: calc(13px * var(--text-scale)); }
.group-display { display: grid; gap: 8px; }
.group-display label.check { align-items: flex-start; }
.group-display small { display: block; font-size: calc(12px * var(--text-scale)); }
.place-vehicles .link .place-mark { display: inline-block; vertical-align: -2px; margin-right: 8px; width: 12px; height: 12px; }
.place-vehicles .link .place-mark.is-path { height: 4px; vertical-align: 2px; margin-top: 0; margin-bottom: 0; }
.place-vehicles .link .place-mark.has-icon { display: inline-grid; width: 18px; height: 18px; vertical-align: -4px; }
.swatch { display: inline-block; width: 28px; height: 14px; border-radius: 3px; background: var(--place); vertical-align: middle; }

/* Place panel, and the vehicle's places in its details */
.place-actions { display: flex; align-items: center; gap: 8px; margin-top: 18px; }
.place-form .place-actions { margin-top: 4px; }
.place-vehicles li { grid-template-columns: 1fr auto; align-items: baseline; }
.place-vehicles .link { padding: 0; text-align: left; color: var(--ink); font-weight: 600; }
.place-vehicles .link:hover { color: var(--select); text-decoration: underline; }
.draw-hint { margin: 0 0 14px; padding: 10px 12px; border-radius: var(--radius); background: var(--surface-2); font-size: calc(14px * var(--text-scale)); }
.draw-hint.drawing { background: var(--banner); color: var(--banner-ink); }
.draw-tools { display: flex; align-items: center; gap: 8px; margin: -4px 0 14px; }
.draw-tools .hint { flex: 1; font-size: calc(13px * var(--text-scale)); }
.color-field input[type=color] { display: block; width: 64px; height: 32px; padding: 2px; margin-top: 2px; cursor: pointer; }
.place-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.place-chip {
  display: inline-flex; align-items: baseline; gap: 6px; padding: 4px 10px 4px 8px; font-weight: 600; font-size: calc(14px * var(--text-scale));
  background: color-mix(in srgb, var(--place) 12%, var(--surface)); color: var(--ink);
  border: 1px solid color-mix(in srgb, var(--place) 45%, transparent); border-left: 4px solid var(--place);
}
.place-chip.is-poi { border-radius: 999px; border-left-width: 1px; }
.place-chip small { font-weight: 400; color: var(--muted); font-size: calc(12px * var(--text-scale)); }
.place-chip:hover { background: color-mix(in srgb, var(--place) 22%, var(--surface)); }

/* Handles for drawing places on the map (MapLibre markers) */
.place-handle { width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 2.5px solid var(--place); box-shadow: 0 1px 4px rgba(0,0,0,.35); cursor: grab; }
.place-handle:active { cursor: grabbing; }
.place-handle.first { width: 16px; height: 16px; background: var(--place); cursor: pointer; box-shadow: 0 0 0 4px color-mix(in srgb, var(--place) 30%, transparent); }
.place-handle.mid { width: 9px; height: 9px; border-width: 2px; opacity: .65; }
.place-handle.mid:hover { opacity: 1; }
.place-handle.center { width: 14px; height: 14px; background: var(--place); cursor: move; }
.place-handle.edge { width: 14px; height: 14px; border-radius: 3px; cursor: ew-resize; }
.place-handle.poi-dot { width: 18px; height: 18px; background: var(--place); border: 3px solid #fff; box-shadow: 0 0 0 1.5px var(--place), 0 2px 6px rgba(0,0,0,.35); cursor: move; }

.panel {
  position: absolute; top: 12px; right: 12px; bottom: 12px; width: 380px; z-index: 5;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  display: flex; flex-direction: column; box-shadow: 0 8px 28px rgba(22, 36, 45, .18);
}
.panel-head { display: flex; align-items: flex-start; justify-content: space-between; padding: 14px 14px 8px 18px; }
.panel-title { margin: 0; font-size: calc(20px * var(--text-scale)); }
.panel-sub { margin: 2px 0 0; color: var(--muted); font-size: calc(13px * var(--text-scale)); }
.tabs { display: flex; gap: 2px; padding: 0 12px; border-bottom: 1px solid var(--line); overflow-x: auto; }
.tabs button, .subnav button { background: none; color: var(--muted); font-weight: 400; border-radius: 0; padding: 8px 10px; border-bottom: 2px solid transparent; white-space: nowrap; }
.tabs button[aria-selected="true"], .subnav button[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--select); }
.tab-body { padding: 16px 18px; overflow-y: auto; flex: 1; }

/* The vehicle window: its tabs stay put while the tab's content scrolls. */
.vehicle-window .win-body { display: flex; flex-direction: column; overflow: hidden; }
.vehicle-panel { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.vehicle-panel[hidden] { display: none; }
.vehicle-panel .panel-head { padding: 8px 18px 2px; }
.vehicle-panel .panel-sub { margin: 0; }

.facts { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; margin: 0; font-size: calc(14px * var(--text-scale)); }
.facts dt { color: var(--muted); }
.facts dd { margin: 0; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.section-title { font-size: calc(14px * var(--text-scale)); margin: 18px 0 8px; color: var(--muted); font-weight: 400; }

/* Details tab: figures as cards (a grid of tiles) or as a list (label left, value right), as the user picks. */
.details { display: grid; gap: 0; }
.details > * { min-width: 0; }
.details-view { justify-self: end; margin-bottom: 6px; }
.details-view button { padding: 3px 6px; display: inline-grid; place-items: center; }
.dcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 6px; }
.dcard { background: var(--surface-2); border-radius: 8px; padding: 7px 10px; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dcard.wide { grid-column: 1 / -1; }
.dcard > span { font-size: calc(12px * var(--text-scale)); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dcard > b { font-size: calc(16px * var(--text-scale)); font-weight: 600; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.dcard.wide > b { font-size: calc(14px * var(--text-scale)); font-weight: 500; }
.dcard small { font-weight: 400; }
.as-list .dcards { display: block; }
.as-list .dcard { flex-direction: row; justify-content: space-between; align-items: baseline; gap: 16px; background: none; border-radius: 0; padding: 4px 0; border-bottom: 1px solid var(--line); }
.as-list .dcard > span { font-size: calc(14px * var(--text-scale)); flex: none; max-width: 45%; }
.as-list .dcard > b, .as-list .dcard.wide > b { font-size: calc(14px * var(--text-scale)); font-weight: 400; text-align: right; }
.details-section .seg-buttons { margin-bottom: 8px; }
.stack { display: grid; gap: 10px; }
.inline { display: flex; gap: 8px; align-items: end; }
.inline > label { flex: 1; }
.playback { display: grid; gap: 6px; margin-top: 14px; }
.playback input[type=range] { padding: 0; border: 0; }
.playback output { font-size: calc(13px * var(--text-scale)); color: var(--muted); font-variant-numeric: tabular-nums; }
.list { list-style: none; margin: 0; padding: 0; font-size: calc(14px * var(--text-scale)); }
.list li { padding: 8px 0; border-bottom: 1px solid var(--line); display: grid; gap: 2px; }
.list small { color: var(--muted); }
.badge { font-size: calc(12px * var(--text-scale)); padding: 1px 7px; border-radius: 4px; background: var(--surface-2); color: var(--muted); white-space: nowrap; }
.badge.sent, .badge.ok { color: var(--moving); }
.badge.failed { color: var(--alarm); }
.badge.warn { color: var(--idle); }
button.danger { background: var(--alarm); color: #fff; }
button.danger:hover { filter: brightness(.92); }
#command-list li { grid-template-columns: 1fr auto; align-items: center; column-gap: 8px; padding: 6px 0; }
#command-list li > small { grid-column: 1 / -1; }

/* Tracker terminal: always dark, like a console. Received lines cyan, sent lines amber, connection notes grey. */
/* Commands tab: text and Send on one line; Recent and Terminal fold away. */
.command-send { display: flex; gap: 8px; align-items: stretch; }
.command-send input { flex: 1; min-width: 0; }
.command-send input.preset { color: var(--muted); font-family: ui-monospace, Consolas, monospace; font-size: calc(13px * var(--text-scale)); }
.command-send button { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.fold { margin-top: 14px; }
.fold-head { display: flex; align-items: center; gap: 12px; }
.fold-head .check { font-size: calc(13px * var(--text-scale)); color: var(--muted); }
.fold-toggle { display: inline-flex; align-items: center; gap: 6px; margin-right: auto; padding: 4px 0; background: none; color: var(--muted); font-weight: 400; font-size: calc(14px * var(--text-scale)); }
.fold-toggle:hover { color: var(--ink); }
.fold-toggle svg { transition: transform .15s; }
.fold-toggle[aria-expanded="false"] svg { transform: rotate(-90deg); }
.fold-head:has([aria-expanded="false"]) > :not(.fold-toggle) { display: none; }
.fold-body { margin-top: 4px; }
#command-list { max-height: 320px; overflow-y: auto; }

/* Server > Device types > Commands */
.type-commands { display: grid; gap: 6px; }
.tc-row { display: grid; grid-template-columns: minmax(140px, 1fr) minmax(200px, 2fr) 56px 36px; gap: 8px; align-items: center; }
.tc-head { font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.tc-row .check { justify-self: center; }
.tc-row .mono { font-family: ui-monospace, Consolas, monospace; font-size: calc(13px * var(--text-scale)); }
.actions-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.actions-row [data-save] { margin-left: auto; }
@media (max-width: 640px) { .tc-row { grid-template-columns: 1fr 44px 36px; } .tc-row [name=text] { grid-column: 1 / -1; grid-row: 2; } .tc-head { display: none; } }
.terminal {
  --t-in: #5CC8F5; --t-out: #F5B544; --t-info: #8A9BA6;
  background: #0E171D; color: #CFD9DE; border-radius: var(--radius); margin-top: 8px; padding: 6px 0;
  height: 340px; overflow-y: auto; font: 12px/1.45 ui-monospace, Consolas, monospace; overscroll-behavior: contain;
}
.terminal:focus-visible { outline: 2px solid var(--select); outline-offset: 2px; }
.t-line { display: grid; grid-template-columns: auto auto 1fr; gap: 0 8px; padding: 3px 10px; border-left: 3px solid transparent; }
.t-line + .t-line { border-top: 1px solid #1B2730; }
.t-line time { color: #6E808B; }
.t-arrow { display: inline-flex; align-items: center; width: 14px; }
.t-in { border-left-color: var(--t-in); }
.t-in .t-arrow, .t-in .t-sum { color: var(--t-in); }
.t-out { border-left-color: var(--t-out); }
.t-out .t-arrow, .t-out .t-sum { color: var(--t-out); }
.t-info .t-arrow, .t-info .t-sum { color: var(--t-info); font-style: italic; }
.t-raw { grid-column: 3; color: inherit; opacity: .62; word-break: break-all; font: inherit; font-size: calc(11px * var(--text-scale)); }
.t-in .t-raw { color: var(--t-in); }
.t-out .t-raw { color: var(--t-out); }
.terminal.hide-raw .t-raw { display: none; }
.t-line[data-hex] { cursor: copy; }
.t-line[data-hex]:hover { background: #15222B; }
.t-line.copied { animation: t-copied .8s ease-out; }
@keyframes t-copied { from { background: #24506B; } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) { .t-line.copied { animation: none; outline: 1px solid #24506B; } }
.t-empty { color: var(--t-info); padding: 8px 12px; margin: 0; }
.terminal-key { margin-top: 6px; }
.terminal-key .t-in { color: #0B7FB0; border: 0; }
.terminal-key .t-out { color: #A86A00; border: 0; }
:root[data-theme="dark"] .terminal-key .t-in { color: #5CC8F5; }
:root[data-theme="dark"] .terminal-key .t-out { color: #F5B544; }

/* Admin pages */
.view-page { overflow-y: auto; }
.subnav { display: flex; gap: 2px; padding: 0 24px; background: var(--surface); border-bottom: 1px solid var(--line); overflow-x: auto; }
.page-body { padding: 24px; } /* pages use the whole width */
.page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 16px; }
.page-head h1 { margin: 0 0 4px; font-size: calc(22px * var(--text-scale)); letter-spacing: -0.01em; }
.page-head .hint { max-width: 70ch; }

/* Ticking rows in a table, and what to do with them */
.grid .dt-check { width: 34px; padding-right: 0; }
.grid .dt-check input { margin: 0; }
.grid tr[aria-selected="true"] td { background: var(--select-tint); }
.grid .row-actions { text-align: right; white-space: nowrap; }
.bulk-bar { display: flex; align-items: center; gap: 8px; padding: 8px 12px; margin-bottom: 10px; border-radius: var(--radius); background: var(--select-tint); }
.bulk-bar .bulk-count { margin-right: auto; font-weight: 600; }
.bulk-bar[hidden] { display: none; }
.notice { padding: 10px 14px; margin-bottom: 14px; border-radius: var(--radius); background: var(--banner); color: var(--banner-ink); }
.notice ul { margin: 6px 0 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.notice li { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.notice .hint { color: inherit; opacity: .8; }
code { font-family: ui-monospace, Consolas, monospace; font-size: .92em; }

/* Manage: categories down the side, a category's pages as tabs */
.manage { display: grid; grid-template-columns: 216px minmax(0, 1fr); min-height: 100%; }
.manage-side { background: var(--surface); border-right: 1px solid var(--line); }
.manage-nav { position: sticky; top: 0; display: grid; gap: 2px; padding: 14px 10px; }
.manage-nav a { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: var(--radius); color: var(--muted); text-decoration: none; font-weight: 500; }
.manage-nav a svg { flex: none; }
.manage-nav a:hover { background: var(--surface-2); color: var(--ink); }
.manage-nav a[aria-current="page"] { background: var(--select-tint); color: var(--ink); font-weight: 600; box-shadow: inset 3px 0 0 var(--select); }
.manage-nav a[aria-current="page"] svg { color: var(--select); }
.manage-main { min-width: 0; }
.manage-tabs { padding: 0 24px; }
.subnav a { color: var(--muted); padding: 10px 12px 8px; border-bottom: 2px solid transparent; text-decoration: none; white-space: nowrap; }
.subnav a:hover { color: var(--ink); }
.subnav a[aria-current="page"] { color: var(--ink); border-bottom-color: var(--select); font-weight: 600; }
@media (max-width: 760px) {
  .manage { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .manage-side { border-right: 0; border-bottom: 1px solid var(--line); }
  .manage-nav { position: static; grid-auto-flow: column; justify-content: start; overflow-x: auto; padding: 8px 12px; }
  .manage-nav a { padding: 8px 10px; }
  .manage-tabs { padding: 0 12px; }
}
.page-actions { display: flex; gap: 8px; flex-shrink: 0; }
.grid { width: 100%; border-collapse: collapse; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; font-size: calc(14px * var(--text-scale)); }
.grid th { text-align: left; font-weight: 400; color: var(--muted); font-size: calc(13px * var(--text-scale)); padding: 9px 12px; border-bottom: 1px solid var(--line); background: var(--surface-2); }
.grid td { padding: 10px 12px; border-bottom: 1px solid var(--line); vertical-align: top; }
.grid tr:last-child td { border-bottom: 0; }
.grid td small { color: var(--muted); }
.grid .num { text-align: right; font-variant-numeric: tabular-nums; }
.grid tr.clickable { cursor: pointer; }
.grid tr.clickable:hover td { background: var(--select-tint); }
/* Rows of wide lists: tinted under the pointer, and the one last clicked stays marked (app.js) with an edge on the left. */
.grid tbody tr:hover td, .map-row:not(.map-head):hover { background: var(--select-tint); }
.grid tbody tr.picked td, .map-row.picked { background: var(--select-tint); }
.grid tbody tr.picked td:first-child { box-shadow: inset 3px 0 0 var(--select); }
.map-row.picked { box-shadow: inset 3px 0 0 var(--select); }
.empty { padding: 32px; text-align: center; color: var(--muted); background: var(--surface); border: 1px dashed var(--line); border-radius: 8px; }

/* Signal mapping editor */
.page-content section + section, .page-content > section + details { margin-top: 28px; }
.page-content h2 { font-size: calc(16px * var(--text-scale)); margin: 0 0 10px; }
.map-rows { display: grid; gap: 0; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; }
.map-row { display: grid; grid-template-columns: minmax(150px, 1.1fr) minmax(130px, 1fr) minmax(150px, 1fr) minmax(200px, 1.6fr) minmax(80px, .6fr) 36px; gap: 10px; align-items: start; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.map-row:last-child { border-bottom: 0; }
.map-head { background: var(--surface-2); color: var(--muted); font-size: calc(13px * var(--text-scale)); border-radius: 8px 8px 0 0; padding-top: 8px; padding-bottom: 8px; }
.map-row > span { display: grid; gap: 4px; }
.map-settings { display: flex !important; flex-wrap: wrap; gap: 8px; align-items: center; }
.map-settings textarea { font: 13px/1.4 var(--font); }
.inline-field { display: inline-flex; align-items: center; gap: 4px; font-size: calc(14px * var(--text-scale)); color: var(--ink); }
.map-result { font-variant-numeric: tabular-nums; padding-top: 7px; font-weight: 600; }
.map-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.map-row.read-only > span { padding-top: 2px; }
/* Devices (devices.js): protocol → device type → mapper, then the mapper's rules */
.mapper-bar { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: flex-end; margin-bottom: 16px; }
.mapper-bar > label { display: grid; gap: 4px; font-size: calc(13px * var(--text-scale)); color: var(--muted); width: 240px; }
.mapper-bar > label[hidden] { display: none; }
.mapper-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 12px; }
.mapper-head h2 { margin: 0 0 4px; font-size: calc(17px * var(--text-scale)); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.mapper-head .hint { margin: 2px 0; max-width: 80ch; }
.mapper-tools { display: flex; gap: 8px; flex-shrink: 0; }
.mapper-choice { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.mapper-choice > :nth-child(3) { grid-column: 1 / -1; }
.mapper-choice.automatic { grid-template-columns: minmax(0, 1fr); }
.mapper-choice.automatic > :not(:first-child) { display: none; }
.raw-fields .facts { margin-top: 2px; }
/* Sections of the vehicle window's Details tab: each folds away with a click on its title. */
.dsec > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 4px; user-select: none; }
.dsec > summary::-webkit-details-marker { display: none; }
.dsec > summary:hover { color: var(--ink); }
.dsec > summary .dsec-chevron { flex: none; transition: transform .15s; }
.dsec[open] > summary .dsec-chevron { transform: rotate(90deg); }
.back-link { display: inline-block; margin-bottom: 8px; color: var(--muted); text-decoration: none; font-size: calc(14px * var(--text-scale)); }
.back-link:hover { color: var(--ink); }

@media (max-width: 900px) {
  .map-row { grid-template-columns: 1fr 1fr; }
  .map-head { display: none; }
  .mapper-bar > label { width: 100%; }
  .mapper-head { flex-direction: column; }
  .mapper-choice { grid-template-columns: minmax(0, 1fr); }
}

.icon-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 6px; max-height: 220px; overflow-y: auto; }
.icon-picker label { display: grid; justify-items: center; gap: 2px; padding: 6px 4px; border: 1px solid var(--line); border-radius: 6px; cursor: pointer; font-size: calc(12px * var(--text-scale)); color: var(--ink); text-align: center; }
.icon-picker label:has(input:checked) { border-color: var(--select); background: var(--select-tint); }
.icon-picker label:has(input:focus-visible) { outline: 2px solid var(--select); outline-offset: 1px; }
.icon-picker input { position: absolute; opacity: 0; pointer-events: none; }
.icon-thumb { width: 28px; height: 28px; vertical-align: middle; }
.icon-thumb.tint { color: var(--moving); }
.share-url { display: flex; gap: 8px; }
.share-url input { font-family: ui-monospace, Consolas, monospace; font-size: calc(13px * var(--text-scale)); }
.perm-list { display: flex; flex-wrap: wrap; gap: 4px; }

/* Dialogs */
dialog { border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: var(--ink); padding: 0; width: min(480px, calc(100% - 32px)); max-height: calc(100vh - 48px); overflow-y: auto; }
dialog::backdrop { background: rgba(22, 36, 45, .4); }
.dialog-form { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px; padding: 22px; }
.dialog-form > * { grid-column: 1 / -1; }
.dialog-form h2 { margin: 0; font-size: calc(20px * var(--text-scale)); }
.dialog-form .field { display: grid; gap: 4px; align-content: start; }
.dialog-form .field.half { grid-column: auto; }
.dialog-actions { display: flex; align-items: center; gap: 8px; margin-top: 4px; position: sticky; bottom: -22px; background: var(--surface); padding: 10px 0 0; }
.dialog-actions > :first-child:not(.danger-link) { margin-left: auto; }
fieldset { border: 1px solid var(--line); border-radius: var(--radius); padding: 8px 12px 10px; margin: 0; }
legend { font-size: calc(13px * var(--text-scale)); color: var(--muted); padding: 0 4px; }
.checklist { display: grid; gap: 6px; max-height: 180px; overflow-y: auto; }
.field-label { font-size: calc(13px * var(--text-scale)); color: var(--muted); }

/* Windows (window.js): title bar to drag, edges to resize, maximise, close */
dialog.win { position: fixed; inset: 0; margin: auto; height: fit-content; max-width: calc(100vw - 16px); max-height: calc(100vh - 16px);
  overflow: hidden; padding: 0; box-shadow: 0 12px 40px rgba(10, 20, 28, .28); }
dialog.win[open] { display: flex; flex-direction: column; }
dialog.win:not([open]) { display: none; }
.win-head { display: flex; align-items: center; gap: 2px; padding: 2px 4px 2px 14px; border-bottom: 1px solid var(--line);
  background: var(--surface-2); cursor: move; user-select: none; touch-action: none; flex: none; }
.win-title { margin: 0; font-size: calc(14px * var(--text-scale)); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.win-btn { display: grid; place-items: center; width: 24px; height: 24px; padding: 0; border-radius: var(--radius); cursor: pointer; }
.win-btn:hover { background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--ink); }
.win-body { flex: 1; min-height: 0; overflow: auto; }
.win-rz { position: absolute; z-index: 1; touch-action: none; }
.win-rz-n, .win-rz-s { left: 10px; right: 10px; height: 6px; cursor: ns-resize; }
.win-rz-e, .win-rz-w { top: 10px; bottom: 10px; width: 6px; cursor: ew-resize; }
.win-rz-n { top: 0; } .win-rz-s { bottom: 0; } .win-rz-e { right: 0; } .win-rz-w { left: 0; }
.win-rz-ne, .win-rz-se, .win-rz-sw, .win-rz-nw { width: 14px; height: 14px; }
.win-rz-ne { top: 0; right: 0; cursor: nesw-resize; } .win-rz-sw { bottom: 0; left: 0; cursor: nesw-resize; }
.win-rz-nw { top: 0; left: 0; cursor: nwse-resize; } .win-rz-se { bottom: 0; right: 0; cursor: nwse-resize; }
/* A small grip in the corner people usually resize from. */
.win-rz-se::after { content: ""; position: absolute; right: 3px; bottom: 3px; width: 7px; height: 7px;
  border-right: 2px solid var(--line); border-bottom: 2px solid var(--line); border-bottom-right-radius: 2px; }
dialog.win.win-maxed { inset: 8px; margin: 0; width: auto !important; height: auto !important; max-width: none; max-height: none; }
dialog.win.win-maxed .win-rz { display: none; }
body.win-dragging { user-select: none; }
body.win-dragging dialog.win { transition: none; }
.form-window .dialog-form { padding-top: 16px; }
@media (max-width: 640px) {
  dialog.win { inset: 0; margin: 0; width: 100% !important; height: 100% !important; max-width: none; max-height: none; border-radius: 0; border: 0; }
  .win-head { cursor: default; }
  .win-rz, [data-win-max] { display: none; }
}

/* Dropdowns (select.js): the native <select> stays for forms, hidden; a button and a list replace it on screen */
.sel { position: relative; display: block; min-width: 0; }
.sel-native { position: absolute; left: 0; bottom: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none; padding: 0; border: 0; }
.sel-button { display: flex; align-items: center; gap: 8px; width: 100%; min-height: var(--control-h); padding: calc(var(--cpy) - 1px) 8px; font-size: calc(13px * var(--text-scale)); line-height: var(--control-lh); text-align: left;
  background: var(--input-bg); color: var(--input-ink); border: 1px solid var(--input-border); border-radius: var(--radius); font-weight: 400; cursor: pointer; }
.sel-button:hover:not(:disabled) { background: var(--input-bg); border-color: var(--input-border-hover); }
.sel-button[aria-expanded="true"], .sel-button:focus-visible { border-color: var(--input-focus); box-shadow: 0 0 0 3px var(--input-ring); outline: none; }
.sel-button:disabled { background: var(--input-disabled-bg); color: var(--input-disabled-ink); }
.sel-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sel-placeholder { color: var(--input-placeholder); }
.sel-chevron { flex: none; color: var(--muted); transition: transform .15s; }
.sel-button[aria-expanded="true"] .sel-chevron { transform: rotate(180deg); }
.sel-pop { position: fixed; inset: auto; margin: 0; padding: 6px; display: flex; flex-direction: column; gap: 6px; z-index: 2000;
  background: var(--menu-bg); color: var(--ink); border: 1px solid var(--menu-line); border-radius: 8px; box-shadow: 0 8px 28px rgba(10, 20, 28, .22); overflow: hidden; }
.sel-pop:not(:popover-open)[popover] { display: none; }
.sel-pop[hidden] { display: none; }
.sel-search { width: 100%; flex: none; }
.sel-tools { display: flex; align-items: center; gap: 2px; flex: none; font-size: calc(13px * var(--text-scale)); }
.sel-tools .link { font-size: calc(13px * var(--text-scale)); padding: 2px 6px; }
.sel-tools .link:hover { color: var(--select); }
.sel-count { margin-left: auto; color: var(--muted); padding-right: 4px; font-variant-numeric: tabular-nums; }
.sel-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; min-height: 0; flex: 1; outline: none; }
.sel-list [role=option] { display: flex; align-items: flex-start; gap: 8px; padding: 7px 8px; border-radius: 5px; cursor: pointer; font-size: calc(14px * var(--text-scale));
  content-visibility: auto; contain-intrinsic-size: auto 34px; } /* thousands of options: only those in view are laid out */
.sel-list [role=option].active { background: var(--menu-hover); }
.sel-list [role=option][aria-selected="true"] { color: var(--select); font-weight: 600; }
.sel-multi .sel-list [role=option][aria-selected="true"], .sel-pop:has([aria-multiselectable]) [role=option][aria-selected="true"] { font-weight: 400; color: var(--ink); }
.sel-list [role=option][aria-disabled="true"] { opacity: .5; cursor: default; }
.sel-text { display: grid; min-width: 0; }
.sel-text small { color: var(--muted); font-weight: 400; font-size: calc(12px * var(--text-scale)); }
.sel-check { flex: none; width: 16px; height: 16px; margin-top: 2px; border: 1.5px solid var(--input-border); background: var(--check-off-bg); border-radius: 4px; display: grid; place-items: center; }
[aria-selected="true"] > .sel-check { background: var(--check-on); border-color: var(--check-on); }
[aria-selected="true"] > .sel-check::after { content: ""; width: 4px; height: 8px; border: solid var(--check-mark); border-width: 0 2px 2px 0; transform: translateY(-1px) rotate(45deg); }
.sel-group { padding: 8px 8px 2px; font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.sel-empty { margin: 0; padding: 8px; color: var(--muted); font-size: calc(13px * var(--text-scale)); }

/* Date and time pickers (datepicker.js): the real input, with a calendar button in it and a pop-up in the app's style */
.dp { position: relative; display: block; min-width: 0; }
.dp.dp-compact { display: inline-block; }
.dp > input.dp-input { padding-right: 30px; }
.dp-input::-webkit-calendar-picker-indicator { display: none; }
.dp-button { position: absolute; top: 50%; right: 3px; transform: translateY(-50%); display: grid; place-items: center; width: 24px; height: 22px; padding: 0;
  background: none; color: var(--muted); border-radius: 4px; }
.dp-button:hover:not(:disabled), .dp-button[aria-expanded="true"] { background: var(--menu-hover); color: var(--ink); }
.dp:has(> input:disabled) .dp-button { opacity: .5; pointer-events: none; }
.dp-pop { position: fixed; inset: auto; margin: 0; padding: 8px; width: 260px; display: grid; gap: 8px; z-index: 2000;
  background: var(--menu-bg); color: var(--ink); border: 1px solid var(--menu-line); border-radius: 8px; box-shadow: 0 8px 28px rgba(10, 20, 28, .22); font-size: calc(13px * var(--text-scale)); }
.dp-pop:not(:popover-open)[popover] { display: none; }
.dp-head { display: flex; align-items: center; gap: 4px; }
.dp-head .dp-step { width: 28px; height: 28px; padding: 0; display: grid; place-items: center; color: var(--ink); }
.dp-head .dp-step:hover, .dp-title:hover { background: var(--menu-hover); }
.dp-title { flex: 1; color: var(--ink); font-weight: 600; text-transform: capitalize; padding: 4px 6px; border-radius: var(--radius); }
.dp-body { display: grid; gap: 2px; }
.dp-days { grid-template-columns: repeat(7, 1fr); }
.dp-months { grid-template-columns: repeat(3, 1fr); gap: 4px; }
.dp-wd { text-align: center; color: var(--muted); font-size: calc(12px * var(--text-scale)); padding: 2px 0 4px; text-transform: capitalize; }
.dp-cell { height: 30px; padding: 0; background: none; color: var(--ink); font-weight: 400; border-radius: var(--radius); font-variant-numeric: tabular-nums; text-transform: capitalize; }
.dp-months .dp-cell { height: 40px; }
.dp-cell:hover:not(:disabled) { background: var(--menu-hover); }
.dp-cell.out { color: var(--muted); }
.dp-cell.today { box-shadow: inset 0 0 0 1px var(--select); }
.dp-cell.on, .dp-cell.on:hover:not(:disabled) { background: var(--button-bg); color: var(--button-ink); font-weight: 600; }
.dp-cell:disabled { opacity: .35; }
.dp-cell:focus-visible { outline: 2px solid var(--select); outline-offset: 1px; }
.dp-time { display: flex; align-items: center; gap: 4px; padding-top: 8px; border-top: 1px solid var(--menu-line); }
.dp-pop:not(:has(.dp-head)) .dp-time { padding-top: 0; border-top: 0; }
.dp-time-label { margin-right: auto; color: var(--muted); }
.dp-time input { width: 44px; text-align: center; font-variant-numeric: tabular-nums; }
.dp-foot { display: flex; align-items: center; gap: 4px; }
.dp-foot .link { padding: 4px 6px; font-size: calc(13px * var(--text-scale)); }
.dp-foot .link:hover { color: var(--select); }
.dp-foot [data-done] { margin-left: auto; }

/* Tables (datatable.js): search, sort by heading, row count, show more */
.dt-tools { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.dt-search { width: min(320px, 100%); }
.dt-count { color: var(--muted); font-size: calc(13px * var(--text-scale)); font-variant-numeric: tabular-nums; }
.dt-sort { background: none; color: inherit; padding: 0; font: inherit; font-weight: inherit; border-radius: 3px; display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.dt-sort:hover { color: var(--ink); }
th[aria-sort="ascending"] .dt-sort, th[aria-sort="descending"] .dt-sort { color: var(--ink); font-weight: 600; }
.grid th.num .dt-sort { flex-direction: row-reverse; }
/* Column widths (datatable.js): an edge to drag on each heading; once one is set the table keeps them (fixed layout),
   cuts what doesn't fit, and scrolls sideways when the columns are wider than the page */
.dt-table { overflow-x: auto; }
.grid th[data-col] { position: relative; }
.dt-resize { position: absolute; top: 0; bottom: 0; right: -3px; width: 7px; cursor: col-resize; touch-action: none; z-index: 1; }
.dt-resize:hover, .dt-resize:focus-visible, .dt-resize.dragging { background: linear-gradient(90deg, transparent 2px, var(--select) 2px, var(--select) 4px, transparent 4px); outline: none; }
.grid.dt-fixed { table-layout: fixed; }
.grid.dt-fixed td, .grid.dt-fixed th { overflow: hidden; overflow-wrap: anywhere; }
.grid.dt-fixed th .dt-sort { max-width: 100%; }
.dt-arrow { display: inline-flex; min-width: 13px; }
.dt-arrow .dt-idle { opacity: 0; }
.dt-sort:hover .dt-arrow .dt-idle { opacity: .45; }
.dt-foot { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.dt-foot:empty { display: none; }

/* Toasts */
.toasts { position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); display: grid; gap: 8px; z-index: 3000; } /* above floating windows */
.toast {
  background: var(--ink); color: var(--paper); padding: 10px 16px; border-radius: var(--radius);
  border-left: 4px solid var(--alarm); box-shadow: 0 6px 20px rgba(0,0,0,.25);
}
.toast-info { border-left-color: var(--moving); }
.toast { display: flex; gap: 10px; align-items: baseline; }
.toast-count { font-weight: 600; font-variant-numeric: tabular-nums; }
.toast-count:empty, .toast[data-count="1"] .toast-count { display: none; }

/* Map layer switcher (MapLibre control) */
.layer-control { position: relative; }
.layer-control .layer-toggle { width: 29px; height: 29px; padding: 0; display: grid; place-items: center; color: #333; background: #fff; border-radius: 4px; }
.layer-panel {
  position: absolute; top: 0; left: 36px; z-index: 3; width: max-content; min-width: 180px; max-width: min(330px, calc(100vw - 90px));
  max-height: calc(100vh - 170px); overflow-y: auto; display: grid; gap: 8px; padding: 10px;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 6px 20px rgba(22, 36, 45, .18); font: 13px var(--font);
}
/* Compact: one line per option as far as the width allows. */
.layer-panel fieldset { display: grid; gap: 1px; padding: 3px 10px 7px; }
.layer-panel legend { font-size: calc(12px * var(--text-scale)); }
.layer-panel label.check { gap: 7px; min-height: 24px; font-size: calc(13px * var(--text-scale)); line-height: 1.25; }
.layer-panel input[type=checkbox], .layer-panel input[type=radio] { width: 15px; height: 15px; vertical-align: -3px; }
.layer-panel input[type=checkbox]:checked::before { width: 4px; height: 8px; }
.layer-panel input[type=radio]:checked::before { width: 7px; height: 7px; }
.layer-panel .hint { font-size: calc(12px * var(--text-scale)); line-height: 1.3; margin-top: 2px; width: 0; min-width: 100%; } /* wraps to the options' width, never widens it */
.layer-panel .traffic input:disabled + * , .layer-panel .traffic:has(input:disabled) { color: var(--muted); }
.options-panel [data-fit] { width: 100%; white-space: nowrap; }
.options-panel .inline-select { gap: 12px; min-height: 30px; margin-top: 2px; font-size: calc(13px * var(--text-scale)); }
/* MapLibre styles every button in a control as a 29 px icon box: a dropdown in the panel is a field again. */
.maplibregl-ctrl-group .layer-panel .sel-button { display: flex; width: 100%; height: auto; min-height: 28px; padding: 3px 8px;
  background: var(--input-bg); border: 1px solid var(--input-border); border-radius: var(--radius); color: var(--input-ink); font-size: calc(13px * var(--text-scale)); }
.maplibregl-ctrl-group .options-panel .inline-select .sel-button { width: auto; gap: 6px; }
.inline-select { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--ink); font-size: calc(14px * var(--text-scale)); }
.inline-select select { width: auto; padding: 3px 6px; }
.layer-control .layer-toggle.active { color: var(--select); box-shadow: inset 0 0 0 2px var(--select); }

.maplibregl-popup-content { background: var(--surface); color: var(--ink); font: 14px var(--font); }
/* The tip in the popup's colour, in both themes. */
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip, .maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip, .maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip { border-top-color: var(--surface); }
.maplibregl-popup-anchor-top .maplibregl-popup-tip, .maplibregl-popup-anchor-top-left .maplibregl-popup-tip, .maplibregl-popup-anchor-top-right .maplibregl-popup-tip { border-bottom-color: var(--surface); }
.maplibregl-popup-anchor-left .maplibregl-popup-tip { border-right-color: var(--surface); }
.maplibregl-popup-anchor-right .maplibregl-popup-tip { border-left-color: var(--surface); }

/* The light map engine (leaflet-gl.js): Leaflet's panes stay in a layer of their own, under the controls, the address
   search and whatever else the app puts on the map; popups and markers keep MapLibre's look. */
.lgl-surface { position: absolute; inset: 0; z-index: 0; outline: none; }
.lgl-surface.leaflet-container { font: 12px/20px var(--font); }
.lgl-surface .maplibregl-popup { display: flex; pointer-events: none; z-index: 1; }
.lgl-surface .maplibregl-popup a { color: var(--select); }
.lgl-surface .maplibregl-marker { z-index: 1; }
.lgl-surface .leaflet-control-attribution { font-size: calc(11px * var(--text-scale)); background: rgba(255, 255, 255, .7); }
.lgl-canvas { pointer-events: none; }

/* Address search over the map (geosearch.js), right of the map buttons */
.geo-search { position: absolute; top: 10px; left: 52px; z-index: 3; width: min(340px, calc(100% - 64px)); }
.geo-search input { padding-left: 32px; box-shadow: 0 1px 4px rgba(0, 0, 0, .18); }
.geo-search-icon { position: absolute; left: 10px; top: 11px; color: var(--muted); pointer-events: none; }
.geo-results { list-style: none; margin: 4px 0 0; padding: 4px; max-height: 320px; overflow-y: auto; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 8px 28px rgba(10, 20, 28, .22); }
.geo-results [role=option] { display: grid; gap: 1px; padding: 7px 9px; border-radius: 5px; cursor: pointer; font-size: calc(14px * var(--text-scale)); }
.geo-results [role=option] b { font-weight: 400; }
.geo-results [role=option] small { color: var(--muted); font-size: calc(12px * var(--text-scale)); }
.geo-results [role=option]:hover, .geo-results [aria-selected="true"] { background: var(--surface-2); }
.geo-note { padding: 8px 9px; color: var(--muted); font-size: calc(13px * var(--text-scale)); }
.geo-pin { width: 22px; height: 30px; background: no-repeat center/contain url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 30'%3E%3Cpath d='M11 29C11 29 21 17.5 21 10.5A10 10 0 0 0 1 10.5C1 17.5 11 29 11 29Z' fill='%23C2412D' stroke='white' stroke-width='2'/%3E%3Ccircle cx='11' cy='10.5' r='3.6' fill='white'/%3E%3C/svg%3E"); cursor: pointer; }
.maplibregl-popup-close-button { color: var(--muted); background: none; font-size: calc(18px * var(--text-scale)); padding: 0 6px; }
.address-row { display: flex; gap: 8px; }
.address-row input { flex: 1; min-width: 0; }
.address-field label { font-size: calc(13px * var(--text-scale)); color: var(--muted); }
.address-hint:empty { display: none; }
.bell-address { margin: 2px 0 0; font-size: calc(13px * var(--text-scale)); color: var(--muted); }
.geocoder-result .facts { margin-top: 4px; }
@media (max-width: 760px) { .geo-search { left: 50px; width: calc(100% - 62px); } }

@media (max-width: 900px) {
  .account-name { display: none; }
  .grid { display: block; overflow-x: auto; }
}

@media (max-width: 760px) {
  .app { height: auto; min-height: 100vh; }
  .view-map { grid-template-columns: 1fr; grid-template-rows: 45vh auto; }
  .view-map .map { grid-row: 1; }
  .board { border-right: 0; }
  .board-resizer { display: none; }
  .panel { position: fixed; inset: 56px 8px 8px 8px; width: auto; }
  .page-body { padding: 16px; }
  .page-head { flex-direction: column; }
}

@media (prefers-reduced-motion: reduce) {
  * { scroll-behavior: auto !important; transition: none !important; }
}

/* Notifications: the bell in the top bar and its panel */
.bell { position: relative; background: none; color: var(--muted); padding: 6px 8px; border-radius: var(--radius); display: grid; place-items: center; }
.bell:hover, .bell[aria-expanded="true"] { color: var(--ink); background: var(--surface-2); }
.bell:focus-visible { outline: 2px solid var(--select); outline-offset: 1px; }
.bell-count {
  position: absolute; top: 1px; right: 0; min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px;
  background: var(--alarm); color: #fff; font-size: calc(11px * var(--text-scale)); font-weight: 600; line-height: 17px; text-align: center; font-variant-numeric: tabular-nums;
}
.bell-count[hidden] { display: none; }
.bell-panel {
  position: fixed; top: 52px; right: 12px; z-index: 3000; width: min(420px, calc(100vw - 24px)); max-height: calc(100vh - 72px);
  display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 10px 32px rgba(22, 36, 45, .22); overflow: hidden;
}
.bell-panel[hidden] { display: none; }
.bell-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; padding: 12px 14px 10px; border-bottom: 1px solid var(--line); }
.bell-head h2 { margin: 0; font-size: calc(17px * var(--text-scale)); flex: 1; }
.bell-head .link { padding: 2px 4px; font-size: calc(13px * var(--text-scale)); }
.bell-filter { display: flex; gap: 2px; order: 3; width: 100%; }
.bell-filter button { background: none; color: var(--muted); font-weight: 400; padding: 2px 8px; font-size: calc(13px * var(--text-scale)); border: 1px solid transparent; }
.bell-filter button[aria-pressed="true"] { color: var(--ink); border-color: var(--line); background: var(--surface-2); }
.bell-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; }
.bell-item { --kind: var(--select); padding: 10px 14px 10px 12px; border-bottom: 1px solid var(--line); border-left: 4px solid var(--kind); }
.bell-item.t-speeding, .bell-item.t-alarm { --kind: var(--alarm); }
.bell-item.t-idle { --kind: var(--idle); }
.bell-item.t-offline { --kind: var(--offline); }
.bell-item.t-signal { --kind: #9B3FB5; }
.bell-item.done { border-left-color: var(--line); }
.bell-item.done .bell-message { font-weight: 400; color: var(--muted); }
.bell-message { margin: 0; font-weight: 600; font-size: calc(14px * var(--text-scale)); overflow-wrap: anywhere; }
.bell-meta { margin: 2px 0 0; display: flex; justify-content: space-between; gap: 8px; color: var(--muted); font-size: calc(12px * var(--text-scale)); }
.bell-meta time { white-space: nowrap; font-variant-numeric: tabular-nums; }
.deliveries { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 4px; font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.delivery.failed { color: var(--alarm); }
.delivery.sent { color: var(--moving); }
.bell-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 6px; }
.bell-actions .link { padding: 2px 0; font-size: calc(13px * var(--text-scale)); color: var(--select); text-align: left; }
.bell-actions small { color: var(--muted); font-size: calc(12px * var(--text-scale)); }
.bell-empty { padding: 20px 16px; }
.bell-more { margin: 10px 14px; align-self: start; }

/* Server settings forms */
.settings-form { margin-bottom: 20px; }
/* The pages are full width; a field doesn't need to be. */
.settings-form select, .settings-form .sel, .settings-form input:not([type=checkbox]):not([type=radio]) { max-width: 480px; }
.settings-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 14px; }
.settings-row .narrow { max-width: 120px; }
.settings-row:has(.narrow) { grid-template-columns: 1fr 120px; }
/* A row of port numbers (and what goes with them), side by side. */
.settings-row.ports { display: flex; flex-wrap: wrap; align-items: end; }
.settings-row.ports .narrow { width: 120px; }
.settings-row.ports .badge { margin-bottom: 9px; }
@media (max-width: 760px) { .settings-row, .settings-row:has(.narrow) { grid-template-columns: 1fr; } }

/* Segmented period buttons (history, trips) */
.seg-buttons { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.seg-buttons button[aria-pressed="true"], .seg-buttons button[aria-pressed="true"]:hover { background: var(--button-bg); color: var(--button-ink); border-color: var(--button-bg); }

/* History tab: period, summary, trips and stops, points, playback */
/* The trips (or points) list takes the rest of the window's height; the tab scrolls only when the window is very short. */
.tab-body:has(> .hist) { display: flex; flex-direction: column; }
.hist { flex: 1 0 auto; display: flex; flex-direction: column; gap: 10px; }
.hist-range { display: grid; gap: 8px; }
.hist-dates { display: flex; flex-wrap: wrap; align-items: end; gap: 8px; }
.hist-dates label { display: grid; gap: 2px; font-size: calc(13px * var(--text-scale)); color: var(--muted); flex: 1 1 150px; }
.hist-dates input { width: 100%; }
.hist-result { flex: 1 0 auto; display: flex; flex-direction: column; gap: 10px; }
.hist-body { flex: 1 1 0; min-height: 200px; display: flex; flex-direction: column; }
.hist-summary { display: flex; flex-wrap: wrap; margin: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.hist-summary > div { flex: 1 1 96px; padding: 8px 10px; box-shadow: 1px 0 0 var(--line), 0 1px 0 var(--line); }
.hist-summary dt { font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.hist-summary dd { margin: 2px 0 0; font-size: calc(17px * var(--text-scale)); font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hist-note { margin: -4px 0 0; font-size: calc(12px * var(--text-scale)); }
.hist-views { display: flex; gap: 2px; border-bottom: 1px solid var(--line); }
.hist-views button { background: none; color: var(--muted); font-weight: 400; border-radius: 0; padding: 6px 10px; border-bottom: 2px solid transparent; }
.hist-views button[aria-selected="true"] { color: var(--ink); font-weight: 600; border-bottom-color: var(--select); }
.hist-views span { font-size: calc(12px * var(--text-scale)); color: var(--muted); font-weight: 400; margin-left: 2px; }
.hist-segments { list-style: none; margin: 0; padding: 0; flex: 1 1 0; min-height: 0; overflow: auto; }
.seg-row { display: grid; grid-template-columns: 26px minmax(0, 1fr); gap: 10px; padding: 8px 6px; border-bottom: 1px solid var(--line); cursor: pointer; font-size: calc(14px * var(--text-scale)); }
.seg-row:hover { background: var(--surface-2); }
.seg-row[aria-selected="true"] { background: var(--select-tint); }
.seg-row:focus-visible { outline: 2px solid var(--select); outline-offset: -2px; }
.seg-mark { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; font-size: calc(12px * var(--text-scale)); font-weight: 600; }
.is-trip .seg-mark { background: var(--trip); color: #fff; }
.is-stop .seg-mark { background: var(--surface); color: #1F5F8F; border: 2px solid #1F5F8F; border-radius: 6px; width: 22px; height: 22px; }
.is-gap .seg-mark { color: var(--muted); border-color: var(--muted); border-style: dashed; }
.is-stop { background: color-mix(in srgb, var(--surface-2) 50%, transparent); }
.seg-main { min-width: 0; display: grid; gap: 2px; }
.seg-line { display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: baseline; font-variant-numeric: tabular-nums; }
.seg-line span { color: var(--muted); }
.seg-line .seg-km { color: var(--ink); font-weight: 600; margin-left: auto; }
.seg-places { display: grid; gap: 1px; font-size: calc(13px * var(--text-scale)); color: var(--muted); min-width: 0; }
.seg-place { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.seg-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; vertical-align: 1px; box-sizing: border-box; }
.is-from .seg-dot { border: 2px solid var(--trip, var(--moving)); }
.is-to .seg-dot { background: var(--trip, var(--moving)); }
.seg-facts { font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.hist-points { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: var(--radius); font-size: calc(13px * var(--text-scale)); font-variant-numeric: tabular-nums; }
.hist-points:focus-visible { outline: 2px solid var(--select); outline-offset: 1px; }
.pt-head, .pt-row { display: grid; grid-template-columns: minmax(118px, 1.2fr) 40px 32px 30px 56px minmax(0, 1.5fr); gap: 6px; padding: 0 8px; align-items: center; }
.pt-head { height: 30px; background: var(--surface-2); color: var(--muted); font-size: calc(12px * var(--text-scale)); border-bottom: 1px solid var(--line); }
.pt-scroll { flex: 1 1 0; min-height: 0; overflow: auto; }
.pt-space { position: relative; }
.pt-rows { position: absolute; left: 0; right: 0; top: 0; }
.pt-row { height: 30px; border-bottom: 1px solid var(--line); cursor: pointer; white-space: nowrap; }
.pt-row span { overflow: hidden; text-overflow: ellipsis; }
.pt-row:hover { background: var(--surface-2); }
.pt-row.current { background: var(--select-tint); font-weight: 600; box-shadow: inset 3px 0 0 var(--select); }
.pt-row.no-fix { color: var(--muted); }
.hist-play { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; align-items: center; gap: 8px; }
.hist-play .play[aria-pressed="true"] { background: var(--select-tint); color: var(--select); }
.hist-play input[type=range] { padding: 0; border: 0; }
.hist-play select { width: auto; padding-top: 4px; padding-bottom: 4px; }
.hist-play output { grid-column: 1 / -1; font-size: calc(13px * var(--text-scale)); color: var(--muted); font-variant-numeric: tabular-nums; }
.hist-play .play { width: 30px; padding: var(--cpy) 0; display: grid; place-items: center; }

/* Manage → Settings */
.settings-layout { display: block; }
.settings-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 14px 18px; }
.settings-grid label { display: grid; gap: 4px; align-content: start; }
.settings-grid .wide { grid-column: 1 / -1; max-width: 760px; }
.with-unit { display: flex; align-items: center; gap: 8px; }
.with-unit input { width: 120px; }
.with-unit span { color: var(--muted); font-size: calc(14px * var(--text-scale)); }
.settings-category label.check { align-items: flex-start; }
.settings-category label.check small, .settings-grid small { display: block; font-size: calc(12px * var(--text-scale)); }
.form-actions { display: flex; align-items: center; gap: 8px; }

/* Manage → Trips */
.trips-filter { display: flex; flex-wrap: wrap; align-items: end; gap: 10px 14px; margin-bottom: 12px; }
.trips-filter > label { display: grid; gap: 4px; font-size: calc(13px * var(--text-scale)); color: var(--muted); }
.trips-vehicles { min-width: 260px; flex: 1 1 260px; max-width: 420px; }
.trips-total { max-width: 560px; margin-bottom: 8px; }

/* Manage → Reports */
.report-filter .trips-vehicles { flex-basis: 220px; max-width: 320px; }
.report-choice { border: 0; margin: 0; padding: 0; display: grid; gap: 4px; }
.report-choice legend { padding: 0; margin-bottom: 4px; font-size: calc(13px * var(--text-scale)); color: var(--muted); }
.trips-filter > label.report-stops { display: flex; align-self: end; min-height: var(--control-h); font-size: calc(13px * var(--text-scale)); color: var(--ink); }
.report-title { margin: 8px 0 6px; font-size: calc(18px * var(--text-scale)); }
.report-facts { display: grid; grid-template-columns: max-content 1fr; gap: 2px 14px; margin: 0 0 12px; font-size: calc(13px * var(--text-scale)); }
.report-facts > div { display: contents; }
.report-facts dt { color: var(--muted); }
.report-facts dd { margin: 0; }
.report-summary { max-width: 760px; margin-bottom: 10px; }
.report-note { font-style: italic; }
.report-table { overflow-x: auto; margin-bottom: 6px; }
.report-table .grid { font-size: calc(13px * var(--text-scale)); }
.report-table .grid td, .report-table .grid th { padding: 6px 9px; }
.report-table .grid td.num { white-space: nowrap; }
.grid tr.row-muted td { color: var(--muted); }
.grid tr.row-warning td { color: var(--alarm); }
.grid tr.row-subtotal td { background: var(--surface-2); font-weight: 600; }
.grid tr.row-total td { background: var(--select-tint); font-weight: 600; }
.report-generated { margin-top: 14px; }

/* Server > Listeners: messages per minute over the last hour. */
.sparkline { display: block; fill: var(--select); }
.listener-process { margin-bottom: 12px; }
.listener-firewall { margin-top: 14px; }
.listener-firewall code { display: inline-block; margin-top: 4px; padding: 4px 8px; background: var(--surface-2); border-radius: var(--radius); user-select: all; overflow-wrap: anywhere; }
.listener-disconnect { display: flex; gap: 10px; align-items: end; max-width: 560px; margin-top: 18px; }
.listener-disconnect label { flex: 1; }
.listener-new-trackers { margin-top: 18px; display: grid; gap: 6px; }
.listener-new-trackers[hidden] { display: none; }
.inventory-filter { margin-bottom: 12px; }

/* Server > Web & HTTPS. */
.web-section { margin-bottom: 26px; }
.web-section h2 { font-size: calc(16px * var(--text-scale)); margin: 0 0 8px; }
.web-form { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: end; margin: 6px 0; }
.web-form label:not(.check) { display: grid; gap: 4px; min-width: 220px; }
.web-form label.narrow { min-width: 0; width: 140px; }
.web-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.job-output { max-height: 60vh; overflow: auto; margin: 0; padding: 10px 12px; background: var(--surface-2); border-radius: var(--radius); font: 12px/1.45 ui-monospace, Consolas, monospace; white-space: pre-wrap; overflow-wrap: anywhere; }
.banner-note { padding: 10px 14px; border-radius: var(--radius); background: var(--banner); color: var(--banner-ink); }
/* Server > Backups */
.backup-form { display: grid; gap: 10px; max-width: 760px; }
.backup-form .web-form label:not(.narrow):not(.check) { flex: 1 1 360px; min-width: min(100%, 360px); }
.web-section .facts + .web-actions, .web-section .facts ~ .web-actions { margin-top: 12px; }
.backup-form .check input[type=time] { margin-left: 6px; width: auto; }
.help-steps-list { margin: 8px 0 0; padding-left: 22px; display: grid; gap: 4px; max-width: 760px; }

/* Questions and notices (confirm.js). */
button.danger { background: var(--alarm); color: #fff; }
:where(button.danger:not(:disabled)):hover { background: color-mix(in srgb, var(--alarm) 85%, #000); }
.confirm-window .win-body { overflow: visible; }
.confirm { display: grid; gap: 14px; padding: 18px 22px 18px; }
.confirm-text { display: flex; gap: 14px; align-items: flex-start; }
.confirm-text p { margin: 0 0 8px; line-height: 1.5; }
.confirm-text p:last-child { margin-bottom: 0; }
.confirm-icon { flex: none; margin-top: 1px; color: var(--select); }
.confirm-danger .confirm-icon { color: var(--alarm); }
.confirm-warning .confirm-icon { color: var(--idle); }
.confirm-details { margin: 6px 0 0; padding-left: 18px; color: var(--muted); font-size: calc(13px * var(--text-scale)); }
.confirm-type { margin-left: 42px; }
.confirm .dialog-actions { position: static; padding: 0; }

/* Icons (Lucide, icons.js): inline with text, in its colour. */
svg.lucide { flex: none; vertical-align: -2px; }
.back-link svg.lucide { vertical-align: -2px; }
.from-arrow { color: var(--muted); }
.manage-nav svg.lucide { vertical-align: middle; }

/* MapLibre's own buttons (zoom, compass, attribution) with Lucide icons. */
.maplibregl-ctrl button .maplibregl-ctrl-icon { background-image: none !important; background-color: #333;
  -webkit-mask: var(--ctrl-icon) center / 18px 18px no-repeat; mask: var(--ctrl-icon) center / 18px 18px no-repeat; }
.maplibregl-ctrl button.maplibregl-ctrl-zoom-in .maplibregl-ctrl-icon { --ctrl-icon: url("data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%2024%2024%27%20fill=%27none%27%20stroke=%27black%27%20stroke-width=%272%27%20stroke-linecap=%27round%27%20stroke-linejoin=%27round%27%3E%3Cpath%20d=%27M5%2012h14%27/%3E%3Cpath%20d=%27M12%205v14%27/%3E%3C/svg%3E"); }
.maplibregl-ctrl button.maplibregl-ctrl-zoom-out .maplibregl-ctrl-icon { --ctrl-icon: url("data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%2024%2024%27%20fill=%27none%27%20stroke=%27black%27%20stroke-width=%272%27%20stroke-linecap=%27round%27%20stroke-linejoin=%27round%27%3E%3Cpath%20d=%27M5%2012h14%27/%3E%3C/svg%3E"); }
.maplibregl-ctrl button.maplibregl-ctrl-compass .maplibregl-ctrl-icon { --ctrl-icon: url("data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%2024%2024%27%20fill=%27none%27%20stroke=%27black%27%20stroke-width=%272%27%20stroke-linecap=%27round%27%20stroke-linejoin=%27round%27%3E%3Cpolygon%20points=%2712%202%2019%2021%2012%2017%205%2021%2012%202%27/%3E%3C/svg%3E"); }
.maplibregl-ctrl-attrib-button { background-image: none !important; background-color: #333;
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%2024%2024%27%20fill=%27none%27%20stroke=%27black%27%20stroke-width=%272%27%20stroke-linecap=%27round%27%20stroke-linejoin=%27round%27%3E%3Ccircle%20cx=%2712%27%20cy=%2712%27%20r=%2710%27/%3E%3Cpath%20d=%27M12%2016v-4%27/%3E%3Cpath%20d=%27M12%208h.01%27/%3E%3C/svg%3E") center / 16px 16px no-repeat; mask: url("data:image/svg+xml,%3Csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20viewBox=%270%200%2024%2024%27%20fill=%27none%27%20stroke=%27black%27%20stroke-width=%272%27%20stroke-linecap=%27round%27%20stroke-linejoin=%27round%27%3E%3Ccircle%20cx=%2712%27%20cy=%2712%27%20r=%2710%27/%3E%3Cpath%20d=%27M12%2016v-4%27/%3E%3Cpath%20d=%27M12%208h.01%27/%3E%3C/svg%3E") center / 16px 16px no-repeat; }

/* Server > Database */
.db-check-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.db-check { display: grid; grid-template-columns: 24px minmax(0, 1fr); gap: 10px; align-items: start; }
.db-check-icon { display: inline-flex; padding: 0; background: none; margin-top: 1px; }
.db-query { font-size: calc(12px * var(--text-scale)); white-space: pre-wrap; overflow-wrap: anywhere; display: block; max-width: 520px; color: var(--muted); }

/* Context menus (menu.js) */
.context-menu { position: fixed; z-index: 4000; min-width: 220px; max-width: 320px; padding: 6px; background: var(--menu-bg); color: var(--ink);
  border: 1px solid var(--menu-line); border-radius: var(--radius); box-shadow: 0 10px 30px rgba(0,0,0,.22); display: grid; }
.context-menu .context-title { margin: 2px 8px 6px; font-size: calc(12px * var(--text-scale)); color: var(--muted); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.context-menu button { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 28px; height: auto; padding: 4px 8px; border: 0; font-size: calc(13px * var(--text-scale));
  background: none; color: inherit; text-align: left; font-weight: 400; border-radius: calc(var(--radius) - 2px); cursor: pointer; }
.context-menu button:hover:not([disabled]), .context-menu button:focus-visible { background: var(--menu-hover); outline: none; }
.context-menu button[disabled] { opacity: .45; cursor: default; }
.context-menu button svg { color: var(--muted); width: 15px; height: 15px; flex: none; }
.context-menu .danger-item { color: var(--alarm); }
.context-menu .context-gap { width: 15px; }
.context-menu .menu-sep { margin: 4px 2px; border-top-color: var(--menu-line); }

/* Route planning (routing.js) */
.route-point { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; font-size: calc(12px * var(--text-scale)); font-weight: 600;
  color: #fff; background: #7A3FC4; border: 2px solid #fff; box-shadow: 0 2px 6px rgba(0,0,0,.35); cursor: grab; flex: none; }
.route-point.is-start { background: #1F9D63; }
.route-point.is-end { background: #B0233A; }
.maplibregl-marker.route-point:active { cursor: grabbing; }
.route-body { display: grid; gap: 10px; padding: 12px 14px; }
.route-points { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.route-points li { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 10px; align-items: center; }
.route-points .route-point { cursor: default; box-shadow: none; }
.route-where { font-size: calc(13px * var(--text-scale)); overflow-wrap: anywhere; }
.route-summary { margin: 0; font-size: calc(15px * var(--text-scale)); }
.route-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.route-actions button { display: inline-flex; align-items: center; gap: 6px; }
/* One position of a vehicle's history (history.js): from the points list or a click on the route. */
.point-pop .maplibregl-popup-content { padding: 0 12px 10px; font-size: calc(13px * var(--text-scale)); max-height: min(60vh, 460px); overflow-y: auto; border-radius: 10px;
  width: max-content; min-width: 260px; max-width: min(400px, calc(100vw - 24px)); box-shadow: 0 6px 24px rgba(10, 20, 28, .24); }
.point-pop .facts dd { overflow-wrap: break-word; } /* "anywhere" let the popup shrink until values broke mid-word */
/* Header: the vehicle's name and plate, staying in view while the readings scroll; the close button sits on it */
.point-pop .point-head {
  position: sticky; top: 0; z-index: 1; margin: 0 -12px 8px; padding: 8px 34px 8px 12px;
  background: var(--surface-2); border-bottom: 1px solid var(--line); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: calc(14px * var(--text-scale));
}
.point-pop .point-head small { color: var(--muted); font-size: calc(12px * var(--text-scale)); }
/* A place's popup (What's here?, a found address): fixed width, so a long address wraps evenly; each line copied with a click. */
.place-pop .maplibregl-popup-content { width: 300px; min-width: 0; }
.point-pop .point-head > svg { flex: none; vertical-align: -2px; color: var(--muted); }
.copy-line { display: flex; align-items: flex-start; gap: 6px; width: calc(100% + 12px); margin: 0 -6px 2px; padding: 3px 6px; border-radius: 6px;
  background: none; color: var(--ink); font-weight: 400; text-align: left; line-height: 1.4; cursor: pointer; }
.copy-line.point-address-copy { font-weight: 600; }
.copy-line.point-coords { color: var(--muted); font-variant-numeric: tabular-nums; }
.copy-line .copy-icon { flex: none; margin-left: auto; padding-top: 2px; color: var(--muted); opacity: 0; transition: opacity .15s; }
.copy-line:hover { background: var(--surface-2); }
.copy-line:hover .copy-icon, .copy-line:focus-visible .copy-icon, .copy-line.copied .copy-icon { opacity: 1; }
.copy-line.copied .copy-icon { color: var(--ok, #1F9D63); }
.place-pop-actions { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line); }
.place-pop-actions button { display: inline-flex; align-items: center; gap: 6px; }
.point-pop .point-time { margin: 0 0 2px; font-weight: 600; }
.point-pop .point-address { margin: 0 0 8px; color: var(--muted); }
.point-pop .facts { font-size: calc(13px * var(--text-scale)); gap: 0; margin: 0 -6px; }
/* Name left, value right; every other row shaded, the one under the pointer highlighted, so a value is easy to pair with its name. */
.point-pop .facts dt, .point-pop .facts dd { padding: 3px 6px; }
.point-pop .facts dt { border-radius: 4px 0 0 4px; }
.point-pop .facts dd { padding-left: 16px; text-align: right; border-radius: 0 4px 4px 0; }
.point-pop .facts dt:nth-of-type(even), .point-pop .facts dd:nth-of-type(even) { background: color-mix(in srgb, var(--surface-2) 60%, transparent); }
.point-pop .facts dt:hover, .point-pop .facts dt:hover + dd, .point-pop .facts dd:hover, .point-pop .facts dt:has(+ dd:hover) { background: var(--select-tint); }
.point-pop .point-received { margin-top: 8px; }
.point-pop .point-sec { margin-top: 10px; }
/* A section's title folds it away (Readings, raw data), like the vehicle window's sections. */
.point-pop .point-sec > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 4px; margin-bottom: 4px; user-select: none;
  font-size: calc(12px * var(--text-scale)); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.point-pop .point-sec > summary::-webkit-details-marker { display: none; }
.point-pop .point-sec > summary:hover { color: var(--ink); }
.point-pop .point-sec > summary .dsec-chevron { flex: none; transition: transform .15s; }
.point-pop .point-sec[open] > summary .dsec-chevron { transform: rotate(90deg); }
/* The selected vehicle's popup (map option "When I select a vehicle": a popup), with shortcuts. */
/* The point pop-up's look: a tinted header with the name and the close button, rounded corners. Also the settings' preview. */
.vehicle-pop .maplibregl-popup-content { padding: 0; border-radius: 10px; overflow: hidden; box-shadow: 0 6px 24px rgba(10, 20, 28, .24); }
:is(.vehicle-pop, .point-pop) .maplibregl-popup-close-button { z-index: 2; top: 5px; right: 5px; width: 24px; height: 24px; padding: 0; border-radius: 6px; line-height: 1; }
:is(.vehicle-pop, .point-pop) .maplibregl-popup-close-button:hover { background: color-mix(in srgb, var(--ink) 10%, transparent); color: var(--ink); }
:is(.vehicle-pop, .point-pop):is(.maplibregl-popup-anchor-top, .maplibregl-popup-anchor-top-left, .maplibregl-popup-anchor-top-right) .maplibregl-popup-tip { border-bottom-color: var(--surface-2); }
.vp { width: var(--vp-w, 300px); max-width: calc(100vw - 24px); font-size: calc(13px * var(--text-scale)); color: var(--ink); background: var(--surface); }
.vp-head { display: flex; align-items: baseline; gap: 7px; padding: 8px 34px 8px 12px; background: var(--surface-2); border-bottom: 1px solid var(--line);
  font-size: calc(14px * var(--text-scale)); white-space: nowrap; overflow: hidden; }
.vp-head b { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.vp-head small { flex: none; color: var(--muted); font-size: calc(12px * var(--text-scale)); }
.vp-dot { flex: none; align-self: center; width: 9px; height: 9px; border-radius: 50%; background: var(--status); }
.vp-body { padding: 8px 12px 6px; }
.vp-body:not(:has(*)) { display: none; }
.vp-status { font-weight: 600; }
.vp-line { margin: 0 0 3px; }
/* A long address keeps to its lines (Settings): the last one fades out; the whole address shows on hover. */
.vp-address { --lh: 1.4em; margin: 0 0 4px; color: var(--muted); line-height: var(--lh); max-height: calc(var(--vp-lines, 2) * var(--lh)); overflow: hidden; overflow-wrap: anywhere; }
.vp-address.clipped {
  -webkit-mask-image: linear-gradient(#000, #000), linear-gradient(to right, #000 55%, transparent 95%);
  mask-image: linear-gradient(#000, #000), linear-gradient(to right, #000 55%, transparent 95%);
  -webkit-mask-size: 100% calc(100% - var(--lh)), 100% 100%; mask-size: 100% calc(100% - var(--lh)), 100% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-position: top left; mask-position: top left;
}
.vp-actions { display: flex; gap: 2px; margin: 6px -6px 0; padding-top: 4px; border-top: 1px solid var(--line); }
.vp-actions button { padding: 6px 7px; border-radius: 6px; }
.vp-actions button:hover { background: var(--surface-2); color: var(--ink); }
.vp-actions button[aria-pressed="true"] { color: var(--select); }
/* Manage › Settings › Vehicle popup: the choices beside a preview on a map-like background. */
.popup-settings { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px; align-items: start; }
.popup-preview { position: sticky; top: 12px; display: grid; gap: 8px; justify-items: center; padding: 28px 24px 36px; border-radius: 10px; border: 1px solid var(--line);
  background: linear-gradient(135deg, color-mix(in srgb, var(--ok, #1F9D63) 10%, var(--paper)), color-mix(in srgb, var(--select) 10%, var(--paper))); }
.popup-preview .vp-frame { position: relative; border-radius: 10px; overflow: hidden; box-shadow: 0 6px 24px rgba(10, 20, 28, .24); }
.popup-preview .vp-close { position: absolute; top: 5px; right: 5px; display: grid; place-items: center; width: 24px; height: 24px; color: var(--muted); }
.popup-preview .vp-tip { width: 0; height: 0; margin-top: -8px; border: 10px solid transparent; border-top-color: var(--surface); border-bottom: 0; }
.popup-preview .vp-pin { width: 14px; height: 14px; border-radius: 50%; background: #1F9D63; border: 3px solid #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .3); }
.popup-preview > small { color: var(--muted); }
.popup-settings fieldset.settings-grid { border: 0; padding: 0; margin: 0; min-width: 0; }
.popup-settings fieldset:disabled { opacity: .55; }
@media (max-width: 900px) { .popup-settings { grid-template-columns: 1fr; } .popup-preview { position: static; } }
/* A notification at the place it happened (from the bell). */
/* An alert's bubble (map.js, from the bell): the point pop-up's look, with the alert's colour (as in the bell) */
.notification-pop { --kind: var(--select); }
.notification-pop.t-speeding, .notification-pop.t-alarm { --kind: var(--alarm); }
.notification-pop.t-idle { --kind: var(--idle); }
.notification-pop.t-offline { --kind: var(--offline); }
.notification-pop.t-signal { --kind: #9B3FB5; }
.notification-pop .point-head { display: flex; align-items: baseline; gap: 6px; box-shadow: inset 0 3px 0 var(--kind); }
.notification-pop .point-head small { flex: none; }
.notification-kind { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--kind); transform: translateY(-1px); }
.notification-pop .notification-message { margin: 0 0 4px; font-size: calc(14px * var(--text-scale)); font-weight: 600; line-height: 1.35; }
.notification-pop .point-time { font-weight: 400; color: var(--muted); }
.notification-pop .notification-actions { display: flex; justify-content: flex-end; margin-top: 10px; }
.notification-pop .notification-actions button { display: inline-flex; align-items: center; gap: 6px; }
.notification-pop .notification-ack { display: flex; align-items: center; gap: 6px; margin: 10px 0 0; font-size: calc(13px * var(--text-scale)); }

/* ---------------------------------------------------------------- Fleet dashboard (dashboard.js), over the whole map
   Chart colours: categorical slots s1-s5 (+ grey "Other"), the speed ramp o0-o4 (slow to fast), the heatmap's steps
   q1-q5 (little to much driving), each validated against this theme's surface. Status colours are the map's. */
.dash {
  --s1: #2a78d6; --s2: #eb6834; --s3: #1baf7a; --s4: #eda100; --s5: #e87ba4; --s-other: #9a958c;
  --o0: #86b6ef; --o1: #5598e7; --o2: #2a78d6; --o3: #1c5cab; --o4: #104281;
  --q0: var(--surface-2); --q1: #b7d3f6; --q2: #86b6ef; --q3: #5598e7; --q4: #2a78d6; --q5: #1c5cab;
  --grid: #E3DDD3; --base: #C9C1B4;
  --status-moving: #1F9D63; --status-towing: #D7263D; --status-idle: #D08A00; --status-parked: #3F72B5; --status-offline: #8C9AA3; --status-noData: #C3CBD1;
  position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column;
  background: var(--paper); color: var(--ink); overflow: hidden;
  animation: dash-in .18s ease-out;
}
:root[data-theme="dark"] .dash {
  --s1: #3987e5; --s2: #d95926; --s3: #199e70; --s4: #c98500; --s5: #d55181; --s-other: #6d7c86;
  --o0: #1c5cab; --o1: #2a78d6; --o2: #5598e7; --o3: #86b6ef; --o4: #b7d3f6;
  --q1: #1c5cab; --q2: #2a78d6; --q3: #5598e7; --q4: #86b6ef; --q5: #b7d3f6;
  --grid: #26353F; --base: #3A4D59;
  --status-offline: #5E6E78; --status-noData: #3A4A54;
}
@keyframes dash-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .dash { animation: none; } }
.dash-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; padding: 14px 20px; border-bottom: 1px solid var(--line); background: var(--surface); }
.dash-head h2 { display: flex; align-items: center; gap: 8px; margin: 0; font-size: calc(18px * var(--text-scale)); }
.dash-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-right: auto; }
.dash-filters select { width: auto; min-width: 160px; }
.dash-filters [data-refresh] { display: inline-grid; place-items: center; padding: 5px 7px; }
.dash-updated { font-size: calc(12px * var(--text-scale)); }
.dash-close { background: none; color: var(--muted); padding: 6px; border-radius: 50%; display: grid; place-items: center; }
.dash-close:hover { background: var(--surface-2); color: var(--ink); }
.dash-body { flex: 1; overflow: auto; padding: 18px 20px 24px; transition: opacity .2s; }
.dash-body.is-loading { opacity: .55; pointer-events: none; }

.dash-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 12px; margin-bottom: 14px; }
.dash-tile { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; display: grid; gap: 2px; align-content: start; }
.dash-tile > svg { position: absolute; top: 14px; right: 14px; color: var(--s1); opacity: .85; }
.dash-tile-label { font-size: calc(13px * var(--text-scale)); color: var(--muted); }
.dash-tile-value { font-size: calc(26px * var(--text-scale)); font-weight: 650; letter-spacing: -.01em; line-height: 1.2; }
.dash-tile-note { font-size: calc(12px * var(--text-scale)); color: var(--muted); }

.dash-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.dash-card { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px 16px; min-width: 0; display: flex; flex-direction: column; }
.dash-card.span-2 { grid-column: span 2; }
@media (max-width: 1100px) { .dash-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 720px) { .dash-grid { grid-template-columns: minmax(0, 1fr); } .dash-card.span-2 { grid-column: auto; } .dash-head, .dash-body { padding-left: 16px; padding-right: 16px; } }
.dash-card > header { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.dash-card h3 { margin: 0 auto 0 0; font-size: calc(15px * var(--text-scale)); font-weight: 600; }
.dash-views button { padding: 3px 6px; display: inline-grid; place-items: center; }
.dash-chart { flex: 1; min-width: 0; }
.dash-table { display: none; max-height: 320px; overflow: auto; }
.dash-card.show-table .dash-chart { display: none; }
.dash-card.show-table .dash-table { display: block; }
.dash-tbl { width: 100%; border-collapse: collapse; font-size: calc(13px * var(--text-scale)); }
.dash-tbl th { text-align: left; font-weight: 500; color: var(--muted); border-bottom: 1px solid var(--line); padding: 4px 6px; position: sticky; top: 0; background: var(--surface); }
.dash-tbl td { padding: 4px 6px; border-bottom: 1px solid var(--line); }
.dash-tbl .num { text-align: right; font-variant-numeric: tabular-nums; }
.dash-empty { margin: 30px 0; text-align: center; }

.dash-svg { display: block; overflow: visible; }
.dash-gridline { stroke: var(--grid); stroke-width: 1; shape-rendering: crispEdges; }
.dash-base { stroke: var(--base); stroke-width: 1; shape-rendering: crispEdges; }
.dash-axis { fill: var(--muted); font-size: calc(11px * var(--text-scale)); font-variant-numeric: tabular-nums; }
.dash-mark { cursor: default; outline: none; }
g.dash-mark:hover path, g.dash-mark:focus-visible path { filter: brightness(1.12); }
g.dash-mark:hover rect { fill: var(--surface-2); fill-opacity: .6; }
g.dash-mark:focus-visible rect { stroke: var(--select); stroke-width: 2; }
.dash-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: calc(12px * var(--text-scale)); color: var(--muted); margin: -4px 0 6px; }
.dash-dot { display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 6px; vertical-align: 0; }

.dash-donut { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 16px 22px; padding: 4px 0; }
.dash-arc { stroke: var(--surface); stroke-width: 2; stroke-linejoin: round; transition: transform .15s; transform-origin: 84px 84px; }
.dash-arc:hover, .dash-arc:focus-visible { transform: scale(1.04); }
@media (prefers-reduced-motion: reduce) { .dash-arc { transition: none; } }
.dash-donut-value { fill: var(--ink); font-size: calc(24px * var(--text-scale)); font-weight: 650; }
.dash-key { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; min-width: 140px; font-size: calc(13px * var(--text-scale)); }
.dash-key li { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 0 4px; }
.dash-key b { font-weight: 600; text-align: right; padding-left: 12px; }
.dash-key li.is-zero { color: var(--muted); }

.dash-hbars { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.dash-hbars button { all: unset; box-sizing: border-box; width: 100%; display: grid; grid-template-columns: minmax(70px, 34%) minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 4px 6px; border-radius: 6px; cursor: pointer; font-size: calc(13px * var(--text-scale)); }
.dash-hbars button:hover, .dash-hbars button:focus-visible { background: var(--surface-2); }
.dash-hbars button:focus-visible { outline: 2px solid var(--select); outline-offset: -2px; }
.dash-hbar-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-hbar-track { display: block; height: 10px; }
.dash-hbar { display: block; height: 100%; background: var(--s1); border-radius: 0 4px 4px 0; min-width: 2px; }
.dash-hbars b { font-weight: 600; font-size: calc(12px * var(--text-scale)); text-align: right; white-space: nowrap; }

.dash-heat { display: grid; grid-template-columns: auto repeat(24, minmax(0, 1fr)); gap: 2px; align-items: center; font-size: calc(11px * var(--text-scale)); color: var(--muted); }
.dash-heat-hour { text-align: left; font-variant-numeric: tabular-nums; }
.dash-heat-day { padding-right: 6px; }
.dash-cell { display: block; aspect-ratio: 1.25; border-radius: 3px; background: var(--q0); }
.dash-cell.q1 { background: var(--q1); } .dash-cell.q2 { background: var(--q2); } .dash-cell.q3 { background: var(--q3); }
.dash-cell.q4 { background: var(--q4); } .dash-cell.q5 { background: var(--q5); }
.dash-heat .dash-cell:hover, .dash-heat .dash-cell:focus-visible { outline: 2px solid var(--ink); outline-offset: 0; }
.dash-scale { display: flex; flex-wrap: wrap; align-items: center; gap: 3px; margin-top: 10px; font-size: calc(11px * var(--text-scale)); color: var(--muted); }
.dash-scale i.dash-cell { width: 14px; aspect-ratio: 1; }
.dash-scale > span:first-child { margin-right: 4px; }
.dash-scale > span:nth-of-type(2) { margin: 0 12px 0 4px; }

.dash-tip {
  position: absolute; left: 0; top: 0; z-index: 2; pointer-events: none; max-width: 260px;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 6px 20px rgba(22, 36, 45, .18); padding: 7px 10px; font-size: calc(12px * var(--text-scale)); line-height: 1.5;
}
.dash-tip small { color: var(--muted); }
.maplibregl-ctrl .dashboard-button { display: grid; place-items: center; color: #333; } /* the controls stay white in both themes */
@media (max-width: 720px) {
  /* On a phone the map is only part of the screen: the dashboard takes all of it, its close button beside the title. */
  .dash { position: fixed; z-index: 60; }
  .dash-head { padding-top: 10px; padding-bottom: 10px; }
  .dash-head h2 { flex: 1; }
  .dash-close { order: 2; }
  .dash-filters { order: 3; flex-basis: 100%; }
}

/* ---------- Telegram chats (Manage > Alerts) */
.telegram-window .win-body { padding: 18px 22px; display: grid; gap: 14px; align-content: start; }
.tg-chats { list-style: none; margin: 0; padding: 0; border: 1px solid var(--line); border-radius: 8px; }
.tg-chats li { display: flex; align-items: center; gap: 10px; padding: 10px 12px; }
.tg-chats li + li { border-top: 1px solid var(--line); }
.tg-chat-icon { color: var(--muted); display: flex; }
.tg-chat-name { flex: 1; min-width: 0; display: grid; }
.tg-chat-name b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tg-chat-name .hint { font-size: calc(13px * var(--text-scale)); }
.tg-connect { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.tg-connect p { margin: 0; flex-basis: 100%; }
.tg-waiting { display: flex; gap: 8px; align-items: flex-start; }
.tg-waiting svg { flex: none; margin-top: 3px; }
.tg-link { word-break: break-all; }
.tg-bot-state { margin: 0; display: flex; gap: 8px; align-items: center; }
.spin { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spin { animation: none; } }

/* ---------- re-applying mappings (Server > Device types) */
.reapply-window .win-body { padding: 18px 22px; display: grid; gap: 12px; align-content: start; }
.reapply-window p { margin: 0; }
.reapply-window progress { width: 100%; height: 10px; accent-color: var(--select); }
.reapply-outcome.failed { color: var(--alarm); }
.reapply-window .dialog-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* Importing from a file (import.js) */
/* Forwarding (forwarding.js): templates in a fixed-width font, the request preview, the log */
.form-window [data-field="header"] textarea, .form-window [data-field="footer"] textarea, .form-window [data-field="record"] textarea,
.form-window [data-field="names"] textarea, .form-window [data-field="headers"] textarea, .form-window [data-field="separator"] input {
  font-family: ui-monospace, Consolas, monospace; font-size: calc(13px * var(--text-scale)); }
.form-window [data-field="record"] textarea { min-height: 140px; }
.fw-preview { display: grid; gap: 8px; padding: 12px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-2); }
.fw-preview-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.fw-preview-head [data-test] { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; }
.fw-line { margin: 0; overflow-wrap: anywhere; }
.fw-url { font-family: ui-monospace, Consolas, monospace; font-size: calc(13px * var(--text-scale)); overflow-wrap: anywhere; }
.fw-code { margin: 0; padding: 8px 10px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  font-family: ui-monospace, Consolas, monospace; font-size: calc(12px * var(--text-scale)); white-space: pre-wrap; overflow-wrap: anywhere; max-height: 320px; overflow: auto; }
.fw-headers { color: var(--muted); }
.fw-test p { margin: 0 0 6px; }
.fw-log .win-body { padding: 16px 20px; display: grid; gap: 10px; }
.fw-log-head { display: flex; align-items: center; gap: 12px; }
.fw-log-head p { margin: 0; flex: 1; }
.fw-answer { font-size: calc(12px * var(--text-scale)); white-space: pre-wrap; overflow-wrap: anywhere; display: block; max-height: 80px; overflow: auto; }
.schedule-error { color: var(--alarm); white-space: pre-line; display: inline-block; max-width: 320px; overflow-wrap: anywhere; }

/* Alert conditions (conditions.js): one row per condition, joined by "and" / "or" */
.conditions { display: grid; gap: 8px; justify-items: start; }
.conditions > * { justify-self: stretch; }
.conditions > [data-add] { justify-self: start; display: inline-flex; align-items: center; gap: 6px; }
.cond-match { display: flex; align-items: center; gap: 8px; margin: 0; flex-wrap: wrap; }
.cond-match .sel { min-width: 200px; }
.cond-list { display: grid; gap: 6px; }
.cond-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-2, var(--surface)); }
.cond-what { flex: 1 1 160px; min-width: 0; }
.cond-row > .cond-op { flex: 0 1 140px; min-width: 110px; }
.cond-value { flex: 1 1 90px; min-width: 80px; display: flex; align-items: center; gap: 6px; }
.cond-value input { width: 100%; min-width: 0; }
.cond-value.with-unit > span { color: var(--muted); font-size: calc(13px * var(--text-scale)); white-space: nowrap; }
.cond-targets { flex: 2 1 180px; min-width: 0; }
.cond-targets.wide { flex-basis: 100%; order: 1; } /* under the row, after its remove button */
.cond-remove { margin-left: auto; }
.cond-join { font-size: calc(12px * var(--text-scale)); color: var(--muted); text-transform: uppercase; letter-spacing: .04em; padding-left: 10px; }

.import { display: grid; gap: 12px; padding: 16px 22px 20px; }
.import > p { margin: 0; }
.import-steps { display: flex; gap: 4px; margin: 0; padding: 0; list-style: none; counter-reset: step; font-size: calc(13px * var(--text-scale)); color: var(--muted); }
.import-steps li { counter-increment: step; display: flex; align-items: center; gap: 6px; padding: 3px 10px 3px 4px; border-radius: 999px; }
.import-steps li::before { content: counter(step); display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: var(--surface-2); font-weight: 600; font-size: calc(12px * var(--text-scale)); }
.import-steps li[aria-current="step"] { color: var(--ink); font-weight: 600; background: var(--select-tint); }
.import-steps li[aria-current="step"]::before { background: var(--select); color: #fff; }
.import-drop { position: relative; display: flex; align-items: center; gap: 12px; padding: 22px; border: 2px dashed var(--line); border-radius: 8px; cursor: pointer; color: var(--muted); }
.import-drop:hover, .import-drop:focus-within { border-color: var(--select); color: var(--ink); }
.import-drop b { color: var(--select); }
.import-drop input { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.import-paste summary { cursor: pointer; color: var(--muted); font-size: calc(14px * var(--text-scale)); }
.import-paste textarea { width: 100%; margin: 8px 0; font-family: ui-monospace, monospace; font-size: calc(12px * var(--text-scale)); }
.import-columns, .import-rows { width: 100%; border-collapse: collapse; font-size: calc(13px * var(--text-scale)); }
.import-columns th, .import-rows th { text-align: left; font-weight: 600; color: var(--muted); font-size: calc(12px * var(--text-scale)); padding: 4px 8px; border-bottom: 1px solid var(--line); }
.import-columns td, .import-rows td { padding: 5px 8px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.import-columns td:last-child { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.import-columns select { width: 100%; min-width: 180px; }
.import-rows td.num { color: var(--muted); font-variant-numeric: tabular-nums; width: 1%; white-space: nowrap; }
.import-rows tr.error td { background: color-mix(in srgb, var(--alarm) 6%, transparent); }
.import-table { max-height: 320px; overflow: auto; border: 1px solid var(--line); border-radius: 6px; }
.import-table .import-rows th { position: sticky; top: 0; background: var(--surface); }
.import-summary { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.import-summary.ok { color: var(--moving); font-weight: 600; }
.import-summary.ok svg { vertical-align: -4px; }
.import-options { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; font-size: calc(14px * var(--text-scale)); }
.inline-field { display: inline-flex; align-items: center; gap: 8px; font-size: calc(14px * var(--text-scale)); }
.inline-field select, .inline-field input { width: auto; padding: 4px 8px; }
.inline-field input[type=number] { width: 90px; }
.import-map { height: 240px; border-radius: 6px; overflow: hidden; border: 1px solid var(--line); }
.import-passwords { display: grid; gap: 8px; }
.import-passwords p { margin: 0; }
.import-passwords table { max-width: 420px; }
.import-busy { padding: 24px 0; }
.import .dialog-actions { display: flex; align-items: center; gap: 8px; }
.import .dialog-actions .spacer { flex: 1; }
.import .dialog-actions > :first-child { margin-left: 0; }

/* Phones: one column that fits the screen (so the browser never zooms the page out), the menus scrolling sideways.
   Nothing here applies above 760 px. */
@media (max-width: 760px) {
  .topbar { flex: none; flex-wrap: wrap; gap: 0 10px; padding: 4px 12px 0; }
  .topbar .mainnav { order: 10; flex: 1 0 100%; min-width: 0; margin: 0 -12px; padding: 0 4px; overflow-x: auto; scrollbar-width: none; }
  .mainnav a { padding: 8px 10px 9px; white-space: nowrap; }
  .user-button .user { max-width: 32vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .acting-banner { gap: 8px; padding: 4px 12px; font-size: calc(13px * var(--text-scale)); }
  .subnav, .manage-tabs { padding: 0 8px; scrollbar-width: none; }
  .manage { grid-template-columns: minmax(0, 1fr); }
  .manage-side { min-width: 0; }
  /* Typing in a field smaller than 16 px makes phones zoom in. */
  input:not([type=checkbox], [type=radio]), textarea, .sel-search { font-size: 16px; }

  /* The map page is the screen's height: the map on top, the list under it scrolling on its own. */
  .app:has(> #view-map:not([hidden])) { height: 100dvh; min-height: 0; }
  .view-map { grid-template-rows: minmax(220px, 46%) minmax(0, 1fr); }
  .view-map .board { min-height: 0; }
  /* The map's panels (layers, options) float over the screen under the controls, scrolling when long. */
  .maplibregl-ctrl.layer-control { transform: none; } /* MapLibre's translate(0) would hold the fixed panel inside the button */
  .layer-panel { position: fixed; top: 100px; left: 52px; right: 8px; width: auto; min-width: 0; max-width: none; max-height: calc(100dvh - 110px); z-index: 50; }
  .map:has(.layer-panel:not([hidden])) .geo-search { visibility: hidden; } /* it would cover the panel */
}

/* The replay graph (history-graph.js): one lane per value on one time axis, the playhead and a hover crosshair. */
.graph { display: grid; gap: 8px; padding: 10px 12px 12px; position: relative; }
.graph-tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.graph-pick { min-width: 260px; max-width: 520px; flex: 1; }
.graph-lanes { position: relative; cursor: crosshair; touch-action: none; user-select: none; border-radius: var(--radius); }
.graph-lanes:focus-visible { outline: 2px solid var(--input-focus); outline-offset: 2px; }
.graph-lane + .graph-lane { margin-top: 4px; }
.graph-lane-head { display: flex; justify-content: space-between; gap: 8px; padding-left: var(--graph-left, 48px); font-size: calc(12px * var(--text-scale)); color: var(--muted); line-height: 20px; }
.graph-lane-head b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.graph-lane svg, .graph-time { display: block; overflow: visible; }
.graph-line { fill: none; stroke: var(--series, var(--graph)); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.graph-area { fill: var(--series, var(--graph)); opacity: .12; }
.graph-on rect { fill: var(--series, var(--graph)); opacity: .55; }
.graph-grid { stroke: var(--line); stroke-width: 1; }
.graph-axis { fill: var(--muted); font-size: calc(11px * var(--text-scale)); font-variant-numeric: tabular-nums; }
.graph-empty { padding: 6px 0 6px var(--graph-left, 48px); margin: 0; font-size: calc(13px * var(--text-scale)); }
.graph-playhead, .graph-cross { position: absolute; top: 0; bottom: 22px; width: 0; pointer-events: none; }
.graph-playhead { border-left: 2px solid var(--ink); margin-left: -1px; }
.graph-cross { border-left: 1px dashed var(--muted); }
.graph-tip { position: absolute; pointer-events: none; background: var(--surface); border: 1px solid var(--line); border-radius: 4px;
  padding: 1px 6px; font-size: calc(12px * var(--text-scale)); color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; box-shadow: 0 1px 3px rgba(0, 0, 0, .12); }
.graph-swatch { display: inline-block; width: 12px; height: 3px; border-radius: 2px; background: var(--series); margin-right: 6px; vertical-align: middle; }
.graph-legend { list-style: none; margin: 0 0 4px; padding: 0 0 0 var(--graph-left, 48px); display: flex; flex-wrap: wrap; gap: 2px 16px; font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.graph-legend b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.graph-legend .graph-swatch { height: 4px; }
.graph-brush { position: absolute; top: 0; bottom: 22px; background: var(--select-tint); border-left: 1px solid var(--select); border-right: 1px solid var(--select); opacity: .7; pointer-events: none; }
.graph-tools [data-zoom-reset] { display: inline-flex; align-items: center; gap: 4px; }
.graph-tools [data-zoom-reset][hidden] { display: none; }

/* Manage > Style (style-page.js) */
.style-form { max-width: 820px; }
.style-preview-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.style-preview-bar .seg-buttons button { display: inline-flex; align-items: center; gap: 6px; }
.style-title { font-size: calc(15px * var(--text-scale)); margin: 8px 0 10px; }
.style-colours { display: grid; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; }
.style-row { display: grid; grid-template-columns: minmax(0, 1fr) 190px 190px; gap: 12px; align-items: center; padding: 8px 12px; border-top: 1px solid var(--line); }
.style-row.style-head { border-top: 0; background: var(--surface-2); color: var(--muted); font-size: calc(13px * var(--text-scale)); padding-block: 6px; }
.style-row [role=rowheader] { display: grid; gap: 1px; min-width: 0; }
.style-row [role=rowheader] small { font-size: calc(12px * var(--text-scale)); }
.style-cell { display: flex; align-items: center; gap: 8px; min-width: 0; }
.style-cell input[type=color] { flex: none; width: 44px; height: var(--control-h); padding: 2px; border-radius: var(--radius); }
.style-hex { font-size: calc(12px * var(--text-scale)); color: var(--muted); }
.style-cell.set .style-hex { color: var(--ink); }
.style-cell [data-reset] { padding: 4px; }
.style-warnings { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px; color: var(--alarm); font-size: calc(13px * var(--text-scale)); }
.style-warnings:empty { display: none; }
.style-warnings li { display: flex; align-items: center; gap: 6px; }
.style-sample-box { display: grid; gap: 12px; padding: 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.style-sample-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.style-sample-row > input, .style-sample-row > .sel { width: 180px; }
.style-sample-list { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.style-sample-list li { padding: 8px 12px; border-top: 1px solid var(--line); }
.style-sample-list li:first-child { border-top: 0; }
.style-sample-list li.picked { background: var(--select-tint); }
@media (max-width: 640px) {
  .style-row { grid-template-columns: 1fr 1fr; }
  .style-row [role=rowheader] { grid-column: 1 / -1; }
  .style-row.style-head [role=columnheader]:first-child { display: none; }
}
