﻿/* Модуль управления институтом. Оформление намеренно спокойное: экран открывают,
   чтобы найти проблемы, и цвет здесь несёт смысл (тревожность статуса), а не украшает.

   ⛔ ЦВЕТА, КЕГЛИ, ОТСТУПЫ И РАДИУСЫ ЗДЕСЬ НЕ ОБЪЯВЛЯЮТСЯ. Все значения берутся
   из системы оформления — `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;
  display: flex; align-items: center; justify-content: center;
  /* Подложка под карточкой входа — утопленная поверхность: карточка лежит ВЫШЕ
     неё, и это же различие переживает обе темы клиента Pilot. */
  background: var(--цвет-поверхность-утопленная);
  z-index: 100;
}

/* ОБЯЗАТЕЛЬНО. Встроенное правило браузера `[hidden] { display: none }` живёт
   в стилях агента, то есть СЛАБЕЕ любого авторского: `display: flex` выше его
   перебивает атрибут hidden, и экран входа не скрывается никогда. Приложение
   при этом отрисовано — просто накрыто непрозрачным слоем во весь экран,
   и после успешного входа человек продолжает видеть форму.
   Поймано снимком экрана, а не тестом: запросы при этом отвечали 200. */
.login-screen[hidden] { display: none; }
#app[hidden] { display: none; }

.login-box {
  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(--кегль-основной);
}
.login-box button {
  width: 100%; margin-top: var(--отступ-крупный);
  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(--цвет-граница);
  position: sticky; top: 0; z-index: 10;
}

header h1 { margin: 0; font-size: var(--кегль-заголовок); white-space: nowrap; }
.who { margin-left: auto; color: var(--цвет-текст-3); font-size: var(--кегль-таблица); }

.tabs { display: flex; gap: var(--отступ-малый); }
.tabs button {
  background: transparent; border: 1px solid transparent; color: var(--цвет-текст-2);
  padding: var(--отступ-малый) var(--отступ-средний);
  border-radius: var(--скругление); cursor: pointer; font-size: var(--кегль-основной);
}
.tabs button:hover { background: var(--цвет-фон-наведение); }
.tabs button.active { background: var(--цвет-фон-выбрано); color: var(--цвет-текст-выбрано); }

/* ⛔ ЦЕЛЬ НАЖАТИЯ ОСНОВНОЙ КНОПКИ — НЕ МЕНЬШЕ 44×44 px (WCAG 2.1 SC 2.5.5).
   44 стоит числом, а не токеном, намеренно: система объявляет пол 24 px
   (SC 2.5.8, `--цель-нажатия`), и поднять её значит тронуть источник на все
   четыре контура сразу. Число названо здесь, чтобы его было видно, а не
   размазано по паддингам. Содержимое кнопка центрирует сама. */
button {
  background: var(--цвет-акцент); color: var(--цвет-текст-на-акценте);
  border: 0; border-radius: var(--скругление);
  padding: 0 var(--отступ-средний);
  min-height: 44px; min-width: 44px;
  cursor: pointer; font-size: var(--кегль-основной);
}
button:hover { background: var(--цвет-акцент-2); }
/* Кнопка-ссылка стоит ВНУТРИ строки текста и заголовка («закрыть», «выйти»,
   «Показать все»): 44 px разорвали бы строку, поэтому здесь пол системы — 24 px. */
button.link {
  background: none; color: var(--цвет-акцент);
  padding: 0 var(--отступ-микро); text-decoration: underline;
  min-height: var(--цель-нажатия); min-width: var(--цель-нажатия);
}
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);
}
.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(--цвет-фон-наведение); }
/* ⛔ ЧИСЛО — ВПРАВО И ТАБЛИЧНЫМИ ЦИФРАМИ, ШАПКА ВМЕСТЕ С НИМ. Центрирования
   в этом контуре нет и появиться не должно: на центрированной клетке табличные
   цифры бесполезны — разряды всё равно не выстраиваются.
   ⚠ `th.num` сегодня не с чем сопоставить: класс числовому столбцу ставит
   app.js только у `td` (ветка `columns[i].numeric`), а JS этот заход не трогает.
   Правило стоит здесь заранее и вступит в силу тем же классом на `th` — одной
   правкой, без второго решения о том, куда выравнивать число. */
th.num, td.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
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` и уходят в печатную
   форму, а сверяет их тест `Палитра_по_умолчанию_в_стилях_совпадает_с_ядром`. */
.st.ok     { background: var(--st-ok-bg, #dcfce7);   color: var(--st-ok-fg, #166534); }
.st.low    { background: var(--st-low-bg, #fef9c3);  color: var(--st-low-fg, #854d0e); }
.st.mid    { background: var(--st-mid-bg, #fed7aa);  color: var(--st-mid-fg, #9a3412); }
.st.high   { background: var(--st-high-bg, #fee2e2); color: var(--st-high-fg, #991b1b); }
/* «Нет данных» — свой цвет, не зелёный и не красный: это отсутствие сведений
   о возможной беде, а не благополучие и не подтверждённая проблема. */
.st.nodata { background: var(--st-nodata-bg, #e5e7eb); color: var(--st-nodata-fg, #4b5563); }

.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(--цвет-акцент);
}
.banner + .banner { margin-top: calc(var(--отступ-малый) * -1); }

.pw {
  font-family: var(--шрифт-моно); background: var(--подсветка-внимание);
  padding: var(--отступ-микро) var(--отступ-малый); border-radius: var(--скругление);
}

/* Выгрузка — ссылка, а не кнопка: браузер сам покажет диалог сохранения
   и возьмёт имя файла с датой из заголовка ответа.
   Цель нажатия та же, что у кнопки (44 px): человек не отличает их видом,
   и отличать пальцем тем более не должен. Отсюда inline-flex — у ссылки нет
   собственного центрирования содержимого. */
.ex-btn {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--цвет-акцент); color: var(--цвет-текст-на-акценте); text-decoration: none;
  padding: 0 var(--отступ-средний);
  min-height: 44px; min-width: 44px;
  border-radius: var(--скругление); font-size: var(--кегль-основной);
}
.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(--кегль-служебный); }

/* Опасное действие красится лестницей срочности — тем же «горит», что и в таблице:
   второй красный завёл бы второй смысл у одного цвета. */
button.danger { background: var(--цвет-тревога); color: var(--цвет-текст-на-тревоге); }
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(--отступ-крупный);
}
.admin-nav button {
  background: none; color: var(--цвет-текст-2); border: none;
  border-radius: var(--скругление);
  text-align: left; padding: var(--отступ-малый); font: inherit;
  font-size: var(--кегль-таблица); cursor: pointer;
}
.admin-nav button:hover { background: var(--цвет-фон-наведение); }
.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: var(--отступ-микро) var(--отступ-крупный) var(--отступ-малый);
  user-select: all;
}

/* ⛔ ПОЛОСА РЕЖИМА РАБОТЫ. Видна поверх всего, включая экран входа: режим, о котором
   сказано только внутри, не виден тому, кто ещё не вошёл, — а решение «это боевая
   установка» принимают именно глядя на экран. Цвет предупреждающий, а не декоративный:
   полоса обязана читаться как «остановись и прочти», иначе её перестают замечать
   на второй день. Роль в лестнице срочности — «риск» с кантом «горит»: тот же цвет,
   что у любого другого предупреждения продукта, и он же переживает ч/б печать. */
.stand-banner {
  position: sticky;
  top: 0;
  z-index: 1000;
  padding: var(--отступ-малый) var(--отступ-крупный);
  background: var(--цвет-внимание);
  color: var(--цвет-текст-на-внимании);
  font-size: var(--кегль-таблица);
  line-height: var(--интерлиньяж-обычный);
  border-bottom: 2px solid var(--цвет-тревога);
}

/* Полоса «названия не прочитаны» живёт ВНЕ main, поэтому отступы задаются ей самой:
   иначе она прижимается к краю окна и читается как часть шапки, а не как
   предупреждение о состоянии данных. Своего `display` у неё НЕТ намеренно —
   встроенное правило `[hidden]{display:none}` обязано её гасить. */
#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; }
}
