/* ============================================================
   Hakku 2.0 — Landing layer (ui_kits/landing)
   ------------------------------------------------------------
   Опциональный слой поверх hakku.css для лендингов и колодцев
   (data-mode="comm"). Продуктовым поверхностям не нужен.

     <link rel="stylesheet" href="design_system/hakku.css">
     <link rel="stylesheet" href="design_system/ui_kits/landing/landing.css">

   Слой решает три задачи, которые в ядре не описаны:
     1. цветной акцент без заливки — линии, тонировки, цифры;
     2. экранный ритм секций;
     3. ленты-разделители с полотном.

   Все значения — семантические токены ядра. Своих цветов слой
   не заводит, кроме промежуточного фиолетового цикла линеек.
   ============================================================ */

/* ============ 1. АКЦЕНТ ====================================
   Правила, по которым лендинг получает цвет, не превращаясь
   в раскраску:

     — цвет несёт смысл (позиция на пути, направление, ступень),
       декоративной заливки нет;
     — заливка цветом не крупнее чипа (7–10% альфы), крупные
       плоскости остаются бумагой или чернилами;
     — один акцент на секцию; цикл из четырёх тонов — только
       там, где это последовательность;
     — градиент — редкий «момент» (шкала прогресса, кромка
       футера, одно слово), не фон;
     — текст, заголовки и хайрлайны цвета не берут.
   ============================================================ */

/* ---- Линии отступа: цветная линейка над блоком -------------
   Даёт структуру и цвет ценой нулевой площади заливки.
   Заменяет карточку-коробку там, где рамка избыточна. */
.rule {
  padding-top: var(--s-4);
  border-top: 3px solid var(--border);
}
.rule-thin { border-top-width: 2px; }
.rule-hair { border-top-width: 1px; }

/* ---- Та же линейка, вертикально -----------------------------
   Связь «этап → его карточки» (Products.jsx) держится линейкой сбоку
   колонки, а не сверху: `.rule` на весь блок даёт линию-шапку, это
   другой смысл (граница секции, а не связь этапа с его карточками).
   `.rule-v` — самостоятельный вариант того же приёма, с той же схемой
   (padding + border, 3px по умолчанию), только на левом крае вместо
   верхнего. `.rule-thin`/`.rule-hair` его не трогают — они управляют
   только `border-top-width` и остаются вариантами горизонтальной
   линейки; про запас вертикальные веса не заводим (не просили). */
.rule-v {
  padding-left: var(--s-4);
  border-left: 3px solid var(--border);
}

/* Тона переиспользуют семейство `.rule*` целиком — заявлены один раз
   через `border-color` (все стороны), а не `border-top-color`: у
   `.rule` только верх имеет width+style, у `.rule-v` только левый край,
   остальные стороны остаются `border-style: none` и `border-color` на
   них ни на что не влияет. Так один и тот же `.rule-blue` красит и
   горизонтальную, и вертикальную линейку без второго набора классов
   и без новых переменных цвета. */
.rule-blue    { border-color: var(--blue); }
.rule-violet  { border-color: #7A2CB4; }   /* середина цикла синий→маджента */
.rule-magenta { border-color: var(--magenta); }
.rule-orange  { border-color: var(--orange); }
.rule-ink     { border-color: var(--fg); }

/* Автоцикл по группе — для последовательностей (кейсы, шаги,
   продукты этапа). Тем же приёмом (border-color) цикл работает и на
   `.rule`, и на `.rule-v` — какая сторона видна, решает базовый класс
   элемента, не цикл. */
.rules-cycle > *:nth-child(4n + 1) { border-color: var(--blue); }
.rules-cycle > *:nth-child(4n + 2) { border-color: #7A2CB4; }
.rules-cycle > *:nth-child(4n + 3) { border-color: var(--magenta); }
.rules-cycle > *:nth-child(4n + 4) { border-color: var(--orange); }

/* ---- Цифры ------------------------------------------------
   .numeral (Tektur, tnum, tight) живёт в ядре — здесь только
   тона и кегли. Оранжевый на бумаге слишком светлый, поэтому
   текстовый вариант затемнён. */
.numeral-blue    { color: var(--blue); }
.numeral-violet  { color: #7A2CB4; }
.numeral-magenta { color: var(--magenta); }
.numeral-orange  { color: #C25A02; }

.numeral-xl { font-size: clamp(3rem, 6vw, 4.75rem); display: block; }
.numeral-lg { font-size: clamp(2rem, 3.4vw, 2.75rem); display: block; }

/* ---- Тонированные плашки ---------------------------------- */
.tint {
  background: rgba(42, 62, 244, 0.07);
  color: var(--blue);
  border: 1px solid transparent;
}
.tint-violet  { background: rgba(122, 44, 180, 0.08); color: #7A2CB4; }
.tint-magenta { background: rgba(213, 31, 117, 0.08); color: var(--magenta); }
.tint-orange  { background: rgba(253, 114, 2, 0.10);  color: #C25A02; }

/* На чернильном полотне тонировка не читается — переводим в
   полупрозрачную бумагу с цветной обводкой. */
[data-canvas="ink"] .tint,
[data-theme="dark"] .tint {
  background: rgba(42, 62, 244, 0.18);
  color: #A8B4FF;
  border-color: rgba(168, 180, 255, 0.35);
}

/* ---- Плоская решётка статистики ---------------------------
   Клетки на 1px хайрлайне, линии сверху и снизу, без скруглений
   и боковых границ. Паддинг меньше базового .lattice: решётка
   стоит в секциях, обязанных влезать в экран. */
.lattice-flush {
  border-radius: 0;
  border-left: 0;
  border-right: 0;
}
.lattice-flush > * { padding: var(--s-5) var(--s-4); }

/* ---- Градиентная линия — «момент», не фон ------------------ */
.grad-rule {
  height: 2px;
  border: 0;
  margin: 0;
  background: var(--grad-full);
}

/* ---- Eyebrow акцентом ------------------------------------- */
.eyebrow-accent { color: var(--accent); }

/* ---- Обводка акцентом (карточка, на которую смотрим) ------ */
.outline-accent { border: 1px solid var(--blue) !important; }

/* ============ 2. ЭКРАННЫЙ РИТМ =============================
   Ключевые секции лендинга занимают ровно один экран.

   Всегда min-height, НЕ height: на 13" ноуте и в зуме контент
   выше вьюпорта, и жёсткая высота его срежет. Ритм держится
   там, где места хватает, и отпускает там, где нет.

   Если секция не добирает до экрана — растёт её контент,
   а не отступы и не разделитель.
   ============================================================ */
:root {
  --screen-h: calc(100dvh - var(--topbar-h, 72px));
  --band-h: clamp(96px, 12vh, 152px);
}

.screen,
.screen-with-band,
.screen-between-bands {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.screen { min-height: var(--screen-h); }
/* Секция + следующая за ней лента вместе дают один экран */
.screen-with-band { min-height: calc(var(--screen-h) - var(--band-h)); }
/* Лента + секция + лента вместе дают один экран */
.screen-between-bands { min-height: calc(var(--screen-h) - 2 * var(--band-h)); }

/* На коротких экранах ритм отключается — иначе контент жмётся */
@media (max-height: 640px), (max-width: 768px) {
  .screen, .screen-with-band, .screen-between-bands { min-height: 0; }
}

/* ============ 3. ЛЕНТА-РАЗДЕЛИТЕЛЬ =========================
   Полоса между секциями с полотном вместо плоской заливки.
   Полотно — фрейм F9 по imagery/README.md.

   Высота одна на весь сайт и не настраивается: разделитель —
   элемент ритма, а не способ добрать высоту секции.

   Контракт полотна: слой задаёт только геометрию (.band — высота,
   overflow, тёмная подложка на случай, если картинки ещё нет) и вуаль
   (.band-veil — градиент под текстом). Само изображение — .band > img —
   подставляет потребитель; здесь имён конкретных полотен нет и не
   будет. Откуда брать картинку: imagery/README.md, фрейм F9 (раздел 5,
   «разделитель между секциями»); своих модификаторов-имён полотна
   (`.band-*`) слой не заводит — мотив живёт в файле, а не в классе.
   Лента без картинки (как в ui_kits/landing/example/) — законное
   состояние: голый `.band` на тёмной подложке, без `.band-veil`,
   потому что вуали без текста нечего скрывать.
   ============================================================ */
.band {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  min-height: var(--band-h);
  display: flex;
  align-items: center;
}
.band > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Полотно — подложка под текст, не самостоятельная картинка:
     приглушение по умолчанию, потребитель переопределяет opacity
     только когда нужно иначе. */
  opacity: 0.9;
}
/* z-index обязателен: вуаль рисуется псевдоэлементом ::after,
   то есть последней, и без подъёма легла бы поверх текста. */
.band > .band-content { position: relative; z-index: 1; }

/* Вуаль под текстом ленты. У пустых лент-проставок её нет —
   полотно видно в полную силу. */
.band-veil::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(0,0,0,.86) 0%, rgba(0,0,0,.72) 45%, rgba(0,0,0,.42) 100%);
}

/* ============ 4. СОСТОЯНИЯ КАРТОЧЕК ========================
   Кликабельная карточка показывает это ховером и стрелкой,
   а не постоянным украшением: пять стрелок в ряд спорят
   с содержимым карточек.
   ============================================================ */
.product-card {
  transition: background var(--dur-fast, 150ms) var(--ease-brand, ease),
              transform var(--dur-fast, 150ms) var(--ease-brand, ease);
}
.product-card-arrow {
  opacity: 0;
  transform: scale(0.8);
  transition: opacity var(--dur-fast, 150ms) var(--ease-brand, ease),
              transform var(--dur-fast, 150ms) var(--ease-brand, ease);
}
/* Стрелка в цветном кружке — белая явным значением (LAYOUT.md §8):
   правило ядра .icon, svg.lucide { color: var(--fg-muted) } (0,0,1,1)
   красит любую lucide-иконку в чернила и без этого перебивает
   наследование от обёртки. Специфичность (0,0,2,1) — два класса,
   один тип — обязана перебить (0,0,1,1) независимо от порядка правил,
   как у .card-click-arrow (components/components.css). */
.product-card .product-card-arrow svg { color: var(--paper); }
@media (hover: hover) {
  .product-card:hover { background: var(--surface); transform: translateY(-2px); }
  .product-card:hover .product-card-arrow { opacity: 1; transform: scale(1); }
}
.product-card:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring, 0 0 0 3px rgba(42, 62, 244, 0.25));
}
.product-card:focus-visible .product-card-arrow { opacity: 1; transform: scale(1); }

/* ============ 5. НАВИГАЦИЯ — РАСКЛАДКА И ПОДСВЕТКА ПУНКТА ==
   Раскладка — здесь, а не на совести потребителя. hakku.ai собирает её
   поверх этого класса ещё раз через Tailwind (`flex items-center
   gap-1 lg:gap-2`) — рабочий, но избыточный слой: без него у любого
   потребителя без Tailwind (в т.ч. у ui_kits/landing/example/) пункты
   меню слипались бы в одно слово, потому что между `<a>` в JSX нет
   пробельных текстовых узлов. gap — var(--s-2) (8px), как в
   Tailwind-версии на проде (lg:gap-2). Ниже 1280px .nav-links целиком
   уходит в display:none (components/mobile.css, «.nav > .nav-links»,
   specificity 0,2,0) — это правило гасит раскладку ниже, конфликта нет:
   выше 0,1,0 текущего блока по specificity, порядок файлов не важен. */
.nav-links {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.nav-links a { position: relative; isolation: isolate; }
.nav-links a::before {
  content: "";
  position: absolute;
  inset: -2px -6px;
  z-index: -1;
  border-radius: var(--r-pill);
  background: var(--grad-full);
  filter: blur(10px);
  opacity: 0;
  transform: scale(0.9);
  transition: opacity var(--dur-fast, 150ms) var(--ease-brand, ease),
              transform var(--dur-fast, 150ms) var(--ease-brand, ease);
}
@media (hover: hover) {
  .nav-links a:hover::before { opacity: 0.21; transform: scale(1); }
}
.nav-links a:focus-visible::before { opacity: 0.21; transform: scale(1); }

/* Активный пункт — линейка акцентом */
.nav-links a.is-current { color: var(--fg); }
.nav-links a.is-current::after {
  content: "";
  position: absolute;
  left: var(--s-2);
  right: var(--s-2);
  bottom: 0;
  height: 2px;
  border-radius: 2px;
  background: var(--blue);
}

/* ============ 6. КНОПКА НА HALFTONE-ПОЛОТНЕ ================
   Растр — фон кнопки. Лента образца лежит в правой части
   кадра, поэтому подпись садится левее, на чистой бумаге.
   ============================================================ */
.btn-halftone {
  position: relative;
  overflow: hidden;
  background: var(--paper);
  color: var(--ink);
  border-color: transparent;
  padding-right: var(--s-7);
}
.btn-halftone > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: right center;
  opacity: 0.9;
}
.btn-halftone > span {
  position: relative;
  z-index: 1;
  text-shadow: 0 0 6px var(--paper), 0 0 12px var(--paper);
}
@media (hover: hover) { .btn-halftone:hover > img { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .product-card, .product-card-arrow, .nav-links a::before { transition: none; }
  .product-card:hover { transform: none; }
}

/* ============ 7. ЛЕНТА МАТЕРИАЛОВ ==========================
   Карточка контентного раздела. В покое — обложка, тег и заголовок;
   описание и мета выезжают на ховере: ряд читается картинками,
   а не пятью абзацами подряд.

   Сдвиг — transform на фиксированную высоту блока раскрытия, а не рост
   высоты: layout ради ховера не анимируем. Сдвигается вся нижняя группа
   целиком (тег, заголовок и блок раскрытия) — уезжает за нижний край
   ровно на высоту блока раскрытия, поэтому за краем прячется только он,
   а тег с заголовком встают на своё место без пустоты под ними. Одного
   сдвига мало: часть блока раскрытия геометрически остаётся в пределах
   карточки (высота считается от его собственного края, а не от края
   группы с отступом), поэтому он ещё и прозрачный в покое — ховер и
   `:focus-visible` снимают оба слоя разом. На тач-устройствах
   (hover: none) карточка сразу показывает всё — раскрывать там нечем.
   ============================================================ */
.media-card {
  --media-reveal: 74px;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  transition: transform var(--dur-fast, 150ms) var(--ease-brand, ease);
}
.media-card-body {
  transform: translateY(var(--media-reveal));
  transition: transform var(--dur-med, 250ms) var(--ease-brand, ease);
}
/* Высота блока раскрытия фиксирована, а не растёт по контенту — иначе
   ряд карточек с текстом разной длины разъезжается по высоте. Описание
   обрезано двумя строками, чтобы гарантированно уместиться. */
.media-card-more {
  height: var(--media-reveal);
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--dur-fast, 150ms) var(--ease-brand, ease);
}
.media-card-more p {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
@media (hover: hover) {
  .media-card:hover { transform: translateY(-2px); }
  .media-card:hover .media-card-body { transform: translateY(0); }
  .media-card:hover .media-card-more { opacity: 1; }
}
.media-card:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring, 0 0 0 3px rgba(42, 62, 244, 0.25));
}
.media-card:focus-visible .media-card-body { transform: translateY(0); }
.media-card:focus-visible .media-card-more { opacity: 1; }

/* Без ховера (тач) раскрывать нечем — карточка сразу показывает всё. */
@media (hover: none) {
  .media-card-body { transform: none; }
  .media-card-more { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .media-card, .media-card-body, .media-card-more { transition: none; }
  .media-card:hover { transform: none; }
}

/* ============ 8. ВИТРИНА И НАВИГАЦИЯ РАЗДЕЛА ===============
   Сжатие шапки: когда строка фильтров прилипает под шапку, две панели
   навигации друг на друге дают визуальный шум. Пункты размываются
   и уходят, по центру встаёт метка раздела из активного пункта —
   поэтому механика работает на любом колодце, не только в Медиа.

   Наведение и :focus-within возвращают шапку целиком: сжатие экономит
   внимание при чтении, но не должно мешать уйти в другой раздел.
   ============================================================ */

/* Витрина: заголовок материала подчёркивается на ховере — знак
   кликабельности там, где карточки нет и рамку рисовать нечем. */
.media-lead-title {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 4px;
  transition: text-decoration-color var(--dur-fast, 150ms) var(--ease-brand, ease);
}
@media (hover: hover) {
  .media-lead:hover .media-lead-title { text-decoration-color: var(--blue); }
}
.media-lead:focus-visible { outline: none; }
.media-lead:focus-visible .media-lead-title { text-decoration-color: var(--blue); }
@media (prefers-reduced-motion: reduce) { .media-lead-title { transition: none; } }

/* Контракт состояния: body.nav-condensed вешает JS-хук по скроллу
   (сентинел уходит под шапку) — здесь описан только внешний вид,
   не логика переключения. .nav-section лежит в .nav как третий
   ребёнок грида и центрируется абсолютным позиционированием
   поверх .nav-links, а не раскладкой — так проще держать её всегда
   по центру шапки независимо от ширины соседних блоков. */
.nav-section {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-display);
  /* Метка остаётся в шапке одна — размер берём на ступень заголовка карточки,
     иначе она читается подписью, а не названием раздела. */
  font-size: var(--t-h5);
  letter-spacing: -0.01em;
  color: var(--fg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-med, 250ms) var(--ease-brand, ease);
}
.nav-links {
  transition: opacity var(--dur-med, 250ms) var(--ease-brand, ease),
              filter var(--dur-med, 250ms) var(--ease-brand, ease);
}
body.nav-condensed .nav-links {
  opacity: 0;
  filter: blur(8px);
  pointer-events: none;
}
body.nav-condensed .nav-section { opacity: 1; }

/* Наведение на шапку возвращает её целиком: сжатие экономит внимание при
   чтении, но не должно мешать уйти в другой раздел. Фокус с клавиатуры
   работает так же — иначе пункты недостижимы без мыши. */
@media (hover: hover) {
  body.nav-condensed .nav:hover .nav-links { opacity: 1; filter: none; pointer-events: auto; }
  body.nav-condensed .nav:hover .nav-section { opacity: 0; }
}
body.nav-condensed .nav:focus-within .nav-links { opacity: 1; filter: none; pointer-events: auto; }
body.nav-condensed .nav:focus-within .nav-section { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .nav-section, .nav-links { transition: none; }
}

/* Метка страницы над заголовком раздела: прямые углы и хайрлайн, без
   заливки — чтобы не спорить с чипами типов материалов в ленте. */
.page-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-1) var(--s-3);
  border: 1px solid var(--border-strong);
  font-size: var(--t-caption);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg);
  white-space: nowrap;
}
.page-eyebrow-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--blue);
  flex: none;
}

/* ============ 9. ПУБЛИКАЦИЯ ================================
   Оглавление липкое, активный раздел подчёркнут: читатель длинного
   материала должен видеть, где находится, не возвращаясь наверх.

   Активный раздел считается по координате заголовка, а не
   IntersectionObserver — при быстрой прокрутке через несколько
   заголовков активным оставался случайный.
   ============================================================ */

/* Оглавление публикации: липкая колонка справа, активный раздел
   подчёркнут синим. Подчёркивание, а не заливка — по правилу
   «цвет несёт смысл, заливка не крупнее чипа».

   Сама липкость (position: sticky, отступ сверху calc(--topbar-h + --s-5))
   задаётся потребителем на обёртке — .publication-toc здесь только рамка
   и внутренний отступ, колонку в sticky ставит верстающий компонент. */
.publication-toc { border-left: 1px solid var(--border); padding-left: var(--s-4); }

/* Контракт активного пункта: потребитель вычисляет текущий раздел (по
   координате заголовка, см. шапку раздела) и ставит на ссылку
   data-active="true". Класс здесь описывает только вид состояния —
   логику вычисления несёт потребитель. */
.publication-toc-link {
  display: block;
  padding: var(--s-2) 0;
  font-size: var(--t-small);
  line-height: 1.3;
  color: var(--fg-muted);
  border-bottom: 2px solid transparent;
  transition: color var(--dur-fast, 150ms) var(--ease-brand, ease),
              border-color var(--dur-fast, 150ms) var(--ease-brand, ease);
}
.publication-toc-link[data-active="true"] {
  color: var(--fg);
  border-bottom-color: var(--blue);
}
@media (hover: hover) {
  .publication-toc-link:hover { color: var(--fg); }
}
@media (prefers-reduced-motion: reduce) {
  .publication-toc-link { transition: none; }
}

/* Крошки публикации: базовый отступ снизу рассчитан на страницы, где
   дальше идёт секция с собственным паддингом. В материале под ними сразу
   линейка рубрики — воздух между ними лишний. */
.publication-breadcrumbs nav { margin-bottom: var(--s-4); }

/* Таблицы research-разборов: один стиль на таблицу внутри контейнера
   .research-table вместо построчных классов. Целится в голый <table>,
   не в .table из ядра — разбор живёт в комм-режиме лендинга (мельче
   шрифт, паддинг без row-h), .table обслуживает продуктовый режим
   приложения; смысловые is-up/is-down здесь ядру не нужны вовсе. */
.research-table table { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.research-table th {
  text-align: left;
  padding: var(--s-2) var(--s-4);
  border-bottom: 1px solid var(--border);
  font-size: var(--t-caption);
  font-weight: 500;
  color: var(--fg-faint);
}
.research-table td { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--ink-08); color: var(--fg-muted); }
.research-table tr:last-child td { border-bottom: 0; }
.research-table td strong { color: var(--fg); }
.research-table .is-up { color: #1F7A4C; }
.research-table .is-down { color: var(--magenta); }

/* Типографика текста материала: мельче тела ядра (`--t-small` вместо
   `--t-body`) и с управляемым интервалом между абзацами — ядро задаёт
   только цвет и межстрочный интервал у голого `p`, здесь абзацы идут
   плотным списком внутри раскрывающихся блоков и разборов. Селектор
   `.research-prose p` конкретнее ядрового `p`, поэтому переопределяет
   его без `!important`. */
.research-prose p { font-size: var(--t-small); line-height: 1.65; color: var(--fg-muted); margin-bottom: var(--s-3); }
.research-prose p:last-child { margin-bottom: 0; }
.research-prose strong { color: var(--fg); }

/* Тот же текст на чернильной подложке (`data-canvas="ink"`): цвет там
   держит сама подложка через rgba(255,255,255,.85) на обёртке, поэтому
   здесь остаются только интервалы между абзацами и белый — для `strong`,
   у которого своего цвета иначе нет. Отдельным классом, а не через
   секционную инверсию токенов — потому что заливка на `.research-*`
   локальная (одна панель посреди светлого материала), а не тема всей
   секции. */
.research-ink-prose p { margin-bottom: var(--s-3); }
.research-ink-prose p:last-child { margin-bottom: 0; }
.research-ink-prose strong { color: #fff; }
.research-ink-prose li { padding: var(--s-2) 0; border-bottom: 1px solid rgba(255,255,255,.1); }
.research-ink-prose li:last-child { border-bottom: 0; }

/* ============ 10. ШАПКА СЕКЦИИ =============================
   Тонированная метка + цветная линейка над заголовком + подводка.
   Тон шапки задаёт акцент всей секции: всё акцентное внутри
   наследует именно его, перебор палитры внутри секции запрещён.

   Разметка: .section-head-eyebrow берёт `.tint*`, заголовок — `.rule*`
   того же тона — оба класса живут в разделе 1, здесь не дублируются.

   Кегль заголовка не переопределяется: `h2, .h2` из ядра уже даёт
   `--t-h2` (шкала), шрифт, вес, трекинг и цвет — здесь только отступ
   под линейку. Подводка — всегда 16px без адаптива: «14 на мобиле →
   16 на десктопе» давало бы разнобой между соседними секциями. */
.section-head { display: block; }
.section-head-eyebrow {
  display: inline-block; margin-bottom: var(--s-4);
  padding: 4px 12px; border-radius: 999px;
  font-size: var(--t-caption); font-weight: 600;
  text-transform: uppercase; letter-spacing: .04em;
}
.section-head h2 { margin-bottom: var(--s-4); }
.section-head-lead { font-size: var(--t-body); color: var(--fg-muted); max-width: 860px; }

/* ============ 11. СЕТКА КАРТОЧЕК ===========================
   Не путать с .lattice (раздел «LATTICE» в components/components.css):
   .lattice — решётка на ОБЩЕЙ границе для плотных ячеек статистики —
   одна рамка на весь блок, между ячейками только 1px хайрлайн
   (`gap: 1px` на подложке `--border`), внутренний clip по
   `--r-md`. У неё нет своего border/border-radius на детях — именно
   поэтому карточка со своей рамкой туда не встаёт: `.card` держит
   `border-radius: var(--r-lg)` (24px), крупнее clip-радиуса `.lattice`
   (`--r-md`, 16px) — на крайних ячейках угол обрезается не в размер,
   а собственный 1px бордер карточки задваивает решётчатый хайрлайн.
   Проверено на примере (ui_kits/landing/example/Proof.jsx): до этого
   раздела ряд карточек кейсов стоял на `.lattice lattice-3` именно
   с этим дефектом.

   .card-grid — раскладка ОТДЕЛЬНО СТОЯЩИХ карточек: каждая остаётся
   при своей рамке, тени и радиусе, между ними обычный зазор на `gap`,
   без общей рамки и без clip. Это самый частый приём лендинга (ряд
   `.card`, `.card-click`) — на сайте его сегодня даёт Tailwind
   (`grid grid-cols-3 gap-6` и близкие варианты); здесь — тот же
   результат средствами слоя, без стороннего фреймворка.

   Только два варианта, потому что только они и встречаются на сайте
   и в примере: 2 и 3 колонки. Третий вариант «про запас» не заводим.
   Брейкпоинт — 768px литералом (custom properties в @media не
   работают, см. tokens/mobile.css), это то же значение, что несёт
   токен `--bp-md`, и та же точка, на которой схлопывается `.lattice`. */
.card-grid {
  display: grid;
  gap: var(--s-5);
}
.card-grid-2 { grid-template-columns: repeat(2, 1fr); }
.card-grid-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 768px) {
  .card-grid-2, .card-grid-3 { grid-template-columns: 1fr; }
}

/* ============ 12. КОЛОНКА СЕКЦИИ ============================
   LAYOUT.md §4 «Раскладка секции»: текстовая колонка секции —
   половина ширины, граница блока проходит по центру секции. Колонка
   в 40% читается узкой лентой у края, а полотно перетягивает
   разворот на себя. Полотно при этом остаётся фоном ВСЕЙ секции
   (LAYOUT.md §4: «не картинка в рамке рядом с текстом») — класс
   отвечает только за ширину и положение текстовой колонки, фон и
   негативную зону полотна не рисует и не обрезает: они приходят
   картинкой, которую слой не поставляет (imagery/README.md).

   На узких экранах колонка занимает всю ширину — тот же брейкпоинт
   768px литералом, что и у `.card-grid-2/-3` выше: у полотна на узком
   экране уже нет второй половины, которую надо освобождать под него.
   ============================================================ */
.section-col {
  width: 100%;
  max-width: 50%;
}
@media (max-width: 768px) {
  .section-col { max-width: 100%; }
}

/* ---- Зеркальный вариант --------------------------------------
   Направления сайта чередуют сторону текста (F1 → F3 → F1,
   imagery/README.md §5): `.section-col-mirror` — тот же размер
   колонки, прижатый к правому краю контейнера вместо левого.

   Полотно зеркального блока — СВОЯ генерация с негативной зоной с
   другой стороны, а не CSS-отражение того же кадра: `transform:
   scaleX(-1)` запрещён (LAYOUT.md §4). Отражение переворачивает и
   типографику внутри картинки, если она там есть, и читается дешёвым
   трюком вместо отдельного сюжета — класс поэтому не пытается это
   решить сам, он только двигает колонку текста, изображение вне его
   ответственности. */
.section-col-mirror {
  margin-left: auto;
}
@media (max-width: 768px) {
  .section-col-mirror { margin-left: 0; }
}
