/*
 * Слой стилей административных страниц Vigorix — v0.26.0, UNF-60/UNF-61.
 *
 * ЗАЧЕМ ФАЙЛ СУЩЕСТВУЕТ.
 *
 * До этого релиза 69 собственных шаблонов несли 839 инлайновых `style="…"` и
 * сотни захардкоженных hex-цветов. Инлайновый цвет не переключается вместе с
 * темой: `color:#666` на тёмной подложке становится нечитаемым, `#b00` —
 * грязным пятном. Для контура, где оператор читает суммы выводов и статусы
 * kill-switch, это не косметика: неразличимая красная пометка «ручное
 * вмешательство» — это пропущенное ручное вмешательство.
 *
 * ПОЧЕМУ СВОЙ ФАЙЛ, А НЕ ТОЛЬКО УТИЛИТЫ UNFOLD. `django-unfold` поставляет
 * СОБРАННЫЙ бандл Tailwind v4: набор классов в нём фиксирован сборкой, и
 * произвольных значений (`max-w-[62em]`) там нет и появиться не может.
 * Ширины колонок проекта заданы в `em` — привязка к кеглю, а не к пикселям, —
 * и в шкалу Tailwind не ложатся. Кроме того, привязка 839 мест к именам
 * вендорных утилит означала бы, что обновление Unfold может молча увести
 * вёрстку: утилита, которую перестали использовать шаблоны вендора, из сборки
 * исчезает. Свой слой этот риск снимает.
 *
 * ПРИНЦИП. Цвета берутся ИЗ ПАЛИТРЫ UNFOLD через её CSS-переменные
 * (`--color-red-*`, `--color-green-*`, `--color-orange-*`, `--color-blue-*`,
 * `--color-base-*`, `--color-font-*`, `--color-primary-*`). Смена
 * `UNFOLD["COLORS"]` на фирменные подхватится этим слоем автоматически, а
 * тёмная тема работает через `.dark`, как во всём остальном интерфейсе.
 *
 * Именование: смысл там, где он есть (`vx-danger`, `vx-badge--ok`,
 * `vx-card--warn`), явная величина там, где элемент шкалы (`vx-w-62` —
 * `max-width: 62em`). Придумывать «семантику» для ступени шкалы вредно:
 * `vx-w-md` не сообщает читателю ничего, `vx-w-40` сообщает ровно то, что есть.
 *
 * КАСКАД. Файл подключается через `UNFOLD["STYLES"]`, то есть в `<head>` он
 * идёт ДО `unfold/css/styles.css`. Порядок здесь не решает: бандл Tailwind v4
 * целиком лежит в каскадных слоях (`@layer theme/base/components/utilities`),
 * а этот файл — вне слоёв, поэтому при равной специфичности выигрывает он.
 * Отсюда правило: селекторы держать узкими (`.vx-*`), чтобы не перебить
 * вендорные компоненты случайно.
 *
 * ГРАНИЦА ОБЛАСТИ. Страницы входа кабинетов (`support_admin/desk_*.html`,
 * `owner_admin/owner_2fa.html`) этот файл не подключают: они намеренно не
 * наследуют оболочку админки, живут на своих поддоменах и несут собственный
 * набор токенов. Их инлайновые значения — уже переменные (`var(--muted)`),
 * а не hex, и в область UNF-60 не входят.
 *
 * Проверяется гейтом `docs/tools/check_admin_template_style.py`.
 */

/* ── Семантические цвета ──────────────────────────────────────────────────
 * У палитры Unfold нет ролей «опасно / предупреждение / успех / информация»,
 * поэтому роли объявлены здесь — но значениями из её же шкал, а не своими.
 * Ступени подобраны по контрасту: 700 на светлой подложке, 400 на тёмной —
 * тот же приём, что в собственных компонентах Unfold (`errornote`).
 */
:root {
  --vx-danger: var(--color-red-700);
  --vx-danger-bg: var(--color-red-50);
  --vx-danger-border: var(--color-red-300);

  --vx-warn: var(--color-orange-700);
  --vx-warn-bg: var(--color-orange-50);
  --vx-warn-border: var(--color-orange-300);

  --vx-ok: var(--color-green-700);
  --vx-ok-bg: var(--color-green-50);
  --vx-ok-border: var(--color-green-300);

  --vx-info: var(--color-blue-700);
  --vx-info-bg: var(--color-blue-50);
  --vx-info-border: var(--color-blue-300);

  /* Приподнятая поверхность (карточки, плитки) — светлее страницы, и
   * граница у неё есть в обеих темах: в тёмной одна лишь заливка карточку
   * не выделяет, тон страницы и тон карточки там расходятся слабо. */
  --vx-surface: var(--color-white);
  --vx-surface-border: var(--color-base-200);
  /* Утопленная поверхность (вложенные строки таблиц, нейтральная подсветка) —
   * темнее страницы. Один токен на обе роли дал бы невидимый блок в одной из
   * тем: белая карточка на белой таблице или base-900 на base-900 странице. */
  --vx-surface-sunken: var(--color-base-100);
  --vx-font: var(--color-font-default-light);
  --vx-font-subtle: var(--color-font-subtle-light);
  --vx-font-important: var(--color-font-important-light);
}

.dark {
  --vx-danger: var(--color-red-400);
  --vx-danger-bg: var(--color-red-950);
  --vx-danger-border: var(--color-red-800);

  --vx-warn: var(--color-orange-400);
  --vx-warn-bg: var(--color-orange-950);
  --vx-warn-border: var(--color-orange-800);

  --vx-ok: var(--color-green-400);
  --vx-ok-bg: var(--color-green-950);
  --vx-ok-border: var(--color-green-800);

  --vx-info: var(--color-blue-400);
  --vx-info-bg: var(--color-blue-950);
  --vx-info-border: var(--color-blue-800);

  --vx-surface: var(--color-base-800);
  --vx-surface-border: var(--color-base-700);
  --vx-surface-sunken: var(--color-base-950);
  --vx-font: var(--color-font-default-dark);
  --vx-font-subtle: var(--color-font-subtle-dark);
  --vx-font-important: var(--color-font-important-dark);
}

/* ── Тон текста ───────────────────────────────────────────────────────── */
.vx-danger { color: var(--vx-danger); }
.vx-warn { color: var(--vx-warn); }
.vx-ok { color: var(--vx-ok); }
.vx-info { color: var(--vx-info); }
.vx-muted { color: var(--vx-font-subtle); }

/* ── Начертание ───────────────────────────────────────────────────────── */
.vx-semibold { font-weight: 600; }
.vx-bold { font-weight: 700; }
.vx-normal { font-weight: 400; }
.vx-mono { font-family: var(--font-mono); }

/* ── Кегль ────────────────────────────────────────────────────────────────
 * Относительные единицы: страницы админки читают и при увеличенном шрифте
 * системы, фиксированные px это ломают.
 */
.vx-2xs { font-size: 0.7em; }
.vx-xs { font-size: 0.75em; }
.vx-sm { font-size: 0.85em; }
.vx-md { font-size: 0.9em; }
.vx-lg { font-size: 1.1em; }
.vx-xl { font-size: 1.3em; }
.vx-2xl { font-size: 1.4em; }

/* ── Плашка статуса ───────────────────────────────────────────────────── */
.vx-badge {
  border: 1px solid transparent;
  border-radius: 0.375rem;
  display: inline-block;
  font-size: 0.85em;
  padding: 0.35em 0.6em;
  white-space: nowrap;
}
.vx-badge--danger { background: var(--vx-danger-bg); border-color: var(--vx-danger-border); color: var(--vx-danger); }
.vx-badge--warn { background: var(--vx-warn-bg); border-color: var(--vx-warn-border); color: var(--vx-warn); }
.vx-badge--ok { background: var(--vx-ok-bg); border-color: var(--vx-ok-border); color: var(--vx-ok); }
.vx-badge--neutral { background: var(--vx-surface-sunken); border-color: var(--vx-surface-border); color: var(--vx-font); }

/* Сплошные плашки: текст на цветной подложке. Применяются там, где статус
 * должен быть виден боковым зрением, — аварийные режимы и активная вкладка. */
.vx-badge--solid-primary { background: var(--color-primary-600); border-color: var(--color-primary-600); color: var(--color-white); font-weight: 700; }

/* ── Карточка / панель ────────────────────────────────────────────────── */
.vx-card {
  background: var(--vx-surface);
  border: 1px solid var(--vx-surface-border);
  border-radius: 0.5rem;
  padding: 1em;
}
.vx-card--danger { background: var(--vx-danger-bg); border-color: var(--vx-danger-border); }
.vx-card--warn { background: var(--vx-warn-bg); border-color: var(--vx-warn-border); }
.vx-card--ok { background: var(--vx-ok-bg); border-color: var(--vx-ok-border); }
/* Толстая рамка — для блоков, мимо которых нельзя пройти (kill-switch,
 * подтверждение необратимого действия). */
.vx-card--alert { background: var(--vx-danger-bg); border: 2px solid var(--vx-danger); }
.vx-card--alert-ok { background: var(--vx-ok-bg); border: 2px solid var(--vx-ok); }
.vx-card--alert-warn { background: var(--vx-warn-bg); border: 2px solid var(--vx-warn); }
.vx-card--alert-info { background: var(--vx-info-bg); border: 2px solid var(--vx-info); }

/* v0.26.2 FIX-3 (ТЗ UNF-64, НФ-5). Приглушённый текст на ТОНИРОВАННОЙ подложке.
 *
 * ЧТО БЫЛО. `.vx-muted` берёт `--vx-font-subtle` (в светлой теме это
 * `base-500`). На белом фоне пара даёт 4,84 — законно. На заливке карточки
 * состояния (`--vx-danger-bg` = `red-50`) она падает до 4,42, то есть ниже
 * порога AA. Обнаружено прогоном по DOM (`stand/browser_run.py`), страница
 * `/admin/impersonation/`, светлая тема. Ни токенная проверка, ни прогон
 * стенда v0.26.1 этого не видели: первая сверяет пару «subtle на странице»,
 * второй охватывал 20 экранов из 78.
 *
 * ПОЧЕМУ ПЕРЕОПРЕДЕЛЯЕТСЯ ПЕРЕМЕННАЯ, А НЕ ЦВЕТ. Тонированная подложка
 * забирает у приглушённого текста запас контраста — значит внутри неё роль
 * «приглушённый» должна разрешаться в обычный цвет текста. Одно правило на
 * все четыре карточки и обе темы: `.vx-muted` подхватит его каскадом, как и
 * любой другой потребитель роли. Точечная правка цвета в одном классе
 * оставила бы ту же дыру соседям.
 */
.vx-card--alert,
.vx-card--alert-ok,
.vx-card--alert-warn,
.vx-card--alert-info {
  --vx-font-subtle: var(--vx-font);
}

/* ── Группа полей формы (v0.26.1 FIX-10, UNF-51) ───────────────────────────
 * Партиал `includes/_form.html` раскладывает поля по группам, когда форма
 * объявила `fieldsets`. Правило одно и по делу: у последней группы нижний
 * отступ лишний — под ней сразу кнопка отправки, и двойной зазор читается
 * как «форма закончилась раньше». */
.vx-fieldset:last-of-type { margin-bottom: 0.75rem; }

/* ── Подсказка «где это правится» ─────────────────────────────────────────
 * v0.26.1 FIX-1 (UNF-68). Партиал `admin/includes/_domain_hint.html`
 * включается оболочкой Unfold в ШТАТНУЮ страницу changelist, а базовый слой
 * элементов привязан к `.vx-page` и на штатные страницы намеренно не
 * распространяется (иначе он ломает форму редактирования вендора — см. блок
 * «БАЗОВЫЙ СЛОЙ ЭЛЕМЕНТОВ»). Поэтому ссылке и коду внутри подсказки нужны
 * собственные правила: без них preflight Tailwind оставляет ссылку обычным
 * текстом, и указатель «правится здесь» перестаёт читаться как ссылка. */
.vx-hint a { color: var(--color-primary-600); font-weight: 600; }
.dark .vx-hint a { color: var(--color-primary-400); }
.vx-hint a:hover { text-decoration: underline; }
.vx-hint code {
  background: var(--vx-surface-sunken);
  border-radius: 0.25rem;
  font-family: var(--font-mono);
  font-size: 0.9em;
  padding: 0.1em 0.35em;
}

/* ── Плитка показателя ────────────────────────────────────────────────────
 * Ряд одинаковых по высоте блоков «название → число». Минимальная ширина не
 * даёт числу переноситься, `flex-wrap` у контейнера — переносит сами плитки.
 */
.vx-tile {
  background: var(--vx-surface);
  border: 1px solid var(--vx-surface-border);
  border-radius: 0.375rem;
  min-width: 12em;
  padding: 0.5em 0.8em;
}
.vx-tile--sm { min-width: 9em; }
.vx-tile--md { min-width: 10em; }
.vx-tile--lg { min-width: 14em; }
.vx-tile--danger { background: var(--vx-danger-bg); border-color: var(--vx-danger-border); }
.vx-tile--warn { background: var(--vx-warn-bg); border-color: var(--vx-warn-border); }
.vx-tile--ok { background: var(--vx-ok-bg); border-color: var(--vx-ok-border); }
.vx-tile--info { background: var(--vx-info-bg); border-color: var(--vx-info-border); }

/* ── Раскладка ────────────────────────────────────────────────────────── */
.vx-row { display: flex; flex-wrap: wrap; gap: 0.5em; }
.vx-row--tight { gap: 0.25em; }
.vx-row--sm { gap: 0.4em; }
.vx-row--md { gap: 0.6em; }
.vx-row--lg { gap: 1em; }
.vx-row--wide { gap: 2em; }
.vx-row--center { align-items: center; }
.vx-row--start { align-items: flex-start; }
.vx-row--end { align-items: flex-end; }
.vx-inline { display: inline; }

/* ── Отступы ──────────────────────────────────────────────────────────── */
.vx-m-0 { margin: 0; }
.vx-mt-0 { margin-top: 0; }
.vx-mt-2xs { margin-top: 0.2em; }
.vx-mt-xs { margin-top: 0.3em; }
.vx-mt-sm { margin-top: 0.6em; }
.vx-mt { margin-top: 1em; }
.vx-mt-lg { margin-top: 1.5em; }
.vx-mb-xs { margin-bottom: 0.3em; }
.vx-mb-sm { margin-bottom: 0.5em; }
.vx-mb { margin-bottom: 1em; }
.vx-mb-lg { margin-bottom: 1.2em; }
.vx-my { margin: 1em 0; }
.vx-my-sm { margin: 0.5em 0; }
.vx-ml-xs { margin-left: 0.5em; }
.vx-ml { margin-left: 1em; }
/* Подпись вплотную под заголовком: заголовок уже отбит снизу, свой отступ
 * добавил бы разрыв. Отрицательное значение подтягивает её обратно. */
.vx-lead { margin: -0.6em 0 1em; }

.vx-pad { padding: 1em; }
.vx-pad-lg { padding: 0.8em 1em; }
.vx-pr { padding-right: 1em; }

/* ── Ширины ───────────────────────────────────────────────────────────────
 * `max-width` — шкала читаемости текстовой колонки, в `em`: ширина строки
 * должна следовать за кеглем, иначе при увеличенном шрифте строка становится
 * длиннее допустимой. Значения — ступени, к ближайшей из которых приведены
 * прежние инлайновые (отклонение не более 4em).
 */
.vx-w-24 { max-width: 24em; }
.vx-w-30 { max-width: 30em; }
.vx-w-36 { max-width: 36em; }
.vx-w-40 { max-width: 40em; }
.vx-w-46 { max-width: 46em; }
.vx-w-54 { max-width: 54em; }
.vx-w-60 { max-width: 60em; }
.vx-w-70 { max-width: 70em; }
.vx-w-80 { max-width: 80em; }
.vx-w-full { width: 100%; }
.vx-w-auto { width: auto; }

/* Фиксированные ширины полей ввода и служебных колонок таблиц. */
.vx-fw-2xs { width: 3rem; }
.vx-fw-xs { width: 5rem; }
.vx-fw-sm { width: 10em; }
.vx-fw-md { width: 14em; }
.vx-fw-lg { width: 24em; }
.vx-fw-xl { width: 28em; }

/* ── Таблицы ──────────────────────────────────────────────────────────── */
.vx-left { text-align: left; }
.vx-right { text-align: right; }
.vx-nowrap { white-space: nowrap; }
.vx-wrap { white-space: pre-wrap; }
.vx-break { word-break: break-word; }
/* v0.38.0. Группы секрета TOTP на странице привязки устройства
 * (`admin_identity/setup_2fa.html`). Правила стояли в теге `<style>` прямо в
 * шаблоне и держали гейт оформления красным: цвет рамки был захардкожен
 * (`#ccc`), а класс отсутствовал в этом файле, то есть по правилам проекта
 * «элемент останется без оформления». Заодно тот блок ПЕРЕОПРЕДЕЛЯЛ
 * `.vx-break` на `break-all` — то же имя с другим поведением на одной
 * странице. Цвет рамки взят из токена, как у всех прочих поверхностей. */
.vx-secret span {
  display: inline-block;
  padding: 4px 8px;
  margin: 0 4px 4px 0;
  border: 1px solid var(--vx-surface-border);
  border-radius: 6px;
  font-weight: 700;
  letter-spacing: 0.08em;
}
/* v0.44.0 ADMIN-2FA-QR. QR-код на странице привязки второго фактора.
 *
 * Белая подложка задана ЯВНО и не берётся из темы: QR рисуется тёмными
 * модулями по светлому полю, и на тёмной теме админки картинка без своей
 * подложки сливалась бы с фоном — телефон такой код не берёт. Рамка и радиус
 * — как у прочих поверхностей, чтобы картинка читалась элементом страницы, а
 * не вставленным изображением. */
.vx-qr {
  display: block;
  background: #ffffff;
  padding: 10px;
  border: 1px solid var(--vx-surface-border);
  border-radius: 8px;
  image-rendering: pixelated;
}
.vx-top { vertical-align: top; }
.vx-cell { padding: 0.35em 0.6em; }
.vx-cell--tight { padding: 0.25em 0.6em; }
/* Колонка названий в таблице «свойство → значение». Треть ширины: короче —
 * названия переносятся, шире — значение прижимается к правому краю. */
.vx-kv-th { width: 34%; }
.vx-kv-th--wide { width: 44%; }
/* Вложенная строка-раскрытие под основной: сдвиг слева показывает подчинение. */
.vx-subrow { padding: 0 0 12px 24px; background: var(--vx-surface-sunken); }

/* ── Прочее ───────────────────────────────────────────────────────────── */
/* Пояснение к странице: вертикальная черта вместо рамки — не отнимает
 * ширину у текста и не читается как отдельный блок. */
.vx-note { border-left: 3px solid var(--color-primary-500); padding-left: 10px; }
.vx-note--warn { border-left: 3px solid var(--vx-warn-border); padding: 0.4em 0.9em; }
/* Контейнер графика: высота задаётся здесь, потому что канвас без неё
 * схлопывается в ноль до отработки скрипта. */
.vx-chart { height: 220px; margin: 0 0 1em; }
/* Ссылка, выглядящая как кнопка действия. */
.vx-link-btn { border-radius: 0.3125rem; display: inline-block; padding: 0.35em 0.8em; text-decoration: none; }
/* Кнопка, выглядящая как ссылка: submit внутри строки таблицы. */
.vx-plain-btn { background: none; border: none; cursor: pointer; padding: 0; }

/* ── Кнопки действий ──────────────────────────────────────────────────────
 * Unfold красит `button.default` в основной цвет темы. Необратимое действие
 * (приостановить аккаунт, отклонить выплату, закрыть позиции) обязано
 * отличаться от обычного «Сохранить» ДО нажатия, а не только текстом на
 * подтверждении: цвет — единственная подсказка, которую оператор считывает
 * не читая. Правило вне каскадных слоёв, поэтому перебивает утилиты бандла.
 */
.vx-btn-danger,
.vx-btn-danger:link,
.vx-btn-danger:visited {
  background: var(--color-red-700);
  border-color: var(--color-red-700);
  color: var(--color-white);
}
.vx-btn-danger:hover { background: var(--color-red-800); border-color: var(--color-red-800); }
.dark .vx-btn-danger { background: var(--color-red-800); border-color: var(--color-red-800); }
.dark .vx-btn-danger:hover { background: var(--color-red-900); border-color: var(--color-red-900); }

.vx-btn-ok,
.vx-btn-ok:link,
.vx-btn-ok:visited {
  background: var(--color-green-700);
  border-color: var(--color-green-700);
  color: var(--color-white);
}
.vx-btn-ok:hover { background: var(--color-green-800); border-color: var(--color-green-800); }
.dark .vx-btn-ok { background: var(--color-green-800); border-color: var(--color-green-800); }
.dark .vx-btn-ok:hover { background: var(--color-green-900); border-color: var(--color-green-900); }

/* ── Вкладки и переключатели периода ──────────────────────────────────────
 * Активный элемент отличается заливкой, а не только цветом текста: в тёмной
 * теме разница «синий текст против серого» на глаз почти не читается.
 */
.vx-tabstrip { border-bottom: 2px solid var(--vx-surface-border); padding-bottom: 0.4em; }
.vx-tab {
  border-radius: 0.3125rem 0.3125rem 0 0;
  color: var(--color-primary-600);
  padding: 0.35em 0.7em;
  text-decoration: none;
}
.dark .vx-tab { color: var(--color-primary-400); }
.vx-tab--active {
  background: var(--color-primary-600);
  color: var(--color-white);
  font-weight: 700;
}
.dark .vx-tab--active { color: var(--color-white); }

.vx-chip {
  border: 1px solid transparent;
  border-radius: 0.25rem;
  font-size: 0.85em;
  padding: 0.25em 0.6em;
  text-decoration: none;
}
.vx-chip--link { border-color: var(--color-primary-200); color: var(--color-primary-600); }
.dark .vx-chip--link { border-color: var(--color-primary-800); color: var(--color-primary-400); }
.vx-chip--active {
  background: var(--color-primary-600);
  color: var(--color-white);
  font-weight: 700;
}

/* ── Подсветка строки таблицы ─────────────────────────────────────────────
 * Строка целиком, а не отдельная ячейка: в реестре выплат оператор ищет
 * глазами «что не так» по всей ширине, а не по одной колонке.
 */
.vx-tr--danger { background: var(--vx-danger-bg); }
.vx-tr--warn { background: var(--vx-warn-bg); }
.vx-tr--ok { background: var(--vx-ok-bg); }
.vx-tr--neutral { background: var(--vx-surface-sunken); }

.vx-ml-auto { margin-left: auto; }

/* ── Доступность ──────────────────────────────────────────────────────────
 * Текст только для скринридера. В сборке Unfold утилиты `sr-only` нет —
 * её шаблоны ею не пользуются, значит в бандл она не попала, — а пометка
 * «обязательное поле» рядом со звёздочкой нужна: `aria-hidden` на звёздочке
 * без текстовой замены оставил бы поле без признака обязательности.
 */
.vx-sr-only {
  border-width: 0;
  clip-path: inset(50%);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * БАЗОВЫЙ СЛОЙ ЭЛЕМЕНТОВ
 *
 * ЗАЧЕМ. До миграции собственные страницы наследовали `admin/css/base.css`
 * стоковой админки: она задавала размеры заголовков, отступы абзацев, рамки и
 * padding ячеек, вид `fieldset.module` и кнопок. Оболочка Unfold эту таблицу
 * стилей НЕ подключает, а Tailwind поверх того сбрасывает умолчания браузера
 * (preflight: у `h1`…`h6` тот же кегль, что у текста, у списков нет маркеров,
 * у ячеек нет отступов). Вендор это компенсирует классами в своих шаблонах —
 * но 66 собственных шаблонов проекта его классов не несут.
 *
 * Итог до этого слоя, снятый в браузере: заголовки разделов неотличимы от
 * текста, таблицы выводов и сверок сливаются в сплошное полотно, `<button>`
 * выглядит как подчёркнутое слово. На странице казначейства, где оператор
 * подтверждает выплаты, это не вопрос вкуса.
 *
 * ПОЧЕМУ `:where(...)`. У `:where()` НУЛЕВАЯ специфичность. Значит любой класс
 * — что вендорный (`px-2.5`, `text-left` в шаблонах Unfold), что проектный
 * (`vx-cell`) — перебивает эти правила, а сами они работают только там, где на
 * элементе нет ничего другого.
 *
 * v0.26.1 FIX-17. ОБЁРНУТЫ И ПРЕДКИ — РАНЬШЕ СЛОЙ БЫЛ СИЛЬНЕЕ, ЧЕМ ОБЕЩАЛ.
 *
 * Правила писались как `.vx-page :where(a)` и `.dark .vx-page :where(a)`, то
 * есть имели специфичность (0,1,0) и (0,2,0) — а не ноль. Абзац выше при этом
 * утверждал обратное, и на него полагались компоненты.
 *
 * Что это ломало, замерено на стенде по отрендеренному DOM:
 *
 *   · СВЕТЛАЯ тема. `.vx-page :where(a)` объявлено НИЖЕ `.vx-tab--active`
 *     (0,1,0 против 0,1,0 — при равенстве побеждает последнее), поэтому
 *     активная вкладка дашборда и активная плашка периода получали цвет
 *     ссылки поверх собственного белого: фиолетовый текст на фиолетовой
 *     заливке, контраст 1.0. На снимке — сплошной прямоугольник без подписи:
 *     оператор не видел, какая вкладка и какой период выбраны.
 *
 *   · ТЁМНАЯ тема. `.dark .vx-page :where(a)` (0,2,0) перебивало `.vx-btn-ok`
 *     и `.vx-btn-danger` (0,1,0), и подписи кнопок «Подтвердить вывод»,
 *     «Отклонить», «Активировать» становились фиолетовыми на зелёном и
 *     красном: контраст 2.55 и 2.99 при пороге 4.5.
 *
 * Ни того, ни другого не видел тест контраста: он считает пары ТОКЕНОВ
 * палитры арифметически и не знает, какое правило победит в каскаде. Видно
 * это только на отрисованной странице — поэтому проверка контраста по
 * отрендеренному DOM (UNF-64) заведена в прогон стенда. Слой поэтому НЕ меняет вид штатных страниц
 * Unfold: у её `<td>` классы есть. Проверено сравнением снимков changelist и
 * формы редактирования до и после появления слоя.
 *
 * ПОЧЕМУ `.vx-page`, А НЕ `#content`. Обёртка содержимого одна и та же у
 * собственных и у штатных страниц. Проверено сравнением снимков: слой,
 * привязанный к `#content`, ломал форму редактирования Unfold — её
 * `fieldset.module` получал вторую рамку, а таблица инлайнов — чужие отступы.
 * Класс `vx-page` ставит на контейнер контекст-процессор `admin_shell`, и
 * только когда маршрут НЕ принадлежит пространству имён `admin`. Признак
 * берётся у резолвера, чтобы не заводить список путей, который отстанет.
 * ═══════════════════════════════════════════════════════════════════════════ */

/* ── Типографика ──────────────────────────────────────────────────────── */
/* `h1` здесь не описан намеренно: заголовок первого уровня на странице один и
 * его рисует оболочка (`unfold/helpers/welcomemsg.html`). Собственные `<h1>`
 * из шаблонов убраны (UNF-62), и гейт не даёт им вернуться, поэтому правило
 * для `h1` было бы правилом ни для чего. Верхний заголовок содержимого —
 * `h2`. */
:where(.vx-page) :where(h2) {
  color: var(--vx-font-important);
  font-size: 1.2rem;
  font-weight: 600;
  line-height: 1.3;
  margin: 1.5rem 0 0.5rem;
}
:where(.vx-page) :where(h3) {
  color: var(--vx-font-important);
  font-size: 1.05rem;
  font-weight: 600;
  margin: 1.2rem 0 0.4rem;
}
:where(.vx-page) :where(p) { margin: 0 0 0.75rem; }
:where(.vx-page) :where(ul, ol) { margin: 0 0 0.75rem; padding-left: 1.5rem; }
:where(.vx-page) :where(ul) { list-style: disc; }
:where(.vx-page) :where(ol) { list-style: decimal; }
:where(.vx-page) :where(li) { margin-bottom: 0.2rem; }
:where(.vx-page) :where(dl) { margin: 0 0 0.75rem; }
:where(.vx-page) :where(dt) { color: var(--vx-font-important); font-weight: 600; }
:where(.vx-page) :where(dd) { margin: 0 0 0.5rem; }
:where(.vx-page) :where(hr) { border: 0; border-top: 1px solid var(--vx-surface-border); margin: 1.2rem 0; }
:where(.vx-page) :where(small) { font-size: 0.85em; }
:where(.vx-page) :where(a) { color: var(--color-primary-600); }
:where(.dark) :where(.vx-page) :where(a) { color: var(--color-primary-400); }
:where(.vx-page) :where(a):hover { text-decoration: underline; }
:where(.vx-page) :where(code) {
  background: var(--vx-surface-sunken);
  border-radius: 0.25rem;
  /* v0.26.1 FIX-18. Цвет задан явно, а не наследуется.
   * Замерено на стенде: `<code>` внутри приглушённого абзаца получал
   * `--vx-font-subtle` и на подложке `--vx-surface-sunken` давал контраст
   * 4.39 при пороге 4.5 — то есть имя роли или команды читалось хуже
   * окружающего текста. Встроенный код обязан быть читаемее прозы, а не
   * бледнее её: его читают по символам, а не по смыслу фразы. */
  color: var(--vx-font);
  font-family: var(--font-mono);
  font-size: 0.9em;
  padding: 0.1em 0.35em;
}
:where(.vx-page) :where(pre) {
  background: var(--vx-surface-sunken);
  border-radius: 0.375rem;
  font-family: var(--font-mono);
  font-size: 0.85em;
  margin: 0 0 0.75rem;
  overflow-x: auto;
  padding: 0.75em 1em;
}
:where(.vx-page) :where(pre) :where(code) { background: none; padding: 0; }

/* ── Таблицы ──────────────────────────────────────────────────────────────
 * Разделитель — горизонтальная линия, без вертикальных: колонок в реестрах
 * до девяти, сетка из линий на такой ширине читается хуже, чем строки.
 */
:where(.vx-page) :where(table) { border-collapse: collapse; margin: 0 0 1rem; }
:where(.vx-page) :where(th, td) {
  border-bottom: 1px solid var(--vx-surface-border);
  padding: 0.5rem 0.6rem;
  text-align: left;
  vertical-align: top;
}
:where(.vx-page) :where(thead th) {
  border-bottom: 2px solid var(--vx-surface-border);
  color: var(--vx-font-important);
  font-weight: 600;
  white-space: nowrap;
}
:where(.vx-page) :where(tbody tr:last-child td) { border-bottom: 0; }

/* ── Блок-раздел ──────────────────────────────────────────────────────────
 * `fieldset.module` — разметка стоковой админки, которой пользуются и шаблоны
 * проекта, и шаблоны Unfold. Оформления у неё нет ни там, ни там; проекту она
 * нужна как карточка раздела.
 */
:where(.vx-page) :where(fieldset.module) {
  background: var(--vx-surface);
  border: 1px solid var(--vx-surface-border);
  border-radius: 0.5rem;
  margin: 0 0 1.2rem;
  padding: 1rem 1.2rem;
}
:where(.vx-page) :where(fieldset.module) > :where(h2):first-child { margin-top: 0; }
:where(.vx-page) :where(legend) { color: var(--vx-font-important); font-weight: 600; padding: 0 0.4em; }
:where(.vx-page) :where(.help) { color: var(--vx-font-subtle); font-size: 0.85em; }

/* ── Элементы управления ──────────────────────────────────────────────────
 * В шаблонах есть формы, собранные разметкой, а не классом Form: фильтры,
 * быстрые действия. Классы Unfold на них никто не проставит — миксин видит
 * только поля Django-форм. Поэтому вид задаётся элементу.
 */
:where(.vx-page) :where(button, input[type="submit"], input[type="button"], a.button) {
  background: var(--color-primary-600);
  border: 1px solid transparent;
  border-radius: 0.375rem;
  color: var(--color-white);
  cursor: pointer;
  display: inline-block;
  font-weight: 500;
  padding: 0.45em 0.9em;
  text-decoration: none;
}
:where(.vx-page) :where(button, input[type="submit"], input[type="button"], a.button):hover {
  background: var(--color-primary-700);
  text-decoration: none;
}
:where(.vx-page) :where(input[type="text"], input[type="number"], input[type="password"],
                input[type="email"], input[type="url"], input[type="date"],
                input[type="datetime-local"], input[type="search"], select, textarea) {
  background: var(--vx-surface);
  border: 1px solid var(--vx-surface-border);
  border-radius: 0.375rem;
  color: var(--vx-font);
  padding: 0.4em 0.6em;
}
:where(.vx-page) :where(input[type="checkbox"], input[type="radio"]) { accent-color: var(--color-primary-600); }
:where(.vx-page) :where(input:focus-visible, select:focus-visible, textarea:focus-visible) {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 1px;
}

/* ── v0.70.0 ID-03. Идентификатор с кнопкой копирования ──────────────────────
   Кнопка стоит РЯДОМ со значением, а не заменяет его: оператор сверяет номер
   глазами (он назван в обращении) и копирует его же — два разных действия
   над одним значением. */
.vx-id {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.vx-id-value {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.vx-id-copy {
  border: 1px solid var(--color-base-300, #d1d5db);
  border-radius: 6px;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 11px;
  line-height: 1.2;
  padding: 2px 7px;
  min-width: 78px;
}

.vx-id-copy:hover {
  border-color: var(--color-primary-500, #6366f1);
}

/* 14.09.2026 PROMO-GEN-01. «Сгенерировать» под полем кода промокода: та же
   кнопка, что «Копировать», но в форме — с отступом от поля и крупнее, чтобы
   не выглядеть подписью к нему. Селектор по атрибуту, а не отдельный класс:
   кнопку создаёт vigorix-admin.js, и класс, которого нет в шаблонах, гейт
   check_admin_template_style считал бы мёртвым. */
.vx-id-copy[data-vx-generate-for] {
  display: inline-block;
  margin-top: 6px;
  font-size: 12px;
  padding: 4px 10px;
}

.vx-id-internal {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  opacity: 0.65;
}
