/* EnergoLink interface.
 *
 * The palette is D-070's and the material rules are D-071's, and both are
 * decisions rather than taste:
 *   - night is the primary background, day is a real second palette and not an
 *     inversion;
 *   - the base is never pure black and the text never pure white, because both
 *     make elements float and text halate;
 *   - the accent is a lifted variant of the brand green, which the deep #0F6E56
 *     cannot be on a dark surface;
 *   - roughly 90/8/2 neutral / text / accent: the accent is the smallest
 *     quantity on the screen and therefore the most noticed.
 *
 * Glass governs the CHROME and never the data (D-071): the sidebar and the top
 * bar may float, tables and cards never do. Default is night + plain, which
 * works on every machine backdrop-filter does not.
 *
 * There is no domain constant in this file and there cannot be one: it holds no
 * threshold, no factor and no unit rule (REQ-UIX-002). Every colour a value is
 * painted with comes from the `tone` the SERVER decided.
 */

:root{
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;
  --mono:"SF Mono",Menlo,Consolas,monospace;
  --r:16px; --r-s:11px; --r-l:22px;
}
[data-theme="night"]{
  --bg:#0D1014; --s1:#13171D; --s2:#191F27; --s3:#212932;
  --line:rgba(255,255,255,.07); --line-s:rgba(255,255,255,.13);
  --tx1:#E9EDF2; --tx2:#98A4B3; --tx3:#64707E;
  --ok:#3FC493; --ok-d:rgba(63,196,147,.13); --ok-b:rgba(63,196,147,.28);
  --wn:#E8A83C; --wn-d:rgba(232,168,60,.13); --wn-b:rgba(232,168,60,.30);
  --dg:#EF6A5E; --dg-d:rgba(239,106,94,.13);
  --in:#8B7DF0; --in-d:rgba(139,125,240,.13);
  --shadow:0 1px 2px rgba(0,0,0,.5),0 8px 24px rgba(0,0,0,.32);
  --map1:rgba(46,196,150,.34); --map2:rgba(94,124,255,.30);
  --map3:rgba(168,92,246,.26); --map4:rgba(232,168,60,.18);
  --mapbase:linear-gradient(155deg,#0B1219,#0A1017 52%,#0D0F18);
  --mesh:rgba(255,255,255,.032);
  --gl-bg:rgba(255,255,255,.045); --gl-brd:rgba(255,255,255,.10);
  --gl-top:rgba(255,255,255,.24); --gl-in:rgba(255,255,255,.13);
}
[data-theme="day"]{
  --bg:#F6F5F1; --s1:#FFFFFF; --s2:#FFFFFF; --s3:#F1EFE9;
  --line:rgba(20,24,28,.09); --line-s:rgba(20,24,28,.16);
  --tx1:#15191D; --tx2:#5D666F; --tx3:#8B939C;
  --ok:#0E6B54; --ok-d:rgba(14,107,84,.09); --ok-b:rgba(14,107,84,.22);
  --wn:#B4720C; --wn-d:rgba(180,114,12,.10); --wn-b:rgba(180,114,12,.24);
  --dg:#C0392F; --dg-d:rgba(192,57,47,.09);
  --in:#4B3FB0; --in-d:rgba(75,63,176,.09);
  --shadow:0 1px 2px rgba(20,24,28,.05),0 6px 20px rgba(20,24,28,.07);
  --map1:rgba(14,107,84,.16); --map2:rgba(75,99,200,.14);
  --map3:rgba(140,80,210,.12); --map4:rgba(200,140,20,.12);
  --mapbase:linear-gradient(155deg,#EDEBE4,#F2F0EA 52%,#E9E7E1);
  --mesh:rgba(20,24,28,.045);
  --gl-bg:rgba(255,255,255,.34); --gl-brd:rgba(255,255,255,.62);
  --gl-top:rgba(255,255,255,.92); --gl-in:rgba(255,255,255,.72);
}

*{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--font);background:var(--bg);color:var(--tx1);min-width:320px}
[hidden]{display:none !important}

/* The layout has three tiers and they are not a taste:
 *
 *   > 860px   the desktop frame — a permanent rail on the left, the content
 *             beside it. A 980px window is a SMALL DESKTOP, not a telephone,
 *             and this is the width a phone reports when the person asks for
 *             the "PC version". The previous breakpoint was 1000px and turned
 *             exactly that window into the narrow layout.
 *   <= 860px  the rail folds behind a control. Below this a 236px rail costs
 *             more room than it returns.
 *   <= 560px  a telephone: a row of a table stops being a row and becomes a
 *             block of label-and-value pairs.
 *
 * Nothing anywhere sets overflow-x:hidden on the page to make an overflow go
 * away. Hiding it would leave the content off the screen and unreachable, and
 * would make the test that measures it pass.
 */

/* ── material ─────────────────────────────────────────────────────────────── */
.chrome{background:var(--s1);border:1px solid var(--line);box-shadow:var(--shadow)}
[data-mat="glass"] .chrome{
  background:var(--gl-bg);
  backdrop-filter:blur(30px) saturate(180%) brightness(1.06);
  -webkit-backdrop-filter:blur(30px) saturate(180%) brightness(1.06);
  border:1px solid var(--gl-brd);
  box-shadow:0 20px 56px rgba(0,0,0,.42),0 1px 0 var(--gl-in) inset}

/* ── frame ────────────────────────────────────────────────────────────────── */
.app{position:relative;min-height:100vh;overflow:hidden}
/* The frame is centred and capped at 1440 px — his order of 2026-09-07 evening, seen on a
   2000 px monitor: every row stretched from edge to edge, the label at the left and its
   value 1700 px away. 1440 is the width the layout family is proved at (fleettests, 1440),
   so on any wider screen the page IS the tested page, with the body's own colour on both
   sides. `.side`, `.top` and `.main` are positioned against .app, so they move with it;
   the phone rules (fixed drawer, sticky header) apply only below the fold and are untouched.
   `body > .app` outranks the adopted `.app{...}` further down this file by one element. */
body > .app{max-width:1440px;margin:0 auto}
/* The backdrop bleeds 8% past the frame on purpose, so its gradients have no
   hard edge. The clip belongs HERE and not on .app: the narrow layout needs
   .app to overflow visibly for the sticky header, and with the clip on .app
   that bleed became 78px of real sideways scroll at 980px. */
.canvas{position:absolute;inset:0;z-index:0;overflow:hidden}
.mapbg{position:absolute;inset:-8%;background:
  radial-gradient(38% 34% at 20% 24%,var(--map1),transparent 68%),
  radial-gradient(34% 30% at 76% 14%,var(--map2),transparent 68%),
  radial-gradient(40% 36% at 66% 82%,var(--map3),transparent 70%),
  radial-gradient(28% 26% at 26% 86%,var(--map4),transparent 68%),
  var(--mapbase)}
.mesh{position:absolute;inset:0;opacity:.6;
  background-image:linear-gradient(var(--mesh) 1px,transparent 1px),
                   linear-gradient(90deg,var(--mesh) 1px,transparent 1px);
  background-size:60px 60px}

.side{position:absolute;left:0;top:0;bottom:0;width:236px;z-index:5;padding:17px 13px;
  border-radius:0 var(--r-l) var(--r-l) 0;border-left:none;overflow-y:auto}
.brand{display:flex;align-items:center;gap:10px;padding:3px 8px 15px}
.logo{width:28px;height:28px;border-radius:9px;background:linear-gradient(150deg,#6BEFBC,#28A97B);
  display:grid;place-items:center;font-weight:800;font-size:14px;color:#052018}
.bname{font-size:14.5px;font-weight:660;letter-spacing:-.01em}
.nsec{font-size:9.5px;font-weight:680;letter-spacing:.12em;text-transform:uppercase;
  color:var(--tx3);padding:13px 9px 5px}
.nav{display:flex;align-items:center;justify-content:space-between;padding:7px 11px;width:100%;
  border-radius:var(--r-s);font-size:13px;color:var(--tx2);margin-bottom:1px;cursor:pointer;
  background:none;border:none;font-family:var(--font);text-align:left}
.nav:hover{background:var(--s3);color:var(--tx1)}
.nav.on{background:var(--ok-d);color:var(--ok);font-weight:600;box-shadow:inset 0 0 0 1px var(--ok-b)}

.top{position:absolute;left:258px;right:22px;top:20px;height:56px;z-index:5;border-radius:18px;
  display:flex;align-items:center;gap:12px;padding:0 15px}
/* Who is signed in, and where. It is a LABEL: it was drawn as a filled, bordered
   box eight hundred pixels wide, which reads as a search field that does
   nothing when clicked. A control either acts or is not here (REQ-UIX-021), and
   this is not a control. min-width:0 is what lets it shrink instead of pushing
   the pills off the right edge, which is what it did at 412px. */
.search{flex:1 1 auto;min-width:0;line-height:34px;font-size:12.5px;color:var(--tx2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.search b{color:var(--tx1);font-weight:580}
.tpills{display:flex;align-items:center;gap:12px;flex:none}
/* The control that opens the rail when the rail is folded. It is display:none
   above 860px, so on a desktop it does not exist at all. */
.menu{display:none;width:34px;height:34px;flex:none;padding:0;cursor:pointer;
  place-items:center;border-radius:var(--r-s);background:var(--s3);
  border:1px solid var(--line);color:var(--tx2)}
.menu:hover{color:var(--tx1);background:var(--s2)}
.mb{position:relative;display:block;width:16px;height:1.6px;border-radius:2px;
  background:currentColor}
.mb::before,.mb::after{content:"";position:absolute;left:0;width:16px;height:1.6px;
  border-radius:2px;background:currentColor}
.mb::before{top:-5px}
.mb::after{top:5px}
/* The dim behind the open rail. It has no rule above 860px, so a window widened
   with the rail open cannot leave it covering a desktop. */
.nscrim{display:none}
.pill{font-size:11.5px;font-weight:570;padding:5px 11px;border-radius:20px;
  background:var(--s3);border:1px solid var(--line);color:var(--tx2);cursor:pointer;
  flex:none;white-space:nowrap}
.pill.act{color:var(--ok);border-color:var(--ok-b);background:var(--ok-d);font-weight:640}
.ava{width:29px;height:29px;border-radius:50%;background:linear-gradient(150deg,#6BEFBC,#28A97B);
  display:grid;place-items:center;font-size:10.5px;font-weight:700;color:#052018}
/* The avatar OPENS «Профиль» and since D-164 it is the only way an accountant
   has: the profile belongs to «Настройки», she holds neither `settings.read`
   nor `team.read`, and that entry is not on her rail at all. A control that
   acts must look like one (REQ-UIX-021), so it takes the pointer and a focus
   ring — it is reachable by the keyboard, which a `<span>` is not without the
   `tabindex` app.js gives it. */
.ava{cursor:pointer}
.ava:focus-visible{outline:2px solid var(--ok);outline-offset:2px}

.main{position:absolute;left:236px;right:0;top:88px;bottom:0;z-index:2;padding:8px 22px 22px;
  overflow-y:auto}

/* ── the navigation's second line, and its badges ─────────────────────────── */
/* design/app.html:698-737. Seven headings and, on eight entries, a number or a
   dot. `.nsec` already existed and was used once; it is now used once per
   section. The three below are copied from the drawing's own rules. */
.nlab{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ncount{font-size:10.5px;color:var(--tx3);flex:none;margin-left:8px}
.ndot{font-size:10px;font-weight:700;color:#fff;background:var(--dg);
  padding:1px 6px;border-radius:20px;flex:none;margin-left:8px}
/* D-033 and REQ-UIX-011: a section of the plan that is not built is VISIBLE and
   says so. This badge is what says it before the click rather than after it. */
.soon{font-size:9px;font-weight:660;letter-spacing:.05em;color:var(--tx3);
  border:1px solid var(--line-s);padding:0 5px;border-radius:5px;flex:none;
  margin-left:8px;text-transform:uppercase}

/* Whose data this is, under the brand.
   The drawing gives the top bar no slot for the organisation's name — the
   `.search` there is the search field (design/app.html:742) — and losing the
   name is not an option: it is what makes a screenshot of this product
   readable in correspondence, and on a lens it is the customer being looked at
   (REQ-IDN-106). So it moved here, under «EnergoLink», which is where the
   sign-in surface already puts it. */
.brand{flex-wrap:wrap}
.bsub{flex-basis:100%;font-size:11px;color:var(--tx3);line-height:1.5;
  padding-top:2px;overflow-wrap:anywhere}
.bsub b{color:var(--tx2);font-weight:580}

/* ── global search (design/app.html:742) ──────────────────────────────────── */
/* It IS a control now, so it is drawn as one: the drawing's filled bordered
   box, which the product refused to draw while the slot held a label. */
.srch{position:relative;flex:1 1 auto;min-width:0}
.srchi{width:100%;height:34px;border-radius:var(--r-s);background:var(--s3);
  border:1px solid var(--line);padding:0 13px;font-size:12.5px;color:var(--tx1);
  font-family:var(--font)}
.srchi::placeholder{color:var(--tx3)}
.srchi:focus{outline:none;border-color:var(--ok-b);box-shadow:0 0 0 3px var(--ok-d)}
/* The answers. Fixed inside the header's stacking context so a long list is not
   clipped by the header's own height, and bounded so it never runs off a
   telephone: it scrolls instead. */
.srchr{position:absolute;left:0;right:0;top:40px;z-index:30;max-height:min(62vh,420px);
  overflow-y:auto;border-radius:var(--r);background:var(--s1);
  border:1px solid var(--line);box-shadow:var(--shadow);padding:5px}
.srchg{font-size:9.5px;font-weight:680;letter-spacing:.12em;text-transform:uppercase;
  color:var(--tx3);padding:9px 10px 4px}
.srchh{display:block;width:100%;text-align:left;border:none;background:none;
  font-family:var(--font);font-size:13px;color:var(--tx2);cursor:pointer;
  padding:7px 10px;border-radius:var(--r-s)}
.srchh:hover,.srchh:focus{background:var(--s3);color:var(--tx1);outline:none}
.srchh .sh2{display:block;font-size:11px;color:var(--tx3);margin-top:2px}
.srchm{padding:11px 10px;font-size:12px;color:var(--tx3);line-height:1.55}

/* ── the top bar's two standing pills ─────────────────────────────────────── */
/* «22 / 24 онлайн» (design/app.html:743) and «Супер-админ» (:749). Neither is a
   control: they say something and are not pressed, so they carry no pointer. */
.pill.live{color:var(--ok);background:var(--ok-d);border-color:var(--ok-b);cursor:default}
.pill.live.warn{color:var(--wn);background:var(--wn-d);border-color:var(--wn-b)}
.rolepill{border-color:var(--in);color:var(--in);font-weight:640;cursor:default}

/* ── two columns (design/app.html: `.g2`, 32 places) ──────────────────────── */
/* A wide column of tables and a narrow one of the small cards that qualify
   them. It collapses to one column at 1100px, not at 860px: the rail is 236px
   wide and the narrow column is 340px, so below about 1100px the wide column is
   too narrow for a six-column table and the two-column arrangement costs more
   than it gives. Below that width the blocks are one column in the order the
   server sent them, which is what every shell did before this rule existed. */
.g2{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:13px;align-items:start}
.gc{min-width:0}
@media (max-width:1100px){
  .g2{grid-template-columns:minmax(0,1fr)}
}
/* A TABLE in the narrow column, and the reason it needs a rule of its own.
   `.tw table{min-width:920px}` below was measured for the WIDE column at a
   980px window; in a 340px card it puts 580px of the table outside the card and
   the reader has to scroll a card sideways to reach the figure it is named
   after. Dish 37's «Лига водителей» is drawn in that column
   (design/app.html:2628) with сум/км as its third of four columns, so the
   number the card exists for was the one off the edge.
   The drawing itself carries this rule — design/app.css:948,
   `#p-analytics table{min-width:0}` — for exactly the same reason at exactly
   the same place, and this is that rule where the product's columns are
   decided rather than where a page is named. A narrow table wraps its cells,
   which is tighter than a wide one and readable, and no column disappears. */
.gcn .tw table{min-width:0}
/* At a third of the width the sixteen-pixel gutters are half the cell. */
.gcn .tw td, .gcn .tw th{padding-left:10px;padding-right:10px}
/* The SAME rule for the wide column of a two-column run, and the same argument
   read one step further. `.tw table{min-width:920px}` was measured for a wide
   column that IS the page; inside a `.g2` at 1440px that column is about 810px,
   so a 920px table hangs 110px over its card's edge — and what hangs over is
   the LAST column, which on a queue is the row's controls. Found on the
   2026-09-06 shot of «Обзор»: «Закрыть: неважно» read «Закрыт».
   `assertNothingIsCutOff` cannot see it, because the page does not scroll and
   the card does — the same blindness recorded for the narrow column above and
   for a flex item clipped by itself. A table that wraps its cells is tighter
   than one that hides a control behind a horizontal scrollbar nobody looks
   for. */
.g2 .gc .tw table{min-width:0}

/* ── the segmented control (design/app.html: `.seg`, 49 places) ───────────── */
/* One group, two or more options, exactly one of them current. It is drawn as a
   row of buttons inside a tinted well, which is what makes «this is one choice»
   readable at a glance instead of «these are two buttons».
   Every option is a real <button>: it either opens a screen or performs an act,
   and REQ-UIX-021 keeps the option that would do neither off the wire. */
/* It does NOT wrap. A choice with five options — the period selector on three
   screens — wrapped into three lines at 360 px and pushed the first card 395 px
   down the page, which is a person scrolling past the chrome to reach the
   answer «Обзор» exists to give. It scrolls sideways instead, the way the wide
   tables of this product already do (`.tw`). */
/* And the scroll needs a signal, or it reads as broken rather than scrollable.
   2026-09-15: the owner's own phone screenshots of «Контроль газа», «Обзор»
   and «Карта: история» all show the same five-option switch with its third
   option sliced mid-word at the well's right edge — this harness renders with
   Chrome's `--hide-scrollbars` and a resting phone screen shows exactly the
   same nothing, because a touch scrollbar is invisible until touched. Two
   background layers fix it with no JS: a shadow fixed to the WELL's own edge
   (`attachment:scroll`, always there) and a cover the same colour as the well,
   glued to the CONTENT's trailing edge (`attachment:local`, moves with what
   scrolls) that slides over the shadow and erases it the moment there is
   nothing left past the visible options. At rest, with more than fits, the
   fade is the last thing drawn; scrolled to the true end, the cover is. */
.segw{display:flex;gap:3px;padding:3px;border-radius:10px;
  flex-wrap:nowrap;overflow-x:auto;max-width:100%;min-width:0;
  background:
    linear-gradient(to left, var(--s3) 0, var(--s3) 3px, transparent 30px) right/30px 100% no-repeat local,
    linear-gradient(to left, rgba(0,0,0,.55), transparent) right/22px 100% no-repeat scroll,
    var(--s3)}
.seg{font-size:12px;font-weight:580;padding:5px 13px;border-radius:9px;color:var(--tx2);
  cursor:pointer;border:none;background:none;font-family:var(--font);white-space:nowrap}
.seg:hover{color:var(--tx1)}
.seg.on{background:var(--ok-d);color:var(--ok);box-shadow:inset 0 0 0 1px var(--ok-b)}

/* ── the chart primitive (G-1) ────────────────────────────────────────────── */
/* Three shapes of one picture, copied from the drawing's own rules:
     bars   design/app.html:835  — a labelled row per reading
     gauge  design/driver.html:311 — one wide track under a number
     fill   design/app.html:4196 — one short track inside a table cell
   The track is painted by the server's own per-cent (Bar.Fill), which view.go
   refuses unless it is a per-cent between 0 and 100: there is no arithmetic
   here and no threshold, and the colour comes from the server's Tone. */
.bars{display:grid;gap:8px}
.br{display:grid;grid-template-columns:minmax(30px,auto) minmax(0,1fr) minmax(92px,auto);
  align-items:center;gap:10px}
.bl{font-size:11.5px;color:var(--tx3);white-space:nowrap}
/* A chart whose labels are WORDS, and why it needs a selector that outranks the
   drawing's own.
   `design/app.css` sets `.br{grid-template-columns:30px 1fr 92px}` and `.bl`
   without `white-space`, which is right for the chart it was drawn for — «Пн»,
   «Вт», «Ср» on «Расход по дням». `adopt_css.py` appends the drawing AFTER this
   file, so those two rules win on order over the ones above, and the label
   column becomes a hard thirty pixels. «День парка одной полосой» puts «Стоял
   без двигателя» in that column: read on the 1440 px shot of 2026-09-06 the
   words ran under the bar and were unreadable.
   Specificity rather than order is what settles it — `#main .bars .br` outranks
   `.br` wherever it stands — and the column is `max-content` so a chart of short
   labels is not widened by a rule written for a chart of long ones. */
#main .bars .br{grid-template-columns:minmax(30px,max-content) minmax(0,1fr) minmax(92px,auto)}
#main .bars .bl{white-space:nowrap}
.bbg{height:7px;border-radius:4px;background:var(--s3);overflow:hidden}
.bf{height:100%;border-radius:4px;background:var(--ok)}
.bf.tone-warn{background:var(--wn)}
.bf.tone-bad{background:var(--dg)}
.bf.tone-info{background:var(--in)}
.bf.tone-muted{background:var(--tx3)}
.bv{font-size:11.5px;color:var(--tx2);text-align:right;overflow-wrap:anywhere}
/* At a telephone's width a three-column grid of 30 + track + 92 leaves the
   track about forty pixels wide, which is not a picture. The row becomes two
   lines: the label and the reading on one, the track under them full width. */
@media (max-width:560px){
  .br{grid-template-columns:minmax(0,1fr) auto;gap:4px 10px}
  .bl{grid-row:1;grid-column:1}
  .bv{grid-row:1;grid-column:2;text-align:right}
  .bbg{grid-row:2;grid-column:1 / -1}
}
.gauge{height:9px;border-radius:5px;background:var(--s3);overflow:hidden;margin:9px 0 6px}
.gfill{height:100%;border-radius:5px;background:var(--ok)}
.gfill.tone-warn{background:var(--wn)}
.gfill.tone-bad{background:var(--dg)}
.gfill.tone-info{background:var(--in)}
.gfill.tone-muted{background:var(--tx3)}
.gv{font-size:12.5px;color:var(--tx2);overflow-wrap:anywhere}
.fillw{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.fillb{width:64px;height:6px;border-radius:4px;background:var(--s3);overflow:hidden;flex:none}
.fillf{height:100%;border-radius:4px;background:var(--ok)}
.fillf.tone-warn{background:var(--wn)}
.fillf.tone-bad{background:var(--dg)}
.fillf.tone-info{background:var(--in)}
.fillf.tone-muted{background:var(--tx3)}

/* ── the bar a viewing session carries ────────────────────────────────────── */
/* REQ-IDN-106: on every screen, and saying three things at once — that a
   platform operator opened it, whose data it is, and which lens is in force.
   It wraps rather than scrolls: at 360px it becomes three lines and stays
   entirely on the screen (REQ-UIX-043), which is what a bar that must be READ
   has to do. The colour is the warning one on purpose: this is not the
   customer's own workplace and it must not look like it. */
.sesbar{margin-bottom:13px;min-width:0}
.sesbar .vph{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;margin-bottom:15px;flex-wrap:wrap}
.sesbar .vt{font-size:21px;font-weight:670;letter-spacing:-.02em;min-width:0;overflow-wrap:anywhere}
.sesbar .vbtn{text-decoration:none}
.sesbar .card{margin-bottom:0}

/* ── page ─────────────────────────────────────────────────────────────────── */
.ph{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:15px;gap:16px}
.pt{font-size:21px;font-weight:670;letter-spacing:-.02em}
.ps{font-size:12.5px;color:var(--tx3);margin-top:3px}
/* margin-left:auto packs the meta and the action area together at the RIGHT
   edge. Without it, justify-content:space-between spreads three children and
   puts the timezone in the middle of the header — and the action area is not
   where design/app.html puts it, which is hard against the right edge, bottom
   aligned with the title (`.ph{justify-content:space-between;
   align-items:flex-end}`, app.html:171). With no action area the two children
   behave exactly as they did before this line. */
.pmeta{font-size:11px;color:var(--tx3);text-align:right;line-height:1.7;flex:none;
  margin-left:auto}
/* The page's action area, copied from design/app.html:174 rather than
   re-invented: the same display, the same 8px gap, the same refusal to shrink.
   `.btn` and `.btn-p` were already this file's and are already the drawing's
   own rule (app.html:175-178), so a page control needs no button style of its
   own. */
.pa{display:flex;gap:8px;flex-shrink:0}

.card{background:var(--s1);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--shadow);overflow:hidden;margin-bottom:13px}
.ch{padding:13px 16px;border-bottom:1px solid var(--line);display:flex;
  justify-content:space-between;align-items:center;gap:12px}
.ct{font-size:13.5px;font-weight:620}
.cs{font-size:11.5px;color:var(--tx3);font-weight:450;margin-left:7px}
.cb{padding:15px 16px}

/* The scroll container a wide table lives in. A table's used width can never go
   below its own min-content, so a card narrower than that clips it and the
   right-hand columns disappear silently. overflow-x:auto turns that into a
   scroll; the width:100% below keeps the ordinary case looking exactly as it
   did, because a table that fits produces no scrollbar at all. */
.tw{width:100%;overflow-x:auto}
table{width:100%;border-collapse:collapse}
/* The width below which this table stops being readable rather than merely
   tight. A table's own floor is its min-content, and at a 980px window — which
   is what a telephone asking for the desktop site reports — that floor put
   «25 384» on three lines and every sentence one word per line. Below 920px
   the table keeps its shape and the container scrolls; above it, nothing here
   applies and the desktop is exactly what it was. */
.tw table{min-width:920px}
th{font-size:10px;font-weight:660;letter-spacing:.07em;text-transform:uppercase;color:var(--tx3);
  text-align:left;padding:9px 16px;background:var(--s3)}
td{padding:11px 16px;font-size:12.5px;color:var(--tx2);border-top:1px solid var(--line);
  vertical-align:top}
/* Cell.Band — the drawing's own highlighted summary row (design/app.html
   #p-billing:5790, «Итого по 24 приборам»), the same background its header
   wears rather than an ordinary row's. */
td.band{background:var(--s3)}
td b{color:var(--tx1);font-weight:580}
.sub{display:block;font-size:11px;color:var(--tx3);margin-top:2px}
.u{font-size:11px;color:var(--tx3);margin-left:4px}
.absent{font-style:normal}
/* An absent value is the drawing's amber tag (design/app.html:1905-1913, `.tag.g-w`).
   The server's absent string can be a whole sentence, so unlike a chip holding a
   number it may wrap. */
.absent.mut{color:var(--tx3);font-style:normal;background:none;border:0;white-space:normal}
td .tag,.kvr .tag,.tv .tag{font-family:var(--font)}
.lnk{cursor:pointer;border-bottom:1px solid var(--line-s)}
.lnk:hover{color:var(--ok)}
/* A link that IS a cell's value wraps; a link that is a CONTROL does not.

   The drawing's .lnk is white-space:nowrap (design/app.css:281) and that is
   right for what the drawing puts in a cell: «открыть», «скачать»,
   «Журнал платформы» — short phrases a person presses, which must not
   break in half. The drawing NEVER puts a VALUE inside one: on «Список
   клиентов» (design/app.html:3996) the customer's name is a plain <b>
   inside a tr.go row, and the control beside it is a separate .alb.

   Both shells DO put a value there — REQ-IDN-106 makes the customer's name the
   way into the customer's own interface, and REQ-UIX-021 makes a cell that
   leads somewhere a real control — so a value inherited a nowrap written for
   control labels. A value that cannot wrap is a column that cannot shrink.

   Measured on the console at 1440 px with thirty customers (2026-09-07): the
   customers table's min-content was 1145.7 px inside a 1142 px card, so the
   last column («Журнал») stood 3.7 px outside it and the card had a
   horizontal scrollbar for four pixels. With this rule the min-content is
   1089.4 px — 53 px of slack — and, which matters more, the name column's
   contribution is bounded by its longest WORD instead of by the whole name, so
   a real customer name can no longer widen the table at all. The console draws
   TEN columns where the drawing draws six, so this table has no room to spare.

   The selector is the cell's DIRECT child: a control inside a cell is .alb
   inside .ala and is not touched. It covers all three forms because the two
   shells build the holder differently — a.lnk and button.lnk in platform.js,
   span.lnk or b.lnk in app.js — and a rule that held on one surface only is how
   «Обзор» once shipped with two different layouts. Specificity, not order,
   settles it against the adopted .lnk further down this file. */
#main .card td > .lnk{white-space:normal}
/* A .lnk that is a <button> rather than an <a>. The platform console opens a
   screen of the SAME document — there is no address to put in a href — and a
   button is what that is, honestly. Everything a browser gives a button by
   default is stripped so that the two forms of .lnk are indistinguishable to a
   reader: the difference is about what the control does, not what it looks
   like. text-align:inherit matters inside a table cell, where a button would
   otherwise centre its own contents against every neighbouring cell. */
button.lnk{background:none;border:0;border-bottom:1px dotted var(--line-s);
  padding:0;margin:0;font-family:inherit;font-weight:inherit;font-size:11.5px;line-height:inherit;
  color:var(--tx2);text-align:inherit;cursor:pointer}
button.lnk:hover{color:var(--tx1);border-bottom-color:var(--tx3)}
/* .why is the drawing's card-level «Почему так ↗» (design/app.html, `.why a`,
   e.g. :1293) — REQ-UIX-054's D-191 amendment names it the pointerless
   carrier of a card's own explanation, beside the pointer-device `title`
   originControl already carries (2026-09-22). The drawing draws it as an
   <a> to notes.html, which is the DESIGNER's own rationale file and never
   shipped; the product's own carrier opens the SAME words REQ-UIX-019
   already sends (the origins behind this card's values) in this shell's own
   dialog, so it is a <button>, styled to read exactly like the drawing's
   link — `.why a`'s own rules, copied here for the one part of speech the
   drawing did not draw a button version of, the same way `button.lnk`
   above stands beside `.lnk` for the identical reason. */
.why button{background:none;border:0;padding:0;margin:0;font:inherit;cursor:pointer;
  font-size:11px;color:var(--tx3);text-decoration:none;
  border-bottom:1px dotted var(--ln);padding-bottom:1px}
.why button:hover{color:var(--tx1);border-bottom-color:var(--tx3)}
.why button::after{content:"\2009\2197";font-size:9px;vertical-align:1px}
/* Screen.Why can carry more than one link (design/app.html:437's two —
   «экран руководителя» and «восемь пунктов меню»); the drawing separates them
   with a plain space in its own markup, which a button-to-button neighbour
   has none of by default. */
.why button + button{margin-left:10px}
/* REQ-UIX-042: the tier is a size, and only a size. Both readings are always
   present, always in this order; .lead is the one the server said to draw
   large for this role. No rule below hides either of them. */
.duo{display:inline-block}
.duo-p,.duo-m{display:block}
.duo-p:not(.lead),.duo-m:not(.lead){font-size:11px;color:var(--tx2);margin-top:2px}
.duo .lead{font-size:15px;font-weight:600;color:var(--tx1)}
.flag{display:inline-block;font-size:10px;font-weight:640;padding:1px 6px;border-radius:20px;
  background:var(--wn-d);color:var(--wn);margin-left:5px}

.tone-good{color:var(--ok)}
.tone-warn{color:var(--wn)}
.tone-bad{color:var(--dg)}
.tone-info{color:var(--in)}
.tone-muted{color:var(--tx3)}

.kvr{display:flex;justify-content:space-between;gap:12px;padding:9px 0;
  border-bottom:1px solid var(--line);font-size:12.5px}
.kvr:last-child{border-bottom:none}
.kvr .l{color:var(--tx3)}
.kvr .v{color:var(--tx1);font-weight:560;text-align:right}
/* The tone of a value in a key-and-value list.
 *
 * These five rules exist because `.kvr .v` (two classes) outranks `.tone-bad`
 * (one), so every tone the server sent on a Fact was silently overridden and
 * every key-and-value list in the product painted its values in the ordinary
 * colour. Found by looking at a rendered console screen where «не трогать»
 * stood in white beside the same words in red in the table above it — a defect
 * no test could see, because the server was sending the tone correctly and the
 * client was setting the class correctly. REQ-UIX-024 keeps the WORD as the
 * carrier of the meaning, which is why this was a degradation rather than a
 * wrong answer; it is still the difference between a screen that is read and a
 * screen that is scanned. */
.kvr .v.tone-good{color:var(--ok)}
.kvr .v.tone-warn{color:var(--wn)}
.kvr .v.tone-bad{color:var(--dg)}
.kvr .v.tone-info{color:var(--in)}
.kvr .v.tone-muted{color:var(--tx3)}

/* ── a Fact list as the SOLE content of a full-width card ─────────────────
 *
 * Defect seen by the owner on a 2000 px monitor, 2026-09-07: `.kvr` is
 * `display:flex;justify-content:space-between`, and a card with no table and
 * nothing to sit beside it spans the whole content column — up to ~1700 px.
 * The label landed at the left edge, the value at the right, with empty
 * space between them («Сводка по парку» on «Автопарк», «Газ на борту» /
 * «Давление и температура трубы» on the vehicle card). The drawing never
 * does this — `.kvr` in design/app.html (283 uses) stands only in narrow
 * two-column cells and side panels, never full width (D-131).
 *
 * The repair keeps `.kvr`'s own markup and every child it draws untouched —
 * the label, the value, its unit, its flags, its `?` hint — and turns only
 * the CONTAINER into a grid of tiles: label above, value below, the shape
 * the drawing's own `.kpi`/`.kl`/`.kv` draws for a headline row
 * (app.html:341-456). facts() and seriesFallback() both put `.kvr` rows
 * straight into `.cb`, which is the container this keys on.
 *
 * `#main >` is the ID-specificity trick already in force at `#main .bars
 * .br` above: an ID outranks any run of classes, so this beats the ADOPTED
 * `.kvr{display:flex...}` and `.kvr .v{text-align:right}` further down this
 * file regardless of source order — the specificity trap this file's own
 * comments say has bitten twice does not get a third turn here.
 *
 * `#main > .card >` (not merely `.card`) is what keeps this OFF the narrow
 * two-column cell (`.gcn`, 340 px) and the map's side panel (`.pside`): both
 * sit inside an intermediate wrapper (`.g2 .gc`, `.mh`) and are never a
 * direct child of `#main`, so they stay exactly the row shape the drawing
 * already draws them as. `:has(> .kvr)` is what keeps this OFF a card's
 * OTHER `.cb` — the one series() builds for a bars chart or a gauge, which
 * carries no `.kvr` at all and must not be squeezed into a grid cell.
 *
 * The 1220 px fold below is the same one `.kpis` already uses a few hundred
 * lines below the adoption marker — kept at the same width on purpose —
 * stepped to 3 columns rather than 2, because a Fact tile carries more prose
 * (a caveat, a period, an origin) than a headline KPI does. */
/* 2026-10-06 (T7 of _reports/2026-10-06-reviewer-page-pairs.md): the rule of 2026-09-07 that
   turned every `#main > .card > .cb` holding `.kvr` rows into a four-column grid of bordered
   boxes stood here and is gone. The drawing draws a fact list as ROWS — label left, value
   right, a 1px line between, 12.5px (design/app.css:327-331) — and tiles only where it draws
   `.kpis`. */

/* ── a row of headline numbers ────────────────────────────────────────────
 *
 * The shape a screen opens with: the few numbers that are read before anything
 * else on the page. The label stands above, the number is large, and the origin
 * is read out underneath — on a tile the origin is half the answer (a count of
 * customers means nothing without the split by state) and a telephone has no
 * hover to reveal a tooltip with.
 *
 * auto-fit + minmax is what carries it from 1440 px to 360 px with no media
 * query of its own: the tiles are one row on a desktop, two by two at 412 and
 * 360, and a single column below that. 150 px is the floor because «24 / 26»
 * with its label above it wraps mid-pair under it.
 *
 * The 1 px gap over the line colour is the separator: no border on the tile
 * itself, so the outer edges of the row stay flush with the card. */
.cb.tiles{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:1px;padding:0;background:var(--line)}
.tile{background:var(--s1);padding:14px 16px;min-width:0}
.tl{font-size:10px;font-weight:660;letter-spacing:.07em;text-transform:uppercase;
  color:var(--tx3)}
.tv{font-size:22px;font-weight:600;color:var(--tx1);margin-top:7px;line-height:1.25;
  overflow-wrap:anywhere}
.tv .u{font-size:11px}
.tv .absent{font-size:13px;font-weight:500}
.tsub{font-size:11px;color:var(--tx3);margin-top:6px;line-height:1.55;overflow-wrap:anywhere}
/* The same specificity trap `.kvr .v` fell into, fixed at the same time it is
 * created: `.tv` is one class and so is `.tone-bad`, and the later rule wins —
 * so without these five the server's tone would be silently inert on every
 * tile, which is a defect no test that reads the response can see. */
.tv.tone-good{color:var(--ok)}
.tv.tone-warn{color:var(--wn)}
.tv.tone-bad{color:var(--dg)}
.tv.tone-info{color:var(--in)}
.tv.tone-muted{color:var(--tx3)}

.empty{padding:34px 20px;text-align:center}
.et{font-size:13.5px;font-weight:600;color:var(--tx2)}
.es{font-size:12px;color:var(--tx3);margin-top:5px;line-height:1.6;max-width:64ch;
  margin-left:auto;margin-right:auto}
.fchips{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-top:11px}
.fchip{font-size:11px;padding:3px 9px;border-radius:20px;background:var(--s3);
  border:1px solid var(--line);color:var(--tx2)}

.errb{display:flex;gap:11px;padding:15px 16px}
.erri{width:26px;height:26px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:var(--dg-d);color:var(--dg);font-size:14px;font-weight:700}
.errt{font-size:12.5px;font-weight:600;color:var(--tx1)}
.errs{font-size:11.5px;color:var(--tx3);margin-top:3px;line-height:1.55}

.note{margin:0;padding:11px 16px;border-top:1px solid var(--line);
  font-size:11.5px;color:var(--tx3);line-height:1.6}

.ala{display:flex;gap:6px;margin-top:9px;flex-wrap:wrap}
.alb{font-size:11px;font-weight:570;padding:4px 10px;border-radius:7px;cursor:pointer;
  border:1px solid var(--line-s);color:var(--tx2);background:none;font-family:var(--font)}
.alb:hover{color:var(--tx1);background:var(--s3)}
.alb.bad{color:var(--dg);border-color:var(--dg-d)}
.alb:disabled{cursor:default;opacity:.55}
.alb:disabled:hover{color:var(--tx2);background:none}
/* .albd wraps ONE disabled control and the reason it is disabled
   (Action.Disabled/DisabledReason, internal/httpapi/view.go, added
   2026-09-29 for «Перевыпустить пароль» alone — a deliberate exception to
   REQ-UIX-021's usual "absent, not dark" rule, and the one place this
   console draws a control it will not act on). The reason sits directly
   under the button rather than beside it, at the same width, because a
   caption a person has to hunt for beside a disabled control is not a
   control that says why. */
.albd{display:flex;flex-direction:column;gap:3px;max-width:260px}
.albd .mut{font-size:11px;line-height:1.4}
/* The same row of controls INSIDE a table cell — the drawing's per-row «alb»
   (design/app.html:4070-4096), which stands in a column of its own at the end
   of the row. It keeps the buttons' own gap and loses only the top margin the
   card version needs: in a cell the margin pushes the row taller than every
   neighbouring cell and the table stops lining up. */
td>.ala{margin-top:0}

.sk{border-radius:6px;background:linear-gradient(90deg,var(--s3) 0%,var(--s2) 46%,var(--s3) 92%);
  background-size:220% 100%;animation:sh 1.5s ease-in-out infinite;height:12px;margin-bottom:9px}
@keyframes sh{0%{background-position:120% 0}100%{background-position:-120% 0}}
.stale{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--wn);margin-top:9px}

.btn{font-size:12.5px;font-weight:560;padding:7px 14px;border-radius:var(--r-s);cursor:pointer;
  border:1px solid var(--line-s);background:var(--s1);color:var(--tx1);font-family:var(--font)}
.btn-p{background:var(--ok);border-color:var(--ok);color:#fff}
[data-theme="night"] .btn-p{color:#052018;font-weight:640}
.btn.wide{width:100%;text-align:center;padding:12px 14px;font-size:14px;font-weight:620}

/* ── sign-in ──────────────────────────────────────────────────────────────── */
.lgn{position:fixed;inset:0;z-index:40;background:var(--bg);
  display:grid;grid-template-columns:1fr 508px}
.lgn[hidden]{display:none}
.lg-bg{position:absolute;inset:0;background:
  radial-gradient(40% 36% at 24% 22%,var(--map1),transparent 68%),
  radial-gradient(34% 30% at 80% 18%,var(--map2),transparent 68%),
  radial-gradient(42% 38% at 62% 86%,var(--map3),transparent 70%),
  radial-gradient(26% 24% at 18% 84%,var(--map4),transparent 68%),
  var(--mapbase)}
.lg-mesh{position:absolute;inset:0;opacity:.5;
  background-image:linear-gradient(var(--mesh) 1px,transparent 1px),
                   linear-gradient(90deg,var(--mesh) 1px,transparent 1px);
  background-size:64px 64px}
.lg-l{position:relative;overflow:hidden;display:flex;flex-direction:column;
  justify-content:space-between;padding:44px 46px;z-index:1}
.lg-l::after{content:"";position:absolute;left:0;right:0;bottom:0;height:66%;
  background:linear-gradient(to top,var(--bg) 6%,transparent 100%);opacity:.86;pointer-events:none}
.lg-rd{position:absolute;height:2.5px;border-radius:3px;
  background:linear-gradient(90deg,transparent,var(--ok) 18%,var(--ok) 82%,transparent);opacity:.42}
.lg-in{position:relative;z-index:1}
.lg-brand{display:flex;align-items:center;gap:12px}
.lg-bn{font-size:17px;font-weight:670;letter-spacing:-.015em}
.lg-claim{font-size:38px;font-weight:680;letter-spacing:-.032em;line-height:1.14;
  max-width:15ch;margin-bottom:15px}
.lg-sub{font-size:14px;color:var(--tx2);line-height:1.65;max-width:44ch}
.lg-r{position:relative;display:flex;flex-direction:column;justify-content:space-between;
  padding:30px 54px 26px;background:var(--s1);border-left:1px solid var(--line);z-index:1}
/* The brand is in the left half, which the narrow layout does not draw. This is
   the compact copy that appears there instead, so the product still says its
   name on the first screen a person ever sees. */
.lg-head{display:flex;align-items:center;justify-content:flex-end;gap:14px}
.lg-mb{display:none;align-items:center;gap:10px;min-width:0}
.lg-top{display:flex;justify-content:flex-end;gap:7px;flex:none;flex-wrap:wrap}
/* The message and the form are ONE block of the sign-in column, and this is
   the fix for a defect a browser found: with #signin-error a direct child of
   .lg-r (a column with justify-content:space-between) the message was pushed
   to the top of the column and the form began some 180px below it, so at 1280
   px the reason for a refusal read as belonging to nothing. The wrapper is
   what puts them back together; the message stays OUTSIDE the form element, so
   it still survives the form being withdrawn when branding cannot be fetched. */
.lg-mid{width:100%;max-width:352px;margin:0 auto}
.lg-mid .errb{margin-bottom:14px;background:var(--dg-d);border:1px solid var(--line);
  border-radius:var(--r-s)}
.lg-form{width:100%}
.lg-t{font-size:25px;font-weight:680;letter-spacing:-.025em}
.lg-s{font-size:13px;color:var(--tx3);margin-top:6px;line-height:1.55;margin-bottom:24px}
.lg-s b{color:var(--tx1);display:block;margin-bottom:4px}
.fld{margin-bottom:14px}
.fld label{display:block;font-size:11px;font-weight:640;letter-spacing:.05em;
  text-transform:uppercase;color:var(--tx3);margin-bottom:6px}
.inp{width:100%;height:44px;border-radius:12px;background:var(--s3);
  border:1px solid var(--line);padding:0 14px;font-size:13.5px;color:var(--tx1);
  font-family:var(--font)}
.inp:focus{outline:none;border-color:var(--ok-b);box-shadow:0 0 0 3px var(--ok-d)}
/* The second factor (REQ-IDN-122, REQ-IDN-123). The key and the recovery codes
   are values a person copies by eye, so they are monospaced and spaced out:
   every ambiguity between two characters here costs a trip to the server. */
.fkey{margin-bottom:18px}
.fsec{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:15px;letter-spacing:.12em;word-break:break-all;padding:10px 12px;
  border-radius:10px;background:var(--s3);border:1px solid var(--line)}
/* The address, drawn as the link it is rather than as a wall of characters.
   It is the FIRST thing a person on a telephone should reach, so it is sized
   like a control and not like a footnote — the old 10.5px grey block was what
   made «scan the address» read as an instruction with no object. */
.furi{display:block;margin-top:10px;font-size:13px;color:var(--ok);
  text-decoration:none;text-align:center;padding:9px 12px;border-radius:10px;
  border:1px solid var(--line);background:var(--s3)}
.furi:hover{border-color:var(--ok-b)}
/* The picture the words promise. White padding around it deliberately: a QR on
   a dark surface is not read by every camera, and the quiet zone is part of the
   symbol rather than decoration. Centred and bounded so it stays inside a
   telephone's width. */
.fqr{display:block;margin:0 auto 12px;width:180px;height:180px;
  background:#fff;padding:10px;border-radius:10px;box-sizing:content-box}
.fcodes{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-bottom:20px}
.fcode{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px;
  letter-spacing:.08em;padding:8px 10px;border-radius:10px;background:var(--s3);
  border:1px solid var(--line);text-align:center}

.lg-foot{display:flex;justify-content:space-between;align-items:center;
  font-size:11px;color:var(--tx3)}

/* ── narrow: the rail folds away ──────────────────────────────────────────── */
/* 980, not 860: the drawing folds the rail at ≤980 (design/app.css), and the
   adopted copy of that rule hid the rail between 861 and 980 while the
   product's drawer, scrim and header rules below did not apply — a phone in
   Chrome's «desktop site» mode (≈980 px) got the folded rail with the header
   over the open drawer. He saw it on 2026-09-07 morning. One breakpoint. */
@media (max-width:980px){
  /* Sign-in. One column, the brand at the top, and the page scrolls rather
     than clipping when a keyboard takes half the screen. */
  .lgn{display:block;overflow-y:auto}
  .lg-l{display:none}
  /* Top-packed, not centred. The form floating in the middle of an empty
     screen was one of the things the user saw; and on a telephone the keyboard
     takes the lower half the moment the login field is touched. */
  .lg-r{min-height:100vh;padding:24px 22px 20px;border-left:none;
    justify-content:flex-start;gap:32px}
  .lg-head{justify-content:space-between}
  .lg-mb{display:flex}
  .lg-mid{max-width:420px}
  .lg-s{margin-bottom:18px}
  .lg-foot{margin-top:auto;flex-wrap:wrap;gap:4px 14px;padding-top:18px}

  /* The shell. The rail becomes a drawer over the content instead of a screen
     of menu above it: a person opening «Автопарк» must see a gas figure, not
     eight section names. It is chrome, so it keeps the chrome material (D-071). */
  .menu{display:grid}
  /* `.app .side`, not `.side`: the drawing's stylesheet is appended AFTER this
     section and its base rule `.side{position:absolute;z-index:5}` outranked
     this one by order alone, so the open drawer slid UNDER the header
     (`.top` is also 5 in the drawing, and later in the DOM). He saw it on his
     phone twice — 2026-09-05 in the drawing, 2026-09-07 on the site. Two
     classes beat one whatever the order. */
  .app .side{position:fixed;left:0;top:0;bottom:0;width:min(280px,84vw);z-index:40;
    border-radius:0 var(--r-l) var(--r-l) 0;
    transform:translateX(-102%);visibility:hidden;
    transition:transform .2s ease,visibility 0s linear .2s}
  .app.nav-open .side{transform:none;visibility:visible;transition:transform .2s ease}
  .app.nav-open .nscrim{display:block;position:fixed;inset:0;z-index:35;
    background:rgba(6,9,13,.62)}

  /* The header stays with the person while the page scrolls; it is how the
     control that opens the rail stays reachable. */
  .app .top{position:sticky;left:auto;right:auto;top:0;height:auto;z-index:20;
    border-radius:0;border-left:none;border-right:none;border-top:none;
    padding:9px 12px;gap:10px;flex-wrap:wrap}
  .menu{order:0}
  /* flex-basis:0, not auto. A wrapping flex line is broken on the item's
     HYPOTHETICAL size, before any shrinking, so with basis:auto a long
     customer name puts the avatar on a line of its own. */
  .search{order:1;flex:1 1 0}
  .ava{order:2}
  .tpills{order:3;flex:1 1 100%;flex-wrap:wrap;justify-content:flex-start;gap:7px}

  .main{position:relative;left:0;right:auto;top:0;bottom:auto;z-index:2;
    padding:14px 14px 26px}
  /* .app may overflow again now that the backdrop is clipped by .canvas: a
     sticky header inside an overflow:hidden ancestor never sticks. */
  .app{overflow:visible}
}

/* ── telephone: a row of a table is not a row ─────────────────────────────── */
@media (max-width:560px){
  .main{padding:12px 10px 24px}
  .lg-r{padding:22px 18px 18px}

  .ph{flex-direction:column;align-items:flex-start;gap:6px;margin-bottom:13px}
  .pmeta{text-align:left;flex:1 1 auto;line-height:1.6;margin-left:0}
  /* design/app.html:547 — at this width the action area is full width and its
     controls wrap instead of being squeezed. */
  .pa{width:100%;flex-wrap:wrap;align-items:center}
  /* The choice shares the line with the acts beside it and scrolls inside
     whatever is left. flex-basis is 0 and not auto: a wrapping flex line is
     broken on the item's HYPOTHETICAL size, so with basis:auto a five-option
     choice claims its full unwrapped width first and puts «Экспорт» on a line
     of its own — 42 px that pushed the first card past the fold. */
  /* ...but not below the width at which it stops being readable. min-width was
     0 here, and on 2026-08-30 «Прошивки» grew a THIRD control in this area:
     «Журнал платформы» + «＋ Загрузить прошивку» take 341 px of the 340 px a
     360 px telephone has, so the choice between them was flexed to a 10 px
     sliver — present, drawn, countable by every assertion, and impossible to
     see or press. A minimum makes the line break instead: the group drops to a
     line of its own and scrolls inside it. It is min() and not a bare 10rem so
     that a narrower area than the minimum still cannot overflow. */
  /* «Scrolls inside it» was the sentence above's promise from the day it was
     written, and the rule that makes it true was missing until 2026-09-05:
     «Аналитика» put a 175 px vehicle pill beside a three-option choice at
     360 px, the choice was flexed to its 160 px minimum, and «30 дней» was cut
     off by its own well — present, drawn, countable by every assertion, and
     half invisible. Found by opening the screenshot and by nothing else.
     `overflow-x` and NOT a wider minimum: 14rem was tried first and put
     «Экспорт» on a line of its own on «Обзор», which is the defect the
     paragraph above this one already records. */
  .pa .segw{flex:1 1 0;min-width:min(100%,10rem);overflow-x:auto}
  /* And the meta goes last. The document order is title, meta, controls,
     because at a desk the controls must be the right-most thing on the row;
     folded, that would put the timezone between the lead and the controls,
     and the drawing puts the controls directly under the lead. One `order`
     on the block that has to move, not two. */
  .pmeta{order:2}
  .ch{flex-wrap:wrap;padding:12px 14px}
  .ch>div:first-child{min-width:0;flex:1 1 auto}
  .cb{padding:13px 14px}

  /* REQ-UIX-042's two readings and REQ-UIX-017's flags need room a sixth of
     412px does not have. Six columns became four wrapped lines in a sixty-pixel
     cell, so at this width the table is not a table: every row is a block and
     every value carries the name of the column it came from. Nothing is
     dropped and nothing is hidden — the state label, the flags, the unit and
     the provenance are all still on the screen. */
  /* min-width:0 undoes the desktop floor above. Left in place it would make
     every stacked row 920px wide and put the whole page off the screen. */
  .card table,.card tbody{display:block;width:100%;min-width:0}
  .card .thr{display:none}
  /* Every table of `table()` is `.rt` and is drawn by the compact-card template at the end of this
     file; the labelled-line stack below is what is left for the tables that are not (the timeline
     switch, `.tlsw`). */
  .card table:not(.rt) tr{display:block;border-top:1px solid var(--line);padding:7px 0 9px}
  .card table:not(.rt) tr:first-child,.card table:not(.rt) .thr+tr{border-top:none}
  .card table:not(.rt) td{display:block;width:auto;border-top:none;padding:6px 14px;font-size:13px}
  .card table:not(.rt) td[data-label]::before{content:attr(data-label);display:block;
    font-size:9.5px;font-weight:680;letter-spacing:.09em;text-transform:uppercase;
    color:var(--tx3);margin-bottom:3px}
  .card table:not(.rt) td b{font-size:14px}
  .duo{display:block}
  .flag{white-space:normal}

  /* N1 (render walk 2): a fact keeps its label on the left and its value on the right, on one line (the
     drawing's `.kvr` is a row at 360 too); only a value that cannot fit wraps under the label. */
  .kvr{flex-wrap:wrap;padding:8px 0}
  .kvr .v{margin-left:auto;max-width:100%;min-width:0;overflow-wrap:anywhere}

  .empty{padding:26px 14px}
  .note{padding:11px 14px}
}

/* ── the one dialog: publishing a firmware release ────────────────────────── */
/* REQ-OTA-069 and §3.5 of 07-ota.md. It is a native <dialog>, so Escape closes
   it, the page behind it is inert, and focus is trapped without a line of
   script written here to do any of the three.

   The hint under each field is a full sentence and is drawn at a readable size
   rather than as a footnote. On this dialog the hints ARE the rule — «версия
   читается из паспорта файла и вручную не вводится» is the whole reason the
   form has no version field — and a rule set in 9px grey is a rule nobody
   reads. */
.ala.pad{padding:0 16px 14px}
.ala.pad.first{padding:15px 16px 0}
.cb.afteracts{padding-top:11px}
.cellact{margin-top:5px}
.cellact .btn{display:inline-block;font-size:11px;padding:4px 10px;line-height:1.3;text-decoration:none}

/* margin:auto is written out because line 61 of this file takes it away. A
   modal dialog is centred by the user-agent stylesheet with `margin:auto`, and
   `*{margin:0}` at the top of this file wins over it: without this line the
   dialog is pinned to the top-left corner of the viewport and, at 360 px, runs
   off the right edge. Measured in Chrome on 2026-08-29, both widths.
   The two sizes are % rather than vw for the same reason: the containing block
   of a modal dialog IS the viewport, and vw counts a scrollbar that a phone
   does not have. */
.dlg{border:1px solid var(--line);border-radius:var(--r);background:var(--s1);
  color:var(--tx1);padding:0;margin:auto;
  width:min(560px,calc(100% - 24px));max-height:calc(100% - 48px)}
.dlg::backdrop{background:rgba(0,0,0,.55)}
.dlgf{padding:20px;overflow-y:auto;max-height:calc(100vh - 50px);box-sizing:border-box;
  position:relative}
.dlgt{font-size:17px;font-weight:660;letter-spacing:-.015em;margin-bottom:18px;
  padding-right:34px}
/* The way out of the window, and it carries no word on purpose: the server
   sends «Отмена» only beside a form (view.go refuses dialog buttons on any
   other shape), so a confirmation has no server-side word for it and a word
   written into the client would be one language compiled in. A symbol is not a
   word. It is 40 px square because it is the control a thumb reaches for
   first. */
.dlgx{position:absolute;top:12px;right:12px;width:34px;height:34px;line-height:1;
  font-size:20px;border-radius:9px;cursor:pointer;border:1px solid transparent;
  background:none;color:var(--tx3);font-family:var(--font)}
.dlgx:hover{color:var(--tx1);background:var(--s3);border-color:var(--line)}
/* What is about to happen, in the server's own words, above the control that
   does it (REQ-UIX-028). It is a SENTENCE and not a field label, so it is not
   the uppercased 11 px of «.fld label»: this is the one line in the window a
   person is meant to read rather than scan. */
.dlgm{font-size:13.5px;line-height:1.6;color:var(--tx1);margin-bottom:18px}
/* The same sentence when it belongs to a field: still a sentence, so it keeps
   none of «.fld label»'s capitals, spacing or weight. */
.fld label.dlgm{text-transform:none;letter-spacing:0;font-size:13.5px;
  font-weight:500;color:var(--tx1);margin-bottom:10px;line-height:1.6}
/* A field caption longer than a short caption (40 characters) is a phrase and not a
   tag: no capitals, no letter-spacing (D-199; a long caption in letter-spaced
   capitals is a line nobody reads). The server's `prose` flag decides the rest. */
.fld label.lbll{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:560;
  color:var(--tx2)}
/* The confirming button of an act whose tone is «bad». A destructive act and a
   saved setting must not be the same green. */
.btn-d{background:var(--dg);border-color:var(--dg);color:#fff;font-weight:640}

.chkl{display:flex;align-items:flex-start;gap:9px}
.chkl label{text-transform:none;letter-spacing:0;font-size:12.5px;font-weight:560;
  color:var(--tx1);margin:0}
.chk{width:17px;height:17px;flex:none;accent-color:var(--ok);margin:0}
select.inp{appearance:auto}
/* The refusal, drawn INSIDE the dialog. The person's next act is to choose a
   different file, and closing the dialog to show them why would make them start
   again in order to read it. */
.dlge{border:1px solid var(--dg-d);background:var(--dg-d);color:var(--dg);
  border-radius:10px;padding:10px 12px;font-size:12.5px;line-height:1.55;margin-bottom:14px}
/* B-63 (design-v2 20-b2.css): a refusal of a typed field is said on the field - the same field
   outlined in the danger colour with ONE line under it. */
.dlgf .bad{border-color:var(--dg);box-shadow:0 0 0 3px var(--dg-d)}
.rfl{margin-top:6px;font-size:11.5px;font-weight:600;color:var(--dg)}
.dlga{display:flex;gap:9px;justify-content:flex-end;margin-top:6px}

/* At 360px the two buttons stop sitting side by side and stack in DOM order,
   which puts «Сохранить» at the BOTTOM — nearest the thumb, and the harder of
   the two to reach by accident while scrolling the hints above it. */
@media (max-width:520px){
  .dlg{width:calc(100% - 16px)}
  .dlgf{padding:16px}
  .dlga{flex-direction:column}
  .dlga .btn{width:100%;padding:11px 14px;font-size:13.5px}
}

/* ── what a person is told when an act completes ─────────────────────────── */
/* It stands at the TOP of the screen the act returned to, on both shells, and
   it replaces window.alert — which hangs a headless browser for ever and
   therefore made every act's completion unverifiable by the one instrument this
   project checks its own screens with.

   Why a line on the screen rather than a modal: a modal after every act is a
   modal a person stops reading, and it stands between them and the result they
   pressed the button to see. This stands ABOVE that result, on the redrawn
   screen, so the outcome and its evidence are readable at once.

   It is not on a timer. A notice that erases itself tells nothing to the person
   who looked away for four seconds, and «what did that button do» is precisely
   the question they come back with. It goes when the person dismisses it or
   when they open another screen. */
.said{display:flex;gap:11px;align-items:flex-start;margin:0 0 16px;padding:13px 15px;
  border-radius:var(--r);border:1px solid var(--line);background:var(--s1);
  box-shadow:var(--shadow)}
.said-ok{border-color:var(--ok-b);background:var(--ok-d)}
.said-bad{border-color:var(--dg);background:var(--dg-d)}
.saidi{width:24px;height:24px;border-radius:50%;flex:none;display:grid;place-items:center;
  font-size:13px;font-weight:700;background:var(--s1)}
.said-ok .saidi{color:var(--ok)}
.said-bad .saidi{color:var(--dg)}
/* min-width:0 so a long sentence wraps inside the flex row instead of pushing
   the dismiss control off the side of a 360 px screen. */
.saidt{flex:1;min-width:0;font-size:13px;line-height:1.6;color:var(--tx1);
  overflow-wrap:anywhere}
/* A symbol and not a word: there is no server string for «закрыть» here, and a
   word written into the client would be one language compiled in. */
.saidx{flex:none;width:26px;height:26px;line-height:1;border-radius:8px;cursor:pointer;
  border:1px solid transparent;background:none;color:var(--tx3);font-size:17px;
  font-family:var(--font)}
.saidx:hover{color:var(--tx1);background:var(--s3);border-color:var(--line)}
@media (max-width:560px){
  .said{padding:12px 13px;gap:9px;margin-bottom:13px}
  .saidt{font-size:12.5px}
}

/* The copy control `told()` draws beside a one-time link (owner's order,
   2026-09-29): a read-only field a person can select by hand and a button
   that copies it for them. `flex-wrap` and `min-width:0` on the field are
   what `.saidt` already does above, for the same 360 px reason. */
.linkcopy{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-top:10px}
.linkcopy-field{flex:1 1 200px;min-width:0;font-family:ui-monospace,SFMono-Regular,
  Menlo,monospace;font-size:12.5px;padding:8px 10px;border-radius:10px;
  background:var(--s3);border:1px solid var(--line);color:var(--tx1)}
.linkcopy-btn{flex:none}
.linkcopy-status{flex:none;font-size:12px;color:var(--ok)}
@media (max-width:560px){
  .linkcopy{gap:6px}
  .linkcopy-field{font-size:12px;flex-basis:100%}
}

/* The consequence dialog's two lists («Что произойдёт» / «Что НЕ произойдёт»,
   design/app.html's operator dialogs, adopted 2026-09-04). Product-only
   markup: the drawing writes them as prose blocks, the shell draws them as a
   heading and a list so the two are told apart by shape and not by reading. */
.dlgc{margin:12px 0 0}
.dlgch{font-size:10.5px;font-weight:660;letter-spacing:.07em;text-transform:uppercase;color:var(--tx3);margin-bottom:5px}
.dlgc.wont .dlgch{color:var(--tx3)}
.dlgc ul{margin:0;padding-left:18px;font-size:12.5px;color:var(--tx2);line-height:1.55}
.dlgc.will ul{color:var(--tx1)}

/* ── «Карта: история» on a REAL map (D-163, REQ-UIX-092) ─────────────────────
   The drawing's own rules for this screen — `.mh`, `.mapc`, `.mh-leg`, the
   player's `.pl-*`, the ribbon's `.tl*` and the cause dots `.sd.st-*` — are
   adopted verbatim below and are NOT repeated here. What is here is the part
   the drawing has no word for, because the drawing draws a stand-in SVG where
   the product draws Leaflet:
     · the marker shapes, which are `divIcon`s in the product and `<g>`s in the
       drawing, so they need the same colours through different selectors;
     · the track's colours as a polyline CLASS, because Leaflet owns the
       element and the class is the only thing the server may decide;
     · the scrub, which is a native range styled to BE the drawing's `.pl-head`
       so that the head's position is the browser's and no per-cent is computed
       in the client;
     · the word drawn when the base layer is not there (REQ-UIX-006).
   The speed variables `--sp1…--sp3` are the drawing's own and are inherited
   from `.mh`. */
.mh .mapcard{padding:0}
.mapc .leaflet-container{position:absolute;inset:0;width:100%;height:100%;
  background:var(--s3);font-family:var(--font);z-index:1}
.mapc .mh-layers,.mapc .mh-attr,.mapc .mh-cap,.mapc .mh-noti{z-index:500}
/* The pills stand over a picture this product does not control, and the
   drawing's chosen state is a translucent green that is a state on a dark
   canvas and invisible on a light one — the browser walk of 2026-09-06 showed
   «Скорость Стоянки Места» as pale green words lying on a road. So over the
   map, and only there, the pill keeps the drawing's colour as its BORDER and
   its text and takes a solid ground of its own. */
.mapc .mh-layers .pill{background:var(--s1);border:1px solid var(--line);color:var(--tx2)}
.mapc .mh-layers .pill.act{border-color:var(--ok-b);color:var(--ok)}
/* The caption: the window and the zone the times are read in (REQ-UIX-003). */
.mh-cap{position:absolute;left:12px;bottom:8px;font-size:9.5px;color:var(--tx3);
  background:var(--s1);padding:2px 7px;border-radius:6px;opacity:.9;max-width:60%}
/* REQ-UIX-006: a base layer that did not arrive is a WORD and never a blank. */
.mh-noti{display:none;position:absolute;left:50%;top:12px;transform:translateX(-50%);
  max-width:82%;text-align:center;font-size:11px;line-height:1.45;color:var(--wn);
  background:var(--s1);border:1px solid var(--line);border-radius:8px;padding:6px 11px}
.mh-noti.on{display:block}
/* The track. The colour is picked by the band INDEX the server sent and never
   by comparing a speed against a threshold in the client (REQ-UIX-002). */
.geo-sp0{stroke:var(--sp1)} .geo-sp1{stroke:var(--sp2)} .geo-sp2{stroke:var(--sp3)}
.geo-sp3{stroke:var(--sp3)}
/* A break carries no line at all (REQ-MOV-033). What is drawn is a dashed ring
   at each end of it, which is the drawing's own `.st-silent`. */
.geo-gap{stroke:var(--tx3);stroke-width:2;stroke-dasharray:4 3;fill:none}
.geo-mk{display:grid;place-items:center;border-radius:50%;box-sizing:border-box;
  border:2.5px solid var(--s1);background:var(--tx3)}
.geo-mk .geo-lb{font-family:var(--font);font-size:13px;font-weight:700;color:#fff;line-height:1}
.geo-mk.st-fill{background:var(--in)} .geo-mk.st-idle{background:var(--wn)}
.geo-mk.st-park{background:var(--tx3)} .geo-mk.st-drop{background:var(--dg)}
.geo-mk.st-silent{background:var(--tx3)} .geo-mk.st-unknown{background:var(--line-s)}
/* Silence is a fact ABOUT a stop and not the cause of it, so it is a ring
   around the cause's colour rather than a colour of its own. */
.geo-mk.geo-ring{box-shadow:0 0 0 2px var(--s1),0 0 0 4px var(--tx3)}
.geo-mk.geo-pause{width:11px;height:11px;background:var(--s1);border:2px solid var(--tx3)}
.geo-mk.geo-place{border-radius:4px;background:var(--s1);border:1.2px solid var(--line-s)}
.geo-mk.geo-place .geo-lb{font-size:11px;color:var(--tx2)}
.geo-mk.geo-point{background:var(--s1);border-color:var(--line-s)}
.geo-mk.geo-point .geo-lb{color:var(--tx1)}
.geo-mk.geo-last{width:12px;height:12px;background:var(--ok);opacity:.8}
.geo-mk.geo-vehicle{background:var(--ok-d);border-color:var(--ok)}
.geo-mk.geo-vehicle::after{content:"";width:0;height:0;border:6px solid transparent;
  border-bottom-color:var(--ok);transform:rotate(var(--course,0deg)) translateY(-3px)}
/* A vehicle whose direction is NOT known keeps the disc and loses the chevron.
   The fallback in the rule above is `0deg`, which draws a perfectly convincing
   arrow pointing north — and «направление не определено» is exactly what
   REQ-MOV-003 says about a vehicle that was not moving. The disc still says
   where it is; nothing says where it is going. */
.geo-mk.geo-vehicle.geo-nocourse::after{content:none}
/* A pressed row puts one subject in focus. The rest are DIMMED and never
   removed: taking the day's other routes off the map would say they did not
   happen, and the case is common — two routes with a break between them
   (REQ-UIX-095's second line). The drawing says the same with `.mh-fit .dim`
   at 0.32 on its own canvas (design/app.css:1766); on a real map the same
   opacity is applied to the Leaflet nodes instead. */
.geo-dim{opacity:.32}
.geo-hi{filter:drop-shadow(0 0 3px var(--ok))}
path.geo-hi{stroke-width:7}
/* The live map's own marker for a vehicle whose position is not the current
   one, and for a device that has said nothing (REQ-MOV-068, §17.1's second
   open place: they are two states and two pictures, because they call an
   installer to two different places). The drawing gives the first a dotted
   ring and the second a dashed one (design/app.css:1758). */
.geo-mk.geo-last{border-style:dotted;border-color:var(--tx3);background:var(--s1)}
.geo-mk.geo-last.geo-ring{border-style:dashed;
  box-shadow:0 0 0 2px var(--s1),0 0 0 4px var(--tx3)}
/* ── the vehicle drawn as itself (REQ-FLT-029) ──────────────────────────────
   The silhouette is the KIND and the fill is the BODY COLOUR, and both arrive
   already decided from the server: `--lk-fill` and `--lk-stroke` are set on the
   node from the response, and there is no colour and no shape named in this
   file that a browser could pick on its own (REQ-UIX-002).

   `fill` and `stroke` are inherited SVG properties, so setting them on the
   wrapper is what paints the `<use>`d symbol. The wheels and the windows carry
   the contrast colour instead, which is what stops a white lorry being a white
   rectangle. */
.lkdefs{position:absolute;width:0;height:0;overflow:hidden}
.lki{display:inline-flex;align-items:center;justify-content:center;
  width:19px;height:19px;flex:none;margin-right:6px;vertical-align:-4px}
.lki svg,.lkm{width:100%;height:100%;display:block;
  fill:var(--lk-fill,var(--tx3));stroke:var(--lk-stroke,var(--s1));stroke-width:.6}
.lki .lkw,.lkm .lkw{fill:var(--lk-stroke,var(--s1));stroke:none}
/* A colour nobody entered: the palette's grey, and a DASHED outline so that
   «not stated» cannot be mistaken for a lorry somebody entered as grey. The
   words are beside it either way (REQ-UIX-007, REQ-UIX-092). */
.lki.lki-nc svg,.geo-mk.geo-nocolour .lkm{stroke-dasharray:2.2 1.8;stroke-width:1}
.lki.lki-h{width:22px;height:22px;margin-right:8px}
/* On the map the marker becomes the vehicle and the STATE becomes a ring around
   it. These selectors carry three classes so they outrank the two-class state
   rules above whatever order the stylesheets end up in — the state colour is
   the ring's colour here and never the fill's. */
.geo-mk.geo-look{position:relative;background:transparent;border:0;width:30px;height:30px;
  padding:3px;box-shadow:0 0 0 2px var(--tx3)}
.geo-mk.geo-look.st-park{background:transparent;box-shadow:0 0 0 2px var(--tx3)}
.geo-mk.geo-look.st-idle{background:transparent;box-shadow:0 0 0 2px var(--wn)}
.geo-mk.geo-look.st-drop{background:transparent;box-shadow:0 0 0 2px var(--dg)}
.geo-mk.geo-look.st-fill{background:transparent;box-shadow:0 0 0 2px var(--in)}
/* Silence and staleness are not causes and get no colour of their own: they are
   the drawing's dashed and dotted rings (design/app.css:1758), which is what
   §17.1's second open place asks for — two states, two pictures. */
.geo-mk.geo-look.st-silent{background:transparent;box-shadow:none;
  border:2px dashed var(--tx3)}
.geo-mk.geo-look.st-stale{background:transparent;box-shadow:none;
  border:2px dotted var(--tx3)}
.geo-mk.geo-look .lkm{width:22px;height:22px}
/* `.geo-mk` is a one-cell grid and its label is the cell. A vehicle marker
   carries no label — the letters belong to stops — so on a look marker the
   empty span is removed from the flow; left in, it takes a grid row of its own
   and pushes the silhouette off the coordinate it is standing on. */
.geo-mk.geo-look .geo-lb{display:none}
/* The chevron of a moving vehicle stands BESIDE the silhouette rather than on
   it: drawn over the body it would be a second colour inside the fill, and the
   fill is the one thing on this marker that means «which lorry is this».
   It is taken OUT of the flow, because `.geo-mk` is a grid and a pseudo-element
   left in it is a second grid ROW — which pushes the silhouette off the
   coordinate the server sent it to stand on. */
.geo-mk.geo-look.geo-vehicle::after{position:absolute;left:50%;top:50%;
  margin:-6px 0 0 -6px;transform:rotate(var(--course,0deg)) translateY(-16px)}
.mapc .leaflet-popup-content-wrapper{background:var(--s1);color:var(--tx1);
  border:1px solid var(--line);border-radius:var(--r-s);box-shadow:var(--shadow)}
.mapc .leaflet-popup-tip{background:var(--s1);border:1px solid var(--line)}
.mapc .leaflet-popup-content{margin:10px 12px}
.mapc .leaflet-popup-content .mh-pop{position:static;width:auto;padding:0;background:none;border:none}
.mapc .leaflet-tooltip{background:var(--s1);color:var(--tx1);border:1px solid var(--line);
  font-family:var(--font);font-size:11px}
.mapc .leaflet-control-scale-line{background:var(--s1);border-color:var(--tx3);
  color:var(--tx3);font-family:var(--mono);font-size:10px}
/* The scale bar sits above the caption, which owns the bottom-left corner. On
   a telephone the caption wraps to two lines, so it is given the room it
   actually takes — the browser walk showed the bar lying across the words. */
.mapc .leaflet-bottom.leaflet-left{bottom:26px}
@media (max-width:620px){
  .mapc .leaflet-bottom.leaflet-left{bottom:48px}
  .mh-cap{max-width:calc(100% - 24px)}
}
.mapc .leaflet-bar a{background:var(--s1);color:var(--tx2);border-bottom-color:var(--line)}
.mapc .leaflet-bar a:hover{background:var(--s3);color:var(--tx1)}
/* The scrub. The native thumb IS the drawing's head (`.pl-head`): its position
   is the browser's, so the client places nothing and computes no per-cent. */
.pl-scrub{position:absolute;left:0;right:0;top:18px;height:30px;width:100%;margin:0;
  padding:0;background:none;border:none;appearance:none;-webkit-appearance:none;cursor:pointer;z-index:3}
.pl-scrub:focus{outline:none}
.pl-scrub:focus-visible{outline:2px solid var(--ok);outline-offset:3px;border-radius:6px}
.pl-scrub::-webkit-slider-runnable-track{height:30px;background:none}
.pl-scrub::-moz-range-track{height:30px;background:none}
.pl-scrub::-webkit-slider-thumb{appearance:none;-webkit-appearance:none;width:2px;height:30px;
  background:var(--ok);border:none;border-radius:0;box-shadow:0 -5px 0 -1px var(--ok),0 0 0 1px var(--s1)}
.pl-scrub::-moz-range-thumb{width:2px;height:30px;background:var(--ok);border:none;
  border-radius:0;box-shadow:0 -5px 0 -1px var(--ok),0 0 0 1px var(--s1)}
.plyr .pl-btn{user-select:none}
/* The question is a real input and not the drawing's sized stand-in, so it
   needs a width the whole placeholder fits in: the browser walk of 2026-09-06
   showed «Где была машина в 14:0С» cut off by its own box, which is the class
   of defect nothing measures — a flex item clipped by itself rather than by
   the viewport. */
.plyr .instq .inp{min-width:196px}
/* The owner's map is drawn dark (design/app.html#p-trips) and the default
   provider's standard style is a light one. The tiles are a PICTURE and never a source of
   any number (REQ-MOV-034), so they may be toned to the surface they stand on;
   nothing is inverted and no colour is replaced, so a road is still a road and
   water is still water. In the day theme they are left exactly as the provider
   drew them. */
[data-theme="night"] .mapc .leaflet-tile-pane{filter:brightness(.74) saturate(.82) contrast(1.06)}

/* ═════════════════════════════════════════════════════════════════════════════
   THE DRAWING'S STYLESHEET, ADOPTED 2026-09-04.
   design/app.css is the source of truth for how the interface looks (D-131);
   until this day the product carried an older copy of it. Everything from
   here down is design/app.css with the mock-up-only rules removed by
   tools/adopt_css.py (role switching `[data-r]`, the demo renderings
   `[data-org]`, mock page ids `#p-…`, the drawing's own sign-in and driver
   mocks, `.page` show/hide) and is appended AFTER the product's own rules so
   that, where both name one selector, the drawing wins. The product-only
   rules the drawing has no word for — dialogs `.dlg*`, forms `.fld`, the
   sign-in `.lg-*`, the global search `.srch*`, the lens bar `.vb*`, tones —
   stay above, untouched. The reconciliation block at the very end resolves
   the places the two disagree on a MECHANISM rather than a look. Generated;
   do not edit by hand — run python tools/adopt_css.py.
   ═════════════════════════════════════════════════════════════════════════ */
:root{--font:-apple-system,BlinkMacSystemFont,"Segoe UI","Helvetica Neue",Arial,sans-serif;
  --mono:"SF Mono",Menlo,Consolas,monospace;
  --r:16px; --r-s:11px; --r-l:22px;}
[data-theme="night"]{--bg:#0D1014; --s1:#13171D; --s2:#191F27; --s3:#212932;
  --line:rgba(255,255,255,.07); --line-s:rgba(255,255,255,.13);
  --tx1:#E9EDF2; --tx2:#98A4B3; --tx3:#64707E;
  --ok:#3FC493; --ok-d:rgba(63,196,147,.13); --ok-b:rgba(63,196,147,.28);
  --wn:#E8A83C; --wn-d:rgba(232,168,60,.13);
  --dg:#EF6A5E; --dg-d:rgba(239,106,94,.13);
  --in:#8B7DF0; --in-d:rgba(139,125,240,.13);
  --shadow:0 1px 2px rgba(0,0,0,.5),0 8px 24px rgba(0,0,0,.32);
  --map1:rgba(46,196,150,.34); --map2:rgba(94,124,255,.30);
  --map3:rgba(168,92,246,.26); --map4:rgba(232,168,60,.18);
  --mapbase:linear-gradient(155deg,#0B1219,#0A1017 52%,#0D0F18);
  --mesh:rgba(255,255,255,.032);
  --gl-bg:rgba(255,255,255,.045); --gl-brd:rgba(255,255,255,.10);
  --gl-top:rgba(255,255,255,.24); --gl-in:rgba(255,255,255,.13);
  --glc-bg:rgba(255,255,255,.05);
  --glc-fx:url(#lens-soft) blur(16px) saturate(150%) brightness(.72);}
[data-theme="day"]{--bg:#F6F5F1; --s1:#FFFFFF; --s2:#FFFFFF; --s3:#F1EFE9;
  --line:rgba(20,24,28,.09); --line-s:rgba(20,24,28,.16);
  --tx1:#15191D; --tx2:#5D666F; --tx3:#8B939C;
  --ok:#0E6B54; --ok-d:rgba(14,107,84,.09); --ok-b:rgba(14,107,84,.22);
  --wn:#B4720C; --wn-d:rgba(180,114,12,.10);
  --dg:#C0392F; --dg-d:rgba(192,57,47,.09);
  --in:#4B3FB0; --in-d:rgba(75,63,176,.09);
  --shadow:0 1px 2px rgba(20,24,28,.05),0 6px 20px rgba(20,24,28,.07);
  --map1:rgba(14,107,84,.16); --map2:rgba(75,99,200,.14);
  --map3:rgba(140,80,210,.12); --map4:rgba(200,140,20,.12);
  --mapbase:linear-gradient(155deg,#EDEBE4,#F2F0EA 52%,#E9E7E1);
  --mesh:rgba(20,24,28,.045);
  --gl-bg:rgba(255,255,255,.34); --gl-brd:rgba(255,255,255,.62);
  --gl-top:rgba(255,255,255,.92); --gl-in:rgba(255,255,255,.72);
  --glc-bg:rgba(255,255,255,.30);
  --glc-fx:url(#lens-soft) blur(14px) saturate(190%) brightness(1.10);}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--font);background:var(--bg);color:var(--tx1);
  width:100%;min-width:340px}
.chrome{background:var(--s1);border:1px solid var(--line);box-shadow:var(--shadow)}
[data-mat="glass"] .chrome{background:var(--gl-bg);
  backdrop-filter:url(#lens) blur(2px) saturate(170%) brightness(1.06);
  -webkit-backdrop-filter:url(#lens) blur(2px) saturate(170%) brightness(1.06);
  border:1px solid var(--gl-brd);
  box-shadow:0 20px 56px rgba(0,0,0,.42),0 1px 0 var(--gl-in) inset;
  isolation:isolate}
[data-mat="glass"] .chrome::after{content:"";position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;background:linear-gradient(142deg,var(--gl-top) 0%,transparent 40%,
  transparent 76%,var(--gl-in) 100%);opacity:.28}
[data-mat="glass"] .card,
[data-mat="glass"] .kpi{position:relative;isolation:isolate;
  background:var(--glc-bg);
  backdrop-filter:var(--glc-fx);
  -webkit-backdrop-filter:var(--glc-fx);
  border:1px solid var(--gl-brd);
  box-shadow:0 18px 48px rgba(0,0,0,.34),0 1px 0 var(--gl-in) inset}
[data-mat="glass"] .card::after,
[data-mat="glass"] .kpi::after{content:"";position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;z-index:0;background:linear-gradient(142deg,var(--gl-top) 0%,
  transparent 42%,transparent 76%,var(--gl-in) 100%);opacity:.22}
[data-mat="glass"] .card > *,
[data-mat="glass"] .kpi > *{position:relative;z-index:1}
[data-mat="glass"] th{background:transparent}
[data-mat="glass"] .search,
[data-mat="glass"] .pill:not(.live):not(.act),
[data-mat="glass"] .btn:not(.btn-p){background:rgba(255,255,255,.07)}
[data-theme="day"][data-mat="glass"] .search,
[data-theme="day"][data-mat="glass"] .pill:not(.live):not(.act),
[data-theme="day"][data-mat="glass"] .btn:not(.btn-p){background:rgba(255,255,255,.55)}
[data-theme="day"][data-mat="glass"]{--map1:rgba(14,140,104,.32); --map2:rgba(70,104,224,.30);
  --map3:rgba(150,84,224,.26); --map4:rgba(224,150,20,.24);
  --mapbase:linear-gradient(155deg,#DCE6E2,#E6E8EC 48%,#E4DEE8);
  --mesh:rgba(20,24,28,.07);
  --tx3:#6E7780;}
[data-theme="day"][data-mat="glass"] .chrome,
[data-theme="day"][data-mat="glass"] .card,
[data-theme="day"][data-mat="glass"] .kpi{border:1px solid rgba(255,255,255,.62);
  box-shadow:0 22px 54px rgba(20,28,40,.20),
             0 2px 10px rgba(20,28,40,.10),
             0 0 0 .5px rgba(20,28,40,.14),
             0 1px 0 rgba(255,255,255,.92) inset,
             0 -1px 0 rgba(20,28,40,.05) inset}
[data-theme="day"][data-mat="glass"] .chrome::after,
[data-theme="day"][data-mat="glass"] .card::after,
[data-theme="day"][data-mat="glass"] .kpi::after{opacity:.40}
[data-theme="day"][data-mat="glass"] th{background:rgba(255,255,255,.30)}
[data-theme="day"][data-mat="glass"] .fi,
[data-theme="day"][data-mat="glass"] .segw{background:rgba(255,255,255,.40)}
.app{position:relative;min-height:max(940px,100vh);overflow:hidden}
body > .app{max-width:1440px;margin:0 auto}
.canvas{position:absolute;inset:0;z-index:0}
.mapbg{position:absolute;inset:-8%;background:
  radial-gradient(38% 34% at 20% 24%,var(--map1),transparent 68%),
  radial-gradient(34% 30% at 76% 14%,var(--map2),transparent 68%),
  radial-gradient(40% 36% at 66% 82%,var(--map3),transparent 70%),
  radial-gradient(28% 26% at 26% 86%,var(--map4),transparent 68%),
  var(--mapbase)}
.mesh{position:absolute;inset:0;opacity:.6;
  background-image:linear-gradient(var(--mesh) 1px,transparent 1px),
                   linear-gradient(90deg,var(--mesh) 1px,transparent 1px);
  background-size:60px 60px}
.rd{position:absolute;height:2.5px;border-radius:3px;
  background:linear-gradient(90deg,transparent,var(--ok) 20%,var(--ok) 80%,transparent);opacity:.5}
.pin{position:absolute;width:11px;height:11px;border-radius:50%;background:var(--ok);
  box-shadow:0 0 0 5px var(--ok-d),0 0 22px var(--ok)}
.pin.w{background:var(--wn);box-shadow:0 0 0 5px var(--wn-d),0 0 22px var(--wn)}
.pin.d{background:var(--dg);box-shadow:0 0 0 5px var(--dg-d),0 0 22px var(--dg)}
.side{position:absolute;left:0;top:0;bottom:0;width:252px;z-index:5;padding:17px 13px;
      border-radius:0 var(--r-l) var(--r-l) 0;border-left:none;overflow-y:auto}
.brand{display:flex;align-items:center;gap:10px;padding:3px 8px 15px}
.logo{width:28px;height:28px;border-radius:9px;background:linear-gradient(150deg,#6BEFBC,#28A97B);
      display:grid;place-items:center;font-weight:800;font-size:14px;color:#052018}
.bname{font-size:14.5px;font-weight:660;letter-spacing:-.01em}
.nsec{font-size:9.5px;font-weight:680;letter-spacing:.12em;text-transform:uppercase;
      color:var(--tx3);padding:13px 9px 5px}
.nav{display:flex;align-items:center;justify-content:space-between;padding:7px 11px;
     border-radius:var(--r-s);font-size:13px;color:var(--tx2);margin-bottom:1px;cursor:pointer}
.nav:hover{background:var(--s3);color:var(--tx1)}
.nsub{padding-left:18px}
.nsecg{display:flex;align-items:center;gap:7px;cursor:pointer;user-select:none;
       font-size:13px;font-weight:600;letter-spacing:0;text-transform:none;
       color:var(--tx1);padding:8px 11px;margin:9px 0 2px;border-radius:var(--r-s);
       background:var(--s2)}
.nsecg:hover{background:var(--s3)}
.nsecg .nchev{margin-left:auto;font-size:12px;color:var(--tx3);transition:transform .15s}
.nav.on{background:var(--ok-d);color:var(--ok);font-weight:600;box-shadow:inset 0 0 0 1px var(--ok-b)}
.ncount{font-size:10.5px;color:var(--tx3)}
.ndot{font-size:10px;font-weight:700;color:#fff;background:var(--dg);padding:1px 6px;border-radius:20px}
.soon{font-size:9px;font-weight:660;letter-spacing:.05em;color:var(--tx3);
      border:1px solid var(--line-s);padding:0 5px;border-radius:5px}
.top{position:absolute;left:274px;right:22px;top:20px;height:56px;z-index:5;border-radius:18px;
     display:flex;align-items:center;gap:12px;padding:0 15px}
.search{flex:1;height:34px;border-radius:var(--r-s);background:var(--s3);
        border:1px solid var(--line);display:flex;align-items:center;padding:0 13px;
        font-size:12.5px;color:var(--tx3)}
.pill{font-size:11.5px;font-weight:570;padding:5px 11px;border-radius:20px;
      background:var(--s3);border:1px solid var(--line);color:var(--tx2);cursor:pointer}
.pill.live{color:var(--ok);background:var(--ok-d);border-color:var(--ok-b)}
.pill.act{color:var(--ok);border-color:var(--ok-b);background:var(--ok-d);font-weight:640}
.ava{width:29px;height:29px;border-radius:50%;background:linear-gradient(150deg,#6BEFBC,#28A97B);
     display:grid;place-items:center;font-size:10.5px;font-weight:700;color:#052018}
.main{position:absolute;left:252px;right:0;top:88px;bottom:0;z-index:2;padding:8px 22px 22px;overflow-y:auto}
.ph{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:15px}
body[data-role="op"] .ph{align-items:flex-start;gap:18px}
body[data-role="op"] .ph > div:first-child{min-width:0}
body[data-role="op"] .ph .pa{margin-top:3px;flex-wrap:wrap;justify-content:flex-end;align-items:center}
.pt{font-size:21px;font-weight:670;letter-spacing:-.02em}
.ps{font-size:12.5px;color:var(--tx3);margin-top:3px}
.pa{display:flex;gap:8px;flex-shrink:0}
.btn{font-size:12.5px;font-weight:560;padding:7px 14px;border-radius:var(--r-s);cursor:pointer;
     border:1px solid var(--line-s);background:var(--s1);color:var(--tx1)}
.btn-p{background:var(--ok);border-color:var(--ok);color:#fff}
[data-theme="night"] .btn-p{color:#052018;font-weight:640}
.card{background:var(--s1);border:1px solid var(--line);border-radius:var(--r);
      box-shadow:var(--shadow);overflow:hidden}
.ch{padding:13px 16px;border-bottom:1px solid var(--line);display:flex;
    justify-content:space-between;align-items:center}
.ct{font-size:13.5px;font-weight:620}
.cs{font-size:11.5px;color:var(--tx3);font-weight:450;margin-left:7px}
.cb{padding:15px 16px}
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:13px}
.kpi{background:var(--s1);border:1px solid var(--line);border-radius:var(--r);
     padding:14px 16px;box-shadow:var(--shadow)}
.kl{font-size:10px;font-weight:660;letter-spacing:.08em;text-transform:uppercase;color:var(--tx3)}
.kv{font-size:27px;font-weight:670;letter-spacing:-.028em;margin:8px 0 2px}
.kv span{font-size:12.5px;font-weight:520;color:var(--tx3);margin-left:3px}
.km{font-size:11.5px;color:var(--tx2)}
.kd{display:inline-block;font-size:11.5px;font-weight:640;margin-top:9px;padding:2px 8px;border-radius:20px}
.up{color:var(--ok);background:var(--ok-d)}
.dn{color:var(--dg);background:var(--dg-d)}
.nt{color:var(--tx2);background:var(--s3)}
table{width:100%;border-collapse:collapse}
th{font-size:10px;font-weight:660;letter-spacing:.07em;text-transform:uppercase;color:var(--tx3);
   text-align:left;padding:9px 16px;background:var(--s3)}
td{padding:11px 16px;font-size:12.5px;color:var(--tx2);border-top:1px solid var(--line)}
td b{color:var(--tx1);font-weight:580}
.num{font-family:var(--mono);font-size:12px;color:var(--tx1)}
.mut{color:var(--tx3)}
tr.go{cursor:pointer}
.kpi.go{cursor:pointer}
.kpi.go:hover{box-shadow:inset 0 0 0 1px var(--ok-b)}
.kvr.go{cursor:pointer;margin:0 -13px;padding-left:13px;padding-right:13px;border-radius:var(--r-s)}
.kvr.go:hover{background:var(--s3)}
tr.go:hover td{background:var(--s3)}
.tag{display:inline-block;font-size:10.5px;font-weight:640;padding:3px 8px;border-radius:20px;white-space:nowrap}
.g-ok{color:var(--ok);background:var(--ok-d)}
.g-w{color:var(--wn);background:var(--wn-d)}
.g-d{color:var(--dg);background:var(--dg-d)}
.g-i{color:var(--in);background:var(--in-d)}
.g-n{color:var(--tx2);background:var(--s3)}
.g2{display:grid;grid-template-columns:1fr 340px;gap:13px}
.g3{display:grid;grid-template-columns:repeat(3,1fr);gap:13px}
.g2 > div, .g3 > div{min-width:0}
.bars{display:grid;gap:8px}
.br{display:grid;grid-template-columns:30px 1fr 92px;align-items:center;gap:10px}
.bl{font-size:11.5px;color:var(--tx3)}
.bbg{height:7px;border-radius:4px;background:var(--s3);overflow:hidden}
.bf{height:100%;border-radius:4px;background:var(--ok)}
.bf.w{background:var(--wn)}
.bv{font-size:11.5px;color:var(--tx2);text-align:right;font-family:var(--mono)}
/* Mono is for numbers only: a WORD inside a bar value — the absent reading, a
   flag — is set in the ordinary face, and the absent word at the drawing's
   `.mut` size for such a word (design/app.html:386, 10px). Digits and units
   stay mono. */
.bv .absent,.bv .flag{font-family:var(--font)}
.bv .absent{font-size:10px;font-weight:inherit;padding:0;background:none;color:var(--tx3);border-radius:0;white-space:normal}
.al{display:flex;gap:10px;padding:11px 13px;border-left:3px solid;border-top:1px solid var(--line)}
.al:first-child{border-top:none}
.al-d{border-left-color:var(--dg)}
.al-w{border-left-color:var(--wn)}
.al-i{border-left-color:var(--ok)}
.alt{font-size:12.5px;font-weight:600;color:var(--tx1)}
.als{font-size:11.5px;color:var(--tx2);margin-top:2px}
.ala{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px}
.alb{font-size:11px;font-weight:570;padding:3px 9px;border-radius:7px;
     border:1px solid var(--line-s);color:var(--tx2);cursor:pointer}
.lnk{font-size:11.5px;color:var(--tx2);cursor:pointer;white-space:nowrap;
     border-bottom:1px dotted var(--line-s)}
.lnk:hover{color:var(--tx1);border-bottom-color:var(--tx3)}
.empty{padding:34px 20px;text-align:center}
.et{font-size:13.5px;font-weight:600;color:var(--tx2)}
.es{font-size:12px;color:var(--tx3);margin-top:5px;line-height:1.6}
.back{font-size:12px;color:var(--tx3);cursor:pointer;margin-bottom:9px;display:inline-block}
.back:hover{color:var(--tx2)}
.back-step{margin-right:14px}
.vhead{display:flex;align-items:center;gap:13px}
.vplate{font-size:23px;font-weight:680;letter-spacing:-.02em}
.chart{position:relative;padding:5px 0}
.chart svg{display:block;width:100%;height:auto;overflow:visible}
.gapb{fill:var(--dg-d)}
.gapl{font-size:9.5px;fill:var(--dg);font-family:var(--mono)}
.axl{font-size:9.5px;fill:var(--tx3);font-family:var(--mono)}
.gridl{stroke:var(--line);stroke-width:1}
.pline{fill:none;stroke:var(--ok);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.pfill{fill:var(--ok-d)}
.refl{stroke:var(--in);stroke-width:1.5;stroke-dasharray:3 3}
.reft{font-size:9.5px;fill:var(--in);font-family:var(--mono)}
.tml{position:relative;padding-left:19px}
.tmi{position:relative;padding:0 0 15px 0}
.tmi:last-child{padding-bottom:0}
.tmi::before{content:"";position:absolute;left:-19px;top:4px;width:9px;height:9px;border-radius:50%;
  background:var(--tx3);box-shadow:0 0 0 3px var(--s1)}
.tmi.ok::before{background:var(--ok)}
.tmi.w::before{background:var(--wn)}
.tmi.d::before{background:var(--dg)}
.tmi::after{content:"";position:absolute;left:-15px;top:17px;bottom:0;width:1px;background:var(--line)}
.tmi:last-child::after{display:none}
.tmt{font-size:12.5px;font-weight:590;color:var(--tx1)}
.tms{font-size:11.5px;color:var(--tx3);margin-top:2px;line-height:1.55}
.tmw{font-size:10.5px;color:var(--tx3);font-family:var(--mono);margin-bottom:2px}
.kvr{display:flex;justify-content:space-between;gap:12px;padding:8px 0;
     border-bottom:1px solid var(--line);font-size:12.5px}
.kvr:last-child{border-bottom:none}
.kvr .l{color:var(--tx3)}
.kvr .v{color:var(--tx1);font-weight:560;text-align:right}
.cap{display:flex;gap:7px;padding:6px 0;font-size:12px;color:var(--tx2);line-height:1.5}
.cap i{font-style:normal;width:13px;text-align:center;flex:none}
.cap.no{color:var(--tx3)}
.stlab{display:inline-block;font-family:var(--mono);font-size:10px;font-weight:600;
  letter-spacing:.04em;padding:2px 7px;border-radius:6px;background:var(--s3);color:var(--tx3);
  border:1px solid var(--line)}
.sk{border-radius:6px;background:linear-gradient(90deg,var(--s3) 0%,var(--s2) 46%,var(--s3) 92%);
  background-size:220% 100%;animation:sh 1.5s ease-in-out infinite}
@keyframes sh{0%{background-position:120% 0}100%{background-position:-120% 0}}
.stale{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--tx3);margin-top:9px}
.erri{width:26px;height:26px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:var(--dg-d);color:var(--dg);font-size:14px;font-weight:700}
.errt{font-size:12.5px;font-weight:600;color:var(--tx1)}
.errs{font-size:11.5px;color:var(--tx3);margin-top:3px;line-height:1.55}
.fchips{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-top:11px}
.fchip{font-size:11px;padding:3px 9px;border-radius:20px;background:var(--s3);
  border:1px solid var(--line);color:var(--tx2)}
.fchip b{color:var(--tx1);font-weight:600}
.ovl{position:absolute;inset:0;z-index:30;display:none;place-items:center;
  background:rgba(6,9,13,.58);backdrop-filter:blur(7px) saturate(120%)}
[data-theme="day"] .ovl{background:rgba(24,30,38,.34)}
.ovl.on{display:grid}
.mod{width:520px;max-width:calc(100% - 40px);border-radius:22px;position:relative;
  overflow:hidden}
.mod-h{padding:19px 22px 0}
.mod-t{font-size:16.5px;font-weight:660;letter-spacing:-.015em}
.mod-s{font-size:12.5px;color:var(--tx3);margin-top:5px;line-height:1.55}
.mod-b{padding:17px 22px 4px}
.mod-f{display:flex;justify-content:flex-end;gap:8px;padding:17px 22px 19px}
.warn{border-left:3px solid var(--dg);background:var(--dg-d);border-radius:0 11px 11px 0;
  padding:11px 13px;font-size:12px;color:var(--tx2);line-height:1.6}
.warn b{color:var(--tx1);font-weight:620}
.lose{margin:9px 0 0;padding-left:17px}
.lose li{font-size:12px;color:var(--tx2);line-height:1.75}
.fld{margin-bottom:12px}
.fld label{display:block;font-size:11px;font-weight:640;letter-spacing:.05em;
  text-transform:uppercase;color:var(--tx3);margin-bottom:5px}
.inp{width:100%;height:40px;border-radius:var(--r-s);background:var(--s3);
  border:1px solid var(--line);padding:0 13px;font-size:13px;color:var(--tx1);
  font-family:var(--font);display:flex;align-items:center}
.inp.ph{color:var(--tx3)}
.inp:focus{outline:2px solid var(--ok-b);outline-offset:1px}
.btn-d{background:var(--dg);border-color:var(--dg);color:#fff;font-weight:620}
.btn.wide{width:100%;text-align:center;padding:11px 14px;font-size:13.5px}
@keyframes drive{0%{transform:translateX(0)}100%{transform:translateX(420px)}}
.fld{margin-bottom:14px}
.fld label{display:flex;justify-content:space-between;align-items:baseline;
  font-size:11px;font-weight:640;letter-spacing:.05em;text-transform:uppercase;
  color:var(--tx3);margin-bottom:6px}
.fld label a{font-size:11px;font-weight:560;letter-spacing:0;text-transform:none;
  color:var(--ok);cursor:pointer}
.inp{width:100%;height:44px;border-radius:12px;background:var(--s3);
  border:1px solid var(--line);padding:0 14px;font-size:13.5px;color:var(--tx1);
  font-family:var(--font);display:flex;align-items:center;gap:10px}
.inp .ic{font-size:13px;color:var(--tx3);flex:none}
.inp.ph{color:var(--tx3)}
.caps{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--wn);margin-top:7px}
.rem{display:flex;align-items:center;gap:9px;font-size:12.5px;color:var(--tx2);
  margin:4px 0 20px;cursor:pointer}
.box{width:17px;height:17px;border-radius:5px;border:1.5px solid var(--line-s);flex:none;
  display:grid;place-items:center;font-size:11px;color:transparent}
.box.on{background:var(--ok);border-color:var(--ok);color:#fff;font-weight:800}
[data-theme="night"] .box.on{color:#052018}
.btn.wide{width:100%;text-align:center;padding:12px 14px;font-size:14px;font-weight:620}
.svc{display:grid;gap:8px}
.svc-r{display:flex;align-items:center;gap:9px;font-size:12px;color:var(--tx2)}
.svc-d{width:7px;height:7px;border-radius:50%;background:var(--ok);flex:none;
  box-shadow:0 0 8px var(--ok)}
.svc-d.w{background:var(--wn);box-shadow:0 0 8px var(--wn)}
.svc-v{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--tx3)}
.gate{margin-top:14px;border:1px solid var(--line-s);border-radius:13px;padding:13px 15px;
  background:var(--s3)}
.gate-l{font-size:11px;font-weight:650;letter-spacing:.05em;text-transform:uppercase;
  color:var(--tx3);margin-bottom:9px}
.gate-r{display:flex;align-items:center;gap:11px}
.gate-q{font-family:var(--mono);font-size:19px;font-weight:600;color:var(--tx1);
  letter-spacing:.02em;white-space:nowrap}
.gate-i{width:92px;height:38px;border-radius:var(--r-s);background:var(--s1);
  border:1px solid var(--line-s);padding:0 12px;font-family:var(--mono);font-size:16px;
  font-weight:600;color:var(--tx1);text-align:center}
.gate-i:focus{outline:2px solid var(--ok-b);outline-offset:1px}
.gate-i.bad{border-color:var(--dg);color:var(--dg)}
.gate-i.good{border-color:var(--ok);color:var(--ok)}
.gate-n{font-size:11px;color:var(--tx3);line-height:1.6;margin-top:9px}
button[disabled]{opacity:.40;cursor:not-allowed}
.src{font-size:10.5px;color:var(--tx3);font-family:var(--mono)}
.note{font-size:11.5px;color:var(--tx3);line-height:1.65;margin-top:11px}
.why{margin-top:10px}
.why a{font-size:11px;color:var(--tx3);text-decoration:none;
       border-bottom:1px dotted var(--ln);padding-bottom:1px}
.why a:hover{color:var(--tx1);border-bottom-color:var(--tx3)}
.why a::after{content:"\2009\2197";font-size:9px;vertical-align:1px}
.note b{color:var(--tx2);font-weight:600}
.fh{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.fp{font-size:14.5px;font-weight:670}
.fs{font-size:11.5px;color:var(--tx2)}
.fg{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.fi{background:var(--s3);border:1px solid var(--line);border-radius:var(--r-s);padding:8px 11px}
.fl{font-size:9.5px;font-weight:680;letter-spacing:.08em;text-transform:uppercase;color:var(--tx3)}
.fv{font-size:16px;font-weight:630;margin-top:2px}
.fv span{font-size:10.5px;color:var(--tx3);font-weight:500;margin-left:2px}
.mapbar{position:relative;display:flex;align-items:center;gap:7px;padding:9px 13px;border-radius:15px;margin-bottom:12px}
.seg{font-size:12px;font-weight:580;padding:5px 13px;border-radius:9px;color:var(--tx2);cursor:pointer}
.seg.on{background:var(--ok-d);color:var(--ok);box-shadow:inset 0 0 0 1px var(--ok-b)}
.mdiv{width:1px;height:20px;background:var(--line-s);margin:0 4px}
.vlist{position:absolute;right:22px;top:100px;width:296px;border-radius:var(--r);
       padding:6px;z-index:6;max-height:520px;overflow:hidden}
.vl-h{font-size:12px;font-weight:640;padding:9px 11px 8px;color:var(--tx1)}
.vrow{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--r-s);cursor:pointer}
.vrow.on{background:var(--ok-d);box-shadow:inset 0 0 0 1px var(--ok-b)}
.vrow.stale,.vrow.off{opacity:.72}
.vdot{width:8px;height:8px;border-radius:50%;background:var(--ok);flex:none;box-shadow:0 0 9px var(--ok)}
.vdot.w{background:var(--wn);box-shadow:0 0 9px var(--wn)}
.vdot.d{background:var(--dg);box-shadow:0 0 9px var(--dg)}
.vdot.g{background:var(--tx3);box-shadow:none}
.vdot.o{background:var(--tx3);box-shadow:none;opacity:.5}
.vp{font-size:12.5px;font-weight:600;color:var(--tx1)}
.vs{font-size:11px;color:var(--tx3);margin-top:1px}
.vg{font-size:11.5px;font-family:var(--mono);color:var(--tx2)}
.mlv .vlist .vrow .vg{flex:0 1 84px;max-width:84px;text-align:right;overflow-wrap:break-word}
/* REQ-GAS-101/REQ-UIX-017: a mark such as fleet.flag.nocorrection is a whole
 * sentence, not a word, and this column's 84px width was sized for the
 * NUMBER alone. Widening only the rows that actually carry a mark (:has)
 * keeps every plain number column at its original width and lets the
 * sentence wrap at word boundaries — never mid-word, never one word per
 * line — the same trap frontend-standards names: a narrow column plus a
 * global word-break wraps text one character/word per line. The mark stays
 * a child of .vg, which is what apitest/browser.go's ProbeScript(REQ-UIX-017)
 * checks: the mark must sit inside the box that carries its own number. */
.mlv .vlist .vrow .vg:has(.flag){flex:0 1 124px;max-width:124px}
.mlv .vlist .vrow > div[style*="flex:1"]{min-width:130px}
.pmobs{position:relative;width:640px;max-width:calc(100% - 318px);margin-top:12px;
       z-index:6;border-radius:var(--r);padding:13px 15px}
.pmobs .kvr{padding:7px 0}
.stg{display:flex;justify-content:space-between;align-items:center;padding:11px 0;border-bottom:1px solid var(--line)}
.stg-l{font-size:13px;font-weight:590;color:var(--tx1)}
.stg-s{font-size:11.5px;color:var(--tx3);margin-top:2px}
.segw{display:flex;gap:3px;background:var(--s3);padding:3px;border-radius:10px}
.pill.ico{display:inline-flex;align-items:center;justify-content:center;
          width:30px;padding:5px 0;line-height:0}
.rp-n{font-size:13.5px;font-weight:620;color:var(--tx1)}
.rp-d{font-size:11.5px;color:var(--tx2);margin-top:5px;line-height:1.55;min-height:36px}
.rp-a{display:flex;gap:6px;margin-top:10px}
.alh{display:flex;align-items:center;gap:8px;margin-bottom:5px}
.alw{font-size:11px;color:var(--tx3)}
.scw{display:flex;align-items:center;gap:9px}
.scb{width:56px;height:6px;border-radius:4px;background:var(--s3);overflow:hidden;flex:none}
.scf{height:100%;border-radius:4px;background:var(--ok)}
.scf.w{background:var(--wn)}
.scf.d{background:var(--dg)}
.assum{position:relative;border-radius:var(--r);padding:13px 16px;margin-bottom:13px}
.as-t{font-size:11px;font-weight:660;letter-spacing:.07em;text-transform:uppercase;
      color:var(--tx3);margin-bottom:11px}
.as-g{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.as-l{font-size:11.5px;color:var(--tx2)}
.as-v{font-size:17px;font-weight:640;margin:3px 0 2px}
.as-v span{font-size:11.5px;font-weight:500;color:var(--tx3)}
.as-s{font-size:10.5px;color:var(--tx3)}
.fbar{display:flex;align-items:center;gap:7px;margin-bottom:12px}
.fillw{display:flex;align-items:center;gap:9px}
.fillb{width:64px;height:6px;border-radius:4px;background:var(--s3);overflow:hidden;flex:none}
.fillf{height:100%;border-radius:4px;background:var(--ok)}
.fillf.w{background:var(--wn)}
.fillf.d{background:var(--dg)}
.burger{display:none;width:34px;height:34px;border-radius:var(--r-s);flex:none;
  align-items:center;justify-content:center;font-size:15px;cursor:pointer;
  background:var(--s3);border:1px solid var(--line);color:var(--tx1)}
.scrim{display:none;position:absolute;inset:0;z-index:4;background:rgba(6,9,13,.5)}
.scrim.on{display:block}
@media (max-width:1220px){
  .kpis{grid-template-columns:repeat(2,1fr)}
  .g2{grid-template-columns:1fr}
  .g3{grid-template-columns:1fr 1fr}
  .vlist{width:262px}
}
@media (max-width:980px){
  .side{transform:translateX(-104%);transition:transform .22s ease;
        box-shadow:0 0 60px rgba(0,0,0,.5)}
  .side.open{transform:none;z-index:7}
  .scrim.on{z-index:6}
  .top{left:16px;right:16px}
  .main{left:0;padding-left:16px;padding-right:16px}
  .burger{display:flex}
  .vlist{right:16px;top:96px;width:auto;left:16px;max-height:270px}
  .g3{grid-template-columns:1fr}
  .card{overflow-x:auto}
  table{min-width:660px}
  .g2 > div, .g3 > div{min-width:0}
  .mapbar{flex-wrap:wrap}
  .mapbar > div[style*="flex:1"]{display:none}
}
@media (max-width:620px){
  .app{min-height:100vh}
  .top{height:auto;flex-wrap:wrap;padding:9px 12px;gap:8px;top:12px;left:12px;right:12px}
  .top > *{min-width:0}
  .top .pill{flex:0 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .top .pill.ico, .top .burger, .top .ava{flex:none}
  .top .rolepill{flex:1 1 0;text-align:center}
  .top .pill.live{order:4;flex:0 0 auto}
  .top .pill.live .lw{display:none}
  .search{order:3;flex:1 1 180px;height:32px}
  .main{top:132px;padding:8px 12px 26px}
  .kpis{grid-template-columns:1fr;gap:10px}
  body[data-role="op"] .kpis{grid-template-columns:1fr 1fr;gap:8px}
  body[data-role="op"] .kpi{padding:11px 12px}
  body[data-role="op"] .kv{font-size:21px;margin:5px 0 1px}
  body[data-role="op"] .kd{margin-top:6px}
  .kv{font-size:23px}
  .pt{font-size:18px}
  .ph{flex-direction:column;align-items:flex-start;gap:11px}
  .pa{width:100%;flex-wrap:wrap}
  .fbar{flex-wrap:wrap}
  .mod{width:calc(100% - 24px);border-radius:18px}
  .mod-h{padding:17px 18px 0}
  .mod-b{padding:15px 18px 4px}
  .mod-f{padding:15px 18px 17px;flex-wrap:wrap}
  .mod-f .btn{flex:1;text-align:center}
  .vplate{font-size:19px}
  .ps{white-space:normal;line-height:1.5}
  .main{top:112px}
  .rt{min-width:0}
  .rt, .rt tbody, .rt tr, .rt td{display:block}
  .rt tr.h{display:none}
  .rt tr{padding:8px 14px 12px;border-top:1px solid var(--line)}
  .rt tr:first-of-type{border-top:none}
  .rt td{border:none;padding:4px 0;display:flex;justify-content:space-between;
         align-items:baseline;gap:12px;text-align:right}
  .rt td::before{content:attr(data-l);color:var(--tx3);font-size:10.5px;
                 letter-spacing:.05em;text-transform:uppercase;flex:none;text-align:left}
  .rt td.act{display:block;text-align:left;padding-top:9px}
  .rt td.act::before{display:none}
  .rt td.act > div{display:inline-block;margin:0 0 0 6px!important}
}
body[data-role="dr"] .top .live,
  body[data-role="op"] .top .live{display:none}
body[data-role="dr"] .top .search{color:var(--tx3)}
.rolepill{border-color:var(--in);color:var(--in);font-weight:640}
.rgrid{display:grid;grid-template-columns:1.4fr repeat(6,1fr);gap:0;font-size:12px}
.rgrid > div{padding:9px 10px;border-bottom:1px solid var(--line)}
.rgrid .rh{font-weight:660;font-size:11px;text-transform:uppercase;letter-spacing:.04em;
    color:var(--tx3);border-bottom:1px solid var(--line-s)}
.rgrid .rl{color:var(--tx3)}
.rgrid .y{color:var(--ok);text-align:center;font-weight:700}
.rgrid .n{color:var(--tx3);opacity:.35;text-align:center}
.rgrid .h{color:var(--wn);text-align:center;font-weight:700}
.mono{font-family:var(--mono);font-size:12px;letter-spacing:-.01em}
.as-i{padding:9px 12px;border-radius:var(--r-s);background:var(--s3);
    border:1px solid var(--line)}
.duo{display:flex;flex-direction:column;margin:8px 0 2px}
.d-m,.d-p{letter-spacing:-.028em;line-height:1.16}
.d-m{font-size:27px;font-weight:670;color:var(--tx1);order:1}
.d-p{font-size:13px;font-weight:560;color:var(--tx2);order:2;margin-top:3px}
.d-m span{font-size:12.5px;font-weight:520;color:var(--tx3);margin-left:3px}
.d-p span{font-size:11px;font-weight:500;color:var(--tx3);margin-left:2px}
body[data-role="mg"] .d-p{font-size:27px;font-weight:670;color:var(--tx1);order:1;margin-top:0}
body[data-role="mg"] .d-m{font-size:13px;font-weight:560;color:var(--tx2);order:2;margin-top:3px}
body[data-role="mg"] .d-p span{font-size:12.5px;font-weight:520;margin-left:3px}
body[data-role="mg"] .d-m span{font-size:11px;font-weight:500;margin-left:2px}
.duo2{display:flex;flex-direction:column}
.t-m{order:1;color:var(--tx1)}
.t-p{order:2;font-size:10.5px;color:var(--tx3);margin-top:1px}
body[data-role="mg"] .t-p{order:1;font-size:inherit;color:var(--tx1);margin-top:0}
body[data-role="mg"] .t-m{order:2;font-size:10.5px;color:var(--tx3);margin-top:1px}
/* REQ-UIX-042 fixes the MARKUP order of a Duo (physical, then money) and the
   server names the leading reading with `.lead`; the drawing says which is big
   and which is first with `order` (design/app.css:776-781), never by moving
   nodes. The product's own class names (`duo-p`/`duo-m`, `lead`) stand in for
   the drawing's `.d-m`/`.d-p` (+ body[data-role=mg] flip), which nothing emits.

   TILE — design/app.css:776-781: leading 27px/670/order 1, other 13px/order 2. */
.kpi .duo-p,.kpi .duo-m{letter-spacing:-.028em;line-height:1.16;margin-left:0}
.kpi .duo .lead{font-size:27px;font-weight:670;color:var(--tx1);order:1;margin-top:0}
.kpi .duo .duo-p:not(.lead),.kpi .duo .duo-m:not(.lead){font-size:13px;font-weight:560;
  color:var(--tx2);order:2;margin-top:3px}
.kpi .duo .lead .u{font-size:12.5px;font-weight:520;color:var(--tx3);margin-left:3px}
.kpi .duo .duo-p:not(.lead) .u,.kpi .duo .duo-m:not(.lead) .u{font-size:11px;font-weight:500;
  color:var(--tx3);margin-left:2px}
/* TABLE CELL — design/app.css:785-790 (`.duo2`): the leading reading is the
   cell's own text, the other 10.5px under it, no tile margin. */
td .duo{margin:0}
td .duo .lead{font-size:inherit;font-weight:inherit;color:var(--tx1);order:1;margin-top:0}
td .duo .duo-p:not(.lead),td .duo .duo-m:not(.lead){font-size:10.5px;color:var(--tx3);
  order:2;margin-top:1px}
.sgrid{display:grid;grid-template-columns:1fr 1fr;gap:13px;align-items:start}
.sgrid .wide{grid-column:1 / -1}
@media (max-width:900px){
  .sgrid{grid-template-columns:1fr}
}
.phone{width:236px;margin:0 auto;border-radius:26px;border:1px solid var(--line-s);
    background:var(--s2);padding:13px;box-shadow:var(--shadow)}
.phone .pscr{border-radius:16px;background:#0A0D11;height:172px;display:grid;
    place-items:center;text-align:center;padding:14px;border:1px solid var(--line)}
.note details{margin:0}
.note summary{cursor:pointer;list-style:none;display:block;position:relative;
    padding-right:19px}
.note summary::-webkit-details-marker{display:none}
.note summary::after{content:"\203A";position:absolute;right:2px;top:-1px;
    font-size:15px;line-height:1;color:var(--tx3);
    transform:rotate(90deg);transform-origin:50% 50%;transition:transform .16s}
.note details[open] summary::after{transform:rotate(-90deg)}
.note summary:hover::after{color:var(--tx1)}
.note summary:focus-visible{outline:2px solid var(--ok);outline-offset:3px;
    border-radius:4px}
.note details > *:not(summary){margin-top:7px}
@media (prefers-reduced-motion:reduce){
  .note summary::after{transition:none}
}
.day1{display:none}
body[data-role="ac"] .kpi.noac{display:none}
button.alb,a.alb{font:inherit;font-size:11px;font-weight:570;background:transparent;line-height:inherit;text-decoration:none;display:inline-block}
.pt.vhead{display:flex;align-items:center;gap:13px}
@media (max-width:620px){
  .as-g{grid-template-columns:1fr 1fr}
}
.gauge{height:9px;border-radius:5px;background:var(--s3);overflow:hidden;margin:11px 0 7px}
.gfill{height:100%;border-radius:5px;background:linear-gradient(90deg,#28A97B,#6BEFBC)}
.gfill.w{background:linear-gradient(90deg,#B4720C,var(--wn))}
.qlist{padding-top:2px;padding-bottom:2px}
.q{display:flex;gap:10px;align-items:center;padding:10px 0;border-bottom:1px solid var(--line)}
.q:last-child{border-bottom:none}
.q[data-go]{cursor:pointer}
.thumb{width:40px;height:40px;border-radius:9px;flex:none;background:linear-gradient(150deg,#1B2620,#101711);
       border:1px solid var(--line);display:grid;place-items:center;font-size:15px;color:#4E7A63}
.qt{font-size:12.5px;font-weight:590}
.qs{font-size:11px;color:var(--tx3);margin-top:2px;line-height:1.5}
.vk{display:flex;gap:9px;padding:9px 0;border-bottom:1px solid var(--line)}
.vk:last-of-type{border-bottom:none}
.vki{width:19px;height:19px;border-radius:50%;flex:none;display:grid;place-items:center;font-size:10px;font-weight:800}
.vki.ok{background:var(--ok-d);color:var(--ok)}
.vki.w{background:var(--wn-d);color:var(--wn)}
.vkt{font-size:12.5px;font-weight:580}
.vks{font-size:11px;color:var(--tx3);margin-top:2px;line-height:1.5}
@media (max-width:620px){
  .shotg > div:last-child{order:-1}
}
.astrip{position:sticky;top:-8px;z-index:3;display:flex;gap:10px;padding:10px 12px;border-radius:var(--r);margin-bottom:15px;overflow-x:auto}
.ast{flex:1 1 0;min-width:150px;padding:6px 10px;border-right:1px solid var(--line)}
.ast:last-child{border-right:none}
.ast.go{cursor:pointer;border-radius:var(--r-s)}
.ast.go:hover{background:var(--s3)}
.asl{font-size:9.5px;font-weight:680;letter-spacing:.08em;text-transform:uppercase;color:var(--tx3)}
.asv{font-size:19px;font-weight:670;letter-spacing:-.025em;margin-top:3px}
.asv span{font-size:11px;font-weight:520;color:var(--tx3);margin-left:2px}
.ass{font-size:10.5px;color:var(--tx2);margin-top:3px;line-height:1.45}
.asec{display:flex;align-items:flex-start;gap:12px;margin:22px 0 12px;flex-wrap:wrap}
.asn{width:26px;height:26px;border-radius:50%;flex:none;display:grid;place-items:center;font-size:12px;font-weight:700;
     background:var(--ok-d);color:var(--ok);box-shadow:inset 0 0 0 1px var(--ok-b)}
.ast-t{font-size:16.5px;font-weight:660;letter-spacing:-.015em}
.ast-q{font-size:11.5px;color:var(--tx3);margin-top:2px}
.ph-vh{flex-basis:100%;display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-left:38px}
.pr{display:inline-block;font-family:var(--mono);font-size:9.5px;color:var(--tx3);margin-top:5px}
.pr::before{content:"\2190\00a0"}
.kvr .pr,.km .pr,.ass .pr{margin-top:0;margin-left:5px}
.dm{display:inline-block;font-size:10px;font-weight:640;padding:1px 6px;border-radius:20px;color:var(--in);background:var(--in-d);white-space:nowrap}
.dmleg{flex-basis:100%;margin-left:38px;font-size:11px;color:var(--tx3)}
.kpis.k5{grid-template-columns:repeat(5,1fr)}
.livedot{display:flex;gap:10px;align-items:flex-start}
.livedot .vdot{margin-top:5px}
.pair{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.pairc{background:var(--s3);border:1px solid var(--line);border-radius:var(--r-s);padding:9px 11px}
.pairc .kv{font-size:21px;margin:4px 0 1px}
.tline{fill:none;stroke:var(--wn);stroke-width:1.6;stroke-linejoin:round;stroke-dasharray:4 3}
.sunb{fill:var(--wn-d)}
.sunl{font-size:9.5px;fill:var(--wn);font-family:var(--mono)}
.axl.tl{fill:var(--wn)}
.ndot{fill:var(--ok)}
.ndot.now{fill:var(--in)}
.nbar{fill:var(--ok-b)}
.medl{fill:none;stroke:var(--in);stroke-width:2}
.quant{stroke:var(--tx3);stroke-width:1;stroke-dasharray:2 3}
.sdot{fill:var(--ok);opacity:.85}
.vline{fill:none;stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.vline.on{stroke:var(--ok)}
.vline.off{stroke:var(--tx3)}
.sw{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:4px;vertical-align:-1px}
.sw-p{background:var(--ok)}
.sw-t{background:var(--wn)}
.sw-off{background:var(--tx3)}
.tl{display:flex;height:18px;border-radius:6px;overflow:hidden;background:var(--s3)}
.tls{min-width:2px}
.tl-st{background:var(--s3)}
.tl-idl{background:var(--wn)}
.tl-mv{background:var(--ok)}
.tl-ref{background:var(--in)}
.tl-gap{background:var(--dg-d)}
.tl-al{background:var(--dg)}
.tl-unk{background:var(--line-s)}
.tl-nofix{background:var(--tx3)}
.tlax{display:flex;justify-content:space-between;font-size:9.5px;color:var(--tx3);font-family:var(--mono);margin-top:4px}
.tlleg{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:10.5px;color:var(--tx3);margin-top:8px}
.tlleg .sw{border:1px solid var(--line)}
/* «День парка одной полосой» (design-v2 p-dash): the legend of three kinds and the one line under it. */
.dayl{display:flex;flex-wrap:wrap;gap:6px 16px;margin-top:10px;font-size:11.5px;color:var(--tx2)}
.dayl .sw{margin-right:6px}
.dayo{margin-top:8px;font-family:var(--mono);font-size:13px;font-weight:620}
.six{display:flex;height:14px;border-radius:5px;overflow:hidden;background:var(--s3)}
.six > div{min-width:2px}
.bf.n{background:var(--tx3)}
.br.brw{grid-template-columns:96px 1fr 150px}
.instq{display:flex;margin-bottom:9px}
.cb > .instq{gap:8px;align-items:center}
.cb > .instq .inp{height:34px;width:auto;flex:1}
.g2e{grid-template-columns:1fr 1fr}
@media (max-width:1220px){
  .kpis.k5{grid-template-columns:repeat(3,1fr)}
  .g2e{grid-template-columns:1fr}
}
@media (max-width:620px){
  .astrip{position:static;display:grid;grid-template-columns:1fr 1fr;gap:8px;overflow:visible}
  .ast{border-right:none;border:1px solid var(--line);border-radius:var(--r-s);min-width:0}
  .kpis.k5{grid-template-columns:1fr}
  .pair{grid-template-columns:1fr}
  .ph-vh,.dmleg{margin-left:0}
  .br.brw{grid-template-columns:78px 1fr 132px}
}
.segw.wrap{flex-wrap:wrap;max-width:100%}
.mh{--sp1:#8FB4FF;--sp2:#4F7BE8;--sp3:#2A4DC0;--st-park:var(--tx3);
    display:grid;grid-template-columns:1fr 300px;grid-template-rows:auto auto;gap:13px;margin-bottom:13px}
[data-theme="day"] .mh{--sp1:#9FB9F2;--sp2:#5A7FE0;--sp3:#22409E}
.mh .mapcard{grid-column:1;grid-row:1}
.mh .pside{grid-column:2;grid-row:1 / span 2;align-self:start}
.mh .plyr{grid-column:1;grid-row:2}
.mapc{position:relative;height:520px;overflow:hidden;border-radius:var(--r) var(--r) 0 0;background:var(--s3)}
.mapc > svg{position:absolute;inset:0;width:100%;height:100%;display:block}
.mh-built rect{fill:var(--line);opacity:.55}
.mh-water path{fill:none;stroke:rgba(90,140,220,.22);stroke-width:12;stroke-linecap:round}
.mh-roads path{fill:none;stroke:var(--line-s);stroke-width:5;stroke-linecap:round;stroke-linejoin:round}
.mh-lbl text{font-family:var(--font);font-size:13px;fill:var(--tx3);font-weight:560;letter-spacing:.01em}
.mh-lbl .mh-lblw{font-style:italic;font-weight:450;fill:rgba(90,140,220,.7)}
.mh-trk .sp1{stroke:var(--sp1)}
.mh-trk .sp2{stroke:var(--sp2)}
.mh-trk .sp3{stroke:var(--sp3)}
.mh-pause circle{fill:var(--s1);stroke:var(--tx3);stroke-width:2.5}
.mh-place rect{fill:var(--s1);stroke:var(--line-s);stroke-width:1.2}
.mh-place text{font-size:11px;text-anchor:middle;fill:var(--tx2)}
.mh-stop text{font-family:var(--font);font-size:13px;font-weight:700;fill:#fff;text-anchor:middle}
.mh-stop .st-fill{fill:var(--in);stroke:var(--s1);stroke-width:2.5}
.mh-stop .st-idle{fill:var(--wn);stroke:var(--s1);stroke-width:2.5}
.mh-stop .st-park{fill:var(--tx3);stroke:var(--s1);stroke-width:2.5}
.mh-stop .st-drop{fill:var(--dg);stroke:var(--s1);stroke-width:2.5}
.mh-stop .st-silent{fill:none;stroke:var(--tx3);stroke-width:2;stroke-dasharray:4 3}
.mh-now circle{fill:var(--ok);stroke:var(--s1);stroke-width:2;opacity:.75}
.mh-veh .ring{fill:var(--s1);fill-opacity:.88;stroke:var(--ok);stroke-width:2.5}
.mh-veh path{fill:var(--ok);stroke:var(--s1);stroke-width:1.5;stroke-linejoin:round}
.mh-chip rect{fill:var(--s1);stroke:var(--line-s);stroke-width:1}
.mh-chip text{font-family:var(--mono);font-size:11px;fill:var(--tx1)}
.mh-chip .chip-veh rect{stroke:var(--ok-b);fill:var(--s1)}
.mh-chip .chip-veh text{fill:var(--ok);font-weight:600}
.mh-chip .chip-mut text{fill:var(--tx3)}
.mh-scale path{fill:none;stroke:var(--tx3);stroke-width:1.5}
.mh-scale text{font-family:var(--mono);font-size:10px;fill:var(--tx3);text-anchor:middle}
.mh-layers{position:absolute;left:12px;top:12px;display:flex;gap:6px;flex-wrap:wrap;max-width:60%}
.mh-ctl{position:absolute;right:12px;top:12px;bottom:auto;left:auto}
.mh-pop{position:absolute;left:12px;bottom:44px;width:262px;border-radius:var(--r-s);padding:10px 12px}
.mp-t{font-size:12.5px;font-weight:620}
.mp-s{font-size:10.5px;color:var(--tx3);margin:2px 0 6px}
.mp-r{display:flex;justify-content:space-between;gap:10px;font-size:11px;padding:3px 0;border-top:1px solid var(--line)}
.mp-r span{color:var(--tx3);flex:none}
.mp-r b{font-weight:560;text-align:right}
.mh-attr{position:absolute;right:10px;bottom:8px;font-size:9.5px;color:var(--tx3);background:var(--s1);padding:2px 7px;border-radius:6px;opacity:.9}
.mh-leg{display:flex;flex-wrap:wrap;gap:6px 14px;align-items:center;padding:10px 16px;font-size:10.5px;color:var(--tx3);border-top:1px solid var(--line)}
.mh-leg .sw{border:none;height:4px;border-radius:2px;width:16px;vertical-align:2px}
.sw.sp1{background:var(--sp1)}
.sw.sp2{background:var(--sp2)}
.sw.sp3{background:var(--sp3)}
.sw.sw-gap{background:repeating-linear-gradient(90deg,var(--tx3) 0 4px,transparent 4px 7px)}
.sd{display:inline-block;width:11px;height:11px;border-radius:50%;margin-right:4px;vertical-align:-1px;box-sizing:border-box}
.sd.st-park{background:var(--tx3)}
.sd.st-idle{background:var(--wn)}
.sd.st-drop{background:var(--dg)}
.sd.st-fill{background:var(--in)}
.sd.st-silent{border:2px dashed var(--tx3)}
.sd.st-pause{width:7px;height:7px;border:2px solid var(--tx3);background:var(--s1)}
.sd.st-idle.st-sil{box-shadow:0 0 0 2px var(--s1),0 0 0 3.5px var(--tx3)}
.st-t{font-weight:600}
.st-t.st-idle{color:var(--wn)}
.st-t.st-fill{color:var(--in)}
.st-t.st-silent{color:var(--tx2)}
.st-t.st-drop{color:var(--dg)}
.plyr{padding:12px 16px 13px}
.pl-bar{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.pl-btn{display:inline-grid;place-items:center;width:30px;height:30px;border-radius:9px;background:var(--s3);color:var(--tx2);font-size:12px;cursor:pointer;border:1px solid var(--line)}
.pl-btn.pl-play{background:var(--ok);color:#fff;border-color:var(--ok);width:36px}
.pl-time{font-family:var(--mono);font-size:14px;font-weight:600;color:var(--tx1);min-width:64px}
.plyr .instq{margin:0;gap:6px;align-items:center}
.plyr .instq .inp{height:30px;width:auto;flex:none;padding:0 11px;font-size:11.5px;border-radius:9px}
.pl-ans{font-size:11px;color:var(--tx2);margin:8px 0 12px;padding:6px 10px;border-radius:8px;background:var(--s3)}
.pl-strip{position:relative;padding-top:20px}
.pl-marks{position:absolute;left:0;right:0;top:0;height:18px}
.pm{position:absolute;top:0;transform:translateX(-50%);font-family:var(--mono);font-size:9.5px;font-weight:700;line-height:16px;height:16px;padding:0 5px;border-radius:5px;background:var(--s3);color:var(--tx2);cursor:pointer;white-space:nowrap}
.pm-pt{background:var(--tx1);color:var(--bg)}
.pm-fill{color:var(--in);background:var(--in-d)}
.pm-al{color:#fff;background:var(--dg);width:16px;padding:0;text-align:center}
.pm-pause{width:7px;height:7px;top:5px;padding:0;border-radius:50%;background:var(--s1);border:2px solid var(--tx3);box-sizing:border-box}
.pl-strip .tl{height:26px}
.tl-fut{background:repeating-linear-gradient(135deg,var(--s3) 0 6px,var(--line) 6px 8px)}
.pl-head{position:absolute;top:18px;width:2px;height:30px;background:var(--ok);transform:translateX(-50%);box-shadow:0 0 0 1px var(--s1)}
.pl-head::after{content:"";position:absolute;left:50%;top:-2px;width:10px;height:10px;border-radius:50%;background:var(--ok);transform:translate(-50%,-50%);box-shadow:0 0 0 2px var(--s1)}
.pl-now{position:absolute;top:18px;width:1px;height:30px;border-left:1px dashed var(--tx3);transform:translateX(-50%)}
.pl-now span{position:absolute;left:4px;top:8px;font-size:9px;color:var(--tx3);white-space:nowrap}
.pside .kvr .v{font-size:12px}
.pside .kvr .pr{margin-top:0;margin-left:5px}
.sheet-h{display:none}
@media (max-width:1220px){
  .mh{grid-template-columns:1fr 262px}
}
@media (max-width:980px){
  .mh{grid-template-columns:1fr}
  .mh .mapcard,.mh .plyr,.mh .pside{grid-column:1}
  .mh .mapcard{grid-row:1}
  .mh .plyr{grid-row:2}
  .mh .pside{grid-row:3}
  .mapc{height:400px}
  .mh-pop{display:none}
  .mh-layers{max-width:75%}
  .mh .card{overflow-x:visible}
}
@media (max-width:620px){
  .mh{margin-left:-12px;margin-right:-12px;gap:10px}
  .mh .mapcard{border-radius:0;border-left:none;border-right:none}
  .mapc{height:360px;border-radius:0}
  .mh .plyr{margin:0 12px;padding:10px 12px 12px}
  .plyr .instq{width:100%}
  .plyr .instq .inp{flex:1}
  .mh .pside{position:sticky;bottom:0;z-index:4;margin:0 12px;border-radius:var(--r-l) var(--r-l) 0 0;max-height:46vh;overflow:auto;box-shadow:0 -10px 30px rgba(0,0,0,.25)}
  .sheet-h{display:block;width:38px;height:4px;border-radius:2px;background:var(--line-s);margin:6px auto -4px}
  .mh .pside .ch{padding:9px 14px}
  .mh .pside .cb{padding:9px 14px 12px}
  .mh .pside .kvr{padding:5px 0}
  .mh-leg{padding:9px 12px}
  .pm{font-size:9px}
}
.mapleg .lgi{font-size:11px;color:var(--tx2)}
.mapleg > span{white-space:nowrap}
/* Owner's order 2026-09-28: the map takes almost the whole screen and the
 * «Автомобили» list moves BELOW it, at every width — not only under 980px as
 * before. `.mlv` is one column now, the map's own card first (the server's
 * block order, `mapscreens.go`'s `mapLiveCanvas` before `mapLiveList`) and the
 * list's card second, so the DOM order this file draws is already the order
 * the drawing wants; only the grid and the map's height changed. */
.mlv{display:flex;flex-direction:column;gap:13px;margin-bottom:13px}
/* min(...) keeps the map at least 70vh tall under the header on every screen
 * and gives it more room on a wide one, without ever exceeding a sane cap so a
 * very tall monitor does not turn the map into the whole page. */
.mlv .mapc{height:max(70vh,460px);border-radius:var(--r)}
.mlv .vlist{position:static;width:auto;max-height:none;overflow:visible;padding:6px;border-radius:var(--r)}
.vl-h{display:flex;align-items:center;gap:6px}
.vl-h .cs{flex:1}
.vl-upd{font-size:10.5px;color:var(--tx3);font-family:var(--mono);font-weight:500}
.vl-s{padding:2px 5px 6px}
.vl-s .inp{height:32px;font-size:12px}
.vl-chips{display:flex;flex-wrap:wrap;gap:5px;padding:0 5px 8px}
.vl-chips .pill{padding:3px 9px;font-size:10.5px}
/* The rows: a responsive grid rather than one long column, now that the list
 * is a full-width section under the map and not a 340px sidebar. */
.vl-rows{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:4px 10px}
/* «Парк сейчас» (map.live.summary, seven numbers) compacted into one strip
 * above the map, drawn with the same `.astrip`/`.ast` the Обзор/Аналитика
 * strip already uses (design/app.css:1813) rather than the tall `.kpi`
 * tiles — `.mapnow` only drops the sticky positioning that strip is not on
 * the map screen for. */
.astrip.mapnow{position:static;margin-bottom:13px}
.vrow.fx:hover{background:var(--s3)}
.vrow.on:hover{background:var(--ok-d)}
.vrow.nomap{opacity:.55}
.vdot.i{background:var(--in);box-shadow:0 0 9px var(--in)}
.c-white{--bc:#F4F4F2;--bs:#7D838B}
.c-black{--bc:#17191C;--bs:#C9CDD2}
.c-silver{--bc:#C9CDD2}
.c-grey{--bc:#7D838B}
.c-red{--bc:#D23B2E}
.c-blue{--bc:#2F6FD6}
.c-navy{--bc:#1F3A70}
.c-green{--bc:#2E9E5B}
.c-darkgreen{--bc:#1F5E3A}
.c-yellow{--bc:#F2C230}
.c-orange{--bc:#F0812A}
.c-brown{--bc:#7A4E2B}
.c-beige{--bc:#D9C7A3}
.c-none{--bc:#7D838B;--bs:var(--tx2)}
.kb{fill:var(--bc);stroke:var(--bs,var(--s1));stroke-width:1;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.c-none .kb{stroke-dasharray:2 1.5;stroke-width:1.2;fill-opacity:.5}
.kic{display:inline-block;width:26px;height:16px;vertical-align:-3px;margin-right:6px;flex:none;overflow:visible}
.kic.sm{width:20px;height:12px;margin-right:5px;vertical-align:-2px}
.ml-veh .ring{fill:var(--s1);fill-opacity:.88;stroke:var(--ok);stroke-width:2.5}
.ml-veh .ring.st-idle{stroke:var(--wn)}
.ml-veh .ring.st-park{stroke:var(--tx3)}
.ml-veh .ring.st-fill{stroke:var(--in)}
.ml-veh .ring.st-drop{stroke:var(--dg)}
.ml-veh .ring.st-silent{stroke:var(--tx3);stroke-dasharray:4 3;stroke-width:2}
.ml-veh .ring.st-stale{stroke:var(--tx3);stroke-dasharray:2 2;stroke-width:2}
.ml-veh .crs{fill:var(--ok);stroke:var(--s1);stroke-width:1}
.ml-veh.sel .ring{stroke-width:3.5}
.ml-veh .halo{fill:none;stroke:var(--ok-b);stroke-width:1.5}
.sr{display:inline-block;width:12px;height:12px;border-radius:50%;border:2.5px solid var(--ok);margin-right:4px;vertical-align:-2px;box-sizing:border-box;background:var(--s1)}
.sr.st-idle{border-color:var(--wn)}
.sr.st-park{border-color:var(--tx3)}
.sr.st-drop{border-color:var(--dg)}
.sr.st-fill{border-color:var(--in)}
.sr.st-silent{border:2px dashed var(--tx3)}
.sr.st-stale{border:2px dotted var(--tx3)}
.kpick .seg{display:inline-flex;align-items:center}
.kpick .kic{width:26px;height:16px;margin-right:7px}
.swr{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
.swb{width:24px;height:24px;border-radius:7px;background:var(--bc);border:1px solid var(--bs,var(--line-s));cursor:pointer;box-sizing:border-box}
.swb.on{box-shadow:0 0 0 2px var(--s1),0 0 0 4px var(--ok)}
.swb.c-none{background:repeating-linear-gradient(45deg,var(--s3) 0 3px,var(--s1) 3px 6px);border-style:dashed}
.mapleg .lgi .kic.sm{margin-right:2px}
.ml-st circle{stroke:var(--s1);stroke-width:2.5}
.ml-st .st-park{fill:var(--tx3)}
.ml-st .st-idle{fill:var(--wn)}
.ml-st .st-fill{fill:var(--in)}
.ml-st .st-drop{fill:var(--dg)}
.ml-sil circle{fill:none;stroke:var(--tx3);stroke-width:2;stroke-dasharray:4 3}
.ml-stale circle{fill:var(--s1);stroke:var(--tx3);stroke-width:2;stroke-dasharray:2 2}
.ml-lbl rect{fill:var(--s1);stroke:var(--line-s);stroke-width:1}
.ml-lbl text{font-family:var(--mono);font-size:10.5px;fill:var(--tx2)}
.ml-lbl.sel rect{stroke:var(--ok-b)}
.ml-lbl.sel text{fill:var(--ok);font-weight:600}
.ml-lbl.st-idle text{fill:var(--wn)}
.ml-lbl.st-fill text{fill:var(--in)}
.ml-lbl.st-drop text{fill:var(--dg)}
.ml-lbl.sil text,.ml-lbl.stale text{fill:var(--tx3)}
.vpop{left:12px;bottom:12px;width:396px;padding:12px 14px}
.vpop .fg{grid-template-columns:repeat(4,1fr);gap:6px}
.vpop .fi{padding:7px 9px}
.vpop .fv{font-size:15px}
.vpop .fh{margin-bottom:9px}
.sd.st-mv{background:var(--ok)}
.sd.st-stale{border:2px dotted var(--tx3);background:var(--s1)}
.mh-fit .dim{opacity:.32}
.mh-trk .hi{stroke-width:5}
.pm.on{box-shadow:0 0 0 2px var(--ok)}
@media (max-width:980px){
  .vpop{display:none}
}
@media (max-width:620px){
  .mlv{margin-left:-12px;margin-right:-12px;gap:10px}
  .mlv .mapcard{border-radius:0;border-left:none;border-right:none}
  .mlv .mapc{height:max(70vh,340px);border-radius:0}
  /* The list is no longer a floating bottom sheet on a phone: it stands below
   * the map in the ordinary page flow, like at every other width, so it needs
   * neither the sticky handle nor its own scroll region — the page scrolls. */
  .mlv .vlist{margin:0 12px}
  .mlv .vlist .sheet-h{display:none}
  .mlv .vl-chips{padding-bottom:6px}
  .vl-rows{grid-template-columns:1fr}
}
.vbar{margin-bottom:12px}
.vbar .seg .ndot,.vbar .seg .ncount{margin-left:5px}
body[data-role="ac"] .noac{display:none}
@media (max-width:620px){
  .vbar .seg{padding:5px 10px;font-size:11.5px}
  .pa .segw{flex:1 1 100%;flex-wrap:wrap;max-width:100%}
}
.av{display:inline-flex;width:28px;height:28px;border-radius:50%;background:var(--in-d);color:var(--in);font-size:10.5px;font-weight:700;align-items:center;justify-content:center;flex:none;letter-spacing:.02em}
.av.off{background:var(--s3);color:var(--tx3)}
.who{display:flex;align-items:center;gap:9px}
.who .sub{font-size:11px;color:var(--tx3);margin-top:1px;white-space:nowrap}
.ldot{display:inline-block;width:7px;height:7px;border-radius:50%;background:var(--ok);margin-right:6px;vertical-align:middle}
.tfilt{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:9px 13px;margin-bottom:13px}
.tfilt .inp{height:32px;flex:1;min-width:180px;width:auto;font-size:12px}
.tfilt .seg b{font-weight:640;margin-left:5px;color:var(--tx3)}
.tfilt .seg.on b{color:var(--ok)}
/* .chipw is a toggle group's row (FilterGroup.Toggle, added 2026-09-22): a
   set of independent `.pill` chips, none sharing the `.segw` radio's own
   background box, matching design/app.html#p-tariffs's own bare pills. */
.tfg .chipw{display:flex;gap:6px;flex-wrap:wrap}
.rlist{display:grid;grid-template-columns:1fr 1fr;gap:0 26px}
.rlist .kvr .l{color:var(--tx2)}
.rlist .kvr .v{font-size:14px;line-height:1}
.rlist .y{color:var(--ok)}
.rlist .n{color:var(--tx3)}
.jact .tag{float:right;margin-left:8px}
.jact b{display:block;white-space:nowrap}
.jact .mut{font-size:11px;display:block;margin-top:2px}
@media (max-width:980px){
  .rlist{grid-template-columns:1fr}
  .who .sub{white-space:normal}
}
@media (max-width:620px){
  .tfilt .inp{min-width:100%}
  .jact b{white-space:normal}
}

/* ═════════ RECONCILIATION ═════════ */
/* The rail is buttons here, not divs: the drawing's .nav rule sets no reset, so
   the product's button reset is restated after it. */
.nav,.nsecg{width:100%;background:none;border:none;font-family:var(--font);text-align:left}
.nav.on{background:var(--ok-d)}
.nsecg{background:var(--s2)}
/* The top bar's first slot is a LABEL on this surface (the operator's name, the
   organisation on the customer's) and not a search box: REQ-UIX-021, a control
   either acts or is not here. The drawing's filled box is for its search
   field, which the product draws as .srch instead. */
.search{flex:1 1 auto;min-width:0;height:auto;line-height:34px;font-size:12.5px;color:var(--tx2);
  background:none;border:none;padding:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.search b{color:var(--tx1);font-weight:580}
/* The folded rail opens by a class on .app (the product's mechanism), not by
   .side.open (the drawing's). Same widths as the drawing: the rail folds at
   980 px and the burger appears there. */
@media (max-width:980px){
  .menu{display:grid}
  .app.nav-open .side{transform:none}
  .app.nav-open .nscrim{display:block;position:absolute;inset:0;z-index:4;background:rgba(6,9,13,.5)}
}
.kpi.go{cursor:pointer}
.kpi.go:hover{background:var(--s3)}
@media (max-width:620px){
  .chart{overflow-x:auto}
  .chart > svg{height:172px;width:auto;max-width:none;min-width:600px}
  /* The drawing's own escape (design/app.css:984-985, scoped to
     #p-analytics), generalised here the same way the rule above already is
     — to every .chart on every screen, because the SVG that needs it is not
     analytics-specific either. An svg carrying a style attribute is the
     drawing's own signal that THIS chart is drawn full-width and short
     (design/app.html:2993's scatter, style="max-height:130px") rather than
     wide and scrolling (the pressure/voltage tracks, which carry no style
     attribute and keep the 600 px floor above on purpose — a whole day
     genuinely needs the width). Batch-5 review, lens 4, 2026-09-24: this
     rule did not exist in the product at all, so the scatter inherited the
     600 px floor meant for the OTHER charts and scrolled sideways where the
     drawing does not. */
  .chart > svg[style]{min-width:0;width:100%;height:auto}
}
/* .num (the drawing's own class for a measured quantity, applied by table()
   since 2026-09-22) is a single class at the same specificity as .tone-good/
   -warn/-bad/-info/-muted above, and the drawing's stylesheet is appended
   AFTER those by tools/adopt_css.py — so on a cell that is both toned and a
   quantity, .num's own colour would win by position alone and silence the
   tone. REQ-UIX-024 keeps the tone as the carrier of meaning on a value that
   has one; these two-class rules outrank .num regardless of where either
   stylesheet places it, the same technique .tv.tone-* already uses above. */
td.num.tone-good{color:var(--ok)}
td.num.tone-warn{color:var(--wn)}
td.num.tone-bad{color:var(--dg)}
td.num.tone-info{color:var(--in)}
td.num.tone-muted{color:var(--tx3)}

/* ── the confirmation window, in the drawing's dialog language (owner, 2026-09-30) ──
   The window was one small grey block of capitals with «8 + 10» buried at its end.
   Now: the warning is a `.warn` box in ordinary case, the question stands alone and
   large. Nothing explanatory stands in the window (owner's order 2026-10-06). */


/* What will happen — the drawing's `.warn` box at the window's own text size. */
.warn.dlgw{white-space:pre-line;font-size:13.5px;color:var(--tx1);line-height:1.6;margin-bottom:16px;
  text-transform:none;letter-spacing:0}

/* The question: its own line, in the drawing's headline face (`.d-m`), and the
   answer box beside it, short and the same height as every other input. */
.fld label.gq-l{margin-bottom:8px}
.gq{display:flex;align-items:center;gap:12px}
.gq-x{font-family:var(--mono);font-size:27px;font-weight:670;color:var(--tx1);
  letter-spacing:-.028em;line-height:1.16;white-space:nowrap;text-transform:none}
.gq .inp{width:calc(6ch + 30px);flex:none;font-family:var(--mono);font-size:18px;
  font-weight:600;text-align:center;padding:0 8px}

/* A checkbox label is a sentence of the window, never a field caption: it keeps
   none of «.fld label»'s capitals. (`.chkl label` alone loses to the later
   `.fld label` rules of the same weight.) */
.fld .chkl label{text-transform:none;letter-spacing:0;font-size:12.5px;
  font-weight:560;color:var(--tx1);margin:0;display:block}

/* ── design base, pass 2 (2026-10-01, D-131: the drawing decides every value) ── */

/* ONE reading is first and large, the other second and small, in EVERY context
   that draws a Duo — not only the tile (`.kpi`) and the table cell (`td`) that
   the 2026-09-30 rule reached. The server names the leading reading with
   `.lead` (money for the owner's roles, physics for the manager's); the drawing
   says which is first with `order` (design/app.css:776-781, 785-790), never by
   moving nodes. The contexts the drawing draws a Duo in: a KPI tile
   (app.html:338, 1101, 1404, 1972), a card headline (:397, :2792), a table cell
   (`.duo2`, :1272) and the analytics strip (:226-229, money in `.asv`, Nm³ under
   it in `.ass`). A fact tile or a fact row has no drawn Duo: it follows the
   tile's order at the size the list already gives its value. */
.duo .lead{order:1}
.duo > :not(.lead){order:2}
.kvr .v .duo{margin:0}
.asv .duo{margin:0}
.asv .duo .lead{font-size:inherit;font-weight:inherit;letter-spacing:inherit;color:var(--tx1);margin:0}
.asv .duo > :not(.lead){font-size:10.5px;font-weight:400;letter-spacing:0;color:var(--tx2);
  margin-top:3px;line-height:1.45}

/* The page head never overflows. `.pa` was `flex-shrink:0`, so ten acts pushed
   the last ones off the page at 1440 px and squeezed the title to a sliver;
   the acts now wrap inside what is left and the title keeps a readable width. */
@media (min-width:561px){
  .ph > div:first-child{flex:1 1 260px;min-width:min(260px,100%)}
  .pa{justify-content:flex-end}
}
.pa{flex:0 1 auto;min-width:0;flex-wrap:wrap;align-items:center}

/* Words are not numbers. `.num` is monospace for figures; an absent reason and
   a flag that ride inside a numeric cell read in the face of the page. */
td.num .absent,td.num .flag,td.num .mut{font-family:var(--font)}

.btn:disabled{opacity:.55;cursor:default}
/* A row of controls keeps each at its own height: a disabled one carries its reason
   under it (`.albd`), and a stretched row turned the filled buttons beside it into
   tall squares. */
.ala{align-items:flex-start}

/* ── «Карта устройств» (design/app.html#p-pmap), the platform console ─────────
   The map IS the page: it fills the stage from under the title down, and the
   mapbar, the filter line, the panel of devices and the cluster card float over
   it as translucent `.chrome` (the drawing lays them out with absolute offsets;
   here they are cells of one overlay grid, so a wrapped bar pushes the cards
   down instead of lying on them). Below 980 px the overlay is ordinary flow and
   the panels stack under a map of fixed height.
   The points are the drawing's `.vdot` colours, one per
   state: green on line, amber silent beyond its threshold, red quarantined or
   taken out (REQ-UIX-111); a device with no position has no point and a grey dot. */
.pmstage{position:relative;height:max(560px,calc(100vh - 158px));margin-bottom:13px}
.pmground{position:absolute;inset:0;margin:0;padding:0;overflow:hidden;border-radius:var(--r)}
.pmground .mapc{height:100%;border-radius:inherit;z-index:0}
.pmground:not([data-state="normal"]){display:grid;place-items:center}
.pmover{position:absolute;inset:12px;z-index:6;display:grid;grid-template-columns:minmax(0,1fr) 296px;
  grid-template-rows:auto auto 1fr;gap:10px;pointer-events:none;min-height:0}
.pmover > *{pointer-events:auto;margin:0}
.pmo-bar{grid-column:1 / 3;grid-row:1;flex-wrap:wrap}
.pmo-filter{grid-column:1;grid-row:2;justify-self:start;max-width:100%;flex-wrap:wrap;gap:6px;padding:7px 12px}
.pmo-fl{font-size:11px;margin-right:2px}
.pmo-fp{font-size:11px;padding:4px 10px;cursor:pointer}
.pmo-pw{position:relative}
.pmo-menu{position:absolute;left:0;top:calc(100% + 6px);min-width:160px;max-height:260px;overflow:auto;
  padding:5px;border-radius:12px;z-index:20}
.pmo-mi{font-size:11.5px;padding:6px 10px;border-radius:8px;cursor:pointer;white-space:nowrap;color:var(--tx2)}
.pmo-mi:hover,.pmo-mi.on{background:var(--ok-d);color:var(--ok)}
.pmo-left{grid-column:1;grid-row:3;align-self:start;width:640px;max-width:100%;overflow:auto}
.pmo-list{grid-column:2;grid-row:2 / 4;align-self:start;position:static;width:auto;max-height:100%;overflow:auto}
.pmo-list .vl-h{display:flex;align-items:center;gap:6px}
.pmo-list .vl-h .cs{flex:1}
.pmo-list .vrow .vg{flex:0 1 84px;max-width:84px;text-align:right;overflow-wrap:anywhere}
.pmo-list .vrow > div[style*="flex:1"]{min-width:0}
@media (max-width:980px){
  .pmstage{height:auto}
  .pmground{position:relative;inset:auto;height:360px}
  .pmover{position:static;display:flex;flex-direction:column;margin-top:12px;pointer-events:auto}
  .pmo-left{width:100%}
  .pmo-list{max-height:none}
}
/* A point's own pop-up is the second provider's marker detail; here a press
   leaves the screen at once, so it would only flash. */
.pmapc .mh-pop-inline{display:none}
/* platform home — drawn p-platform */
/* Category cards: the whole card is the click target and lights up with a green
   glowing border on hover and on keyboard focus (design/app.css `.kpi.go:hover`). */
.kpis > .kpi.go:hover,.kpis > .kpi.go:focus-visible{
  outline:none;border-color:var(--ok-b);
  box-shadow:0 0 0 1px var(--ok-b),0 0 18px var(--ok-d)}
.kpis > .kpi .km{margin-top:2px}
/* The queue «Требует решения сегодня» is ONE LIST of rows. The 2026-09-07 rule
   that turns every `.cb` holding `.kvr` rows into a grid of cards is for fact
   lists; the queue opts out through `.queue`. */
#main > .card > .cb.queue:has(> .kvr){display:block;padding:15px 16px}
#main > .card > .cb.queue:has(> .kvr) > .kvr{
  display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:12px;
  margin:0 -13px;padding:9px 13px;border:0;border-bottom:1px solid var(--line);
  border-radius:var(--r-s);background:none}
#main > .card > .cb.queue:has(> .kvr) > .kvr:last-child{border-bottom:none}
#main > .card > .cb.queue:has(> .kvr) > .kvr.go:hover,
#main > .card > .cb.queue:has(> .kvr) > .kvr.go:focus-visible{background:var(--s3);outline:none}
.queue > .kvr .v{flex:none;margin-left:auto;max-width:none;text-align:right}
/* The row's link is a quiet right-aligned label: no underline, no border. */
.queue .qlink{font-size:11.5px;color:var(--tx2);white-space:nowrap;text-decoration:none;border:0}
.queue > .kvr.go:hover .qlink,.queue > .kvr.go:focus-visible .qlink{color:var(--tx1)}
@media (max-width:620px){
  #main > .card > .cb.queue:has(> .kvr) > .kvr{flex-direction:column;align-items:flex-start;gap:4px}
  .queue > .kvr .v{margin-left:0;text-align:left}
}
/* A monospace cell (Cell.Mono) holds an unbroken frame body: it wraps anywhere rather than widening the table. */
td.mono{word-break:break-all;font-size:11px}

/* ═════════ 2026-10-06 — THE SHARED CHROME, AS DRAWN (T1-T13 of _reports/2026-10-06-reviewer-page-pairs.md) ═════════
   Written by hand AFTER the adopted copy and never produced by tools/adopt_css.py: that tool
   rebuilds everything below its marker, and this block would be lost with it. Each rule names the
   drawing line it copies. */

/* T1 — the top bar's avatar menu holds what the drawing has no pill for: the zone, the profile
   and the way out. */
.amw{position:relative;flex:none;display:flex;align-items:center}
.amw .ava{cursor:pointer}
.amenu{position:absolute;right:0;top:calc(100% + 12px);z-index:50;min-width:210px;padding:6px;
  display:flex;flex-direction:column;gap:2px;border-radius:var(--r-s);background:var(--s1);
  border:1px solid var(--line-s);box-shadow:var(--shadow)}
.amenu[hidden]{display:none}
.amz,.amn{font-size:11px;color:var(--tx3);padding:7px 11px 5px}
.amn{color:var(--tx1);font-weight:600;font-size:12.5px}
.amb{font-size:12.5px;font-weight:560;text-align:left;padding:8px 11px;border-radius:8px;cursor:pointer;
  background:none;border:none;color:var(--tx1);font-family:var(--font)}
.amb:hover{background:var(--s3)}
/* design/app.css:565 — the two icon pills; the glyph is chosen by the attribute the pill flips. */
.pill.ico svg{display:block}
#th .i-sun,#mt .i-glass{display:none}
[data-theme="day"] #th .i-sun{display:block}
[data-theme="day"] #th .i-moon{display:none}
[data-mat="glass"] #mt .i-glass{display:block}
[data-mat="glass"] #mt .i-plain{display:none}
.pill.rolepill{cursor:default}
#park{cursor:pointer}
/* The console's search is the organisation shell's `.srch`, without the answers list's
   own group headings. */
.top .srch{flex:1 1 auto}
.top .srchi{width:100%}

/* REQ-UIX-107 — a button and a chip answer the pointer, one rule for every one of them. The drawing
   draws no `:hover` for `.btn` and `.pill` (D-191 part 2: the rule is written in the drawing's own
   language, not taken from it). */
.btn:hover{background:var(--s3);border-color:var(--tx3)}
.btn-p:hover{background:var(--ok);border-color:var(--ok);filter:brightness(1.1)}
.btn-d:hover{background:var(--dg);border-color:var(--dg);filter:brightness(1.1)}
.pill:not(.live):not(.rolepill):hover{background:var(--s2);border-color:var(--line-s);color:var(--tx1)}
.pill.act:hover{background:var(--ok-d);border-color:var(--ok-b);color:var(--ok)}
.btn:disabled,.btn:disabled:hover{opacity:.55;cursor:default;background:var(--s1);border-color:var(--line-s)}

/* T3 — the page head is the title and `.pa` (design/app.css:201-210); a stale note under the
   title is the only thing the head may carry besides. */
.ph .stale{font-size:11px;color:var(--wn);margin-top:3px}

/* T5 — ONE `.fbar` row of `.pill` chips (design/app.css:587, :191; the label at
   design/app.html:2394, font-size:11px). A free row ABOVE the block's card (REQ-UIX-113). */
.fbar{flex-wrap:wrap}
.fbar .inp{height:32px;flex:1 1 180px;min-width:160px;width:auto;font-size:12px}
.fbar > .mut{font-size:11px;margin-right:2px}
.fbar > .mdiv:first-child,.fbar > .mdiv:last-child{display:none}
.fbar .pill{white-space:nowrap}
@media (max-width:620px){.fbar .inp{min-width:100%}}

/* T9 — the count a card head names is the drawn right-aligned `.tag` pill
   (design/app.css:253), not grey `.cs` text. */
.ch .chr{display:flex;align-items:center;gap:9px;flex:none;margin-left:auto}
.ch > div:first-child{min-width:0}

/* T6 — the headline tiles stand free above the cards (design/app.css:224); a row of them
   needs the same gap the drawing leaves under it. */
#main > .kpis,.gc > .kpis{margin-bottom:13px}

/* T8 — a row that leads somewhere is the press, as `tr.go` (design/app.css:243,:251); the
   button inside it does its own act. */
tr.go td{cursor:pointer}
tr.go td .btn,tr.go td button{cursor:pointer}

/* T10 — every act is a `.btn` at 12.5px in the cell, the card and the head alike
   (REQ-UIX-106). The small `.alb` chip is retired. */
td .ala{display:flex;gap:6px;flex-wrap:wrap}
.btn.bad{color:var(--dg)}

/* T11 — the act's window, as drawn: `.ovl` backdrop and `.mod` (design/app.css:354-364). */
.dlg{width:min(520px,calc(100% - 40px));border-radius:22px;overflow:hidden;
  background:var(--s1);box-shadow:var(--shadow)}
.dlg::backdrop{background:rgba(6,9,13,.58);backdrop-filter:blur(7px) saturate(120%)}
[data-theme="day"] .dlg::backdrop{background:rgba(24,30,38,.34)}
.dlgf{padding:19px 22px 19px}
.dlgt{font-size:16.5px;font-weight:660;letter-spacing:-.015em;margin-bottom:0;padding-right:30px}
.dlgs{font-size:12.5px;color:var(--tx3);margin:5px 0 0;line-height:1.55;padding-right:30px}
.dlgf > .fld:first-of-type,.dlgf > .dlgm:first-of-type,.dlgf > .warn:first-of-type{margin-top:17px}
.dlgx{top:15px;right:16px;width:26px;height:26px;border:none;background:none;font-size:18px;border-radius:50%}
.dlga{padding-top:11px;margin-top:6px}
.fld .segw{width:max-content;max-width:100%;flex-wrap:wrap}
.fld .segw .seg{cursor:pointer}
.fld .segw .seg:hover{color:var(--tx1)}
@media (max-width:520px){.dlg{width:calc(100% - 16px)}}

/* T8 — the anchor that stays beneath a pressed row is not drawn as a link. */
a.rl{color:inherit;text-decoration:none;border:0}

/* Two-column layouts: a card is as tall as its own content and never stretches to the taller column
   (design/app.css `.g2` has no stretch; the adopted copy lost `align-items:start` to a later rule). */
.g2,.g2e,.g3{align-items:start}

/* 2026-10-07 — the grey tail after a figure (`Value.Mut`, «90 из 92», «при 0 °C и 101,325 кПа»)
   keeps its own gap, so the server need not prefix a space (two spaces collapse anyway). */
.vt{margin-left:4px}

/* `.sgrid` columns are half the page each: the same rule `.g2` has, for the same reason (the
   thresholds table's last column is its «Изменить»). */
.sgrid .gc .tw table{min-width:0}

/* A card head whose title is long wraps its controls onto a line of their own (right-aligned by
   .chr own margin-left:auto) instead of overlapping them. */
.ch{flex-wrap:wrap;row-gap:8px}
.ch>div:first-child{min-width:0;flex:1 1 auto}
/* Cell.TwoLine: «06.05 ·» over «11:47». */
.tln{display:block}
/* Block.WayWide: the one primary act, the card's full width, under its facts. */
.cb.wayw{padding-top:4px}
.cb.wayw .btn{display:block;width:100%}
/* A page or head act that is an address is an anchor drawn like the button. */
a.btn{display:inline-block;text-decoration:none}
a.lnk{text-decoration:none}

/* Client follow-ups, batch 3 (2026-10-07). */
/* FilterGroup.Trailing: the drawing's `<div style="flex:1">` before the right-edge group. */
.fbar > .fsp{flex:1 1 0;min-width:0}
/* A row act is the drawn small pill: design/app.html#p-billing «PDF» is `.btn` at 3px 9px, 11.5px. */
.btn.sm{font-size:11.5px;padding:3px 9px;line-height:1.3}
/* Cell.Tags and a control beside the pills: ONE line, no break (design/app.html#p-refuel). */
.cell-acts{display:inline-flex;align-items:center;gap:6px;flex-wrap:nowrap;white-space:nowrap;vertical-align:middle}
.tag.ctg{margin-left:6px}
.cell-acts > .tag.ctg{margin-left:0}
/* The score number stays beside its bar on a wide row (design/app.html#p-drivers). */
@media (min-width:561px){td .fillw{flex-wrap:nowrap}}

/* Block.Foot: the grey line under a card's table (design/app.html#p-journal, #p-acc, #p-reports). */
.tfoot{font-size:11.5px;color:var(--tx3);padding:9px 16px 11px;border-top:1px solid var(--line)}
/* The foot with its press (design-v2 08-team.css `.tfoot`: «Показано N из M» left, «Показать ещё» right;
   one under the other on a phone). A foot of words alone is a text node and is not changed by this. */
.tfoot{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:10px}
@media (max-width:620px){.tfoot{flex-direction:column;align-items:flex-start}}
/* LayoutList + TwoCol: the rights list in two columns (design/app.html#p-rolemap «что может»). */
@media(min-width:980px){.cb.kvr2{column-count:2;column-gap:32px}.cb.kvr2 .kvr{break-inside:avoid}}

/* «Карта» live (design/app.html#p-map): the grey age line in the first bar, the
   dark label beside a pin (`.ml-lbl`), the ring of a moving vehicle, and the card
   that floats over the canvas (`.vpop`) above the tiles. */
.mapbar .mb-age{font-size:11px}
.mapbar .pill{cursor:pointer}
.mapc .vpop{z-index:600}
.mapc .vpop[hidden]{display:none}
.geo-mk.geo-look.geo-vehicle{box-shadow:0 0 0 2px var(--ok)}
.geo-pill{display:block;position:absolute;left:36px;top:6px;white-space:nowrap;pointer-events:none;
  padding:2px 6px;border-radius:5px;background:var(--s1);border:1px solid var(--line-s);
  font-family:var(--mono);font-size:10.5px;line-height:13px;color:var(--tx2)}
.geo-mk.geo-vehicle .geo-pill{display:none}
.geo-mk.sel .geo-pill{display:block;border-color:var(--ok-b);color:var(--ok);font-weight:600}
.geo-mk.st-idle .geo-pill{color:var(--wn)}
.geo-mk.st-fill .geo-pill{color:var(--in)}
.geo-mk.st-silent .geo-pill,.geo-mk.st-stale .geo-pill{color:var(--tx3)}
.geo-mk.sel{z-index:700}

/* A tile whose value is absent (owner's drawing, 2026-10-07): «—» and the absent word grey on ONE
   line — a long word is cut with an ellipsis and read whole in the tooltip. A mark on a mini tile
   (the floating card's `.fi`) wraps at most two lines. */
.kv.na,.fv.na{display:flex;align-items:baseline;gap:6px;min-width:0}
.kv.na .dash,.fv.na .dash{color:var(--tx3);flex:none}
.kv.na .absent,.fv.na .absent{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:11px;font-weight:500;color:var(--tx3);background:none;border:0;padding:0}
.fi .flag{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* «Карта · история» (design/app.html#p-trips): the silhouette inside a head button, the legend headings, the focus line. */
.lki.lki-b{width:22px;height:14px;margin-right:6px;vertical-align:-3px}
.mh-leg .lg-h{font-weight:660;color:var(--tx2);text-transform:uppercase;letter-spacing:.06em;font-size:9.5px}
.mapbar .mb-focus{font-size:11px}
.mapbar .mb-all{cursor:pointer}
.mapbar [hidden]{display:none}
.sw.gl-sp0{background:var(--sp1)}
.sw.gl-sp1{background:var(--sp2)}
.sw.gl-sp2{background:var(--sp3)}
/* A fact line of a window (Field kind fact) stands apart from the first field under it, as the drawing sets it (margin-top:11px). */
.dlgf .kvr+.fld{margin-top:11px}

/* ── v2 · «Карта · Сейчас» (D-212): ported from design-v2/css/17-map.css — the five state colours defined ONCE, the strip, the stage, the drawer, the car card, the phone ── */
[data-theme="night"]{--c-move:var(--ok);--c-stand:#4F8EF0;--c-engine:var(--wn);--c-silent:#8794A5;--c-alert:var(--dg)}
[data-theme="day"]{--c-move:var(--ok);--c-stand:#2D6CD0;--c-engine:var(--wn);--c-silent:#7A838D;--c-alert:var(--dg)}
.mk-move{--k:var(--c-move)}.mk-stand{--k:var(--c-stand)}.mk-engine{--k:var(--c-engine)}.mk-silent{--k:var(--c-silent)}.mk-alert{--k:var(--c-alert)}.mk-nopos{--k:var(--c-silent)}
/* «без положения»: no device, no position or a lost fix — the sixth state of REQ-MOV-068 (CD-4), a dotted grey disc */
.mp-chip.mk-nopos i,.mp-row.mk-nopos i{background:transparent;border:2px dotted var(--c-silent)}

.mp-page{position:relative}
:where(#p-map,[data-block="overview.map"] .mapchips) button{font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;text-align:inherit}
.mp-sr{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none}
.mp-strip{position:relative;z-index:8;display:flex;align-items:center;gap:10px;height:48px;padding:0 10px;border-radius:var(--r) var(--r) 0 0}
.mp-seg{display:flex;flex:none;border:1px solid var(--line-s);border-radius:var(--r-s);overflow:hidden;background:var(--s2)}
.mp-seg > button,.mp-seg > label{display:flex;align-items:center;height:32px;padding:0 14px;font-size:12.5px;font-weight:600;color:var(--tx2);cursor:pointer;white-space:nowrap}
.mp-seg .on{background:var(--tx1);color:var(--bg)}
.mp-find{display:flex;align-items:center;gap:7px;flex:0 1 210px;min-width:0;height:34px;padding:0 10px;border-radius:var(--r-s);background:var(--s3);border:1px solid var(--line);color:var(--tx3)}
.mp-find input{flex:1;min-width:0;border:0;outline:0;background:none;color:var(--tx1);font:inherit;font-size:12.5px}
.mp-find:focus-within{outline:2px solid var(--ok-b);outline-offset:1px}
.mp-chips{display:flex;align-items:center;gap:6px;flex:1;min-width:0}
.mp-chip{display:flex;align-items:center;gap:6px;height:30px;padding:0 11px 0 9px;border-radius:999px;border:1px solid var(--line-s);background:var(--s2);color:var(--tx1);font-size:12px;font-weight:600;white-space:nowrap;cursor:pointer}
.mp-chip i{width:11px;height:11px;border-radius:50%;background:var(--k);flex:none}
.mp-chip b{font-family:var(--mono);font-size:13px}
.mp-chip:hover{background:var(--s3)}
.mp-chip.sm{height:26px;padding:0 9px 0 7px;font-size:11px}
.mp-fresh{display:flex;align-items:center;gap:6px;margin-left:auto;flex:none;font-family:var(--mono);font-size:11px;color:var(--tx3)}
.mp-fresh i{width:8px;height:8px;border-radius:50%;background:var(--c-move);box-shadow:0 0 0 3px var(--ok-d)}

/* ───── the stage: the map, full height; the list drawer and the car card float over it ───── */
.mp-stage{position:relative;overflow:hidden;background:var(--s3);border:1px solid var(--line);border-top:0;border-radius:0 0 var(--r) var(--r)}
#p-map .mp-stage{height:clamp(460px,calc(100vh - 144px),900px)}
.mp-lay{position:absolute;right:14px;top:12px;display:flex;align-items:center;gap:6px;height:30px;padding:0 11px;border-radius:999px;font-size:12px;font-weight:600;color:var(--tx2);cursor:pointer;z-index:4}
.mp-lay input{accent-color:var(--ok)}
.mp-zoom{position:absolute;right:14px;top:50px;z-index:4;display:flex;flex-direction:column;border-radius:var(--r-s);overflow:hidden}
.mp-zoom button{width:36px;height:36px;font-size:18px;line-height:1;color:var(--tx1);text-align:center;cursor:pointer;border-top:1px solid var(--line)}
.mp-zoom button:first-child{border-top:0}

/* list drawer, 340 px, rows 44 px; collapses to 48 */
.mp-drawer{position:absolute;top:12px;right:12px;bottom:12px;width:340px;z-index:5;display:flex;flex-direction:column;border-radius:var(--r);overflow:hidden}
.mp-grab{display:none}
.mp-dh{display:flex;align-items:center;gap:8px;height:44px;padding:0 10px 0 14px;flex:none}
.mp-dh b{font-size:14px}
.mp-dh .cs{font-family:var(--mono);font-size:12px;color:var(--tx3)}
.mp-dh .lnk{margin-left:auto}
.mp-fold{display:grid;place-items:center;width:30px;height:30px;border-radius:8px;border:1px solid var(--line-s);color:var(--tx2);font-size:18px;line-height:1;cursor:pointer}
.mp-rows{flex:1;overflow-y:auto}
.mp-row{display:grid;grid-template-columns:4px 112px minmax(0,1fr) auto;gap:8px;align-items:center;width:100%;height:44px;padding:0 12px 0 0;border-top:1px solid var(--line);text-align:left;color:var(--tx1);cursor:pointer}
.mp-row > i{align-self:stretch;background:var(--k)}
.mp-row:hover{background:var(--s2)}
.mp-row.sel{background:var(--s3)}
.mp-row .w b{display:block;font-family:var(--mono);font-size:12.5px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mp-row .w small,.mp-row .s small{display:block;font-size:11px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mp-row .w small{color:var(--tx3)}
.mp-row .s em{display:block;font-style:normal;font-weight:650;font-size:12px;line-height:1.2;color:var(--k);white-space:nowrap}
.mp-row .s small{color:var(--tx2);font-family:var(--mono)}
.mp-row .g{font-family:var(--mono);font-size:12px;text-align:right;white-space:nowrap}
.mp-row .g small{color:var(--tx3);margin-left:2px;font-size:10.5px}
/* OD-40: the list's arrow, «Места» and the zoom group are ONE column at the stage's right edge, top to bottom;
   a collapsed list is gone altogether (no strip) and the column moves to the edge */
#p-map .mp-ctl{position:absolute;top:12px;right:372px;z-index:6;display:flex;flex-direction:column;align-items:flex-end;gap:8px}
#p-map .mp-ctl .mp-lay,#p-map .mp-ctl .mp-zoom{position:static}
#p-map .mp-ctl .mp-fold{width:36px;height:36px;font-size:20px}
#p-map:has(#mp-dc:checked) .mp-ctl{right:14px}
#p-map .mp-ctl .mp-back{display:flex;align-items:center;height:30px;padding:0 12px;margin:0;border-radius:999px;white-space:nowrap}
#p-map:has(#mp-dc:checked) .mp-fold{transform:rotate(180deg)}
@media (min-width:621px){#p-map:has(#mp-dc:checked) .mp-drawer{display:none}}

/* car card on press: bottom-left, 380 x 128 */
.mp-car{position:absolute;left:12px;bottom:12px;z-index:6;width:380px;height:128px;padding:10px 12px;border-radius:14px;display:flex;flex-direction:column;justify-content:space-between}
.mp-car .h{display:flex;align-items:center;gap:8px}
.mp-mini{width:30px;height:30px;flex:none;overflow:visible}
.mp-car .h b{font-family:var(--mono);font-size:15px;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mp-st{display:flex;align-items:center;gap:6px;font-weight:650;font-size:12.5px;color:var(--k);white-space:nowrap}
.mp-st i{width:9px;height:9px;border-radius:50%;background:var(--k)}
.mp-car .fa{margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--tx3);white-space:nowrap}
.mp-car .x{width:26px;height:26px;border-radius:8px;color:var(--tx3);font-size:18px;line-height:1;cursor:pointer}
.mp-car .f{display:grid;grid-template-columns:.9fr 1fr 1.1fr 1.2fr;gap:8px}
.mp-car .f small{display:block;font-size:9.5px;color:var(--tx3);font-weight:650;letter-spacing:.07em;text-transform:uppercase}
.mp-car .f b{display:block;font-family:var(--mono);font-size:13px;margin-top:1px;white-space:nowrap}
.mp-go{display:flex;align-items:center;justify-content:center;height:30px;border-radius:999px;border:1px solid var(--ok-b);background:var(--ok-d);color:var(--ok);font-weight:650;font-size:12.5px;cursor:pointer}

/* ───── the pin: a filled state disc, the vehicle silhouette in its body colour, an auto-contrast outline between them (D-165) ─────
   The map under it is a real base layer, so the pin is a map-library marker of 40 px holding the cell's own SVG (disc r13,
   selected r16 with a halo, silhouette scale 1.05 / 1.2, the course tick on the disc's edge). The silhouette is never rotated. */
.geo-mk.geo-pin{display:block;position:relative;width:40px;height:40px;border:0;border-radius:0;background:none;box-shadow:none;cursor:pointer}
.mkp{position:absolute;left:0;top:0;width:40px;height:40px;overflow:visible;display:block}
.mkp .mp-disc{r:13px;fill:var(--k);stroke:#fff;stroke-width:2}
.geo-pin.sel .mp-disc{r:16px;stroke-width:4.5}
.mkp .mp-halo{r:0;fill:rgba(0,0,0,.3)}
.geo-pin.sel .mp-halo{r:19px}
.mkp .mp-tick{fill:var(--k);stroke:#fff;stroke-width:1.5;stroke-linejoin:round;transform:rotate(var(--course,0deg)) translateY(-14.2px)}
.geo-pin.sel .mp-tick{transform:rotate(var(--course,0deg)) translateY(-17.2px)}
.mkp .mp-vg{transform:scale(1.05)}
.geo-pin.sel .mp-vg{transform:scale(1.2)}
.mkp-stale .mp-disc{stroke-dasharray:2 3}
.mp-veh{--wc:rgba(255,255,255,.75);--ol:var(--ol-n,#fff)}
[data-theme="day"] .mp-veh{--ol:var(--ol-d,#111)}
.mp-veh.vk-wd{--wc:rgba(0,0,0,.55)}
.vs-b{fill:var(--bc,#7D838B);stroke:var(--ol);stroke-width:1.2;stroke-linejoin:round}
.vs-w{fill:var(--wc)}
.mp-veh.vk-none .vs-b{fill-opacity:.5;stroke-dasharray:2 1.5}
.vs-wh{fill:var(--bc,#7D838B);stroke:var(--ol);stroke-width:1.1}
.geo-pin .mkp-lbl{display:none;position:absolute;left:42px;top:10px;height:20px;padding:0 7px;border-radius:10px;background:var(--s1);border:1px solid var(--line-s);
  font:650 11px/18px var(--font);color:var(--tx1);white-space:nowrap;pointer-events:none}
.geo-pin.sel .mkp-lbl,.geo-pin.mk-alert .mkp-lbl{display:block}
.geo-pin.mk-alert .mkp-lbl{background:var(--c-alert);border-color:transparent;color:#fff}
.geo-pin[hidden]{display:none}
/* pins standing together: one pin with the number of them on its disc, then a ring of their own */
.geo-pin.mkc-off{display:none!important}
.geo-pin .mkp-wrap{transform:translate(var(--dx,0px),var(--dy,0px));transition:transform .18s ease-out}
.geo-pin.mkc .mkp-lbl{display:none!important}
.mkp-n{position:absolute;left:24px;top:1px;min-width:17px;height:17px;padding:0 4px;box-sizing:border-box;border-radius:9px;background:var(--s1);border:1.5px solid var(--k);color:var(--tx1);
  font:700 10.5px/14px var(--font);text-align:center;pointer-events:none}
/* the one symbol of a place of the organisation */
.geo-mk.geo-site{display:block;position:relative;width:16px;height:16px;border:0;border-radius:0;background:none;box-shadow:none}
.mkpl{display:block;width:16px;height:16px;overflow:visible}
.mkpl rect{fill:var(--s1);stroke:var(--tx2);stroke-width:1.4}
.mkpl path{fill:none;stroke:var(--tx2);stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}
.mkpl-n{position:absolute;left:21px;top:1px;font:560 11px/14px var(--font);color:var(--tx2);white-space:nowrap;pointer-events:none;
  paint-order:stroke;-webkit-text-stroke:3px var(--s3)}

/* the stage holds the real map edge to edge; the base layer's own controls give way to the cell's three */
.mp-stage .mapc{position:absolute;inset:0;height:auto;border-radius:0;z-index:0}
.mp-stage .leaflet-control-zoom,.mp-stage .geo-fit{display:none}
.mp-stage .leaflet-control-scale{display:none}
.mp-stage .mh-attr{right:auto;left:12px;bottom:2px}
.mp-row[hidden],.mp-car[hidden],.mp-none[hidden]{display:none}
.mp-none{padding:14px;font-size:12px;color:var(--tx3)}
.mp-nomap{position:absolute;left:12px;top:12px;right:372px;z-index:4;padding:12px 14px;border-radius:var(--r-s);font-size:12.5px;color:var(--tx2)}
.mp-row .g.na{color:var(--tx3)}

/* Обзор's map card: the miniature, and the five small chips under it */
[data-block="overview.map"] .mapc{height:420px;border-radius:0}
[data-block="overview.map"] .leaflet-control-zoom,[data-block="overview.map"] .geo-fit,[data-block="overview.map"] .leaflet-control-scale{display:none}
[data-block="overview.map"] .mapchips{display:flex;flex-wrap:wrap;gap:6px;padding:10px 12px;border-top:1px solid var(--line)}
:where([data-block="overview.map"] .mapchips) button{font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;text-align:inherit}
.mp-chip.on{outline:2px solid var(--tx1);outline-offset:1px}

/* the operator's device map: the same disc in the colour of the state, no silhouette (design-v2 css/17-map.css `.pm-*`) */
.geo-mk.geo-device{width:18px;height:18px;border:0;border-radius:0;background:none;box-shadow:none;position:relative;cursor:pointer}
.geo-mk.geo-device::before{content:"";position:absolute;inset:2px;border-radius:50%;border:2px solid #fff;box-sizing:border-box}
.geo-mk.geo-device.st-on::before{background:var(--c-move);box-shadow:0 0 0 5px var(--ok-d)}
.geo-mk.geo-device.st-silent::before{background:var(--c-silent)}
.geo-mk.geo-device.st-pending::before,.geo-mk.geo-device.st-blocked::before,.geo-mk.geo-device.st-retired::before{border-color:var(--tx2)}

/* phone, 360 */
@media (max-width:980px){
  .mp-chips{overflow-x:auto}
  .mp-find{flex-basis:150px}
}
@media (max-width:620px){
  .mp-strip{gap:6px;padding:0 6px}
  .mp-seg > button,.mp-seg > label{padding:0 10px;font-size:12px;height:32px}
  .mp-find{flex:1 1 0}
  .mp-fresh{display:none}
  /* «Сейчас»: the map is the first screen; the five chips lie over it, the list is a bottom sheet with an 88-px peek */
  #p-map .mp-stage{height:clamp(420px,calc(100svh - 168px),640px)}
  #p-map .mp-chips{position:absolute;left:0;right:0;top:54px;padding:0 6px;gap:5px;z-index:7;overflow-x:auto;scrollbar-width:none}
  #p-map .mp-chip{height:32px;box-shadow:var(--shadow);background:var(--s1)}
  #p-map .mp-lay{display:none}
  #p-map .mp-ctl,#p-map:has(#mp-dc:checked) .mp-ctl{top:48px;left:8px;right:auto}
  #p-map .mp-zoom{display:none}
  .mp-nomap{right:12px;top:48px}
  .mp-drawer{top:auto;left:0;right:0;bottom:0;width:auto;height:88px;border-radius:16px 16px 0 0;border-bottom:0}
  #p-map:has(#mp-so:checked) .mp-drawer{height:72%}
  .mp-grab{display:block;height:20px;flex:none;cursor:pointer;position:relative}
  .mp-grab::after{content:"";position:absolute;left:50%;top:8px;width:40px;height:4px;margin-left:-20px;border-radius:2px;background:var(--line-s)}
  .mp-dh{height:30px;padding:0 12px}
  .mp-fold{display:none}
  #p-map:has(#mp-dc:checked) .mp-drawer{width:auto}
  /* a pin press raises a 140-px sheet over the peek */
  .mp-car{left:6px;right:6px;bottom:96px;width:auto;height:140px;padding:10px}
  .mp-car .fa{display:none}
  .mp-st{white-space:nowrap}
  .mp-car .x{margin-left:auto}
    [data-block="overview.map"] .mapc{height:260px}
}

/* the car card's own small pin: the same picture as on the map, drawn selected (design-v2 `.mp-mini`) */
.mp-mini .mp-halo{r:0}
.mp-mini .mp-disc{r:14px;fill:var(--k);stroke:#fff;stroke-width:4}
.mp-mini .mp-tick{fill:var(--k);stroke:#fff;stroke-width:1.5;stroke-linejoin:round;transform:rotate(var(--course,0deg)) translateY(-15.2px)}
.mp-mini .mp-vg{transform:scale(1.15)}
.mkp-wrap{display:block}

/* ── the table at 360, ONE template for the organisation and the console (D1 of
   design-v2/css/18-slice-a.css, product slice 13a, U1 of the render walk) ──
   A row is a block of two or three lines: the first cell is the title, the others are
   «label: value» pairs that wrap, no empty labels, nothing pushed off the edge. Every value the
   row carries is still there — the label is the column's own header string (`data-l`), the
   header row is the one hidden. «Поездки за сутки» keeps the base `.rt` layout (label left,
   value right), as the cell does for p-daytrips. */
@media (max-width:560px){
  .card:not([data-block="daytrips.list"]) .rt tr:not(.thr){display:flex;flex-wrap:wrap;align-items:baseline;gap:3px 14px;padding:10px 14px 11px}
  .card:not([data-block="daytrips.list"]) .rt td{display:flex;justify-content:flex-start;flex-wrap:wrap;align-items:baseline;column-gap:6px;
    flex:0 1 auto;min-width:0;max-width:100%;padding:0;border:0;text-align:left;font-size:12.5px;line-height:1.45;white-space:normal}
  .card:not([data-block="daytrips.list"]) .rt td:empty{display:none}
  .card:not([data-block="daytrips.list"]) .rt td::before{content:none;display:none}
  .card:not([data-block="daytrips.list"]) .rt td[data-l]:not([data-l=""]):not(:first-child)::before{content:attr(data-l) ":";display:inline;
    color:var(--tx3);font-size:11px;letter-spacing:0;text-transform:none;margin:0}
  .card:not([data-block="daytrips.list"]) .rt td:first-child{flex:1 1 100%;font-size:13.5px;font-weight:700;color:var(--tx1)}
  .card:not([data-block="daytrips.list"]) .rt td.act{flex:1 1 100%;padding-top:5px}
  .card:not([data-block="daytrips.list"]) .rt td.act::before{display:none}
  .card:not([data-block="daytrips.list"]) .rt td > *{margin-left:0}
  .card:not([data-block="daytrips.list"]) .rt td .sub{display:inline;margin-left:0}
  .card:not([data-block="daytrips.list"]) .rt td .duo{display:inline-flex;flex-direction:row;flex-wrap:wrap;gap:0 6px;align-items:baseline;margin:0}
  .card:not([data-block="daytrips.list"]) .rt td .duo-p,.card:not([data-block="daytrips.list"]) .rt td .duo-m{display:inline;margin:0}
  /* a plain holder of a value gives its pieces (figure, unit, flag) to the row, so a long flag wraps by itself
     and the figure stays beside its label */
  .card:not([data-block="daytrips.list"]) .rt td > span:not([class]),.card:not([data-block="daytrips.list"]) .rt td > b:not([class]){display:contents}
  .card:not([data-block="daytrips.list"]) .rt td .flag{white-space:normal}
  .card:not([data-block="daytrips.list"]) .rt td b{font-size:inherit}
}

/* Field.HintFor: what the chosen option means, under a choice of a window (m-invite). */
.fld .fhint{margin-top:8px;font-size:11px;line-height:1.5;color:var(--tx3);max-height:6.2em;overflow-y:auto;padding-right:4px}

/* slice 13b hunks - LayoutSteps (design-v2 p-acc `.ck`), the search at the end of a strip, the
   journal's pager in the foot. The foot itself is already a flex row (13a, `.tfoot` above): the
   pager only joins it at the right, and stacks under the words on a phone with the rest. */
.ck .ckr{display:flex;align-items:center;gap:12px;padding:11px 0;border-top:1px solid var(--line)}
.ck .ckr:first-child{border-top:0}
.ck .ckr.go{cursor:pointer}
.ck .ckt{flex:1;min-width:0;font-size:13.5px;font-weight:600;color:var(--tx1)}
.ck .ckt .mut{font-weight:400;margin-top:3px}
.ck .ckr .btn,.ck .ckr .lnk{flex:none}
.d1n{flex:none;width:22px;height:22px;border-radius:50%;border:1.5px solid var(--tx3);color:var(--tx2);font-size:11.5px;font-weight:700;display:inline-flex;align-items:center;justify-content:center}
@media (max-width:620px){.ck .ckr{flex-wrap:wrap}.ck .ckr .btn,.ck .ckr .lnk{margin-left:34px}}
.fbar .inp.fsr{margin-left:auto;flex:0 1 220px;min-width:200px;border-radius:20px;height:30px;font-size:11.5px;padding:0 13px}
.tfoot .pgr{display:flex;gap:6px;flex-wrap:wrap}
.tfoot .pill{padding:4px 11px}

/* ── N10 (render walk 2), the page head's «⋯» at 360, both shells (design-v2 18-slice-a.css B-13): the head keeps
   its ONE primary act and «⋯»; every other act AND link is behind «⋯». A head with no primary keeps «⋯» alone. */
.ph .pa .pa-more{display:none}
@media (max-width:620px){
  .ph .pa{position:relative}
  .ph .pa.has-more:not(.open) > :not(.btn-p):not(.pa-more){display:none!important}
  .ph .pa.has-more .pa-more{display:inline-block}
  .ph .pa.has-more:not(.open){flex-wrap:nowrap;align-items:center}
  .ph .pa.has-more.open{flex-wrap:wrap}
  /* N45 (render walk 4): the cell puts a lone act or link at the RIGHT under the title (`body[data-role="op"] .ph .pa`) */
  body[data-role="op"] .ph .pa{justify-content:flex-end}
}

/* ── N4 / N8 (render walk 2): at 360 a filter strip is ONE row that scrolls sideways, no divider, no search field
   (design-v2 03-fleet.css, 06-alerts.css `#p-fleet .fbar`); the search is short and right above it. ── */
@media (max-width:620px){
  .fbar{flex-wrap:nowrap;overflow-x:auto;margin-left:-12px;margin-right:-12px;padding:0 12px 2px;scrollbar-width:none}
  .fbar::-webkit-scrollbar{display:none}
  .fbar > *{flex:none}
  .fbar > .mdiv,.fbar > .fsp,.fbar:not(.fl-card) > .inp{display:none}
}

/* ── N13 / N6 (render walk 2): a row of three tiles spans the row at 1440 (the drawing's tiles are `repeat(n,1fr)` of the
   tiles it holds); at 360 the tiles are two columns and an odd last one goes across (design-v2 04-gas.css, 01-dash.css). ── */
@media (min-width:981px){
  .kpis:has(> .kpi:nth-child(3):last-child){grid-template-columns:repeat(3,1fr)}
  .kpis:has(> .kpi:nth-child(2):last-child){grid-template-columns:repeat(2,1fr)}
}
@media (max-width:980px){
  .kpis > .kpi:last-child:nth-child(odd){grid-column:1/-1}
}
@media (max-width:620px){
  .kpis,body[data-role="op"] .kpis{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .kpis > .kpi{min-width:0}
}

/* ── N19 (render walk 2): the PRIMARY act of an alert card is the drawn filled green `btn btn-p sm` (design-v2 p-alerts). ── */
.alb.btn-p,.alb.btn-p:hover{background:var(--ok);border-color:var(--ok);color:#fff}
[data-theme="night"] .alb.btn-p,[data-theme="night"] .alb.btn-p:hover{color:#052018;font-weight:640}

/* ── N5 (render walk 2): «Подробно» is a CARD BAR with ↓ (↑ when open), the console's `.pdet` (design-v2 24-polish.css). ── */
.adet{margin-top:13px}
.adet > summary{list-style:none;cursor:pointer;display:flex;justify-content:space-between;align-items:center;
  padding:13px 16px;background:var(--s1);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);
  font-size:13.5px;font-weight:620;color:var(--tx1)}
.adet > summary::-webkit-details-marker{display:none}
.adet > summary::after{content:"\2193";color:var(--tx3);font-weight:500}
.adet[open] > summary::after{content:"\2191"}
.adet > summary:hover{background:var(--s2)}
.adet > div{margin-top:13px}

/* ── N18 / N18' (render walks 2 and 4): a matrix table (Block.Matrix: «Что видит и что может») stays a table at 360 and
   FITS: the section column and six role columns, the heads small and in their own case, no sideways scroll
   (design-v2 08-team.css `#p-rolemap .rgrid`: 1.35fr and six .75fr columns, 8.5px heads, 4px cell padding). ── */
@media (max-width:560px){
  .card table.mx:not(.rt){display:table;width:100%;min-width:0;table-layout:fixed}
  .card table.mx:not(.rt) tbody{display:table-row-group;width:auto}
  .card table.mx:not(.rt) tr,.card table.mx:not(.rt) .thr{display:table-row;padding:0}
  .card table.mx:not(.rt) .thr{display:table-row}
  .card table.mx:not(.rt) th{display:table-cell;padding:8px 0;font-size:8px;letter-spacing:0;text-transform:none;
    text-align:center;overflow-wrap:normal;word-break:normal;hyphens:none}
  .card table.mx:not(.rt) th:first-child,.card table.mx:not(.rt) td:first-child{width:20%;text-align:left;padding-left:12px}
  .card table.mx:not(.rt) td{display:table-cell;padding:8px 4px;font-size:11px;border-top:1px solid var(--line);text-align:center}
  .card table.mx:not(.rt) td[data-label]::before{content:none;display:none}
}

/* ── the lens frame: the customer's site inside the operator's frame (OD-11, design-v2 p-lens) ── */
/* The operator's rail stays outside (`#nav`, «Клиенты» lit). Inside the frame stand the session's
   strip, then the customer's OWN rail (`#lensnav`, the same entries the customer's people see for
   the chosen lens) beside the stage (`#main`), where the customer's pages are drawn by the
   customer's own renderers. The stage scrolls, the rail and the strip stay. */
.main.lensframe{display:flex;flex-direction:column;overflow:hidden}
.lensframe > .sesbar{flex:none}
.lensbody{flex:1 1 auto;min-height:0;display:flex;gap:14px;align-items:stretch}
.lensrail{flex:0 0 206px;min-width:0;overflow-y:auto;padding:9px 8px;background:var(--s1);
  border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);align-self:flex-start;max-height:100%}
.lensrail .nav{margin-bottom:1px}
.lensstage{flex:1 1 auto;min-width:0;overflow-y:auto;padding:0 2px 8px 0}
@media (max-width:980px){
  .main.lensframe{overflow:visible;display:block}
  .lensbody{display:block}
  .lensrail{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:13px;max-height:none;padding:7px}
  .lensrail .nav{margin:0}
  .lensstage{overflow:visible;padding:0}
}

/* ── slice 17a (render walk 3) ── */

/* N1: a header-less two-cell table is a FACT table («Здоровье парка»): at 360 each row stays label left / value right
   on one line, as the drawing's `.kvr` does, and is not cut into the compact-card template. */
@media (max-width:560px){
  html body .card .rt.kv2 tr:not(.thr){display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px}
  html body .card .rt.kv2 td{display:block;flex:0 1 auto;padding:0;border:none;font-size:13px;font-weight:400;color:var(--tx2);min-width:0}
  html body .card .rt.kv2 td:first-child{flex:1 1 auto;font-size:13px;font-weight:400;color:var(--tx3)}
  html body .card .rt.kv2 td:last-child{margin-left:auto;text-align:right;color:var(--tx1);font-weight:560}
  html body .card .rt.kv2 td:last-child:empty{display:none}
}
/* N1: a fact with no label (the money card's one figure) stands on the left, as the drawing's `.duo` does. */
.kvr.nolab{justify-content:flex-start}
.kvr.nolab .l{display:none}
.kvr.nolab .v{margin-left:0;text-align:left}

/* N23 / N26: a search that stands FIRST is short (the journal's «Отбор» line), has no auto margin, and stays at 360. */
.fbar .inp.fsr.fsr-l{margin-left:0}
@media (max-width:620px){
  .fbar > .inp.fsr-l{display:block}
}

/* N28: on the pages whose cell stacks the tiles, ONE per row at 360 (an odd last tile does not span). */
@media (max-width:620px){
  .kpis.k1,body[data-role="op"] .kpis.k1{grid-template-columns:minmax(0,1fr)}
  .kpis.k1 > .kpi:last-child:nth-child(odd){grid-column:auto}
}

/* N36: the «Топливо» view bar is ONE row at 360 (three segments: «Потери газа», «Заправки», «Экономика парка»). */
@media (max-width:620px){
  .vbar{flex-wrap:nowrap;gap:2px}
  .vbar .seg{flex:none;white-space:nowrap;padding:5px 7px;font-size:11px}
}

/* N29: the console's act buttons on the invoice and the price list are full width and stacked at 360. */
@media (max-width:620px){
  .ala.pad.wide{flex-direction:column;align-items:stretch}
  .ala.pad.wide > .btn,.ala.pad.wide > div > .btn{width:100%;justify-content:center;text-align:center}
}

/* ── N39 (render walk 4), the console map at a phone width (design-v2 10-f6ca450.css, 04-gas.css `.mapbar.frow`): the map
   window comes FIRST, then the title with its «⋯», then the status chips and the filter line, each ONE row that scrolls
   sideways, then the panels. The stage dissolves into its two parts so the head can stand between them. ── */
@media (max-width:980px){
  #main:has(> .pmstage){display:flex;flex-direction:column}
  #main:has(> .pmstage) > .pmstage{display:contents}
  /* N52: the ground is a flex item of #main; on a short window it shrank to ~160 px. The cell's window is 340 px, always. */
  .pmstage > .pmground{order:-1;margin-bottom:12px;flex:none}
  .pmstage > .pmover{order:1;margin-top:0}
  .pmo-bar,.pmo-filter{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
  .pmo-bar::-webkit-scrollbar,.pmo-filter::-webkit-scrollbar{display:none}
  .pmo-bar > *,.pmo-filter > *{flex:none;white-space:nowrap}
}

/* ── N43 (render walk 4), the report card (design-v2 00-base.css `.rp-d`, 07-reports.css, `.alb`): small «XLSX» / «CSV»
   chips in a compact card — the description under the title with no reserved height, the chips 11px with 3px 9px. ── */
.card .rp-d{min-height:0;margin-top:4px}
.card .rp-a{gap:6px;margin-top:10px}
.card .rp-a .btn{font-size:11px;font-weight:570;padding:3px 9px;border-radius:7px;line-height:1.5}
/* N41 (render walk 4), the money card (design-v2 p-dash `overview.money`): ONE large figure with its unit on one line, no tile box. */
[data-block="overview.money"] .kpis{display:block;margin:0}
[data-block="overview.money"] .kpi{background:none;border:0;border-radius:0;box-shadow:none;padding:0}
[data-block="overview.money"] .kpi .kl:empty{display:none}
[data-block="overview.money"] .kv{white-space:nowrap;margin:8px 0 2px}
/* N58' (render walk 8), the operator's lens: there the money block IS the `.kpis` (design-v2 p-lens `.kpis.kpis1`,
   css/24-polish.css:4) — a framed `.kpi` tile in a 320 px box — not the aside card the customer's own «Обзор» draws.
   The card rules above reach the lens through the descendant selector; this puts the tile back. */
.kpis[data-block="overview.money"]{display:grid;grid-template-columns:minmax(0,320px);margin-top:13px;margin-bottom:13px}
.kpis[data-block="overview.money"] .kpi{background:var(--s1);border:1px solid var(--line);border-radius:var(--r);padding:14px 16px;box-shadow:var(--shadow)}
.kpis[data-block="overview.money"] .kv{margin:8px 0 2px}

/* N62 (walk 9): the payment reference in «Как оплатить» is read off the screen and typed into a bank; the cell holds it in one
   `mono` token on one line. The value is plain text here, so the row keeps its value whole and the LABEL wraps instead. */
.card[data-block="billing.howtopay"] .kvr:last-child .v{white-space:nowrap}

/* ── Slice 30s (render walk 10) ──
   N64: the prices page's «Цена сейчас» holds three tiles in the cell's TWO-column grid (design-v2 07-reports.css
   `.kpis.k2{repeat(2,1fr);margin:0}`, one column in its phone fold), so the third tile («Последнее изменение») stands on a
   second row, half width. The N13 rule above (three tiles span one row) is for the pages whose cell draws them so.
   N65: a tile never outgrows its column; a long unbroken value (a login stands in for a missing name) wraps inside it. */
[data-block="prices.now"] .kpis{margin:0}
@media (min-width:981px){
  [data-block="prices.now"] .kpis:has(> .kpi:nth-child(3):last-child){grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:980px){
  [data-block="prices.now"] .kpis,[data-block="prices.now"] .kpis:has(> .kpi:nth-child(3):last-child){grid-template-columns:minmax(0,1fr)}
}
[data-block="prices.now"] .kpi{min-width:0}
[data-block="prices.now"] .kpi .kv{overflow-wrap:anywhere}
/* N62': the label of the payment-reference row stays on one line where the cell holds it (the cell's number is a narrower
   `mono` token, the product's is bold sans, so the flex row used to squeeze the label). At a phone width the row may wrap. */
@media (min-width:621px){
  [data-block="billing.howtopay"] .kvr .l{white-space:nowrap;flex:none}
}

/* ── v2 · OD-39 · the side rail's glyphs (slice 35a) ──
   The owner asked for a glyph beside every section name (the rail has two views, REQ-UIX-132: names and glyphs, or glyphs only).
   One set, drawn here and nowhere else: inline SVG, a 20 px box, a 1.5 px stroke, round caps and joins, monochrome `currentColor`,
   so the lit item lights its glyph with its name and the idle item keeps the name's grey. The sizes are the weight of the small
   icons the drawing already has (the theme and material pills, the vehicle silhouette) scaled to a 20 px box. Items inside a group
   (`.nsub`) carry no glyph: the group's own header does. */
.nav .nlab{display:flex;align-items:center;gap:10px;min-width:0}
.nav .nname{min-width:0}
/* A long organisation name is cut with an ellipsis and never pushes the pill off the logo's row (F4). */
.brand .bname{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ng{width:20px;height:20px;flex:none}
.nsecg{gap:10px}

/* ── v2 · OD-39 · the rail's two views (slice 35b, REQ-UIX-132) ──
   Expanded: the glyph and the name (above). Collapsed: the glyph alone in a 56 px column, the page grown by the
   difference; the name stays for the tooltip and the screen reader (visually hidden, not removed); the count or the dot
   rides the glyph's top-right corner; the lit entry stays lit; a group shows its header's glyph and opens its items as a
   short list beside it (`.railfly`). The pill at the rail's head switches the view. Both views exist from 981 px (collapsed by default under 1100, expanded from it until the person chooses):
   under it the rail is the drawer it was, and the pill is not drawn. */
.railtog{display:none}
@media (min-width:981px){
  .railtog{display:grid;place-items:center;width:28px;height:28px;margin-left:auto;flex:none;padding:0;
    border-radius:20px;background:var(--s3);border:1px solid var(--line);color:var(--tx2);cursor:pointer;font-family:inherit}
  .railtog:hover{color:var(--tx1)}
  .railtog .ng{width:16px;height:16px;transition:transform .15s}
  .app.rail-c .railtog .ng{transform:rotate(180deg)}
  .app.rail-c .side{width:56px;padding:17px 8px}
  .app.rail-c .brand{flex-direction:column;gap:10px;padding:3px 0 12px}
  .app.rail-c .brand .bname{display:none}
  .app.rail-c .railtog{margin-left:0}
  .app.rail-c :is(.side,.lensrail) .nav{justify-content:center;padding:7px 0;position:relative}
  .app.rail-c :is(.side,.lensrail) .nav .nlab{gap:0;overflow:visible}
  .app.rail-c .nname{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .app.rail-c .nsecg{justify-content:center;padding:8px 0}
  .app.rail-c .nsecg .nchev{display:none}
  .app.rail-c .nsecg.has-on,.app.rail-c .nsecg.fly{color:var(--ok);background:var(--ok-d);box-shadow:inset 0 0 0 1px var(--ok-b)}
  .app.rail-c .side .nav.nsub{display:none!important}
  .app.rail-c :is(.side,.lensrail) .nav .ndot,.app.rail-c :is(.side,.lensrail) .nav .ncount{position:absolute;top:0;right:2px;margin:0;min-width:15px;padding:0 4px;
    font-size:9px;font-weight:700;line-height:14px;text-align:center;border-radius:20px}
  .app.rail-c :is(.side,.lensrail) .nav .ncount{background:var(--s3);border:1px solid var(--line);color:var(--tx2)}
  .app.rail-c .top{left:78px}
  .app.rail-c .main{left:56px}
  .app.rail-c .lensrail{flex:0 0 58px;padding:9px 6px}
}
.railfly{position:fixed;z-index:50;min-width:220px;padding:6px;border-radius:var(--r);background:var(--s1);
  border:1px solid var(--line);box-shadow:var(--shadow)}
.railfly .nav{width:100%}
/* A scope chosen among many (Field.multi, slice 38 / OD-57 item 2): a framed list of ticks, the first row
   «the whole fleet» excludes the rest. At most ~4.5 rows are shown; the rest scrolls inside the frame. */
.chk{width:17px;height:17px;flex:none;accent-color:var(--ok);margin:0}
.msel{width:100%;max-height:176px;overflow-y:auto;border-radius:var(--r-s);background:var(--s3);
  border:1px solid var(--line);padding:4px 0}
.fld .msel .msr{display:flex;justify-content:flex-start;align-items:center;gap:9px;margin:0;padding:8px 13px;font-size:13px;
  font-weight:560;letter-spacing:0;text-transform:none;color:var(--tx1);cursor:pointer}
.msel .chk{appearance:none;-webkit-appearance:none;position:relative;border:1.5px solid var(--tx3);border-radius:4px;background:transparent}
.msel .chk:checked{background:var(--ok);border-color:var(--ok)}
.msel .chk:checked::after{content:"";position:absolute;left:4px;top:1px;width:4px;height:8px;border:solid var(--s1);
  border-width:0 2px 2px 0;transform:rotate(45deg)}
.fld .msel .msr:hover{background:var(--s2)}
.pill.still{cursor:default}
