﻿/* Модуль управления институтом. Оформление намеренно спокойное: экран открывают,
   чтобы найти проблемы, и цвет здесь несёт смысл (тревожность статуса), а не украшает.

   ⛔ ЦВЕТА, КЕГЛИ, ОТСТУПЫ И РАДИУСЫ ЗДЕСЬ НЕ ОБЪЯВЛЯЮТСЯ. Все значения берутся
   из системы оформления — `ui-tokens.css`, разложенный сборкой из единственного
   источника `src/Shared.Ui/ui-tokens.css` (см. docs/Система-оформления.md).
   Правило простое: понадобилось новое число или новый цвет — его заводят ТАМ
   и замером, а не здесь на глаз. Именно место хранения породило 41 цвет
   и 10 ступеней кегля в этом контуре, рука тут ни при чём.

   Ступени, по которым разложены прежние значения (снап на шкалу, а не подбор):
     кегль    11 → --кегль-подпись · 12 → --кегль-служебный · 13 → --кегль-таблица
              14, 15 → --кегль-основной · 17, 18, 20 → --кегль-заголовок
              26 → --кегль-крупное-число
     отступ   2, 4 → микро(4) · 6, 8, 9, 10 → малый(8) · 12, 14 → средний(12)
              16, 18 → крупный(16) · 20, 24, 28, 30 → раздел(24)
   Разнобой в 2-3 пикселя и есть то, что убирается: одинаковая роль — одна ступень.

   ⛔ ЧТО ОСТАВЛЕНО ЛИТЕРАЛАМИ ОСОЗНАННО, И ПОЧЕМУ (это не забывчивость):
   1. Цвета уровней тревожности `.st.*` — вторые аргументы var(). Они ЗЕРКАЛЯТ
      `Institute.Core/Appearance.cs` (`StatusPalette.Fallback` / `FallbackText`),
      сверяются тестом `Палитра_по_умолчанию_в_стилях_совпадает_с_ядром` и уезжают
      той же парой в ПЕЧАТНУЮ форму. Заменить их ролями системы значит развести
      экран и бумагу — ровно тот дефект, против которого настройка цвета и сделана.
   2. Затемнение под карточкой (`.card-screen`) — роли «штора поверх экрана»
      в системе нет: `--цвет-фон-страницы` в тёмной теме тёмный, а в светлой
      светлый, то есть шторой не может быть ни один объявленный цвет.
   3. Пол цели нажатия 44 px — система объявляет `--цель-нажатия: 24px`
      (WCAG 2.2 SC 2.5.8), а здесь требуется 44 (SC 2.5.5). Поднимать токен —
      правка источника на четыре контура сразу, это не работа этого захода. */

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--шрифт);
  font-size: var(--кегль-основной);
  line-height: var(--интерлиньяж-обычный);
  color: var(--цвет-текст);
  background: var(--цвет-фон-страницы);
}

/* ---------- вход ---------- */

.login-screen {
  position: fixed; inset: 0;
  /* Карточка по центру — ПОЛЯМИ самой карточки (margin: auto у .login-box), а не
     align-items/justify-content: центр флекса при низком окне уводит верх карточки за край,
     а экран fixed без прокрутки не даёт его достать (ревью волны 1, 26.09.2026: 911×430 при
     масштабе 150 % — форма от −30 px, заголовок под полосой стенда). Поля auto центрируют,
     пока место есть, и прижимают к началу, когда его нет; остаток — своей прокруткой.
     `safe center` не берём: возможность свежая, браузер VDI не замерен (спека §2 п. 3). */
  display: flex;
  overflow-y: auto;
  /* Подложка под карточкой входа — утопленная поверхность: карточка лежит ВЫШЕ
     неё, и это же различие переживает обе темы клиента Pilot. */
  background: var(--цвет-поверхность-утопленная);
  z-index: 100;
}

/* ОБЯЗАТЕЛЬНО. Встроенное правило браузера `[hidden] { display: none }` живёт
   в стилях агента, то есть СЛАБЕЕ любого авторского: `display: flex` выше его
   перебивает атрибут hidden, и экран входа не скрывается никогда. Приложение
   при этом отрисовано — просто накрыто непрозрачным слоем во весь экран,
   и после успешного входа человек продолжает видеть форму.
   Поймано снимком экрана, а не тестом: запросы при этом отвечали 200. */
.login-screen[hidden] { display: none; }
/* Полоса стенда — первая строка body поверх экрана входа (z-index 1000): её высоту экран
   входа оставляет пустой, иначе верх карточки у начала прокрутки лежит под полосой. Только
   пока полоса видна — соседним селектором (без :has, спека §2 п. 3); на боевой установке
   полосы нет, и отступа нет. Высота — роль полосы оболочки (одна строка). */
.stand-banner:not([hidden]) ~ .login-screen { padding-top: var(--высота-полосы); }
#app[hidden] { display: none; }
/* ОБЩЕЕ ПРАВИЛО (как Finance.Web/wwwroot/app.css): у органов со своим display (.arcrow, .arcsave,
   .arline — ряды «Архива дел») атрибут hidden проигрывал авторскому display:flex, и ряды ввода
   с «Сохранить архив» стояли на экране у роли без права ведения (проверка стенда 28.09.2026;
   сервер запись и так отклонял). Одно правило вместо пары на каждый класс. */
[hidden] { display: none !important; }

.login-box {
  margin: auto;
  background: var(--цвет-поверхность);
  padding: var(--отступ-раздел);
  border-radius: var(--скругление-крупное);
  width: 360px; box-shadow: var(--тень-парения);
}

.login-box h1 { margin: 0 0 var(--отступ-микро); font-size: var(--кегль-заголовок); }
.login-box label {
  display: block; margin: var(--отступ-средний) 0 var(--отступ-микро);
  font-size: var(--кегль-таблица); color: var(--цвет-текст-2);
}
.login-box input {
  width: 100%; padding: var(--отступ-малый);
  border: 1px solid var(--цвет-граница-сильная);
  border-radius: var(--скругление); font-size: var(--кегль-основной);
}
/* Кнопка формы: ширина и отступ сверху — раскладка, в обоих режимах; вид и размер — только без
   флага (кластер отката ниже, у глобального `button`): под флагом «Войти» и «Сменить» —
   главные компоненты.css (`.сис-главная` в разметке). */
.login-box button { width: 100%; margin-top: var(--отступ-крупный); }
:root:not([data-оболочка="2"]) .login-box button {
  padding: var(--отступ-малый); font-size: var(--кегль-основной);
}
.login-error {
  margin-top: var(--отступ-средний); color: var(--цвет-отказ);
  min-height: var(--цель-нажатия); font-size: var(--кегль-таблица);
}

/* ---------- каркас ---------- */

header {
  display: flex; align-items: center; gap: var(--отступ-крупный);
  padding: var(--отступ-малый) var(--отступ-крупный);
  background: var(--цвет-поверхность); border-bottom: 1px solid var(--цвет-граница);
}
/* Липкая шапка — только без оболочки: под флагом шапка обычная (спека веб-пакета §2 п. 10:
   липкая панель спорит с липкими шапками таблиц в окнах прокрутки). */
:root:not([data-оболочка="2"]) header { position: sticky; top: 0; z-index: 10; }

header h1 { margin: 0; font-size: var(--кегль-заголовок); white-space: nowrap; }

/* ⛔ ОТКАТ ОБОЛОЧКИ (WebShell ≠ 2 — служба снимает флаг data-оболочка с <html>): правила
   оболочки не действуют, и шапка собирается прежним оформлением двумя рядами: строка
   «название · кто я · сборка · Выйти» и под ней ряд вкладок во всю ширину (ряд не жмётся,
   подписи вкладок не переносятся). Проверено браузером 26.09.2026: одна строка на всё,
   как до пакета, с добавленным штампом рвала «кто я» и штамп на три строки. Правила ПО ID
   сильнее классовых правил оболочки (:root[data-оболочка="2"] .класс), поэтому всё, что
   перекрывало бы её, живёт только здесь — под отрицанием флага. */
:root:not([data-оболочка="2"]) header.top { flex-direction: column; align-items: stretch; gap: var(--отступ-малый); }
:root:not([data-оболочка="2"]) header.top > .сис-верх { display: flex; align-items: center; gap: var(--отступ-крупный); }
:root:not([data-оболочка="2"]) header.top .сис-контуры:empty { display: none; }
:root:not([data-оболочка="2"]) #whoami { margin-left: auto; color: var(--цвет-текст-3); font-size: var(--кегль-таблица); }

.tabs { display: flex; gap: var(--отступ-малый); }

/* ⛔ КНОПКИ — КЛАСТЕР ОТКАТА (веб-пакет «один продукт», волна 2; план волны 2 §2.1, §3.3).
   Всё, что задаёт ВИД или РАЗМЕР кнопки (тег button и классы, висящие на <button>: .link,
   .linkBtn, .arxbtn, .danger, .pd-go, .ex-btn, кнопки .tabs и .admin-nav, кнопка формы входа),
   стоит здесь ДОСЛОВНО, но под :root:not([data-оболочка="2"]) — действует только при откате
   (служба сняла флаг настройкой WebShell). Под флагом вид даёт компоненты.css: база (0,0,0),
   уровни поимённо в разметке — .сис-главная (одна на экран), .сис-тихая (бывшие ссылки),
   .сис-опасная (бывшая .danger), размер «в строке» — .сис-в-строке.
   ⛔ ПЕРЕВОДИТСЯ КЛАСТЕР ЦЕЛИКОМ: приставка добавляет (0,2,0), и прибавка у всех одинакова —
   порядок внутри кластера сохраняется. Переведи одно глобальное `button` без .linkBtn/.pd-go/
   .arxbtn — оно (0,2,1) перебило бы их (0,1,0), и откат перестал бы быть откатом.
   В обоих режимах остаётся только раскладка (width, margin, display/выравнивание содержимого) —
   и ни одно откатное правило того же органа её не задаёт. Проверяет браузер: «вид органов»
   в режиме WebShell=1 до и после — 0 расхождений (ворота 12 плана). Держит сторож
   КнопкиИнститутаПодОткатомTests (Institute.Server.Tests). */
:root:not([data-оболочка="2"]) .tabs button {
  background: transparent; border: 1px solid transparent; color: var(--цвет-текст-2);
  padding: var(--отступ-малый) var(--отступ-средний);
  border-radius: var(--скругление); cursor: pointer; font-size: var(--кегль-основной);
}
:root:not([data-оболочка="2"]) .tabs button:hover { background: var(--цвет-фон-наведение); }
:root:not([data-оболочка="2"]) .tabs button.active { background: var(--цвет-фон-выбрано); color: var(--цвет-текст-выбрано); }

/* ⛔ ЦЕЛЬ НАЖАТИЯ ОСНОВНОЙ КНОПКИ — НЕ МЕНЬШЕ 44×44 px (WCAG 2.1 SC 2.5.5).
   44 стоит числом, а не токеном, намеренно: система объявляет пол 24 px
   (SC 2.5.8, `--цель-нажатия`), и поднять её значит тронуть источник на все
   четыре контура сразу. Число названо здесь, чтобы его было видно, а не
   размазано по паддингам. Содержимое кнопка центрирует сама.
   Под флагом тот же пол держит база компоненты.css (--высота-кнопки = max(орган, 44 px)). */
:root:not([data-оболочка="2"]) button {
  background: var(--цвет-акцент); color: var(--цвет-текст-на-акценте);
  border: 0; border-radius: var(--скругление);
  padding: 0 var(--отступ-средний);
  min-height: 44px; min-width: 44px;
  cursor: pointer; font-size: var(--кегль-основной);
}
:root:not([data-оболочка="2"]) button:hover { background: var(--цвет-акцент-2); }
/* Кнопка-ссылка стоит ВНУТРИ строки текста и заголовка («закрыть», «выйти»,
   «Показать все»): 44 px разорвали бы строку, поэтому здесь пол системы — 24 px.
   Под флагом — .сис-тихая, а в строке текста ещё и .сис-в-строке (24 px). */
:root:not([data-оболочка="2"]) button.link {
  background: none; color: var(--цвет-акцент);
  padding: 0 var(--отступ-микро); text-decoration: underline;
  min-height: var(--цель-нажатия); min-width: var(--цель-нажатия);
}
:root:not([data-оболочка="2"]) button.link:hover { background: none; }

main { padding: var(--отступ-крупный) var(--отступ-крупный) var(--отступ-экран); }
.view { display: none; }
.view.active { display: block; }

.panel {
  background: var(--цвет-поверхность); border: 1px solid var(--цвет-граница);
  border-radius: var(--скругление-крупное);
  padding: var(--отступ-крупный); margin-bottom: var(--отступ-крупный); overflow-x: auto;
}

.form h3 { margin: 0 0 var(--отступ-малый); font-size: var(--кегль-основной); }
.form label {
  display: block; margin: var(--отступ-малый) 0 var(--отступ-микро);
  font-size: var(--кегль-таблица); color: var(--цвет-текст-2);
}
/* Цели нажатия ВНЕ форм (поиск реестра, списки над таблицами, чекбоксы): не ниже пола
   системы `--высота-органа` — как у планировщика (консилиум UX 17.09.2026, № 14; замер
   аудита: select 19 px, поиск 21 px, чекбокс 13 px). Чекбокс растёт до пола квадратом. */
input:not([type="checkbox"]):not([type="radio"]), select, textarea {
  min-height: var(--высота-органа); font-family: var(--шрифт); font-size: var(--кегль-таблица);
}
input[type="checkbox"], input[type="radio"] { width: var(--цель-нажатия); height: var(--цель-нажатия); }
.form input, .form textarea, .form select {
  padding: var(--отступ-малый); border: 1px solid var(--цвет-граница-сильная);
  border-radius: var(--скругление); font: inherit; width: 100%;
}
.form textarea { font-family: var(--шрифт-моно); font-size: var(--кегль-таблица); }
.form button { margin-top: var(--отступ-малый); }

.row-inline {
  display: flex; gap: var(--отступ-малый); flex-wrap: wrap;
  align-items: center; margin-top: var(--отступ-малый);
}
.row-inline input, .row-inline select { width: auto; flex: 1 1 160px; }
.row-inline button { margin-top: 0; }

.hint {
  color: var(--цвет-текст-3); font-size: var(--кегль-таблица);
  margin: var(--отступ-малый) 0;
}
.hint b { color: var(--цвет-текст-2); }
code {
  background: var(--цвет-поверхность-утопленная); padding: 1px var(--отступ-микро);
  border-radius: var(--скругление); font-size: var(--кегль-служебный);
}

/* ---------- таблица реестра ---------- */

table { border-collapse: collapse; width: 100%; font-size: var(--кегль-таблица); }
th, td {
  padding: var(--поле-клетки-по-вертикали) var(--поле-клетки-по-горизонтали);
  border-bottom: 1px solid var(--цвет-граница); text-align: left; vertical-align: top;
}
th {
  background: var(--цвет-поверхность-утопленная); font-weight: var(--начертание-выделенное);
  color: var(--цвет-текст-2); white-space: nowrap; position: sticky; top: 0;
}
tbody tr:hover { background: var(--цвет-фон-наведение); }
/* ⛔ ЧИСЛО — ВПРАВО И ТАБЛИЧНЫМИ ЦИФРАМИ, ШАПКА ВМЕСТЕ С НИМ. Центрирования
   в этом контуре нет и появиться не должно: на центрированной клетке табличные
   цифры бесполезны — разряды всё равно не выстраиваются.
   Класс ставит app.js постоянной строкой, а не из данных: у реестра и досок — по признаку
   столбца `numeric` службы (шапке тоже), у таблиц экрана — третьим аргументом `table()`,
   у календаря сдач — столбцу числа (волна 2 веб-пакета, В3; действует в обоих режимах). */
th.num, td.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* ⛔ ПОД ФЛАГОМ ШАПКА ЧИСЛА ПЕРЕНОСИТСЯ (план волны 2 §2.4; гейт ревью волны 2, MEDIUM-3). Неразрывная шапка
   `th.num` (правило выше и глобальное `th{white-space:nowrap}`) — вид до пакета: без флага он и остаётся (ворота 12
   сверяют с ним вид органов — сортируемая шапка тоже орган). Под флагом шапка переносится словами, как у
   планировщика: поправка только под флагом (ср. `rep-text`). Держит сторож ШапкаЧислаПереноситсяTests. */
:root[data-оболочка="2"] th.num { white-space: normal; }
td.code { font-weight: var(--начертание-выделенное); white-space: nowrap; }
.muted { color: var(--цвет-текст-3); }
.late { color: var(--цвет-тревога-текст); font-weight: var(--начертание-выделенное); }
.soon { color: var(--цвет-внимание); }

/* Цвет из ЧИСЛА тревожности: три зашитые градации не упорядочили бы девятнадцать
   статусов оплаты между собой, а сводный статус выбирается сравнением. */
.st {
  display: inline-block; padding: var(--отступ-микро) var(--отступ-малый);
  border-radius: var(--скругление); font-size: var(--кегль-служебный); white-space: nowrap;
}
/* Цвет берётся из переменной, а значение по умолчанию стоит тут же вторым
   аргументом var(): администратор, ничего не менявший, получает подобранную
   пару «фон + надпись», а переопределивший — свой фон и вычисленный контраст.
   Переменные ставит app.js ТОЛЬКО для переопределённых уровней: подставляя их
   всегда, мы заменили бы зелёную надпись на чёрную у всех без всякой причины.

   ⛔ ЭТИ ПЯТЬ ПАР — НЕ ХАРДКОД, А ЗЕРКАЛО ЯДРА, и на роли системы они
   не переводятся: те же значения лежат в `StatusPalette` и уходят в печатную
   форму, а сверяет их тест `Палитра_по_умолчанию_в_стилях_совпадает_с_ядром`. */
/* Умолчания ОБЪЯВЛЕНЫ, а не спрятаны запасным значением в var(): токен без объявления
   не виден ни сторожу «необъявленные токены», ни человеку, читающему палитру (волна 0). */
:root {
  --st-ok-bg: #dcfce7;     --st-ok-fg: #166534;
  --st-low-bg: #fef9c3;    --st-low-fg: #854d0e;
  --st-mid-bg: #fed7aa;    --st-mid-fg: #9a3412;
  --st-high-bg: #fee2e2;   --st-high-fg: #991b1b;
  /* «Нет данных» — свой цвет, не зелёный и не красный: это отсутствие сведений
     о возможной беде, а не благополучие и не подтверждённая проблема. */
  --st-nodata-bg: #e5e7eb; --st-nodata-fg: #4b5563;
}
.st.ok     { background: var(--st-ok-bg);     color: var(--st-ok-fg); }
.st.low    { background: var(--st-low-bg);    color: var(--st-low-fg); }
.st.mid    { background: var(--st-mid-bg);    color: var(--st-mid-fg); }
.st.high   { background: var(--st-high-bg);   color: var(--st-high-fg); }
.st.nodata { background: var(--st-nodata-bg); color: var(--st-nodata-fg); }

.banner {
  border-radius: var(--скругление);
  padding: var(--отступ-малый) var(--отступ-средний);
  margin-bottom: var(--отступ-средний); font-size: var(--кегль-таблица);
  border: 1px solid transparent;
}
.banner.warn {
  background: var(--подсветка-внимание); border-color: var(--цвет-внимание);
  color: var(--цвет-внимание);
}
.banner.info {
  background: var(--подсветка-акцент); border-color: var(--цвет-акцент);
  color: var(--цвет-акцент);
}
/* Отказ (kind = Problem) — тревожным тоном; прежде класс `error` рисовался без правила,
   и «Планировщик недоступен» выглядел как обычная заметка (волна 0, §4 Б2). */
.banner.error {
  background: var(--подсветка-тревога); border-color: var(--цвет-тревога-текст);
  color: var(--цвет-тревога-текст);
}
.banner + .banner { margin-top: calc(var(--отступ-малый) * -1); }

/* ---------- органы, рождённые скриптом, без правила до волны 0 (§4 Б2) ----------
   Правила минимальны и только токенами: не оформление, а место и читаемость. */
/* Ряд ввода архива и ряд «Сохранить»: органы в строку, переносом при узком окне. */
.arcrow, .arcsave, .arline {
  display: flex; flex-wrap: wrap; gap: var(--отступ-малый); align-items: center;
}
.arcrow { margin: 0 0 var(--отступ-малый); }
.arcsave { margin: var(--отступ-малый) 0; }
/* Строка списка архива: текст + кнопки правки; строки отделены линией, не отступом. */
.arline { padding: var(--отступ-микро) 0; border-bottom: 1px solid var(--цвет-граница); }
/* Кнопка строки списка — кластер отката (под флагом — .сис-в-строке, 24 px). */
:root:not([data-оболочка="2"]) .arxbtn { min-width: var(--цель-нажатия); min-height: var(--цель-нажатия); padding: 0 var(--отступ-малый); }
/* Кнопка-ссылка («открыть/закрыть» допуск): действие, оформленное как ссылка.
   Кластер отката: под флагом — .сис-тихая. */
:root:not([data-оболочка="2"]) .linkBtn {
  background: none; border: 0; padding: 0; min-height: var(--цель-нажатия);
  color: var(--цвет-акцент); text-decoration: underline; cursor: pointer; font: inherit;
}
.planner-link { color: var(--цвет-акцент); }
/* Таблица описания колонок и сгруппированный отчёт: группа — утопленной полосой. */
table.grid { margin-top: var(--отступ-малый); }
table.grid th, table.grid td { vertical-align: top; }
tr.grp td { background: var(--цвет-поверхность-утопленная); font-weight: var(--начертание-выделенное); }
/* «Строк нет» — состояние, названное словами, приглушённым тоном. */
.empty { color: var(--цвет-текст-3); margin: var(--отступ-малый) 0; }
details.banner summary { cursor: pointer; }
details.banner div { margin-top: var(--отступ-малый); }

/* Доска договоров: строка ОБЪЕКТА — группа, видна с трёх метров; панель переходов —
   орган, а не подпись (консилиум UX 17.09.2026, № 12). */
tr.contract-object-row td { background: var(--цвет-поверхность-утопленная); font-weight: 600; }
#cbDrill { display: flex; flex-wrap: wrap; gap: var(--отступ-малый); align-items: center;
  padding: var(--отступ-малый) var(--отступ-средний); margin-bottom: var(--отступ-средний);
  border: 1px solid var(--цвет-граница); border-radius: var(--скругление); }
#cbDrill[hidden] { display: none; }

.pw {
  font-family: var(--шрифт-моно); background: var(--подсветка-внимание);
  padding: var(--отступ-микро) var(--отступ-малый); border-radius: var(--скругление);
}

/* Выгрузка — ссылка, а не кнопка: браузер сам покажет диалог сохранения
   и возьмёт имя файла с датой из заголовка ответа.
   Цель нажатия та же, что у кнопки (44 px): человек не отличает их видом,
   и отличать пальцем тем более не должен. Отсюда inline-flex — у ссылки нет
   собственного центрирования содержимого.
   ⛔ КЛАСС ВИСИТ И НА <button> (кнопки редактора переписки, ltКнопка), поэтому вид — в кластере
   отката. В обоих режимах — только раскладка содержимого: под флагом ссылка берёт вид кнопки
   базы компоненты.css классом .сис-кнопка в разметке, и черту ссылки снимает сама база; в откате
   черту снимает откатное правило (находка F5 ревью волны 2: снятие черты в обоих режимах было
   контурной заплаткой пробела общего слоя). Пара [hidden] — потому что здесь задан display. */
.ex-btn { display: inline-flex; align-items: center; justify-content: center; }
.ex-btn[hidden] { display: none; }
:root:not([data-оболочка="2"]) .ex-btn {
  background: var(--цвет-акцент); color: var(--цвет-текст-на-акценте); text-decoration: none;
  padding: 0 var(--отступ-средний);
  min-height: 44px; min-width: 44px;
  border-radius: var(--скругление); font-size: var(--кегль-основной);
}
:root:not([data-оболочка="2"]) .ex-btn:hover { background: var(--цвет-акцент-2); }

.panel.form[hidden] { display: none; }

/* ---------- сводка ---------- */

.tiles {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: var(--отступ-средний); margin-bottom: var(--отступ-крупный);
}

.tile {
  background: var(--цвет-поверхность); border: 1px solid var(--цвет-граница);
  border-radius: var(--скругление-крупное); padding: var(--отступ-крупный);
}
/* Плитка со списком объектов за числом — кликабельна. Показатель, за которым
   нельзя увидеть объекты, не проверяется и потому не используется. */
.tile.clickable { cursor: pointer; }
.tile.clickable:hover { border-color: var(--цвет-граница-сильная); }

/* Единственное число сводки. Табличные цифры и здесь: плитки стоят сеткой,
   и без них соседние числа пляшут по ширине разряда. */
.tile .num {
  font-size: var(--кегль-крупное-число); font-weight: var(--начертание-выделенное);
  line-height: var(--интерлиньяж-плотный); font-variant-numeric: tabular-nums;
}
.tile .cap {
  font-size: var(--кегль-таблица); color: var(--цвет-текст-3);
  margin-top: var(--отступ-микро);
}
.tile .sub {
  font-size: var(--кегль-служебный); color: var(--цвет-текст-3);
  margin-top: var(--отступ-малый);
}

.tile.high .num  { color: var(--цвет-тревога-текст); }
.tile.mid  .num  { color: var(--цвет-внимание); }
.tile.ok   .num  { color: var(--цвет-успех-текст); }
.tile.grey .num  { color: var(--цвет-текст-2); }

/* ---------- карточка объекта ---------- */

.card-screen {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: flex-start; justify-content: center;
  /* ⛔ ШТОРА. Единственный цвет файла без роли в системе: объявленные цвета
     меняются вместе с темой, а штора обязана оставаться тёмной в обеих —
     иначе в тёмной теме она осветляла бы экран под карточкой. */
  background: rgba(17, 24, 39, .55);
  padding: var(--отступ-раздел) var(--отступ-крупный); overflow-y: auto;
}

/* ОБЯЗАТЕЛЬНО: правило браузера `[hidden]{display:none}` слабее авторского `display:flex`
   и им перебивается — карточка не закрывалась бы никогда, накрывая реестр непрозрачным
   слоем. Эта грабля в проекте уже стоила захода на экране входа. */
.card-screen[hidden] { display: none; }

.card-box {
  background: var(--цвет-поверхность); border-radius: var(--скругление-крупное);
  padding: var(--отступ-раздел);
  width: 100%; max-width: 720px; box-shadow: var(--тень-парения);
}

.card-head {
  display: flex; align-items: center; gap: var(--отступ-средний);
  margin-bottom: var(--отступ-микро);
}
.card-head h2 { margin: 0; font-size: var(--кегль-заголовок); flex: 1; }

/* Вычисляемое: показываем, но не даём вводить. Поле, которое можно посчитать,
   но дали заполнить руками, гарантированно разойдётся с расчётом. */
.computed {
  background: var(--цвет-поверхность-утопленная); border: 1px solid var(--цвет-граница);
  border-radius: var(--скругление);
  padding: var(--отступ-малый) var(--отступ-средний);
  margin: var(--отступ-малый) 0; font-size: var(--кегль-таблица);
}
.computed b { color: var(--цвет-текст); }
.computed .muted { color: var(--цвет-текст-3); }

.card-grid {
  display: grid; grid-template-columns: 180px 1fr;
  gap: var(--отступ-малый) var(--отступ-крупный);
  align-items: center; margin: var(--отступ-крупный) 0;
}
.card-grid label { margin: 0; font-size: var(--кегль-таблица); color: var(--цвет-текст-2); }
.card-grid input, .card-grid select {
  width: 100%; padding: var(--отступ-малый);
  border: 1px solid var(--цвет-граница-сильная);
  border-radius: var(--скругление); font: inherit;
}
.card-grid input:disabled, .card-grid select:disabled {
  background: var(--цвет-поверхность-утопленная); color: var(--цвет-текст-отключено);
}

.card-history {
  margin-top: var(--отступ-крупный); border-top: 1px solid var(--цвет-граница);
  padding-top: var(--отступ-средний);
}
.card-history h3 { margin: 0 0 var(--отступ-малый); font-size: var(--кегль-основной); }
.card-history table { font-size: var(--кегль-служебный); }

/* Опасное действие красится лестницей срочности — тем же «горит», что и в таблице:
   второй красный завёл бы второй смысл у одного цвета.
   Кластер отката: под флагом — .сис-опасная компоненты.css. */
:root:not([data-оболочка="2"]) button.danger { background: var(--цвет-тревога); color: var(--цвет-текст-на-тревоге); }
:root:not([data-оболочка="2"]) button.danger:hover { background: var(--цвет-отказ); }

tr.voided td { opacity: var(--непрозрачность-отключено); }
/* ⛔ КЛИКАБЕЛЬНАЯ СТРОКА — ЭТО ЦЕЛЬ НАЖАТИЯ (WCAG 2.2 SC 2.5.8, 24 px).
   Поля клетки её высоту не гарантируют: при ступени «тесно» ритм ужимается,
   и строка с коротким текстом может оказаться ниже пола. Токен `--высота-строки`
   записан через max(), поэтому ручка плотности пол НЕ ПРОБИВАЕТ. */
tr.clickable { cursor: pointer; }
tr.clickable td { height: var(--высота-строки); }

/* Уведомление о результате действия. Поверх карточки (z-index выше её слоя):
   сообщение «сохранено», спрятанное под модальным окном, равносильно молчанию. */
.toast {
  position: fixed; left: 50%; bottom: var(--отступ-раздел); transform: translateX(-50%);
  background: var(--цвет-акцент); color: var(--цвет-текст-на-акценте);
  padding: var(--отступ-малый) var(--отступ-крупный); border-radius: var(--скругление-крупное);
  font-size: var(--кегль-основной); z-index: 200; box-shadow: var(--тень-парения);
}

/* НАСТРОЙКИ: список разделов слева. Панелей девять, и подряд они превращаются
   в свиток, где нужное оказывается ниже сгиба. */
.admin-layout { display: flex; gap: var(--отступ-крупный); align-items: flex-start; }
.admin-nav {
  flex: 0 0 210px; display: flex; flex-direction: column; gap: var(--отступ-микро);
  position: sticky; top: var(--отступ-крупный);
}
/* Пункт меню — подпись к левому краю в обоих режимах (раскладка содержимого); вид — кластер
   отката. Под флагом пункты — кнопки базы компоненты.css, выбранный — .сис-выбрано (ставит
   showAdminSection вместе с .active). */
.admin-nav button { text-align: left; }
:root:not([data-оболочка="2"]) .admin-nav button {
  background: none; color: var(--цвет-текст-2); border: none;
  border-radius: var(--скругление);
  padding: var(--отступ-малый); font: inherit;
  font-size: var(--кегль-таблица); cursor: pointer;
}
:root:not([data-оболочка="2"]) .admin-nav button:hover { background: var(--цвет-фон-наведение); }
:root:not([data-оболочка="2"]) .admin-nav button.active {
  background: var(--подсветка-акцент); color: var(--цвет-акцент);
  font-weight: var(--начертание-выделенное);
}
.admin-panels { flex: 1 1 auto; min-width: 0; }
/* Скрытая панель обязана иметь СВОЁ правило: `[hidden]{display:none}` живёт
   в стилях агента и слабее любого авторского. Ровно на этом экран входа
   не скрывался никогда. */
.admin-panels .sec[hidden] { display: none; }

@media (max-width: 900px) {
  .admin-layout { flex-direction: column; }
  .admin-nav { flex: 1 1 auto; flex-direction: row; flex-wrap: wrap; position: static; }
}

/* Редактор дополнительных полей и надписей: узкие колонки не растягиваются
   на всю ширину, иначе поле ввода в тысячу пикселей соседствует с числом. */
td.tight { white-space: nowrap; }
td.tight input[type=number] { width: 76px; }
.opt-list { font-size: var(--кегль-служебный); color: var(--цвет-текст-3); }
.lbl-default { color: var(--цвет-текст-3); font-size: var(--кегль-служебный); }

/* Заголовок-сортировщик. Курсор и подсветка говорят, что по нему можно нажать:
   таблица без этого выглядит статичной, и сортировку не находят вовсе. */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { background: var(--цвет-фон-наведение); }

/* Договорные этапы в карточке. Таблица шире карточки — прокрутка своя, чтобы
   не тащить горизонтальную полосу на всю страницу. */
.card-stages {
  margin-top: var(--отступ-крупный); border-top: 1px solid var(--цвет-граница);
  padding-top: var(--отступ-средний);
}
.card-stages h3 { margin: 0; font-size: var(--кегль-основной); }
.card-stages .card-head { align-items: center; margin-bottom: var(--отступ-малый); }
#stgTable { overflow-x: auto; }
#stgTable table { font-size: var(--кегль-служебный); min-width: 100%; }
#stgTable input, #stgTable select {
  padding: var(--отступ-микро); font: inherit; font-size: var(--кегль-служебный);
  border: 1px solid var(--цвет-граница-сильная); border-radius: var(--скругление);
}
/* Число вводится тем же правилом, каким показывается: вправо и табличными цифрами.
   Иначе разряды в столбце сумм не выстраиваются ровно там, где их сверяют. */
#stgTable input.num { text-align: right; font-variant-numeric: tabular-nums; width: 110px; }
#stgTable input.dt { width: 130px; }
#stgTable .stg-title { width: 150px; }
/* Просрочка видна цветом в самой ячейке: отдельная колонка «просрочено» на узкой
   таблице уезжает за край, и её не увидят там, где она нужнее всего. */
#stgTable td.late-cell { background: var(--подсветка-тревога); }

/* Версия сборки в строке шапки. Мелко и выделяемо мышью: её диктуют в поддержку.
   Раскладку под оболочкой даёт .сис-сборка; здесь — вид без флага. */
.buildstamp {
  font-size: var(--кегль-подпись); color: var(--цвет-текст-3);
  padding: 0; white-space: nowrap;
  user-select: all;
}

/* ⛔ ПОЛОСА РЕЖИМА РАБОТЫ. Видна поверх всего, включая экран входа: режим, о котором
   сказано только внутри, не виден тому, кто ещё не вошёл, — а решение «это боевая
   установка» принимают именно глядя на экран.
   ТОН ЗАВИСИТ ОТ ФЛАГА ОБОЛОЧКИ. Без флага (откат) — правило ниже: цвет предупреждающий,
   а не декоративный, роль в лестнице срочности «риск» с кантом «горит» — тот же цвет, что
   у любого другого предупреждения продукта. Под флагом цвет, фон и черту даёт оболочка:
   showMode ставит полосе класс .сис-полоса-демо — акцентный тон со знаком ●, как
   «● Демонстрационные данные» в спеке веб-пакета §3.3, а не тон предупреждения. Значение
   несут знак и слово, фон вторичен (закон 1 ui-tokens.css), и они же переживают ч/б печать. */
.stand-banner {
  /* Над экраном входа (fixed, z-index 100) — но под оболочкой НЕ липкая: липкая полоса
     спорила бы с липкими шапками таблиц (спека §2 п. 10); липкость — только без флага. */
  position: relative;
  z-index: 1000;
  padding: var(--отступ-малый) var(--отступ-крупный);
  background: var(--цвет-внимание);
  color: var(--цвет-текст-на-внимании);
  font-size: var(--кегль-таблица);
  line-height: var(--интерлиньяж-обычный);
  border-bottom: 2px solid var(--цвет-тревога);
}
:root:not([data-оболочка="2"]) .stand-banner { position: sticky; top: 0; }
/* Знак полосы без флага. Отступ до слова оболочка задаёт только под флагом, и при откате знак
   прилипал к тексту: «●Демонстрационный…», «⚠Названия…» — зазор 0 px (ревью волны 1). */
:root:not([data-оболочка="2"]) .сис-полоса-знак { margin-right: var(--отступ-малый); }

/* Полное предупреждение о стенде под формой входа (`/api/mode`.warning): полоса оболочки
   несёт короткое слово, длинное читают здесь — до входа, там, где решают «это боевая?». */
.stand-note {
  margin-top: var(--отступ-средний); padding-top: var(--отступ-малый);
  border-top: 1px solid var(--цвет-граница);
  color: var(--цвет-текст-2); font-size: var(--кегль-таблица);
  line-height: var(--интерлиньяж-обычный);
}

/* Полоса «названия не прочитаны» живёт ВНЕ main, поэтому отступы задаются ей самой:
   иначе она прижимается к краю окна и читается как часть шапки, а не как
   предупреждение о состоянии данных. Своего `display` у неё НЕТ намеренно —
   встроенное правило `[hidden]{display:none}` обязано её гасить. Правило по id
   сильнее оболочки — потому только без флага: под ним полоса .сис-полоса без полей. */
:root:not([data-оболочка="2"]) #labelsWarning { margin: 0 var(--отступ-крупный) var(--отступ-средний); }

/* ── РОЛЕВОЙ ДАШБОРД: шапка-герой + фокус-списки ──
   «По делу» = роль видит своё. Тон-плитки берут визуальный язык у `.tile`
   (второго не заводим), здесь — только рамка роли и списки «что горит/критично». */
.rd-head {
  background: var(--цвет-поверхность-утопленная);
  border: 1px solid var(--цвет-граница);
  border-radius: var(--скругление-крупное);
  padding: var(--отступ-средний) var(--отступ-крупный);
  margin-bottom: var(--отступ-средний);
}
.rd-title { font-size: var(--кегль-заголовок); color: var(--цвет-текст); }
.rd-asof {
  color: var(--цвет-текст-2); font-size: var(--кегль-служебный);
  font-weight: var(--начертание-обычное);
}
.rd-note { color: var(--цвет-текст-2); font-size: var(--кегль-служебный); margin-top: var(--отступ-микро); }
.rd-focus { margin-top: var(--отступ-средний); }
.rdrow { padding: var(--отступ-микро) 0; border-top: 1px solid var(--цвет-граница); }
.rd-focus .rdrow:first-of-type { border-top: 0; }
.rd-section {
  margin: var(--отступ-раздел) 0 var(--отступ-малый);
  font-size: var(--кегль-служебный); font-weight: var(--начертание-выделенное);
  text-transform: uppercase; letter-spacing: .04em; color: var(--цвет-текст-3);
}

/* ── ВОРОНКА ПОРТФЕЛЯ КАК ГОРИЗОНТАЛЬНЫЕ ПОЛОСЫ ──
   Поток «где застревает» виден формой, а не только числом. Всё на токенах. */
.funnelchart { display: flex; flex-direction: column; gap: var(--отступ-микро); }
.funnelgroup {
  margin-top: var(--отступ-малый); font-size: var(--кегль-служебный);
  font-weight: var(--начертание-выделенное); color: var(--цвет-текст-2);
}
.funnelbar {
  display: grid; grid-template-columns: minmax(140px, 34%) 1fr auto;
  align-items: center; gap: var(--отступ-малый);
}
/* Полоса со шифрами — орган перехода в реестр (правило провалитьсяВРеестр).
   Признак не только цветом: форма курсора плюс граница дорожки при наведении. */
.funnelbar.clickable { cursor: pointer; }
.funnelbar.clickable:hover .fb-track { outline: 1px solid var(--цвет-граница-сильная); }
.fb-label { font-size: var(--кегль-таблица); color: var(--цвет-текст); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fb-track {
  background: var(--цвет-поверхность-утопленная); border-radius: var(--скругление);
  height: 18px; overflow: hidden;
}
.fb-fill { display: block; height: 100%; border-radius: var(--скругление); min-width: 2px; }
.fb-accent { background: var(--цвет-акцент); }
.fb-warn { background: var(--цвет-внимание); }
.fb-num {
  font-variant-numeric: tabular-nums; font-weight: var(--начертание-выделенное);
  color: var(--цвет-текст); min-width: 3ch; text-align: right;
}

/* ── ГРАФИК ПО ГРУППАМ — классы рендера chart.js (общий src/Shared.Ui/chart.js) ──
   Копия блока из Finance.Web/wwwroot/app.css: рендер один на все контуры, а стили у каждого
   контура свои (ссылок между продуктами нет). Только токены — сторож О-1 считает литералы. */
.chart-block { margin: var(--отступ-средний) 0; }
.chart-box { margin: var(--отступ-средний) 0; padding: var(--отступ-малый) 0; }
.chart-title {
  font-size: var(--кегль-таблица); font-weight: var(--начертание-выделенное);
  color: var(--цвет-текст-2); margin-bottom: var(--отступ-микро);
}
.chart { width: 100%; height: auto; max-width: 100%; display: block; }
.chart-cov { font-size: var(--кегль-подпись); color: var(--цвет-текст-3); margin-top: var(--отступ-микро); }
.chart-empty {
  padding: var(--отступ-средний); background: var(--цвет-поверхность-утопленная);
  border-radius: var(--скругление); color: var(--цвет-текст-2); font-size: var(--кегль-таблица);
}
.chart-data { margin-top: var(--отступ-микро); font-size: var(--кегль-подпись); }
.chart-data summary {
  cursor: pointer; color: var(--цвет-акцент);
  min-height: max(var(--высота-органа), 44px); display: flex; align-items: center;
}
.chart-data table { border-collapse: collapse; margin-top: var(--отступ-микро); }
.chart-data td, .chart-data th { border: 1px solid var(--цвет-граница); padding: 2px var(--отступ-малый); }
@media print {
  .chart-data[open], .chart-data { display: block; }
  .chart-data summary { display: none; }
  .chart-data table { display: table; }
}

/* ═══ ДАШБОРД ПРОЕКТА И ЛЕНТА ВНИМАНИЯ (18.09.2026) ═══ */
.pd-pick { display: flex; gap: var(--отступ-малый); align-items: center; flex-wrap: wrap; }
.pd-title { font-size: var(--кегль-заголовок); font-weight: var(--начертание-выделенное); margin: var(--отступ-малый) 0 0; }
.pd-meta { color: var(--цвет-текст-2); margin-top: var(--отступ-малый); }
.pd-meta span + span::before { content: ' · '; }
.pd-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--отступ-средний); }
.pd-block { display: flex; flex-direction: column; gap: var(--отступ-малый); }
.pd-block h3 { margin: 0; font-size: var(--кегль-основной); }
.pd-block .hint { margin: 0; }
.pd-axes { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--отступ-малый); }
.pd-axis { border: 1px solid var(--цвет-граница); border-radius: var(--скругление); padding: var(--отступ-малый); cursor: pointer; background: var(--цвет-поверхность); }
.pd-axis:hover { border-color: var(--цвет-граница-сильная); }
.pd-axis .cap { color: var(--цвет-текст-2); font-size: var(--кегль-таблица); }
.pd-axis.unnamed .val { color: var(--цвет-текст-3); font-style: italic; }
.pd-rows { display: flex; flex-direction: column; gap: 2px; }
.pd-row { display: flex; gap: var(--отступ-малый); align-items: baseline; padding: 2px 0; border-bottom: 1px solid var(--цвет-граница); }
.pd-row:last-child { border-bottom: 0; }
.pd-row .grow { flex: 1; min-width: 0; }
.pd-row .num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.pd-gap { border-left: 3px solid var(--цвет-внимание); padding-left: var(--отступ-малый); }
.pd-gap.planner { border-left-color: var(--цвет-акцент); }
/* Переход с дашборда — кластер отката; под флагом — .сис-тихая .сис-в-строке. */
:root:not([data-оболочка="2"]) .pd-go { background: none; border: 0; color: var(--цвет-акцент); cursor: pointer; padding: 0; font: inherit; text-decoration: underline; }
:root:not([data-оболочка="2"]) .pd-go:hover { color: var(--цвет-текст); }
.pd-state { color: var(--цвет-текст-2); }
.pd-state.missing { color: var(--цвет-внимание); }
.att-row { display: grid; grid-template-columns: minmax(90px, auto) 1fr auto auto auto; gap: var(--отступ-малый); align-items: baseline; padding: var(--отступ-малый) 0; border-bottom: 1px solid var(--цвет-граница); cursor: pointer; }
.att-row:hover { background: var(--цвет-поверхность-утопленная); }
.att-row:last-child { border-bottom: 0; }
.att-row .why { color: var(--цвет-текст-2); font-size: var(--кегль-таблица); grid-column: 2 / -1; }
.att-row .lvl-high { color: var(--цвет-тревога-текст); }
.att-row .lvl-mid { color: var(--цвет-внимание); }
.att-row .lvl-ok { color: var(--цвет-успех-текст); }
.att-row .lvl-nodata { color: var(--цвет-текст-3); }

/* ═══ ПЛАНШЕТ (показ 28.09.2026: Chrome на iPad — движок WebKit) — ТОЛЬКО под оболочкой ═══
   Плитка, за числом которой есть список объектов, — кнопка: знак «›» в углу и отклик на касание
   (у тача наведения нет, :hover не подсказывает). Плитка-показатель без списка утоплена и без
   знака: руководитель не жмёт в пустоту. Кликабельность решает одно правило — tile() в app.js
   (класс clickable только при непустом списке шифров). */
:root[data-оболочка="2"] .tile { position: relative; }
:root[data-оболочка="2"] .tile.clickable { padding-right: calc(var(--отступ-крупный) + 16px); }
:root[data-оболочка="2"] .tile.clickable::after {
  content: "›"; position: absolute; top: var(--отступ-средний); right: var(--отступ-средний);
  font-size: var(--кегль-заголовок); line-height: 1; color: var(--цвет-акцент);
}
:root[data-оболочка="2"] .tile.clickable:active { background: var(--цвет-фон-нажатие); }
:root[data-оболочка="2"] .tile:not(.clickable) { background: var(--цвет-поверхность-утопленная); }
/* Строка «Горит по срокам» / «Требуют внимания по статусу» ведёт на дашборд проекта (renderRoleDash). */
:root[data-оболочка="2"] .rdrow.rd-go { cursor: pointer; }
:root[data-оболочка="2"] .rdrow.rd-go::after { content: " ›"; color: var(--цвет-акцент); }
:root[data-оболочка="2"] .rdrow.rd-go:active,
:root[data-оболочка="2"] .att-row:active { background: var(--цвет-фон-нажатие); }
/* Поле карточки, на которое привела плитка оси статуса дашборда проекта (pdКПолюКарточки). */
:root[data-оболочка="2"] .pd-к-полю { outline: 2px solid var(--цвет-фокус); outline-offset: 2px; border-radius: var(--скругление); }
/* «Куда смотреть первым» в портрете планшета (768/820): пять колонок в строку сжимали название проекта
   до трёх строк по слову. Под 900 px — название на всю ширину, числа и статус второй строкой под ним.
   Порядок детей строки ленты задаёт renderAttention: шифр, название, работы, пробелы, статус, почему. */
@media (max-width: 900px) {
  :root[data-оболочка="2"] .att-row { grid-template-columns: minmax(80px, auto) auto auto 1fr; }
  :root[data-оболочка="2"] .att-row > .grow { grid-column: 2 / -1; }
  :root[data-оболочка="2"] .att-row > :nth-child(3) { grid-column: 2; }
  :root[data-оболочка="2"] .att-row > :nth-child(4) { grid-column: 3; }
  :root[data-оболочка="2"] .att-row > :nth-child(5) { grid-column: 4; }
}

/* ═══ ВОЛНА Р1 ПЕРЕРАБОТКИ ВЕБА (флаги службы data-вкл; Shared.WebAuth/ВключённыеВиды.cs) ═══
   Б11, флаг «тихие-кнопки»: высота обычной кнопки — 32 px для мыши (роль --высота-органа, пол цели нажатия
   24 px внутри неё); палец (pointer: coarse) сохраняет 44 px. Роль, а не правило кнопки: вид и размер кнопок
   под флагом оболочки рисует общий слой (компоненты.css, база min-height: var(--высота-кнопки)). */
/* ⛔ ГЛАВНАЯ остаётся 44 px и под флагом (дизайн-направление §2.5): свою роль --высота-кнопки она берёт
   в компоненты.css (уровень .сис-главная), правило кнопки здесь — второй источник вида под флагом.
   Снятие пола 44 px для мыши — решение Макса (§2.5, §8.3): до него флаг у Заказчика не включается. */
@media (pointer: fine){
  :root[data-вкл~="тихие-кнопки"]{--высота-кнопки:var(--высота-органа)}
}
