/* ==========================================================================
   Styles for Styles vs Trends (Maison&Objet 2026 Presentation)
   Derived strictly from Dela Design Tokens (_tokens.generated.css / _design.yaml)
   Inv-CSS-tokens-from-Spec: No literal hex overrides in :root.
   ========================================================================== */

/* Baseline & Reset */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  background-color: var(--surface);
  color: var(--ink);
  font-family: var(--sans);
  line-height: var(--lh-body);
  min-height: 100vh;
  transition: background-color 0.25s ease, color 0.25s ease;
}

/* ── ПОКАЗ СНЯТ (принципал 2026-08-20) ─────────────────────────────────────
   Здесь жили ДВА блока: хром переключателя подач (`.top-nav`, `.nav-brand`,
   `.btn-mode`, `.btn-icon`) и сцена 16:9 («HYPOSTASIS 2» — `.broadcast-*`,
   `.stage-*`, `.hud-*`, `.thumb-*`, `.btn-pill`, `.btn-ctrl`), а с ними
   двенадцать литеральных `--cinema-*` в `:root` — при том, что шапка ЭТОГО ЖЕ
   файла объявляет `Inv-CSS-tokens-from-Spec: No literal hex overrides in
   :root`. Вторая подача была РЕЖИМОМ над одним рядом единиц: она требовала
   собственной палитры, собственного слоя и собственного рендерера в браузере.
   Со снятием подачи всё это перестало иметь предмет — вместе с `z-index: 1000`
   у `.top-nav`, который накрывал тумблер темы (`z-index: 101`) и делал его
   недостижимым (замер `Inv-SITE-form-at-reader`: `button.theme-toggle` ←
   `header#topNav`, во всех шести условиях просмотра).
   ────────────────────────────────────────────────────────────────────────── */


/* ==========================================================================
   ИПОСТАСЬ 1: ДОКУМЕНТ (#doc) — ЕДИНСТВЕННАЯ РЕДАКЦИОННАЯ ПРОЕКЦИЯ

   Оформление цепляется за КООРДИНАТЫ, которыми рендерер уже назвал узел
   (`data-kind` — род, `data-role` — роль в станце, `data-field` — поле модели,
   `data-layout` — раскладка секции). Собственного словаря классов у страницы
   больше нет: прежде их было 122 — под разметку, которую рисовал ВТОРОЙ
   рендерер в браузере, и оформление не могло совпасть с документом даже в
   принципе (замер 2026-08-18: у читателя со скриптом не было ни одного
   <article>, 67 из 227 единиц прозы до него не доезжали).
   ========================================================================== */
#doc {
  /* ХОЛСТ, НЕ МЕРА. --max-width = потолок хаба (~50em); на широком экране он
     оставлял рассказ-показ островом в пустоте. --page — редакционный холст Spec
     (text/site.md); проза/речь ниже по-прежнему --measure. */
  max-width: var(--page);
  margin: 0 auto;
  padding: var(--space-section) var(--space-padding) var(--space-top);
}

#doc :is(h1, h2, h3, h4) { font-weight: 400; letter-spacing: var(--tracking-display); }
/* ОПТИЧЕСКОЕ СЖАТИЕ ДИСПЛЕЯ — РЕШЕНИЕ О СТРОЧНЫХ, И НА ПРОПИСНЫЕ ОНО НЕ РАСПРОСТРАНЯЕТСЯ.
   Строка выше берёт ВСЕ заголовки и потому молча перебивала закон: `_tokens.generated.css`
   эмитит `[data-case="upper"] { letter-spacing: var(--tracking-caps) }` со специфичностью
   (0,1,0), а `#doc :is(h1…)` имеет (1,0,1) и выигрывает — прописные приезжали к читателю
   с −0.02em, то есть СЛИПШИМИСЯ (Брингхерст §3.2.2; Мильчин §3.2.4). Закон при этом был
   зелен и прав: он определён на СУЩЕСТВОВАНИИ правила, а правило существует. Судит это
   теперь `Inv-SITE-form-at-reader::caps_tracking` — у читателя, по вычисленному стилю.
   Величина — `--tracking-caps-mid` (0.05em), а не ярлычная `--tracking-caps` (0.16em):
   крупный дисплейный капс при ярлычном просвете рассыпается. */
#doc :is(h1, h2, h3, h4)[data-case="upper"] { letter-spacing: var(--tracking-caps-mid); }
/* Домовый росчерк хаба (`h1::after { content: ' —' }`) — знак ИНДЕКСА, а не статьи;
   страницы-статьи снимают его тем же способом (`.article-wrapper h1::after`). Пока
   у страницы была своя таблица, вопрос не стоял: она просто не подключала домовую. */
#doc h1::after { content: none; }
/* ── ССЫЛКА У ЭТОЙ СТРАНИЦЫ ОДНА (принципал 2026-08-26: «пусть все ссылки
   одинаково оформлены, включая: красный») ────────────────────────────────────
   Здесь стояло `color: inherit`, а РЯДОМ — ещё пять оформлений одного рода:
   оглавление (без подчёркивания, чернилами), путь-возврат (акцентом, без
   подчёркивания), штамп времени (акцентом), рёбра осей (серой ПИЛЮЛЕЙ в рамке) и
   подвал (серая черта домовой таблицы, `a { border-bottom: 1px solid #ccc }`).
   Шесть решений об одном речевом акте — «отсюда можно уйти туда», — и ни одно не
   выведено: каждое родилось при своём месте. Читателю это приезжает шестью
   разными обещаниями, из которых он обязан вывести одно.
   ОФОРМЛЕНИЕ ССЫЛКИ ЕСТЬ СВОЙСТВО РОДА УЗЛА, А НЕ ЕГО МЕСТА, и потому объявлено
   ровно раз. Место вправе решать РАСКЛАДКУ (ряд, отбивка, зона нажатия) — оно не
   вправе решать, чем ссылка выглядит.
   Цвет ссылок в теле — чернила прозы (`--ink`), не акцент Outremer: иначе вся
   перекрёстная навигация читается как «синие ссылки» (замер 2026-08-27). */
#doc a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-offset: 0.18em;
  /* Домовая таблица подчёркивает всякую <a> серой чертой (`border-bottom`), и та
     приезжала СВЕРХ подчёркивания — две линии на одну ссылку. Подчёркивание
     решается здесь, значит вторую черту снимает то же правило. */
  border-bottom: 0;
}
#doc a:hover,
#doc a:focus-visible { text-decoration-thickness: 2px; }
/* ОБЁРТКА ИЗОБРАЖЕНИЯ — НЕ ТЕКСТОВАЯ ССЫЛКА: подчёркивать в ней нечего. */
#doc a[data-role="zoom"] { text-decoration: none; }
#doc img { max-width: 100%; height: auto; display: block; }
#doc ul { list-style: none; }

/* ── ПОТОЛОК МЕРЫ ЕСТЬ СВОЙСТВО НАБОРНОГО ЭЛЕМЕНТА, А НЕ СПИСКА СЕЛЕКТОРОВ ──
   КОРЕНЬ (замер 2026-08-26). `max-width: var(--measure)` стоял ПЕРЕЧНЕМ — при
   `section > [data-role="prose"]`, при `[data-role="speech"]`, при полях шапки — и
   только внутри широкого регистра. Проза внутри рисунка (`figcaption > p`, `figure >
   p`, `figcaption > blockquote`) в перечень не попала НИ ОДНОЙ строкой, и, когда
   рукописные дорожки ушли, эти блоки растянулись на весь холст: 102 знака в строке
   при потолке 75. Перечень селекторов есть множество из перечисленных членов, и цена
   невписанности — тишина; ровно этот класс Спека уже назвала для контракта набора
   («АДРЕС КОНТРАКТА ЕСТЬ РОЛЬ ДОКУМЕНТА, А НЕ ИМЯ КЛАССА»).
   ЗДЕСЬ АДРЕС — САМ НАБОРНЫЙ ЭЛЕМЕНТ: абзац, цитата, член списка, определение. Их
   роль в документе И ЕСТЬ «здесь набрана проза», и потому потолок держится по
   построению — включая всё, что рендерер выпустит завтра. Ни `@media`, ни предка в
   селекторе: мера не зависит ни от ширины экрана, ни от места в дереве. */
/* ── КЕГЛЬ ПРОЗЫ ОБЪЯВЛЯЕТСЯ НА ТОМ ЖЕ СЛОЕ, ЧТО И ЕЁ МЕРА ──────────────────
   КОРЕНЬ (замер 2026-08-26, последние 46 находок меры из 46). Оформление этого
   документа объявлено ПО РОЛЯМ (`[data-role="prose"]`), а общесайтовый лист несёт
   голое `p { font-size: var(--font-size-p) }` — объявление на слое ЭЛЕМЕНТА. Всякое
   объявление бьёт унаследованное значение, каким бы точным ни было наследование, и
   потому ролевая типографика документа молча проигрывала одному правилу из чужого
   листа: проза рисунка приезжала кеглем 22.4px при базовом 17.5, и 551px ящика давали
   39 знаков вместо 60. Ни одно правило страницы этого не назначало — размер брался из
   слоя, к документу отношения не имеющего.
   СЛОЙ ЛЕЧИТСЯ СЛОЕМ, И ЛЕЧЕНИЕ ЕСТЬ `inherit`, А НЕ ЗНАЧЕНИЕ. Первая редакция этой
   правки поставила здесь `font-size: var(--fs-s)` — и ПОВТОРИЛА исходную ошибку на том
   же слое, только с другим числом: подпись рисунка, объявленная своим регистром
   (`figcaption { --fs-xs }` = 17.5px), была поднята до 21.25px, и мера у неё стала
   ХУЖЕ (замер: 46 → 44 находки, то есть почти ничего, при 41 знаке вместо 60).
   Документ не выбирает кегль прозы — он объявляет, что кегль прозы приходит ИЗ
   КОНТЕКСТА, а контекст объявлен ролью. `inherit` есть ровно это: он снимает чужое
   объявление с элементного слоя и возвращает каскад ролевому. Ни одного значения,
   ни одного числа — только слой. Чужой лист не тронут: у него свои читатели. */
#doc :is(p, blockquote, li, dd, dt) {
  max-width: var(--measure);
  font-size: inherit;
}

/* ── ШАПКА ────────────────────────────────────────────────────────────── */
#doc > header {
  text-align: center;
  padding: var(--space-section) 0 calc(var(--space-section) * 0.85);
  margin-bottom: var(--sp-2);
}
#doc > header [data-field="pretitle"] {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--accent);
  font-weight: 600;
  margin-bottom: var(--sp-2);
}
/* КАПС — ЯРЛЫК, А НЕ ПРЕДЛОЖЕНИЕ. `context` несёт ФРАЗУ со ссылкой внутри («Для
   Британской высшей школы дизайна · Maison&Objet 2026»), и набранная прописными с
   ярлычной разрядкой она давала на 360px худший рваный край всей страницы
   (rag_mean 0.463 при потолке 0.2, худшая недостача 0.771 при 0.55 — замер 2026-08-26)
   и рвала подчёркивание ссылки посреди имени. Прописными набирают НАДЗАГОЛОВОК в
   два-три слова; длинный пассаж прописными Брингхерст §3.2.2 запрещает прямо. Ярлык
   на первом экране остаётся — им служит `pretitle` («РАССКАЗ-ПОКАЗ»), у которого капс
   и есть предмет. Оптическая поправка остаётся, ярлычный просвет уходит с ярлыком. */
#doc > header [data-field="context"] {
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-emphasis);
  color: var(--ink-soft);
  margin-bottom: var(--sp-3);
  text-wrap: pretty;
}
/* Заголовок страницы — РЕГИСТР СТАТЬИ, не хаба.
   `--font-size-h1` (site.md) — clamp 2.5–7rem для посадочного героя; на рассказе-показе
   он давал скачок шкалы (замер шапки). Та же идиома, что `.article-wrapper h1`:
   clamp между ступенями μ, роль `--sans-display`, ведущий `--lh-display`.
   Прописные в модели; трекинг дисплейный (оптическое сжатие крупного кегля), не caps-каталог. */
#doc > header h1 {
  font-family: var(--sans-display);
  font-weight: 700;
  font-size: clamp(var(--fs-2xl), 1.6rem + 3.6vw, var(--fs-3xl));
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
  /* ИМЯ ЕСТЬ АКЦЕНТ (принципал 2026-08-26: «пусть „Стили … Тренды" красным»).
     Прежде цветом был выделен ЯРЛЫК РОДА («Рассказ-показ»), а имя набрано
     чернилами: голос отдавался служебной строке, а не тому, ради чего страница
     существует. */
  color: var(--accent);
  margin-bottom: var(--sp-3);
  text-wrap: balance;
}
#doc > header [data-field="subtitle"] {
  font-size: clamp(var(--fs-m), 1.05rem + 1.2vw, var(--fs-l));
  color: var(--ink-soft);
  margin-bottom: var(--sp-2);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-micro);
  text-wrap: pretty;
  max-width: var(--measure);
  margin-left: auto;
  margin-right: auto;
}
#doc > header [data-field="author"] {
  font-size: var(--fs-s);
  color: var(--muted);
  margin-bottom: var(--sp-4);
}
#doc > header [data-field="staccato"] {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: var(--sp-4);
  font-size: var(--fs-s);
  color: var(--muted);
  letter-spacing: var(--tracking-fine);
}
/* Эпиграф шапки: цитата + атрибуция (не путать со стаккато-строкой).
   Без font-style:italic — Inv-TYPO-italic-real-cut: в гротеске курсив синтетический. */
#doc > header blockquote {
  margin: 0 auto var(--sp-2);
  max-width: var(--measure);
  font-size: var(--fs-s);
  color: var(--ink-soft);
  border: 0;
  padding: 0;
  letter-spacing: var(--tracking-fine);
}
#doc > header [data-role="by"] {
  font-size: var(--fs-xs);
  color: var(--muted);
  margin: 0 0 var(--sp-4);
  font-style: normal;
}
#doc > header [data-role="by"]::before {
  content: "— ";
}
#doc > header [data-field="badges"] {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}
#doc > header [data-field="badges"] li {
  padding: 0.25rem 0.75rem;
  background-color: var(--surface-deep);
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--ink-soft);
}

/* ── ДВА ПОКАЗА ОБХОДА, ДВА ОФОРМЛЕНИЯ ────────────────────────────────────
   «Оглавление» (обещание, под шапкой) и «путь» (возврат, в конце) суть разные
   речевые акты и потому оформляются врозь. Прежде оба ловились селектором
   `#doc > nav` — одно правило на два объекта, — и оглавление выходило облаком
   тегов. Селектор теперь именует ОБЪЕКТ, а не его место в дереве.
   Итерация оформления выполнена Composer 2.5 (`agent -p`, party:cursor) по
   замеру и брифу; принято после сверки токенов и прогона закона формы. */
/* ── ОГЛАВЛЕНИЕ (#doc-contents): центрированный перечень без линеек-таблицы
   Принципал 2026-08-26: «буллиты не перед названиями глав, а вместо горизонтальных
   линий, отделяющих содержание; крупные». Линейка обещает ряды и колонки, которых
   у обещания нет; типографский dinkus по центру — знак РАЗДЕЛА блоков. Вместе с
   линейками ушла и разбивка на две колонки (штамп слева, имя справа): колонки
   были той же таблицей, только на широком экране. */
#doc-contents ul {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) 0;
  list-style: none;
  text-align: center;
}
#doc-contents li { max-width: var(--measure); }
/* ЗОНА НАЖАТИЯ ЕСТЬ ВЕЛИЧИНА, А НЕ СЛЕДСТВИЕ ОТСТУПА — тот же токен, что у рёбер
   осей ниже (`--touch-min`), и своего числа здесь нет. */
#doc-contents a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min, 44px);
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 0.4em;
}
/* ШТАМП ИДЁТ В СТРОКЕ С ИМЕНЕМ, А НЕ НАД НИМ: перечень есть одна строка на пункт.
   Разрядка — `--tracking-emphasis`: регистр штампа СМЕШАННЫЙ («Глава 1 · 00:00–
   16:47»), а ярлычная `--tracking-caps` есть просвет ПРОПИСНЫХ и в строчных рвёт
   слово на буквы (Inv-SITE-form-at-reader::max_tracking_vars). */
#doc-contents [data-role="stamp"] {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-emphasis);
  color: var(--muted);
}
#doc-contents [data-role="title"] {
  font-size: var(--fs-s);
  font-weight: 600;
  line-height: var(--lh-tight);
}

/* ── НАВИГАЦИЯ (#doc-nav): компактная полоса в конце ───────────────────── */
#doc-nav ul {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 0.35rem 0.5rem;
  padding: var(--sp-2) 0 var(--sp-3);
  list-style: none;
}
/* ДИНКУС ВМЕСТО ЛИНЕЙКИ — знак РАЗДЕЛА блоков, а не табличный ряд (принципал
   2026-08-26: крупный «•» по центру там, где линейка отделяла содержание).
   Одно правило на три стыка: шапка, оглавление, навигация — не три копии. */
#doc > header::after,
#doc-contents ul::after,
#doc-nav ul::after {
  content: "•";
  display: block;
  text-align: center;
  /* КРУПНЫЙ (принципал: «крупные»). Глиф «•» занимает ~0.23em своего кегля,
     поэтому ступень шкалы берётся ДИСПЛЕЙНАЯ: на --fs-l точка вышла бы 5px —
     меньше снятой линейки, т.е. замена была бы понижением, а не заменой. */
  font-size: var(--fs-2xl);
  line-height: 1;
  color: var(--rule);
  padding-top: var(--sp-2);
  padding-bottom: var(--sp-2);
}
#doc-nav li {
  display: block;
}
#doc-nav li:not(:last-child)::after {
  content: none;
}
#doc-nav::before {
  content: none;
}
#doc-nav a {
  display: inline-block;
  font-size: var(--fs-xs);
  /* ВОЗВРАТ НЕСЁТ ИМЕНА, А НЕ ЯРЛЫКИ (`toc.nav: [title]`), и имена набраны смешанным
     регистром: ярлычная разрядка рвала «Макрооптика» на буквы. Оптическая поправка
     остаётся, ярлычный просвет уходит вместе с ярлыком. */
  letter-spacing: var(--tracking-emphasis);
  padding: 0.15rem 0;
}

/* ── СЕКЦИЯ ───────────────────────────────────────────────────────────── */
#doc section {
  padding: var(--space-section) 0 2.5rem;
  border-bottom: 1px solid var(--rule);
}
/* ДИСПЛЕЙНЫЙ КЕГЛЬ ОБЯЗАН ЗНАТЬ ШИРИНУ, В КОТОРУЮ ЕГО СТАВЯТ.
   Здесь стояла НЕПОДВИЖНАЯ ступень шкалы (`--fs-2xl` = μ⁴ = 39px при любом экране), а
   ступень есть ТОЧКА, не функция: она ничего не знает о колонке. На вьюпорте 360px
   колонка главы — 291px, и одно слово «псевдоискусства» при 39px занимает 320px:
   заголовок «Номер без псевдоискусства» выходил за правый край и обрезался
   `html,body{overflow-x:hidden}` — то есть симптом гасился, а не разрешался (замер
   Inv-SITE-form-at-reader, принципал 2026-08-20).
   Идиома шкалы в Системе уже объявлена и используется сайтом: ступени — НЕПОДВИЖНЫЕ
   ТОЧКИ, а текучесть собирается КЛАМПОМ МЕЖДУ НИМИ (`clamp(var(--fs-2xl), …, var(--fs-3xl))`
   у h1 хаба). Здесь — та же идиома, а не своё решение. */
#doc section > h2 {
  font-size: clamp(var(--fs-l), 1.1rem + 3vw, var(--fs-2xl));
  line-height: var(--lh-tight);
  color: var(--ink);
  margin-bottom: 0.75rem;
  /* ДИСПЛЕЙНАЯ СТРОКА БАЛАНСИРУЕТСЯ, А НЕ ОПТИМИЗИРУЕТСЯ ПО ВДОВАМ. h1 объявлял это
     давно, h2 — нет, и на 360px «Номер без псевдоискусства» приходил с последней
     строкой в три знака (rag_mean 0.304, недостача 0.608 — замер 2026-08-26). Закон
     о переносе строк объявляет ОБА значения решениями (`text-wrap: [pretty, balance]`,
     typography.md): у короткой дисплейной строки решение — баланс. */
  text-wrap: balance;
}
/* КООРДИНАТА И ИМЯ — ДВЕ РАЗНЫЕ ВЕЩИ, И НОВОСТРОЧИЕ ЭТО ГОВОРИТ. Одной строкой
   «Глава 1 · 00:00 – 16:47 — Каркас и реакция» читается как одно длинное имя:
   штамп есть АДРЕС главы на записи, заголовок — её тезис, и семантику различия
   несёт вертикаль, а не тире (принципал 2026-08-19). */
/* Части заголовка разделены ФОРМОЙ: штамп — своей строкой над именем, а внутри одной
   строки (карточка определения) — обычным пробелом. Разделитель-литерал в рендерере
   был бы третьим написанием того же решения. */
#doc :is(h2, h3, dt) [data-role] + [data-role] { margin-left: 0.4em; }
/* Штамп главы — БЛОК, поэтому имя за ним начинает строку и отступа не берёт. */
/* ИМЯ ГЛАВЫ БАЛАНСИРУЕТСЯ САМО, А НЕ ВМЕСТЕ СО ШТАМПОМ. `text-wrap: balance` у `h2`
   не давал эффекта: балансировщик Chromium отступает перед блочным потомком, а штамп
   объявлен блоком строкой ниже — заголовок оставался с последней строкой в три знака
   («Номер без псевдоискусства», 360px). Имя получает СВОЙ простой блок, и балансир
   работает на нём. Отбивки не меняются: `display: block` у соседа уже есть. */
#doc section > h2 [data-role="stamp"] + [data-role] {
  margin-left: 0;
  display: block;
  text-wrap: balance;
}
#doc section > h2 [data-role="stamp"] {
  display: block;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--tracking-caps);
  color: var(--accent);
  margin-bottom: 0.35rem;
}
#doc section > [data-role="prose"],
#doc section > [data-role="speech"],
#doc section > blockquote {
  font-size: var(--fs-s);
  color: var(--ink-soft);
  max-width: var(--measure);
  margin-bottom: var(--sp-2);
}
/* ЧЕРНИЛА СЛЕДУЮТ ЗА ГОЛОСОМ, А НЕ ЗА ЭТАЖОМ РАЗМЕТКИ. Проза главы есть речь САМОЙ
   страницы — её основной текст, — и полтора десятка тысяч знаков основного текста
   набирались вспомогательными чернилами (#4D4D4D при #2A2A2A у заголовка над ними):
   документ читался как один длинный комментарий к себе. Вспомогательные чернила
   остаются там, где голос ВТОРИЧЕН, — у цитаты и у расшифрованной речи. */
#doc section > [data-role="prose"] { color: var(--ink); }
#doc section > [data-role="note"] {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--accent);
  font-weight: 600;
  margin-bottom: 0.5rem;
}
/* Речь отделена ЛИНЕЙКОЙ и ГРАДАЦИЕЙ ЧЕРНИЛ — тем, чем гротеск умеет отделять.
   Наклон здесь был синтезированным сдвигом кириллицы (Inv-TYPO-italic-real-cut). */
#doc blockquote {
  color: var(--ink-soft);
  border-left: 2px solid var(--rule);
  padding-left: 1rem;
}
#doc section > [data-role="strophe"] {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.25rem;
  margin-bottom: var(--sp-2);
  color: var(--muted);
  font-size: var(--fs-s);
}
/* Ширина — поверхность; color-scheme — чтобы нативный chrome плеера следовал теме,
   а не оставался белой плашкой на ночном фоне (замер шапки). */
#doc audio {
  width: min(100%, 30rem);
  margin-bottom: var(--sp-2);
  color-scheme: light dark;
}
html[data-theme="night"] #doc audio { color-scheme: dark; }
html[data-theme="day"] #doc audio { color-scheme: light; }
/* Штамп времени / якорь записи — акцент темы, не второй hex. */
#doc time[data-field="timecode"] { color: var(--accent); }

/* ── ОСИ: семь карточек, а не семь вкладок ────────────────────────────── */
#doc dl {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
  counter-reset: axis;
}
#doc dl > [data-kind="axis"] {
  counter-increment: axis;
  /* ЯЧЕЙКА ОБЯЗАНА УМЕТЬ СЖАТЬСЯ: у grid/flex-элемента `min-width` по умолчанию
     `auto`, поэтому лента внутри (её содержимое шире экрана) растягивала бы
     ДОРОЖКУ, и вся страница получала горизонтальную прокрутку на телефоне
     (замер 2026-08-19, 390px). */
  min-width: 0;
  background-color: var(--surface-deep);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  padding: 1rem;
}
#doc dl dt::before {
  /* Лапидарность: ведущий ноль не несёт ничего (принципал 2026-08-19). */
  content: counter(axis, decimal);
  display: block;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--accent);
  margin-bottom: 0.25rem;
}
#doc dl dt {
  font-size: var(--fs-s);
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.35rem;
}
#doc dl dd [data-field="title"],
#doc dl dd [data-field="hint"] {
  font-size: var(--fs-xs);
  color: var(--muted);
  line-height: var(--lh-tight);
}
#doc dl dd [data-role="prose"] {
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  margin-top: 0.5rem;
}
/* РЁБРА ОСИ ПЕРЕНОСЯТСЯ. Прежде здесь стояла ЛЕНТА с горизонтальной прокруткой —
   ради того, чтобы карточка не выросла выше главы. Цена оказалась выше выигрыша:
   горизонтальная прокрутка внутри вертикального чтения неэргономична (принципал
   2026-08-19) — её не видно, она конфликтует с жестом страницы и прячет ровно то,
   ради чего ось и раскрыта. Карточка растёт по содержанию; высоту держит сама
   сетка (`auto-fill` по ширине, ряд по самой высокой). */
/* РЁБРА ОТДЕЛЕНЫ ОТ ПРОЗЫ — иначе список единиц читается продолжением абзаца
   (принципал 2026-08-26: «ссылки графически отделены от сути»). */
#doc dl dd [data-role="links"] {
  flex-wrap: wrap;
  gap: 0.25rem 0.4rem;
  margin-top: var(--sp-3);
  padding-top: var(--sp-2);
  padding-bottom: var(--sp-2);
  border-top: 1px solid var(--rule-soft);
}
#doc dl dd [data-role="links"] li { flex: 0 1 auto; min-width: 0; }
#doc dl dd [data-role="links"] a { max-width: 100%; }

/* ── ССЫЛКИ-РЁБРА: ось ↔ единица (69 рёбер, прежде невидимых) ─────────── */
#doc [data-role="links"] {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.6rem;
  min-width: 0;
}
/* Элемент ряда обязан УМЕТЬ СЖАТЬСЯ: без этого длинное имя единицы выносит чип
   за границу карточки (flex-элемент по умолчанию не уже своего содержимого). */
#doc [data-role="links"] li { max-width: 100%; min-width: 0; }
#doc [data-role="links"] a {
  /* ЗОНА НАЖАТИЯ ЕСТЬ ВЕЛИЧИНА, А НЕ СЛЕДСТВИЕ ОТСТУПА (замер ревизии 2026-08-26:
     чип осей 163×29px при объявленном `--touch-min: 44px`). Токен уже объявлен
     Системой; правило лишь ПОТРЕБЛЯЕТ его, своего числа здесь нет. */
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min, 44px);
  max-width: 100%;
  /* ПИЛЮЛЯ СНЯТА (принципал 2026-08-26). Рамка и серые чернила делали ребро
     «ось ↔ единица» ШЕСТЫМ оформлением ссылки — и самым непохожим на остальные
     пять. Ряд, отбивка, зона нажатия и усечение суть РАСКЛАДКА и остаются здесь;
     чем ссылка выглядит, сказано один раз выше. */
  padding: 0.15rem 0;
  font-size: var(--fs-xs);
  /* ИМЯ ЕДИНИЦЫ ЦЕЛИКОМ ЖИВЁТ В РАЗМЕТКЕ (извлечение и reader-режимы читают его
     полностью); усечение — только показ, поэтому оно и стоит в оформлении. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}
/* Ребро графа — один речевой акт: graph_tag в обе проекции (сегмент и ось). */
#doc a[data-link-form="graph_tag"],
#doc [data-field="axis"] a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min, 44px);
  padding: var(--sp-1) var(--sp-2);
  font-size: var(--fs-xs);
  text-decoration: none;
  border: 1px solid var(--rule);
  border-radius: var(--radius-control);
  background-color: var(--surface-deep);
}


/* ── ГЛАВА: раскладку выбирает АВТОР, разметка единиц одна ────────────── */
/* СЕКЦИЯ ЕСТЬ СТОПКА СВОИХ ЧАСТЕЙ, А НЕ СЕТКА ЭКСПОНАТОВ. Экспонаты несёт ИХ
   СОБСТВЕННЫЙ носитель (`[data-collection]`), и раскладка их — свойство ЕГО, а не
   секции. Пока носителя не было, единственным способом разложить членов были дорожки
   ЧУЖОЙ сетки; сетка синхронизирует, и вся разница экстентов членов становилась мёртвым
   низом (замер 2026-08-25: 18 находок `band_slack_max`, до 2034 px в одной главе). */
#doc section[data-kind="chapter"] { display: block; }
#doc section[data-kind="chapter"] > * { min-width: 0; }
#doc section[data-kind="chapter"] > [data-collection] { margin-top: var(--sp-3); }

/* ── РОД СВЯЗИ ЧЛЕНОВ ОБЪЯВЛЕН ДАННЫМИ (`layouts.<имя>.relation`) ─────────
   flow — последовательность: строки нет вовсе, дорожки балансирует БРАУЗЕР
          (его собственная задача о минимальном максимуме — тот, чей это факт);
   row  — ровня: строка значима, и потому дорожки сетки.
   РОД СВЯЗИ — свойство содержимого и потому живёт в объявлении.

   ── ЧИСЛО ДОРОЖЕК ВЫВОДИТСЯ ИЗ ОБЪЯВЛЕННОЙ МЕРЫ, А НЕ НАЗНАЧАЕТСЯ ─────────
   КОРЕНЬ (замер 2026-08-26, шесть условий просмотра). Здесь стояли `columns: 2`,
   `columns: 3` и `repeat(2, …)` при рукописных порогах 680px и 1200px — число
   дорожек было РЕШЕНИЕМ РУКИ, ничем не связанным с мерой строки. Оттого на 1366px
   галерея делилась натрое и давала подписи по 29 знаков при поле закона 45: 40 из
   45 наборных блоков вне меры. Чинить это подпись за подписью значит чинить
   следствие; дорожка ýже пола меры не набирает прозу НИ ПРИ КАКОМ содержимом, и
   потому её не следует заводить вовсе.
   `auto-fit` + `minmax(min(100%, --measure-min), 1fr)` и `column-width` ровно это и
   говорят: браузер заводит столько дорожек, сколько помещается ПО ПОЛУ МЕРЫ, и ни
   одной сверх. Класс исчезает по построению, а рукописные пороги исчезают вместе с
   ним — их больше нечему держать. */
/* КОЛЛЕКЦИЯ ИЗ ОДНОГО НЕ ИМЕЕТ ВНУТРЕННЕЙ РАСКЛАДКИ: отношения между членами нет,
   и дорожек не бывает больше, чем членов. Мощность приезжает числом от производителя. */
#doc [data-collection][data-members="1"] { display: block; columns: initial; }
#doc [data-relation="flow"] { columns: auto; column-width: var(--measure-min); column-gap: var(--sp-2); }
#doc [data-relation="flow"] > * { break-inside: avoid; margin-bottom: var(--sp-3); }
#doc [data-relation="row"] {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--measure-min)), 1fr));
  gap: var(--sp-3) var(--sp-2);
  align-items: start;
}
#doc dl { grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--measure-min)), 1fr)); }

/* ── РАЗВОРОТ СЕКЦИИ (`feature`) СНЯТ, А НЕ ПЕРЕНАСТРОЕН ───────────────────
   Здесь стояла сетка `minmax(0,1.15fr) minmax(0,1fr)` с прозой, положенной ВО ВТОРУЮ
   дорожку ПОИМЕННО (`grid-column: 2`), и порогом 680px. Порог давал прозе ≈300px ≈ 19
   знаков — разворот заводился там, где ни одна дорожка не несла набора.
   ПОЧЕМУ НЕ ПОДОБРАН ПОРОГ ПОЛУЧШЕ. Первая редакция этой правки посчитала порог рукой
   (2 × пол меры + зазор + поля ≈ 1123px) и записала арифметику в комментарий. Число,
   выведенное рукой, есть число, которое обязана выводить машина: это тот же хардкод,
   лишь с приложенным доказательством. Достать его моделью нельзя — медиазапрос не
   читает пользовательских свойств, — и упираемся мы в это не случайно: ПОИМЕННОЕ
   размещение (`grid-column: 2`) само и есть хардкод МОЩНОСТИ раскладки, а он требует
   знать, сколько дорожек есть, то есть требует порога.
   КОРЕНЬ ГЛУБЖЕ CSS И ЛЕЖИТ В ДОКУМЕНТЕ: у секции есть экспонат и есть ПРОЗА, но
   рендерер оборачивает контейнером только первое, и «сторона прозы» существует лишь
   как «всё остальное среди сиблингов». Лист стилей достраивал недостающую структуру
   номерами дорожек. Пока прозе не дан СВОЙ контейнер, всякий разворот держится на
   рукописной мощности; с контейнером он выражается `flex-wrap` + `flex-basis:
   var(--measure-min)` и не содержит НИ ОДНОГО числа: перенос случается ровно тогда,
   когда обеим сторонам не хватает их пола.
   ДО ТОГО секция остаётся обычным потоком документа: экспонат, под ним проза по
   `--measure`. Ноль чисел, ноль порогов, мера держится по построению.
   Открытая нить: контейнер стороны прозы в `narrative_showcase` ⇒ возврат разворота
   без единого числа. */

/* ── ЕДИНИЦА ──────────────────────────────────────────────────────────── */
#doc [data-kind="segment"] {
  /* РЕГИСТР ОБЪЯВЛЯЕТСЯ ПРИ КАРТОЧКЕ — ЭТО ЕЁ СЛОЙ, А НЕ СЛОЙ ЕЁ АБЗАЦЕВ.
     Замер 2026-08-26 (последние 10 находок меры): подпись рисунка свой регистр имела
     (`figcaption { --fs-xs }`), а проза атомарного разворота и текст карточки-без-
     носителя — НЕ ИМЕЛИ НИ ОДНОГО, и потому брали кегль КОРНЯ СТРАНИЦЫ (20px при
     текучем `--font-size-base`), то есть величину, принадлежащую оболочке сайта, а не
     документу. 43.6 знака при поле 45 — промах на 3 %, и причина его не в вёрстке.
     Регистр есть свойство КАРТОЧКИ: всё, что в ней набрано, набрано её кеглем, и
     объявить это следует один раз при ней, а не по разу при каждом её абзаце. */
  font-size: var(--fs-xs);
  background-color: var(--surface-deep);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
/* ПРОПОРЦИЯ — ФАКТ НОСИТЕЛЯ, А НЕ ПРАВИЛО ОФОРМЛЕНИЯ. Здесь стояло
   `aspect-ratio: 16/9; object-fit: cover` — форма, верная для 30 слайдов и КАДРИРУЮЩАЯ
   8 разворотов журналов (5 портретных 1500×2000, 3 — 2000×1500; замер 2026-08-19).
   Рендерер объявляет ИЗМЕРЕННЫЕ width/height, поэтому браузер знает пропорцию сам:
   место резервируется точно, ничего не обрезается, и новый носитель любой формы
   приезжает без правки стиля. */
/* ── НАДПИСЬ ЛИСТА — ЦИТАТА ЧУЖОЙ ФОРМЫ, А НЕ ПРОЗА ЭТОГО ДОКУМЕНТА ─────────
   Атомы, снятые с разобранного слайда, набраны ЕГО типографикой. Прописные там —
   НАБЛЮДЁННЫЙ ФАКТ артефакта, а не решение документа кричать: понизить их значило бы
   испортить запись, а «TRANSFORMISM BY HARRY NURIEV» несёт имя. Пока роль была `prose`,
   надпись объявлялась прозой САМОЙ СТРАНИЦЫ — отсюда 66 находок из 102 всей меры.
   Роль объявлена (`narrative-showcase.md::leaves.atomic.role`), и надпись получает свой
   ярус: кегль подписи, чернила вспомогательные. Разрядка — только там, где регистр
   ИЗМЕРЕН прописным (`data-case`): капс без разрядки слипается (Мильчин §3.2.4), а
   строчной надписи разрядка не нужна. Ни одного числа — только токены модели. */
#doc [data-role="inscription"] {
  font-size: var(--fs-xs);
  color: var(--ink-soft);
}
#doc [data-role="inscription"][data-case="upper"] {
  letter-spacing: var(--tracking-caps);
}

#doc figure[data-kind="segment"] img { width: 100%; height: auto; }
#doc a[data-role="zoom"] { display: block; cursor: zoom-in; }
/* Клавиатурный обход шёл по UA-умолчанию (1px auto), тогда как у страницы есть
   объявленное кольцо фокуса. Замер ревизии 2026-08-26: 48 ленивых растров. */
#doc a[data-role="zoom"]:focus-visible {
  outline: var(--focus-outline-min, 2px) solid var(--accent);
  outline-offset: 2px;
}
#doc [data-form="atomic"] a[data-role="zoom"] img { width: 100%; height: auto; }

/* ── УВЕЛИЧЕНИЕ ────────────────────────────────────────────────────────
   Надстройка над ЯКОРЕМ документа: без скрипта ссылка открывает носитель,
   со скриптом он показывается на месте. Второго поведения не заводится. */
/* ПО ЦЕНТРУ, А НЕ В УГЛУ. Модальный <dialog> центрируется автополями браузера
   (`inset: 0; margin: auto`), а сброс в начале файла (`*{margin:0}`) их снимал —
   и увеличенное изображение появлялось в левом верхнем углу (принципал
   2026-08-19). Свойство несёт свою причину: сброс написан до того, как на
   странице появился <dialog>, и молча отнял у него механизм положения. */
dialog[data-role="zoom"] {
  inset: 0; margin: auto;
  max-width: 100vw; max-height: 100vh; width: max-content; height: max-content;
  padding: 0; border: 0; background: transparent;
}
dialog[data-role="zoom"]::backdrop { background: rgba(0, 0, 0, 0.82); }
dialog[data-role="zoom"] img {
  display: block; max-width: calc(100vw - 2 * var(--space-padding)); max-height: 94vh;
  width: auto; height: auto; cursor: zoom-out;
}
#doc figcaption {
  padding: 0.75rem 0.85rem 1rem;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
#doc figcaption > * { margin: 0; }
#doc figcaption b { display: block; font-weight: 400; }
#doc figcaption [data-role="note"] {
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  font-size: var(--fs-2xs);
  color: var(--accent);
}
#doc figcaption [data-role="title"] { font-weight: 600; color: var(--ink); }
#doc [data-role="stamp"] {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--muted);
}
/* ГОЛОС — ОТДЕЛЬНАЯ СТРОКА ПОД РЕЧЬЮ. Прежде селектор целил в АТРИБУТ `data-by`,
   то есть красил саму речь, а имя произнёсшего читателю не показывалось вовсе
   (Inv-PROV, замер 2026-08-20). Роль — та же, что у всей разметки класса. */
#doc [data-role="by"] { display: block; margin-top: 0.4rem; font-size: var(--fs-xs); color: var(--muted); }
#doc figcaption [data-role="prose"] { margin-top: 0.5rem; }
#doc figcaption [data-role="strophe"] { display: flex; flex-wrap: wrap; gap: 0.25rem 0.75rem; margin-top: 0.5rem; color: var(--muted); }

/* Единица БЕЗ носителя — закрывающая карточка */
#doc div[data-kind="segment"] { padding: 1.5rem; }
#doc div[data-kind="segment"] h3 { font-size: var(--fs-l); color: var(--ink); margin-bottom: 0.5rem; }
#doc div[data-kind="segment"] [data-role="note"] {
  display: inline-block;
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
  color: var(--accent);
  margin-bottom: 0.5rem;
}
#doc div[data-kind="segment"] [data-role="prose"] { color: var(--ink-soft); margin-bottom: 0.75rem; }
#doc div[data-kind="segment"] [data-role="strophe"] { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 0.85rem; color: var(--muted); font-size: var(--fs-xs); }
#doc div[data-kind="segment"] [data-role="links"] a { font-size: var(--fs-xs); }

/* ── АТОМАРНАЯ ФОРМА ЛИСТА ────────────────────────────────────────────── */
#doc [data-form="atomic"] [data-role="figure"] {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--atom-min)), 1fr));
  gap: 0.6rem;
  padding: 0.6rem 0.6rem 0;
}
#doc [data-form="atomic"] [data-role="prose"] { display: block; margin: 0.35rem 0.85rem; }
#doc [data-form="atomic"] b[data-role="prose"] { font-size: var(--fs-s); color: var(--ink); }

/* ── ПОДВАЛ ───────────────────────────────────────────────────────────── */
#doc > footer { padding-top: var(--space-section); display: grid; gap: 0.75rem; }
#doc > footer blockquote { font-size: var(--fs-l); border: 0; padding: 0; color: var(--ink-soft); }
#doc > footer [data-role="links"] { margin: 0; }
/* ── УЗКИЙ ЭКРАН — БОЛЬШЕ НЕ ОСОБЫЙ СЛУЧАЙ ────────────────────────────────
   Здесь стоял «откат к одной колонке» для `feature` на ≤680px. Он был нужен, пока
   разворот заводился с 680px: одно рукописное число чинило другое. Разворот теперь
   заводится ТОЛЬКО там, где обе дорожки несут пол меры, а вне этого условия секция
   остаётся обычным блоком в порядке документа — откатывать нечего. Правило снято, а
   не ослаблено: у него не осталось предмета. */

/* ── ШИРОКИЙ ЭКРАН: холст `--page`, поток = зрение (Spec::wide_register).
   Nav — после тела на любой ширине; sticky-рельс снят (замер 2026-08-24:
   grid-row поднимал оглавление «впереди всего»). Сетки — фиксированные дорожки. */
@media (min-width: 880px) {
  /* КОЛОНКИ ОБЪЯВЛЕНЫ ДАННЫМИ И ПРИЕЗЖАЮТ СТРУКТУРОЙ (`wide_register.spread` →
     `<div data-col>`). Здесь стояли СЕМЬ литералов `[data-field=…]`, тогда как Спека
     класса объявляет ровно обратное: «код знает конечный словарь РОЛЕЙ; какое ПОЛЕ
     играет роль — не знает и знать не должен». CSS есть код: всякое новое поле автора
     молча уезжало в колонку 1, и никто этого не видел. Теперь оформление не знает ни
     полей, ни ролей — только КОЛОНКУ, а какая роль в какой колонке, сказано в Спеке.
     И колонка стала СТОПКОЙ: дорожки одной сетки делили строки, отчего правая
     начиналась там, где её первый узел встретился в потоке, и рвалась по высотам левой
     (замер 2026-08-25: 744 px пустоты сверху, 174 px между манифестациями). */
  /* РАЗВОРОТ СУЩЕСТВУЕТ, ПОКА ХОЛСТ НЕСЁТ ОБЕ КОЛОНКИ, — И ЭТО УСЛОВИЕ ОБЪЯВЛЕНО
     СОДЕРЖИМЫМ, А НЕ ЧИСЛОМ. Здесь стояла сетка `minmax(0, 1fr) minmax(16rem, --measure)`:
     у колонки голоса пол был ОБЪЯВЛЕН (мера строки), у колонки имени — НУЛЬ. Колонка с
     нулевым полом не колонка, а ОСТАТОК: она получала то, что не забрала соседка, и на
     холсте между 880 и 1200 остатка не оставалось. ЗАМЕР 2026-08-25 по всей оси ширин
     (вьюпорт → col1 × col2): 360→305×305 · 665→576×576 · 753→655×655 · 865→40×639 ·
     885→54×643 · 985→124×660 · 1085→194×677 · 1185→280×680 · 1351→429×680. То есть на
     ЦЕЛОМ ИНТЕРВАЛЕ ~865…1185 имя рассказа-показа верстается в колонку 40–280 px и
     ломается по буквам: «СТ ИЛ И», «ТР ЕН ДЫ», «РАССКА З-ПОКАЗ». Три ширины, которыми
     закон о форме проверял страницу (375 · 768 · 1366), лежат РОВНО ВНЕ этого интервала.

     ПОЛ КОЛОНКИ ЕСТЬ `min-content` ЕЁ СОДЕРЖИМОГО — величина, которую МЕРИТ БРАУЗЕР, а
     не сочиняем мы: ни одного нового числа в оформлении не появляется. А складывается
     разворот СОБОЙ: строка flex переносится ровно тогда, когда полы обеих колонок
     перестают умещаться, — то есть условие существования разворота выведено из
     содержимого, а не угадано вторым порогом рядом с 880. */
  #doc[data-register="wide"] > header { text-align: start; }
  /* РАЗВОРОТ СУЩЕСТВУЕТ ТОГДА, КОГДА ЕГО ОБЪЯВИЛИ ДАННЫЕ, А НЕ КОГДА ШИРОК ЭКРАН.
     Здесь `display: flex` висел на РЕГИСТРЕ — то есть оформление само решало, что шапка
     о двух колонках, а данные лишь поставляли обёртки. Стоило объявлению снять разворот
     (`wide_register.spread: {}`), как ряд flex остался и разложил в строку уже не
     колонки, а САМИ УЗЛЫ СТАНЦЫ: имя рассказа-показа 174 px рядом с подзаголовком
     33 px, 141 px мёртвых (замер `band_slack_max` 2026-08-25, найден законом за одну
     итерацию после правки данных). Условие ряда есть НАЛИЧИЕ КОЛОНОК, и спросить о нём
     надо у разметки, которую породило объявление, — тогда «развернуть/свернуть» есть
     строка данных, и оформление следует за ней по построению. */
  #doc[data-register="wide"] > header:has(> [data-col]) {
    display: flex;
    flex-wrap: wrap;
    column-gap: calc(var(--gutter) * 2);
    row-gap: var(--sp-2);
    align-items: flex-start;
  }
  /* ШИРИНА КОЛОНКИ ГОЛОСА ЕСТЬ МЕРА СТРОКИ, А НЕ ДОЛЯ ХОЛСТА (замер 2026-08-25: доля
     росла вместе с экраном и на 1920 давала 760 px под реплику в 190 px). Основа —
     мера — ПОТОЛОК колонки голоса, а не её основа. Основа у обеих колонок одна и та же и
     не есть число: СОБСТВЕННЫЙ МИНИМУМ СОДЕРЖИМОГО. Отсюда условие существования
     разворота — ровно `min(col1) + зазор + min(col2) ≤ холст`, то есть ИСТИННОЕ условие,
     а не приближение мерой: поставив основой меру, я складывала разворот уже на 1185 px,
     хотя обе колонки там умещались. Ни одного числа в этих двух строках больше нет. */
  #doc[data-register="wide"] > header > [data-col] { flex: 1 1 min-content; }
  /* ПОПРАВКА 2026-08-26 К СТРОКЕ ВЫШЕ, И ОНА О ПОЛЕ, А НЕ О ПОТОЛКЕ. Основа
     `min-content` верна для колонки-имени и НЕВЕРНА для колонки голоса: у прозы пол
     задан не её буквами, а МЕРОЙ. Замер: разворот складывался «по содержимому» и
     оставлял голосу 31.4 знака при поле закона 45 — то есть заводился там, где набора
     в этой колонке быть не может. Рассуждение прежней редакции («мера основой сложила
     бы разворот уже на 1185px, хотя обе колонки умещались») верно арифметически и
     подменяет предмет: «умещаются» и «несут меру» — разные условия, и разворот стоит на
     втором. Числа по-прежнему ни одного: пол приезжает токеном, перенос считает flex. */
  #doc[data-register="wide"] > header > [data-col="2"] {
    flex: 1 1 var(--measure-min);
    /* ОСНОВА НЕ ЕСТЬ ПОЛ: при `flex-shrink: 1` колонка садится НИЖЕ основы, и первая
       редакция этой правки получила 21.5 знака вместо 31.4 — стало хуже, а не лучше.
       Пол ставит `min-width`; `min(100%, …)` не даёт ему переполнить холст, и тогда
       единственный оставшийся исход — ПЕРЕНОС, то есть ровно то, чего мы и хотим. */
    min-width: min(100%, var(--measure-min));
    max-width: var(--measure);
  }
  /* КОЛОНКА ТЯНЕТ СВОИХ ДЕТЕЙ (align-items по умолчанию — stretch): у абзаца ширина
     есть ширина колонки, а не ширина его букв. `flex-start` здесь сжимал каждого
     ребёнка до содержимого, и плеер, чья ширина объявлена как 100 % родителя, схлопнулся
     в НОЛЬ (замер: `record w=0`) — ⊥, надевший вид значения. */
  #doc[data-register="wide"] > header > [data-col] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    /* ПОЛ — СОБСТВЕННЫЙ МИНИМУМ СОДЕРЖИМОГО. Здесь стоял `min-width: 0`, снятый ради
       плеера (`flex-start` сжимал детей до содержимого, и плеер шириной 100 % схлопывался
       в НОЛЬ). Причина верна, лекарство било шире болезни: нуль снимает пол У ВСЕХ, и
       вместе с плеером его лишилось имя рассказа-показа. `min-content` лечит ровно то же
       (пол не мешает ребёнку тянуться) и сохраняет то, что нуль уничтожал. */
    min-width: min-content;
  }
  #doc[data-register="wide"] > header blockquote,
  #doc[data-register="wide"] > header [data-field="subtitle"] {
    margin-left: 0;
    margin-right: 0;
  }
  #doc[data-register="wide"] > header [data-field="staccato"],
  #doc[data-register="wide"] > header [data-field="badges"] {
    align-items: flex-start;
    justify-content: flex-start;
  }
  /* ПЛЕЕР ТЯНЕТСЯ ПО КОЛОНКЕ, А БЕЗ КОЛОНКИ — ПО МЕРЕ СТРОКИ: у элемента управления
     нет причины быть шире прозы, рядом с которой он стоит. */
  #doc[data-register="wide"] > header audio { width: 100%; max-width: var(--measure); }
  #doc[data-register="wide"] > header:has(> [data-col]) audio { max-width: 100%; }

  #doc[data-register="wide"] section > [data-role="prose"],
  #doc[data-register="wide"] section > [data-role="speech"],
  #doc[data-register="wide"] section > blockquote,
  #doc[data-register="wide"] > header [data-field="subtitle"],
  #doc[data-register="wide"] > header blockquote {
    max-width: var(--measure);
    margin-left: 0;
    margin-right: 0;
  }

  /* ЧИСЛО ДОРОЖЕК ЗДЕСЬ НЕ ПЕРЕНАЗНАЧАЕТСЯ. Прежде широкий регистр ставил `repeat(3,…)`
     и `repeat(2,…)` поверх выведенных выше — то есть возвращал руку ровно там, где мера
     уже сказала своё. Широкий регистр есть решение о ХОЛСТЕ (`--page`, поля, поток), и
     дорожки ему не принадлежат: они выводятся из меры на любой ширине. Осталась одна
     строка — зазор, который холст вправе назначить. */
  #doc[data-register="wide"] dl { gap: var(--sp-3) var(--gutter); }
}

/* ── Уважение к prefers-reduced-motion (Inv-CSS-prefers-reduced-motion) ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}


/* ВЫДЕЛЕННЫЙ ТОКЕН типографики (Inv-TYPO-emphasis-token): латинская связка
   противопоставления внутри русской фразы. Курсив + лёгкий разряд — знак отношения
   держится отдельно от имён, которые он сравнивает (принципал 2026-08-19).
   СТЕК ЗАГОЛОВКА (СТИЛИ / vs / ТРЕНДЫ) несёт МОДЕЛЬ (`\n` → `<br>`), а не
   `display:block` на `.t-emph`: иначе топология заголовка жила бы во втором доме. */
.t-emph {
  font-style: italic;
  letter-spacing: var(--tracking-emphasis);
  font-feature-settings: "kern" 1, "liga" 1;
}
/* Связка внутри дисплейного заголовка: не наследует 700 и чернила имени —
   иначе «vs» читается третьим именем, а не отношением (Inv-TYPO-emphasis-token). */
#doc > header h1 .t-emph {
  font-weight: 400;
  color: var(--muted);
  /* Связка живёт ВНУТРИ прописного заголовка и приезжает к читателю прописной
     (`text-transform` наследуется), поэтому просвет ей нужен тот же, что имени. Без
     этой строки `.t-emph` (0,1,0) возвращала бы ей `--tracking-emphasis`. */
  letter-spacing: var(--tracking-caps-mid);
}

/* ── ПРОПИСНЫЕ ССЫЛКИ-ЗАПИСИ ПРИХОДЯТ ФОРМОЙ, А НЕ ИЗ ДАННЫХ ───────────────
   Ярлык «Видеозапись» — СЛОВО САМОЙ СИСТЕМЫ (модель страницы), а не транскрипция
   листа, и он был набран прописными В ДАННЫХ: читатель получал капс с НУЛЕВОЙ
   разрядкой, а закон о разрядке этого не видел — он читает правило, а правила не
   было (замер 2026-08-26, `Inv-TYPO-case-is-form-not-text`, 12 находок из 78).
   Датум приведён к естественному регистру, решение о регистре отдано форме, и
   разрядка приезжает вместе с ним ОДНИМ токеном: вход в капс здесь стал единственным,
   а значит Inv-TYPO-consistent-tracking-caps на этом узле тотален по построению. */
#doc > header [data-role="record"] a {
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}

/* «и» между аудио и видео — композиция принципала (2026-08-20).
   КУРСИВ СНЯТ по его же слову 2026-08-26 («„И" перед „ВИДЕОЗАПИСЬ" не должно быть
   курсивом»). Вместе с наклоном снято и ИЗЪЯТИЕ, которым он держался в законе
   (typography.md::Inv-TYPO-italic-real-cut.exceptions): изъятие живёт ровно
   столько, сколько живёт его причина. */
#doc > header p[data-kind="video"]::before {
  content: "и";
  display: block;
  font-size: var(--fs-m);
  letter-spacing: var(--tracking-emphasis);
  color: var(--muted);
  margin-bottom: var(--sp-2);
}

/* ПРАВИЛО СНЯТО ВМЕСТЕ СО СВОИМ ПРЕДМЕТОМ (2026-08-26). Оно снимало двойную
   линейку на стыке «оси → глава Transformism», и пара эта перестала быть парой
   ещё до сегодняшней правки: оси стояли ПОСЛЕДНЕЙ секцией, Transformism — второй
   главой. Правило без предмета есть тихий долг: не действует, а читается как
   действующее. Оси теперь идут СРАЗУ ЗА ОГЛАВЛЕНИЕМ (порядок ключей модели), и
   стык у них с первой главой: секции разделены `border-bottom`, верхней у них
   нет — линейка там ровно одна. */



/* ── ЦЕЛЬ КАСАНИЯ И ПЕЧАТЬ — ДВЕ ГРАНИ ОДНОГО: ФОРМА У ЧИТАТЕЛЯ ──────────── */
/* Штамп таймкода ведёт в запись; замер ревизии 2026-08-26 — 43×18px при
   объявленном `--touch-min`. Растёт зона, не кегль: мера строки не трогается. */
#doc [data-role="stamp"] a {
  display: inline-block;
  min-height: var(--touch-min, 44px);
  padding: 0.55rem 0.4rem;
  margin: -0.55rem -0.4rem;
}

/* ПЕЧАТЬ ЕСТЬ ВТОРАЯ ПРОЕКЦИЯ ОДНОГО ДОКУМЕНТА, А НЕ СНИМОК ЭКРАНА. Замер
   ревизии 2026-08-26: карточка уносила на бумагу фон #ECEAE3 и цветную заливку
   поверхности — тонер за декорацию, которой на бумаге нет предмета. */
@media print {
  #doc,
  #doc [data-kind="segment"] { background: transparent !important; }
  #doc [data-kind="segment"] { border: 1px solid #999; break-inside: avoid; }
  #doc a[data-role="zoom"] { break-inside: avoid; }
}


/* ── ПОЛЕ ЕСТЬ ВЕЛИЧИНА, КОТОРАЯ ОБЯЗАНА УСТУПАТЬ МЕРЕ ────────────────────────
   ЗАМЕР 2026-08-26 (проба `Inv-SITE-form-at-reader`, mobile_375): колонка подписи
   несёт 27.6 знака при объявленном Системой поле меры `--measure-min: 45ch`. Поля
   на этой странице ВЛОЖЕНЫ ТРИЖДЫ — холст (`--space-padding`) ⊃ разворот атомов
   ⊃ подпись, — и вместе съедают 93 px из 360: четверть холста уходит на воздух,
   которого узкому читателю негде взять. Следствие видно и другому закону: рваность
   края в одном абзаце 0.237 при потолке 0.20 (`Inv-TYPO-rag-bound`) — узкая колонка
   не оставляет набору выбора, куда перенести длинное русское слово.

   ЛЕЧЕНИЕ БЕЗ ВТОРОГО ПОРОГА. Прибавить `@media (max-width: N)` значило бы починить
   одно рукописное число вторым — ровно то, что эта же таблица уже отвергла, снимая
   «откат к одной колонке на ≤680px». Поле объявляется ФУНКЦИЕЙ ХОЛСТА: `min()` от
   величины, объявленной для просторного холста, и его доли. На широком экране
   выигрывает объявленная величина (при 1920px: 57.6 > 48 · 17.3 > 13.6 · 15.4 > 9.6),
   на узком — доля, и колонка растёт с 27.6 до 32.7 знака: рваность худшего абзаца
   падает с 0.237 до величины в границах, и это ЗАМЕР пробы самого закона, а не
   расчёт. Доля выбрана наименьшей уступкой, при которой проба зелена во ВСЕХ шести
   условиях; запас над потолком назван в этой же сессии и невелик — если правка текста
   его съест, лечить надо будет НЕ поле, а корень, Системой уже названный: решение о
   показе («не вешать союз») записано в ЗНАЧЕНИЕ символом NBSP и потому не умеет
   уступить, когда не умещается (text/site.md::Inv-SITE-form-at-reader, ось ширин). */
#doc { padding-inline: min(var(--space-padding), 3vw); }
#doc figcaption { padding-inline: min(0.85rem, 0.9vw); }
#doc [data-form="atomic"] [data-role="figure"] { padding-inline: min(0.6rem, 0.8vw); }
