/*
 * Reset-минимум для SSR-страниц (Twig). Компонентная библиотека и
 * фронт-пайплайн React — Task 9; здесь только то, что нужно, чтобы
 * страница на токенах не выглядела "голым HTML".
 *
 * ВЕСЬ СБРОС — ВНУТРИ `@layer base` (Дизайн-спринт, Task 13.5). Слой
 * объявлен в `assets/css/layers.css`: `base` стоит РАНЬШЕ `primitives`/
 * `components`/`pages` и по правилам каскадных слоёв ОБЯЗАН проигрывать им
 * порядком — а не жить неслоёным файлом, который по тем же правилам
 * побеждает ЛЮБОЙ слой независимо от специфичности. До этой задачи файл не
 * был обёрнут вовсе (слой в `layers.css` был объявлен, но не использован
 * здесь) — и `a { color: var(--primary) }`/`img, svg { display: block }`
 * ниже били примитивы и компоненты каждый раз: спринт находил и точечно
 * патчил следствия по одному (`.rf-card h3 a`, `.rf-card .rf-icon`,
 * `.rf-filter-chip` как ссылка — докблоки `app.css` документируют каждый
 * случай и объясняют, почему заглушки сняты этой задачей), а корень
 * оставался неслоёным. Обёртка ниже — тот корень: любое правило `@layer
 * primitives`/`components`/`pages` отныне честно побеждает reset порядком
 * слоя, специфичность в этой войне больше не участвует.
 *
 * ОБЁРТКУ ДЕРЖИТ ГЕЙТ `apps/shared/ui/css-layers.test.ts`. Снять её можно
 * было одной строкой, и набор остался бы зелёным — сайт молча вернулся бы
 * к акцентным ссылкам везде (проверено 08.09: с временно снятой обёрткой
 * чипы фандома снова красились `--primary`, замер `getComputedStyle()` на
 * живом стенде). Гейт требует нуля неслоёных правил в этом файле — кроме
 * одного ПОИМЕНОВАННОГО исключения ниже — и отдельно проверяет, что
 * `a { color }` лежит внутри `@layer base`, а не рядом с ним. Он же ведёт
 * счёт неслоёных правил во всём дереве: на 15.09 они остались в `app.css`,
 * `reader.css`, `tokens.css`/`fonts.css`, CSS витрины и `print.css`, а
 * `studio.css`/`editor.css`, которые ниже по тексту ещё названы частично
 * неслоёными, обёрнуты целиком (Task 20, Task 23) — довод про `!important`
 * от этого не слабеет, пока неслоёные правила есть хоть где-то.
 *
 * ИСКЛЮЧЕНИЕ — `@media (prefers-reduced-motion: reduce)` В САМОМ НИЗУ
 * ФАЙЛА, СОЗНАТЕЛЬНО ВНЕ `@layer base` И С `!important`. Это не пропущенная
 * строка и не половинчатая правка: это ДВА РАЗНЫХ МЕХАНИЗМА для двух разных
 * задач. `@layer base` здесь решает войну АВТОРСКИХ правил друг с другом
 * (reset против примитива против компонента) — слоя достаточно, специфика
 * не нужна. Сокращённое движение — не авторское оформление, а
 * ПОЛЬЗОВАТЕЛЬСКОЕ ПРЕДПОЧТЕНИЕ, и обязано побеждать вообще всё, включая
 * компоненты и страницы, независимо от того, из какого слоя они пришли, —
 * а `@layer` для этого не годится ни при каком порядке: последний слой в
 * очереди побеждает только другие СЛОЁНЫЕ правила, а `app.css`/`reader.css`/
 * `studio.css`/`editor.css` по сей день частично неслоёные (Task 13.5 не
 * трогает их — не её задача) и в этой войне побеждают ЛЮБОЙ слой сразу.
 * Единственный работающий инструмент здесь — `!important` на нулевой
 * специфичности `*` (докблок у самого правила ниже расписывает это
 * подробно, включая историю первой неудачной попытки решить это слоем).
 * Обернуть это правило в `@layer base` было бы РЕГРЕССИЕЙ доступности:
 * сокращённое движение снова перестало бы гасить анимации в неслоёных
 * файлах, той же дырой, что нашёл и закрыл Task 3.
 */

@layer base {

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* мобильный viewport (см. <meta name="viewport"> в base.html.twig) —
     это только поддержка на уровне CSS: без масштабирования системных
     настроек шрифта у пользователя */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, "Noto Sans", sans-serif,
    "Apple Color Emoji", "Segoe UI Emoji";
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--primary);
}

h1, h2, h3, h4, h5, h6 {
  line-height: 1.2;
}

img, svg {
  max-width: 100%;
  display: block;
}

}

/*
 * `!important` — ЕДИНСТВЕННОЕ ЗАДОКУМЕНТИРОВАННОЕ ИСКЛЮЧЕНИЕ ИЗ ПОТОЛКА
 * СПЕЦИФИЧНОСТИ 0,2,0 (спек §4.1, принцип 4), восстановлено фикс-раундом 1
 * (Task 3, Finding 2) по ruling'у контроллера, тем же приёмом, что уже
 * применён к `no-hardcoded-colors` (исключения `tokens.css`/`reader.css` —
 * с письменной причиной, а не молча).
 *
 * Потолок специфичности существует, чтобы СОБСТВЕННЫЕ компоненты проекта
 * не гонялись селекторами друг с другом — для этого достаточно порядка
 * слоёв каскада, специфичность внутри слоя не нужна вовсе. Но универсальный
 * сброс `*` играет в другую игру: у него нулевая специфичность (0,0,0), и
 * он ОБЯЗАН побеждать любое авторское правило — включая написанное одним
 * классом, — независимо от того, в каком слое оно лежит. Первый проход
 * задачи снял `!important` и обернул правило в `@layer utilities`, рассудив,
 * что последний слой победит и так, — но охват оказался не просто уже, а
 * не покрывал главное: `app.css`/`reader.css`/`studio.css`/`editor.css` НЕ
 * обёрнуты ни в один слой, а НЕслоёный CSS побеждает ЛЮБОЙ слой независимо
 * от специфичности. Слой здесь не помог бы вовсе — «нет слоя» сильнее
 * любого слоя. Замерено контроллером с `prefers-reduced-motion: reduce`:
 * `.rf-card`/`.chip` (`app.css` — на момент замера класс карточки ещё
 * назывался `.card`, переименован дизайн-спринтом, Task 11), `header.chrome`/
 * `#sheet` читалки
 * (`reader.css`) продолжали переезжать и выезжать, хотя человек явно
 * попросил не двигать интерфейс — самые «двигательные» места продукта.
 *
 * ЭТО НЕ ВРЕМЕННЫЙ ДОЛГ, который спишется, когда все файлы переедут в свои
 * слои (план §Architecture). Даже после переезда слой снова не решит задачу:
 * это правило описывает пользовательское ПРЕДПОЧТЕНИЕ
 * (`prefers-reduced-motion`), а не авторское оформление, и обязано побеждать
 * оформление независимо от того, из какого слоя оно пришло, — ровно тот
 * случай, для которого `!important` и придуман: пользовательское важнее
 * авторского. `!important` здесь остаётся навсегда, а не до тех пор.
 *
 * ЭТО ОСТАЁТСЯ ВЕРНЫМ И ПОСЛЕ Task 13.5 (сам `base.css` выше теперь в
 * `@layer base`): обёртка вылечила войну АВТОРСКИХ правил друг с другом
 * (reset против примитивов/компонентов), но не изменила состав дерева —
 * `app.css`/`reader.css`/`studio.css`/`editor.css` по-прежнему частично
 * неслоёные, и именно поэтому это правило по-прежнему не может стать
 * слоёным само (докблок в начале файла объясняет тем же текстом, почему
 * `@layer` для ПОЛЬЗОВАТЕЛЬСКОГО предпочтения не работает ни при каком
 * порядке слоёв).
 *
 * Гейт `css-specificity.test.ts` знает про это исключение: `!important`
 * разрешён ТОЛЬКО внутри блока `@media (prefers-reduced-motion: reduce)`,
 * везде остальное — по-прежнему нарушение (проверено тестом самого теста).
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
