/* Оформление диспетчерской.
 *
 * **Светлая тема по умолчанию, тёмная — переключателем (v1.8.0).**
 *
 * До этого раунда тема была одна и очень тёмная, и пользователь сказал
 * прямо: «экран в Windows очень тёмный, глазам тяжело, буквы и цифры
 * нечёткие». Причин было четыре, и все измеримы:
 *
 *   1. `--bg: #0D0C08` — около 5 % яркости от белого. Это не «тёмная
 *      тема», это почти чёрный.
 *   2. `--border: #55D9A521` — восьмизначный hex, последние знаки `21`
 *      это АЛЬФА 13 %. Рамки панелей, полей и кнопок были прозрачны на
 *      87 % и на таком фоне попросту не видны; `--hair` отличался от
 *      `--surface` на 4 % яркости, и разделители строк не читались.
 *   3. Весь текст был набран моноширинным шрифтом, КОТОРОГО В WINDOWS
 *      НЕТ. Объявлялись `Share Tech Mono` и `Orbitron`, файлов шрифтов в
 *      проекте нет и не будет (внешняя ссылка на офлайн-машине не
 *      отваливается, а ВИСИТ — см. шапку `index.html`), поэтому реально
 *      рисовались Consolas и Bahnschrift: не те гарнитуры, под которые
 *      подбирались кегли и разрядка.
 *   4. Размеры были дробные и вразнобой: база 13 px, а в скриптах — 103
 *      объявления одиннадцати разных значений, из них семьдесят мельче
 *      базы. Дробные пиксели Windows растрирует нечётко, а сочетание
 *      «мелкий кегль + широкая разрядка + приглушённый цвет» (`.badge`
 *      9,5 px + .08em, `.group-title` 11 px + .14em) и давало ощущение,
 *      что буквы не складываются в слова.
 *
 * Что сделано взамен:
 *
 *   * две палитры, обе через переменные. Светлая — по умолчанию; тёмная
 *     включается атрибутом `data-theme="dark"` на `<html>`. Рамки в
 *     обеих НЕПРОЗРАЧНЫЕ;
 *   * текст — системным шрифтом (в Windows это Segoe UI, который система
 *     и рисует своим растеризатором). Моноширинный остался там, где он
 *     полезен: идентификаторы, токены, числа — класс `.mono`;
 *   * шкала кеглей ЦЕЛЫМИ пикселями, переменными, плюс второй набор для
 *     крупного режима (`data-size="large"`). Ни одного дробного размера;
 *   * разрядка снята со всего мелкого текста.
 */

/* ВИД v8 (04.10.2026, слово Open «обновить интерфейс в ПО»; Карта-штаб v8, набор Cowork
 * Navigator-v8-dlya-pulta, tokens.css). Две палитры v8 легли на прежние две темы, имена тем не менялись:
 *   «День» — голый `:root` (тема `light`, умолчание сервера), «Ночь» — `data-theme="dark"`.
 * Почему не `data-theme="day"`, как в наборе: имена тем сервер хранит и ПРОВЕРЯЕТ
 * (server/lib/settings.dart, defaultTheme), а сервер в этом круге не меняется.
 * Переменные `--nv-*` — цвета каркаса (шапка, рельс) ровно из tokens.css; прежние `--bg`, `--ink`…
 * переложены на них же, чтобы экраны внутри получили тот же вид без правки экранов.
 * Остальные семь тем (контраст, «Янтарь» …) — прежние палитры экранов; каркас у тёмных — ночной. */
:root {
  /* Н-221: светлые темы — светлые поля и списки браузера (тёмные темы переопределяют ниже). */
  color-scheme: light;
  /* --- «День» (тема light, по умолчанию) — tokens.css html[data-theme="day"] --- */
  --nv-bg: #EEF3F6;  --nv-bar: #F9FBFC;  --nv-txt: #0B1C26;  --nv-mut: #4B6170;
  --nv-line: #B8C7D1; --nv-cy: #0068C4;  --nv-ok: #00784A;   --nv-warn: #A15B00;
  --nv-down: #D0122F; --nv-sar: #C2185B; --nv-dim: #6E808C;  --nv-bl: #5C86B0;
  --nv-fill: rgba(232,240,246,.55); --nv-grid: #D6E0E6;
  --nv-font: 'Manrope', 'Segoe UI', system-ui, sans-serif;
  --nv-mono: 'JetBrains Mono', 'Consolas', monospace;
  --nv-caps: 'Oswald', 'Segoe UI', sans-serif;
  --nv-top: 56px;   /* шапка */
  /* 1.72.30 (п. 1, замер Cowork на экране Open 1706×935 @1,5: v12 — 69 px, наш — 84): рельс 70 px, размеры внутри — v12 × 0,825.
     «Крупный кегль» — 84 px, как было (ниже, :root[data-size='large']). */
  --nv-rail: 70px;  /* рельс вкладок */
  /* Цвета рельса v12 (kh_shell.py `rail`, den.py): подписи пунктов, фиолетовый включённого NRL / NRN, доля подложки выбранного. */
  --nv-rail-txt: #3C5465; --nv-vi: #5A45D0; --nv-sel-dolya: 26%; --nv-vi-dolya: 26%;

  --bg:        var(--nv-bg);
  --surface:   var(--nv-bar);   /* панель светлее страницы */
  --attention: #F4E8D3;         /* строка, требующая внимания: --nv-warn поверх дня */
  --hair:      var(--nv-grid);  /* внутренние волосяные линии */
  --border:    var(--nv-line);  /* рамка панели — НЕПРОЗРАЧНАЯ */
  --ink:       var(--nv-txt);
  --muted:     var(--nv-mut);   /* он же цвет НЕИЗВЕСТНОСТИ */
  --accent:    var(--nv-cy);
  --on-accent: #FFFFFF;         /* текст поверх акцента */
  --ok:        var(--nv-ok);
  --warn:      var(--nv-warn);
  --critical:  var(--nv-down);
  --teal:      var(--nv-bl);
  --nav-active:#DCE7F1;
  --badge-op:  #D3EDE2;
  --backdrop:  rgba(11, 28, 38, .45);

  /* --- шкала кеглей: целые пиксели --- */
  --t-xs:  11px;
  --t-sm:  12px;
  --t-md:  14px;   /* база */
  --t-lg:  16px;
  --t-xl:  20px;
  --t-dsp: 28px;

  /* --- гарнитуры --- */
  /* v8: Manrope — текст, JetBrains Mono — числа и коды, Oswald — заголовки прописными.
     Файлами рядом (vendor/fonts), системные — запасные. */
  --font-ui: 'Manrope', 'Segoe UI', 'Inter', system-ui, -apple-system,
             'Noto Sans', 'DejaVu Sans', sans-serif;
  --font-mono: 'JetBrains Mono', 'Consolas', 'DejaVu Sans Mono', 'Courier New', monospace;
}

/* Крупный кегль — второй НАБОР целых чисел, а не множитель.
   Множитель вернул бы дробные пиксели (11 × 1,15 = 12,65), то есть ровно
   то, из-за чего буквы и были нечёткими. */
:root[data-size='large'] {
  --nv-rail: 84px;   /* 1.72.30: рельс крупного кегля — прежний */
  --t-xs:  13px;
  --t-sm:  14px;
  --t-md:  16px;
  --t-lg:  18px;
  --t-xl:  22px;
  --t-dsp: 32px;
}

/* --- тёмная тема ------------------------------------------------------- */
/* «Ночь» v8 — tokens.css :root. Каркас (--nv-*) ночной и у прочих тёмных тем. */
:root[data-theme='dark'], :root[data-theme='tactical_amber'],
:root[data-theme='phosphor'], :root[data-theme='signal'] {
  /* Н-221: тёмные темы — тёмные поля и списки браузера. */
  color-scheme: dark;
  --nv-bg: #02060B;  --nv-bar: #02070C;  --nv-txt: #DDF4FF;  --nv-mut: #7A9AB0;
  --nv-line: #0F2C40; --nv-cy: #1FC8FF;  --nv-ok: #2BE3A7;   --nv-warn: #FFC21A;
  --nv-down: #FF3B4E; --nv-sar: #FF4F9A; --nv-dim: #4F6577;  --nv-bl: #1E78D8;
  --nv-fill: rgba(3,14,22,.55); --nv-grid: #0A1D2B;
  --nv-rail-txt: #8FB0C6; --nv-vi: #8B6CFF; --nv-sel-dolya: 16%; --nv-vi-dolya: 16%;
}
:root[data-theme='dark'] {
  --bg:        var(--nv-bg);
  --surface:   #06111A;          /* панель: --nv-fill поверх ночи, непрозрачно */
  --attention: #2A2006;          /* --nv-warn поверх ночи */
  --hair:      var(--nv-grid);
  --border:    var(--nv-line);   /* тоже непрозрачная */
  --ink:       var(--nv-txt);
  --muted:     var(--nv-mut);
  --accent:    var(--nv-cy);
  --on-accent: #02060B;
  --ok:        var(--nv-ok);
  --warn:      var(--nv-warn);
  --critical:  var(--nv-down);
  --teal:      var(--nv-bl);
  --nav-active:#072333;
  --badge-op:  #0B2A22;
  --backdrop:  rgba(0, 0, 0, .62);
}

/* --- повышенная контрастность (v1.10.0) ---
 *
 * Четвёртая палитра, а не «светлая с усилением»: усиление отдельными
 * правилами поверх светлой означало бы два места, где живёт один цвет.
 *
 * Заведена ради той самой жалобы, с которой начался разговор про
 * оформление: «глазам тяжело воспринимать информацию». Светлая тема эту
 * жалобу сняла не до конца — приглушённый текст `--muted` остаётся
 * приглушённым по построению, а именно им набраны подписи, которые
 * читают чаще всего.
 *
 * Здесь: чистая бумага, почти чёрные буквы, рамки в полный контраст, и
 * `--muted` поднят почти до основного цвета — «тише», но всё ещё
 * читаемо. Цвета состояний взяты темнее обычного: на белом фоне светлый
 * зелёный и светлый жёлтый не читаются вовсе.
 */
:root[data-theme='contrast'] {
  --bg:        #FFFFFF;
  --surface:   #FFFFFF;
  --attention: #FFF3D4;
  --hair:      #8C8C8C;
  --border:    #1A1A1A;
  --ink:       #000000;
  --muted:     #3A3A3A;
  --accent:    #6B3F00;
  --on-accent: #FFFFFF;
  --ok:        #14532D;
  --warn:      #7A4400;
  --critical:  #8B0000;
  --teal:      #10394A;
  --nav-active:#D7E4D9;
  --badge-op:  #D7E4D9;
  --backdrop:  rgba(0, 0, 0, .6);
}

/* --- пять тем по имени (v1.18.0) ---------------------------------------
 *
 * Пользовательский запрос: «добавь в темы новые темы — TACTICAL AMBER,
 * ARCTIC, PHOSPHOR, SIGNAL, DAYLIGHT — в apk + windows».
 *
 * **Цвета взяты из приложения, а не подобраны заново.** Одноимённая
 * тема на телефоне и на пульте обязана выглядеть одинаково, иначе имя
 * ничего не значит. Роли в приложении и здесь названы по-разному
 * (`starLoadCritical` против `--critical`), но совпадают по смыслу, и
 * пять главных — фон, текст, акцент, три сигнальных — перенесены
 * посимвольно из `app/lib/ui/theme.dart`. Остальные одиннадцать
 * выведены под каждую палитру: у пульта есть панели, волосяные линии и
 * подложка окна, которых у телефона нет.
 *
 * **Планка читаемости не опускалась.** В приложении палитры проходят
 * `app/test/palette_contrast_test.dart` — WCAG-яркость плюс различие
 * оттенков по OKLab; здесь те же числа. Ни одного цвета не подбиралось
 * «на глаз, потом посмотрим».
 *
 * Прозрачных рамок нет ни в одной — та самая причина, с которой в
 * v1.8.0 начался разговор про оформление.
 */

/* TACTICAL AMBER — янтарь приборной подсветки на почти чёрном.
   Отличается от штатной тёмной насыщенностью: та мягкая, эта резкая. */
:root[data-theme='tactical_amber'] {
  --bg:        #0A0805;
  --surface:   #15110A;
  --attention: #2A1B08;
  --hair:      #33291A;
  --border:    #4A3B22;
  --ink:       #F2E3C8;
  --muted:     #A89876;
  --accent:    #E0A83C;
  --on-accent: #0A0805;
  --ok:        #63B07A;
  --warn:      #E85A28;
  --critical:  #E2478F;
  --teal:      #7FA8C8;
  --nav-active:#2A3B2E;
  --badge-op:  #1C2A20;
  --backdrop:  rgba(0, 0, 0, .66);
}

/* ARCTIC — светлая холодная: сталь и лёд вместо бумаги.
   Имя освободилось: тёмная палитра приложения звалась «Arctic» внутри
   кода, хотя была янтарной; ей вернули имя NEON GRID. */
:root[data-theme='arctic'] {
  --bg:        #F2F7FA;
  --surface:   #FFFFFF;
  --attention: #FFF1D6;
  --hair:      #D3DEE6;
  --border:    #A9BCC8;
  --ink:       #0E1A22;
  --muted:     #4E6472;
  --accent:    #1E6FA8;
  --on-accent: #FFFFFF;
  --ok:        #2E7D4F;
  --warn:      #8A5A00;
  --critical:  #B02A1B;
  --teal:      #17708A;
  --nav-active:#DCE9F2;
  --badge-op:  #DCEBE2;
  --backdrop:  rgba(14, 26, 34, .45);
}

/* PHOSPHOR — люминофор ЭЛТ: зелёный здесь ТЕКСТ, а не акцент.
   Поэтому акцентом взят бирюзовый: зелёный акцент на зелёном тексте
   перестал бы что-либо выделять. */
:root[data-theme='phosphor'] {
  --bg:        #050806;
  --surface:   #0C130E;
  --attention: #14210F;
  --hair:      #1E3322;
  --border:    #2C4A33;
  --ink:       #9EE8A8;
  --muted:     #6FA87A;
  --accent:    #45C8D0;
  --on-accent: #050806;
  --ok:        #5FD07A;
  --warn:      #E0A028;
  --critical:  #E0584A;
  --teal:      #45C8D0;
  --nav-active:#14301F;
  --badge-op:  #10251A;
  --backdrop:  rgba(0, 0, 0, .70);
}

/* SIGNAL — предельный контраст на тёмном: чистый чёрный, чистый белый,
   рамки в полную силу. Для яркого света и для экранов, где чёрный
   действительно чёрный. */
:root[data-theme='signal'] {
  --bg:        #000000;
  --surface:   #000000;
  --attention: #1A1200;
  --hair:      #4D4D4D;
  --border:    #FFFFFF;
  --ink:       #FFFFFF;
  --muted:     #C8C8C8;
  --accent:    #4FA8FF;
  --on-accent: #000000;
  --ok:        #36C46A;
  --warn:      #FFB020;
  --critical:  #FF4A3A;
  --teal:      #4FD0E0;
  --nav-active:#123322;
  --badge-op:  #0E2418;
  --backdrop:  rgba(0, 0, 0, .75);
}

/* DAYLIGHT — предельный контраст на белом, для работы на солнце.
   **Соседствует с «повышенным контрастом» и это сказано вслух:**
   различие в акценте (синий против коричневого) и в том, что имя общее
   с приложением. Кому важна только читаемость — обе подойдут. */
:root[data-theme='daylight'] {
  --bg:        #FFFFFF;
  --surface:   #FFFFFF;
  --attention: #FFF0C8;
  --hair:      #8C8C8C;
  --border:    #000000;
  --ink:       #000000;
  --muted:     #333333;
  --accent:    #0B4FA8;
  --on-accent: #FFFFFF;
  --ok:        #0F6B34;
  --warn:      #7A5000;
  --critical:  #A3170D;
  --teal:      #0B4A5A;
  --nav-active:#D8E6F5;
  --badge-op:  #D8ECE0;
  --backdrop:  rgba(0, 0, 0, .60);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: var(--t-md);
}

/* Заголовки. Гарнитура та же — своей у нас нет и взять негде; отличие
   даёт вес и лёгкая разрядка. */
.dsp { font-weight: 600; letter-spacing: .04em; }

/* Моноширинный — там, где он ПОЛЕЗЕН: идентификаторы терминалов и
   правил, токены, столбцы чисел. `tabular-nums` держит цифры в колонке
   одинаковой ширины, иначе числа в таблице «пляшут» при обновлении. */
.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

/* Классы шкалы. Ими заменены инлайновые размеры в скриптах: один список
   значений на весь пульт вместо одиннадцати вразнобой. */
.t-xs { font-size: var(--t-xs); }
.t-sm { font-size: var(--t-sm); }
.t-md { font-size: var(--t-md); }
.t-lg { font-size: var(--t-lg); }
.t-xl { font-size: var(--t-xl); }

#app { height: 100%; display: flex; }

button, input {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 0;
}
button { cursor: pointer; }
button:hover { border-color: var(--accent); }
button:disabled { cursor: default; opacity: .5; }
button:focus-visible, input:focus-visible, a:focus-visible {
  outline: 1px solid var(--accent);
  outline-offset: 1px;
}

/* --- скобки ------------------------------------------------------------ */
.br { position: relative; }
.br::before, .br::after {
  content: '';
  position: absolute;
  width: 14px; height: 14px;
  pointer-events: none;
}
.br::before {
  left: -1px; top: -1px;
  border-left: 1.5px solid var(--bc, var(--accent));
  border-top: 1.5px solid var(--bc, var(--accent));
}
.br::after {
  right: -1px; bottom: -1px;
  border-right: 1.5px solid var(--bc, var(--accent));
  border-bottom: 1.5px solid var(--bc, var(--accent));
}
/* Одна скобка вместо двух — у второстепенных панелей. */
.br-tl::after { display: none; }

/* --- каркас ------------------------------------------------------------ */
.rail {
  width: 208px; flex-shrink: 0;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column;
}
.rail-head {
  padding: 20px 18px 18px 18px;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 10px;
}
.rail-nav { padding: 12px 10px; display: flex; flex-direction: column; gap: 2px; }
.rail-nav button {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px;
  font-size: var(--t-sm);
  color: var(--muted);
  border: none; border-left: 2px solid transparent;
  text-align: left; width: 100%;
}
.rail-nav button:hover { color: var(--ink); border-color: transparent; }
.rail-nav button[aria-current='page'] {
  background: var(--nav-active);
  border-left: 2px solid var(--accent);
  color: var(--ink);
}
/* Выключенный пункт остаётся ЧИТАЕМЫМ. Здесь стоял хардкод #5A5540 с
   контрастом 2,4:1 — пункт не «приглушался», он исчезал. */
.rail-nav button[disabled] { color: var(--muted); opacity: .65; }
.rail-foot {
  margin-top: auto;
  padding: 14px 16px;
  border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 5px;
  font-size: var(--t-xs); color: var(--muted);
}

.col { flex-grow: 1; min-width: 0; display: flex; flex-direction: column; }
/* Верхняя полоса ПЕРЕНОСИТСЯ на вторую строку, когда не помещается.
   В v1.8.0 к языку, выходу и учётной записи добавились тема, кегль,
   звук, проба и «принял»; на узком окне они уезжали за край вместе с
   выходом. Жёсткая высота 58 px это скрывала — кнопки просто пропадали. */
.bar {
  min-height: 58px; flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap;
  padding: 9px 22px;
}
.bar .title { font-size: var(--t-lg); letter-spacing: .06em; }
.grow { margin-left: auto; }

.panel { background: var(--surface); border: 1px solid var(--border); }
.scroll { flex-grow: 1; overflow: auto; min-height: 0; }

/* --- общие мелочи ------------------------------------------------------ */
.muted { color: var(--muted); }
/* Подпись поля. Разрядка снижена с .1em: на 11 px широкий трекинг
   рассыпает слово на буквы, и это была одна из причин жалобы. */
.cap { font-size: var(--t-xs); letter-spacing: .04em; color: var(--muted); }
.dot { width: 8px; height: 8px; flex-shrink: 0; display: inline-block; }
.dot9 { width: 9px; height: 9px; }
.s-ok { color: var(--ok); }        .b-ok { background: var(--ok); }
.s-warn { color: var(--warn); }    .b-warn { background: var(--warn); }
.s-critical { color: var(--critical); } .b-critical { background: var(--critical); }
.s-silent { color: var(--muted); } .b-silent { background: var(--muted); }
.s-teal { color: var(--teal); }    .b-teal { background: var(--teal); }

.kpis { display: grid; gap: 14px; padding: 16px 22px 4px 22px; }
.kpi { padding: 13px 15px; display: flex; flex-direction: column; gap: 5px; }
.kpi .n { font-size: var(--t-dsp); font-variant-numeric: tabular-nums; }

/* --- кольцевые показатели (v1.45.0) ---
 *
 * Кольцо и число ЛЕЖАТ ДРУГ НА ДРУГЕ, а не рядом: числу в середине
 * кольца отведено то же место, что раньше занимала цифра плитки, и
 * страница от замены не выросла ни на пиксель.
 *
 * Размер кольца задан в px, а не в em: он не должен расти вместе с
 * буквами. При крупном шрифте (`data-size='large'`) растёт текст ВНУТРИ
 * кольца, и это правильно — читают именно его.
 */
.gauge-panel { align-items: stretch; gap: 8px; }
.gauge { position: relative; align-self: center; line-height: 0; }
/* Текст живёт ВНУТРИ делений, а не поверх кольца: `inset` в 22 % от
 * стороны оставляет ему круг внутри насечек. Без этой рамки «100 %»
 * вылезало за кольцо — поймано снимком экрана в том же круге. */
.gauge-text {
  position: absolute; inset: 22%; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1px; line-height: 1.1;
  overflow: hidden;
}
/* СЕЛЕКТОР С `.kpi`, а не голый `.gauge-big`. Рядом живёт правило
 * `.kpi .n { font-size: var(--t-dsp) }` — оно весомее по частностям и
 * молча перебивало размер: число рисовалось крупным и переносилось на
 * две строки внутри кольца. Поймано снимком экрана, а не чтением. */
.kpi .gauge-big { font-size: var(--t-xl); font-weight: 600; white-space: nowrap; }
.kpi .gauge-big-md { font-size: var(--t-lg); }
.kpi .gauge-big-sm { font-size: var(--t-md); }
.gauge-small { font-size: var(--t-xs); text-align: center; }
.gauge-sub { font-size: var(--t-xs); font-family: var(--font-mono); }
.gauge-note { font-size: var(--t-xs); text-align: center; }
.gauge-legs {
  display: flex; flex-wrap: wrap; gap: 4px 10px; justify-content: center;
}
.gauge-leg { display: flex; align-items: center; gap: 4px; font-size: var(--t-xs); }
.gauge-leg .n { font-size: var(--t-xs); font-variant-numeric: tabular-nums; }

/* --- полоса вкладок под картой (v1.45.0) --- */
.strips {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px; padding: 12px 22px 0 22px;
}
.strip-card { padding: 12px 15px; display: flex; flex-direction: column; gap: 9px; }
.strip-head { display: flex; align-items: center; gap: 8px; }
.strip-lines { display: flex; flex-direction: column; gap: 6px; }
.strip-line {
  display: flex; align-items: baseline; gap: 10px; font-size: var(--t-sm);
}
.strip-line .muted { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }   /* подпись переносится, число не выталкивается (Н-153) */
.strip-line .n { font-variant-numeric: tabular-nums; }
.badge {
  font-size: var(--t-xs); padding: 1px 7px; margin-left: auto;
  font-variant-numeric: tabular-nums; color: var(--on-accent);
}
.badge-warn { background: var(--warn); }
.badge-critical { background: var(--critical); }

/* Узкий экран: кольца по два, полосы в столбик. */
@media (max-width: 1100px) {
  .gauges { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  .strips { grid-template-columns: minmax(0, 1fr); }
}

.pill {
  font-size: var(--t-xs); padding: 4px 10px;
  border: 1px solid var(--border); color: var(--muted);
}
.pill[aria-pressed='true'] { border-color: var(--accent); color: var(--accent); }

.row-grid { display: grid; align-items: center; }
.head-cell {
  /* 1.72.7: справа отступ меньше (6 px) — шапка выровнена с клеткой по левому краю, а места подписи больше. */
  padding: 9px 6px 9px 16px; font-size: var(--t-xs);
  letter-spacing: .03em; color: var(--muted);
  /* 1.72.7 (п. 1): шапка столбца — одной строкой (переносилась: «СЛЕДУЮЩИЙ / ПЛАТЁЖ», «SNR, / дБ»). */
  white-space: nowrap; min-width: 0;
}
/* Заголовок блока (.ht) — тоже одной строкой («ЖУРНАЛ ПРОСМОТРОВ / МЕСТ», «УЗЛЫ MESH · / 4»). */
.ht { white-space: nowrap; min-width: 0; }
/* Многоточие (полный текст — подсказкой, ставит el()) — только в окнах уже окна Open (< 1666; Cowork 19:16 п. 1): в 1666 и
   шире шапки помещаются целиком, как в v12; не поместилась — находка прибора и правка раскладки, а не многоточие. */
@media (max-width: 1665px) {
  .head-cell, .ht { overflow: hidden; text-overflow: ellipsis; }
}
/* Цифры в таблицах — моноширинными по ширине. `tabular-nums` не меняет
   гарнитуру, только заставляет цифры занимать одинаковую ширину: без
   этого столбец чисел дёргается при каждом обновлении, а с появлением
   автообновления это происходит каждые тридцать секунд. */
.cell { padding: 11px 16px; font-size: var(--t-sm); min-width: 0;
  font-variant-numeric: tabular-nums; }
.tr { border-bottom: 1px solid var(--hair); }
.tr:last-child { border-bottom: none; }
.tr.attn { background: var(--attention); }
.tr-link { cursor: pointer; }
.tr-link:hover { background: var(--attention); }

.badge { font-size: var(--t-xs); letter-spacing: .02em; padding: 2px 7px; }
.badge-op { background: var(--badge-op); color: var(--ok); }
.badge-admin { background: var(--accent); color: var(--on-accent); }

.bar-track { height: 4px; background: var(--hair); }
.bar-fill { height: 4px; }

.note {
  border: 1px solid var(--border);
  border-left: 2px solid var(--warn);
  background: var(--surface);
  padding: 12px 15px;
  font-size: var(--t-sm); color: var(--muted); line-height: 1.55;
}

.foot {
  margin-top: auto;
  padding: 9px 16px;
  border-top: 1px solid var(--hair);
  font-size: var(--t-xs); color: var(--muted); line-height: 1.5;
}

/* --- вход -------------------------------------------------------------- */
.login-wrap {
  flex-grow: 1; display: flex; align-items: center;
  justify-content: center; flex-direction: column; gap: 26px;
}
.login-card { width: 420px; padding: 28px 30px; display: flex;
  flex-direction: column; gap: 18px; }
/* Вход поверх открытого окна: та же форма, без растяжки на всю страницу. */
.vhod-poverh { padding: 18px 20px; max-width: min(480px, 94vw); }
.vhod-poverh .login-wrap { flex-grow: 0; gap: 14px; }
.vhod-poverh .login-card { width: auto; }
.field { display: flex; flex-direction: column; gap: 7px; }
.field input {
  background: var(--bg); border: 1px solid var(--border);
  padding: 11px 13px; font-size: var(--t-md);
}
.field input:focus { border-color: var(--accent); outline: none; }
.cta {
  background: var(--accent); color: var(--on-accent); border: none;
  padding: 12px; text-align: center; font-size: var(--t-md);
  letter-spacing: .03em; font-weight: 600;
}
.cta:hover { background: var(--warn); }
.err { color: var(--critical); font-size: var(--t-sm); line-height: 1.5; }

/* --- разделы v1.4.0 ---------------------------------------------------- */

/* Поля формы вне карточки входа: select оформляется отдельно от input —
   у него своя стрелка и своя высота, и без явных правил он приезжает
   белым прямоугольником посреди тёмного экрана. */
.field select {
  background: var(--bg); border: 1px solid var(--border);
  color: var(--ink);
  padding: 10px 12px; font-size: var(--t-md);
}
.field select:focus { border-color: var(--accent); outline: none; }
.field label { letter-spacing: .04em; }

/* Н-221 (1.72.7): ОДНО правило на все поля выбора и ввода в окнах и формах — в любой теме. До него select «Доступа»
   (класс dost-vybor) шёл мимо .field select и ночью приезжал белым прямоугольником (боевой 1.72.6, «Выдать PIN»,
   «Завести человека»). color-scheme — по теме (ниже, у тем): им браузер красит то, до чего правило не достаёт, —
   выпадающий список, стрелку, полосу прокрутки. */
.modal select, .modal textarea,
.modal input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),
.field select, .field input {
  background: var(--bg); color: var(--ink); border: 1px solid var(--border);
}
.modal select:focus, .modal textarea:focus, .modal input:focus { border-color: var(--accent); outline: none; }
/* Выключенное поле — приглушённым блоком: фон-подложка, приглушённый текст, пунктир; прозрачность не трогаем — на
   светлом поле ночью «серое на светлом» и не читалось. */
.modal select:disabled, .modal textarea:disabled, .modal input:disabled,
.field select:disabled, .field input:disabled {
  background: var(--hair); color: var(--muted); border-style: dashed; opacity: 1; cursor: not-allowed;
}

.cta-danger { background: var(--critical); }
.cta-danger:hover { background: var(--warn); }

/* Мелкая кнопка внутри строки таблицы. */
.mini {
  font-size: var(--t-xs); padding: 4px 10px;
  border: 1px solid var(--border); color: var(--muted);
  white-space: nowrap;
}
.mini:hover { border-color: var(--accent); color: var(--accent); }

.badge-reserved { background: var(--hair); color: var(--muted); }
/* Владелец установки (v1.5.0): свой цвет, чтобы роль читалась с одного
   взгляда, а не по длине слова. */
.badge-owner { background: var(--teal); color: var(--on-accent); }

/* Выбор компании в шапке — только у владельца установки. */
select.org-pick-sel {
  background: var(--bg); border: 1px solid var(--border);
  color: var(--ink); font-size: var(--t-xs); padding: 4px 8px;
  max-width: 200px;
}
select.org-pick-sel:focus { border-color: var(--accent); outline: none; }
.badge-due { background: var(--warn); color: var(--on-accent); }
.badge-revoked { background: var(--hair); color: var(--critical); }

.section { display: flex; flex-direction: column; margin-bottom: 14px; }
.section-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid var(--border);
}
.section-body { padding: 4px 0; }

/* Строка «подпись — значение». Две колонки, а не таблица: подписи
   разной длины, и колонка по самой длинной оставила бы половину экрана
   пустой. */
.kv {
  display: grid; grid-template-columns: 240px minmax(0, 1fr);
  gap: 12px; align-items: center;
  padding: 9px 16px; border-bottom: 1px solid var(--hair);
}
.kv:last-child { border-bottom: none; }
.kv .cap { color: var(--muted); }

/* Раздел, показанный, но не работающий: приглушён целиком, чтобы это
   было видно с одного взгляда, а не прочитано в подписи. */
.section-reserved .section-body { opacity: .55; }

/* Заголовок группы разделов (v1.4.1). Отделяет «правится» от «показано»
   раньше, чем человек доедет до подписи внизу панели. */
.group-title {
  font-size: var(--t-xs); letter-spacing: .05em; color: var(--muted);
  padding: 10px 2px 8px 2px; font-weight: 600;
}
.group-title:not(:first-child) { padding-top: 20px; }

/* Пояснение вместо значения: у раздела, которого нет, нет и величины. */
.explain {
  padding: 12px 16px; font-size: var(--t-sm); line-height: 1.55;
  color: var(--muted);
}

/* Полоса «страница из старой сборки» (v1.4.1). Поверх всего, потому что
   она про то, что нарисованному ниже верить нельзя. */
.stale-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 50;
  background: var(--critical); color: var(--on-accent);
  padding: 9px 16px; font-size: var(--t-sm); text-align: center;
}
.stale-bar ~ .rail, .stale-bar ~ .col { padding-top: 34px; }

/* --- диалоги (v1.4.0) --------------------------------------------------- */

/* Родной <dialog>: ловушка фокуса, Escape и возврат фокуса уже сделаны
   браузером. Оформляется только вид. */
.modal {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 0;
  padding: 22px 24px;
  width: min(460px, calc(100vw - 40px));
  display: flex; flex-direction: column; gap: 14px;
}
.modal::backdrop { background: var(--backdrop); }
/* Шапка общего окна: заголовок слева, ✕ справа (1.72.7, Н-168). */
.okno-shapka { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.okno-shapka .okno-krestik { flex: none; }
.modal input, .modal select { width: 100%; box-sizing: border-box; }

/* Потолок высоты и прокрутка (v1.6.0). Без `max-height` диалог,
   содержимое которого длиннее экрана, обрезается МОЛЧА: кнопки внизу
   просто нет, и человек не понимает, куда она делась. */
.modal { max-height: calc(100vh - 60px); overflow: auto; }

/* Окно со списком терминалов шире обычного: слева список, справа
   телеметрия, и в 460 пикселей это не помещается. */
.modal-wide { width: min(900px, calc(100vw - 40px)); }

/* Строка списка терминалов в этом окне. Кнопка, а не div: выбор
   переключается с клавиатуры так же, как мышью. */
.pick-item {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; font-size: var(--t-sm);
  border: 0; border-bottom: 1px solid var(--hair);
  background: transparent; color: var(--ink);
  cursor: pointer; text-align: left; width: 100%;
}
.pick-item:hover { background: var(--bg); }
.pick-item[aria-pressed='true'] {
  background: var(--bg); box-shadow: inset 2px 0 0 var(--accent);
}

/* Переключатели звука и автообновления в верхней полосе. */
.toggle { display: inline-flex; align-items: center; gap: 6px; }
.toggle[aria-pressed='true'] { border-color: var(--accent); color: var(--accent); }

/* Строка значений под графиком. Место занято ВСЕГДА, даже когда строка
   пуста: иначе четыре графика ниже прыгали бы при каждом движении
   мыши. */
.chart-readout { min-height: 16px; font-variant-numeric: tabular-nums; }

/* Предупреждение в окне подтверждения (v1.7.0). Это не отказ и не
   ошибка — действие пройдёт; цвет только говорит, что последствие стоит
   дочитать. */
.note-warn {
  border-color: var(--warn);
  box-shadow: inset 2px 0 0 var(--warn);
}

/* «Браузер не разрешил звук» — значок в шапке рядом с «ЗВУК», на всех экранах: тишина сейчас ничего не значит, и человек
   должен это видеть. Полосы во всю ширину нет — на низком окне она отнимала высоту у каждой вкладки. */
/* Подпись — в две строки внутри высоты кнопок полосы: в одну строку значок (164 px) переносил полосу
   пульта на вторую строку при 1600×1000 (замер 28.09: не хватало 30 px), и карта теряла 29 px высоты. */
.zvuk-znachok {
  background: var(--warn); color: var(--on-accent); border: none; border-radius: 4px;
  padding: 2px 6px; font-size: var(--t-xs); line-height: 1.15; font-weight: 600; cursor: pointer;
  white-space: normal; max-width: 118px; text-align: left;
}
/* Узкая шапка: значок уже — иначе он отнимал у выбора компании ~18 px, и «все компании» резалось до «все ко…». */
@media (max-width: 1500px) { .zvuk-znachok { max-width: 80px; padding: 1px 4px; } }

/* Развёрнутое описание правила (v1.6.0). Отделено чертой слева: это
   пояснение к строке над ним, а не самостоятельный абзац. */
.rule-explain {
  border-left: 2px solid var(--hair);
  padding: 2px 0 2px 9px;
}

/* Поле, из которого токен выделяют и копируют. Моноширинный — чтобы
   группы знаков читались глазами, если копирование недоступно. */
.token-box {
  font-family: var(--font-mono);
  font-size: var(--t-lg); letter-spacing: .06em;
  background: var(--bg); border: 1px solid var(--accent);
  color: var(--accent);
  padding: 12px 14px; width: 100%; box-sizing: border-box;
  text-align: center;
}

canvas { display: block; width: 100%; }

/* Карта флота (v1.3.0). Высота задана явно: Leaflet требует контейнер с
   размером, иначе тайлы не рассчитываются и рамка остаётся пустой. */
/* В отдельном окне карта занимает всё, что осталось от высоты окна:
 * ради этого окно и открывают. `100dvh` — не `100vh`: на телефоне в
 * альбомной ориентации панель браузера съедает часть `vh`, и низ карты
 * уходил бы под неё. */
.map-window .map-host { height: calc(100dvh - 168px); min-height: 340px; }

.map-host {
  height: 340px;
  width: 100%;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
/* Тёмная подложка под тайлами: пока они грузятся (или не грузятся
   вовсе), белый прямоугольник посреди тёмного экрана бьёт по глазам. */
.leaflet-container { background: var(--surface); }
.leaflet-tooltip {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  font-family: inherit;
  font-size: var(--t-xs);
}
.leaflet-tooltip-top:before { border-top-color: var(--border); }
.leaflet-control-attribution {
  background: var(--surface) !important;
  color: var(--muted) !important;
  font-size: var(--t-xs);
}
.leaflet-control-attribution a { color: var(--muted) !important; }

/* --- рябь у живой точки на карте (v1.13.0) ---------------------------

   ПЕРВАЯ анимация в этом файле, и заводится она вместе со своим
   выключателем. Пульт живёт на стене сутками; постоянное движение в
   поле зрения у части людей вызывает головную боль, а у части —
   тошноту. Поэтому `prefers-reduced-motion` стоит здесь с первого дня,
   а не «когда-нибудь потом».

   ЧТО ОЗНАЧАЕТ РЯБЬ. Она не украшение: она утверждает «этот терминал
   сейчас работает». Ставится только там, где это правда, — решает
   `ui/map.mjs`, здесь только рисование.

   ПОЧЕМУ transform, а не радиус. Маркер Leaflet — это SVG `<path>`;
   радиус в нём зашит в геометрию пути и через CSS не меняется.
   `transform-box: fill-box` заставляет масштаб считаться от центра
   самой фигуры, а не от начала координат холста, — без него волна
   уезжала бы в угол карты. */
@keyframes sl-ripple {
  0%   { transform: scale(0.75); opacity: 0.50; }
  70%  { transform: scale(2.30); opacity: 0; }
  100% { transform: scale(2.30); opacity: 0; }
}

.sl-ripple {
  transform-box: fill-box;
  transform-origin: center;
  animation: sl-ripple 2.8s ease-out infinite;
  /* Волна под точкой не должна ловить курсор: подсказка и щелчок
     принадлежат самой точке, а не её тени. */
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  /* Не «медленнее», а НАСОВСЕМ. Замедленная пульсация раздражает не
     меньше быстрой, а человек, попросивший покоя, просил покоя. Точка
     остаётся точкой, и ни одного сведения на экране от этого не
     теряется: живость видна по цвету и по возрасту снимка. */
  .sl-ripple { display: none; }
}

/* Подсказка карты стала многострочной (v1.13.0): раньше в ней была одна
   склейка через точки, теперь — имя, состояние, показания, координаты. */
.map-tip { display: flex; flex-direction: column; gap: 3px; line-height: 1.45; }
.map-tip-name { font-size: var(--t-sm); }
.map-tip-where { font-size: var(--t-xs); opacity: .8; }

/* ═══ КАРКАС v8 (04.10.2026) ═══════════════════════════════════════════════════════════════════
 * Шапка 56 px во всю ширину, рельс 84 px слева, нижний правый угол (EN · RU, «Техподдержка»).
 * Эталон — css/karkas.css набора Navigator-v8-dlya-pulta (классы как в прототипе, корень .kh);
 * здесь цвета — только через --nv-*, размеры — те же. Сетка включается, только когда на экране есть
 * шапка (`#app:has(> .kh-top)`): вход и отдельное окно карты рисуются, как прежде. */
#app:has(> .kh-top) {
  display: grid;
  grid-template-columns: var(--nv-rail) minmax(0, 1fr);
  grid-template-rows: var(--nv-top) minmax(0, 1fr);
  background: var(--nv-bg);
}
#app:has(> .kh-top) > .kh-top { grid-column: 1 / 3; grid-row: 1; }
#app:has(> .kh-top) > .rail { grid-column: 1; grid-row: 2; }
/* Н-313 (1.72.28, п. 6): отступ 54 px под угол «EN · RU · Техподдержка» (`.kh-niz`, fixed справа внизу) — только экранам без
   карты (таблицы: Billing, Аренда, Отчёты, Доступ…). На экранах с картой и правой колонкой (`.kh-flot`, `.kh-set` — MESH, LoRa,
   «Карта сети») отступ — только правой колонке, карта и левая колонка — до низа. Свёрнута правая колонка — угол лёг бы на
   карту: тогда отступ всей колонке, как прежде. */
#app:has(> .kh-top) > .col { grid-column: 2; grid-row: 2; min-height: 0; }
#app:has(> .kh-top) > .col:not(:has(> .kh-flot:not(.bez-spravoy), > .kh-set:not(.bez-spravoy))) { padding-bottom: 54px; }
/* Отступ — полем снаружи (margin), а не padding: колонка листается сама, и padding внизу прокрутки не держит место, пока она не
   долистана до конца (сквозной 1440: «занято сейчас» «Карты сети» под «EN · RU · Техподдержка»). */
.kh-flot:not(.bez-spravoy) > :last-child, .kh-set:not(.bez-spravoy) > :last-child { margin-bottom: 54px; }
/* Полосы «нет связи» / «звук» — fixed сверху: сетка сдвигается целиком, а не рельс с колонкой по отдельности. */
#app:has(> .kh-top) > .rail, #app:has(> .kh-top) > .col { padding-top: 0; }
#app:has(> .stale-bar):has(> .kh-top) { padding-top: 34px; }

.kh-top {
  height: var(--nv-top); display: flex; align-items: center; gap: 14px; padding: 0 16px;
  border-bottom: 1px solid var(--nv-line); background: var(--nv-bar); color: var(--nv-txt);
  font-family: var(--nv-font); min-width: 0; overflow: hidden;
}
.kh-brand { display: flex; align-items: center; gap: 10px; font: 700 var(--t-lg) var(--nv-font); white-space: nowrap;
  color: var(--nv-txt); flex-shrink: 0; }
.kh-brand svg { color: var(--nv-cy); flex: none; }
/* 1.72.28 (п. 7): логотип v12 — рамка и вершина голубые, дуги рельефа — синие. */
.kh-logo .kh-lg-ramka { stroke: var(--nv-cy); stroke-opacity: .95; stroke-linecap: butt; stroke-linejoin: miter; }
.kh-logo .kh-lg-duga { stroke: var(--accent); stroke-width: 1.3; }
.kh-logo .kh-lg-duga2 { opacity: .6; }
.kh-logo .kh-lg-vershina { stroke: var(--nv-cy); stroke-width: 1.5; }
.kh-logo .kh-lg-tochka { fill: var(--nv-cy); stroke: none; }
.kh-sec { display: flex; flex-direction: column; gap: 1px; min-width: 120px; padding-left: 16px;
  border-left: 1px solid var(--nv-line); flex-shrink: 0; }
.kh-sec .hl { font: 500 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-mut); }
.kh-sec b { font: 600 var(--t-md) var(--nv-font); color: var(--nv-cy); white-space: nowrap; }
/* Уголки рамки — четыре градиента, как в прототипе (.kh-search, .kh-chip): цвет из --nv-cy. */
.kh-search, .kh-chip {
  --ug: color-mix(in srgb, var(--nv-cy) 50%, transparent);
  background:
    linear-gradient(var(--ug), var(--ug)) top left / 7px 1.2px no-repeat,
    linear-gradient(var(--ug), var(--ug)) top left / 1.2px 7px no-repeat,
    linear-gradient(var(--ug), var(--ug)) top right / 7px 1.2px no-repeat,
    linear-gradient(var(--ug), var(--ug)) top right / 1.2px 7px no-repeat,
    linear-gradient(var(--ug), var(--ug)) bottom left / 7px 1.2px no-repeat,
    linear-gradient(var(--ug), var(--ug)) bottom left / 1.2px 7px no-repeat,
    linear-gradient(var(--ug), var(--ug)) bottom right / 7px 1.2px no-repeat,
    linear-gradient(var(--ug), var(--ug)) bottom right / 1.2px 7px no-repeat,
    color-mix(in srgb, var(--nv-cy) 4%, transparent);
}
/* 1.72.28 (п. 8, v12 `.kh-search` 330 px; сверки Cowork 03:57 п. 5 и 04:35 п. 2). Ряд чипов — по содержимому, не режется и
   не сжимается (был overflow: hidden — в EN на 1706 «1 min» срезался до «1 mi»); место отдаёт ПОЛЕ ПОИСКА: оно до 330 px и
   сжимается первым. Подсказка выбирается по ширине самого поля (@container), а не окна: влезает полная «Найти терминал, узел,
   людей, дрон» — полная; нет — короткая «Терминал, узел»; нет и её — значок и «/». Многоточия у подсказки нет никогда. */
.kh-search { display: flex; align-items: center; gap: 9px; height: 36px; flex: 0 1 330px; min-width: 76px; overflow: hidden;
  container-type: inline-size; container-name: poisk;
  padding: 0 12px; color: var(--nv-mut); font: 400 var(--t-md) var(--nv-font); white-space: nowrap; border: none; cursor: pointer; }
.kh-search-kratko { display: none; }
.kh-search > svg { flex: none; }
.kh-search:hover { color: var(--nv-txt); }
.kh-search em { margin-left: auto; flex: none; font: 500 var(--t-xs) var(--nv-mono); font-style: normal; color: var(--nv-cy);
  border: 1px solid color-mix(in srgb, var(--nv-cy) 35%, transparent); padding: 0 6px; }
/* Пороги — ширина содержимого поля (без полей 12 px): полная подсказка RU/EN до ~250 px + значок 16 + «/» 22 + промежутки 18. */
@container poisk (max-width: 292px) {
  .kh-search-polno { display: none; }
  .kh-search-kratko { display: inline; }
}
@container poisk (max-width: 165px) {
  .kh-search-kratko { display: none; }
}
/* 1.72.28 (п. 12): блок чипов не растягивается — пустота не посередине шапки, а перед компанией и часами (как v12); и не
   сжимается — чипы целиком (сверка 04:35 п. 2). */
.kh-chips { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.kh-chip { display: inline-flex; align-items: center; gap: 7px; height: 30px; padding: 0 10px; white-space: nowrap;
  font: 400 var(--t-sm) var(--nv-font); color: var(--nv-txt); flex: 0 0 auto; }
.kh-chip[data-chip='server'] { gap: 6px; }
.kh-sv-k { flex-shrink: 0; }
.kh-sv-ver { flex-shrink: 0; }
/* 1.72.30 (п. 2): короткое «PIN · N мин» (сверка 04:35 п. 1) снято — фишка PIN ушла из ряда чипов вправо, за «авто», и место ей
   отдаёт поле поиска (оно сжимается первым); текст фишки целиком на всех ширинах от 1280 px. */
@media (max-width: 1800px) {
  .kh-top { gap: 12px; }
  .kh-who { gap: 12px; }
}
@media (max-width: 1599px) {
  .kh-who { gap: 12px; }
  .kh-top { gap: 10px; }
  /* 1280–1599 px (кадры 1440×900): у чипа сервера — версия (слово «Сервер» — в подсказке); у логотипа — знак без слов (название —
     в подсказке). Так компания целиком, а чипы — в ряду. */
  .kh-sv-k { display: none; }
  .kh-brand > span { display: none; }
}
.kh-chip .m { font-family: var(--nv-mono); }
.kh-chip svg { color: var(--nv-cy); flex-shrink: 0; }
.kh-chip.dim, .kh-chip.dim svg { color: var(--nv-dim); }
.kh-chip.g { --ug: color-mix(in srgb, var(--nv-ok) 60%, transparent); color: var(--nv-ok); }
.kh-chip.g svg { color: var(--nv-ok); }
.kh-chip.y { --ug: color-mix(in srgb, var(--nv-warn) 70%, transparent); color: var(--nv-warn); }
.kh-chip.y svg { color: var(--nv-warn); }
.kh-chip.r { --ug: color-mix(in srgb, var(--nv-down) 70%, transparent); color: var(--nv-down); }
.kh-chip.r svg { color: var(--nv-down); }
.kh-chip[role='button'] { cursor: pointer; }
/* 1.72.30 (п. 2, v12 `topbar`): фишка PIN — справа от «авто», перед компанией; рамка-уголки, как у чипов; не сжимается и не режется.
   Окно открыто — бирюзовая (.g); окна нет и пауза — янтарная (.y); не выдан — приглушённая (.dim); superadmin «места всегда» —
   приглушённо-бирюзовая. Число — моно, цветом текста, как `.kh-chip .m` v12. */
.kh-top > .kh-chip.kh-pin { flex: 0 0 auto; }
.kh-chip.kh-pin .m { color: var(--nv-txt); }
.kh-chip.kh-pin[role='button']:focus-visible { outline: 2px solid var(--nv-cy); outline-offset: 1px; }
.kh-chip.kh-pin-vsegda { --ug: color-mix(in srgb, var(--nv-ok) 32%, transparent); color: color-mix(in srgb, var(--nv-ok) 55%, var(--nv-mut)); }
.kh-chip.kh-pin-vsegda svg { color: color-mix(in srgb, var(--nv-ok) 55%, var(--nv-mut)); }
.kh-chip.kh-pin.dim { --ug: color-mix(in srgb, var(--nv-dim) 80%, transparent); }
.kh-who { margin-left: auto; display: flex; align-items: center; gap: 16px; flex-shrink: 0; }
.kh-co { display: flex; align-items: center; gap: 6px; font: 600 var(--t-md) var(--nv-font); white-space: nowrap; color: var(--nv-txt); }
.kh-co > svg { color: var(--nv-mut); flex: none; }
/* 1.72.28 (п. 11, v12 «⌂ Компания … ▾»): подпись выбранной компании целиком; <select> прозрачный поверх неё. */
.kh-co-vybor { position: relative; cursor: pointer; padding: 4px 2px; }
.kh-co-vybor:hover .kh-co-imya { color: var(--nv-cy); }
.kh-co-vybor:focus-within { outline: 2px solid var(--nv-cy); outline-offset: 2px; }
.kh-co-imya { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kh-co-vybor > select.org-pick-sel { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; padding: 0; opacity: 0; cursor: pointer;
  font: inherit; border: 0; margin: 0; }
.kv-okno { width: min(640px, calc(100vw - 32px)); max-height: calc(100vh - 48px); padding: 18px 20px; gap: 10px; display: flex; flex-direction: column; }
.kv-okno:not([open]) { display: none; }
.kv-spisok { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; scrollbar-width: thin; }
.kv-str { display: grid; grid-template-columns: 16px 44px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 10px 12px;
  border: 1px solid var(--nv-line); cursor: pointer; }
.kv-str.sel { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.kv-radio { width: 14px; height: 14px; border-radius: 50%; border: 1.5px solid var(--muted); }
.kv-radio.on { border-color: var(--accent); box-shadow: inset 0 0 0 3px var(--nv-bg), inset 0 0 0 7px var(--accent); }
.kv-kolco-m { position: relative; width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center; }
.kv-kolco-m > svg { position: absolute; inset: 0; }
.kv-kolco circle { fill: none; stroke-width: 4; }
.kv-dor { stroke: var(--nv-line); }
.kv-seg.norma { stroke: var(--ok); } .kv-seg.zamech { stroke: var(--warn); } .kv-seg.propala { stroke: var(--critical); }
.kv-seg.molchit { stroke: var(--warn); stroke-dasharray: 2 2; }
.kv-imena { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.kv-imena > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kv-moduli { display: flex; gap: 4px; flex-wrap: wrap; }
.kv-modul { padding: 1px 6px; border: 1px solid var(--nv-line); font-size: var(--t-xs); }
.kv-modul.net { color: var(--muted); }
.kv-sprava { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; text-align: right; }
.kv-chip { padding: 2px 8px; font-size: var(--t-xs); border-left: 2px solid currentColor; text-transform: uppercase; letter-spacing: .06em; }
.kv-chip.ok { color: var(--ok); } .kv-chip.zamech { color: var(--warn); } .kv-chip.avaria { color: var(--critical); } .kv-chip.net { color: var(--muted); }
.kv-snoska { padding: 8px 12px; border-left: 2px solid var(--accent); background: color-mix(in srgb, var(--accent) 6%, transparent); }
/* 1.72.30 (п. 2, 9.462): с длинным именем компании шапка уходила за правый край на 173–198 px (кадры k30a: 1706 и 1440 — часы и
   кружок за окном). Теперь место сперва отдаёт поле поиска (до 76 px), потом — подпись компании (многоточие, полное имя — в
   подсказке); часы, кружок, фишка PIN и кнопки не сжимаются. Обычное имя помещается целиком — его это не касается.
   Как: от 1280 px основа поиска 0 (min 76, max 330) — он только РАСТЁТ в свободное место до 330 px, а сжимать ему нечего; если и
   при 76 px ряд не влез — сжимается блок «кто». Долями сжатия очередь не выстроить: доля 100 у поиска всё равно отдавала «кто»
   доли пикселя, и обычное имя («…(default)») уходило в многоточие (кадры k30a); дробная доля .01 у «кто» по правилам flex урезала
   само сжатие (шапка за краем на 184 px). */
@media (min-width: 1280px) {
  .kh-top > .kh-search { flex: 1 1 0; max-width: 330px; }
}
.kh-top > .kh-who { flex-shrink: 1; min-width: 0; }
.kh-who > .kh-co { flex: 0 1 auto; min-width: 0; }
.kh-who > .kh-clock, .kh-who > .kh-av-obertka { flex-shrink: 0; }
#org-name > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.kh-clock { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.15; }
.kh-clock b { font: 500 var(--t-lg) var(--nv-mono); color: var(--nv-txt); font-variant-numeric: tabular-nums; }
.kh-clock small { font-size: var(--t-xs); color: var(--nv-mut); white-space: nowrap; }
/* Н-155 (1.72.1): узкое окно. Сужение выбора компании до 130 px стояло в @media ВЫШЕ общего правила 170 px той же
   специфичности — и не действовало никогда: место отдавал чип сервера, сжимаясь до значка и буквы. Теперь узкие правила —
   ПОСЛЕ общих. До 1279 px чип сервера — значок и версия, не ужимается (имя и адрес — в подсказке, title). */
/* 1.72.5: до 1279 px у поиска нет «/», выбор компании уже. 1.72.28: чип «срез» — одна давность на всех ширинах (shell.mjs). */
@media (max-width: 1279px) {
  .kh-search > em { display: none; }
  .kh-search { flex: none; min-width: 0; }
  .kh-search > span { display: none !important; }
  /* Н-213 (Cowork 19:58 п. 2): ещё место для «АВТО» — у промежутков между группами шапки (14 → 8 px; при 10 px не хватало 2 px), не у выбора компании. */
  .kh-top { gap: 8px; }
  .kh-chips { gap: 4px; }
  .kh-chip { padding: 0 7px; gap: 5px; }
  .kh-top .kh-upr { gap: 4px; }
  .kh-top .kh-upr .pill { padding: 3px 6px; }
  .kh-sv-k { display: none; }
  .kh-chip[data-chip='server'] { flex: 0 0 auto; }
  /* Только в окнах уже 1280 px подпись компании — до 160 px с многоточием (полное имя — в подсказке). */
  .kh-co-vybor { max-width: 160px; }
  /* 1.72.28 (Н-155, сквозной 1152×700): у чипов «звук» / «авто» — без точки (включено — зелёным цветом самого чипа), иначе
     чип «обновлено» уходил за край ряда на 21 px. */
  .kh-top .kh-upr .kh-chip-knopka .dot { display: none; }
}
.kh-av { width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  font: 600 var(--t-sm) var(--nv-mono); color: var(--nv-txt); box-shadow: inset 0 0 0 1.5px var(--nv-cy); }
/* 1.72.5: кнопки рабочего места — в шапке; «кто» и «Выйти» — меню под кружком (v12). Строка под шапкой — только своё вкладки:
   заголовок есть в шапке («ВКЛАДКА …»), а строка, где кроме заголовка ничего нет, не показывается. */
/* Н-213 (1.72.9, PLAN-1.72.9 ред. 1–2): ряд кнопок — НЕсжимаемый, без обрезки; место отдаёт блок чипов (.kh-chips: flex 1 1 auto,
   min-width 0, overflow hidden — чипы ужимаются и прячутся, подробности — в подсказке). Было flex-shrink: 1 + overflow: hidden —
   ряд резал край «АВТО» на 2–4 px в окнах 1366–1440, как только текст шапки становился шире (1.72.8). Блок «кто» тоже не сжимается. */
.kh-upr { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* 1.72.30: блок «кто» сжимается последним (доля .01) — выше, у «длинного имени компании». */
.kh-upr .pill { padding: 3px 8px; font-size: var(--t-xs); white-space: nowrap; }
/* 1.72.28 (п. 12): «звук», «принял», «авто» — чипы v12 (уголки рамки, включённый — зелёный), кнопкой. */
.kh-chip.kh-chip-knopka { border: 0; cursor: pointer; font: 400 var(--t-sm) var(--nv-font); color: var(--nv-mut); text-transform: lowercase; }
.kh-chip.kh-chip-knopka.g { color: var(--nv-ok); }
.kh-chip.kh-chip-knopka.y { color: var(--nv-warn); }
.kh-chip.kh-chip-knopka:hover { color: var(--nv-txt); }
.kh-chip.kh-chip-knopka:focus-visible { outline: 2px solid var(--nv-cy); outline-offset: 1px; }
.kh-chip.kh-chip-knopka .dot { width: 7px; height: 7px; }
.kh-upr > span { white-space: nowrap; }
/* Н-213 (1.72.7, ред. 2 п. 2): в окнах ≤ 1400 px «АВТО» не режется — за счёт отступов и кегля, подписи те же (значки вместо
   слов — к Н-171, только по слову Open). */
@media (max-width: 1600px) {
  .kh-top .kh-upr { gap: 3px; }
  .kh-top .kh-upr .pill { padding: 2px 5px; font-size: var(--t-xs); letter-spacing: .02em; }
  .kh-top .kh-upr .kh-chip { padding: 0 7px; gap: 5px; }
}
@media (min-width: 1280px) and (max-width: 1400px) {
  /* Н-213 (Cowork 19:16 п. 2): место для «АВТО» — у строки поиска, не у кнопок (1.72.28: компания не режется). */
  .kh-search > em { display: none; }
  /* Н-213 (Cowork 19:58 п. 2): ещё место для «АВТО» — у промежутков между группами шапки (14 → 8 px; при 10 px не хватало 2 px), не у выбора компании. */
  .kh-top { gap: 8px; }
}
button.kh-av { border: 0; background: none; cursor: pointer; padding: 0; }
.kh-av-obertka { position: relative; flex: none; }
.kh-menyu { position: fixed; z-index: 2500;   /* шапка режет переполнение — меню ставится по кружку (menyuKto) */
  min-width: 200px; display: flex;
  flex-direction: column; gap: 10px; padding: 12px; background: var(--nv-bar); border: 1px solid var(--nv-line);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .35); }
.kh-menyu[hidden] { display: none; }
.kh-menyu-kto { display: flex; align-items: center; gap: 8px; justify-content: space-between; }
.kh-menyu-login { font-size: var(--t-sm); color: var(--ink); }
.kh-menyu-upr { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.col > .bar > .dsp.title { display: none; }
.col > .bar:has(> .dsp.title:only-child) { display: none; }
.col > .bar { min-height: 0; padding-top: 6px; padding-bottom: 6px; }
/* Н-248 (1.72.14): имя терминала в полосе отчёта — не `title` (тот спрятан строкой выше); длинное — многоточием. */
.bar > .report-imya { font-size: var(--t-lg); letter-spacing: .06em; min-width: 0; max-width: 40%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.report-niz { margin-top: 14px; }
/* Н-249: причина вместо голого «—» в клетке покрытия и в сводке. */
/* Н-303 (1.72.25): слово причины не обрезается многоточием («источник…» у 8 из 9) — переносится в две строки. */
/* 1.72.26 (поток Б, Cowork 13.10 21:16 п. 3 [3]: «источнико / в: 2»): перенос только между словами — слово не рвётся. */
.ot12-str .ot12-pokr-prichina { color: var(--warn); min-width: 0; white-space: normal; line-height: 1.1; overflow-wrap: normal; word-break: normal; }
.ot12-pok-n > b.ot12-pok-prichina { font-size: var(--t-md); color: var(--warn); }

/* --- рельс --- */
.rail.kh-rail { width: var(--nv-rail); background: var(--nv-bar); border-right: 1px solid var(--nv-line);
  display: flex; flex-direction: column; padding: 8px 0; overflow-y: auto; overflow-x: hidden;
  /* 18 пунктов на 1080 px помещаются; ниже 900 px — плотный рельс (правка 1.1). Если и он не влез —
     ВИДИМАЯ тонкая полоса прокрутки: скрытая прятала бы «Доступ» и «Настройки» (Cowork 01:45). */
  scrollbar-width: thin; scrollbar-color: var(--nv-line) transparent; font-family: var(--nv-font); }
.rail.kh-rail::-webkit-scrollbar { width: 4px; }
.rail.kh-rail::-webkit-scrollbar-thumb { background: var(--nv-line); }
.kh-rail .rail-nav { padding: 0; gap: 0; }
/* 1.72.30 (п. 1, v12 `.kh-rg`): межбуквенный .14em (был .06em). */
.kh-rg { font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .14em; text-transform: uppercase; color: var(--nv-dim);
  text-align: center; margin: 8px 0 4px; }
/* 1.72.30 (п. 1, v12 `.kh-ri`): подписи пунктов — цвет v12 (#8FB0C6 ночью; был --nv-mut, темнее); перенос только по словам. */
.kh-rail .rail-nav button.kh-ri { position: relative; min-height: 41px; padding: 3px 2px; width: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  color: var(--nv-rail-txt); font: 400 var(--t-xs) var(--nv-font); letter-spacing: .02em; text-align: center; line-height: 1.1;
  border: none; background: none; cursor: pointer; }
.kh-rail .rail-nav button.kh-ri span { max-width: 78px; overflow-wrap: normal; word-break: normal; hyphens: manual; }
.kh-rail .rail-nav button.kh-ri:hover { color: var(--nv-txt); }
/* 1.72.30 (п. 1, v12 `.kh-ri.sel`): выбранный — подложка-градиент слева направо и полоса 3 px слева (подложки не было). */
.kh-rail .rail-nav button.kh-ri.sel { color: var(--nv-cy); border: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--nv-cy) var(--nv-sel-dolya), transparent), transparent);
  box-shadow: inset 3px 0 0 var(--nv-cy); }
/* Выключенный пункт (karkas.css набора, .kh-ri.off): виден, читаем, с тире; причина — в title. */
.kh-rail .rail-nav button.kh-ri.off, .kh-rail .rail-nav button.kh-ri[disabled] { color: var(--nv-dim); opacity: 1; cursor: not-allowed; }
.kh-rail .rail-nav button.kh-ri.off::after { content: '\2014'; position: absolute; top: 4px; right: 10px;
  font: 600 var(--t-xs) var(--nv-mono); color: var(--nv-dim); }
.kh-rail .kh-bd { position: absolute; top: 5px; right: 9px; min-width: 18px; height: 15px; padding: 0 4px;
  font: 600 var(--t-xs) var(--nv-mono); display: flex; align-items: center; justify-content: center;
  color: var(--nv-bg); white-space: nowrap; letter-spacing: 0; }
.kh-rail .kh-bd { transform: scale(.667); transform-origin: 100% 0; }
/* Значок SAR — как v12 (kh_shell.py: шрифт 7,5 px, высота 10 px, у края пункта): размеры из шкалы × 0,68, иначе «в процессе» не влезает в рельс. */
.kh-rail .kh-bd.sar { transform: scale(.68); min-width: 0; padding: 0 3px; font-family: var(--nv-caps); letter-spacing: .02em; top: 6px; right: 1px; }
.kh-rail .kh-bd.down { background: var(--nv-down); }
.kh-rail .kh-bd.warn { background: var(--nv-warn); }
/* 1.72.28 (п. 13, v12 `.kh-bd.info`): контурный знак — просто число, без тревоги. */
.kh-rail .kh-bd.info { background: transparent; color: var(--nv-cy); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 55%, transparent); }
.kh-rsp { flex: 1; min-height: 8px; }
.kh-thm { display: flex; justify-content: center; gap: 4px; margin: 0 8px 6px; padding: 3px; border: none;
  background: none; box-shadow: inset 0 0 0 1px var(--nv-line); }
/* 1.72.7: половины — настоящие кнопки (Tab, Enter, пробел); вид — прежний. */
.kh-tm { flex: 1; height: 36px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; color: var(--nv-mut); font-style: normal; border: none; background: none; padding: 0; cursor: pointer; font: inherit; }
.kh-tm:focus-visible { outline: 2px solid var(--nv-cy); outline-offset: -2px; }
.kh-tm b { font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .06em; }
.kh-tm.on { color: var(--nv-cy); background: color-mix(in srgb, var(--nv-cy) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 55%, transparent); }
/* 1.72.30 (п. 1, v12 `.kh-thm.kh-vw .kh-tm.on`): включённый NRL / NRN — фиолетовый v12 (подложка .16, рамка .6); 2D и ночь — циан. */
.kh-rezhim .kh-tm.on { color: var(--nv-vi); background: color-mix(in srgb, var(--nv-vi) var(--nv-vi-dolya), transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-vi) 60%, transparent); }

/* --- нижний правый угол: EN · RU и «Техподдержка» --- */
.kh-niz { position: fixed; right: 16px; bottom: 9px; display: flex; gap: 12px; align-items: center; z-index: 40; }
.kh-lang { display: flex; gap: 8px; }
.kh-lb { width: 72px; height: 36px; display: flex; align-items: center; justify-content: center;
  font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; color: var(--nv-mut);
  background: color-mix(in srgb, var(--nv-bg) 92%, transparent); border: none;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 35%, transparent); cursor: pointer;
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px); }
.kh-lb:hover { color: var(--nv-txt); }
.kh-lb.on { color: var(--nv-cy); background: color-mix(in srgb, var(--nv-cy) 14%, var(--nv-bg));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 75%, transparent); }
/* Оранжевая — единственная кнопка этого цвета в продукте (как в прототипе): её находят глазами сразу. */
.kh-sup { display: flex; align-items: center; justify-content: center; gap: 9px; height: 36px; padding: 0 18px 0 13px;
  color: #1A0A00; font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap;
  background: linear-gradient(90deg, #FFB21F, #FF6B1F); border: none; cursor: pointer;
  box-shadow: 0 0 0 1px rgba(255,214,150,.95), 0 0 22px rgba(255,120,31,.45);
  clip-path: polygon(9px 0, 100% 0, 100% calc(100% - 9px), calc(100% - 9px) 100%, 0 100%, 0 9px); }
.kh-sup:hover { filter: brightness(1.08); }
.kh-sup b { font-weight: 600; }
/* 1.72.28 (сверка Cowork 05:11): до 1500 px правая колонка «Карты сети», MESH, LoRa — 290 px, «Моих терминалов» — 300 px; угол
   «EN · RU · Техподдержка» (был ~312 px) заходил на карту на ~24 px. Здесь он не шире 276 px (2 × 56 + 6 + 8 + 150) и стоит
   под колонкой (правый край угла — 16 px от окна, колонки — 14 px). */
@media (max-width: 1500px) {
  .kh-niz { gap: 8px; }
  .kh-lang { gap: 6px; }
  .kh-lb { width: 56px; }
  .kh-sup { width: 150px; padding: 0 10px; gap: 6px; }
}
.podderzhka-tekst { width: 100%; min-width: 360px; font: 400 var(--t-sm) var(--nv-mono); color: var(--ink);
  background: var(--bg); border: 1px solid var(--border); padding: 8px; resize: none; margin: 6px 0 10px; }
#podderzhka .kv { display: flex; justify-content: space-between; gap: 16px; padding: 4px 0; }
/* Полоса «нет связи» — высота строки задана числом: отступ 34 px зашит в правила выше, а с Manrope красная полоса
   выходила 35 px. */
.stale-bar { line-height: 16px; }
/* Плотный рельс ниже 1120 px по высоте (правка 1.1; 1.72.4 — с 900 до 1120: у Open страница 1706×935, и полный рельс
   уходил «Настройками» на 177 px за окно — замер сквозного в окне Open): пункт ~34 px, значок 18. Кегль — шкалой (v1.8.0),
   поэтому плотность берётся из отступов, высоты строки и значка, а не из мелкого шрифта. */
@media (max-height: 1120px) {
  .rail.kh-rail { padding: 0 0 8px; }   /* снизу 8 px: «Настройки» не упираются в низ окна (Cowork 04.10 23:03 В5) */
  /* overflow: hidden — при line-height 1 буквы выступают за строку на долю пикселя, и рельс считал это
     переполнением: появлялась полоса прокрутки на 1 px (замер 04.10: 680 / 681). */
  /* 1.73.0: под «ночь · день» встала вторая полоска «NRL · NRN» — рельс на 1366×768 ушёл за окно на 20 px (сквозной
     06.10). min-height тут не помогает (высоту даёт значок с подписью): значок пункта 16 px вместо 18 — около 40 px на
     рельс. 28 px (04.10, Cowork 23:03 В5): при 30 px «Настройки» вставали вплотную к низу окна. */
  .kh-rail .rail-nav button.kh-ri { min-height: 28px; padding: 0 2px; gap: 1px; line-height: 1; overflow: hidden; }
  .kh-rail .rail-nav button.kh-ri svg { width: 16px; height: 16px; }
  .kh-rail .kh-bd { top: 1px; }
  .kh-rail .rail-nav button.kh-ri.off::after { top: 0; }
  .kh-rg { margin: 1px 0 0; }
  .kh-rsp { min-height: 0; }
  /* «Ночь / День» в одну строку и без значков: на 76 px значок с подписью не помещаются оба. */
  .kh-thm { margin: 1px 4px; padding: 1px; gap: 2px; }
  .kh-tm { height: 18px; }
  .kh-tm svg { display: none; }
}
/* 769–1120 px (1.72.4, окно Open 1706×935): плотный рельс оставлял под пунктами ~250 px пустоты, а подписи в 28 px
   наезжали на значки — пункт 38 px (20 пунктов × 10 px = 200 px из этого запаса), подпись не режется. */
@media (min-height: 769px) and (max-height: 1120px) {
  .kh-rail .rail-nav button.kh-ri { min-height: 35px; line-height: 1.1; overflow: visible; }
  /* 1.72.28 (п. 14, v12): переключатели 2D/3D, ночь/день, NRL/NRN — плитками со значками (значок над подписью); место —
     у пунктов рельса (38 → 35 px: 20 пунктов × 3 px = 60 px на три плитки по +16 px). */
  .kh-thm { margin: 0 6px 4px; padding: 2px; gap: 3px; }
  .kh-tm { height: 34px; gap: 1px; }
  .kh-tm svg { display: block; width: 15px; height: 15px; }
}
/* 1.72.28: окно 769–1000 px по высоте (1440×900, у Open 935 — с полосой «звук» 32 px сверху) — рельс с плитками уходил за низ на
   58 px (кадры u28): пункт 33 px, плитка 30 px (значок 13 над подписью — в строку «день» и NRN не влезали), рамки плиток тоньше. */
@media (min-height: 769px) and (max-height: 1000px) {
  .kh-rail .rail-nav button.kh-ri { min-height: 33px; }
  .kh-thm { margin: 0 6px 2px; padding: 1px; }
  .kh-tm { height: 30px; }
  .kh-tm svg { width: 13px; height: 13px; }
}
/* 1.72.30 (п. 1, доска Cowork 14.10 14:11): рельс «как видит Open» — 70 px, внутри размеры v12 × 0,825 (`kh_shell.py`: пункт 43 →
   35 px, значок 21 → 17, подпись 10,5 → 9 px; «КАРТЫ / РАБОТА» 9,5 → 8 px; плитка 36 → 30 px, значок 17 → 14, подпись 9,5 → 8 px).
   Только обычный кегль: у «Крупного» рельс 84 px и прежние размеры (правила выше). Высоты окна: от 921 px — пункт 35 px (окно
   Open 935 — без прокрутки); 769–920 (1440×900) — 33 px; до 768 — прежний плотный рельс, только шрифт и ширина новые. */
:root:not([data-size='large']) .kh-rg { font: 500 8px var(--nv-mono); letter-spacing: .14em; margin: 7px 0 3px; }
:root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri { font: 400 9px var(--nv-font); letter-spacing: .02em; padding-left: 1px; padding-right: 1px; }
:root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri span { max-width: 68px; }
:root:not([data-size='large']) .kh-rail .kh-bd { right: 6px; top: 4px; }
:root:not([data-size='large']) .kh-tm b { font: 500 8px var(--nv-mono); letter-spacing: .06em; }
@media (min-height: 769px) {
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri { gap: 3px; line-height: 1.1; overflow: visible; }
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri svg { width: 17px; height: 17px; }
  :root:not([data-size='large']) .kh-thm { margin: 0 6px 4px; padding: 2px; gap: 3px; }
  :root:not([data-size='large']) .kh-tm { height: 30px; gap: 2px; }
  :root:not([data-size='large']) .kh-tm svg { display: block; width: 14px; height: 14px; }
}
@media (min-height: 921px) {
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri { min-height: 35px; }
}
@media (min-height: 769px) and (max-height: 920px) {
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri { min-height: 33px; }
  :root:not([data-size='large']) .kh-thm { margin: 0 6px 2px; padding: 1px; }
}
/* Н-368 (1.01.01.03): окно Open 1706×935 даёт поле ~781 px — 19 пунктов по 33 px, две подписи групп и три плитки уводили
   «Настройки» на 71 px за низ (низ 852 при окне 781). До 860 px: пункт 29 px, плитка 26 px, подписи групп ближе. */
@media (min-height: 769px) and (max-height: 860px) {
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri { min-height: 29px; gap: 2px; }
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri svg { width: 15px; height: 15px; }
  :root:not([data-size='large']) .kh-rg { margin: 3px 0 1px; }
  :root:not([data-size='large']) .kh-tm { height: 26px; gap: 1px; }
  :root:not([data-size='large']) .kh-tm svg { width: 12px; height: 12px; }
}
/* Н-368: до 768 px (1366×768; окно 1440×900 даёт поле 746 px) — плотный рельс уходил за низ на 16–20 px: подписи групп брали
   поля обычного кегля (7 + 3 px). Пункт 25 px: значок 15 + 1 + строка 9. */
@media (max-height: 768px) {
  :root:not([data-size='large']) .kh-rg { margin: 1px 0 0; }
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri { min-height: 25px; }
  :root:not([data-size='large']) .kh-rail .rail-nav button.kh-ri svg { width: 15px; height: 15px; }
}

/* ═══ «МОИ ТЕРМИНАЛЫ» v8 (этап 2, 04.10.2026): слои и лагеря · карта или таблица · карточка, лента ═══ */
/* 1.72.4 (Cowork 07:16Z): страница не листается — колонки во всю высоту окна, длинное листается в своём блоке; колонки
   сворачиваются «‹ ›» (тот же приём, что у «Карты сети»: `.set-kolonka` / `.set-svernuta`). */
.kh-flot { flex-grow: 1; min-height: 0; display: grid; gap: 12px; padding: 12px 14px 0 14px;
  grid-template-columns: 300px minmax(0, 1fr) 340px; }
.kh-flot.bez-slevoy { grid-template-columns: 28px minmax(0, 1fr) 340px; }
.kh-flot.bez-spravoy { grid-template-columns: 300px minmax(0, 1fr) 28px; }
.kh-flot.bez-slevoy.bez-spravoy { grid-template-columns: 28px minmax(0, 1fr) 28px; }
.kh-flot .set-kolonka { gap: 10px; }
.kh-flot .set-kolonka > .flot-blok:first-of-type .flot-blok-head { padding-right: 28px; }
/* Левая: «Лагеря и тропы» забирает остаток высоты и листается внутри — низ колонки без дыры. */
.kh-flot .set-kolonka > .flot-lagerya-mesto { flex: 1 1 0; min-height: 140px; display: flex; flex-direction: column; }
/* Н-300 (1.72.25): при 112 px сам список «Лагеря и тропы» в 1440×900 сжимался до 36 px; 150 px (поток Е) выводили левую колонку
   за низ окна на 33 px (сквозной 1440: «дыр нет», Н-213 — от 1440×900 колонки без прокрутки) — 116 px: колонка в окне, список
   листается со знаком «ещё N». */
@media (max-height: 920px) { .kh-flot .set-kolonka > .flot-lagerya-mesto { min-height: 116px; } }
/* Короткий список «Лагеря и тропы» (меньше пяти строк — не заполняет место) — по содержимому: остаток высоты забирает развёрнутое
   «Обозначение», его сетка листается и покажет больше, а не пустота под строками. Длинный список и свёрнутое «Обозначение» — как выше. */
.kh-flot .set-kolonka:has(> .obozn-gruppy:not(.svernut)) > .flot-lagerya-mesto:not(:has(.flot-l-str:nth-of-type(5))) { flex: 0 0 auto; min-height: 0; }
.kh-flot .set-kolonka:has(> .obozn-gruppy:not(.svernut)) > .flot-lagerya-mesto:not(:has(.flot-l-str:nth-of-type(5))) :is(.flot-lagerya, .flot-lagerya-spisok) { flex: 0 0 auto; }
/* Е5-5 (слово Open «колонка по содержимому»): когда список лагерей короче своего места (замер после отрисовки) левая колонка кончается на последнем блоке —
   ниже фон страницы без рамки, пустой рамки нет; «Обозначение» по содержимому, не влезает — сжимается до 120 px и листает свою сетку.
   Длинный список заполняет колонку и листается сам — как было. */
.kh-flot .set-kolonka.flot-sleva[data-po-soderzhimomu] { align-self: start; max-height: 100%; }
.kh-flot .set-kolonka.flot-sleva[data-po-soderzhimomu] > :last-child { flex-grow: 0; }
.kh-flot .set-kolonka.flot-sleva[data-po-soderzhimomu] > .flot-lagerya-mesto { flex: 0 0 auto; min-height: 0; }
.kh-flot .set-kolonka.flot-sleva[data-po-soderzhimomu] > .flot-lagerya-mesto :is(.flot-lagerya, .flot-lagerya-spisok) { flex: 0 0 auto; }
.kh-flot .set-kolonka.flot-sleva[data-po-soderzhimomu] > #flot-oboznacheniya.obozn-gruppy:not(.svernut) { flex: 0 1 auto; min-height: 120px; display: flex; flex-direction: column; }
.kh-flot .set-kolonka.flot-sleva[data-po-soderzhimomu] > #flot-oboznacheniya.obozn-gruppy:not(.svernut) > .obozn-setka-2 { flex: 0 1 auto; min-height: 0; max-height: none; overflow-y: auto; }
.flot-lagerya { flex: 1 1 0; min-height: 0; }
.flot-lagerya-spisok { flex: 1 1 0; min-height: 0; overflow-y: auto; scrollbar-width: thin; display: flex; flex-direction: column; }
.flot-l-str { display: grid; grid-template-columns: 14px minmax(0, 1fr) auto; align-items: center; gap: 8px; min-height: 28px;
  padding: 2px 4px; border: none; border-top: 1px solid var(--hair); background: none; color: var(--ink); font: inherit;
  font-size: var(--t-sm); text-align: left; cursor: pointer; width: 100%; }
.flot-l-str.sel { color: var(--nv-cy); background: color-mix(in srgb, var(--nv-cy) 8%, transparent); }
.flot-l-imya { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flot-l-kogda { white-space: nowrap; }
/* Правая: карточка во всю высоту, листается внутри. */
.kh-flot .set-sprava > .flot-sprava-telo { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.flot-sprava-telo > .flot-blok { flex: 1 1 0; min-height: 0; overflow-y: auto; scrollbar-width: thin; }
/* Середина: строка «Терминалы · N», рамка карты (карта + лента) до низа; список — панелью поверх. */
.flot-seredina { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 10px; padding-bottom: 12px;
  position: relative; }
.flot-seredina > .note { margin: 0; flex: none; }
.flot-stroka { flex: none; }
.flot-ramka { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.flot-ramka > .karta-golova { flex: none; }
.flot-karta-telo { flex: 1 1 0; min-height: 0; display: flex; }
.flot-karta-telo > .col { flex: 1 1 0; min-height: 0; min-width: 0; position: relative; }
.kh-flot .flot-karta-telo .map-host { flex: 1 1 0; height: auto; min-height: 160px; }
.flot-lenta-mesto { flex: none; }
.flot-spisok { position: absolute; top: 40px; left: 0; right: 0; bottom: 12px; z-index: 1200; display: flex;
  flex-direction: column; background: var(--nv-bar); box-shadow: 0 8px 28px rgba(0, 0, 0, .45); }
.flot-spisok[hidden] { display: none; }
.flot-spisok-golova { padding: 12px 16px; display: flex; gap: 12px; flex-wrap: wrap; align-items: center;
  border-bottom: 1px solid var(--border); flex: none; }
.flot-spisok-telo { flex: 1 1 0; min-height: 0; overflow: auto; scrollbar-width: thin; }
/* Одна прокрутка на обе оси (Cowork 15:28): у вложенной горизонтальной полоса была внизу всего списка — за краем панели. */
/* Н-300 (1.72.25): по ширине панели, не `max-content` — тот раздувал последний столбец по самому длинному замечанию, и
   таблица уходила за правый край окна. Уже суммы нижних границ столбцов (fleet.mjs COLS) не сжимается — тогда листается
   та же единая прокрутка. Шапка — переносом внутри своей ячейки, не поверх соседней. */
.flot-spisok .flot-tablica-skroll { overflow: visible; width: 100%; min-width: min-content; }
.flot-spisok .flot-tablica-skroll > .row-grid, .flot-spisok .flot-tablica-skroll #fleet-rows .row-grid { min-width: 0; }
.flot-spisok .head-cell { white-space: normal; overflow-wrap: break-word; hyphens: manual; }
/* 1.72.26 (поток Б, Cowork 13.10 21:16 п. 3 [3]: «есть замечан…»): состояние в «Выбрать терминал» — переносом по словам, а не
   многоточием посреди слова (stateDot ставит nowrap и многоточие строкой стиля — отсюда !important). */
.flot-spisok .sd-tekst { white-space: normal !important; overflow: visible !important; text-overflow: clip !important; overflow-wrap: normal; word-break: normal; }
.flot-spisok .flot-tablica-skroll .head-cell, .flot-spisok .flot-tablica-skroll .cell { padding-left: 10px; padding-right: 8px; }
.kz-ugol { position: absolute; right: 6px; top: 4px; z-index: 2; font-size: var(--t-xs); color: var(--muted);
  background: color-mix(in srgb, var(--nv-bg) 70%, transparent); padding: 0 4px; cursor: help; }
.flot-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.flot-blok-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
/* Н-443: «Трекеры · N» — своей строкой под шлюзами списка LoRa. */
.lo12-podzag { margin: 12px 0 4px; }
.flot-blok .ht, .flot-stroka .ht, .flot-kartochka .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em;
  text-transform: uppercase; color: var(--nv-cy); }
/* слои */
.flot-sloy { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto 18px auto; align-items: center; gap: 8px;
  min-height: 30px; padding: 2px 2px; border: none; border-top: 1px solid var(--hair); background: none;
  color: var(--ink); text-align: left; width: 100%; font: inherit; }
button.flot-sloy, div.flot-sloy[role=button] { cursor: pointer; }
.flot-sloy-go { width: 18px; height: 18px; padding: 0; border: 0; background: none; color: var(--nv-cy); cursor: pointer;
  display: flex; align-items: center; justify-content: center; }
.flot-sloy-go:hover { color: var(--ink); }
.flot-sloy.off .flot-sloy-go { color: var(--nv-cy); cursor: pointer; }
/* «Вне карты» (1.72.5, v12 h1-city). Н-300 (1.72.25): переносом, не срезом — в 1440×900 «Цех-4» уходил за край на 25 px. */
.flot-vne { display: flex; flex-wrap: nowrap; overflow: hidden; align-items: center; gap: 6px 10px; padding: 8px 12px; border: 1px solid var(--nv-line);
  background: var(--nv-bar); }
.flot-vne[hidden] { display: none; }
.flot-vne-plus { color: var(--muted); cursor: help; }
.flot-vne > * { flex: none; white-space: nowrap; }
.flot-vne-t { display: inline-flex; align-items: center; gap: 5px; border: 0; background: none; color: var(--ink); padding: 0;
  cursor: pointer; font-size: var(--t-xs); }
.flot-sloy svg { color: var(--nv-cy); }
.flot-sloy.off, .flot-sloy.off svg { color: var(--nv-dim); cursor: not-allowed; }
.flot-sloy-imya { display: flex; flex-direction: column; min-width: 0; }
.flot-sloy-imya small { font-size: var(--t-xs); overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.flot-sloy-chto { font-family: var(--nv-mono); }
/* Н-269 (1.72.22): «шлюз 1 · трекеров 2» — переносом в узкой колонке, подписи слоя слева не сжимаются. */
.flot-sloy-chto { max-width: 92px; white-space: normal; text-align: right; line-height: 1.2; }
.flot-tumbler { width: 28px; height: 14px; border: 1px solid var(--nv-line); position: relative; }
.flot-tumbler::after { content: ''; position: absolute; top: 2px; left: 2px; width: 8px; height: 8px; background: var(--nv-dim); }
.flot-tumbler.on { border-color: var(--nv-cy); }
.flot-tumbler.on::after { left: auto; right: 2px; background: var(--nv-cy); }
/* лагеря: чипы терминалов для выбора карточки */
.flot-chipy { display: flex; flex-wrap: wrap; gap: 6px; }
.flot-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px; border: 1px solid var(--border);
  background: none; color: var(--ink); font: inherit; font-size: var(--t-xs); cursor: pointer; max-width: 100%; }
.flot-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flot-chip.sel { border-color: var(--nv-cy); color: var(--nv-cy); }
/* середина */
.flot-stroka { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.flot-schet { display: inline-flex; align-items: center; gap: 5px; font-size: var(--t-sm); }
.flot-tablica-skroll { overflow-x: auto; }
.drugie-skroll { overflow-x: auto; }   /* «Другие терминалы»: таблица листается внутри панели (Н-153) */
.flot-tablica-skroll > .row-grid, .flot-tablica-skroll #fleet-rows .row-grid { min-width: 1000px; }
.kh-flot #other-terminals { padding: 12px 0 0 !important; }
/* ═══ 1.72.5 (карточка Cowork 19:35, образец — v12 #terminals): лента поверх карты, графики, карточка, «Обозначение» ═══ */
/* Заголовки блоков — «»» и мелкие разреженные заглавные (v12 `.ht` с K1.chev, `.hl`). */
.kh-flot .flot-blok-head .ht::before, .ok-okno .kart-blok-head .ht::before, .vm-head .ht::before, .kh-flot .kart-blok-head .ht::before, .flot-stroka .ht::before {
  content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
.hl { font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }

/* карточка справа */
.flot-k-head { display: flex; align-items: center; gap: 12px; padding-right: 28px; }
.flot-k-znak { flex: none; display: flex; }
.flot-k-znak[data-state='down'] .znak { filter: drop-shadow(0 0 5px color-mix(in srgb, var(--critical) 60%, transparent)); }
.flot-k-imena { min-width: 0; }
.flot-k-imya { font: 600 var(--t-xl) var(--nv-mono); color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flot-k-pod { overflow-wrap: anywhere; }
.flot-k-sost { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin: 10px 0 6px;
  padding: 8px 10px; border: 1px solid var(--border); }
.flot-k-sost[data-state='warn'], .flot-k-sost[data-state='recentOutage'] { border-color: var(--warn); }
.flot-k-posled { display: flex; flex-direction: column; align-items: flex-end; text-align: right; }
.flot-k-plashka { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 4px 6px; margin: 10px 0 6px;
  padding: 8px 10px; border: 1px solid var(--critical); color: var(--critical);
  background: color-mix(in srgb, var(--critical) 9%, transparent); }
.flot-k-plashka-t { display: flex; align-items: center; gap: 8px; min-width: 0; }
.flot-k-plashka .flot-k-posled b { color: var(--ink); }
/* Подпись «последние данные» не влезает рядом с плашкой — уходит строкой ниже, а не поверх текста плашки (колонка в 1366). */
.flot-k-plashka .flot-k-posled { margin-left: auto; }
.flot-k-gauge { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; align-items: center; margin: 6px 0; }
.flot-k-kv { display: flex; flex-direction: column; min-width: 0; }
.flot-kv { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 3px 0;
  border-bottom: 1px solid var(--hair); font-size: var(--t-sm); }
.flot-kv .cell { padding: 0; }
.flot-kv > span:last-child { text-align: right; }
/* 1.72.32 (доска 15.10 01:29 Cowork): свежее число с единицей в таблице правой колонки — одной строкой, как у давнего (Н-174):
   Chrome рвал «5,2 Мбит/с» после «/» («Мбит/» и «с» строкой ниже — кадр kolonka-do 1706). */
.flot-k-kv [data-kv], .flot-k-kv [data-kv] > span { white-space: nowrap; }
/* 1.01.01.10 (сверка Cowork 17:34 п. 1): «Тревоги терминала» — список словами, не число: в узкой «Телеметрии» окна одной
   строкой он обрезался бы справа. Переносится по словам; правило Н-174 для чисел выше не тронуто. */
.flot-k-kv [data-kv="trevogi"], .flot-k-kv [data-kv="trevogi"] > span { white-space: normal; overflow-wrap: anywhere; }
.kart-tarelka-prichina { margin-top: 4px; white-space: normal; overflow-wrap: anywhere; }
.kart-vyhod [data-vyhod-skorost] { margin-top: 2px; }
/* «Скорость вниз» входа — словами («не даёт · тарелка не отвечает RP5 …»): одной строкой обрезалась. Переносится по словам. */
.flot-k-kv [data-kv="vniz"][data-vhod] { white-space: normal; overflow-wrap: anywhere; }
/* «Каналы»: полоса доли уступает место словам (до нуля) — «даёт ↓ 1 ↑ 1 кбит/с» не переносится; у недающего её нет вовсе. */
.st12-kanal.kn-vhod { grid-template-columns: auto auto minmax(0, 1fr) auto; }
.kn-vhod > [data-kanal-skorost], .kn-vhod > [data-vedet-s] { white-space: nowrap; }
.st12-kanal.kn-vhod[data-daet="0"] { grid-template-columns: auto auto 1fr; }
.kn-vhod[data-daet="0"] > .st12-kanal-polosa { display: none; }
.kn-vhod[data-daet="0"] > [data-kanal-skorost] { text-align: right; }
/* Факты недающего входа — второй строкой во всю ширину строки входа, переносятся словами. */
.kn-vhod > .kn-fakty { grid-column: 1 / -1; white-space: normal; overflow-wrap: anywhere; line-height: 1.15; padding-top: 1px; }
.kart-blok { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.kart-blok-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.kart-blok-head .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
/* Число с единицей не рвётся («7 кбит/с»); переносится заголовок, а не значение. */
.kart-blok-head > .ht { min-width: 0; }
.kart-blok-head > .m { white-space: nowrap; flex: none; }
/* Н-496: сворачиваемый блок правой колонки — заголовок кнопкой, «»» повёрнут вниз у развёрнутого; свёрнутый — начало или только заголовок. */
.kart-blok-head.svorot-head { cursor: pointer; user-select: none; }
.kh-flot .kart-blok-head.svorot-head .ht::before { display: inline-block; transition: transform .15s ease; }
.kh-flot .kart-blok:not(.svernut) > .kart-blok-head.svorot-head .ht::before { transform: rotate(90deg); }
.kart-blok.svernut[data-svorot='zagolovok'] > :not(.kart-blok-head) { display: none; }
.kart-blok.svernut[data-svorot='nachalo'] > :not(.kart-blok-head) ~ :not(.kart-blok-head) { display: none; }
.kart-blok.svernut[data-svorot='nachalo'] > .kart-blok-head + * { max-height: 2.7em; overflow: hidden; }
@media (prefers-reduced-motion: reduce) { .kh-flot .kart-blok-head.svorot-head .ht::before { transition: none; } }
/* Справочные блоки (ui/svorot.mjs spravochnyyBlok): свёрнутый — один заголовок; в низком окне так по умолчанию. */
.flot-blok-head.svorot-head { cursor: pointer; user-select: none; }
.svernut[data-svorot='zagolovok'] > :not(.flot-blok-head):not(.kart-blok-head) { display: none; }
.svernut[data-svorot='zagolovok'] > .flot-blok-head { margin-bottom: 0; }
.flot-blok-head.svorot-head .ht::before, .obozn > .flot-blok-head.svorot-head .hl::before { content: '»'; margin-right: 6px; color: var(--nv-cy);
  font-weight: 700; }
.flot-blok-head.svorot-head .ht::before, .flot-blok-head.svorot-head .hl::before { display: inline-block; transition: transform .15s ease; }
:not(.svernut) > .flot-blok-head.svorot-head .ht::before,
:not(.svernut) > .flot-blok-head.svorot-head .hl::before { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .flot-blok-head.svorot-head .ht::before, .flot-blok-head.svorot-head .hl::before { transition: none; } }
.kart-chto-delat { line-height: 1.5; cursor: help; }
/* Н-441: совет — название проблемы строкой над действием, причина от тарелки — мелко ниже. */
.kart-sovet + .kart-sovet { margin-top: 8px; }
.kart-sovet-zag { display: block; font-weight: 600; }
.kart-sovet-prichina { margin-top: 2px; }
.kart-poteri { display: flex; justify-content: center; }
.kart-poteri .gauge-big { font-size: var(--t-lg); font-weight: 600; white-space: nowrap; }
.kart-poteri .gauge-small { line-height: 1.1; }
.kart-poteri .gauge-text { gap: 4px; }   /* «100 %» не прижато к «потери данных» (сквозной 1.72.5: текст на текст) */
.kart-poteri .gauge-big { line-height: 1; }
/* ═══ 1.72.30 · круг «Потеря данных» — B «Орбита» (ui/orbita.mjs; эталон Документы/KRUG-B-ORBITA-etalon-2026-10-14.html,
   выбор Open 14.10). День — :root (цвета эталона «день»), ночь — тёмные темы. Размеры — эталона: круг 96 px, подпись
   JetBrains Mono 9 px .14em, число 13 px 600; красное от 5 %. ═══ */
:root {
  /* День: средняя точка градиента — 0,45 (#0068C4); на 0,4 — цвет прямой #5FC6F0 → #0068C4 в этом месте (8/9 пути). */
  --orb-dor: var(--nv-line); --orb-g1: #5FC6F0; --orb-g2a: #0B72C9; --orb-g2b: #0068C4; --orb-g3: #2F4BC8;
  --orb-risk: #0068C4; --orb-risk-op: .35; --orb-orbita: #5C86B0; --orb-orbita-op: .4; --orb-sput: #0068C4;
  --orb-krest: #0068C4; --orb-krest-op: .5; --orb-konec: #0068C4; --orb-konec-ten: none;
  --orb-svet: drop-shadow(0 0 3px rgba(0,104,196,.3)); --orb-blik: #FFFFFF;
}
:root[data-theme='dark'], :root[data-theme='tactical_amber'], :root[data-theme='phosphor'], :root[data-theme='signal'] {
  /* Ночь: средняя точка — 0,4 (#36D2FF); на 0,45 — цвет прямой #36D2FF → #2F5BFF в этом месте (1/12 пути). */
  --orb-dor: #0B2232; --orb-g1: #E0FAFF; --orb-g2a: #36D2FF; --orb-g2b: #35C8FF; --orb-g3: #2F5BFF;
  --orb-risk: #1FC8FF; --orb-risk-op: .4; --orb-orbita: #1E78D8; --orb-orbita-op: .35; --orb-sput: #7FE6FF;
  --orb-krest: #1FC8FF; --orb-krest-op: .55; --orb-konec: #E0FAFF; --orb-konec-ten: drop-shadow(0 0 4px #36D2FF);
  --orb-svet: drop-shadow(0 0 4px rgba(54,210,255,.35)); --orb-blik: #FFFFFF;
}
.orb { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.orb-svg { display: block; overflow: visible; }
.orb-svg.svet { filter: var(--orb-svet); }
.orb-s1 { stop-color: var(--orb-g1); } .orb-s2a { stop-color: var(--orb-g2a); } .orb-s2b { stop-color: var(--orb-g2b); }
.orb-s3 { stop-color: var(--orb-g3); }
.orb-dor { fill: none; stroke: var(--orb-dor); stroke-width: 6; }
.orb-duga { fill: none; stroke-width: 6; stroke-linecap: round; }
.orb-blik { fill: none; stroke: var(--orb-blik); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 5 100; opacity: 0; }
.orb-riski { fill: none; stroke: var(--orb-risk); stroke-opacity: var(--orb-risk-op); stroke-width: 5; stroke-dasharray: 0.06 0.94; }
.orb-orbita { fill: none; stroke: var(--orb-orbita); stroke-opacity: var(--orb-orbita-op); }
.orb-sput { fill: var(--orb-sput); }
.orb-sput.tusklo { fill-opacity: .35; }
.orb-krest { fill: none; stroke: var(--orb-krest); stroke-opacity: var(--orb-krest-op); stroke-width: 1.2; }
.orb-konec { fill: var(--orb-konec); filter: var(--orb-konec-ten); transform-box: fill-box; transform-origin: center; }
.orb-konec.tusklo { fill-opacity: .35; filter: none; }
.orb-konec-g, .orb-sput-g { transform-box: view-box; transform-origin: 75px 75px; }
.orb-podpis { font-family: var(--nv-mono); white-space: nowrap; line-height: 1.2; }
.orb-podpis i { font: normal 500 9px var(--nv-mono); letter-spacing: .14em; color: var(--nv-mut); }
.orb-podpis b { margin-left: 6px; font: 600 13px var(--nv-mono); color: var(--nv-txt); }
/* 1.72.31, Н-323 (доска 14.10 19:27 Cowork п. 1): ширину блока не задаёт число — место под самое широкое «100 %» (5 знаков
   моноширинного), иначе круг и таблица справа сдвигались на 8–23 px при 9 → 10 %, к «—» и при смене терминала.
   inline-block наследует выравнивание подписи: в одну строку — от начала, в две — по центру. */
.orb-podpis b { display: inline-block; min-width: 5ch; }
.orb-podpis b.bad { color: var(--critical); }
/* 1.72.32 (доска 15.10 01:10 Cowork п. 3): в правой колонке «Моих терминалов» блок одной строкой был 144,9 px — на 1706 таблице
   справа не хватало места, «Скорость вниз» уходила в две строки. Число по-прежнему под «100 %» (5ch — ровно его ширина у
   моноширинного, запаса нет); ужата разрядка подписи «ПОТЕРЯ ДАННЫХ» (.14em → .06em) и отступ числа (6 → 4 px) — только здесь,
   эталон «Орбиты» в остальных местах прежний. */
#flot-kartochka .orb-podpis i { letter-spacing: .06em; }
#flot-kartochka .orb-podpis b { margin-left: 4px; }
/* Зазор между «Орбитой» и таблицей — 8 px (было 12): у колонки бывает полоса прокрутки (12 px, сквозной k32h: колонка 340 → 328),
   и «Скорость вниз» (83,5 px одной строкой) без него снова не помещалась (места 83,2). */
#flot-kartochka .flot-k-gauge { gap: 8px; }
/* Как v12 (задание 04:27 п. 6): в карточке число и «потеря данных» — внутри кольца, по центру; крест под ними не рисуется.
   Число сверху, подпись под ним в две строки. Разметка та же — меняется только раскладка. */
#flot-kartochka .orb { position: relative; }
#flot-kartochka .orb-podpis { display: flex; flex-direction: column-reverse; align-items: center; white-space: normal; text-align: center; }
/* Н-496 (слово Open 01.11): в круге — только число; «потеря данных» — под кругом. */
#flot-kartochka .orb-podpis b { position: absolute; left: 0; top: 0; width: 96px; height: 96px; display: flex; align-items: center; justify-content: center;
  pointer-events: none; }
#flot-kartochka .orb-podpis i { max-width: 110px; font-size: var(--t-xs); line-height: 1.1; }
#flot-kartochka .orb-podpis b { margin-left: 0; min-width: 0; font-size: var(--t-lg); }
#flot-kartochka .orb-podpis .orb-tochka { display: none; }
/* Н-472: «за N ч снимков» — под «потеря данных», мельче и приглушённо; в строке вне карточки — после числа. */
.orb-podpis .orb-za { display: block; max-width: 64px; margin: 1px auto 0; font: 500 9px/1.1 var(--nv-mono); color: var(--warn); }
#flot-kartochka .orb-krest { display: none; }
/* Давность старых чисел — в плашке («последние данные») и в подсказке числа; строкой под каждым числом таблица росла на
   четыре строки, и карточка уходила под край (задание 04:27 п. 5). Число приглушено — старое. */
#flot-kartochka .flot-k-kv .reading-vozrast { display: none; }
#flot-kartochka .flot-k-kv .reading-stack { color: var(--muted); }
/* Карточка в колонке — целиком, с кнопками внизу, без прокрутки в 1706×935 (задание 04:27 п. 5, как v12): действие «Что делать» —
   две строки (целиком — в подсказке и в окне «Данные»), плашка «Нет связи» — одной строкой (подпись при нехватке места — под ней), блоки ближе. */
#flot-kartochka .kart-sovet-delat { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden; }
#flot-kartochka .kart-chto-delat { line-height: 1.35; }
#flot-kartochka .flot-k-plashka { margin: 6px 0 4px; padding: 6px 10px; }
#flot-kartochka .flot-k-plashka b, #flot-kartochka .flot-k-plashka .flot-k-posled > span { white-space: nowrap; }
#flot-kartochka .kart-blok { margin-top: 7px; }
#flot-kartochka .flot-k-gauge { margin: 4px 0; }
#flot-kartochka .flot-kv { padding: 2px 0; }
/* Кнопки — две строки, как v12: «Связаться» во всю ширину, ниже «Данные · Другой · Компас». */
#flot-kartochka .flot-k-knopki.flot-k-knopki-v12 { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-top: 6px; }
#flot-kartochka .flot-k-knopki-v12 > .flot-k-kompas { grid-column: auto; }
/* Крупный кегль (доска 17:11 п. 4): подпись 11 px, число 15 px (+2, как остальная шкала крупного кегля). */
:root[data-size='large'] .orb-podpis i { font: normal 500 11px var(--nv-mono); }
:root[data-size='large'] .orb-podpis b { font: 600 15px var(--nv-mono); }
/* Крупным кеглем правая колонка узкая при любом окне: подпись в одну строку (~165 px) и на 1706 рвала числа справа
   («5,2 Мбит / с», «0,2 / %» — кадр k30b 1706, крупный кегль). Там — две строки по п. 3, как при окне уже 1600 px. */
:root[data-size='large'] #flot-kartochka .orb-podpis { text-align: center; }
:root[data-size='large'] #flot-kartochka .orb-podpis i, :root[data-size='large'] #flot-kartochka .orb-podpis b { display: block; }
:root[data-size='large'] #flot-kartochka .orb-podpis b { margin: 2px 0 0; }
:root[data-size='large'] #flot-kartochka .orb-tochka { display: none; }
/* Узкое окно (1440): в правой колонке подпись одной строкой (~135 px) отнимала место у чисел справа — «5,2 Мбит/с» и
   «0,2 %» рвались (кадр k30b 1440). Там две строки (доска 17:11 п. 3): «ПОТЕРЯ ДАННЫХ» и число, обе по центру под кругом;
   «·» — только в одну строку (в две он прячется). */
@media (max-width: 1599px) {
  #flot-kartochka .orb-podpis { text-align: center; }
  #flot-kartochka .orb-podpis i, #flot-kartochka .orb-podpis b { display: block; }
  #flot-kartochka .orb-podpis b { margin: 2px 0 0; }
  #flot-kartochka .orb-tochka { display: none; }
}
@keyframes orb-kruzhit { to { transform: rotate(360deg); } }
@keyframes orb-migaet { 0%, 100% { opacity: .15; } 50% { opacity: 1; } }
@keyframes orb-ezd-duga { from { stroke-dasharray: var(--orb-ot) 100; } }
@keyframes orb-ezd-konec { from { transform: rotate(var(--orb-ot-ug)); } }
@keyframes orb-blik { 0% { stroke-dashoffset: 0; opacity: 0; } 12% { opacity: .95; } 85% { opacity: .9; }
  100% { stroke-dashoffset: var(--orb-blik-do); opacity: 0; } }
@keyframes orb-vspyshka { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.8); } }
.orb-sput-g.kruzhit { animation: orb-kruzhit 8s linear infinite; }
.orb .migaet { animation: orb-migaet 1.4s ease-in-out infinite; }
.orb-duga.ezd { animation: orb-ezd-duga 1s ease-out; }
.orb-konec-g.ezd { animation: orb-ezd-konec 1s ease-out; }
.orb-blik { animation: orb-blik .9s ease-out forwards; }
.orb-konec.vspyshka { animation: orb-vspyshka .5s ease-out .7s; }
@media (prefers-reduced-motion: reduce) {
  .orb-sput-g.kruzhit, .orb .migaet, .orb-duga.ezd, .orb-konec-g.ezd, .orb-blik, .orb-konec.vspyshka { animation: none; }
}
/* ═══ Общий круг (ui/krug.mjs) — вид «Орбиты»: те же радиусы и толщины в сетке 150 (дорожка и дуга 6, риски 5, точка
   r 4,5). Цвет — статус места: основной — переменная темы (--ok / --warn / --critical / --accent), светлый край градиента
   — она же, разбавленная белым; `info` — градиент и точка самой «Орбиты». ═══ */
:root { --krug-punktir: var(--nv-line); }
:root[data-theme='dark'], :root[data-theme='tactical_amber'], :root[data-theme='phosphor'], :root[data-theme='signal'] {
  --krug-punktir: #1F3A4E;
}
.krug { --krug-c: var(--accent); --krug-l: color-mix(in srgb, var(--krug-c) 40%, #FFFFFF); --krug-konec: var(--krug-c);
  display: inline-flex; flex-direction: column; align-items: center; gap: 4px; }
:root[data-theme='dark'] .krug, :root[data-theme='tactical_amber'] .krug, :root[data-theme='phosphor'] .krug,
:root[data-theme='signal'] .krug { --krug-konec: var(--krug-l); }
.krug[data-status='ok'] { --krug-c: var(--ok); }
.krug[data-status='warn'] { --krug-c: var(--warn); }
.krug[data-status='crit'] { --krug-c: var(--critical); }
.krug-kolco { position: relative; line-height: 0; }
.krug-svg { display: block; overflow: visible; }
.krug-svg.svet { filter: drop-shadow(0 0 4px color-mix(in srgb, var(--krug-c) 35%, transparent)); }
.krug[data-status='info'] .krug-svg.svet { filter: var(--orb-svet); }
.krug-s1 { stop-color: var(--krug-l); } .krug-s2a, .krug-s2b, .krug-s3 { stop-color: var(--krug-c); }
.krug[data-status='info'] .krug-s1 { stop-color: var(--orb-g1); } .krug[data-status='info'] .krug-s2a { stop-color: var(--orb-g2a); }
.krug[data-status='info'] .krug-s2b { stop-color: var(--orb-g2b); } .krug[data-status='info'] .krug-s3 { stop-color: var(--orb-g3); }
.krug-dor { fill: none; stroke: var(--orb-dor); stroke-width: 6; }
.krug-duga { fill: none; stroke-width: 6; stroke-linecap: round; }
/* «Нет данных»: пунктир 4° через 5° (pathLength 100 → 1,11 и 1,39). */
.krug-punktir { fill: none; stroke: var(--krug-punktir); stroke-width: 6; stroke-dasharray: 1.11 1.39; }
/* Счётчик без доли: 2 px на экране при любом размере круга. */
.krug-tonkoe { fill: none; stroke: var(--krug-c); stroke-width: 2; vector-effect: non-scaling-stroke; }
.krug-riski { fill: none; stroke: var(--orb-risk); stroke-opacity: var(--orb-risk-op); stroke-width: 5; stroke-dasharray: 0.06 0.94; }
.krug-konec { fill: var(--krug-konec); filter: drop-shadow(0 0 4px var(--krug-c)); transform-box: fill-box; transform-origin: center; }
.krug[data-status='info'] .krug-konec { fill: var(--orb-konec); filter: var(--orb-konec-ten); }
.krug .krug-konec.tusklo { fill-opacity: .35; filter: none; }
.krug-konec-g { transform-box: view-box; transform-origin: 75px 75px; }
.krug-centr { position: absolute; inset: 20%; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1px; line-height: 1.1; overflow: hidden; text-align: center; }
.krug-n { font-family: var(--nv-mono); font-weight: 600; white-space: nowrap; color: var(--nv-txt); }
.krug-n.krug-n-st { color: var(--krug-c); }
.krug[data-krug='net'] .krug-n { color: var(--nv-mut); font-weight: 500; }
.krug-pod { font-style: normal; font-family: var(--nv-mono); color: var(--nv-mut); white-space: nowrap; }
.krug-prichina { max-width: 140px; font-size: var(--t-xs); line-height: 1.2; color: var(--nv-mut); text-align: center; }
@keyframes krug-dyshit { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
.krug-konec.dyshit { animation: krug-dyshit 2s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .krug-konec.dyshit { animation: none; }
}
.kart-grafik { width: 100%; min-height: 52px; }
.kach-sh { stroke-width: 1.2; }
.kach-sh.norma { stroke: var(--ok); } .kach-sh.zamech { stroke: var(--warn); } .kach-sh.propala { stroke: var(--critical); }
.kach-sh.net { stroke: var(--muted); stroke-dasharray: 2 2; opacity: .6; }
.kach-leg { display: flex; gap: 10px; flex-wrap: wrap; }
.kach-leg span::before { content: ''; display: inline-block; width: 8px; height: 8px; margin-right: 4px; vertical-align: middle; }
.kach-leg-norma::before { background: var(--ok); } .kach-leg-zamech::before { background: var(--warn); }
.kach-leg-propala::before { background: var(--critical); }
.kach-leg-net::before { background: repeating-linear-gradient(180deg, var(--muted) 0 2px, transparent 2px 4px); }
.skor-liniya { fill: none; stroke: var(--accent); stroke-width: 1.5; }
.skor-liniya.vybran { stroke: var(--accent); stroke-width: 2; }
.skor-zaliv { fill: color-mix(in srgb, var(--accent) 16%, transparent); stroke: none; }
.flot-k-knopki { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; }
.flot-k-knopki .pill { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.pill.kontur { background: none; border: 1px solid var(--nv-cy); color: var(--nv-cy); text-transform: uppercase;
  letter-spacing: .06em; font-size: var(--t-xs); }
.pill.zalivka { background: var(--nv-cy); border: 1px solid var(--nv-cy); color: var(--nv-bg); text-transform: uppercase;
  letter-spacing: .06em; font-size: var(--t-xs); font-weight: 600; }
/* 1.72.25 (Н-302): неактивная залитая кнопка («Паспорт» при выбранном роутере) — приглушена, а не «подсвечена»: прежде правило
   было только у «Доступа» (.dost-blok), и общая заливка выглядела рабочей кнопкой, по которой окно не открывается. */
.pill.zalivka:disabled { opacity: .45; filter: saturate(.3); cursor: not-allowed; }
/* Контурная — тоже: голубая рамка при общем opacity .5 на тёмном фоне читалась рабочей кнопкой («SOS всем рядом» без права),
   а соседняя простая «Отправить» — серой. Выключенная контурная — серая, как простая. */
.pill.kontur:disabled { border-color: var(--border); color: var(--muted); cursor: not-allowed; }

/* Лента — поверх карты, внизу рамки, полупрозрачная, с уголками (v12 `_timeline`). Нижние элементы управления карты
   (линейка, источники, курсор) — над лентой. */
.flot-karta-telo { position: relative; }
.flot-lenta-mesto { position: absolute; left: 10px; right: 10px; bottom: 10px; z-index: 650; pointer-events: none; }
.flot-lenta-mesto > * { pointer-events: auto; }
.kh-flot .flot-karta-telo:has(.lenta-v12) .leaflet-bottom { bottom: calc(var(--lenta-h, 126px) + 14px); }
/* Н-172 (1.72.7): подпись источников — своей тонкой полосой у нижнего края карты, над лентой, во всю ширину; текст лицензий —
   дословно (GOTCHAS 9.205), мелко, справа. Лента её не перекрывает: отступ — высота ленты (--lenta-h, ставит fleet.mjs). */
.kh-flot .flot-karta-telo:has(.lenta-v12) .leaflet-bottom.leaflet-right { left: 10px; right: 10px; }
.kh-flot .flot-karta-telo:has(.lenta-v12) .leaflet-control-attribution { float: none; margin: 0; width: 100%; box-sizing: border-box;
  text-align: right; padding: 1px 8px; line-height: 1.35; font-size: var(--t-xs);
  background: color-mix(in srgb, var(--surface) 82%, transparent) !important; }
/* 1.72.28 (поток Л, макет v2): левая колонка — по ширине ряда кнопок «‹ −N ч» · «В данный момент» (не уже 236 px), легенда
   её не раздвигает (`width: 0; min-width: 100%`) — кнопки в ряд и никогда не заходят на заголовок, события и график (было
   236 px: «В данный момент» вылезала на график). Справа — кольцо телеметрии v12 (96 px) вместо «СЕЙЧАС чч:мм». */
.lenta-v12 { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto 100px; gap: 10px;
  padding: 6px 10px 4px; background: color-mix(in srgb, var(--nv-bg) 78%, transparent); border: 1px solid var(--nv-line);
  backdrop-filter: blur(1.5px); }
.lenta-sleva { display: flex; flex-direction: column; gap: 8px; min-width: 236px; padding-top: 6px; }
.lenta-knopki { display: flex; flex-wrap: nowrap; gap: 6px; }
.lenta-knopki .pill { flex: none; padding: 4px 9px; white-space: nowrap; }
.lenta-imena { display: flex; flex-direction: column; gap: 3px; width: 0; min-width: 100%; }
.lenta-imya { display: flex; align-items: center; gap: 6px; font-size: var(--t-xs); min-width: 0; white-space: normal;
  color: var(--ink); }
.lenta-imya-t { overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; min-width: 0; }
.lenta-imya-k { color: var(--muted); flex: none; white-space: nowrap; }
.lenta-obr { width: 16px; height: 0; flex: none; border-top: 1.5px solid var(--warn); }
.lenta-obr.vybran { border-top: 2.5px solid var(--accent); } .lenta-obr.warn { border-top-color: var(--warn); }
.lenta-obr.down { border-top-color: var(--critical); } .lenta-obr.ok { border-top-color: var(--ok); }
.lenta-obr.silent { border-top-style: dashed; border-top-color: var(--warn); }
.lenta-obr.kanal { border-top-width: 1.4px; } .lenta-obr.kanal.starlink { border-top-color: var(--ok); }
.lenta-obr.kanal.lte { border-top-color: #4C7DFF; } .lenta-obr.kanal.provod { border-top-color: var(--muted); }
.lenta-obr.propusk { width: 12px; height: 8px; margin: 0 2px; border: 1px solid var(--warn); background: color-mix(in srgb, var(--warn) 18%, transparent); }
.lenta-imya.propusk .lenta-imya-t { color: var(--warn); }
.lenta-obr.tarelka { width: 12px; height: 4px; margin: 0 2px; border: 0;
  background: linear-gradient(90deg, var(--critical) 0 50%, var(--warn) 50% 100%); }
.lenta-pole { position: relative; min-width: 0; min-height: 112px; }
.lenta-svg { display: block; overflow: visible; }
.lenta-tcap { font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .06em; text-transform: uppercase; fill: var(--muted); }
.lenta-setka { stroke: var(--hair); stroke-dasharray: 1 4; fill: none; }
.lenta-liniya { fill: none; stroke-width: 1; stroke-linejoin: round; }
.lenta-liniya.ok { stroke: var(--ok); stroke-opacity: .45; }
.lenta-liniya.warn, .lenta-liniya.attention, .lenta-liniya.recentOutage { stroke: var(--warn); stroke-opacity: .75; }
/* Н-442: Starlink не ведёт — линия тарелки приглушена; скорость ведущего выхода — подписью над графиком. */
.lenta-liniya.ne-vedet { stroke-opacity: .25; stroke-dasharray: 3 3; }
.lenta-vyhod { font-size: var(--t-sm); font-weight: 600; fill: var(--accent); paint-order: stroke; stroke: var(--surface); stroke-width: 3px; }
/* В6: линии входов площадки на ленте — цветом, как в блоке «Каналы» (Starlink зелёным, LTE синим, провод серым). */
.lenta-kanal { fill: none; stroke-width: 1.4; stroke-linejoin: round; }
.lenta-kanal.starlink { stroke: var(--ok); }
.lenta-kanal.lte { stroke: #4C7DFF; }
.lenta-kanal.provod { stroke: var(--muted); }
.lenta-liniya.down { stroke: var(--critical); stroke-opacity: .85; }
.lenta-liniya.silent { stroke: var(--warn); stroke-opacity: .6; stroke-dasharray: 3 3; }
.lenta-liniya.vybran { stroke: var(--accent); stroke-width: 2;
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--accent) 60%, transparent)); }
.lenta-osn { stroke: var(--nv-line); }
/* Ряд качества: зелёный — норма, оранжевый — замечания и пропуск снимков (во всю длину полосой), красный — пропала и обрыв
   точки. Серого «нет данных» нет (правило Open): до первых снимков окна — пусто. */
.lenta-shtrih { stroke-width: 1; }
.lenta-shtrih.norma { stroke: var(--ok); } .lenta-shtrih.zamech, .lenta-shtrih.propusk { stroke: var(--warn); }
.lenta-shtrih.propala, .lenta-shtrih.obryv { stroke: var(--critical); }
.lenta-propusk-polosa { fill: var(--warn); opacity: .32; }
/* Строка «тарелка» точки с RP5: красный — RP5 не достаёт тарелку, оранжевый — тарелка не снимала при живой точке. */
.lenta-tarelka.nedostupna { fill: var(--critical); } .lenta-tarelka.neSnimala { fill: var(--warn); }
.lenta-propusk-l { stroke: var(--warn); stroke-width: 1.4; }
.lenta-os-l { stroke: var(--nv-cy); stroke-opacity: .5; }
.lenta-os-sh { stroke: var(--nv-cy); stroke-opacity: .55; }
.lenta-chas { font-size: var(--t-xs); fill: var(--muted); }
.lenta-chas.propusk { fill: var(--warn); font-weight: 600; }
.lenta-seychas-k { fill: var(--nv-bg); stroke: var(--nv-cy); stroke-width: 1.6; }
.lenta-sob-t.perezagruzka { fill: var(--accent); } .lenta-sob-t.vernulas { fill: var(--ok); }
.lenta-sob-t.propala { fill: var(--critical); }
/* Н-291 (1.72.25): обрыв точки с RP5 поверх полос и графиков — цветом «пропала», точными минутами; событие обрыва на ленте. */
.obryv-polosa { fill: var(--critical); opacity: .78; } .obryv-polosa.open { opacity: 1; }
.lenta-sob-t.tochkaObryv { fill: var(--critical); }
.lenta-sob-t.tochkaVernulas { fill: var(--ok); }
.lenta-sob-p { font-size: var(--t-xs); fill: var(--ink); paint-order: stroke; stroke: var(--nv-bg); stroke-width: 3; }
.lenta-propala-l { stroke: var(--critical); stroke-width: 1.2; }
.lenta-eshche { font-size: var(--t-xs); fill: var(--muted); cursor: help; text-decoration: underline dotted; }
/* Рамки над лентой — разметкой v12 `.h1-tip.hf.(y|r).o`: уголки цветом события, непрозрачный фон, время моноширинным. */
.lenta-ramki { position: absolute; left: 0; right: 0; top: 0; height: 0; pointer-events: none; }
.h1-tip { position: absolute; top: 0; height: 17px; box-sizing: border-box; display: flex; align-items: center; gap: 6px;
  padding: 0 8px 0 5px; font-size: var(--t-xs); line-height: 1; white-space: nowrap; color: var(--ink); overflow: hidden;
  pointer-events: auto; cursor: help; }
.h1-tip b { font: 600 var(--t-xs) var(--nv-mono); flex: none; }
/* Вторая рамка, не влезшая в строку заголовка, — ярусом над лентой (как v12: рамка над панелью); лента даёт ей место сверху,
   и высота ленты (--lenta-h) поднимает подпись источников карты над ней. */
.h1-tip.yarus { top: -28px; }
.lenta-v12.est-yarus { margin-top: 24px; }
.h1-tip.yarus2 { top: -50px; }
.lenta-v12.est-yarus2 { margin-top: 46px; }
.h1-tip-t { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.h1-tip.hf { --hf-c: var(--nv-cy);
  background: linear-gradient(var(--hf-c), var(--hf-c)) top left / 9px 1.5px no-repeat,
    linear-gradient(var(--hf-c), var(--hf-c)) top left / 1.5px 9px no-repeat,
    linear-gradient(var(--hf-c), var(--hf-c)) top right / 9px 1.5px no-repeat,
    linear-gradient(var(--hf-c), var(--hf-c)) top right / 1.5px 9px no-repeat,
    linear-gradient(var(--hf-c), var(--hf-c)) bottom left / 9px 1.5px no-repeat,
    linear-gradient(var(--hf-c), var(--hf-c)) bottom left / 1.5px 9px no-repeat,
    linear-gradient(var(--hf-c), var(--hf-c)) bottom right / 9px 1.5px no-repeat,
    linear-gradient(var(--hf-c), var(--hf-c)) bottom right / 1.5px 9px no-repeat,
    color-mix(in srgb, var(--nv-bg) 92%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--hf-c) 16%, transparent); }
.h1-tip.hf.y { --hf-c: var(--warn); } .h1-tip.hf.y b { color: var(--warn); }
.h1-tip.hf.r { --hf-c: var(--critical); } .h1-tip.hf.r b { color: var(--critical); }
.h1-shp { display: block; flex: none; }
.h1-shp-k { fill: var(--nv-bg); stroke-width: 1.6; }
.h1-shp.swarn .h1-shp-k { stroke: var(--warn); stroke-dasharray: 2.4 2; }
.h1-shp.sdown .h1-shp-k, .h1-shp-x { stroke: var(--critical); }
.h1-shp-x { stroke-width: 1.6; fill: none; }
/* Кольцо телеметрии — `.h1-gauge` v12: 48 штрихов от r 45 до 37,8, круги r 32,5 и 29,5 пунктиром, число и подпись капсом.
   Кусок без данных — дорожкой кольца (незакрашенное деление v12), не серым. */
.lenta-sprava { display: flex; align-items: center; justify-content: center; grid-column: 4; }
/* «СЕЙЧАС ЧЧ:ММ» (v12) — своей колонкой слева от кольца, столбиком. */
.lenta-seychas-v { grid-column: 3; display: flex; flex-direction: column; justify-content: center; align-items: flex-end; gap: 2px;
  font-family: var(--nv-mono); }
.lenta-seychas-v-t { font-size: var(--t-xs); letter-spacing: .06em; color: var(--muted); }
.lenta-seychas-v b { font-size: var(--t-lg); font-weight: 600; color: var(--ink); }
.kolco-svg { display: block; overflow: visible; width: 76px; height: 76px; }
/* Н-496: в кольце — только число; окно («за 24 ч») и «на связи» — подписью под кольцом. */
.lenta-sprava { flex-direction: column; gap: 2px; }
.kolco-vne { display: flex; flex-direction: column; align-items: center; font-family: var(--nv-mono); line-height: 1.15; white-space: nowrap; }
.kolco-vne .kolco-verh { font-size: var(--t-xs); color: var(--muted); }
.kolco-vne .kolco-podpis { font-size: var(--t-xs); letter-spacing: .06em; color: var(--muted); }
.h-rs { stroke-width: 2; stroke-linecap: butt; }
.h-rs.norma { stroke: var(--ok); stroke-opacity: .95; }
.h-rs.zamech, .h-rs.propusk { stroke: var(--warn); stroke-opacity: .95; }
.h-rs.obryv { stroke: var(--critical); stroke-opacity: .95; }
.h-rs.pusto { stroke: var(--nv-line); stroke-opacity: .9; }
.h-rs.tek { stroke-width: 3.6; filter: drop-shadow(0 0 3px currentColor); }
.kolco-k1 { fill: none; stroke: var(--nv-cy); stroke-opacity: .25; }
.kolco-k2 { fill: none; stroke: var(--nv-cy); stroke-opacity: .45; stroke-width: 1.6; stroke-dasharray: 1.5 8.6; }
/* Буквы — из шкалы (`--t-*`), не 21 и 8,5 px v12 (правило strings_test): «97,8 %» — `--t-lg`, короткое «88 %» — `--t-xl`. */
.kolco-chislo { font-family: var(--nv-mono); font-weight: 600; font-size: var(--t-lg); fill: var(--ink); }
.kolco-chislo.krupno { font-size: var(--t-xl); }
.kolco-podpis, .kolco-verh { font-family: var(--nv-mono); font-weight: 500; font-size: var(--t-xs); letter-spacing: .04em; fill: var(--muted); }
.kolco-data { font-family: var(--nv-mono); font-weight: 600; font-size: var(--t-xs); fill: var(--warn); }
.lenta-pusto { padding: 30px 0; }
/* Узкая лента (окно 1152×700, Н-153): графику — место. Кольцо уходит (при ширине ленты до 600 px график был 56 px; потери за
   окно — кольцом в карточке справа), левая колонка — по ширине кнопок, без запаса 236 px. */
.flot-lenta-mesto { container-type: inline-size; }
@container (max-width: 600px) {
  .lenta-v12 { grid-template-columns: auto minmax(0, 1fr); }
  .lenta-v12 > .lenta-sprava { display: none; }
  .lenta-v12 > .lenta-seychas-v { display: none; }
  .lenta-sleva { min-width: 0; }
}
/* Не помещается рядом — уходит «Сейчас», кольцо остаётся (задание 04:27 п. 8). */
@container (max-width: 820px) {
  .lenta-v12 > .lenta-seychas-v { display: none; }
}

/* Поведение графиков (ui/grafik.mjs): курсор, точки, пипки, значок увеличения, подсказка. */
.gr-on { cursor: crosshair; user-select: none; }
.gr-vert { stroke: var(--nv-cy); stroke-opacity: .6; stroke-dasharray: 2 3; }
.gr-tochka { stroke: var(--nv-bg); stroke-width: 1; }
.gr-sob-kolco { fill: none; stroke: var(--warn); stroke-width: 1.6; }
.gr-pipka { fill: none; stroke: var(--warn); stroke-width: 1.6; }
.gr-pipka-t { font: 500 var(--t-xs) var(--nv-mono); fill: var(--warn); paint-order: stroke; stroke: var(--nv-bg); stroke-width: 3; }
.gr-zt { font: 500 var(--t-xs) var(--nv-mono); fill: var(--nv-cy); paint-order: stroke; stroke: var(--nv-bg); stroke-width: 3; }
.gr-tip { position: fixed; z-index: 3000; pointer-events: none; max-width: 320px; padding: 6px 9px; font-size: var(--t-xs);
  line-height: 1.45; color: var(--ink); background: var(--nv-bar); border: 1px solid var(--nv-line);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .35); }
.gr-tip[hidden] { display: none; }
.gr-tip-vremya { font-style: normal; font-family: var(--nv-mono); color: var(--nv-cy); display: block; }
.gr-tip-sob { color: var(--warn); font-weight: 600; display: block; }
.gr-tip-sbros { color: var(--muted); display: block; }

/* «Обозначение на карте» (v12 `_legend`): значки те же, что на карте; три столбца; без подчёркивания. */
.obozn { padding: 10px 14px; }
.obozn-setka { display: grid; grid-template-columns: repeat(3, minmax(0, auto)); gap: 7px 12px; font-size: var(--t-xs);
  justify-content: start; }
.obozn-punkt { display: flex; align-items: center; gap: 6px; min-width: 0; white-space: nowrap; }
.obozn-punkt[title] { cursor: help; }
.obozn-punkt.shir { grid-column: 1 / -1; }
.obozn-punkt.shir2 { grid-column: span 2; }
/* Легенда группами (1.72.22, Н-269): 2 колонки, длинное — многоточием (полный текст — в подсказке). */
.obozn-setka-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 5px 12px; justify-content: stretch;
  max-height: 128px; overflow-y: auto; }
.obozn-gruppy .obozn-punkt .obozn-t { overflow: hidden; text-overflow: ellipsis; }
.obozn-gr { grid-column: 1 / -1; margin-top: 3px; color: var(--muted); letter-spacing: .04em; font-weight: 600; }
.obozn-fig { display: inline-flex; color: var(--ink); }
.obozn-svg.lora .lora-l { stroke: currentColor; stroke-width: 2; stroke-dasharray: 1 4; stroke-linecap: round; fill: none; }
/* Н-226 (1.72.7): в ≤ 1440 три колонки не вмещают подписи (white-space: nowrap) — «Замечания» налезали на знак «Пропала»,
   «Не отвечает» — на стрелку потока, «река, озеро» — на ледник. Две колонки; широкий пункт — на всю строку. */
@media (max-width: 1440px) {
  .obozn-setka { grid-template-columns: repeat(2, minmax(0, auto)); }
  .obozn-punkt.shir2 { grid-column: 1 / -1; }
}
.obozn-z { width: 22px; display: flex; justify-content: center; flex: none; }
.obozn-punkt.shir .obozn-z + .obozn-t + .obozn-z, .obozn-punkt.shir2 .obozn-z + .obozn-t + .obozn-z { margin-left: 8px; }
.obozn-svg path, .obozn-svg rect, .obozn-svg circle { fill: none; }
.obozn-svg .reka-l { stroke: var(--karta-reka); stroke-width: 1.4; stroke-linecap: round; }
.obozn-svg .lednik-r { fill: color-mix(in srgb, var(--nv-cy) 6%, transparent); stroke: var(--karta-lednik); stroke-dasharray: 3 2.4; }
.obozn-svg .gor40-l { stroke: var(--karta-gor40); stroke-width: .8; }
.obozn-svg .gor200-l { stroke: var(--karta-gor200); stroke-width: 1.4; }
.obozn-svg .potok-l { stroke: var(--nv-cy); stroke-width: 1.5; stroke-dasharray: 2 4; stroke-linecap: round; }
.obozn-svg .potok-s { stroke: var(--nv-cy); stroke-width: 1.2; }
.obozn-svg .shl-r { stroke: var(--teal); stroke-width: 1.3; } .obozn-svg .shl-c { fill: var(--teal); }
.obozn-svg .lager-t { fill: none; stroke: var(--ink); stroke-width: 1.4; stroke-linejoin: round; }
.obozn-svg .tropa-l { stroke: var(--muted); stroke-width: 1.4; stroke-dasharray: 1.5 2.5; stroke-linecap: round; }
.obozn-svg .zona-k { fill: none; stroke: var(--muted); stroke-width: 1.3; stroke-dasharray: 2.5 2.5; }
.obozn-svg .mesh-l { stroke: var(--ok); stroke-width: 1.6; }
.obozn-svg .lora-c { fill: var(--teal); }
@media (max-width: 1500px) {
  .kh-flot { grid-template-columns: 260px minmax(0, 1fr) 300px; }
}

/* ═══ «УВЕДОМЛЕНИЯ» v8 (этап 3, 04.10.2026): сводка · лента «сначала тяжёлое» · правила справа ═══ */
.kh-uv { flex-grow: 1; min-height: 0; display: grid; gap: 12px; padding: 12px 14px 0 14px;
  grid-template-columns: minmax(0, 1fr) 340px; }
.uv-seredina { min-width: 0; display: flex; flex-direction: column; gap: 12px; padding-bottom: 12px; }
.uv-sprava { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px;
  scrollbar-width: thin; padding-bottom: 12px; }
.uv-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.uv-blok .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.uv-svod-chisla { display: flex; gap: 28px; align-items: baseline; flex-wrap: wrap; }
.uv-chislo { display: inline-flex; align-items: baseline; gap: 8px; }
.uv-chislo .dot { align-self: center; }
.uv-chislo-n { font: 600 var(--t-dsp) var(--nv-mono); line-height: 1.1; }
.uv-kolonki { display: grid; grid-template-columns: 250px minmax(0, 1fr) 360px; gap: 16px; padding: 6px 17px;
  font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .06em; color: var(--muted); border-bottom: 1px solid var(--hair); }
.uv-lenta { display: flex; flex-direction: column; gap: 10px; }
.uv-razdel { display: flex; align-items: center; gap: 4px; margin-top: 8px; font: 600 var(--t-xs) var(--nv-caps);
  letter-spacing: .06em; color: var(--muted); }
.uv-razdel[data-razdel="critical"] { color: var(--critical); }
.uv-razdel[data-razdel="warning"] { color: var(--warn); }
.uv-razdel::after { content: ""; flex: 1; height: 1px; margin-left: 10px; background: var(--hair); }
.uv-kartochka { padding: 13px 17px; display: grid; grid-template-columns: 250px minmax(0, 1fr) 360px; gap: 16px;
  align-items: start; }
.uv-kartochka[data-sev="critical"] { background: color-mix(in srgb, var(--critical) 9%, var(--surface)); }
.uv-chto { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.uv-zag { font: 600 var(--t-md) var(--nv-font); }
.uv-gde { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.uv-term { display: grid; grid-template-columns: minmax(0, 1fr) 64px 90px 110px; gap: 10px; align-items: center; }
.uv-term-imya { font-size: var(--t-sm); cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv-term-imya:hover { color: var(--nv-cy); }
.uv-molchat { display: flex; flex-direction: column; gap: 9px; margin-top: 8px; }
.uv-pravilo { display: grid; grid-template-columns: 12px minmax(0, 1fr) auto; gap: 10px; align-items: center;
  padding: 6px 0; border-top: 1px solid var(--hair); }
.uv-pravilo .dot.b-none { background: transparent; box-shadow: inset 0 0 0 1px var(--nv-dim); }
.uv-pravilo-imya { display: flex; flex-direction: column; min-width: 0; font-size: var(--t-sm); }
.uv-pravilo-imya small { font-size: var(--t-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv-teg { font: 600 var(--t-xs) var(--nv-mono); white-space: nowrap; }
@media (max-width: 1500px) {
  .kh-uv { grid-template-columns: minmax(0, 1fr) 290px; }
  .uv-kolonki, .uv-kartochka { grid-template-columns: 210px minmax(0, 1fr) 300px; }
  .uv-term { grid-template-columns: minmax(0, 1fr) 58px 60px; }
  .uv-term > :last-child { grid-column: 1 / -1; }
}

/* ═══ BILLING v8 (этап 3, 04.10.2026): плитки · шкала дат · график оплат по разрядам · итоги и отметки справа ═══ */
.kh-bill { flex-grow: 1; min-height: 0; display: grid; gap: 12px; padding: 12px 14px 0 14px;
  grid-template-columns: minmax(0, 1fr) 340px; }
.bill-seredina { min-width: 0; display: flex; flex-direction: column; gap: 12px; padding-bottom: 12px; }
.bill-sprava { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px;
  scrollbar-width: thin; padding-bottom: 12px; }
.kh-bill .bill-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); padding: 0; }
.bill-kpi-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.bill-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.bill-blok .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.bill-shkala-svg { width: 100%; height: auto; display: block; }
.bill-sh-skoro { fill: var(--warn); opacity: .08; }
.bill-sh-os { stroke: var(--border); stroke-width: 1; }
.bill-sh-metka { fill: var(--muted); font: 11px var(--nv-mono); }
.bill-sh-segodnya { stroke: var(--warn); stroke-width: 1.5; }
.bill-sh-segodnya-t { fill: var(--warn); font: 600 11px var(--nv-mono); }
.bill-sh-t { stroke-width: 2; fill: var(--surface); stroke: var(--nv-cy); }
.bill-sh-t.overdue { stroke: var(--critical); fill: var(--critical); }
.bill-sh-t.soon { stroke: var(--warn); }
.bill-sh-imya { fill: var(--ink); font: 11px var(--nv-mono); }
.bill-tablica { overflow-x: auto; }
.bill-tablica > .row-grid, .bill-tablica #billing-rows .row-grid { min-width: 1240px; }
.bill-razdel { display: flex; justify-content: space-between; gap: 12px; padding: 10px 0 4px;
  font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; color: var(--muted); border-bottom: 1px solid var(--hair); }
.bill-razdel[data-razdel="overdue"] { color: var(--critical); }
.bill-razdel[data-razdel="soon"] { color: var(--warn); }
.bill-valyuty { display: flex; flex-direction: column; gap: 10px; }
.bill-valyuta-kod { font: 600 var(--t-lg) var(--nv-caps); letter-spacing: .06em; }
.bill-valyuta .kv { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 3px 0; }
.bill-valyuta .kv > :last-child { white-space: nowrap; }
.bill-otmetka { display: grid; grid-template-columns: 52px minmax(0, 1fr) auto; gap: 10px; padding: 6px 0;
  border-top: 1px solid var(--hair); align-items: baseline; }
@media (max-width: 1500px) {
  .kh-bill { grid-template-columns: minmax(0, 1fr) 290px; }
  .kh-bill .bill-kpis .kpi { padding: 10px 12px; }
}

/* ═══ «АРЕНДА» v8 (этап 3, 04.10.2026): плитки · сроки сданных · таблица · свободные · справа ближайшее ═══ */
.kh-rent { flex-grow: 1; min-height: 0; display: grid; gap: 12px; padding: 12px 14px 0 14px;
  grid-template-columns: minmax(0, 1fr) 320px; }
.rent-seredina { min-width: 0; display: flex; flex-direction: column; gap: 12px; padding-bottom: 12px; }
.rent-sprava { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px;
  scrollbar-width: thin; padding-bottom: 12px; }
.kh-rent .rent-kpis { grid-template-columns: repeat(6, minmax(0, 1fr)); padding: 0; }
.kh-rent .rent-kpis .kpi { padding: 10px 12px; }
.rent-tablica, .rent-svobodnye { min-width: 0; flex-shrink: 0; }
.rent-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.rent-blok .ht, .b12-ar-karta .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.rent-sroki { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.rent-srok { border: 1px solid var(--border); padding: 10px 12px; display: flex; flex-direction: column; gap: 5px; cursor: pointer; }
.rent-srok:hover, .rent-srok:focus-visible { border-color: var(--nv-cy); }
.rent-srok[data-term="over"] { border-color: var(--critical); }
.rent-srok[data-term="ending"] { border-color: var(--warn); }
.rent-srok-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.rent-srok-imya { font: 600 var(--t-md) var(--nv-font); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rent-teg { font: 600 var(--t-xs) var(--nv-mono); white-space: nowrap; color: var(--ok); }
.rent-teg.ending { color: var(--warn); } .rent-teg.over { color: var(--critical); } .rent-teg.open { color: var(--muted); }
.rent-srok-polosa { height: 6px; background: var(--hair); position: relative; margin-top: 4px; }
.rent-srok-proshlo { height: 100%; background: var(--nv-cy); }
.rent-srok-proshlo.ending { background: var(--warn); } .rent-srok-proshlo.over { background: var(--critical); }
.rent-srok-daty { display: flex; justify-content: space-between; color: var(--muted); }
.rent-sob { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 10px; padding: 6px 0; border-top: 1px solid var(--hair); }
@media (max-width: 1500px) {
  .kh-rent { display: flex; flex-direction: column; overflow-y: auto; }
  .kh-rent > * { flex: none; height: auto; }
  .kh-rent .rent-seredina { overflow: visible; }
  .kh-rent .rent-sprava { overflow: visible; }
  .kh-rent .rent-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* колонки v8 этапа 3: блоки в колонке не сжимаются по высоте — колонка прокручивается целиком */
.uv-seredina > *, .bill-seredina > *, .rent-seredina > * { flex-shrink: 0; }

/* ═══ TICKET-ONLINE v8 (этап 3, 04.10.2026): плитки · по тарифам · по продавцам · справа цены и «Доступ» ═══ */
.kh-sales { flex-grow: 1; min-height: 0; display: grid; gap: 12px; padding: 12px 14px 0 14px;
  grid-template-columns: minmax(0, 1fr) 380px; }
.sales-seredina { min-width: 0; display: flex; flex-direction: column; gap: 12px; padding-bottom: 12px; }
.sales-seredina > * { flex-shrink: 0; }
.sales-sprava { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px;
  scrollbar-width: thin; padding-bottom: 12px; }
.kh-sales .sales-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); padding: 0; }
.kh-sales .sales-kpis .kpi { padding: 10px 12px; }
.sales-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.sales-blok .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.sales-tarif { display: grid; grid-template-columns: 110px 90px 140px 110px minmax(0, 1fr); gap: 12px; align-items: center;
  padding: 7px 0; border-top: 1px solid var(--hair); }
.sales-tarif-head { font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .06em; color: var(--muted); border-top: none; }
.sales-dolya { display: grid; grid-template-columns: minmax(0, 1fr) 44px; gap: 8px; align-items: center; }
.sales-tablica { overflow-x: auto; }
.sales-dostup { display: grid; grid-template-columns: 1fr; gap: 1px; padding: 6px 0; border-top: 1px solid var(--hair); }
@media (max-width: 1500px) {
  .kh-sales { grid-template-columns: minmax(0, 1fr) 320px; }
}

/* ═══ «ОТЧЁТЫ» v8 (этап 3, 04.10.2026): сводка за окно · таблица · справа покрытие по терминалам ═══ */
.kh-otch { flex-grow: 1; min-height: 0; display: grid; gap: 12px; padding: 12px 14px 0 14px;
  grid-template-columns: minmax(0, 1fr) 320px; }
.otch-seredina { min-width: 0; display: flex; flex-direction: column; gap: 12px; padding-bottom: 12px; }
.otch-seredina > * { flex-shrink: 0; }
.otch-sprava { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px;
  scrollbar-width: thin; padding-bottom: 12px; }
.otch-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.otch-blok .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.otch-pokazateli { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
.otch-pok { padding: 4px 16px; border-left: 1px solid var(--hair); display: flex; flex-direction: column; gap: 2px; }
.otch-pok:first-child { border-left: none; padding-left: 0; }
.otch-pok-n { font: 600 var(--t-dsp) var(--nv-mono); line-height: 1.15; }
.otch-tablica { min-width: 0; overflow-x: auto; }
.otch-pk { display: grid; grid-template-columns: minmax(0, 1fr) 90px 50px; gap: 10px; align-items: center; padding: 5px 0;
  border-top: 1px solid var(--hair); }
.otch-pk-imya { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 1500px) {
  .kh-otch { display: flex; flex-direction: column; overflow-y: auto; }
  .kh-otch > * { flex: none; height: auto; }
  .kh-otch .otch-seredina, .kh-otch .otch-sprava { overflow: visible; }
}

/* ═══ «КАРТА СЕТИ» v8 (этап 4, 04.10.2026; v11): колонки · полоса · карта · «Во весь экран» ═══ */
/* Потоки к мачте на карте NRL: над плитками, под элементами управления Leaflet, щелчков не перехватывают. */
.set-potoki { position: absolute; left: 0; top: 0; pointer-events: none; z-index: 450; overflow: visible; }
.set-potok { stroke: var(--accent); stroke-linecap: round; opacity: .9; }
.set-potok.sotr { stroke: var(--ok); }
.set-potok.prochie { stroke: var(--muted); }
.set-potok.bezDostupa, .set-potok-zasechka { stroke: var(--warn); }
.set-potok.nebo { stroke: var(--warn); stroke-dasharray: 2 5; }
.set-potok-podpis { fill: var(--ink); font: var(--t-xs) var(--font-mono); paint-order: stroke; stroke: var(--bg); stroke-width: 3px; }
/* «Источники · помеха GNSS» — около половины колонки (v12); кольцо места источника слева, строки справа. */
.set-gnss { min-height: 300px; display: flex; flex-direction: column; gap: 4px; }
.set-gnss-verh { display: flex; gap: 12px; align-items: center; }
.set-gnss-kolco { flex: none; width: 64px; height: 64px; border-radius: 50%; border: 4px solid var(--hair);
  display: grid; place-content: center; text-align: center; }
.set-gnss-kolco b { font: 600 var(--t-lg) var(--font-mono); color: var(--muted); }
.set-gnss-kolco small { font-size: var(--t-xs); color: var(--muted); }
.set-gnss-kv { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; }
.set-gnss-dey { display: flex; gap: 8px; align-items: center; margin-top: 6px; }
.set-gnss-zag { margin: 8px 0 2px; }
.kh-set { flex-grow: 1; min-height: 0; display: grid; gap: 12px; padding: 12px 14px 0 14px;
  grid-template-columns: 300px minmax(0, 1fr) 340px; }
.kh-set.bez-slevoy { grid-template-columns: 28px minmax(0, 1fr) 340px; }
.kh-set.bez-spravoy { grid-template-columns: 300px minmax(0, 1fr) 28px; }
.kh-set.bez-slevoy.bez-spravoy { grid-template-columns: 28px minmax(0, 1fr) 28px; }
.set-kolonka { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; padding-bottom: 12px;
  scrollbar-width: thin; position: relative; }
.set-kolonka > * { flex-shrink: 0; }
/* 1.72.4 (Cowork 07:16Z «дыр нет»): последний блок колонки дотягивается до её низа — пустота внутри рамки, а не под ней. */
.set-kolonka > :last-child { flex-grow: 1; }
/* «Мои терминалы»: остаток высоты забирает «Лагеря и тропы» (список), а не «Обозначение» (кадр в окне Open: список сжимался до двух строк). */
.kh-flot .set-kolonka > .obozn:last-child { flex-grow: 0; }
.set-svernut { position: absolute; top: 8px; z-index: 2; width: 22px; height: 22px; padding: 0; border: 1px solid var(--nv-line);
  background: var(--nv-bar); color: var(--nv-cy); font: 600 var(--t-sm) var(--nv-mono); cursor: pointer; }
.set-sleva .set-svernut { right: 8px; } .set-sprava .set-svernut { right: 8px; }
.set-svernuta { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 8px 0; border: 1px solid var(--nv-line);
  background: var(--nv-bar); color: var(--nv-cy); cursor: pointer; font: 600 var(--t-sm) var(--nv-mono); align-self: start; }
.set-svernuta-t { writing-mode: vertical-rl; font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; color: var(--muted); }
.set-seredina { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 8px; padding-bottom: 12px; }
.set-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
.set-blok .ht, .set-polosa .ht, .set-okno-poloska .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em;
  text-transform: uppercase; color: var(--nv-cy); }
.set-sleva .set-blok:first-of-type .flot-blok-head, .set-sprava .set-blok:first-of-type .flot-blok-head { padding-right: 28px; }
.set-poyasn { line-height: 1.5; margin-top: 4px; }
.set-tochka { display: inline-block; width: 9px; height: 9px; border-radius: 1.5px; background: var(--nv-dim); flex-shrink: 0; }
.set-gruppa { display: flex; align-items: center; gap: 8px; margin-top: 8px; padding-bottom: 3px; border-bottom: 1px solid var(--hair);
  font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.set-ustr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; width: 100%; padding: 5px 4px;
  border: none; border-bottom: 1px solid var(--hair); background: none; color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
.set-ustr:hover, .set-ustr.sel { background: var(--nav-active); }
.set-ustr-imya { min-width: 0; display: flex; flex-direction: column; }
.set-ustr-imya > *, .set-ustr-imya small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-xs); }
.set-kv { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 3px 0; font-size: var(--t-sm);
  border-bottom: 1px solid var(--hair); }
.set-kv > span { color: var(--muted); } .set-kv > b { font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.set-legenda { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 10px; font-size: var(--t-xs); }
.set-leg { display: flex; align-items: center; gap: 7px; }
.set-v-seti-itog { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
.set-chislo { font: 600 var(--t-dsp) var(--nv-mono); line-height: 1.1; }
.set-klass { display: grid; grid-template-columns: 12px minmax(0, 1fr) 40px 90px; gap: 8px; align-items: center; padding: 4px 0;
  border-bottom: 1px solid var(--hair); font-size: var(--t-sm); }
.set-klass > b { text-align: right; } .set-klass > :last-child { text-align: right; }
.set-chas { margin-top: 6px; }
.set-pasport-head { display: flex; align-items: center; gap: 8px; }
.set-pasport-imya { font: 600 var(--t-md) var(--nv-font); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-teg { margin-left: auto; flex-shrink: 0; font: 600 var(--t-xs) var(--nv-mono); color: var(--nv-cy); white-space: nowrap; }
.set-kanal + .set-kanal { margin-top: 10px; }
.set-polosa { border: 1px solid var(--nv-line); background: var(--surface); padding: 8px 12px; display: flex; flex-direction: column; gap: 6px; }
.set-polosa-verh, .set-polosa-niz { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.set-terminal { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; }
.set-terminal select { max-width: 260px; }
.set-zum-b { min-width: 30px; padding: 4px 8px; }
.set-razd { width: 1px; height: 18px; background: var(--nv-line); }
.set-radius { display: inline-flex; align-items: center; gap: 6px; }
.set-radius input { width: 70px; }
.set-ves-ekran { border-color: var(--nv-cy); color: var(--nv-cy); }
.set-ustarel { padding: 2px 8px; margin: 0; }
.set-okno { position: fixed; inset: 0; display: flex; flex-direction: column; background: var(--nv-bg); }
.set-okno > .karta-seti { flex: 1 1 auto; }
.set-okno-poloska { position: absolute; top: 12px; left: 12px; z-index: 5; display: flex; align-items: center; gap: 12px;
  padding: 8px 12px; border: 1px solid var(--nv-cy); background: var(--nv-bar); transition: opacity .3s; }
.set-okno-poloska.skryta { opacity: 0; pointer-events: none; }
@media (max-width: 1500px) {
  .kh-set { grid-template-columns: 260px minmax(0, 1fr) 290px; }
  .kh-set.bez-slevoy { grid-template-columns: 28px minmax(0, 1fr) 290px; }
  .kh-set.bez-spravoy { grid-template-columns: 260px minmax(0, 1fr) 28px; }
  .set-klass { grid-template-columns: 12px minmax(0, 1fr) 32px 70px; }
}
/* полоса над картой — в две строки и на 1366–1440: кнопки мельче, «радиус» короче, список терминалов уже */
.set-polosa .pill { padding: 3px 8px; font-size: var(--t-xs); }
.set-polosa-verh { gap: 8px; } .set-polosa-niz { gap: 6px; }
#set-zagolovok { text-transform: none; }
.set-terminal select { max-width: 220px; font-size: var(--t-xs); }
.set-radius input { width: 58px; font-size: var(--t-xs); padding: 2px 4px; }
#set-po-dannym { font-size: var(--t-xs); color: var(--muted); }
@media (max-width: 1500px) { .set-terminal select { max-width: 170px; } }

/* ═══ MESH v8 (этап 4, 04.10.2026): узлы · нейроны и профиль · соседи и связи ═══ */
.kh-mesh { grid-template-columns: 320px minmax(0, 1fr) 340px; }
.mesh-seredina { overflow: hidden; }
.mesh-skroll { min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; scrollbar-width: thin; }
.mesh-ht { margin-top: 6px; font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.mesh-uzly { display: flex; flex-direction: column; gap: 8px; }
.mesh-kartochka { cursor: pointer; display: flex; flex-direction: column; gap: 2px; font-size: var(--t-xs); }
.mesh-kartochka.sel { border-color: var(--nv-cy); box-shadow: inset 3px 0 0 var(--nv-cy); }
/* Таблица узлов MESH (1.73.0, этап 3, референс v12): узел · высота GPS · связь · питание — строкой. */
.mesh-tablica { display: flex; flex-direction: column; }
.mesh-tab-str { display: grid; grid-template-columns: minmax(0, 1.6fr) 74px 82px 64px; gap: 6px; align-items: center;
  padding: 5px 4px; border-bottom: 1px solid var(--hair); font-size: var(--t-xs); }
.mesh-tab-str.tr { cursor: pointer; } .mesh-tab-str.sel { box-shadow: inset 3px 0 0 var(--nv-cy); background: var(--nav-active); }
.mesh-tab-imya { display: flex; gap: 6px; align-items: flex-start; min-width: 0; }
.mesh-tab-imya b { font-weight: 600; }
.mesh-tab-imya-t { min-width: 0; } .mesh-tab-imya-t b { display: block; overflow-wrap: anywhere; }
.mesh-tab-str > .mono { white-space: nowrap; }
/* 1.72.7 (прибор): шапка компактной таблицы — без общего отступа .head-cell (16 px с боков в колонках 74/82/64 px — текст на тексте). */
.mesh-tab-golova .head-cell { padding: 2px 0; }
/* «Сводка по терминалам» в «Отчётах» (1.72.7): десять столбцов в 1230 px окна Open — справа отступ 6 px, шапка без разрядки. */
.otch-tab > .cell, .otch-tab > .head-cell { padding-left: 12px; padding-right: 6px; }
.otch-tab > .head-cell { letter-spacing: 0; }
/* Кнопки карточки «Моих терминалов» (1.72.7, раскладка v12): «Связаться с лагерем» — во всю ширину, «Данные · Другой» — пополам. */
.flot-k-knopki.flot-k-knopki-v12 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.flot-k-knopki-v12 > .flot-k-svyaz { grid-column: 1 / -1; }
.flot-k-knopki-v12 > .pill { justify-content: center; min-width: 0; }
.kart-blok.off { opacity: .55; }
.mesh-znak { width: 9px; height: 9px; margin-top: 3px; flex: none; border: 2px solid var(--kl-sluzh); transform: rotate(45deg); }
.mesh-znak.shlyuz { border-color: var(--kl-mesh-shlyuz); outline: 1px solid var(--kl-mesh-shlyuz); outline-offset: 2px; } .mesh-znak.molchit { border-color: var(--critical); border-style: dashed; }
.m-tekst-ok { color: var(--ok); } .m-tekst-sred { color: var(--warn); } .m-tekst-slab { color: var(--critical); } .m-tekst-net { color: var(--muted); }
.mesh-svyaz { display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; gap: 4px 8px; align-items: center; padding: 5px 0;
  border-bottom: 1px solid var(--hair); }
.mesh-svyaz > :last-child { grid-column: 2 / -1; }
.mesh-svyaz > :last-child:empty { display: none; }
.mesh-liniya { display: inline-block; width: 24px; height: 0; border-top: 3px solid var(--kl-sluzh); }
.mesh-liniya.m-ok { border-top-color: var(--kl-svyaz); } .mesh-liniya.m-sred { border-top-color: var(--warn); }
.mesh-liniya.m-slab { border-top-color: var(--critical); } .mesh-liniya.m-net { border-top-color: var(--kl-sluzh); opacity: .55; }
.mesh-liniya.odna { border-top-style: dashed; } .mesh-liniya.neust { opacity: .45; }
.mesh-leg { display: flex; align-items: center; gap: 8px; padding: 2px 0; }
/* 1.72.25 (MESH [3]): «в интернет» — своим знаком (v12: синий штрих-пунктир), не тем же зелёным, что «связь в норме». */
.mesh-liniya.m-internet { border-top: 3px dashed var(--accent); }
.mesh-liniya.m-staroe { border-top: 3px dotted var(--warn); opacity: .75; }
/* 1.72.25 (MESH/LoRa [3]): приглушённые блоки v12 — с отступами, как живые (`.set-blok`), а не впритык к рамке. */
.kh-mesh .nvv-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; }
#mesh-neyrony circle.m-vybran { stroke-width: 5; stroke: var(--nv-cy); }
#mesh-neyrony circle[data-uzel] { cursor: pointer; }
.mesh-okno-holst { flex: 1 1 auto; min-height: 0; display: flex; align-items: center; justify-content: center; padding: 56px 16px 16px; }
/* Только холст NRN — прямой потомок. Тот же класс стоит на контейнере карты Leaflet (NRL), и «все svg внутри» растягивали флажок
   подписи и слой векторов на пол-окна (П6 1.72.11, Open 09.10 22:52). */
.mesh-okno-holst > svg { width: 100%; height: 100%; }
#mesh-vybran { text-transform: none; }   /* имя узла как есть (n02), не N02 — Cowork 05.10 00:46 п. 3 */
@media (max-width: 1500px) { .kh-mesh { grid-template-columns: 270px minmax(0, 1fr) 290px; } }

/* ═══ «ДОСТУП» v8 (этап 5, 05.10.2026): люди и роли · кто что видит · PIN и журнал; ниже — терминалы, компании, токены ═══ */
.kh-dost { padding: 12px 14px 12px 14px; display: flex; flex-direction: column; gap: 12px; }
.kh-dost > * { flex-shrink: 0; }
.dost-verh { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, .9fr); gap: 12px; align-items: start; }
.dost-sprava { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.dost-blok { padding: 12px 14px; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.dost-blok .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.dost-roli { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0; border: 1px solid var(--nv-line); margin: 4px 0 6px; }
.dost-rol.off { opacity: .45; }
/* «Доступ» по референсу v12 (1.73.0, этап 5): верхний ряд — по месту (списки листаются внутри), нижний — вкладками. */
.dost-verh > .panel, .dost-verh > .dost-sprava { max-height: 560px; }
.dost-verh > .panel { overflow-y: auto; overscroll-behavior: contain; }
.dost-chel { display: grid; grid-template-columns: 32px minmax(0, 1fr) minmax(0, .9fr) 34px; gap: 8px; align-items: center;
  padding: 6px 0; border-bottom: 1px solid var(--hair); font-size: var(--t-sm); }
.dost-chel-golova { border-bottom: 1px solid var(--nv-line); padding: 2px 0; text-transform: uppercase; letter-spacing: .06em; }
.dost-inic { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; font: 600 11px var(--nv-mono, monospace);
  border: 1.5px solid var(--accent); color: var(--accent); }
.dost-chel-imya b { margin-right: 6px; }
.dost-chel-imya .badge { font-size: var(--t-xs); }
.dost-mesta { display: block; }
.dost-menyu { position: relative; }
.dost-menyu > summary { list-style: none; cursor: pointer; text-align: center; }
.dost-menyu > summary::-webkit-details-marker { display: none; }
.dost-menyu-spisok { position: absolute; right: 0; top: 100%; z-index: 5; display: flex; flex-direction: column; gap: 4px;
  padding: 8px; background: var(--surface); border: 1px solid var(--border); min-width: 170px; }
.dost-znak { display: inline-block; width: 10px; height: 10px; margin-right: 5px; vertical-align: -1px; border-radius: 50%; }
.dost-znak.da { border: 2px solid var(--ok); background: radial-gradient(circle, var(--ok) 30%, transparent 32%); }
.dost-znak.pin { border: 2px solid var(--warn); border-radius: 2px; }
.dost-znak.net { height: 0; border-top: 2px solid var(--muted); border-radius: 0; vertical-align: 3px; }
.dost-pin-krug-ryad { display: flex; gap: 12px; align-items: center; }
.dost-pin-svod { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
#dost-zhurnal-mest.off { opacity: .5; }
.dost-niz { padding: 10px 14px; display: flex; flex-direction: column; gap: 10px; }
.dost-niz-vkladki { display: flex; gap: 6px; flex-wrap: wrap; }
.dost-niz-vkladki [aria-selected='true'] { border-color: var(--nv-cy); color: var(--nv-cy); box-shadow: inset 0 -2px 0 var(--nv-cy); }
.dost-tokeny-golova { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; }
.dost-tokeny-znachki { display: flex; flex-wrap: wrap; gap: 10px 14px; padding: 4px 12px 10px; }
.dost-token-z { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.dost-token-ikon { width: 22px; height: 22px; border: 1.5px solid var(--accent); border-radius: 3px;
  background: linear-gradient(var(--accent), var(--accent)) center 60% / 8px 2px no-repeat; }
.dost-rol { padding: 8px 10px; display: flex; flex-direction: column; border-left: 1px solid var(--nv-line); }
.dost-rol:first-child { border-left: none; }
.dost-rol b { font: 600 var(--t-xl) var(--nv-mono); } .dost-rol span { font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
/* строка человека в узкой колонке: имя, роль и вход — сверху, кнопки — строкой ниже */
.dost-lyudi .row-grid { grid-template-columns: minmax(0, 1fr) auto auto !important; }
.dost-lyudi .row-grid > :last-child { grid-column: 1 / -1; flex-wrap: wrap; padding-top: 0; }
.dost-mat { display: grid; grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr)); gap: 6px; align-items: center; padding: 5px 0;
  border-bottom: 1px solid var(--hair); }
.dost-mat-head { font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .06em; color: var(--muted); text-transform: uppercase; }
.dost-mat-head .ya { color: var(--nv-cy); }
.dost-ya { font-size: var(--t-xs); } .dost-ya.da { color: var(--ok); } .dost-ya.net { color: var(--muted); } .dost-ya.pin { color: var(--warn); }
/* Журнал в правой колонке (Н-159, 1.73.0): запись — ОДНОЙ строкой (время · кто · что), прокрутка — своя, внутри панели.
   Было `1fr` на всё: запись шла в три строки, 50 записей растягивали верхний ряд на тысячи точек, и блоки под ним
   («Мои терминалы и телефоны», «Компании», «Телефоны и токены») владелец не находил. */
.dost-sprava .row-grid { grid-template-columns: 122px minmax(0, .7fr) minmax(0, 1.6fr) !important; gap: 6px; }
.dost-sprava .row-grid > .cell { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-top: 3px; padding-bottom: 3px; }
/* Свёрнут (слово Open 03:34Z) — видны первые пять записей, «Ещё» спрятано. Развёрнут — высота журнала ПО МЕСТУ в сетке,
   а не числом (сверка Cowork 03:19Z): правая колонка тянется на высоту ряда, который задают «Люди и роли» и матрица,
   список забирает остаток (`height: 0` + `flex: 1` — своё содержимое высоту ряда не растит) и листается внутри. */
.dost-sprava { align-self: stretch; }
.dost-zhurnal.svernut #audit-rows [data-audit]:nth-child(n+6), .dost-zhurnal.svernut .audit-niz { display: none; }
.dost-zhurnal:not(.svernut) { flex: 1 1 0; min-height: 0; }
.dost-zhurnal:not(.svernut) #audit-rows { flex: 1 1 0; height: 0; min-height: 140px; overflow-y: auto; overscroll-behavior: contain; }
@media (max-width: 1500px) {
  .dost-verh { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .dost-sprava { grid-column: 1 / -1; }
}

/* ═══ «НАСТРОЙКИ» v8 (этап 5, 05.10.2026): разделы колонками; порядок разметки прежний (заморожен проверкой) ═══ */
.kh-nastr { padding: 12px 14px 20px 14px; column-count: 3; column-gap: 12px; }
.kh-nastr > .section { break-inside: avoid; display: flex; margin: 0 0 12px; }
.kh-nastr .section-head .dsp { font: 600 var(--t-sm) var(--nv-caps) !important; letter-spacing: .06em !important;
  text-transform: uppercase; color: var(--nv-cy); }
.kh-nastr .kv { flex-wrap: wrap; }
@media (max-width: 1500px) { .kh-nastr { column-count: 2; } }

/* ═══ «КАРТА В ОКНЕ» v8 (этап 5, 05.10.2026; v11 «отдельное окно · ТВ, проектор») ═══ */
.map-window { position: relative; height: 100dvh; display: flex; flex-direction: column; background: var(--nv-bg); }
.mapw-karta { flex: 1 1 auto; min-height: 0; }
.map-window .map-host { height: calc(100dvh - 76px); }
.mapw-poloska { position: absolute; top: 12px; left: 64px; z-index: 1000; display: flex; gap: 12px; align-items: center;
  padding: 8px 12px; border: 1px solid var(--nv-cy); background: var(--nv-bar); }
.mapw-poloska .title { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; color: var(--nv-cy); }

/* ═══ ВХОД и окна (в т.ч. «Выбрать терминал») — v8 (этап 5, 05.10.2026): шрифт и цвета набора, разметка прежняя ═══ */
.login-wrap { background: var(--nv-bg); }
.login-wrap .login-brand { font: 600 var(--t-xl) var(--nv-font); letter-spacing: 0; }   /* как бренд в шапке пульта */
.login-card { border-color: var(--nv-line); background: var(--nv-bar); }
.login-card .cap { font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.login-card button[type="submit"] { font-family: var(--nv-caps); text-transform: uppercase; letter-spacing: .06em; }
.modal { border: 1px solid var(--nv-line); background: var(--nv-bar); box-shadow: 0 0 0 1px var(--nv-bg), 0 18px 48px rgba(0, 0, 0, .45); }
.modal .dsp { font-family: var(--nv-caps); letter-spacing: .06em; color: var(--nv-cy); }   /* без text-transform: имена терминалов в окне — как есть */
.modal .pick-item[aria-selected="true"], .modal .pick-item.on { box-shadow: inset 3px 0 0 var(--nv-cy); }
.modal .cta { font-family: var(--nv-caps); text-transform: uppercase; letter-spacing: .06em; }
/* Имя устройства без hostname — ПОЛНЫЙ MAC (слово Open 05.10): в списке «Без места» и в паспорте имя не режется многоточием, а переносится. */
.set-ustr-imya > div:first-child { white-space: normal !important; overflow: visible !important; text-overflow: clip !important; overflow-wrap: anywhere; }
.set-pasport-imya { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }

/* ═══ КАРТА «КЫРГЫЗСТАН · МИР» (05.10.2026, П6 Open; оригинал — v12 kh_z.py) ═══
   Холст SVG по Natural Earth, без тайлов. Все цвета — токены темы: «Ночь / День» и прочие темы — без своих правил. */
.kz-masshtab { display: flex; gap: 4px; flex: none; }
.kz-host { position: relative; overflow: hidden; background: var(--nv-bg); }
.kz-svg { display: block; width: 100%; height: 100%; }
.kz-fon { fill: var(--nv-bg); }
/* Контраст (сверка Cowork 16:20 п. 2): суша отделена от моря и фона в обеих темах, границы — сплошнее. */
.kz-sfera { fill: color-mix(in srgb, var(--nv-bl) 10%, var(--nv-bg)); stroke: var(--nv-cy); stroke-opacity: .35; }
.kz-setka { fill: none; stroke: var(--nv-grid); stroke-width: .7; }
.kz-susha { fill: color-mix(in srgb, var(--nv-cy) 12%, var(--nv-bg)); stroke: var(--nv-bl); stroke-opacity: .5; stroke-width: .6; }
.kz-susha-mir { fill: color-mix(in srgb, var(--nv-cy) 24%, var(--nv-bg)); stroke: var(--nv-bl); stroke-opacity: .9; stroke-width: .7; }
.kz-granicy { fill: none; stroke: var(--nv-bl); stroke-opacity: .9; stroke-width: 1.2; stroke-dasharray: 5 3; }
.kz-granicy-mir { fill: none; stroke: var(--nv-bl); stroke-opacity: .7; stroke-width: .6; }
.kz-strana-svet { fill: none; stroke: var(--nv-cy); stroke-opacity: .25; stroke-width: 5; stroke-linejoin: round; }
.kz-strana { fill: var(--nv-cy); fill-opacity: .1; stroke: var(--nv-cy); stroke-width: 1.6; stroke-linejoin: round; }
.kz-strana-mir { fill-opacity: .6; stroke-width: 1.2; }
.kz-skryta { display: none; }
/* Выноска кольца (п. 1): рамка в цвет панели, место — акцентом, счёт — приглушённо, линия к кольцу. */
.kz-vynoska { cursor: pointer; }
.kz-vynoska-liniya { fill: none; stroke: var(--nv-cy); stroke-opacity: .7; stroke-width: 1; }
.kz-vynoska-ramka { fill: var(--nv-bar); stroke: var(--nv-cy); stroke-width: 1; }
.kz-svg .kz-vynoska-z { fill: var(--nv-cy); font-weight: 600; stroke-width: 0; }
.kz-svg .kz-vynoska-s { fill: var(--nv-mut); font-family: var(--nv-mono); stroke-width: 0; }
.kz-ozera path { fill: var(--nv-bl); fill-opacity: .18; stroke: var(--nv-bl); stroke-opacity: .8; stroke-width: .9; }
.kz-svg text { font-family: var(--nv-font); paint-order: stroke; stroke: var(--nv-bg); stroke-width: 3.5px; stroke-linejoin: round; }
.kz-setka-t { fill: var(--nv-dim); font-family: var(--nv-mono) !important; }
.kz-t-strana { fill: var(--nv-cy); font-weight: 600; letter-spacing: .06em; }
.kz-t-sosed { fill: var(--nv-mut); font-weight: 600; letter-spacing: .06em; }
.kz-t-kray { fill: var(--nv-mut); font-style: italic; }
.kz-t-voda { fill: var(--nv-bl); font-style: italic; }
.kz-t-stolica { fill: var(--nv-txt); font-weight: 600; }
.kz-t-gorod { fill: var(--nv-mut); font-weight: 500; }
.kz-t-chuzhoy { fill: var(--nv-dim); font-weight: 500; }
.kz-t-vershina { fill: var(--nv-mut); font-family: var(--nv-mono) !important; }
.kz-stolica { fill: var(--nv-bg); stroke: var(--nv-txt); stroke-width: 1.4; }
.kz-gorod { fill: var(--nv-bg); stroke: var(--nv-mut); stroke-width: 1.3; }
.kz-vershina path { fill: var(--nv-mut); }
.kz-tochka, .kz-gruppa { cursor: pointer; outline: none; }
.kz-tochka circle { stroke: var(--nv-bg); stroke-width: 2; }
.kz-tochka:hover circle, .kz-tochka:focus-visible circle { stroke: var(--nv-txt); }
.kz-gruppa-fon { fill: var(--nv-bg); fill-opacity: .88; stroke: var(--nv-cy); stroke-opacity: .35; }
.kz-gruppa:hover .kz-gruppa-fon, .kz-gruppa:focus-visible .kz-gruppa-fon { stroke-opacity: 1; }
.kz-dolya { fill: none; stroke-width: 4.2; }
.kz-dolya-tikho { stroke-dasharray: 2.6 2.2; }
.kz-gruppa-n { fill: var(--nv-txt); font-family: var(--nv-mono) !important; font-weight: 600; stroke-width: 0 !important; }
.kz-polosa { position: absolute; top: 10px; left: 12px; display: flex; gap: 12px; align-items: baseline; padding: 6px 10px;
  border: 1px solid var(--nv-line); background: var(--nv-bar); font-size: var(--t-xs); pointer-events: none; }
.kz-polosa b { font: 500 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
/* Линейка — справа внизу, над подписями долгот: слева край занят подписями широт (сверка 16:20 п. 4). */
.kz-lineyka { position: absolute; right: 14px; bottom: 30px; display: flex; gap: 8px; align-items: center;
  font: var(--t-xs) var(--nv-mono); pointer-events: none; }
.kz-lineyka-svg path { fill: none; stroke: var(--nv-txt); stroke-width: 1.4; }
.kz-tip { position: absolute; z-index: 5; max-width: 260px; padding: 6px 9px; pointer-events: none;
  background: var(--surface); color: var(--ink); border: 1px solid var(--border); font-size: var(--t-xs); }

/* ═══ ШАПКА КАРТЫ — с переносом строки (Н-153, 1.72.0): «Мои терминалы» и LoRa. На узком окне кнопки масштаба
   и «Открыть картой в отдельном окне» уходят на следующую строку, а не за край колонки. ═══ */
.karta-golova { padding: 10px 16px; display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center;
  border-bottom: 1px solid var(--border); min-width: 0; }
.karta-golova > .muted { flex: 1 1 180px; min-width: 0; }
.karta-golova .kz-masshtab { flex-wrap: wrap; }
/* 1.72.5: значки у кнопок, панель масштаба «+ ×1 − ⊕», «Во весь экран» (v12). */
.s-znachkom { display: inline-flex; align-items: center; gap: 6px; }
.pill.ikon { display: inline-flex; align-items: center; justify-content: center; padding: 4px 6px; }
.karta-zum { display: flex; align-items: center; gap: 4px; flex: none; }
.karta-zum-k { min-width: 40px; text-align: center; font-size: var(--t-xs); color: var(--nv-cy); }
#flot-karta:fullscreen { background: var(--nv-bg); width: 100vw; height: 100vh; display: flex; flex-direction: column; }
/* 1.72.9 п. 1.5 (i): во весь экран — режим документа, а рамку растягивает класс (ставится из ctx на каждой отрисовке): пересборка
   #app режим не снимает, тик идёт. Поверх шапки и рельсов. */
#flot-karta.ves-ekran { position: fixed; inset: 0; z-index: 5000; margin: 0; background: var(--nv-bg);
  display: flex; flex-direction: column; }
.flot-schet { gap: 6px; }

/* ═══ ВКЛАДКА LoRa (1.72.0) ═══ */
.kz-tochka rect { stroke: var(--nv-bg); stroke-width: 2; }
.kz-tochka:hover rect, .kz-tochka:focus-visible rect { stroke: var(--nv-txt); }
.sl-kvadrat { border: 2px solid; box-sizing: border-box; opacity: .95; cursor: pointer; }
/* Фигуры устройств (1.72.22, ui/figury.mjs): SVG с currentColor; у шлюза своя фигура вместо залитого квадрата. */
.sl-kvadrat.sl-fig { border: 0; background: none !important; opacity: 1; }
.sl-fig svg, .sl-fig-nalozhenie svg { display: block; overflow: visible; filter: drop-shadow(0 0 2px rgba(0, 0, 0, .55)); }
.sl-fig-nalozhenie { pointer-events: none; background: none; border: 0; }
path.sl-staroe { stroke-dasharray: 3 2.4; stroke-opacity: .6; fill-opacity: .5; }
/* Связи MESH на карте (1.72.2) — те же классы и цвета, что у «нейронов» (screens/mesh.mjs, STIL); CSS перебивает stroke Leaflet. */
.sl-mesh-liniya { fill: none; stroke-linecap: round; opacity: .9; }
/* M1: веер узлов без места у шлюза (ui/veer_mesh.mjs) — линия пунктиром: место не настоящее. */
.sl-veer line.sl-mesh-liniya { stroke-dasharray: 5 4; }
.sl-veer-romb { fill: var(--surface); stroke-width: 2; }
.sl-veer-romb.m-ok { stroke: var(--kl-svyaz); } .sl-veer-romb.m-sred { stroke: var(--warn); }
.sl-veer-romb.m-slab { stroke: var(--critical); } .sl-veer-romb.m-net { stroke: var(--critical); }
.sl-veer-imya { font-size: var(--t-sm); font-weight: 600; fill: var(--ink); paint-order: stroke; stroke: var(--surface); stroke-width: 3px; }
.sl-veer-pod { font-size: var(--t-xs); fill: var(--muted); paint-order: stroke; stroke: var(--surface); stroke-width: 3px; }
.sl-mesh-liniya.m-ok { stroke: var(--kl-svyaz); } .sl-mesh-liniya.m-sred { stroke: var(--warn); }
.sl-mesh-liniya.m-slab { stroke: var(--critical); } .sl-mesh-liniya.m-net { stroke: var(--kl-sluzh); opacity: .55; }
.sl-mesh-liniya.m-odna { stroke-dasharray: 6 6; } .sl-mesh-liniya.m-neust { opacity: .45; }
/* Курсор и компас карты (1.73.0, референс v12): панель темы, моноширинные числа; компас мышь не ловит. */
.sl-kursor { background: var(--surface); border: 1px solid var(--border); padding: 4px 8px; min-width: 150px;
  font: 500 11px/1.4 var(--nv-mono, 'JetBrains Mono', monospace); color: var(--ink); text-align: right; }
.sl-kursor-zag { font: 600 10px var(--nv-caps, inherit); letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.sl-kursor-mesto:empty { display: none; }
.sl-kompas { pointer-events: none; }
.sl-kompas circle { fill: var(--surface); stroke: var(--accent); stroke-width: 1.2; opacity: .9; }
.sl-kompas path { fill: var(--accent); }
.sl-kompas text { fill: var(--muted); font: 600 8px var(--nv-mono, monospace); }
/* Значок терминала (1.72.4, референс v12): кольцо цветом состояния, точка в центре, ореол тем же цветом (currentColor —
   его ставит map.mjs); выбранный без связи — красный круг с крестом. */
.sl-kolco { filter: drop-shadow(0 0 4px currentColor); }
.sl-kolco-tochka { pointer-events: none; background: none; border: 0; }
/* Поток данных в небо (1.72.5, вариант к ряби): пунктир бежит вверх; «уменьшить движение» — стоит. */
.sl-potok { pointer-events: none; background: none; border: 0; }
/* 1.72.9 п. 0: бег пунктира — transform у корневой svg-ленты в окне-коробке (композитор), а не stroke-dashoffset у path
   (перерисовка на главном потоке каждый кадр). Окно — y 6…44 значка; лента на период (6 px) длиннее и сдвигается на период. */
.sl-potok .potok-z { position: relative; width: 22px; height: 46px; }
.sl-potok .potok-strelka { position: absolute; left: 0; top: 0; overflow: visible; }
.sl-potok .potok-okno { position: absolute; left: 0; top: 6px; width: 22px; height: 38px; overflow: hidden; }
/* 1.72.9 п. 0, доводка 09.10 (Cowork 03:38 п. 5): лента — HTML-div (цель анимации — не элемент SVG: Chrome такие на композитор не отдаёт), пунктир —
   svg внутри неё; рисунок, размеры и скорость те же. */
.sl-potok .potok-lenta { display: block; width: 22px; height: 44px; will-change: transform; animation: sl-potok-beg 0.6s linear infinite; }
.sl-potok .potok-lenta-svg { display: block; overflow: visible; }
.sl-potok .potok-l { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-dasharray: 2 4; stroke-linecap: round; }
.sl-potok .potok-s { fill: none; stroke: currentColor; stroke-width: 1.4; }
@keyframes sl-potok-beg { from { transform: translateY(0); } to { transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .sl-potok .potok-lenta { animation: none; } }
/* Значки состояния (1.72.5, ui/znaki.mjs): одни на карте, в «Обозначении», карточке и строке над картой. */
.znak { flex: none; overflow: visible; }
.znak .z-kolco { fill: none; stroke-width: 2; }
.znak .z-punktir { stroke-dasharray: 2.6 2; }
.znak .z-centr { stroke: none; }
.znak.z-ok .z-kolco { stroke: var(--ok); } .znak.z-ok .z-centr { fill: var(--ok); }
.znak.z-warn .z-kolco { stroke: var(--warn); } .znak.z-warn .z-centr { fill: var(--warn); }
.znak.z-silent .z-kolco { stroke: var(--muted); }
/* «Обозначение на карте» при 3D «Сетке»: норма — янтарь терминала #ffb347 (как знак на сетке), замечание — кольцо и «!». */
.znak.z-setka.z-ok .z-kolco { stroke: #ffb347; } .znak.z-setka.z-ok .z-centr { fill: #ffb347; }
.obozn-svg.zam-setka .zam-k { stroke: var(--warn); stroke-width: 2; } .obozn-svg.zam-setka .zam-v { stroke: var(--warn); stroke-width: 2; stroke-linecap: round; }
.obozn-svg.zam-setka .zam-t { fill: var(--warn); }
.znak.z-down .z-zaliv { fill: color-mix(in srgb, var(--critical) 22%, transparent); stroke: var(--critical); stroke-width: 1.8; }
.znak.z-down .z-krest { stroke: var(--critical); stroke-width: 2; stroke-linecap: round; fill: none; }
.sl-krest { background: none; border: 0; pointer-events: none; }
.sl-krest svg { overflow: visible; filter: drop-shadow(0 0 5px var(--critical)); }
.sl-krest circle { fill: none; stroke: var(--critical); stroke-width: 2; }
.sl-krest path { stroke: var(--critical); stroke-width: 2.5; stroke-linecap: round; }
/* Н-331: кольцо выбора у значка выбранного терминала со связью (без связи — крест выше). */
.sl-vybran { background: none; border: 0; pointer-events: none; }
.sl-vybran svg { overflow: visible; }
.sl-vybran circle { fill: none; stroke: var(--accent); stroke-width: 2.5; }
/* Имя терминала рамкой у точки (1.73.0, референс v12). Цвет рамки = цвет уровня (ставит map.mjs), фон — панель темы. */
.sl-ramka-uzel { background: none; border: 0; }
.sl-ramka { position: absolute; left: 12px; top: -9px; display: inline-block; white-space: normal; width: max-content; max-width: 26ch; font: 600 11px/1.3 var(--nv-mono, 'JetBrains Mono', monospace);
  padding: 1px 6px; border: 1px solid currentColor; background: var(--surface); pointer-events: none; }
.sl-ramka[hidden] { display: none; }
/* Длинное имя у точки — второй строкой, многоточие только после второй; рамку меряет ui/ramki.mjs по offsetWidth/offsetHeight. */
.sl-ramka-imya { overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
/* Н-328 (1.72.32): один значок точки — имя, «+N» и строка состава под именем, как v12 («LoRa и MESH · Starlink»). */
.sl-ramka.sl-ramka-tochka { display: inline-grid; grid-template-columns: repeat(3, auto); column-gap: 6px; align-items: baseline; top: -12px; }
.sl-ramka.sl-ramka-tochka[hidden] { display: none; }
.sl-ramka-tochka .sl-plus { font-weight: 700; }
/* Площадка лагеря на «Моих терминалах» (karta/ploshchadka.mjs): знаки — своей панелью Leaflet поверх точек; подпись площадки — строками
   без обрезки (тревога и замечание — цветом уровня); у нормы рамки нет, у тревоги и замечания — есть; линия к подписи в столбике. */
.leaflet-slPloshchadki-pane .sl-ploshchadki { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; z-index: auto; }
.sl-ramka.sl-ramka-pl { display: inline-flex; flex-direction: column; max-width: 34ch; }
.sl-ramka.sl-ramka-pl[hidden] { display: none; }
.sl-ramka.sl-ramka-pl[data-uroven="ok"], .sl-ramka.sl-ramka-pl[data-uroven="silent"] { border-color: transparent; }
.sl-ramka-pl .sl-pl-str { color: var(--ink); white-space: normal; overflow-wrap: break-word; }
.sl-ramka-pl .sl-pl-str:first-child { font-weight: 700; }
.sl-ramka-pl .sl-pl-problema { color: var(--critical); }
.sl-ramka-pl .sl-pl-zamechanie { color: var(--warn); }
.set-potoki.sl-ploshchadki .sl-pl-vynoska { stroke: var(--muted); stroke-width: 1; stroke-opacity: .8; }
.set-potoki .m12-schet-trevog circle { fill: var(--critical); stroke: var(--bg); stroke-width: 1.5; }
.set-potoki .m12-schet-trevog text { fill: #FFFFFF; font: 700 9px var(--font-mono); }
.set-potoki circle.m12-cel-yarusa { fill: transparent; stroke: none; pointer-events: auto; cursor: pointer; }
.set-potoki .m12-pl-problema { fill: var(--critical); } .set-potoki .m12-pl-zamechanie { fill: var(--warn); }
/* Теснота у знака площадки (E4): тревога и замечание в тесноте — выноской цвета уровня; подпись — тем же цветом. */
.set-potoki .m12-vynoska { stroke-opacity: .85; } .set-potoki .m12-vyn-problema { stroke: var(--critical); } .set-potoki .m12-vyn-zamechanie { stroke: var(--warn); }
.set-potoki text.m12-vynoska-t[data-vynoska="problema"] { fill: var(--critical); } .set-potoki text.m12-vynoska-t[data-vynoska="zamechanie"] { fill: var(--warn); }
.set-potoki.sl-ploshchadki .sl-pl-vynoska.m12-vyn-problema { stroke: var(--critical); } .set-potoki.sl-ploshchadki .sl-pl-vynoska.m12-vyn-zamechanie { stroke: var(--warn); }
/* «Мои терминалы»: знак в тесноте у площадки — мельче (5/7, как у «Карты сети»). */
.sl-dot[data-tesno] { transform-box: fill-box; transform-origin: center; transform: scale(.7); } .sl-fig-nalozhenie[data-tesno] svg { transform: scale(.7); }
.set-potoki.sl-ploshchadki [data-ustr], .set-potoki.sl-ploshchadki .m12-esche { pointer-events: auto; cursor: pointer; }
/* Ряд значков состояния в плашке площадки (средний масштаб): буква вида цветом типа, тревога — «✕» / «!» цветом уровня. */
.sl-ramka-pl .sl-pl-znaki { display: flex; gap: 4px; flex-wrap: wrap; }
.sl-ramka-pl .sl-pl-zn { padding: 0 4px; border: 1px solid currentColor; border-radius: 3px; font-weight: 700; }
.sl-ramka-pl .sl-pl-zn.m12-tip-tarelka { color: var(--m12-tip-tarelka); } .sl-ramka-pl .sl-pl-zn.m12-tip-router { color: var(--m12-tip-router); }
.sl-ramka-pl .sl-pl-zn.m12-tip-mesh { color: var(--m12-tip-mesh); } .sl-ramka-pl .sl-pl-zn.m12-tip-lora { color: var(--m12-tip-lora); }
.sl-ramka-pl .sl-pl-zn.sl-pl-problema { color: var(--critical); } .sl-ramka-pl .sl-pl-zn.sl-pl-zamechanie { color: var(--warn); }
.sl-ramka-tochka .sl-sostav { grid-column: 1 / -1; font: 400 10px/1.3 var(--nv-mono, 'JetBrains Mono', monospace); color: var(--muted); }
/* Строка площадки у терминала (RP5, роутер) — второй строкой под именем. */
.sl-ramka .sl-ploshchadka { display: block; font: 400 10px/1.3 var(--nv-mono, 'JetBrains Mono', monospace); color: var(--muted); }
/* Н-328 п. 4: зона трекера без своего места у шлюза — круг в метрах пунктиром (цвет — худший из трекеров зоны, ставит map.mjs). */
path.sl-zona-u-shlyuza { stroke-dasharray: 4 4; }
/* Н-328 этап 2: общий значок слипшихся — круг в среднем месте своих, накрывает их места; число — сколько устройств; беда — «!». */
.sl-slip { background: none; border: 0; }
.sl-slip-krug { box-sizing: border-box; border-radius: 50%; border: 2px solid currentColor; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, currentColor 16%, var(--surface)); position: relative; }
.sl-slip-krug b { font: 700 12px/1 var(--nv-mono, 'JetBrains Mono', monospace); color: var(--ink); }
.sl-beda { position: absolute; top: -6px; right: -6px; width: 14px; height: 14px; border-radius: 50%; background: var(--critical); color: #fff;
  font: 700 10px/14px var(--nv-mono, 'JetBrains Mono', monospace); text-align: center; font-style: normal; }
.sl-ramka .sl-beda { position: static; display: inline-block; margin-left: 4px; }
/* Н-328 п. 4: след трекера с GPS — тонкой линией по местам, что пульт видел. */
path.sl-sled-trekera { stroke: var(--accent, #7aa2c8); stroke-opacity: .7; stroke-dasharray: 2 4; stroke-linecap: round; fill: none; }
/* Куда шёл пропавший: стрелка последнего шага — цветом тревоги, без фона значка Leaflet. */
.sl-strelka-puti { background: none; border: 0; color: var(--critical); font-size: var(--t-lg); line-height: 18px; text-align: center; }
/* Мачта (1.72.22, ui/figury.mjs): ось — тонкой линией вверх от основания; подписи ярусов — столбиком слева (трекер — справа). */
.sl-machta-os-uzel, .sl-machta-podpis-uzel { pointer-events: none; background: none; border: 0; }
.sl-machta-os { position: absolute; bottom: 0; left: -.5px; width: 0; border-left: 1px solid var(--muted); opacity: .7; }
.sl-machta-podpis { position: absolute; left: 0; top: 0; transform: translate(calc(-100% - 16px), -50%); display: flex; flex-direction: column;
  align-items: flex-end; white-space: nowrap; padding: 2px 6px; background: var(--surface); border: 1px solid var(--border); pointer-events: none;
  font: 600 11px/1.3 var(--nv-mono, 'JetBrains Mono', monospace); color: var(--ink); }
.sl-machta-podpis span { font-weight: 400; opacity: .85; color: var(--muted); }
/* «Сеть лагеря» у точки (ui/set_lagerya.mjs, v12 data-lyr="network"): веер сети и выноска рамкой слева с линией к точке. */
.sl-setl { position: absolute; left: 0; top: 0; width: 0; height: 0; pointer-events: none; }
.sl-setl-svg { position: absolute; overflow: visible; }
.sl-setl-liniya { stroke: var(--nv-cy); stroke-width: 1; fill: none; opacity: .8; }
.sl-setl-svyaz { stroke: var(--nv-cy); stroke-width: .8; stroke-dasharray: 1.5 3; fill: none; opacity: .45; }
.sl-setl-sluzh { fill: color-mix(in srgb, var(--nv-cy) 25%, var(--bg)); stroke: var(--nv-cy); stroke-width: 1.2; pointer-events: auto; }
.sl-setl-sluzh-l { stroke: var(--nv-cy); stroke-width: 1.2; }
.sl-setl-ustr { stroke: var(--bg); stroke-width: 1; pointer-events: auto; }
.sl-setl-cel { fill: transparent; stroke: none; pointer-events: auto; cursor: pointer; }
.sl-setl-ustr.kl-sotr { fill: var(--kl-sotr); } .sl-setl-ustr.kl-klient { fill: var(--kl-klient); } .sl-setl-ustr.kl-nizk { fill: var(--kl-nizk); }
.sl-setl-ustr.kl-intr { fill: var(--kl-intr); } .sl-setl-ustr.kl-prochie { fill: none; stroke: var(--kl-prochie); stroke-width: 1.2; }
.sl-setl-vynoska { position: absolute; display: flex; flex-direction: column; gap: 1px; white-space: nowrap; pointer-events: auto; cursor: pointer;
  padding: 3px 9px 4px; border: 1px solid color-mix(in srgb, var(--nv-cy) 55%, transparent); background: color-mix(in srgb, var(--nv-bar) 88%, transparent); }
.sl-setl-vynoska b { font-weight: 600; font-size: var(--t-sm); line-height: 1.3; color: var(--nv-cy); }
.sl-setl-vynoska span { font-size: var(--t-xs); line-height: 1.3; color: var(--muted); }
.sl-setl-vynoska:hover, .sl-setl-vynoska:focus-visible { border-color: var(--nv-cy); outline: none; }
.sl-setl-vynoska.ustarel { border-color: color-mix(in srgb, var(--warn) 55%, transparent); } .sl-setl-vynoska.ustarel b { color: var(--warn); }
.sl-machta-podpis.sbok { transform: translate(14px, -50%); align-items: flex-start; }
/* Н-294 (1.72.25): у основания мачты — «место · ±N м» под значком основания; точка — настоящее место. */
.sl-machta-mesto-uzel { pointer-events: none; background: none; border: 0; }
.sl-machta-mesto { position: absolute; left: 0; top: 13px; transform: translateX(-50%); display: inline-flex; align-items: center; gap: 4px;
  white-space: nowrap; padding: 0 5px; background: var(--surface); border: 1px solid var(--border); pointer-events: none;
  font: 400 10px/1.4 var(--nv-mono, 'JetBrains Mono', monospace); color: var(--muted); }
.sl-machta-mesto i { width: 5px; height: 5px; border-radius: 50%; background: var(--ink); flex: none; }
/* Узел MESH в веере (ui/figury.mjs `rezhim: 'veer'`): линия от значка к настоящему месту и метка на нём — как .v12-k-mestu. */
.sl-k-mestu-uzel { pointer-events: none; background: none; border: 0; }
.sl-k-mestu { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.sl-k-mestu path { stroke: var(--ink); stroke-opacity: .55; stroke-width: .8; fill: none; }
.sl-k-mestu circle { fill: var(--ink); fill-opacity: .7; }
/* Круг со сдвигом значка (Н-294, ui/map.mjs krugZnachkom): path круга Leaflet в своём svg, рамки значка нет. */
.sl-krug-uzel { background: none; border: 0; }
.sl-krug-uzel svg { display: block; overflow: visible; }
/* Линия LoRa трекер → шлюз (1.72.22, макет п. 3): точками; подпись на линии. */
path.sl-mesh-liniya.m-lora { stroke-dasharray: 1 6; stroke-linecap: round; }
.sl-liniya-podpis-uzel { pointer-events: none; background: none; border: 0; }
.sl-liniya-podpis[hidden] { display: none; }
.sl-liniya-podpis { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); white-space: nowrap; padding: 1px 6px;
  background: var(--surface); border: 1px solid var(--border); color: var(--muted); pointer-events: none;
  font: 400 11px/1.3 var(--nv-mono, 'JetBrains Mono', monospace); }
/* Ночного фильтра у своей подложки больше нет (1.73.0): с 1.72.1 по 1.72.2 тёмную тему библиотеки вытягивали
   `filter: brightness(1.8) contrast(1.3)`; теперь палитра своя и выводится из токенов темы (`--karta-*` ниже). */
/* Рельеф ночью (1.72.2): те же плитки, что днём, но прозрачнее — на тёмной подложке тени тяжелели (кадр kadr-tyanshan-noch). */
:root[data-theme='dark'] .sl-relef, :root[data-theme='tactical_amber'] .sl-relef,
:root[data-theme='phosphor'] .sl-relef, :root[data-theme='signal'] .sl-relef {
  opacity: .55;
}
/* Своя подложка в палитре референса v12 (1.73.0, ui/podlozhka_stil.mjs). Цвета — ИЗ ТОКЕНОВ ТЕМЫ, а не числами: у пульта
   десять тем (четыре тёмные), и карта обязана совпадать с темой, как в референсе с его акцентом. Холст библиотеки берёт
   готовый цвет — JS снимает их пробным элементом (getComputedStyle → rgb). */
:root {
  --karta-fon: color-mix(in srgb, var(--bg) 90%, var(--accent));
  --karta-voda: color-mix(in srgb, var(--accent) 20%, var(--karta-fon));
  --karta-reka: color-mix(in srgb, var(--accent) 58%, var(--karta-fon));
  --karta-lednik: color-mix(in srgb, var(--accent) 72%, var(--karta-fon));
  --karta-lednik-zalivka: color-mix(in srgb, var(--surface) 40%, transparent);
  --karta-gor40: color-mix(in srgb, var(--accent) 17%, var(--karta-fon));
  --karta-gor200: color-mix(in srgb, var(--accent) 45%, var(--karta-fon));
  --karta-gor-podpis: color-mix(in srgb, var(--muted) 85%, var(--karta-fon));
  --karta-doroga: color-mix(in srgb, var(--muted) 50%, var(--karta-fon));
  --karta-granica: color-mix(in srgb, var(--muted) 80%, var(--karta-fon));
  --karta-mesto: color-mix(in srgb, var(--ink) 75%, var(--karta-fon));
  --karta-vershina: var(--ink);
  --karta-setka: color-mix(in srgb, var(--accent) 38%, transparent);
  --karta-setka-tochki: color-mix(in srgb, var(--accent) 13%, transparent);
}
.lora-row { grid-template-columns: minmax(110px, 1.3fr) 82px 64px 72px 64px 96px 48px 72px minmax(110px, 1fr); }
.lora-tablica { min-width: 760px; }   /* шапка и строки — одна ширина (сверка 20:34 п. 1) */
.lora-row.tr { cursor: pointer; }
/* Строка ленты — текстом в строку, как была: «Передать» и отметка — в её конце, а не отдельными рядами (лента в узкой колонке). */
.lora-soob-str { flex: none; }
.lora-peredat-k { margin-left: 6px; padding: 0 6px; border: 1px solid var(--nv-cy); border-radius: 4px; background: transparent; color: var(--nv-cy); font: inherit; line-height: 1.35; cursor: pointer; }
.lora-peredano { color: var(--nv-cy); }
.lora-listok { display: flex; flex-direction: column; gap: 6px; }
.lora-listok-str { display: grid; grid-template-columns: 9em minmax(0, 1fr); gap: 8px; overflow-wrap: anywhere; }
@media print { body > *:not(dialog[open]) { display: none !important; } dialog[open] .ok12-niz, dialog[open] .ok-shapka button { display: none !important; } }
.lora-row.sel { box-shadow: inset 3px 0 0 var(--nv-cy); }
.lora-shlyuzy .flot-chip { display: flex; flex-wrap: wrap; gap: 4px 8px; width: 100%; text-align: left; }

/* --- 1.72.5 пп. 6–9 (Cowork 20:45): приборы карты и окно «Карточка терминала» ------------------------------------- */
/* Низ правой колонки (v12): компас · линейка · «Курсор». Не растягивается — карточка над ним листается сама. */
.kh-flot .set-kolonka > .pr-niz:last-child { flex-grow: 0; }
/* Н-213 (1.72.7, Cowork 19:16 п. 2): блок компаса и линейки внизу — своей высоты. Карточный блок (.flot-sprava-telo) гибкий
   уже с 1.72.5 (.set-sprava > .flot-sprava-telo, выше), карточка в нём листается сама. */
.kh-flot .set-kolonka > .pr-niz { flex: 0 0 auto; }
/* 1.72.28 (п. 5, v12 `kzfix`): одна строка без своей панели и рамки, поверх фона — компас · линейка · справа по правому краю
   «КУРСОР · имя», координаты крупно, «высота …». Под строкой — угол EN · RU · Техподдержка (отступ колонки, Н-313). */
.pr-niz { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 6px 0 0; border: none; background: none;
  min-width: 0; }
.pr-niz .pr-kompas { flex: none; overflow: visible; }
.pr-ks-kolco { fill: none; stroke: color-mix(in srgb, var(--nv-cy) 55%, transparent); stroke-width: 1.2; }
.pr-ks-vnutr { fill: none; stroke: color-mix(in srgb, var(--accent) 50%, transparent); stroke-width: 1; }
.pr-ks-shtrih { stroke: color-mix(in srgb, var(--nv-cy) 80%, transparent); stroke-width: 1; }
.pr-ks-strelka { fill: var(--nv-ok); }
.pr-ks-os { stroke: var(--nv-ok); stroke-width: 1.4; }
.sl-kompas text.pr-ks-s { fill: var(--nv-mut); font: 500 10px var(--nv-caps, sans-serif); }
.pr-lineyka { flex: none; min-width: 0; }
/* Н-311: подписи под чертой и внутри viewBox; overflow: visible — запас, если шрифт шире оценки. */
.pr-lin-svg { display: block; overflow: visible; }
.pr-lin { fill: none; stroke: var(--nv-cy); stroke-width: 1.2; }
.pr-lin:first-child { stroke-opacity: .65; }
.pr-lin-melk { stroke-width: 1; stroke-opacity: .4; }
.pr-lin-t { fill: var(--nv-mut); font-family: var(--nv-mono, monospace); }
.pr-kursor { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; text-align: right;
  font-family: var(--nv-mono, monospace); }
.pr-k-zag { font-size: var(--t-xs); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-mut); }
.pr-k-mesto { font: 500 var(--t-sm) var(--nv-mono, monospace); color: var(--nv-txt); }
/* 1.72.28 (сверка Cowork 03:57 п. 8): «высота ≈ N м» — одной строкой, без обрезки («по рельефу» — в подсказке). */
.pr-k-vys { font-size: var(--t-xs); color: var(--nv-mut); white-space: nowrap; }
/* 1.72.29 (поток А п. 4): имя в «Курсоре» — целиком всегда. Было многоточие: длинное имя (учебное «UCHEB-REV9_STEND7») резалось
   до «UCHEB-REV9_…», а ширина блока зависела от линейки и цифр координат — то резалось, то нет. Теперь не режется никогда:
   не влезло в строку — переносится после «Курсор ·», имя длиннее блока — переносится внутри себя. Координаты — одной строкой. */
.pr-k-zag { max-width: 100%; white-space: normal; overflow-wrap: anywhere; line-height: 1.25; }
.pr-k-imya { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
.pr-k-mesto { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pr-k-mesto:empty { display: none; }
/* Шкала высот у правого края карты: не ловит мышь, подписи на полупрозрачной подложке. */
.leaflet-control.pr-vs { pointer-events: none; margin-top: 14px; margin-right: 6px; }
.pr-vs-svg { display: block; overflow: visible; }
.pr-vs-l, .pr-vs-sh { stroke: var(--ink); stroke-width: 1.2; fill: none; opacity: .75; }
.pr-vs-t, .pr-vs-zag { fill: var(--ink); font-size: var(--t-xs); paint-order: stroke; stroke: var(--surface); stroke-width: 3px;
  stroke-linejoin: round; }
.pr-vs-zag { fill: var(--muted); }
.pr-vs-ukaz { fill: var(--accent); }
.pr-vs-ukaz-l { stroke: var(--accent); stroke-width: 1.4; }
.pr-vs-ukaz-t { fill: var(--accent); font-size: var(--t-xs); font-weight: 600; paint-order: stroke; stroke: var(--surface);
  stroke-width: 3px; stroke-linejoin: round; }
/* «Выход в мир» — правый верхний угол карты (v12 `uplink`). */
.leaflet-control.vyhod-v-mir, .vyhod-v-mir { padding: 8px 10px; background: color-mix(in srgb, var(--nv-bg) 82%, transparent);
  border: 1px solid var(--nv-line); color: var(--ink); backdrop-filter: blur(1.5px); max-width: 420px; }
.vm-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 6px;
  font-size: var(--t-xs); }
.vm-lat { color: var(--muted); white-space: nowrap; }
.vm-lat b { color: var(--accent); font-family: var(--nv-mono, monospace); }
.vm-cep { display: flex; align-items: flex-start; gap: 4px; }
.vm-y { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 56px; font-size: var(--t-xs);
  text-align: center; }
.vm-y b { font-weight: 600; white-space: nowrap; }
.vm-y i { font-style: normal; color: var(--muted); white-space: nowrap; }
.vm-i { display: grid; place-items: center; width: 28px; height: 28px; border: 1px solid var(--nv-line); color: var(--accent); }
.vm-i.s { border-color: var(--accent); }
.vm-l { flex: 1 1 18px; min-width: 14px; height: 28px; display: flex; align-items: center; }
.vm-l i { display: block; width: 100%; border-top: 1px dashed var(--accent); opacity: .7; }
/* 1.72.25 (MESH [2]): цепочка рвётся на неработающем звене — разрыв красным крестом, звенья за ним серые. */
.vm-l.vm-rvan { position: relative; justify-content: center; }
.vm-l.vm-rvan i { border-top-color: var(--critical); opacity: .5; }
.vm-l.vm-rvan b { position: absolute; color: var(--critical); font-weight: 700; background: var(--nv-bg); padding: 0 2px; line-height: 1; }
.vm-l.vm-seroe i { border-top-color: var(--muted); opacity: .45; }
.vm-y.vm-seroe b, .vm-y.vm-seroe .vm-i { color: var(--muted); opacity: .7; }
.vm-y.vm-seroe .vm-i { border-style: dashed; }
/* 1.72.25 (Н-298): связь не отвечающего узла — серым (числа из старого среза). */
.me12-staroe, .me12-staroe .mono, .me12-staroe .t-xs { color: var(--muted); }
.me12-romb.staroe { border-color: var(--kl-sluzh); border-style: dashed; color: var(--kl-sluzh); opacity: .55; }
/* Окно «Карточка терминала»: шапка, две колонки, подвал. */
/* Окно карточки — три колонки, как эталон v12 `_modal_term` (слово Open 06.10: эталон не менять). */
.ok-okno { width: min(1200px, calc(100vw - 40px)); padding: 18px 22px; gap: 12px; }
.ok-shapka { display: flex; align-items: flex-start; gap: 12px; }
.ok-imena { flex: 1 1 auto; min-width: 0; }
.ok-zag { margin: 0; font-size: var(--t-lg, 1.15rem); font-weight: 600; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.ok-pod { margin-top: 2px; }
.ok-telo { display: grid; grid-template-columns: minmax(0, 320fr) minmax(0, 470fr) minmax(0, 340fr); gap: 22px; }
.ok-kol { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.ok-cep { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: var(--t-xs); }
.ok-zveno { display: inline-flex; align-items: center; gap: 4px; padding: 3px 7px; border: 1px solid var(--nv-line);
  max-width: 100%; min-width: 0; }
.ok-zveno span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ok-zveno svg { color: var(--accent); flex: 0 0 auto; }
.ok-strelka { color: var(--muted); }
.ok-sob { display: flex; flex-direction: column; gap: 2px; font-size: var(--t-sm); }
.ok-sob-str { display: flex; gap: 10px; }
.ok-podval { display: flex; align-items: center; justify-content: space-between; gap: 16px; border-top: 1px solid var(--hair);
  padding-top: 12px; }
.ok-podval .ok-poyasnenie { max-width: 420px; }
.ok-podval .flot-k-knopki { flex: 1 1 auto; min-width: 0; }
.ok-podval .ok-poyasnenie { flex: 0 1 auto; min-width: 0; }
/* Н-300 (1.72.25, Cowork 13.10 16:02: «окно терминала — кнопки пополам»): окно ниже экрана листается, а подвал с кнопками
   прилипает к нижнему краю окна — кнопки всегда целиком; знак «ещё N» встаёт над подвалом (ui/eshche_kolonki.mjs). */
.ok-okno > .ok-podval { position: sticky; bottom: 0; z-index: 2; background: var(--nv-bar); padding-bottom: 14px; margin-bottom: -18px; }
/* 1.72.26 (поток Б, Cowork 13.10 21:16 п. 3 [3]: «правая колонка обрезана, Сдать в аренду и Billing наполовину, ещё N нет»):
   в три колонки окно не листается целиком — тело окна по высоте того, что осталось от шапки и подвала, каждая колонка
   листается сама, внизу у неё знак «ещё N ↓» (ui/eshche_kolonki.mjs). Блоки колонки не сжимаются — листаются. */
@media (min-width: 1101px) {
  .ok-okno > .ok-telo { flex: 1 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); }
  /* Прилипший подвал заходит на низ тела окна (его отрицательный нижний отступ) — колонке отступ снизу, чтобы последняя
     строка, прокрученная до конца, не пряталась под подвалом. */
  .ok-okno .ok-kol { min-height: 0; overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; padding-bottom: 12px; }
  .ok-okno .ok-kol > * { flex-shrink: 0; }
}
@media (max-width: 1100px) { .ok-telo { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (max-width: 760px) { .ok-telo { grid-template-columns: minmax(0, 1fr); } .ok-podval { flex-direction: column; align-items: stretch; } }
.ok-zag .ht { font: 500 var(--t-md) var(--nv-mono, monospace); letter-spacing: .06em; text-transform: uppercase; color: var(--accent); }
.ok-zag .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }

/* --- 1.72.5: окно «Сервер и выход в сеть» (эталон v12 `m-uplink`, слово Open 06.10) --------------------------------- */
.vyhod-v-mir[role=button] { cursor: pointer; }
.vyhod-v-mir[role=button]:hover, .vyhod-v-mir[role=button]:focus-visible { border-color: var(--accent); outline: none; }
/* Низкое окно: карте «Моих терминалов» остаётся около 300 px — «Выход в мир» одной строкой (цепочка — в окне по щелчку),
   подсказка управления картой не занимает отдельный ряд. */
@media (max-height: 720px) {
  .kh-flot #vyhod-v-mir > .vm-cep, .kh-flot #vyhod-v-mir > .vm-zapas { display: none; }
  .kh-flot #vyhod-v-mir > .vm-head { margin-bottom: 0; }
  .kh-flot .karta-pomoshch { display: none; }
}
.vo-okno { width: min(1240px, calc(100vw - 40px)); padding: 18px 22px; gap: 10px; }
.vo-zag { margin: 0; flex: 1 1 auto; font-size: var(--t-md, 1rem); }
.vo-okno .ok-shapka { align-items: center; }
.vo-telo { display: grid; grid-template-columns: minmax(0, 780fr) minmax(300px, 400fr); gap: 26px; align-items: start; }
.vo-svg { display: block; width: 100%; height: auto; overflow: visible; }
.vo-kol { fill: var(--accent); font: 500 var(--t-xs) var(--nv-mono, monospace); letter-spacing: .06em; }
.vo-b rect { fill: var(--surface); stroke: var(--accent); stroke-opacity: .6; stroke-width: 1.1; }
.vo-b svg { color: var(--accent); }
.vo-b.c-ok rect { stroke: var(--ok); } .vo-b.c-ok svg { color: var(--ok); }
.vo-b.c-sar rect { stroke: var(--nv-sar, #C2185B); } .vo-b.c-sar svg { color: var(--nv-sar, #C2185B); }
.vo-b.c-warn rect { stroke: var(--warn); } .vo-b.c-warn svg { color: var(--warn); }
.vo-b.net { opacity: .5; }
.vo-b.net rect { stroke-dasharray: 3 3; }
.vo-imya { fill: var(--ink); font-size: var(--t-sm); font-weight: 600; }
.vo-pod-t { fill: var(--muted); font-size: var(--t-xs); }
.vo-l { fill: none; stroke: var(--accent); stroke-width: 1.3; stroke-dasharray: 4 4; opacity: .85; }
.vo-l.net { stroke: var(--muted); opacity: .45; }
.vo-l.bezhit { animation: vo-beg 2s linear infinite; }
@keyframes vo-beg { to { stroke-dashoffset: -16; } }
@media (prefers-reduced-motion: reduce) { .vo-l.bezhit { animation: none; } }
.vo-leg { fill: var(--muted); font-size: var(--t-xs); }
.vo-sprava { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.vo-kv { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 14px; font-size: var(--t-sm); }
.vo-kv b { font-weight: 500; text-align: right; overflow-wrap: anywhere; }
.vo-chto-kuda { margin-top: 6px; }
.vo-w2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.vo-w2 > div { border: 1px solid var(--nv-line); padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; }
.vo-w2 b { font-size: var(--t-sm); }
.vo-w2 i { font-style: normal; color: var(--muted); font-size: var(--t-xs); line-height: 1.45; }
.vo-note { --bc: var(--warn); display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; font-size: var(--t-sm);
  line-height: 1.45; border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent); }
.vo-note svg { color: var(--warn); flex: 0 0 auto; margin-top: 2px; }
.vo-podval { display: flex; justify-content: flex-end; gap: 10px; border-top: 1px solid var(--hair); padding-top: 12px; }
.vo-podval .pill { display: inline-flex; align-items: center; gap: 6px; }
.vo-okno .kart-blok-head .ht::before, .vo-zag .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
@media (max-width: 1100px) { .vo-telo { grid-template-columns: minmax(0, 1fr); } }
.ping-obryv { stroke: var(--critical); stroke-width: 1.2; stroke-dasharray: 3 3; }
.ping-obryv-t { fill: var(--critical); font: 500 9px var(--nv-mono, monospace); }
.skor-konec { fill: var(--accent); }
.skor-konec.propala { fill: var(--critical); }
.skor-spusk { fill: none; stroke: var(--critical); stroke-width: 2; }
.vt-okno { width: min(640px, calc(100vw - 32px)); max-height: calc(100vh - 48px); padding: 18px 20px; gap: 8px; display: flex; flex-direction: column; }
.vt-okno:not([open]) { display: none; }
.vt-podpis { letter-spacing: .06em; }
.vt-pole { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border: 1px solid var(--nv-line); }
.vt-pole svg { color: var(--muted); flex: 0 0 auto; }
.vt-poisk { flex: 1 1 auto; min-width: 0; background: none; border: 0; outline: none; color: var(--ink); font-size: var(--t-sm); }
.vt-pole:focus-within { border-color: var(--accent); }
.vt-chipy { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.vt-chip { display: inline-flex; gap: 6px; align-items: center; padding: 4px 9px; border: 1px solid var(--nv-line); background: none;
  color: var(--ink); font-size: var(--t-xs); cursor: pointer; }
.vt-chip.sel { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.vt-golova { display: flex; justify-content: space-between; gap: 8px; margin-top: 6px; letter-spacing: .06em; }
.vt-spisok { flex: 1 1 auto; min-height: 120px; overflow-y: auto; border-top: 1px solid var(--hair); scrollbar-width: thin; }
.vt-str { display: grid; grid-template-columns: 24px 64px minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 7px 8px;
  border-bottom: 1px solid var(--hair); border-left: 2px solid transparent; cursor: pointer; }
.vt-str:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.vt-str.aktiv { border-left-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.vt-kod { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt-mesto { display: flex; flex-direction: column; min-width: 0; }
.vt-mesto > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vt-mesto-t { font-size: var(--t-sm); }
.vt-snimok { display: flex; flex-direction: column; align-items: flex-end; letter-spacing: .06em; }
.vt-niz { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; border-top: 1px solid var(--hair);
  padding-top: 10px; }
.vt-knopki { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.vt-knopki .pill { display: inline-flex; align-items: center; gap: 6px; }
.ok-itog { line-height: 1.45; }
#kartochka-okno .orb { position: relative; }
#kartochka-okno .orb-podpis { display: flex; flex-direction: column-reverse; align-items: center; white-space: normal; text-align: center; }
/* Н-496 (слово Open 01.11): в круге — только число; «потеря данных» — под кругом. */
#kartochka-okno .orb-podpis b { position: absolute; left: 0; top: 0; width: 96px; height: 96px; display: flex; align-items: center; justify-content: center;
  pointer-events: none; }
#kartochka-okno .orb-podpis i { max-width: 110px; font-size: var(--t-xs); line-height: 1.1; letter-spacing: .06em; }
#kartochka-okno .orb-podpis b { margin-left: 0; min-width: 0; font-size: var(--t-lg); }
#kartochka-okno .orb-podpis .orb-tochka, #kartochka-okno .orb-krest { display: none; }
/* Плашка окна карточки «на связи» (Cowork 23:12, эталон v12 m-term-SL-01): цвет — по состоянию, а не красный. */
.ok-plashka[data-state=ok] { --pl: var(--ok); }
.ok-plashka[data-state=warn], .ok-plashka[data-state=recentOutage] { --pl: var(--warn); }
.ok-plashka[data-state=silent] { --pl: var(--muted); }
.flot-k-plashka.ok-plashka { border-color: var(--pl); color: var(--pl); background: color-mix(in srgb, var(--pl) 9%, transparent); }
.ok-cherez { color: var(--muted); margin-top: 8px; }
.ok-cherez b { color: var(--ink); font-weight: 600; }
/* Шесть кнопок (с арендой и Billing) в узком окне в ряд не встают — переносятся строкой ниже, а не уходят за край. */
.ok-podval .flot-k-knopki { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px 10px; }
.ok-podval .flot-k-knopki .pill { white-space: nowrap; }
/* Давность у значения («· 4 ч 1 мин») переносится целиком, а не рвётся посреди (1.72.5, правая колонка 1440 px). */
.stale > .t-xs { white-space: nowrap; }
/* Цепочка «Выхода к серверу» — пять звеньев в строку, как в v12 (компактнее: мелкий кегль, узкие поля). */
.ok-cep { gap: 4px; }
.ok-zveno { padding: 2px 6px; gap: 4px; font-size: var(--t-xs); }
.ok-strelka { font-size: var(--t-xs); }
/* Н-163 (1.72.6): цепочка «Выхода к серверу» — одна строка, как в v12; длинное имя — многоточием (полное — в подсказке звена). */
.ok-cep { flex-wrap: nowrap; min-width: 0; }
.ok-zveno { flex: 0 1 auto; min-width: 0; max-width: 34%; }
/* Н-207: короткие звенья («роутер», «спутник», «сервер») не сжимаются — сокращаются только длинные (полное — в подсказке). */
.ok-zveno.kratko { flex: none; max-width: none; }
.ok-zveno span { min-width: 0; }
.ok-strelka { flex: none; }
/* Н-163: надпись молчащего «нет данных — молчит с hh:mm» — внутри поля графика, по центру (v12 m-term-SL-05). */
.kart-grafik { position: relative; }
.kart-grafik-nadpis { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none;
  text-align: center; }

/* ═══ 1.72.6 «Доступ» по эталону v12 (сверка Cowork 07.10 03:24): один экран, три колонки по два блока ═══ */
.kh-dost { flex: 1 1 0; min-height: 0; overflow: hidden; padding: 10px 14px 12px; display: flex; flex-direction: column; gap: 10px; }
.kh-dost > * { flex-shrink: 0; }
.dost-shapka { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.dost-shapka-zag { display: flex; align-items: baseline; gap: 14px; min-width: 0; }
.dost-shapka-imya { font: 600 var(--t-xl) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--ink); }
.dost-shapka-imya::before { content: '»'; margin-right: 8px; color: var(--nv-cy); font-weight: 700; }
.dost-shapka-pravee { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dost-shapka-pravee .pill, .dost-pin-knopki .pill, .dost-okno-knopki .pill, .dost-tokeny-niz .pill { display: inline-flex; align-items: center; gap: 6px; }
.dost-zamok { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.dost-kolonki { flex: 1 1 0; min-height: 0; display: grid; grid-template-columns: minmax(0, 520fr) minmax(0, 760fr) minmax(0, 440fr); gap: 14px; }
.dost-kol { display: flex; flex-direction: column; gap: 12px; min-height: 0; min-width: 0; }
.dost-kol > .dost-blok { min-height: 0; }
.dost-golova-bloka { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.kh-dost .dost-golova-bloka .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
#dost-lyudi { flex: 1 1 0; }
#dost-lyudi .dost-lyudi { flex: 1 1 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
#dost-tokeny, #dost-pin { flex: none; }
/* Остаток средней колонки — таблице «Кто что видит»: строки расходятся по высоте, легенда — внизу; «Посты МЧС» — одной
   строкой «в этой версии нет», не растягиваются (правило 3 раздела 0). Иначе под ними оставалась пустота. */
#dost-matrica:not([hidden]) { flex: 1 0 auto; display: flex; flex-direction: column; justify-content: space-between; }
#dost-zhurnal-mest { flex: 1 1 0; }
#dost-posty { flex: 0 0 auto; }
.dost-roli { grid-template-columns: repeat(5, minmax(0, 1fr)); }
/* Строка человека: кружок с точкой связи · имя и роль · места · выдать/отозвать · «…» */
.dost-chel { grid-template-columns: 34px minmax(0, 1fr) minmax(0, .85fr) auto 30px; padding: 5px 0; }
.dost-chel.ya { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.dost-inic { position: relative; width: 32px; height: 32px; }
/* Н-206: у admin кружок залит цветом акцента — буквы цветом «на акценте», иначе .dost-inic красил их в тот же акцент. */
.dost-inic.badge-admin { color: var(--on-accent); }
/* Н-197: выключенная кнопка с заливкой («Выдать PIN» у admin) — приглушена, а не как рабочая. */
.dost-blok .pill.zalivka:disabled { opacity: .45; filter: saturate(.3); cursor: not-allowed; }
/* Н-210: в узкой колонке (1366×768) подписи счётчиков ролей не налезают — мельче и без разрядки, лишнее — многоточием;
   «кто · связь» — одной строкой. */
@media (max-width: 1400px) {
  .dost-rol { padding: 6px 6px; min-width: 0; }
  .dost-rol span { font-size: var(--t-xs); letter-spacing: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dost-kto-svyaz { white-space: nowrap; font-size: var(--t-xs); letter-spacing: 0; }
}
.dost-svyaz { position: absolute; right: -1px; bottom: -1px; width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid var(--surface);
  background: var(--muted); opacity: .45; }
.dost-svyaz-leg { display: inline-block; width: 7px; height: 7px; border-radius: 50%; border: 1px solid var(--muted); margin: 0 3px 0 8px; opacity: .6; }
.dost-svyaz-leg.da { background: var(--ok); border-color: var(--ok); }
/* Н-216 (1.72.7): легенда «кто · связь ● в сети ○ нет» — как v12: строчными, без разрядки, одной строкой при любой ширине
   (не только ≤ 1400: в ~1666 она переносилась «○» / «НЕТ»). Не влезает в клетку — многоточие, смысл в подсказке (title).
   Шапка «МЕСТА» рядом — прежняя (заглавными). */
.dost-chel-golova .dost-kto-svyaz { text-transform: none; letter-spacing: 0; white-space: nowrap; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; font-size: var(--t-xs); }
.dost-chel-str { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.dost-chel-str b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Вторая строка человека — роль и «· был дд.мм» в ряд; роль переносится на вторую строку, многоточие только после второй; дата и метка — целиком. */
.dost-chel-pod { display: flex; align-items: flex-start; min-width: 0; overflow: hidden; white-space: normal; }
.dost-chel-rol { flex: 0 1 auto; min-width: 0; overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.dost-chel-byl { flex: none; white-space: nowrap; }
.dost-rol-metka { font: 600 var(--t-xs) var(--nv-mono); letter-spacing: .04em; text-transform: uppercase; color: var(--nv-cy); white-space: nowrap; }
.dost-mesta { display: inline-flex; align-items: center; gap: 5px; font-size: var(--t-xs); min-width: 0; }
.dost-mesta > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dost-mesta.da { color: var(--nv-cy); } .dost-mesta.pin { color: var(--warn); } .dost-mesta.net, .dost-mesta.nevidit { color: var(--muted); }
.dost-ssylka { border: 0; background: none; padding: 0; cursor: pointer; font-size: var(--t-xs); white-space: nowrap; }
.dost-ssylka.sn { color: var(--nv-cy); } .dost-ssylka.kr { color: var(--critical); }
.dost-ssylka-tekst { border: 0; background: none; padding: 0; cursor: pointer; text-align: left; }
.dost-menyu > summary { opacity: .55; }
.dost-snoska { line-height: 1.45; }
/* Токены: значки рядами с переносом, имя терминала полностью (ширина — по имени, не 46 px) */
.dost-tokeny-znachki { flex-wrap: wrap; overflow: visible; gap: 6px 12px; padding: 4px 0; min-height: 46px; }
.dost-token-z { width: auto; max-width: 100%; flex: none; border: 0; background: none; color: var(--accent); cursor: pointer; padding: 2px 0; }
.dost-token-z > span { color: var(--ink); overflow: hidden; white-space: normal; overflow-wrap: anywhere; line-height: 1.15;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; text-align: center; } /* Н-514 з: имя токена — до двух строк, не «Link-…» */
.dost-token-z.eshche { color: var(--nv-cy); font: 600 var(--t-sm) var(--nv-mono); justify-content: center; }
.dost-tokeny-niz { display: flex; justify-content: flex-end; }
/* Кто что видит: 5 ролей v12 */
/* Роли, которых в этой версии нет (сотрудники, МЧС), — узкими колонками в той же линии: без них в сетке ячейки «—»
   переносились второй линией под каждую строку, таблица вырастала вдвое и выталкивала «Посты МЧС» за край (Н-645). */
.dost-mat { grid-template-columns: minmax(0, 1.25fr) repeat(5, minmax(min-content, 1fr)) repeat(2, minmax(0, .3fr)); gap: 4px; padding: 5px 0; }
/* Шапка — без разрядки, перенос только по пробелам; колонка роли не уже самого длинного слова (min-content): ADMINISTRATOR
   наезжал на ADMIN, с разрядкой и переносом внутри слова — рвался на букву.
   Подписи колонок ролей, которых в этой версии нет, — в подсказке: в узкой колонке они вставали по буквам; строка
   «сотрудники, МЧС — в этой версии нет» стоит в «Людях и ролях». */
.dost-mat-head { letter-spacing: 0; }
.dost-mat-head > div { min-width: 0; }
.dost-mat-head > .off { font-size: 0; }
/* Узкое окно: ширину — ролям; колонки «нет в этой версии» — только «—». */
@media (max-width: 1500px) {
  .dost-mat { grid-template-columns: minmax(0, 1fr) repeat(5, minmax(min-content, 1fr)) repeat(2, minmax(0, .15fr)); }
}
.dost-mat-imya { display: flex; align-items: center; gap: 8px; min-width: 0; }
.dost-mat-imya svg { color: var(--accent); flex: none; }
.dost-mat-imya.off, .dost-mat-head .off { opacity: .45; }
.dost-ya { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
/* К68: слово ячейки переносится по словам, без многоточия — «шлюз — без PIN» резалось на последней букве. */
.dost-ya > span:last-child { min-width: 0; white-space: normal; overflow-wrap: break-word; }
.dost-ya.ya { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.dost-ya.chast { color: var(--warn); } .dost-ya.vv { color: var(--muted); opacity: .5; }
.dost-znak { width: auto; height: auto; border: 0 !important; background: none !important; margin: 0; display: inline-flex; vertical-align: middle; }
.dost-znak.da { color: var(--ok); } .dost-znak.chast { color: var(--warn); } .dost-znak.pin { color: var(--warn); }
.dost-znak.net, .dost-znak.vv { color: var(--muted); }
.dost-leg { display: flex; flex-wrap: wrap; gap: 6px 14px; padding-top: 6px; border-top: 1px solid var(--hair); }
.dost-leg > span { display: inline-flex; align-items: center; gap: 4px; }
/* Посты МЧС — в этой версии нет: приглушены */
.dost-posty.off { opacity: .5; }
/* Ticket manager на RP5 (круг 4.2): колонка фиксированной высоты — блоку своя прокрутка, иначе он сжимается и ложится на соседа */
/* «Ticket manager на RP5» — по содержимому; остаток колонки — «Журналу просмотров мест» (К68). */
.dost-kol > .dost-rp5 { flex: none; overflow-y: auto; }
.dost-rp5-lager { margin-top: 6px; font-weight: 600; }
.dost-rp5-chel { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 3px 0; border-bottom: 1px solid var(--line, rgba(255,255,255,.06)); }
.dost-rp5-chel > .m { min-width: 90px; }
/* PIN мест */
.dost-pin-spisok { display: flex; flex-direction: column; gap: 2px; max-height: 140px; overflow-y: auto; scrollbar-width: thin; }
.dost-pin-str { display: grid; grid-template-columns: 16px auto auto minmax(0, 1fr) auto; gap: 8px; align-items: center; font-size: var(--t-sm);
  padding: 3px 0; border-bottom: 1px solid var(--hair); }
.dost-pin-str > span:nth-of-type(2) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--t-xs); }
.dost-pin-knopki { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pill.kr { color: var(--critical); border-color: color-mix(in srgb, var(--critical) 60%, transparent); }
/* Журнал просмотров мест */
.dost-zm-pravee { display: inline-flex; align-items: baseline; gap: 10px; }
.dost-zm-filtry { display: flex; gap: 4px; }
.dost-zm-filtry .pill { padding: 2px 8px; font-size: var(--t-xs); }
.dost-zm-filtry [aria-selected='true'] { border-color: var(--nv-cy); color: var(--nv-cy); }
/* 1.01.07.07 · «Доступ» (ТЗ 10.11 ред. 2, раздел 10): человек в две строки (имя; под ним роль одной строкой), пять ячеек
   ролей в ряд, таблица «Кто что видит и может» в центре — своя прокрутка, колонка своей роли подсвечена. */
.dost-chel-imya { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dost-chel-pod { align-items: baseline; }
.dost-chel-pod > .dost-rol-metka { flex: none; }
.dost-vladelec .dost-chel-imya b { margin-right: 0; }
.dost-roli { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.dost-roli > .dost-rol { min-width: 0; padding-left: 6px; padding-right: 4px; }
/* Имя роли — целиком в своей ячейке (З-4): без разрядки «ADMINISTRATOR» помещается в строку, «TICKET MANAGER» — в две по словам; без многоточия. */
.dost-roli > .dost-rol span { min-width: 0; white-space: normal; overflow-wrap: break-word; letter-spacing: 0; line-height: 1.15; }
.dost-roli-net { margin: -2px 0 4px; }
/* Обе таблицы прав — одним блоком, на месте одна (слово 226): своей прокрутки нет — 13 строк помещаются. */
.dost-tablicy { display: flex; flex-direction: column; gap: 6px; flex: 1 0 auto; min-width: 0; }
.dost-tabl-pereklyuchatel { display: flex; gap: 6px; }
.dost-tabl-pereklyuchatel .pill.on { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.dost-tablicy > [hidden] { display: none !important; }
#dost-prava { flex: none; }
.dost-pr { display: grid; grid-template-columns: minmax(0, 1.5fr) repeat(5, minmax(0, 1fr)); gap: 4px; padding: 4px 0;
  border-bottom: 1px solid var(--hair); align-items: center; font-size: var(--t-xs); }
.dost-pr-head { font: 500 var(--t-xs) var(--nv-mono); letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.dost-pr-head .ya { color: var(--nv-cy); }
.dost-pr-ya { min-width: 0; overflow-wrap: anywhere; }
.dost-pr-ya.da { color: var(--ok); } .dost-pr-ya.chast { color: var(--warn); } .dost-pr-ya.net { color: var(--muted); }
.dost-pr-ya.ya { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.dost-zm-spisok { flex: 1 1 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
/* Н-234 (1.72.10): дате — своя ширина — не уже 44 px («hh:mm», в этом году «дд.мм»), запись прошлых лет («дд.мм.гггг») раздвигает
   свою строку, а не ложится на значок события. */
.dost-zm { display: grid; grid-template-columns: minmax(44px, max-content) 18px minmax(0, 1fr) auto; gap: 8px; align-items: start; padding: 5px 0;
  border-bottom: 1px solid var(--hair); font-size: var(--t-sm); }
.dost-zm > .m { white-space: nowrap; }
.dost-zm-tekst > div { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dost-zm-ik.otkryt, .dost-zm-metka.otkryt { color: var(--ok); } .dost-zm-ik.neverno, .dost-zm-metka.neverno { color: var(--warn); }
.dost-zm-ik.pauza, .dost-zm-metka.pauza, .dost-zm-ik.otozvan, .dost-zm-metka.otozvan { color: var(--critical); }
.dost-zm-ik.vydan, .dost-zm-metka.vydan { color: var(--nv-cy); }
.dost-zm-metka { font: 600 var(--t-xs) var(--nv-mono); letter-spacing: .04em; white-space: nowrap; }
/* Окна v12 */
.dost-okno { width: min(620px, calc(100vw - 40px)); padding: 18px 22px; gap: 8px; }
.dost-okno .ok-zag .ht { font: 500 var(--t-md) var(--nv-mono, monospace); letter-spacing: .06em; text-transform: uppercase; color: var(--accent); }
.dost-okno .ok-zag .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
.dost-okno.kr { border-color: var(--critical); } .dost-okno.kr .ok-zag .ht { color: var(--critical); }
.dost-okno .ok-shapka { display: flex; align-items: center; justify-content: space-between; }
.dost-pole-metka { margin-top: 8px; }
.dost-vybor { width: 100%; box-sizing: border-box; }
.dost-segment { display: flex; gap: 0; flex-wrap: wrap; }
/* display: flex перебивает атрибут hidden: ряд тарифов окна выдачи при «Служебном» прячется именно им. */
.dost-segment[hidden] { display: none; }
.dost-segment .pill { border-radius: 0; }
.dost-segment .pill.on { border-color: var(--nv-cy); color: var(--nv-cy); box-shadow: inset 0 0 0 1px var(--nv-cy); }
.dost-segment .pill.off, .dost-okno .off { opacity: .5; }
.dost-kletki { display: flex; align-items: center; gap: 8px; }
.dost-kletka { width: 32px; height: 36px; display: grid; place-items: center; border: 1px solid var(--nv-line); color: var(--muted); }
.dost-notka { border-left: 3px solid var(--accent); padding: 10px 12px; background: color-mix(in srgb, var(--accent) 7%, transparent);
  font-size: var(--t-sm); line-height: 1.45; margin-top: 6px; }
.dost-notka.kr { border-left-color: var(--critical); background: color-mix(in srgb, var(--critical) 7%, transparent); }
.dost-dve { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.dost-vidit { display: flex; flex-direction: column; gap: 2px; }
.dost-vidit-str { display: grid; grid-template-columns: 18px minmax(0, 1fr) minmax(0, 1fr); gap: 8px; font-size: var(--t-sm);
  border-bottom: 1px solid var(--hair); padding: 3px 0; }
.dost-okno-knopki { display: flex; justify-content: flex-end; gap: 10px; border-top: 1px solid var(--hair); padding-top: 12px; margin-top: 8px; }
.dost-okno-tablica { width: min(1560px, calc(100vw - 40px)); max-height: calc(100vh - 40px); }
.dost-okno-tablica .dost-niz-telo { max-height: calc(100vh - 220px); overflow-y: auto; }
/* «Весь журнал» (Н-202): у окна своя высота (до 85 % окна браузера), журнал внутри — остаток высоты со своей прокруткой.
   Без высоты окна правило экрана `.dost-zhurnal { flex: 1 1 0; min-height: 0 }` сжимало журнал в окне до нуля — полоса
   в заголовок, записей не видно. */
.dost-okno-zhurnal { width: min(960px, calc(100vw - 40px)); height: min(85vh, calc(100vh - 40px)); max-height: calc(100vh - 40px); overflow: hidden; }
.dost-okno-zhurnal > .dost-zhurnal { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.dost-okno-zhurnal .dost-zhurnal #audit-rows { flex: 1 1 auto; height: auto; min-height: 200px; max-height: none; overflow-y: auto; }
/* «Доступ» по v12: окно «Вход в Ticket» (#access-ops) — три колонки: операторы · страницы и пояснения · карточка. */
.dost-okno-ticket { width: min(1400px, calc(100vw - 40px)); height: min(88vh, calc(100vh - 40px)); max-height: calc(100vh - 40px); display: flex; flex-direction: column; gap: 8px; }
.dost-tk-kolonki { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, 1fr); gap: 10px; overflow: auto; }
.dost-tk-kol { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.dost-tk-spisok { display: flex; flex-direction: column; gap: 2px; }
.dost-tk-op { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 5px 6px; cursor: pointer; border-bottom: 1px solid var(--hair); }
.dost-tk-op:hover, .dost-tk-op:focus-visible, .dost-tk-op.sel { background: var(--nav-active); }
.dost-tk-op.sel { box-shadow: inset 2px 0 0 var(--nv-cy); }
.dost-tk-op[data-tk-status="pinZadan"] .dost-tk-op-st { color: var(--nv-ok); }
.dost-tk-op[data-tk-status="neDoshlo"] .dost-tk-op-st, .dost-tk-op[data-tk-status="netSostoyaniya"] .dost-tk-op-st { color: var(--nv-warn); }
.dost-tk-stranica { display: flex; justify-content: space-between; gap: 8px; padding: 4px 0; border-bottom: 1px solid var(--hair); }
.dost-tk-stranica.prinyal span { color: var(--nv-ok); }
.dost-tk-stranica.zhdyot span, .dost-tk-stranica.netSostoyaniya span { color: var(--nv-warn); }
.dost-tk-str.off, .dost-tk-kartochka .nvv-tekst { opacity: .55; }
.dost-tk-pin { padding: 4px 0; border-bottom: 1px solid var(--hair); }
.dost-tk-cep { display: flex; flex-direction: column; gap: 4px; margin: 4px 0; }
.dost-tk-shag { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 6px; align-items: center; font-size: var(--t-sm); color: var(--muted); }
.dost-tk-shag.sdelan { color: var(--ink); }
.dost-tk-shag.sdelan .dost-tk-shag-ik { color: var(--nv-ok); }
.dost-tk-status { margin: 4px 0 8px; padding: 6px 8px; border: 1px solid var(--nv-line); font-weight: 600; }
.dost-tk-status.pinZadan { color: var(--nv-ok); }
.dost-tk-status.neDoshlo, .dost-tk-status.netSostoyaniya, .dost-tk-status.pinSbroshen { color: var(--nv-warn); }
.dost-tk-knopki { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.dost-tk-komu { display: flex; gap: 10px; align-items: center; margin-bottom: 6px; }
.dost-tk-kod { margin: 10px 0; padding: 10px; border: 1px dashed var(--nv-line); text-align: center; }
.dost-tk-kod b.mono { display: block; font-size: var(--t-xl); letter-spacing: .06em; user-select: all; }
@media (max-width: 900px) { .dost-tk-kolonki { grid-template-columns: minmax(0, 1fr); } }
.dost-vydelena { outline: 2px solid var(--nv-cy); outline-offset: -2px; }
/* Низкое окно (1366×768 и ниже): колонки — по высоте окна (список людей листается внутри, «Токены» под ним видны); ниже 520 px
   колонки не сжимаются — тогда листается сам «Доступ». */
@media (max-height: 820px) {
  .kh-dost { overflow-y: auto; }
  .dost-kolonki { min-height: 520px; }
}
@media (max-width: 1280px) {
  .dost-kolonki { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); flex: none; height: auto; }
  .kh-dost { overflow-y: auto; }
}
/* Окна «Доступа», что лежат в документе закрытыми (Таблица, Весь журнал): .modal { display: flex } перебивает скрытие <dialog>. */
dialog.modal:not([open]) { display: none; }
/* «Ввести PIN» — вид окна v12 (1.72.6) на странице MESH и LoRa */
.pin-vvod { margin: 18px auto; max-width: 560px; padding: 18px 22px; display: flex; flex-direction: column; gap: 10px; border: 1px solid var(--nv-line); background: var(--surface); }
.pin-vvod-zag .ht { font: 500 var(--t-md) var(--nv-mono, monospace); letter-spacing: .06em; color: var(--accent); }
.pin-vvod-zag .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
.pin-vvod-kv { display: flex; flex-direction: column; gap: 3px; border-top: 1px solid var(--hair); padding-top: 8px; font-size: var(--t-sm); }
/* Слово и подпись v12 в ячейке «Кто что видит» (1.72.6): «видит» и ниже «места всегда». */
.dost-ya-t { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
/* Подпись — переносом без ограничения строк: «клиенты узла — по PIN · окно 15 мин» в узкой колонке резалась многоточием (К68). */
.dost-ya-t > small { font-size: var(--t-xs); overflow: hidden; white-space: normal; overflow-wrap: break-word;
  display: block; }
/* Н-204: причина «нет» по модулю — «модуль не подключён» — переносится в две строки, а не режется многоточием. */
.dost-ya.net .dost-ya-t > small { white-space: normal; }

/* ── 1.72.11 · главный · общие части ── */
/* Часть 1: блок v12 без нашей функции — приглушённый на месте (закон 2, ui/net_v_versii.mjs; образец — «Посты МЧС»). */
.nvv-blok.off { opacity: .5; }
.nvv-golova { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; min-width: 0; }
.nvv-golova .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; }
.nvv-metka { white-space: nowrap; }
/* 1.72.26 (поток Б, Cowork 13.10 21:16 п. 3 [3]: LoRa, шлюз — «Пакетов за час по каналам, МГц» налезал на «в этой версии нет»):
   заголовок остаётся в одну строку (заголовки блоков — однострочные, сквозной), а метка, если рядом не помещается, уходит
   строкой ниже, к правому краю. */
.nvv-golova { flex-wrap: wrap; row-gap: 2px; }
.nvv-golova .nvv-metka { flex: none; margin-left: auto; }
.nvv-telo { display: flex; flex-direction: column; gap: 8px; }
.nvv-knopki { display: flex; flex-wrap: wrap; gap: 6px; }
.nvv-tekst { cursor: help; }
/* Заглушка одной строкой — по своей высоте и последней в колонке: иначе колонка растягивала её пустой рамкой до низа. Остаток
   колонки берёт блок над ней — низ колонки без дыры, как у прочих. */
.nvv-stroka { flex: 0 0 auto; }
.set-kolonka > .nvv-stroka:last-child { flex-grow: 0; }
.set-kolonka > :has(+ .nvv-stroka:last-child) { flex-grow: 1; }

/* ── 1.72.11 · поток А · MESH ── (PLAN-1.72.11 раздел А: раскладка v12, без PIN, окна m-pin и m-node) */
.kh-mesh.me12, .me12-okno-ves { --me12-neyron: var(--kl-sluzh); }
.kh-mesh.me12 { padding-bottom: 12px; overflow: hidden; }
.kh-mesh.me12 .set-kolonka { overflow: hidden; padding-bottom: 0; }
/* Н-313 (1.72.28): правая колонка MESH и LoRa — над углом «EN · RU · Техподдержка» (у .kh-mesh.me12 свои 12 px снизу). */
.kh-mesh.me12:not(.bez-spravoy) > .set-kolonka:last-child { margin-bottom: 42px; }
.kh-mesh.me12 .set-sprava { overflow-y: auto; scrollbar-width: thin; }
.kh-mesh.me12 .set-kolonka > .me12-radary { flex-grow: 0; }
.me12-legenda .mesh-leg > span:last-child, .me12-knopki .pill > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.me12-knopki .pill { min-width: 0; white-space: nowrap; }
.me12-blok { min-width: 0; }
/* Список колонки (MESH — узлы, LoRa — трекеры) растягивается на высоту ячейки: низ колонки без дыры (проверка 1.72.4). */
#mesh-uzly-blok, #lora-trekery { flex: 1 1 0 !important; min-height: 0; }
.me12-spisok { flex: 1 1 0; min-height: 60px; overflow-y: auto; scrollbar-width: thin; display: flex; flex-direction: column; }
.lora-ish-str { min-width: 0; overflow-wrap: anywhere; }   /* 200 байт без пробела — законный текст; без переноса строка тянет блок вбок */
/* Большое окно сообщений LoRa: почти весь экран; слева трекеры, справа лента и ввод. Лента прокручивается сама, ввод всегда виден. */
dialog.lo-okno { width: min(1180px, calc(100vw - 48px)); max-width: none; height: min(820px, calc(100vh - 48px)); }
dialog.lo-okno .ok12-telo { display: flex; flex-direction: column; min-height: 0; flex: 1; }
dialog.lo-okno[open] { display: flex; flex-direction: column; }
.lo-okno-setka { display: grid; grid-template-columns: minmax(200px, 260px) minmax(0, 1fr); gap: 14px; flex: 1; min-height: 0; }
.lo-okno-levo { display: flex; flex-direction: column; gap: 4px; overflow-y: auto; min-height: 0; padding-right: 4px;
  border-right: 1px solid var(--line); }
.lo-okno-tr { display: flex; justify-content: space-between; gap: 8px; text-align: left; padding: 6px 8px; background: none; border: 0;
  color: var(--text); cursor: pointer; font: inherit; border-radius: 4px; }
.lo-okno-tr:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.lo-okno-tr.sel { background: color-mix(in srgb, var(--accent) 16%, transparent); box-shadow: inset 2px 0 0 var(--accent); }
.lo-okno-tr-imya { min-width: 0; overflow-wrap: anywhere; }
.lo-okno-pravo { display: flex; flex-direction: column; min-height: 0; gap: 10px; }
.lo-okno-lenta { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; padding-right: 4px; }
/* Лента симметричная (слово Open 15.11): входящие слева, исходящие справа, карточки одной ширины, подписи зеркальные. */
.lo-okno-s { width: calc(58% - 6px); box-sizing: border-box; padding: 6px 10px; border-radius: 6px; border: 1px solid var(--line); min-width: 0; overflow-wrap: anywhere;
  flex: none; display: flex; flex-direction: column; gap: 4px; }
.lo-okno-s.vhod { align-self: flex-start; background: color-mix(in srgb, var(--surface) 90%, transparent); }
.lo-okno-s.ishod { align-self: flex-end; background: color-mix(in srgb, var(--accent) 10%, transparent); text-align: right; }
.lo-okno-s.ishod .lo-okno-s-knopki { justify-content: flex-end; }
.lo-okno-filtr { display: flex; gap: 6px; flex-wrap: wrap; }
.lo-okno-f.on { background: color-mix(in srgb, var(--nv-cy) 18%, transparent); }
.lo-okno-den { align-self: center; padding: 0 10px; border: 1px solid var(--line); border-radius: 10px; text-transform: lowercase; flex: none; }
/* Дорожка доставки: узлы с временем шага; по сети — бегущая черта, по радио — волна; текущий отрезок движется, после доставки стоит. */
.lo-dr { display: flex; align-items: flex-start; gap: 0; margin: 2px 0; text-align: center; }
.lo-dr-uzel { display: flex; flex-direction: column; align-items: center; gap: 1px; min-width: 0; flex: 0 1 auto; font-size: var(--t-xs); }
.lo-dr-tochka { width: 9px; height: 9px; border-radius: 50%; border: 1.5px solid var(--muted); display: block; }
.lo-dr-uzel.proyden .lo-dr-tochka { background: var(--nv-cy); border-color: var(--nv-cy); }
.lo-dr-uzel.stoit .lo-dr-tochka { box-shadow: 0 0 0 3px color-mix(in srgb, var(--nv-cy) 35%, transparent); }
.lo-dr-uzel.slom .lo-dr-tochka { border-color: var(--critical); }
.lo-dr-uzel.slom .lo-dr-vremya { color: var(--critical); }
.lo-dr.gotovo .lo-dr-uzel:last-child .lo-dr-tochka { background: var(--ok); border-color: var(--ok); }
.lo-dr-imya { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.lo-dr-vremya { color: var(--muted); font-variant-numeric: tabular-nums; }
/* Отрезки дорожки — прямые, как линия паспорта (слово Open ≈18:48): по сети — пунктир, по радио — сплошная; на отрезке, где
   сообщение сейчас, бежит точка-сигнал в сторону передачи; не дошло — пунктир тревогой. */
.lo-dr-otr { position: relative; flex: 1 1 18px; min-width: 14px; height: 9px; margin: 0 2px; background-repeat: repeat-x; background-position: 0 50%; }
.lo-dr-otr.set { background-image: linear-gradient(90deg, var(--line) 50%, transparent 50%); background-size: 6px 1.5px; }
.lo-dr-otr.set.proyden, .lo-dr-otr.set.idet { background-image: linear-gradient(90deg, var(--nv-cy) 50%, transparent 50%); }
.lo-dr-otr.radio { background-image: linear-gradient(var(--line), var(--line)); background-size: 100% 1.5px; }
.lo-dr-otr.radio.proyden, .lo-dr-otr.radio.idet { background-image: linear-gradient(var(--nv-cy), var(--nv-cy)); }
.lo-dr-otr.slom { background-image: linear-gradient(90deg, var(--critical) 50%, transparent 50%); background-size: 6px 1.5px; }
.lo-dr-otr.idet::after { content: ''; position: absolute; top: 50%; left: 0; width: 6px; height: 6px; border-radius: 50%; background: var(--nv-cy);
  box-shadow: 0 0 5px var(--nv-cy); transform: translate(-50%, -50%); animation: lo-dr-signal 1.2s linear infinite; }
@keyframes lo-dr-signal { from { left: 0; } to { left: 100%; } }
@media (prefers-reduced-motion: reduce) { .lo-dr-otr.idet::after { animation: none; left: 50%; } }
.lo-okno-chisla { display: flex; flex-wrap: wrap; gap: 4px 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.lo-okno-s.ishod .lo-okno-chisla { justify-content: flex-end; }
.lo-okno-tekst { margin: 2px 0; }
.lo-okno-s-knopki { display: flex; gap: 6px; margin-top: 4px; }
.lo-okno-vvod { display: flex; flex-direction: column; gap: 4px; border-top: 1px solid var(--line); padding-top: 8px; }
.lo-okno-vvod textarea { width: 100%; box-sizing: border-box; resize: vertical; font: inherit; line-height: 1.4; padding: 6px 8px; }
.lo-okno-vvod-niz { display: flex; justify-content: space-between; gap: 10px; }
@media (max-width: 900px) { .lo-okno-setka { grid-template-columns: 1fr; } .lo-okno-levo { max-height: 160px; border-right: 0; } }
.me12-str { display: grid; grid-template-columns: minmax(0, 1fr) 104px 72px; gap: 6px; align-items: center; padding: 5px 4px;
  border-bottom: 1px solid var(--hair); }
.me12-str.tr { cursor: pointer; } .me12-str.sel { box-shadow: inset 3px 0 0 var(--nv-cy); background: var(--nav-active); }
.me12-shapka { font-size: var(--t-xs); color: var(--muted); text-transform: uppercase; letter-spacing: .04em; position: sticky; top: 0;
  background: var(--surface); z-index: 1; }
.me12-shapka > :nth-child(n+2), .me12-str > :nth-child(n+2) { text-align: right; }
.me12-imya { display: flex; gap: 8px; align-items: center; min-width: 0; }
.me12-imya-t { display: flex; flex-direction: column; min-width: 0; }
.me12-imya-t > b { font-weight: 600; font-size: var(--t-sm); overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.me12-vt { display: flex; align-items: center; gap: 4px; min-width: 0; font-size: var(--t-xs); color: var(--muted); }
.me12-vt > span { overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; min-width: 0; }
.me12-vt.s-critical { color: var(--critical); }
.me12-svyaz { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.15; }
.me12-romb { width: 9px; height: 9px; flex: none; border: 2px solid var(--kl-sluzh); transform: rotate(45deg); }
.me12-romb.shlyuz { outline: 1px solid currentColor; outline-offset: 2px; color: var(--kl-mesh-shlyuz); border-color: var(--kl-mesh-shlyuz); }
.me12-romb.zamechanie { border-color: var(--warn); color: var(--warn); }
.me12-romb.molchit { border-color: var(--critical); border-style: dashed; color: var(--critical); }
.me12-legenda { display: grid; grid-template-columns: 1fr 1fr; gap: 0 10px; padding-top: 6px; }
#mesh-bez-pin-podval { grid-template-columns: 1fr; color: var(--muted); }
.me12-str4 { display: grid; grid-template-columns: 1fr 1.4fr 1fr 28px; gap: 6px; }
@media (max-height: 760px) { .me12-radary .nvv-telo, .me12-radary .nvv-knopki { display: none; } }
.me12-seredina { overflow: hidden; }
/* Не влезает в строку (длинное имя шлюза, узкий экран) — переносится, а не режется многоточием: шапка — это ответ «куда выход». */
.me12-polosa .set-polosa-verh { flex-wrap: wrap; row-gap: 4px; min-width: 0; }
.me12-polosa .set-polosa-verh > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.me12-polosa-sprava { margin-left: auto; flex: none; }
.me12-chip-pin { display: flex; gap: 6px; align-items: center; }
.pill.me12-ok { color: var(--ok); border-color: var(--ok); }
.pill.me12-warn { color: var(--warn); border-color: var(--warn); display: inline-flex; gap: 6px; align-items: center; }
.me12-upr { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.me12-upr .pill { display: inline-flex; gap: 6px; align-items: center; }
.me12-telo { flex: 1 1 0; min-height: 0; position: relative; border: 1px solid var(--nv-line); background: var(--surface); overflow: hidden; }
.me12-karta, .me12-holst, .me12-zamok-fon { position: absolute; inset: 0; }
.me12-karta > .col { height: 100%; }
.me12-karta .map-host { height: 100%; min-height: 0; border-bottom: 0; }
.me12-bez-mesta { position: absolute; left: 12px; bottom: 64px; z-index: 500; display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  max-width: 60%; padding: 6px 10px; background: color-mix(in srgb, var(--nv-bar) 88%, transparent); border: 1px dashed var(--warn);
  font-size: var(--t-xs); }
.me12-bez-mesta b { color: var(--warn); font-weight: 600; }
.me12-bez-mesta-uzel { padding: 1px 6px; border: 1px solid var(--nv-line); font-family: var(--nv-mono, monospace); }
.me12-bez-mesta-uzel.m-net { color: var(--warn); border-style: dashed; }
.me12-vyhod { position: absolute; top: 10px; left: 10px; z-index: 500; max-width: calc(100% - 20px); }
/* 3D MESH: слева сверху — окно «3D · рельеф», «Выход в мир» — справа и поверх рамки 3D (как у «Карты сети»). */
.me12-karta.v-3d > .me12-vyhod { left: auto; right: 10px; z-index: 700; }
.me12-holst { display: flex; align-items: stretch; justify-content: stretch; padding: 6px; }
.me12-holst svg { width: 100%; height: 100%; cursor: grab; touch-action: none; }
.me12-holst .m-svyaz.m-ok, .me12-holst .m-svyaz.m-sred { stroke: var(--me12-neyron); }
.me12-holst .m-svyaz.m-slab { stroke: var(--warn); stroke-dasharray: 6 5; }
.me12-holst .m-uzel.m-v12 { filter: drop-shadow(0 0 6px var(--me12-neyron)); }
.me12-holst circle.m-vybran { stroke: var(--nv-cy) !important; stroke-width: 5; }
.me12-zamok-fon { display: grid; place-items: center;
  background: repeating-linear-gradient(0deg, transparent 0 39px, var(--hair) 39px 40px),
    repeating-linear-gradient(90deg, transparent 0 39px, var(--hair) 39px 40px); }
.me12-zamok { max-width: 460px; margin: 16px; padding: 22px 26px; display: flex; flex-direction: column; align-items: center; gap: 10px;
  text-align: center; border: 1px solid var(--warn); background: var(--surface); }
.me12-zamok-ik { color: var(--warn); }
.me12-zamok-zag { font-size: var(--t-md); font-weight: 600; }
/* Н-260 (1.72.18): кнопки на компании с данными под строкой «здесь пусто». */
.sar12-pusto-kompanii { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
.me12-zamok .cta, .me12-shirokaya { display: inline-flex; gap: 8px; align-items: center; justify-content: center; }
.me12-shirokaya { width: 100%; }
.me12-kolco { display: flex; gap: 12px; align-items: center; }
.me12-kolco .krug { flex: none; }
.me12-kv { flex: 1 1 auto; min-width: 0; }
.me12-vn-zag { margin-top: 8px; color: var(--warn); }
.me12-vn { display: flex; flex-direction: column; }
.me12-vn-str { display: flex; gap: 10px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--hair); }
#mesh-kto-vidit { display: flex; gap: 8px; align-items: flex-start; margin: 8px 0; }
.me12-k-golova { display: flex; gap: 10px; align-items: center; padding-right: 28px; }
.me12-k-golova .me12-romb { width: 14px; height: 14px; }
.me12-k-imya { flex: 1 1 auto; min-width: 0; }
.me12-k-imya .dsp { font-size: var(--t-md); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me12-st { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; padding: 6px 10px; margin: 6px 0;
  border: 1px solid currentColor; }
.me12-radar-kv { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.lo12-pakety-tabl { display: grid; grid-template-columns: 1fr auto auto; gap: 2px 14px; padding-top: 4px; }
.lo12-pakety-tabl b { text-align: right; }
.me12-trafik-svg { display: block; margin-top: 4px; }
.me12-trafik-os { font-size: var(--t-xs); fill: var(--muted); }
.me12-budzhet { display: flex; flex-direction: column; gap: 2px; padding: 6px 0; }
.me12-sosed { display: grid; grid-template-columns: 14px minmax(0, 1fr) auto auto; gap: 8px; align-items: center; padding: 4px 0;
  border-bottom: 1px solid var(--hair); }
.me12-sosed > .t-sm { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me12-knopki { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 8px; }
.me12-knopki > :first-child { grid-column: 1 / -1; }
.me12-knopki .pill { display: inline-flex; gap: 6px; align-items: center; justify-content: center; }
dialog.me12-okno { width: min(720px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); display: flex; flex-direction: column;
  gap: 10px; overflow-y: auto; }
dialog.me12-okno:not([open]) { display: none; }
dialog#m-pin { width: min(480px, calc(100vw - 32px)); }
.me12-pin-forma { display: flex; flex-direction: column; gap: 10px; }
.me12-pin-yacheyki { position: relative; display: flex; gap: 8px; justify-content: center; cursor: text; }
.me12-pin-ya { width: 40px; height: 48px; display: grid; place-items: center; border: 1px solid var(--nv-line); font-size: var(--t-lg);
  background: var(--surface); }
.me12-pin-ya.kursor { border-color: var(--accent); box-shadow: inset 0 -3px 0 var(--accent); }
.me12-pin-pole { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; border: 0; padding: 0; caret-color: transparent; }
.me12-okno-knopki { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }
.me12-okno-dve { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.me12-okno-kol { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.me12-okno-kol > .ht { margin-top: 8px; font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; color: var(--nv-cy); }
dialog.me12-uzel.zamechanie { border-color: var(--warn); }
dialog.me12-uzel.molchit { border-color: var(--critical); }
.me12-mesto { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
@media (max-width: 1500px) { .kh-mesh.me12 .me12-str { grid-template-columns: minmax(0, 1fr) 58px 52px; } }
/* Шапка v12 «связь, кбит/с» и «питание» в окне Open (1706 px, прибор 1.72.7) — целиком, без многоточия: столбцы 104 и 72 px
   (замер прибора: «связь, кбит/с» +36 px к 64, «питание» +10 к 58), левая колонка — 360 px. Уже 1500 px — прежние ширины,
   шапки режутся многоточием с подсказкой (el() ставит title у head-cell). */
@media (min-width: 1501px) {
  .kh-mesh.me12 { grid-template-columns: 360px minmax(0, 1fr) 340px; }
  .kh-mesh.me12.bez-slevoy { grid-template-columns: 28px minmax(0, 1fr) 340px; }
  .kh-mesh.me12.bez-spravoy { grid-template-columns: 360px minmax(0, 1fr) 28px; }
  .kh-mesh.me12.bez-slevoy.bez-spravoy { grid-template-columns: 28px minmax(0, 1fr) 28px; }
}
@media (max-width: 1279px) { .me12-okno-dve { grid-template-columns: 1fr; } }
/* ═══ 1.72.11 · поток В · Настройки (Н-191): шапка и три колонки v12; документ не листается, колонка — своей прокруткой ═══ */
.kh-na12 { flex: 1 1 0; min-height: 0; overflow: hidden; padding: 10px 14px 0; display: flex; flex-direction: column; gap: 10px; }
.kh-na12 > * { flex-shrink: 0; }
.na12-shapka { flex-wrap: nowrap; }
.na12-shapka-zag { flex: 1 1 auto; min-width: 0; }
.na12-shapka-pod { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.na12-shapka .dost-shapka-pravee { flex: none; flex-wrap: nowrap; }
.na12-kolonki { flex: 1 1 0; min-height: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
/* Колонка листается сама (отступ под угол «EN · RU · Техподдержка» даёт .col — padding-bottom; в v12 «Звук тревог» уходил под угол). */
.na12-kol { display: flex; flex-direction: column; gap: 12px; min-height: 0; min-width: 0; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; }
.kh-na12 .na12-blok { flex: none; gap: 2px; padding: 10px 12px; }
.kh-na12 .dost-golova-bloka .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
.na12-golova > :last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.na12-blok.off, .na12-str.off, .na12-ist.off, .na12-snoska.off, .na12-polosa.off, .na12-dvizhenie.off, .na12-seg.off { opacity: .5; }
.na12-blok.off .na12-str.off { opacity: 1; }
.na12-sar { border-left: 2px solid color-mix(in srgb, var(--critical) 45%, transparent); }
.na12-str { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 4px 0;
  border-bottom: 1px solid var(--hair); }
.na12-blok > .na12-str:last-child { border-bottom: 0; }
.na12-str-t { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.na12-str-t > b { font-weight: 500; font-size: var(--t-sm); overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.na12-str-t > i { font-style: normal; font-size: var(--t-xs); color: var(--muted); overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.na12-str-v { display: flex; align-items: center; gap: 8px; flex: none; }
.na12-ssylka { cursor: pointer; }
.na12-ssylka:hover > b, .na12-ssylka:focus-visible > b { color: var(--nv-cy); }
.na12-val { white-space: nowrap; }
.na12-val, .na12-val > b { font: 600 var(--t-sm) var(--nv-mono); }
.na12-val > small { font: 400 var(--t-xs) var(--nv-mono); color: var(--muted); }
.na12-knopka-val { border: 0; background: none; color: inherit; padding: 0; cursor: pointer; }
.na12-knopka-val:disabled { cursor: default; }
.na12-knopka-val:not(:disabled):hover > b { color: var(--nv-cy); }
.na12-seg { flex-wrap: nowrap; }
.na12-seg .pill { padding: 2px 8px; font: 600 var(--t-xs) var(--nv-mono); letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; }
.na12-seg .pill:disabled:not(.on) { opacity: .6; }
.na12-teg { font: 600 var(--t-xs) var(--nv-mono); letter-spacing: .04em; text-transform: uppercase; padding: 1px 7px; border: 1px solid currentColor;
  white-space: nowrap; }
.na12-teg.ok { color: var(--ok); } .na12-teg.warn { color: var(--warn); } .na12-teg.kr { color: var(--critical); }
.na12-teg.net, .na12-teg.off { color: var(--muted); }
.na12-cena { font: 600 var(--t-sm) var(--nv-mono); min-width: 28px; text-align: right; }
.na12-tumbler { width: 30px; height: 16px; flex: none; border: 1px solid var(--nv-line); background: none; padding: 1px; cursor: pointer;
  display: inline-flex; align-items: center; }
.na12-tumbler > i { width: 12px; height: 12px; background: var(--muted); transition: transform .15s; }
.na12-tumbler.on { border-color: var(--nv-cy); }
.na12-tumbler.on > i { background: var(--nv-cy); transform: translateX(14px); }
.na12-tumbler:disabled { opacity: .45; cursor: not-allowed; }
.na12-mal { padding: 2px 8px; font-size: var(--t-xs); display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.na12-snoska { padding-top: 4px; line-height: 1.4; }
.na12-zamok { text-transform: uppercase; letter-spacing: .04em; }
.na12-na-svyazi { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.na12-tochka { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
.na12-tochka.ok { background: var(--ok); }
.na12-skhema { display: grid; grid-template-columns: auto minmax(40px, 1fr) auto; align-items: center; gap: 8px; padding: 4px 0 6px;
  border-bottom: 1px solid var(--hair); }
.na12-skhema-sleva { display: flex; flex-direction: column; gap: 4px; font-size: var(--t-sm); min-width: 0; }
.na12-skhema-uzel { display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.na12-skhema-uzel > svg { color: var(--ok); flex: none; }
.na12-skhema-uzel.off { opacity: .5; }
.na12-skhema-uzel.off > svg { color: var(--muted); }
.na12-skhema-linii { border-top: 1px dashed var(--nv-cy); text-align: center; font: 600 var(--t-xs) var(--nv-mono); color: var(--nv-cy);
  padding-top: 2px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-transform: uppercase; }
.na12-skhema-server { display: flex; align-items: center; gap: 6px; color: var(--nv-cy); }
.na12-skhema-server > div { display: flex; flex-direction: column; color: var(--ink); }
.na12-polosa { height: 8px; margin: 2px 0 4px; background: repeating-linear-gradient(90deg, var(--nv-line) 0 2px, transparent 2px 6px); }
.na12-ist { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 3px 0; }
.na12-lenta { height: 12px; background: repeating-linear-gradient(90deg, var(--nv-line) 0 1px, transparent 1px 9px); }
.na12-lenta.off { opacity: .6; }
.na12-lenta.est { position: relative; background: none; border-bottom: 1px solid var(--nv-line); }
.na12-lenta.est > i { position: absolute; top: 1px; bottom: 1px; width: 2px; margin-left: -1px; background: var(--nv-cy); }
.na12-polosa.est { background: color-mix(in srgb, var(--nv-line) 60%, transparent); }
.na12-polosa.est > i { display: block; height: 100%; background: var(--nv-cy); }
.na12-tarify-telo { max-height: 60vh; overflow-y: auto; }
.na12-podzag { display: block; padding-top: 4px; }
.na12-obrazcy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.na12-obrazets { display: flex; flex-direction: column; gap: 6px; text-align: left; padding: 8px 10px; border: 1px solid var(--nv-line);
  background: none; color: inherit; cursor: pointer; min-width: 0; font: inherit; }
.na12-obrazets.on { border-color: var(--nv-cy); box-shadow: inset 0 0 0 1px var(--nv-cy); }
.na12-obr-zag { display: flex; align-items: center; gap: 6px; font-size: var(--t-sm); min-width: 0; }
.na12-obr-zag > b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.na12-obr-kartinka { height: 40px; border: 1px solid var(--nv-line); display: flex; gap: 6px; padding: 6px; }
.na12-obr-noch .na12-obr-kartinka { background: #02060B; }
.na12-obr-den .na12-obr-kartinka { background: #EEF3F7; }
.na12-obr-kartinka > i { flex: 1; border-top: 1px dashed #1FC8FF; }
.na12-obr-den .na12-obr-kartinka > i { border-top: 2px dashed #0068C4; }
.na12-obr-pod { font-style: normal; font-size: var(--t-xs); color: var(--muted); line-height: 1.35; }
.na12-dvizhenie-golova { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-top: 6px; }
.na12-dvizhenie { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.na12-dv { display: flex; flex-direction: column; gap: 3px; padding: 6px 8px; border: 1px solid var(--hair); min-width: 0; }
.na12-dv.on { border-color: var(--nv-cy); }
.na12-dv > b { font: 600 var(--t-xs) var(--nv-mono); text-transform: uppercase; letter-spacing: .04em; }
.na12-dv > i { font-style: normal; font-size: var(--t-xs); color: var(--muted); line-height: 1.3; }
/* Окно «Все настройки ›» — размером с «Таблицу» «Доступа»; внутри прежний экран, разделы колонками, своя прокрутка. */
.na12-okno-vse { display: flex; flex-direction: column; overflow: hidden; }
.na12-okno-vse > .na12-vse-telo { flex: 1 1 auto; min-height: 0; overflow-y: auto; max-height: calc(100vh - 140px); }
/* Окно «Выбор компании» (m-company) */
.na12-okno-kompanii { width: min(680px, calc(100vw - 40px)); }
.na12-kompanii { display: flex; flex-direction: column; gap: 8px; max-height: calc(100vh - 340px); overflow-y: auto; scrollbar-width: thin; }
.na12-kompaniya { display: grid; grid-template-columns: 16px 54px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 8px 12px;
  border: 1px solid var(--nv-line); background: none; color: inherit; text-align: left; cursor: pointer; font: inherit; }
.na12-kompaniya.on { border-color: var(--nv-cy); box-shadow: inset 0 0 0 1px var(--nv-cy); }
.na12-radio { width: 14px; height: 14px; border-radius: 50%; border: 1px solid var(--muted); }
.na12-kompaniya.on .na12-radio { border-color: var(--nv-cy); box-shadow: inset 0 0 0 3px var(--nv-bar, var(--surface)); background: var(--nv-cy); }
.na12-kompaniya-t { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.na12-kompaniya-t > b, .na12-kompaniya-t > i { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.na12-kompaniya-t > i { font-style: normal; font-size: var(--t-xs); color: var(--muted); }
.na12-chipy { display: flex; gap: 4px; flex-wrap: wrap; }
.na12-chip { font: 600 var(--t-xs) var(--nv-mono); padding: 1px 6px; border: 1px solid var(--nv-line); }
.na12-chip.off { color: var(--muted); }
/* 1706×935 и 1440×900: один экран — строки и блоки плотнее (колонка «Тариф · SAR · Billing» — самая длинная). */
@media (max-height: 960px) {
  .kh-na12 { gap: 8px; padding-top: 8px; }
  .na12-kolonki, .na12-kol { gap: 10px; }
  .kh-na12 .na12-blok { padding: 8px 12px; }
  .na12-str { padding: 3px 0; }
  .na12-obr-kartinka { height: 30px; }
  /* 1440×900 (прибор 76d5988): колонка 2 «Доступ · Сервер · Хранение» была выше места на 14 px (758 из 744) — схема, полоса
     занятого места, сноска и зазоры блока плотнее: около 20 px запаса. */
  .na12-skhema { padding: 1px 0 3px; gap: 6px; }
  .na12-skhema-sleva { gap: 1px; line-height: 1.25; }
  .na12-polosa { margin: 0 0 2px; height: 6px; }
  .kh-na12 .na12-blok { gap: 1px; }
  .na12-snoska { padding-top: 2px; line-height: 1.3; }
  .kh-na12 .na12-golova { margin-bottom: 3px; }
}
/* Низкие окна (1366×768, 1152×700): колонки листаются сами, документ — нет; шапка — подпись многоточием. */
@media (max-width: 1279px) {
  .na12-kolonki { gap: 10px; }
  .na12-shapka-pod { max-width: 100%; }
  .na12-shapka .dost-shapka-pravee .pill > span { max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .na12-ist { grid-template-columns: minmax(0, 110px) minmax(0, 1fr) auto; }
}

/* ═══ 1.72.11 · поток В · Карта сети (Н-183, Н-212): колонки и полоса v12, «Выход в мир» поверх карты (NRL), окно m-device ═══ */
.kh-set .set-blok.off, .kh-set .set-gruppa.off, .st12-leg.off, .kh-set .set-kv.off, .st12-po-chasam.off, .st12-spark.off,
.kh-set .set-poyasn.off, .st12-grafik.off, .st12-chto > .off { opacity: .5; }
.kh-set .set-gruppa { text-transform: none; letter-spacing: 0; font: 500 var(--t-sm) var(--nv-font); color: var(--ink); }
.kh-set .set-gruppa > b { flex: 1 1 auto; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kh-set .set-gruppa > span:not(.set-tochka) { white-space: nowrap; }
.kh-set .set-ustr { grid-template-columns: 16px minmax(0, 1fr) auto; }
.set-ustr-ik { color: var(--muted); display: inline-flex; }
.st12-eshche { border: 0; background: none; color: var(--nv-cy); font: 600 var(--t-xs) var(--nv-mono); text-align: left; padding: 4px 4px 2px 24px;
  cursor: pointer; white-space: nowrap; }
.st12-teg { font: 600 var(--t-xs) var(--nv-mono); letter-spacing: .04em; text-transform: uppercase; padding: 1px 6px; border: 1px solid currentColor;
  white-space: nowrap; }
.st12-teg.info { color: var(--nv-cy); } .st12-teg.warn { color: var(--warn); } .st12-teg.critical { color: var(--critical); }
.st12-legenda { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--hair); font-size: var(--t-xs); }
.st12-leg { display: flex; align-items: center; gap: 7px; }
.st12-mal { display: inline-flex; align-items: center; gap: 5px; padding: 3px 8px; font-size: var(--t-xs); white-space: nowrap; }
.st12-klass-t { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.st12-klass-t > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st12-klass-t > small { font-size: var(--t-xs); }
.st12-doli { display: flex; gap: 2px; height: 6px; margin: 2px 0 6px; }
.st12-doli > i { display: block; min-width: 3px; background: var(--nv-dim); }
/* Cowork 17:29 п. 1: одна строка (многоточием) — «Каналы» ниже помещаются без прокрутки, как v12. */
.st12-nashe { margin-top: 4px; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.st12-pasport-knopki { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.st12-pasport-knopki .pill.zalivka { margin-left: auto; }
.st12-po-chasam { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.st12-polosa-chasov { height: 14px; background: repeating-linear-gradient(90deg, var(--nv-line) 0 2px, transparent 2px 7px); }
/* 1.01.01.03: ряд 24 ч по часам — столбик на час, высота — доля от самого полного часа; пустой час — линия основания. */
.st12-uchet .st12-polosa-chasov { height: 28px; display: flex; align-items: flex-end; gap: 1px; background: none;
  border-bottom: 1px solid var(--nv-line); }
.st12-uchet .st12-polosa-chasov > i { flex: 1; min-height: 1px; background: var(--accent); }
.st12-uchet-s { margin-top: 2px; }
.st12-nazvat-pole { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.st12-nazvat-pole input { width: 100%; box-sizing: border-box; }
.kh-set .set-kv > b { min-width: 0; overflow: hidden; white-space: normal; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; } /* Н-514 з: значение паспорта — до двух строк, не «… п…» */
.kh-set .set-kv > span { flex: none; white-space: nowrap; }
.st12-kanaly-pravee { display: inline-flex; align-items: baseline; gap: 8px; min-width: 0; flex: 1 1 auto; justify-content: flex-end; }
.st12-kanaly-imya { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#set-kanaly .flot-blok-head { justify-content: flex-start; }
#set-kanaly .flot-blok-head > .ht { flex: none; }
.st12-kanal-itog { display: flex; align-items: baseline; gap: 10px; }
.st12-big { font: 600 var(--t-xl) var(--nv-mono); white-space: nowrap; }
.st12-kanal { display: grid; grid-template-columns: auto auto minmax(30px, 1fr) auto; gap: 8px; align-items: center; padding: 3px 0; }
.st12-kanal > .mono { white-space: nowrap; }
.st12-kanal + .st12-kanal { margin-top: 0; }
.st12-kanal-polosa { height: 6px; background: var(--hair); }
.st12-kanal-polosa > i { display: block; height: 100%; background: var(--accent); }
/* «Занято сейчас»: тарелка — группа строк; длинная строка — переносом на вторую, многоточие только после второй, полный текст в подсказке. */
.zs-tarelka { display: flex; flex-direction: column; gap: 2px; padding: 6px 0; }
.zs-tarelka + .zs-tarelka { border-top: 1px solid var(--hair); }
.zs-stroka { overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; min-width: 0; }
.zs-tarelka[data-molchit="1"] [data-zs="3"] { color: var(--warn); }
.st12-spark { display: block; width: 100%; height: 36px; }
.st12-os-chasov { display: flex; justify-content: space-between; line-height: 1.1; font-variant-numeric: tabular-nums; }
/* «Отображение связи»: сетка видимости в метрах от площадки (screens/svyaz_plan.mjs). */
.sv-plan-ekran { flex-grow: 1; min-height: 0; display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 12px; padding: 12px 14px; }
.sv-plan-panel { overflow-y: auto; min-height: 0; gap: 8px; }
.sv-plan-chestno { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sv-plan-nastroyki { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 10px; }
.sv-plan-nastroyki .sv-plan-shiroko { grid-column: 1 / -1; }
.sv-plan-nastroyki .field { gap: 3px; }
.sv-plan-nastroyki .field input, .sv-plan-nastroyki .field select { padding: 6px 8px; font-size: var(--t-sm); width: 100%; min-width: 0; }
.sv-plan-stroki-blok { display: flex; flex-direction: column; gap: 6px; }
.sv-plan-stroki-blok ul { margin: 0; padding-left: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-size: var(--t-sm); }
.sv-plan-pravo { min-height: 0; min-width: 0; display: flex; flex-direction: column; }
.sv-plan-setka { display: block; flex: 1 1 0; min-height: 0; width: 100%; cursor: crosshair; }
.sv-plan-setka .sv-noda-imya { fill: var(--ink); font-family: var(--font-mono); }
:is(.sv-plan-setka, .sv-plan-sloy) .sv-vidno, .sv-leg.sv-vidno::before { fill: var(--ok); background: var(--ok); opacity: .55; }
:is(.sv-plan-setka, .sv-plan-sloy) .sv-nevidno, .sv-leg.sv-nevidno::before { fill: var(--bad, #E5484D); background: var(--bad, #E5484D); opacity: .55; }
:is(.sv-plan-setka, .sv-plan-sloy) .sv-net, .sv-leg.sv-net::before { fill: var(--muted); background: var(--muted); opacity: .25; }
:is(.sv-plan-setka, .sv-plan-sloy) .sv-krug { stroke: var(--muted); stroke-dasharray: 4 4; vector-effect: non-scaling-stroke; }
:is(.sv-plan-setka, .sv-plan-sloy) .sv-shlyuz { fill: var(--accent); stroke: var(--bg); stroke-width: 2; vector-effect: non-scaling-stroke; }
:is(.sv-plan-setka, .sv-plan-sloy) .sv-noda { fill: none; stroke: var(--ink); stroke-width: 2; vector-effect: non-scaling-stroke; }
.sv-plan-karta-ramka { position: relative; flex: 1 1 0; min-height: 0; width: 100%; }
.sv-plan-karta-ramka > .col { height: 100%; display: flex; flex-direction: column; }
.sv-plan-karta-ramka .map-host { flex: 1 1 0; min-height: 0; height: auto; position: relative; }
.sv-plan-karta-ramka .map-host > * { height: 100%; }
.sv-plan-sloy { position: absolute; inset: 0; pointer-events: none; z-index: 450; }
.sv-plan-sloy .sv-k { opacity: .42; }
.sv-plan-sloy .sv-shlyuz-bukva { font: 700 13px var(--font-mono); fill: var(--ink); paint-order: stroke; stroke: var(--bg); stroke-width: 3px; }
.sv-plan-karta-ramka .leaflet-container { cursor: crosshair; }
.sv-plan-leg { display: flex; gap: 14px; }
.sv-leg::before { content: ''; display: inline-block; width: 10px; height: 10px; margin-right: 5px; vertical-align: -1px; }
/* Блок «Каналы» для любых входов (ui/kanaly.mjs): сумма — толстой линией, каждый вход — тонкой своего цвета; не дающий — приглушён. */
.kn-grafik { display: block; width: 100%; height: 40px; }
/* Правая колонка с «Каналами» помещается без прокрутки в 1706×935 и на словах боевого (факты недающего входа — две строки):
   иначе знак «ещё N ↓» ложится на строки входов и график. */
.set-sprava:has(> #set-kanaly) { padding-bottom: 0; gap: 8px; }
/* Сквозной 31.10 17:16 пп. 3–4 (вторая строка LTE «раньше нет данных с …» не влезла): колонка с «Каналами» не листается —
   «Каналы» целиком внизу, листается паспорт между «В сети сейчас» и ними, знак «ещё N» — у низа паспорта, над «Каналами». */
.set-sprava:has(> #set-kanaly) { overflow-y: hidden; }
.set-sprava:has(> #set-kanaly) > #set-pasport { flex: 1 1 0; min-height: 96px; overflow-y: auto; scrollbar-width: thin; }
.set-sprava:has(> #set-kanaly) > #set-kanaly { flex-grow: 0; }
/* «Занято сейчас» — по содержимому: остаток высоты забирает паспорт (он листается), а не пустота под строками тарелок. Тарелок
   много — «Занято» сжимается и листается своей прокруткой, а не вылезает за колонку и не сжимает паспорт до нуля. */
.set-sprava:has(> #set-pasport) > #set-zanyato:last-child { flex: 0 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; }
/* Выбрано что-то («В сети сейчас» свёрнут в строку): паспорт выбранного — целиком, уступает «Занято сейчас». */
.set-sprava:has(> #set-v-seti.set-svernut-blok) > #set-pasport { flex: 0 0 auto; }
.set-sprava:has(> #set-v-seti.set-svernut-blok) > #set-zanyato:last-child { flex: 1 1 0; }
/* Итог «Занято сейчас» по двум и больше тарелкам длиннее места в шапке: заголовок блока целиком, итог переносится справа. */
#set-zanyato > .flot-blok-head .ht { flex-shrink: 0; }
#set-zanyato > .flot-blok-head #zs-itog { min-width: 0; text-align: right; }
/* Слово Open ~17:45 и ~18:25: выбрано что-то — «В сети сейчас» одной строкой; выбрано устройство — и «Каналы»; паспорт целиком. */
.set-svod { display: none; }
.set-blok.set-svernut-blok { padding-top: 8px; padding-bottom: 8px; }
.set-blok.set-svernut-blok > :not(.set-svod) { display: none; }
.set-blok.set-svernut-blok > .set-svod { display: flex; align-items: baseline; gap: 8px; width: 100%; min-width: 0; padding: 0;
  border: 0; background: none; color: var(--ink); cursor: pointer; text-align: left; font: inherit; }
/* У первого блока колонки справа — кнопка «›» свернуть колонку: строке — отступ под неё. */
#set-v-seti.set-svernut-blok > .set-svod { padding-right: 28px; }
.set-svod > .ht { flex: none; }
.set-svod-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
.set-svernut-kn { margin-left: 6px; }
.set-blok:not(.set-svorachivaemyy) .set-svernut-kn { display: none; }
#set-kanaly { padding-top: 8px; padding-bottom: 8px; }
.kn-vhodov { flex: 0 0 auto; white-space: nowrap; }
.kn-zag-grafika { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; }
.kn-grafik-blok { position: relative; }
.kn-grafik-blok > .kn-zag-grafika { position: absolute; top: 0; left: 0; right: 0; pointer-events: none; line-height: 1.1; }
.kn-zag-grafika .kn-podpis { text-transform: none; letter-spacing: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kn-grafik .kn-summa { fill: none; stroke: var(--accent); stroke-width: 1.6; }
.kn-grafik .kn-liniya { fill: none; stroke-width: 1; stroke-opacity: .7; }
.kn-grafik .kn-liniya.starlink { stroke: var(--ok); }
.kn-grafik .kn-liniya.lte { stroke: #4C7DFF; }   /* LTE — синим, как клетка LTE «Карты сети» (1.01.03.01) */
.kn-grafik .kn-liniya.provod { stroke: var(--muted); }
.kn-vhod[data-daet="0"] .st12-kanal-polosa > i { width: 0 !important; }
.st12-spark.off { background: repeating-linear-gradient(90deg, var(--nv-line) 0 1px, transparent 1px 8px); }
/* Полоса: распорка отодвигает PIN, «терминал» и «Карта · Таблица» вправо; строка Н-183 — мелко, многоточием с подсказкой. */
.st12-raspor { flex: 1 1 0; min-width: 0; }
.set-polosa .st12-raspor ~ .set-terminal { margin-left: 0; }
.st12-nrn { font: 600 var(--t-xs) var(--nv-mono); color: var(--nv-cy); white-space: nowrap; }
.st12-183 { max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st12-pin { display: inline-flex; align-items: center; gap: 4px; font: 600 var(--t-xs) var(--nv-mono); color: var(--ok); white-space: nowrap; }
.st12-vid { display: flex; gap: 4px; }
.st12-koleso { white-space: nowrap; }
.st12-polosa-tablicy { margin: 12px 22px 0; }
/* Рамка карты: хозяин карты на всю рамку, «Выход в мир» — поверх, в правом верхнем углу (только NRL). */
.st12-ramka { position: relative; flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.st12-ramka > .karta-seti { flex: 1 1 auto; }
/* 1.72.25 (слово Open 13.10): NRL с местом RP5 по GPS — сеть на карте с рельефом поверх рисунка модуля (тот скрыт, но жив). */
.st12-nrl { font: 600 var(--t-xs) var(--nv-mono); color: var(--nv-cy); white-space: nowrap; }
.set-relef { position: absolute; inset: 0; z-index: 2; display: flex; flex-direction: column; isolation: isolate; }
.set-relef > .col { flex: 1 1 auto; height: 100%; min-height: 0; }
.set-relef .map-host { flex: 1 1 auto; height: 100%; min-height: 0; border-bottom: 0; }
.st12-ramka.v-relef > .karta-seti, .set-okno.v-relef > .karta-seti { visibility: hidden; }
.st12-vyhod { position: absolute; top: 8px; right: 8px; z-index: 3; cursor: pointer; max-width: min(420px, calc(100% - 16px)); }
.st12-vyhod .vm-y b, .st12-vyhod .vm-y i { max-width: 90px; overflow: hidden; text-overflow: ellipsis; }
.st12-vyhod-niz { margin-top: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Окно m-device */
.st12-okno-ustr { width: min(760px, calc(100vw - 40px)); }
.st12-ustr-telo { display: grid; grid-template-columns: minmax(0, 1fr) 150px; gap: 16px; align-items: start; }
.st12-ustr-kv { display: flex; flex-direction: column; min-width: 0; }
.st12-ustr-kv .set-kv > b { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st12-ustr-kv .set-kv.off { opacity: .5; }
.st12-ustr-krug { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.st12-grafik { height: 40px; border: 1px dashed var(--nv-line); padding: 4px 8px; }
.st12-chto { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; font-size: var(--t-xs); }
.st12-chto > div { display: flex; flex-direction: column; gap: 3px; }
.st12-okno-knopki { display: flex; justify-content: flex-end; gap: 8px; }
@media (max-width: 1279px) {
  .kh-set { grid-template-columns: 240px minmax(0, 1fr) 290px; }
  .kh-set.bez-slevoy { grid-template-columns: 28px minmax(0, 1fr) 290px; }
  .kh-set.bez-spravoy { grid-template-columns: 240px minmax(0, 1fr) 28px; }
  .st12-183 { max-width: 220px; }
  .st12-vyhod .vm-y b, .st12-vyhod .vm-y i { max-width: 60px; }
}

/* ═══ 1.72.11 · поток В · Отчёты (Н-190): шапка с периодом, сводка и таблица v12, приём снимков, ряд 2; окно m-export ═══ */
.kh-ot12 { flex: 1 1 0; min-height: 0; overflow: hidden; padding: 10px 14px 0; display: flex; flex-direction: column; gap: 10px; }
.kh-ot12 > * { flex-shrink: 0; }
.ot12-shapka { flex-wrap: nowrap; }
.ot12-shapka .dost-shapka-zag { flex: 1 1 auto; min-width: 0; }
.ot12-shapka-pod { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ot12-shapka .dost-shapka-pravee { flex: none; flex-wrap: nowrap; }
.ot12-period .pill, .ot12-okno .dost-segment .pill { padding: 3px 10px; font: 600 var(--t-xs) var(--nv-mono); text-transform: uppercase;
  letter-spacing: .04em; white-space: nowrap; }
.ot12-period .pill.off, .ot12-okno .pill.off { opacity: .5; }
.ot12-diap { font-size: var(--t-sm); white-space: nowrap; }
.ot12-ryad1 { flex: 1 1 0; min-height: 460px; display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 14px; }
.ot12-ryad2 { flex: 0 1 auto; min-height: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.ot12-ryad2 > .ot12-blok { min-height: 0; overflow: hidden; }
/* SAR и Drone — полосой по содержимому: каждый блок высотой в свои строки, не по соседу. */
.ot12-ryad3 { flex: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; align-items: start; }
/* «Приём снимков» — правой колонкой на высоту верха; слева «Сводка» высотой в свои строки, под ней MESH и LoRa забирают
   остаток: при одном терминале под таблицей не остаётся пустого поля, при многих графики не сжимаются в полоску. */
.ot12-verh { flex: 1 1 0; min-height: 0; display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 14px; }
.ot12-levo { display: flex; flex-direction: column; gap: 10px; min-height: 0; min-width: 0; }
.ot12-levo > .ot12-svodka { flex: 0 1 auto; min-height: 220px; }
.ot12-levo .ot12-tablica { flex: 0 1 auto; }
/* Строки — высотой в себя: до семи без прокрутки, предел по низу седьмой ставит reports.mjs (predelSvodki) — высота строки
   не постоянная, «Трафик» и «Главное» переносятся. Когда семь не входят в окно, уступают строки, а не MESH и LoRa:
   экран от 1440 по ширине не листается (приёмка 1.72.11), и низ ряда не должен обрезаться. */
.ot12-levo .ot12-stroki { flex: 0 1 auto; }
.ot12-levo > .ot12-ryad2 { flex: 1 1 auto; min-height: 200px; }
.ot12-levo .ot12-ryad2 > .ot12-blok { display: flex; flex-direction: column; }
.ot12-levo .ot12-lr-graf { flex: 1 1 40px; min-height: 40px; height: auto; }
/* Списки MESH и LoRa — окна прокрутки: не влезло — общий знак «ещё N», край не режет строку; подписи под ними — своим ростом, не режутся. */
.ot12-levo .ot12-ms-polosy { flex: 1 1 0; min-height: 14px; overflow-y: auto; scrollbar-width: thin; grid-auto-rows: minmax(14px, 1fr); }
.ot12-levo .ot12-lr-sobytiya { flex: 0 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; }
.ot12-levo .ot12-ryad2 > .ot12-blok > :not(.ot12-ms-polosy):not(.ot12-lr-graf):not(.ot12-lr-sobytiya) { flex: none; }
@media (max-width: 1400px) { .ot12-verh { flex: none; grid-template-columns: minmax(0, 1fr); } }
/* Н-521: смена периода — «читаю…» в панелях, экран на месте (ui/chtenie_paneley.mjs). */
.chitayu { position: relative; }
.chitayu > :not(.panel-chitayu) { opacity: .45; transition: opacity .15s; }
.panel-chitayu { position: absolute; top: 8px; right: 12px; z-index: 2; padding: 2px 8px; border-radius: 4px;
  background: var(--surface); border: 1px solid var(--hair); }
.panel-chitayu.s-critical { color: var(--critical); }
.ot12-blok { padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; min-width: 0; min-height: 0; }
.ot12-sar-str { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 8px; align-items: center; }
.kh-ot12 .ot12-golova .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
.ot12-golova .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
.ot12-golova > :last-child:not(.ht) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ot12-blok.off, .ot12-grafik.off, .ot12-stolbiki.off, .ot12-shtrih.off, .ot12-galka.off, .ot12-dve.off { opacity: .5; }
.ot12-blok.off .ot12-blok.off { opacity: 1; }
.ot12-svodka { overflow: hidden; }
.ot12-pokazateli { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; border-bottom: 1px solid var(--hair); padding-bottom: 8px; }
.ot12-pokazateli.tri { grid-template-columns: repeat(3, minmax(0, 1fr)); border-bottom: 0; }
.ot12-pok { display: flex; align-items: center; gap: 10px; padding: 0 10px; min-width: 0; border-left: 1px solid var(--hair); }
.ot12-pok:first-child { border-left: 0; padding-left: 0; }
.ot12-pok-t { display: flex; flex-direction: column; min-width: 0; flex: 0 1 auto; }
.ot12-pok-t > i { font-style: normal; font-size: var(--t-xs); color: var(--muted); overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
/* 1.72.26: подпись покрытия — причина целиком, в две строки, без многоточия. */
.ot12-pok-krug .ot12-pok-t > i { white-space: normal; text-overflow: clip; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
.ot12-pok-n > b { font: 600 var(--t-xl) var(--nv-mono); }
.ot12-pok-n > small { font: 400 var(--t-xs) var(--nv-mono); color: var(--muted); }
.ot12-pok > .ot12-grafik, .ot12-pok > .ot12-stolbiki { flex: 1 1 60px; min-width: 40px; }
.ot12-grafik { height: 30px; display: flex; align-items: center; }
.ot12-grafik > svg { width: 100%; height: 100%; display: block; }
.ot12-grafik.off { background: repeating-linear-gradient(90deg, var(--nv-line) 0 1px, transparent 1px 8px); }
.ot12-stolbiki { height: 30px; display: flex; align-items: flex-end; gap: 2px; }
.ot12-stolbiki > i { flex: 1 1 0; min-width: 1px; background: var(--accent); opacity: .8; }
.ot12-stolbiki.off > i { background: var(--nv-line); }
/* Н-309 (1.72.26): столбики простоя по суткам — цветом легенды (были синие при зелёной/жёлтой/красной легенде). */
.ot12-stolbiki > i.ot12-leg-ok { background: var(--ok); } .ot12-stolbiki > i.ot12-leg-warn { background: var(--warn); }
/* 1.72.27 (слово Open 14.10 — оранжевый): сутки без данных об обрывах — штриховка, не сплошной «до 30 мин». */
.ot12-stolbiki > i.ot12-leg-nd, .ot12-leg.nd { background: repeating-linear-gradient(135deg, var(--warn) 0 2px, transparent 2px 5px); }
.ot12-stolbiki > i.ot12-leg-kr { background: var(--critical); } .ot12-stolbiki > i.ot12-leg-silent { background: var(--muted); }
/* Число дня под клеткой суток; место под подписи — отступом снизу, чтобы высота столбиков не менялась. */
.ot12-stolbiki[data-dni] { margin-bottom: 12px; }
.ot12-stolbiki[data-dni] > i { position: relative; }
.ot12-stolbiki[data-dni] > i::after { content: attr(data-den); position: absolute; top: 100%; left: 0; right: 0; padding-top: 1px; text-align: center;
  font: 9px/11px var(--nv-mono, 'JetBrains Mono', monospace); color: var(--muted); background: none; overflow: hidden; white-space: nowrap; }
.ot12-tablica { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.ot12-tablica .head-cell { text-transform: uppercase; letter-spacing: .04em; }
.ot12-stroki { flex: 1 1 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
.ot12-str .cell { min-width: 0; display: flex; align-items: center; gap: 6px; }
/* Строка «Сводки» в одну строчку (слово 307): имя и «N назад» рядом, ячейки ниже — в окно 1707×932 входят шесть строк. */
.ot12-str > .cell { padding-top: 5px; padding-bottom: 5px; }
.ot12-imya { flex-direction: row; align-items: baseline !important; gap: 6px !important; }
.ot12-imya > div { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ot12-imya > div + div { flex: none; }
.ot12-imya > div + div::before { content: '· '; }
.ot12-pot > .ot12-grafik, .ot12-pr > .ot12-stolbiki { flex: 1 1 auto; min-width: 30px; height: 18px; }
.ot12-pot > span, .ot12-pr > span { flex: none; white-space: nowrap; }
/* Простой строки за сутки — полоса из 24 клеток по часам: клетка во всю высоту, цвет — по легенде; зазор в 1 px, чтобы часы
   читались по отдельности. За 30 суток клеток нет — «—» с причиной в подсказке. */
.ot12-pr > .ot12-stolbiki.ot12-chasy { gap: 1px; align-items: stretch; }
.ot12-pr > .ot12-pr-net { flex: 1 1 auto; min-width: 30px; }
/* Drone — пунктирной рамкой: «в этой версии нет», а не «данных нет». */
.ot12-blok.ot12-punktir { border: 1px dashed var(--nv-line); }
/* Главное за период — одна строка; колонка широкая, многоточие — редкий случай, полный текст — в отчёте терминала по нажатию на строку. */
.ot12-glavnoe > span { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; line-height: 1.2; }
.ot12-glavnoe > svg { flex: none; }
.ot12-legenda { display: flex; flex-wrap: wrap; gap: 4px 14px; padding-top: 6px; }
.ot12-legenda > span { display: inline-flex; align-items: center; gap: 5px; }
.ot12-leg { display: inline-block; width: 3px; height: 10px; }
.ot12-leg.ok { background: var(--ok); } .ot12-leg.warn { background: var(--warn); } .ot12-leg.kr { background: var(--critical); }
.ot12-leg.silent { background: var(--muted); }
.ot12-shtrih { margin-left: auto; }
.ot12-priyom-grafik { flex: 1 1 auto; min-height: 60px; border: 1px dashed var(--nv-line); display: grid; place-items: center; }
#ot12-priyom:not(.off) .ot12-priyom-grafik { border: 0; display: block; flex: 1 1 auto; min-height: 170px; }
.ot12-pr-ramka { display: flex; flex-direction: column; width: 100%; height: 100%; }
.ot12-pr-sobytiya { position: relative; flex: none; height: calc(var(--ryadov, 3) * 18px + 6px); margin-left: 34px; }
.ot12-pr-metka { position: absolute; top: calc(var(--ryad) * 18px); transform: translateX(-1px); border-left: 1px dashed var(--warn);
  height: calc((var(--ryadov, 3) - var(--ryad)) * 18px + 6px); padding-left: 4px; line-height: 16px; font-size: var(--t-xs); color: var(--warn); white-space: nowrap; }
.ot12-pr-metka span { position: relative; z-index: 1; background: var(--surface); padding: 0 2px; }
.ot12-pr-metka.server { color: var(--accent); border-left-color: var(--accent); }
.ot12-pr-metka.vlevo { transform: translateX(-100%); border-left: 0; border-right: 1px dashed var(--warn); padding: 0 4px 0 0; }
.ot12-pr-metka.server.vlevo { border-right-color: var(--accent); }
.ot12-pr-metka.sejchas { color: var(--muted); border-right-color: var(--muted); }
.ot12-pr-telo { position: relative; flex: 1 1 auto; display: grid; grid-template-columns: 34px 1fr; grid-template-rows: minmax(150px, 1fr) auto; }
.ot12-pr-osy { position: relative; }
.ot12-pr-osy > span { position: absolute; right: 6px; transform: translateY(-50%); font-size: var(--t-sm); color: var(--muted); font-family: var(--mono, monospace); }
.ot12-pr-pole { position: relative; border-left: 1px solid var(--nv-line); border-bottom: 1px solid var(--nv-line); }
.ot12-pr-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ot12-pr-setka { stroke: var(--nv-line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.ot12-pr-srazu { fill: color-mix(in srgb, var(--accent) 22%, transparent); }
.ot12-pr-iz { fill: color-mix(in srgb, var(--teal) 75%, transparent); }
.ot12-pr-liniya { fill: none; stroke: var(--accent); stroke-width: 2; vector-effect: non-scaling-stroke; }
.ot12-pr-shtrih { stroke: var(--warn); stroke-width: 2; vector-effect: non-scaling-stroke; }
.ot12-pr-pusto { fill: none; stroke: var(--muted); stroke-width: 2; stroke-dasharray: 4 4; vector-effect: non-scaling-stroke; }
.ot12-pr-dni { position: absolute; inset: 0; display: flex; }
.ot12-pr-dni > i { flex: 1 1 0; }
.ot12-pr-dni > i:hover { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.ot12-pr-osx { grid-column: 2; position: relative; height: 20px; }
.ot12-pr-osx > span { position: absolute; top: 4px; font-size: var(--t-sm); color: var(--muted); font-family: var(--mono, monospace); }
.ot12-pr-leg { display: inline-block; width: 10px; height: 8px; }
.ot12-pr-leg.srazu { background: var(--accent); } .ot12-pr-leg.iz { background: var(--teal); }
.ot12-pr-leg.nd { background: repeating-linear-gradient(135deg, var(--warn) 0 2px, transparent 2px 5px); }
.ot12-pr-stupen { margin-left: auto; }
.ot12-lr-verh { display: flex; gap: 14px; align-items: center; }
.ot12-lr-stroki { flex: 1 1 auto; display: grid; gap: 4px; min-width: 0; }
.ot12-lr-str { display: flex; justify-content: space-between; gap: 8px; font-size: var(--t-sm); }
.ot12-lr-graf-zag { display: flex; justify-content: space-between; align-items: baseline; margin-top: 8px; font-size: var(--t-xs); }
.ot12-lr-graf { height: 40px; border-bottom: 1px solid var(--nv-line); }
.ot12-lr-svg { width: 100%; height: 100%; display: block; }
.ot12-lr-liniya { fill: none; stroke: var(--accent); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.ot12-lr-liniya.nepolnye { stroke-dasharray: 4 3; opacity: .7; }
.ot12-lr-sobytiya { display: grid; gap: 4px; margin-top: 8px; font-size: var(--t-xs); }
.ot12-lr-sob { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ot12-lr-sob.gluhota { color: var(--warn); }
.ot12-lr-sob.sos { color: var(--critical); font-weight: 600; }
.ot12-ms-polosy { display: grid; gap: 3px; margin-top: 10px; }
.ot12-ms-stroka { display: grid; grid-template-columns: 124px 1fr; align-items: center; gap: 6px; }
.ot12-ms-imya { font-size: var(--t-xs); color: var(--muted); font-family: var(--mono, monospace); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ot12-ms-dni { display: grid; grid-template-columns: repeat(var(--dney), 1fr); gap: 2px; height: 12px; }
.ot12-ms-dni > i { display: block; }
.ot12-ms-dni > i.ok { background: var(--ok); } .ot12-ms-dni > i.chast { background: var(--warn); }
.ot12-ms-dni > i.propala { background: var(--critical); }
.ot12-ms-dni > i.net { background: repeating-linear-gradient(135deg, var(--muted) 0 1px, transparent 1px 4px); opacity: .6; }
.ot12-ms-osx { position: relative; height: 16px; margin-left: 130px; }
.ot12-ms-osx > span { position: absolute; top: 2px; font-size: var(--t-xs); color: var(--muted); font-family: var(--mono, monospace); }
.ot12-ms-sob { display: grid; font-size: var(--t-xs); }
.ot12-ms-sob.warn > b { color: var(--warn); }
.ot12-snoska-priyom { line-height: 1.45; color: var(--ink); }
.ot12-knopki { display: flex; gap: 6px; flex-wrap: wrap; margin-top: auto; }
.ot12-mal { padding: 3px 8px; font-size: var(--t-xs); white-space: nowrap; }
/* Окно m-export */
.ot12-okno { width: min(640px, calc(100vw - 40px)); }
.ot12-period-str { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.ot12-razdely { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 14px; }
.ot12-galka { display: flex; align-items: center; gap: 6px; font-size: var(--t-sm); min-width: 0; }
.ot12-galka > input { width: auto !important; margin: 0; }
.ot12-galka > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ot12-dve { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-height: 960px) {
  .kh-ot12 { gap: 8px; padding-top: 8px; }
  .ot12-ryad1, .ot12-ryad2, .ot12-ryad3 { gap: 10px; }
  .ot12-pok-n > b { font-size: var(--t-lg, 1.1rem); }
}
/* ≤ 1400 px (1366×768, 1152×700): ряд 2 — по два блока, экран листается своей прокруткой; документ — нет.
   Порог 1400, а не 1500 из плана (п. 8 раздела В): при 1500 окно 1440×900 тоже попало бы сюда, и экран в нём листался бы,
   а приёмка 1.72.11 требует в 1440×900 один экран без прокрутки. Решение главного 09.10 — оставить 1400. */
@media (max-width: 1400px) {
  .kh-ot12 { overflow-y: auto; }
  .ot12-ryad1 { flex: none; grid-template-columns: minmax(0, 1fr); }
  .ot12-ryad1 .ot12-svodka { height: 520px; }
  .ot12-ryad2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ot12-shapka { flex-wrap: wrap; }
}
@media (max-width: 1279px) {
  .ot12-pokazateli { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 8px; }
  .ot12-pok:nth-child(3) { border-left: 0; padding-left: 0; }
}

/* ═══ 1.72.11 · поток В · Уведомления (Н-187): счётчики и шкала часа, лента v12 по событиям, справа правила, звук, лестница ═══ */
.kh-uv12 { flex: 1 1 0; min-height: 0; overflow: hidden; display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 14px; padding: 10px 14px 0; }
.uv12-seredina { display: flex; flex-direction: column; gap: 10px; min-height: 0; min-width: 0; }
.uv12-sprava { display: flex; flex-direction: column; gap: 12px; min-height: 0; min-width: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
.uv12-sprava > * { flex: none; }
.uv12-blok { padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.kh-uv12 .uv12-golova .ht::before { content: '»'; margin-right: 6px; color: var(--nv-cy); font-weight: 700; }
.uv12-golova .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); white-space: nowrap; }
.uv12-golova > :last-child:not(.ht):not(.uv12-lenta-pravee) { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv12-svod { flex: none; display: grid; grid-template-columns: minmax(260px, 340px) minmax(0, 1fr); gap: 16px; align-items: start; }
.uv12-svod-chisla { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.uv12-chisla { display: flex; gap: 18px; flex-wrap: wrap; }
.uv12-chislo { display: grid; grid-template-columns: auto auto; grid-template-rows: auto auto; column-gap: 6px; align-items: center; }
.uv12-chislo > svg { grid-row: 1; }
.uv12-chislo > span { grid-column: 1 / 3; }
.uv12-chislo-n { font: 600 var(--t-dsp, 28px) var(--nv-mono); line-height: 1; }
.uv12-avaria { color: var(--critical); } .uv12-zamech { color: var(--warn); } .uv12-sved { color: var(--nv-cy); }
.uv12-svod-chisla .uv12-sved, .uv12-chislo-n.uv12-sved { color: var(--nv-cy); }
/* График событий (alerts.mjs grafikBlok): дорожки во всю ширину правой части шапки; полосы — по времени строк ленты. */
.uvg { position: relative; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.uvg-shapka { display: flex; align-items: center; gap: 10px; min-width: 0; }
.uvg-shapka > .hl { white-space: nowrap; }
.uvg-schet { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uvg-okna { display: flex; gap: 2px; flex: none; }
.uvg-okno { border: 1px solid var(--nv-line); background: none; color: var(--muted); padding: 1px 8px; cursor: pointer;
  font: 600 var(--t-xs) var(--nv-mono); white-space: nowrap; }
.uvg-okno[aria-pressed="true"] { color: var(--nv-cy); border-color: var(--nv-cy); }
.uvg-pole { position: relative; display: flex; flex-direction: column; gap: 3px; cursor: grab; user-select: none; }
.uvg-pole:active { cursor: grabbing; }
.uvg-dorozhka { display: grid; grid-template-columns: 86px minmax(0, 1fr); gap: 8px; align-items: center; height: 18px; }
.uvg-dorozhka > .hl { text-align: right; }
.uvg-trek { position: relative; height: 18px; border-bottom: 1px dashed var(--hair); overflow: hidden; }
.uvg-bar { position: absolute; top: 3px; height: 12px; min-width: 6px; padding: 0 4px; border: 0; border-radius: 2px; cursor: pointer;
  background: color-mix(in srgb, currentColor 35%, transparent); box-shadow: inset 0 0 0 1px currentColor; overflow: hidden;
  display: flex; align-items: center; }
.uvg-bar.zhdyot { background: color-mix(in srgb, currentColor 60%, transparent); }
.uvg-bar.idyot { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.uvg-bar:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.uvg-avaria { color: var(--critical); } .uvg-zamech { color: var(--warn); } .uvg-sved, .uvg-sar { color: var(--nv-cy); }
.uvg-podp-vnutri { font: 600 var(--t-xs) var(--nv-mono); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 12px; }
.uvg-podp { position: absolute; top: 2px; font: 600 var(--t-xs) var(--nv-mono); white-space: nowrap; pointer-events: none; }
.uvg-os { position: relative; height: 16px; margin-left: 94px; border-top: 1px solid var(--nv-line); }
.uvg-os > span { position: absolute; top: 2px; transform: translateX(-50%); font: 400 var(--t-xs) var(--nv-mono); color: var(--muted); white-space: nowrap; }
.uvg-os > .uvg-seychas { transform: translateX(-100%); color: var(--accent); }
.uvg-zum { position: absolute; right: 0; top: -2px; color: var(--accent); }
.uvg-karta { position: absolute; z-index: 30; min-width: 200px; max-width: 320px; padding: 6px 9px; display: flex; flex-direction: column; gap: 2px;
  background: var(--surface); border: 1px solid var(--nv-line); box-shadow: 0 4px 14px rgba(0, 0, 0, .35); font-size: var(--t-xs); pointer-events: none; }
.uvg-karta[hidden] { display: none; }
.uv12-str.uvg-podsvet, .uv12-sv.uvg-podsvet { box-shadow: inset 3px 0 0 var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
@media (prefers-reduced-motion: no-preference) {
  .uv12-str, .uv12-sv { transition: background-color .3s; }
}
.uv12-lenta-blok { flex: 1 1 0; min-height: 0; }
.uv12-lenta-pravee { display: flex; align-items: center; gap: 8px; min-width: 0; }
.uv12-vkladki { display: flex; gap: 2px; flex-wrap: nowrap; }
.uv12-vkl { border: 0; border-bottom: 2px solid transparent; background: none; color: var(--muted); padding: 3px 8px; cursor: pointer;
  font: 600 var(--t-xs) var(--nv-mono); text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; }
.uv12-vkl[aria-selected="true"] { color: var(--nv-cy); border-bottom-color: var(--nv-cy); }
.uv12-vkl:disabled { opacity: .45; cursor: not-allowed; }
/* Время — «ЧЧ:ММ» или «ЧЧ:ММ UTC» (часы экрана не компании — закон поясов, Н-196): колонка вмещает пометку UTC. */
.uv12-kolonki, .uv12-str { display: grid; grid-template-columns: 96px minmax(150px, 1.1fr) minmax(120px, .9fr) minmax(0, 1.3fr) minmax(0, 1.3fr) 118px;
  gap: 10px; }
.uv12-kolonki { border-bottom: 1px solid var(--hair); padding-bottom: 4px; }
.uv12-lenta-skroll { flex: 1 1 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
.uv12-razdel { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; padding: 8px 0 4px; border-bottom: 1px solid var(--hair); }
.uv12-razdel.r-avaria > .hl { color: var(--critical); }
.uv12-str { padding: 8px 0; border-bottom: 1px solid var(--hair); align-items: start; }
.uv12-str.r-avaria.zhdyot { background: color-mix(in srgb, var(--critical) 7%, transparent); box-shadow: inset 2px 0 0 var(--critical); }
.uv12-vremya { display: grid; grid-template-columns: 16px auto; column-gap: 4px; align-items: center; }
.uv12-vremya > i { grid-column: 2; font-style: normal; }
.uv12-vremya > b { white-space: nowrap; }
.uv12-chto, .uv12-gde { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.uv12-zag { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv12-chto > i { font-style: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv12-chto > .uv12-teg { align-self: flex-start; }
.uv12-gde > span { font-size: var(--t-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv12-minikarta { gap: 3px; }
/* Мини-карта «Где»: точка по центру на сетке (без подложки) или на тени рельефа. */
.uv12-mk { position: relative; width: 96px; height: 48px; flex: none; padding: 0; cursor: pointer; border: 1px solid var(--nv-line);
  background-color: var(--surface); background-repeat: no-repeat;
  background-image: linear-gradient(var(--hair) 1px, transparent 1px), linear-gradient(90deg, var(--hair) 1px, transparent 1px);
  background-size: 12px 12px; }
.uv12-mk.s-podlozhkoy { background-size: auto; }
.uv12-mk:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.uv12-mk-tochka { position: absolute; left: 50%; top: 50%; width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%;
  background: var(--nv-cy); box-shadow: 0 0 0 2px var(--surface); }
.uv12-mk-avaria .uv12-mk-tochka { background: var(--critical); } .uv12-mk-zamech .uv12-mk-tochka { background: var(--warn); }
.uv12-mk-niz { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
.uv12-mk-niz > span { font-size: var(--t-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.uv12-minikarta.off { opacity: .55; }
/* Широкое окно (слово Open по 372 а): рамка 220×100, как в v12, — плитка рельефа по центру точки, значок уровня и имя устройства;
   колонка «Где» 228 px. Узкое окно — прежняя маленькая рамка, чтобы в ленте помещались четыре аварии. */
.uv12-mk-znak, .uv12-mk-imya, .uv12-mk-mesto { display: none; }
@media (min-width: 1501px) {
  .uv12-kolonki, .uv12-str { grid-template-columns: 96px minmax(150px, 1.1fr) 228px minmax(0, 1.3fr) minmax(0, 1.3fr) 118px; }
  .uv12-mk { width: 220px; height: 100px; }
  .uv12-mk.s-podlozhkoy { background-position: calc(110px - var(--mk-px)) calc(50px - var(--mk-py)) !important; }
  .uv12-mk-tochka { display: none; }
  .uv12-mk-znak { display: block; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); line-height: 0;
    filter: drop-shadow(0 0 4px var(--surface)); }
  .uv12-mk-imya { display: block; position: absolute; left: 6px; right: 6px; bottom: 4px; text-align: center; font: 600 var(--t-xs) var(--nv-mono);
    color: var(--ink); text-shadow: 0 0 3px var(--surface), 0 0 3px var(--surface); white-space: nowrap; overflow: hidden; }
  .uv12-mk-imya.s-mestom { bottom: 18px; }
  .uv12-mk-mesto { display: block; position: absolute; left: 6px; right: 6px; bottom: 4px; text-align: center; font: 500 var(--t-xs) var(--nv-mono);
    color: var(--muted); text-shadow: 0 0 3px var(--surface), 0 0 3px var(--surface); white-space: nowrap; overflow: hidden; }
}
.uv12-znachit, .uv12-delat { min-width: 0; line-height: 1.4; overflow-wrap: anywhere; }
.uv12-knopki { display: flex; flex-direction: column; gap: 4px; align-items: stretch; }
.uv12-mal { display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 3px 8px; font-size: var(--t-xs); white-space: nowrap; }
.uv12-prinyato { display: flex; align-items: flex-start; gap: 5px; color: var(--ok); font-size: var(--t-xs); }
.uv12-vzyal { display: flex; align-items: flex-start; gap: 5px; color: var(--warn); font-size: var(--t-xs); }
.uv12-minikarta-okno { grid-column: 1 / -1; height: 220px; margin-top: 6px; border: 1px solid var(--hair); }
.uv12-prinyato > div { display: flex; flex-direction: column; }
.uv12-str.r-avaria.zhdyot.proveryaem { background: color-mix(in srgb, var(--warn) 9%, transparent); box-shadow: inset 2px 0 0 var(--warn); }
.uv12-proveryaem, .ok-proveryaet { display: inline-flex; align-items: center; gap: 5px; color: var(--warn); font-size: var(--t-xs); }
.uv12-teg { font: 600 var(--t-xs) var(--nv-mono); letter-spacing: .04em; text-transform: uppercase; padding: 1px 6px; border: 1px solid currentColor;
  white-space: nowrap; }
.uv12-teg.avaria { color: var(--critical); } .uv12-teg.zamech, .uv12-teg.dengi { color: var(--warn); }
.uv12-teg.sved, .uv12-teg.info { color: var(--nv-cy); } .uv12-teg.ok { color: var(--ok); }
.uv12-teg.problema { color: var(--warn); }
/* Сжатая лента (низкое окно, alerts.mjs): строка — заголовок и терминал, «что значит» и «что делать» по одной строке, из кнопок —
   «Принять»; щелчок по строке раскрывает её (.raskryt). Полный текст — и в подсказке заголовка. */
.uv12-szhato .uv12-str:not(.raskryt) { cursor: pointer; padding: 5px 0; }
.uv12-szhato .uv12-str:not(.raskryt) .uv12-zag { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.uv12-szhato .uv12-str:not(.raskryt) :is(.uv12-znachit, .uv12-delat) { display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; white-space: normal; }
.uv12-szhato .uv12-str:not(.raskryt) :is(.uv12-chisla-str, .uv12-vremya > i, .uv12-chto > .uv12-teg, .uv12-povtor) { display: none; }
.uv12-szhato .uv12-str:not(.raskryt) .uv12-znachit > :not(:first-child) { display: none; }
.uv12-szhato .uv12-str:not(.raskryt) .uv12-knopki > button:not([data-prinyat]):not([data-proveryat]) { display: none; }
.uv12-szhato .uv12-str:not(.raskryt) .uv12-mk { display: none; }
.uv12-sved-setka { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 18px; }
.uv12-sv { display: grid; grid-template-columns: 16px 46px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 6px 0; border-bottom: 1px solid var(--hair); }
.uv12-sv[role="button"] { cursor: pointer; }
.uv12-sv-t { min-width: 0; display: flex; flex-direction: column; }
.uv12-sv-t > div, .uv12-sv-t > i { overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; font-style: normal; }
.uv12-pr { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 4px 0; border-bottom: 1px solid var(--hair); }
.uv12-pr:not(.aktivno) > svg { opacity: .45; }
.uv12-pr.off { opacity: .5; }
.uv12-pr-t { display: flex; flex-direction: column; min-width: 0; }
.uv12-pr-t > b { font-weight: 500; font-size: var(--t-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv12-pr-t > i { font-style: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.uv12-eshche-pravil { align-self: flex-start; margin-top: 4px; }
.uv12-okno-pravil { width: min(720px, calc(100vw - 40px)); }
.uv12-okno-spisok { max-height: calc(100vh - 260px); overflow-y: auto; scrollbar-width: thin; }
.uv12-gromkost { display: grid; grid-template-columns: auto minmax(60px, 1fr) auto auto; gap: 8px; align-items: center; }
.uv12-gromkost input[type=range] { width: 100%; accent-color: var(--nv-cy); }
/* 1.72.25 (Н-295): ползунок своего цвета; подписи одной ширины, чтобы три ползунка стояли ровно. */
.zvuk-cvet { grid-template-columns: 5.5em minmax(60px, 1fr) auto auto; margin: 2px 0; }
.zvuk-cvet > .hl { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zvuk-red input[type=range] { accent-color: var(--critical); }
.zvuk-yellow input[type=range] { accent-color: var(--warn); }
.zvuk-green input[type=range] { accent-color: var(--ok); }
.zvuk-zablokirovan { background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline dotted; font-family: inherit; color: var(--warn); }
.uv12-snoska { line-height: 1.45; }
.uv12-snoska.off { opacity: .5; }
.uv12-stupen { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 4px 0; }
.uv12-stupen-n { width: 20px; height: 20px; display: grid; place-items: center; font: 600 var(--t-xs) var(--nv-mono); border: 1px solid var(--ok);
  color: var(--ok); }
.uv12-stupen.plan .uv12-stupen-n { border-style: dashed; border-color: var(--muted); color: var(--muted); }
@media (max-height: 960px) {
  .kh-uv12 { padding-top: 8px; gap: 10px; }
  .uv12-sprava { gap: 10px; }
  .uv12-blok { padding: 8px 12px; gap: 4px; }
  .uv12-pr { padding: 3px 0; }
}
/* ≤ 1500: правая колонка уже; ≤ 1279: «что значит» и «что делать» друг под другом, рамки мини-карты нет — место строкой. */
@media (max-width: 1500px) {
  .kh-uv12 { grid-template-columns: minmax(0, 1fr) 320px; }
  .uv12-svod { grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); }
}
@media (max-width: 1279px) {
  .kh-uv12 { grid-template-columns: minmax(0, 1fr) 260px; }
  .uv12-kolonki, .uv12-str { grid-template-columns: 92px minmax(130px, 1fr) minmax(90px, .7fr) minmax(0, 1.6fr) 104px; }
  .uv12-kolonki > :nth-child(5) { display: none; }
  .uv12-str > .uv12-znachit { grid-column: 4; grid-row: 1; }
  .uv12-str > .uv12-delat { grid-column: 4; grid-row: 2; }
  .uv12-str > .uv12-knopki { grid-column: 5; grid-row: 1 / 3; }
  .uv12-sved-setka { grid-template-columns: minmax(0, 1fr); }
  .uv12-svod { grid-template-columns: minmax(0, 1fr); }
}




/* ── 1.72.11 · главный · общая часть 2: окно v12 (ui/okno_v12.mjs) ── */
/* Окно целиком не листается: тело — своей прокруткой, низ с кнопками виден всегда (1152×700 тоже). */
.ok12 { overflow: hidden; }
.ok12 > .ok12-telo { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.ok12 > .ok-shapka, .ok12 > .ok12-podzag, .ok12 > .ok12-niz { flex: none; }
.ok12-podzag { margin-top: -4px; }
.ok12-zametka.zh { border-left-color: var(--warn, #d9a400); background: color-mix(in srgb, var(--warn, #d9a400) 8%, transparent); }
.ok12-pole { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ok12-pole[hidden] { display: none; }
.ok12-polya { display: grid; gap: 8px 14px; }
.ok12-polya.k2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ok12-polya.k3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 720px) { .ok12-polya.k2, .ok12-polya.k3 { grid-template-columns: minmax(0, 1fr); } }
.ok12-summa { display: flex; align-items: stretch; }
.modal .ok12-summa .ok12-summa-vvod { flex: 1 1 auto; min-width: 0; width: auto; font-variant-numeric: tabular-nums; }
.modal .ok12-summa .ok12-summa-val { flex: none; width: auto; display: inline-flex; align-items: center; padding: 0 10px; border: 1px solid var(--nv-line); border-left: 0; }
.ok12-chipy { flex-wrap: wrap; }
.ok12-chto-budet { border: 1px dashed var(--nv-line); padding: 8px 12px; }
.ok12-chto-budet ul { margin: 4px 0 0; padding-left: 18px; }
/* ── 1.72.11 · главный · Техподдержка v12 (m-support, ui/podderzhka.mjs) ── */
.ok12.ps12 { width: min(1080px, calc(100vw - 40px)); }
.ps12-setka { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 18px; }
@media (max-width: 860px) { .ps12-setka { grid-template-columns: minmax(0, 1fr); } }
.ps12-kol { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ps12-golova { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; border-bottom: 1px solid var(--hair); padding-bottom: 4px; }
.ps12-golova .ht { font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; }
.ps12-str { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 10px; align-items: baseline; font-size: var(--t-sm); }
.ps12-str.off { opacity: .5; }
.ps12-v { overflow-wrap: anywhere; }
.ps12-vlozheniya { display: flex; flex-wrap: wrap; gap: 6px; }
.modal textarea.ps12-pole { width: 100%; box-sizing: border-box; resize: vertical; font-size: var(--t-sm); font-family: inherit; }
.ps12-bufer { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.ok12.ps12 .podderzhka-kontakty { display: flex; flex-wrap: wrap; gap: 6px 18px; font-size: var(--t-sm); }
/* Контакт — текстом, а не полем ввода на вид: поле только ради выделения и копирования. */
.ok12.ps12 .podderzhka-kontakty .kv { display: inline-flex; align-items: center; gap: 6px; }
.ok12.ps12 .podderzhka-kontakty .kontakt-pole { border: 0; background: transparent; color: inherit; font: inherit; padding: 0; width: auto; }
/* ═══ 1.72.11 · поток В · Настройки · «движение» (ui/prefs.mjs → data-dvizhenie на <html>) и Уведомления · свёрнутая колонка ═══ */
/* «выкл» — стоит всё: анимации на паузе, переходы мгновенные. «только тревоги» — пульсируют только волны под проблемными
   терминалами (.sl-ripple) и «дыхание» проблемы на мачте NRL (.m12-trevoga), остальное на паузе. Рисунок карты сети (тень) —
   неподвижным кадром: karta/karta_seti.mjs. */
:root[data-dvizhenie="vykl"] *, :root[data-dvizhenie="vykl"] *::before, :root[data-dvizhenie="vykl"] *::after {
  animation-play-state: paused !important; transition: none !important; }
:root[data-dvizhenie="trevogi"] *:not(.sl-ripple):not(.m12-trevoga), :root[data-dvizhenie="trevogi"] *::before, :root[data-dvizhenie="trevogi"] *::after {
  animation-play-state: paused !important; }
button.na12-dv { background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
button.na12-dv:hover { border-color: var(--nv-line); }
/* «Уведомления»: правая колонка сворачивается (prefs uvSpravaSvern), как колонки «Карты сети». */
.kh-uv12.bez-spravoy { grid-template-columns: minmax(0, 1fr) 28px; }
.uv12-sprava { position: relative; }
.uv12-sprava > .set-svernut { position: absolute; top: 8px; right: 8px; z-index: 2; }
.uv12-sprava > .uv12-blok:first-of-type .uv12-golova { padding-right: 28px; }

/* ── 1.72.11 · поток А · LoRa ── (PLAN-1.72.11 раздел А, LoRa: раскладка v12 на общих классах MESH me12-*) */
.lo12-str { grid-template-columns: minmax(0, 1fr) 44px 64px; }
.lo12-krug { width: 10px; height: 10px; flex: none; border-radius: 50%; border: 2px solid var(--kl-sluzh); }
.lo12-krug.warn { border-color: var(--warn); } .lo12-krug.silent { border-color: var(--critical); border-style: dashed; }
.lo12-zaryad { display: flex; align-items: center; justify-content: flex-end; gap: 4px; }
.lo12-polosa-z { width: 22px; height: 8px; border: 1px solid currentColor; display: inline-block; }
.lo12-polosa-z > i { display: block; height: 100%; background: currentColor; }
.lo12-shlyuzy { display: inline-flex; gap: 4px; align-items: center; min-width: 0; }
.lo12-shlyuz-knopka { display: inline-flex; gap: 4px; align-items: center; }
.lo12-shlyuz-knopka.on { border-color: var(--nv-cy); }
.lo12-diapazony { display: inline-flex; gap: 10px; }
.lo12-ik-shlyuz { color: var(--kl-lora-shlyuz); }
.sl-mesh-liniya.m-oranzh { stroke: color-mix(in srgb, var(--warn) 55%, var(--critical)); }
.me12-holst .m-svyaz.lo12-ok { stroke: var(--kl-svyaz); } .me12-holst .m-svyaz.lo12-sred { stroke: var(--warn); }
.me12-holst .m-svyaz.lo12-slab { stroke: var(--critical); } .me12-holst .m-svyaz.lo12-net { stroke: var(--kl-sluzh); opacity: .55; }
.me12-holst .m-svyaz.lo12-davno { stroke: color-mix(in srgb, var(--warn) 55%, var(--critical)); stroke-dasharray: 6 5; }
.me12-holst .m-svyaz.lo12-propal { stroke: var(--critical); stroke-dasharray: 3 5; opacity: .7; }
.me12-holst .lo12-shlyuz { stroke: var(--kl-lora-shlyuz); fill: color-mix(in srgb, var(--kl-lora-shlyuz) 22%, var(--surface)); filter: drop-shadow(0 0 6px var(--kl-lora-shlyuz)); }
.me12-holst .m-uzel.lo12-t { stroke: var(--kl-sluzh); fill: color-mix(in srgb, var(--kl-sluzh) 22%, var(--surface)); }
.me12-holst .m-uzel.lo12-t.warn { stroke: var(--warn); } .me12-holst .m-uzel.lo12-t.silent { stroke: var(--muted); stroke-dasharray: 3 3; }
/* 1.72.25 (Н-298): нет данных от шлюза — серым, без тревоги; круг точности огрублённого места (LoRa [2]). */
.lo12-krug.nodata { border-color: var(--critical); border-style: dotted; }
.me12-holst .m-uzel.lo12-t.nodata { stroke: var(--critical); stroke-dasharray: 1 3; fill: var(--surface); }
/* 1.72.27 (слово Open 14.10: серый не использовать): серая вторая строка «нет данных от шлюза» снята — красным классом s-critical. */
.sl-krug-tochnosti { stroke: var(--muted); stroke-dasharray: 4 4; fill: var(--muted); fill-opacity: .08; }
/* L1: место за экраном — плашка у края в его сторону (ui/strelki_kraya.mjs). */
.sl-strelka-kraya { position: absolute; z-index: 650; transform: translate(-50%, -50%); background: var(--surface);
  border: 1px solid var(--line, var(--muted)); border-radius: 10px; padding: 1px 7px; font-size: var(--t-xs); color: var(--muted);
  white-space: nowrap; cursor: pointer; }
.sl-strelka-kraya .sl-strelka-ugol { display: inline-block; }
/* Н-393: пропавший за краем (молчит дольше суток) — красной плашкой: его ищут. */
.sl-strelka-kraya.propal { color: var(--critical); border-color: var(--critical); font-weight: 600; }
/* 1.01.02.08: блок порога и «выключен» в карточке трекера — поля во всю ширину столбца, кнопка своей строкой. */
.lo12-otmetka input { width: 100%; box-sizing: border-box; }
.lo12-vykl { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
/* ═══ LoRa · карточка трекера: имя → строка состояния → четыре плитки → Место → Путь → Тревога, если молчит → Человек;
   сообщения — своим блоком ниже. Каждый блок — своей полосой с заголовком; подписи и кнопки переносятся, а не режутся справа
   (колонка узкая, многоточие прятало конец подписи). ═══ */
/* Плитки карточки трекера — сеткой 2 × 2 (SNR · заряд / пересылок · шлюз, лист 4 макета; З-6): в четыре колонки «пересылок» рвался посреди слова. */
.lo12-plitki { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin: 6px 0; }
/* «Показать» и «Копировать» — одной строкой под подписью места (З-7): подпись занимает свою строку целиком. */
.lo12-kartochka-trekera .mesto > .mesto-tekst { flex-basis: 100%; }
.lo12-plitka { border: 1px solid var(--line); padding: 6px 8px; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lo12-plitka.shir { grid-column: span 2; }
.lo12-pl-metka { font-size: var(--t-xs); overflow-wrap: anywhere; }
.lo12-plitka > b { font-weight: 600; font-size: var(--t-sm); overflow-wrap: anywhere; }
.lo12-pl-pod { font-size: var(--t-xs); color: var(--muted); overflow-wrap: anywhere; }
.lo12-pl-polosa { height: 4px; background: var(--hair); margin-top: 2px; }
.lo12-pl-polosa > i { display: block; height: 100%; background: currentColor; }
.lo12-k-blok { border-top: 1px solid var(--line); padding: 8px 0 4px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.lo12-k-zag { font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); }
/* Паспорт «Линия связи»: трекер —— шлюз, над линией расстояние и хопы, под ней сигнал; волна идёт от трекера к шлюзу. */
.lo12-linia { display: flex; flex-direction: column; gap: 2px; margin: 6px 0 2px; min-width: 0; }
.lo12-ln-kontsy { display: flex; justify-content: space-between; gap: 8px; }
.lo12-ln-nad, .lo12-ln-pod { text-align: center; overflow-wrap: anywhere; }
/* Линия сигнала (слово Open ≈18:48): прямая, по ней бежит точка-сигнал от трекера к шлюзу; связи нет — линия тихая, без точки. */
.lo12-ln-svg { display: flex; align-items: center; gap: 4px; height: 24px; }
.lo12-ln-treker { width: 12px; height: 12px; border-radius: 50%; background: var(--nv-cy); flex: none; }
.lo12-ln-shlyuz { width: 12px; height: 12px; border: 1.6px solid var(--nv-cy); box-sizing: border-box; flex: none; }
.lo12-ln-liniya { position: relative; flex: 1; height: 2px; background: var(--nv-cy); min-width: 0; }
.lo12-ln-liniya.tiho { background: var(--muted); opacity: .5; }
.lo12-ln-signal { position: absolute; top: 50%; left: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--nv-cy);
  box-shadow: 0 0 6px var(--nv-cy); transform: translate(-50%, -50%); animation: lo12-signal 1.4s linear infinite; }
@keyframes lo12-signal { from { left: 0; } to { left: 100%; } }
.lo12-ln-radio { text-align: center; }
/* Живые плитки: число набегает, полоса заполняется (переход), по нажатию — подробно. */
.lo12-zh-plitki { margin-top: 4px; }
.lo12-zh.mozhno { cursor: pointer; text-align: left; font: inherit; color: inherit; background: none; width: 100%; }
.lo12-zh.mozhno:hover { border-color: var(--nv-cy); }
.lo12-zh-znach { font-weight: 600; font-size: var(--t-md); font-variant-numeric: tabular-nums; }
.lo12-zh-polosa > i { transition: width .7s cubic-bezier(.2, .7, .2, 1); }
/* Подробно — во всю ширину под обеими плитками (обёртка сетке прозрачна). */
.lo12-zh-obertka { display: contents; }
.lo12-zh-podrobno { grid-column: 1 / -1; order: 1; padding: 6px 8px; border: 1px solid var(--line); color: var(--muted); }
.lo12-zh-grafik svg { display: block; width: 100%; height: 40px; }
.lo12-zh-grafik polyline { fill: none; stroke: var(--nv-cy); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
@media (prefers-reduced-motion: reduce) { .lo12-ln-signal { animation: none; left: 50%; } .lo12-zh-polosa > i { transition: none; } }
.lo12-zh-podrobno[hidden] { display: none; }
/* Разделы гармошкой — на показ (слово Open ≈18:00): голова — кнопка на всю ширину, свёрнутый — одна строка со значением справа. */
.lo12-razdel { gap: 0; }
.lo12-r-golova { display: flex; align-items: baseline; gap: 6px; width: 100%; background: none; border: 0; padding: 0 0 4px; color: inherit;
  font: inherit; text-align: left; cursor: pointer; min-width: 0; }
.lo12-r-strelka { color: var(--nv-cy); width: 10px; flex: none; }
.lo12-r-svodka { margin-left: auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lo12-razdel.svernut { padding-bottom: 6px; }
.lo12-r-telo { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.lo12-r-telo[hidden] { display: none; }
/* Низ Б: постоянная высота — две строки в одну строку с обрезкой и кнопки. */
.lo12-niz { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.lo12-niz-str { display: flex; gap: 6px; min-width: 0; white-space: nowrap; }
.lo12-niz-strelka { flex: none; color: var(--muted); }
.lo12-niz-tekst { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.lo12-porog-bystro { display: flex; flex-wrap: wrap; gap: 4px; margin: 4px 0; }
.lo12-porog-bystro .pill.on { border-color: var(--nv-cy); color: var(--nv-cy); }
.lo12-kartochka-trekera .me12-knopki .pill, .lo12-kartochka-trekera .me12-knopki .pill > span { white-space: normal; overflow: visible;
  text-overflow: clip; }
@media (max-width: 1500px) { .kh-lora.lo12 .lo12-str { grid-template-columns: minmax(0, 1fr) 40px 56px; } }
/* Н-265 (1.72.18): столбца «дБм» нет, пока RSSI не приходит. */
.lo12-str.bez-dbm { grid-template-columns: minmax(0, 1fr) 64px; }
@media (max-width: 1500px) { .kh-lora.lo12 .lo12-str.bez-dbm { grid-template-columns: minmax(0, 1fr) 56px; } }

/* ═══ 1.72.11 · поток Б · Billing (v12 `payments`): плитки · шкала двумя дорожками · график без горизонтальной прокрутки ·
   итог по валютам, платежи съёмщиков, журнал оплат. Блоки v8 (`.bill-*`) — основа; здесь только поправки v12. ═══ */
.kh-bill.b12-bill { grid-template-columns: minmax(0, 1fr) 360px; }
.b12-seredina { min-height: 0; overflow: hidden; }
.b12-seredina > .b12-grafik { flex: 1 1 0; min-height: 200px; display: flex; flex-direction: column; }
.b12-tablica { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; scrollbar-width: thin; }
.bill-tablica.b12-tablica > .row-grid, .bill-tablica.b12-tablica #billing-rows .row-grid { min-width: 0; }
.b12-shapka { position: sticky; top: 0; background: var(--surface); z-index: 1; }
.b12-tablica .cell { padding: 7px 8px; }
.b12-tablica .head-cell { padding: 7px 6px 7px 8px; }
.b12-ell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.b12-term { display: flex; flex-direction: column; gap: 1px; }
.b12-imya { font-size: var(--t-md); }
.b12-svyaz { display: flex; align-items: center; gap: 7px; }
.b12-svyaz .dot { border-radius: 50%; }
.b12-summa small { color: var(--muted); font-size: var(--t-xs); }
.b12-knopki { display: flex; gap: 6px; justify-content: flex-end; }
.pill.mini12 { display: inline-flex; align-items: center; gap: 5px; padding: 4px 9px; font-size: var(--t-xs); white-space: nowrap; }
/* плитки: число слева, текст справа, строки — по одной (Н-230) */
.b12-kpis .b12-kpi { flex-direction: row; align-items: center; gap: 14px; min-width: 0; position: relative; }
.b12-kpi.kr { background: color-mix(in srgb, var(--critical) 9%, transparent); }
.b12-kpi.zh { --bc: var(--warn); }
.b12-kpi-n { font-size: var(--t-dsp); font-variant-numeric: tabular-nums; flex: none; }
.b12-kpi-tekst { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; }
.b12-kpi-zag { font-size: var(--t-md); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.b12-kpi-str { font-size: var(--t-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.b12-kpi-znak { position: absolute; top: 10px; right: 10px; opacity: .8; }
.b12-kpi-krug .krug { flex: none; }
/* ═══ Плитка шапки (ui/plitka_shapki.mjs) — Billing, Аренда, Ticket-online: слот круга слева, справа метка, главная строка,
   подстрока. Слот не сжимается, у текста min-width 0 и многоточие: длинное число раздвигает слот (не больше половины плитки),
   а строки режутся у своего края и не заходят под число. Высота — по ряду: плитки ряда растянуты сеткой. Размеры — из шкалы
   (метка 11 px, подстрока 12 px); 15 px в шкале нет, главная строка — ближайший крупнее, --t-lg. ═══ */
.kpis > .plsh, .kpis > .plsh-deystviya { height: 100%; box-sizing: border-box; }
.kpi.plsh { flex-direction: row; align-items: center; gap: 12px; min-width: 0; min-height: 96px; }
.plsh-krug { flex: 0 0 auto; min-width: 76px; max-width: 50%; min-height: 76px; display: flex; align-items: center; justify-content: center;
  overflow: hidden; }
.plsh-krug > * { min-width: 0; max-width: 100%; }
.plsh-krug .b12-kpi-n, .plsh-krug .s12-kpi-n { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.plsh-krug .krug svg { width: 76px; height: 76px; }
.plsh-tekst { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.plsh-metka { font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
  overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; min-width: 0; }
.plsh-glav { font-size: var(--t-lg); font-weight: 700; }
.plsh-pod { font-size: var(--t-sm); color: var(--muted); }
/* Главная строка и подстрока не режутся на первой строке: перенос на вторую, многоточие — только после второй (ТЗ разд. 0, З-2). */
.plsh-glav, .plsh-pod { min-width: 0; overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2; line-height: 1.2; }
.plsh-glav:empty, .plsh-pod:empty { min-height: 1em; }
.plsh[data-k-bloku] { cursor: pointer; }
.plsh[data-k-bloku]:hover, .plsh[data-k-bloku]:focus-visible { outline: 1px solid var(--nv-cy); outline-offset: -1px; }
.kpi.plsh-deystviya { justify-content: center; gap: 6px; min-width: 0; min-height: 96px; }
/* шкала */
.bill-sh-krasn { fill: var(--critical); opacity: .10; }
.bill-sh-skoro-t { fill: var(--nv-cy); font: 600 10px var(--nv-mono); letter-spacing: .06em; }
.bill-sh-dor { fill: var(--muted); font: 600 10px var(--nv-mono); letter-spacing: .06em; }
.bill-sh-imya { font: 10px var(--nv-mono); }
.bill-sh-imya.overdue { fill: var(--critical); }
.bill-sh-imya.ar { fill: var(--warn); }
.bill-sh-t.ar { stroke: var(--nv-cy); fill: var(--nv-cy); }
.bill-sh-romb { fill: none; stroke: var(--warn); stroke-width: 1.6; }
.b12-golova-sprava { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* правая колонка */
.b12-valyuty { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px 18px; }
.b12-valyuty .bill-valyuta { min-width: 0; }
.b12-valyuty .kv { font-size: var(--t-xs); }
.b12-itog-podval { margin-top: 4px; }
.b12-ssylka { color: var(--nv-cy); text-decoration: none; white-space: nowrap; }
.b12-syom-spisok, .b12-zhurnal { display: flex; flex-direction: column; }
.b12-syom { display: grid; grid-template-columns: 10px minmax(0, 1fr) auto; gap: 4px 10px; align-items: center; padding: 8px 0;
  border-top: 1px solid var(--hair); cursor: pointer; }
.b12-syom .dot { border-radius: 50%; }
.b12-syom-tekst { min-width: 0; }
.b12-syom-knopka { grid-column: 2 / -1; justify-self: end; }
.b12-metka { font: 600 var(--t-xs) var(--nv-mono); white-space: nowrap; padding: 1px 6px; border-left: 2px solid currentColor; }
.b12-metka.ok { color: var(--ok); } .b12-metka.zh { color: var(--warn); } .b12-metka.kr { color: var(--critical); }
.b12-zh-str { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 10px; padding: 6px 0; border-top: 1px solid var(--hair);
  align-items: baseline; }
.b12-zh-summa { white-space: nowrap; }
/* окна */
.ok12.b12-okno { width: min(600px, calc(100vw - 40px)); }
.b12-okno .b12-vvod { width: 100%; box-sizing: border-box; }
.b12-tolko-chtenie { padding: 6px 10px; border: 1px solid var(--hair); min-height: 32px; display: flex; align-items: center; }
.b12-kv-spisok { display: flex; flex-direction: column; gap: 4px; }
.b12-kv { display: flex; justify-content: space-between; gap: 12px; font-size: var(--t-sm); }
.b12-kv > :last-child { text-align: right; }
.b12-otrezok { display: flex; align-items: center; gap: 10px; margin: 6px 0; }
.b12-otrezok-liniya { flex: 1 1 auto; text-align: center; border-bottom: 1px dashed var(--nv-line); font-size: var(--t-xs); color: var(--muted); }
.b12-oshibka[hidden] { display: none; }
@media (max-width: 1500px) {
  .kh-bill.b12-bill { grid-template-columns: minmax(0, 1fr) 300px; }
  .b12-kpis .b12-kpi { gap: 10px; }
  /* Н-300: 64 px срезали подпись «В СРОК» на 3 px (прибор potok-e-krai, 1440×900). */
  .b12-kpi-krug .krug svg { width: 72px; height: 72px; }
}
@media (max-width: 1279px) {
  .kh-bill.b12-bill { grid-template-columns: minmax(0, 1fr) 260px; }
  /* «связь» — только значок (слово в подсказке ячейки), «прошлая отметка» — дата (кто — в подсказке) */
  .b12-svyaz-t { display: none; }
  .b12-tablica [data-last-paid] { font-size: var(--t-xs); }
  .b12-kpi-krug .krug { display: none; }
}
@media (max-height: 760px) {
  .b12-seredina { overflow-y: auto; scrollbar-width: thin; }
  .b12-seredina > .b12-grafik { flex: none; }
  .b12-tablica { overflow-y: visible; }
}

/* ═══ 1.72.11 · поток Б · Аренда (v12 `rent`): плитки · карточки аренд и приглушённая мини-карта · таблица ·
   свободные и прошлые · справа «Карточка аренды». Без складывания в одну колонку ≤ 1500 px: колонки ужимаются,
   списки — своей прокруткой. ═══ */
.kh-rent.b12-rent { display: grid; grid-template-columns: minmax(0, 1fr) 360px; overflow: hidden; }
.kh-rent.b12-rent.svernuta { grid-template-columns: minmax(0, 1fr) 40px; }
.kh-rent.b12-rent > * { height: auto; }
.kh-rent.b12-rent .b12-seredina-ar { min-height: 0; overflow-y: auto; scrollbar-width: thin; }
.kh-rent.b12-rent .rent-sprava { overflow-y: auto; }
.kh-rent.b12-rent .rent-kpis { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.b12-kpi-n small { font-size: var(--t-xs); }
.b12-ar-ryad { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 12px; min-width: 0; }
.b12-ar-kartochki { display: flex; gap: 12px; overflow-x: auto; scrollbar-width: thin; min-width: 0; }
.b12-ar-kart { flex: 0 0 calc(50% - 6px); min-width: 280px; padding: 12px 14px; display: flex; flex-direction: column; gap: 4px; cursor: pointer; }
/* Одна сданная — на весь ряд: шапка и съёмщик сверху, слева шесть строк условий, справа срок, «Связь · 24 ч» и кнопки. */
.b12-ar-kart.odna { flex: 1 1 100%; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 24px; align-content: start; }
.b12-ar-kart.odna > :nth-child(-n+2) { grid-column: 1 / -1; }
.b12-ar-kart.odna > :nth-child(n+3):nth-child(-n+8) { grid-column: 1; }
.b12-ar-kart.odna > :nth-child(9) { grid-column: 2; grid-row: 3 / span 2; }
.b12-ar-kart.odna > :nth-child(10) { grid-column: 2; grid-row: 5 / span 2; }
.b12-ar-kart.odna > :nth-child(11) { grid-column: 2; grid-row: 7 / span 2; align-self: end; }
/* Н-580: пустая «Аренда» — строка во всю ширину ряда карточек, не карточка на полряда с рукой-курсором. */
.b12-ar-pusto { flex: 1 1 auto; padding: 12px 14px; display: flex; align-items: center; }
.b12-ar-kart.vybr { --bc: var(--warn); }
.b12-ar-kart[data-term="ending"] { --bc: var(--warn); }
.b12-ar-kart[data-term="over"] { --bc: var(--critical); }
.b12-ar-kto { display: flex; justify-content: space-between; gap: 8px; align-items: baseline; font-size: var(--t-sm); min-width: 0; }
.b12-ar-knopki, .b12-ar-k-knopki { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.b12-ar-k-knopki .pill { display: inline-flex; align-items: center; gap: 6px; }
.b12-vernut-shiroko { flex: 1 1 100%; justify-content: center; }
.b12-ar-svyaz24 { font-size: var(--t-xs); }
.b12-lenta24 { display: grid; grid-template-columns: repeat(97, minmax(0, 1fr)); gap: 1px; height: 12px; margin-top: 3px; }
.b12-lenta24 i { display: block; background: var(--nv-ok); opacity: .75; }
.b12-lenta24 i.zh { background: var(--nv-warn); }
.b12-lenta24 i.kr { background: var(--nv-down, var(--critical)); }
.b12-lenta24 i.net { background: var(--nv-line); opacity: 1; }
.b12-srok { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; }
.b12-srok-golova { display: flex; justify-content: space-between; }
.rent-srok-proshlo.ok, .rent-srok-proshlo.open { background: var(--nv-cy); }
.b12-ar-karta { min-width: 0; }
.b12-ar-karta-telo { height: 260px; position: relative; }
.b12-ar-karta-telo > * { height: 100%; }
.kh-rent.b12-rent .tr.vybr { background: color-mix(in srgb, var(--nv-cy) 10%, transparent); }
.b12-ar-niz { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; min-width: 0; }
.b12-ar-svob-ryad { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 12px; min-width: 0; align-items: start; }
.b12-ar-svob-ryad.odin { grid-template-columns: minmax(0, 1fr); gap: 4px; }
.b12-ar-svob-ryad > #b12-ar-proshlyh-net { padding: 0 14px; }
@media (min-width: 1501px) {
  .kh-rent.b12-rent .b12-ar-bez-sdannyh { overflow: hidden; }
  .b12-ar-bez-sdannyh > .b12-ar-svob-ryad { flex-shrink: 1; min-height: 120px; grid-template-rows: minmax(0, auto); overflow: hidden; }
  .b12-ar-bez-sdannyh #b12-ar-svob { display: flex; flex-direction: column; min-height: 0; max-height: 100%; }
  .b12-ar-bez-sdannyh #rent-free { flex: 0 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; }
  .b12-ar-bez-sdannyh > #rent-karta { flex: 1 1 260px; flex-shrink: 1; min-height: 240px; display: flex; flex-direction: column; overflow: hidden; }
  .b12-ar-bez-sdannyh > #rent-karta .b12-ar-karta-telo { flex: 1 1 0; height: auto; min-height: 0; }
}
.b12-svob { grid-template-columns: 30px minmax(0, .9fr) minmax(0, 1.6fr) auto; }
.b12-svob .cell { padding: 6px 6px; }
/* Н-299: без своей прокрутки — «Свободно N» на плитке и N строк видно одинаково (было 9 на плитке при 7 видимых). */
.b12-golova-l { display: flex; align-items: baseline; gap: 12px; min-width: 0; }
.b12-vse { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.b12-ar-k-imya { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.b12-ar-k-imya .dsp { font-size: var(--t-xl); }
.b12-ar-podzag { margin-top: 8px; border-bottom: 1px solid var(--hair); padding-bottom: 2px; }
.b12-razvernut { align-self: start; margin-top: 12px; }
/* окна аренды */
.b12-pole-shapka { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.b12-dva { display: grid; grid-template-columns: minmax(0, 1fr) 90px; gap: 6px; }
.ok12.b12-okno.zh { --bc: var(--warn); }
.b12-vz-vopros { font-size: var(--t-md); font-weight: 600; }
.b12-razdelitel { display: flex; justify-content: space-between; border-bottom: 1px solid var(--hair); margin-top: 6px; }
.b12-galka { display: flex; gap: 8px; align-items: flex-start; font-size: var(--t-sm); padding: 4px 0; border-bottom: 1px solid var(--hair); }
.b12-ro-forma { display: flex; flex-direction: column; gap: 8px; }
.b12-ro-forma [hidden] { display: none; }
@media (max-width: 1500px) {
  .kh-rent.b12-rent { grid-template-columns: minmax(0, 1fr) 300px; }
  .b12-ar-ryad { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 1279px) {
  .kh-rent.b12-rent { grid-template-columns: minmax(0, 1fr) 260px; }
  .b12-ar-niz { grid-template-columns: minmax(0, 1fr); }
}

/* ═══ 1.72.11 · поток Б · Ticket-online (v12 `sales`): плитки · по тарифам и продавцам · по дням и часам · запас
   (приглушён) · справа цены, доли (приглушены), события «Доступа»; окно m-price (Н-238). ═══ */
.kh-sales.s12-sales { grid-template-columns: minmax(0, 1fr) 360px; }
.s12-seredina { min-height: 0; overflow-y: auto; scrollbar-width: thin; }
.s12-ryad { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 12px; min-width: 0; }
.s12-kpi-n { display: flex; align-items: baseline; gap: 4px; }
.s12-kpi .n { font-size: var(--t-dsp); }
.s12-ell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.s12-vydat-knopki { display: flex; gap: 6px; flex-wrap: wrap; }
.s12-vydat-knopki .pill { display: inline-flex; align-items: center; gap: 5px; }
.s12-vydat-prichina { margin-top: 4px; }
/* QR на своём белом поле и в тёмной теме: камера не читает инвертированный. */
.izd-qr { margin: 8px 0; line-height: 0; }
.izd-qr svg { display: block; max-width: 100%; height: auto; }
.tok-qr { margin: 10px 0 4px; }
.tok-qr svg { display: block; max-width: 100%; height: auto; margin-bottom: 6px; }
.s12-vkladki { display: flex; gap: 4px; }
.s12-vkladki .pill.on { background: var(--nv-cy); color: var(--nv-bg); }
.s12-blok .row-grid .cell { padding: 6px 8px; }
.s12-blok .head-cell { padding: 6px 6px 6px 8px; }
.s12-itogo .cell { border-top: 1px solid var(--hair); }
.s12-zag-knopka { background: none; border: 0; padding: 0; cursor: pointer; text-align: left; }
.s12-prod { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 6px 0; border-top: 1px solid var(--hair); }
.s12-prod .dot { border-radius: 50%; justify-self: center; }
.s12-krug { width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--nv-cy); display: inline-flex; align-items: center;
  justify-content: center; font: 600 var(--t-xs) var(--nv-mono); color: var(--nv-cy); }
.s12-prod-tekst { min-width: 0; }
.s12-prod-chisla { text-align: right; }
.s12-podzag { margin-top: 8px; }
/* Столбики «Продаж»: поле со столбиками тянется по колонке, текст — в px страницы (не ужимается вместе с рисунком). Над полем —
   место под числа, под ним — строка подписей. */
.s12-stolbiki { width: 100%; height: calc(var(--s12-vys, 110px) + 34px); min-height: 64px; display: flex; flex-direction: column; }
.s12-st-pole { position: relative; flex: 1 1 0; min-height: 24px; margin-top: 15px; }
.s12-st-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; overflow: visible; }
.s12-st { fill: color-mix(in srgb, var(--nv-cy) 35%, transparent); stroke: var(--nv-cy); stroke-width: 1; }
.s12-st.seg { fill: color-mix(in srgb, var(--nv-cy) 65%, transparent); }
.s12-st-ch { position: absolute; transform: translate(-50%, -2px); color: var(--ink); font: 11px/1 var(--nv-mono); white-space: nowrap; }
.s12-st-podpisi { position: relative; flex: none; height: 19px; }
.s12-st-m { position: absolute; top: 5px; transform: translateX(-50%); color: var(--muted); font: 11px/1 var(--nv-mono); white-space: nowrap; }
.s12-st-m.seg { color: var(--warn); }
.s12-podzag-ryad { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.s12-sar-tekst { white-space: nowrap; }
.s12-sar-liniya { stroke: var(--critical); stroke-width: 1; stroke-dasharray: 3 3; }
.s12-sar-tochka { position: absolute; top: -3px; width: 6px; height: 6px; border-radius: 50%; background: var(--critical); transform: translateX(-50%); }
.s12-sar-podpis { position: absolute; top: -12px; margin-left: 6px; color: var(--critical); font: 11px/1 var(--nv-mono); white-space: nowrap; }
.s12-sar-podpis.sleva { transform: translateX(-100%); margin-left: -6px; }
.s12-zapas-stolby { display: flex; gap: 14px; justify-content: space-around; align-items: stretch; flex: 1 0 84px; min-height: 84px; padding: 4px 0;
  overflow: hidden; }
.s12-zapas-stolb { display: flex; flex-direction: column; align-items: center; gap: 4px; min-height: 0; }
.s12-zapas-stolb b { color: var(--ink); }
.s12-zapas-stolb.malo b { color: var(--warn); }
.s12-zapas-trubka { display: flex; flex-direction: column; gap: 2px; padding: 3px; border: 1px solid var(--hair); border-radius: 8px; width: 22px;
  flex: 1 1 0; min-height: 0; max-height: 96px; }
.s12-zapas-trubka i { display: block; flex: 1 1 0; min-height: 1px; border-radius: 1px; background: color-mix(in srgb, var(--ok) 12%, transparent); }
.s12-zapas-trubka i.on { background: var(--ok); }
.s12-zapas-stolb.malo .s12-zapas-trubka i.on { background: var(--warn); }
.s12-zapas-malo { border-left: 3px solid var(--warn); }
.s12-dostup { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 8px; padding: 5px 0; border-top: 1px solid var(--hair); align-items: baseline; }
.s12-dostup-spisok { max-height: 260px; overflow-y: auto; scrollbar-width: thin; }
.s12-sv { display: flex; gap: 18px; }
.ok12.s12-prodavcy { width: min(1100px, calc(100vw - 40px)); }
.s12-pr-tablica { display: grid; grid-template-columns: repeat(auto-fit, minmax(64px, 1fr)); gap: 6px; }
.s12-pr-kol.vybr { color: var(--nv-cy); }
/* Раскладка как v12 — экран без прокрутки: плитки по своей высоте, два ряда блоков делят остаток поровну; что в блок не влезает,
   прокручивается внутри блока; столбики сжимаются по высоте, сохраняя пропорции. Верхний ряд выше (1,4 : 1): таблице тарифов нужна
   высота строк, а столбики «по дням» сжимаются без потерь. Справа лента «Доступа» берёт остаток колонки. */
.s12-sales .s12-seredina { display: grid; grid-template-rows: auto minmax(0, 1.4fr) minmax(0, 1fr); overflow: hidden; }
.s12-seredina > .s12-ryad { min-height: 0; }
.s12-ryad > * { min-height: 0; overflow-y: auto; scrollbar-width: thin; }
.s12-ryad > #s12-po-dnyam { overflow: hidden; }
#s12-po-dnyam .s12-stolbiki { flex: 1 1 0; min-height: 0; height: 100%; }
.s12-sales .sales-sprava { overflow: hidden; }
.s12-sales .sales-sprava > * { flex-shrink: 0; }
.s12-sales .sales-sprava > #sales-dostup { flex: 1 1 0; min-height: 0; }
#sales-dostup .s12-dostup-spisok { max-height: none; flex: 1 1 0; min-height: 0; }
@media (max-width: 1500px) {
  .kh-sales.s12-sales { grid-template-columns: minmax(0, 1fr) 300px; }
}
@media (max-width: 1279px) { .kh-sales.s12-sales { grid-template-columns: minmax(0, 1fr) 260px; } }

/* ── 1.72.13 · главный · Н-243: место трекера устарело — линия на карте пунктиром ── 1.72.29 (Н-317, правило Open «серый не
   использовать»): старая линия — оранжевым («старое»), и у LoRa, и у MESH (связь к не отвечающему узлу); было — серым --muted. */
.sl-mesh-liniya.m-staroe { stroke: var(--warn) !important; stroke-dasharray: 3 7; opacity: .75; }
.me12-holst .m-podpis-svyazi.lo12-staroe, .me12-holst .m-pod.lo12-staroe { fill: var(--muted); }
/* ── 1.72.15 · Н-250: старое место — «место не обновлялось N» главным; линия NRN пунктиром без длины ── */
.me12-holst .m-svyaz.lo12-staroe-liniya { stroke-dasharray: 3 7; opacity: .75; }
.lo12-staroe-glavnoe { font-weight: 600; color: var(--warn); }
.map-tip .lo12-staroe-tip { color: var(--warn); font-weight: 600; }
/* ── 1.72.17 · 3D «Янтарь»: рельс «2D | 3D» (v12), слой 3D поверх карты, окно «3D · рельеф» (v12 r3-tb), подписи эталона ── */
.kh-tm.off { opacity: .4; cursor: not-allowed; }
.kh-tm.off:hover { color: inherit; }
.k3d-ramka { position: absolute; inset: 0; z-index: 600; display: flex; }
.flot-karta-telo.v-3d .map-host .leaflet-pane, .st12-ramka.v-3d > .karta-seti { visibility: hidden; }
.k3d { --k3d-fon: var(--nv-bg); --k3d-ink: var(--nv-txt); position: relative; flex: 1 1 auto; min-width: 0; min-height: 0;
  overflow: hidden; background: var(--nv-bg); }
.k3d-cv { position: absolute; left: 0; top: 0; display: block; cursor: grab; }
.k3d-cv:active { cursor: grabbing; }
.k3d-sloy { position: absolute; left: 0; top: 0; pointer-events: none; overflow: visible; }
.k3d-sloy text { paint-order: stroke; stroke: var(--k3d-fon); stroke-width: 3.4px; stroke-linejoin: round; }
.k3d-n { font: 600 12px var(--nv-font); fill: var(--nv-txt); }
.k3d-s { font: 500 11px var(--nv-mono); fill: var(--nv-mut); }
.k3d-status { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 7; padding: 8px 14px;
  font: 500 var(--t-xs) var(--nv-mono); color: var(--nv-mut); background: color-mix(in srgb, var(--nv-bg) 88%, transparent);
  box-shadow: inset 0 0 0 1px var(--nv-line); }
.k3d-ramka > .k3d-status { position: absolute; }
.r3-tb { position: absolute; left: 12px; top: 12px; z-index: 6; display: flex; flex-direction: column; align-items: stretch; gap: 6px; width: 124px; }
.r3-cap { font: 500 11px var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-cy); padding: 2px 2px 0;
  text-shadow: 0 0 4px var(--nv-bg), 0 0 2px var(--nv-bg); }
.r3-seg { display: flex; background: color-mix(in srgb, var(--nv-bg) 92%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 28%, transparent); }
.r3-seg.v { flex-direction: column; }
.r3-seg button { font-style: normal; height: 28px; padding: 0 10px; display: flex; align-items: center; justify-content: center; flex: 1;
  font: 500 11px var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-mut); cursor: pointer; white-space: nowrap;
  background: none; border: 0; }
.r3-seg button:hover:not(:disabled) { color: var(--nv-txt); }
.r3-seg button.on { color: var(--nv-cy); background: color-mix(in srgb, var(--nv-cy) 14%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 60%, transparent); }
.r3-seg button:disabled, .r3-up:disabled { opacity: .45; cursor: not-allowed; }
.r3-seg button:focus-visible, .r3-up:focus-visible { outline: 2px solid var(--nv-cy); outline-offset: -2px; }
.r3-up { height: 30px; display: flex; align-items: center; justify-content: center; font: 500 11px var(--nv-caps); letter-spacing: .06em;
  text-transform: uppercase; color: var(--nv-ok); background: color-mix(in srgb, var(--nv-bg) 92%, transparent); border: 0;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-ok) 45%, transparent); white-space: nowrap; }
.r3-cmp { display: flex; align-items: center; gap: 8px; color: var(--nv-cy); padding: 2px; }
.r3-cmp b { font: 600 11px var(--nv-mono); }
.r3-hint { font: 500 10px var(--nv-mono); letter-spacing: .04em; color: var(--nv-dim); line-height: 1.5;
  text-shadow: 0 0 4px var(--nv-bg), 0 0 2px var(--nv-bg); }
/* «Сетка» (ТЗ ZADANIE-SETKA-I-SLOI, шаг 1): фон окна и обводка подписей — цвет фона сетки, иначе вокруг плиты и букв — чужой фон.
   `display: flex` кнопок перебивает [hidden] браузера — кнопку, которой на этой вкладке нет, прячем явно. */
.r3-seg button[hidden] { display: none; }
.k3d[data-k3d-podlozhka="setka"] { --k3d-fon: #07140f; background: #07140f; }
/* Слой «поверх рельефа»: подпись строки и кнопки уже прочих — «Радиовидимость» должна влезть в ширину панели. Полоса слоя —
   обозначение цветов и числа «Радара узла» — внизу слева, выше подписи источников (её не закрывать). «Закрыто» — тёмным с сизыми линиями: красный занят аварией. */
.r3-poverh { font: 500 10px var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; color: var(--nv-dim); padding: 2px 2px 0;
  text-shadow: 0 0 4px var(--nv-bg), 0 0 2px var(--nv-bg); }
.r3-seg.s button { padding: 0 4px; }
.r3-poverh[hidden], .r3-seg.s[hidden], .k3d-polosa[hidden] { display: none; }
.k3d-polosa { position: absolute; left: 148px; bottom: 40px; z-index: 6; max-width: calc(100% - 300px); padding: 6px 10px; pointer-events: none;
  display: flex; flex-direction: column; gap: 3px; font: 500 10px var(--nv-mono); color: var(--nv-mut);
  background: color-mix(in srgb, #07140f 88%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 22%, transparent); }
.k3d-polosa-cveta { display: flex; flex-wrap: wrap; gap: 4px 14px; color: var(--nv-txt); }
.k3d-polosa-cveta i { display: inline-block; width: 12px; height: 10px; margin-right: 5px; vertical-align: -1px; box-shadow: inset 0 0 0 1px currentColor; }
.k3d-polosa-cveta .slyshno i { background: #1c4c3e; color: #8fe6c8; }
.k3d-polosa-cveta .zakryto i { background: #020604; color: #66758a; }
.k3d-polosa-cveta .za-r i { color: #60d0ac; background: repeating-linear-gradient(135deg, #2f7f68 0 2px, #07140f 2px 5px); }
.k3d-polosa-cveta .net i { background: #07140f; color: #5d6360; box-shadow: inset 0 0 0 1px currentColor; border: 1px dashed #5d6360; width: 10px; height: 8px; }
.k3d-polosa b { font-weight: 600; color: var(--nv-txt); }
/* Свёрнутая полоса (узкий экран): цвета и первая строка чисел; кнопка «ещё ▾» — единственное, что в полосе ловит нажатие. */
.k3d-polosa[data-svernuta="1"] .k3d-polosa-dop { display: none; }
.k3d-polosa-esche { pointer-events: auto; align-self: flex-start; margin-top: 2px; padding: 1px 6px; font: 600 10px var(--nv-mono);
  color: var(--nv-cy); background: none; border: 0; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--nv-cy) 45%, transparent); cursor: pointer; }
.k3d-polosa-esche:focus-visible { outline: 2px solid var(--nv-cy); outline-offset: 1px; }
/* Знак солнца слоя «Солнце и тень»: над рельефом в стороне солнца, вне кадра — у края; без нажатий. Цвет — свой, тёплый белый:
   не цвет устройства и не цвет состояния. */
.k3d-solnce-znak { position: absolute; z-index: 6; transform: translate(-50%, -50%); pointer-events: none; padding: 4px 10px 4px 8px;
  font: 600 13px var(--nv-mono); color: #fff4d6; background: color-mix(in srgb, #07140f 85%, transparent); border-radius: 14px;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #fff4d6 55%, transparent); white-space: nowrap; }
.k3d-solnce-znak[hidden] { display: none; }
.k3d-polosa.k3d-polosa-sprava { left: auto; right: 8px; max-width: 40%; }
.k3d-solnce-krug { display: inline-block; width: 16px; height: 16px; margin-right: 8px; border-radius: 50%; background: #ffd479; box-shadow: 0 0 10px 3px #ffb84d; vertical-align: -3px; }
.k3d-solnce-znak[data-v-kadre=""] { opacity: .85; }
/* Бегущие точки по связям выбранного — анимация слоя SVG, не кадры WebGL (Н-254). Попросили покоя (система или «Движение» не «вкл») —
   стоят насовсем, как рябь. */
@keyframes k3d-beg { to { stroke-dashoffset: -14; } }
.k3d-beg { animation: k3d-beg 1.4s linear infinite; }
@media (prefers-reduced-motion: reduce) { .k3d-beg { animation: none; } }
:root[data-dvizhenie] .k3d-beg { animation: none; }
.st12-ramka.v-3d > .st12-vyhod { z-index: 700; }
/* 3D: из приборов Leaflet над рельефом остаются «Выход в мир» (v12) и подпись источников (Copernicus GLO-30 — рельеф 3D из него); курсор и прочее — про 2D */
.flot-karta-telo.v-3d .leaflet-control:not(.vyhod-korobka):not(.leaflet-control-attribution) { display: none; }
.k3d-istochnik { position: absolute; right: 8px; bottom: 6px; z-index: 6; max-width: 70%; text-align: right; pointer-events: none;
  font: 500 10px var(--nv-mono); color: var(--nv-dim); text-shadow: 0 0 4px var(--nv-bg), 0 0 2px var(--nv-bg); }
/* «Мои терминалы»: подпись источников — у карты Leaflet (она над рельефом и так), низ рамки занят лентой */
.flot-karta-telo .k3d-istochnik { display: none; }

/* ── 1.72.17 · SAR (PLAN-SAR П1–П8): раскладка v12 «готовность» / «режим идёт», чип шапки, окна m-sar-on и m-sar-off ── */
.kh-sar12 { --sar: var(--nv-sar); grid-template-columns: minmax(0, 1fr) 440px; padding-bottom: 12px; overflow: hidden; }
@media (max-width: 1500px) { .kh-sar12 { grid-template-columns: minmax(0, 1fr) 380px; } }
.kh-sar12 .set-kolonka { overflow-y: auto; scrollbar-width: thin; padding-bottom: 0; gap: 10px; }
.kh-sar12 .set-kolonka > :last-child { flex-grow: 0; }
.sar12-seredina { overflow: hidden; }
.sar12-vkladki { display: flex; align-items: center; gap: 4px; padding: 6px 10px; flex-wrap: nowrap; overflow: hidden; }
.sar12-vk, .sar12-vk-sost { padding: 4px 10px; font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase;
  white-space: nowrap; }
.sar12-vk.on { color: var(--nv-cy); box-shadow: inset 0 -2px 0 var(--nv-cy); background: var(--nav-active); }
.sar12-vk.nvv-tekst { opacity: .55; }
.sar12-vk-sost { display: inline-flex; gap: 6px; align-items: center; color: var(--muted); border-right: 1px solid var(--nv-line);
  max-width: 320px; overflow: hidden; text-overflow: ellipsis; }
.sar12-vk-sost.on { color: var(--sar); }
a.sar12-vk { color: var(--ink); text-decoration: none; }
a.sar12-vk:hover, a.sar12-vk:focus-visible { color: var(--nv-cy); background: var(--nav-active); }
.sar12-sloi { display: flex; align-items: center; gap: 6px; padding: 4px 10px; flex-wrap: wrap; }
.sar12-sloi-zag { display: inline-flex; align-items: center; gap: 4px; color: var(--nv-cy);
  font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; margin-right: 4px; }
.sar12-sloy { display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px; border: 1px solid var(--nv-line);
  background: transparent; color: var(--muted); font-size: var(--t-xs); white-space: nowrap; cursor: pointer; }
.sar12-sloy i { width: 8px; height: 8px; border: 1px solid currentColor; }
.sar12-sloy.on { color: var(--ink); }
.sar12-sloy.on i { background: currentColor; }
.sar12-sloy.on.lyudi i { color: var(--sar); background: var(--sar); }
.sar12-sloy.on.mesh i, .sar12-sloy.on.lora i { color: var(--nv-ok); background: var(--nv-ok); }
.sar12-sloy.nvv-tekst { opacity: .55; cursor: default; }
.sar12-chel.k-karte { cursor: pointer; }
.sar12-chel.k-karte:hover, .sar12-chel.k-karte:focus-visible { background: var(--nav-active); }
.sar12-chel.sel { box-shadow: inset 2px 0 0 var(--nv-cy); background: var(--nav-active); }
.sar12-shag { display: grid; grid-template-columns: 18px 44px minmax(0, 1fr); gap: 6px; align-items: center; padding: 2px 0; font-size: var(--t-sm); }
.sar12-shag.sdelan .sar12-ik { color: var(--nv-ok); }
.sar12-shag.zhdyot .sar12-ik, .sar12-shag.potom { color: var(--muted); }
.sar12-shag-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sar12-shkala { position: relative; height: 38px; margin: 2px 0 6px; flex: 0 0 auto; }
.sar12-shk-15 { position: absolute; left: 0; top: 0; height: 22px; border-bottom: 2px solid var(--sar); background: color-mix(in srgb, var(--sar) 10%, transparent); }
.sar12-shk-15 span { position: absolute; right: 4px; top: 2px; color: var(--sar); font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.sar12-shk-15.uzko span { right: auto; left: 4px; }
.sar12-shk-liniya { position: absolute; left: 0; right: 0; top: 21px; border-top: 1px solid var(--nv-line); }
.sar12-shk-t { position: absolute; top: 17px; width: 8px; height: 8px; margin-left: -4px; border-radius: 50%; border: 1.5px solid var(--nv-cy); background: var(--surface); }
.sar12-shk-t.vkl { border-color: var(--sar); background: var(--sar); }
.sar12-shk-t.opov { border-color: var(--nv-warn); }
.sar12-shk-m { position: absolute; top: 26px; transform: translateX(-50%); font-size: var(--t-xs); white-space: nowrap; }
.sar12-shk-seychas { position: absolute; top: 2px; margin-left: 8px; font-size: var(--t-xs); color: var(--sar); white-space: nowrap; }
.sar12-shk-seychas.sleva { margin-left: 0; transform: translateX(calc(-100% - 8px)); }
.sar12-shk-t.seychas { border-color: var(--sar); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sar) 30%, transparent); }
.sar12-video-kadr { min-height: 150px; }
.sar12-video-str { display: block; padding: 3px 0; }
#m-alert-tekst { width: 100%; box-sizing: border-box; resize: vertical; font: inherit; }
.sar12-verh { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.sar12-verh-lev { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.sar12-verh > #sar-vyhod { position: static; flex: 0 1 auto; max-width: 44%; }
.sar12-video .sar12-okno-kol { gap: 4px; }
.sar12-blok { gap: 4px; }
.sar12-golova { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; min-width: 0; margin-bottom: 2px; }
.sar12-golova .ht { display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--nv-cy);
  font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.sar12-golova .ht > span { overflow: hidden; text-overflow: ellipsis; }
.sar12-sprava { white-space: nowrap; }
.sar12-metka { padding-left: 8px; margin-left: 2px; border-left: 2px solid currentColor; font-size: var(--t-xs); color: var(--muted); }
.sar12-glavnyy .ht.sar12-vykl { color: var(--muted); }
.sar12-glavnyy.idet { border-color: var(--sar); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sar) 40%, transparent); }
.sar12-glavnyy .ht.sar12-idet { color: var(--sar); }
.sar12-glavnyy .ht.sar12-idet .sar12-metka { color: var(--sar); }
.sar12-zag { font-size: var(--t-xl, 22px); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.sar12-vid-tajmer { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; min-width: 0; }
.sar12-tajmer { color: var(--sar); font: 600 30px var(--nv-mono); letter-spacing: .04em; flex: none; }
.sar12-cta { display: inline-flex; gap: 8px; align-items: center; justify-content: center; margin-top: 8px; width: 100%;
  background: color-mix(in srgb, var(--sar) 18%, var(--surface)); color: var(--ink); border: 1px solid var(--sar);
  font: 600 var(--t-sm) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; }
.sar12-cta:hover:not([disabled]) { background: color-mix(in srgb, var(--sar) 32%, var(--surface)); }
.sar12-cta[disabled] { opacity: .5; cursor: not-allowed; }
.sar12-str { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto; gap: 8px; align-items: center; padding: 4px 0;
  border-bottom: 1px solid var(--hair); font-size: var(--t-sm); min-width: 0; }
.sar12-str.off { opacity: .5; cursor: help; }
.sar12-str.s-ok .sar12-ik { color: var(--ok); } .sar12-str.s-warn .sar12-ik { color: var(--warn); }
.sar12-str.s-ok, .sar12-str.s-warn { color: var(--ink); }
.sar12-ik { display: inline-flex; color: var(--sar); }
.sar12-imya { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sar12-imya > b { font-weight: 600; }
.sar12-dve { display: flex; flex-direction: column; white-space: normal; }
.sar12-dve > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sar12-znach { color: var(--ink); }
.sar12-av { width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--ok); color: var(--ok); display: grid; place-items: center;
  font: 600 9px var(--nv-mono); }
.sar12-kto { grid-template-columns: 22px minmax(0, 1fr) auto; }
.sar12-ist { grid-template-columns: 44px minmax(0, 1fr) auto; }
.sar12-chel { grid-template-columns: 14px minmax(0, 1fr) auto; }
.sar12-podval { padding-top: 6px; }
.sar12-kletki { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 4px 0; }
.sar12-kletka { display: flex; flex-direction: column; gap: 2px; padding: 6px 8px; border: 1px solid var(--nv-line); min-width: 0; }
.sar12-kletka.off { opacity: .5; cursor: help; }
.sar12-kletka > b { font-size: var(--t-lg, 18px); }
.sar12-vidyat { grid-template-columns: 18px minmax(0, 1fr) auto; }
.sar12-knopki { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; flex: none; }
.sar12-knopki .pill { display: inline-flex; gap: 6px; align-items: center; justify-content: center; min-width: 0; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.sar12-knopki .sar12-shir, .sar12-knopki .sar12-zav { grid-column: 1 / -1; }
.sar12-zav { color: var(--critical); border-color: var(--critical); text-transform: uppercase; letter-spacing: .06em; }
.sar12-zav[disabled] { opacity: .5; cursor: not-allowed; }
.sar12-niz { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: 8px; flex: 0 0 auto; max-height: 34%; min-height: 120px; }
.sar12-niz > * { min-height: 0; overflow: hidden; }
.sar12-zhurnal { display: flex; flex-direction: column; }
.sar12-zh-spisok { flex: 1 1 auto; min-height: 0; overflow-y: auto; scrollbar-width: thin; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 0 14px; align-content: start; }
.sar12-zh { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 6px; padding: 3px 0; border-bottom: 1px solid var(--hair);
  font-size: var(--t-sm); }
.sar12-zh-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sar12-radary .nvv-telo { font-size: var(--t-xs); }
.me12-telo .sar12-podpis-karty { position: absolute; right: 10px; bottom: 10px; z-index: 500; display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 8px; border: 1px solid var(--nv-line); background: var(--nv-bar); color: var(--muted); }
/* чип шапки «SAR · вид · ЧЧ:ММ:СС» (П2) — цветом SAR, не ужимается: это напоминание, что места открыты */
.kh-chip.sar12-chip { --ug: var(--nv-sar); color: var(--nv-sar); cursor: pointer; flex: 0 0 auto; overflow: hidden;
  font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; }
.kh-chip.sar12-chip .sar12-chip-vid { overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 240px; }
.sar12-okno .sar12-imya { white-space: normal; }
.sar12-vid-tajmer .sar12-zag { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; font-size: var(--t-lg); line-height: 1.2; }
.kh-chip.sar12-chip > b { flex: none; font: 600 var(--t-sm) var(--nv-mono); letter-spacing: .02em; }
.kh-rail .kh-bd.sar { background: var(--nv-sar); }
/* окна */
dialog.sar12-okno { width: min(860px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); display: flex; flex-direction: column; gap: 10px; }
dialog.sar12-okno:not([open]) { display: none; }
dialog.sar12-on { border-color: var(--nv-sar); }
dialog.sar12-on .ok-zag .ht { color: var(--nv-sar); }
.sar12-okno-dve { align-items: start; }
.sar12-okno-kol { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sar12-okno .ok12-chipy .pill.on { border-color: var(--nv-sar); color: var(--ink); background: color-mix(in srgb, var(--nv-sar) 16%, transparent); }
.sar12-okno textarea, .sar12-okno input[type=text] { width: 100%; box-sizing: border-box; }
.sar12-pamyatka { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 8px; align-items: start; padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--nv-sar) 50%, var(--nv-line)); background: color-mix(in srgb, var(--nv-sar) 6%, transparent);
  font-size: var(--t-sm); cursor: pointer; }
.sar12-otschet { margin-right: auto; display: inline-flex; align-items: center; gap: 4px; }
.sar12-cta-okno { color: var(--nv-sar); border-color: var(--nv-sar); display: inline-flex; gap: 6px; align-items: center;
  text-transform: uppercase; letter-spacing: .06em; }
.sar12-cta-okno[disabled] { opacity: .5; cursor: not-allowed; }
.sar12-kletki.k3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sar12-tajmer-okno { font: 600 var(--t-lg, 18px) var(--nv-mono); }
@media (max-width: 720px) { .sar12-kletki, .sar12-kletki.k3 { grid-template-columns: minmax(0, 1fr); } }

/* 1.72.23 — контроль точки: обрывы точки с RP5 (ui/tochka.mjs). Полоса — длина обрыва, внутри — причины по времени. */
.tk-spisok { display: flex; flex-direction: column; gap: 8px; }
.tk-obryv { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.tk-obryv > .t-sm { overflow-wrap: anywhere; }
.tk-polosa { position: relative; height: 8px; border-radius: 4px; background: color-mix(in srgb, var(--critical) 22%, transparent); overflow: hidden; }
.tk-polosa[data-obryv="open"] { background: color-mix(in srgb, var(--critical) 40%, transparent); }
.tk-polosa > i { position: absolute; top: 0; bottom: 0; }
.tk-polosa > .tk-svet { background: var(--warn); }
.tk-polosa > .tk-kabelStarlink, .tk-polosa > .tk-kabelRp5 { background: var(--critical); }
.tk-polosa > .tk-svyaz { background: color-mix(in srgb, var(--critical) 65%, transparent); }
.tk-obryv > .tk-fakt { overflow-wrap: anywhere; line-height: 1.4; }
.tk-obryv > .tk-sovet { overflow-wrap: anywhere; line-height: 1.4; padding-left: 8px; border-left: 2px solid var(--warn); }
#report-obryvy-tochki { display: flex; flex-direction: column; gap: 4px; font-size: var(--t-md); }
#report-obryvy-tochki > .t-sm { overflow-wrap: anywhere; line-height: 1.4; }

/* Н-300 (1.72.25, Cowork 13.10 16:02) — «ничего за краем без прокрутки». */
/* Знак «ещё N ↓» внизу листающейся колонки или окна (ui/eshche_kolonki.mjs): поверх нижнего края, непрозрачный, щелчок листает. */
.eshche-kolonki { position: fixed; z-index: 1250; margin: 0; padding: 2px 10px; border: 1px solid var(--nv-cy); border-radius: 10px;
  background: var(--nv-bar); color: var(--nv-cy); font: 600 var(--t-xs) var(--nv-font); letter-spacing: .03em; line-height: 1.5;
  white-space: nowrap; cursor: pointer; box-shadow: 0 2px 8px rgba(0, 0, 0, .25); }
.eshche-kolonki:hover { color: var(--ink); border-color: var(--ink); }
/* 1.72.26 (поток Б, Cowork 13.10 21:16 п. 3 [2]): знак не поверх последней строки — колонке со знаком полоса снизу на его
   высоту (прозрачная нижняя рамка: она не листается, окно прокрутки становится ниже на полосу), знак стоит в ней; над
   прилипшим подвалом окна — полоса отступом сверху подвала. Высота — --eshche-h (ставит ui/eshche_kolonki.mjs). */
.eshche-mesto { border-bottom: var(--eshche-h, 26px) solid transparent !important;
  min-height: calc(var(--eshche-h, 26px) + 34px) !important; }   /* над полосой — хотя бы одна строка (1440: «Лагеря и тропы» в 40 px) */
.eshche-mesto-podval { padding-top: calc(var(--eshche-h, 26px) + 12px) !important; }
/* Заглушки «в этой версии нет» (ui/net_v_versii.mjs) без своего отступа от экрана лежали текстом вплотную к рамке (Ticket:
   «Доли канала», «Запас ticket пачками»). :where — нулевая весомость: у кого отступ задан экраном, тот остаётся. */
:where(.nvv-blok) { padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
/* Дневная тема: нижняя лента карты «Моих терминалов» была на 78 % — сквозь неё просвечивала карта; днём — непрозрачная. */
:root:not([data-theme]) .lenta-v12, :root[data-theme='light'] .lenta-v12 { background: var(--nv-bar); backdrop-filter: none; }
.lo12-trekerov-iz { flex: none; white-space: nowrap; }  /* 1.72.25: «трекеров N из M» в полосе LoRa не сжимается (1440). */
/* 1.72.25 поток З (слово Open 13.10 п. 9): «Мои терминалы» в NRN при слое MESH или LoRa (ui/map.mjs, `karta-nrn`) — те же точки
   на ПРИГЛУШЁННОЙ подложке (плитки и рельеф бледнее и серее — фон, а не карта), связи — «нейронами»: широкий прозрачный ствол,
   как синапс «Карты сети» (karta/karta_kod.mjs:339–342), и бегущие по нему импульсы (там же, :344–350). Точки — без изменений. */
.karta-nrn .leaflet-tile-pane { opacity: .34; filter: grayscale(.75); }
path.sl-mesh-liniya.sl-neyron { stroke-opacity: .32; stroke-dasharray: none; }
path.sl-mesh-liniya.sl-neyron.m-odna:not(.m-lora) { stroke-width: 1.6px; stroke-opacity: .6; stroke-dasharray: 4 7; }
path.sl-mesh-liniya.sl-neyron.m-staroe { stroke-opacity: .18; }
path.sl-neyron-impuls { fill: none; stroke-linecap: round; stroke-dasharray: .1 22; pointer-events: none;
  animation: sl-neyron-impuls 1.6s linear infinite; }
path.sl-neyron-impuls.m-ok { stroke: var(--ok); } path.sl-neyron-impuls.m-sred { stroke: var(--warn); }
path.sl-neyron-impuls.m-slab { stroke: var(--critical); } path.sl-neyron-impuls.m-oranzh { stroke: color-mix(in srgb, var(--warn) 55%, var(--critical)); }
@keyframes sl-neyron-impuls { to { stroke-dashoffset: -22.1; } }
@media (prefers-reduced-motion: reduce) { path.sl-neyron-impuls { animation: none; } }
/* «Карта сети»: бегущие точки к площадке по линии к точному месту (слово Open 268), цветом типа ветви; длительность — по трафику (style). */
.set-potoki path.m12-beg { fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-dasharray: .1 18; pointer-events: none; animation: m12-beg 1.6s linear infinite; }
.set-potoki path.m12-beg.m12-tip-mesh { stroke: var(--m12-tip-mesh); } .set-potoki path.m12-beg.m12-tip-lora { stroke: var(--m12-tip-lora); }
.set-potoki path.m12-beg.m12-tip-chelovek { stroke: var(--m12-tip-osnovanie); }
@keyframes m12-beg { to { stroke-dashoffset: -18.1; } }
@media (prefers-reduced-motion: reduce) { .set-potoki path.m12-beg { animation: none; } }
/* 1.72.25 поток З (п. 10): круг площадки R из «R, м» на «Карте сети» в NRL — тонкий пунктир, как внешнее кольцо «Карты сети». */
path.sl-krug-ploshchadki { fill: none; stroke: var(--nv-cy, var(--accent)); stroke-opacity: .9; stroke-width: 1px; stroke-dasharray: 2 7; pointer-events: none; }
path.sl-krug-radara { fill: var(--accent); fill-opacity: .06; stroke: var(--accent); stroke-opacity: .8; stroke-width: 1px; stroke-dasharray: 4 4; pointer-events: none; }
/* Радар как v12: развёртка (клин вращается, период у точки свой), пульс у точки, проявление кольца и рост полос — после «Радары · вкл». */
.sl-radar-sloy { pointer-events: none; overflow: visible; }
.sl-radar-razv { transform-box: view-box; transform-origin: 0 0; animation: sl-rad-rot var(--period, 6s) linear infinite; animation-delay: var(--faza, 0s); }
.sl-radar-klin { fill: var(--accent); fill-opacity: .16; }
.sl-radar-luch { stroke: var(--accent); stroke-opacity: .45; stroke-width: 1.3; vector-effect: non-scaling-stroke; }
.sl-radar-puls { position: absolute; left: -6px; top: -6px; width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--accent);
  pointer-events: none; animation: sl-rad-puls 2s ease-out infinite; animation-delay: var(--faza, 0s); }
path.sl-krug-radara.sl-poyavlenie, .me12-rad-polosa.sl-rad-rost > i { animation: sl-rad-in .9s ease-out both; }
.me12-rad-polosa.sl-rad-rost > i { transform-origin: left center; animation-name: sl-rad-rost; animation-duration: 1.4s; }
.sl-radar-vidno { fill: var(--accent); fill-opacity: .16; }
.sl-radar-uperlos { opacity: .35; }
.sl-radar-sht { stroke: var(--warn); stroke-width: .5; stroke-opacity: .7; vector-effect: non-scaling-stroke; }
.sl-radar-kraj { fill: none; stroke: var(--accent); stroke-opacity: .85; stroke-width: 1.2; vector-effect: non-scaling-stroke; }
.sl-radar-zony.sl-poyavlenie, .sl-radar-kraj.sl-poyavlenie { animation: sl-rad-in .9s ease-out both; }
.sl-radar-polyar-mesto { display: flex; justify-content: center; padding: 4px 0; }
.sl-radar-polyar { width: 150px; height: 150px; overflow: visible; }
.sl-radar-polyar-krug { fill: none; stroke: var(--hair); stroke-width: 1; }
.sl-radar-polyar-kraj { fill: var(--ok); fill-opacity: .18; stroke: var(--ok); stroke-width: 1; }
.sl-radar-polyar-luchi { stroke: var(--ok); stroke-width: 1.2; stroke-opacity: .8; }
.sl-radar-polyar text { fill: var(--muted); font-size: var(--t-xs); text-anchor: middle; }
@keyframes sl-rad-rot { to { transform: rotate(360deg); } }
@keyframes sl-rad-puls { 0% { opacity: .9; transform: scale(1); } 100% { opacity: 0; transform: scale(2.4); } }
@keyframes sl-rad-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes sl-rad-rost { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@media (prefers-reduced-motion: reduce) {
  .sl-radar-razv, .sl-radar-puls, path.sl-krug-radara.sl-poyavlenie, .me12-rad-polosa.sl-rad-rost > i, .sl-radar-zony.sl-poyavlenie,
  .sl-radar-kraj.sl-poyavlenie { animation: none; }
}
.me12-radar .me12-radar-kv { grid-template-columns: 1fr; }
.me12-radary .me12-str4 { grid-template-columns: 1fr 1.2fr 44px 64px; }
.me12-radary .me12-str4 > b:last-child { white-space: nowrap; text-align: right; }
.me12-rad-polosa { display: flex; height: 6px; align-self: center; background: var(--border); border-radius: 3px; overflow: hidden; }
.me12-rad-polosa .pr { background: var(--ok); }
/* «Упёрлось» — штриховкой цветом предупреждения (как v12), не заливкой: заливка совпадала с «слабой» связью легенды. */
.me12-rad-polosa .up { background: repeating-linear-gradient(125deg, var(--warn) 0 1.2px, transparent 1.2px 4px); }
.me12-rad-polosa .nd { background: var(--muted); }
/* 1.72.26 поток А (слово Open 13.10 «да», Cowork 19:44 п. 2): точки классов левой колонки «Карты сети» днём — тем же тёмным цветом, что
   на карте (цвет — kod.CLASS рисунка, screens/network.mjs pokrasit). Приглушённые строки «нет в этой версии» (.off, opacity .5) делали
   точку вдвое светлее (сотрудник #009B31: 3,26 → 1,81:1 к фону дня). Днём строка приглушается по детям, кроме точки; ночью — как было. */
:root:not([data-theme]) .kh-set .set-gruppa.off, :root[data-theme='light'] .kh-set .set-gruppa.off,
:root:not([data-theme]) .kh-set .st12-leg.off, :root[data-theme='light'] .kh-set .st12-leg.off { opacity: 1; }
/* 1.72.27 поток Ц (слово Open 14.10: «текст тоже ярче и насыщеннее»): днём текст приглушённых строк левой колонки — не
   приглушается (было opacity .5 у детей, кроме точки); ночью — как было (строка .off целиком .5). */
/* 1.72.27 поток Ц (слово Open 14.10: «если молчит — оранжевый, если нет данных и не слышен — красным, серый не использовать,
   зелёный — когда всё ок»). Числа: давно / молчащий узел — zn-warn, не слышен / нет данных от шлюза — zn-krit. */
.zn-warn, .zn-warn .mono, .zn-warn .t-xs, .zn-warn .muted { color: var(--warn); }
.zn-krit, .zn-krit .mono, .zn-krit .t-xs, .zn-krit .muted { color: var(--critical); }
.zn-warn .me12-romb.staroe { border-color: var(--warn); color: var(--warn); }
/* LoRa: круг и узел трекера «не слышен» / «нет данных от шлюза» — красным (было --muted); пунктир/точки — как были. */
.lo12-krug.silent, .lo12-krug.nodata { border-color: var(--critical); }
/* «неизвестно» (шлюз не слушает, приёма не было) — цветом неизвестности, а не зелёным базового кружка: зелёный читался как «слышен». */
.lo12-krug.neizvestno { border-color: var(--kl-sluzh); border-style: dashed; opacity: .55; }
.me12-vt.s-warn { color: var(--warn); }
.me12-holst .m-uzel.lo12-t.silent, .me12-holst .m-uzel.lo12-t.nodata { stroke: var(--critical); }
.me12-holst .m-uzel.lo12-t.silent, .me12-holst .m-uzel.lo12-t.nodata { fill: color-mix(in srgb, var(--critical) 18%, var(--surface)); }
/* LoRa: связь трекер → шлюз. Пропал — красным пунктиром (было серым); слышен без SNR — как норма (трекер слышен);
   старое место — оранжевым (как «место не обновлялось» в карточке). Холст NRN и карта NRL (m-lora; и на «Моих терминалах», SAR). */
.me12-holst .m-svyaz.lo12-propal { stroke: var(--critical); }
.me12-holst .m-svyaz.lo12-net { stroke: var(--kl-svyaz); }
.me12-holst .m-podpis-svyazi.lo12-staroe, .me12-holst .m-pod.lo12-staroe { fill: var(--warn); }
.sl-mesh-liniya.m-lora.m-net.m-neust { stroke: var(--critical); }
.sl-mesh-liniya.m-lora.m-net:not(.m-neust) { stroke: var(--kl-svyaz); opacity: .9; }
.sl-mesh-liniya.m-lora.m-staroe { stroke: var(--warn) !important; }
/* 1.72.28 поток Ц (слово Open 14.10 02:45, пп. 15–16: «серый нет», «числа трекера в норме — зелёным»). Числа в порядке —
   zn-ok (зелёный); давно / по старому снимку / старый замер — zn-warn (выше); не слышен / нет данных — zn-krit (выше). */
.zn-ok, .zn-ok .mono, .zn-ok .t-xs { color: var(--ok); }
/* Подпись строки «по снимку ЧЧ:ММ» в паспорте: .set-kv > span серая по умолчанию (строка 1587) — у старого снимка оранжевым. */
.set-kv > span.zn-warn { color: var(--warn); }
/* «Отчёты» (Н-315): «молчит — не знаем» и «нет данных об обрывах» — один пункт «не знаем» оранжевой штриховкой; сутки молчания
   — той же штриховкой (класс nd), серого silent нет. Строка «молчит с ЧЧ:ММ» — оранжевым, кольцо знака — оранжевым. */
.ot12-stolbiki > i.ot12-leg-silent, .ot12-leg.silent { background: repeating-linear-gradient(135deg, var(--warn) 0 2px, transparent 2px 5px); }
.ot12-molchit .znak.z-silent .z-kolco { stroke: var(--warn); }
/* Тексты правил Open (Н-292): списки через перенос строки — pre-line; название в «Уведомлениях» — целиком, переносом. */
.uv12-znachit, .uv12-delat, .kart-chto-delat, .rule-explain > div { white-space: pre-line; }
.uv12-zag { white-space: normal; overflow-wrap: anywhere; }

/* 1.72.28 поток К (п. 21, Cowork 14.10 03:20): окно «Компас» — наведение тарелки, только чтение. Окно v12 (.ok12): шапка
   «» КОМПАС · НАВЕДЕНИЕ · <терминал> ✕», строка «снимок раз в 5 с…», тело, низ «Закрыть · Данные терминала». Слева — экран
   «Наведение» APK, справа — роза азимута и четверть высоты, ниже — две точные шкалы ±10°. Цвета — правило пульта: зелёный,
   оранжевый (--warn), красный; серого нет. */
.km-okno { width: min(1180px, calc(100vw - 40px)); }
.km-telo { gap: 14px; }
.km-verh { display: grid; grid-template-columns: minmax(240px, 300px) minmax(0, 1fr); gap: 20px; align-items: start; }
.km-apk { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 4px; padding: 6px 4px; min-width: 0; }
.km-apk-zag { letter-spacing: .06em; }
.km-chislo { font: 700 88px/1 var(--nv-caps); letter-spacing: .02em; font-variant-numeric: tabular-nums; }
.km-gradusov { font-size: var(--t-sm); margin-top: -2px; }
.km-strelka { margin: 8px 0 2px; }
.km-slovo { font: 700 26px/1.15 var(--nv-caps); letter-spacing: .06em; text-transform: uppercase; }
.km-kuda { font-size: var(--t-md, 15px); }
.km-pod { max-width: 300px; margin-top: 6px; color: var(--ink); white-space: pre-line; }
.km-melko { margin-top: 10px; color: var(--muted); display: flex; flex-direction: column; gap: 2px; }
.km-apk[data-cvet="ok"] .km-chislo, .km-apk[data-cvet="ok"] .km-slovo, .km-apk[data-cvet="ok"] .km-strelka, .km-apk[data-cvet="ok"] .km-kuda { color: var(--ok); }
.km-apk[data-cvet="warn"] .km-chislo, .km-apk[data-cvet="warn"] .km-slovo, .km-apk[data-cvet="warn"] .km-strelka, .km-apk[data-cvet="warn"] .km-kuda { color: var(--warn); }
.km-apk[data-cvet="critical"] .km-chislo, .km-apk[data-cvet="critical"] .km-slovo, .km-apk[data-cvet="critical"] .km-strelka, .km-apk[data-cvet="critical"] .km-kuda { color: var(--critical); }
.km-apk[data-cvet="warn"] .km-pod[data-pod="ustarel"], .km-apk[data-cvet="warn"] .km-pod[data-pod="filtr"] { color: var(--warn); }
/* 1.72.30: одна ось пуста — «высота в допуске; азимута нет — по нему не судим» оранжевым, не зелёным «ГОТОВО». */
.km-apk[data-cvet="warn"] .km-pod[data-pod="netAz"], .km-apk[data-cvet="warn"] .km-pod[data-pod="netVys"] { color: var(--warn); }
.km-apk[data-cvet="critical"] .km-pod { color: var(--critical); }
.km-apk[data-cvet="ok"] .km-pod { color: var(--ok); }
.km-pribor { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.km-krugi { display: grid; grid-template-columns: minmax(0, 300fr) minmax(0, 220fr); gap: 18px; align-items: center; }
.km-roza, .km-chetvert { width: 100%; height: auto; max-height: 330px; display: block; overflow: visible; }
.km-obod { fill: color-mix(in srgb, var(--accent) 4%, transparent); stroke: var(--border); stroke-width: 1.2; }
.km-obod-vn { fill: none; stroke: var(--hair); stroke-width: 1; stroke-dasharray: 2 4; }
.km-risk { stroke: var(--muted); stroke-width: 1; }
.km-risk-b { stroke: var(--ink); stroke-width: 1.6; }
.km-cifra { fill: var(--muted); font: 500 11px var(--nv-mono); }
.km-storona { fill: var(--ink); font: 700 15px var(--nv-caps); }
.km-storona.km-sever { fill: var(--accent); }
.km-centr { fill: var(--surface); stroke: var(--border); }
.km-centr-t { fill: var(--muted); font: 500 10px var(--nv-mono); letter-spacing: .06em; }
.km-dop-ok { fill: none; stroke: var(--ok); stroke-width: 6; }
.km-dop-zh { fill: none; stroke: var(--warn); stroke-width: 6; }
.km-nuzhno { stroke: var(--warn); stroke-width: 2; stroke-dasharray: 5 4; }
.km-romb { fill: none; stroke: var(--warn); stroke-width: 2; }
.km-seychas { stroke: var(--accent); stroke-width: 3; stroke-linecap: round; }
.km-seychas-nos { fill: var(--accent); }
.km-legenda { display: flex; flex-direction: column; gap: 3px; padding-left: 4px; }
.km-legenda > div { display: flex; align-items: center; gap: 6px; }
.km-legenda i { flex: none; display: inline-block; width: 18px; height: 0; }
.km-leg-seychas { border-top: 3px solid var(--accent); }
.km-leg-nuzhno { border-top: 2px dashed var(--warn); }
.km-leg-dopusk { height: 6px !important; background: linear-gradient(90deg, var(--warn) 0 25%, var(--ok) 25% 75%, var(--warn) 75%); }
.km-c-seychas { color: var(--accent); } .km-c-nuzhno { color: var(--warn); }
.km-shkaly { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 28px; padding-top: 6px; border-top: 1px solid var(--hair); }
.km-shkala { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.km-shkala-pole { position: relative; padding: 30px 16px 18px; }
.km-shkala-pole > .km-shkala-mera { position: absolute; left: 16px; right: 16px; top: 0; bottom: 0; }
.km-shkala-polosa { height: 10px; background: linear-gradient(90deg,
  color-mix(in srgb, var(--critical) 55%, transparent) 0 35%, color-mix(in srgb, var(--warn) 60%, transparent) 35% 40%,
  color-mix(in srgb, var(--ok) 55%, transparent) 40% 60%, color-mix(in srgb, var(--warn) 60%, transparent) 60% 65%,
  color-mix(in srgb, var(--critical) 55%, transparent) 65% 100%); }
.km-shkala-riski { position: absolute; left: 16px; right: 16px; bottom: 0; height: 14px; }
.km-shkala-riski span { position: absolute; transform: translateX(-50%); font: 500 11px var(--nv-mono); color: var(--muted); }
.km-shkala-marker { position: absolute; top: 19px; width: 0; height: 0; transform: translateX(-50%);
  border-left: 7px solid transparent; border-right: 7px solid transparent; border-top: 10px solid var(--accent); }
.km-shkala-chislo { position: absolute; top: 0; transform: translateX(-50%); font: 600 12px var(--nv-mono); color: var(--accent); white-space: nowrap; }
.km-shkala-pod { text-align: center; }
.km-niz { align-items: center; }
.km-niz .km-poyasnenie { margin-right: auto; }
/* 1.72.31: на точке с RP5 строки про APK нет (пустая и скрытая), но место-распорка остаётся — кнопки не съезжают влево. */
.km-niz .km-poyasnenie[hidden] { display: block; visibility: hidden; }
.flot-k-knopki-v12 > .flot-k-kompas { grid-column: 1 / -1; }
@media (max-width: 900px) {
  .km-verh, .km-shkaly { grid-template-columns: minmax(0, 1fr); }
}

/* ═══ «Карта сети»: цвета классов — слово Open 17.10 ~15:15 (серого нет; отменяет «v12 везде» для классов) ═══
   Клиенты (гости лагеря) — насыщенный градиент ярко-жёлтый → оранжевый (--kl-klient-a → --kl-klient-b; сплошной — --kl-klient);
   служебные (оборудование и управление лагерем: роутер, RP5, GPS, тарелка, шлюзы MESH и LoRa, трекеры) — светло-синий со сливовым;
   сотрудники — насыщенный зелёный; низкий приоритет — светло-розовый; ждут код (без доступа) — бледный голубой; чужак (без
   спроса, атака — этап 3) — чёрный с красным контуром; класс не определён — контур цветом текста (Н-317; свободного различимого
   цвета нет); «были, не сейчас» — цвет своего класса бледнее. Значения — палитра Cowork 15:44 (OKLab: норма ≥ 15, протан и дейтан
   ≥ 8); днём контраст к фону дня холста и к белому не ниже 3:1, у жёлтого края градиента — кант (test/karta_cveta_test.mjs). */
:root {
  --kl-klient-a: #E3A200; --kl-klient: #A65400; --kl-klient-b: #C85000;
  --kl-sluzh: #4C4BBA; --kl-sotr: #007B1E; --kl-nizk: #C3457F; --kl-intr: #4B87B5; --kl-prochie: var(--ink);
  --kl-chuzhak: #000000; --kl-chuzhak-kontur: #D0122F; --kl-byl: .45;
  /* Сверка Cowork 20:03: роутер и HaLow — заливкой (тёмные), кант — канал и служебный; буква и ядро на заливке — цвет фона днём. */
  --kl-svyaz: #42AA66; --kl-router: #0B4D27; --kl-starlink: #FF6A00; --kl-starlink-kant: #B03A00; --kl-mesh-shlyuz: #2B1680;
  --kl-lora-shlyuz: #1773FF; --kl-lte: #1D4ED8; --kl-na-zalivke: var(--bg);
}
:root[data-theme='dark'], :root[data-theme='tactical_amber'], :root[data-theme='phosphor'], :root[data-theme='signal'] {
  --kl-klient-a: #FFE546; --kl-klient: #FFAF1D; --kl-klient-b: #FF8101;
  --kl-sluzh: #8B94F4; --kl-sotr: #00AA33; --kl-nizk: #FFA6CB; --kl-intr: #B5E3FF; --kl-prochie: var(--ink);
  --kl-chuzhak: #000000; --kl-chuzhak-kontur: #FF3B4E; --kl-byl: .45;
  --kl-svyaz: #4ADE80; --kl-router: #166534; --kl-starlink: #FF6A00; --kl-starlink-kant: transparent; --kl-mesh-shlyuz: #3B1FA3;
  --kl-lora-shlyuz: #1773FF; --kl-lte: #4C7DFF; --kl-na-zalivke: var(--ink);
}
/* Сцена NRL: штрих — цвет класса; клиенты — градиентом (#kl-grad-klient — общий <defs> страницы, screens/network.mjs). */
.set-potoki .kl-sotr { stroke: var(--kl-sotr); } .set-potoki .kl-klient { stroke: url(#kl-grad-klient) var(--kl-klient); }
.set-potoki .kl-nizk { stroke: var(--kl-nizk); } .set-potoki .kl-intr { stroke: var(--kl-intr); }
.set-potoki .kl-sluzh { stroke: var(--kl-sluzh); } .set-potoki .kl-prochie { stroke: var(--kl-prochie); }
/* Каналы связи (RP5, шлюзы, тарелка и её луч, трекеры, ноды) — зелёным (слово Open 17.10 ~19:40). */
.set-potoki .kl-svyaz { stroke: var(--kl-svyaz); }
.set-potoki text.kl-sotr { fill: var(--kl-sotr); stroke: none; } .set-potoki text.kl-klient { fill: var(--kl-klient); stroke: none; }
.set-potoki text.kl-nizk { fill: var(--kl-nizk); stroke: none; } .set-potoki text.kl-intr { fill: var(--kl-intr); stroke: none; }
.set-potoki text.kl-prochie { fill: var(--kl-prochie); stroke: none; } .set-potoki text.kl-sluzh { fill: var(--kl-sluzh); stroke: none; }
/* Точки групп, полоса долей, полоски слева — те же токены; клиенты — градиентом. */
/* Вес (0,2,0) — двойным атрибутом: сильнее общих `.set-gruppa-polosa` и `.st12-doli > i` (кадр 41 de08230: полоска клиентов —
   контуром, отрезок полосы — серым; прежде это прятала подкраска pokrasit). */
[data-klass-tsvet='sotr'][data-klass-tsvet] { background: var(--kl-sotr); box-shadow: none; }
[data-klass-tsvet='klient'][data-klass-tsvet] { background: linear-gradient(90deg, var(--kl-klient-a), var(--kl-klient-b)); box-shadow: none; }
[data-klass-tsvet='nizk'][data-klass-tsvet] { background: var(--kl-nizk); box-shadow: none; }
[data-klass-tsvet='intr'][data-klass-tsvet] { background: var(--kl-intr); box-shadow: none; }
[data-klass-tsvet='sbor'][data-klass-tsvet] { background: var(--kl-sluzh); box-shadow: none; }
[data-klass-tsvet='bezklassa'][data-klass-tsvet] { background: transparent; box-shadow: inset 0 0 0 1.5px var(--kl-prochie); }
[data-klass-tsvet='chuzhak'][data-klass-tsvet] { background: var(--kl-chuzhak); box-shadow: inset 0 0 0 1.5px var(--kl-chuzhak-kontur); }
/* «Были, не сейчас» — группа смешанная, своего класса нет: пунктир цветом текста (бледный цвет класса — у строк). Смесь цветов
   классов при 45 % на тёмном фоне выходила серой (#677781, сверка Cowork 18:23). */
[data-klass-tsvet='molchit'][data-klass-tsvet] { background: repeating-linear-gradient(90deg, var(--ink) 0 4px, transparent 4px 7px);
  box-shadow: none; }
/* Группа слева — цветной полоской, значки справа — квадратиками (v12 `kha-sw`). */
.set-gruppa-polosa { display: inline-block; width: 22px; height: 4px; border-radius: 1px; background: transparent; box-shadow: inset 0 0 0 1px var(--kl-prochie); flex: none; }
.set-potoki .kh-flow { animation: v12-bezhit var(--dur) linear infinite; }
/* Образцы легенды — те же элементы сцены и те же цвета классов. */
.v12-obrazec { width: 36px; height: 16px; flex: none; overflow: visible; }
.v12-obrazec .kl-klient { stroke: url(#kl-grad-klient) var(--kl-klient); } .v12-obrazec .kl-intr { stroke: var(--kl-intr); }
.v12-obrazec .kh-flow { animation: v12-bezhit var(--dur) linear infinite; }
.v12-obrazec .v12-sotr-mesto { stroke: var(--ok); } .v12-obrazec .v12-sotr-mesto-t { fill: var(--ok); }
/* Волна узла (v12 `_ping`): расходится и гаснет. */
.set-potoki .v12-ping { stroke: var(--nv-cy); stroke-width: 1.4; stroke-opacity: .7; transform-box: fill-box; transform-origin: center;
  animation: v12-ping 3s ease-out var(--del, 0s) infinite; }
@keyframes v12-ping { 0% { transform: scale(.6); opacity: .9; } 100% { transform: scale(3.2); opacity: 0; } }
@keyframes v12-bezhit { to { stroke-dashoffset: calc(-1px * var(--per)); } }
.set-potoki .v12-podpis, .set-potoki .v12-pod, .set-potoki .v12-imya { font: 500 10.5px var(--font-mono); paint-order: stroke;
  stroke: var(--bg); stroke-width: 3px; }
.set-potoki .v12-imya { font: 600 12px var(--font-body, var(--font-mono)); fill: var(--ink); }
.set-potoki .v12-pod { fill: var(--muted); }
.set-potoki text.v12-potok-podpis { stroke: var(--bg); stroke-width: 3px; paint-order: stroke; }
.set-potoki .v12-uzel-telo { fill: var(--kl-router); stroke: var(--kl-svyaz); stroke-width: 1.4; }
.set-potoki .v12-bukva { fill: var(--kl-na-zalivke); font: 600 11px var(--font-mono); }
.set-potoki .v12-rp5-telo { fill: var(--bg); stroke: var(--kl-sluzh); stroke-width: 1.2; }
.set-potoki .v12-rp5 path { stroke: var(--kl-sluzh); }
.set-potoki .v12-tarelka-krug { fill: var(--bg); stroke: var(--kl-starlink); stroke-width: 1.4; }
.set-potoki .v12-tarelka path, .set-potoki .v12-shevron { stroke: var(--kl-starlink); }
.set-potoki .v12-mesh-kolco { fill: var(--kl-mesh-shlyuz); stroke: var(--kl-sluzh); stroke-width: 1.6; } .set-potoki .v12-mesh-yadro { fill: var(--kl-na-zalivke); }
/* Тарелка днём — тонкий внешний кант (#FF6A00 к фону дня 2,4:1, с кантом — 5,0:1); ночью канта нет. */
.set-potoki .v12-tarelka-kant { fill: none; stroke: var(--kl-starlink-kant); stroke-width: 1; }
/* Выход LTE в сцене «Карты сети» — синий круг с «LTE»: оранжевый тарелки читался второй тарелкой; не ведёт — приглушён. */
.set-potoki .v12-lte-krug { fill: var(--bg); stroke: var(--kl-lte); stroke-width: 1.6; }
.set-potoki .v12-lte-znak { fill: var(--kl-lte); font: 700 8px var(--font-mono); }
.set-potoki .v12-lte:not(.vedet) { opacity: .55; }
.set-potoki .v12-lora { fill: var(--bg); stroke: var(--kl-lora-shlyuz); stroke-width: 1.6; }
/* Трекер LoRa (слово Open 17.10): ромб служебным цветом; не слышен свежо — контур без заливки. */
.set-potoki .v12-trek { fill: var(--kl-sluzh); stroke: var(--bg); stroke-width: 1; }
.set-potoki .v12-trek.davno { fill: var(--bg); stroke: var(--kl-sluzh); stroke-width: 1.4; }
/* Нода MESH (слово Open 17.10): кружок служебным цветом; не слышна — контур без заливки. */
.set-potoki .v12-noda { fill: var(--kl-sluzh); stroke: var(--bg); stroke-width: 1; }
.set-potoki .v12-noda.davno { fill: var(--bg); stroke: var(--kl-sluzh); stroke-width: 1.4; }
/* Веер устройств у шлюза (1.01.01.02): точка — цвет класса, кант фоном; «не определён» — контур цветом текста; «были» — бледнее
   своего класса; выбранная — кольцо цветом текста; «+N» — контур цветом текста, не серым. Тап ловят только точки и «+N». */
.set-potoki circle.v12-ustr { stroke: var(--bg); stroke-width: 1; pointer-events: auto; cursor: pointer; }
.set-potoki circle.v12-ustr.kl-sotr { fill: var(--kl-sotr); } .set-potoki circle.v12-ustr.kl-klient { fill: url(#kl-grad-klient) var(--kl-klient); }
.set-potoki circle.v12-ustr.kl-nizk { fill: var(--kl-nizk); } .set-potoki circle.v12-ustr.kl-intr { fill: var(--kl-intr); }
.set-potoki circle.v12-ustr.kl-sluzh { fill: var(--kl-sluzh); }
.set-potoki circle.v12-ustr.kl-prochie { fill: var(--bg); stroke: var(--ink); stroke-width: 1.3; }
.set-potoki .v12-ustr.byl, .set-potoki .v12-ustr-svyaz.byl { opacity: .45; }
.set-potoki .v12-ustr-vybor { stroke: var(--ink); }
/* Цель тапа поверх точки (r 12 при видимой r 6): прозрачна, но ловит палец. Точка, сдвинутая веером, — тонкая линия к своему
   настоящему месту и малая метка на нём. */
.set-potoki circle.v12-cel { fill: transparent; stroke: none; pointer-events: auto; cursor: pointer; }
/* Значки точки (шлюз, RP5, тарелка, шлюзы MESH и LoRa) — цели тапа: щелчок выбирает паспорт. */
.set-potoki [data-znachok] { pointer-events: auto; cursor: pointer; }
/* Волна узла расходится поверх RP5 рядом — щелчок по RP5 не должен уходить узлу. */
.set-potoki [data-znachok] .v12-ping { pointer-events: none; }
/* Башня NRL кольцом (karta/machta_seti.mjs): кольцо, основание, строки ветвей, «+N» лишних, линия к своему месту, метка, стрелка у края. */
.set-potoki .m12-kolco-put { stroke: var(--kl-sluzh); stroke-opacity: .6; }
.set-potoki .m12-osn-kolco { stroke: var(--kl-sluzh); } .set-potoki .m12-osn-yadro { fill: var(--kl-sluzh); }
.set-potoki .m12-vetv-t { fill: var(--ink); }
.set-potoki .m12-dop { pointer-events: auto; cursor: pointer; fill: var(--ink); text-decoration: underline; }
/* «Был» и неслышный — пустая точка: контур без заливки. */
.set-potoki .v12-ustr.m12-na-duge.byl { fill: none; opacity: .7; }
.set-potoki .m12-k-mestu { stroke: var(--ink); stroke-opacity: .5; }
/* Линия от знака к отнесённой подписи (Н-641): тоньше и бледнее линии к месту — указатель, а не связь. */
.set-potoki .m12-k-podpisi { stroke: var(--muted); stroke-opacity: .7; }
.set-potoki .m12-sost-zam { fill: var(--warn); } .set-potoki .m12-sost-probl { fill: var(--critical); }
.set-potoki .m12-metka-krug { fill: var(--kl-sluzh); stroke: var(--bg); stroke-width: 1.5; }
.set-potoki .m12-metka-krug.m12-ur-zamechanie { fill: var(--warn); } .set-potoki .m12-metka-krug.m12-ur-problema { fill: var(--critical); }
.set-potoki .m12-strelka { pointer-events: auto; cursor: pointer; }
.set-potoki .m12-strelka-znak { font: 700 16px var(--font-mono); fill: var(--ink); paint-order: stroke; stroke: var(--bg); stroke-width: 3px; }
.set-potoki .m12-esche { pointer-events: auto; cursor: pointer; fill: var(--ink); text-decoration: underline; }
/* Выноска мачты (круг 2): тонкая линия от основания к подножию; выноска поверх мест ушедших — приглушена, ушедшие видны поверх. */
.set-potoki .m12-vynoska-liniya { stroke: var(--kl-sluzh); stroke-opacity: .6; }
.set-potoki .m12-priglushena { opacity: .4; }
/* Неон мачты (круг 2 Б, решения Open 02.11 «кольцо… залей цвет», «неон — свечение ок»): кольцо с заливкой цветом типа; свечение —
   цвет состояния; проблема — медленное «дыхание» (m12-trevoga: и при «только тревоги»); нет данных — без свечения, пунктиром;
   пульс по трафику (--puls — период, ≤ 3 Гц); вспышка на отчёт или пакет — один раз; люди — белое свечение. */
:root { --m12-tip-tarelka: #E0E7FF; --m12-tip-router: #6366F1; --m12-tip-rp5: #22D3EE; --m12-tip-mesh: #A855F7; --m12-tip-lora: #0EA5E9;
  --m12-tip-osnovanie: #FFFFFF; }
.set-potoki .m12-kolco { stroke-width: 2; fill-opacity: .3; transform-box: fill-box; transform-origin: center; }
.set-potoki .m12-tip-tarelka { stroke: var(--m12-tip-tarelka); fill: var(--m12-tip-tarelka); }
.set-potoki .m12-tip-router { stroke: var(--m12-tip-router); fill: var(--m12-tip-router); }
.set-potoki .m12-tip-rp5 { stroke: var(--m12-tip-rp5); fill: var(--m12-tip-rp5); }
.set-potoki .m12-tip-mesh { stroke: var(--m12-tip-mesh); fill: var(--m12-tip-mesh); }
.set-potoki .m12-tip-lora { stroke: var(--m12-tip-lora); fill: var(--m12-tip-lora); }
.set-potoki .m12-osn-kolco.m12-tip-osnovanie { fill: var(--m12-tip-osnovanie); stroke: var(--ink); }
.set-potoki .m12-kolco.m12-pustoy { stroke-dasharray: 3 3; fill-opacity: .08; }
.set-potoki .m12-glif { stroke: var(--ink); } .set-potoki .m12-glif-t { fill: var(--ink); } .set-potoki .v12-bukva.m12-glif { fill: var(--ink); }
.set-potoki .m12-svechenie { stroke: none; opacity: .5; filter: blur(3px); }
.set-potoki .m12-sv-norma { fill: var(--ok); } .set-potoki .m12-sv-zamechanie { fill: var(--warn); } .set-potoki .m12-sv-problema { fill: var(--critical); }
.set-potoki .m12-trevoga { animation: m12-dyhanie 2.4s ease-in-out infinite; }
/* Рамка захвата аварии (слово Open 268, 269): скобки цветом аварии, дышат вместе со свечением тревоги; «уменьшить движение» — стоят. */
.set-potoki .m12-zahvat, .sl-zahvat path { stroke: var(--critical); fill: none; stroke-width: 1.6; stroke-linecap: round; animation: m12-dyhanie 2.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .set-potoki .m12-zahvat, .sl-zahvat path { animation: none; } }
@keyframes m12-dyhanie { 0%, 100% { opacity: .3; } 50% { opacity: .85; } }
.set-potoki .m12-kolco.m12-puls { animation: m12-puls var(--puls) ease-in-out infinite; }
/* Движение — только transform и opacity: их браузер ведёт без перерисовки слоя. */
@keyframes m12-puls { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.15); opacity: .6; } }
.set-potoki .v12-ustr.m12-puls { animation: m12-puls-t var(--puls) ease-in-out infinite; }
@keyframes m12-puls-t { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
.set-potoki .m12-kolco.m12-vspyshka { animation: m12-vspyshka .7s ease-out 1; }
@keyframes m12-vspyshka { 0% { transform: scale(1.4); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
.set-potoki .m12-chelovek { filter: drop-shadow(0 0 3px #FFFFFF); }
/* Устройства ветвей — кольцом цветом типа, как ярусы: ноды MESH и трекеры — заливка и кольцо цветом типа; люди — белое кольцо, заливка — класс. */
.set-potoki .v12-ustr.m12-ustr-kolco { stroke-width: 2; }
.set-potoki .v12-ustr.m12-tip-mesh { fill: var(--m12-tip-mesh); fill-opacity: .45; stroke: var(--m12-tip-mesh); }
.set-potoki .v12-ustr.m12-tip-lora { fill: var(--m12-tip-lora); fill-opacity: .45; stroke: var(--m12-tip-lora); }
.set-potoki .v12-ustr.m12-tip-chelovek { stroke: var(--m12-tip-osnovanie); }
.set-potoki .m12-znak-sost { font: 700 11px var(--font-mono); paint-order: stroke; stroke: var(--bg); stroke-width: 3px; }
.set-potoki .m12-znak-zamechanie { fill: var(--warn); } .set-potoki .m12-znak-problema { fill: var(--critical); }
/* Системное «уменьшить движение» — как «только тревоги»: пульс и вспышки стоят, дышит только проблема. */
@media (prefers-reduced-motion: reduce) { .set-potoki .m12-puls, .set-potoki .m12-vspyshka { animation: none; } }
.set-potoki .v12-k-mestu { stroke: var(--ink); stroke-opacity: .55; }
.set-potoki .v12-ist { fill: var(--ink); fill-opacity: .7; }
.set-potoki .v12-krug-tochnosti { stroke: var(--muted); stroke-dasharray: 4 4; fill: var(--muted); fill-opacity: .08; pointer-events: none; }
/* Круг точности шире 200 px — без заливки: накрыл бы полкарты. */
.set-potoki .v12-krug-tochnosti.m12-krug-shirokiy, path.sl-krug-tochnosti.sl-krug-shirokiy { fill: none; fill-opacity: 0; stroke-dasharray: 2 6; }

/* Этап 3 «Карты сети» (1.01.01.05): цвета категорий трафика — видео красный, мессенджеры зелёный, соцсети розовый, музыка
   фиолетовый, карты бирюзовый, работа синий, обновления серо-голубой, игры оранжевый, прочее приглушённый. День — темнее
   (контраст к светлому фону), ночь — светлее. Линия сотрудника на карте — цвет категории поверх цвета класса (В3). */
:root {
  --kat-video: #C8102E; --kat-messendzhery: #0E8A3A; --kat-socseti: #C2357E; --kat-muzyka: #6B3FB5; --kat-karty: #0E8C8C;
  --kat-rabota: #1F5FBF; --kat-obnovleniya: #5E7A93; --kat-igry: #C26100; --kat-prochee: #8A8F98;
}
:root[data-theme='dark'], :root[data-theme='tactical_amber'], :root[data-theme='phosphor'], :root[data-theme='signal'] {
  --kat-video: #FF4D5E; --kat-messendzhery: #3DDC7A; --kat-socseti: #FF6FB3; --kat-muzyka: #A98BFF; --kat-karty: #33D6D6;
  --kat-rabota: #5C9DFF; --kat-obnovleniya: #8FA9C0; --kat-igry: #FF9B3D; --kat-prochee: #9AA0A8;
}
.set-potoki .v12-potok.kat-video { stroke: var(--kat-video); } .set-potoki .v12-potok.kat-messendzhery { stroke: var(--kat-messendzhery); }
.set-potoki .v12-potok.kat-socseti { stroke: var(--kat-socseti); } .set-potoki .v12-potok.kat-muzyka { stroke: var(--kat-muzyka); }
.set-potoki .v12-potok.kat-karty { stroke: var(--kat-karty); } .set-potoki .v12-potok.kat-rabota { stroke: var(--kat-rabota); }
.set-potoki .v12-potok.kat-obnovleniya { stroke: var(--kat-obnovleniya); } .set-potoki .v12-potok.kat-igry { stroke: var(--kat-igry); }
.set-potoki .v12-potok.kat-prochee { stroke: var(--kat-prochee); }
/* Устройство в блоке — точка с красным контуром: ограничено или на паузе по роутеру. */
.set-potoki .v12-ustr.blok { stroke: var(--kl-chuzhak-kontur); stroke-width: 2; }
.st3-blok { display: flex; flex-direction: column; gap: 6px; margin: 6px 0; }
.st3-knopki { justify-content: flex-start; }
.st3-sroki { display: flex; flex-wrap: wrap; gap: 4px; }
.st3-sroki-zag { margin-top: 4px; color: var(--muted); }
.st3-srok { font-size: var(--t-sm); padding: 2px 8px; border-radius: 10px; border: 1px solid var(--line); background: transparent; color: var(--ink); cursor: pointer; }
.st3-srok:hover { border-color: var(--accent); }
.st3-legenda { display: flex; flex-wrap: wrap; gap: 4px 10px; margin: 4px 0; }
.st3-leg { display: inline-flex; align-items: center; gap: 4px; background: none; border: 0; color: var(--ink); font-size: var(--t-sm); cursor: pointer; padding: 0; }
.st3-leg.off { opacity: .35; }
.st3-leg-cvet { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }
.st3-ryad { display: flex; align-items: flex-end; gap: 2px; height: 64px; margin: 4px 0; border-bottom: 1px solid var(--line); }
.st3-stolb { flex: 1; height: 100%; display: flex; flex-direction: column-reverse; }
.st3-stolb i { display: block; width: 100%; }
.st3-kolco-ryad { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; }
.st3-kolco { width: 120px; height: 120px; flex: none; }
.st3-kolco path { cursor: pointer; }
.st3-domeny { flex: 1; min-width: 180px; }
.st3-lenta { display: flex; flex-direction: column; gap: 3px; }
.st3-lenta-str { display: grid; grid-template-columns: 140px 1fr; gap: 6px; align-items: center; }
.st3-lenta-domen { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st3-lenta-polosa { position: relative; height: 8px; background: var(--line); border-radius: 2px; }
.st3-lenta-polosa i { position: absolute; top: 0; height: 100%; }
.st3-plitki { display: flex; flex-wrap: wrap; gap: 4px; }
.st3-plitka { min-width: 64px; padding: 4px 6px; border-left: 4px solid; display: flex; flex-direction: column; background: var(--panel); }
/* «Оборудование», часть 1: подвкладки в шапке, готовность лагеря, «В работе», журнал, паспорт. */
.obor-vkladki { margin-left: 14px; }
.obor-zag { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.obor-filtry { display: flex; gap: 2px; flex-wrap: wrap; margin-bottom: 8px; }
.obor-gt { margin-top: 8px; border-top: 1px solid var(--hair); padding-top: 6px; }
.obor-gt-itog { font: 600 var(--t-xs) var(--nv-mono); text-transform: uppercase; letter-spacing: .04em; color: var(--warn); margin-bottom: 4px; }
.obor-gt-itog[data-gotov="true"] { color: var(--ok); }
.obor-gt-str { display: grid; grid-template-columns: 110px minmax(0, 1fr) auto; gap: 8px; align-items: baseline; padding: 2px 0; }
.obor-gt-imya { color: var(--muted); font-size: var(--t-sm); }
.obor-sost { font: 600 var(--t-xs) var(--nv-mono); text-transform: uppercase; letter-spacing: .04em; white-space: nowrap; color: var(--muted); }
.obor-sost[data-sost="da"], .obor-sost[data-sost="chitaetsya"] { color: var(--ok); }
.obor-sost[data-sost="zamech"], .obor-sost[data-sost="molchit"] { color: var(--warn); }
.obor-tab { display: flex; flex-direction: column; }
.obor-str { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) 110px 80px 76px; gap: 8px;
  align-items: center; padding: 5px 0; border-bottom: 1px solid var(--hair); font-size: var(--t-sm); }
.obor-str > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.obor-kolonki { border-bottom-color: var(--border); }
.obor-zh { display: flex; flex-direction: column; }
.obor-zh-str { display: grid; grid-template-columns: 130px minmax(0, 1fr) 110px; gap: 8px; padding: 5px 0; border-bottom: 1px solid var(--hair); font-size: var(--t-sm); }
.obor-ps-str { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 8px; font-size: var(--t-sm); padding: 2px 0; }
.obor-spisok { flex: 0 0 220px; display: flex; flex-direction: column; gap: 2px; position: sticky; top: 0; }
.obor-sp-str { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 8px; text-align: left; background: none; border: 0;
  border-left: 2px solid var(--hair); padding: 5px 8px; cursor: pointer; color: var(--ink); font: inherit; }
.obor-sp-str:hover { border-left-color: var(--accent); }
.obor-sp-str > .muted { grid-column: 1 / -1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* «Оборудование → Найдено» (часть 2а): строка найденного — имя и метка, что видно, где, когда; кнопки решений — у тех, кто правит лагерь. */
.obor-nd { display: flex; flex-direction: column; }
.obor-nd-str { display: flex; flex-direction: column; gap: 2px; padding: 8px 0; border-bottom: 1px solid var(--hair); cursor: pointer; }
.obor-nd-str:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.obor-nd-glav { display: flex; align-items: baseline; gap: 8px; }
.obor-nd-knopki { display: flex; gap: 6px; margin-top: 4px; }

/* «Проверка» и «Данные» */
.dn-plitki { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
/* Шапка «Проверки» — пять плиток одной высоты на всю ширину; последняя («Последняя проверка» с кнопками) шире. */
.prv-verh { grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 1.3fr); gap: 12px; padding: 0; margin-bottom: 12px; }
.prv-plitka-proverka { flex-direction: row; align-items: center; min-width: 0; min-height: 96px; }
.prv-plitka-knopki { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.dn-knopki, .dn-filtry { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
.dn-kolonki { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 14px; align-items: start; }
/* Одна сетка на вкладку: края колонок одни сверху донизу; колонка — стопка блоков по содержимому, без дыр под короткими.
   Дорожки и зазор — те же, что у плиток шапки (4 × 1fr + 1,3fr): левая колонка — три дорожки, правая — две, края совпадают. */
.prv-setka { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 1.3fr); gap: 12px; align-items: start; }
#prv-kol-l { grid-column: 1 / 4; }
#prv-kol-p { grid-column: 4 / 6; }
.prv-kol { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.prv-kol > .prv-blok { margin-bottom: 0; }
.prv-podval { margin-top: 10px; }
/* Уже 1280 px две колонки дают обрезку и пустоты — одна колонка, правая уходит вниз. */
@media (max-width: 1279px) { .prv-setka { grid-template-columns: minmax(0, 1fr); } #prv-kol-l, #prv-kol-p { grid-column: 1 / -1; } }
/* Кнопки отбора — в заголовке «Что исправить» справа. */
.prv-knopki { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; justify-content: flex-end; margin-left: auto; }
/* Кнопка перехода — сразу за текстом, а не у правого края через пустоту. */
.prv-isp-str { display: grid; grid-template-columns: 92px minmax(0, max-content) auto; justify-content: start; gap: 10px 14px; align-items: start; padding: 6px 0;
  border-top: 1px solid var(--line); }
.prv-isp-tekst { display: flex; flex-direction: column; gap: 2px; min-width: 0; overflow-wrap: anywhere; }
.prv-isp-str.warn .prv-isp-chto { color: var(--warn); }
.prv-isp-str.down .prv-isp-chto { color: var(--crit, var(--down)); }
.prv-isp-knopka { white-space: nowrap; }
.prv-blok, .dn-blok { margin-bottom: 12px; }
/* Таблица лагеря — одна сетка: колонки по содержимому, «Итог» — остаток; шапка и строки — её подсетки, названия над своими строками. */
.prv-tablica { display: grid; grid-template-columns: max-content max-content max-content minmax(0, 1fr) max-content; column-gap: 14px; }
.prv-str, .prv-shapka { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; padding: 4px 0;
  border-top: 1px solid var(--line); align-items: baseline; }
.prv-shapka { border-top: 0; padding-top: 0; }
.prv-str.warn .prv-itog { color: var(--warn); }
.prv-str.down .prv-itog { color: var(--crit, var(--down)); }
.prv-str.silent { opacity: .65; }
/* Метка статуса — справа в строке, словом и цветом статуса. */
.prv-metka { justify-self: end; font: 600 var(--t-xs) var(--nv-caps); letter-spacing: .04em; text-transform: uppercase; padding: 1px 6px;
  border: 1px solid currentColor; border-radius: 3px; white-space: nowrap; }
.prv-metka.ok { color: var(--ok); }
.prv-metka.warn { color: var(--warn); }
.prv-metka.down { color: var(--crit, var(--down)); }
.prv-metka.silent { color: var(--muted); }
.prv-isp-str .prv-metka { justify-self: start; }
/* «Выкладки» — в две колонки, без прокрутки; «Установка» и «Версии» — компактно справа. */
.prv-vykl-kolonki { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 14px; }
.prv-sprava .set-kv { padding: 2px 0; }
/* Сумма файла RP5 не совпала ни с одним внесённым выпуском — значение оранжевым, как итог строки с замечанием. */
.set-kv[data-sovpalo="false"] > b { color: var(--warn); }
.dn-klass { display: grid; grid-template-columns: 120px minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr); gap: 8px; padding: 3px 0; border-top: 1px solid var(--line); }
.dn-zh { display: grid; grid-template-columns: 96px 80px minmax(0, 1fr) 110px; gap: 8px; }
.dn-zh-chto { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 1100px) { .dn-kolonki { grid-template-columns: minmax(0, 1fr); }
  .prv-verh { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* «Рядом на карте» в карточке терминала: строка в две линии — сверху имя и число справа, снизу пояснение или метки узлов MESH;
   переход — вся строка. Ширина колонки та же: длинное имя и метки переносятся, а не режутся многоточием. */
.kart-ryadom-str { display: flex; flex-direction: column; gap: 2px; padding: 6px 0; border-top: 1px solid var(--line); color: inherit; text-decoration: none; }
.kart-ryadom-str:first-of-type { border-top: 0; }
a.kart-ryadom-str:hover b { text-decoration: underline; }
.kart-ryadom-verh { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; min-width: 0; }
.kart-ryadom-imya { min-width: 0; overflow-wrap: anywhere; }
.kart-ryadom-chislo { flex: none; white-space: nowrap; }
.kart-ryadom-niz { min-width: 0; overflow-wrap: anywhere; }
.kart-ryadom-uzly { display: flex; flex-wrap: wrap; gap: 3px 6px; }
.kart-ryadom-uzel { padding: 0 5px; border: 1px solid var(--line); color: var(--muted); white-space: nowrap; }
/* «Отображение связи»: «как считаем ›», панель железа, окна «Как считаем» и «Состав железа». */
.sv-plan-chestno-ryad { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.sv-plan-chestno-ryad .sv-plan-chestno { flex: 1 1 auto; min-width: 0; }
.sv-plan-chestno-ryad #sv-plan-kak { flex: none; }
.sv-plan-knopki { display: flex; flex-wrap: wrap; gap: 6px; }
.pl6-zhelezo { display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--line); padding-top: 8px; }
.pl6-zhelezo-chislo { display: inline-flex; align-items: center; gap: 6px; }
.pl7-kak { display: flex; flex-direction: column; gap: 6px; border-top: 1px solid var(--line); padding-top: 8px; }
.pl7-kak .pl6-shag { grid-template-columns: 14px minmax(0, 1fr); gap: 6px; }
.pl6-zh-stroki { display: flex; flex-direction: column; gap: 6px; }
.pl6-zh-stroka { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 8px; }
.pl6-zh-stroka > .pl6-chto, .pl6-zh-stroka > .muted { grid-column: 1; }
.pl6-zh-stroka > .pl6-sht { grid-column: 2; grid-row: 1; }
.pl6-okno { width: min(860px, calc(100vw - 40px)); }
.pl6-shagi { display: flex; flex-direction: column; gap: 6px; }
.pl6-shag { display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 8px; }
.pl6-shag-n { font-family: var(--font-mono); color: var(--accent); }
.pl6-shag[data-schitaem="0"] .pl6-shag-n { color: var(--muted); }
.pl6-formuly { display: flex; flex-direction: column; gap: 3px; border-top: 1px solid var(--line); padding-top: 6px; }
.pl6-kv { display: grid; grid-template-columns: 140px minmax(0, 1fr); gap: 8px; padding: 3px 0; border-top: 1px solid var(--line); }
.pl6-spisok { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
.pl6-tabl-str { display: grid; grid-template-columns: minmax(0, 1.2fr) 36px minmax(0, 2fr) minmax(0, 1fr); gap: 8px; padding: 4px 0; border-top: 1px solid var(--line); }
.pl6-tabl-golova { border-top: 0; }
.pl6-sht { font-family: var(--font-mono); }
/* «Оборудование»: девять пунктов готовности с кнопкой строки, панель и окно ключей (только состояние), «Новый лагерь · по шагам». */
.obor-levaya { flex: 0 0 220px; display: flex; flex-direction: column; gap: 14px; position: sticky; top: 0; }
.obor-levaya .obor-spisok { flex: none; position: static; }
.obor-gt-zag { font-size: var(--t-sm); font-weight: 600; margin-bottom: 2px; }
.obor-gt-str { grid-template-columns: 150px minmax(0, 1fr) auto auto; }
.obor-kl { display: flex; flex-direction: column; gap: 4px; }
.obor-kl-zag { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
/* Колонка 220 px: «задано 7 из 7 · копия · сверена» в одну строку не входит — значения переносятся под имя лагеря. */
.obor-kl-str { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px; font-size: var(--t-xs); padding: 2px 0;
  border-bottom: 1px solid var(--hair); }
.obor-kl-imya { flex: 1 1 60px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.obor-kl .pill { align-self: flex-start; margin-top: 4px; }
.obor-kl-tab { display: flex; flex-direction: column; }
.obor-kl-tstr { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) 90px 90px 90px; gap: 8px; padding: 4px 0;
  border-bottom: 1px solid var(--hair); font-size: var(--t-sm); }
.obor-kl-chto { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; padding: 2px 0; font-size: var(--t-sm); }
.obor-kl-vid { padding-left: 14px; font-size: var(--t-xs); }
.obor-kl-pravilo { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 6px; padding: 2px 0; font-size: var(--t-sm); }
.obor-nl { padding: 12px 14px; margin-top: 12px; }
.obor-nl-shag { display: grid; grid-template-columns: 18px 130px minmax(0, 1fr); gap: 8px; align-items: baseline; padding: 3px 0; }
.obor-nl-niz { display: flex; align-items: center; gap: 6px; margin-top: 8px; padding-top: 6px; border-top: 1px solid var(--hair); }
.obor-gt-itog[data-gotov="ogovorka"], .obor-sost[data-sost="ogovorka"] { color: var(--accent); }
/* 1.01.07.07 · «Оборудование» тремя колонками и «Данные» (ТЗ 10.11 ред. 2, разделы 8–9).
   Оборудование: слева карточки лагерей с кругом, ключи с кругом, «Кто работает»; в центре таблица готовности под полосой
   из 9 отрезков (кнопки — одной колонкой); справа «Что стоит» (паспорт встаёт на его место). Место круга — .krug-slot:
   общий круг (ui/krug.mjs) подставляется по data-krug-slot, пока — доля числом в тонком кольце, без данных — пунктир. */
.obor-tri > .obor-levaya { flex: 0 0 250px; }
.obor-tri > .obor-bok { flex: 0 0 300px; }
.krug-slot { flex: none; display: inline-grid; place-items: center; width: 56px; height: 56px; overflow: hidden; }
/* Кольцо рисует сам общий круг (56 px — меньше 54 круг не пишет число; колонка 250 px): у слота своей рамки нет, иначе два кольца и круг поверх текста. */
.krug-slot > .krug { width: 56px; height: 56px; }
.obor-sp-str { grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; }
.obor-sp-str > .krug-slot { grid-row: span 2; }
.obor-sp-str > .muted { grid-column: 2 / -1; }
.obor-kl-verh { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.obor-kl-verh .obor-kl-zag { margin-bottom: 0; flex-wrap: wrap; }
.obor-kto { display: flex; flex-direction: column; gap: 4px; }
.obor-kto .badge { display: inline-block; margin: 0 6px 4px 0; }
.obor-gt-polosa { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: 3px; margin: 6px 0 8px; }
.obor-gt-seg { height: 6px; border-radius: 1px; background: var(--muted); opacity: .35; }
.obor-gt-seg[data-sost="da"] { background: var(--ok); opacity: 1; }
.obor-gt-seg[data-sost="zamech"] { background: var(--warn); opacity: 1; }
.obor-gt-shapka, .obor-gt-str { grid-template-columns: 170px minmax(0, 1fr) 110px 150px; }
.obor-gt-shapka { display: grid; gap: 8px; padding-bottom: 3px; border-bottom: 1px solid var(--hair); }
.obor-gt-str { border-bottom: 1px solid var(--hair); padding: 4px 0; align-items: center; }
.obor-gt-str > :last-child { justify-self: start; }
.obor-chto { display: flex; flex-direction: column; gap: 2px; }
.obor-chto-lager { font-weight: 600; font-size: var(--t-sm); margin-top: 6px; }
.obor-u { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: center; padding: 4px 0; border-bottom: 1px solid var(--hair); }
.obor-u > .linklike { text-align: left; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#obor-chto-nazad { margin-bottom: 8px; }
/* «Новый лагерь»: семь шагов одной строкой, заголовок и низ — на всю ширину. */
.obor-nl { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px 12px; }
.obor-nl > .obor-kl-zag, .obor-nl > .obor-nl-niz { grid-column: 1 / -1; }
.obor-nl-shag { grid-template-columns: 18px minmax(0, 1fr); align-content: start; }
.obor-nl-shag > :last-child { grid-column: 2; }
/* Данные: 7 плиток + плитка с двумя кнопками — сетка из 8 равных ячеек; классы с цветной меткой; цепочка «где лежат». */
.dn-plitki { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 10px; }
.dn-plitka { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.dn-plitka > .cap, .dn-plitka-pod { overflow: hidden; white-space: normal; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.dn-plitka-pod { min-height: 1.3em; }
.dn-plitki > .dn-knopki { margin: 0; flex-direction: column; flex-wrap: nowrap; align-items: stretch; justify-content: center; }
.dn-plitki > .dn-knopki > * { width: 100%; }
@media (max-width: 1300px) { .dn-plitki { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.dn-klass { grid-template-columns: 150px minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr); }
.dn-klass-shapka { border-top: 0; }
.dn-klass-imya { display: inline-flex; align-items: center; gap: 6px; }
.dn-metka { flex: none; width: 10px; height: 10px; border-radius: 2px; }
.dn-metka[data-metka="k0"] { background: #2fcf8a; }
.dn-metka[data-metka="k1"] { background: #9bd65a; }
.dn-metka[data-metka="k2"] { background: #ffb020; }
.dn-metka[data-metka="k3"] { background: #ff8a3d; }
.dn-metka[data-metka="k4"] { background: #ff5a55; }
.dn-cep { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; margin: 4px 0 6px; }
.dn-cep-zveno { position: relative; border: 1px solid var(--nv-line, var(--line)); padding: 8px 10px; }
.dn-cep-zveno + .dn-cep-zveno::before { content: '→'; position: absolute; left: -15px; top: 50%; transform: translateY(-50%); color: var(--muted); }
.dn-srok { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; }
.dn-srok > :last-child { text-align: right; justify-self: end; }
/* Колонка — стопка блоков по содержимому (общее правило «блоки без пустот»): ни колонка, ни журнал не тянутся по соседней. */
.dn-kol { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.dn-kol > .dn-blok { margin-bottom: 0; }

/* Приглушённое (data-net-v-versii) полевым ролям не показывается: body[data-seroe] ставит postavitSeroe по роли входа */
body[data-seroe="0"] [data-net-v-versii] { display: none !important; }

/* Star Camp · «Ticket и касса» (этап 4, Ш1). Светлая тема прототипа Cowork v3 — только внутри `.camp`: рельс и шапка пульта
   остаются в теме человека. Цвета — свои, не --nv-*: тёмная тема пульта не должна перекрашивать экран продукта.
   Экран не листается на 1707×932 и 1366×768 — строки и таблицы ужимаются, а не уходят вниз. */
.camp {
  --cp-bg: #E9EBE5; --cp-card: #FFFFFF; --cp-tx: #1D2A25; --cp-mut: #56645D; --cp-line: #E6E9E3; --cp-ak: #E2622B;
  --cp-ok: #1E7444; --cp-okf: #E2F1E8; --cp-warn: #8A5A00; --cp-warnf: #FFF4DC; --cp-dor: #E3E7E1;
  flex: 1 1 auto; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 8px; padding: 10px 16px 10px;
  background: var(--cp-bg); color: var(--cp-tx); font-size: var(--t-md); line-height: 1.4; font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-variant-numeric: tabular-nums;
}
.camp b { font-weight: 800; }
.camp .camp-mut { color: var(--cp-mut); }
.camp .camp-mono { font-variant-numeric: tabular-nums; color: var(--cp-mut); }
.camp-hd { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; min-height: 36px; }
.camp-hd h1 { margin: 0; font-family: inherit; font-size: var(--t-xl); font-weight: 800; letter-spacing: -.01em; }
.camp-period { padding: 3px 10px; border-radius: 999px; background: var(--cp-card); font-weight: 700; font-size: var(--t-sm); }
.camp-hd-knopki { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.camp-btn { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 14px; border-radius: 10px; border: 1.5px solid #C3CBC2;
  background: var(--cp-card); color: var(--cp-tx); font-weight: 700; font-size: var(--t-sm); line-height: 1; cursor: pointer; white-space: nowrap; }
.camp-btn.glav { background: var(--cp-ak); border-color: var(--cp-ak); color: #FFFFFF; }
.camp-btn:disabled { opacity: .45; cursor: default; }
.camp-avariya { display: flex; flex-wrap: wrap; gap: 4px 10px; padding: 8px 14px; border-radius: 12px; background: var(--cp-warnf);
  border: 1.5px solid #E9C46A; color: var(--cp-warn); }
.camp-card { background: var(--cp-card); border-radius: 16px; padding: 10px 14px; min-width: 0; min-height: 0; }
.camp-ht { font-size: var(--t-xs); font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--cp-mut); }
.camp-ht-ryad { display: flex; align-items: baseline; gap: 10px; }
.camp-pod { margin-top: 6px; font-size: var(--t-sm); color: var(--cp-mut); }
.camp-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; flex: none; }
.camp-kpi-telo { display: flex; align-items: center; gap: 12px; margin-top: 6px; }
.camp-kolco-box { position: relative; flex: none; width: 84px; height: 84px; }
.camp-kolco { width: 100%; height: 100%; transform: rotate(-90deg); }
.camp-kolco circle { fill: none; stroke-width: 9; }
.camp-kolco-dor { stroke: var(--cp-dor); }
.camp-kolco-duga { stroke: var(--cp-ak); stroke-linecap: round; }
.camp-kolco-c { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.05; }
.camp-kolco-c b { font-size: var(--t-xl); }
.camp-kolco-c b.dlinnoe { font-size: var(--t-md); }
.camp-kolco-c span { font-size: var(--t-xs); color: var(--cp-mut); }
.camp-kpi-stroki { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.camp-kv { display: flex; justify-content: space-between; gap: 8px; font-size: var(--t-sm); }
.camp-kv > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.camp-kv.mut { color: var(--cp-mut); }
.camp-kv.malo b { color: var(--cp-ak); }
.camp-ryad2 { flex: 1 1 auto; min-height: 0; display: grid; grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr); gap: 10px; }
.camp-ryad3 { flex: none; display: grid; grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr); gap: 10px; }
.camp-prod { display: flex; flex-direction: column; gap: 6px; overflow: hidden; }
.camp-stolby { display: flex; align-items: flex-end; gap: 4px; height: 92px; flex: none; }
.camp-stolb { flex: 1 1 0; min-width: 0; height: 100%; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.camp-stolb em { font-weight: 700; font-size: var(--t-xs); line-height: 1; font-style: normal; color: var(--cp-mut); min-height: 11px; }
.camp-stolb-trubka { flex: 1 1 auto; width: 100%; max-width: 26px; display: flex; align-items: flex-end; }
.camp-stolb-trubka i { display: block; width: 100%; border-radius: 4px 4px 2px 2px; background: var(--cp-ak); }
.camp-stolb.budet .camp-stolb-trubka { border-bottom: 2px dotted var(--cp-dor); }
.camp-stolb span { font-size: var(--t-xs); color: var(--cp-mut); }
.camp-stolb.seychas span { color: var(--cp-tx); font-weight: 800; }
.camp-podzag { display: flex; flex-wrap: wrap; align-items: baseline; align-content: flex-start; gap: 4px 10px; flex: 1 1 auto; min-height: 0; overflow: auto; }
.camp-podzag > .camp-ht { margin-top: 4px; }
.camp-tbl { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.camp-tbl th { font-size: var(--t-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--cp-mut); text-align: right;
  padding: 4px 0 4px 10px; white-space: nowrap; }
.camp-tbl th:first-child, .camp-tbl td:first-child { text-align: left; padding-left: 0; }
.camp-tbl td { padding: 5px 0 5px 10px; border-top: 1px solid var(--cp-line); text-align: right; white-space: nowrap; }
.camp-tbl tr.sum td { font-weight: 800; border-top: 1.5px solid var(--cp-tx); }
.camp-who { display: flex; align-items: center; gap: 9px; min-width: 0; }
.camp-who > i { flex: none; width: 30px; height: 30px; border-radius: 15px; background: #243E37; color: #FFFFFF; display: flex; align-items: center;
  justify-content: center; font-size: var(--t-xs); font-weight: 800; font-style: normal; }
.camp-who > span { min-width: 0; }
.camp-who b { display: block; font-weight: 700; }
.camp-who span span { display: block; font-size: var(--t-sm); color: var(--cp-mut); overflow: hidden; text-overflow: ellipsis; }
.camp-sob { display: flex; flex-direction: column; gap: 2px; overflow: hidden; }
.camp-sob-str { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 8px; padding: 6px 0; border-top: 1px solid var(--cp-line); font-size: var(--t-sm); }
.camp-sob-str:first-of-type { border-top: 0; }
.camp-sob-t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.camp-tochka { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-top: 1px solid var(--cp-line); }
.camp-tochka:first-of-type { border-top: 0; }
.camp-tochka-t { min-width: 0; display: flex; flex-direction: column; }
.camp-tochka-t > span { font-size: var(--t-sm); }
.camp-tag { flex: none; padding: 3px 10px; border-radius: 999px; font-weight: 700; font-size: var(--t-sm); background: var(--cp-okf); color: var(--cp-ok); }
.camp-tag.zapas { background: var(--cp-warnf); color: var(--cp-warn); }
.camp-tag.net { background: var(--cp-dor); color: var(--cp-mut); }
.camp-zapas { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--cp-line); }
#camp-tochki { display: grid; grid-template-columns: minmax(0, 1fr); align-content: start; }
#camp-tochki:has(.camp-zapas) { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); column-gap: 18px; }
#camp-tochki:has(.camp-zapas) > .camp-ht { grid-column: 1 / -1; }
#camp-tochki:has(.camp-zapas) > .camp-zapas { grid-column: 2; grid-row: 2 / span 6; margin-top: 0; padding-top: 0; border-top: 0; }
/* Узкое окно (1366): числа карточек — меньше, кольцо — меньше; ряды те же. */
@media (max-width: 1500px) {
  .camp-kolco-box { width: 70px; height: 70px; }
  .camp-kolco-c b { font-size: var(--t-lg); }
  .camp-kolco-c b.dlinnoe { font-size: var(--t-sm); }
  .camp-kv, .camp-tbl, .camp-sob-str { font-size: var(--t-sm); }
  .camp-stolby { height: 76px; }
}
/* Окно ниже 960 (Open 1707×932, 1366×768): данных столько же, строки плотнее — продавец одной строкой, столбики и кольца ниже. */
@media (max-height: 960px) {
  .camp { gap: 6px; padding: 8px 14px 8px; }
  .camp-hd { min-height: 32px; }
  .camp-btn { height: 32px; }
  .camp-avariya { padding: 5px 12px; }
  .camp-card { padding: 8px 12px; }
  .camp-kpi-telo { margin-top: 4px; }
  .camp-kolco-box { width: 60px; height: 60px; }
  .camp-kolco-c b { font-size: var(--t-md); }
  .camp-kolco-c b.dlinnoe { font-size: var(--t-sm); }
  .camp-kolco-c span { font-size: var(--t-xs); }
  .camp-pod { margin-top: 3px; }
  .camp-tbl td { padding: 3px 0 3px 10px; }
  .camp-who > i { width: 22px; height: 22px; font-size: var(--t-xs); }
  .camp-who > span { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
  .camp-who b { display: inline; white-space: nowrap; }
  .camp-who span span { display: inline; white-space: nowrap; }
  .camp-sob-str { padding: 4px 0; }
  .camp-tochka { padding: 3px 0; }
}
@media (max-height: 800px) {
  /* Баннер аварии связи длинный (слова Open) — в низком окне плотнее, чтобы ряд «Продавцов» не срезался. */
  .camp-avariya { padding: 3px 12px; gap: 0 8px; font-size: var(--t-sm); line-height: 1.25; }
  .camp-stolby { height: 38px; }
  .camp-stolb em { display: none; }
  .camp-tbl th { padding: 2px 0 2px 10px; }
  .camp-ht { font-size: var(--t-xs); }
}
/* Цвета сегментов кольца и квадратиков строк — как в прототипе v3: тарифы синими от светлого к тёмному, вошли — зелёным. */
.camp { --cp-t0: #9CCBEA; --cp-t1: #4A9BD6; --cp-t2: #1F5E9C; --cp-okk: #2E9E5B; --cp-dork: #C9CFC7; }
.camp .camp-kolco-duga { stroke-linecap: butt; }
.camp .camp-kolco-duga.c-t0 { stroke: var(--cp-t0); }
.camp .camp-kolco-duga.c-t1 { stroke: var(--cp-t1); }
.camp .camp-kolco-duga.c-t2 { stroke: var(--cp-t2); }
.camp .camp-kolco-duga.c-ok { stroke: var(--cp-okk); }
.camp .camp-kolco-duga.c-ak { stroke: var(--cp-ak); }
.camp-kv-kv { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 7px; vertical-align: -1px; }
.camp-kv-kv.c-t0 { background: var(--cp-t0); }
.camp-kv-kv.c-t1 { background: var(--cp-t1); }
.camp-kv-kv.c-t2 { background: var(--cp-t2); }
.camp-kv-kv.c-ok { background: var(--cp-okk); }
.camp-kv-kv.c-ak { background: var(--cp-ak); }
.camp-kv-kv.c-dor { background: var(--cp-dork); }
.camp .camp-stolb-trubka i { background: var(--cp-t1); }
/* Ш2: выбор лагеря чипами; столбик часа частями по тарифам (снизу вверх, цвета колец); кружок инициалов шире (З-30). */
.camp-lageri { display: flex; gap: 4px; padding: 3px; border-radius: 12px; background: var(--cp-card); }
.camp-chip { height: 28px; padding: 0 12px; border: 0; border-radius: 9px; background: transparent; color: var(--cp-tx); font-weight: 700;
  font-size: var(--t-sm); cursor: pointer; white-space: nowrap; }
.camp-chip.on { background: #243E37; color: #FFFFFF; }
.camp .camp-stolb-trubka { flex-direction: column-reverse; justify-content: flex-start; align-items: stretch; }
.camp .camp-stolb-trubka i.c-t0 { background: var(--cp-t0); }
.camp .camp-stolb-trubka i.c-t1 { background: var(--cp-t1); }
.camp .camp-stolb-trubka i.c-t2 { background: var(--cp-t2); }
.camp .camp-stolb-trubka i + i { border-radius: 4px 4px 0 0; }
.camp .camp-stolb-trubka i:not(:last-child) { border-radius: 0 0 2px 2px; }
.camp-who > i { width: 34px; height: 34px; border-radius: 17px; font-size: var(--t-xs); letter-spacing: -.02em; }
@media (max-height: 960px) { .camp-who > i { width: 26px; height: 26px; border-radius: 13px; } }
@media (max-width: 1500px) {
  .camp-hd { gap: 6px 10px; }
  .camp-hd-knopki { gap: 6px; }
  .camp-btn { padding: 0 10px; }
  .camp-chip { padding: 0 9px; }
}
@media (max-height: 960px) { .camp .camp-who > i { width: 24px; height: 24px; border-radius: 12px; } }
/* З-30: две широкие буквы («ЖМ») касались краёв кружка — кружок шире и буквы плотнее; в плотном виде 28 px. */
.camp .camp-who > i { width: 36px; height: 36px; border-radius: 18px; letter-spacing: -.06em; }
@media (max-height: 960px) { .camp .camp-who > i { width: 28px; height: 28px; border-radius: 14px; } }
@media (max-height: 800px) { .camp .camp-who > i { width: 24px; height: 24px; border-radius: 12px; letter-spacing: -.1em; } }
/* З-30: шрифт меньше шкалы не взять — буквы уменьшены преобразованием, кружок прежний; две широкие буквы входят с полем. */
.camp .camp-who > i { letter-spacing: 0; }
.camp .camp-who > i > b { display: inline-block; font-weight: 800; transform: scale(.78); white-space: nowrap; }
@media (max-height: 800px) { .camp .camp-who > i { letter-spacing: 0; } .camp .camp-who > i > b { transform: scale(.7); } }
/* Ш3а-1: правая колонка — «Ждут входа» сверху, события под ним; число в кружке у заголовка, как в прототипе. */
.camp-prava { min-height: 0; display: flex; flex-direction: column; gap: 10px; }
.camp-prava > .camp-sob { flex: 1 1 auto; }
.camp-schyot { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: 11px; background: #F2B33D; color: var(--cp-tx); font-size: var(--t-xs); }
.camp-zhdut { flex: none; display: flex; flex-direction: column; gap: 2px; }
.camp-zhdut-str { display: flex; justify-content: space-between; gap: 10px; padding: 5px 0; border-top: 1px solid var(--cp-line); font-size: var(--t-sm); }
.camp-zhdut-str:first-of-type { border-top: 0; }
.camp-zhdut-str > span:last-child { flex: none; }
@media (max-height: 960px) { .camp-prava { gap: 6px; } .camp-zhdut-str { padding: 3px 0; } }
/* Окно ниже 800 при «Ждут входа»: событий — последние две (лента «последние», не таблица — меньшее число строк не теряет счёт). */
@media (max-height: 800px) { .camp-prava .camp-sob-str:nth-of-type(n+4) { display: none; } }
@media (max-height: 800px) { .camp-prava { gap: 4px; } .camp-zhdut-str { padding: 2px 0; } .camp-zhdut .camp-pod { margin-top: 1px; } }
/* Ш3б: «Отменить» в строке «Ждут входа» — маленькая кнопка; отменённая строка — зачёркнута и приглушена; заметка — курсивом;
   отказ платы — её словами под строкой; нижний ряд из трёх карточек, когда есть «Служебные». */
.camp-btn.mini { height: 26px; padding: 0 9px; border-radius: 8px; font-size: var(--t-xs); }
.camp-btn.mini.otm { border-color: #D98C7F; color: #A93421; }
.camp-btn.mini:disabled { opacity: .5; }
.camp-zhdut-str { align-items: center; flex-wrap: wrap; }
.camp-zhdut-str > .camp-sob-t { flex: 1 1 auto; min-width: 0; }
.camp-zhdut-str.otmenyon > .camp-sob-t { text-decoration: line-through; opacity: .55; }
.camp-zametka { font-style: italic; color: var(--cp-mut); }
.camp-oshibka { flex-basis: 100%; font-size: var(--t-xs); color: #A93421; }
.camp-ryad3.tri { grid-template-columns: minmax(0, 1.4fr) minmax(0, .9fr) minmax(0, 1fr); }
.camp-ryad3.chetyre { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr) minmax(0, 1fr) minmax(0, 1.1fr); }
.camp-sdacha { display: flex; flex-direction: column; gap: 2px; }
.camp-sdacha .camp-kassa-str > .camp-kassa-znach { flex: 0 1 auto; text-align: right; font-weight: 600; }
.camp-kassa-str[data-sost="vozvrat"] > .camp-kassa-znach, .camp-kassa-str[data-sost="bezCeny"] > .camp-kassa-znach { color: var(--cp-ak, #b4561e); font-weight: 500; }
.camp-kassa-str.prinyato > .camp-kassa-znach { opacity: .6; font-weight: 500; }
.camp-sdacha .camp-kassa-str > .camp-sob-t { flex: 1 1 auto; min-width: 0; overflow-wrap: normal; }
.camp-kassa-podtv { flex: 1 0 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; padding: 4px 0 2px; }
.camp-kassa-podtv > b { flex: 1 0 100%; }
.camp-kassa-podtv > .camp-kassa-zametka { flex: 1 1 8em; min-width: 0; }
.camp-kassa-podtv > .camp-oshibka { flex: 1 0 100%; }
.camp-sdacha.otkryt [data-sdacha], .camp-sdacha.otkryt > .camp-pod { display: none; }
/* [hidden] у кнопки и ошибки проигрывает display из .camp-btn — без этого «Принять кассу ›» видна рядом с открытым вопросом. */
.camp-sdacha [hidden] { display: none !important; }
.camp-kassa-zametka { font: inherit; padding: 3px 6px; border: 1px solid var(--cp-line); border-radius: 6px; background: transparent; color: inherit; }
.camp-kassa-kn { display: flex; gap: 6px; }
.camp-sluzh { display: flex; flex-direction: column; gap: 2px; }
@media (max-height: 800px) { .camp-btn.mini { height: 22px; } }
/* «Ждут входа» — длинное (заметка продавца, по ней ищут гостя) переносится второй строкой, не многоточием. Подпись точки — одной строкой:
   текст подписи короткий, многоточие — только запас на чужие длинные имена. */
.camp-zhdut-str > .camp-sob-t { flex: 1 1 0; white-space: normal; overflow-wrap: anywhere; }
.camp-tochka-t > span, .camp-tochka-t > b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Ниже 800 строки «Ждут входа» несут кнопку «Отменить» и выше прежних — событий остаётся одно, последнее. */
@media (max-height: 800px) { .camp-prava .camp-sob-str:nth-of-type(n+3) { display: none; } }
