/* Рамка публичного сайта: тело страницы, шапка, подвал, корзина и формы.

   🔴 Отдельным файлом не по привычке, а по требованию политики содержимого: строгая политика
   разрешает стили только своим файлом — `style-src 'self'` (core/security/csp.py). Ни `<style>`
   внутри страницы, ни атрибут `style=` браузер не применит, и вёрстка разъехалась бы у клиента,
   а не у нас.

   🔴 Мобильный вид первым, а не «потом адаптируем» (3.3): узкий экран получает простой поток
   сверху вниз, широкий — те же блоки шире. Каталог растений смотрят с телефона на участке.

   🔴 ГРАНИЦЫ ФАЙЛА ИЗМЕНИЛИСЬ 31.07.2026, когда UI стал строиться тремя дорожками сразу
   (`PROEKT.md` 9А.0б). Раньше здесь лежали стили всего сайта, и три строителя переписали бы
   один файл втроём. Теперь у каждого объекта свой файл-владелец (0.1):

   | Что                                   | Чей файл       |
   |---------------------------------------|----------------|
   | цвета, шрифты, скругления, ширины      | `tokens.css`   ← только координатор
   | тело, шапка, подвал, корзина, формы    | `site.css`     ← этот файл, координатор
   | меню разделов и видов                  | `nav.css`      ← дорожка A
   | плитки, раздел, главная                | `catalog.css`  ← дорожка B
   | карточка сорта, галерея, переключатель  | `product.css`  ← дорожка C

   ⚠️ Классы `.availability`, `.availability--none`, `.availability--preorder` и `.zvonok` остаются ЗДЕСЬ,
   хотя ими пользуются и раздел, и карточка: они про одно и то же состояние товара в двух
   местах сайта, и разъехавшись, начали бы означать разное одним словом. Дорожки их
   используют, но не переопределяют. */

/* 🔴 СПРЯТАННОЕ АТРИБУТОМ `hidden` СПРЯТАНО ВСЕГДА. Правило стоит первым и с `!important`,
   и это единственное место во всех пяти файлах стилей, где `!important` оправдан.

   ⚠️ Повод — блокер, найденный общим ревью 31.07.2026, и он не про вёрстку. Браузер прячет
   `hidden` своим правилом `[hidden] { display: none }`, но ЛЮБОЕ правило автора бьёт правило
   браузера — по происхождению, а не по весу селектора. Достаточно объявить элементу `display`,
   и `hidden` перестаёт работать МОЛЧА.

   Цена этого в куске была такой: скрипт прятал блок кнопки «в корзину» при переходе на снятый
   с продажи размер (`product.js`) — блок не прятался, а адрес в кнопке уже был подменён
   на снятый. **Снятое с продажи уезжало в корзину и в заявку.** Сервер это правило исполняет
   (`views._chosen_block`), скрипт исполнить не мог.

   🔴 Почему правило общее, а не две заплатки по местам. Класс встречался в ДВУХ местах —
   `.deystviya` (страница сорта) и `.header__counter` (счётчик корзины на каждой странице,
   он висел пустой таблеткой на шапке при пустой корзине). Починить оба поимённо значило бы
   завести список, который стареет на следующем куске: третий элемент с `display` и `hidden`
   сломается так же и так же молча (🅰️4-1а, шаг 5 — сплошной проход вместо перечня).

   ⚠️ Тестами это не ловится по устройству: они читают разметку, отданную сервером, а поломка
   живёт в браузере после клика. Поэтому защита стоит в самом оформлении. */
[hidden] { display: none !important; }

/* 🔴 ПОЛЯ ВХОДЯТ В ЗАДАННЫЙ РАЗМЕР, А НЕ ПРИБАВЛЯЮТСЯ К НЕМУ. Спецификация v8, пункт 1.

   До 04.08.2026 свойства `box-sizing` в проекте не было ни разу, и работало умолчание
   браузера `content-box`: заданная ширина и высота считаются БЕЗ полей и рамки, а поля
   прибавляются сверх. Отсюда жалоба Кирилла «все очень крупное при 100%» — она оказалась
   арифметикой, а не вкусом:

       задано:      min-height 820 + поле сверху 128 + поле снизу 128
       получилось:  1076 точек в окне высотой 900  →  первый экран занимает 120% окна

   То же самое ломало плитку без снимка (заглушка вылезала за край на 1,8rem) и полосу
   первого экрана. Оба места чинились поимённо, оба лечения оставляли класс живым.

   ⚠️ Правило намеренно сплошное, а не по списку элементов. Список стареет на следующем
   куске: новый блок с полями и заданной шириной сломается так же и так же молча.
   Так же чинилось `[hidden]` выше — по той же причине.

   ⚠️ Числа отступов, набранные под старое поведение, после этой правки означают другое.
   Разбор расхождений — в снимках до и после, `tools/zamer/design-scale-shots.py`. */
*, *::before, *::after { box-sizing: border-box; }

/* 🔴 ПОДВАЛ ПРИЖАТ К НИЗУ ОКНА НА КОРОТКИХ СТРАНИЦАХ. Правка Кирилла по стенду 08.08.2026:
   «нижняя полоса поднялась наверх, а вместе с ней и текст нижний поднялся».

   Замер, объясняющий, что он увидел: страница контактов после снятия двух абзацев стала
   короче на 107 точек, и подвал вместе с линией уехал вверх по экрану — сам подвал
   не двигался, у него по-прежнему поля 32 точки, а линия стоит вплотную к концу `main`.
   На широком мониторе (2540×1300) короткая страница помещается в окно целиком, и подвал
   оказывается посреди экрана, а под ним остаётся пустое поле.

   Лечится это у подвала, а не отступом: отступ на длинных страницах дал бы дыру.
   Правило стоит ниже, у самого подвала (`.footer`).

   ⛔ ЗДЕСЬ БЫЛ `display: flex` У ТЕЛА СТРАНИЦЫ — классическая раскладка «подвал внизу»,
   и она у нас ЛОМАЕТ ГЛАВНУЮ. Замер сторожа вида сразу после правки: страница шире окна
   на 794 точки на телефоне и на 364 на планшете. Причина в том, что у детей flex-контейнера
   наименьшая ширина считается по содержимому, и сетка плиток перестала сжиматься.
   Поймал сторож, а не человек, — и ровно за этим он и написан. */
body {
  margin: 0;
  font-family: var(--shrift-teksta);
  font-size: 17px;
  line-height: 1.5;
  color: var(--tekst);
  background: var(--fon);
}

/* ══ ЖИВОЙ ФОН: ОДИН ЗАКРЕПЛЁННЫЙ СЛОЙ НА ВСЮ СТРАНИЦУ ═══════════════════════
   Спецификация v10, раздел 4. Решение Кирилла 04.08.2026 про видео, дословно:
   «давай пока с ним».

   🔴 ЗАЧЕМ ЭТО ВООБЩЕ ПЕРЕДЕЛЫВАЛОСЬ. До сегодня фонов было четыре: снимок в первом
   экране, заливка ниже, своя текстура у полосы, снова заливка. Стык между ними видно
   глазом, и Кирилл назвал это первым пунктом разбора десятого варианта. Теперь фон
   ОДИН, он закреплён за окном, и каждый раздел страницы стоит на нём же — поэтому
   стыкам взяться неоткуда.

   ⛔ ОТСЮДА ЗАПРЕТ, КОТОРЫЙ ДЕЙСТВУЕТ НА ВСЕ ФАЙЛЫ ДОРОЖЕК: ни одной сплошной заливки
   от края до края. Раздел — это вуаль или стекло, сквозь которое видно тот же фон.
   Залей один раздел наглухо, и вернётся ровно тот стык, ради снятия которого всё это
   и переделано.

   🔴 ПОРЯДОК СЛОЁВ НЕСУЩИЙ, снизу вверх: видео → ПТИЦЫ → передний план с елями →
   вуаль → солнце → лучи. Задан он порядком узлов в разметке, а не числами `z-index`:
   шесть чисел разъехались бы с разметкой при первой же вставке нового слоя.

   ⚠️ Птицы стоят между видео и передним планом не для красоты: так они залетают ЗА ели,
   а вуаль и солнце ложатся на них так же, как на весь кадр. Подними их выше — птица
   поедет поверх крон и мимо дымки, то есть станет наклейкой на стекле.

   ⚠️ `z-index: -1` у обёртки — то единственное число, которое здесь нужно: оно уводит
   весь фон под содержимое страницы разом. Шапка стоит на 8 и остаётся выше. */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
  /* Геометрия маски крон на птицах: те же cover и scale(1.03), что у `.backdrop__video`. */
  --mask-w: max(103vw, calc(103vh * 16 / 9));
  --mask-h: max(calc(103vw * 9 / 16), 103vh);
}

.backdrop > * { position: absolute; inset: 0; }

/* ⛔ СВОЕЙ АНИМАЦИИ У ВИДЕО НЕТ. Здесь стояло медленное «дыхание» масштаба, и вместе
   с уводом камеры в самом ролике оно давало то, что Кирилл назвал землетрясением:
   «фон просто хуярит влево-вправо». Движение должно быть только в кадре — ветер
   и туман, — а рамка обязана стоять.

   `scale(1.03)` — не движение, а постоянная поправка: она прячет кромку кадра,
   которая иначе видна при обрезке по высоте окна. */
/* 🔴🔴 ЗДЕСЬ БОЛЬШЕ НЕ ПОДБИРАЮТ ЯРКОСТЬ ЧИСЛАМИ, И ЭТО ГЛАВНОЕ, ЧТО НАДО ЗНАТЬ.
   Стояло `brightness(.40) contrast(.86)`, до того `.43`/`1.20`, до того `.41`/`.86`,
   `.355`/`.875`. Пять подборов за трое суток, каждый по жалобе Кирилла на темноту,
   и последняя жалоба 06.08.2026 — та же самая: «при светлой комнате где стоит монитор
   вообще не видно фона нормально».

   Замер объяснил, почему подборы не помогали. `brightness()` по спецификации — «linear
   multiplier», множитель на всю шкалу разом. Он опускает тени и света на одну и ту же
   долю, и расстояния между соседними тонами внутри хвои и травы схлопываются вместе
   со всем остальным. Шаги светлоты внутри картинки в светлой комнате, ΔL* (единица —
   предел, ниже которого два тона сливаются в один): 0,28 · 0,64 · 2,83 · 8,53. Два шага
   из четырёх были НЕРАЗЛИЧИМЫ, то есть тёмной половины кадра на экране не было вовсе.

   ⛔ И ЭТО НЕ ЧИНИТСЯ ЧИСЛАМИ В CSS НИКАКИМИ. `brightness(k) contrast(c)` даёт прямую
   `вход·k·c + 127,5·(1−c)`; слой `mix-blend-mode: screen` поверх — тоже прямую; прямая
   поверх прямой остаётся прямой. Перебор 70 наклонов × 30 сдвигов × 5 плотностей ореола
   дал в лучшем случае слабейший шаг 0,57 — по-прежнему ниже порога различимости.
   Решения в семье прямых не существует. Нужна кривая, а кривой у коротких фильтров нет.

   🔴 ПОЭТОМУ КРИВАЯ ЛЕЖИТ В САМОМ РОЛИКЕ, а здесь остался только уровень.
   Отменено вечером того же дня: подъём теней на ролике, сжатом до 1,1 Мбит/с, вытащил
   наверх блочность вместо фактуры, и Кирилл забраковал результат. Кадр переснят утренним
   (10:30), ему подъём теней не нужен вовсе. Кривой в файле нет и не будет.

   Второй путь — `feComponentTransfer` через `filter: url(#…)` — отвергнут не по вкусу:
   он пересчитывался бы на каждом кадре видео во весь экран у каждого посетителя,
   а попадание SVG-фильтра на видеокарту в Chrome не гарантировано и зависит от пути
   отрисовки. Для фонового ролика отрасль правит файл, а не браузер.

   ⛔ `contrast()` УБРАН СОВСЕМ. Он стоял здесь как самодельный подъём теней — сжимал
   шкалу к середине, чтобы низ не упирался в ноль. Кривая делает ровно это, и делает
   правильно: подъём теней у неё зависит от самой тени, а не прибавляется всем поровну.
   Вернёшь `contrast()` поверх кривой — получишь двойную обработку и молочный кадр.

   🔴 `--svet-fona` СТОИТ ТОЛЬКО У `.backdrop__video`. Слой `.backdrop__front` убран
   11.08.2026 — статичная копия крон смазывала картину. Разбор самого уровня — над
   `--svet-fona` в `tokens.css`. */
.backdrop__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.03);
  filter: var(--svet-fona);
}

/* 🔴 ПЕРЕДНИЙ ПЛАН: ЕЛИ ПОВЕРХ ПТИЦ. Правка Кирилла 05.08.2026: «хочу что бы птицы
   залетали за елки, то есть елки будут слоем выше чем птицы… а то щас птицы поверх
   елок летят, странно смотрится. Перспективы ведь нету».

   Отраслевая классика трёх слоёв: задний фон, объекты между, вырезанный передний план
   картинкой с прозрачностью сверху. Кроны вырезаны из кадра самого ролика
   (`tools/birds/front_layer.py`), поэтому совпадают с ним точка в точку.

   🔴 ГЕОМЕТРИЯ ОБЯЗАНА СОВПАДАТЬ С ВИДЕО ДО ТОЧКИ: и `cover`, и `scale(1.03)` здесь
   ровно те же, что у `.backdrop__video`. Разойдись хоть одно — кроны сдвинутся
   относительно своего же продолжения в кадре, и вместо глубины получится двоение.

   🔴 ПОПРАВКА ЯРКОСТИ ТОЖЕ ТА ЖЕ, И ТЕПЕРЬ ОНА БУКВАЛЬНО ТА ЖЕ ЗАПИСЬ — `--svet-fona`.
   Слой вырезается из кадра ролика, а ролик на странице притушен; без одинакового
   фильтра крона светилась бы поверх собственной тени в фоне.

   ⛔ И САМ ФАЙЛ СЛОЯ ОБЯЗАН БЫТЬ ОТ ТОГО ЖЕ РОЛИКА. `backdrop-front.webp` режется
   из кадра `background.mp4` — значит после каждой замены ролика слой надо пересобрать:

       python tools/birds/front_layer.py

   Замер после пересборки 06.08.2026: геометрия выреза не поехала (доля кроны 10,98 →
   11,13 %, плотность по высоте совпала до сотых), яркость кроны в файле 47,2 → 102,3 —
   ровно как в ролике. Пороги вырезки в `front_layer.py` берутся из показателя кривой,
   а не числами, поэтому сами приезжают за ней. */

/* Вуаль поверх видео: сверху прозрачнее, ниже плотнее. Без неё светлый текст ложится
   на светлый туман кадра и не читается вовсе — плотность подобрана по снимку. */
.backdrop__veil { background: var(--vual); }

/* Солнце — тёплое пятно за левой сосной, оно же вершина лучей. Не на весь слой,
   а своим размером, поэтому у него свои координаты.

   ⚠️ КЛАСС НАЗЫВАЕТСЯ `glow`, А НЕ `sun`, И ЭТО НЕ ВКУС. Слово `sun` — значение поля
   «свет» в базе (`light="sun"`), и проверка `test_product_card.py` следит, чтобы ни одно
   значение из базы не выехало на страницу ни одним написанием: она ищет подстроку `sun`
   во всём теле ответа. Класс с таким именем ронял её на исправной странице карточки
   товара — красный на здоровом перестают читать.

   🔴 ЧИСЛА СЧИТАЮТСЯ ОТ СЕРЕДИНЫ ПЯТНА, ПОЭТОМУ ЗДЕСЬ `calc`. Замеренная точка солнца
   в кадре — 4,5 % по ширине окна и 38 % по высоте; коробка квадратная, 68vw, значит
   до её левого верхнего угла надо отнять половину, 34vw. Запиши `inset: 38% auto auto
   4.5%` — и в эту точку попадёт УГОЛ пятна, а его середина уедет вправо и вниз на треть
   экрана. Ровно так солнце и разъехалось с лучами в прежней редакции.

   ⚠️ Размер в `vw`, а не в точках: у пятна в 520 точек на широком мониторе доля экрана
   вдвое меньше, чем на ноутбуке, и рассвет из общего света превращается в фонарик. */
/* 🔴 СВЕЧЕНИЕ УБРАНО ОТ ЛЕВОГО КРАЯ 12.08.2026. Кирилл увидел его глазами: «вот тут светлый
   полукруг слева остался, сделай его таким же по затемнению, как остальное».

   Пятно света рисовалось у левого края с тех пор, когда там ничего не лежало. Теперь там
   стоит текст первого экрана и зона затемнения, и пятно спорит с ними: замер 12.08.2026 дал
   в этом месте яркость 63,5 против 19,4 при снятом свечении — втрое светлее соседнего фона.

   Пятно не удалено, а сдвинуто вправо и вниз, где оно и работает по замыслу — подсвечивает
   туман над дальним лесом. Размер оставлен прежним. */
.backdrop__glow {
  inset: calc(46% - 34vw) auto auto calc(38% - 34vw);
  width: 68vw;
  height: 68vw;
  background: var(--solnce);
  animation: glow-breathes 13s ease-in-out infinite;
}

/* Дыхание солнца: было 7 с при размахе масштаба 1,12 — на пятне во весь экран это
   читается как пульс лампы. Настоящий свет сквозь туман меняется медленнее и слабее. */
@keyframes glow-breathes {
  0%, 100% { opacity: .84; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.05); }
}

/* Лучи выходят за края окна на десятую долю: иначе их поворот открывал бы пустые углы.
   Из-за этого координаты вершины ЗДЕСЬ ДРУГИЕ, чем у солнца, хотя точка одна и та же:
   коробка слоя шире окна в 1,2 раза и начинается на 10 % левее его.

       доля окна p  →  доля коробки (p + 10) / 1,2
       4,5 % → 12,1 %        38 % → 40 %

   ⛔ Эти же 12,1 % и 40 % стоят в трёх местах: в вершине конического градиента
   (`--luchi`), в середине маски (`--zatuhanie-luchey`) и в `transform-origin` ниже.
   Первые два лежат в `tokens.css`, третье здесь — так требует сторож цветов: он не пускает
   в файлы дорожек ни одной цветовой функции, а маска записана именно такой функцией.
   Разойдись хоть одно из трёх — лучи поедут мимо солнца, а на повороте ещё и поплывут
   относительно него.

   ⚠️ И в этом пояснении её тоже нельзя назвать по имени: сторож цветов читает файл СЫРЫМ,
   комментарии он не вырезает. Здесь на этом уже покраснел прогон.

   🔴 МАСКА — ЭТО ЛЕЧЕНИЕ «ПРЯМОУГОЛЬНОГО ТОЛСТОГО ЛУЧА»; чем именно она его лечит,
   разобрано над `--zatuhanie-luchey` в `tokens.css`. */
/* ⚠️ Прозрачность поднята .49 → .58 вместе с осветлением фона 06.08.2026 — по той же
   причине, что и доли солнца: луч виден разницей с небом, а небо стало светлее.
   Разбор и числа — над `--solnce` в `tokens.css`. */
.backdrop__rays {
  inset: -10%;
  opacity: .58;
  background: var(--luchi);
  -webkit-mask-image: var(--zatuhanie-luchey);
  mask-image: var(--zatuhanie-luchey);
  transform-origin: 12.1% 40%;
  animation: rays-walk 17s ease-in-out infinite alternate;
}

/* 🔴 ПОВОРОТ ВОКРУГ СОЛНЦА, А НЕ ВОКРУГ СЕРЕДИНЫ ЭКРАНА, И БЕЗ СДВИГА. Здесь стояло
   `rotate(-1.8deg) translateY(1.2%)` при повороте вокруг середины слоя: вершина лучей
   лежит от неё почти в половине экрана, и каждый градус уводил её на десятки точек
   в сторону от неподвижного солнца. Плюс сдвиг уводил весь слой вниз. Кирилл о том,
   что получилось: «просто мистические три луча двигаются вправо-влево».

   Теперь ось поворота стоит в самой вершине: солнце не двигается вовсе, а веер лучей
   медленно ведёт — так, как ведёт настоящие лучи движущийся туман. Размах уменьшен
   вчетверо: при длине луча во весь экран даже градус на конце виден. */
@keyframes rays-walk {
  from { transform: rotate(-.7deg); }
  to { transform: rotate(.9deg); }
}

/* ══ ТРИ ПТИЦЫ НА ФОНЕ ═══════════════════════════════════════════════════════
   Правка Кирилла 05.08.2026, дословно: «ХОЧУ ТРИ ПТИЧКИ (например, Синицы)… первая
   птичка просто летает по воздуху и улетает за елку, потом влетая с другой стороны
   экрана. вторая птичка летит к солнышку вверх, постепенно удаляясь в дали и пропадая.
   Потом прилетает с противоположной стороны экрана. третья птичка — летает с ветки
   на ветку, с паузами… важно еще что бы птички стали дополнением, и не мозолили глаза
   и не бесили. А наоборот умиляли».

   🔴🔴 ЗДЕСЬ НЕТ НИ ОДНОЙ ТРАЕКТОРИИ, И ЭТО САМОЕ ВАЖНОЕ В ЭТОМ ФАЙЛЕ. Прежняя редакция
   везла три набора ключевых кадров: птица ехала по процентам экрана, которые я расставил
   на глаз. Кирилл забраковал её со словами «она просто летает в одном положении,
   мультяшная», а до того — «это мультяшная анимация, при чем убогая» и «там не птицы,
   там приведения какие-то». Три попытки подряд, и причина у всех одна: движение было
   ВЫДУМАНО, а не снято.

   Теперь птица летит внутри своего ролика — так, как летела перед камерой. Взмахи,
   провалы между ними, крен на повороте и переменная скорость взяты из съёмки целиком,
   и ни одна из этих величин здесь не задаётся. Стили решают только, какого размера
   показать ролик; когда и где его показать — `birds.js`.

   🔴 ЧТО ЭТО СТОИТ СЕРВЕРУ: ТРИ ФАЙЛА ПО ОДНОМУ РАЗУ. Ролики весят 123 КБ на все три
   и лежат в статике; браузер берёт их однажды и держит в своём хранилище. Требование
   «сайт должен работать идеально даже при 1000 клиентах» этим не задевается: тысяча
   клиентов — нагрузка на сервер, а показ идёт в браузере каждого, у себя.

   🔴 ЧТО ЭТО СТОИТ БРАУЗЕРУ. Между вылетами ролик СТОИТ, а не крутится: `birds.js` его
   останавливает, и декодировать нечего. Во время вылета работает один маленький ролик
   на аппаратном декодере, а двигаются только `transform` и `opacity` — те два свойства,
   которые браузер отдаёт видеокарте. Замер — `tools/zamer/frame-budget.py` с замедлением
   процессора вчетверо, с птицами и без.

   ⚠️ «ЗА ЕЛКУ» — ЭТО УХОД ЗА КРАЙ СВОЕГО РОЛИКА. Ель нарисована ВНУТРИ фонового видео,
   значит поставить птицу под неё нельзя ничем: слой ролика цельный. Птица улетает за
   границу кадра и гаснет, а следующий вылет начинается с другого края экрана —
   то самое «влетая с другой стороны», о котором просил Кирилл. */
/* 🔴 ПТИЦА — СЛОЙ ВО ВСЁ ОКНО, А НЕ ПРЕДМЕТ В УГЛУ. Переделано 05.08.2026 по разбору
   Кирилла: «влетает в пустоту и пропадает», «то появляется то исчезает», «появляется
   РЕДКО… мало времени видна на экране».

   Прежде ролик был шириной 190 точек, и птица долетала до его границы на середине
   пути — обрезалась о невидимую рамку посреди экрана. Правкой анимации это не лечится:
   полёт физически не мог быть длиннее рамки. Замер того ролика: птица была в кадре
   на 38 кадрах из 54, то есть треть вылета играла пустота.

   Теперь ролик растянут на всё окно, и весь путь от края до края лежит внутри него.
   Птица входит из-за края экрана и уходит за край; обрезаться ей негде. Замер нового
   ролика: пустых кадров в середине полёта — ноль.

   ⚠️ `object-fit: cover` обязателен. Кадр снят в отношении 16:9, а окна бывают любые;
   без него птица растянулась бы вместе с кадром и стала бы плоской. */
/* 🔴 РОЛИК — ПОЛОСА, А НЕ ВЕСЬ ЭКРАН, И ЭТО НЕ ВЁРСТКА, А ПРОИЗВОДИТЕЛЬНОСТЬ.
   Жалоба Кирилла 05.08.2026: «они чуть тормозят, как будто не фпс, а фризы…
   птицы сами, иногда».

   Замер при замедлении процессора вчетверо подтвердил: с птицей 13 кадров
   длиннее 100 мс, худший 292 мс; без птиц — ни одного.

   Причина в устройстве прозрачного видео, а не в птице. VP9 держит альфу
   ОТДЕЛЬНЫМ потоком, и аппаратные декодеры его не умеют ни у NVIDIA, ни
   у Intel: браузер разжимает такой ролик процессором, целиком, каждый кадр.
   У полноэкранного ролика это два миллиона точек, из которых на птицу
   приходится тридцать.

   Поэтому кадр обрезан до полосы, в которой птица летает:

       было  1920 × 1080 = 2 073 600 точек на кадр
       стало 1280 ×  158 =   202 240   (across, вдесятеро меньше)

   ⚠️ Высота НЕ задаётся: `height: auto` держит пропорции ролика, а место
   на экране задаёт `top` у каждой повадки. Поставь высоту в процентах —
   и полоса растянется, а птица в ней сплющится.

   ⛔ Фильтра здесь больше нет. `brightness`/`saturate` пересчитываются
   на каждый кадр видео; окрас теперь запечён в самом ролике при отрисовке. */
.bird {
  inset: auto auto auto 0;
  width: 100%;
  height: auto;
  opacity: 0;
  will-change: opacity;
  /* Плавный вход и уход: резкое включение читается как мигание, а не как прилёт. */
  transition: opacity .9s linear;
  pointer-events: none;
  /* 🔴 МАСКА НЕБА, А НЕ СЛОЙ ПОВЕРХ ВИДЕО. Кирилл 11.08.2026: статичная копия крон
     смазывала ролик. Маска прячет птицу за ветками, видео не трогаем. Картинка —
     `tools/birds/bird_mask.py`, геометрия совпадает с фоновым роликом. */
  -webkit-mask-image: url("img/backdrop-bird-mask.webp");
  mask-image: url("img/backdrop-bird-mask.webp");
  -webkit-mask-size: var(--mask-w) var(--mask-h);
  mask-size: var(--mask-w) var(--mask-h);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: calc((100vw - var(--mask-w)) / 2)
    calc((100vh - var(--mask-h)) / 2 - var(--mask-shift));
  mask-position: calc((100vw - var(--mask-w)) / 2)
    calc((100vh - var(--mask-h)) / 2 - var(--mask-shift));
}

/* ⚠️ Числа — это центры полос из отрисовки, пересчитанные в положение на экране.
   Меняешь траекторию в `render_bird.html` — пересчитывай и их, иначе птица
   поедет по экрану выше или ниже своего неба. */
.bird--across { top: 22%; --mask-shift: 22vh; }
.bird--flit { top: 31%; --mask-shift: 31vh; }
.bird--rising { top: 13.5%; --mask-shift: 13.5vh; }

.bird.is-flying { opacity: 1; }

/* ⚠️ На узком экране птиц нет. Дело не в кадрах, а в размере: на телефоне окно шириной
   в четыре сотни точек, и предмет в полсотни занимает в нём заметную долю — вместо
   «дополнения» получается мельтешение поперёк текста, то есть ровно то, что запрещено. */
@media (max-width: 48rem) {
  .bird { display: none; }
}

/* 🔴 ЧЕЛОВЕК, ПОПРОСИВШИЙ СИСТЕМУ УБРАТЬ ДВИЖЕНИЕ, ПОЛУЧАЕТ НЕПОДВИЖНУЮ КАРТИНКУ.
   Это не забота о вкусах: движущийся фон вызывает тошноту у людей с вестибулярными
   нарушениями, и просьба приходит настройкой системы, а не кнопкой на сайте.
   Видео при этом останавливает скрипт — атрибутом это не выражается. */
@media (prefers-reduced-motion: reduce) {
  .backdrop__glow, .backdrop__rays { animation: none; }
  /* Птиц человек, попросивший убрать движение, не получает вовсе: неподвижная птица,
     повисшая в воздухе посреди экрана, — это не «спокойнее», это непонятно. */
  .bird { display: none; }
}

/* Заголовки антиквой — так набраны и палитра, и примеры доски (9А.0в). Правило одно на все
   уровни: разнобой начертаний внутри страницы читается как разные разделы сайта.

   🔴 МЕЖСТРОЧНЫЙ СЧИТАЕТСЯ ОТ КЕГЛЯ, А НЕ НАЗНАЧАЕТСЯ ЧИСЛОМ. Спецификация v8, пункт 2.

   Замер 04.08.2026 живым браузером, три страницы, все заголовки подряд: у ВОСЬМИ из
   четырнадцати межстрочный был 1,5 — они наследовали его от `body`, где он задан для
   обычного текста. На кегле 32,8 это разрыв между строками в полсотни точек, и заголовок
   в три строки съедает экран.

   Почему одно правило, а не восемь правок по местам: один и тот же тег `h2` набран на сайте
   шестью разными кеглями (40, 32,8, 25,5, 21,6, 17,6, 16,8) — назначить ему одно число
   значит промахнуться пять раз из шести. Список кеглей устареет на следующем блоке.

   `calc(1em + 0.3rem)` держит постоянную прибавку в 4,8 точки к росту букв, и коэффициент
   выходит сам, тем плотнее, чем крупнее кегль — ровно как в восьми из девяти разобранных
   дизайн-систем:

       74,9 px → 1,06      32,8 px → 1,15      21,6 px → 1,22
       64   px → 1,08      25,5 px → 1,19      17,6 px → 1,27

   ⚠️ `1em` здесь — кегль самого заголовка, а `0.3rem` — доля корневого кегля, она одинакова
   для всех. Заменить `rem` на `em` нельзя: прибавка станет пропорциональной, и весь смысл
   правила исчезнет.

   Вес 600 вместо 700 — тоже по замеру: из девяти систем ни одна не набирает крупные
   заголовки самым жирным начертанием, крупные буквы и так тяжелы площадью. Обе оси наших
   шрифтов идут от 400 до 700, значит 600 существует и подделываться браузером не будет. */
h1, h2, h3 {
  font-family: var(--shrift-zagolovka);
  font-weight: 600;
  line-height: calc(1em + 0.3rem);
}

/* 🔴 КЕГЛЬ ЗАГОЛОВКА НАЗНАЧАЕМ МЫ, А НЕ БРАУЗЕР. Спецификация v8, пункт 3.

   Замер 04.08.2026 поймал заголовки «Разделы» и «Растения» на странице каталога с кеглем
   25,5 точки. Такого числа нет ни в одном нашем файле: это умолчание браузера для `h2` —
   полтора кегля основного текста, 1,5 × 17. То есть размер заголовка на живом сайте
   определял браузер.

   Ступени ниже — низ шкалы для заголовков без своего правила. Места, где заголовок работает
   витриной или именем страницы, перебивают их своим значением, и это видно в их файлах. */
h1 { font-size: var(--t-xxl); }
h2 { font-size: var(--t-xl); }
h3 { font-size: var(--t-l); }

/* 🔴 СТРОКА ТЕКСТА НЕ ДЛИННЕЕ 68 ЗНАКОВ. Спецификация v8, пункт 6.

   На длинной строке глаз теряет начало следующей: он возвращается влево и попадает
   не на ту строку. Замер 04.08.2026 нашёл на главной абзац в 129 знаков — почти вдвое
   длиннее предела.

   ⚠️ Правило сплошное и намеренно не перечисляет классы: длинные абзацы нашлись в четырёх
   разных местах (`.blok__proekt-tekst`, `.page`, `.description`, `.encyclopedia`), и пятое
   появится на следующей странице. Абзацам в узких колонках правило не мешает — там ширина
   и так меньше предела, а `max-width` только ограничивает сверху. */
p { max-width: var(--shirina-stroki); }

/* 🔴 ПОДЧЁРКИВАНИЙ НА САЙТЕ НЕТ НИГДЕ. Правка Кирилла 01.08.2026, дословно: «нижние
   подчеркивания все убираем в визуале сразу» (п. 2 его списка), и второй раз о том же месте
   отдельно — «деревья с нижним подчеркиванием» (п. 11, про путь по каталогу на странице сорта).

   🔴 Правило одно и общее, а не по местам, ровно потому, что второй пункт и был вторым местом
   того же класса (🅰️4-1а, шаг 5). Список подчёркнутых мест устарел бы на следующей странице:
   любая новая ссылка получила бы подчёркивание обратно, и никто бы этого не заметил, кроме
   Кирилла — как и вышло дважды.

   ⚠️ У ссылки остаётся ДВА признака вместо трёх: цвет и отклик на наведение. Отклик заведён
   здесь же и не для красоты — сняв подчёркивание, мы забрали у ссылки половину её опознавания,
   и без ответа на курсор она стала бы неотличима от крашеного текста. */
a { color: var(--akcent); text-decoration: none; }
a:hover { color: var(--akcent-navedenie); }

main {
  /* Ширина текста ограничена: строка длиной во весь монитор не читается. Каталог шире —
     свою ширину он задаёт сам, одной строкой `--width-page` в своём файле стилей
     (`card.css`, `product.css`, `projects.css`). По умолчанию колонка текстовая. */
  max-width: var(--width-page);
  margin: 0 auto;
  padding: 0 1rem 3rem;
}

/* 🔴 ЯКОРЬ НЕ ПРЯЧЕТСЯ ПОД ЗАКРЕПЛЁННОЙ ШАПКОЙ. Волна 3 закрепила полосу наверху экрана,
   и с этого дня браузер, прыгая по ссылке `#katalog`, ставил бы цель ровно под ней — то есть
   прятал бы то, ради чего человек нажал. Лечится У ЦЕЛИ (`scroll-margin-top`), а не отступом
   сверху: отступ сдвинул бы блок на странице всегда, а поправка нужна только в момент прыжка.

   🔴 Правило СПЛОШНОЕ — любому узлу с именем, а не перечню якорей (🅰️4-1а, шаг 5). Сегодня
   якорь на сайте один («Смотреть каталог» → блок разделов главной), и список из одной строки
   устарел бы на следующем куске: новый якорь уехал бы под шапку МОЛЧА, и заметил бы это
   Кирилл на живом сайте, а не мы.

   ⚠️ Величина взята с запасом над высотой шапки (предел 80 точек, `tools/zamer/site-appearance.py`):
   заголовок цели должен оказаться ПОД полосой, а не вплотную к её нижнему краю. */
[id] { scroll-margin-top: 6rem; }

/* ── Шапка ───────────────────────────────────────────────────────────────── */
/* 🔴 Тёмная полоса во всю ширину — главный опознавательный знак гаммы (9А.0в): у всех примеров
   доски шапка контрастная, а не белая с серой линией. Внутри неё ссылки перекрашиваются:
   цвет ссылок по умолчанию — тёмно-зелёный, а на тёмно-зелёном фоне он невидим.

   🔴 ЗАКРЕПЛЕНА `sticky`, А НЕ `fixed`, и это требование спецификации волны 3 (Р-2 п. 1),
   а не вкус. `fixed` вынимает полосу из потока страницы: содержимое начинается ПОД её
   местом, то есть первый экран каждой страницы сайта уезжает под шапку и его верх исчезает.
   `sticky` своё место в потоке сохраняет и всплывает только при прокрутке.

   🔴 СЛОЙ (`z-index`) ВЫШЕ ВСЕГО, ЧТО ЕСТЬ НА СТРАНИЦАХ, И НИЖЕ УВЕЛИЧЕННОГО СНИМКА.
   Числа-соседи, с которыми он сравнивается, живут в `product.css`: прилипающая колонка
   и раскрытый список размеров стоят на слое 5, увеличение снимка во весь экран — на 10.
   Шапка обязана перекрывать первые (иначе список размеров всплывёт поверх неё — ровно
   то наслоение, которое Кирилл уже ловил глазами, правка № 16) и обязана уходить под второе
   (полный экран поверх всего на то и полный). Сверяется числами в `tests/test_frame.py`.

   ⚠️ Закреплённая полоса создаёт слой для всего, что внутри неё, поэтому выпадающему меню
   свой большой `z-index` не нужен: оно всплывает вместе с шапкой.

   🔴 ВЫСОТА — ЗАМЕРЯЕМОЕ ЧИСЛО (≤ 80 точек, `tools/zamer/site-appearance.py`). Поля уменьшены
   с `0.9rem` до `0.35rem`, а телефон и корзина набраны плотнее: до волны 3 шапка занимала
   84 точки, и с закреплением это стало платой на КАЖДОЙ прокрутке КАЖДОЙ страницы.

   ⚠️ Перенос на вторую строку разрешён и нужен: на узком экране пять вкладок в строку
   не помещаются по устройству. Замер требует одной строки только на мониторе — там перенос
   и означал бы, что шапка не помещается. */
/* ⚠️ ВЫРАВНИВАНИЕ ПО БАЗОВОЙ ЛИНИИ ПРОБОВАЛИ 05.08.2026 И ОТКАЗАЛИСЬ — ЗАМЕР ХУЖЕ.
   Правка Кирилла: «надпись Dervo и разделы сайта тоже на разном уровне находятся».

   Казалось, что глаз читает строку по линии букв, а не по серединам коробок, и `baseline`
   это починит. На деле стало хуже: «Корзина», телефон и «Кабинет» лежат внутри своих
   флексов рядом со значками, и базовую линию такой флекс берёт у ПЕРВОГО ребёнка — то есть
   у значка, а не у слова. Замер после правки: вкладки 11,1…32,1, правая группа 7,1…28,1 —
   разошлись на четыре точки вместо нуля.

   Настоящая причина расхождения оказалась другой и уже устранена: телефон был набран
   16 точками при 17 у всех соседей. После выравнивания кегля коробки текста совпали
   до десятой доли — 10,4…31,4 у вкладок, у корзины и у телефона.

   Имя сайта при этом выше и ниже соседей по-прежнему, и иначе быть не может: антиква
   в 21,6 точки против гротеска в 17. Совпадают их середины, а буквы у крупного кегля
   длиннее в обе стороны. */
.header {
  position: sticky;
  top: 0;
  z-index: 8;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.9rem;
  align-items: center;
  padding: 0.35rem 1.2rem;
  /* 🔴 ШАПКА СТАЛА СТЕКЛОМ, А НЕ ПОЛОСОЙ КРАСКИ. Спецификация v10, разделы 3 и 4.
     Сплошная заливка перерезала бы живой фон поперёк экрана — тот самый стык, ради
     снятия которого фон и переделан. Под полупрозрачной полосой видео продолжается.

     ⚠️ `backdrop-filter` — ЕДИНСТВЕННОЕ размытие на всём сайте, и это замеренный размен
     (спецификация v10, раздел 2, пункт 1): размытие браузер пересчитывает каждый кадр
     заново, 108 кадров в секунду против 135. Здесь оно окупается — без него сквозь
     полосу читалась бы движущаяся картинка, и текст шапки стал бы нечитаемым в момент,
     когда под ним проезжает светлый туман. Второго такого места быть не должно. */
  background: var(--fon-shapki);
  backdrop-filter: var(--steklo-blur-shapki);
  border-bottom: 1px solid var(--frame);
  color: var(--tekst);
  /* 🔴 ВСЯ ПОЛОСА — ЗАГОЛОВОЧНЫМ ШРИФТОМ, ТЕМ ЖЕ, ЧТО МАРКА НА ПЕРВОМ ЭКРАНЕ. Слово Кирилла
     12.08.2026: «шрифт ставь как у слова DERVO белое на главной, всем этим словам в шапке».

     До этого дня в полосе жили три шрифта разом: один у самой полосы, другой у вкладок
     и у меню каталога, а имя сайта было вовсе картинкой. Отсюда и бралось «всё криво
     и пляшет»: у разных шрифтов при одном кегле разная высота строчных и разная посадка
     на строке, и совпасть их коробки не могут никаким выравниванием.

     Шрифт задан ОДИН РАЗ здесь, всей полосе сразу. Отдельные объявления у вкладок и у меню
     сняты — стоя ниже по файлу, они перебивали бы это правило. */
  font-family: var(--shrift-zagolovka);
  /* 🔴 КЕГЛЬ ШАПКИ МЕЛЬЧЕ СТРАНИЧНОГО — 15 точек против 17. Правка Кирилла 07.08.2026,
     дословно: «шрифты на закрепе сверху чуть уменьши, слишком крупные буквы».

     Задан ОДИН РАЗ ЗДЕСЬ, всей полосе сразу, а не восемью правилами по надписям. Так он
     не может разъехаться: вкладки, «Корзина», телефон, «Кабинет» и подпись «Меню» берут
     его наследованием, и совпадение их коробок держится этим, а не совпадением восьми чисел.

     ⚠️ Ровно одно исключение — поле поиска, и оно вынужденное: браузер телефона приближает
     страницу при вводе, если шрифт поля мельче 16 точек. Разбор — у `.search__field`.

     ⚠️ Высота полосы от правки падает, а не растёт: она замеряемый предел (≤ 80 точек). */
  /* 🔴 С 12.08.2026 КЕГЛЬ ТЯНЕТСЯ ЗА ШИРИНОЙ ОКНА. Правка Кирилла: «увеличь в 2 раза буквы
     минимум», затем «делай не х2 а поменьше — 1.7».

     Постоянным числом это не задать, и вот почему. Замер того же дня при буквальном
     удвоении (кегль 30 точек): на 1920 полоса раздувается с 46 точек до 100, на 1440
     вкладки уходят в две строки. Высота полосы у нас замеряемый предел — не больше 80.

     Поэтому доля ширины окна с двумя упорами. Что получается: на мониторе Кирилла (2464)
     кегль 25,9 точки — ровно 1,7 от прежних 15; на 1920 — 20,2; на 1440 и уже — прежние 15,
     где больше и не влезает. Высота полосы по этой формуле: 54 · 48 · 46 · 46.

     ⚠️ Кегль по-прежнему задан ОДИН РАЗ здесь, всей полосе сразу: вкладки, «Корзина»,
     телефон, «Кабинет» и подпись «Меню» берут его наследованием, а логотип — долей от него
     (`em` у знака и слова), поэтому растёт вместе с соседями и не отстаёт. */
  font-size: clamp(0.9375rem, 1.05vw, 1.75rem);
  /* 🔴 МЕЖСТРОЧНЫЙ ИНТЕРВАЛ ТОЖЕ ЗАДАН ПОЛОСЕ ЦЕЛИКОМ, И ЭТО ПОЧИНКА «СЛОВА ПЛЯШУТ».
     Замер 07.08.2026 браузером, середины строк текста в шапке:

         вкладки, «Корзина», телефон   20,48
         «Кабинет»                     20,23

     Четверть точки — это мало, но причина у неё общая и умеет вырасти. Интервал у восьми
     надписей был набран восемью отдельными строками `line-height: 1.2`, а у «Кабинета» —
     не набран вовсе, и он наследовал страничные полтора. Каждая НОВАЯ надпись в полосе
     попадала бы в ту же яму: забыть одну строку из восьми легко, а увидеть четверть точки
     нельзя. Теперь интервал наследуется от полосы, и забыть его негде.

     ⚠️ Одно исключение — поле поиска: `font: inherit` в его правиле сбрасывает интервал
     обратно, поэтому там он набран своей строкой (разбор у `.search__field`). */
  line-height: 1.2;
  /* Небольшая разрядка. На тёмном фоне светлые буквы оптически слипаются, и ряд из восьми
     коротких слов читается плотной полосой; сотая доли эма разводит их, не двигая раскладку. */
  letter-spacing: .01em;
}

.header a { color: var(--tekst); }
/* 🔴 ОТКЛИК НА НАВЕДЕНИЕ — ПЕСОЧНЫЙ, И ТЕПЕРЬ ЭТО ПРАВДА. Здесь стояло ровно это объяснение
   («на тёмной полосе шапки отклик на наведение — песочный»), а код красил в ЗЕЛЁНЫЙ
   (`--akcent`). Комментарий, отрицающий код, хуже отсутствующего: следующее окно верит ему
   и «чинит» не то.

   Правится это вместе с требованием Кирилла 06.08.2026 по шапке — «Берем одинаковые буквы»:
   зелёных надписей в полосе не остаётся ни одной, ни в покое, ни под курсором. Зелёный
   на сайте означает ДЕЙСТВИЕ — кнопку, а переход по вкладке действием не является.
   Песочный здесь ровно в своей роли: тонкая деталь, а не заливка. */
.header a:hover { color: var(--akcent-detal); }

/* 🔴 ИМЯ САЙТА — ЛОГОТИП НАТАЛЬИ КАРТИНКАМИ, А НЕ НАДПИСЬ. Задача Кирилла 06.08.2026.
   Здесь стояло правило для слова `Dervo`: заголовочный шрифт, 1,35 рема, вес 700.

   🔴 ЭТИМ ЗАКРЫТА ЖАЛОБА «НАДПИСЬ DERVO И РАЗДЕЛЫ САЙТА НА РАЗНОМ УРОВНЕ» (05.08.2026)
   по её настоящей причине, а не поверх неё. Разбор выше объясняет: имя было антиквой
   в 21,6 точки среди гротеска в 17, и буквы крупного кегля длиннее в обе стороны — совпасть
   такие коробки не могут никак. Выравнивание по базовой линии тогда попробовали и откатили,
   потому что оно сделало хуже.

   Картинке высота задаётся числом, а не рисунком шрифта. Обе половины логотипа стоят
   на середине полосы вместе со всем остальным (`align-items: center` у `.header`),
   и «разного уровня» у них не бывает по устройству. */
.header__name {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  /* Гибкая раскладка обрезает переполнение хуже, чем блок: без этой строки длинный ряд
     вкладок мог бы сжать логотип по ширине и раздавить круглый знак в овал. */
  flex: 0 0 auto;
}

/* Знак и слово — две картинки с фиксированной высотой; ширину браузер берёт из соотношения
   в атрибутах разметки. Числа подобраны так, что высота прописных букв слова (≈13 точек)
   совпадает с высотой прописных у вкладок рядом: логотип чуть крупнее соседей, но не спорит
   с ними, как спорила прежняя антиква. */
/* 🔴 ЗНАК УМЕНЬШЕН НА 15 % И ЗАДАН ДОЛЕЙ КЕГЛЯ, А НЕ ТОЧКАМИ. Слово Кирилла 12.08.2026:
   «логотип и слово dervo в шапке уменьши на 15% примерно».

   1,73 эма — это те же 26 точек при прежнем кегле полосы 15, то есть ровно на 15 % меньше
   тридцати. Доля, а не число, потому что кегль полосы теперь тянется за шириной окна:
   поставь здесь точки — и на мониторе знак остался бы горошиной рядом с крупными
   вкладками, а на телефоне торчал бы над ними. */
.header__znak { height: 1.73em; width: auto; flex: 0 0 auto; }

/* 🔴 СЛОВО — НАСТОЯЩИЙ ТЕКСТ, А НЕ КАРТИНКА, И НАБРАНО ОНО ТЕМ ЖЕ ШРИФТОМ, ЧТО МАРКА
   НА ГЛАВНОЙ. Разбор — в шаблоне рядом с разметкой.

   Кегль подобран замером, а не расчётом: у картинки высота прописных была 13 точек,
   на 15 % меньше — 11, и столько давало 1,05 рема при прежнем кегле полосы. Записан он
   долей (1,12 эма) по той же причине, что у знака: полоса теперь тянется за шириной окна,
   и слово обязано ехать вместе с ней. Проверка — `tools/zamer/shapka-rovnaya.py`.
   Разрядка та же, что у марки первого экрана: без неё слово из пяти прописных читается
   плотным пятном.

   ⚠️ Правое отрицательное поле гасит разрядку ПОСЛЕДНЕЙ буквы — иначе между словом
   и первой вкладкой оказался бы лишний просвет в две десятых эма, и полоса выглядела бы
   сдвинутой. Тот же приём стоит у заголовка первого экрана. */
.header__slovo {
  flex: 0 0 auto;
  font-family: var(--shrift-zagolovka);
  font-size: 1.12em;
  font-weight: 500;
  letter-spacing: .2em;
  margin-right: -.2em;
  line-height: 1;
}

/* ⚠️ Наведение гасит подсветку логотипа, а не красит его: правило `.header a:hover` красит
   ТЕКСТ, а внутри логотипа текста нет вовсе — без этой строки клик по имени сайта
   не давал бы никакого отклика. */
.header__name:hover .header__znak,
.header__name:hover .header__slovo { opacity: .82; }

/* ── Вкладки шапки ───────────────────────────────────────────────────────── */
/* 🔴 ПЯТЬ ВКЛАДОК ОДНОЙ СТРОКОЙ — состав задан спецификацией волны 3 (Р-1). До неё сайт
   не имел ни одной страницы кроме каталога, и навигацией была полоса разделов ВТОРОЙ строкой
   под шапкой. Полосы больше нет: разделы выпадают под вкладкой «Каталог» (`nav.css`). */
.tabs { flex: 0 1 auto; }

.tabs__list {
  display: flex;
  flex-wrap: wrap;
  /* 🔴 ПРОМЕЖУТКА МЕЖДУ ПУНКТАМИ НЕТ, И ЭТО УСЛОВИЕ РОВНЫХ ПРОБЕЛОВ ВОКРУГ ТОЧКИ-РАЗДЕЛИТЕЛЯ.
     Кирилл просил точку «через пробел с обеих сторон». Пробелы дают боковые поля самих
     ссылок (`.tabs__link`), они одинаковые слева и справа. Добавь сюда ещё 0,2 рема —
     и они лягут ТОЛЬКО слева от точки, потому что точка стоит в начале следующего пункта:
     слева от неё оказались бы поле ссылки плюс промежуток, справа — одно поле. Так и было
     до 07.08.2026: 0,7 рема против 0,5. */
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Вкладка не сжимается: сжатая переносилась бы по буквам, и «Сотрудничество» встало бы
   в три строки. Переносится СПИСОК целиком, а не слово внутри пункта.

   ⚠️ Строчная раскладка внутри пункта обязательна, и без неё точка-разделитель ниже
   не работает вовсе: ссылка вкладки набрана `display: block`, поэтому в обычном пункте
   списка точка встала бы ОТДЕЛЬНОЙ СТРОКОЙ над словом. */
.tabs__item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}

/* 🔴 ТОЧКА МЕЖДУ СЛОВАМИ ШАПКИ — требование Кирилла 07.08.2026, дословно: «между вот этими
   словами в шапке поставь центральную точку везде через пробел с обех сторон (кроме
   последнего слова)».

   Разделитель принадлежит ПРОМЕЖУТКУ, а не слову, поэтому пишется от второго соседа
   (`+`), а не от каждого пункта: так точка стоит между словами и не появляется ни перед
   первым, ни после последнего. Правило «кроме последнего слова» выполняется устройством
   селектора, а не перечнем вкладок, — вкладок станет семь, и трогать здесь будет нечего.

   ⚠️ Пробелы вокруг точки не набраны знаками, и это не забывчивость: у ссылок вкладок
   свои боковые поля (`.tabs__link`), и набранный пробел прибавился бы к ним третьим
   зазором. Промежуток даёт то же самое и едет вместе с раскладкой на узком экране.

   ⛔ Разделитель не набирается в разметке: он оформление и ничего больше — диктору
   и роботу нейросети читать точку между пунктами меню незачем. */
.tabs__item + .tabs__item::before {
  content: "·";
  color: var(--tekst-tihiy);
}

/* 🔴 ВЕС 500, А НЕ 700. Правка Кирилла 05.08.2026: «что с шрифтами на верхней панели
   и с текстом? почему он такой неприятный, жирный?»

   Он про весь ряд сразу: жирными были ВСЕ надписи шапки — пять вкладок, «Корзина», телефон
   и «Кабинет», — то есть восемь слов подряд, набранных как заголовки. Полужирное начертание
   на мелком кегле съедает просветы внутри букв, и строка читается плотным пятном,
   а не словами.

   Пятьсот — не «тоньше ради тонкости»: это средний вес, при котором надпись остаётся
   уверенной на движущемся фоне, но перестаёт спорить с именем сайта. Имя остаётся на 700 —
   оно одно и обязано быть тяжелее того, что стоит рядом. */
/* 🔴 ПРОМЕЖУТКИ МЕЖДУ ВКЛАДКАМИ УВЕЛИЧЕНЫ В ПОЛТОРА РАЗА — 0,75 рема вместо 0,5. Слово
   Кирилла 12.08.2026: «между этими словами сделай расстояние больше в полтора раза,
   равномерно».

   Раздвигаются именно боковые поля ссылок, а не промежуток списка, и это не вкус: точка
   между вкладками стоит в начале следующего пункта, поэтому промежуток лёг бы ТОЛЬКО слева
   от неё, а справа осталось бы одно поле. Пробелы вокруг точки перестали бы быть равными —
   ровно то, что Кирилл ловил 07.08.2026.

   ⚠️ Шрифта здесь больше нет: он один на всю полосу и задан у `.header`. Пока объявление
   стояло тут, оно перебивало полосу по порядку в файле, и вкладки оставались гротеском. */
.tabs__link {
  display: block;
  padding: 0.35rem 0.75rem;
  font-weight: 500;
  white-space: nowrap;
}


/* 🔴 ПОДПИСЬ РАСКРЫТИЯ ДЛЯ ПАЛЬЦА. Это `label` к скрытой галочке, а не ссылка: нажатие
   по ней переключает галочку силами браузера, без единой строки кода. В мире мыши она
   не нужна и спрятана — там список выпадает по наведению. */
/* ⚠️ Цвет светлый, а не зелёный, — тем же решением 06.08.2026, что и названия разделов
   внутри выпадения («Берем одинаковые буквы»). Подпись стоит в одном ряду с вкладками
   и обязана читаться их частью, а не отдельным действием: зелёный на сайте означает
   действие, а раскрытие списка действием не является. */
.tabs__name {
  display: block;
  /* Поля те же, что у ссылки вкладки: подпись стоит в одном ряду с ними и обязана
     раздвигаться вместе с ними. Шрифт наследуется от полосы. */
  padding: 0.35rem 0.75rem;
  color: var(--tekst);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}

.tabs__name::after { content: " ▾"; color: var(--tekst-tihiy); }

/* 🔴 ГАЛОЧКИ, КОТОРЫМИ ОТКРЫВАЮТ ВКЛАДКИ И РАЗДЕЛЫ ПАЛЬЦЕМ. Спрятаны размером и прозрачностью,
   а НЕ `display: none` и не `visibility: hidden`: спрятанная любым из тех двух способов
   галочка выпадает из порядка обхода клавиатурой, и меню перестаёт открываться у человека
   без мыши — молча, как всегда бывает с недоступностью. Тот же приём и тот же довод, что
   у `.menu__toggle` в `nav.css`.

   `position: absolute` убирает их из потока: места в полосе под них не отводится. */
.header__toggle, .tabs__toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

/* Подпись «Меню» — вход во вкладки на телефоне. Обвод для клавиатуры обязателен обеим
   подписям: сами галочки невидимы, и без него человек, идущий по странице клавишей,
   видит, что список открылся, но не видит, на чём стоит. */
.header__toggle-name {
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--frame);
  border-radius: var(--skruglenie);
  font-weight: 700;
  cursor: pointer;
}

.header__toggle:focus-visible + .header__toggle-name,
.tabs__toggle:focus-visible ~ .tabs__name {
  outline: 2px solid var(--akcent);
  outline-offset: -2px;
}

/* ── Поиск в шапке ───────────────────────────────────────────────────────── */
/* 🔴 В ПОКОЕ — КРУГЛАЯ КНОПКА-ЛУПА; по нажатию раскрывается в поле. Скрипт `poisk.js`. */
.search {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex: 0 0 auto;
  min-width: 0;
}

.search__raskrytie {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  padding: 0;
  border: 1px solid var(--frame);
  border-radius: var(--r-pill);
  background: var(--fon-kartochki);
  cursor: pointer;
}

.search__raskrytie:hover { border-color: var(--akcent); }

/* 🔴 СВЁРНУТЫМ ПОЛЕ БЫВАЕТ ТОЛЬКО ПОД ПРИЗНАКОМ `est-skript`, который ставит `poisk.js`.
   Без скрипта — до его исполнения, при отключённом скрипте, при не доехавшем файле —
   в шапке остаётся обычная рабочая форма: поле видно, кнопка отправляет.

   Замер 12.08.2026 в браузере без скрипта показал прежнее устройство целиком: предельная
   ширина поля 0, кнопок отправки в форме 0. Поиска на сайте не существовало, страница
   при этом отвечала 200, и ни один сторож не краснел. */
.search__field {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--frame);
  border-radius: var(--skruglenie);
  background: var(--fon-kartochki);
  color: var(--tekst);
  font: inherit;
  font-size: 1rem;
  line-height: 1.2;
  transition: max-width var(--hod), opacity var(--hod), padding var(--hod),
              border-color var(--hod), background var(--hod);
}

.est-skript .search__field {
  width: 0;
  max-width: 0;
  padding: 0;
  border-color: transparent;
  background: transparent;
  opacity: 0;
  pointer-events: none;
}

.search--raskryt .search__field {
  width: auto;
  max-width: 12rem;
  padding: 0.3rem 0.6rem;
  border-color: var(--frame);
  background: var(--fon-kartochki);
  opacity: 1;
  pointer-events: auto;
}

.search--raskryt .search__field:focus { outline: 2px solid var(--akcent); outline-offset: -2px; }

/* На телефоне поле всегда видно — своя ветка `@media (hover: none)` ниже. */
@media (hover: hover) {
  .search { flex: 0 0 auto; }
}

@media (hover: none) {
  .search__raskrytie { display: none; }

  .search__field {
    width: auto;
    max-width: none;
    flex: 1 1 auto;
    padding: 0.3rem 0.6rem;
    border-color: var(--frame);
    background: var(--fon-kartochki);
    opacity: 1;
    pointer-events: auto;
  }
}

/* Высота значка от размера текста — он держится на одной линии с полем при любом масштабе
   шрифта, который человек выставил в браузере. Тот же приём, что у знака корзины. */
.search__znak { width: 1.1em; height: 1.1em; display: block; }

/* 🔴 ЗНАКИ ШАПКИ ПРИГЛУШЕНЫ ДО 0,7 И ПРОЯСНЯЮТСЯ ПОД КУРСОРОМ. Требование Кирилла
   06.08.2026: «иконки и правая часть шапки тоже убогая… значок кабинета тоже сделать
   чуть прозрачнее, чуть премиальнее».

   Сами рисунки заменены в тот же день: были залитые силуэты из автоматической обводки
   генерации, стали линии в 1,4 точки — тем же языком, что фирменный знак Натальи, который
   теперь стоит слева в той же полосе. Залитое пятно рядом с тонким контуром выглядит
   значком из чужого набора, и это первое, что видно в шапке.

   ⚠️ Приглушение делается прозрачностью, а не второй краской: краска у нас именованная,
   и заводить «молочный потише» ради трёх значков значило бы ставить в палитру роль,
   которой на странице нет. Прозрачность — это состояние, а не цвет.

   ⚠️ Правило одно на три значка сразу, а не три одинаковых: разъедутся они молча. */
.header__cart-znak,
.header__kabinet-znak,
.search__znak,
.header__svet-znak {
  opacity: .7;
  transition: opacity var(--hod);
}

.header__cart:hover .header__cart-znak,
.header__kabinet:hover .header__kabinet-znak,
.search__raskrytie:hover .search__znak {
  opacity: 1;
}

/* ── Яркость фона ────────────────────────────────────────────────────────── */
/* 🔴 ЗНАЧОК И ПОЛЗУНОК СРАЗУ В ПОЛОСЕ, слева от поиска (правка 11.08.2026). Отступ до соседей
   — тот же `gap` у `.header`, своих margin не задаём. */
.header__svet {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  flex: 0 0 auto;
  /* 🔴 ВПРАВО ЕДЕТ ОН, А НЕ ПОИСК. Замер 11.08.2026 на ширине 2540: поиск был прижат
     , ползунок оставался у меню, и между ними лежало 1018 точек —
     Кирилл читал это как «ползунок не рядом с поиском». Теперь вправо уходит эта пара
     целиком, а зазор между ними держит промежуток строки шапки. */
  margin-left: auto;
}

.header__svet-znak { width: 1.15em; height: 1.15em; flex: 0 0 auto; display: block; }

/* 🔴 НАТИВНЫЙ ПОЛЗУНОК — как `compare__slider` на странице проектов. Ручка 8 точек,
   краской действия: 11.08.2026 она была 44 точки песочного цвета, и Кирилл прочитал её
   как «гигантский жёлтый шар» — «максимум 6 или 8 точек мне кажется надо», цвет —
   «приглушённого зеленоватого как деревья». Обводка при переходе клавиатурой — цветом действия.

   ⚠️ `::-webkit-slider-thumb` и `::-moz-range-thumb` — имена из спецификации CSS, а не наши. */
.header__svet-polzunok {
  display: block;
  width: 6.25rem;
  margin: 0;
  -webkit-appearance: none;
  appearance: none;
  height: 0.25rem;
  border-radius: 999px;
  background: var(--frame);
  cursor: pointer;
}

.header__svet-polzunok:focus-visible { outline: 3px solid var(--akcent); outline-offset: 3px; }

.header__svet-polzunok::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 8px;
  height: 8px;
  border: none;
  border-radius: 50%;
  background: var(--akcent);
  cursor: pointer;
}

.header__svet-polzunok::-moz-range-thumb {
  width: 8px;
  height: 8px;
  border: none;
  border-radius: 50%;
  background: var(--akcent);
  cursor: pointer;
}

/* ── Кабинет ─────────────────────────────────────────────────────────────── */
/* ⛔ Ссылка и больше ничего: механики входа не существует (спецификация 3.5). */
.header__kabinet {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
}

.header__kabinet-znak { width: 1.15em; height: 1.15em; flex: 0 0 auto; }

/* Вес 500 — тот же ряд шапки, что и вкладки, разбор у `.tabs__link`. */
.header__kabinet-name { font-weight: 500; }

/* ── Шапка на узком экране: две строки вместо трёх ───────────────────────── */
/* 🔴 ПРАВКА КООРДИНАТОРА ПО ЖИВОМУ ЗАМЕРУ С ТЕЛЕФОНА, 02.08.2026. Замер вида этого не видит
   и увидеть не может: `site-appearance.py` гоняет обычный Chromium, у которого признак `hover: hover`
   истинен на всех трёх ширинах, — то есть мир пальца им не проверяется вовсе. Строитель
   дорожки шапки назвал эту дыру вслух, и она подтвердилась с первого же снимка настоящим
   набором признаков телефона.

   Что было: поле поиска просит `15rem` и на 390 точках не помещалось рядом с именем сайта
   и подписью «Меню», поэтому уезжало на свою строку, а корзина с кабинетом на третью.
   Закреплённая шапка занимала около 130 точек, то есть шестую часть экрана телефона,
   и занимала её на КАЖДОЙ прокрутке КАЖДОЙ страницы. А каталог растений смотрят именно
   с телефона, стоя на участке (3.3).

   Что стало: поле сжимается до остатка первой строки, и шапка складывается в две строки.
   ⚠️ Предел «не выше 80 точек» к телефону не относится и здесь не нарушен: он про широкий
   экран, где перенос как раз и означал бы, что шапка не помещается.

   ⚠️ Граница взята ПО ШИРИНЕ, а не по признаку `hover`, и соседнему разделу это
   не противоречит: там вопрос был «чем тычут», и на него ширина отвечает неверно; здесь
   вопрос ровно «сколько места», и отвечает на него именно ширина. */
@media (max-width: 40rem) {
  .header { gap: 0.3rem 0.6rem; padding: 0.35rem 0.8rem; }

  /* Логотип на шаг мельче: на телефоне он и так самый крупный в полосе, а место нужнее полю. */
  .header__znak { height: 26px; }
  .header__slovo { height: 14px; }

  /* Поле отдаёт всё, что можно, и садится в остаток первой строки. ⚠️ `min-width: 0` у поля
     уже стоит выше, и без него правило не сработало бы вовсе: `input` по умолчанию
     не сжимается ниже своей собственной ширины, сколько бы ему ни разрешали. */
  .search { flex: 1 1 6rem; }
  .search--raskryt .search__field { max-width: none; }
}

/* ── ШАПКА В ОДНУ СТРОКУ НА НОУТБУКЕ ─────────────────────────────────────────
   🔴 ДОЛГ, НАЗВАННЫЙ 06.08.2026 И ЗАКРЫТЫЙ 06.08.2026 ЖЕ. В разборе шестой вкладки
   («Калькулятор») он записан дословно: «Понадобится одна строка и на 1440 — сжимаются
   промежутки вкладок в `nav.css`, это отдельная правка рамки сайта».

   Замер до правки на окне 1440×900: шапка 74 точки, «Кабинет» уехал во вторую строку.
   Формально предела в 80 точек это не нарушало, но Кирилл в тот же день сказал про шапку
   «все текущие слова пиздец как пляшут, не выровнены» — а ряд, разорванный на две строки
   посередине, и есть самая заметная форма этого.

   Что сжимается и в каком порядке: сначала промежутки между вкладками и полями полосы,
   потом поле поиска. Кегль и вес НЕ трогаются — мельче станут все восемь надписей сразу,
   а жалоба была ровно на то, что их плохо читать.

   ⚠️ Верхняя граница взята по ширине, а не по признаку `hover`: здесь вопрос ровно «сколько
   места», и отвечает на него именно ширина. Ниже 40rem работает своя раскладка телефона.

   ⚠️ ЗДЕСЬ БЫЛА ЧЕТВЁРТАЯ СТРОКА — промежуток у столбика корзины с телефоном, и она снята
   по двум причинам
   сразу. Она не работала: строчная раскладка корзины и телефона задаётся ниже по файлу
   (`@media (min-width: 75rem)`), то есть ПОСЛЕ этого блока, и перебивала его. И она сломала
   сторожа `test_9_01`: он берёт ПЕРВОЕ в файле правило `.header__contacts` и требует в нём
   столбик, а первым стало это. Замер после снятия: шапка на 1440×900 всё равно одна строка
   в 44 точки — промежутка корзины с телефоном для этого не потребовалось вовсе. */
@media (min-width: 40rem) and (max-width: 100rem) {
  .header { gap: 0.3rem 0.55rem; padding: 0.35rem 0.9rem; }
  .tabs__link { padding: 0.35rem 0.32rem; }
  .search { flex: 0 1 11rem; }
  .search--raskryt { flex: 0 1 15rem; }
}

/* ── ДВА УСТРОЙСТВА — ДВА СПОСОБА, и разводит их признак `hover`, а не ширина экрана ───
   Ширина врёт: планшет бывает шире ноутбука, а пальцем по нему всё равно тычут. Тот же
   раздел ввода, что у меню разделов (`nav.css`), и заведён он здесь по той же причине. */

/* ── МЫШЬ: вкладки стоят строкой, прятать их не за чем ────────────────────── */
@media (hover: hover) {
  /* Подписи раскрытия не нужны: список выпадает по наведению. Спрятаны `display: none`
     сознательно — они не должны попадать ни в порядок обхода клавишей, ни в раскладку. */
  .header__toggle-name, .tabs__name { display: none; }

  /* Точка отсчёта для выпадающего меню разделов: список привязан к своей вкладке и потому
     не сдвигает под собой ни одной строки (`nav.css` держит само выпадение). */
  .tabs__item { position: relative; }

  /* Знак «здесь есть продолжение» — только у той вкладки, под которой оно есть. ⛔ Отклик
     на наведение отдельным правилом НЕ пишется: он уже задан всем ссылкам шапки
     (`.header a:hover`), и второе объявление того же смысла разъехалось бы с первым (🅱️5). */
  .tabs__item--catalog > .tabs__link::after { content: " ▾"; color: var(--tekst-tihiy); }
}

/* ── ПАЛЕЦ: наведения нет, вкладки уходят под одну подпись ────────────────── */
@media (hover: none) {
  /* Пять вкладок в строку на телефоне не помещаются по устройству. Раскрытый список занимает
     всю ширину полосы (`flex-basis: 100%`) и лежит В ПОТОКЕ шапки: шапка от этого растёт,
     а не всплывает поверх страницы. Всплывающий слой здесь и не нужен — закреплена сама
     шапка, и растёт она сверху вниз от края экрана.

     ⚠️ Второе нажатие по подписи гасит список — галочка снимается сама. */
  .tabs { display: none; }

  .header__toggle:checked ~ .tabs { display: block; flex-basis: 100%; }

  .header__toggle-name::after { content: " ▾"; color: var(--tekst-tihiy); }

  .header__toggle:checked + .header__toggle-name::after { content: " ▴"; }

  .tabs__list { flex-direction: column; align-items: flex-start; }

  /* ⛔ Точек-разделителей в столбике НЕТ. Они разводят слова, стоящие в строку; в списке,
     где каждый пункт на своей строке, точка перед словом читается как маркер списка,
     то есть говорит неправду. */
  .tabs__item + .tabs__item::before { content: none; }

  /* Ссылка и подпись раскрытия стоят в одну строку: подпись переключает список, ссылка
     ведёт на страницу каталога, и потерять второе нельзя (тот же довод, что у строки
     «Все …» внутри раздела). */
  .tabs__item--catalog { display: flex; flex-wrap: wrap; align-items: baseline; }

  .tabs__toggle:checked + .tabs__link + .tabs__name::after { content: " ▴"; }
}

/* 🔴 КОРЗИНА СВЕРХУ, ТЕЛЕФОН ПОД НЕЙ — правка Кирилла 01.08.2026, п. 9: «номер телефона
   под корзиной». Это столбик в правом углу шапки, а не два соседа по строке.

   ⚠️ Прижат вправо (`align-items: flex-end`), иначе на широком экране телефон висел бы
   под левым краем слова «Корзина» и столбик читался бы как случайно съехавший. */
.header__contacts {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.15rem;
}

/* 🔴 НА ШИРОКОМ ЭКРАНЕ КОРЗИНА И ТЕЛЕФОН СТОЯТ В СТРОКУ. 02.08.2026, правка Кирилла:
   «корзина уехала».

   Замер объясняет, почему столбик читался как съехавший: телефон занимает 146 точек,
   слово с корзиной — 96, и при выравнивании по правому краю левый край корзины оказывается
   на пятьдесят точек правее телефона. Глаз видит не столбик, а сдвинутую вправо корзину.

   ⚠️ Столбик при этом НЕ отменён и остаётся на узких экранах — там для строки просто нет
   места. Порядок «сначала корзина, потом телефон» сохранён в обеих раскладках: он назван
   правкой Кирилла 01.08.2026 и от ширины окна не зависит.

   📌 Побочно это снимает высоту: два ряда задавали высоту всей шапки, а она с волны 3 —
   замеряемый предел (≤ 80 точек). */
@media (min-width: 75rem) {
  .header__contacts {
    flex-direction: row;
    align-items: center;
    gap: 1.1rem;
  }
}

/* 🔴 Мельче и плотнее, чем было (`1.1rem` при полутора интервалах). Столбик «корзина плюс
   телефон» — самый высокий блок шапки, то есть именно он и задаёт её высоту, а высота
   с волны 3 стала замеряемым пределом (≤ 80 точек): полоса закреплена и отнимает место
   у первого экрана на каждой прокрутке каждой страницы. */
/* 🔴 СВОЕГО КЕГЛЯ У ТЕЛЕФОНА БОЛЬШЕ НЕТ, И ЭТО ПОЧИНКА ВЫРАВНИВАНИЯ, А НЕ ЭКОНОМИЯ СТРОКИ.
   Здесь стояло `font-size: 1.0625rem` — 17 точек, набранных числом. Ровно тем же способом
   телефон однажды оказался на 16 точках при 17 у соседей, и его базовая линия не совпадала
   с ними; правку тогда сделали, поставив второе число вместо первого. Второе число живёт
   ровно до следующей правки кегля полосы — а она случилась 07.08.2026 («шрифты на закрепе
   сверху чуть уменьши»), и телефон снова остался бы единственной надписью прежнего размера.

   Теперь кегль у полосы один и наследуется (`.header`), и разойтись ему не с чем.

   ⚠️ Вес 500 — тот же ряд шапки, что и вкладки, разбор у `.tabs__link`.

   🔴 ЦИФРЫ ТАБЛИЧНЫЕ (`tabular-nums`). Требование Кирилла 06.08.2026: «шрифты и цифры
   в новый шрифт». В Manrope пропорциональные цифры разной ширины — единица уже семёрки, —
   и номер `+7 900 000-00-00` из десяти цифр читается рваной строкой: группы получаются
   неодинаковой ширины при одинаковом числе знаков. Табличное начертание выравнивает
   их по одной ширине, и номер встаёт ровным столбиком цифр. */
.header__phone {
  font-weight: 500;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  letter-spacing: .015em;
}

/* ── Подвал ──────────────────────────────────────────────────────────────── */
/* 🔴 ЗАЛИВКА ПОДВАЛА СНЯТА. Спецификация v10, раздел 4. Здесь стояло «тем же тёмным,
   что шапка: страница получает верх и низ» — это была раскладка под сплошной фон,
   которого больше нет. На живом фоне тёмная плашка внизу читается как оборванная
   картинка: видео идёт до самого низа страницы и упирается в прямоугольник краски.

   Осталась светлая кромка сверху — она отделяет подвал от содержимого не цветом,
   а линией, и сквозь него по-прежнему видно фон. */
.footer {
  /* 🔴 ПОДВАЛ ПРИЖАТ К НИЗУ ОКНА НА КОРОТКИХ СТРАНИЦАХ — правка Кирилла 08.08.2026
     («нижняя полоса поднялась наверх»). Приём: липкий элемент, чья точка прилипания стоит
     на высоте окна. Пока страница короче окна, подвал держится у нижнего края; как только
     содержимое переросло окно, точка уходит за экран и подвал ведёт себя обычно.

     ⚠️ Взято ВМЕСТО раскладки `display: flex` у тела страницы: та ломала сетку плиток
     на главной (разбор — у `body` выше). Здесь контекст форматирования не меняется вовсе,
     поэтому сломать раскладку остальных страниц нечем. */
  position: sticky;
  top: 100vh;
  /* 🔴 ПЛАШКА СТАЛА НИЖЕ И ТОНЬШЕ — правка 10.08.2026, замер `tools/zamer/site-appearance.py`.
     Числа — переменные `tokens.css`, не догма: правится там, одной строкой на весь сайт. */
  padding: var(--podval-vozduh-sverhu) 0 var(--podval-vozduh-snizu);
  border-top: 1px solid var(--frame);
  color: var(--tekst-tihiy);
  font-size: 0.95rem;
}

/* 🔴 ЛЕВЫЙ КРАЙ ПОДВАЛА — ОДНО ЧИСЛО НА ВСЕХ СТРАНИЦАХ, ОТДЕЛЬНОЕ ОТ ШИРИНЫ КОЛОНКИ.
   Правка 10.08.2026. Прежде подвал брал ту же переменную, что и `main` (`--width-page`),
   и центрировался внутри неё `margin: 0 auto` — а эту переменную каждая страница объявляет
   себе сама: текстовая колонка 46 рем, каталожная 74 рем. Поэтому левый край подвала
   совпадал с содержимым своей страницы и расходился между страницами: на окне 2540
   страница контактов начинала его на 918-й точке, а главная на 694-й — Кирилл читает
   такую разницу как «съехало».

   Теперь край держит `--podval-kray` (`tokens.css`), число не зависит от ширины колонки
   и одно и то же на любой странице. `--podval-kray: auto` возвращает прежнее поведение —
   центр колонки — это и есть обещанный рычаг. */
.footer__inner {
  max-width: var(--width-page);
  margin-left: var(--podval-kray);
  margin-right: auto;
  padding: 0 1rem;
  /* 🔴 ТЕНЬ ПОД БУКВАМИ ПОДВАЛА — та же, что у текста страниц поверх видео, и понадобилась
     она ровно из-за переезда в колонку. У левого края кадр тёмный, а по центру на коротких
     страницах под подвалом оказывается светлая дорожка: замер стенда на окне 2540 показал
     реквизиты серым по светлому. Тень держит их читаемыми на любом кадре. */
  text-shadow: var(--ten-teksta);
}

.footer a { color: var(--tekst); }
.footer p { margin: 0.4rem 0; }

/* ── Реквизиты юрлица в подвале ──────────────────────────────────────────── */
/* 🔴 Стоят на КАЖДОЙ странице — задача Кирилла 08.08.2026. Значения приезжают
   из `core/company.py`, здесь только вид.

   Отбиты воздухом, а не второй линией: линия у подвала уже есть, и вторая такая же
   в паре сантиметров от первой читается как оборванный блок, а не как отдельный раздел.

   ⚠️ Кегль самый мелкий на сайте, и это роль, а не экономия места: реквизиты нужны тому,
   кто их ищет — бухгалтеру заказчика перед платежом, — а не каждому посетителю. Набери их
   вровень с текстом подвала, и последний экран любой страницы стал бы стеной цифр,
   в которой теряется телефон.

   🔴 Цифры табличные. В ОГРН тринадцать знаков, в ИНН десять, и в обычном начертании единица
   уже соседних цифр: ряд выглядит рваным ровно там, где человек сверяет его знак в знак. */
.footer__legal {
  margin-top: var(--o-5);
  font-size: var(--t-xs);
  letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
}

/* 🔴 МЕРА СТРОКИ СНЯТА, И БЕЗ ЭТОЙ СТРОКИ ПОДВАЛ ЛОМАЕТСЯ ВИДИМО. Рамка сайта ограничивает
   каждый абзац мерой чтения в единицах его кегля (`p { max-width: var(--shirina-stroki) }`).
   Реквизиты набраны самым мелким кеглем, поэтому мера у них самая узкая — на стенде 1440
   строка рвалась посреди реквизита: «КПП» оставалось на первой строке, «080001001» уезжало
   на вторую. Реквизит, разорванный пополам, читается как две разные строки.

   ⚠️ Мера чтения здесь и не нужна: это не текст, который читают подряд, а перечень значений
   через разделитель. */
.footer__legal p { margin: 0.2rem 0; max-width: none; }

/* Ряд правовых ссылок — тот же подвал, но отдельной строкой с зазором: это не реквизит,
   а перечень документов. Перенос по словам здесь РАЗРЕШЁН, в отличие от реквизитов выше:
   названия документов длинные, и на телефоне ряд обязан ложиться в несколько строк.
   Запрети перенос — и подвал вытолкнул бы страницу шире окна, а это та поломка, которую
   на мониторе не видно вовсе. */
.footer__pravo {
  margin-top: 0.5rem;
  line-height: 1.7;
}

.footer__pravo a { color: inherit; }

/* Версия сайта — самая тихая строка подвала. Клиенту она не адресована: он пришёл за туей,
   а не за номером сборки. Адресована она нам — по ней видно, какой код открыт у клиента,
   и после выкладки она обязана смениться. Поэтому строка есть, но кегль на ступень ниже
   правовых ссылок, а краска приглушена. */
.footer__versiya {
  margin-top: 0.5rem;
  font-size: var(--t-s);
  opacity: 0.55;
}

/* ── Состояние товара: общее для раздела и карточки ──────────────────────── */
/* ⚠️ КЕГЛЬ ОБЩИЙ СО СТРОКОЙ СОРТОВ. Правка Кирилла 05.08.2026: «тут вообще шрифты
   разные у слов в наличии и сорта». Шрифт был один, а кегли разные — 1,05 рем против
   0,95, — и на соседних строках это читается как два разных шрифта. Обе строки теперь
   берут ступень шкалы `--t-s`: они говорят об одном и том же товаре и стоят рядом. */
.availability { margin: 1rem 0; font-size: var(--t-s); }
.availability--none { font-weight: 700; font-size: 1.15rem; }

/* «Привозим под заказ» — это ПРОДАЖА, а не отказ, поэтому цветом акцента, а не серым.
   Раздел, весь товар которого идёт по предзаказу, покупают. */
.availability--preorder { font-weight: 700; font-size: 1.1rem; color: var(--akcent); }

/* Сорта выбранного размера: «сорта: Бонфаер, Вимс Ред». Тише строки наличия и тише цены —
   это уточнение к уже принятому решению «беру этот размер», а не само решение. Гортензия
   в C7.5 привозит сюда 25 имён, поэтому строка обязана переноситься и не ломать раскладку. */
.cultivars {
  margin: -0.4rem 0 1rem;
  font-size: var(--t-s);
  line-height: 1.45;
  color: var(--tekst-tihiy);
}

/* Зелёная галочка после строки наличия — правка Кирилла 04.08.2026, дословно: «сделать
   галочку зеленую в наличи, на те товары, на которые стоит остаток >=1». Класс ставится там,
   где остаток есть (`views._card`, `views._variant_block`).

   Рисуется двумя рамками и поворотом, а не знаком из шрифта: «✓» в разных системах выглядит
   по-разному, а картинку по ссылке не пустит политика содержимого. Тем же приёмом сделана
   стрелка разворачивающихся полос (`product.css`, `.strip__arrow`).

   Размер в `em`: на карточке строка крупнее, чем на плитке, и галочка растёт вместе с ней. */
.in-stock::after {
  content: '';
  display: inline-block;
  width: 0.3em;
  height: 0.58em;
  margin-left: 0.42em;
  border-right: 0.13em solid var(--akcent-pokupki);
  border-bottom: 0.13em solid var(--akcent-pokupki);
  transform: translateY(-0.08em) rotate(45deg);
}

/* Отбита и по центру — так она стоит на всех трёх утверждённых макетах: это не строка
   текста в потоке, а завершение страницы. */
.zvonok { margin: 4rem 0 2rem; font-size: 1.1rem; text-align: center; }

/* ── Корзина: значок в шапке ─────────────────────────────────────────────── */
/* 🔴 ВЫЛОЖЕНА В СТРОКУ С ЗАЗОРОМ — это и есть подготовка места под знак корзины (п. 8 правок
   Кирилла: «где иконка корзины»). Знак рисует координатор и кладёт своим файлом; вставленная
   перед словом картинка встанет на свою линию сама, и ни одну строку раскладки для этого
   править не придётся.

   ⛔ Правила для самого знака здесь НЕТ, пока нет знака: сторож `test_styles.py` считает
   правило без разметки такой же находкой, как разметку без правил, — и он прав, мёртвое
   правило через месяц читается как «здесь что-то оформлено», и его боятся трогать (🅱️23). */
.header__cart {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
}

/* Слово живёт отдельным узлом, и это часть подготовки: придёт знак — слово либо прячут
   от глаза, оставив диктору, либо убирают вовсе, и делается это одной строкой ЗДЕСЬ.
   Безымянный кусок текста внутри ссылки не выбирается ничем, и тогда та же правка означала бы
   переписывание разметки шапки. Начертание задано ему, а не ссылке: у счётчика рядом своё. */
/* Знак корзины: высота от размера текста, поэтому он держится на одной линии со словом
   при любом масштабе шрифта, который человек выставил в браузере. */
.header__cart-znak { width: 1.15em; height: 1.15em; flex: 0 0 auto; }

/* Вес 500 — тот же ряд шапки, разбор у `.tabs__link`. */
.header__cart-name { font-weight: 500; }

/* Счётчик по умолчанию скрыт разметкой (`hidden`) и показывается скриптом, когда в корзине
   что-то есть. Пустая корзина и корзина без скриптов выглядят одинаково — и это честно:
   на сервере корзины нет, знать о ней страница не может.

   🔴 На тёмной шапке значок обязан быть светлым: до перекраски он был тёмно-зелёным на белом,
   и после неё стал бы тёмным на тёмном, то есть исчез бы молча (🅱️15 — правило проверяется
   и в той ветке, о которой не думали). */
/* ⚠️ Число в кружке набрано ТАБЛИЧНЫМИ цифрами и весом 600, а не 700: на 14 точках
   полужирная единица и полужирная восьмёрка имеют заметно разную ширину, и кружок
   при смене числа менял размер. Кегль на ступень мельче тоже не случайно — счётчик
   стоит поверх слова «Корзина» и не должен спорить с ним. */
.header__counter {
  display: inline-block;
  min-width: 1.4rem;
  padding: 0 0.35rem;
  border-radius: var(--r-pill);
  background: var(--akcent);
  color: var(--tekst-na-akcente);
  font-size: 0.875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* ── Страница корзины ────────────────────────────────────────────────────── */
/* 🔴 КОРЗИНА ЛЕЖИТ НА СТЕКЛЕ, А НЕ ПРЯМО НА ВИДЕО. Спецификация v10, раздел 4, 05.08.2026.
   На всех прочих страницах текст крупный и его держит вуаль; здесь же строка состоит
   из мелких чисел — цена, количество, сумма, — и под ними по фону проезжает то тёмный
   куст, то светлый туман. Число, которое читается через раз, в корзине недопустимо:
   человек на этой странице считает деньги.

   ⚠️ Это стекло, а не заливка: сквозь него фон по-прежнему виден, а по краям панели
   обходит её целиком. Сплошного прямоугольника от края до края не появляется. */
.cart {
  list-style: none;
  margin: 1.5rem 0;
  padding: var(--o-2) var(--o-5);
  border: 1px solid var(--frame);
  border-radius: var(--r-m);
  background: var(--steklo-panel);
  box-shadow: var(--ten-2);
}

.cart__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 1rem;
  align-items: baseline;
  padding: 0.8rem 0;
  border-bottom: 1px solid var(--frame);
}

/* Последняя строка панели линию не несёт: она отделяла бы содержимое от собственного края
   панели, то есть рисовала бы границу там, где её уже нарисовала кромка. */
.cart__row:last-child { border-bottom: 0; }

.cart__name { flex-basis: 100%; font-weight: 700; }
.cart__size, .cart__availability, .cart__price { color: var(--tekst-tihiy); font-size: 0.95rem; }

/* Кнопки количества — ссылки, а не скрипт: адрес страницы и есть состав корзины. */
.cart__quantity { margin-left: auto; white-space: nowrap; }

.cart__button {
  display: inline-block;
  min-width: 2rem;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--frame);
  border-radius: var(--skruglenie);
  text-align: center;
  text-decoration: none;
  font-weight: 700;
}

.cart__count { display: inline-block; min-width: 2rem; text-align: center; font-weight: 700; }
.cart__total { font-weight: 700; white-space: nowrap; min-width: 6rem; text-align: right; }
.cart__remove { font-size: 0.95rem; color: var(--tekst-tihiy); }

/* ── Переключатель ступени посадки ──────────────────────────────────────────
   Решение Кирилла 12.08.2026: «прикрути в корзине просто переключатель красивыый
   аккуратный приятный глазу». Две ССЫЛКИ на ту же корзину с другим значением параметра
   адреса (`core/site/cart.py`, `LEVEL_PARAM`) — ни строки скрипта, страница обязана
   работать без него. Краски — только именами ролей из `tokens.css` (9А-0в-01). */
.cart__guarantee { margin: 1.5rem 0 1rem; }
.cart__guarantee-lead { margin: 0 0 var(--o-2); color: var(--tekst-tihiy); font-size: var(--t-s); }

/* 🔴 НА ТЕЛЕФОНЕ ПОЛОВИНЫ ВСТАЮТ ДРУГ ПОД ДРУГА, А НЕ ВЫЛЕЗАЮТ ЗА ОКНО. Замер 12.08.2026,
   ширина 390: строка «40% — гарантия 1 год · 50% — гарантия 2 года» не помещается, страница
   становится 412 точек при окне 390 и ездит вбок вместе с шапкой — то же, что уже ловил сторож
   вида на калькуляторе.

   `flex-wrap` даёт перенос, а не сжатие: сжатая надпись про срок гарантии рвалась бы посреди
   слова, а это цена в рублях и обещание на два года — их читают целиком.

   ⚠️ При переносе скругление в пилюлю остаётся у КАЖДОЙ половины, потому что оно задано им,
   а не группе: два овала друг под другом читаются как выбор, а срезанные углы — как поломка. */
.guarantee-toggle {
  display: inline-flex;
  flex-wrap: wrap;
  max-width: 100%;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--frame);
  border-radius: var(--r-pill);
  background: var(--steklo-panel);
}

/* Невыбранная половина — прозрачная, читается только текстом и рамкой группы вокруг неё. */
.guarantee-toggle__option {
  padding: var(--o-2) var(--o-4);
  border-radius: var(--r-pill);
  color: var(--tekst);
  background: transparent;
  text-decoration: none;
  font-weight: 700;
  font-size: var(--t-s);
  white-space: nowrap;
  transition: background var(--hod), color var(--hod);
}

.guarantee-toggle__option:hover { color: var(--akcent-navedenie); }

/* Выбранная половина — залита тем же зелёным, что и главное действие сайта: одна краска
   действия на весь сайт, второй заводить незачем (см. `--list` в `tokens.css`). */
.guarantee-toggle__option--selected,
.guarantee-toggle__option--selected:hover {
  background: var(--akcent);
  color: var(--tekst-na-pokupke);
}

/* ── Итог ────────────────────────────────────────────────────────────────── */
.itog { border-collapse: collapse; margin: 1rem 0; min-width: 60%; }
.itog th, .itog td { text-align: left; padding: 0.4rem 1rem 0.4rem 0; }
.itog td { text-align: right; white-space: nowrap; }
.itog th { font-weight: 400; color: var(--tekst-tihiy); }
.itog__vsego th, .itog__vsego td { font-weight: 700; color: var(--tekst); font-size: 1.15rem; }
.itog__ogovorka { color: var(--tekst-tihiy); font-size: 0.95rem; }

/* ── Форма заявки ────────────────────────────────────────────────────────── */
.inquiry { margin: 1.5rem 0; max-width: 30rem; }
.inquiry__field { display: flex; flex-direction: column; gap: 0.3rem; margin: 0 0 1rem; }
.inquiry__field label { font-weight: 700; }

/* Поля во всю ширину и с крупным шрифтом: заявку оставляют с телефона, стоя на участке (3.3).
   Шрифт мельче 16 точек заставляет браузер телефона приближать страницу при вводе. */
.inquiry input, .inquiry textarea {
  font: inherit;
  font-size: 1.05rem;
  padding: 0.6rem;
  border: 1px solid var(--frame);
  border-radius: var(--skruglenie);
  background: var(--fon-kartochki);
  color: var(--tekst);
}

.inquiry__error { color: var(--oshibka); font-size: 0.95rem; }

/* 🔴 СОГЛАСИЕ НА ОБРАБОТКУ — не такое же поле, как остальные, и выглядеть должно иначе.
   Подпись остальных полей набрана жирным и стоит НАД полем; здесь подпись стоит СПРАВА
   от квадратика и обычным начертанием — иначе строка читается как ещё один заголовок
   поля, а человек ищет глазами, где ввести данные.

   ⚠️ Квадратик и текст лежат в одном `label` по требованию доступности: нажатие на слова
   обязано ставить галочку. Поэтому `label` здесь строка (`flex-direction: row`), а не
   колонка, как у соседей. */
.inquiry__consent label {
  flex-direction: row;
  align-items: flex-start;
  gap: 0.55rem;
  font-weight: 400;
  display: flex;
  cursor: pointer;
}

/* Квадратик не сжимается длинным текстом рядом и стоит по верхней строке, а не по центру
   блока: при переносе подписи на две строки центрированный квадратик уезжает в середину
   и перестаёт читаться как начало строки. */
.inquiry__consent input[type="checkbox"] {
  flex: 0 0 auto;
  margin-top: 0.2rem;
  width: 1.1rem;
  height: 1.1rem;
  accent-color: var(--akcent);
}

/* Две ссылки под галочкой — тише самой подписи: это справка, а не действие. Кегль тот же,
   что у прочих пояснений формы. */
.inquiry__consent-links {
  display: block;
  margin-left: 1.65rem;
  font-size: 0.95rem;
  color: var(--tekst-tihiy);
}

/* 🔴 ЛОВУШКА НА РОБОТА. Поле спрятано СДВИГОМ ЗА КРАЙ ЭКРАНА, а не `display: none`
   и не `visibility: hidden`: поле, спрятанное любым из тех двух способов, роботы пропускают
   как заведомо служебное, и ловушка ловила бы пустоту, оставаясь зелёной.

   `position: absolute` убирает поле из потока — места под него в форме не отводится, и человек
   не видит ни пустой строки, ни щели между «Комментарием» и кнопкой. Тот же приём и тот же
   довод, что у галочек `.header__toggle` выше.

   ⚠️ Отрицательное `left` не создаёт прокрутки: область прокрутки страницы растёт вправо
   и вниз, а влево за начало — нет. Проверять это надо глазами на снимке страницы, потому что
   тест увидел бы форму целой и в том случае, если полоса прокрутки появилась.

   Правило нельзя убрать, не сломав приём: `.inquiry input` выше даёт полю рамку, отступы
   и крупный шрифт — без этого правила ловушка станет видимой строкой посреди формы,
   и её заполнит человек. Держит проверка `test_v1_43` в `core/site/tests/test_cart.py`. */
.inquiry__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  opacity: 0;
}

.inquiry__submit {
  padding: 0.9rem 1.6rem;
  border: 0;
  border-radius: var(--skruglenie);
  background: var(--akcent);
  color: var(--tekst-na-akcente);
  font: inherit;
  font-size: 1.1rem;
  font-weight: 700;
  cursor: pointer;
}

/* ── «Заявка принята» ────────────────────────────────────────────────────── */
.prinyato { margin: 2rem 0; }
.accepted__number { font-size: 1.3rem; }
.prinyato__ogovorka { color: var(--tekst-tihiy); }

/* ── Заголовок-металл ────────────────────────────────────────────────────── */
/* 🔴 ЗДЕСЬ СТОЯЛ ЗАГОЛОВОК С ЕДУЩИМ БЛИКОМ (класс `blesk`, заведён 07.08.2026). Снят
   08.08.2026 правкой Кирилла по стенду: «этот золотой переливающийся текст мне не нравится,
   он плохо читается. Как будто сами буквы в низком разрешении… как будто он в 144p
   вместо 1080hd».

   🔴 ПОЧЕМУ ОН ДЕЙСТВИТЕЛЬНО ВЫГЛЯДЕЛ РАЗМЫТЫМ, а не «показалось». Две причины, и обе
   про то, как браузер рисует буквы:

   1. Буквы красились не цветом, а градиентом, обрезанным по их форме (`background-clip: text`
      плюс `color: transparent`). Прозрачный текст браузер сглаживает по серому, отключая
      субпиксельное сглаживание, — на том же экране буквы становятся тоньше и мягче краями.
   2. Тень давалась фильтром (`drop-shadow`). Фильтр растрирует элемент целиком и накладывает
      результат — по краям букв появляется ореол, который на светлом кадре фона читается
      как расфокус.

   Обе беды лечит одно: сплошная краска. Металл остаётся, он в самом цвете
   (`--heading-metal`, светлый песок) и в размере, а не в бегущем блике.

   ⚠️ Тень букв теперь общая, из тех же правил, что у остального текста страницы: сплошным
   буквам `text-shadow` ложится ровно под форму и пятна не даёт. */
.metal {
  color: var(--heading-metal);
  /* Крупным буквам разрядка не нужна, а вот собранность нужна: на кегле 37 стандартный
     трекинг Manrope читается разболтанным. */
  letter-spacing: -.005em;
}

/* 🔴 НА СРЕДНИХ ШИРИНАХ ПОЛЯ ВКЛАДОК УЖЕ, ИНАЧЕ ШАПКА ЛОМАЕТСЯ В ДВЕ СТРОКИ. Замер 12.08.2026,
   после того как вкладка «Гарантия» стала «Гарантией и доставкой» по слову Кирилла: на 1280
   и 1440 шапка выросла с 46 точек до 69 — «Кабинет» уезжал на вторую строку и вставал под
   логотипом. На 1600 и шире всё помещалось, поэтому на мониторе штаба поломка не показывалась
   вовсе.

   ⚠️ Блок стоит В КОНЦЕ ФАЙЛА, и это не про порядок чтения. Правило `.header__svet-polzunok`
   объявлено ниже по файлу, вес у них одинаковый, и медиазапрос, поставленный выше,
   молча проигрывал: ползунок оставался прежней длины, а замер это показывал числом.

   Сужаются ПОЛЯ, а не кегль: мелкий шрифт в шапке читается хуже, а поля в шапке и так
   держатся на минимуме, при котором точка-разделитель стоит ровно между пунктами. Ниже 1100
   вкладки и так уходят в раскрывающееся меню, поэтому нижней границы у правила нет. */
@media (max-width: 1599px) {
  .tabs__link { padding: 0.35rem 0.3rem; }

  /* Ползунок яркости короче на треть — он единственный объект шапки, у которого длина
     произвольна: у остальных её задаёт текст. Ход ручки от этого не меняется, меняется
     только путь пальца. */
  .header__svet-polzunok { width: 4.25rem; }

  /* 🔴 У «КАБИНЕТА» ОСТАЁТСЯ ЗНАЧОК БЕЗ ПОДПИСИ. Двух прежних правок не хватило: шапке
     недоставало ещё около семидесяти точек, и «Кабинет» продолжал уезжать второй строкой
     под логотип. Подпись — самое дешёвое, что можно снять: вход в кабинет открывают редко,
     значок человечка узнаётся сам, и ссылка остаётся той же ссылкой того же размера.

     ⚠️ Название кабинета остаётся в разметке для экранного диктора — оно спрятано от глаз,
     а не удалено: `clip-path` прячет текст, не убирая его из дерева страницы. */
  .header__kabinet-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Ещё уже — прячется и подпись корзины: на 1280 и 1366 одного «Кабинета» не хватило.
   Значок тележки со счётчиком узнаётся сам, а счётчик — то единственное, ради чего
   на корзину смотрят в шапке, — остаётся на месте и не уменьшается. */
@media (max-width: 1439px) {
  .header__cart-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Набор значков: фигуры лежат в разметке один раз, дальше на них ссылаются тегом `use`.
   Сам набор невидим. ⛔ Прятать его строкой `style="display:none"` нельзя: политика
   содержимого встроенные стили не выполняет, и сторож `test_3_4_3a_20` на них краснеет. */
.znachki-nabor {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}
