/* ПЛИТКА РАЗДЕЛА — ФАЙЛ, КОТОРЫЙ ВЕЗУТ ОБЕ СТРАНИЦЫ СО СПИСКОМ РАЗДЕЛОВ (волна 3, дорожка Г).

   🔴 ЗАЧЕМ ЗАВЕДЁН ОТДЕЛЬНЫЙ ФАЙЛ, А НЕ «главная поделилась своим». Плитка раздела стоит
   в двух местах — на главной («Каталог по типам») и в корне каталога («Разделы»), — а её
   правила жили в `home.css`, который корень каталога не подключает. Итог был виден глазами
   на боевом сайте: на главной плитка со значком и постоянной высотой ячейки, в каталоге —
   голый список из двух слов. Браузер о ненайденном правиле не сообщает, поэтому расхождение
   держалось молча (🅰️7).

   🔴 РАССМАТРИВАЛИСЬ ДВА ПУТИ, И ВЫБРАН ВТОРОЙ:
   · корень каталога начинает везти `home.css` — отвергнут: вместе с плиткой он потащил бы
     первый экран главной, её кнопки и блоки экранов 3–5, то есть правила, которых на той
     странице нет ни одной штуки. Файл страницы перестал бы быть файлом страницы;
   · правила плитки раздела уезжают в СВОЙ файл, и его подключают обе страницы — принято.
     Ровно тем же приёмом и по тому же доводу живёт `card.css`: объект, стоящий на нескольких
     страницах, получает своего владельца (0.1 — один объект, один файл-владелец).
   ⛔ Третий путь — «дописать в `card.css`» — закрыт не правом доступа, а смыслом: там лежит
   плитка ТОВАРА, стоящая ещё и на двух других страницах, и рамка значка ей не нужна вовсе.

   🔴 ЗДЕСЬ ТОЛЬКО ТО, ЧЕГО НЕТ У ТОВАРНОЙ ПЛИТКИ. Панель, тень, ссылка во всю высоту,
   название и латынь — всё это `card.css`, и повторять их здесь значило бы завести второго
   владельца (🅱️5). Своего четыре: рамка значка (у товара на её месте снимок), ширина колонки
   сетки разделов, бронзовая обводка и движение — обводку и движение просил Кирилл 06.08.2026
   отдельно, и просил их именно этим восьми плиткам, а не всему сайту.

   🔴 НИ ОДНОГО КОДА ЦВЕТА. Все цвета — именами ролей из `tokens.css`. Проверяется сплошным
   проходом по всем файлам стилей (`tests/test_catalog_appearance.py`, проверка 9А-0в-01), и новый
   файл попадает под него САМ, заводить его мимо сторожа нельзя. */

/* ── Сетка разделов ───────────────────────────────────────────────────────── */
/* 🔴 ДВА СВОЙСТВА, И ОБА ПРО ОДНО: «ячейки одного размера, слово на одном месте» — претензия
   Кирилла 01.08.2026 (`docs/spec/v3-kirill-fixes.md`, пункт 5).

   Ширина колонки шире общей (`card.css` даёт разделам 11 rem): на утверждённом виде главной
   плитка раздела — это картинка с подписью, а не строка списка, и в 11 rem рамка значка
   становится мельче самого значка. Число одно на обе страницы ровно затем, чтобы один и тот
   же раздел не выглядел на них по-разному.

   ⚠️ СЕЛЕКТОР ИЗ ДВУХ ИМЁН, А НЕ ИЗ ОДНОГО, И ЭТО НЕ УКРАШЕНИЕ. Одноимённое правило
   в `card.css` весит один класс, наше — два, поэтому наше побеждает ВСЕГДА, независимо
   от того, в каком порядке страница подключит файлы. Прежняя запись на главной опиралась
   на порядок подключения (`.blok .blok__razdely`) и была верна ровно до тех пор, пока файл
   везла одна страница: на второй порядок другой, и правило проиграло бы МОЛЧА.

   ⚠️ Сколько плиток встанет в последний ряд — это данные, а не вёрстка: разделы заводит
   человек в панели (9А.2б), и «ровно два полных ряда» верно только для одного их числа.
   Здесь задан размер плитки, а не число колонок; хвост из одной-двух плиток законен. */
.cards.cards--categories {
  grid-template-columns: repeat(7, minmax(0, 1fr));
  grid-auto-rows: auto;
  align-items: start;
}

/* 🔴 НА ГЛАВНОЙ КОЛОНОК ШЕСТЬ, А НЕ СЕМЬ, С 12.08.2026 — это второй конец пары к комментарию
   в `site/home/_categories.html`: оттуда временно снята плитка «Сажаем сейчас». Вернут
   плитку — эту врезку убрать целиком, и главная снова возьмёт общую семёрку сверху; иначе
   седьмая плитка уедет во второй ряд и первый экран перестанет закрываться целым рядом.

   ⛔ ЧИСЛО ПРИБИТО К ГЛАВНОЙ, А НЕ К ОБЩЕМУ ПРАВИЛУ, И ЭТО НЕ ОСТОРОЖНОСТЬ РАДИ ОСТОРОЖНОСТИ.
   Тот же файл везёт корень каталога, а там разделов семь: «Многолетники» сняты с главной
   11.08.2026, но из каталога никуда не делись. Замер 12.08.2026 на общем правиле: седьмая
   плитка уходила в одиночку во второй ряд, а подписи укорачивались многоточием на всех
   четырёх широких окнах — четыре штуки вместо ни одной. */
.blok--katalog .cards.cards--categories {
  grid-template-columns: repeat(6, minmax(0, 1fr));
}

/* 🔴 ШИРИНА ВО ВСЁ ОКНО ЖИВЁТ ТОЛЬКО НА ГЛАВНОЙ, И ЭТО НЕ ПРИДИРКА К СЕЛЕКТОРУ.
   Ряд разделов стоит на двух страницах: на главной внутри блока, растянутого во всё окно
   (`home.css`, `.blok--katalog` с `width: 100vw`), и в корне каталога
   (`catalog.html`) — там он лежит в обычном `main` шириной 74rem.

   Правило `width: 88vw; margin-left: 6vw` написано под первый случай. Во втором оно
   выносит сетку за края родителя, и вся страница едет вбок. Замер штаба 12.08.2026,
   насколько страница каталога шире окна:

       1440 → 99 точек · 1920 → 282 · 2464 → 488 · 2560 → 525

   То есть на мониторе Кирилла правый край плиток уходит за экран на полтысячи точек,
   и внизу появляется полоса прокрутки всей страницы.

   Проверка — не чтение правил, а число: `document.documentElement.scrollWidth`
   минус `clientWidth` на `/katalog/` обязан быть нулём. */
/* 🔴🔴 ПРАВЫЙ КРАЙ РЯДА ОТСТУПАЕТ ОТ КНОПКИ ПОМОЩНИКА НА ТОТ ЖЕ ЗАЗОР, ЧТО МЕЖДУ ПЛИТКАМИ.
   Задача Кирилла 12.08.2026, дословно: «для окна леши появится место (от окна леши
   до плитки тоже синхронный отступ)».

   Что было: ряд шириной 88vw доходил на 2464 до 2316, а кнопка помощника начинается
   на 2214 — ряд лез на неё сверху на 102 точки, и последняя плитка читалась через кнопку.

   Кнопка закреплена у края окна (`chat.css`: `position: fixed; right: 1rem`) и в потоке
   страницы не участвует — подвинуть её потоком нельзя, место под неё отводится полем
   справа. Ширина кнопки замерена, а не взята из правил: 234 точки на всех широких окнах
   (текст «Спросить о растениях» и поля кнопки). Плюс её собственный отступ от края 1rem.

   ⛔ Ширину `--shirina-ryada` (88vw) НЕ ТРОГАЕМ: её же везёт первый экран главной, и левый
   край заголовка обязан совпадать с левым краем первой плитки. Поэтому ряд теперь тянется
   полями: левое — те же 6 %, правое — место под кнопку плюс зазор. Ширина получается сама,
   и разъезда с заголовком не возникает ни на одном окне.

   Проверка числом: расстояние от правого края ряда до левого края кнопки равно зазору
   между плитками, а `document.documentElement.scrollWidth` минус `clientWidth` — ноль.

   ⚠️ Прежний довод остаётся в силе: правило именное, `.blok--katalog`. В корне каталога
   (`catalog.html`) ряд лежит в обычном `main` шириной 74rem, и поля в долях окна вынесли бы
   его за края родителя — вся страница поехала бы вбок (замер 12.08.2026: 1440 → 99 точек,
   1920 → 282, 2464 → 488, 2560 → 525). Там кнопка помощника лежит на плитках второго ряда,
   а не на первом экране, и места под неё не отводится. */
.blok--katalog .cards.cards--categories {
  --mesto-pod-chatom: calc(234px + 1rem);
  width: auto;
  max-width: none;
  margin-left: var(--pole-okna);
  margin-right: calc(var(--mesto-pod-chatom) + var(--zazor-razdelov));
}

/* 🔴🔴 ЗАЗОР РАСТЁТ НА ТО, ЧТО ОСВОБОДИЛА СНЯТАЯ ПЛИТКА, А ПЛИТКИ ОСТАЮТСЯ ПРЕЖНЕГО РАЗМЕРА.
   «оставшиеся 6 плиток слегка раздвинь равномерно» (Кирилл, 12.08.2026).

   Почему именно так, а не «плитки стали крупнее». Высота ряда идёт за шириной плитки:
   рамка значка держит соотношение сторон. А низ ряда на мониторе Кирилла стоит на 95 %
   высоты окна — это потолок, ради которого считалась вся геометрия первого экрана
   (`home.css`, `.blok--katalog`, отступ сверху `calc(93svh - 28rem - 11vw)`). Дай плиткам
   вырасти на десятую часть — ряд подрастёт на два десятка точек и уедет за этот потолок,
   и пришлось бы пересчитывать отступ, утверждённый на глаз. Поэтому вся освободившаяся
   ширина уходит в зазоры, ряд остаётся той же высоты, и вертикаль не пересчитывается вовсе.

   Откуда взялось число. Ширина плитки при семи колонках: (0.88·V − 6·з_старый) / 7.
   При шести и новых полях: (0.94·V − 250 − 6·з) / 6. Приравняли и выразили зазор:
   он оказался почти прямой — 3.8 % ширины окна минус 42 точки. Растёт быстрее самой ширины
   потому, что место под кнопку отмерено в точках и на узком окне съедает большую долю.

   Замер 12.08.2026 на пяти окнах, ширина колонки была → стала: 1440 → 171 → 171,2 ·
   1920 → 228 → 228,2 · 2464 → 292,6 → 292,7 · 2560 → 304,7 → 304,4. Высота ряда при этом:
   128,8 → 128,9 · 171,5 → 171,6 · 220 → 220 · 229 → 228,8, то есть вертикаль стоит на месте.
   Зазор: 11,7 → 12,7 · 15,6 → 31 · 20 → 51,6 · 20 → 55.

   ⚠️ Верхняя граница 55 точек — не украшение: без неё на окне шире 2560 зазор пополз бы
   дальше и ряд разошёлся бы на отдельные картинки, потеряв вид одной полосы.
   ⛔ Общий зазор ряда разделов (ниже по файлу) не тронут: он держит корень каталога, где
   ряд лежит в 74 rem и такие поля его расклеили бы. */
.blok--katalog .cards.cards--categories {
  --zazor-razdelov: clamp(12px, calc(3.8vw - 42px), 55px);
  gap: var(--zazor-razdelov);
}

/* 🔴 СЕМЬ КОЛОНОК ОСТАЮТСЯ НА ЛЮБОМ ШИРОКОМ ЭКРАНЕ, И ЭТО ВЫБОР ИЗ ДВУХ ЗОЛ.
   Кирилл принял ряд из семи, глядя на макет шириной 2464: там колонка 310 точек и подписи
   стоят целиком. На 1440 те же семь дают 171 точку, и замер 12.08.2026 показал: пять
   подписей из семи укорачиваются многоточием.

   ⚠️ ЧЕТЫРЕ КОЛОНКИ ПРОБОВАЛИСЬ И СНЯТЫ. Они лечили укорачивание, но ломали требование
   посильнее: два ряда по четыре уводят низ ряда на 127 % высоты окна, и первый экран
   перестаёт влезать целиком — ради этого вся геометрия и считалась.

   Кегль подписи ниже 100rem убавлен на шестую часть: это не убирает укорачивание совсем,
   но снимает тесноту внутри плитки. Числа замера на 12.08.2026 — укорочено подписей:
   1440 → пять из семи · 1920 → одна · 2464 и 2560 → ни одной. */
@media (max-width: 100rem) {
  .cards--categories .card__name {
    font-size: calc(var(--t-s) * .84);
    letter-spacing: 0;
  }
}

@media (max-width: 56rem) {
  .cards.cards--categories {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* ⚠️ Две колонки на телефоне повторены ИМЕННО ДЛЯ ГЛАВНОЙ, потому что шестёрка выше
     написана двумя именами и весом побеждает одноимённое правило рядом. Без этой строки
     телефон получил бы шесть колонок по 40 точек. */
  .blok--katalog .cards.cards--categories {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* 🔴 НА ТЕЛЕФОНЕ МЕСТО ПОД КНОПКУ ПОМОЩНИКА НЕ ОТВОДИТСЯ, И ЭТО НЕ ЗАБЫТЫЙ СЛУЧАЙ.
     Замер 12.08.2026 на 390×844: ряд идёт в две колонки и занимает 532 точки по высоте,
     то есть три экрана прокрутки, а кнопка закреплена у нижнего края окна и плывёт над
     содержимым всегда. Отними справа её ширину (59 точек плюс отступ) — плитка похудеет
     с 166 до 134 точек, подписи укоротятся сильнее, а кнопка всё равно останется лежать
     поверх ряда: она перекрывает его не сбоку, а по высоте.

     Поэтому поля на телефоне остаются равными, 6 % с каждой стороны. */
  .blok--katalog .cards.cards--categories {
    margin-right: var(--pole-okna);
  }
}

/* ── Зазор между плитками ─────────────────────────────────────────────────
   Свой зазор у ряда разделов: общий `--o-5` держит ещё три товарные сетки, и правка
   там поехала бы на страницах каталога. Число подбирается глазами вместе с шириной
   плитки — инструмент `../ozelenenie/maket/plitki-v2/razmer_plitok.py`. */
.cards.cards--categories {
  gap: clamp(10px, 0.812vw, 20px);
}

/* ── Фон уходит из фокуса под самим рядом ─────────────────────────────────────
   🔴 ПРОБА ПО СЛОВУ КИРИЛЛА 11.08.2026: «у нас все еще деревья на фоне деревьев»,
   и на выбор из шести приёмов он взял этот — «снять с фона резкость именно под рядом,
   плитки остаются единственным резким».

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

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

   ⚠️ Это ВТОРОЙ `backdrop-filter` на сайте, и он заведён осознанно: первый стоит у шапки
   (`--steklo-blur-shapki`). Строка запрета в `tokens.css` относилась к стеклу карточек —
   там размывать нечего, снимок непрозрачен и закрывает подложку целиком.
   Разбор — `../ozelenenie/maket/plitki-v2/proverka_c.py`. */
.cards.cards--categories {
  position: relative;
}

/* 🔴 РАЗМЫТИЕ СОБРАНО ИЗ ДВУХ СЛОЁВ, А НЕ ИЗ ОДНОГО, И ЭТО НЕ УКРАШЕНИЕ.
   Правка Кирилла 11.08.2026, дословно: «рамка чуть выходит капельку за края от иконок…
   давай ПЛАВНЫМ смазыванием, чем ближе к концу рамки - тем меньше размытия фона. а внутри
   рамки как по центру такое размытие не надо, некрасиво, слегка размыто, а мы сделал
   грязное стекло прям».

   Причина обеих бед одна: `backdrop-filter` не умеет менять силу по площади. Один слой
   с `blur(16px)` даёт всюду одинаковое сильное размытие, а маска гасит его прозрачностью —
   и на границе прозрачности видна кромка плашки, та самая, что он обвёл.

   Лечится так, как это делают в отрасли — послойно. Первый слой слабый и растянут на всю
   зону с длинной растушёвкой; второй сильнее, но живёт только в середине и гаснет задолго
   до края. Сумма даёт силу, убывающую к краям постепенно, и ни одной видимой границы. */
.cards.cards--categories::before,
.cards.cards--categories::after {
  content: "";
  position: absolute;
  z-index: -1;
  border-radius: 4rem;
  pointer-events: none;
}

/* 🔴 СЛОЙ ПЕРВЫЙ — ТОТ, ЧТО ПРЯЧЕТ ГРАНИЦУ, и потому он самый слабый и самый широкий.
   Правка Кирилла 11.08.2026 со стрелками на стволы фоновой ели справа от ряда: «давай
   совсем минимальное размезывание по краям от рамок где я показал, посмотри какой
   некрасивый выперающий переход остается, где уже реальная елка или дерево».

   Что было не так: маска гасла на 92 % радиуса, то есть довольно быстро, и её край попадал
   ровно на резкие стволы фона — глаз ловил ступень. Теперь зона шире плиток на четыре
   пальца, а сила падает четырьмя ступенями и приходит к нулю на самом краю: у границы
   размытие практически нулевое, и сравнивать глазу нечего. */
.cards.cards--categories::before {
  inset: -10rem -8rem;
  /* 🔴 ЗАТЕМНЕНИЕ ИДЁТ ОТДЕЛЬНОЙ КРАСКОЙ, А НЕ ПОБОЧНЫМ ДЕЙСТВИЕМ ФИЛЬТРА.
     Правка Кирилла 11.08.2026: «затемнение по периметру полностью пропало». Оно и правда
     пропало: в первой пробе тень давал `saturate(.9)` при сильном размытии, а когда
     размытие ослабили до двух точек ради плавного края, вместе с ним ушла и тень.
     Теперь это своя заливка под той же маской — гаснет к краям вместе с размытием. */
  /* Плотность выбрана Кириллом 11.08.2026 из трёх предложенных: «на четверть темнее»
     и «ровно по всей зоне». Поэтому тень целиком живёт здесь, у широкого слоя,
     а ближний её больше не добавляет — иначе в середине выходило бы гуще, чем по краям. */
  background: var(--ten-zony-plitok);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  /* Затухание идёт по двум осям отдельно и перемножается (`intersect`), поэтому сила
     падает и вверх-вниз, и вбок — как показано стрелкой на его снимке. Радиальная маска
     так не умеет: она гасит кольцом, и кольцо ложится поперёк фона видимой дугой.
     Сами градиенты лежат в палитре: они набраны кодами цвета, а тем в файле дорожки
     не место (проверка 9А-0в-01). */
  mask-image: var(--maska-zony-sverhu-vniz), var(--maska-zony-vbok);
  /* ⛔ ВЕБКИТОВСКИХ ДУБЛЕЙ ЗДЕСЬ НЕТ, И ЭТО НЕ ЗАБЫВЧИВОСТЬ. `-webkit-mask-composite`
     понимает другой набор значений (`source-in` вместо `intersect`) и, будучи объявленным
     рядом, ПЕРЕБИВАЕТ стандартное свойство. 11.08.2026 из-за этой пары маски перестали
     перемножаться, зона превратилась в сплошной прямоугольник с резкой кромкой, и Кирилл
     видел её глазами, пока замер показывал «всё применилось». Проверка — не наличие строки
     в файле, а `getComputedStyle(el, '::before').maskComposite`: там должно стоять
     `intersect, intersect`. */
  mask-composite: intersect;
}

/* Слой второй: чуть больше мягкости вплотную к плиткам. Он маленький и гаснет задолго
   до края зоны первого слоя, поэтому в сумме сила убывает от рамки к краю до почти нуля. */
.cards.cards--categories::after {
  inset: -3rem -2.5rem;
  /* Своей тени у ближнего слоя нет: вся темнота отдана широкому, чтобы зона была затемнена
     равномерно — выбор Кирилла 11.08.2026. Здесь остаётся только мягкость у самых плиток. */
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
  /* 🔴 РАДИУСЫ МЕНЬШЕ ПОЛОВИНЫ РАЗМЕРА СЛОЯ, И ЭТО НЕ ПОДБОР ЧИСЕЛ НА ГЛАЗ.
     У `radial-gradient` проценты считаются от ВСЕЙ ширины и высоты элемента, а не от
     половины. Со значениями 85 % и 80 % эллипс выходил за края слоя, маска не успевала
     сойти на нет и обрывалась на его границе — получалась та самая кромка, которую Кирилл
     видел над рядом 11.08.2026.

     Замер, которым это поймано (`kto_daet_styk.py`): перепад яркости в полосе над рядом
     3,14 единицы при обоих слоях · 1,9 при выключенном этом слое · 3,2 при выключенном
     широком. То есть кромку давал именно он.

     Здесь радиусы 62 % и 42 %: маска приходит к нулю ВНУТРИ слоя, и обрывать нечего. */
  mask-image: var(--maska-zony-blizhnyaya);
}

/* ── Бронзовая обводка ─────────────────────────────────────────────────────── */
/* 🔴 ТРЕБОВАНИЕ КИРИЛЛА 06.08.2026, дословно: «добавь каждому из 8 окошек обводку
   бронзво-золотую нашу как у окна наши работы снизу экрана». «Окно наши работы» — это панель
   «Проекты» в ленте главной (`home.css`, `.blok--proekty`), и её рамка набрана `--akcent-detal`.
   Здесь стоит ссылка на ту же роль через `--kromka-razdela`, а не второй такой же цвет:
   две бронзы на одной странице разъехались бы на первой правке палитры, и МОЛЧА.

   Восемь плиток — это семь опубликованных разделов каталога плюс «Сажаем сейчас». Правило
   написано от СЕТКИ разделов, поэтому накрывает все восемь разом и ни одной товарной плитки
   не задевает: на страницах товара сетка называется без `--categories`.

   ⚠️ СЕЛЕКТОР ИЗ ДВУХ ИМЁН ОБЯЗАТЕЛЕН. Одноимённое правило в `card.css` весит один класс,
   и при равном весе побеждал бы файл, подключённый позже; на главной и в корне каталога
   порядок подключения разный, и правило проиграло бы на одной из двух страниц без единого
   признака в браузере.

   ⚠️ ПЛИТКА «САЖАЕМ СЕЙЧАС» ТЕРЯЕТ ЗДЕСЬ СВОЮ ЗЕЛЁНУЮ КРОМКУ (`home.css`,
   `--kromka-glavnaya`, вес один класс) и получает общую бронзовую — так и просили,
   «каждому из 8». Выделенной она остаётся зелёной заливкой и зелёной подписью, то есть
   двумя признаками из трёх. */
.cards--categories .card {
  border-color: var(--kromka-razdela);
  /* Ход у плитки раздела свой, длиннее общего: 300 мс читаются как отклик кнопки,
     520 мс с длинным выходом — как движение предмета, у которого есть вес. */
  transition: transform var(--hod-plavno);
}

/* Приподнимается выше товарной (10 точек против 6): плитка раздела крупнее, и на её размере
   шесть точек читаются как дрожание, а не как подъём. */
.cards--categories .card:hover {
  transform: translateY(-10px);
}

/* 🔴 ПОД КУРСОРОМ ЗАЖИГАЕТСЯ БРОНЗОВОЕ КОЛЬЦО СО СВЕЧЕНИЕМ, А НЕ ПЕРЕКРАШИВАЕТСЯ РАМКА.
   Слой `.card::after` уже лежит готовым (`card.css`) и проявляется прозрачностью; ему
   здесь меняются только краска кольца и тень, а анимируется по-прежнему ОДНА прозрачность.
   Прямая запись «переход по `box-shadow` и `border-color`» короче и запрещена замером:
   тень браузер пересчитывает каждый кадр заново, прозрачность отдаёт видеокарте. */
.cards--categories .card::after {
  border-color: var(--kromka-razdela-navedenie);
  box-shadow: var(--oreol-razdela);
  transition: opacity var(--hod-plavno);
}

/* ── Название раздела поверх снимка ───────────────────────────────────────── */
.cards--categories .card__link {
  padding-bottom: 0;
}

/* ⚠️ ВУАЛЬ ПО КРАЮ СНИМКА СНЯТА 12.08.2026 — слово Кирилла: «на главной с плиток убираем
   вуаль, которую делали вчера». Она заводилась днём раньше, чтобы растение у края кадра
   не вытекало в живой фон; после того как под рядом появилась зона размытия, край держит
   она, и вуаль стала второй границей на том же месте.

   Затемнение низа под подписью остаётся: на нём стоит читаемость подписи, замер даёт
   91–96 по APCA при пороге 60. */
.cards--categories .category-card__frame::after {
  background: var(--zatemnenie-podpisi-razdela);
}

.category-card__podpis {
  position: absolute;
  z-index: 2;
  inset: auto 0 0 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--o-2);
  padding: var(--o-3) var(--o-4);
  pointer-events: none;
}

/* 🔴 ПОДПИСЬ ВСЕГДА В ОДНУ СТРОКУ, ДЛИННОЕ ИМЯ ОБРЕЗАЕТСЯ МНОГОТОЧИЕМ. Правило Кирилла,
   данное сначала меню каталога 11.08.2026 («обрезание делай, в чём сложность?», «не надо
   расширять окно»), а потом и плиткам: подпись живёт внутри кадра, и расширять кадр под
   длинное имя нельзя — поедет весь ряд.

   Замер 12.08.2026 показал, что на плитках правила не было вовсе: «Декоративные лиственные»
   занимало 69 точек при межстрочном 17 — ЧЕТЫРЕ строки, со словом, разорванным посередине
   без переноса. Стрелка при этом висела по центру блока, напротив третьей строки.

       окно 1440 → 69 точек (4 строки) · 1920 → 34 (2) · 2464 → 17 (1)

   То есть однострочный вид получался случайно, только там, где колонка достаточно широка.

   ⚠️ `min-width: 0` обязателен: подпись лежит во flex-строке со стрелкой, а элемент flex
   по умолчанию не сжимается меньше своего содержимого — без этой строки `overflow: hidden`
   не сработает и обрезания не будет. */
.cards--categories .card__name {
  min-width: 0;
  overflow: hidden;
  margin: 0;
  color: var(--tekst);
  font-family: var(--shrift-teksta);
  font-size: var(--t-s);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: .02em;
  text-align: left;
  text-overflow: ellipsis;
  text-shadow: var(--ten-teksta);
  white-space: nowrap;
  transition: transform var(--hod-plavno);
}

.category-card__strelka {
  flex: 0 0 auto;
  color: var(--akcent-detal);
  font-size: var(--t-m);
  line-height: 1;
  text-shadow: var(--ten-teksta);
}

/* 🔴 РАМКЕ ВОЗВРАЩЕНО ОТНОШЕНИЕ 4:3 — слово Кирилла 11.08.2026: «нам нужна вуаль на той же
   рамке что была». Пока рамка забирала остаток ячейки, кадр вытягивался в вертикальный
   (замер: 268x458 против 268x201), у деревьев обрезались бока, а вуаль по краю снимка
   ложилась на кадр другой формы, чем тот, который он смотрел и выбрал. */
.cards--categories .category-card__frame {
  flex: none;
  aspect-ratio: 4 / 3;
  min-height: 0;
}

.cards--categories .card:hover .card__name {
  transform: translateY(-2px);
}

/* ── Появление плитки при прокрутке ────────────────────────────────────────── */
/* 🔴 ДВИЖЕНИЕ ПРИВЯЗАНО К ПРОКРУТКЕ, А НЕ К ЗАГРУЗКЕ СТРАНИЦЫ, и скрипта здесь нет ни строки.
   Блок разделов — второй экран ленты главной: анимация «при загрузке» отыграла бы, пока
   человек смотрит первый экран, и до плиток он доехал бы к уже отработавшему движению.

   `animation-timeline: view()` делает браузер тем же, чем `reveal.js` показывает развороты
   на странице проектов. Скрипт там нужен по своей причине — он ставит начальную прозрачность
   сам, иначе страница без JavaScript осталась бы пустой навсегда. Здесь этой опасности нет
   вовсе: правило целиком лежит внутри `@supports`, и браузер, который прокруточных дорожек
   не знает, просто показывает плитки как показывал.

   🔴 ДВИГАЮТСЯ `translate` И `scale` ОТДЕЛЬНЫМИ СВОЙСТВАМИ, А НЕ ЧЕРЕЗ `transform`.
   Это не манера записи. `transform` занят наведением, а свойство, которое анимируется,
   перебивает обычное объявление — плитка перестала бы приподниматься под курсором совсем.
   Найти это было бы нечем: оба правила по отдельности верны, и браузер молчит. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .cards--categories .card {
      animation: vyezd-plitki-razdela linear both;
      animation-timeline: view();
      /* 🔴 ДВИЖЕНИЕ КОНЧАЕТСЯ ТАМ, ГДЕ ПЛИТКА ЦЕЛИКОМ ВОШЛА В ЭКРАН, А НЕ ЧЕТВЕРТЬЮ ПУТИ
         ПОЗЖЕ. Здесь стояло `entry 10% cover 25%`, и вот что это значило на главной: ряд
         разделов виден СРАЗУ, без единого движения колеса, а «cover 25 %» до него ещё
         не доехало — плитки замирали на прозрачности 0,845 и оставались такими, пока
         человек не тронет страницу.

         Ломается это не движением, а снимками: сквозь полупрозрачную плитку просвечивает
         тёмный фон, и фотографии растений выглядят притушенными. Замер 12.08.2026, средняя
         яркость кадра из 255: «Плодовые деревья» 95,2 против 109,1 у непрозрачной плитки,
         «Хвойные» 134,7 против 154,8, «Декоративные лиственные» 131,1 против 146,8 — то есть
         снимок терял до пятой части яркости. Кирилл: «на всех фото на плитках затемнение,
         затемнение должно было быть СЗАДИ плиток, а не поверх них».

         ⚠️ Зоны затемнения первого экрана к этому непричастны, и это тоже замерено: их вклад
         в яркость кадра 0,3–0,9 из 255. Причина была одна — сама плитка. */
      animation-range: entry 10% entry 100%;
    }
  }
}

@keyframes vyezd-plitki-razdela {
  from {
    opacity: 0;
    translate: 0 28px;
    scale: .96;
  }

  to {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }
}

/* ── Рамка значка ─────────────────────────────────────────────────────────── */
/* 🔴 ЭТО ТО, ЧТО ДЕРЖИТ ОДИНАКОВЫЙ РАЗМЕР ЯЧЕЕК, и единственное место плитки раздела
   с ЗАДАННОЙ высотой. Соотношение сторон 4:3 повторяет место снимка на утверждённом макете
   и совпадает с рамкой снимка товарной плитки (`card.css`, `.card__photo`): плитка раздела
   и плитка товара стоят на одной странице, и разъедься эти два числа — сетка поехала бы
   ступеньками.

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

   🔴 Подложка рамки — САМАЯ ГЛУБОКАЯ из ролей, и это не вкус, а видимость границы: полотно
   страницы и подложка плитки различаются слабо, и возьми рамка цвет полотна — верхний край
   плитки просто исчез бы, а на макете плитка читается как предмет целиком. Значок нарисован
   песочным по такому же глубокому фону — он стоит ровно в той гамме, в какой нарисован. */
/* 🔴 РАМКА ЖИВЁТ ПО ТЕМ ЖЕ ПРАВИЛАМ, ЧТО РАМКА СНИМКА У ТОВАРНОЙ ПЛИТКИ (`card.css`,
   `.card__frame`), и это не совпадение вкуса: обе стоят в одном ряду на главной, и разъедься
   они — сетка читалась бы как две разные сетки.

   ⛔ ЗДЕСЬ СТОЯЛ ПЕРЕХОД ПО ФОНУ: под курсором рамка перекрашивалась из одного градиента
   в другой. Убрано переносом v10 (раздел 8, запрет 3): в переходах меняются только `transform`
   и `opacity`, а перекраску браузер считает каждый кадр заново. Отклик на курсор остался
   и стал заметнее — снимок наезжает, а сверху зажигается пятно света.

   `overflow: hidden` переехал сюда с плитки: обрезать увеличенный снимок по скруглённому углу
   должен тот, кто его показывает, — у самой плитки обрезка съедала бы её же тень.

   `flex: none` обязателен: иначе длинное название в соседней плитке сжало бы рамку по высоте,
   и снимки поехали бы разного размера — то есть вернулась бы ровно та беда, от которой рамка
   и заведена. */
.category-card__frame {
  position: relative;
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: calc(var(--r-l) - 1px);
  background: var(--steklo-plitka);
}

/* Пятно света под курсором — то же, что у товарной плитки, и по той же причине неподвижное:
   ходить за мышью оно умеет только со скриптом, который ставит ему координаты, а мёртвое
   правило с запасным значением выглядело бы работающим и не работало. */
.category-card__frame::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: radial-gradient(70% 60% at 50% 0%, var(--blik-navedeniya), transparent 70%);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--hod-medlenno);
}

.card:hover .category-card__frame::before { opacity: 1; }

/* Низ снимка затемнён, потому что под ним стоит название раздела: без затемнения светлые
   буквы ложатся на светлую крону и не читаются. */
.category-card__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--zatemnenie-snimka);
  pointer-events: none;
}

/* 🔴 ВУАЛЬ ПО КРАЮ СНИМКА — выбор Кирилла 11.08.2026 из семи вариантов, снятых на стенде.
   Растение у краёв кадра переходило в живой фон страницы без единого перепада: замер
   10.08.2026 дал контраст снимка у края против фона Lc 9,6 у плодовых и у хвойных при
   уровне 30, ниже которого APCA считает границу неразличимой.

   ⚠️ ПОЧЕМУ НЕ КРОМКА. Тонкую кромку и мягкую тень мы пробовали первыми, и они проиграли
   замеру: правка сдвигала цвет на 0,5–1,4 из 255, то есть глаз её не видел вовсе. Линия
   в одну точку не читается поверх видео, сколько её ни крась, — это её физика, а не наш
   подбор чисел.

   Слой уже стоит готовым (`::after` выше, затемнение низа), поэтому вуаль ложится на него
   тенью внутрь и не заводит ни нового элемента, ни нового слоя отрисовки.

   Правило написано от СЕТКИ разделов: у товарной плитки свой снимок и своя задача,
   и накрой мы её заодно — поехали бы три страницы каталога вместо одной. */

/* Значок тянется вместе с плиткой (доля, а не точки): у файла нет ни `width`, ни `height`,
   только область просмотра, поэтому размер задаётся здесь и в одном месте. Область просмотра
   у всех файлов значков одна и та же квадратная, поэтому широкая лейка и узкая ёлка стоят
   на плитках в том же соотношении, в каком нарисованы на общем листе. */
.category-card__icon {
  display: block;
  width: 42%;
  transition: transform var(--hod-medlenno);
}

.card:hover .category-card__icon { transform: scale(1.08); }

/* 🔴 ФОТОГРАФИЯ РАЗДЕЛА ЗАПОЛНЯЕТ РАМКУ ЦЕЛИКОМ. Спецификация v8, пункт 8.

   `object-fit: cover` обрезает снимок по короткой стороне вместо того, чтобы сплющить
   его: наши снимки сделаны 4:3 ровно под эту рамку, но плитка на узком экране может
   получить другое соотношение, и растянутое дерево видно сразу.

   ⚠️ `<picture>` вокруг снимка — это элемент разметки, а не рамка: по умолчанию он ведёт
   себя как строчный, и снимок внутри флексовой рамки встал бы не во всю её высоту.
   Поэтому размеры задаются и ему тоже.

   🔴 ПРИБЛИЖЕНИЕ ПОДНЯТО 1,04 → 1,09 И ЗАМЕДЛЕНО. Требование Кирилла 06.08.2026:
   «добавь сочную дорогую анимацию для этих ui-окошек». Прежние 1,04 за 300 мс на снимке
   размером в 300 точек дают сдвиг края в шесть точек — глаз его почти не ловит.
   Наезд остаётся МЕДЛЕННЕЕ подъёма самой плитки, и это не совпадение чисел: когда снимок
   и плитка едут с одной скоростью, кадр читается приклеенным к рамке. */
.category-card__frame picture {
  display: block;
  width: 100%;
  height: 100%;
}

.category-card__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--hod-plavno);
}

.card:hover .category-card__photo { transform: scale(1.09); }

/* Человек, попросивший систему убрать движение, получает неподвижную плитку: свет зажигается
   мгновенно, снимок и значок не наезжают вовсе. То же правило стоит у товарной плитки.

   🔴 СЮДА ДОПИСАНЫ ВСЕ ЧЕТЫРЕ НОВЫХ ДВИЖЕНИЯ 06.08.2026 — подъём плитки, наезд снимка,
   подъём подписи и свечение кольца. Пропусти одно, и человек с отключённой анимацией
   получил бы плитку, которая частью стоит, а частью едет; выезд при прокрутке сюда
   не дописывается, потому что он и не включается вовсе — он стоит внутри
   `prefers-reduced-motion: no-preference` выше. */
@media (prefers-reduced-motion: reduce) {
  .category-card__frame::before,
  .category-card__icon,
  .category-card__photo,
  .cards--categories .card,
  .cards--categories .card::after,
  .cards--categories .card__name {
    transition: none;
  }

  .card:hover .category-card__icon,
  .card:hover .category-card__photo,
  .cards--categories .card:hover,
  .cards--categories .card:hover .card__name {
    transform: none;
  }
}
