/* ЕДИНСТВЕННЫЙ ИСТОЧНИК БЛОКА ТЕМ платформы «Виртуальный менеджер».
   Задача 167. Создан 11.09.2026, vm-designer.

   ===========================================================================
   ПОЧЕМУ ЭТОТ ФАЙЛ ВООБЩЕ ПОЯВИЛСЯ
   ===========================================================================
   До сегодняшнего дня один и тот же набор цветов был переписан от руки
   ШЕСТЬ раз: web/landing.css, web/index.html, web/admin.html,
   web/brand/brand.css, desktop/renderer/donor.html и — что хуже всего —
   словарём внутри самого измерителя web/brand/check-contrast.py.
   Измеритель мерил свою копию, а страницы показывали свою.

   Чем это кончилось дважды за неделю:
   * задача 84 — обводка полей;
   * задача 159 — `--warn:#8a6410` давал 4,33:1 при пороге 4,5. Правка дошла
     до трёх копий из пяти; шестая (donor.html:17) сломана до сих пор.

   Правило теперь одно: **цветовой токен объявляется только здесь**. Страница,
   которой нужен другой цвет, не заводит его у себя — она приходит сюда.
   Соблюдение проверяется машиной: `check-contrast.py` сканирует web/ и падает,
   если нашёл объявление цветового токена вне этого файла.

   ===========================================================================
   ПОЧЕМУ ОТДЕЛЬНЫЙ ФАЙЛ, А НЕ brand.css И НЕ _theme.css
   ===========================================================================
   * `brand.css` — не подходит: кроме токенов там классы знака, портретов,
     иллюстраций и движения. В нём есть `.brand-lockup .brand-name`, а в
     кабинете и в админке свой `.brand .name` в боковой колонке — подключение
     всего brand.css к кабинету втащило бы в него чужую раскладку ради
     двадцати строк цвета. Теперь brand.css сам читает этот файл
     (`@import` в его первой строке), то есть остаётся самодостаточным.
   * `_theme.css` — не подходит: имя занято другой работой. Тот файл не
     подключается в разметку вовсе, он исходник блока `<style>`, который
     вставлен ВНУТРЬ каждой illo-*.svg, и у него другие имена переменных
     (`--i`, `--su`) с запасными значениями — иллюстрация обязана читаться и
     в `<img>`, где переменных страницы нет. Совпадение значений `_theme.css`
     с этим файлом тоже проверяется машиной в check-contrast.py.

   ===========================================================================
   ЧТО ЗДЕСЬ ЕСТЬ И ЧЕГО ЗДЕСЬ НЕТ
   ===========================================================================
   Есть: цвета четырёх тем, роли (обводка, фокус, цель нажатия), шрифтовые
   стеки — всё, что обязано совпадать на витрине, в кабинете и в админке.
   Нет: геометрии. Скругление и шаг сетки у витрины и у рабочего места
   намеренно разные (одно — первое знакомство, другое — место работы), они
   остаются в своих файлах и на контраст не влияют.

   ===========================================================================
   ЧЕТЫРЕ ТЕМЫ — ТРИ НАБОРА ЗНАЧЕНИЙ
   ===========================================================================
   светлая         :root
   тёмная          :root[data-theme="dark"]
   контрастная     :root[data-theme="contrast"]
   системная       @media (prefers-color-scheme:dark) — берёт значения тёмной
   Системная своих значений не имеет, поэтому наборов три, а тем четыре.
   Оговорка `:not([data-theme="light"]):not([data-theme="contrast"])` в
   медиазапросе обязательна: без неё выбор человека «светлая» проигрывает
   настройке машины. Ровно этим сегодня болен donor.html.

   Заголовки кэша (задача 107): файл с расширением .css попадает в
   `_STATIC_REVALIDATE_SUFFIXES` службы (services/api.py) и отдаётся как
   `Cache-Control: no-cache` + `ETag` от Starlette — то есть браузер спрашивает
   сервер на каждый заход и получает 304 без тела, пока файл не менялся.
   Отдельной правки службы не потребовалось: правило по расширению уже такое. */

/* ---------- светлая (она же значения по умолчанию) ---------- */
:root{
  --ground:#e8e4d9; --surface:#f7f5ef; --surface-2:#efebe1; --surface-3:#e4e0d4;
  --ink:#191712; --ink-2:#5f594c; --ink-3:#8b8577;
  --rule:#d3cdbd; --rule-soft:#e0dbcd;
  --accent:#1e6b57; --accent-soft:#cfe0d8;
  --peak:#ab2b1e; --peak-soft:#f0dcd8;
  /* Тёмнее прежнего #8a6410: тот давал с --warn-soft 4,33:1 при пороге 4,5
     (замер 11.09.2026, задача 159). Новых цветов не заведено — сдвинут
     существующий. */
  --warn:#7d5a0e; --warn-soft:#f2e6c9;
}

/* ---------- системная тёмная ---------- */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]):not([data-theme="contrast"]){
  --ground:#15171a; --surface:#1d2025; --surface-2:#23272c; --surface-3:#2b3036;
  --ink:#ece8dd; --ink-2:#a29c8e; --ink-3:#756f63;
  --rule:#343940; --rule-soft:#2a2e34;
  --accent:#5cb497; --accent-soft:#25392f;
  --peak:#e8695c; --peak-soft:#3b2320;
  --warn:#d6a544; --warn-soft:#3a2f18;
}}

/* ---------- тёмная по выбору человека ---------- */
:root[data-theme="dark"]{
  --ground:#15171a; --surface:#1d2025; --surface-2:#23272c; --surface-3:#2b3036;
  --ink:#ece8dd; --ink-2:#a29c8e; --ink-3:#756f63;
  --rule:#343940; --rule-soft:#2a2e34;
  --accent:#5cb497; --accent-soft:#25392f;
  --peak:#e8695c; --peak-soft:#3b2320;
  --warn:#d6a544; --warn-soft:#3a2f18;
}

/* ---------- контрастная ---------- */
:root[data-theme="contrast"]{
  --ground:#ffffff; --surface:#ffffff; --surface-2:#f2f2f2; --surface-3:#e6e6e6;
  --ink:#000000; --ink-2:#1a1a1a; --ink-3:#4d4d4d;
  --rule:#000000; --rule-soft:#8c8c8c;
  --accent:#00543f; --accent-soft:#d6efe6;
  --peak:#8f0000; --peak-soft:#ffdede;
  --warn:#5c4300; --warn-soft:#fff0c2;
}

/* ---------- роли, а не цвета ---------- */
/* Обводка нажимаемого и заполняемого — отдельная роль, и это не украшение.
   Замер (docs/33-BRAND.md §5.3, web/brand/check-contrast.py): --rule на
   подложке даёт 1,25:1 в светлой теме и 1,40:1 в тёмной при пороге 3:1 по
   критерию WCAG 1.4.11 — границы кнопки и поля практически не видно, а кнопка
   опознаётся почти только по ней. --ink-3 тоже не проходит (2,89:1). Проходит
   --ink-2: 6,38:1 в светлой, 4,87:1 в тёмной, 17,40:1 в контрастной.
   Новых цветов не заведено — переставлены роли уже существующих, поэтому
   тёмная и контрастная темы не разъезжаются.
   Правило: кнопка, поле, список, флажок и вкладка обводятся только через
   --edge; --rule остаётся разделителям и очертанию карточек — карточка по
   нажатию ничего не делает, и 1.4.11 к ней не применяется.
   Значения — ссылки на переменные темы, поэтому пересчитываются сами во всех
   четырёх темах и повторять их в каждой теме не нужно. */
:root{
  --edge:var(--ink-2);
  --edge-quiet:var(--rule);
  /* Главная кнопка и «хорошо»: у витрины и юридических страниц это акцент (прежнее поведение), у рабочей поверхности свои
     значения объявлены в наборах выше. Объявлены ПОСЛЕ наборов, но набор рабочей поверхности специфичнее и их перекрывает. */
  --primary:var(--accent); --on-primary:var(--ground);
  --good:var(--accent); --good-soft:var(--accent-soft);
  --focus:var(--accent);
  /* Наименьшая цель нажатия. 24 px — предел, ниже которого нельзя
     (WCAG 2.5.8), 44 px — то, к чему приводим главные действия. */
  --hit-min:24px;
  --hit:44px;
  /* Шрифты только местные: ни одной загрузки с чужого домена. Платформа уезжает
     на сервер в РФ, и внешняя зависимость там лишняя. Пока woff2 не положены в
     web/brand/fonts, роль узкого акцидентного шрифта на Windows берёт
     Arial Narrow — стек объявлен так, что подстановка происходит молча. */
  --f-display:"Oswald","Arial Narrow",system-ui,sans-serif;
  --f-body:"Golos Text","Segoe UI",system-ui,sans-serif;
  --f-mono:"IBM Plex Mono","Cascadia Mono",ui-monospace,monospace;
}
