/* Government panel — ported from the approved mockup */
:root {
  --r3-overlay: none;
  color-scheme: light;
  --page: #f4f6f9;
  --surface: #ffffff;
  --ink: #131a26;
  --ink-2: #47536a;
  --muted: #7d8698;
  --line: #e3e7ee;
  --line-strong: #cdd4df;
  --accent: #2563c4;
  --accent-soft: #e8f0fc;
  --accent-ink: #ffffff;
  --sidebar-bg: #101f38;
  --sidebar-ink: #c6d2e5;
  --sidebar-ink-strong: #ffffff;
  --sidebar-active: rgba(255,255,255,0.10);
  --sidebar-line: rgba(255,255,255,0.08);
  --chart-1: #2563c4;
  --chart-fill: rgba(37,99,196,0.10);
  --ok: #0ca30c;      --ok-soft: #e4f4e4;   --ok-ink: #0a6e0a;
  --warn: #b97800;    --warn-soft: #fdf1d8;  --warn-ink: #8a5a00;
  --crit: #d03b3b;    --crit-soft: #fbe7e7;  --crit-ink: #a52e2e;
  --neutral-soft: #eef1f5; --neutral-ink: #55607a;
  --shadow: 0 1px 2px rgba(16,31,56,0.05), 0 4px 14px rgba(16,31,56,0.05);
  /* The scrollbar is furniture, not content: a thumb the weight of a
     hairline, no track at all, and it darkens under the pointer. */
  --scroll-thumb: rgba(19,26,38,0.20);
  --scroll-thumb-hover: rgba(19,26,38,0.36);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
  --r3-overlay: invert(1) brightness(1.75);
    --page: #0f1520;
    --surface: #161d2b;
    --ink: #eef2f8;
    --ink-2: #b5bfcf;
    --muted: #8791a3;
    --line: #242d3e;
    --line-strong: #35405a;
    --accent: #4d8fe8;
    --accent-soft: #1c2a44;
    --sidebar-bg: #0b111e;
    --sidebar-ink: #aab6c9;
    --chart-1: #3987e5;
    --chart-fill: rgba(57,135,229,0.14);
    --ok: #0ca30c;    --ok-soft: #12301b;   --ok-ink: #4ecb6f;
    --warn: #e0a63a;  --warn-soft: #33280f; --warn-ink: #e8b95c;
    --crit: #e05b5b;  --crit-soft: #38181c; --crit-ink: #ef8585;
    --neutral-soft: #222b3c; --neutral-ink: #9daabd;
    --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 4px 14px rgba(0,0,0,0.25);
    --scroll-thumb: rgba(238,242,248,0.18);
    --scroll-thumb-hover: rgba(238,242,248,0.34);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --r3-overlay: invert(1) brightness(1.75);
  --page: #0f1520;
  --surface: #161d2b;
  --ink: #eef2f8;
  --ink-2: #b5bfcf;
  --muted: #8791a3;
  --line: #242d3e;
  --line-strong: #35405a;
  --accent: #4d8fe8;
  --accent-soft: #1c2a44;
  --sidebar-bg: #0b111e;
  --sidebar-ink: #aab6c9;
  --chart-1: #3987e5;
  --chart-fill: rgba(57,135,229,0.14);
  --ok: #0ca30c;    --ok-soft: #12301b;   --ok-ink: #4ecb6f;
  --warn: #e0a63a;  --warn-soft: #33280f; --warn-ink: #e8b95c;
  --crit: #e05b5b;  --crit-soft: #38181c; --crit-ink: #ef8585;
  --neutral-soft: #222b3c; --neutral-ink: #9daabd;
  --shadow: 0 1px 2px rgba(0,0,0,0.3), 0 4px 14px rgba(0,0,0,0.25);
  --scroll-thumb: rgba(238,242,248,0.18);
  --scroll-thumb-hover: rgba(238,242,248,0.34);
}

* { box-sizing: border-box; }
html { height: 100%; }
body { margin: 0; }
body {
  font: 14px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--page); color: var(--ink);
  display: flex; min-height: 100vh;
}
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }

/* ---------- scrollbars ----------
   One declaration dresses every scroller in the panel, and it does so by
   inheritance: `scrollbar-width` and `scrollbar-color` are inherited
   properties, so the root hands them to the sidebar, the tables, the map's
   panels, the editor and anything added tomorrow. Nothing has to remember to
   opt in, and a place that wants no scrollbar at all still wins by saying so
   on itself.

   The `@supports` guard is not belt and braces. Chrome and Edge only learned
   these two properties in 121, and Safari in 18.2; older ones need the WebKit
   pseudo-elements. But an element with *any* `::-webkit-scrollbar` rule is
   taken off the platform's modern scrollbar in Chrome — which on macOS means
   losing the overlay bar that appears only while scrolling. So the modern
   browsers get the standard properties and keep their platform behaviour, and
   only the old ones are painted by hand. */
/* Measured, not assumed: of the two properties only `scrollbar-color` is
   inherited. `scrollbar-width` is not — declared on the root alone it thins
   the document's own scrollbar and leaves every inner scroller at `auto`,
   which is exactly the coarse bar this replaces. So the width goes on `*`,
   where the few places that ask for no scrollbar at all still outrank it. */
html { scrollbar-color: var(--scroll-thumb) transparent; }
* { scrollbar-width: thin; }

@supports not (scrollbar-width: thin) {
  ::-webkit-scrollbar { width: 10px; height: 10px; background: transparent; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-corner { background: transparent; }
  /* A 4px thumb inside a 10px gutter: the transparent border is padding the
     background does not paint over, which is the only way to inset a WebKit
     thumb. */
  ::-webkit-scrollbar-thumb {
    background: var(--scroll-thumb);
    border: 3px solid transparent;
    background-clip: content-box;
    border-radius: 99px;
  }
  ::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: content-box; }
}
button:focus-visible, a:focus-visible, select:focus-visible, input:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
}

/* ---------- Sidebar ---------- */
.gov-sidebar {
  width: 248px; flex: none; background: var(--sidebar-bg); color: var(--sidebar-ink);
  display: flex; flex-direction: column; position: sticky; top: 0; height: 100vh;
}
.brand {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 20px 16px 16px; text-align: center;
  border-bottom: 1px solid var(--sidebar-line, rgba(255,255,255,0.08));
}
/* Logo stacked above the labels (132px golden-ratio base scaled down 35%).

   The mark used to be a single-colour glyph, which is why it was whitened to
   sit on the navy: `brightness(0) invert(1)` on full-colour artwork would
   flatten the road, the bars and the network into one white silhouette and
   lose the road markings entirely, since they are white already. So it keeps
   its own colours and gets a light plate to sit on — which is also the only
   way navy artwork stays legible against a navy sidebar. The plate's padding
   is included in the 86px the brand block was built around. */
.brand .brand-logo {
  width: 70px; height: auto;
  padding: 8px;
  border-radius: 11px;
  background: #fff;
  box-shadow: 0 1px 3px rgba(5, 12, 25, 0.35);
}
.brand .brand-text { min-width: 0; }
.brand-home {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  color: inherit; text-decoration: none; border-radius: 7px; padding: 2px 6px;
  transition: opacity 0.15s ease;
}
.brand-home:hover { opacity: 0.85; }
.brand-home:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.brand .t1 { color: var(--sidebar-ink-strong, #fff); font-weight: 650; font-size: 13.5px; line-height: 1.3; }
.brand .t2 { font-size: 11px; opacity: 0.75; margin-top: 2px; letter-spacing: 0.3px; }
/* The nav is the panel's one tall scroller, and a stock scrollbar cuts a pale
   gutter down the dark sidebar. The gutter is kept at a constant width so the
   links never shift when the menu grows past the screen, but the thumb is only
   painted while the pointer is on the sidebar: nothing to see at rest, a hint
   of one when it is being used. */
.gov-nav {
  padding: 14px 10px; overflow-y: auto; flex: 1;
  overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.gov-sidebar:hover .gov-nav { scrollbar-color: rgba(255,255,255,0.16) transparent; }

/* The same hand-painted fallback the root carries, in the sidebar's own
   colours — and behind the same guard, so a browser that understands
   `scrollbar-color` uses the two lines above and keeps its platform scrollbar. */
@supports not (scrollbar-width: thin) {
  .gov-nav::-webkit-scrollbar { width: 6px; }
  .gov-nav::-webkit-scrollbar-track { background: transparent; }
  .gov-nav::-webkit-scrollbar-thumb {
    background: transparent; border: 0; border-radius: 99px;
    transition: background 0.18s ease;
  }
  .gov-sidebar:hover .gov-nav::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.16); }
  .gov-nav:hover::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.26); }
}
.nav-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.09em;
  opacity: 0.55; padding: 14px 10px 6px;
}
.gov-nav a {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; margin: 1px 0;
  border-radius: 5px; color: inherit; text-decoration: none; font-size: 13.5px;
}
.gov-nav a:hover { background: rgba(255,255,255,0.06); color: #fff; }
.gov-nav a.active { background: var(--sidebar-active); color: #fff; font-weight: 600; }
.gov-nav a.active .ic { color: #7fb0f0; }
.gov-nav .ic { width: 18px; height: 18px; flex: none; opacity: 0.9; }
.nav-home { margin-bottom: 6px; padding-bottom: 6px; }
.gov-nav .badge {
  margin-left: auto; background: #d03b3b; color: #fff; font-size: 10.5px;
  font-weight: 700; border-radius: 99px; padding: 1px 7px;
}
.sidebar-foot {
  padding: 12px 16px; border-top: 1px solid rgba(255,255,255,0.08);
  font-size: 11px; opacity: 0.6;
}

/* ---------- Filter sub-sidebar ----------
   A second column against the sidebar for screens with more filters than a
   toolbar can hold. Sticky like the nav, collapses to a rail, and stacks above
   the content once the sidebar itself is gone. */
.gov-subnav {
  width: 276px; flex: none; background: var(--surface);
  border-right: 1px solid var(--line);
  position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column;
  transition: width 0.18s ease;
}
.subnav-head {
  display: flex; align-items: center; gap: 8px;
  padding: 13px 14px; border-bottom: 1px solid var(--line);
}
.subnav-head h2 {
  margin: 0; font-size: 11px; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap; overflow: hidden;
}
.subnav-toggle {
  margin-left: auto; display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 5px; color: var(--ink-2); flex: none;
}
.subnav-toggle:hover { background: var(--page); }
.subnav-body { flex: 1; overflow-y: auto; padding: 14px; }
.subnav-body .field { margin-bottom: 11px; }
.subnav-body .field > span { font-size: 11.5px; color: var(--muted); }
.subnav-body select,
.subnav-body input[type="text"],
.subnav-body input[type="search"],
.subnav-body input[type="number"],
.subnav-body input[type="date"],
.subnav-body .ts-wrapper { width: 100%; }
.subnav-actions { display: grid; gap: 8px; margin-top: 16px; }
.subnav-actions > * { width: 100%; text-align: center; justify-content: center; }

/* Actions live at the foot of the column, one per row: the icon carries its
   name beside it, so what each one does is readable without hovering. */
.subnav-foot {
  border-top: 1px solid var(--line); padding: 10px 12px;
  display: grid; gap: 8px;
}
.subnav-foot .icon-btn {
  min-height: 34px; padding: 0 11px;
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--line); border-radius: 6px;
  color: var(--ink-2); background: var(--surface); text-decoration: none;
  font-size: 12.5px; white-space: nowrap; overflow: hidden;
}
.subnav-foot .icon-btn svg { flex: none; }
.subnav-foot .icon-btn:hover { background: var(--page); color: var(--ink); }

.gov-subnav.collapsed { width: 47px; }

/* Account activity: the user card's sub-sidebar (gov.users._activity). */
.ua-sec { padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--line); }
.ua-sec:last-child { border-bottom: 0; margin-bottom: 0; }
.ua-sec h3 {
  margin: 0 0 8px; font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.ua-facts { margin: 0; display: grid; gap: 3px; font-size: 12.5px; }
.ua-facts dt { color: var(--muted); font-size: 11.5px; margin-top: 6px; }
.ua-facts dt:first-child { margin-top: 0; }
.ua-facts dd { margin: 0; color: var(--ink); }
.ua-facts small, .ua-list small { display: block; color: var(--muted); font-size: 11.5px; }
.ua-count-h { margin: 12px 0 6px; font-size: 11.5px; color: var(--muted); }
.ua-counts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.ua-counts > div {
  border: 1px solid var(--line); border-radius: 6px; padding: 6px 7px;
  display: grid; gap: 1px; min-width: 0;
}
.ua-counts b { font-size: 15px; color: var(--ink); }
.ua-counts span { font-size: 10.5px; color: var(--muted); overflow-wrap: break-word; }
.ua-counts .bad b { color: var(--crit-ink); }
.ua-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; font-size: 12.5px; }
.ua-list a { color: var(--ink); }
.ua-device { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ua-empty { color: var(--muted); }
.ua-ev { font-weight: 600; }
.ua-ev-login_failed, .ua-ev-login_refused { color: var(--crit-ink); }
.ua-ev-password_set, .ua-ev-password_changed { color: var(--warn-ink); }
/* On the rail there is no room for the names; the title attribute carries them. */
.gov-subnav.collapsed .subnav-foot { padding: 8px 6px; }
.gov-subnav.collapsed .subnav-foot .icon-btn { justify-content: center; padding: 0; }
.gov-subnav.collapsed .subnav-foot .icon-btn span { display: none; }
.gov-subnav.collapsed .subnav-head { justify-content: center; padding: 13px 8px; }
.gov-subnav.collapsed .subnav-head h2,
.gov-subnav.collapsed .subnav-body { display: none; }
.gov-subnav.collapsed .subnav-toggle { margin-left: 0; }

/* ---------- Statistics strip ---------- */
.stat-strip { margin-bottom: 14px; }
.stat-split {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 14px; margin-top: 14px; align-items: start;
}
.stat-legend { display: grid; gap: 7px; padding: 6px 18px 16px; font-size: 12.5px; }
.stat-legend .row { display: grid; grid-template-columns: 12px 1fr auto auto; align-items: center; gap: 9px; }
.stat-legend .sw { width: 11px; height: 11px; border-radius: 3px; }
.stat-legend .nm { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stat-legend .vl { font-weight: 650; font-variant-numeric: tabular-nums; }
.stat-legend .pc { color: var(--muted); font-variant-numeric: tabular-nums; min-width: 42px; text-align: right; }
.stat-empty { padding: 10px 18px 18px; color: var(--muted); font-size: 12.5px; }
/* Registry totals run to seven digits and carry a unit, so the label and the
   value both need more room than the dashboard's own bars. */
.stat-bars .bar-row { grid-template-columns: minmax(0, 150px) minmax(0, 1fr) auto; }
.stat-bars .bv { white-space: nowrap; }

@media (max-width: 1100px) {
  .stat-split { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Main ---------- */
.gov-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.topbar {
  display: flex; align-items: center; gap: 14px; padding: 12px 26px;
  background: var(--surface); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
}
.topbar h1 { font-size: 16px; font-weight: 650; margin: 0; }
.tb-btn {
  display: grid; place-items: center; width: 34px; height: 34px; border-radius: 6px;
  border: 1px solid var(--line); color: var(--ink-2);
}
.tb-btn:hover { background: var(--page); }
.tb-spacer { margin-left: auto; }
select.lang {
  border: 1px solid var(--line); background: var(--surface); color: var(--ink);
  border-radius: 6px; padding: 6px 8px; font: inherit; font-size: 13px;
}
.user-chip { display: flex; align-items: center; gap: 10px; padding-left: 6px; }
.user-chip .av {
  width: 34px; height: 34px; border-radius: 50%; background: var(--accent-soft);
  color: var(--accent); display: grid; place-items: center; font-weight: 700; font-size: 13px;
}
.user-chip .nm { font-size: 13px; font-weight: 600; line-height: 1.2; }
.user-chip .rl { font-size: 11.5px; color: var(--muted); }

.content { padding: 24px 26px 48px; max-width: 1240px; width: 100%; margin: 0 auto; }

/* ---------- Cards & grids ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  box-shadow: var(--shadow);
}
.card-h { display: flex; align-items: baseline; gap: 10px; padding: 16px 18px 0; }
.card-h h3 { margin: 0; font-size: 14px; font-weight: 650; }
.card-h .sub { font-size: 12px; color: var(--muted); }
/* Six counters, so the row breaks 3+3 or 2+2+2 rather than stranding one on a
   line of its own — auto-fit at 220px gave five and a widow. */
/* The counters are the headline band; everything under them is the detail
   behind it. A step wider than the 14px the rest of the page runs on, so the
   two read as separate bands rather than as one long stack — before the charts
   went in, the grid's own top margin was doing this and nothing replaced it. */
.kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 14px; margin-bottom: 21px;
}
@media (min-width: 1180px) { .kpis { grid-template-columns: repeat(6, 1fr); } }
@media (min-width: 760px) and (max-width: 1179px) { .kpis { grid-template-columns: repeat(3, 1fr); } }
.kpi { padding: 16px 18px; }
.kpi .lb { font-size: 12px; color: var(--ink-2); }
.kpi .v { font-size: 28px; font-weight: 700; margin-top: 4px; letter-spacing: -0.01em; }
.kpi .v .vs { font-size: 15px; color: var(--muted); font-weight: 600; }
.kpi .d { font-size: 12px; margin-top: 4px; color: var(--muted); }
.kpi .d.up { color: var(--ok-ink); }
.kpi .d.warn { color: var(--warn-ink); }
.grid-2 {
  display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: 14px; margin-top: 14px; align-items: start;
}
@media (max-width: 1000px) { .grid-2 { grid-template-columns: 1fr; } }

/* ---------- Charts ---------- */
.chart-wrap { padding: 8px 12px 14px; position: relative; }
.chart-wrap svg { display: block; width: 100%; height: auto; }
.chart-tooltip {
  position: absolute; pointer-events: none; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: 6px; box-shadow: var(--shadow);
  padding: 7px 10px; font-size: 12px; display: none; z-index: 5; white-space: nowrap;
}
.chart-tooltip .tv { font-weight: 700; font-variant-numeric: tabular-nums; }
.bars { padding: 12px 18px 16px; display: grid; gap: 9px; }
.bar-row { display: grid; grid-template-columns: 110px 1fr 44px; align-items: center; gap: 10px; font-size: 12.5px; }
.bar-row .rg { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { background: var(--neutral-soft); border-radius: 4px; height: 14px; }
.bar-fill { background: var(--chart-1); height: 100%; border-radius: 4px; min-width: 3px; }
.bar-row .bv { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-2); font-weight: 600; }
.legend { display: flex; flex-wrap: wrap; gap: 14px; padding: 0 18px 14px; font-size: 12px; color: var(--ink-2); }
.legend .sw { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 6px; vertical-align: -1px; }
.stack { display: flex; height: 16px; border-radius: 4px; overflow: hidden; margin: 12px 18px 4px; background: var(--neutral-soft); }
.stack div + div { border-left: 2px solid var(--surface); }

/* ---------- Chips ---------- */
.chip {
  display: inline-flex; align-items: center; gap: 6px; border-radius: 99px;
  font-size: 11.5px; font-weight: 600; padding: 3px 10px; white-space: nowrap;
}
.chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.chip.ok   { background: var(--ok-soft);   color: var(--ok-ink); }
.chip.warn { background: var(--warn-soft); color: var(--warn-ink); }
.chip.crit { background: var(--crit-soft); color: var(--crit-ink); }
.chip.mut  { background: var(--neutral-soft); color: var(--neutral-ink); }
.chip.acc  { background: var(--accent-soft); color: var(--accent); }

/* ---------- Attention list ---------- */
.alist { padding: 6px 6px 10px; }
.aitem { display: flex; gap: 12px; padding: 10px 12px; border-radius: 6px; }
.aitem:hover { background: var(--page); }
.aitem .dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; flex: none; }
.aitem .t { font-size: 13px; font-weight: 600; }
.aitem .s { font-size: 12px; color: var(--muted); margin-top: 1px; }
.empty-note { padding: 14px 18px; font-size: 12.5px; color: var(--muted); }

/* ---------- Toolbar, forms, tables ---------- */
.toolbar { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; align-items: center; }
.search {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 12px; width: 280px; color: var(--muted);
}
.search input { border: none; background: none; outline: none; color: var(--ink); width: 100%; font: inherit; }
.toolbar select {
  border: 1px solid var(--line); background: var(--surface); border-radius: 6px;
  padding: 7px 12px; font: inherit; font-size: 13px; color: var(--ink);
}
.btn-primary {
  display: inline-block; text-decoration: none; text-align: center;
  background: var(--accent); color: #fff; border: none; border-radius: 6px;
  padding: 8px 16px; font-weight: 600; font-size: 13px;
}
.btn-primary:hover { filter: brightness(1.08); }
.btn-ghost {
  display: inline-block; text-decoration: none; text-align: center;
  border: 1px solid var(--line); border-radius: 6px; padding: 7px 14px;
  font-size: 13px; color: var(--ink-2); background: var(--surface);
}
.btn-ghost:hover { background: var(--page); }
.ml-auto { margin-left: auto; }
.tbl-wrap { overflow-x: auto; }
table.gov-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.gov-table th {
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--muted); font-weight: 600; padding: 12px 16px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.gov-table td { padding: 12px 16px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.gov-table tr:last-child td { border-bottom: none; }
.gov-table tbody tr:hover { background: var(--page); }
.gov-table td.num { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.proj-name { font-weight: 600; }
.proj-sub { font-size: 11.5px; color: var(--muted); margin-top: 1px; }
.pbar { display: flex; align-items: center; gap: 8px; min-width: 140px; }
.pbar .tr { flex: 1; height: 6px; background: var(--neutral-soft); border-radius: 3px; }
.pbar .fl { height: 100%; border-radius: 3px; background: var(--chart-1); }
.pbar .pv { font-variant-numeric: tabular-nums; font-size: 12px; font-weight: 600; width: 34px; text-align: right; }
.pager {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; font-size: 12.5px; color: var(--muted); border-top: 1px solid var(--line);
}
.pager nav { display: flex; gap: 4px; }
.pager a, .pager span.pg-item {
  display: grid; place-items: center; min-width: 28px; height: 28px; padding: 0 4px;
  border-radius: 4px; border: 1px solid var(--line); font-size: 12.5px;
  color: var(--ink-2); text-decoration: none;
}
.pager a:hover { background: var(--page); }
.pager .pg-cur { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 700; }
.pager .pg-dis { opacity: 0.4; }

/* Jump straight to a page. The numbered links only ever reach a few pages
   either side of this one, so on a long registry they are not a way to get
   anywhere — the field is. */
.pager-nav { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pg-jump { display: flex; align-items: center; gap: 6px; }
.pg-jump label { font-size: 12px; color: var(--muted); }
.pg-jump input {
  width: 58px; height: 28px; padding: 0 6px; text-align: center;
  border: 1px solid var(--line); border-radius: 4px;
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums;
}
.pg-jump input:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.pg-jump-of { font-size: 12px; color: var(--muted); white-space: nowrap; }
.pg-jump-go {
  display: grid; place-items: center; width: 28px; height: 28px; flex: none;
  border: 1px solid var(--line); border-radius: 4px; color: var(--ink-2); cursor: pointer;
}
.pg-jump-go:hover { background: var(--page); color: var(--ink); }

/* ---------- Reports ---------- */
.rep-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(255px, 1fr)); gap: 14px; margin-bottom: 20px; }
.rep-card { padding: 18px; display: flex; flex-direction: column; gap: 8px; }
.rep-card .ric {
  width: 38px; height: 38px; border-radius: 6px; background: var(--accent-soft);
  color: var(--accent); display: grid; place-items: center;
}
.rep-card h4 { margin: 4px 0 0; font-size: 14px; }
.rep-card p { margin: 0; font-size: 12.5px; color: var(--muted); flex: 1; }
.rep-card .acts { display: flex; gap: 8px; margin-top: 6px; }

/* ---------- Users ---------- */
.role-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin-bottom: 16px; }
.role-card { padding: 16px 18px; }
.role-card .rc-n { font-size: 22px; font-weight: 700; }
.role-card .rc-l { font-size: 12.5px; color: var(--ink-2); margin-top: 2px; }
.uav {
  width: 32px; height: 32px; border-radius: 50%; display: inline-grid; place-items: center;
  font-size: 12px; font-weight: 700; background: var(--neutral-soft); color: var(--neutral-ink);
  margin-right: 10px; vertical-align: middle;
}

@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }
@media (max-width: 860px) {
  /* The sidebar becomes a drawer on a phone (see "Phones" at the end of the
     file); the filter column becomes a band above the content, still
     collapsible so the table can have the screen. */
  body { flex-wrap: wrap; }
  .gov-subnav,
  .gov-subnav.collapsed {
    position: static; height: auto; width: 100%;
    border-right: 0; border-bottom: 1px solid var(--line);
  }
  .gov-subnav.collapsed .subnav-head { justify-content: space-between; padding: 13px 14px; }
  .gov-subnav.collapsed .subnav-head h2 { display: block; }
  .gov-subnav.collapsed .subnav-toggle { margin-left: auto; }
}

/* ---------- Login page ---------- */
body.login-page {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; padding: 24px;
}
.login-top { display: flex; gap: 10px; align-items: center; }
.login-card { width: 100%; max-width: 400px; padding: 28px; }
.login-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; }
/* The crest was a gradient tile with "UZ" set in it, standing in for a mark
   there wasn't one of. It is the mark now. The white plate does nothing on the
   light card and is what makes it readable on the dark one. */
.login-brand .crest {
  width: 42px; height: 42px; flex: none; border-radius: 6px;
  padding: 4px; background: #fff; object-fit: contain;
  box-shadow: 0 1px 2px rgba(5, 12, 25, 0.18);
}
.login-brand .t1 { font-weight: 650; font-size: 14.5px; line-height: 1.25; }
.login-brand .t2 { font-size: 11.5px; color: var(--muted); margin-top: 1px; }
.login-h { margin: 0 0 4px; font-size: 18px; font-weight: 700; }
.login-sub { margin: 0 0 18px; font-size: 13px; color: var(--muted); }
.alert-error {
  background: var(--crit-soft); color: var(--crit-ink); border-radius: 6px;
  padding: 10px 14px; font-size: 13px; margin-bottom: 14px;
}
.field { display: block; margin-bottom: 14px; }
.field span {
  display: block; font-size: 12px; font-weight: 600; color: var(--ink-2); margin-bottom: 6px;
}
.field input {
  width: 100%; border: 1px solid var(--line-strong); background: var(--page);
  color: var(--ink); border-radius: 6px; padding: 9px 12px; font: inherit; font-size: 14px;
}
.field input:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }
.remember {
  display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-2);
  margin: 4px 0 18px; cursor: pointer;
}
.remember input { accent-color: var(--accent); width: 15px; height: 15px; }
.login-btn { width: 100%; padding: 10px 16px; font-size: 14px; }
.login-foot { font-size: 12px; color: var(--muted); }

/* ---------- Flash messages & roles page ---------- */
.alert-success {
  background: var(--ok-soft); color: var(--ok-ink); border-radius: 6px;
  padding: 10px 14px; font-size: 13px; margin-bottom: 14px;
}
.content > .alert-error, .content-full > .alert-error { margin-bottom: 14px; }
.roles-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; }
.role-panel { padding: 18px; display: flex; flex-direction: column; gap: 12px; }
.role-panel .rp-head { display: flex; align-items: center; gap: 10px; }
.role-panel .rp-head h4 { margin: 0; font-size: 14.5px; flex: 1; }
.role-panel .rp-users { font-size: 12px; color: var(--muted); }
.perm-list { display: flex; flex-direction: column; gap: 6px; max-height: 220px; overflow-y: auto; }
.perm-item {
  display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--ink-2);
  padding: 6px 9px; border-radius: 5px; cursor: pointer;
}
.perm-item:hover { background: var(--page); }
.perm-item input { accent-color: var(--accent); width: 15px; height: 15px; flex: none; }
.perm-empty { font-size: 12.5px; color: var(--muted); padding: 4px 2px; }
.rp-actions { display: flex; gap: 8px; align-items: center; border-top: 1px solid var(--line); padding-top: 12px; }
.inline-form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.inline-form input[type="text"] {
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink);
  border-radius: 6px; padding: 8px 12px; font: inherit; font-size: 13px; width: 240px;
}
.btn-danger {
  border: 1px solid transparent; border-radius: 6px; padding: 7px 14px; font-size: 13px;
  background: var(--crit-soft); color: var(--crit-ink);
}
.btn-danger:hover { filter: brightness(0.97); }

/* create-role form */
.rp-subtitle { font-size: 12px; font-weight: 600; color: var(--ink-2); margin-bottom: 8px; }
.perm-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 4px 14px; margin-bottom: 4px;
}
.role-panel .rp-head h4 { font-size: 14.5px; margin: 0; }

/* role permission badges on index */
.perm-badges { display: flex; flex-wrap: wrap; gap: 6px; }

/* user form & table actions */
.form-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
@media (max-width: 640px) { .form-2col { grid-template-columns: 1fr; } }
.row-actions { display: inline-flex; gap: 8px; align-items: center; }
.row-actions form { margin: 0; }

/* road form */
.form-3col { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 14px; }
@media (max-width: 640px) { .form-3col { grid-template-columns: 1fr; } }
.field select.field-select {
  width: 100%; border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--ink); border-radius: 6px; padding: 9px 12px; font: inherit; font-size: 14px;
}

/* geometry textarea */
.field textarea.field-textarea {
  width: 100%; border: 1px solid var(--line-strong); background: var(--page);
  color: var(--ink); border-radius: 6px; padding: 9px 12px; font: 12px/1.5 ui-monospace, monospace;
  resize: vertical;
}
.field textarea.field-textarea:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }
.field-hint { display: block; font-size: 11.5px; color: var(--muted); margin-top: 4px; }

/* geometry map editor */
.field-label { display: block; font-size: 12px; font-weight: 600; color: var(--ink-2); margin-bottom: 6px; }
.geo-map { height: 300px; border-radius: 6px; border: 1px solid var(--line-strong); z-index: 0; }
.geo-tools { display: flex; gap: 8px; align-items: center; margin: 8px 0 4px; }
#geoRawWrap:not([hidden]) { display: block; margin-top: 8px; }
.geo-tools .geo-route-toggle {
  display: inline-flex; gap: 6px; align-items: center;
  font-size: 12.5px; color: var(--ink-2); cursor: pointer; white-space: nowrap;
}
.geo-tools .geo-route-toggle input { accent-color: var(--accent); }
#geoSnap:disabled { opacity: 0.6; cursor: progress; }

/* roads index map */
.roads-map-card { margin-bottom: 14px; padding: 0; overflow: hidden; }
.roads-map { height: 380px; }
tr[data-road-id] { cursor: pointer; }
tr[data-road-id].row-active > td { background: color-mix(in srgb, #e11d48 8%, transparent); }
tr[data-road-id].row-active .proj-name { color: #e11d48; }

/* trash tabs */
.trash-tabs { flex-wrap: wrap; gap: 8px; }
.trash-tabs .chip { text-decoration: none; }
.trash-tabs .chip:hover { filter: brightness(0.95); }
@media (max-width: 900px) {
  .roads-map { height: 280px; }
}

/* full-width road form: inputs on top, map below */
.road-form-grid { display: grid; grid-template-columns: 1fr; gap: 6px; }
.road-form-map { margin-top: 8px; }
.road-form-map .geo-map { height: max(48vh, 380px); }
@media (max-width: 900px) {
  .road-form-map .geo-map { height: 320px; }
}

/* grouped permission checkboxes */
.perm-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 12px; margin-bottom: 6px; }
.perm-group { border: 1px solid var(--line); border-radius: 6px; padding: 6px 10px 10px; margin: 0; min-width: 0; }
.perm-group legend {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--muted); font-weight: 600; padding: 0 4px;
}
.perm-badges .chip { white-space: normal; text-align: left; }

/* HRM module helpers */
.field-row { display: flex; flex-wrap: wrap; gap: 14px; }
.field-row .field { flex: 1 1 180px; min-width: 160px; }
.field .hint, small.hint { display: block; margin-top: 4px; font-size: 11px; color: var(--muted); }
p.hint { color: var(--muted); font-size: 13px; margin: 0 0 14px; }

/* Style bare selects/textareas (HRM forms) to match the .field inputs */
.field select {
  width: 100%; border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--ink); border-radius: 6px; padding: 9px 36px 9px 12px; font: inherit; font-size: 14px;
  cursor: pointer; -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat; background-position: right 12px center;
}
.field select:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }
.field select:hover { border-color: var(--accent); }
.field textarea {
  width: 100%; border: 1px solid var(--line-strong); background: var(--page);
  color: var(--ink); border-radius: 6px; padding: 9px 12px; font: inherit; font-size: 14px;
  line-height: 1.5; resize: vertical; min-height: 64px;
}
.field textarea:focus { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }
.badge-ok { background: rgba(34, 160, 90, 0.15); color: #1f9d55; }
.badge-no { background: rgba(210, 60, 60, 0.15); color: #d23c3c; }
.qr-block { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border, #e5e5ea); }
.qr-token { display: inline-block; margin: 8px 0; padding: 8px 12px; border-radius: 6px;
  background: var(--surface-2, #f2f2f5); font-family: ui-monospace, monospace; font-size: 13px; word-break: break-all; }

/* ---------- UI kit: system-standard widgets ---------- */

/* modal confirmation */
.gov-modal-backdrop {
  position: fixed; inset: 0; z-index: 100; display: grid; place-items: center;
  background: rgba(10, 16, 28, 0.55); backdrop-filter: blur(2px);
}
/* display:grid above would otherwise override the [hidden] attribute, keeping
   the modal on screen for AJAX callers that don't navigate away. */
.gov-modal-backdrop[hidden] { display: none; }
.gov-modal {
  background: var(--surface); color: var(--ink); border-radius: 10px;
  width: min(420px, calc(100vw - 32px)); padding: 22px 22px 18px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.35); border: 1px solid var(--line);
}
.gov-modal-title { margin: 0 0 8px; font-size: 15.5px; font-weight: 700; }
.gov-modal-text { margin: 0 0 18px; font-size: 13.5px; color: var(--ink-2); line-height: 1.55; }
.gov-modal-actions { display: flex; gap: 10px; justify-content: flex-end; }

/* three-dot row actions dropdown */
.actions-menu { position: relative; display: inline-block; }
.actions-menu > button {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px;
  border: 1px solid var(--line-strong); border-radius: 6px; font-size: 12.5px;
  color: var(--ink-2); background: var(--surface); white-space: nowrap;
}
.actions-menu > button:hover { background: var(--page); }
.actions-menu .dots { font-weight: 700; letter-spacing: 1px; }
.actions-menu .menu {
  display: none; position: absolute; right: 0; top: calc(100% + 4px); z-index: 30;
  min-width: 190px; background: var(--surface); border: 1px solid var(--line);
  border-radius: 7px; box-shadow: var(--shadow); padding: 5px; text-align: left;
}
.actions-menu.open .menu { display: block; }
.actions-menu .menu a, .actions-menu .menu button {
  display: flex; width: 100%; align-items: center; gap: 8px; padding: 8px 10px;
  border-radius: 5px; font-size: 13px; color: var(--ink); text-decoration: none;
  background: none; border: none; text-align: left;
}
.actions-menu .menu a:hover, .actions-menu .menu button:hover { background: var(--page); }
.actions-menu .menu .danger { color: var(--crit); }
.actions-menu .menu form { margin: 0; }

/* uz/ru/en language tabs */
.lang-tabs { margin-bottom: 12px; }
.lang-tabs .lang-tab-bar { display: inline-flex; gap: 2px; background: var(--neutral-soft); padding: 3px; border-radius: 6px; margin-bottom: 8px; }
.lang-tabs .lang-tab {
  padding: 5px 14px; border-radius: 5px; font-size: 12px; font-weight: 600;
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em;
}
.lang-tabs .lang-tab.active { background: var(--surface); color: var(--accent); box-shadow: var(--shadow); }
.lang-tabs .lang-pane[hidden] { display: none; }

/* toggle switch (active/inactive style booleans) */
.switch { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 13.5px; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  width: 40px; height: 22px; flex: none; border-radius: 99px; background: var(--line-strong);
  position: relative; transition: background 0.15s ease;
}
.switch .track::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
  border-radius: 50%; background: #fff; transition: transform 0.15s ease;
  box-shadow: 0 1px 3px rgba(0,0,0,0.3);
}
.switch input:checked + .track { background: var(--accent); }
.switch input:checked + .track::after { transform: translateX(18px); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch-group { display: flex; flex-wrap: wrap; gap: 14px 26px; padding: 4px 0; }

/* checkbox/radio button-pill groups */
.check-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.check-pills label { position: relative; cursor: pointer; }
.check-pills input { position: absolute; opacity: 0; inset: 0; }
.check-pills .pill {
  display: inline-block; padding: 7px 14px; border-radius: 99px; font-size: 12.5px;
  border: 1px solid var(--line-strong); color: var(--ink-2); background: var(--surface);
  transition: all 0.12s ease; user-select: none;
}
.check-pills input:checked + .pill {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
.check-pills input:focus-visible + .pill { outline: 2px solid var(--accent); outline-offset: 2px; }

/* form layout sections */
.form-section {
  border: 1px solid var(--line); border-radius: 8px; padding: 16px 18px 18px;
  margin: 0 0 14px; min-width: 0;
}
.form-section > legend {
  padding: 0 8px; margin-left: -8px; font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--accent);
}

/* flatpickr theme alignment */
.flatpickr-calendar { background: var(--surface); color: var(--ink); border: 1px solid var(--line); box-shadow: var(--shadow); }
.flatpickr-day.selected, .flatpickr-day.selected:hover { background: var(--accent); border-color: var(--accent); }

/* responsive filter toolbar: inputs/selects stretch to fill the row */
.toolbar .search { flex: 1 1 280px; width: auto; min-width: 220px; }
.toolbar select { flex: 1 1 220px; min-width: 180px; }
.toolbar .ts-wrapper { flex: 1 1 220px; min-width: 180px; width: auto; }
.toolbar .ts-wrapper .ts-control { width: 100%; }
.map-borders-toggle { font-size: 13px; color: var(--ink-2); white-space: nowrap; }
@media (max-width: 900px) {
  .toolbar .search,
  .toolbar select,
  .toolbar .ts-wrapper,
  .toolbar input[name] { width: 100%; flex: 1 1 100%; min-width: 0; }
  .toolbar .btn-ghost, .toolbar .btn-primary { flex: 1 1 auto; text-align: center; justify-content: center; }
  .toolbar .ml-auto { margin-left: 0; }
}

/* ---------- Road segments drawer (roads map) ---------- */
.rs-backdrop {
  position: fixed; inset: 0; z-index: 90;
  display: flex; justify-content: flex-end;
  background: rgba(10, 16, 28, 0.42);
  backdrop-filter: blur(2px);
  opacity: 0; transition: opacity 0.22s ease;
}
.rs-backdrop[hidden] { display: none; }
.rs-backdrop.open { opacity: 1; }

.rs-drawer {
  width: min(500px, 94vw); height: 100%;
  display: flex; flex-direction: column;
  background: var(--surface);
  border-left: 1px solid var(--line-strong);
  box-shadow: -10px 0 34px rgba(16, 31, 56, 0.20);
  transform: translateX(100%);
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}
.rs-backdrop.open .rs-drawer { transform: translateX(0); }

.rs-head {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 20px 22px; border-bottom: 1px solid var(--line);
}
.rs-head-titles { flex: 1; min-width: 0; }
.rs-title {
  margin: 0; font-size: 16px; font-weight: 680; color: var(--ink);
  line-height: 1.35;
}
.rs-sub { margin-top: 4px; font-size: 12.5px; color: var(--muted); font-weight: 600; }
.rs-close {
  flex: none; width: 34px; height: 34px; border-radius: 6px;
  border: 1px solid var(--line); background: var(--page);
  color: var(--ink-2); font-size: 20px; line-height: 1; cursor: pointer;
  display: grid; place-items: center; transition: background 0.15s, color 0.15s;
}
.rs-close:hover { background: var(--crit-soft); color: var(--crit-ink); border-color: transparent; }

.rs-body { flex: 1; overflow-y: auto; padding: 18px 22px 28px; }
.rs-note { color: var(--muted); font-size: 13px; text-align: center; padding: 28px 0; }
.rs-note-err { color: var(--crit-ink); }

.rs-group { margin-bottom: 22px; }
.rs-group-head { display: flex; align-items: center; gap: 9px; margin-bottom: 10px; }
.rs-group-title {
  font-size: 11.5px; font-weight: 720; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-2);
}
.rs-group-count {
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px;
  display: inline-grid; place-items: center; font-size: 11px; font-weight: 700;
  background: var(--neutral-soft); color: var(--neutral-ink);
}
.rs-add {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 11px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--accent); background: transparent; color: var(--accent);
  font-size: 12px; font-weight: 640; transition: background 0.15s, color 0.15s;
}
.rs-add:hover { background: var(--accent); color: var(--accent-ink); }
.rs-add svg { display: block; }

.rs-list { display: flex; flex-direction: column; gap: 8px; }
.rs-seg {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px; border-radius: 7px;
  background: var(--page); border: 1px solid var(--line);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.rs-seg:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.rs-seg-km { font-size: 13.5px; font-weight: 620; color: var(--ink); font-variant-numeric: tabular-nums; }
.rs-seg-actions { margin-left: auto; display: inline-flex; gap: 4px; }
.rs-icon {
  width: 30px; height: 30px; border-radius: 6px; cursor: pointer;
  border: 1px solid transparent; background: transparent; color: var(--muted);
  display: grid; place-items: center; transition: background 0.15s, color 0.15s;
}
.rs-icon:hover { background: var(--accent-soft); color: var(--accent); }
.rs-icon-danger:hover { background: var(--crit-soft); color: var(--crit-ink); }

.rs-empty {
  margin: 0; padding: 16px; text-align: center; font-size: 12.5px;
  color: var(--muted); background: var(--page);
  border: 1px dashed var(--line-strong); border-radius: 7px;
}

/* Value chips — one distinct colour per road category (1..5) */
.rs-chip {
  display: inline-flex; align-items: center; padding: 3px 10px;
  border-radius: 999px; font-size: 11.5px; font-weight: 680; white-space: nowrap;
}
.rs-val-1 { background: var(--accent-soft);  color: var(--accent); }
.rs-val-2 { background: var(--ok-soft);      color: var(--ok-ink); }
.rs-val-3 { background: var(--warn-soft);    color: var(--warn-ink); }
.rs-val-4 { background: var(--crit-soft);    color: var(--crit-ink); }
.rs-val-5 { background: var(--neutral-soft); color: var(--neutral-ink); }

/* Inline add / edit form */
.rs-form {
  padding: 14px; border-radius: 7px; margin-bottom: 2px;
  background: var(--page); border: 1px solid var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.rs-form-row { display: flex; gap: 12px; }
.rs-form-row .rs-field { flex: 1; }
.rs-field { display: block; margin-bottom: 12px; }
.rs-field:last-of-type { margin-bottom: 12px; }
.rs-field > span {
  display: block; margin-bottom: 5px; font-size: 11.5px; font-weight: 620; color: var(--ink-2);
}
.rs-field select, .rs-field input {
  width: 100%; padding: 8px 10px; border-radius: 6px;
  border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--ink); font-size: 13px; font-family: inherit;
}
.rs-field select:focus, .rs-field input:focus {
  outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent);
}
.rs-form-err {
  margin: 0 0 10px; font-size: 12px; color: var(--crit-ink);
  background: var(--crit-soft); padding: 7px 10px; border-radius: 5px;
}
.rs-form-actions { display: flex; gap: 8px; }
.rs-form-actions .btn-primary, .rs-form-actions .btn-ghost { padding: 7px 16px; font-size: 12.5px; }

@media (max-width: 560px) {
  .rs-drawer { width: 100vw; }
  .rs-form-row { flex-direction: column; gap: 0; }
}

/* ---------------------------------------------------------------------------
   Collapsible nav groups + sidebar collapse
   The sidebar width is a token so the collapsed rail and the transition stay
   in sync; `.gov-sidebar` itself is still the sticky 100vh flex column.
--------------------------------------------------------------------------- */
.gov-sidebar { width: var(--sidebar-w, 248px); transition: width 0.18s ease; }
.gov-sidebar.collapsed { --sidebar-w: 68px; }

.brand { position: relative; }
.nav-toggle {
    position: absolute; top: 10px; right: 8px;
    width: 28px; height: 28px; display: grid; place-items: center;
    border-radius: 5px; color: var(--sidebar-ink); opacity: 0.75;
}
.nav-toggle:hover { background: rgba(255, 255, 255, 0.1); opacity: 1; }

.gov-sidebar.collapsed .brand { padding: 16px 8px 12px; }
/* In the rail the plate shrinks with the mark, or 8px of padding would eat a
   quarter of the 68px column. */
.gov-sidebar.collapsed .brand-logo { width: 32px; padding: 5px; border-radius: 7px; }
.gov-sidebar.collapsed .brand-text,
.gov-sidebar.collapsed .sidebar-foot { display: none; }
.gov-sidebar.collapsed .nav-toggle { position: static; margin: 8px auto 0; }

.nav-group { margin-bottom: 2px; }
.nav-group > .nav-label {
    display: flex; align-items: center; gap: 6px; width: 100%;
    padding: 10px 10px 6px; text-align: left;
    font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.09em;
    color: inherit; opacity: 0.55; border-radius: 5px;
}
.nav-group > .nav-label:hover { opacity: 0.85; }
.nav-group > .nav-label span { flex: 1; min-width: 0; }
.nav-group > .nav-label .chev { flex: none; transition: transform 0.16s ease; }
.nav-group.collapsed > .nav-label .chev { transform: rotate(-90deg); }
.nav-group.collapsed > .nav-group-body { display: none; }

/* Icon-only rail: labels and group headers fold away, icons centre. */
.gov-sidebar.collapsed .gov-nav { padding: 10px 8px; }
.gov-sidebar.collapsed .nav-group > .nav-label { display: none; }
.gov-sidebar.collapsed .nav-group.collapsed > .nav-group-body { display: block; }
.gov-sidebar.collapsed .nav-group + .nav-group { border-top: 1px solid var(--sidebar-line); padding-top: 6px; margin-top: 6px; }
.gov-sidebar.collapsed .gov-nav a { justify-content: center; padding: 9px 0; }
.gov-sidebar.collapsed .gov-nav a > span { display: none; }
.gov-sidebar.collapsed .gov-nav .ic { width: 20px; height: 20px; }

/* ---------------------------------------------------------------------------
   Interactive map workspace

   The map is the screen. There is no bar above it and none below it: the
   search rides over its top edge, the filter panel floats clear of its right
   edge, and the dock sits in the bottom-left corner. Every gap, radius and
   control height is a Fibonacci step (5 / 8 / 13 / 21 / 34 / 55), and the
   floating cards share one glass treatment so they read as one layer above
   the canvas rather than as five unrelated boxes.
--------------------------------------------------------------------------- */
body.map-page {
    display: block; height: 100vh; height: 100dvh; overflow: hidden;
}

.map-shell {
    --m-gap: 13px;
    --m-radius: 11px;
    --m-panel: clamp(288px, 21vw, 372px);
    /* The one panel that decides what is drawn. It has the whole left edge
       because that is what it is for; the tools it displaced are along the
       bottom. */
    /* The rail down its left is a 38 px strip of turned names, so the pane
       beside it keeps very nearly the whole column. */
    --m-layers: clamp(306px, 22vw, 366px);
    /* The map API paints its own "Яндекс Карты" badge in this corner and it
       has to stay readable, so the dock clears it rather than sitting on it. */
    --m-dock: 34px;
    /* The bottom bar's height, and zero here on purpose: not every map has
       one. The workspace does and sets it below; the trunk-network screen
       has no dock at all, and a shell that reserved 52 px for a bar that is
       never drawn leaves a dead strip under the canvas. */
    --m-bar: 0px;
    /* Two 38px columns plus their gap, padding and border. */
    --m-tools: 91px;
    /* One height for everything standing on the bottom strip. They were
       drawn at 38, 40, 44, 46, 47 and 48 px — every card sized by whatever
       happened to be inside it — and a row of blocks that do not line up
       reads as a row that is broken rather than as one that is varied. */
    --m-dock-h: 44px;
    /* The widest card the left column holds, which is what everything opening
       beside the column has to clear. */
    --m-left: 144px;
    /* Opaque unless the browser can mix a translucent surface for us; a
       failed color-mix would otherwise leave every floating card unpainted. */
    --m-glass: var(--surface);
    position: fixed; inset: 0; overflow: hidden;
}
@supports (background: color-mix(in srgb, white 50%, transparent)) {
    .map-shell { --m-glass: color-mix(in srgb, var(--surface) 88%, transparent); }
}
#govMap { position: absolute; inset: 0; z-index: 0; }

/* One treatment for everything that floats over the canvas. */
.map-find-bar,
.map-find-list,
.map-panel-card,
.map-panel-head,
.map-layers-card,
.map-tape,
.map-toast,
.map-keys,
.dock-card {
    border: 1px solid var(--line);
    border-radius: var(--m-radius);
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}

/* ------------------------------------------------------------ map search */
/* Centred over the top edge, because that is where the eye starts. The
   results drop under it, and picking one flies the camera to that road. */
/* Centred over the top edge, seven pixels from it, and no wider than the
   space between the tools and the filter panel. */
.map-find {
    position: absolute; z-index: 6; top: 7px; left: 50%; transform: translateX(-50%);
    width: min(466px, calc(100% - 2 * max(var(--m-panel), var(--m-layers)) - 4 * var(--m-gap)));
    min-width: 288px;
    display: flex; flex-direction: column;
}
.map-find-bar {
    flex: none; display: flex; align-items: center; gap: 6px; padding: 4px 4px 4px 10px;
    border-radius: 8px;
}
.map-find-bar > svg { width: 15px; height: 15px; flex: none; color: var(--muted); }
.map-find-bar input {
    flex: 1; min-width: 0; height: 28px; border: 0; background: none;
    color: var(--ink); font-size: 12.5px; outline: none;
}
.map-find-bar .btn-primary {
    height: 28px; width: 30px; flex: none; padding: 0;
    display: inline-grid; place-items: center; border-radius: 6px;
}
.map-find-bar .btn-primary svg { width: 14px; height: 14px; }
/* Our own clear button, so the way out of a search is the same in every
   browser — Chrome draws a native one and Firefox none — and it takes back
   the filter as well as the text. The native one is hidden for that reason. */
.map-find-x {
    width: 24px; height: 24px; flex: none; display: grid; place-items: center;
    padding: 0; border: 0; border-radius: 50%;
    background: var(--page); color: var(--muted); cursor: pointer;
}
.map-find-x:hover { background: var(--line); color: var(--ink); }
.map-find-x[hidden] { display: none; }
.map-find-x svg { width: 12px; height: 12px; }
#filterSearch::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }

/* Which road the DRP figures count, while one is selected. Said above the
   tiles because the same tile reading 40 and 4 000 means two different
   questions, and only this line says which one was asked. */
.ml-scope {
    margin: 0 0 8px; padding: 6px 10px; border-radius: 7px;
    background: var(--accent-soft); color: var(--accent);
    font-size: 11.5px; font-weight: 650;
}
.ml-scope[hidden] { display: none; }
.map-find-list {
    list-style: none; margin: 6px 0 0; padding: 5px;
    /* Tall enough for both registers at their capped five rows plus their two
       headings — a search that covers two registers and shows one of them is
       not one search. */
    min-height: 0; max-height: min(56vh, 430px); overflow-y: auto;
    border-radius: 9px;
}
.map-find-list[hidden] { display: none; }
.map-find-item {
    width: 100%; display: flex; align-items: center; gap: 8px;
    padding: 7px 9px; border-radius: 8px; text-align: left; font-size: 12.5px;
    color: var(--ink-2); background: none; border: 0; cursor: pointer;
}
.map-find-item:hover { background: var(--page); color: var(--ink); }
.map-find-item i { width: 8px; height: 8px; border-radius: 50%; flex: none; }
/* The offer to go to a typed coordinate, which carries a pin where a road
   carries its class colour. */
.map-find-item > svg { width: 15px; height: 15px; flex: none; color: var(--accent); }
.map-find-coord .nm { font-weight: 600; color: var(--ink); }
.map-find-item .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-find-item .ix {
    flex: none; font-size: 10.5px; font-weight: 700; color: var(--accent);
    background: var(--accent-soft); border-radius: 99px; padding: 1px 6px;
}
.map-find-item b { flex: none; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.map-find-empty { padding: 9px 10px; font-size: 12px; color: var(--muted); text-align: center; }

/* Two registers in one list. The heading only appears when there is a second
   group to tell it apart from — a lone heading over a lone group is a label
   nobody needed. */
.map-find-group {
    padding: 8px 10px 3px; font-size: 9.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted);
}
.map-find-group:first-child { padding-top: 3px; }
.map-find-more { padding: 4px 10px 7px; font-size: 10.5px; color: var(--muted); }
/* A survey road carries the trace the survey panel is drawn with, so the two
   read as the same thing in two places. */
.map-find-survey > svg { width: 15px; height: 15px; flex: none; color: var(--accent); }

/* The readout that names the road the survey register is pointed at. Pressing
   it puts the cursor in the one search, which is where the road is chosen. */
/* Deliberately not a field.

   It was a bordered box with a magnifier in it, which is a text input in every
   way a reader can see — so they typed into it, nothing happened, and the
   panel looked broken. It is a value with a way to change it now: no frame, no
   magnifier, the road in the panel's own type and a quiet verb beside it. */
/* One row: the road on the left, the survey year on the right. It was a
   stacked column of four labelled rows, which is a lot of chrome over a panel
   whose whole job is what is under it.

   The row itself is declared **once**, with the panel's own chrome, further
   down. A second `.ml-picker` stood here and lost `display` and
   `flex-direction` to it, which left exactly the two properties that one does
   not set — `align-items: flex-end` and the basis below — standing inside a
   column they were never written for: in a column a `flex-basis` is a
   *height*, so the road field became 140 px of nothing, and `flex-end` is the
   cross axis, so every value was pushed to the right-hand edge. Measured at
   the panel's real width (318 px), that block was 207 px tall. It is 80 px. */
.ml-picker[hidden] { display: none; }
.ml-picker > .ml-field { flex: 1 1 140px; min-width: 0; }
.ml-picker > .ml-field-year { flex: 0 0 auto; }
/* The label is what sizes this field, so it must not wrap: "ГОД
   ОБСЛЕДОВАНИЯ" over two lines makes the row as tall again as the control it
   names, which is what sent the year under the road in the first place. */
.ml-field-year > span { white-space: nowrap; }
.ml-input-sm { width: auto; min-width: 92px; }
/* The road's other numbers, quiet and on their own line under its name.
   `display: block` never achieved that on its own — the button is a flex row
   and a block child is simply an item in it — so it takes a full basis; and
   `order`, because the markup puts this between the name and the verb, where
   a full-width item sends that verb down to a third line. */
.ml-road-alt { order: 1; flex: 1 0 100%; font-size: 10.5px; line-height: 1.35; color: var(--muted); }
.ml-road-alt[hidden] { display: none; }
.ml-road-face {
    width: 100%; min-height: 32px; padding: 0;
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 8px;
    border: 0; background: none; color: var(--ink); cursor: pointer;
    font-size: 12.5px; text-align: left;
}
.ml-road-face b {
    min-width: 0; max-width: 100%; font-weight: 700; font-size: 14px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ml-road-face > span {
    flex: none; font-size: 10.5px; color: var(--accent);
    border-bottom: 1px dashed currentColor;
}
.ml-road-face:hover > span { border-bottom-style: solid; }
.ml-road-face:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
/* Which stretch of the road every figure below is counted over. Under the
   road's own name rather than beside it: it qualifies the whole panel, not
   the name, and a reader scanning the counts has to meet it on the way. */
.ml-bound {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
    margin: -2px 0 0; font-size: 11px; color: var(--muted);
}
.ml-bound[hidden] { display: none; }
.ml-bound button {
    flex: none; padding: 0; border: 0; background: none; cursor: pointer;
    font: inherit; color: var(--accent);
    border-bottom: 1px dashed currentColor;
}
.ml-bound button:hover { border-bottom-style: solid; }

.map-field .ml-road-face { min-height: 36px; }
.map-field .ml-road-face b { font-size: 14.5px; }

/* -------------------------------------------------------- filter panel */
/* Detached from the edge on every side, so the canvas keeps running under
   it — on a wall screen the map is the point, and a rail glued to the frame
   cuts a column out of it. */
.map-panel {
    position: absolute; z-index: 6;
    top: var(--m-gap); right: var(--m-gap); bottom: var(--m-gap);
    width: var(--m-panel);
    display: flex; flex-direction: column; align-items: stretch; gap: 8px;
    pointer-events: none;
}
.map-panel > * { pointer-events: auto; }

/* The panel's own header bar, and its fold.

   It was a 34 px square floating beside the card. Folding the panel left that
   square alone on the edge — a control whose whole message is "there used to
   be a panel here", in a column that had just thrown its width away. As a
   header the width is the panel's whether it is open or folded, so what comes
   back is where it was left. */
.map-panel-head {
    flex: none; width: 100%; height: 40px; padding: 0 12px;
    display: flex; align-items: center; gap: 9px;
    color: var(--ink-2); cursor: pointer; text-align: left;
}
.map-panel-head:hover { color: var(--ink); }
.map-panel-ic { width: 16px; height: 16px; flex: none; color: var(--accent); }
.map-panel-name {
    flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
}
.map-panel-chev { width: 15px; height: 15px; flex: none; transition: transform 0.18s ease; }
/* How much is holding. On the header rather than inside the card, because
   the header is the one part of the panel that survives being folded — and a
   reader who folds the panel and then wonders why the network looks thin is
   exactly the reader this number is for. */
.map-panel-live {
    flex: none; padding: 1px 7px; border-radius: 99px;
    background: var(--accent-soft); color: var(--accent);
    font-size: 10.5px; font-weight: 700; letter-spacing: 0;
}

.map-panel-card {
    flex: 1; min-width: 0; min-height: 0;
    /* A column of sections that fold. It was a row, with a rail of turned
       tabs down the outer edge — see `wirePanelSections`. */
    display: flex; flex-direction: column; overflow: hidden;
}
/* One sheet, divided — not a stack of little cards.

   The panel asks three things in order (where, what is holding, what is
   picked) and they are steps of one reading rather than three objects on a
   shelf, so they are separated by a rule and not by a gutter. The padding
   went with the gutter: a section owns its own 13px, which is what lets a
   list inside one run edge to edge under its heading. */
.map-panel-body {
    flex: 1; min-width: 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    display: flex; flex-direction: column;
    scrollbar-width: thin;
}
.map-insp {
    flex: none; min-width: 0; padding: 13px;
    display: flex; flex-direction: column; gap: 10px;
}
.map-insp + .map-insp { border-top: 1px solid var(--line); }
.map-insp-head { display: flex; align-items: center; gap: 8px; }
.map-insp-ic { width: 16px; height: 16px; flex: none; color: var(--accent); }
.map-insp-name {
    flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 11px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--ink-2);
}
.map-insp-link {
    flex: none; padding: 0; border: 0; background: none; cursor: pointer;
    font-size: 11.5px; font-weight: 600; color: var(--muted);
}
.map-insp-link:hover { color: var(--accent); }
.map-insp-count {
    flex: none; padding: 1px 7px; border-radius: 99px;
    background: var(--neutral-soft); color: var(--muted);
    font-size: 10.5px; font-weight: 700;
}
.map-insp-count.on { background: var(--accent-soft); color: var(--accent); }
.map-insp-apply { width: 100%; height: 34px; font-size: 12.5px; }

/* ---------- the place chain ---------- */
/* Three questions that narrow each other, drawn as the chain they are. The
   node fills in when its own step is answered; the connector below it only
   colours when the step *under* it is answered too, so the rail reads as how
   far down the hierarchy the reader has actually got. */
.map-chain { display: flex; flex-direction: column; }
.map-chain-step { display: flex; gap: 11px; align-items: stretch; }
.map-chain-step.is-locked { opacity: 0.5; }
.map-chain-rail {
    width: 14px; flex: none; display: flex; flex-direction: column; align-items: center;
}
.mc-line { width: 2px; background: var(--line); }
.mc-top { height: 12px; }
.mc-bottom { flex: 1; }
.map-chain-step:first-child .mc-top,
.map-chain-step:last-child .mc-bottom { background: transparent; }
.mc-node {
    width: 12px; height: 12px; flex: none; box-sizing: border-box;
    border-radius: 50%; border: 1.6px solid var(--line-strong); background: var(--surface);
}
.map-chain-step.is-set > .map-chain-rail .mc-node { border-color: var(--accent); background: var(--accent); }
.map-chain-step.is-set > .map-chain-rail .mc-top,
.map-chain-step.is-set + .map-chain-step > .map-chain-rail .mc-top { background: var(--accent); }
.map-chain-step.is-set:has(+ .map-chain-step.is-set) > .map-chain-rail .mc-bottom { background: var(--accent); }
.map-chain-field {
    position: relative; flex: 1; min-width: 0;
    display: flex; flex-direction: column; gap: 1px; padding: 4px 0 8px;
}
.map-chain-label {
    font-size: 10px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
    color: var(--muted);
}
/* The select itself wears the box. Tom Select is bound to these — the map's
   pickers are searchable, which a transparent select laid over a drawn box
   would throw away — so the face is styled at `.ts-control`, and the bare
   element is styled to match for the moment before the widget is built. */
.map-chain-select {
    width: 100%; height: 34px; padding: 0 10px;
    border: 1px solid var(--line-strong); border-radius: 6px;
    background: var(--surface); color: var(--ink); font: inherit; font-size: 13px;
}
/* The widget copies the original select's class list onto its wrapper, so
   the wrapper would wear the box too and draw it twice. It is stripped bare
   and the box moves to the control — written at `.ts-wrapper.single
   .ts-control` or narrower, because that is the selector the widget's own
   stylesheet uses and anything shorter loses to it. */
.map-chain-field .ts-wrapper { border: 0; background: none; padding: 0; border-radius: 0; height: auto; }
.map-chain-field .ts-wrapper.single .ts-control {
    min-height: 34px; height: 34px; padding: 0 10px;
    border: 1px solid var(--line-strong); border-radius: 6px; background: var(--surface);
    font-size: 13px; color: var(--muted);
}
.map-chain-field .ts-wrapper.disabled .ts-control { background: var(--page); }
.map-chain-step.is-set .map-chain-select,
.map-chain-step.is-set .map-chain-field .ts-wrapper.single .ts-control { font-weight: 600; color: var(--ink); }

/* ---------- what is holding ---------- */
.map-active {
    display: flex; flex-direction: column;
    border: 1px solid var(--line); border-radius: 9px; background: var(--surface); overflow: hidden;
}
.map-active[hidden] { display: none; }
.map-active-row {
    display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 11px;
    border: 0; background: none; width: 100%; text-align: left; color: inherit; font: inherit;
}
.map-active-row + .map-active-row { border-top: 1px solid var(--line); }
.map-active-row[data-ml-open] { cursor: pointer; }
.map-active-row[data-ml-open]:hover { background: var(--page); }
/* The group's colour, as a bar rather than a dot: it is read down the list
   as "these four are the survey's", which a dot in a row of text is not. */
.map-active-bar { width: 4px; align-self: stretch; flex: none; border-radius: 99px; }
.map-active-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.map-active-txt > i { font-style: normal; font-size: 10px; color: var(--muted); }
.map-active-txt > b {
    font-size: 12.5px; font-weight: 600; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.map-active-x {
    flex: none; width: 26px; height: 26px; display: grid; place-items: center;
    border: 0; border-radius: 6px; background: none; color: var(--muted); cursor: pointer;
}
.map-active-x:hover { background: var(--crit-soft); color: var(--crit); }
.map-active-x svg { width: 13px; height: 13px; }
.map-active-none {
    margin: 0; padding: 12px 10px; border-radius: 7px; background: var(--page);
    text-align: center; font-size: 11.5px; color: var(--muted);
}
.map-active-clear {
    align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
    height: 30px; padding: 0 10px;
    border: 1px solid var(--line); border-radius: 6px; background: var(--surface);
    color: var(--ink-2); font-size: 12px; font-weight: 600; cursor: pointer;
}
.map-active-clear:hover { border-color: var(--crit); color: var(--crit); }
.map-active-clear svg { width: 14px; height: 14px; flex: none; }
.map-active-clear[hidden] { display: none; }

/* ---------- what is picked ---------- */
/* Drawn whether or not anything is: a heading with a dashed frame under it
   says what the block is for, where an empty column said only that the panel
   had ended. */
.map-insp-empty {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 18px 12px; border: 1px dashed var(--line-strong); border-radius: 9px;
    text-align: center;
}
.map-insp-empty > b { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.map-insp-empty > span { font-size: 11px; line-height: 1.4; color: var(--muted); }
#mapInspSelected:has(#govMapDetail:not([hidden])) .map-insp-empty { display: none; }
.map-insp-sel {
    min-width: 0; display: flex; flex-direction: column; gap: 8px; font-size: 12px;
    animation: map-float-in 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.map-insp-sel[hidden] { display: none; }
.map-detail-class {
    flex: none; display: inline-flex; align-items: center; gap: 5px;
    padding: 1px 7px; border-radius: 99px;
    font-size: 10.5px; font-weight: 700;
}
.map-detail-class[hidden] { display: none; }
.map-detail-class > i { width: 7px; height: 7px; border-radius: 2px; flex: none; }
.map-detail-jump { display: flex; gap: 8px; }
.map-detail-jump[hidden] { display: none; }
.map-detail-jump > button {
    flex: 1; height: 32px; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    font-size: 12px;
}
.map-detail-jump svg { width: 14px; height: 14px; flex: none; }

/* The sections are ordinary accordions in the column: their own frame, their
   own chevron, any number open at once. They were stripped of all three while
   the rail decided which single one was showing. */
/* Folded, the panel is its own header bar and nothing else — at the width it
   had open. It used to shrink to a 34 px pill, which took the column's width
   away along with its contents and left the reader hunting for where the
   panel had gone; the width is the one thing a fold must not take. */
.map-shell.panel-closed .map-panel-card { display: none; }
.map-shell.panel-closed .map-panel { bottom: auto; }
.map-shell.panel-closed .map-panel-chev { transform: rotate(-90deg); }
.map-shell.layers-closed .map-find { width: min(466px, calc(100% - 2 * var(--m-panel) - 4 * var(--m-gap))); }
.map-shell.layers-closed .map-toast { left: calc(34px + 2 * var(--m-gap)); }

/* --------------------------------------------------------- panel sections */
.map-sec {
    flex: none; border: 1px solid var(--line); border-radius: 9px;
    background: var(--surface); overflow: hidden;
}
.map-sec-head {
    display: flex; align-items: center; gap: 8px; padding: 11px 13px;
    list-style: none; cursor: pointer; user-select: none;
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--ink-2);
}
.map-sec-head::-webkit-details-marker { display: none; }
.map-sec-head:hover { background: var(--page); }
.map-sec-head > span:first-of-type { flex: 1; min-width: 0; }
.map-sec-ic { width: 16px; height: 16px; flex: none; color: var(--accent); }
.map-sec-chev { width: 14px; height: 14px; flex: none; color: var(--muted); transition: transform 0.15s ease; }
.map-sec[open] > .map-sec-head .map-sec-chev { transform: rotate(180deg); }
.map-sec-count {
    flex: none; font-size: 10.5px; font-weight: 700; letter-spacing: 0;
    color: var(--muted); background: var(--neutral-soft); border-radius: 99px; padding: 1px 7px;
}
.map-sec-count.on { color: var(--accent); background: var(--accent-soft); }
.map-sec-body { padding: 13px; border-top: 1px solid var(--line); }
.map-sec-tools { display: flex; gap: 5px; margin-bottom: 10px; }
.map-sec-actions { display: flex; gap: 8px; margin-top: 13px; }
.map-sec-btn { flex: 1; height: 34px; display: inline-flex; align-items: center; justify-content: center; font-size: 12.5px; }
.map-mini {
    font-size: 10.5px; font-weight: 600; color: var(--accent);
    padding: 3px 8px; border-radius: 5px; background: var(--accent-soft);
}
.map-mini:hover { filter: brightness(0.96); }

.map-field { display: flex; flex-direction: column; gap: 5px; }
.map-field > span {
    font-size: 10.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--muted);
}
.map-select {
    width: 100%; height: 36px; padding: 0 10px;
    border: 1px solid var(--line-strong); border-radius: 6px;
    background: var(--surface); color: var(--ink); font: inherit; font-size: 13.5px;
}
.map-select:hover { border-color: var(--accent); }

/* Category tiles: two columns, because these lists run to twenty-odd rows
   and a single column pushed everything else off the panel. */
.map-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; }
.map-tile {
    display: flex; align-items: center; gap: 6px; min-width: 0;
    padding: 5px 6px; border-radius: 6px; text-align: left;
    border: 1px solid var(--line); background: var(--page);
    transition: background 0.12s ease, border-color 0.12s ease;
}
.map-tile:hover { border-color: var(--accent); }
.map-tile.active { background: var(--accent); border-color: var(--accent); }
/* Nothing of this kind within what the map is showing. Still offered —
   ticking it is how you find that out — but not pretending otherwise. */
.map-tile-empty:not(.active) { opacity: 0.55; }
.map-tile.active .map-tile-name { color: #fff; }
.map-tile.active .map-tile-val { color: rgba(255, 255, 255, 0.9); }
.map-tile-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; }
/* The name is the tile. It used to open with a circled initial — K, T, a
   digit — which named nothing and made twenty tiles look like twenty of the
   same thing; the wording carries the identity now, so it is what is bold. */
.map-tile-name {
    min-width: 0; font-size: 10.5px; font-weight: 650; line-height: 1.25; color: var(--ink);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.map-tile-val { font-size: 11px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
/* The category's own artwork, which is what it is drawn as on the map. The
   frame is there whether or not a picture arrives — 89 of the 103 categories
   have none uploaded, and the ones that do can still lose the file — so a
   tile is the same height and the name starts in the same column either way,
   instead of a broken glyph in some rows and nothing in others. */
.map-tile-ic {
    width: 22px; height: 22px; flex: none;
    display: grid; place-items: center;
    border-radius: 5px; background: var(--neutral-soft);
    overflow: hidden;
}
/* The glyph sits at three quarters of the tile, which is the ratio the icon
   set's own tile is drawn at (24 of 32). Filling the square edge to edge left
   the drawing touching the rounded corners it is framed by. */
.map-tile-ic img { width: 16px; height: 16px; object-fit: contain; }
.map-tile.active .map-tile-ic { background: rgba(255, 255, 255, 0.24); }

/* The grade a segment tile stands for, in the colour it is drawn in.
   Five steps of one hue read as an order; a name alone does not. */
.map-tile-dot {
    width: 11px; height: 11px; flex: none; border-radius: 3px;
    border: 1px solid rgba(0, 0, 0, 0.16);
}
.map-tile.active .map-tile-dot { border-color: rgba(255, 255, 255, 0.7); }

/* ---------------------------------------------------------- photo viewer */
/* A photo opened from a card stays on the card: full size over a dimmed page,
   walked through with the arrows or the keyboard, closed with Escape or a
   click on the frame. Opening it in a new tab loses the record it belongs to. */
.gov-shots {
    position: fixed; inset: 0; z-index: 90;
    background: rgba(9, 12, 20, 0.86);
    display: grid; grid-template-columns: 64px 1fr 64px; align-items: center;
    padding: 24px;
}
.gov-shots[hidden] { display: none; }
body.gov-shots-open { overflow: hidden; }
.gov-shots-stage {
    grid-column: 2; margin: 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.gov-shots-stage img {
    max-width: 100%; max-height: calc(100vh - 120px);
    border-radius: 8px; background: #fff;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}
.gov-shots-stage figcaption {
    color: rgba(255, 255, 255, 0.82); font-size: 12.5px;
    font-variant-numeric: tabular-nums; text-align: center;
}
.gov-shots-nav, .gov-shots-x {
    display: grid; place-items: center; cursor: pointer;
    border: 0; border-radius: 50%; color: #fff;
    background: rgba(255, 255, 255, 0.14);
}
.gov-shots-nav { width: 44px; height: 44px; }
.gov-shots-prev { grid-column: 1; justify-self: start; }
.gov-shots-next { grid-column: 3; justify-self: end; }
.gov-shots-nav svg { width: 22px; height: 22px; }
.gov-shots-nav:hover, .gov-shots-x:hover { background: rgba(255, 255, 255, 0.26); }
.gov-shots-alone .gov-shots-nav { visibility: hidden; }
.gov-shots-x { position: absolute; top: 18px; right: 18px; width: 38px; height: 38px; }
.gov-shots-x svg { width: 18px; height: 18px; }
.gov-shots-count {
    position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
    color: rgba(255, 255, 255, 0.75); font-size: 12px; font-variant-numeric: tabular-nums;
}

/* The photo block inside the map's floating card. */
.map-shots { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--line); }
.map-shots[hidden] { display: none; }
.map-shots-head {
    display: flex; align-items: baseline; gap: 6px; margin-bottom: 7px;
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
}
.map-shots-head b { color: var(--accent); font-variant-numeric: tabular-nums; }
.map-shots .shot { width: 58px; height: 58px; }

/* The road card's tail: what has been reported done on this stretch. A row
   of dates is the argument and the thumbnails under it are the evidence, so
   the two stay together rather than being split into separate blocks. */
.map-reports { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--line); }
.map-reports[hidden] { display: none; }
.map-report + .map-report { margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--line); }
.map-report-h { display: flex; align-items: baseline; gap: 8px; font-size: 12px; color: var(--ink); }
.map-report-h .nm {
    flex: 1; min-width: 0; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.map-report-h .dt { flex: none; color: var(--muted); font-variant-numeric: tabular-nums; }
.map-report-h:hover .nm { color: var(--accent); }
.map-report-meta { margin-top: 2px; font-size: 11px; color: var(--muted); }
.map-report .shot-strip { margin-top: 6px; }
.map-report .shot { width: 52px; height: 52px; border-radius: 6px; }
.map-reports-all {
    display: inline-block; margin-top: 9px;
    font-size: 11.5px; font-weight: 600; color: var(--accent);
}

/* The strip of thumbnails a record's photos are offered as. */
.shot-strip { display: flex; flex-wrap: wrap; gap: 8px; }
.shot {
    display: block; width: 74px; height: 74px; flex: none;
    border-radius: 7px; overflow: hidden; cursor: zoom-in;
    border: 1px solid var(--line); background: var(--page);
}
.shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shot:hover { border-color: var(--accent); }

/* Where the photographs are the record rather than a footnote to it — a
   day's work report, a repair request's before and after.

   Bigger than the 74 px thumbnail, and still a **fixed** tile: these cards
   had no rule for their photos at all, so a phone picture rendered at its own
   three-thousand-pixel width and ran straight out of the card. It never
   showed locally, where the seeded photos are small. `object-fit: cover`
   crops rather than squashes, and the full frame is one press away in the
   viewer every one of these thumbnails is already wired to. */
.shot-strip-lg .shot { width: 164px; height: 164px; border-radius: 8px; }

@media (max-width: 760px) {
    .shot-strip-lg .shot { width: 132px; height: 132px; }
}
@media (max-width: 480px) {
    /* Two to a row on a phone, whatever the card is worth. */
    .shot-strip-lg .shot { width: calc(50% - 4px); height: auto; aspect-ratio: 1; }
}

/* ------------------------------------------------------- points on the map */
/* A point is the thing it stands for: its category's icon on a white disc
   ringed in that category's colour, so a row of them reads as a row of kinds
   rather than as a row of dots. The colour is handed in as `color`, which is
   what the ring and the plain fallback both inherit. */
.map-pin {
    width: 26px; height: 26px; margin: -13px 0 0 -13px;
    border-radius: 50%; background: #fff;
    border: 2px solid currentColor;
    box-shadow: 0 1px 4px rgba(15, 23, 42, 0.32);
    display: grid; place-items: center; overflow: hidden;
    cursor: pointer;
}
.map-pin img { width: 15px; height: 15px; object-fit: contain; display: block; }
/* Nothing was uploaded for this kind, so the colour is all there is to say. */
.map-pin-plain { background: currentColor; border-color: #fff; width: 14px; height: 14px; margin: -7px 0 0 -7px; }


/* --------------------------------------------------------- the selection */
/* What is selected reads inside the panel's own column, as the third of the
   inspector's three sections, rather than as a second card over the map.

   Two things it used to be and is not: a card floating in the middle of the
   canvas, which put chrome over the very ground the reader had just clicked;
   and a framed block with an accent edge inside the column, which is a card
   drawn inside a card. Its own heading says what it is, and the rule above
   it separates it from what is holding — the frame was saying the same thing
   a third time. */
@keyframes map-float-in { from { opacity: 0; transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) { .map-insp-sel { animation: none; } }
.map-float-head { display: flex; align-items: center; gap: 6px; }
.map-float-head .map-detail-kind { flex: none; min-width: 0; margin: 0; }
.map-float-head .map-x { margin-left: auto; }
.map-x {
    width: 26px; height: 26px; flex: none; display: grid; place-items: center;
    border-radius: 5px; color: var(--ink-2);
}
.map-x:hover { background: var(--crit-soft); color: var(--crit-ink); }
.map-x svg { width: 15px; height: 15px; }
.map-detail-kind {
    flex: none; padding: 1px 7px; border-radius: 99px;
    background: var(--accent-soft); color: var(--accent);
    font-size: 10.5px; font-weight: 700; letter-spacing: 0;
}
.map-detail-title { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.3; }
.map-detail-row { display: flex; align-items: baseline; gap: 10px; padding: 7px 11px; font-size: 12px; }
.map-detail-row + .map-detail-row { border-top: 1px solid var(--line); }
/* The register rows are one card, and the card has to find its own edges:
   the body they sit in also carries the point readout, the copy control, the
   actions and the reports, so the frame belongs to the *run* of rows rather
   than to the block around them. First and last of a run are named by what
   is beside them, which is the only thing that tells them apart here. */
.map-detail-body > .map-detail-row {
    background: var(--surface);
    border-left: 1px solid var(--line); border-right: 1px solid var(--line);
}
.map-detail-body > .map-detail-row:not(.map-detail-row + .map-detail-row) {
    border-top: 1px solid var(--line); border-top-left-radius: 9px; border-top-right-radius: 9px;
}
.map-detail-body > .map-detail-row:not(:has(+ .map-detail-row)) {
    border-bottom: 1px solid var(--line); border-bottom-left-radius: 9px; border-bottom-right-radius: 9px;
}
.map-detail-row > span { flex: 1; min-width: 0; color: var(--muted); overflow-wrap: break-word; }
.map-detail-row > b { font-weight: 600; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; min-width: 0; overflow-wrap: break-word; }
/* The clicked point, ready to be taken elsewhere. Reading a coordinate off a
   screen and typing it back in by hand is how a coordinate acquires a typo. */
.map-detail-copy > button {
    display: flex; align-items: center; gap: 6px; padding: 2px 6px; margin: -2px -6px;
    border: 0; border-radius: 5px; background: none; cursor: pointer;
    color: var(--ink); font: inherit; font-size: 12px;
    /* Without this the button cannot shrink below its own content, so a long
       value runs back over its label instead of wrapping under itself. Only
       `overflow-wrap`, never `word-break: break-word`: these are compound
       technical terms and that breaks them where no reader would. */
    min-width: 0; max-width: 68%;
}
.map-detail-copy > button:hover { background: var(--page); }
.map-detail-copy > button b {
    font-weight: 600; font-variant-numeric: tabular-nums;
    min-width: 0; text-align: right; overflow-wrap: break-word; word-break: normal;
}
.map-detail-copy > button svg { width: 13px; height: 13px; flex: none; color: var(--muted); }
.map-detail-copy > button.copied { background: var(--ok-soft); color: var(--ok-ink); }
.map-detail-copy > button.copied svg { color: var(--ok); }
/* Where the browser refused the clipboard, the text is selected instead. */
.map-detail-copy > button.selected { background: var(--accent-soft); }

.map-detail-actions { margin-top: 13px; display: flex; gap: 8px; }
.map-detail-actions > a { flex: 1; text-align: center; }

/* ------------------------------------------- the point under the cursor */
/* The kilometre and the coordinate the pointer is on, in the panel rather
   than only in the card that follows the cursor: the hover card is where a
   figure is glanced at and this is where it is taken from. Set apart from the
   registry rows above it, because those describe the road and these two
   describe one point on it. */
.map-point {
    margin-top: 11px; padding: 8px 10px 4px;
    border: 1px solid var(--line); border-radius: 6px; background: var(--page);
}
.map-point-head {
    display: flex; align-items: baseline; gap: 8px;
    font-size: 10.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--muted);
}
.map-point-head > span { flex: 1; min-width: 0; }
.map-point-head > i { font-style: normal; font-weight: 600; letter-spacing: 0; text-transform: none; color: var(--accent); }
.map-point .map-detail-row { padding: 4px 0; }
.map-point .map-detail-row:first-of-type { border-top: 0; }
.map-point-hint { margin: 5px 0 6px; font-size: 11.5px; line-height: 1.45; color: var(--muted); }

/* --------------------------------------------- copying the whole card */
/* One press copies, the chevron chooses what "copy" means. The chosen form
   stays on the face of the button, so the reader never has to open the list
   to find out what the next press will do. */
.map-copy-all { position: relative; display: flex; margin-top: 11px; }
.map-copy-all > button {
    display: flex; align-items: center; gap: 7px; padding: 7px 10px;
    border: 1px solid var(--line); background: var(--surface); cursor: pointer;
    color: var(--ink); font: inherit; font-size: 12px; font-weight: 600;
}
.map-copy-all .mca-go { flex: 1; min-width: 0; border-radius: 6px 0 0 6px; }
.map-copy-all .mca-more { border-radius: 0 6px 6px 0; border-left: 0; padding: 7px 8px; }
.map-copy-all > button:hover { background: var(--page); }
.map-copy-all > button svg { width: 14px; height: 14px; flex: none; color: var(--muted); }
.map-copy-all .mca-go > span { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-copy-all .mca-face {
    flex: none; padding: 1px 6px; border-radius: 999px;
    background: var(--accent-soft); color: var(--accent);
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
}
.map-copy-all .mca-go.copied { background: var(--ok-soft); color: var(--ok-ink); border-color: var(--ok-soft); }
.map-copy-all .mca-go.copied svg { color: var(--ok); }
.map-copy-all .mca-go.selected { background: var(--accent-soft); }
/* Upwards: the button sits at the foot of a card that is already as tall as
   the map, so a list dropping below it would open off the bottom. */
.map-copy-all .mca-menu {
    position: absolute; z-index: 12; right: 0; bottom: calc(100% + 5px);
    min-width: 168px; padding: 4px;
    border: 1px solid var(--line); border-radius: 7px; background: var(--surface);
    box-shadow: 0 10px 28px rgba(15, 23, 42, 0.18);
}
.map-copy-all .mca-menu[hidden] { display: none; }
.map-copy-all .mca-menu button {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 7px 9px; border: 0; border-radius: 5px; background: none; cursor: pointer;
    color: var(--ink); font: inherit; font-size: 12px; text-align: left;
}
.map-copy-all .mca-menu button:hover { background: var(--page); }
.map-copy-all .mca-menu button > span { flex: 1; min-width: 0; }
.map-copy-all .mca-tick { width: 13px; height: 13px; flex: none; color: var(--accent); visibility: hidden; }
.map-copy-all .mca-menu button[aria-checked="true"] { color: var(--accent); font-weight: 650; }
.map-copy-all .mca-menu button[aria-checked="true"] .mca-tick { visibility: visible; }

/* ------------------------------------------------------ what the keys do */
.map-keys {
    position: absolute; z-index: 9; left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: min(352px, calc(100% - 2 * var(--m-gap)));
    max-height: calc(100% - 2 * var(--m-gap)); overflow-y: auto;
    padding: 11px 14px 12px; font-size: 12px;
}
.map-keys[hidden] { display: none; }
.map-keys-row {
    display: flex; align-items: center; gap: 12px; padding: 6px 0;
}
.map-keys-row + .map-keys-row { border-top: 1px solid var(--line); }
.map-keys-row > span { flex: 1; min-width: 0; color: var(--ink); }
.map-keys-row > kbd {
    flex: none; padding: 2px 8px; border: 1px solid var(--line); border-bottom-width: 2px;
    border-radius: 4px; background: var(--page); color: var(--ink-2);
    font-family: inherit; font-size: 11px; font-weight: 700; white-space: nowrap;
}
/* Cluster contents: a clickable list of the objects under one bubble. */
.map-detail-list { display: flex; flex-direction: column; gap: 2px; max-height: 42vh; overflow-y: auto; }
.map-detail-item {
    display: flex; align-items: center; gap: 9px; width: 100%;
    padding: 8px; border-radius: 6px; text-align: left; font-size: 12.5px;
}
.map-detail-item:hover { background: var(--page); }
.map-detail-item .dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.map-detail-item .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.map-detail-item .km { flex: none; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.map-empty { margin: 0; font-size: 12.5px; color: var(--muted); }

/* ------------------------------------------------------- hover readout */
/* Follows the cursor along a road and reports the kilometre under it. Never
   takes the pointer: the map has to keep receiving every move that drives it. */
.map-hover {
    position: absolute; z-index: 4; pointer-events: none;
    min-width: 152px; max-width: 280px;
    padding: 10px 13px 11px; border: 1px solid var(--line);
    border-left: 3px solid var(--accent); border-radius: 9px;
    background: var(--m-glass); backdrop-filter: blur(13px);
    -webkit-backdrop-filter: blur(13px); box-shadow: var(--shadow);
    opacity: 0; transform: translateY(4px); transition: opacity 0.12s ease, transform 0.12s ease;
}
.map-hover.on { opacity: 1; transform: none; }
.map-hover-head { display: flex; align-items: baseline; gap: 8px; }
.map-hover-name {
    flex: 1; min-width: 0; font-size: 13px; font-weight: 650; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.map-hover-index {
    flex: none; font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em;
    color: var(--accent); background: var(--accent-soft);
    border-radius: 99px; padding: 1px 7px;
}
.map-hover-index[hidden] { display: none; }
.map-hover-km {
    margin-top: 4px; display: flex; align-items: baseline; gap: 5px;
    font-size: 24px; font-weight: 700; line-height: 1.1; color: var(--accent);
    font-variant-numeric: tabular-nums;
}
.map-hover-km small { font-size: 12px; font-weight: 600; color: var(--muted); }
.map-hover-tag {
    margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--line);
    display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--ink-2);
}
.map-hover-tag[hidden] { display: none; }
.map-hover-tag i { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.map-hover-tag span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* --------------------------------------------------------- tape measure */
/* Its running total sits above the dock, where the eye already is. */
.map-tape {
    position: absolute; z-index: 5; left: var(--m-gap); bottom: calc(var(--m-dock) + 63px);
    width: 233px; padding: 11px 14px 13px; border-left: 3px solid var(--accent);
}
.map-tape[hidden] { display: none; }
.map-tape-head {
    display: flex; align-items: center; gap: 8px;
    font-size: 10.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.08em; color: var(--accent);
}
.map-tape-head > span { flex: 1; min-width: 0; }
.map-tape-km {
    margin-top: 3px; display: flex; align-items: baseline; gap: 5px;
    font-size: 26px; font-weight: 700; line-height: 1.1; color: var(--ink);
    font-variant-numeric: tabular-nums;
}
.map-tape-km small { font-size: 12px; font-weight: 600; color: var(--muted); }
.map-tape-hint { margin: 5px 0 0; font-size: 11px; line-height: 1.4; color: var(--muted); }

/* ------------------------------------------------------- road index badge */
/* The number a line is called, written along it, the way a road atlas prints
   a route shield — and the way the trunk-network map's `.gm-label b` already
   does, which is where the shape comes from. The class colour arrives inline,
   per badge, because three classes share these rules.

   Two differences from the trunk map's, both deliberate. It takes a press
   (`cursor: pointer`, and no `pointer-events: none`), because here the badge
   is the way to "that road, all of it". And it is painted on the map's own
   tiles rather than on a panel surface, so it is opaque by design instead of
   following the panel theme — a translucent plate over a satellite photograph
   is not a plate. */
.map-index {
    /* Yandex drops the layout element at the anchor point and leaves the
       centring to it. A badge is as wide as its index — "M39" to "4K1085" —
       so it translates itself back by half of whatever it turned out to be,
       which is also the box `badgeShape()` measures the press against. */
    width: max-content; transform: translate(-50%, -50%);
    padding: 2px 7px; border-radius: 4px;
    border: 1.5px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 1px 5px rgba(15, 23, 42, 0.4);
    background: #1d6fd0; color: #fff;
    font: 700 11px/1.25 system-ui, -apple-system, "Segoe UI", sans-serif;
    letter-spacing: 0.02em; font-variant-numeric: tabular-nums;
    white-space: nowrap; user-select: none; cursor: pointer;
}

/* ---------------------------------------------------------------- toast */
.map-toast {
    position: absolute; z-index: 5;
    left: calc(var(--m-layers) + 2 * var(--m-gap)); bottom: calc(var(--m-dock) + 117px);
    margin: 0; padding: 8px 14px;
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 12px; color: var(--ink-2); white-space: nowrap;
}
/* Both offsets above are the workspace's: they stand the line clear of the
   layers panel on the left and of the cards that used to sit above the bar.
   A map with neither — the trunk-network screen — reads it in the corner it
   was put in, one gap up from the badge. */
.map-shell:not(:has(.map-layers)) .map-toast {
    left: var(--m-gap); bottom: calc(var(--m-dock) + var(--m-gap));
}
.map-toast[hidden] { display: none; }
.map-toast::before { content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--ok); }
.map-toast.busy::before { background: var(--warn); }
.map-toast.empty::before { background: var(--crit); }
/* The tape owns that corner while it is measuring. */
/* A pointer tool is out: the cursor says so over the whole canvas. */
.map-shell.measuring #govMap,
.map-shell.panorama #govMap { cursor: crosshair; }
.map-shell.measuring .map-toast { bottom: calc(var(--m-dock) + 227px); }

/* ------------------------------------------------------------------ dock */
/* Two cards in the bottom-left corner: which roads are drawn, and how much of
   them there is. The tools live in the palette on the left edge. */
.map-dock {
    position: absolute; z-index: 6; bottom: var(--m-dock);
    left: calc(var(--m-layers) + 2 * var(--m-gap));
    right: calc(var(--m-panel) + 2 * var(--m-gap));
    display: flex; align-items: flex-end; gap: 8px; flex-wrap: wrap;
    pointer-events: none;
}
.map-shell.layers-closed .map-dock { left: calc(34px + 2 * var(--m-gap)); }
.dock-card { pointer-events: auto; display: flex; align-items: center; }
/* An author `display` beats the browser's own `[hidden]` rule, so a card
   that can be hidden has to say so here. */
.dock-card[hidden] { display: none; }

/* ---------- the way out of every filter at once ---------- */
/* First on the bottom bar, and the one thing on it that keeps a fill: every
   other group in the bar drops its card chrome because the bar is the
   surface, and this one does not, because it is the answer to "why does the
   map look like this" and a reader who cannot find it reloads the page
   instead. It has no `order`, so it lands ahead of the tools; when there is
   nothing to clear it is not in the row at all, gap and all. */
.map-clear-all {
    flex: none; pointer-events: auto; cursor: pointer;
    display: inline-flex; align-items: center; gap: 10px;
    height: var(--m-dock-h); padding: 0 17px;
    border: none; border-radius: 9px;
    background: var(--accent); color: var(--accent-ink);
    font-size: 13.5px; font-weight: 650; white-space: nowrap;
    box-shadow: 0 10px 28px rgba(37, 99, 196, 0.34), 0 1px 2px rgba(15, 23, 42, 0.14);
    transition: filter 0.14s ease, transform 0.12s ease;
}
.map-clear-all[hidden] { display: none; }
.map-clear-all:hover { filter: brightness(1.08); }
.map-clear-all:active { transform: translateY(1px); }
.map-clear-all svg { width: 17px; height: 17px; flex: none; }
/* How many are holding. A reader who cannot see why the network looks thin
   needs the number more than the word. */
.map-clear-all b {
    min-width: 22px; height: 22px; padding: 0 6px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 999px; background: rgba(255, 255, 255, 0.24);
    font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
}

.map-classes { gap: 3px; padding: 5px; }
.map-class { position: relative; cursor: pointer; }
.map-class input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.map-class-pill {
    display: inline-flex; align-items: center; gap: 7px;
    height: 34px; padding: 0 13px; border-radius: 8px;
    font-size: 12.5px; font-weight: 600; color: var(--muted);
    white-space: nowrap; user-select: none;
    transition: background 0.12s ease, color 0.12s ease;
}
.map-class-pill i {
    width: 10px; height: 10px; border-radius: 3px; flex: none;
    background: var(--muted); transition: opacity 0.12s ease;
    opacity: 0.35;
}
.map-class input:checked + .map-class-pill { color: var(--ink); background: var(--page); }
.map-class input:checked + .map-class-pill i { opacity: 1; }
.map-class input:focus-visible + .map-class-pill { outline: 2px solid var(--accent); outline-offset: 1px; }

/* A spot in the repair history — a bridge, which the 2026 sheet gives one
   coordinate and no length. Same shape as the survey's own marker, in the
   period's colour, which is written on by the layer rather than here: there
   are five periods and one stylesheet rule cannot be five colours. */
.map-works-pin {
    width: 14px; height: 14px;
    border: 2.5px solid #fff; border-radius: 50%;
    box-shadow: 0 1px 4px rgba(15, 23, 42, 0.45);
    transform: translate(-7px, -7px);
}

/* The repair history's own switch in the strip. It wears the class pills'
   shape so it reads as the end of that row of filters, and nothing else:
   its swatch is a round dot rather than the classes' rounded square, because
   it is a layer over the network and not one of the three the network is
   divided into. */
.map-worksbar .map-class-pill i { border-radius: 50%; }

.map-metrics { gap: 21px; padding: 7px 17px; }
.map-metric { display: flex; flex-direction: column; gap: 1px; }
.map-metric > span {
    font-size: 9.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.08em; color: var(--muted); white-space: nowrap;
}
.map-metric > b {
    font-size: 17px; font-weight: 700; line-height: 1.2; color: var(--accent);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* --------------------------------------------------------- tool palette */
/* Left edge, two columns, the way a drawing program stacks its tools. Every
   button here acts on the view — what is drawn is decided on the right and
   along the bottom, so the two never mix. */
/* The palette and the basemap card stack in one column, so the second is
   always right under the first however many tools the first holds. */
.map-left {
    position: absolute; z-index: 6; left: var(--m-gap); top: var(--m-gap);
    display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
    /* The column is only as wide as whatever is in it, so the narrow icon
       cards stay narrow and the search under them can be a field. */
    pointer-events: none;
}
.map-left > * { pointer-events: auto; flex: none; }
.map-tools {
    display: grid; grid-template-columns: repeat(2, 38px); gap: 3px;
    padding: 5px;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
.tool-btn {
    position: relative; width: 38px; height: 38px;
    display: grid; place-items: center; border-radius: 6px;
    border: 0; background: none; color: var(--ink-2); cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}
.tool-btn:hover { background: var(--page); color: var(--ink); }
.tool-btn svg { width: 19px; height: 19px; }
.tool-btn[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); }
.tool-btn-ok[aria-pressed="true"] { background: var(--ok-soft); color: var(--ok); }
.tool-btn-crit[aria-pressed="true"] { background: var(--crit-soft); color: var(--crit); }
/* Spans both columns, so a group never ends mid-row. */
.tool-sep { grid-column: 1 / -1; height: 1px; background: var(--line); margin: 3px 2px; }
/* A tool that carries a count takes the whole width: four digits crammed into
   a 38px square sat on top of the icon they belong to. */
.tool-btn-wide {
    grid-column: 1 / -1; width: auto; height: 34px;
    display: flex; align-items: center; gap: 8px; padding: 0 8px;
}
.tool-badge {
    margin-left: auto; flex: none; white-space: nowrap; min-width: 15px; height: 16px;
    display: grid; place-items: center; padding: 0 5px;
    border-radius: 99px; background: var(--neutral-ink); color: #fff;
    font-size: 9.5px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums;
}
.tool-btn-warn[aria-pressed="true"] { background: var(--warn-soft); color: var(--warn); }
.tool-btn-ok .tool-badge { background: var(--ok); }
.tool-btn-crit .tool-badge { background: var(--crit); }
.tool-btn-warn .tool-badge { background: var(--warn); }

/* The colour question sits in its own card under the base maps: two of them
   in a row of three would read as a third base map. */
.map-colours { grid-template-columns: repeat(2, 1fr); }

/* Which kilometre the readout means was two unlabelled icons, and nobody
   could tell which was which. Stacked, named, and under a heading that says
   what the choice is about — the column is a little wider for it, which is
   the price of the words. */
.map-kmmode {
    width: var(--m-tools);
    display: flex; flex-direction: column; gap: 2px; padding: 6px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
/* Folded, the card is icon-only and as narrow as the ones above it. */
.map-kmmode.open { width: var(--m-left); }
.kmmode-toggle {
    display: flex; align-items: center; gap: 4px; width: 100%;
    padding: 2px 4px 4px; border: 0; background: none; cursor: pointer;
    color: var(--muted);
}
.kmmode-head {
    flex: 1; min-width: 0; text-align: left;
    font-size: 9.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kmmode-toggle:hover { color: var(--ink-2); }
.kmmode-chev { width: 13px; height: 13px; flex: none; transition: transform 0.15s ease; }
.map-kmmode:not(.open) .kmmode-head { display: none; }
.map-kmmode:not(.open) .kmmode-toggle { justify-content: center; padding: 2px 0 4px; }
.map-kmmode:not(.open) .kmmode-chev { transform: rotate(-90deg); }
.map-kmmode:not(.open) .kmmode-row { justify-content: center; padding: 0; }
.map-kmmode:not(.open) .kmmode-row span { display: none; }
.kmmode-row {
    display: flex; align-items: center; gap: 7px; width: 100%;
    height: 28px; padding: 0 6px; border: 0; border-radius: 6px;
    background: none; color: var(--ink-2); cursor: pointer;
    font-size: 11px; text-align: left;
    transition: background 0.12s ease, color 0.12s ease;
}
.kmmode-row svg { width: 15px; height: 15px; flex: none; }
.kmmode-row span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kmmode-row:hover { background: var(--page); color: var(--ink); }
.kmmode-row[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); font-weight: 650; }

/* The base maps as a segmented card. The workspace moved its three into the
   settings card; the trunk-network screen (`#gmViews`) still wears this. */
.map-views {
    width: 132px;
    display: block;
    padding: 4px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
.view-btn {
    height: 28px; display: grid; place-items: center; border-radius: 6px;
    border: 0; background: none; color: var(--muted); cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}
.view-btn:hover { background: var(--page); color: var(--ink); }
.view-btn svg { width: 16px; height: 16px; }
.view-btn[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); }

.view-list { display: flex; flex-direction: column; gap: 3px; }
.view-list .view-btn {
    width: 100%; height: 32px; padding: 0 9px;
    display: flex; align-items: center; gap: 9px;
    justify-items: start; place-items: center start;
    font-size: 12px; text-align: left;
}
.view-list .view-btn svg { width: 16px; height: 16px; flex: none; }
.view-list .view-btn span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.display-body { padding: 2px 10px 10px; display: flex; flex-direction: column; gap: 9px; }
.display-body[hidden] { display: none; }
.display-row { display: flex; flex-direction: column; gap: 4px; }
.display-row > span {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--muted);
}
.display-row input[type="range"] { width: 100%; accent-color: var(--accent); margin: 0; }

/* One slider per significance class, under one heading: three questions of
   the same kind, which is not the same thing as three settings. */
.display-group { display: flex; flex-direction: column; gap: 7px; }
.display-head {
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--muted);
}
/* Named rather than shouted: these are three labels inside a group that
   already carries the heading, so they read as rows, not as three headings. */
.display-row-class > span {
    display: flex; align-items: center; gap: 6px;
    font-size: 11px; font-weight: 600; text-transform: none;
    letter-spacing: 0; color: var(--ink-2);
}
/* The key is drawn at the weight its slider is set to — the card shows the
   difference between the classes instead of printing two numbers to compare. */
.display-key { width: 14px; height: 3px; border-radius: 2px; flex: none; }
.key-class-1 { background: var(--crit); }
.key-class-2 { background: var(--accent); }
.key-class-3 { background: var(--ok); }
.key-class-4 { background: var(--warn); }
.display-row-class > span b {
    margin-left: auto; font-weight: 700; color: var(--accent);
    font-variant-numeric: tabular-nums;
}
/* Why the control exists, in one line: a reader who meets a slider called
   "base map strength" has no reason to guess it is the answer to the
   restaurants crowding their road. */
/* A switch reads across the row like the sliders beside it, not stacked. */
.display-row-switch { justify-content: space-between; gap: 12px; }
.display-row-switch .switch { flex: none; }
.display-note {
    margin: -2px 0 0; font-size: 10px; line-height: 1.35; color: var(--muted);
}

.display-reset {
    margin-top: 2px; display: flex; align-items: center; justify-content: center; gap: 6px;
    height: 28px; border-radius: 6px; border: 1px solid var(--line);
    background: var(--surface); color: var(--ink-2); cursor: pointer;
    font-size: 11.5px; font-weight: 600;
}
.display-reset:hover { border-color: var(--accent); color: var(--accent); }
.display-reset svg { width: 13px; height: 13px; }

/* ------------------------------------------------------------- panorama */
/* One eye per place a panorama was recorded. Centred on its own point, and
   haloed in white so it reads on satellite imagery as well as on the scheme. */
.pano-eye {
    width: 16px; height: 16px; margin: -8px 0 0 -8px;
    color: var(--accent); cursor: pointer;
    filter: drop-shadow(0 0 1.5px #fff) drop-shadow(0 0 1.5px #fff)
        drop-shadow(0 1px 2px rgba(15, 23, 42, 0.45));
}
.pano-eye svg { display: block; width: 16px; height: 16px; }

/* A Yandex panorama plays over the map rather than in a window of its own:
   the point of picking one is to see the same place from the ground. */
.map-pano {
    position: absolute; z-index: 7; top: 68px;
    left: calc(var(--m-layers) + 2 * var(--m-gap));
    right: calc(var(--m-panel) + 2 * var(--m-gap));
    height: min(52vh, 460px);
    display: flex; flex-direction: column; overflow: hidden;
    border: 1px solid var(--line); border-radius: var(--m-radius);
    background: var(--surface);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
.map-pano[hidden] { display: none; }
.map-pano-head {
    flex: none; display: flex; align-items: center; gap: 8px; padding: 7px 8px 7px 14px;
    border-bottom: 1px solid var(--line);
    font-size: 10.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.08em; color: var(--accent);
}
.map-pano-head > span { flex: 1; min-width: 0; }
.map-pano-stage { flex: 1; min-height: 0; background: var(--page); }

/* ------------------------------------------------------------ responsive */
/* Below the golden-section breakpoint the panel would starve the canvas, so
   it goes full height over it and the dock takes the whole width back. */
@media (max-width: 1200px) {
    .map-shell { --m-panel: min(84vw, 344px); --m-layers: min(84vw, 304px); }
    .map-dock { right: var(--m-gap); }
    .map-find { width: min(400px, calc(100% - 2 * var(--m-layers) - 4 * var(--m-gap))); }
}
/* Narrow enough that two side panels plus a strip between them leaves nothing
   for the map: the panels keep their width and fold, and everything along the
   bottom takes the whole width back and runs under them. */
@media (max-width: 900px) {
    .map-shell { --m-layers: min(86vw, 300px); --m-panel: min(86vw, 300px); }
    .map-dock,
    .map-shell.layers-closed .map-dock { left: var(--m-gap); right: var(--m-gap); }
    .map-toast,
    .map-shell.layers-closed .map-toast { left: var(--m-gap); }
}
@media (max-width: 720px) {
    .map-shell { --m-gap: 8px; }
    .map-metrics { gap: 13px; padding: 7px 13px; }
    .map-metric > b { font-size: 15px; }
}

/* Road card page: all data for one road beside its own geometry. */
.road-card-grid {
    display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: 14px; align-items: start;
}
.road-card-main { min-width: 0; }
.road-card-side { position: sticky; top: 74px; min-width: 0; }
.road-card-map { height: max(46vh, 360px); border-radius: 0 0 8px 8px; overflow: hidden; z-index: 0; }
.mt-14 { margin-top: 14px; }

.kv-grid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 0 18px; padding: 12px 18px 18px;
}
.kv { display: flex; flex-direction: column; gap: 2px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.kv > span { font-size: 11.5px; color: var(--muted); }
.kv > b { font-size: 13.5px; font-weight: 600; }

.el-group + .el-group { border-top: 1px solid var(--line); }
.el-group-head { display: flex; align-items: center; gap: 9px; padding: 14px 18px 6px; }
.el-group-icon { width: 20px; height: 20px; object-fit: contain; flex: none; }
.el-group-name { flex: 1; min-width: 0; font-size: 13px; font-weight: 650; }

@media (max-width: 1000px) {
    .road-card-grid { grid-template-columns: 1fr; }
    .road-card-side { position: static; }
    .road-card-map { height: 320px; }
}


/* ==========================================================================
   Load-capacity calculator (gov.calculator + its two settings registries)
   ========================================================================== */

/* ---------- shared sub-navigation ---------- */
.calc-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.calc-tabs a {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 14px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--ink-2); font-size: 13px; font-weight: 550;
  text-decoration: none; transition: border-color .15s, color .15s, background .15s;
}
.calc-tabs a svg { width: 16px; height: 16px; flex: none; }
.calc-tabs a:hover { border-color: var(--line-strong); color: var(--ink); }
.calc-tabs a.active {
  background: var(--accent-soft); border-color: var(--accent); color: var(--accent);
}

/* ---------- workspace layout ---------- */
.calc-shell { display: grid; grid-template-columns: minmax(320px, 400px) 1fr; gap: 16px; align-items: start; }
.calc-result { display: grid; gap: 16px; transition: opacity .15s; }
.calc-result[aria-busy="true"] { opacity: .55; }
@media (max-width: 1080px) { .calc-shell { grid-template-columns: 1fr; } }

/* ---------- vehicle picker ---------- */
.calc-params { padding-bottom: 18px; }
.calc-group-label {
  margin: 16px 18px 8px; font-size: 11px; font-weight: 650; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.calc-types { display: grid; gap: 8px; padding: 0 18px; }
.calc-type {
  display: grid; grid-template-columns: 54px 1fr auto; align-items: center; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px;
  cursor: pointer; transition: border-color .15s, background .15s, box-shadow .15s;
}
.calc-type:hover { border-color: var(--line-strong); background: var(--neutral-soft); }
/* Visually hidden but still focusable and exposed to assistive tech. */
.calc-type input {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.calc-type:has(input:checked), .calc-type.is-selected {
  border-color: var(--accent); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent);
}
.calc-type:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.ct-figure { display: flex; align-items: center; justify-content: center; color: var(--ink-2); }
.ct-figure svg, .ct-figure img { width: 100%; max-height: 34px; object-fit: contain; }
.calc-type:has(input:checked) .ct-figure, .calc-type.is-selected .ct-figure { color: var(--accent); }
.ct-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ct-name { margin: 0; font-size: 13.5px; font-weight: 600; }
.ct-meta { font-size: 11.5px; color: var(--muted); }
.ct-axles {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-width: 38px; padding: 4px 6px; border-radius: 6px;
  background: var(--neutral-soft); color: var(--neutral-ink); font-size: 15px; font-weight: 700; line-height: 1;
}
.ct-axles i { font-style: normal; font-size: 9.5px; font-weight: 600; text-transform: uppercase; opacity: .75; }
.calc-type:has(input:checked) .ct-axles,
.calc-type.is-selected .ct-axles { background: var(--accent); color: var(--accent-ink); }

/* ---------- mass input ---------- */
.calc-mass { padding: 18px 18px 0; }
.cm-row { display: flex; align-items: center; gap: 0; }
.cm-row input {
  flex: 1; min-width: 0; border-radius: 7px 0 0 7px; border-right: 0;
  font-size: 20px; font-weight: 650; padding: 10px 12px;
}
.cm-unit {
  padding: 11px 14px; border: 1px solid var(--line-strong); border-left: 0; border-radius: 0 7px 7px 0;
  background: var(--neutral-soft); color: var(--muted); font-size: 12.5px; white-space: nowrap;
}
.cm-range { width: 100%; margin: 12px 0 2px; accent-color: var(--accent); }
.calc-actions { display: flex; flex-wrap: wrap; gap: 8px; padding: 16px 18px 0; }
.calc-legal { margin: 14px 18px 0; font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.calc-legal a { color: var(--accent); }

/* ---------- result ---------- */
.calc-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; padding: 14px 18px 0; }
.calc-kpi {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 8px; background: var(--page);
}
.calc-kpi .lb { font-size: 11.5px; color: var(--muted); line-height: 1.3; }
.calc-kpi .v { font-size: 26px; font-weight: 700; letter-spacing: -.02em; line-height: 1; }
.calc-kpi .v i { font-style: normal; margin-left: 4px; font-size: 13px; font-weight: 550; color: var(--muted); }
.calc-kpi.is-hero { background: var(--accent-soft); border-color: var(--accent); }
.calc-kpi.is-hero .v { color: var(--accent); }
.calc-kpi.is-hero .lb { color: var(--accent); opacity: .85; }

.calc-usage { padding: 16px 18px 0; }
.cu-track { height: 10px; border-radius: 999px; background: var(--accent-soft); overflow: hidden; }
.cu-fill { height: 100%; border-radius: 999px; background: var(--ink-2); transition: width .2s ease; }
.cu-legend { display: flex; flex-wrap: wrap; gap: 6px 18px; margin-top: 8px; font-size: 11.5px; color: var(--muted); }
.cu-legend span { display: inline-flex; align-items: center; gap: 6px; }
.cu-sw { width: 10px; height: 10px; border-radius: 3px; }
.cu-sw-veh { background: var(--ink-2); }
.cu-sw-cargo { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent); }

/* ---------- axle diagram ---------- */
.axle-diagram { margin: 4px 0 0; padding: 10px 18px 16px; overflow-x: auto; }
.axle-diagram svg { display: block; width: 100%; max-height: 190px; color: var(--ink-2); }
.axle-diagram figcaption { margin-top: 2px; text-align: center; font-size: 11.5px; color: var(--muted); }
.ax-cab { fill: var(--accent); opacity: .85; }
.ax-body { fill: var(--accent); opacity: .18; stroke: var(--accent); stroke-width: 1.5; }
.ax-chassis { fill: var(--ink-2); opacity: .55; }
.ax-tyre { fill: var(--ink); opacity: .78; }
.ax-hub { fill: var(--surface); }
.ax-load { fill: var(--ink); font-size: 13px; font-weight: 650; }

.calc-note { margin: 0; padding: 0 18px 16px; font-size: 11.5px; line-height: 1.5; color: var(--muted); }

/* ---------- cargo cards ---------- */
.cargo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; padding: 14px 18px 4px; }
.cargo-card {
  display: grid; grid-template-columns: 44px 1fr auto; align-items: center; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--line); border-radius: 8px; background: var(--page);
}
.cg-img { width: 44px; height: 44px; border-radius: 7px; object-fit: cover; flex: none; }
.cg-img-ph {
  display: flex; align-items: center; justify-content: center;
  background: var(--neutral-soft); color: var(--muted);
}
.cg-img-ph svg { width: 22px; height: 22px; }
.cg-body { min-width: 0; }
.cg-name { margin: 0; font-size: 13.5px; font-weight: 600; }
.cg-density { margin: 2px 0 0; font-size: 11.5px; color: var(--muted); }
.cg-vol { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.1; }
.cg-vol strong { font-size: 18px; font-weight: 700; color: var(--accent); }
.cg-vol span { font-size: 11px; color: var(--muted); }

/* ---------- empty states ---------- */
.calc-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 40px 24px; text-align: center; }
.calc-empty > svg { width: 46px; height: 46px; color: var(--muted); opacity: .6; }
.calc-empty .ce-title { margin: 0; font-size: 14px; font-weight: 600; }
.calc-empty .ce-hint { margin: 0; font-size: 12.5px; color: var(--muted); }
.calc-empty.is-inline { padding: 28px 18px; }

/* ---------- settings tables ---------- */
.code-chip {
  padding: 2px 8px; border-radius: 4px; background: var(--neutral-soft);
  color: var(--neutral-ink); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
}
.row-thumb { width: 34px; height: 34px; border-radius: 6px; object-fit: cover; border: 1px solid var(--line); }
/* An element category's icon is a drawing on a 24px grid, not a photograph:
   it is padded and fitted whole rather than cropped to fill, or the glyph's
   own margins are cut off and every icon reads as a different size. */
.row-thumb-icon { object-fit: contain; padding: 4px; background: var(--soft); }
.row-thumb-empty { display: inline-block; background: var(--soft); }
.muted-dash { color: var(--muted); }
.axle-badges { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.axle-badges i {
  font-style: normal; padding: 2px 7px; border-radius: 4px;
  background: var(--accent-soft); color: var(--accent); font-size: 11.5px; font-weight: 650;
}

/* ---------- axle repeater (vehicle type form) ---------- */
.axle-repeater { display: grid; gap: 8px; margin-top: 4px; }
.axle-row { display: grid; grid-template-columns: 28px 1fr auto 30px; align-items: center; gap: 8px; }
.ar-no {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 6px;
  background: var(--neutral-soft); color: var(--neutral-ink); font-size: 12px; font-weight: 650;
}
.ar-unit { font-size: 12px; color: var(--muted); }
.ar-del {
  width: 28px; height: 28px; border-radius: 6px; border: 1px solid var(--line);
  color: var(--muted); font-size: 17px; line-height: 1;
}
.ar-del:hover { border-color: var(--crit); color: var(--crit); }
.axle-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 10px; }
.axle-sum { font-size: 12.5px; color: var(--muted); }


/* ==========================================================================
   GeoJSON export: the filter form beside the counts it produces
   ========================================================================== */

.export-grid {
  display: grid; grid-template-columns: minmax(0, 1.618fr) minmax(0, 1fr);
  gap: 14px; align-items: start;
}
.export-form { min-width: 0; }
.export-side { position: sticky; top: 74px; min-width: 0; }
.export-intro { margin: 0 0 16px; font-size: 12.5px; color: var(--muted); }
.export-form .check-pills + .hint { margin-bottom: 16px; }
.export-pill-tools { display: flex; gap: 8px; margin: 10px 0 16px; }
.export-switches { flex-direction: column; gap: 12px; }
.export-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.export-actions button[disabled] { opacity: .5; cursor: not-allowed; }

@media (max-width: 1000px) {
  .export-grid { grid-template-columns: 1fr; }
  .export-side { position: static; }
}

/* ---------- print: the result panel only ---------- */
@media print {
  .gov-sidebar, .topbar, .calc-tabs, .calc-params, .calc-actions, .pager { display: none !important; }
  .gov-main, .content, .content-full { display: block; padding: 0; }
  .calc-shell { display: block; }
  .card { break-inside: avoid; box-shadow: none; border: 1px solid #ccc; }
  .cargo-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Topbar bell. The count sits on the icon rather than beside it, so the
   button keeps the same width whether or not anything is waiting. */
.tb-bell { position: relative; text-decoration: none; }
.tb-bell-dot {
  position: absolute; top: -4px; right: -4px; min-width: 16px; height: 16px;
  /* A count badge, so a pill rather than a corner radius: it has to stay round
     at one digit and stretch at three. Left out of the radius reduction for
     that reason. */
  padding: 0 4px; border-radius: 99px;
  background: var(--crit); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 16px; text-align: center;
}

/* Track-list board. Columns scroll sideways as a group rather than the page:
   a request with seven stages must not widen the card it sits in. */
.kanban { display: flex; gap: 10px; overflow-x: auto; padding: 4px 0 12px; }
.kanban-col {
  flex: 0 0 210px; background: var(--page);
  border: 1px solid var(--line); border-radius: 7px; padding: 8px;
}
.kanban-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11.5px; font-weight: 600; color: var(--ink-2);
  margin-bottom: 8px; text-transform: uppercase; letter-spacing: .02em;
}
.kanban-card {
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px;
  padding: 8px 9px; margin-bottom: 7px;
}
.kanban-card-t { font-size: 12.5px; font-weight: 600; margin-bottom: 5px; }
.kanban-card-m { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 5px; }
.kanban-card-s { font-size: 11px; color: var(--muted); }
.kanban-empty { font-size: 12px; color: var(--muted); text-align: center; padding: 10px 0; }

/* Per-stage moves sit inside a table cell, so each form stays on one line. */
.stage-actions { display: flex; flex-direction: column; gap: 5px; }
.stage-actions form { display: flex; align-items: center; gap: 5px; }
.stage-actions input[type=number] { width: 62px; }
.stage-actions input[type=text] { min-width: 140px; }
.stage-add { border-top: 1px solid var(--line); margin-top: 12px; padding-top: 12px; }

/* ---- dashboard ------------------------------------------------------ */

/* ---------------------------------------------------------------------------
   Dashboard charts and the list behind a counter

   One measure per chart, so every bar is the same single hue. Where a row
   carries a status the colour rides a dot beside its label — a bar coloured by
   status would put good and satisfactory two ΔE apart for a colourblind
   reader, and the dot plus the label never does.
--------------------------------------------------------------------------- */
.dash-charts {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(288px, 1fr));
    gap: 14px; margin-bottom: 14px;
}
.viz .card-h { margin-bottom: 4px; }
.viz-bars { list-style: none; margin: 0; padding: 4px 18px 18px; display: flex; flex-direction: column; gap: 9px; }
.viz-bar {
    display: grid; grid-template-columns: minmax(0, 9rem) 1fr auto;
    align-items: center; gap: 10px; border-radius: 5px;
}
.viz-bar:hover { background: var(--page); }
/* A bar that has a list behind it says so the way the counters do. */
.viz-bar-open { cursor: pointer; }
.viz-bar-open:hover .viz-bar-key { color: var(--ink); }
.viz-bar-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.viz-bar-key {
    display: flex; align-items: center; gap: 6px; min-width: 0;
    font-size: 12px; color: var(--ink-2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Identity beside the text, never in it: a status hue is unreadable as type. */
.viz-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--muted); }
.viz-dot-ok { background: var(--ok); }
.viz-dot-warn { background: var(--warn); }
.viz-dot-crit { background: var(--crit); }
/* The track is one step off the surface and stays recessive; the fill is
   square where it leaves the baseline and rounded at the data end. */
.viz-bar-track { height: 14px; border-radius: 4px; background: var(--neutral-soft); overflow: hidden; }
.viz-bar-fill { display: block; height: 100%; border-radius: 0 4px 4px 0; background: var(--accent); }
.viz-bar-val {
    font-size: 12.5px; font-weight: 700; color: var(--ink);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.viz-empty { margin: 0; padding: 4px 18px 20px; font-size: 12.5px; color: var(--muted); }

/* A counter that has a list behind it says so by being reachable. */
.kpi-open { cursor: pointer; transition: border-color 0.12s ease, box-shadow 0.12s ease; }
.kpi-open:hover { border-color: var(--accent); }
.kpi-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.dash-modal-box {
    width: min(880px, calc(100vw - 32px)); max-height: min(80vh, 720px);
    display: flex; flex-direction: column; padding: 16px 18px 14px;
}
.dash-modal-head { display: flex; align-items: center; gap: 10px; flex: none; }
.dash-modal-head .gov-modal-title { flex: 1; min-width: 0; margin: 0; }
.dash-modal-body { flex: 1; min-height: 0; overflow: auto; margin-top: 12px; }
.dash-modal-table { width: 100%; }
.dash-modal-table th { position: sticky; top: 0; background: var(--surface); z-index: 1; }
/* The footer carries the pager, so it lays out as a row rather than a line
   of text: the count on the left, the arrows and the field on the right. */
.dash-modal-foot {
  flex: none; margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  font-size: 11.5px; color: var(--muted);
}
.dash-modal-foot:empty { display: none; }
.dash-modal-count { white-space: nowrap; }
.dash-modal-foot nav { display: flex; gap: 4px; }
.dash-modal-foot a, .dash-modal-foot .pg-item {
  display: grid; place-items: center; min-width: 28px; height: 28px; padding: 0 4px;
  border-radius: 4px; border: 1px solid var(--line); font-size: 12.5px;
  color: var(--ink-2); text-decoration: none;
}
.dash-modal-foot a:hover { background: var(--page); color: var(--ink); }
.dash-modal-foot .pg-dis { opacity: 0.4; }
.dash-crumbs {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13px; margin-bottom: 12px; color: var(--ink-2);
}
.dash-crumbs a { color: var(--accent); text-decoration: none; }
.dash-crumbs a:hover { text-decoration: underline; }
.dash-crumbs .sep { color: var(--muted); }
.dash-live { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); }
.dash-live .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); animation: dashPulse 2.4s ease-in-out infinite; }
@keyframes dashPulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

.dash-bar {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 14px; margin-bottom: 14px;
}
.dash-bar .field { margin: 0; min-width: 150px; }
.dash-bar-spacer { flex: 1 1 auto; }

/* Two columns on a wide screen, one on a narrow one. The left column carries
   the wide charts, so it gets the larger share. */
.dash-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); gap: 14px; margin-top: 14px; }
.dash-col { min-width: 0; }
@media (max-width: 1100px) { .dash-grid { grid-template-columns: minmax(0, 1fr); } }

/* Region bars double as drill-down links. */
a.bar-row { text-decoration: none; color: inherit; border-radius: 6px; }
a.bar-row:hover { background: var(--page); }
.bar-fill.tone-ok   { background: var(--ok); }
.bar-fill.tone-warn { background: var(--warn); }
.bar-fill.tone-crit { background: var(--crit); }

.dash-map { height: 340px; border-radius: 7px; overflow: hidden; margin-bottom: 12px; }

/* A number that moved during a poll flashes once rather than the page
   redrawing under the reader. */
.metric-bumped { animation: metricBump 1.1s ease-out; }
@keyframes metricBump {
  0% { background: var(--accent-soft); }
  100% { background: transparent; }
}

/* ---------------------------------------------------------------------------
   INTERNATIONAL NETWORK MAP
   The trunk-network screen. It reuses the map workspace's shell, tools and
   basemap card wholesale; what is new is the list of routes on the right and
   the numbered badge written along each line.
--------------------------------------------------------------------------- */
/* The workspace's panel card is a row, because the workspace builds a rail
   of section tabs down its outer edge and the chosen section takes the rest
   of the card. This one holds no rail — a heading and one list, which stack.
   Said on the card rather than asked of its contents, so the card that has a
   rail keeps the row even where `:has()` is not understood: left as a row,
   the heading and the list sat side by side and the list was squeezed to
   nothing, which is a panel that looks empty while holding fifteen routes. */
.gm-card { flex-direction: column; }

.gm-head {
    flex: none; padding: 13px 14px 11px; border-bottom: 1px solid var(--line);
}
.gm-head h1 {
    margin: 0; font-size: 13.5px; font-weight: 700; line-height: 1.35; color: var(--ink);
}
.gm-head p {
    margin: 5px 0 0; display: flex; align-items: baseline; gap: 5px;
    font-size: 11.5px; color: var(--muted);
}
.gm-head p b { font-size: 12.5px; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.gm-head p i { font-style: normal; color: var(--line); }

.gm-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.gm-item {
    display: flex; align-items: stretch; gap: 2px;
    border-radius: 7px; transition: background 0.12s ease;
}
.gm-item:hover { background: var(--page); }
/* The chosen route, which is also the one drawn over the others. */
.gm-item.is-on { background: var(--accent-soft); }
.gm-item.is-off .gm-row { opacity: 0.42; }

.gm-row {
    flex: 1; min-width: 0; display: flex; align-items: center; gap: 9px;
    padding: 7px 8px; border: 0; border-radius: 7px; background: none;
    text-align: left; cursor: pointer; color: inherit;
}
/* The colour the route is drawn in: the whole legend, one row at a time. */
.gm-row > i { width: 4px; align-self: stretch; border-radius: 99px; flex: none; }
.gm-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.gm-nm { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.gm-nm b {
    flex: none; font-size: 11px; font-weight: 800; letter-spacing: 0.02em;
    color: var(--ink); font-variant-numeric: tabular-nums;
}
.gm-nm span {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 12px; color: var(--ink-2);
}
.gm-sub {
    display: flex; align-items: baseline; gap: 5px;
    font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.gm-sub i { font-style: normal; color: var(--line); }

.gm-eye {
    width: 30px; flex: none; display: grid; place-items: center;
    border: 0; border-radius: 6px; background: none; color: var(--muted); cursor: pointer;
}
.gm-eye:hover { background: var(--surface); color: var(--ink-2); }
.gm-eye svg { width: 15px; height: 15px; }
.gm-eye .gm-eye-off,
.gm-eye[aria-pressed="false"] .gm-eye-on { display: none; }
.gm-eye[aria-pressed="false"] .gm-eye-off { display: block; }

.gm-empty { padding: 16px 10px; font-size: 12px; color: var(--muted); text-align: center; }

/* --------------------------------------------------------- the road number */
/* Written along the line rather than beside it, the way a road atlas prints a
   route shield. Which halves are drawn is the filter's decision, made by
   handing the map a different layout — so nothing here has to hide anything.
   The route's colour arrives inline, per label, because fifteen routes share
   these rules. Never interactive: a click on a label belongs to the line
   underneath it.

   Painted on the map's own tiles rather than on a panel surface, so it is
   opaque by design instead of following the panel's theme. */
.gm-label {
    /* Yandex drops the layout element at the anchor point and leaves the
       centring to it — `.map-pin` does that with negative margins, which only
       works at a fixed size. A label is as wide as its text, so it translates
       itself back by half of whatever it turned out to be. */
    width: max-content; transform: translate(-50%, -50%);
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    pointer-events: none; user-select: none; white-space: nowrap;
}
.gm-label b {
    padding: 2px 7px; border-radius: 4px;
    background: #1d6fd0; color: #fff;
    border: 1.5px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 1px 5px rgba(15, 23, 42, 0.4);
    font: 700 11px/1.25 system-ui, -apple-system, "Segoe UI", sans-serif;
    letter-spacing: 0.02em; font-variant-numeric: tabular-nums;
}
.gm-label i {
    max-width: 240px; overflow: hidden; text-overflow: ellipsis;
    padding: 1px 7px; border-radius: 4px;
    /* The route's colour down the edge, so the name still says which line it
       belongs to in the mode where no numbered badge is drawn above it. */
    border-left: 3px solid #1d6fd0;
    background: rgba(255, 255, 255, 0.94); color: #17233a;
    font: 600 10px/1.3 system-ui, -apple-system, "Segoe UI", sans-serif; font-style: normal;
    box-shadow: 0 1px 4px rgba(15, 23, 42, 0.22);
}

/* ---------- API key, shown once ----------
   The panel that carries a freshly minted key. Deliberately the loudest thing
   on the screen: the string exists for this one response and there is no way
   to produce it again, so an operator who scrolls past it has lost it. */
.api-secret {
    border-left: 3px solid var(--accent);
    background: var(--accent-soft);
    margin-bottom: 14px;
}
.api-secret .as-head { display: flex; align-items: center; gap: 10px; color: var(--accent); }
.api-secret .as-title { font-weight: 700; font-size: 14px; }
.api-secret .as-name { font-size: 12px; color: var(--ink-2); margin-top: 1px; }
.api-secret .as-value {
    display: flex; align-items: center; gap: 10px; margin-top: 12px;
    padding: 10px 12px; border-radius: 6px;
    background: var(--surface); border: 1px solid var(--line);
}
.api-secret .as-value code {
    flex: 1; min-width: 0; font-size: 13px; letter-spacing: 0.01em;
    /* The key is one unbroken token; wrapping it is what lets it be read at
       all on a narrow screen, and it is selected by the button, not by hand. */
    word-break: break-all; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.api-secret .as-value .btn-ghost { flex: none; }
.api-secret .as-value .btn-ghost.is-copied { color: var(--ok-ink); border-color: var(--ok-ink); }
.api-secret .as-note { margin: 10px 0 0; font-size: 12px; color: var(--ink-2); line-height: 1.5; }

/* Scope checkboxes: the same button-group kit as everywhere else, but the
   groups are labelled, because "what may this key read" is read down the
   labels rather than across forty identical pills. */
.scope-group + .scope-group { margin-top: 14px; }
.scope-group > .sg-label {
    display: block; margin-bottom: 6px;
    font-size: 11px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--muted);
}

/* ---------- Road sign catalogue ----------
   The picture is the column a reader actually scans, so it leads the row and
   is given a fixed width: forty signs of different proportions would otherwise
   make every row a different height. */
.gov-table th.sign-col, .gov-table td.sign-col { width: 76px; }
.sign-thumb {
    display: block; width: 56px; height: 56px;
    object-fit: contain;
    /* A white plate, because half the catalogue is white-field artwork that
       would vanish into a dark table. */
    background: #fff; border: 1px solid var(--line); border-radius: 6px; padding: 3px;
}

/* A road sign on the map: its own artwork, not a coloured dot. The white plate
   is load-bearing — half the GOST catalogue is white-field artwork that would
   otherwise dissolve into a satellite basemap. */
.map-sign {
    width: 32px; height: 32px; margin: -16px 0 0 -16px;
    display: grid; place-items: center;
    background: #fff; border-radius: 5px; padding: 2px;
    box-shadow: 0 1px 4px rgba(5, 12, 25, 0.45);
}
.map-sign img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* The section's switch sits on its own line above the hint. */
.map-sec-body > .switch { margin: 2px 0 8px; }

/* A counted cluster of signs. Three sizes, so the distribution is read before
   any of the numbers are: where the network is dense is the question a reader
   opening this layer actually has. */
.map-sign-cluster {
    display: grid; place-items: center;
    border-radius: 50%; color: #fff; font-weight: 700;
    font-variant-numeric: tabular-nums; cursor: pointer;
    background: var(--accent);
    border: 2px solid rgba(255, 255, 255, 0.92);
    box-shadow: 0 2px 8px rgba(5, 12, 25, 0.45);
}
.map-sign-cluster.sm { width: 30px; height: 30px; margin: -15px 0 0 -15px; font-size: 11px; }
.map-sign-cluster.md { width: 38px; height: 38px; margin: -19px 0 0 -19px; font-size: 12.5px; }
.map-sign-cluster.lg { width: 48px; height: 48px; margin: -24px 0 0 -24px; font-size: 13.5px; }

/* Where the signs are, beside the map. A map can only draw what is on screen;
   this is the part that says the thing you want is somewhere else. */
.map-areas { margin-top: 8px; display: flex; flex-direction: column; gap: 2px; }
.map-areas-h {
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--muted); margin-bottom: 4px;
}
.map-area {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 6px 8px; border-radius: 5px; text-align: left;
    background: transparent; color: var(--ink); font-size: 12.5px; cursor: pointer;
}
.map-area:hover { background: var(--page); }
.map-area .ma-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-area .ma-name i { display: block; font-style: normal; font-size: 11px; color: var(--muted); }
.map-area .ma-n {
    flex: none; font-variant-numeric: tabular-nums; font-weight: 650;
    color: var(--accent); background: var(--accent-soft);
    border-radius: 99px; padding: 1px 8px; font-size: 11.5px;
}

/* ---------- Rich-text editor (Quill, CMS forms) ---------- */
.rich-text { border: 1px solid var(--line-strong); border-radius: 7px; background: var(--surface); overflow: hidden; }
.rich-text.is-invalid { border-color: var(--crit); }
.rich-text .ql-toolbar.ql-snow { border: 0; border-bottom: 1px solid var(--line); background: var(--page); }
.rich-text .ql-container.ql-snow { border: 0; font-family: inherit; font-size: 14px; }
.rich-text .ql-editor { min-height: 280px; color: var(--ink); line-height: 1.6; }
.rich-text .ql-editor.ql-blank::before { color: var(--muted); font-style: normal; }
.rich-text .ql-snow .ql-stroke { stroke: var(--ink-2); }
.rich-text .ql-snow .ql-fill { fill: var(--ink-2); }
.rich-text .ql-snow .ql-picker { color: var(--ink-2); }
.rich-text .ql-snow .ql-picker-options { background: var(--surface); border-color: var(--line); }
.rich-text .ql-snow .ql-tooltip { background: var(--surface); color: var(--ink); border-color: var(--line); box-shadow: var(--shadow); }
.rich-text .ql-snow .ql-tooltip input[type=text] { background: var(--page); color: var(--ink); border-color: var(--line-strong); }
.rich-text .ql-editor img { max-width: 100%; height: auto; border-radius: 6px; }
.rich-text .ql-editor h2 { font-size: 1.4em; } .rich-text .ql-editor h3 { font-size: 1.2em; } .rich-text .ql-editor h4 { font-size: 1.05em; }
.row-thumb-wide { width: 72px; height: 44px; object-fit: cover; border-radius: 4px; border: 1px solid var(--line); background: var(--page); }
.badge-draft { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; background: var(--warn-soft); color: var(--warn-ink); }
.badge-live { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; background: var(--ok-soft); color: var(--ok-ink); }
.badge-muted { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; background: var(--neutral-soft); color: var(--neutral-ink); }
.menu-tree .child td:first-child { padding-left: 36px; }
.menu-tree .child td:first-child::before { content: '↳ '; color: var(--muted); }
.msg-body { white-space: pre-wrap; line-height: 1.6; color: var(--ink); }
/* ---------------------------------------------------------------------------
   The external road-condition bank's sign layer.

   Its road list runs to three hundred rows, so it scrolls inside its own
   section instead of pushing every other filter off the panel.
--------------------------------------------------------------------------- */
.map-abdd-fields,
/* The repair history's own filter column — the same stack, named for
   itself so a change to one layer's panel cannot reach the other. */
.map-works-fields { display: flex; flex-direction: column; gap: 9px; margin-top: 9px; }
.map-abdd-roads { max-height: 236px; overflow-y: auto; margin-top: 4px; }
.map-area[aria-pressed="true"] { background: var(--accent-soft); font-weight: 650; }
.map-area .ma-name b { font-weight: 700; }

/* One sign's card, opened from its pin. The artwork is the heading: a reader
   recognises the picture before they read the code beside it. */
.map-abdd-card { display: flex; gap: 10px; align-items: flex-start; max-width: 300px; }
.map-abdd-card img { width: 52px; height: 52px; object-fit: contain; flex: none; }
.map-abdd-card dl { margin: 4px 0 0; display: grid; grid-template-columns: auto 1fr; gap: 2px 8px; font-size: 12px; }
.map-abdd-card dt { color: var(--muted); }
.map-abdd-card dd { margin: 0; }
.map-abdd-card .ac-src { margin-top: 6px; font-size: 10.5px; color: var(--muted); }

/* A surveyed sign with no picture to draw — its GOST code matches no
   catalogue entry, or the artwork is missing or failed to load. It is still a
   sign standing at a real kilometre, so it keeps its place on the road as a
   plain circle instead of leaving a broken-image glyph there. */
.map-sign-dot {
    width: 16px; height: 16px; border-radius: 50%;
    background: var(--accent); border: 2px solid #fff;
    box-shadow: 0 1px 4px rgb(0 0 0 / 0.35);
    padding: 0;
}

/* ===========================================================================
   Diagnostics deck — the camera car's film.

   The bottom of the screen rather than a window of its own, because the map
   above it is the index: the marker moving along the road is the scrubber, and
   the two are only worth anything seen together. Everything on the bar is one
   row — transport, seek, speed, reading — so the eye crosses it once.
   =========================================================================== */
.video-deck {
    /* A card standing clear of the bottom edge, and framed on all four sides.

       It used to be the floor of the screen — edge to edge, flush on the
       bottom, an edge along the top and nothing anywhere else. What that
       looked like was not a deck but a deck with its bottom cut off: the
       controls ran into the edge of the screen and the film read as the top
       half of something. It is a block now, the way the tool strip beside it
       became one, with the map running underneath it on every side. */
    position: absolute; z-index: 8;
    left: var(--m-gap); right: var(--m-gap); bottom: var(--m-gap);
    display: flex; flex-direction: column;
    border: 1px solid var(--line);
    border-radius: var(--m-radius);
    background: var(--m-glass);
    backdrop-filter: blur(16px) saturate(1.45);
    -webkit-backdrop-filter: blur(16px) saturate(1.45);
    box-shadow: 0 18px 54px rgba(15, 23, 42, 0.22), 0 1px 2px rgba(15, 23, 42, 0.08);
    overflow: hidden;
    animation: vd-rise 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes vd-rise { from { transform: translateY(14px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .video-deck { animation: none; } }

/* With the film open, everything that floats over the map clears it: the dock
   would be underneath it, and the two side columns would be cut off by it. */
.map-shell:has(.video-deck:not([hidden])) .map-dock {
    bottom: calc(var(--vd-height) + 2 * var(--m-gap));
}
/* The tools go on working over the film — zooming and switching the base map
   is exactly what a reader does while watching it. The network's two figures
   are what stands down, because they are a readout and the film is one too. */
.map-shell:has(.video-deck:not([hidden])) .map-dock .dock-card { display: none; }
.map-shell:has(.video-deck:not([hidden])) .map-panel,
.map-shell:has(.video-deck:not([hidden])) .map-layers {
    bottom: calc(var(--vd-height) + 3 * var(--m-gap) + var(--m-dock-real, var(--m-dock-h)));
}

/* ---------- the bar ---------- */
.vd-bar {
    display: flex; align-items: center; gap: 14px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--line);
    background: linear-gradient(180deg, color-mix(in srgb, var(--surface) 70%, transparent), transparent);
}

.vd-transport { display: flex; align-items: center; gap: 6px; }
.vd-btn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; flex: none;
    border: 1px solid var(--line-strong); border-radius: 7px;
    background: var(--surface); color: var(--ink-2); cursor: pointer;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}
.vd-btn svg { width: 17px; height: 17px; }
.vd-btn:hover { border-color: var(--accent); color: var(--accent); }
.vd-btn:disabled { opacity: 0.4; cursor: default; border-color: var(--line); color: var(--muted); }

/* The one control the hand goes to without looking. */
.vd-play {
    width: 40px; height: 40px; border-radius: 8px;
    background: var(--accent); border-color: var(--accent); color: #fff;
    box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 38%, transparent);
}
.vd-play:hover { background: var(--accent); border-color: var(--accent); color: #fff; filter: brightness(1.06); }
.vd-play svg { width: 19px; height: 19px; }

.vd-seek { flex: 1; min-width: 120px; display: flex; align-items: center; gap: 10px; }
.vd-seek input[type="range"] {
    flex: 1; min-width: 0; height: 22px; -webkit-appearance: none; appearance: none;
    background: transparent; cursor: pointer;
}
.vd-seek input[type="range"]::-webkit-slider-runnable-track {
    height: 5px; border-radius: 99px;
    /* Filled to the played position, so the track reads as progress rather
       than as a setting. */
    background: linear-gradient(90deg, var(--accent) var(--vd-progress, 0%), var(--line-strong) var(--vd-progress, 0%));
}
.vd-seek input[type="range"]::-moz-range-track { height: 5px; border-radius: 99px; background: var(--line-strong); }
.vd-seek input[type="range"]::-moz-range-progress { height: 5px; border-radius: 99px; background: var(--accent); }
.vd-seek input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 15px; height: 15px; margin-top: -5px; border-radius: 50%;
    background: var(--surface); border: 3px solid var(--accent);
    box-shadow: 0 1px 5px rgba(15, 23, 42, 0.3);
}
.vd-seek input[type="range"]::-moz-range-thumb {
    width: 15px; height: 15px; border-radius: 50%;
    background: var(--surface); border: 3px solid var(--accent);
}
.vd-count {
    flex: none; font-size: 11.5px; font-variant-numeric: tabular-nums;
    color: var(--muted); min-width: 84px; text-align: right;
}

.vd-speed { display: flex; gap: 2px; padding: 3px; border-radius: 7px; background: var(--page); flex: none; }
.vd-rate {
    border: 0; background: transparent; cursor: pointer;
    padding: 4px 9px; border-radius: 6px;
    font-size: 11.5px; font-weight: 650; font-variant-numeric: tabular-nums;
    color: var(--muted);
}
.vd-rate:hover { color: var(--ink); }
.vd-rate[aria-pressed="true"] { background: var(--surface); color: var(--accent); box-shadow: 0 1px 3px rgba(15, 23, 42, 0.12); }

/* The three readings the register itself names: address, latitude, longitude.
   Tabular figures and a fixed width, so they do not shuffle as the car moves. */
.vd-readout { display: flex; gap: 16px; margin: 0; flex: none; }
.vd-readout > div { display: flex; flex-direction: column; gap: 1px; min-width: 88px; }
.vd-readout dt {
    font-size: 9.5px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.vd-readout dd {
    margin: 0; font-size: 13.5px; font-weight: 650; color: var(--ink);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* A coordinate read off a screen is a coordinate typed wrong, so the two GPS
   figures are buttons that put themselves on the clipboard. */
.vd-copy {
    border: 0; padding: 0; background: none; cursor: copy; text-align: left;
    font: inherit; color: inherit;
    border-bottom: 1px dashed var(--line-strong);
}
.vd-copy:hover { color: var(--accent); border-bottom-color: var(--accent); }
.vd-copy.is-copied { color: var(--ok-ink, var(--accent)); border-bottom-color: currentColor; }

.vd-where {
    flex: none; max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 12px; color: var(--muted); padding-left: 14px; border-left: 1px solid var(--line);
}
.vd-where b { color: var(--ink); font-weight: 650; }

.vd-close { margin-left: auto; }

/* ---------- the four frames ---------- */
/* The four frames are **one** picture.

   They are not four cameras looking at four things: they are a single 180°
   view the rig cut into quarters, so any gap between them is a gap torn
   through the middle of the road. No margin, no border between them, no
   rounded corners except at the two outside ends — the strip has to read as
   one continuous photograph, because that is what it is. */
.vd-strip {
    flex: 1; min-height: 0;
    display: grid; grid-template-columns: repeat(var(--vd-cams, 4), minmax(0, 1fr));
    gap: 0; padding: 0;
    background: #0b1119;
}
.vd-cam {
    position: relative; min-width: 0; overflow: hidden;
    background: #0b1119;
    display: flex; align-items: center; justify-content: center;
    /* <figure> carries a 40px side margin from the user agent, which put
       eighty pixels of nothing through the middle of a continuous road. */
    margin: 0;
}
.vd-cam img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    /* The next frame replaces this one; a transition would smear the road. */
    transition: none;
}
.vd-cam.is-empty img { opacity: 0; }

/* Which quarter is which still matters to somebody reading a defect, but not
   enough to cut the picture into four all the time. It shows on hover. */
.vd-cam-label {
    position: absolute; left: 8px; top: 8px; z-index: 2;
    padding: 2px 8px; border-radius: 99px;
    font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
    color: #fff; background: rgba(9, 14, 24, 0.62);
    backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    opacity: 0; transition: opacity 0.15s ease; pointer-events: none;
}
.vd-strip:hover .vd-cam-label { opacity: 1; }
.vd-cam-miss {
    position: absolute; inset: 0; display: none;
    align-items: center; justify-content: center;
    font-size: 11.5px; color: rgba(255, 255, 255, 0.62);
}
.vd-cam.is-empty .vd-cam-miss { display: flex; }

/* The film is wide before it is tall: on a short screen the frames shrink
   rather than the bar, because the bar is where the controls are. A variable,
   so the panel and the tool column know how far to stop short of it. */
.map-shell { --vd-height: clamp(212px, 33vh, 372px); }
.video-deck { height: var(--vd-height); }
/* A class selector outranks the user agent's `[hidden] { display: none }`, so
   `display: flex` above was keeping the deck on screen with nothing in it
   whenever it was hidden. The same trap as the play glyph. */
.video-deck[hidden] { display: none; }

@media (max-width: 1180px) {
    .vd-readout > div:nth-child(n + 3) { display: none; }
    .vd-where { display: none; }
}
@media (max-width: 900px) {
    .map-shell { --vd-height: clamp(180px, 42vh, 320px); }
    .vd-readout { display: none; }
}

/* The car, walking the road while the film plays. A pulse rather than a pin:
   it is not a place you can click, it is where you are. */
.map-car { position: relative; width: 26px; height: 26px; margin: -13px 0 0 -13px; }
.map-car i {
    position: absolute; inset: 7px; border-radius: 50%;
    background: var(--accent); border: 2.5px solid #fff;
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.45);
}
.map-car::before {
    content: ''; position: absolute; inset: 0; border-radius: 50%;
    background: color-mix(in srgb, var(--accent) 34%, transparent);
    animation: car-pulse 1.6s ease-out infinite;
}
@keyframes car-pulse {
    from { transform: scale(0.55); opacity: 0.9; }
    to { transform: scale(1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .map-car::before { animation: none; opacity: 0.35; } }

/* Which glyph the play button wears. Driven by a class, because `hidden` is a
   property of HTMLElement and an <svg> is not one — setting `svg.hidden` in
   script changes nothing at all. The attribute in the markup still needs
   beating, since a global `svg { display: block }` outranks the user agent's
   `[hidden] { display: none }`. */
.vd-play .vd-ic-play { display: block; }
.vd-play .vd-ic-pause { display: none; }
.vd-play.is-playing .vd-ic-play { display: none; }
.vd-play.is-playing .vd-ic-pause { display: block; }

/* ===================================================================
   The layers panel

   The one place the reader decides what is drawn. It replaced three:
   a bar across the top of the map for the survey, tiles in the filter
   panel for this system's own registers, and a section between them
   for the sign layer — so "which layers are on" could only be answered
   by looking in three directions.

   Two lists, because the two halves behave differently. A measurement
   taken along the road colours the line and a line can only be one
   colour: radio buttons. An object stands where it stands and any
   number can be up at once: switches.
   =================================================================== */

.map-layers {
    position: absolute; z-index: 7;
    left: var(--m-gap); top: var(--m-gap); bottom: var(--m-gap);
    width: var(--m-layers);
    display: flex; align-items: flex-start; gap: 8px;
    pointer-events: none;
}
.map-layers > * { pointer-events: auto; }
.map-layers-card {
    flex: 1; min-width: 0; max-height: 100%;
    display: flex; flex-direction: column; overflow: hidden;
    border: 1px solid var(--line); border-radius: var(--m-radius);
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
/* Folded, the panel keeps its width and shows its header — the rule the
   right-hand panel already follows, and the reason it does: a fold that threw
   the column's width away handed the reader something to find again on the
   way back, and two panels on one screen folding differently is two rules
   where there should be one. */
/* Stretched, not `flex-start`: in a column a start-aligned child is as wide
   as its content, so the card narrowed and widened with whichever sub-panel
   or filter list happened to be open. The column's width is the card's. */
.map-layers { flex-direction: column; align-items: stretch; }
.map-layers-card { width: 100%; }
.ml-fold {
    flex: none; width: 100%; border: 1px solid var(--line); border-radius: var(--m-radius);
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
.map-layers-card { max-height: calc(100% - 48px); }
.map-shell.layers-closed .map-layers-card { display: none; }
.map-shell.layers-closed .ml-fold .map-panel-chev { transform: rotate(-90deg); }

/* Unfolding downwards, which is what the chevron promised. */
@keyframes map-unfold { from { opacity: 0; transform: translateY(-9px); } }
.map-layers-card,
.map-panel-card { animation: map-unfold 0.2s cubic-bezier(0.22, 1, 0.36, 1); }
@media (prefers-reduced-motion: reduce) {
    .map-layers-card, .map-panel-card { animation: none; }
}

/* ---------- the head ---------- */
.ml-head {
    flex: none; display: flex; align-items: flex-start; gap: 10px;
    padding: 13px 13px 11px;
}
.ml-title { flex: 1; min-width: 0; }
.ml-title h2 {
    margin: 0; font-size: 15px; font-weight: 700; line-height: 1.25; color: var(--ink);
}
/* One line. Two lines of small grey explaining a panel whose six tabs now
   name themselves is two lines the list underneath was paying for. */
.ml-title p {
    margin: 3px 0 0; font-size: 11.5px; line-height: 1.35; color: var(--muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- which road, and which survey year ---------- */
/* Side by side, bottom-aligned: the road and everything qualifying it on the
   left, the survey year on the right.

   They were stacked for a while, because the row did read badly — the year's
   label wrapped to two lines under a road name that did not, and the pair sat
   lopsided. What fixed the row is holding the label to one line
   (`.ml-field-year > span`), which is what sizes that field: 92 px in Uzbek,
   120 px with "ГОД ОБСЛЕДОВАНИЯ", and the road takes what is left. Measured
   at the panel's real width in both languages, the block is 80 px tall with
   nothing truncated. This is the only `.ml-picker` rule in the file — see the
   note beside `.ml-picker[hidden]` for what having two of them cost. */
.ml-picker {
    flex: none; display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
    padding: 0 13px 11px;
    border-bottom: 1px solid var(--line);
}
/* Our own registers are drawn for the whole country and are not asked of one
   road, so on that tab the road and the survey year are two controls that do
   nothing — and 76 px the list could have had. */
.map-layers-card.on-registry .ml-picker { display: none; }
.ml-field { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ml-field > span {
    font-size: 9.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; color: var(--muted);
}
.ml-field-year { flex: none; }
.ml-input {
    width: 100%; height: 32px; padding: 0 9px;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--surface); color: var(--ink); font-size: 12.5px;
}
.ml-input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: 1px; }
.ml-input:disabled { color: var(--muted); background: var(--page); }

/* The road register's own suggestions. Drops over whatever is under it,
   which on this panel is the tab strip. */
.ml-roads {
    position: absolute; z-index: 4; top: 100%; left: 0; right: 0; margin-top: 4px;
    max-height: 264px; overflow-y: auto; padding: 4px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface);
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.2);
}
.ml-roads[hidden] { display: none; }
.ml-road {
    width: 100%; display: flex; flex-direction: column; gap: 1px;
    padding: 6px 8px; border: 0; border-radius: 6px;
    background: none; color: var(--ink-2); text-align: left; cursor: pointer;
    font-size: 11.5px;
}
.ml-road:hover, .ml-road[aria-selected="true"] { background: var(--accent-soft); }
.ml-road b { font-weight: 700; color: var(--ink); }
.ml-road span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ml-road i { font-style: normal; color: var(--muted); font-size: 10.5px; }

/* ---------- the six lists, and the rail that picks one ---------- */
/* The rail stands down the left rather than across the top.

   Across, six names needed ~470 px in a 300 px column, so the strip scrolled
   sideways with no scrollbar: three tabs were visible, the other three were
   only findable by dragging a strip that did not look draggable, and the
   whole thing cost a row and a rule off the top of the list underneath.

   Down the left every name has a line of its own, all six are in view at
   once, and the list gets that height back. */
.ml-work {
    /* A column now, not a row: the panel shows one thing at a time — the
       grid of what it holds, or the one panel you went into. */
    flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}

/* ---------- the root: what this panel holds ----------

   It opened on a rail of six names turned on their side down the left edge —
   a set of tabs nobody can read without tilting their head, of which only one
   was ever on screen. It is a grid of named tiles now, grouped by the
   question they answer, and pressing one goes *into* it. */
.ml-root {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    padding: 12px 12px 14px; display: flex; flex-direction: column; gap: 16px;
    scrollbar-width: thin;
}
.ml-root[hidden] { display: none; }

/* The first level: two registers, one row each. A row rather than a tile —
   each carries a sentence saying what is inside, and two tiles side by side
   in a 300 px column leave that sentence no room. */
.ml-realms { display: flex; flex-direction: column; gap: 8px; }
.ml-realms[hidden] { display: none; }
.ml-realm-tile {
    position: relative; width: 100%;
    display: flex; align-items: center; gap: 12px;
    min-height: 72px; padding: 12px 12px 12px 13px;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--surface); color: var(--ink); text-align: left; cursor: pointer;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.ml-realm-tile:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.ml-realm-tile.is-on { border-color: color-mix(in srgb, var(--accent) 32%, var(--line)); }
.ml-realm-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ml-realm-text .ml-tile-name { text-align: left; font-size: 13px; font-weight: 700; }
.ml-realm-text i { font-style: normal; font-size: 11px; line-height: 1.3; color: var(--muted); }
.ml-realm-tile .ml-tile-badge { position: static; flex: none; }
.ml-realm-chev { width: 16px; height: 16px; flex: none; color: var(--muted); }

/* The second level: one register's own groups, exactly as the root used to
   hold them all. */
.ml-realm { display: flex; flex-direction: column; gap: 16px; }
.ml-realm[hidden] { display: none; }
/* The picker carries its own side padding and rule for the column it used to
   stand in; inside a realm it is one block among the groups. */
.ml-realm > .ml-picker { padding: 0 0 11px; }

.ml-group { display: flex; flex-direction: column; gap: 9px; }
/* Our own registers first, then the road network, then the external survey.
   The panel used to open on somebody else's data: the survey is what most of
   the map draws, but it is not what this system answers for, and a reader
   looking for our own elements had to scroll past four tiles of it.

   Ordered here and not in the markup, deliberately. The survey group's
   `@can` sits outside its own div, so moving the blocks by hand takes the
   closing tag and leaves the opening one — which scrambled the nesting twice
   and rendered the groups side by side. They are flex children of `.ml-root`;
   the order is a fact about the layout and belongs where the layout is. */
.ml-group.is-registry { order: 1; }
.ml-group.is-network { order: 2; }
.ml-group.is-survey { order: 3; }
.ml-group-head {
    margin: 0; padding: 0 2px; display: flex; align-items: baseline; gap: 8px;
    font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--muted);
}
/* What the group is counted over — "for the chosen road" against "across the
   whole network" — because the same tile means a different thing in each. */
.ml-group-head i {
    margin-left: auto; flex: none;
    font-size: 10.5px; font-style: normal; font-weight: 400;
    letter-spacing: 0; text-transform: none; color: var(--muted);
}

.ml-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.ml-tile {
    position: relative;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
    min-height: 80px; padding: 12px 8px 10px;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--surface); cursor: pointer;
    transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.ml-tile:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.ml-tile-ic {
    width: 36px; height: 36px; flex: none; display: grid; place-items: center;
    border-radius: 8px; background: var(--accent-soft); color: var(--accent);
}
.ml-tile-ic svg { width: 19px; height: 19px; }
.ml-tile-name {
    font-size: 12px; font-weight: 600; line-height: 1.25;
    text-align: center; color: var(--ink);
}
/* What is switched on inside, said on the tile — so the root answers "what is
   holding" without being opened. */
.ml-tile-badge {
    position: absolute; top: 7px; right: 7px;
    min-width: 18px; height: 18px; padding: 0 6px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 99px; background: var(--accent); color: #fff;
    text-decoration: none; font-size: 10px; font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.ml-tile-badge[hidden] { display: none; }
.ml-tile.is-on { border-color: color-mix(in srgb, var(--accent) 32%, var(--line)); }

/* ---------- one level in ---------- */
.ml-sub-head {
    flex: none; display: flex; align-items: stretch;
    border-bottom: 1px solid var(--line);
}
.ml-sub-head[hidden] { display: none; }
.ml-back {
    width: 46px; flex: none; display: grid; place-items: center;
    border: 0; border-right: 1px solid var(--line);
    background: none; color: var(--ink-2); cursor: pointer;
}
.ml-back:hover { background: var(--page); color: var(--accent); }
.ml-back svg { width: 18px; height: 18px; }
.ml-sub-title { flex: 1; min-width: 0; padding: 10px 12px; }
/* Where back is. A drill-down with no breadcrumb is a panel a reader can get
   lost one level inside. */
.ml-crumb {
    margin: 0 0 1px; font-size: 10.5px; color: var(--muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ml-sub-title h3 {
    margin: 0; font-size: 15px; font-weight: 700; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ml-sub-head .map-x { width: 28px; height: 28px; align-self: center; margin-right: 9px; }

@keyframes ml-in { from { opacity: 0; transform: translateX(14px); } }
.ml-pane:not([hidden]) { animation: ml-in 0.22s cubic-bezier(0.22, 1, 0.36, 1); }
@media (prefers-reduced-motion: reduce) { .ml-pane:not([hidden]) { animation: none; } }

.ml-body {
    flex: 1 1 auto; min-width: 0; overflow-y: auto; overscroll-behavior: contain;
    scrollbar-width: thin;
    /* Enough of the list to be a list. With the film open the card has a
       third of the height it usually has, and without this the body was the
       part that gave way — the panel showed its own chrome and none of its
       rows. What gives way is the foot, below. */
    min-height: 92px;
}
.ml-pane { padding: 10px; display: flex; flex-direction: column; gap: 8px; }
.ml-pane[hidden] { display: none; }
.ml-pane-registry { gap: 8px; }

.ml-note, .ml-sub {
    margin: 0; font-size: 11px; line-height: 1.45; color: var(--ink-2);
}
.ml-note {
    padding: 8px 10px; border-radius: 7px;
    background: var(--page); color: var(--muted);
}
.ml-sub { color: var(--muted); }
.ml-empty { margin: 0; padding: 18px 8px; text-align: center; font-size: 12px; color: var(--muted); }

.ml-search {
    display: flex; align-items: center; gap: 7px; padding: 0 10px;
    height: 34px; border: 1px solid var(--line); border-radius: 7px; background: var(--surface);
}
.ml-search svg { width: 14px; height: 14px; flex: none; color: var(--muted); }
.ml-search input {
    flex: 1; min-width: 0; border: 0; background: none; outline: none;
    color: var(--ink); font-size: 12.5px;
}
.ml-bulk { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ml-link {
    border: 0; background: none; cursor: pointer; padding: 0;
    font-size: 11.5px; font-weight: 600; color: var(--accent);
}
.ml-link-mute { color: var(--muted); }
/* The way out of a chosen indicator. Aligned with the rows it clears rather
   than floated off to one side, so it reads as part of the same list. */
.ml-clear { display: inline-flex; align-items: center; gap: 5px; align-self: flex-start; }
.ml-clear[hidden] { display: none; }
.ml-clear svg { width: 12px; height: 12px; }
.ml-link:hover { text-decoration: underline; }

/* ---------- one row of either list ---------- */
.ml-list, .ml-groups { display: flex; flex-direction: column; gap: 1px; }
.ml-row {
    position: relative; display: flex; align-items: center; gap: 9px;
    padding: 8px 10px; border-radius: 7px; cursor: pointer;
    transition: background 0.12s ease;
}
.ml-row:hover { background: var(--page); }
/* A section this road holds nothing for is shown, not hidden: "there is no
   data" is an answer, and hiding it makes the reader wonder where it went. */
.ml-row[data-empty="1"] { opacity: 0.45; cursor: default; }
.ml-row[data-empty="1"]:hover { background: none; }
.ml-ic { width: 17px; height: 17px; flex: none; color: var(--ink-2); }
.ml-row-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ml-row-txt b {
    font-size: 12.5px; font-weight: 600; color: var(--ink); line-height: 1.3;
}
.ml-row-txt i {
    font-style: normal; font-size: 10.5px; color: var(--muted);
}
.ml-row-txt i:empty { display: none; }

/* The chosen indicator, because one of them always is. */
.ml-row:has(.ml-radio-in:checked) { background: var(--ok-soft, var(--accent-soft)); }
.ml-row:has(.ml-radio-in:checked) .ml-ic,
.ml-row:has(.ml-switch-in:checked) .ml-ic { color: var(--accent); }
/* A chosen side is marked on the row itself: the switch is at the far end of
   a 320 px column and the mark is at the near end, and a reader scanning the
   list reads the near end. */
.ml-row:has(.ml-side-in:checked) .ml-side { background: var(--accent-soft); }

/* Every input in these lists is drawn by the mark that follows it, never by
   the browser's own box — a new switch class added without being named here
   shows a bare checkbox beside its switch. */
.ml-radio-in, .ml-switch-in, .ml-side-in, .ml-source-in {
    position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.ml-radio {
    width: 17px; height: 17px; flex: none; border-radius: 50%;
    border: 1.6px solid var(--line-strong); background: var(--surface);
    transition: border-color 0.12s ease;
}
.ml-radio-in:checked + .ml-radio {
    border: 5px solid var(--accent); background: var(--surface);
}
.ml-radio-in:focus-visible + .ml-radio { outline: 2px solid var(--accent); outline-offset: 2px; }

.ml-switch {
    width: 32px; height: 18px; flex: none; border-radius: 99px;
    background: var(--line-strong); position: relative;
    transition: background 0.14s ease;
}
.ml-switch::after {
    content: ''; position: absolute; top: 2px; left: 2px;
    width: 14px; height: 14px; border-radius: 50%; background: #fff;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.35);
    transition: transform 0.14s ease;
}
.ml-switch-in:checked + .ml-switch,
.ml-side-in:checked + .ml-switch,
.ml-source-in:checked + .ml-switch { background: var(--accent); }
.ml-switch-in:checked + .ml-switch::after,
.ml-side-in:checked + .ml-switch::after,
.ml-source-in:checked + .ml-switch::after { transform: translateX(14px); }
.ml-switch-in:focus-visible + .ml-switch,
.ml-side-in:focus-visible + .ml-switch,
.ml-source-in:focus-visible + .ml-switch { outline: 2px solid var(--accent); outline-offset: 2px; }

.ml-count {
    flex: none; min-width: 20px; text-align: center; text-decoration: none;
    font-size: 10px; font-weight: 700; line-height: 16px;
    color: var(--muted); background: var(--neutral-soft);
    border-radius: 99px; padding: 0 6px;
    font-variant-numeric: tabular-nums;
}
.ml-count.on { color: var(--ok, #0ca30c); background: var(--ok-soft, var(--accent-soft)); }

/* ---------- the object headings ---------- */
.ml-group { border-top: 1px solid var(--line); }
.ml-group:first-child { border-top: 0; }
.ml-group-head {
    display: flex; align-items: center; gap: 8px; padding: 9px 10px;
    list-style: none; cursor: pointer; user-select: none;
    font-size: 12px; font-weight: 700; color: var(--ink);
}
.ml-group-head::-webkit-details-marker { display: none; }
.ml-group-head:hover { color: var(--accent); }
.ml-group-head > span { flex: 1; min-width: 0; }
.ml-group-head b {
    font-size: 10.5px; font-weight: 700; color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.ml-group-chev {
    width: 14px; height: 14px; flex: none; color: var(--muted);
    transition: transform 0.15s ease;
}
.ml-group[open] > .ml-group-head .ml-group-chev { transform: rotate(180deg); }
.ml-group-body { padding-bottom: 6px; }

/* ---------- where on the road: the locations panel ---------- */
/* Two filters and a breakdown in one column, so each needs a heading of its
   own — without them the source switches and the placement switches read as
   one long list of unrelated toggles. */
.ml-block { display: flex; flex-direction: column; gap: 6px; }
.ml-block + .ml-block { padding-top: 10px; border-top: 1px solid var(--line); }
.ml-loc-head {
    margin: 0; font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
    text-transform: uppercase; color: var(--muted);
}

/* The side a row stands on, as a mark rather than a word: the list already
   says which side in words, and a reader scanning it wants to find "the right
   ones" without reading. Left and right are the two that are worth drawing;
   everything else shares the neutral mark. */
.ml-side {
    width: 17px; height: 17px; flex: none; border-radius: 4px;
    background: var(--neutral-soft); position: relative;
}
.ml-side::after {
    content: ''; position: absolute; inset: 4px auto 4px 4px;
    width: 3px; border-radius: 2px; background: var(--line-strong);
}
.ml-side[data-side="0"]::after { background: var(--accent); }
.ml-side[data-side="1"]::after { inset: 4px 4px 4px auto; background: var(--accent); }
.ml-side[data-side="7"]::after { left: 50%; transform: translateX(-50%); background: var(--accent); }
.ml-side[data-side="4"]::after,
.ml-side[data-side="5"]::after,
.ml-side[data-side="6"]::after { left: 50%; transform: translateX(-50%); }

.ml-group-side { border-top: 1px solid var(--line); margin-top: 2px; }

/* A row of the breakdown is a button, because it is one: it counts a layer
   and switching that layer on is the only thing a reader wants to do with
   the figure. */
.ml-loc-list { display: flex; flex-direction: column; gap: 1px; }
.ml-loc {
    display: flex; align-items: center; gap: 9px; width: 100%;
    padding: 7px 10px; border: 0; border-radius: 7px; cursor: pointer;
    background: none; text-align: left; color: var(--ink);
    transition: background 0.12s ease;
}
.ml-loc:hover { background: var(--page); }
.ml-loc > span {
    flex: 1; min-width: 0; font-size: 12.5px; font-weight: 600; line-height: 1.3;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ml-loc > u {
    flex: none; text-decoration: none; font-size: 10px; font-weight: 700;
    line-height: 16px; padding: 0 6px; border-radius: 99px;
    color: var(--muted); background: var(--neutral-soft);
    font-variant-numeric: tabular-nums;
}
.ml-loc.on { background: var(--ok-soft, var(--accent-soft)); }
.ml-loc.on > u { color: var(--ok, #0ca30c); background: var(--surface); }

/* A road the filter admits, named. It is in the same list as the rows above
   it and is not one of them — those switch a layer, this one goes somewhere —
   so it carries the mark the map draws it with rather than the tick the
   others carry, and the difference is visible before it is pressed. */
.ml-loc-road > span { font-weight: 600; }
.ml-loc-road::before {
    content: ''; flex: none; width: 3px; height: 15px; border-radius: 2px;
    background: var(--accent);
}
.ml-loc-road > u { color: var(--accent); background: var(--accent-soft); }
.ml-loc-road:hover { background: var(--accent-soft); }

/* ---------- the film, at the foot of the panel ---------- */
/* The foot is what shrinks when the card runs out of height, and it
   scrolls inside itself rather than pushing the status line off the
   bottom of a card that hides its overflow. */
.ml-video {
    flex: 0 1 auto; min-height: 0; display: flex; flex-direction: column;
    border-top: 1px solid var(--line);
}
.ml-video-face {
    width: 100%; display: flex; align-items: center; gap: 9px;
    padding: 10px 13px; border: 0; background: none; cursor: pointer;
    font-size: 12.5px; font-weight: 600; color: var(--ink-2);
}
.ml-video-face:hover { color: var(--accent); }
.ml-video-face > svg { width: 17px; height: 17px; flex: none; }
.ml-video-face > span { flex: 1; min-width: 0; text-align: left; }
.ml-video-chev { width: 14px; height: 14px; flex: none; color: var(--muted); transition: transform 0.15s ease; }
.ml-video-face[aria-expanded="true"] { color: var(--accent); }
.ml-video-face[aria-expanded="true"] .ml-video-chev { transform: rotate(180deg); }
.ml-video-body {
    display: flex; flex-direction: column; gap: 8px; padding: 0 13px 11px;
    min-height: 0; overflow-y: auto; scrollbar-width: thin;
}
.ml-video-body[hidden] { display: none; }

.ml-status {
    flex: none; margin: 0; padding: 9px 13px;
    border-top: 1px solid var(--line);
    font-size: 11px; line-height: 1.45; color: var(--muted);
}
.ml-status:empty { display: none; }
.ml-video-body .ml-status { border-top: 0; padding: 0; }
#videoHint[hidden] { display: none; }

/* What one record says, in the register's own words.

   Three things here were measured against the real register rather than
   guessed, because the balloon it produced was unreadable: 320 px wide, the
   label column taking 176 px of it and the value column left with 134, and
   `word-break: break-word` then chopping what did not fit through the middle
   of a word — "Щебёночно-гравийно-песчаная смесь" came out over three lines
   with the breaks in the wrong places.

   So: the card is wider, the value column gets the larger share and can no
   longer be starved by a long label, and the break is `overflow-wrap`, which
   only splits a word that genuinely cannot fit on a line of its own. */
/* A card that floats ON the map belongs to the map, not to the panel.

   The canvas styles are a setting of their own: a reader can put the ground
   into the dark style and leave the panel in the light theme — and then a
   popup drawn in the panel's colours is a white sheet in the middle of a dark
   map. That is what "the popup comes out white" means; the card was already
   in our style, it was in the *other half* of our style.

   So while the ground is dark these take the dark palette whatever the panel
   is wearing. Where the two already agree nothing changes, and the fallbacks
   keep the card right if it is ever drawn outside the map. */
.map-shell {
    --m-pop: var(--surface);
    --m-pop-ink: var(--ink);
    --m-pop-ink-2: var(--ink-2);
    --m-pop-line: var(--line);
}
.map-shell[data-canvas="dark"] {
    --m-pop: #161d2b;
    --m-pop-ink: #eef2f8;
    --m-pop-ink-2: #b5bfcf;
    --m-pop-line: #35405a;
}

.md-card { min-width: 280px; max-width: 460px; font-size: 13px; }
.md-card h4 {
    margin: 0 0 9px; font-size: 14px; font-weight: 700; color: var(--m-pop-ink, var(--ink));
    line-height: 1.35;
}
.md-card dl {
    margin: 0; display: grid;
    grid-template-columns: minmax(84px, 0.85fr) minmax(0, 1fr);
    gap: 4px 12px; align-items: baseline;
}
.md-card dt { min-width: 0; color: var(--m-pop-ink-2, var(--ink-2)); font-size: 12.5px; line-height: 1.4; }
.md-card dd {
    margin: 0; min-width: 0; font-weight: 600; line-height: 1.4; color: var(--m-pop-ink, var(--ink));
    overflow-wrap: break-word; word-break: normal; hyphens: none;
}
.md-card dl { gap: 6px 14px; }

/* ---------------------------------------------------------- the balloon
   A survey record belongs AT its kilometre, so this is the one layer on the
   map that still opens a Yandex balloon rather than the panel's detail card.
   Its chrome, though, is a white sheet with a white tail and a dark close
   glyph — which is exactly why balloons were taken off every other layer
   here: the card inside is drawn in the panel's colours, so in dark mode its
   labels came out near-white on white and could not be read at all.

   The sheet is restyled rather than replaced. Two things make that work:

   Yandex injects its own stylesheet as inline <style> AFTER panel.css, so a
   single-class selector of ours loses the tie and is silently ignored. Every
   rule below is written under `.map-shell` — the balloon pane lives inside
   it — which outranks theirs without reaching for !important.

   And the version number sits inside their class names
   (`ymaps-2-1-79-balloon__layout`), moving whenever they ship, so each one is
   matched on its suffix and never on the whole name. */
.map-shell [class*="-balloon__layout"],
.map-shell [class*="-balloon__content"] {
    background: var(--m-pop);
    color: var(--m-pop-ink);
}
.map-shell [class*="-balloon__layout"] {
    border: 1px solid var(--m-pop-line);
    border-radius: 11px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.26), 0 1px 2px rgba(15, 23, 42, 0.08);
}
.map-shell [class*="-balloon__content"] {
    margin: 0; padding: 13px 16px 14px;
    font: inherit;
}
/* The pointer is a rotated square drawn by a pseudo-element, and it is a
   separate white that has to be told as well — left alone it reads as a
   white chip hanging off a dark card. */
.map-shell [class*="-balloon__tail"]::after {
    background: var(--m-pop);
    box-shadow: -1px -1px 0 0 var(--m-pop-line);
}
/* Their close glyph is a dark X baked into a background image, which is
   invisible on a dark sheet. Drawn here instead, in the panel's own ink, so
   it is right in both themes. */
.map-shell [class*="-balloon__close-button"] {
    background-image: none;
    position: relative;
    opacity: 0.65;
}
.map-shell [class*="-balloon__close-button"]:hover { opacity: 1; }
.map-shell [class*="-balloon__close-button"]::before,
.map-shell [class*="-balloon__close-button"]::after {
    content: ''; position: absolute; left: 50%; top: 50%;
    width: 14px; height: 1.8px; border-radius: 2px;
    background: var(--m-pop-ink-2);
}
.map-shell [class*="-balloon__close-button"]::before { transform: translate(-50%, -50%) rotate(45deg); }
.map-shell [class*="-balloon__close-button"]::after { transform: translate(-50%, -50%) rotate(-45deg); }

/* A survey record standing at its kilometre. Deliberately not the sign
   layer's plate: that one carries artwork and this one carries a
   measurement, and two different things on one map should not look
   alike. */
.map-diag-pin {
    width: 14px; height: 14px;
    border: 2.5px solid #fff; border-radius: 50%;
    background: var(--accent, #2563c4);
    box-shadow: 0 1px 4px rgba(15, 23, 42, 0.45);
    transform: translate(-7px, -7px);
}

/* An object layer's own marker. Same shape as the indicator's, a colour of
   its own — several of these are up at once and the whole point of switching
   on three is telling them apart. */
.map-elem-pin {
    width: 12px; height: 12px;
    border: 2px solid #fff; border-radius: 50%;
    box-shadow: 0 1px 4px rgba(15, 23, 42, 0.45);
    transform: translate(-6px, -6px);
}

/* ---------- the pavement, in the panel ---------- */
/* The summary is the figure and the picture together: a bar drawn to the
   layers' real thicknesses above the list that names them. A reader who wants
   to turn it over opens the window; a reader who only wants to know how thick
   the asphalt is never has to. */
.ml-station { display: flex; align-items: flex-end; gap: 6px; }
.ml-station[hidden] { display: none; }
.ml-step {
    width: 32px; height: 32px; flex: none; display: grid; place-items: center;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--surface); color: var(--ink-2); cursor: pointer;
}
.ml-step:hover { border-color: var(--accent); color: var(--accent); }
.ml-step svg { width: 15px; height: 15px; }
.ml-open {
    width: 100%; height: 36px; display: inline-flex; align-items: center;
    justify-content: center; gap: 8px; font-size: 12.5px;
}
.ml-open[hidden] { display: none; }
.ml-open svg { width: 16px; height: 16px; }

.pav-stack { display: flex; flex-direction: column; gap: 7px; }
.pav-total { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.pav-total span { font-size: 10.5px; color: var(--muted); }
.pav-total b { font-size: 17px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
/* Drawn to scale: each band is as tall as its layer is thick, so a 4 cm
   wearing course over 30 cm of gravel reads as one at a glance. */
.pav-bar {
    display: flex; flex-direction: column; height: 76px;
    border: 1px solid var(--line); border-radius: 6px; overflow: hidden;
}
.pav-bar i { display: block; min-height: 3px; }
.pav-layer {
    display: flex; align-items: center; gap: 8px; font-size: 11.5px; color: var(--ink-2);
}
.pav-layer > i { width: 10px; height: 10px; flex: none; border-radius: 3px; }
.pav-layer b { flex: 1; min-width: 0; font-weight: 600; color: var(--ink); }
.pav-layer u {
    flex: none; text-decoration: none; font-weight: 700;
    font-variant-numeric: tabular-nums; color: var(--ink-2);
}
.pav-tint {
    display: flex; align-items: center; gap: 7px; margin: 2px 0 0;
    font-size: 10.5px; line-height: 1.4; color: var(--muted);
}
.pav-tint i { width: 10px; height: 10px; flex: none; border-radius: 50%; }

.pav-facts {
    margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 4px 10px;
    font-size: 11.5px;
}
.pav-facts dt { color: var(--muted); }
.pav-facts dd { margin: 0; font-weight: 600; color: var(--ink); text-align: right; }
.pav-condition dd { font-variant-numeric: tabular-nums; font-weight: 550; }
.pav-condition dd span { white-space: nowrap; }

/* ---------- searchable selects, at the panel's size ---------- */
/* Tom Select ships for a full-width form: 40 px tall, 15 px type, its own
   borders. Every one of those is wrong in a 340 px floating card, and the
   dropdown has to clear the card rather than be clipped by it.

   And one thing it does that has to be undone: **it copies the original
   select's class list onto its wrapper**. So `.map-select` and `.ml-input` —
   the panel's own field look, a border, a radius, a background and ten pixels
   of padding — land on the wrapper *and* on the `.ts-control` inside it, and
   the field is drawn as two boxes, one inset from the other. The wrapper is
   chrome and carries nothing; the control is the field. */
.map-shell .ts-wrapper.map-select,
.map-shell .ts-wrapper.ml-input,
.map-shell .ts-wrapper.md-input {
    height: auto; min-height: 0; padding: 0;
    border: 0; border-radius: 0; background: none; box-shadow: none;
}
.map-shell .ts-wrapper.map-select:hover { border-color: transparent; }
.map-shell .ts-wrapper { min-height: 0; }
/* Written at `.ts-wrapper .ts-control` rather than at `.ts-control`, because
   the widget's own stylesheet reaches it as `.ts-wrapper.single .ts-control`
   and a two-class selector loses to a three-class one however late it is
   loaded — which left the search fields a different radius, border and type
   size from the plain inputs beside them. */
.map-shell .ts-wrapper .ts-control {
    min-height: 32px; height: 32px; padding: 0 9px; gap: 4px;
    display: flex; align-items: center; flex-wrap: nowrap;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--surface); color: var(--ink);
    font-size: 12.5px; line-height: 1.4;
}
/* The right-hand filter panel's fields are the taller of the two. */
.map-shell .ts-wrapper.map-select .ts-control {
    min-height: 36px; height: 36px; padding: 0 10px;
    border-color: var(--line-strong); border-radius: 6px; font-size: 13.5px;
}
.map-shell .ts-wrapper.map-select .ts-control:hover { border-color: var(--accent); }
/* The single chosen value is one line that ellipses, not a box that grows. */
.map-shell .ts-wrapper.single .ts-control > .item {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.map-shell .ts-wrapper.single .ts-control { background-image: none; }
/* The widget draws its own caret; the panel's fields do not have one
   drawn into the background, so neither should these. */
.map-shell .ts-wrapper .ts-control > input { margin: 0; min-width: 0; }
.map-shell .ts-wrapper.focus .ts-control, .map-shell .ts-wrapper.focus.single .ts-control {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 28%, transparent);
}
.map-shell .ts-wrapper .ts-control > input { font-size: inherit; color: var(--ink); }
.map-shell .ts-wrapper.disabled .ts-control { background: var(--page); opacity: 0.6; }
/* Written twice over, and the second half is why the first is not enough:
   the map's lists are rendered on <body>, so they are not inside `.map-shell`
   at all and nothing written under it can reach them. See `panel-ui.js` —
   every panel that holds a select on this screen also clips it. */
.map-shell .ts-dropdown,
.ts-dropdown-map {
    margin: 4px 0 0; border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); color: var(--ink);
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.22);
    font-size: 12.5px; overflow: hidden;
}
.map-shell .ts-dropdown .option,
.ts-dropdown-map .option { padding: 7px 10px; }
.map-shell .ts-dropdown .active,
.ts-dropdown-map .active { background: var(--accent-soft); color: var(--accent); }
.map-shell .ts-dropdown .no-results,
.ts-dropdown-map .no-results { padding: 9px 10px; color: var(--muted); }
/* Over the panels it escaped, and over the map's own chrome. */
.map-shell .ts-dropdown { z-index: 50; }
.ts-dropdown-map { z-index: 2000; }
/* It is no longer a child of the field, so its width is set by Tom Select
   from the control it belongs to — but the height is ours, and a list of
   five hundred offices wants more of the screen than the stock 200px. */
.ts-dropdown-map .ts-dropdown-content { max-height: min(320px, 46vh); }

/* ===================================================================
   The pavement in three dimensions

   A window over the whole screen rather than a corner of the panel:
   the viewer is a whole instrument — a model you turn, a cross-section
   chart, a layer list and a set of exports — and half of it in a
   340 px column is none of it.
   =================================================================== */
.road3d {
    position: fixed; inset: 0; z-index: 40;
    display: flex; align-items: center; justify-content: center;
    padding: var(--m-gap);
}
.road3d[hidden] { display: none; }
.r3-veil {
    position: absolute; inset: 0;
    background: color-mix(in srgb, var(--ink, #0f172a) 55%, transparent);
    backdrop-filter: blur(3px);
}
.r3-frame {
    position: relative; z-index: 1;
    width: min(1320px, 100%); max-height: 100%;
    display: flex; flex-direction: column; overflow: hidden;
    border: 1px solid var(--line); border-radius: var(--m-radius);
    background: var(--surface);
    box-shadow: 0 24px 72px rgba(15, 23, 42, 0.34);
    animation: r3-rise 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes r3-rise { from { transform: translateY(12px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .r3-frame { animation: none; } }

.r3-head {
    flex: none; display: flex; align-items: center; gap: 14px;
    padding: 11px 13px 11px 17px; border-bottom: 1px solid var(--line);
}
.r3-title { flex: 1; min-width: 0; }
.r3-eyebrow {
    display: block; font-size: 8.5px; font-weight: 700;
    letter-spacing: 0.13em; color: var(--muted); margin-bottom: 2px;
}
.r3-title h2 { margin: 0; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.r3-title p {
    margin: 2px 0 0; font-size: 11.5px; color: var(--muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.r3-steps { flex: none; display: flex; align-items: center; gap: 6px; }
.r3-steps .ml-input { width: 132px; height: 32px; }

/* The viewer sizes itself off this variable and scrolls inside the frame,
   because its own sidebar and cross-section chart are taller than a laptop. */
.r3-stage {
    flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    padding: 13px; background: var(--page);
    --yol3d-height: min(58vh, 560px);
}
.r3-stage > * { display: block; }
.r3-failed { margin: 0; padding: 40px 12px; text-align: center; color: var(--crit); font-size: 13px; }
.r3-note {
    flex: none; margin: 0; padding: 9px 17px;
    border-top: 1px solid var(--line);
    font-size: 11px; color: var(--muted);
}
.r3-note:empty { display: none; }

/* The map behind keeps its scroll position rather than jumping to the top. */
body.has-modal { overflow: hidden; }

/* The lidar window: the pavement window's chrome around a canvas that fills
   it. The cloud is drawn on a dark ground in both themes — a point cloud is
   light on dark the way a photograph is, and on white its pale ground reads
   as nothing. The stage has a height of its own because a canvas has none. */
.lidar3d .lv-stage {
    position: relative; overflow: hidden; padding: 0;
    height: min(68vh, 720px); background: #0e171f;
}
.lv-canvas { display: block; width: 100%; height: 100%; touch-action: none; cursor: grab; outline: none; }
.lv-canvas:active { cursor: grabbing; }
.lv-bar {
    flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 12px;
    padding: 8px 17px; border-bottom: 1px solid var(--line);
}
.lv-modes { display: inline-flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.lv-modes button {
    padding: 5px 10px; font-size: 12px; color: var(--muted); background: var(--surface);
    border: 0; border-left: 1px solid var(--line);
}
.lv-modes button:first-child { border-left: 0; }
.lv-modes button.is-on { color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.lv-size { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--muted); }
.lv-size input { width: 110px; }
.lidar3d .r3-steps select { min-width: 150px; }

/* The runs in the layers panel: one row each, both of the road's numbers. */
.ml-lidar-runs { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.ml-lidar-run {
    display: grid; grid-template-columns: 1fr auto; gap: 2px 10px; text-align: left;
    padding: 8px 10px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface);
}
.ml-lidar-run:hover { border-color: var(--accent); }
.ml-lidar-run b { font-size: 12.5px; }
.ml-lidar-run span { font-size: 12px; color: var(--muted); text-align: right; }
.ml-lidar-run i { grid-column: 1 / -1; font-style: normal; font-size: 11px; color: var(--muted); }

@media (max-width: 720px) {
    .r3-head { flex-wrap: wrap; }
    .r3-steps { order: 3; width: 100%; }
    .r3-steps .ml-input { flex: 1; width: auto; }
    .r3-stage { padding: 8px; --yol3d-height: 46vh; }
}

/* ===================================================================
   The tool strip

   Every control in it acts on the *view* — zoom, base map, line weight
   — rather than on what is drawn, which is decided in the one panel on
   the left. It used to be a column down that edge; the panel needs the
   edge, and a row along the bottom is where a drawing program puts the
   controls that are not tools anyway.

   Every rule here is written `.map-dock .map-left`, and that is load-
   bearing rather than tidy: `.map-left` is the same wrapper the trunk-
   network map stands down its own left edge, where there is no bar to lie
   along. Unscoped, these rules took that column out of the flow
   (`display: contents`), which left its cards static behind a positioned
   canvas — three toolbars painted under the map, invisible, with nothing
   on screen to say where they had gone.
   =================================================================== */
.map-dock .map-left {
    position: static; flex: 0 0 100%;
    display: flex; flex-direction: row; align-items: flex-end;
    flex-wrap: wrap; gap: 8px;
    pointer-events: none;
}
.map-dock .map-left > * { pointer-events: auto; flex: none; }
.map-dock .map-left .map-tools {
    display: flex; align-items: center; gap: 3px;
    grid-template-columns: none;
}
.map-dock .map-left .tool-sep { width: 1px; height: 22px; margin: 0 4px; }
.map-dock .map-left .tool-btn-wide { width: auto; }
.map-dock .map-left .map-colours { width: auto; }
.map-dock .map-left .map-colours { grid-template-columns: repeat(2, 28px); }

/* The kilometre-mode card lies down with the rest of the strip: its heading
   was the fold, and along the bottom there is nothing to fold away from. */
.map-dock .map-left .map-kmmode, .map-dock .map-left .map-kmmode.open {
    width: auto; flex-direction: row; align-items: center; gap: 2px;
}
.map-dock .map-left .kmmode-toggle { display: none; }

/* The bottom line reads as the question it answers: what acts on the view,
   then which roads are drawn, then how much of them there is — tools, the
   class chips, the totals, left to right.

   It only fits that way if the line is cleared for it, so the cards that
   are neither tool nor answer — the base map, the colour key, the kilometre
   mode and the display settings — are put on a line above. Before this the
   whole strip shared one wrapping row and broke across two and three at any
   ordinary window width, with the tools landing somewhere different every
   time a panel opened.

   Ordered rather than reordered in the markup: the reading order the
   document has is the one a screen reader should keep. */
.map-dock .map-left .map-tools,
.map-dock .map-left .map-classes,
.map-dock .map-left .map-metrics { order: 2; }

/* Measured, not guessed: the three cards wanted 1 239 px and the dock between
   two open panels is 1 140, so the row broke. Every figure below is the
   smallest cut that buys the width back without the controls reading as
   cramped — the chips lose four pixels of padding a side, the totals lose a
   font step and a third of their gap, the separators lose two pixels each.
   Together they take the row to about 1 035 px, which fits with room to
   spare and keeps fitting while the dock is wider than roughly 1 040. Below
   that — a narrow window with both side panels open — the totals still wrap,
   and closing either panel is what gets them back on the line. */
.map-dock .map-left .map-classes { gap: 2px; padding: 3px; }
.map-dock .map-left .map-class-pill { height: 32px; padding: 0 9px; gap: 5px; font-size: 11.5px; }
.map-dock .map-left .map-metrics { gap: 12px; padding: 6px 10px; }
.map-dock .map-left .map-metric > span { font-size: 9px; }
.map-dock .map-left .map-metric > b { font-size: 15px; }
.map-dock .map-left .tool-sep { margin: 0 1px; }
.map-dock .map-left .map-tools { gap: 2px; }
/* The counts wear the toolbar's own spacing: they are the same buttons, in a
   card of their own rather than at the end of the toolbar. */
.map-dock .map-left .map-counts { gap: 2px; padding: 5px; }
/* A zero-height full-width item at the end of the first group, which is how
   a wrapping flex row is made to break where it is told to. */
.map-dock .map-left::after { content: ''; order: 1; flex: 0 0 100%; height: 0; }
.map-dock .map-left .kmmode-row { width: auto; padding: 0 9px; }
.map-dock .map-left .map-kmmode:not(.open) .kmmode-row { justify-content: flex-start; padding: 0 9px; }
.map-dock .map-left .map-kmmode:not(.open) .kmmode-row span { display: block; }


/* The strip wraps rather than dropping anything: a control a reader cannot
   find is worse than a second row. */
.map-dock { max-height: calc(100% - 2 * var(--m-gap)); }

/* ===================================================================
   The bottom bar

   The strip stopped being a set of cards floating over the map and became
   the floor of the screen, the way the film deck already is: edge to edge,
   flush on the bottom, one row that never wraps and never moves.

   The map is shortened by the bar's height rather than being covered by it.
   That is not tidiness — the API paints its "Яндекс Карты" badge in the
   bottom corner and it has to stay readable, which is what the old 34 px
   gap under the dock was for. Shortening the canvas carries the badge up
   with it and keeps the bar flush at the same time.

   Reading order along the bar: what acts on the view, then which roads are
   drawn and how much of them there is, then — pushed to the far end — how
   the map itself is painted. The last group is the one a reader sets once
   and leaves, so it gets the end of the row.
   =================================================================== */
/* Asked of the markup rather than of a class somebody has to remember to
   write: the bar is the dock, so a shell that holds one is a shell that has
   one. Without it `--m-bar` stays 0 and every measurement below — the
   canvas, the two columns, the cards that open upward — collapses to the
   layout the screen had before the bar existed. */
/* The room the floating dock needs at the bottom — its own height plus the
   gap under it — which is what the two side columns and the cards that open
   upward are measured against. The canvas is no longer shortened by it: the
   strip stands clear of the bottom edge and the map runs underneath. */
.map-shell:has(.map-dock) { --m-bar: 58px; --m-dock: var(--m-bar); }

/* Edge to edge. It used to be shortened by the bar's height so the API's own
   badge in the bottom corner stayed clear of it; the dock is centred and
   floating now, so the corners are the badge's again. */
#govMap { inset: 0; }

/* The two side columns stop above the bar rather than running behind it —
   and so does the card that stands in one of their places. It is pinned to
   the top rather than stretched between two edges, so it says the same thing
   as a height. */
.map-layers, .map-panel { bottom: calc(var(--m-dock-real, var(--m-dock-h)) + 2 * var(--m-gap)); }

.map-dock {
    left: 0; right: 0; bottom: var(--m-gap); top: auto;
    height: auto; max-height: none;
    display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: center;
    gap: 8px;
    padding: 0 var(--m-gap);
    /* The strip itself is nothing: it places the cards and takes no clicks
       of its own, so the map runs under it from edge to edge. */
    pointer-events: none;
    overflow: visible;
}
.map-dock > *, .map-dock .dock-card { pointer-events: auto; }
.map-shell.layers-closed .map-dock,
.map-shell.panel-closed .map-dock { left: 0; right: 0; }

/* The wrapper is no longer a row of its own: its children are the bar's. */
.map-dock .map-left { display: contents; }
.map-dock .map-left::after { content: none; }

/* Each group is a card of its own again, floating over the map.

   They had dropped their border, blur and shadow because the bar underneath
   them was the surface — one continuous strip welded to the bottom edge. The
   readers asked for the strip back as separate blocks standing clear of the
   edge, so each one carries its own chrome and the map runs under all of
   them. All at one height: see `--m-dock-h`. */
.map-dock .dock-card,
.map-dock .map-settings,
.map-dock .map-kmmode {
    flex: none;
    height: var(--m-dock-h);
    display: flex; align-items: center;
    padding: 0 4px;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
/* An author `display` beats the browser's own `[hidden]` rule, and the rules
   above are later in the file than `.dock-card[hidden]` and carry the same
   weight — so they were winning it, and the repair-request counts came back
   on a strip they had been taken off. Said again here, after them. */
.map-dock .dock-card[hidden],
.map-dock .map-kmmode[hidden] { display: none; }

.map-dock .map-counts, .map-dock .map-classes { padding: 0 3px; }
.map-dock .map-metrics { padding: 0 12px; gap: 16px; }

/* ---------- the tools, one square each ----------
   They were nine buttons in a single card with hairlines between the groups.
   Separately framed they read as what they are — nine things you can press —
   and the card that held them becomes the spacing between them. */
.map-dock .map-tools {
    flex: none;
    display: flex; align-items: center; gap: 6px;
    height: auto; padding: 0;
    border: 0; border-radius: 0; background: none;
    backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: none;
}
.map-dock .map-tools .tool-btn {
    width: var(--m-dock-h); height: var(--m-dock-h);
    flex: none;
    border: 1px solid var(--line); border-radius: 9px;
    background: var(--m-glass);
    backdrop-filter: blur(13px) saturate(1.4);
    -webkit-backdrop-filter: blur(13px) saturate(1.4);
    box-shadow: 0 8px 34px rgba(15, 23, 42, 0.16), 0 1px 2px rgba(15, 23, 42, 0.06);
}
/* One that carries a count is wider than a square — four digits crammed into
   a 44 px box sit on top of the icon they belong to — but never shorter: the
   row lines up on the height, not on the width. */
.map-dock .map-tools .tool-btn-wide {
    width: auto; height: var(--m-dock-h); padding: 0 10px;
}

/* The groups were told apart by a hairline; between framed squares a rule is
   one edge too many, so it becomes the gap it was drawn beside. */
.map-dock .map-tools .tool-sep {
    width: 4px; height: 0; margin: 0; background: none;
}

/* No hairlines between them any more: a card edge is the separator now, and
   a rule drawn inside one as well reads as two boxes. And no spacer pushing
   the paint settings to the far end — the row is centred, so there is no far
   end to push anything to. */
.map-dock .map-tools { order: 1; }
.map-dock .map-counts { order: 2; }
.map-dock .map-classes { order: 3; }
/* Same order as the classes, after them in the document: flex keeps source
   order within one order value, so the repair-history switch sits at the end
   of that filter without the whole row having to be renumbered. */
.map-dock .map-worksbar { order: 3; }
.map-dock .map-metrics { order: 4; }
.map-dock .map-colours { order: 7; }
.map-dock .map-kmmode { order: 8; }
.map-dock .map-settings { order: 9; }

/* ---------- the map's settings: one face, one card in the middle ----------
   Which ground, how heavy the lines, how the ground is painted. They were
   three dropdowns hanging off three faces; a reader changes them once a
   session, and three places to look for one kind of answer is two too many.
   The card is centred on the screen rather than hung off its face: three
   columns of sliders are wider than anything a 44 px control can carry. */
.settings-face {
    height: 100%; padding: 0 10px;
    display: flex; align-items: center; gap: 9px;
    border: 0; border-radius: 8px; background: none;
    color: var(--ink-2); cursor: pointer; text-align: left;
}
.settings-face:hover { color: var(--ink); }
.map-settings.open .settings-face { color: var(--accent); }
.settings-read { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.settings-read b { font-size: 11.5px; font-weight: 650; white-space: nowrap; }
.settings-read i {
    font-style: normal; font-size: 10.5px; color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.settings-chev { width: 15px; height: 15px; flex: none; color: var(--muted); transition: transform 0.15s ease; }
.map-settings.open .settings-chev { transform: rotate(180deg); }

.map-settings-pop {
    position: absolute; inset: 0; z-index: 40;
    display: grid; place-items: center;
    padding: var(--m-gap);
    background: rgba(15, 23, 42, 0.18);
}
.map-settings-pop[hidden] { display: none; }
.map-settings-card {
    width: min(820px, 100%); max-height: min(86vh, 640px);
    display: flex; flex-direction: column; gap: 8px;
    overflow-y: auto; overscroll-behavior: contain;
    padding: 14px 16px 16px;
    border: 1px solid var(--line); border-radius: var(--m-radius);
    background: var(--surface);
    box-shadow: 0 24px 60px rgba(15, 23, 42, 0.26), 0 1px 2px rgba(15, 23, 42, 0.06);
    animation: settings-in 0.18s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes settings-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } }
@media (prefers-reduced-motion: reduce) { .map-settings-card { animation: none; } }
.settings-cols {
    display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr) minmax(0, 1.1fr);
    gap: 18px;
}
@media (max-width: 760px) { .settings-cols { grid-template-columns: minmax(0, 1fr); } }
.settings-col { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
.settings-head {
    margin: 0; padding-bottom: 7px; border-bottom: 1px solid var(--line);
    font-size: 12px; font-weight: 700; color: var(--ink);
}

.display-top {
    display: flex; align-items: center; gap: 8px;
    margin: -2px -4px 2px 0;
}
.display-title {
    flex: 1; min-width: 0;
    font-size: 10.5px; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.08em; color: var(--accent);
}
/* The panel is pinned to the bar, so it rides up with it when the film opens
   underneath. */


/* With the film open the strip rides above it, and both float clear of the
   edge. The canvas is not shortened for either: a card lifted off the bottom
   over a canvas that stops short of it leaves an empty band under the card
   with nothing in it, which is the cut-off look the frame was added to fix. */
.map-shell:has(.video-deck:not([hidden])) .map-dock { bottom: calc(var(--vd-height) + 2 * var(--m-gap)); }
.map-shell:has(.video-deck:not([hidden])) #govMap { inset: 0; }

/* ---------- how strongly the ground underneath is drawn ----------

   Yandex's names, its restaurants and its shops are painted into the same
   tile as the ground they stand on — the map is drawn on their server and
   arrives as pictures — so there is no switching the labels off and keeping
   the roads. What there is, is turning the whole picture down.

   It reaches only the ground pane, which holds the tiles and nothing of ours:
   every line, pin and badge this system draws lives in the panes above it and
   keeps its full strength. The faded tiles land on the canvas's own sheet
   rather than on nothing, so what the reader sees is a quieter map and not a
   transparent one. */
#govMap { background: var(--page); }
#govMap [class*="-ground-pane"] { opacity: var(--m-ground, 1); }

/* ------------------------------------------------- the map's own colouring
   Yandex's JS API v2 publishes no style sheet for its scheme: the map is
   drawn on their server and arrives as pictures, so the only place left to
   recolour it is where those pictures land — the ground pane, which holds
   the tiles and nothing of ours. Everything this system draws lives in the
   panes above it (`areas` for the lines, `node` for the points), so a filter
   here cannot reach a road colour, a sign icon or the panel: measured on a
   drag with the heaviest of them on, 16.7 ms median and 17.5 ms p95, which is
   the vsync floor — it costs nothing.

   The API's version number sits inside its own class names
   (`ymaps-2-1-79-ground-pane`) and moves whenever Yandex ships, so the pane
   is matched on the suffix and never on the whole name.

   Only the scheme is painted. A photograph recoloured is not a style, it is
   damage — an inverted satellite image reads as a broken map — so the styles
   stand down over satellite and hybrid, and the card says why. */
.map-shell[data-canvas="canvas"] #govMap [class*="-ground-pane"] {
    filter: grayscale(1) brightness(1.07) contrast(0.9);
}
.map-shell[data-canvas="soft"] #govMap [class*="-ground-pane"] {
    filter: saturate(0.42) brightness(1.06) contrast(0.94);
}
.map-shell[data-canvas="blue"] #govMap [class*="-ground-pane"] {
    filter: grayscale(1) brightness(1.02) contrast(0.92) sepia(0.45) hue-rotate(178deg) saturate(1.7);
}
.map-shell[data-canvas="sepia"] #govMap [class*="-ground-pane"] {
    filter: sepia(0.55) saturate(0.85) brightness(1.04) contrast(0.93);
}
.map-shell[data-canvas="dark"] #govMap [class*="-ground-pane"] {
    filter: invert(0.92) hue-rotate(180deg) saturate(0.28) brightness(1.18) contrast(0.76);
}

/* The shade beyond the border, thrown out of focus.

   The colour and the weight of that shade are the mask polygon's own — it is
   a map object, so it is right at every zoom and costs nothing to move. Blur
   is the one thing a polygon cannot do, so it is a pane of our own between
   the tiles and our drawing: `backdrop-filter` over the ground, clipped to
   everything *except* the country with an even-odd path. It exists only
   while the blur is above zero, so the default map builds nothing. */
.map-blur {
    position: absolute; inset: 0; z-index: 900;
    pointer-events: none;
    will-change: clip-path;
}

/* --------------------------------------------------- the style card ----- */
/* The face carries the answer rather than a word for it: the dot is drawn in
   the style the map is set to, so the bar reads without being opened. */
.style-dot {
    width: 17px; height: 17px; flex: none; border-radius: 50%;
    border: 1px solid var(--line);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);
}
.style-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.style-chip {
    display: flex; flex-direction: column; align-items: center; gap: 5px;
    padding: 7px 2px 6px;
    border: 1px solid var(--line); border-radius: 7px;
    background: var(--surface); color: var(--ink-2); cursor: pointer;
    font-size: 10px; font-weight: 600; line-height: 1.1;
    text-align: center;
}
.style-chip:hover { border-color: var(--accent); color: var(--ink); }
.style-chip[aria-checked="true"] {
    border-color: var(--accent); color: var(--accent);
    background: var(--accent-soft);
}
.style-chip > span { overflow: hidden; text-overflow: ellipsis; max-width: 100%; white-space: nowrap; }
.style-swatch {
    width: 26px; height: 26px; border-radius: 50%; flex: none;
    border: 1px solid rgba(15, 23, 42, 0.14);
    box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.45);
}
/* The previews are drawn, not sampled: a swatch showing one tile of one city
   says nothing about how the whole country will read. Each is the palette its
   filter lands on — land, water and the warm ground between them. */
.sw-standard { background: linear-gradient(135deg, #dcefd2, #bfdcf6 52%, #f7e6c2); }
.sw-canvas   { background: linear-gradient(135deg, #f4f5f6, #c9cdd3 52%, #e6e8eb); }
.sw-soft     { background: linear-gradient(135deg, #e6efe2, #d3e2ef 52%, #f0e7d9); }
.sw-blue     { background: linear-gradient(135deg, #e7eefb, #bcd0ee 55%, #8fa9d6); }
.sw-sepia    { background: linear-gradient(135deg, #f6ecd9, #e6d3b3 55%, #d3bb93); }
.sw-dark     { background: linear-gradient(135deg, #2b3340, #161b24 55%, #0d1119); }

.style-note {
    margin: 1px 0 0; font-size: 10px; line-height: 1.35; color: var(--muted);
}
.style-note[hidden] { display: none; }

/* A rule, because the two halves of this card answer for two different
   things: the first for Yandex's ground, the second for the shade this
   system lays over it. */
.style-outside {
    margin-top: 2px; padding-top: 9px;
    border-top: 1px solid var(--line);
}
.style-tints { display: flex; gap: 6px; }
.style-tint {
    width: 30px; height: 26px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--surface); cursor: pointer;
}
.style-tint:hover { border-color: var(--accent); }
.style-tint[aria-checked="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.tint-swatch {
    width: 16px; height: 16px; border-radius: 50%;
    border: 1px solid rgba(15, 23, 42, 0.18);
}
/* Half light, half dark: the one tint that has no colour of its own, because
   it is whichever of the two the panel's theme is wearing. */
.tn-auto  { background: linear-gradient(135deg, #f4f6f9 50%, #0b111e 50%); }
.tn-slate { background: #64748b; }
.tn-ink   { background: #0b111e; }
.tn-blue  { background: #1e3a8a; }
.tn-sand  { background: #a8a29e; }

.style-outside .display-row > span {
    display: flex; align-items: center; gap: 6px;
}
.style-outside .display-row > span b {
    margin-left: auto; font-weight: 700; color: var(--accent);
    font-variant-numeric: tabular-nums; text-transform: none; letter-spacing: 0;
}

/* =====================================================================
   Dashboard — the redrawn boshqaruv paneli
   =====================================================================
   Every colour here is a token. The design was drawn from this palette,
   so nothing needed inventing: #f4f6f9 is --page, #101f38 is --sidebar-bg,
   #2563c4 is --accent, and the three status hues are --ok/--warn/--crit.
   Taking them as tokens rather than as literals is what makes the screen
   work in dark mode, which the design file could not show.

   Radii follow this system's reduced scale (12 -> 8, 10 -> 7, 8 -> 6),
   and 99px stays 99px: a pill is a shape, not a radius.
   ===================================================================== */

.dsh-row { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 16px; }
.dsh-grow-1 { flex: 1 1 340px; min-width: 0; }
.dsh-grow-4 { flex: 4 1 340px; min-width: 0; }
.dsh-grow-5 { flex: 5 1 440px; min-width: 0; }
.dsh-grow-7 { flex: 7 1 560px; min-width: 0; }
.dsh-grow-8 { flex: 8 1 560px; min-width: 0; }

/* ---------- section heading ---------- */
.dsh-sec { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; padding: 4px 2px 0; margin: 18px 0 12px; }
.dsh-sec-no { font-size: 11px; font-weight: 700; letter-spacing: .1em; color: var(--accent); }
.dsh-sec-title { margin: 0; font-size: 20px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.dsh-sec-note { margin-left: auto; font-size: 12px; color: var(--muted); }

/* ---------- the segmented period control ---------- */
.dsh-seg { display: inline-flex; padding: 3px; gap: 2px; border: 1px solid var(--line); border-radius: 6px; background: var(--page); }
.dsh-seg-btn {
    height: 28px; padding: 0 12px; display: inline-flex; align-items: center;
    border-radius: 4px; font-size: 12.5px; font-weight: 600;
    color: var(--ink-2); text-decoration: none; white-space: nowrap;
}
.dsh-seg-btn:hover { background: var(--surface); text-decoration: none; }
.dsh-seg-btn.is-on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(16,31,56,.12); }

/* ---------- hero ---------- */
.dsh-hero {
    background: var(--sidebar-bg); color: #fff; border-radius: 8px;
    padding: 24px 26px; margin-bottom: 16px;
    display: flex; flex-wrap: wrap; gap: 26px;
}
.dsh-hero-main { flex: 1.2 1 360px; min-width: 0; display: flex; flex-direction: column; gap: 13px; }
.dsh-hero-kicker { font-size: 11px; font-weight: 700; letter-spacing: .1em; color: var(--sidebar-ink); text-transform: uppercase; }
.dsh-hero-figure { display: flex; align-items: baseline; gap: 10px; }
.dsh-hero-figure b { font-size: 60px; font-weight: 700; line-height: 1; letter-spacing: -.035em; font-variant-numeric: tabular-nums; }
.dsh-hero-figure span { font-size: 21px; font-weight: 600; color: var(--sidebar-ink); }
.dsh-hero-facts { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: 13px; color: var(--sidebar-ink); }
.dsh-hero-facts b { color: #fff; font-variant-numeric: tabular-nums; }

.dsh-classbar { display: flex; height: 10px; border-radius: 99px; overflow: hidden; background: rgba(255,255,255,.08); gap: 2px; }
/* The registry's gap, under the bar rather than in it: a smaller type, the
   neutral swatch the bar never uses, and the reason said in words. */
.dsh-unclassed {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px;
  margin: 8px 0 0; font-size: 12px; color: var(--muted);
}
.dsh-unclassed i { width: 9px; height: 9px; border-radius: 3px; background: var(--neutral-soft); flex: none; align-self: center; }
.dsh-unclassed b { color: var(--ink-2); font-weight: 650; }
.dsh-unclassed em { font-style: normal; opacity: .85; }
.dsh-classes { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 10px; }
.dsh-class { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dsh-class .k { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--sidebar-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dsh-class .k i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.dsh-class b { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dsh-class b span { font-size: 11.5px; font-weight: 500; color: var(--sidebar-ink); }

.dsh-hero-cards { flex: 2 1 500px; min-width: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; }
.dsh-hc {
    padding: 15px 17px; border-radius: 7px;
    background: rgba(255,255,255,.05); border: 1px solid rgba(255,255,255,.08);
    display: flex; flex-direction: column; gap: 6px; min-width: 0;
}
.dsh-hc.is-open { cursor: pointer; }
.dsh-hc.is-open:hover, .dsh-hc.is-open:focus-visible { background: rgba(255,255,255,.10); outline: none; }
.dsh-hc .lb { font-size: 12px; color: var(--sidebar-ink); }
.dsh-hc .v { font-size: 30px; font-weight: 700; line-height: 1.05; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.dsh-hc .v span { font-size: 15px; font-weight: 600; color: var(--sidebar-ink); }
.dsh-hc .d { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--sidebar-ink); flex-wrap: wrap; }
.dsh-hc .d i { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.dsh-hc .d.warn i { background: var(--warn); }
.dsh-hc .d.crit i { background: var(--crit); }
.dsh-hc .d b { color: #fff; font-variant-numeric: tabular-nums; }
.dsh-hc-bar { display: flex; align-items: center; gap: 8px; }
.dsh-hc-bar > span:first-child { flex: 1; height: 5px; border-radius: 99px; background: rgba(255,255,255,.12); overflow: hidden; }
.dsh-hc-bar > span:first-child span { display: block; height: 100%; background: var(--chart-1); border-radius: 99px; }
.dsh-hc-bar .t { font-size: 12px; color: var(--sidebar-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }

.dsh-ring {
    flex: .8 1 230px; min-width: 0; display: flex; align-items: center; gap: 16px;
    padding: 15px 17px; border-radius: 7px; text-decoration: none; color: #fff;
    background: rgba(127,176,240,.08); border: 1px solid rgba(127,176,240,.22);
}
.dsh-ring:hover { background: rgba(127,176,240,.15); text-decoration: none; }
.dsh-ring.is-off { opacity: .6; }
.dsh-ring-dial { position: relative; flex: none; width: 104px; height: 104px; }
.dsh-ring-dial svg { display: block; width: 104px; height: 104px; }
.dsh-ring-dial circle { fill: none; stroke-width: 11; }
.dsh-ring-dial circle.t { stroke: rgba(255,255,255,.1); }
.dsh-ring-dial circle.v { stroke: var(--chart-1); stroke-linecap: round; }
.dsh-ring-dial b { position: absolute; inset: 0; display: grid; place-items: center; font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dsh-ring-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.dsh-ring-text .k { font-size: 11px; font-weight: 700; letter-spacing: .08em; color: var(--chart-1); text-transform: uppercase; }
.dsh-ring-text b { font-size: 14.5px; font-weight: 650; line-height: 1.3; }
.dsh-ring-text .s { font-size: 12px; color: var(--sidebar-ink); }

/* ---------- cards ---------- */
.dsh-card { padding: 17px 19px; display: flex; flex-direction: column; gap: 13px; }
.dsh-head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px 20px; }
.dsh-title { display: flex; flex-direction: column; min-width: 0; }
.dsh-title h3 { margin: 0; font-size: 14.5px; font-weight: 650; color: var(--ink); }
.dsh-title span { font-size: 12px; color: var(--muted); }
.dsh-sub { margin-left: auto; font-size: 12px; color: var(--muted); }
.dsh-sub b { color: var(--ink); font-variant-numeric: tabular-nums; }
.dsh-stats { margin-left: auto; display: flex; flex-wrap: wrap; gap: 8px 20px; }
.dsh-stats div { display: flex; flex-direction: column; }
.dsh-stats span { font-size: 11px; color: var(--muted); }
.dsh-stats b { font-size: 19px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.dsh-stats b.accent { color: var(--accent); }
.dsh-stats b.ok { color: var(--ok-ink); }
.dsh-stats b.warn { color: var(--warn-ink); }

.dsh-chart { min-height: 230px; }
.dsh-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; font-size: 11.5px; color: var(--ink-2); }
.dsh-legend span { display: inline-flex; align-items: center; gap: 6px; }
.dsh-legend .src { margin-left: auto; color: var(--muted); }
.dsh-legend i { flex: none; }
.dsh-legend .l-line { width: 16px; height: 3px; border-radius: 2px; background: var(--chart-1); }
.dsh-legend .l-dash { width: 16px; height: 0; border-top: 2px dashed var(--muted); }
.dsh-legend .l-sw { width: 11px; height: 11px; border-radius: 3px; background: var(--accent); }

/* ---------- repair requests ---------- */
.dsh-ord-top { display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap; }
.dsh-ord-big { display: flex; flex-direction: column; }
.dsh-ord-big b { font-size: 36px; font-weight: 700; line-height: 1; letter-spacing: -.02em; color: var(--accent); font-variant-numeric: tabular-nums; }
.dsh-ord-big span { font-size: 12px; color: var(--muted); margin-top: 4px; }
.dsh-chips { margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.dsh-chips .chip { padding: 3px 9px; border-radius: 99px; font-size: 11.5px; font-weight: 700; }
.dsh-chips .chip b { font-variant-numeric: tabular-nums; }
.dsh-chips .chip.crit { background: var(--crit-soft); color: var(--crit-ink); }
.dsh-chips .chip.warn { background: var(--warn-soft); color: var(--warn-ink); }

.dsh-stack { display: flex; height: 12px; border-radius: 99px; overflow: hidden; gap: 2px; background: var(--neutral-soft); }
.dsh-rows { display: flex; flex-direction: column; }
.dsh-r { display: grid; grid-template-columns: 10px minmax(0, 1fr) minmax(0, 1.3fr) auto auto; align-items: center; gap: 10px; padding: 5px 0; font-size: 12.5px; }
.dsh-r + .dsh-r { border-top: 1px solid var(--neutral-soft); }
.dsh-r.is-open { cursor: pointer; }
.dsh-r.is-open:hover, .dsh-r.is-open:focus-visible { background: var(--page); outline: none; }
.dsh-r i { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.dsh-r .nm { color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dsh-r .tr { height: 6px; border-radius: 99px; background: var(--neutral-soft); overflow: hidden; }
.dsh-r .tr span { display: block; height: 100%; border-radius: 99px; background: var(--accent); }
.dsh-r b { font-variant-numeric: tabular-nums; text-align: right; color: var(--ink); }
.dsh-r .pc { width: 40px; text-align: right; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

.dsh-foot { margin-top: auto; display: flex; align-items: center; gap: 10px; padding: 9px 11px; border-radius: 5px; background: var(--page); font-size: 12px; color: var(--ink-2); }
.dsh-foot .tr { width: 88px; height: 6px; border-radius: 99px; background: var(--line); overflow: hidden; }
.dsh-foot .tr span { display: block; height: 100%; background: var(--accent); }
.dsh-foot b { font-size: 13px; color: var(--ink); font-variant-numeric: tabular-nums; }

/* ---------- cartogram ---------- */
.dsh-carto { display: grid; grid-template-columns: repeat(var(--carto-cols, 8), minmax(0, 1fr)); grid-auto-rows: 66px; gap: 6px; }
.dsh-tile {
    display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start;
    padding: 7px 8px; border-radius: 6px; text-decoration: none; min-width: 0;
    border: 1px solid var(--line);
    background: color-mix(in srgb, var(--accent) calc(var(--tile, .3) * 100%), var(--surface));
    color: var(--ink);
    transition: transform .12s ease, opacity .12s ease;
}
.dsh-tile:hover { transform: translateY(-2px); text-decoration: none; }
.dsh-tile.is-on { border: 2px solid var(--ink); }
.dsh-tile.is-dim { opacity: .5; }
.dsh-tile .c { font-size: 11px; font-weight: 700; letter-spacing: .04em; }
.dsh-tile b { font-size: 16px; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }

/* ---------- rating table ---------- */
.dsh-tablewrap { overflow-x: auto; }
.dsh-table { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 12.5px; }
.dsh-table th {
    padding: 0 8px 8px; text-align: left; border-bottom: 1px solid var(--line);
    font-size: 10.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.dsh-table td { padding: 6px 8px; border-bottom: 1px solid var(--neutral-soft); color: var(--ink); }
.dsh-table tr:hover td { background: var(--page); }
.dsh-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dsh-table .num.warn { color: var(--warn-ink); font-weight: 600; }
.dsh-table .c-rank { width: 26px; color: var(--muted); font-variant-numeric: tabular-nums; }
.dsh-table .c-name a { font-weight: 600; color: var(--ink); }
.dsh-table .c-km { display: flex; align-items: center; gap: 8px; }
.dsh-table .c-km .tr { flex: 1; min-width: 44px; height: 6px; border-radius: 99px; background: var(--neutral-soft); overflow: hidden; }
.dsh-table .c-km .tr span { display: block; height: 100%; background: var(--accent); border-radius: 99px; }
.dsh-table .c-km b { width: 46px; text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.dsh-mini { display: flex; height: 8px; border-radius: 99px; overflow: hidden; gap: 1px; min-width: 70px; }
.dsh-table .chip { display: inline-block; min-width: 34px; padding: 2px 8px; border-radius: 99px; text-align: center; font-weight: 700; font-size: 12px; font-variant-numeric: tabular-nums; }
.dsh-table .chip.ok { background: var(--ok-soft); color: var(--ok-ink); }
.dsh-table .chip.warn { background: var(--warn-soft); color: var(--warn-ink); }
.dsh-table .chip.crit { background: var(--crit-soft); color: var(--crit-ink); }
.dsh-table .chip.none { background: var(--neutral-soft); color: var(--neutral-ink); }

/* ---------- element condition donut ---------- */
.dsh-donut-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.dsh-donut { position: relative; flex: none; width: 128px; height: 128px; }
.dsh-donut svg { display: block; width: 128px; height: 128px; }
.dsh-donut circle { fill: none; stroke-width: 5; }
.dsh-donut circle.t { stroke: var(--neutral-soft); }
.dsh-donut-mid { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.dsh-donut-mid b { font-size: 21px; font-weight: 700; line-height: 1.1; color: var(--ink); font-variant-numeric: tabular-nums; }
.dsh-donut-mid span { font-size: 11px; color: var(--muted); }
.dsh-donut-keys { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.dsh-k { display: flex; align-items: center; gap: 8px; font-size: 12.5px; padding: 2px 0; }
.dsh-k.is-open { cursor: pointer; }
.dsh-k.is-open:hover, .dsh-k.is-open:focus-visible { background: var(--page); outline: none; }
.dsh-k i { width: 10px; height: 10px; border-radius: 3px; flex: none; }
.dsh-k .nm { flex: 1; color: var(--ink); }
.dsh-k b { font-size: 13px; color: var(--ink); font-variant-numeric: tabular-nums; }
.dsh-k .pc { width: 42px; text-align: right; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---------- pavement ---------- */
.dsh-bigbar { display: flex; height: 32px; border-radius: 5px; overflow: hidden; gap: 2px; }
.dsh-bigbar span { display: flex; align-items: center; justify-content: center; font-size: 11.5px; font-weight: 700; color: #fff; white-space: nowrap; overflow: hidden; }
.dsh-keygrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 6px 14px; }
.dsh-k2 { display: flex; align-items: center; gap: 7px; font-size: 12px; min-width: 0; }
.dsh-k2 i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.dsh-k2 .nm { flex: 1; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dsh-k2 b { font-variant-numeric: tabular-nums; color: var(--ink); }
.dsh-subsec { display: flex; flex-direction: column; gap: 7px; padding-top: 11px; border-top: 1px solid var(--neutral-soft); }
.dsh-subhead { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }

/* ---------- hotspots ---------- */
.dsh-hot { display: flex; flex-direction: column; }
.dsh-hotrow { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 7px 0; text-decoration: none; color: var(--ink); }
.dsh-hotrow + .dsh-hotrow { border-top: 1px solid var(--neutral-soft); }
.dsh-hotrow:hover { text-decoration: none; background: var(--page); }
.dsh-hotrow .rk { width: 22px; height: 22px; border-radius: 5px; display: grid; place-items: center; font-size: 11px; font-weight: 700; background: var(--neutral-soft); color: var(--neutral-ink); }
.dsh-hotrow .rk.top { background: var(--crit-soft); color: var(--crit-ink); }
.dsh-hotrow .bd { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.dsh-hotrow .nm { font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dsh-hotrow .tr { display: flex; height: 5px; border-radius: 99px; overflow: hidden; background: var(--neutral-soft); }
.dsh-hotrow .vl { display: flex; flex-direction: column; align-items: flex-end; }
.dsh-hotrow .vl b { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.dsh-hotrow .vl span { font-size: 10.5px; color: var(--muted); white-space: nowrap; }

/* ---------- operations strip ---------- */
.dsh-ops { display: flex; flex-wrap: wrap; padding: 0; }
.dsh-ops-group { flex: 1 1 500px; display: flex; flex-wrap: wrap; align-items: stretch; }
.dsh-ops-label { flex: none; width: 142px; padding: 15px 18px; display: flex; flex-direction: column; justify-content: center; border-right: 1px solid var(--neutral-soft); }
.dsh-ops-label span { font-size: 10.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.dsh-ops-label b { font-size: 14px; color: var(--ink); }
.dsh-ops-cell { flex: 1 1 104px; padding: 13px 16px; display: flex; flex-direction: column; gap: 2px; border-right: 1px solid var(--neutral-soft); }
.dsh-ops-cell span { font-size: 11.5px; color: var(--muted); }
.dsh-ops-cell b { font-size: 21px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.dsh-ops-cell b.accent { color: var(--accent); }
.dsh-ops-cell b.ok { color: var(--ok-ink); }
.dsh-ops-cell b.warn { color: var(--warn-ink); }
.dsh-ops-cell b.crit { color: var(--crit-ink); }

@media (max-width: 720px) {
    .dsh-hero { padding: 18px; gap: 18px; }
    .dsh-hero-figure b { font-size: 44px; }
    .dsh-sec-note { margin-left: 0; }
    .dsh-stats { margin-left: 0; }
    .dsh-ops-label { width: 100%; border-right: 0; }
}

/* A number that counts up is a flourish; one that cannot be read is not.
   The animation is skipped for a reader who asked for less motion. */
@media (prefers-reduced-motion: reduce) {
    .dsh-tile { transition: none; }
}

.dsh-hero-figure.is-open, .dsh-ops-group.is-open { cursor: pointer; }
.dsh-hero-figure.is-open:hover b, .dsh-hero-figure.is-open:focus-visible b { text-decoration: underline; text-underline-offset: 6px; }
.dsh-hero-figure.is-open:focus-visible, .dsh-ops-group.is-open:focus-visible { outline: 2px solid var(--chart-1); outline-offset: 3px; }
.dsh-ops-group.is-open:hover { background: var(--page); }

/* A screen that is a workspace rather than a document: no measure, no centring.
   `max-width: none` and not `100vw` — the main sits in a row beside the
   sidebar, so its own 100% already is the whole of the room left over, while
   `100vw` counts the sidebar and the scrollbar too and pushes the right-hand
   edge off the window. The side padding stays: full width is not "touching
   the glass". */
/* A full-bleed page wears this **instead of** `.content`, not beside it: the
   container is a 1240px `max-width` in that rule, and a page that has to run
   edge to edge cannot inherit it and then argue with it. So there is no px
   measurement anywhere on this class — the width is the column it is in, which
   is the viewport less the 248px the sidebar stands in. The sidebar is in the
   layout flow, so `100vw` here would put those 248px past the right edge
   behind a horizontal scrollbar rather than on screen. Two rules follow for
   anything added here: the padding is the page's own gutter and never a width,
   and any child that needs the full column says `width: 100%`. */
.content-full {
  width: 100%;
  padding: 20px 20px 48px;
  margin: 0;
}
@media (min-width: 1500px) { .content-full { padding-left: 28px; padding-right: 28px; } }

/* =====================================================================
   Tom Select — a face that does not move when it is used
   =====================================================================
   Two mechanisms in the widget's own stylesheet, both measured against
   tom-select@2.3.1's dist CSS rather than guessed at:

   1. `.ts-control>input { min-width:7rem!important; flex:1 1 auto }` — the
      search input appears on focus, and `.ts-control` is `flex-wrap:wrap`.
      In a filter bar whose selects are 150px wide, seven rems of input
      cannot sit beside the chosen value, so it wraps to a second line and
      the control grows taller the moment it is clicked. `min-width:0` is
      the whole fix, and it needs `!important` to answer theirs.

   2. `.ts-control{background:#fff}`, `.ts-wrapper.single.input-active
      .ts-control{background:#fff}` and `.full .ts-control{background-color:
      #fff}` — three separate rules painting the control white, one of them
      for the ordinary state of a select that simply has a value. In dark
      mode that is a white box under near-white text.

   Every override is written at `.ts-wrapper…` or narrower, because that is
   the specificity the widget's own selectors carry.
   ===================================================================== */

/* One line, always. The chosen value is ellipsised rather than allowed to
   push the control into a second row. */
.ts-wrapper.single .ts-control { flex-wrap: nowrap; align-items: center; }
.ts-wrapper.single .ts-control > input { min-width: 0 !important; flex: 1 1 auto; }
.ts-wrapper.single .ts-control > .item {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

/* The control: the same box as a plain input, in every state the widget
   would otherwise paint white — including `.full`, which is nothing more
   exotic than "this select has a value". */
.ts-wrapper.single .ts-control,
.ts-wrapper.single.full .ts-control,
.ts-wrapper.single.focus .ts-control,
.ts-wrapper.single.input-active .ts-control,
.ts-wrapper.single.dropdown-active .ts-control {
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: 6px;
  font-size: 13.5px; padding: 8px 34px 8px 11px; min-height: 0; box-shadow: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.ts-wrapper.single .ts-control:hover { border-color: var(--muted); }
.ts-wrapper.single.focus .ts-control,
.ts-wrapper.single.dropdown-active .ts-control {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.ts-wrapper.single.disabled .ts-control { background: var(--page); opacity: 1; color: var(--muted); }
.ts-control input { color: var(--ink); font-size: 13.5px; }
.ts-control input::placeholder { color: var(--muted); opacity: 1; }

/* The caret: a drawn chevron in the text colour that turns over while the
   list is open, instead of the widget's hard-coded grey triangle. */
.ts-wrapper.single .ts-control::after,
.ts-wrapper.single.dropdown-active .ts-control::after {
  content: ""; position: absolute; top: 50%; right: 12px; width: 12px; height: 12px;
  margin-top: -6px; border: 0; background: currentColor; opacity: .5;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5 6 8l3.5-3.5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px no-repeat;
  transition: transform .15s ease, opacity .15s ease;
}
.ts-wrapper.single.dropdown-active .ts-control::after { transform: rotate(180deg); opacity: .8; color: var(--accent); }

/* The list: a floating card a few pixels below the control, rows inset with
   their own rounded highlight. Every colour is a token, so the list follows
   the theme — the widget's `.active` (#f5fafd) was the white row in dark mode. */
.ts-dropdown {
  margin-top: 6px; padding: 4px; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line-strong); border-radius: 8px;
  box-shadow: 0 10px 28px rgba(16,31,56,.14), 0 2px 6px rgba(16,31,56,.08);
  font-size: 13.5px; overflow: hidden;
  animation: ts-drop-in .12s ease-out;
}
:root[data-theme="dark"] .ts-dropdown { box-shadow: 0 12px 32px rgba(0,0,0,.5), 0 2px 6px rgba(0,0,0,.35); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ts-dropdown { box-shadow: 0 12px 32px rgba(0,0,0,.5), 0 2px 6px rgba(0,0,0,.35); }
}
@keyframes ts-drop-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .ts-dropdown { animation: none; } }
.ts-dropdown .ts-dropdown-content { max-height: 280px; }
.ts-dropdown .option,
.ts-dropdown .optgroup-header,
.ts-dropdown .no-results,
.ts-dropdown .create { padding: 8px 30px 8px 10px; background: transparent; color: var(--ink); }
.ts-dropdown .option { position: relative; border-radius: 5px; }
.ts-dropdown .option + .option { margin-top: 1px; }
.ts-dropdown .option:hover,
.ts-dropdown .active { background: var(--accent-soft); color: var(--ink); }
/* The chosen row says so — accent ink and a tick — so an opened list shows
   where it stands without the reader comparing it against the control. */
.ts-dropdown .option.selected { color: var(--accent); font-weight: 600; }
.ts-dropdown .option.selected::after {
  content: ""; position: absolute; right: 10px; top: 50%; width: 12px; height: 12px; margin-top: -6px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='m2.5 6.2 2.3 2.3 4.7-5' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='m2.5 6.2 2.3 2.3 4.7-5' fill='none' stroke='%23000' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 12px no-repeat;
}
/* The empty choice ("—") is a way back, not a value: quieter than the rest. */
.ts-dropdown .option[data-value=""] { color: var(--muted); }
.ts-dropdown [data-selectable] .highlight {
  background: color-mix(in srgb, var(--accent) 28%, transparent); color: inherit; border-radius: 2px;
}
.ts-dropdown .optgroup-header { color: var(--muted); font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.ts-dropdown .no-results { color: var(--muted); }
/* `data-collapsible-groups` (panel-ui.js): a heading is a button that opens
   its rows, with a chevron that turns and the row count beside it. */
.ts-dropdown .optgroup.is-collapsible > .optgroup-header {
  display: flex; align-items: center; gap: 8px; cursor: pointer; border-radius: 5px; color: var(--ink);
}
.ts-dropdown .optgroup.is-collapsible > .optgroup-header:hover { background: var(--accent-soft); }
.ts-dropdown .optgroup.is-collapsible > .optgroup-header::before {
  content: ""; width: 7px; height: 7px; flex: none; border: solid currentColor; border-width: 0 1.6px 1.6px 0;
  transform: rotate(45deg); margin: -3px 2px 0 2px; transition: transform .15s;
}
.ts-dropdown .optgroup.is-collapsed > .optgroup-header::before { transform: rotate(-45deg); margin-top: 0; }
.ts-dropdown .optgroup-header .og-count { margin-left: auto; color: var(--muted); font-weight: 600; letter-spacing: 0; }
.ts-dropdown .optgroup.is-collapsed > .option { display: none; }
.ts-dropdown .spinner::after { border-color: var(--line-strong) transparent var(--line-strong) transparent; }

/* The filter bar's own selects: one height with the buttons beside them, so
   the row lines up whether a control is a select, an input or a link. */
.dash-bar .field { min-width: 168px; }
.dash-bar .ts-wrapper { width: 100%; }
.dash-bar .ts-wrapper.single .ts-control,
.dash-bar .field input {
  height: 36px; padding: 0 10px; display: flex; align-items: center;
  border: 1px solid var(--line-strong); border-radius: 6px;
  background: var(--surface); color: var(--ink); font-size: 13px;
}
.dash-bar .ts-wrapper.single .ts-control { padding-right: 26px; }
.dash-bar .field input { background: var(--surface); }
.dash-bar .field span { font-size: 11px; font-weight: 600; color: var(--muted); margin-bottom: 5px; }
.dash-bar .ts-wrapper.focus .ts-control,
.dash-bar .field input:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }

/* ---------- survey: the year trend ----------
   A column per survey year, tall in proportion to how much of that year's
   readings fell outside the norm. Bars and not a line: the years are not
   evenly spaced — a road is re-surveyed when somebody gets to it — and a line
   drawn across them implies a rate of change that the gaps do not support. */
.dsh-trend { display: flex; align-items: flex-end; gap: 6px; min-height: 96px; }
.dsh-trend-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; }
.dsh-trend-col .bar { width: 100%; height: 64px; display: flex; align-items: flex-end; background: var(--neutral-soft); border-radius: 4px; overflow: hidden; }
.dsh-trend-col .bar span { width: 100%; background: var(--warn); border-radius: 4px 4px 0 0; }
.dsh-trend-col .v { font-size: 10.5px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.dsh-trend-col .y { font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* =====================================================================
   Road passport
   =====================================================================
   The same palette as everything else, so dark mode comes free. Two things
   here are not decoration:

   - An empty field is drawn, not hidden. A good half of what a passport is
     supposed to record has never been entered for most roads, and a page
     that quietly drops those rows reports a finished document. They are
     dimmed and counted instead, and the rail turns them into the list of
     what to go and fill in.
   - A value the external survey measured carries a mark. Our registry is
     what the passport legally *is*; the survey is another agency's reading
     of the same road, and a reader correcting a figure needs to know which
     of the two they are looking at.
   ===================================================================== */

.rp-id { background: var(--surface); border: 1px solid var(--line); border-radius: 8px; box-shadow: var(--shadow); padding: 20px 22px; display: flex; flex-direction: column; gap: 18px; margin-bottom: 14px; }
.rp-id-head { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 20px; }
.rp-badge { flex: none; width: 82px; height: 82px; border-radius: 8px; background: var(--sidebar-bg); color: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; position: relative; overflow: hidden; }
.rp-badge::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 5px; background: var(--accent); }
.rp-badge.tone-crit::before { background: var(--crit); }
.rp-badge.tone-ok::before { background: var(--ok); }
.rp-badge.tone-muted::before { background: var(--muted); }
.rp-badge .k { font-size: 9.5px; font-weight: 700; letter-spacing: .12em; color: var(--sidebar-ink); }
.rp-badge b { font-size: 21px; font-weight: 700; letter-spacing: -.01em; line-height: 1.1; }
.rp-id-main { flex: 1 1 400px; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.rp-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.rp-chips .chip { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 10px; border-radius: 99px; font-size: 11.5px; font-weight: 700; background: var(--neutral-soft); color: var(--neutral-ink); }
.rp-chips .chip i { width: 7px; height: 7px; border-radius: 2px; background: currentColor; flex: none; }
.rp-chips .chip.tone-crit { background: var(--crit-soft); color: var(--crit-ink); }
.rp-chips .chip.tone-accent { background: var(--accent-soft); color: var(--accent); }
.rp-chips .chip.tone-ok, .rp-chips .chip.ok { background: var(--ok-soft); color: var(--ok-ink); }
.rp-chips .chip.warn { background: var(--warn-soft); color: var(--warn-ink); }
.rp-chips .chip.outline { background: transparent; border: 1px solid var(--line-strong); color: var(--ink-2); }
.rp-name { margin: 0; font-size: 25px; font-weight: 700; letter-spacing: -.02em; line-height: 1.2; color: var(--ink); }
.rp-meta { display: flex; flex-wrap: wrap; gap: 4px 18px; font-size: 12.5px; color: var(--muted); }
.rp-meta b { color: var(--ink); font-weight: 600; }

.rp-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; }
.rp-kpi { display: flex; flex-direction: column; gap: 2px; padding: 11px 13px; border: 1px solid var(--line); border-radius: 7px; background: var(--page); min-width: 0; }
.rp-kpi .lb { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rp-kpi b { font-size: 19px; font-weight: 700; line-height: 1.2; color: var(--ink); font-variant-numeric: tabular-nums; }
.rp-kpi b span { font-size: 12px; font-weight: 500; color: var(--muted); }

/* The section nav sticks under the topbar. `top` is 0 because the panel's
   own header is not sticky — a second sticky element above it would leave
   this one floating over a gap. */
.rp-nav { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 14px; padding: 0 14px; margin-bottom: 14px; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; box-shadow: 0 2px 8px rgba(16,31,56,.04); }
.rp-nav-road { flex: none; display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--ink-2); white-space: nowrap; }
.rp-nav-road b { padding: 2px 7px; border-radius: 4px; background: var(--sidebar-bg); color: #fff; font-size: 11.5px; }
.rp-nav-sep { flex: none; width: 1px; height: 20px; background: var(--line); }
.rp-nav-links { display: flex; gap: 2px; overflow-x: auto; min-width: 0; scrollbar-width: none; }
.rp-nav-links::-webkit-scrollbar { display: none; }
.rp-nav-links a { flex: none; height: 44px; display: inline-flex; align-items: center; padding: 0 11px; font-size: 13px; font-weight: 600; color: var(--ink-2); text-decoration: none; white-space: nowrap; border-bottom: 2px solid transparent; }
.rp-nav-links a:hover { color: var(--accent); text-decoration: none; border-bottom-color: var(--accent); }

/* Three panes, not one column. The change history was a card in a 320px rail
   and the element inventory ran the length of the page below everything else
   — the two things on the passport that are lists rather than a document, and
   neither fits where a document puts its margin notes. */
.rp-tabs {
  display: flex; gap: 4px; margin: 0 0 14px;
  border-bottom: 1px solid var(--line);
}
.rp-tabs button {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 14px; margin-bottom: -1px;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--muted);
  background: none; border: 0; border-bottom: 2px solid transparent;
  cursor: pointer; appearance: none; -webkit-appearance: none;
}
.rp-tabs button:hover { color: var(--ink-2); }
.rp-tabs button.is-on { color: var(--accent); border-bottom-color: var(--accent); }
.rp-tabs button span {
  font-size: 11px; font-weight: 650; color: var(--muted);
  background: var(--neutral-soft); border-radius: 99px; padding: 1px 7px;
}
.rp-tabs button.is-on span { background: var(--accent-soft); color: var(--accent); }
.rp-pane { display: flex; flex-direction: column; gap: 14px; }
/* On the attribute, not on one class. `hidden` is a UA rule of
   `display: none`, and *any* author `display` beats it — `.rp-body` is
   `display: flex`, so the document's own pane stayed on screen however often
   it was hidden, and pressing a tab looked like it did nothing at all. Every
   pane is matched here whatever else it is styled as. */
[data-rp-pane][hidden] { display: none; }

.rp-body { display: flex; flex-wrap: wrap; gap: 14px; align-items: flex-start; }
.rp-main { flex: 999 1 720px; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.rp-rail { flex: 1 1 310px; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.rp-card { scroll-margin-top: 62px; }
.rp-pad { padding: 16px 18px; display: flex; flex-direction: column; gap: 12px; }

.rp-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; padding: 14px 18px; border-bottom: 1px solid var(--neutral-soft); }
.rp-icon { flex: none; width: 38px; height: 38px; border-radius: 9px; background: var(--sidebar-bg); color: #fff; display: grid; place-items: center; }
.rp-icon svg { width: 19px; height: 19px; }
.rp-head-t { display: flex; flex-direction: column; min-width: 0; }
.rp-head-t h3 { margin: 0; font-size: 15px; font-weight: 650; color: var(--ink); }
.rp-head-t span { font-size: 12px; color: var(--muted); }
.rp-fill { margin-left: auto; display: flex; align-items: center; gap: 9px; }
.rp-fill .tr { width: 68px; height: 5px; border-radius: 99px; background: var(--neutral-soft); overflow: hidden; }
.rp-fill .tr span { display: block; height: 100%; border-radius: 99px; }
.rp-fill .t { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-fill .t b { color: var(--ink); }

.rp-fields { padding: 16px 20px 18px; display: grid; grid-template-columns: repeat(auto-fill, minmax(236px, 1fr)); gap: 8px; }
.rp-field { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 9px; background: var(--surface); min-width: 0; }
/* Every row of the document carries a mark, and it is drawn the way the
   design draws it: a tile to the left of the whole label-and-value stack
   rather than a glyph inline with the label. 36px square, 8px radius, a 19px
   outline inside, and it takes its colour from the state of the field —
   accent on a filled one, neutral on an empty one — not from the pointer. */
.rp-ic { flex: none; }
.rp-kpi .lb { display: flex; align-items: center; gap: 5px; }
.rp-kpi .lb .rp-ic { color: var(--muted); opacity: .8; }
.rp-field-ic {
  flex: none; width: 36px; height: 36px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
}
.rp-field-t { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.rp-field .lb { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted); line-height: 1.35; }
.rp-field .lb .tx { min-width: 0; }
.rp-field.is-empty .rp-field-ic { background: var(--neutral-soft); color: var(--muted); }
button.rp-field:hover .rp-field-ic { background: var(--accent); color: var(--accent-ink); }
.rp-field b { font-size: 14px; line-height: 1.35; color: var(--ink); font-weight: 600; overflow-wrap: break-word; word-break: normal; }
.rp-field .sub { font-size: 11.5px; color: var(--ink-2); line-height: 1.4; }
/* Drawn, not hidden — see the note at the top of this block. */
.rp-field.is-empty { border: 1px dashed var(--line-strong); background: var(--page); }
.rp-field.is-empty b { color: var(--warn-ink); font-weight: 500; }
.rp-src { font-style: normal; color: var(--accent); font-size: 10px; cursor: help; }

/* A field that can be filled in is a button, so it has to be talked back down
   to looking like the cell beside it — the browser's own button styling is a
   centred, bordered, system-font box. What is kept is the pointer and the
   hover, because a cell that answers a press has to look like one. */
/* Every empty cell is a button — it opens the input that fills it, or the
   answer for where the figure is kept when this is not where it is kept —
   so every one of them is talked back down out of the browser's own button
   styling and carries the same `+` in the same corner. A gap that looked
   different from the gap beside it would read as a gap of a different kind. */
button.rp-field {
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  transition: border-color .12s, background .12s;
}
.rp-field { position: relative; }
.rp-field.is-empty::after {
  content: '+'; position: absolute; top: 7px; right: 10px;
  font-size: 13px; font-weight: 700; line-height: 1; color: var(--muted);
}
button.rp-field:hover { border-color: var(--accent); background: var(--accent-soft); }
button.rp-field:hover b,
button.rp-field:hover::after { color: var(--accent); }

.rp-diagram { padding: 16px 18px 12px; display: grid; grid-template-columns: 130px minmax(0, 1fr); column-gap: 14px; row-gap: 6px; }
.rp-track-name { height: 28px; display: flex; align-items: center; font-size: 12px; font-weight: 600; color: var(--ink-2); }
.rp-track { position: relative; height: 28px; border-radius: 5px; background: var(--page); overflow: hidden; }
.rp-seg { position: absolute; top: 0; bottom: 0; display: flex; align-items: center; padding: 0 8px; font-size: 11.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; box-shadow: inset -2px 0 0 var(--surface); color: var(--ink); }
.rp-seg.t-cat-1, .rp-seg.t-lay-1 { background: var(--accent-soft); }
.rp-seg.t-cat-2, .rp-seg.t-lay-2 { background: color-mix(in srgb, var(--accent) 30%, var(--surface)); }
.rp-seg.t-cat-3, .rp-seg.t-lay-3 { background: color-mix(in srgb, var(--accent) 50%, var(--surface)); color: #fff; }
.rp-seg.t-cat-4, .rp-seg.t-lay-4 { background: color-mix(in srgb, var(--accent) 70%, var(--surface)); color: #fff; }
.rp-seg.t-cat-5, .rp-seg.t-lay-5 { background: var(--accent); color: #fff; }
.rp-axis { position: relative; height: 16px; margin-top: 4px; }
.rp-axis span { position: absolute; transform: translateX(-50%); font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.rp-axis span:first-child { transform: none; }
.rp-source { margin: 0; padding: 0 18px 14px; font-size: 11.5px; color: var(--muted); }
.rp-pad .rp-source { padding: 0; }

.rp-rail-h { margin: 0; font-size: 14.5px; font-weight: 650; color: var(--ink); display: flex; align-items: center; gap: 7px; }
.rp-rail-h .rp-ic { color: var(--muted); }
/* The four registers restored onto the passport — the per-kilometre rows, the
   condition table, the element inventory and the line itself. They are tables
   inside a passport card rather than the standalone `.card mt-14` blocks they
   used to be, so the heading above each one is the table's own strip.

   They were laid two abreast for a while, to bring the page down by half.
   That was wrong and is reverted: the registers are five and six columns of
   headings over one or two digits, and half a page cannot hold them — the
   headings ran into each other, and pinning the widths only moved the
   collision rather than removing it. A long page is the honest shape for
   this much data. */
.rp-tbl { display: flex; flex-direction: column; gap: 8px; }
.rp-tbl + .rp-tbl { margin-top: 6px; padding-top: 14px; border-top: 1px solid var(--line); }
.rp-tbl .tbl-wrap { margin: 0; }
.rp-tbl-h {
  display: flex; align-items: center; gap: 9px;
  font-size: 12.5px; font-weight: 650; color: var(--ink-2);
}
/* The category's own artwork, framed the way every other mark on the page is
   framed — 28px rather than 36 because this heads a table rather than a field,
   and it keeps the element list in the same rhythm as the document above it. */
.rp-tbl-h .el-group-icon {
  flex: none; box-sizing: border-box; width: 28px; height: 28px; padding: 4px;
  border-radius: 7px; background: var(--neutral-soft); object-fit: contain;
}
.rp-tbl-h b {
  margin-left: auto; font-weight: 650; font-size: 11.5px; color: var(--muted);
  background: var(--soft); border-radius: 99px; padding: 1px 8px;
}
.rp-tbl .tbl-wrap { margin: 0; }
/* The `.card` chrome belongs to the section around it, so the partial's own
   cards are flattened rather than being redrawn inside one. */
#rp-condition .card { background: none; border: 0; box-shadow: none; margin: 0; }
#rp-condition .card + .card { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
#rp-condition .card-h { padding: 0 0 6px; }
#rp-condition .card-h h3 { font-size: 12.5px; color: var(--ink-2); }
#rp-condition .hint { margin: 0 0 8px; }
/* ------------------------------------------- what changed, and which way */
/* The colour is the direction: what the road no longer says is struck out in
   the critical ink, what it says now is in the good one. The sign says which
   of the three kinds it is without the reader having to compare the two
   halves — a column filled for the first time and a column cleared are
   different events and used to be drawn identically. */
.rp-hist td { vertical-align: top; }
.rp-chg { display: flex; align-items: baseline; flex-wrap: wrap; gap: 5px; padding: 2px 0; font-size: 12.5px; line-height: 1.45; }
.rp-chg .sg {
  flex: none; width: 15px; height: 15px; border-radius: 4px;
  display: inline-grid; place-items: center; align-self: center;
  font-style: normal; font-size: 11px; font-weight: 700; line-height: 1;
}
.rp-chg b { font-weight: 650; color: var(--ink-2); }
.rp-chg .was { color: var(--crit-ink); text-decoration: line-through; text-decoration-thickness: 1px; }
.rp-chg .now { color: var(--ok-ink); font-weight: 600; }
.rp-chg .ar { color: var(--muted); }
.rp-chg-added .sg { background: var(--ok-soft); color: var(--ok-ink); }
.rp-chg-removed .sg { background: var(--crit-soft); color: var(--crit-ink); }
.rp-chg-changed .sg { background: var(--accent-soft); color: var(--accent); }
/* A cleared column has no "now" to print, so the struck-out value is the
   whole of the row and is not also greyed — it is the fact. */
.rp-chg-removed .was { text-decoration: none; }

.rp-map { height: 340px; border-radius: 8px; overflow: hidden; background: var(--soft); }

.rp-rail-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.rp-rail-head .sub { margin-left: auto; font-size: 12px; color: var(--muted); }

.rp-ring-row { display: flex; align-items: center; gap: 15px; }
.rp-ring { position: relative; flex: none; width: 82px; height: 82px; }
.rp-ring svg { display: block; width: 82px; height: 82px; }
.rp-ring circle { fill: none; stroke-width: 9; }
.rp-ring circle.t { stroke: var(--neutral-soft); }
.rp-ring circle.v { stroke: var(--accent); stroke-linecap: round; }
.rp-ring b { position: absolute; inset: 0; display: grid; place-items: center; font-size: 17px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.rp-ring-t { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.rp-ring-t b { font-size: 15px; font-weight: 650; color: var(--ink); font-variant-numeric: tabular-nums; }
.rp-ring-t span { font-size: 12px; color: var(--muted); }
.rp-ring-t span.warn { color: var(--warn-ink); font-weight: 600; }

/* The gap list is the task list, so it carries every gap rather than the
   first ten and scrolls instead of growing the rail to the height of the
   document. `.h` stays put while the rows move under it. */
.rp-missing { display: flex; flex-direction: column; gap: 3px; padding: 11px; border-radius: 6px; background: var(--warn-soft); max-height: 340px; overflow-y: auto; }
.rp-missing[hidden] { display: none; }
.rp-missing .h { position: sticky; top: -11px; margin: -11px -11px 2px; padding: 11px 11px 5px; background: var(--warn-soft); font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--warn-ink); }
.rp-missing a .rp-ic, .rp-missing button .rp-ic { color: var(--warn-ink); opacity: .8; }
.rp-missing a, .rp-missing button {
  display: flex; align-items: baseline; gap: 8px; width: 100%;
  padding: 3px 0; font: inherit; font-size: 12.5px; font-weight: 600;
  color: var(--ink); text-decoration: none; text-align: left;
  background: none; border: 0; appearance: none; -webkit-appearance: none;
}
.rp-missing button { cursor: pointer; }
.rp-missing a:hover, .rp-missing button:hover { color: var(--accent); text-decoration: none; }
.rp-missing a em, .rp-missing button em { margin-left: auto; font-style: normal; font-size: 11px; font-weight: 500; color: var(--warn-ink); white-space: nowrap; }

/* ---------------------------------------- the one box a gap is filled in */
.rp-modal { display: flex; flex-direction: column; gap: 0; }
.rp-modal-hint { margin: 0 0 12px; font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.rp-modal-hint[hidden] { display: none; }
.rp-modal-body { display: flex; flex-direction: column; gap: 9px; margin-bottom: 16px; }
.rp-modal-row { display: flex; flex-direction: column; gap: 3px; }
.rp-modal-row > span { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.rp-modal-input {
  width: 100%; padding: 9px 11px; font: inherit; font-size: 14px;
  color: var(--ink); background: var(--page);
  border: 1px solid var(--line-strong); border-radius: 6px;
}
.rp-modal-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.rp-modal-loading { margin: 0; padding: 8px 0 16px; font-size: 13px; color: var(--muted); }
/* Where the figure is actually kept, when this page is not where it is kept.
   A link and not a second submit: it leaves the passport. */
.rp-modal-go {
  display: inline-flex; align-self: flex-start; margin: 0 0 16px;
  font-size: 12.5px; font-weight: 600; color: var(--accent); text-decoration: none;
}
.rp-modal-go[hidden] { display: none; }
.rp-modal-save[hidden] { display: none; }
/* A gap this registry does not own still opens — it just opens an answer
   rather than a box, and it should not look like the rows that take one. */
.rp-missing button.is-readonly { color: var(--ink-2); }
.rp-modal-error { margin: 0 0 14px; padding: 9px 11px; border-radius: 6px; font-size: 12.5px; line-height: 1.5; background: var(--crit-soft); color: var(--crit-ink); }
.rp-modal-error[hidden] { display: none; }

.rp-inds { display: flex; flex-direction: column; }
.rp-ind { display: flex; align-items: center; gap: 9px; padding: 9px 0 4px; }
.rp-ind > .rp-ic { color: var(--muted); }
.rp-ind .nm { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 12.5px; font-weight: 600; color: var(--ink); }
.rp-ind .nm span { font-size: 11px; font-weight: 400; color: var(--muted); }
.rp-ind b { font-size: 16px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.rp-ind b.muted { color: var(--muted); }
.rp-ind .chip { flex: none; min-width: 58px; text-align: center; padding: 2px 8px; border-radius: 99px; font-size: 11px; font-weight: 700; }
.rp-ind .chip.ok { background: var(--ok-soft); color: var(--ok-ink); }
.rp-ind .chip.warn { background: var(--warn-soft); color: var(--warn-ink); }
.rp-ind .chip.crit { background: var(--crit-soft); color: var(--crit-ink); }
.rp-ind .chip.none { background: var(--neutral-soft); color: var(--neutral-ink); }
.rp-ind-bar { display: flex; height: 5px; border-radius: 99px; overflow: hidden; background: var(--neutral-soft); margin-bottom: 6px; }
.rp-ind-bar .t-ok { background: var(--ok); }
.rp-ind-bar .t-warn { background: var(--warn); }
.rp-ind-bar .t-crit { background: var(--crit); }
.rp-more { font-size: 12.5px; font-weight: 600; }

.rp-layers { display: flex; flex-direction: column; gap: 2px; border-radius: 5px; overflow: hidden; }
.rp-layer { display: flex; align-items: center; gap: 10px; padding: 0 11px; font-size: 12px; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.35); }
.rp-layer span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.rp-layer b { font-variant-numeric: tabular-nums; }

.rp-links { display: flex; flex-direction: column; }
.rp-links a { display: flex; align-items: center; gap: 9px; padding: 9px 6px; margin: 0 -6px; border-radius: 6px; color: var(--ink); text-decoration: none; }
.rp-links a > .rp-ic {
  flex: none; box-sizing: content-box; width: 17px; height: 17px; padding: 7px;
  border-radius: 8px; background: var(--accent-soft); color: var(--accent);
}
.rp-links a:hover > .rp-ic { background: var(--accent); color: var(--accent-ink); }
.rp-links a:hover { background: var(--page); text-decoration: none; }
.rp-links a + a { border-top: 1px solid var(--neutral-soft); }
.rp-links .nm { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 12.5px; font-weight: 600; }
.rp-links .nm em { font-style: normal; font-size: 11px; font-weight: 400; color: var(--muted); }
.rp-links b { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }

@media (max-width: 720px) {
    .rp-name { font-size: 20px; }
    .rp-diagram { grid-template-columns: 96px minmax(0, 1fr); }
    .rp-nav { padding: 0 8px; }
    .rp-nav-road { display: none; }
}


/* ---------------------------------------------- replacing a handed password */
/* One card in the middle of an otherwise empty screen. The block is the
   middleware and not this markup — a dialog is something a browser can be
   told to ignore, and the endpoints behind it would go on answering. */
.pw-shell { display: grid; place-items: center; min-height: 62vh; padding: 24px 0; }
.pw-card { width: min(460px, 100%); padding: 22px 24px 24px; display: flex; flex-direction: column; gap: 16px; }
.pw-head { display: flex; align-items: flex-start; gap: 13px; }
.pw-ic {
  flex: none; width: 40px; height: 40px; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent);
}
.pw-ic svg { width: 20px; height: 20px; }
.pw-head h2 { margin: 0 0 3px; font-size: 16px; font-weight: 650; }
.pw-head p { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.pw-form { display: flex; flex-direction: column; gap: 11px; }
.pw-row { display: flex; flex-direction: column; gap: 4px; }
.pw-row > span { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.pw-row input {
  width: 100%; padding: 9px 11px; font: inherit; font-size: 14px;
  color: var(--ink); background: var(--page);
  border: 1px solid var(--line-strong); border-radius: 6px;
}
.pw-row input:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.pw-hint { margin: 0; font-size: 11.5px; color: var(--muted); }
.pw-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 4px; }

/* ---------- Road operations: the task wizard (after RoadOps' "Topshiriq yaratish") ----------
   One form, shown a step at a time. The steps are a presentation of the same
   fields — the server validates the whole form as before — so a reload with
   errors reopens on the step that holds the first one (`data-start-step`). */
.wz-tabs { display: flex; gap: 22px; border-bottom: 1px solid var(--line); margin-bottom: 18px; }
.wz-tabs a {
  padding: 10px 2px; font-size: 13px; font-weight: 600; color: var(--muted);
  text-decoration: none; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.wz-tabs a:hover { color: var(--ink); }
.wz-tabs a.active { color: var(--accent); border-bottom-color: var(--accent); }

.wz-steps { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; margin-bottom: 18px; }
.wz-step {
  display: flex; align-items: center; gap: 9px; padding: 10px 8px 12px;
  border: none; border-bottom: 2px solid var(--line); background: none;
  color: var(--muted); font: inherit; font-size: 13px; text-align: left; cursor: default;
}
.wz-step .n {
  flex: none; display: inline-grid; place-items: center; width: 26px; height: 26px;
  border: 1.5px solid currentColor; border-radius: 50%; font-size: 12px; font-weight: 600;
}
.wz-step.current { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.wz-step.done { color: var(--ok); border-bottom-color: var(--ok-soft); cursor: pointer; }
.wz-step.done .n { background: var(--ok-soft); }
.wz-step.done .n::after { content: '✓'; }
.wz-step.done .n span { display: none; }

.wz-card {
  max-width: 820px; margin: 0 auto; padding: 22px 24px; border: 1px solid var(--line);
  border-radius: 11px; background: var(--surface); box-shadow: var(--shadow);
  display: flex; flex-direction: column; gap: 14px;
}
.wz-card[hidden] { display: none; }
.wz-card > h3 { margin: 0; font-size: 18px; color: var(--ink); }

.wz-recap {
  border-left: 3px solid var(--accent); background: var(--page); border-radius: 0 7px 7px 0;
  padding: 12px 14px; font-size: 13px; color: var(--ink-2);
}
.wz-recap b { display: block; color: var(--ink); font-size: 14px; margin-bottom: 2px; }
.wz-recap:empty { display: none; }

.wz-pick { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.wz-pick label {
  display: flex; gap: 11px; align-items: flex-start; padding: 12px 13px; cursor: pointer;
  border: 1px solid var(--line-strong); border-radius: 8px; background: var(--surface);
}
.wz-pick label:hover { border-color: var(--accent); }
.wz-pick input { margin-top: 2px; width: 17px; height: 17px; accent-color: var(--accent); flex: none; }
.wz-pick .who { display: flex; flex-direction: column; gap: 2px; font-size: 12.5px; color: var(--muted); }
.wz-pick .who b { color: var(--ink); font-size: 13px; }
.wz-pick label:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.wz-pick label.busy { border-style: dashed; }
.wz-pick label.busy .state { color: var(--crit-ink); font-weight: 600; }
.wz-pick label .state.free { color: var(--ok-ink); }

.wz-error { padding: 10px 12px; border-radius: 7px; background: var(--crit-soft); color: var(--crit-ink); font-size: 13px; }
.wz-error[hidden] { display: none; }

.wz-nav { display: flex; justify-content: space-between; gap: 10px; border-top: 1px solid var(--line); padding-top: 14px; }
.wz-nav .btn-primary { margin-left: auto; }

.wz-summary { width: 100%; border-collapse: collapse; font-size: 13px; }
.wz-summary th { text-align: left; color: var(--muted); font-weight: 500; padding: 7px 12px 7px 0; width: 34%; vertical-align: top; }
.wz-summary td { padding: 7px 0; color: var(--ink); border-bottom: 1px solid var(--line); }
.wz-summary tr:last-child td { border-bottom: none; }

@media (max-width: 760px) {
  .wz-steps { grid-template-columns: repeat(5, auto); overflow-x: auto; }
  .wz-step .t { display: none; }
  .wz-step.current .t { display: inline; }
  .wz-pick { grid-template-columns: 1fr; }
  .wz-card { padding: 16px; }
}

/* ---------- Month-end: the Tabel grid ---------- */
.tabel-grid th, .tabel-grid td { padding: 7px 6px; }
.tabel-grid th:first-child, .tabel-grid td:first-child {
  position: sticky; left: 0; z-index: 1; background: var(--surface); min-width: 180px; padding-left: 14px;
}
.tabel-grid .wkend { background: var(--page); }
.tabel-grid td.work b { color: var(--ok-ink); }
.tabel-grid td.tabel-cell:not(.work):hover { background: var(--accent-soft); }

/* ---------- Month-end: KPI strip and payroll grid ---------- */
.me-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px; margin-bottom: 14px; }
.me-kpis .card { padding: 14px 16px; }
.me-kpis .lb { font-size: 12px; color: var(--muted); }
.me-kpis .v { font-size: 19px; font-weight: 700; color: var(--ink); margin-top: 4px; font-variant-numeric: tabular-nums; }
.payroll-grid input[type="number"] { width: 96px; padding: 5px 7px; font-size: 12.5px; }
.payroll-grid td, .payroll-grid th { padding: 8px 8px; white-space: nowrap; }
.payroll-grid td:first-child, .payroll-grid th:first-child {
  position: sticky; left: 0; z-index: 1; background: var(--surface); min-width: 190px; white-space: normal;
}
.payroll-grid tr.disabled td { color: var(--muted); }
.payroll-grid [data-out] { font-variant-numeric: tabular-nums; font-weight: 600; }
.payroll-grid tfoot td { font-weight: 700; border-top: 2px solid var(--line-strong); }
.payroll-grid .row-error { color: var(--crit-ink); }
.me-tab-pane[hidden] { display: none; }


/* ==========================================================================
   Phones (≤ 860px)
   The sidebar was simply switched off here, with nothing in its place — on a
   phone every screen was a dead end, reachable only by typing its address.
   It is a drawer now: the ☰ in the top bar slides it in over a dimmed page,
   and the page, Escape or the button in its own header put it away. Always
   the full list with its words, never the icon rail: a 68px column of
   unlabelled icons is a guessing game at thumb size.
   ========================================================================== */
.tb-menu { display: none; }
.nav-backdrop { display: none; }

@media (max-width: 860px) {
  .gov-sidebar,
  .gov-sidebar.collapsed {
    --sidebar-w: min(84vw, 300px);
    display: flex; position: fixed; top: 0; bottom: 0; left: 0; z-index: 60;
    height: 100vh; height: 100dvh; overflow-y: auto;
    transform: translateX(-100%); transition: transform 0.22s ease;
  }
  body.nav-open .gov-sidebar { transform: none; box-shadow: 0 0 40px rgba(5, 12, 25, 0.35); }
  .nav-backdrop { position: fixed; inset: 0; z-index: 55; background: rgba(5, 12, 25, 0.45); }
  body.nav-open .nav-backdrop { display: block; }
  body.nav-open { overflow: hidden; }

  .tb-menu { display: grid; flex: none; }
  .topbar { padding: 10px 14px; gap: 8px; }
  .topbar h1 {
    flex: 1; min-width: 0; font-size: 15px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .topbar .tb-spacer { display: none; }
  /* The avatar says who is signed in; the name and role go to save the row. */
  .user-chip { padding-left: 0; }
  .user-chip > div:last-child { display: none; }
  select.lang { padding: 5px 2px; width: 74px; font-size: 12px; }
  /* The theme follows the phone's own setting; the button costs the title
     its room. */
  #govThemeBtn { display: none; }

  .content { padding: 16px 14px 40px; }

  /* Long lists: the page numbers and the jump field wrap under the count
     instead of running off the screen. */
  .pager { flex-wrap: wrap; gap: 10px; }
  .pager-nav, .pager nav { flex-wrap: wrap; min-width: 0; }

  /* A row of tabs (month-end has six) scrolls sideways on its own rather
     than widening the page. */
  .wz-tabs { gap: 16px; overflow-x: auto; scrollbar-width: none; }
  .wz-tabs::-webkit-scrollbar { display: none; }
  .wz-tabs a { flex: none; white-space: nowrap; }

  /* A chip carrying a sentence (the Tabel's legend) wraps. */
  .chip { white-space: normal; max-width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .gov-sidebar { transition: none; }
}

/* ===================================================================
   One object of the «Элемент тури» layer, opened from its marker.

   Centred over the map rather than squeezed into the side panel, because
   the photographs are the reason it is opened: the carousel takes the
   left half and what the register knows takes the right, each figure
   under an icon and a label so the eye can find "which road" without
   reading every row. Stacked on a narrow screen.
   =================================================================== */
.pj-pop {
    position: absolute; inset: 0; z-index: 45;
    display: grid; place-items: center;
    padding: var(--m-gap);
    background: rgba(15, 23, 42, 0.32);
    backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
}
.pj-pop[hidden] { display: none; }
.pj-card {
    width: min(920px, 100%); max-height: min(90vh, 760px);
    display: flex; flex-direction: column; overflow: hidden;
    border: 1px solid var(--line); border-radius: 14px;
    background: var(--surface);
    box-shadow: 0 30px 80px rgba(15, 23, 42, 0.32), 0 1px 2px rgba(15, 23, 42, 0.08);
    animation: pj-in 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes pj-in { from { opacity: 0; transform: translateY(10px) scale(0.98); } }
@media (prefers-reduced-motion: reduce) { .pj-card { animation: none; } }

/* ---------- head ---------- */
.pj-head {
    flex: none; display: flex; align-items: center; gap: 13px;
    padding: 14px 14px 13px 18px;
    border-bottom: 1px solid var(--line);
    background: linear-gradient(180deg, var(--accent-soft), transparent 140%);
}
.pj-badge {
    width: 44px; height: 44px; flex: none; display: grid; place-items: center;
    border-radius: 11px; background: var(--surface); color: var(--accent);
    border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--line));
    box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
}
.pj-badge img { width: 28px; height: 28px; object-fit: contain; }
.pj-badge svg { width: 22px; height: 22px; }
.pj-head-txt { flex: 1; min-width: 0; }
.pj-kicker {
    margin: 0 0 2px; font-size: 10.5px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--accent);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pj-title {
    margin: 0; font-size: 17px; font-weight: 750; line-height: 1.25; color: var(--ink);
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.pj-x { width: 34px; height: 34px; flex: none; }

/* ---------- body ---------- */
.pj-body {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    padding: 16px 18px 18px;
    display: flex; flex-direction: column; gap: 16px;
}
.pj-grid {
    display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: 18px; align-items: start;
}
@media (max-width: 760px) { .pj-grid { grid-template-columns: minmax(0, 1fr); } }

.pj-loading, .pj-empty {
    display: flex; align-items: center; justify-content: center; gap: 10px;
    min-height: 220px; margin: 0; color: var(--muted); font-size: 13px;
}
.pj-spin {
    width: 18px; height: 18px; border-radius: 50%;
    border: 2px solid var(--line); border-top-color: var(--accent);
    animation: pj-spin 0.8s linear infinite;
}
@keyframes pj-spin { to { transform: rotate(360deg); } }

/* ---------- carousel ---------- */
.pj-carousel { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.pj-stage {
    position: relative; overflow: hidden;
    aspect-ratio: 4 / 3; border-radius: 11px;
    background: var(--page); border: 1px solid var(--line);
    touch-action: pan-y; user-select: none;
}
.pj-track {
    display: flex; height: 100%;
    transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) { .pj-track { transition: none; } }
.pj-slide {
    position: relative; flex: 0 0 100%; height: 100%;
    display: grid; place-items: center; cursor: zoom-in;
}
.pj-slide img {
    width: 100%; height: 100%; object-fit: cover;
    opacity: 0; transition: opacity 0.25s ease;
}
.pj-slide.is-loaded img { opacity: 1; }
.pj-broken, .pj-noshot {
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    color: var(--muted); font-size: 12px; text-align: center; padding: 16px;
}
.pj-broken svg, .pj-noshot svg { width: 34px; height: 34px; opacity: 0.6; }
.pj-broken { position: absolute; inset: 0; justify-content: center; display: none; }
.pj-slide.is-broken { cursor: default; }
.pj-slide.is-broken img { display: none; }
.pj-slide.is-broken .pj-broken { display: flex; }
.pj-carousel.is-empty {
    aspect-ratio: 4 / 3; display: grid; place-items: center;
    border: 1px dashed var(--line); border-radius: 11px; background: var(--page);
}

.pj-nav {
    position: absolute; top: 50%; z-index: 2;
    width: 36px; height: 36px; margin-top: -18px;
    display: grid; place-items: center; cursor: pointer;
    border: 0; border-radius: 50%;
    background: rgba(255, 255, 255, 0.92); color: #0f172a;
    box-shadow: 0 4px 14px rgba(15, 23, 42, 0.22);
    opacity: 0.85; transition: opacity 0.15s ease, transform 0.15s ease;
}
.pj-nav:hover { opacity: 1; transform: scale(1.06); }
.pj-nav svg { width: 18px; height: 18px; }
.pj-prev { left: 10px; }
.pj-next { right: 10px; }
.pj-count {
    position: absolute; right: 10px; bottom: 10px; z-index: 2;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 99px;
    background: rgba(15, 23, 42, 0.68); color: #fff;
    font-size: 11.5px; font-variant-numeric: tabular-nums;
    pointer-events: none;
}
.pj-count svg { width: 13px; height: 13px; }
.pj-count b { font-weight: 650; }

.pj-thumbs {
    display: flex; gap: 6px; overflow-x: auto; padding-bottom: 2px;
    scroll-snap-type: x proximity;
}
.pj-thumb {
    flex: 0 0 64px; height: 48px; padding: 0; cursor: pointer;
    border: 2px solid transparent; border-radius: 7px; overflow: hidden;
    background: var(--page); scroll-snap-align: start;
    opacity: 0.62; transition: opacity 0.15s ease, border-color 0.15s ease;
}
.pj-thumb:hover { opacity: 0.9; }
.pj-thumb[aria-selected="true"] { opacity: 1; border-color: var(--accent); }
.pj-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pj-thumb.is-broken img { display: none; }

/* ---------- state chips ---------- */
.pj-info { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.pj-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.pj-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 99px;
    font-size: 11.5px; font-weight: 650;
}
.pj-chip i { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.pj-chip.tone-ok { background: var(--ok-soft); color: var(--ok-ink); }
.pj-chip.tone-crit { background: var(--crit-soft); color: var(--crit-ink); }
.pj-chip.tone-warn { background: var(--warn-soft); color: var(--warn-ink); }
.pj-chip.tone-muted { background: var(--neutral-soft); color: var(--neutral-ink); }

/* ---------- the figures: an icon, a label, a value ---------- */
.pj-fields { margin: 0; display: flex; flex-direction: column; gap: 4px; }
.pj-field {
    display: grid; grid-template-columns: 34px minmax(0, 1fr);
    grid-template-rows: auto auto; column-gap: 11px;
    align-items: center; padding: 7px 8px; border-radius: 9px;
}
.pj-field:hover { background: var(--page); }
.pj-ic {
    grid-row: 1 / span 2; width: 34px; height: 34px;
    display: grid; place-items: center;
    border-radius: 9px; background: var(--accent-soft); color: var(--accent);
}
.pj-ic svg { width: 17px; height: 17px; }
.pj-field dt {
    font-size: 10.5px; font-weight: 650; letter-spacing: 0.04em;
    text-transform: uppercase; color: var(--muted);
}
.pj-field dd {
    margin: 1px 0 0; font-size: 13.5px; font-weight: 600; color: var(--ink);
    line-height: 1.35; overflow-wrap: break-word; word-break: normal;
}
.pj-copy {
    display: inline-flex; align-items: center; gap: 7px; padding: 0;
    border: 0; background: none; cursor: pointer;
    font: inherit; color: inherit; font-variant-numeric: tabular-nums;
}
.pj-copy svg { width: 14px; height: 14px; color: var(--muted); }
.pj-copy:hover svg { color: var(--accent); }
.pj-copy.is-copied svg { color: var(--ok); }

/* ---------- description, files ---------- */
.pj-note {
    padding: 12px 14px; border: 1px solid var(--line); border-radius: 11px;
    background: var(--page);
}
.pj-note h4 {
    display: flex; align-items: center; gap: 7px;
    margin: 0 0 6px; font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
    text-transform: uppercase; color: var(--muted);
}
.pj-note h4 svg { width: 15px; height: 15px; color: var(--accent); }
.pj-note p { margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); white-space: pre-line; }
.pj-files { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.pj-files a {
    display: inline-flex; align-items: center; gap: 6px; max-width: 260px;
    padding: 5px 10px; border: 1px solid var(--line); border-radius: 7px;
    background: var(--surface); color: var(--ink-2); font-size: 12px; text-decoration: none;
}
.pj-files a:hover { border-color: var(--accent); color: var(--accent); }
.pj-files svg { width: 14px; height: 14px; flex: none; }
.pj-files span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- actions ---------- */
.pj-actions {
    display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px;
    padding-top: 14px; border-top: 1px solid var(--line);
}
.pj-act { display: inline-flex; align-items: center; gap: 7px; }
.pj-act svg { width: 16px; height: 16px; }

/* ===================================================================
   The condition profile — skid resistance, roughness and rutting along
   one road, as strips on one kilometre axis under the map
   (`road-profile.js`).

   It takes the film's place at the foot of the map: a framed block clear
   of the bottom edge, with the strip and both side columns lifted above
   it by its measured height (`--cpf-height`, set by map.js), exactly as
   they are for the film. The grade colours are tokens of its own so the
   canvas — which cannot read a class — reads them with getComputedStyle.
   =================================================================== */
.cpf {
    --cpf-good: #1f9d55;
    --cpf-fair: #e2a400;
    --cpf-poor: #d64545;
    --cpf-none: #cfd5df;
    --cpf-label: 210px;
    --cpf-sum: 150px;
    position: absolute; z-index: 8;
    left: var(--m-gap); right: var(--m-gap); bottom: var(--m-gap);
    display: flex; flex-direction: column;
    max-height: min(46vh, 380px);
    border: 1px solid var(--line); border-radius: var(--m-radius);
    background: var(--surface);
    box-shadow: 0 12px 38px rgba(15, 23, 42, 0.18), 0 1px 2px rgba(15, 23, 42, 0.06);
    overflow: hidden;
}
.cpf[hidden] { display: none; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .cpf { --cpf-none: #3a4252; }
}
:root[data-theme="dark"] .cpf { --cpf-none: #3a4252; }

.map-shell:has(.cpf:not([hidden])) .map-dock { bottom: calc(var(--cpf-height, 220px) + 2 * var(--m-gap)); }
.map-shell:has(.cpf:not([hidden])) .map-layers,
.map-shell:has(.cpf:not([hidden])) .map-panel {
    bottom: calc(var(--cpf-height, 220px) + 3 * var(--m-gap) + var(--m-dock-real, var(--m-dock-h)));
}

/* ---------- head ---------- */
.cpf-head {
    flex: none; display: flex; align-items: center; gap: 10px;
    padding: 8px 10px 8px 8px;
    border-bottom: 1px solid var(--line);
}
.cpf-fold {
    width: 30px; height: 30px; flex: none; display: grid; place-items: center;
    border: 0; border-radius: 7px; background: none; color: var(--ink-2); cursor: pointer;
}
.cpf-fold:hover { background: var(--page); }
.cpf-fold svg { width: 18px; height: 18px; transition: transform 0.15s ease; }
.cpf.is-folded .cpf-fold svg { transform: rotate(-90deg); }
.cpf.is-folded .cpf-body, .cpf.is-folded .cpf-legend { display: none; }
.cpf-titles { flex: 1; min-width: 0; }
.cpf-title {
    margin: 0; font-size: 14px; font-weight: 700; color: var(--ink);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cpf-where { margin: 1px 0 0; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cpf-controls { flex: none; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.cpf-field { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted); }
.cpf-select {
    height: 30px; padding: 0 26px 0 9px;
    border: 1px solid var(--line); border-radius: 7px;
    background: var(--surface); color: var(--ink); font: inherit; font-size: 12px;
}
.cpf-select:disabled { opacity: 0.5; }
.cpf-3d {
    height: 30px; padding: 0 12px;
    display: inline-flex; align-items: center; gap: 7px;
    border: 0; border-radius: 7px; cursor: pointer;
    background: var(--accent); color: var(--accent-ink, #fff);
    font: inherit; font-size: 12px; font-weight: 650;
}
.cpf-3d:hover { filter: brightness(1.08); }
.cpf-3d[hidden] { display: none; }
.cpf-3d svg { width: 16px; height: 16px; }
.cpf-close { width: 30px; height: 30px; }

/* ---------- body: three columns, one row per measure ---------- */
.cpf-body { position: relative; flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 4px 0 6px; }
.cpf-grid {
    display: grid;
    grid-template-columns: var(--cpf-label) minmax(0, 1fr) var(--cpf-sum);
    align-items: stretch;
}
.cpf-cell { min-width: 0; }
.cpf-axis-label {
    display: flex; align-items: center; padding: 0 12px;
    font-size: 11px; color: var(--muted);
}
.cpf-axis { position: relative; height: 26px; margin: 0 6px; border-bottom: 1px solid var(--line); }
.cpf-tick {
    position: absolute; bottom: 4px; transform: translateX(-50%);
    font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.cpf-tick::after {
    content: ''; position: absolute; left: 50%; bottom: -5px;
    width: 1px; height: 4px; background: var(--line);
}

.cpf-label {
    display: flex; flex-direction: column; justify-content: center; gap: 2px;
    padding: 8px 12px; min-height: 48px;
    border: 0; border-left: 3px solid transparent; border-bottom: 1px solid var(--line);
    background: none; text-align: left; cursor: pointer; color: var(--ink);
}
.cpf-label:hover { background: var(--page); }
.cpf-label.is-active { border-left-color: var(--accent); background: var(--accent-soft); }
.cpf-label b { font-size: 12.5px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cpf-label small { font-size: 10.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

.cpf-plot { display: flex; align-items: center; padding: 0 6px; border-bottom: 1px solid var(--line); cursor: crosshair; }
.cpf-canvas { display: block; width: 100%; height: 12px; border-radius: 3px; }

.cpf-sum {
    display: flex; flex-direction: column; justify-content: center; gap: 2px;
    padding: 6px 12px; border-bottom: 1px solid var(--line); border-left: 1px solid var(--line);
}
.cpf-sum small { font-size: 10.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cpf-mean { display: flex; align-items: baseline; gap: 4px; }
.cpf-mean b { font-size: 17px; font-weight: 750; color: var(--ink); font-variant-numeric: tabular-nums; }
.cpf-mean span { font-size: 11px; color: var(--muted); }
.cpf-mean.is-empty { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.cpf-mean.tone-good b { color: var(--cpf-good); }
.cpf-mean.tone-fair b { color: var(--cpf-fair); }
.cpf-mean.tone-poor b { color: var(--cpf-poor); }
.cpf-share { display: flex; height: 4px; border-radius: 99px; overflow: hidden; background: var(--cpf-none); }
.cpf-share i { display: block; height: 100%; }

.cpf-note { margin: 0; padding: 22px 16px; text-align: center; font-size: 12.5px; color: var(--muted); }
.cpf-note[hidden] { display: none; }

/* ---------- cursor and its readout ---------- */
.cpf-cursor {
    position: absolute; width: 0; pointer-events: none;
    border-left: 1.5px dashed var(--accent);
}
.cpf-cursor[hidden] { display: none; }
.cpf-chip {
    /* Inside the axis row, over its tick labels: above it the deck's own
       scroll box would cut it off. */
    position: absolute; top: 2px; left: 0; transform: translateX(-50%);
    padding: 2px 7px; border-radius: 6px;
    background: var(--accent); color: var(--accent-ink, #fff);
    font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.cpf-tip {
    position: absolute; z-index: 2; pointer-events: none;
    min-width: 128px; padding: 7px 10px;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); box-shadow: 0 8px 24px rgba(15, 23, 42, 0.16);
    font-size: 11.5px; color: var(--ink);
}
.cpf-tip[hidden] { display: none; }
.cpf-tip > b { display: block; margin-bottom: 4px; font-size: 12px; font-variant-numeric: tabular-nums; }
.cpf-tip-row { display: flex; align-items: center; gap: 6px; }
.cpf-tip-row span { color: var(--muted); }
.cpf-tip-row strong { margin-left: auto; font-variant-numeric: tabular-nums; }

/* ---------- legend ---------- */
.cpf-legend {
    flex: none; display: flex; flex-wrap: wrap; gap: 14px;
    padding: 6px 14px 8px; border-top: 1px solid var(--line);
    font-size: 11px; color: var(--muted);
}
.cpf-key { display: inline-flex; align-items: center; gap: 6px; }
.cpf-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--cpf-none); }
.cpf .tone-good { background: var(--cpf-good); }
.cpf .tone-fair { background: var(--cpf-fair); }
.cpf .tone-poor { background: var(--cpf-poor); }
.cpf .tone-none { background: var(--cpf-none); }
.cpf .cpf-mean.tone-good, .cpf .cpf-mean.tone-fair, .cpf .cpf-mean.tone-poor { background: none; }

@media (max-width: 900px) {
    .cpf { --cpf-label: 130px; --cpf-sum: 96px; }
    .cpf-field > span { display: none; }
    .cpf-3d span { display: none; }
}

/* The national product classifier lookup (resource_items/_mxik-lookup). */
.mxik-lookup { position: relative; }
.mxik-lookup .mxik-chosen {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-top: 6px; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--accent-soft);
}
.mxik-lookup .mxik-chosen strong { font-size: 13px; color: var(--ink); }
.mxik-lookup .mxik-chosen small { flex-basis: 100%; color: var(--muted); font-size: 11.5px; line-height: 1.4; }
.mxik-lookup .mxik-results {
  position: absolute; z-index: 30; left: 0; right: 0; margin-top: 4px; max-height: 320px; overflow: auto;
  background: var(--surface); border: 1px solid var(--line); border-radius: 6px; box-shadow: var(--shadow); padding: 4px;
}
.mxik-lookup .mxik-results > .hint { margin: 6px 8px; display: block; }
.mxik-lookup .mxik-row {
  display: block; width: 100%; text-align: left; padding: 7px 9px; border: 0; border-radius: 5px; background: transparent; color: var(--ink); cursor: pointer; font: inherit;
}
.mxik-lookup .mxik-row:hover, .mxik-lookup .mxik-row:focus-visible { background: var(--accent-soft); outline: none; }
.mxik-lookup .mxik-row strong { display: block; font-size: 12.5px; font-weight: 600; }
.mxik-lookup .mxik-row small { display: block; color: var(--muted); font-size: 11px; line-height: 1.35; margin-top: 2px; }
.mxik-lookup .mxik-row em { display: block; color: var(--muted); font-size: 11px; font-style: normal; margin-top: 2px; }
.mxik-lookup .mxik-row.is-catalogue { border-left: 3px solid var(--accent); }
.receipt-basis { font-size: 12px; line-height: 1.45; }
/* A heading inside a wizard card that holds two lists (machinery, warehouse). */
.wz-card .wz-sub { margin: 6px 0 0; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
#rtVehicles tr.busy td { background: var(--warn-soft); }
#rtVehicles tr.busy .state { color: var(--warn-ink); }
/* The completion form's hour grid: an override, folded away by default. */
.ct-manual { margin: 8px 0 12px; }
.ct-manual > summary { cursor: pointer; font-size: 13px; color: var(--accent); font-weight: 600; padding: 4px 0; }
.ct-manual[open] > summary { margin-bottom: 6px; }
/* The defect form's place picker (defects/_place-map). */
.place-map-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 4px 0 8px; }
.place-map-tools .hint { margin: 0; }
.place-map .geo-map { border-radius: 8px; overflow: hidden; border: 1px solid var(--line); }
/* The road closures screen: the map beside the week's list, stacked on a phone. */
.closures-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.closures-map-card .geo-map { border-top: 1px solid var(--line); }
@media (max-width: 900px) { .closures-grid { grid-template-columns: 1fr; } .closures-map-card .geo-map { height: 420px !important; } }
