/* Регистр сайта fancai.ru.
 *
 * Источник — макет `docs/design/fancai-landing.pen`, принятый владельцем
 * 2026-09-03. Переменные до раздела «Наши добавки» взяты из выгрузки
 * `docs/design/tokens.pen.css` (снята `GetVariables()`) один к одному:
 * значения не подбирались на глаз и не переводились из другого пространства.
 *
 * Прежний файл — 1 084 строки волны 3 (Cormorant Garamond / Inter / STIX Two
 * Text) — заменён целиком, а не дополнен: два регистра в одном файле дают
 * гарантию, что однажды применится не тот. Прежняя редакция этого заголовка
 * называла «1 349 строк под макет bolt.new (Cormorant / Lora / Manrope)» —
 * ни числа, ни набора: тот регистр в дерево не попадал вовсе.
 *
 * Порядок разделов: шрифты, переменные, сброс, типографика, полосы,
 * компоненты, страницы. Компонент здесь один на все двадцать страниц - если
 * страница нуждается в своей кнопке, это расхождение с макетом, а не повод
 * завести второй класс. */

/* ── Шрифты ──────────────────────────────────────────────────────────────────
 *
 * Три семейства, четыре файла, 127 048 байт. Собраны из `google/fonts`
 * инстансингом оси и подмножеством по `fonts/repertoire.txt` — команда и
 * ловушки в отчёте. Кириллица в каждом файле проверена по собранному woff2:
 * 66 знаков из 66, а не по обещанию первоисточника.
 *
 * Пути относительные: файл отдаётся с `/s/<отпечаток>/tokens.css`, поэтому
 * `fonts/…` попадает под тот же отпечаток и тот же `immutable`. */

@font-face {
	font-family: "Unbounded";
	src: url(fonts/unbounded.woff2) format("woff2-variations");
	font-weight: 400 700;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Golos Text";
	src: url(fonts/golos.woff2) format("woff2-variations");
	font-weight: 400 700;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Literata";
	src: url(fonts/literata.woff2) format("woff2-variations");
	font-weight: 400 600;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Literata";
	src: url(fonts/literata-italic.woff2) format("woff2");
	font-weight: 400;
	font-style: italic;
	font-display: swap;
}

:root {
	/* Чернила и бумага. Полосы страницы чередуются: тёмная — светлая. */
	--ink: #0f0f16;
	--ink-2: #1a1a24;
	--ink-3: #262632;
	--paper: #f4efe5;
	--paper-2: #e9e1d2;

	/* Текст. Контраст проверен на своей подложке, ниже 4,5 : 1 пар нет. */
	--on-paper: #14141c;
	--on-paper-2: #55535f;
	--on-ink: #f4efe5;
	--on-ink-2: #a8a4b2;

	/* Акцент — киноварь. Тёмный текст на ней даёт 4,5 : 1 ровно; светлее
	   заливку делать нельзя, темнее — тоже (нажатая кнопка меняет цвет
	   подписи, а не только фон, см. --accent-pressed). */
	--accent: #e8442a;
	--accent-pressed: #c9381f;
	--accent-soft: #fbddd5;

	/* Маркер — сквозной мотив разметки: имена в прозе, слова в заголовках. */
	--mark: #f5b93b;
	--mark-soft: #fbe7b4;

	/* Линейки. */
	--rule-paper: #d5cbb8;
	--rule-ink: #31313e;

	/* Опасное: удаление аккаунта, отклонённый файл, ошибка поля. */
	--danger: #b4301c;
	--danger-soft: #f7d4cd;

	/* Темы читалки в демонстрации. Не интерфейс сайта — содержимое макета. */
	--theme-sepia: #efe3ce;
	--on-sepia: #3b3226;
	--theme-night: #0b0b10;
	--on-night: #9a9aa8;
	--rule-sepia: #3b322622;

	/* Гарнитуры. */
	--font-display: "Unbounded", system-ui, sans-serif;
	--font-ui: "Golos Text", system-ui, sans-serif;
	--font-prose: "Literata", Georgia, serif;

	/* Ритм и форма. */
	--pad-page: 96px;
	--r-sm: 8px;
	--r-md: 18px;
	--r-lg: 28px;

	/* Шкала H1. Три роли на 1440 и четыре на 390: последняя нужна потому,
	   что слово «конфиденциальности» шире экрана 390 при любом кегле
	   крупнее 24px и иначе рвётся посреди слова. */
	--h1-hero: 70px;
	--h1-page: 68px;
	--h1-narrow: 56px;

	/* ── Наши добавки ───────────────────────────────────────────────────────
	 *
	 * Ниже — то, чего в макете нет переменной, но есть числом. Две группы, и
	 * обе про текучесть: макет нарисован на 1440 и 390, а раскладка обязана
	 * не ломаться на 768 и 1024. */

	/* Ширина содержимого: 1440 − 2 × 96. Дальше полоса центрируется, а не
	   растягивается: строка прозы шире 1248 читается хуже. */
	--wrap: 1248px;

	/* Шкала H1 для промежутка между нарисованными ширинами. Значения не
	   выдуманы: это те же три роли, ужатые пропорционально. */
	--h1-mid-hero: 52px;
	--h1-mid-page: 50px;
	--h1-mid-narrow: 42px;
}

/* Промежуточная ширина: поля меньше, заголовки меньше, раскладка ещё в две
   колонки. Порог 1080 выбран замером: на нём двухколоночный герой с полем 96
   оставляет правой колонке меньше 380 px, то есть карточка сущности перестаёт
   помещаться. */
@media (max-width: 1080px) {
	:root {
		--pad-page: 48px;
		--h1-hero: var(--h1-mid-hero);
		--h1-page: var(--h1-mid-page);
		--h1-narrow: var(--h1-mid-narrow);
	}
}

@media (max-width: 480px) {
	:root {
		--pad-page: 20px;
		--h1-hero: 34px;
		--h1-page: 34px;
		--h1-narrow: 32px;
		--h1-long: 28px;
		--h1-xlong: 24px;
	}
}

/* Движение. Значения — из памятки «Состояния и движение» в макете. */
:root {
	--motion-sheet: 240ms;
	--motion-card: 160ms;
	--motion-hover: 120ms;
	--motion-badge: 200ms;
	--motion-spinner: 900ms;
	--motion-generation: 2500ms; /* постановочная пауза «Генерация», 2–3 с */
	/* Одна кривая на весь сайт: быстрый разгон, мягкое торможение, без отскока.
	   Числа те же, что стояли литералом у шторки демонстрации. */
	--ease: cubic-bezier(0.22, 0.8, 0.3, 1);
}

@media (prefers-reduced-motion: reduce) {
	/* Обнуляются И длительности, И задержки: если обнулить только
	   длительности, содержимое остаётся невидимым первые доли секунды.
	   Пауза «Генерация» при этом остаётся — она не украшение, а показ
	   процесса; исчезает только вращение индикатора (см. `.spin`). */
	*, *::before, *::after {
		animation-duration: 1ms !important;
		animation-delay: 0ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 1ms !important;
		transition-delay: 0ms !important;
		scroll-behavior: auto !important;
	}
}

/* ── Сброс и основание ───────────────────────────────────────────────────── */

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

html { -webkit-text-size-adjust: 100%; }

body {
	margin: 0;
	background: var(--paper);
	color: var(--on-paper);
	font-family: var(--font-ui);
	font-size: 16px;
	line-height: 1.5;
	font-variant-numeric: lining-nums tabular-nums;
	-webkit-font-smoothing: antialiased;
}

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

/* Сброс полей, которых в макете нет вовсе: у `figure` браузер по умолчанию
   ставит `margin: 0 40px`, и это **сдвигало каждый кадр на 40 px** и урезало
   его ширину — замерено на кадре героя: 520 вместо 560 и отступ 40 слева.
   `dl`, `dd`, `blockquote` и списки — та же история: макет не знает ни одного
   из этих отступов, потому что в нём нет ни `figure`, ни `dl`. */
figure, dl, dd, blockquote, ul, ol { margin: 0; }
ul, ol { padding-left: 0; }

a { color: inherit; }

button, input, select, textarea { font: inherit; color: inherit; }

/* Фокус виден всегда и от движения не зависит (памятка, правило 3). Обводка
   маркером повторяет образцы фокуса макета: там это внешняя тень `$mark`
   разлётом 4, то есть кольцо той же толщины. */
:focus-visible {
	outline: 3px solid var(--mark);
	outline-offset: 2px;
}

.on-ink :focus-visible, .band-ink :focus-visible { outline-color: var(--mark); }

/* Цели касания не меньше 24 × 24 даже там, где элемент выглядит мельче. */
a, button, summary, label, input[type="radio"], input[type="checkbox"] {
	min-height: 24px;
}

.vh {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ── Типографика ─────────────────────────────────────────────────────────── */

/* Заголовок обязан быть заголовком **по классу, а не по тегу**.
 *
 * Замерено на живой странице: `<p class="h-hero">` брал гарнитуру у `body` —
 * Golos Text вместо Unbounded, вес 400 вместо 600, интерлиньяж 1,5 вместо 1,08.
 * То есть главный заголовок сайта был набран не тем шрифтом, потому что правило
 * висело на теге `h1..h4`, а разметка ставит класс на `p` и `span`. Класс здесь
 * несёт всё сам.
 *
 * Трекинг снят: в макете `letterSpacing` у заголовков **ноль** на 2 048
 * текстовых узлах, кроме двух; прежние −0,01em ужимали каждую строку без
 * основания.
 *
 * Вес по умолчанию 500, а не 600: макет набирает заголовки страниц пятисотым
 * (`disp 68 500`, `disp 34 500`), и только герой — шестисотым. */
h1, h2, h3, h4,
.h-hero, .h-page, .h-narrow, .h-long, .h-xlong {
	margin: 0;
	font-family: var(--font-display);
	font-weight: 500;
	line-height: 1.08;
}

p { margin: 0; }

/* Три роли заголовка. Каждый заголовок макета ссылается на одну из них —
   переносится ссылка, а не значение. Кегль, вес и интерлиньяж — из макета. */
.h-hero { font-size: var(--h1-hero); font-weight: 600; }
.h-page { font-size: var(--h1-page); line-height: 1.05; }
.h-narrow { font-size: var(--h1-narrow); line-height: 1.1; }

@media (max-width: 480px) {
	.h-long { font-size: var(--h1-long); }
	.h-xlong { font-size: var(--h1-xlong); }
}

/* Заголовок раздела внутри полосы. */
/* Кегли заголовков блоков сняты с макета поимённо: 40 · 44 · 46 · 52 · 60 · 76.
   Это не шкала `h1` (та про роли страницы), а размер конкретного заголовка. */
.h2 { font-family: var(--font-display); font-size: 40px; font-weight: 500; line-height: 1.14; }
.d44 { font-size: 44px; }
/* 34 — кегль подзаголовка внутри блока: «Восемь настроек» и «Как из фразы
   получается кадр». Интерлиньяж и трекинг свои, из макета. */
.d34 { font-size: 34px; line-height: 1.15; letter-spacing: -0.6px; font-weight: 600; }
.d34-500 { font-weight: 500; letter-spacing: normal; line-height: 1.2; }
.ls-n1 { letter-spacing: -1px; }
.d46 { font-size: 46px; font-weight: 400; }
.d52 { font-size: 52px; line-height: 1.08; }
.d60 { font-size: 60px; }
.d76 { font-size: 76px; font-weight: 500; }

@media (max-width: 720px) {
	.d44, .d46, .d52, .d60, .d76 { font-size: 28px; }
}
.h3 { font-family: var(--font-display); font-size: 26px; font-weight: 600; line-height: 1.15; }
.h4 { font-family: var(--font-ui); font-size: 20px; font-weight: 600; line-height: 1.3; }

/* Кикер — надпись над заголовком: прописные, разрядка, значок или черта
   слева. Красный маркер у светлой полосы, жёлтый — у тёмной. */
/* Надзаголовок раздела — **только текст**. Переписи по всему файлу макета: из
   сорока с лишним надзаголовков декорацию несут ровно три, и все три на
   Лендинге («СВОЯ КНИГА», «ЧЕСТНО О НЕДОДЕЛАННОМ», «ЧТО СКОЛЬКО СТОИТ»).
   Круглая точка перед каждым была выдумкой сайта. Кегль 13 и трекинг 2,2 —
   тоже из переписи: так набраны надзаголовки всех страниц на 1440. */
.kick {
	display: flex;
	align-items: center;
	gap: 12px;
	font-family: var(--font-ui);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 2.2px;
	text-transform: uppercase;
	color: var(--accent);
}

/* Цвет надзаголовка: **киноварь по умолчанию** и маркер на чернилах — так
   набраны почти все сорок надзаголовков макета. Серый остаётся исключением и
   называется классом: «ЧТО СКОЛЬКО СТОИТ», «ДАЛЬШЕ», «РЕКВИЗИТЫ ПРОДАВЦА»,
   «В ЭТОМ ДОКУМЕНТЕ» — и «ЧЕСТНО О НЕДОДЕЛАННОМ», который на чернилах серый, а
   не маркерный. До правки серым было всё, а киноварь стояла исключением. */
.kick-dim { color: var(--on-paper-2); }
.on-ink .kick-dim, .band-ink .kick-dim { color: var(--on-ink-2); }

/* Черта 22 × 3 — у двух надзаголовков; квадрат 14 × 3 радиуса 3 — у одного. */
.kick-dash::before, .kick-sq::before {
	content: "";
	background: var(--accent);
	flex-shrink: 0;
}

.kick-dash::before { width: 22px; height: 3px; }
/* Точка — единственный круглый маркер во всём файле, и он у надзаголовка
   героя: круг 7 px киноварью, зазор 10, кегль 12 при трекинге 2. Общее
   правило «точки нет» верно для сорока надзаголовков и неверно для этого
   одного, поэтому точка живёт своим классом. */
.kick-dot::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--accent); flex-shrink: 0; }
.kick-dot { gap: 10px; font-size: 12px; letter-spacing: 2px; }
.kick-sq::before { width: 14px; height: 14px; border-radius: 3px; }
.kick-sq { gap: 10px; }

/* На 390 надзаголовок 12-м — там же, в переписи. */
@media (max-width: 720px) {
	.kick { font-size: 12px; }
}

.on-ink .kick { color: var(--mark); }

/* Плашка и кнопка обжимают свой текст, и это приходится писать числом.
 * Причина: `display: inline-flex` внутри колоночного флекса **блокифицируется**
 * — элемент становится флекс-элементом, а тот при `align-items: stretch`
 * растягивается на всю колонку. Поймано на метке блока: 744 px вместо 293.
 *
 * `width: fit-content`, а не `align-self: flex-start`: второй заодно ломает
 * вертикальное выравнивание тех же плашек внутри строк, где они стоят по
 * центру. Полная ширина остаётся у тех, кому она нарисована, — у них своя
 * пометка (`.btn-w720`, `.phone-btn`). */
.kick-badge, .pill, .btn, .phone-cta { width: fit-content; max-width: 100%; }

/* Кнопка во всю ширину только в узкой ширине: так нарисованы главные кнопки
   Лендинга 390 — в герое и в ценах. На 1440 те же кнопки обжимают текст. */
@media (max-width: 720px) {
	.btn-w720 { width: 100%; }
}

/* Подпись раздела с номером — «03 — ЭКРАНЫ ПРИЛОЖЕНИЯ» на плашке. */
.kick-badge {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 7px 12px;
	border-radius: var(--r-sm);
	background: var(--mark-soft);
	color: var(--on-paper);
	font-family: var(--font-ui);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 1.6px;
	text-transform: uppercase;
}

/* Плашка на киноварной заливке набирается **чернилами**, а не бумагой:
   `--paper` на `--accent` даёт 3,46 : 1 при пороге 4,5 для мелкого текста, а
   `--on-paper` — 4,5 : 1 ровно. Замерено, а не выбрано на вид. */
.kick-badge-acc { padding: 6px 11px; background: var(--accent); color: var(--ink); font-weight: 700; letter-spacing: 1.4px; }

/* Малая надпись прописными — «ЕЩЁ ЗОВУТ», «ВНЕШНОСТЬ», «ДОКУМЕНТЫ». */
.cap {
	font-family: var(--font-ui);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	color: var(--on-paper-2);
}

/* `:where` здесь обязателен, и это не украшение. Без него `.on-ink .cap`
   (два класса) побеждает `.acc-txt` и `.mark-txt` (один класс), и метка,
   которой макет назначил киноварь, приезжает серой — замерено на метке
   «ИЛЛЮСТРАЦИЯ ПО ПОДЧЁРКНУТОМУ ОПИСАНИЮ». `:where` обнуляет вклад полосы в
   специфичность, оставляя правило на месте по порядку. */
.on-ink :where(.cap) { color: var(--on-ink-2); }

/* Метка мельче. В макете два размера метки живут рядом: 12/1,4 и 11/1,6 —
   второй стоит у карточки справочника, у подписи иллюстрации и у названий
   настроек. Это не вариация на глаз, а два разных значения в файле.
   Правило обязано стоять **после** `.cap`: специфичность та же, решает порядок. */
.cap2 { font-size: 11px; letter-spacing: 1.6px; }

/* Трекинг метки — **числом, а не именем**.
 *
 * В макете он свой почти у каждого места: 0,4 у метки рода, 0,6 у подписи
 * состояния, 1,4 у колонтитула, 1,6 у подписей разделов карточки, 1,8 у
 * подписей ползунка, 2,0 у надзаголовка героя, 2,2 и 2,4 у надзаголовков
 * блоков. Имя вроде `.cap-wide` тут соврало бы: «широкий» — это шесть разных
 * значений, и выбирать между ними на глаз мы уже пробовали. */
.ls-06 { letter-spacing: 0.6px; }
.ls-16 { letter-spacing: 1.6px; }
.ls-18 { letter-spacing: 1.8px; }
.ls-20 { letter-spacing: 2px; }
.ls-22 { letter-spacing: 2.2px; }
.ls-24 { letter-spacing: 2.4px; }

/* Кегль метки — там же, где трекинг: 13-й у надзаголовков блоков. */
.cap-13 { font-size: 13px; }

/* Интерлиньяж заголовка — тем же числом и по той же причине: в макете он свой
   у каждого заголовка (1,05 · 1,08 · 1,1 · 1,14 · 1,2 · 1,25), и общего
   значения у них нет. */
.lh-105 { line-height: 1.05; }
.lh-115 { line-height: 1.15; }
.lh-110 { line-height: 1.1; }
.lh-120 { line-height: 1.2; }

/* Слово под маркером в заголовке блока: поля 6 / 14 / 10 — у него своя высота
   заливки, потому что кегль 76, а не 70, как в герое. */
.mark-box-2 { padding: 6px 14px 10px; }

/* Подпись состояния живого блока: 13 / 600 / 0,6 со значком рядом — не метка
   колонтитула, и в макете она набрана иначе. */
.state-lab {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: var(--font-ui);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.6px;
}

/* ── Заметка в рамке ─────────────────────────────────────────────────────────
 *
 * В макете подсказка живого блока — не свободная строка, а коробка на вторых
 * чернилах: радиус 8, поля 14 × 16, значок и текст 14 / 1,55. Второй размер
 * (12 × 14, текст 13,5) стоит там, где заметка подпирает карточку. */
.note {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 14px 16px;
	border-radius: var(--r-sm);
	background: var(--ink-2);
	font-size: 14px;
	line-height: 1.55;
	color: var(--on-ink-2);
}

.note-sm { gap: 10px; padding: 12px 14px; font-size: 13.5px; }

/* Внешность в карточке — тоже проза книги: Literata 15 / 1,55. Это описание
   из текста, а не подпись интерфейса. */
.card-bio { font-family: var(--font-prose); font-size: 15px; line-height: 1.55; }

/* Заголовок панели графика — 22 / 600 / 1,3 (`.h4` — двадцатый, это другое
   место). */
.chart-h { font-family: var(--font-ui); font-size: 22px; font-weight: 600; line-height: 1.3; }

/* Лид рядом с заголовком блока — 16 / 1,6 и колонка 440: числа макета.
   `.lede` (17 / 1,55) стоит на страницах, здесь другое место. */
.lede-16 { font-size: 16px; line-height: 1.6; }
.cols-64 { gap: 64px; }
.cols-end { align-items: end; }

/* Проза в карточке шага — Literata 20 / 1,35, как в макете: это текст книги,
   а не подпись. Сама карточка держит текст **по центру**: в макете
   `justifyContent: center`, и от этого шаг читается как показ, а не как
   подпись сверху. */
.step-prose { font-family: var(--font-prose); font-size: 20px; line-height: 1.35; }
.step-body { justify-content: center; }

/* Зазор трёх шагов — 20 в обеих ширинах: в макете `Шаги` gap 20 на 1440 и 20 на
   390. Селектор двойной намеренно: `.cols-3` с общим зазором 40 (и 32 в узкой
   ветке) стоит в файле позже, и одиночный `.steps-3` ему проигрывал по порядку
   — замерено, на боевой стояло 40 в широкой и 32 в узкой. */
.cols-3.steps-3 { gap: 20px; }

/* Три шага в узкой ширине нарисованы в макете своими числами
   (`.pen`, «Лендинг 390 / Как из фразы получается кадр»): плашка 190 у первого
   шага и 210 у второго с третьим, поля 20, зазор внутри 10, номер 24 с
   двенадцатым кеглем, название 15-е, проза 17-я, подпись 13 / 1,55, зазор шагов
   20, заголовок 24 / 1,25, подзаголовок 14 / 1,6.

   До правки узкая ширина брала числа широкой — плашка 260 плюс поля 28,
   название 20-е, проза 20-я, — и три почти пустые плашки давали больше семисот
   пикселей воздуха на экране в 350 шириной. */
@media (max-width: 720px) {
	.steps-head .h2 { font-size: 24px; line-height: 1.25; }
	.steps-head .sm2 { font-size: 14px; line-height: 1.6; }
	.step .h4 { font-size: 15px; }
	.step .step-no { width: 24px; height: 24px; font-size: 12px; }
	.step .step-body { min-height: 190px; gap: 10px; padding: 20px; }
	.step:not(:first-child) .step-body { min-height: 210px; }
	.step .step-prose { font-size: 17px; }
	.step > .sm { font-size: 13px; line-height: 1.55; }
}

/* Полоса блока «кто есть кто» — 96 по вертикали, как в макете; у героя 84, и
   это разные числа в файле, а не одно. */
/* Полоса блока иллюстраций — 96 сверху и снизу, как нарисовано. Класс с
   двумя именами намеренно: у `.band` поля заданы сокращением, и одиночный
   класс проигрывал ему по порядку. */
.band.band-96 { padding-top: 96px; padding-bottom: 96px; }
.note .ico { margin-top: 2px; color: var(--mark); }

/* Строка «значок плюс метка». В макете значок такой строки всегда 14 × 14, а не
   по кеглю метки, поэтому размер стоит здесь, а не наследуется от `1em`. */
.cap-row { display: flex; align-items: center; gap: 8px; }

/* Цвет `.lede` не задаёт намеренно: его задаёт полоса. Явный `--on-paper`
   здесь делал лид невидимым на каждой тёмной полосе. */
.lede { font-size: 17px; line-height: 1.55; }
/* Лид блока иллюстраций — 18-м: там он единственный текст на чернилах.
   Двойной класс — потому что `.prose` задаёт свой кегль ниже по файлу. */
.prose.lede-18 { font-size: 18px; line-height: 1.55; }
.dim { color: var(--on-paper-2); }
.on-ink :where(.dim) { color: var(--on-ink-2); }
.sm { font-size: 13px; line-height: 1.45; }
.sm2 { font-size: 15px; line-height: 1.5; }

/* Проза книги — единственное место Literata. */
.prose {
	font-family: var(--font-prose);
	font-size: 17px;
	line-height: 1.7;
}

.on-ink .prose { color: var(--on-ink); }

/* Маркер: имя сущности в прозе и слово в заголовке. Это не подсветка поиска,
   а сквозной мотив разметки. */
/* Маркер имени в прозе: в макете рамка с радиусом 3 и полями 1 × 5, а само
   имя набрано шестисотым — в остальной прозе вес обычный. */
.mark {
	background: var(--mark);
	color: var(--on-paper);
	font-weight: 600;
	padding: 1px 5px;
	border-radius: 3px;
	box-decoration-break: clone;
}

.mark-soft { background: var(--mark-soft); }

/* Слово в заголовке, залитое маркером целиком. Числа из макета: поля 2 × 14,
   радиус 6, чернила `--ink`, а не `--on-paper` — это два разных чёрных
   (#0F0F16 против #14141C), и подмена видна на заливке маркером. */
.mark-box {
	display: inline-block;
	background: var(--mark);
	color: var(--ink);
	padding: 2px 14px;
	border-radius: 6px;
}

/* Подчёркнутая линия под фразой заголовка: маркер или киноварь. */
.uline { box-shadow: inset 0 -0.14em 0 var(--mark); }
/* Полоса под строкой заголовка — прямоугольник 8 px радиуса 2 под текстом, а
   не подчёркивание внутри строки: в макете это отдельный маркер, и он стоит
   только под второй строкой. */
/* Черта под второй строкой заголовка. В широкой ширине узел блочный и черта
   ровно под ним — так нарисовано (623 px под строкой 623). В узкой ширине узел
   становится строчным, а заголовок — одним потоком: иначе четыре строки вместо
   трёх и черта во всю ширину экрана (см. узкую ветку ниже по файлу). */
.uline-mark {
	display: inline-block;
	width: fit-content;
	padding-bottom: 10px;
	background: linear-gradient(var(--mark), var(--mark)) 0 100% / 100% 8px no-repeat;
	border-radius: 2px;
}

/* Полоса маркером 6 px — та же фраза, но в блоке своей книги она маркерная. */
.uline-mark-bar {
	align-self: flex-start;
	display: inline-block;
	padding-bottom: 10px;
	background: linear-gradient(var(--mark), var(--mark)) 0 100% / 100% 6px no-repeat;
}

/* То же для фразы пояснения: киноварная полоса 5 px под каждой из двух строк. */
.claim { font-family: var(--font-ui); font-size: 17px; font-weight: 600; }
.uline-acc-bar {
	align-self: flex-start;
	display: inline-block;
	padding-bottom: 9px;
	background: linear-gradient(var(--accent), var(--accent)) 0 100% / 100% 5px no-repeat;
}

/* Пояснение шлюза — интерфейсной гарнитурой 17 / 1,55, а не прозой: в макете
   оба абзаца набраны Golos Text. */
.sm2-17 { font-family: var(--font-ui); font-size: 17px; line-height: 1.55; }
/* 15 / 1,6 — кегль пояснений блока своей книги. У общего `.sm2` интерлиньяж
   1,5, и на трёх шагах разница видна строкой. */
.sm2-15 { font-size: 15px; line-height: 1.6; }
.uline-acc { box-shadow: inset 0 -0.12em 0 var(--accent); }

/* Зачёркнутое слово — «а не за месяц». Черта киноварью поверх. */
.strike { position: relative; color: var(--on-paper-2); }

/* Зачёркивание — киноварная полоса 9 px, шире слова с обеих сторон и на 52 %
   высоты: числа макета. Радиус и наклон **разные у двух мест**: у FB2 в блоке
   своей книги полоса радиуса 4 и повёрнута на два градуса, у «за месяц» в
   ценах — радиуса 2 и ровная. Прежняя была одна на оба, 5 px и без радиуса. */
.strike::after {
	content: "";
	position: absolute;
	left: -3%;
	right: -3%;
	top: 52%;
	height: 9px;
	border-radius: 2px;
	background: var(--accent);
}

.strike-tilt::after { left: -5%; right: -5%; border-radius: 4px; transform: rotate(2deg); }

/* Фраза-описание в прозе: подчёркивание киноварью, нажатие рисует кадр. */
.descr {
	border-bottom: 1px solid var(--accent);
	cursor: pointer;
	background: none;
	border-left: 0;
	border-right: 0;
	border-top: 0;
	padding: 0;
	font: inherit;
	color: inherit;
	text-align: left;
}

.num { font-variant-numeric: lining-nums tabular-nums; }
.danger-txt { color: var(--danger); }

/* ── Значок ──────────────────────────────────────────────────────────────── */

/* Значок несёт свой размер **сам**, атрибутами `width`/`height`.
 *
 * Здесь стояло `width: 1em; height: 1em`, и это тихо отменяло размер, который
 * ставит вызов `@Icon(имя, N)`: правило CSS всегда сильнее презентационного
 * атрибута. Замерено на живых страницах: на `/features` **72 значка из 76**
 * рисовались не в своём размере (18 объявлено — 16 нарисовано), значок внутри
 * `<summary>` выходил нулевой ширины, а значок функции героя сжимался флексом
 * до 11 px при объявленных 22. Размер значка приходит из разметки и снят с
 * макета поштучно; правил размера в этом файле больше нет ни одного. */
.ico {
	flex: none;
	stroke: currentColor;
	fill: none;
}

/* Обёртка, в которой лежит только значок, тоже не имеет права сжиматься:
   сжимается **она**, а не сам значок, и замер это поймал — значок функции
   героя при объявленных 22 рисовался в 11,28 px, потому что флекс отдал всю
   ширину тексту рядом.
   
   Обёртки названы поимённо, а не выбраны через `:has(> .ico:only-child)`:
   такое правило задевает `<summary>` бургера в шапке, и замер на 390 поймал
   это сразу — шапка вылезала за экран на 7 px. */
/* Значок функции героя не сжимается флексом: 22 px в разметке — 22 px на
   экране. Замер до правки давал 10 px у первого и 18 у второго. */
.hero-feat-i { flex: none; }

/* Пункт «своей книги» на демонстрации — карточка вторыми чернилами: радиус 18,
   поля 22, зазор 16, значок 22. До сверки это была строка без подложки. */
.own-item { padding: 22px; border-radius: var(--r-md); background: var(--ink-2); }
.own-item-i { flex: none; color: var(--mark); }

/* Вращение индикатора: 900 мс, равномерно, бесконечно. При сниженном
   движении вращение исчезает, а сам индикатор остаётся на месте. */
.spin { animation: spin var(--motion-spinner) linear infinite; }

@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
	.spin { animation: none !important; }
}

/* ── Полосы ──────────────────────────────────────────────────────────────── */

.band { padding: 88px var(--pad-page); }
/* Шапка внутренней страницы: 80 сверху и 56 снизу у публичных, 72/48 у
   кабинета — числа макета. Стояло 56/56 у всех. */
.band-tight { padding: 80px var(--pad-page) 56px; }
.band-tight-cab { padding: 72px var(--pad-page) 48px; }
/* Последняя полоса демонстрации: 104 снизу — макет даёт воздух перед подвалом. */
.band-b104 { padding-bottom: 104px; }
/* Полоса 80 сверху и снизу — так набраны «что бесплатно» и «правила» на ценах. */
.band.band-80 { padding-top: 80px; padding-bottom: 80px; }
/* Полосы страницы «что умеет»: честная строка 28, оглавление 24, разделы 72. */
.band.band-strip { padding-top: 28px; padding-bottom: 28px; }
.band.band-toc { padding-top: 24px; padding-bottom: 24px; }
.band.band-72 { padding-top: 72px; padding-bottom: 72px; }
/* 16 сверху: шапка страницы уже дала воздух снизу, и макет его не удваивает. */
.band.band-t16 { padding-top: 16px; }

/* Контакты: первый абзац 22 / 1,64, черта маркером 120 × 2, второй 19 / 1,68. */
.contacts-lede { font-family: var(--font-ui); font-size: 22px; line-height: 1.64; }
.contacts-x { font-family: var(--font-ui); font-size: 19px; line-height: 1.68; }
.rule-mark { width: 120px; height: 2px; margin: 0; border: 0; background: var(--mark); }

/* Реквизиты — карточка второй бумаги: радиус 18, поля 32, зазор 18; значение в
   своей коробке высотой 52 с полями 16. */
.req-card { padding: 32px; border-radius: var(--r-md); background: var(--paper-2); border: 1px solid var(--rule-paper); }
.req-lab { font-family: var(--font-ui); font-size: 15px; font-weight: 600; }
.req-note { font-family: var(--font-ui); font-size: 15px; line-height: 1.6; }
.req-val { display: flex; align-items: center; min-height: 52px; padding: 0 16px; border-radius: var(--r-sm); background: var(--paper); font-family: var(--font-ui); font-size: 15px; }

.strip-t { font-family: var(--font-ui); font-size: 18px; line-height: 1.56; }
.band-strip .ico { color: var(--mark); }
.toc-note { font-family: var(--font-ui); font-size: 14px; color: var(--on-paper-2); }

/* Плашка оглавления: высота 44, таблетка, подпись 14, счётчик своей плашкой.
   Выбранный раздел — чернильный с маркерным счётчиком. */
.toc-i {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	height: 44px;
	padding: 0 16px;
	border-radius: 999px;
	background: var(--paper);
	color: var(--on-paper);
	font-family: var(--font-ui);
	font-size: 14px;
	font-weight: 500;
	text-decoration: none;
}

.toc-i:hover { background: var(--ink); color: var(--on-ink); }
.toc-i:hover .toc-n { background: var(--ink-3); color: var(--on-ink); }
.toc-i-on { background: var(--ink); color: var(--on-ink); font-weight: 600; }
.toc-n { padding: 2px 7px; border-radius: 999px; background: var(--paper-2); color: var(--on-paper); font-size: 13px; font-weight: 600; }
.toc-i-on .toc-n { background: var(--mark); color: var(--ink); }

/* Шапка раздела: номер маркером 44, название 40, счётчик плашкой, линейка снизу
   с отступом 20. */
.feat-head { align-items: flex-end; flex-wrap: wrap; padding-bottom: 20px; border-bottom: 1px solid var(--rule-paper); }
.band-ink .feat-head { border-bottom-color: var(--rule-ink); }
.feat-no { font-family: var(--font-display); font-size: 44px; font-weight: 500; line-height: 1; color: var(--mark); }
.feat-h { flex: 1 1 auto; min-width: 0; margin: 0; font-family: var(--font-display); font-size: 40px; font-weight: 500; line-height: 1.1; }
.feat-cnt { padding: 7px 14px; border-radius: 999px; background: var(--paper-2); font-family: var(--font-ui); font-size: 14px; font-weight: 600; }
.band-ink .feat-cnt { background: var(--ink-3); color: var(--on-ink); }

/* Пункт — карточка второй бумаги радиуса 8 с полями 20, значок 16, текст
   15 / 1,53. Три в ряд, зазор 14. */
.feat-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.feat-i { gap: 12px; padding: 20px; border-radius: var(--r-sm); background: var(--paper-2); }
.band-ink .feat-i { background: var(--ink-2); }
.feat-i .ico { color: var(--accent); flex-shrink: 0; margin-top: 3px; }
.band-ink .feat-i .ico { color: var(--mark); }
.feat-t { font-family: var(--font-ui); font-size: 15px; line-height: 1.53; }

@media (max-width: 1080px) { .feat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .feat-grid { grid-template-columns: minmax(0, 1fr); } }
/* Полоса 96 сверху — завершающее действие страницы цен. */
.band.band-96 { padding-top: 96px; padding-bottom: 96px; }

/* Карточка бесплатного: вторые чернила, радиус 28, поля 36, зазор 16. */
.free-card { padding: 36px; border-radius: var(--r-lg); background: var(--ink-2); }

/* Коробка примечания: вторая бумага, радиус 8, поля 16 / 20, текст 16 / 1,55. */
.note-box { align-items: center; gap: 12px; padding: 16px 20px; border-radius: var(--r-sm); background: var(--paper-2); }
.note-box-t { font-family: var(--font-ui); font-size: 16px; line-height: 1.55; }

/* Заметка под ползунком — карточка вторых чернил радиуса 8 с полями 14 / 16,
   значок 18 и текст 14 / 1,57. До сверки это были свободные строки. */
.note-ink { margin: 0; gap: 12px; padding: 14px 16px; border-radius: var(--r-sm); background: var(--ink-2); font-family: var(--font-ui); font-size: 14px; line-height: 1.57; color: var(--on-ink-2); }
.note-ink .ico { color: var(--mark); flex-shrink: 0; }
.on-ink .note-box, .band-ink .note-box { background: var(--ink-2); }

/* Завершающее действие: заголовок 44 в 900, сноска 17 в 700. */
.cta-head { max-width: 900px; }
.cta-note { max-width: 700px; font-family: var(--font-ui); font-size: 17px; line-height: 1.59; }
.band-tall { padding: 112px var(--pad-page); }

.band-ink { background: var(--ink); color: var(--on-ink); }
.band-ink2 { background: var(--ink-2); color: var(--on-ink); }
.band-p2 { background: var(--paper-2); }

.wrap { max-width: var(--wrap); margin-inline: auto; }

/* Одна карточка на полосе. Ширина — как у формы в двухколонной раскладке, а
   левый край — как у заголовка полосы: карточка по центру пустой строки
   читается как заглушка, хотя это состояние. Заведено под закрытую регистрацию
   — единственную страницу с одной карточкой вместо формы и врезки. */
.card-one { max-width: 560px; }

.hair { height: 1px; background: var(--rule-paper); border: 0; margin: 0; }
.on-ink .hair, .band-ink .hair { background: var(--rule-ink); }

.stack { display: flex; flex-direction: column; }
.row { display: flex; flex-direction: row; align-items: center; }
.row-top { display: flex; flex-direction: row; align-items: flex-start; }
.wrap-row { flex-wrap: wrap; }
.between { justify-content: space-between; }
.push { margin-left: auto; }
.g6 { gap: 6px; } .g8 { gap: 8px; } .g10 { gap: 10px; } .g12 { gap: 12px; }
.g16 { gap: 16px; } .g18 { gap: 18px; } .g20 { gap: 20px; } .g22 { gap: 22px; } .g24 { gap: 24px; } .g26 { gap: 26px; } .g28 { gap: 28px; } .g32 { gap: 32px; }
.g40 { gap: 40px; } .g48 { gap: 48px; } .g56 { gap: 56px; } .g64 { gap: 64px; } .g72 { gap: 72px; }

/* Две колонки «текст — врезка». Ширина правой взята из макета: 520 у героя,
   440 у страниц. Под 1080 обе схлопываются в одну. */
/* Правая колонка — **600**, как в макете, а не 520: страница книги там 560
   широкая, и в 520 она не влезала, отчего вся композиция героя ужималась.
   Зазор 72 — тоже из макета. */
.cols {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 600px;
	gap: 72px;
	align-items: center;
}

.cols-top { align-items: start; }
.cols-440 { display: grid; grid-template-columns: minmax(0, 1fr) 440px; }
.cols-360 { display: grid; grid-template-columns: minmax(0, 1fr) 360px; }
.cols-480 { display: grid; grid-template-columns: minmax(0, 1fr) 480px; }
.cols-520 { display: grid; grid-template-columns: 520px minmax(0, 1fr); }
.cols-560 { display: grid; grid-template-columns: minmax(0, 1fr) 560px; }
.cols-330 { display: grid; grid-template-columns: minmax(0, 1fr) 330px; }
.phone-hold-cap { font-size: 14px; line-height: 1.5; color: var(--on-ink-2); }
.own-item-t { font-family: var(--font-ui); font-size: 18px; font-weight: 600; }
.cols-mid { align-items: center; }
.row-end { align-items: flex-end; }
/* Шапка шлюза: слева 680 — заголовок, справа остаток под пояснение. */
.cols-680 { display: grid; grid-template-columns: 680px minmax(0, 1fr); }
.cols-g64 { gap: 64px; }
.cols-g80 { gap: 80px; }
/* `display: grid` тут не украшение: без него класс задавал колонки, а полосу
   раскладывал блоком — обе половины шли во всю ширину друг под другом. Поймано
   замером (`display: block`, дети по 1248 при полосе 1248), а жил дефект во
   **всех десяти** местах класса: Главная, цены (два), что умеет, контакты,
   покупка, восстановление пароля (два), профиль кабинета и демонстрация. */
.cols-half { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 56px; }
.cols-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 40px; }
.cols-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; }

@media (max-width: 1080px) {
	.cols, .cols-440 { grid-template-columns: minmax(0, 1fr); gap: 48px; }
	.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
	.cols-half, .cols-3, .cols-4 { grid-template-columns: minmax(0, 1fr); gap: 32px; }
}

/* ── Кнопка ──────────────────────────────────────────────────────────────────
 *
 * Семь состояний макета — одно правило и его ветки, а не семь копий:
 * главная (`$accent`, подпись `$on-paper`), второстепенная (обводка 1,5),
 * опасная (`$danger`), в фокусе (кольцо маркером разлётом 4), нажата
 * (`$accent-pressed`, подпись `$paper`), выключена (`$paper-2` и обводка),
 * отправка (прозрачность 0,75 и вращающийся индикатор). */

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	height: 56px;
	padding: 0 28px;
	border: 0;
	border-radius: 999px;
	background: var(--accent);
	color: var(--on-paper);
	font-family: var(--font-ui);
	font-size: 17px;
	font-weight: 600;
	text-decoration: none;
	cursor: pointer;
	transition: background var(--motion-hover) ease, color var(--motion-hover) ease,
		border-color var(--motion-hover) ease, box-shadow var(--motion-hover) ease;
}


.btn:hover { background: var(--accent-pressed); color: var(--paper); }

.btn:active { background: var(--accent-pressed); color: var(--paper); }

.btn:focus-visible { outline: 0; box-shadow: 0 0 0 4px var(--mark); }

/* Второстепенная: без заливки, обводка 1,5 цветом текста. */
.btn-2 {
	background: none;
	border: 1.5px solid currentColor;
	color: var(--on-paper);
}

.btn-2:hover { background: var(--on-paper); color: var(--paper); }
/* Тёмная шапка кабинета — тоже чернильный контекст, и без неё в перечне
   подпись «Выйти» набиралась бумажными чернилами по чернилам: замерено на
   живой странице, 1,04 : 1. Класс `hdr-ink` стоит рядом с `on-ink` и
   `band-ink` именно поэтому. */
.on-ink .btn-2, .band-ink .btn-2, .hdr-ink .btn-2, .card-ink .btn-2 { color: var(--on-ink); }
.on-ink .btn-2:hover, .band-ink .btn-2:hover, .hdr-ink .btn-2:hover, .card-ink .btn-2:hover {
	background: var(--on-ink);
	color: var(--ink);
}

/* Опасная: обводка и подпись `$danger`, заливка появляется при наведении. */
.btn-dz {
	background: none;
	border: 1.5px solid var(--danger);
	color: var(--danger);
}

.btn-dz:hover { background: var(--danger); color: var(--paper); }

/* Маркерная — герой лендинга. */
.btn-mark { background: var(--mark); color: var(--on-paper); }
.btn-mark:hover { background: var(--mark-soft); color: var(--on-paper); }

/* Чернильная — блок цен на светлой полосе. */
.btn-ink { background: var(--ink); color: var(--on-ink); }
.btn-ink:hover { background: var(--ink-3); color: var(--on-ink); }

.btn-sm { height: 48px; padding: 0 24px; gap: 9px; font-size: 15px; }
.btn-full { width: 100%; }

.btn:disabled, .btn[aria-disabled="true"] {
	background: var(--paper-2);
	border: 1px solid var(--rule-paper);
	color: var(--on-paper-2);
	cursor: not-allowed;
}

/* Отправка: htmx вешает `.htmx-request` на время запроса. Индикатор рисуется
   тем же значком, что в макете, — он лежит в разметке и до отправки скрыт. */
.btn .send-i { display: none; }
.btn.htmx-request { opacity: 0.75; pointer-events: none; }
.btn.htmx-request .send-i { display: block; }
.btn.htmx-request .rest-i { display: none; }

/* ── Ссылка ──────────────────────────────────────────────────────────────── */

/* Подчёркивание — черта по ширине **текста**, а не блока, и `width` здесь
   обязателен. Причина в блокировании: строчный элемент, ставший элементом
   флекс-контейнера (`.stack`, `.bookrow-body`, `.foot-links`), теряет строчность
   — `inline-flex` считается как `flex`, растяжка по умолчанию тянет его во всю
   ширину, и черта уезжает на всю колонку. Замерено на боевой, `/account/books`,
   название «Гранетанцор»: до правки черта 1 110 px, после — 114 px, то есть
   ширина самого названия. Это единственное место, где число названо. */
.lnk {
	display: inline-flex;
	width: fit-content;
	max-width: 100%;
	align-items: center;
	gap: 8px;
	padding: 6px 0;
	font-size: 15px;
	font-weight: 600;
	color: var(--on-paper);
	text-decoration: none;
	border-bottom: 1px solid var(--rule-paper);
	transition: border-color var(--motion-hover) ease, color var(--motion-hover) ease;
}

.lnk:hover { border-bottom-color: var(--accent); }
.on-ink .lnk, .band-ink .lnk { color: var(--on-ink); border-bottom-color: var(--rule-ink); }
.on-ink .lnk:hover, .band-ink .lnk:hover { border-bottom-color: var(--mark); }

.lnk:focus-visible {
	outline: 0;
	border-radius: var(--r-sm);
	padding-inline: 10px;
	box-shadow: 0 0 0 3px var(--mark);
}

/* Строчная ссылка без стрелки. `width` — по той же причине, что у `.lnk`:
   внутри строки текста он не действует вовсе, а элементом флекс-колонки
   (название книги в строке списка) держит черту по ширине названия. */
.lnk-in {
	color: inherit;
	text-decoration: none;
	border-bottom: 1px solid var(--accent);
	font-weight: 600;
	width: fit-content;
	max-width: 100%;
}

/* ── Поле ────────────────────────────────────────────────────────────────────
 *
 * Семь состояний макета: пустое, заполненное, в фокусе (обводка киноварью 2
 * плюс кольцо маркером), с ошибкой (обводка `$danger` 2 и строка со значком),
 * только для чтения (`$paper-2`), пароль (кнопка «показать»), с подсказкой. */

.fld { display: flex; flex-direction: column; gap: 8px; }

.fld-lab {
	font-family: var(--font-ui);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 1.4px;
	text-transform: uppercase;
	color: var(--on-paper-2);
}

.fld-in {
	display: flex;
	align-items: center;
	gap: 10px;
	height: 56px;
	padding: 0 18px;
	background: var(--paper);
	border: 1px solid var(--rule-paper);
	border-radius: var(--r-sm);
	transition: border-color var(--motion-hover) ease, box-shadow var(--motion-hover) ease;
}

.fld-in input {
	flex: 1 1 auto;
	min-width: 0;
	border: 0;
	background: none;
	font-size: 16px;
	outline: 0;
}

.fld-in input::placeholder { color: var(--on-paper-2); }

.fld-in:focus-within {
	border: 2px solid var(--accent);
	padding: 0 17px;
	box-shadow: 0 0 0 4px var(--mark);
}

.fld-pw input { letter-spacing: 2px; }

.fld-eye {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	border: 0;
	border-radius: 999px;
	background: none;
	color: var(--on-paper-2);
	cursor: pointer;
}


.fld-hint { font-size: 13px; line-height: 1.5; color: var(--on-paper-2); }

.fld-err {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.45;
	color: var(--danger);
}

.fld-err .ico { margin-top: 2px; }

.fld-bad .fld-in { border: 2px solid var(--danger); padding: 0 17px; }
.fld-ro .fld-in { background: var(--paper-2); }
.fld-ro input { color: var(--on-paper-2); }

/* Чекбокс согласия. */
.chk { display: flex; align-items: flex-start; gap: 12px; font-size: 15px; line-height: 1.5; }
.chk input { width: 22px; height: 22px; margin: 1px 0 0; accent-color: var(--accent); flex-shrink: 0; }

/* ── Метка состояния и плашки ────────────────────────────────────────────────
 *
 * Плашек шесть на пять состояний схемы: у `pending` два разных смысла, и
 * читателю они говорят разное — суточный потолок откладывает книгу и не
 * требует от него ничего. */

.tag {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 6px 12px;
	border-radius: 999px;
	background: var(--ink);
	color: var(--mark);
	font-family: var(--font-ui);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 1.4px;
	text-transform: uppercase;
}

.plq {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	height: 34px;
	padding: 0 13px;
	border-radius: 999px;
	border: 1px solid transparent;
	font-family: var(--font-ui);
	font-size: 13px;
	font-weight: 600;
	white-space: nowrap;
	transition: opacity var(--motion-badge) ease;
}


.plq-wait { background: var(--paper-2); border-color: var(--rule-paper); color: var(--on-paper); }
.plq-cap { background: var(--mark); color: var(--ink); }
.plq-run { background: var(--accent-soft); color: var(--on-paper); }
.plq-done { background: var(--ink); color: var(--on-ink); }
.plq-fail { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
.plq-stop { background: none; border-color: var(--on-paper-2); color: var(--on-paper); }

/* Те же пять на тёмном фоне — макет рисует их отдельными плашками, потому
   что бумажные цвета на чернилах не читаются. */
.on-ink .plq-wait, .band-ink .plq-wait { background: var(--ink-3); border-color: transparent; color: var(--on-ink); }
.on-ink .plq-wait .ico, .band-ink .plq-wait .ico { color: var(--on-ink-2); }
.on-ink .plq-run, .band-ink .plq-run { background: var(--accent); color: var(--ink); }
.on-ink .plq-done, .band-ink .plq-done { background: var(--mark); color: var(--ink); }
.on-ink .plq-fail, .band-ink .plq-fail { background: none; border-color: var(--danger); color: var(--danger-soft); }
.on-ink .plq-stop, .band-ink .plq-stop { border-color: var(--on-ink-2); color: var(--on-ink); }
.on-ink .plq-stop .ico, .band-ink .plq-stop .ico { color: var(--on-ink-2); }

/* Обновление плашки опросом htmx: затухание на месте 200 мс, строка не
   переставляется. */
.plq-swap.htmx-swapping { opacity: 0; }

/* Пилюля — «персонаж», «Анна Каренина», «Стива». */
.pill {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 10px;
	border-radius: 999px;
	background: var(--mark);
	color: var(--on-paper);
	font-size: 13px;
	font-weight: 600;
	white-space: nowrap;
}

/* Псевдоним — не таблетка: в макете это прямоугольник радиуса 8 с полями
   5 × 10 и **прозой книги** 14-м на второй бумаге. Имя пишет книга — поэтому и
   гарнитура книжная. */
.pill-soft {
	background: var(--paper-2);
	color: var(--on-paper);
	border-radius: 8px;
	padding: 5px 10px;
	font-family: var(--font-prose);
	font-size: 14px;
	font-weight: 400;
	white-space: normal;
}

.on-ink :where(.pill-soft), .band-ink :where(.pill-soft) { background: var(--ink-3); color: var(--on-ink); }
/* Подпись на киноварной заливке — чернилами: бумага на киноварь даёт
   3,46 : 1, чернила — 4,5 : 1 ровно. Регистр так и объявляет: у `--accent`
   парная переменная подписи это `--on-paper`, а `--paper` берётся только на
   **нажатой** кнопке, где заливка темнее (`--accent-pressed`). */
.pill-acc { background: var(--accent); color: var(--on-paper); }
.pill-sq { border-radius: 4px; }

/* Метка рода: **заливка** `--accent-soft` с точкой киноварью и чернильной
   подписью 12 / 600 / 0,4 — так в макете. Прежняя обводка киноварью по бумаге
   была догадкой и давала 3,4 : 1. */
.pill-kind {
	background: var(--accent-soft);
	color: var(--on-paper);
	gap: 7px;
	padding: 5px 11px;
	font-size: 12px;
	letter-spacing: 0.4px;
	text-transform: uppercase;
}

.pill-kind::before {
	content: "";
	width: 7px;
	height: 7px;
	border-radius: 999px;
	background: var(--accent);
	flex-shrink: 0;
}

.on-ink :where(.pill-kind), .band-ink :where(.pill-kind) { background: var(--ink-3); color: var(--on-ink); }

/* ── Шапка и подвал ──────────────────────────────────────────────────────── */

.hdr {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	height: 96px;
	padding: 0 var(--pad-page);
	background: var(--paper);
	border-bottom: 1px solid var(--rule-paper);
}

.hdr-ink { background: var(--ink); color: var(--on-ink); border-bottom-color: var(--rule-ink); }

/* Марка: слово с толстой подложкой маркера снизу — 15 px внутрь. */
.brand {
	display: inline-flex;
	align-items: flex-start;
	font-family: var(--font-display);
	font-size: 26px;
	font-weight: 600;
	line-height: 1;
	color: var(--on-paper);
	text-decoration: none;
	box-shadow: inset 0 -15px 0 var(--mark);
	padding: 2px 2px 0;
}

.hdr-ink .brand { color: var(--on-ink); }

.nav { display: flex; align-items: center; gap: 38px; }

.nav a {
	font-size: 15px;
	font-weight: 500;
	color: var(--on-paper-2);
	text-decoration: none;
	padding: 2px 0;
	border-bottom: 2px solid transparent;
	transition: color var(--motion-hover) ease, border-color var(--motion-hover) ease;
}

.nav a:hover { color: var(--on-paper); border-bottom-color: var(--mark); }
.nav a[aria-current] { color: var(--on-paper); border-bottom-color: var(--mark); }
.hdr-ink .nav a { color: var(--on-ink-2); }
.hdr-ink .nav a:hover, .hdr-ink .nav a[aria-current] { color: var(--on-ink); }

.hdr-right { display: flex; align-items: center; gap: 24px; }

.hdr-login {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 15px;
	font-weight: 600;
	color: var(--on-paper);
	text-decoration: none;
}

.hdr-ink .hdr-login { color: var(--on-ink); }

.hdr-mail { font-size: 14px; color: var(--on-paper-2); }
.hdr-ink .hdr-mail { color: var(--on-ink-2); }

/* Метка «кабинет» в шапке кабинета. */
/* Раздел рядом с маркой. Это подпись, а не кнопка: пилюля с заливкой стояла
   вплотную к логотипу и читалась как действие. Разделитель отодвигает её от
   марки и снимает это прочтение. */
.hdr-sect {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	color: var(--on-ink-2);
	font-family: var(--font-ui);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 1.6px;
}
.hdr-sect::before {
	content: "";
	width: 1px;
	height: 22px;
	background: var(--rule-ink);
}

/* Гамбургер: под 720 навигация уезжает в раскрывающийся список. Без JS —
   `details`, потому что вторая механика на одну кнопку не нужна. */
.hdr-burger { display: none; }

@media (max-width: 900px) {
	.nav { gap: 22px; }
	.hdr-right { gap: 12px; }
}

@media (max-width: 720px) {
	.hdr { height: 70px; }
	.brand { font-size: 22px; box-shadow: inset 0 -11px 0 var(--mark); }
	.hdr-nav-wide { display: none; }
	.hdr-burger { display: block; position: relative; }
	.hdr-burger > summary {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 40px;
		height: 40px;
		border-radius: 999px;
		border: 1px solid var(--rule-paper);
		cursor: pointer;
		list-style: none;
	}
	.hdr-burger > summary::-webkit-details-marker { display: none; }
	.hdr-ink .hdr-burger > summary { border-color: var(--rule-ink); }
	.hdr-drop {
		position: absolute;
		right: 0;
		top: 48px;
		z-index: 20;
		display: flex;
		flex-direction: column;
		gap: 4px;
		min-width: 220px;
		padding: 12px;
		background: var(--paper);
		border: 1px solid var(--rule-paper);
		border-radius: var(--r-md);
		box-shadow: 0 18px 40px rgba(15, 15, 22, 0.18);
	}
	.hdr-ink .hdr-drop { background: var(--ink-2); border-color: var(--rule-ink); }
	.hdr-drop a { padding: 10px 12px; border-radius: var(--r-sm); border-bottom: 0; }
}

/* Подвал. */
.foot { background: var(--ink); color: var(--on-ink); padding: 80px var(--pad-page) 48px; }

.foot-top { display: flex; align-items: flex-end; justify-content: space-between; gap: 80px; flex-wrap: wrap; }

.foot-word {
	display: flex;
	align-items: flex-end;
	gap: 10px;
	font-family: var(--font-display);
	font-size: 104px;
	font-weight: 600;
	line-height: 1;
}

/* Точка после слова — тем же приёмом: псевдоэлемент, а не пустой узел. */
.foot-word::after {
	content: "";
	width: 16px;
	height: 16px;
	margin-bottom: 0.1em;
	border-radius: 4px;
	background: var(--accent);
	flex-shrink: 0;
}

/* Ярлык «ДОКУМЕНТЫ» в подвале — 13 / 1,6, как в макете; общий `.cap` 12 / 1,4. */
.foot .cap { font-size: 13px; letter-spacing: 1.6px; color: var(--on-ink-2); }
.foot-links { display: grid; grid-template-columns: repeat(2, minmax(0, auto)); gap: 16px 56px; }

@media (max-width: 720px) {
	.foot-word { font-size: 54px; }
	.foot-links { grid-template-columns: minmax(0, 1fr); }
}

/* ── Карточка сущности ───────────────────────────────────────────────────────
 *
 * Карточка знает ровно то, что прочитано: спойлерный шлюз — функция базы, и
 * ни один запрос сайта её не обходит. Ни замков, ни размытий, ни счётчиков
 * «N из M» на непрочитанном здесь нет по решению, а не по недосмотру. */

.card {
	background: var(--paper);
	border-radius: var(--r-lg);
	border: 1px solid var(--rule-paper);
	padding: 26px 28px;
	display: flex;
	flex-direction: column;
	gap: 16px;
	transition: opacity var(--motion-card) ease;
}

.card.htmx-swapping { opacity: 0; }

.on-ink .card, .band-ink .card {
	background: var(--ink-2);
	border-color: var(--rule-ink);
	color: var(--on-ink);
}

/* ── Карточка сущности: два состояния, как в макете ──────────────────────────
 *
 * Радиус 18, а не 28: сверено по всему файлу — 140 узлов радиуса 18 против 56
 * радиуса 28, и все 56 это панели (глоссарий, график, настройки), а не
 * карточки.
 *
 * Состояний два, и они значат разное. **Открыта нажатием на имя** — бумажная
 * карточка: её позвал читатель, и она главная на полосе. **Последней
 * открылась** — обведённая на чернилах: её никто не звал, она следствие
 * положения ползунка. Поля и зазоры тоже из макета: 28 / 20 против 24 / 16,
 * имя 26 против 21. */

.card-paper, .card-out { border-radius: var(--r-md); }

.on-ink .card-paper, .band-ink .card-paper {
	background: var(--paper);
	border-color: var(--rule-paper);
	color: var(--on-paper);
	padding: 28px;
	gap: 20px;
}

.card-paper .cap, .card-paper .dim { color: var(--on-paper-2); }
.card-paper .hair { background: var(--rule-paper); }

.on-ink .card-out, .band-ink .card-out {
	background: none;
	border-color: var(--rule-ink);
	padding: 24px;
	gap: 16px;
}

.card-out .card-name { font-size: 21px; }

/* Имя в карточке набрано **интерфейсной** гарнитурой, а не заголовочной:
   в макете это Golos Text 26 / 600 / 1,2. Unbounded здесь был догадкой. */
.card-name { font-family: var(--font-ui); font-size: 26px; font-weight: 600; line-height: 1.2; }

/* Веха — **проза книги**: Literata 16 / 1,5, а не интерфейсные 15. Полоса
   слева киноварная на бумаге и маркерная на чернилах — в макете это два разных
   цвета у двух состояний одной карточки, а не один на оба. */
.card-milestone {
	border-left: 3px solid var(--accent);
	padding-left: 16px;
	font-family: var(--font-prose);
	font-size: 16px;
	line-height: 1.5;
}

.on-ink :where(.card-milestone), .band-ink :where(.card-milestone) {
	border-left-color: var(--mark);
}

.card-paper .card-milestone { border-left-color: var(--accent); }

/* Числа из макета: колонка ключа 96, зазоры 10 × 14, ключ 13-м, значение
   14-м с интерлиньяжем 1,4. Прежние 130 / 16 / 15 были выбраны на глаз. */
.kv { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 10px 14px; }
.kv dt { font-size: 13px; color: var(--on-paper-2); }
.kv dd { margin: 0; font-size: 14px; line-height: 1.4; }
.on-ink :where(.kv) dt, .band-ink :where(.kv) dt { color: var(--on-ink-2); }

.card-rel { display: flex; flex-direction: column; gap: 8px; }
/* Строка связи переносится, а плашка имени внутри неё — рвётся по словам.
   Без этого длинное имя («Степан Аркадьич Облонский», 207 px) вылезало за
   экран на 390: замерено, и вылезало оно и до нынешней правки — `.pill` держит
   `white-space: nowrap`, а роль занимала 120 px из 232 доступных. */
.card-rel-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; min-width: 0; }
.card-rel-row .pill { white-space: normal; }
.card-rel-role { min-width: 120px; font-size: 14px; color: var(--on-paper-2); border-left: 2px solid var(--accent); padding-left: 10px; }
.on-ink .card-rel-role, .band-ink .card-rel-role { color: var(--on-ink-2); }

/* ── Ползунок главы ──────────────────────────────────────────────────────── */

.slider { display: flex; flex-direction: column; gap: 10px; }

.slider input[type="range"] {
	-webkit-appearance: none;
	appearance: none;
	width: 100%;
	height: 22px;
	background: none;
	cursor: pointer;
}

.slider input[type="range"]::-webkit-slider-runnable-track {
	height: 4px;
	border-radius: 999px;
	background: var(--rule-ink);
}

/* Ручка — **бумажная с киноварным кольцом 3 px**, как в макете: 22 × 22,
   заливка `--paper`, обводка `--accent`. Прежняя маркерная с чернильным
   кантом была догадкой. */
.slider input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none;
	width: 22px;
	height: 22px;
	margin-top: -9px;
	border-radius: 999px;
	background: var(--paper);
	border: 3px solid var(--accent);
}

.slider input[type="range"]::-moz-range-track {
	height: 4px;
	border-radius: 999px;
	background: var(--rule-ink);
}

.slider input[type="range"]::-moz-range-thumb {
	width: 22px;
	height: 22px;
	border-radius: 999px;
	background: var(--paper);
	border: 3px solid var(--accent);
}

.slider-scale { display: flex; justify-content: space-between; font-size: 13px; color: var(--on-ink-2); }

/* ── Столбики «сколько статей открыто» ───────────────────────────────────── */

.bars { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 24px; align-items: end; }
.bar-col { display: flex; flex-direction: column; align-items: stretch; gap: 10px; }
.bar-val { font-family: var(--font-display); font-size: 26px; font-weight: 500; text-align: center; }
/* Столбик серый, а маркерный — только у главы, на которой стоит ползунок. До
   сверки маркером были залиты все, и «здесь вы» терялось. Исключение — большой
   график шлюза: там маркерные все, а текущий киноварный (см. ниже). */
.bar { background: var(--on-ink-2); border-radius: var(--r-sm) var(--r-sm) 0 0; min-height: 2px; }
.bar-here .bar { background: var(--mark); }
.bars-big .bar { background: var(--mark); }
.bars-big .bar-here .bar { background: var(--accent); }
/* Ноль — огрызок цвета линейки, а не пустота с чертой: так нарисовано. */
.bar-zero, .bar-here.bar-zero .bar { background: var(--rule-ink); }
.bars-big .bar-zero { background: var(--mark); }
.bar-here .bar-val { color: var(--accent); }
.bar-here .bar { background: var(--accent); }
.bar-lab { font-size: 13px; color: var(--on-ink-2); text-align: center; }
.bars-big .bar-lab { display: flex; flex-direction: column; gap: 4px; min-height: 46px; }
.bar-lab-l { white-space: nowrap; }
.bars-big .bar-here .bar-lab { color: var(--on-ink); font-weight: 600; }
.bar-here-cap { font-size: 11px; font-weight: 400; color: var(--accent); }

@media (max-width: 720px) {
	.bar-val { font-size: 17px; }
	.bar-lab { font-size: 11px; }
}


/* ── Кадр и подпись ──────────────────────────────────────────────────────────
 *
 * Текста поверх кадра нет нигде: замерено, что мелкий текст на иллюстрации
 * даёт 1,49 : 1, а довести затемнение до порога значит скрыть кадр под 91 %
 * чёрного. Кадр и подпись занимают разные полосы. */

/* Кадр и его подпись: между ними 14, внутри подписи 7 — числа макета. */
.shot { display: flex; flex-direction: column; gap: 14px; }

.shot img {
	width: 100%;
	height: auto;
	border-radius: var(--r-md);
	background: var(--ink-3);
}

.shot-cap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; }
/* Фраза под кадром — две строки: столько ей отведено в макете, и столько же
   даёт `Подпись` при кегле 13 / 1,5. Настоящее описание бывает длиннее в
   несколько раз, поэтому текст обрезается показом, а не выборкой — полностью
   он стоит в `alt` и читается вслух средствами доступности. */
.shot-txt {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-size: 13px;
	line-height: 1.5;
	color: var(--on-ink-2);
}
/* Номер кадра — киноварный **текст**, а не плашка: в макете у него нет ни
   подложки, ни поля, только цвет, кегль 11 и трекинг 0,6. */
.shot-no { color: var(--accent); font-size: 11px; font-weight: 600; letter-spacing: 0.6px; }

/* Постановочная пауза «Генерация»: бегущий блик по тёмной подложке плюс
   вращение индикатора. В макете это шейдер `generating.glsl`; WebGL и
   сборщика у нас нет по решению, поэтому состояние воспроизведено CSS —
   единственное сознательное отступление от макета по существу. */
.gen {
	position: relative;
	overflow: hidden;
	border-radius: var(--r-md);
	background-color: #1d0b09;
	background-image: linear-gradient(180deg, #3b1410, #1d0b09);
	min-height: 220px;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
}

.gen::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(100deg, transparent 20%, rgba(245, 185, 59, 0.22) 50%, transparent 80%);
	transform: translateX(-100%);
	animation: sweep var(--motion-generation) ease-in-out infinite;
}

@keyframes sweep { to { transform: translateX(100%); } }

@media (prefers-reduced-motion: reduce) {
	/* Пауза остаётся, блик — нет: памятка требует показывать процесс, а не
	   двигать пиксели. */
	.gen::after { animation: none !important; opacity: 0.14; transform: none; }
}

.gen-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 12px 16px;
	background: rgba(15, 15, 22, 0.55);
	color: var(--on-ink);
	font-size: 13px;
	font-weight: 600;
	position: relative;
	z-index: 1;
}

/* ── Таблица-перечень ────────────────────────────────────────────────────── */

.list { display: flex; flex-direction: column; }
.list > * + * { border-top: 1px solid var(--rule-paper); }
.on-ink .list > * + *, .band-ink .list > * + * { border-top-color: var(--rule-ink); }

.item { display: flex; align-items: center; gap: 20px; padding: 18px 0; }

/* Строка книги в списке кабинета. */
.bookrow {
	display: flex;
	align-items: center;
	gap: 22px;
	padding: 22px;
	background: var(--paper);
	border: 1px solid var(--rule-paper);
	border-radius: var(--r-md);
}

/* 52 × 72 и радиус 8 — числа макета (`Строка книги в списке`); стояли 64 × 92. */
.bookrow-cover { width: 52px; height: 72px; border-radius: var(--r-sm); object-fit: cover; background: var(--paper-2); flex-shrink: 0; }
.bookrow-body { display: flex; flex-direction: column; gap: 6px; flex: 1 1 auto; min-width: 0; }
.bookrow-title { font-size: 18px; font-weight: 600; }

/* Строка покупки: вид, количество, цена, кнопка. */
.buy {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	padding: 22px;
	background: var(--paper);
	border: 1px solid var(--rule-paper);
	border-radius: var(--r-md);
}

.buy-qty { font-size: 22px; font-weight: 600; }
.buy-sum { font-family: var(--font-display); font-size: 24px; font-weight: 500; line-height: 1; }

@media (max-width: 560px) {
	.buy { flex-direction: column; align-items: stretch; }
	.buy form { width: 100%; }
	.buy .btn { width: 100%; }
}

/* Оглавление документа. */
/* Оглавление документа: карточка второй бумаги радиуса 18 с полями 16, зазор 4,
   метка 12 / 1,4 и пункты плашками радиуса 8 с киноварной чертой слева. Текущий
   пункт залит бумагой и набран полужирным. Числа макета. */
.toc {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 16px;
	background: var(--paper-2);
	border-radius: var(--r-md);
}

.toc-cap { padding-bottom: 6px; font-size: 12px; letter-spacing: 1.4px; }
.toc-row {
	padding: 10px 12px;
	border-radius: var(--r-sm);
	border-left: 3px solid var(--accent);
	color: var(--on-paper-2);
	font-family: var(--font-ui);
	font-size: 14px;
	line-height: 1.35;
	text-decoration: none;
}

.toc-row:hover { background: var(--paper); color: var(--on-paper); }
.toc-row-on { background: var(--paper); color: var(--on-paper); font-weight: 600; }

/* Колонки документа: оглавление 300 слева, текст 760 справа, зазор 88. До
   сверки было наоборот — текст слева, оглавление справа в 440. */
.cols-toc { display: grid; grid-template-columns: 300px minmax(0, 760px); }

/* Заголовок раздела 30 / 1,25, абзац 17,5 / 1,8 — числа макета; стояли 26 и 17. */
.legal-h { margin: 0; font-family: var(--font-display); font-size: 30px; font-weight: 500; line-height: 1.25; }
.legal-p { margin: 0; font-family: var(--font-ui); font-size: 17.5px; line-height: 1.8; }

/* Плашка якоря раздела и плашка даты редакции: обе — вторая бумага в линейке. */
.anchor-chip, .date-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	width: fit-content;
	padding: 5px 10px;
	border-radius: 999px;
	background: var(--paper-2);
	border: 1px solid var(--rule-paper);
	color: var(--on-paper);
	font-family: var(--font-ui);
	font-size: 12px;
	font-weight: 600;
	text-decoration: none;
}

.date-chip { gap: 9px; padding: 8px 14px; font-size: 14px; font-weight: 500; }
.date-chip .ico { color: var(--on-paper-2); }

@media (max-width: 1080px) { .cols-toc { grid-template-columns: minmax(0, 1fr); } }

/* ── Крупное число и цена ────────────────────────────────────────────────── */

/* Сумма — 88 / 1,05, а не 96 / 0,95: числа макета. */
.big { font-family: var(--font-display); font-size: 88px; font-weight: 600; line-height: 1.05; }
.mid { font-family: var(--font-display); font-size: 52px; font-weight: 600; line-height: 1; }

@media (max-width: 720px) {
	.big { font-size: 54px; }
	.mid { font-size: 34px; }
	.h2 { font-size: 28px; }
	.band, .band-tall { padding: 56px var(--pad-page); }
}

/* ── Полоса заполнения ───────────────────────────────────────────────────── */

.meter { height: 34px; border-radius: 6px; background: var(--paper-2); overflow: hidden; }
.meter-fill { height: 100%; background: var(--mark); }
.meter-thin { height: 6px; border-radius: 999px; }
.on-ink .meter, .band-ink .meter { background: var(--ink-3); }

/* ── Проза читалки ───────────────────────────────────────────────────────────
 *
 * Две метки, которые ставит `renderProse`: имя сущности и якорь описания.
 * Курсор-указатель — только там, где нажатию есть что показать: обещание без
 * обработчика было тем самым дефектом, за который отвергли прежнюю
 * демонстрацию. Поэтому `.m-shot` (у якоря есть готовый кадр) и `.m-entity`
 * получают курсор, а `.m-descr` без кадра — нет. */

.m-entity {
	background: var(--mark);
	color: var(--on-paper);
	padding: 0 5px;
	border-radius: 3px;
	cursor: pointer;
	box-decoration-break: clone;
}

.m-descr {
	background: none;
	color: inherit;
	border-bottom: 2px solid var(--accent);
	box-decoration-break: clone;
}

.m-descr-fill {
	background: var(--mark-soft);
	color: var(--on-paper);
	border-radius: 3px;
	padding: 0 4px;
}

.m-shot { cursor: pointer; }

/* Статическая копия подчёркнутой фразы в герое: нажатие живёт в живом блоке
   ниже, а здесь фраза только показана. */
.descr-static { border-bottom: 2px solid var(--accent); }

.mark-txt { color: var(--mark); }
.acc-txt { color: var(--accent); }
.on-ink-txt { color: var(--on-ink); }

.g2 { gap: 2px; } .g5 { gap: 5px; } .g7 { gap: 7px; } .g4 { gap: 4px; } .g14 { gap: 14px; }
.g30 { gap: 30px; } .g36 { gap: 36px; }
.center-col { align-items: center; }
.center-txt { text-align: center; max-width: 900px; margin-inline: auto; }

/* Образец цвета в подписи-легенде — псевдоэлемент, а не пустой узел разметки:
   пустой `<i>` это след того, что данные не сошлись с шаблоном, и сторож
   разметки на него кричит справедливо. Декорация цветом — дело CSS. */
.legend { display: inline-flex; align-items: center; gap: 10px; font-size: 14px; }

/* Образцы легенды — числа макета: маркер 22 × 14 радиуса 3, подчёркивание
   22 × 2 без радиуса. */
.legend::before {
	content: "";
	width: 28px;
	height: 14px;
	border-radius: 3px;
	flex-shrink: 0;
}

.legend-mark::before { background: var(--mark); }
.legend-acc::before { height: 2px; border-radius: 0; background: var(--accent); }

.pill-big { font-size: 16px; padding: 7px 14px; }

.code {
	font-family: ui-monospace, monospace;
	font-size: 13px;
	background: var(--ink-3);
	padding: 2px 6px;
	border-radius: 4px;
}

/* ── Герой лендинга ──────────────────────────────────────────────────────────
 *
 * Композиция макета: справа три карточки со сдвигом внутри поля 600 × 870.
 * Наложение воспроизведено абсолютным позиционированием — ровно как в макете, —
 * и распускается в поток под 1080: на узкой ширине оно читается как дефект. */

.hero {
	padding: 84px var(--pad-page);
	/* Цвет **и** градиент, а не только градиент: `background-color` держит
	   подложку там, где градиент не нарисовался, — а он не рисуется и при
	   отключённых изображениях, и при высокой контрастности системы. Без него
	   светлый текст героя оказывался на бумажном фоне: замерено на боевой
	   странице, пара давала 1 : 1. */
	background-color: var(--ink);
	background-image: linear-gradient(180deg, var(--ink), var(--ink-2));
	color: var(--on-ink);
}

.hero-sub { font-family: var(--font-display); font-size: 36px; font-weight: 400; line-height: 1.2; color: var(--on-ink-2); }
.hero-note { max-width: 300px; }
/* Значок функции: первый маркером, второй киноварью — так в макете, и это
   не украшение: жёлтый значок стоит у справочника, красный у иллюстраций, и
   тот же красный ведёт дальше по всей странице к подчёркиваниям и кадрам. */
.hero-feat-i { color: var(--mark); margin-top: 2px; }
.hero-feat-acc { color: var(--accent); }

/* Название функции — 16-м. `.h4` (20) про подзаголовок раздела; здесь макет
   называет 16, и разница видна рядом с описанием на 15. */
.hero-feat-t { font-family: var(--font-ui); font-size: 16px; font-weight: 600; line-height: 1.3; }

.hero-art { position: relative; height: 870px; }

.hero-page {
	position: absolute;
	left: 0;
	top: 10px;
	width: 560px;
	max-width: 100%;
	display: flex;
	flex-direction: column;
	gap: 18px;
	padding: 32px;
	border-radius: var(--r-md);
	background: var(--paper);
	color: var(--on-paper);
	box-shadow: 0 18px 40px -8px rgba(0, 0, 0, 0.4);
	/* Наклон на один градус — из макета (`rotation: 1` у «Страницы книги»).
	   Он и есть причина, по которой карточка справочника читается как
	   положенная сверху, а не вклеенная в сетку. Знак минуса потому, что в
	   макете поворот против часовой. */
	transform: rotate(-1deg);
}

.hero-page .hair { background: var(--rule-paper); }
.hero-prose { font-size: 18px; line-height: 1.85; }

.hero-card {
	position: absolute;
	left: 150px;
	top: 236px;
	width: 450px;
	max-width: 100%;
	/* Поля и зазор из макета: 24 и 16 против 26/28 и 16 у обычной карточки. */
	padding: 24px;
	gap: 16px;
	border-radius: var(--r-md);
	box-shadow: 0 22px 44px -6px rgba(0, 0, 0, 0.5);
}

/* Имя в карточке — 24-м, а не 26-м: `.h3` про заголовок раздела, а здесь
   карточка. Источник — тот же макет. */
.hero-card .h3 { font-size: 24px; font-weight: 600; line-height: 1.2; }

/* Пояснение под именем — одна строка. В макете это «Персонаж · граф, офицер ·
   появляется в главе XIV», ровно строка, и от неё зависит высота карточки: на
   живой вехе строка вторая, карточка вырастала и наезжала на подпись кадра. */
.card-sub {
	display: -webkit-box;
	-webkit-line-clamp: 1;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Значение факта — **одна** строка, и это не косметика, а арифметика позиций.
 *
 * Карточка стоит на 236, кадр — на 540: числа из макета. Значит у карточки есть
 * потолок высоты, 304, иначе она наезжает на подпись кадра. В макете все три
 * значения — по одной строке («невысокий, плотно сложенный брюнет», 34 знака),
 * и карточка выходит 277 — от неё до кадра 27 px воздуха. На живых данных
 * сводка длиннее: с обрезом в две строки карточка выросла до 300, воздух
 * съёжился до 4 px, и это то, что видно глазом. Одна строка делает высоту
 * **независимой от данных**: 277 при любой сводке. */
.hero-card .kv dd {
	display: -webkit-box;
	-webkit-line-clamp: 1;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Источник под фактами — 12-м, как в макете, а не 13-м от `.sm`. */
.hero-card .card-src { font-size: 12px; }

.hero-shot { position: absolute; left: 0; top: 540px; width: 560px; max-width: 100%; }
.hero-shot img { height: 260px; object-fit: cover; }

@media (max-width: 1080px) {
	.hero-art { position: static; height: auto; display: flex; flex-direction: column; gap: 20px; }
	.hero-page, .hero-card, .hero-shot { position: static; width: auto; }
	.hero-sub { font-size: 26px; }
	.hero-note { max-width: none; }
}

/* ── Светлые острова внутри тёмных полос ─────────────────────────────────────
 *
 * Страница книги в герое и экран телефона — бумага на чернилах. Правила вида
 * `.on-ink .prose` до них доходят и красят текст в цвет чернильной полосы, то
 * есть светлым по светлому. **Замерено на живой странице: пара давала 1 : 1** —
 * проза героя была невидима целиком, и ни один сторож этого не видел, потому
 * что разметка была на месте.
 *
 * Поэтому остров переопределяет цвета обратно. Селекторы длиннее правил
 * полосы намеренно: специфичность и есть то, чем остров держится. */

.hero-page,
.hero-page .prose,
.phone-screen,
.phone-screen .prose,
.reader-page,
.reader-page .prose {
	color: var(--on-paper);
}

.hero-page .cap,
.hero-page .dim,
.phone-screen .cap,
.phone-screen .dim {
	color: var(--on-paper-2);
}

.hero-page .hair,
.phone-screen .hair {
	background: var(--rule-paper);
}

/* Имя и якорь описания в прозе острова — теми же чернилами, что на бумаге. */
.hero-page .m-entity,
.phone-screen .m-entity {
	color: var(--on-paper);
}

/* ── Живой блок ──────────────────────────────────────────────────────────── */

/* Панель глоссария. Обводка 1 px `--rule-ink` — из макета; без неё панель
   сливается с полосой: фон отличается на один шаг. */
.who {
	display: flex;
	flex-direction: column;
	gap: 0;
	background: var(--ink-2);
	border: 1px solid var(--rule-ink);
	border-radius: var(--r-lg);
	overflow: hidden;
}

.who-grid { display: grid; grid-template-columns: minmax(0, 1fr) 460px; }

.who-page {
	display: flex;
	flex-direction: column;
	gap: 18px;
	/* Поля 40 / 44 / 44 — из макета. */
	padding: 40px 44px 44px;
	background: var(--ink-2);
}

.who-ch { font-family: var(--font-prose); font-size: 20px; }
/* Строка прозы — 38 px при кегле 19, то есть ровно 2. В макете каждая строка
   лежит во фрейме высотой 38, и это единственное её измерение. */
.who-prose { font-size: 19px; line-height: 2; max-height: 520px; overflow: auto; }

/* Столбец карточек — на чернилах, а не на вторых чернилах: в макете он темнее
   прозы, и это единственное, чем он от неё отделён кроме линии. */
.who-grid > .stack { padding: 40px; border-left: 1px solid var(--rule-ink); background: var(--ink); }

/* Связи отдельной карточкой: в макете они лежат под внешностью, но в своей
   рамке — иначе карточка вырастает до высоты, на которой уже не читается. */
.who-rel { padding: 18px 22px; }

.who-slider {
	display: flex;
	flex-direction: column;
	gap: 26px;
	padding: 36px 44px 44px;
	background: var(--ink);
	border-top: 1px solid var(--rule-ink);
}

.who-opened { text-align: right; }

/* Ползунок и вторая карточка — два столбца, 460 у правого: числа макета.
   Правый столбец отвечает на вопрос «а кто открылся последним», левый — на
   «докуда я дочитал». Это разные вопросы, поэтому и столбца два. */
.who-slider-in { display: grid; grid-template-columns: minmax(0, 1fr) 460px; gap: 40px; align-items: start; }
.who-latest { padding-left: 40px; border-left: 1px solid var(--rule-ink); }

@media (max-width: 1080px) {
	.who-slider-in { grid-template-columns: minmax(0, 1fr); }
	.who-latest { padding-left: 0; border-left: 0; }
}

.who-chart {
	display: flex;
	flex-direction: column;
	gap: 26px;
	padding: 40px;
	background: var(--ink-2);
	border: 1px solid var(--rule-ink);
	border-radius: var(--r-lg);
	margin-top: 24px;
}

.chart-note { max-width: 330px; }

@media (max-width: 1080px) {
	.who-grid { grid-template-columns: minmax(0, 1fr); }
	.who-grid > .stack { border-left: 0; border-top: 1px solid var(--rule-ink); }
}

/* ── Шаги и шторки ───────────────────────────────────────────────────────── */

.step-no {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 26 — из макета; кружок ровно на два пикселя больше, чем был. */
	width: 26px;
	height: 26px;
	border-radius: 999px;
	border: 1px solid var(--rule-ink);
	font-size: 13px;
	font-weight: 600;
	color: var(--on-ink-2);
	flex-shrink: 0;
}

.band:not(.band-ink) .step-no { border-color: var(--rule-paper); color: var(--on-paper-2); }

/* Карточка шага: 260 высоты и поля 28 — из макета. Прежние 150 и 20 делали
   три шага заметно ниже нарисованных, и «фраза → генерация → кадр» читалась
   как подпись, а не как показ. */
.step-body {
	display: flex;
	flex-direction: column;
	gap: 14px;
	min-height: 260px;
	padding: 28px;
	border-radius: var(--r-md);
	background: var(--ink-2);
	border: 1px solid var(--rule-ink);
}

/* Шторка демонстрации — чернильная карточка целиком: ручка 44 × 4, шапка с
   номером в круге 24 и подписью 16 / 600, тело высотой 250 с полями 8/24/24.
   Радиус 28 только сверху — шторка «выезжает» снизу. */
.curtain {
	display: flex;
	flex-direction: column;
	border-radius: var(--r-lg) var(--r-lg) 0 0;
	background: var(--ink);
	color: var(--on-ink);
	overflow: hidden;
}

.curtain-grip { width: 44px; height: 4px; margin: 11px auto; border: 0; border-radius: 2px; background: var(--ink-3); }
.curtain-head { align-items: center; padding: 0 24px 14px; }
.curtain-no { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 999px; border: 1px solid var(--rule-ink); font-size: 12px; font-weight: 600; color: var(--on-ink-2); flex-shrink: 0; }
.curtain-t { font-family: var(--font-ui); font-size: 16px; font-weight: 600; }

.curtain-body {
	min-height: 250px;
	padding: 8px 24px 24px;
	justify-content: center;
	/* Шторка поднимается снизу: 240 мс, замедление к концу, без отскока. */
	animation: rise var(--motion-sheet) cubic-bezier(0.22, 0.8, 0.3, 1) both;
}

@keyframes rise { from { transform: translateY(14px); opacity: 0; } }

.curtain-note { max-width: 420px; }
.curtains .step-no { border-color: var(--rule-paper); color: var(--on-paper-2); }

/* Узкая ширина шторок нарисована в макете отдельно
   (`.pen`, «fancai — Демонстрация 390 / Фраза в кадр»): ручка 22 при полоске
   40 × 4, шапка с полями 0/20/12, номер 22 с одиннадцатым кеглем, название
   15-е, тело первой шторки **по содержимому** с полями 6/20/22, тела второй и
   третьей — 210. До правки узкая ширина брала числа широкой (тело 250 с полями
   8/24/24), и первая шторка держала пустоту вокруг двух строк. */
@media (max-width: 720px) {
	.curtain-grip { width: 40px; margin: 9px auto; }
	.curtain-head { padding: 0 20px 12px; }
	.curtain-no { width: 22px; height: 22px; font-size: 11px; }
	.curtain-t { font-size: 15px; }
	.curtain-body { min-height: 0; padding: 6px 20px 22px; }
	.curtain:not(:first-child) .curtain-body { min-height: 210px; }
	/* Поле генерации в макете 390 — 210 вместе с индикатором 58; у нас индикатор
	   лежит внутри поля, поэтому 182 плюс поля тела дают ровно 210. */
	.curtain-body .gen { min-height: 182px; }
	.curtain-body .gen-bar { height: 38px; }
}

/* ── Что будет дальше ────────────────────────────────────────────────────────
 *
 * Разворот: слева текст, справа два кадра **своей** ширины 232 × 300 — они
 * hug, а не половина полосы, поэтому колонка справа `auto`, а зазор 88.
 * Прежняя сетка ставила справа 600 и растягивала кадры. */

.cols-auto { display: grid; grid-template-columns: minmax(0, 1fr) auto; }
.cols-g88 { gap: 88px; }
.cols-400 { display: grid; grid-template-columns: 400px minmax(0, 1fr); }

.next-shot { display: flex; flex-direction: column; gap: 14px; }
.next-shot img { width: 232px; height: 300px; object-fit: cover; border-radius: var(--r-md); }
.next-ch { font-size: 15px; font-style: italic; color: var(--on-ink-2); }

/* Фраза с киноварной чертой под ней: 20 / 600, черта 3 px и отступ 8. */
.claim-20 { width: fit-content; padding-bottom: 8px; border-bottom: 3px solid var(--accent); font-family: var(--font-ui); font-size: 20px; font-weight: 600; }

/* Плашка утверждения маркером: радиус 8, поля 7 / 12. Кегль 20 в блоке
   «дальше» и 18 в ценах — так нарисовано, поэтому вторым классом. */
.mark-chip {
	display: inline-block;
	width: fit-content;
	max-width: 100%;
	padding: 7px 12px;
	border-radius: var(--r-sm);
	background: var(--mark);
	color: var(--ink);
	font-family: var(--font-ui);
	font-size: 20px;
	font-weight: 600;
}

.mark-chip-18 { font-size: 18px; }

/* ── Цены ────────────────────────────────────────────────────────────────────
 *
 * Шкала знаков: **полосы разной длины, а отрезок маркера один и тот же** —
 * 216 и 800 при отрезке 200. Прежняя мерка была одной ширины с разной долей
 * заливки, то есть показывала не то, что обещает подпись рядом. */

.vol { align-items: center; }
.vol-lab { width: 170px; flex-shrink: 0; font-family: var(--font-ui); font-size: 17px; font-weight: 600; }
.vol-track { height: 46px; max-width: 100%; border-radius: var(--r-sm); background: var(--paper-2); border: 1px solid var(--rule-paper); overflow: hidden; }
.vol-novel { width: 216px; }
.vol-tome { width: 800px; }
.vol-seg { height: 100%; background: var(--mark); border-radius: var(--r-sm); }
.vol-note { font-size: 16px; font-style: italic; color: var(--on-paper-2); }
.vol-legend { font-size: 15px; }

.price-note { font-family: var(--font-ui); font-size: 18px; color: var(--on-paper-2); }
.price-foot { font-family: var(--font-ui); font-size: 16px; color: var(--on-paper-2); }
.price-cta { align-items: center; }

/* Большая кнопка блока цен — единственная не таблетка: радиус 18, поля
   19 / 34, подпись 19-м. Обычная кнопка сайта остаётся таблеткой 56 (так
   нарисована в памятке компонентов). */
.btn-lg { height: auto; padding: 19px 34px; border-radius: var(--r-md); font-size: 19px; }

/* Кегли заголовков блоков цен: 28 у двух колонок, 30 у шкалы. */
.d28 { font-size: 28px; }
.d30 { font-size: 30px; }
.lh-13 { line-height: 1.3; }

/* Лид разных блоков: 19, 20 и 21 — числа макета, а не общая шкала. */
.prose.lede-19 { font-size: 19px; line-height: 1.6; }
.prose.lede-20 { font-size: 20px; line-height: 1.55; }
.prose.lede-21 { max-width: 660px; font-size: 21px; line-height: 1.5; }

/* Трекинг надзаголовка у блоков 7 и 8 — 1,6, а не 2,2. */
.kick-16 { letter-spacing: 1.6px; }
.fw-600 { font-weight: 600; }

/* ── Опись книг блока иллюстраций ────────────────────────────────────────────
 *
 * Пять строк с маркером названия и счётчиком, столбец 360 px. Числа макета:
 * шапка 12 / 600 / 1,6, строка с полями 8 сверху и снизу и линейкой **снизу**,
 * счётчик 12-м. До правки это был общий `.list` с полями 18 и таблеткой
 * `pill-soft` вместо маркера — строка выходила вдвое выше нарисованной. */

.cap-idx { font-family: var(--font-ui); font-size: 12px; font-weight: 600; letter-spacing: 1.6px; text-transform: uppercase; color: var(--on-ink-2); }
.idx { display: flex; flex-direction: column; }
.idx-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--rule-ink); }
.idx-num { font-size: 12px; color: var(--on-ink-2); }

/* Маркер названия книги — прямоугольник радиуса 4 на бледном маркере с
   чернильным текстом 12 / 600. Он же стоит в подписи каждого кадра. */
.mark-sq {
	display: inline-block;
	padding: 3px 7px;
	border-radius: 4px;
	background: var(--mark-soft);
	color: var(--ink);
	font-family: var(--font-ui);
	font-size: 12px;
	font-weight: 600;
}

/* Сноска блока: линейка сверху и отступ 24 под ней, текст 14 / 1,55 в 720. */
.wall-note { padding-top: 24px; border-top: 1px solid var(--rule-ink); }
.sm2-14 { max-width: 720px; font-size: 14px; line-height: 1.55; }

/* Надзаголовок киноварью — в блоке иллюстраций он киноварный, а не маркерный:
   `on-ink` красит надзаголовки маркером, и здесь это исключение из макета. */
.on-ink .kick-acc { color: var(--accent); }



/* Заголовок блока иллюстраций набран **семисотым**, а не пятисотым: единственное
   место, где макет берёт самый тяжёлый Unbounded. */
.fw-700 { font-weight: 700; }

/* ── Мозаика кадров ──────────────────────────────────────────────────────────
 *
 * Пять рядов разной ёмкости — 2 · 3 · 2 · 4 · 3, ровно четырнадцать кадров.
 * Ширины кадров в макете **не равные**: 816 + 408 в первом ряду, 312 + 384 +
 * 504 во втором и так далее. Прежняя сетка делила ряд поровну (6 + 6 из
 * двенадцати колонок), и первый ряд выходил двумя половинами вместо крупного
 * кадра с узким соседом.
 *
 * Числа переведены в двадцать четыре колонки: 1248 px содержимого минус зазоры
 * по 24 дают доли 16/8, 6/8/10, 10/14, 5/7/5/7, 11/6/7 — каждый ряд ровно 24.
 *
 * Высота кадра тоже своя у каждого ряда — 480, 320, 400, 240, 300, — поэтому
 * пропорция кадра не постоянна, и `object-fit: cover` здесь обязателен. */

.mosaic { display: flex; flex-direction: column; gap: 40px; }
.mrow { display: flex; gap: 24px; }
/* Доля кадра приходит разметкой (`flex-grow`), высота ряда — переменной. */
.shot { flex: 0 1 0; min-width: 0; }
.mosaic img { width: 100%; height: var(--shot-h); object-fit: cover; border-radius: var(--r-sm); }

/* Под 1080 мозаика становится двумя колонками и остаётся ими до самой узкой
   ширины: **макет на 390 рисует стену именно двумя колонками** мелких кадров по
   169 px, а не одной. Одна колонка растила блок вдвое против нарисованного. */
@media (max-width: 1080px) {
	.mosaic { gap: 28px; }
	.mrow { flex-wrap: wrap; gap: 28px 16px; }
	/* Две колонки: доля из макета уступает место равным половинам — на 390
	   макет рисует стену именно двумя колонками мелких кадров по 169 px. */
	.shot { flex: 1 1 calc(50% - 8px); }
	.mosaic img { height: auto; aspect-ratio: 3 / 2; }
}

/* Подпись кадра на узкой ширине обрезается двумя строками — ровно столько
   отведено ей в макете. Без обрезки цитата разворачивалась в шесть строк на
   каждом из четырнадцати кадров, и блок вырастал вчетверо против
   нарисованного. Полная цитата при этом не теряется: она стоит в `alt` и
   читается вслух средствами доступности. */
@media (max-width: 1080px) {
	.mosaic .shot-txt {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
		font-size: 12px;
	}

	.mosaic .shot-cap { gap: 6px; font-size: 11px; }
	.mosaic .mark-sq { font-size: 11px; padding: 2px 6px; }
}

/* ── Спойлерный шлюз ─────────────────────────────────────────────────────────
 *
 * Две карточки одной сущности рядом, и они **разной ширины**: 424 у второй
 * главы, 664 у третьей. Так и должно быть — правая знает больше, и её ширина
 * это показывает до чтения. Между ними столбец 96 со стрелкой, зазор 32.
 * Прежняя раскладка делила поровну (1fr / 120 / 1fr), то есть теряла ровно то,
 * что блок доказывает. */

.gate-pair { display: grid; grid-template-columns: 424px 96px minmax(0, 1fr); gap: 32px; align-items: start; }

.gate-arrow {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 14px;
	padding-top: 150px;
	color: var(--accent);
	text-align: center;
}

.gate-arrow-cap { font-size: 12px; line-height: 1.4; color: var(--on-ink-2); }

/* Карточка шлюза: вторые чернила, радиус 18, поля 28, зазор 22 — и **без
   обводки**: её в макете нет, а общий `.card` рисует линейку. */
.gate-card {
	display: flex;
	flex-direction: column;
	gap: 22px;
	padding: 28px;
	border-radius: var(--r-md);
	background: var(--ink-2);
}

.cap-ch { font-family: var(--font-ui); font-size: 12px; font-weight: 600; letter-spacing: 2.4px; text-transform: uppercase; color: var(--on-ink-2); }
.cap-lab { font-family: var(--font-ui); font-size: 11px; font-weight: 600; letter-spacing: 1.8px; text-transform: uppercase; color: var(--on-ink-2); }

/* Имя — маркер радиуса 8 с полями 6 / 12, набранный Unbounded 16-м. */
.gate-name {
	align-self: flex-start;
	padding: 6px 12px;
	border-radius: var(--r-sm);
	background: var(--mark);
	color: var(--ink);
	font-family: var(--font-display);
	font-size: 16px;
	font-weight: 400;
}

/* Мета строчными: в макете «персонаж · впервые — глава 2» без заглавной. */
.gate-meta { font-size: 12px; color: var(--on-ink-2); text-transform: lowercase; }
.gate-mile { font-size: 15px; line-height: 1.55; }
.gate-bio { font-size: 14px; line-height: 1.6; }

/* Плашка имени: бледный маркер, радиус 8, поля 5 / 11. Псевдоним 14-м, имя
   связи 13-м — так в макете. */
.chip-soft {
	display: inline-block;
	padding: 5px 11px;
	border-radius: var(--r-sm);
	background: var(--mark-soft);
	color: var(--ink);
	font-family: var(--font-ui);
	font-size: 14px;
	font-weight: 600;
}

.chip-soft-sm { font-size: 13px; }

/* Связь: метка 3 × 20 вторыми чернилами, роль в столбце 104, имя плашкой. */
.gate-rel { display: flex; align-items: center; gap: 12px; }
.gate-rel::before { content: ""; width: 3px; height: 20px; border-radius: 2px; background: var(--ink-3); flex-shrink: 0; }
.gate-rel-role { width: 104px; flex-shrink: 0; font-size: 13px; color: var(--on-ink-2); }

/* Легенда прибавки: образец 16 × 16 радиуса 4 маркером, отступ сверху 14. */
.gate-legend { display: flex; align-items: center; gap: 10px; padding-top: 14px; font-size: 12px; color: var(--on-ink-2); }
.gate-swatch { width: 16px; height: 16px; margin: 0; border: 0; border-radius: 4px; background: var(--mark); flex-shrink: 0; }

/* Шкала книги: ярлык 12 / 600 / 2, справка 12-м, график 330 с зазором 24. */
.cap-scale { font-family: var(--font-ui); font-size: 12px; font-weight: 600; letter-spacing: 2px; text-transform: uppercase; color: var(--on-ink-2); }
.scale-note { font-size: 12px; color: var(--on-ink-2); }

@media (max-width: 1080px) {
	.gate-pair { grid-template-columns: minmax(0, 1fr); gap: 24px; }
	.gate-arrow { padding-top: 0; flex-direction: row; }
}

/* ── Столбики ────────────────────────────────────────────────────────────── */

/* Большой график: высота 330, столбик радиуса 8 сверху, значение Unbounded
   22-м, подпись главы 13-м в полосе высотой 46 с зазором 4 — числа макета.
   Высота столбика приходит разметкой в пикселях (см. `barHeight`). */
.bars-big { height: 330px; }
.bars-big .bar-val { font-size: 22px; }
/* Высота столбцов и их зазор — из макета: 250 и 14. Столбик — не палка, а
   фрейм радиуса 8 с полями 12 × 8, и у главы, на которой стоит ползунок, он
   залит третьими чернилами. */
/* Блок «кто есть кто»: полоса 250, зазор 14, колонка радиуса 8 с полями 12 / 8
   и зазором 10, значение 16 / 600, подпись 13; у главы ползунка колонка залита
   третьими чернилами. */
.bars-small { min-height: 250px; gap: 14px; }
.bars-small .bar-col { gap: 10px; }
.bar-col { border-radius: var(--r-sm); padding: 12px 8px; }
.bars-small .bar-here { background: var(--ink-3); }
.bars-small .bar-val { font-size: 16px; font-family: var(--font-ui); font-weight: 600; }
.bars-small .bar-lab { font-size: 13px; font-weight: 600; }
.bar-col { height: 100%; justify-content: flex-end; }

/* Демонстрация: та же полоса вдвое ниже — 150, зазор 12, колонка с полями 8 / 6
   и зазором 7, значение 14 / 600, подпись 12. Числа макета демонстрации. */
.bars-demo { min-height: 150px; gap: 12px; }
.bars-demo .bar-col { gap: 7px; padding: 8px 6px; border-radius: var(--r-sm); }
.bars-demo .bar-here { background: var(--ink-3); }
.bars-demo .bar-val { font-family: var(--font-ui); font-size: 14px; font-weight: 600; }
.bars-demo .bar-lab { font-size: 12px; }
.bars-demo .bar-here .bar-val, .bars-demo .bar-here .bar-lab { color: var(--mark); font-weight: 600; }
.bars-small .bar-here .bar-val, .bars-small .bar-here .bar-lab { color: var(--mark); }

/* Панель счётчика на демонстрации: поля 26 / 36, зазор 32, подпись 330 и всё по
   центру по вертикали — в блоке «кто есть кто» те же роли, но поля 40 и 26. */
.chart-demo { flex-direction: row; align-items: center; gap: 32px; padding: 26px 36px; }
.chart-demo .chart-note { width: 330px; flex: none; font-size: 15px; line-height: 1.6; }
.chart-demo .bars { flex: 1 1 auto; }

/* Узкая ширина — свои числа макета 390: высота столбцов 180, зазор 5, поля
   10 × 4, радиус 6, значение 12, подпись 11 и **одно число** вместо «гл. N».
   Блок стоит **после** базовых правил намеренно: медиазапрос выше базы
   проигрывает ей по порядку при равной специфичности, и первая попытка это
   поймала — семь столбцов вылезали за экран на 74 px. */
@media (max-width: 720px) {
	.bars { gap: 5px; }
	.bars-small { min-height: 180px; }
	.bar-col { padding: 10px 4px; border-radius: 6px; }
	.bars-small .bar-val { font-size: 12px; }
	.bars-small .bar-lab { font-size: 11px; }
	.bar-lab-w { display: none; }
	/* Панель графика: поля 16, зазор 14, радиус 18 — числа макета 390. */
	.who-chart { padding: 16px; gap: 14px; border-radius: var(--r-md); }
	/* Полоса блока — 48 / 20 / 52. */
	.band-96 { padding-top: 48px; padding-bottom: 52px; }
}

/* ── Своя книга ──────────────────────────────────────────────────────────── */

.fmt-old { font-family: var(--font-display); font-size: 76px; font-weight: 400; color: var(--on-paper-2); }
/* Ряд конвертации: зазор 36 и поля 8 сверху и снизу — числа макета. */
.fmt-row { align-items: center; padding: 8px 0; }
.fmt-new {
	font-family: var(--font-display);
	font-size: 76px;
	font-weight: 400;
	background: var(--mark);
	color: var(--ink);
	padding: 10px 20px;
	border-radius: var(--r-md);
}

/* Пояснение конвертации: отступ слева 20, заголовок 18 / 600, текст 15 / 1,6. */
.fmt-note { flex: 1 1 320px; min-width: 0; padding-left: 20px; }
.fmt-note-h { font-family: var(--font-ui); font-size: 18px; font-weight: 600; }

/* Шаг: линейка 3 px киноварью, отступ 16, номер Unbounded **30-м** (стоял
   52-й полужирный), подпись 20 / 600, текст 15 / 1,6. */
.own-step { padding-top: 16px; border-top: 3px solid var(--accent); }
.own-no { font-family: var(--font-display); font-size: 30px; font-weight: 400; line-height: 1; }
.own-h { font-family: var(--font-ui); font-size: 20px; font-weight: 600; }
.own-step .ico { color: var(--on-paper-2); }

/* Сноска блока: отступ 8 сверху, слева проза 15-м, справа 13-й с трекингом. */
.own-foot { padding-top: 8px; }
.own-price { font-size: 13px; letter-spacing: 0.6px; color: var(--on-paper-2); }

.own-item {
	padding: 18px 22px;
	border-radius: var(--r-md);
	background: var(--ink-2);
	border: 1px solid var(--rule-ink);
}

.own-item-i { color: var(--mark); margin-top: 2px; }

/* ── Что будет дальше ────────────────────────────────────────────────────── */

.next-pair { display: grid; grid-template-columns: minmax(0, 1fr) 60px minmax(0, 1fr); gap: 16px; align-items: center; }
.next-ne { font-family: var(--font-display); font-size: 52px; font-weight: 600; color: var(--accent); text-align: center; }

/* Узкая ширина этого блока нарисована в макете отдельно, и числа ниже — его:
   `.pen`, «fancai — Лендинг 390 / Блок 7 — Что будет дальше». Одна колонка,
   два кадра **рядом** во всю её ширину высотой 180 и радиусом 12, подпись 12-м,
   поля полосы 48 сверху и 52 снизу, зазор узлов 20, заголовок 28 / 1,2 весом
   500, проза 15 / 1,65, надзаголовок с трекингом 2,2. Знака «≠» в макете 390
   нет вовсе.

   Дефект, который это чинит, был грубым: колонка `auto` отдавала паре кадров её
   собственные 245 px, а тексту оставляла **17** — страница ставила по одному
   слову в строке, и блок вытягивался на 2 177 px. */
@media (max-width: 720px) {
	.cols-auto { grid-template-columns: minmax(0, 1fr); }
	#next { padding: 48px var(--pad-page) 52px; }
	#next .wrap > .stack { gap: 20px; }
	#next .kick { letter-spacing: 2.2px; }
	#next .h2 { line-height: 1.2; font-weight: 500; }
	#next .lede-20 { font-size: 15px; line-height: 1.65; }
	#next .claim-20, #next .mark-chip { font-size: 15px; }
	.next-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
	.next-ne { display: none; }
	.next-shot { gap: 8px; }
	.next-shot img { width: 100%; height: 180px; border-radius: 12px; }
	.next-shot figcaption { flex-direction: column; align-items: flex-start; gap: 4px; }
	.next-ch { font-size: 12px; font-style: normal; }
}

/* ── Цены ────────────────────────────────────────────────────────────────── */

.price-split .price-right { padding-left: 56px; border-left: 1px solid var(--rule-paper); }
.refund-note { border-left: 3px solid var(--accent); padding: 4px 0 4px 28px; }
/* Правило: киноварная черта слева 3 px, отступ 20, зазор 14, значок 22,
   название 20 / 1,3, текст 16 / 1,62 — числа макета. */
.rule-card { padding-left: 20px; border-left: 3px solid var(--accent); }
.rule-card .ico { color: var(--accent); }
.rule-t { font-family: var(--font-ui); font-size: 20px; font-weight: 600; line-height: 1.3; }
.rule-x { font-family: var(--font-ui); font-size: 16px; line-height: 1.62; }

.vol { align-items: center; }
.vol-lab { min-width: 190px; }
.vol-meter { flex: 1 1 auto; min-width: 120px; max-width: 800px; }

@media (max-width: 1080px) {
	.price-split .price-right { padding-left: 0; border-left: 0; }
}

/* ── Демонстрация ────────────────────────────────────────────────────────── */

/* Описание в шапке страницы — 19 / 1,58 интерфейсной гарнитурой и не шире 820:
   так набраны все восемь публичных шапок и четыре кабинетных. Стояло 17 / 1,55. */
.page-lede { max-width: 820px; font-family: var(--font-ui); font-size: 19px; line-height: 1.58; }
.demo-lede { max-width: 820px; }
/* Рабочая поверхность: 24 сверху и 80 снизу — числа макета. */
.demo-surface { padding-top: 24px; padding-bottom: 80px; }

.panel { background: var(--ink-2); border-radius: var(--r-lg); overflow: hidden; }
/* Три полосы панели: 320 настройки, проза по остатку, карточка 340 — числа
   макета демонстрации (319,5 и 339,5 в его флексе). Стояло 380 справа. */
.panel-cols { display: grid; grid-template-columns: 320px minmax(0, 1fr) 340px; }
.panel-set { padding: 28px 30px; border-right: 1px solid var(--rule-ink); }
.panel-card { padding: 28px 30px; border-left: 1px solid var(--rule-ink); }

.panel-slider {
	display: flex;
	flex-direction: column;
	gap: 24px;
	padding: 30px 36px 36px;
	background: var(--ink);
	border-top: 1px solid var(--rule-ink);
}

@media (max-width: 1200px) {
	.panel-cols { grid-template-columns: minmax(0, 1fr); }
	.panel-set { border-right: 0; border-bottom: 1px solid var(--rule-ink); }
	.panel-card { border-left: 0; border-top: 1px solid var(--rule-ink); }
}

/* Читалка: пять читательских тем — содержимое демонстрации, а не палитра
   сайта, поэтому цвета приходят инлайновым `style` из `ProseStyle()`. */
.reader { margin: 0; display: flex; flex-direction: column; gap: 12px; padding: 24px 28px; }
.reader-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.reader-page { padding: 22px 24px; border-radius: var(--r-md); max-height: 560px; overflow: auto; }

/* Органы настроек. */
.ctl { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 12px 0; border-bottom: 1px solid var(--rule-ink); }
.ctl-lab { font-size: 14px; }
.ctl-check { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 12px 0; }
.ctl-check input { width: 40px; height: 22px; accent-color: var(--mark); }
.ctl-range { display: flex; align-items: center; gap: 12px; }
.ctl-range input { width: 130px; }
.ctl-val { font-size: 13px; font-weight: 600; min-width: 48px; text-align: right; }

.seg { display: flex; flex-wrap: wrap; gap: 6px; }
.seg-i { position: relative; }
.seg-i input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }

.seg-i span {
	display: inline-flex;
	align-items: center;
	min-height: 26px;
	padding: 4px 10px;
	border-radius: 999px;
	border: 1px solid var(--rule-ink);
	font-size: 12px;
	color: var(--on-ink-2);
	transition: background var(--motion-hover) ease, color var(--motion-hover) ease;
}

.seg-i input:checked + span { background: var(--paper); border-color: var(--paper); color: var(--on-paper); }
.seg-i input:focus-visible + span { outline: 3px solid var(--mark); outline-offset: 2px; }

.ticks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.tick { display: flex; align-items: flex-start; gap: 12px; font-size: 16px; }
.tick .ico { color: var(--mark); margin-top: 3px; }
.band:not(.band-ink) .tick .ico { color: var(--accent); }

/* Каталог классики: пять книг в ряд. */
.shelf { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 20px; }
/* Обложка каталога — 290 в высоту, а не пропорция 2 : 3: в макете все пять
   одной высоты, и подпись под ними встаёт в одну линию. */
.shelf-cover { width: 100%; height: 290px; object-fit: cover; border-radius: var(--r-md); background: var(--paper-2); }
/* Название в полке — две строки под ним зарезервированы (48 px), чтобы числа
   у всех пяти книг встали в одну линию, как в макете. */
.shelf-t { min-height: 48px; font-family: var(--font-ui); font-size: 18px; font-weight: 600; line-height: 1.28; }
.shelf-a { font-size: 14px; color: var(--on-paper-2); }
.shelf-lab { font-size: 13px; color: var(--on-paper-2); }
.shelf-num { margin: 0; display: flex; flex-direction: column; gap: 4px; padding-top: 12px; border-top: 1px solid var(--rule-paper); }
.shelf-num dt, .shelf-num dd { margin: 0; }
.shelf-val { font-size: 15px; font-weight: 600; }

@media (max-width: 1080px) { .shelf { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 640px) { .shelf { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ── Телефон ─────────────────────────────────────────────────────────────────
 *
 * Экраны приложения нарисованы дизайн-системой сайта, а не снимками: в макете
 * это фрейм той же палитрой и теми же гарнитурами, поэтому снимков экранов в
 * репозитории нет вовсе. */

.phones { align-items: start; }

/* Узкая ширина: **лента со свайпом** — решение владельца 2026-09-04. До этого
   здесь стояло `.phones > *:not(:first-child) { display: none }`: макет 390
   рисует один экран, и правило честно повторяло макет, но на живой странице это
   означало, что три экрана из четырёх читателю **не показываются вовсе**.
   Теперь показываются все четыре: экран 300 px, прокрутка по горизонтали с
   прилипанием, поля полосы съедены отрицательным отступом, чтобы лента начиналась
   от края экрана и было видно, что справа есть ещё. */

/* Подпись экрана: название 16 / 600 и пояснение 13 / 1,4 через 5, а до
   телефона 18 — числа макета, а не общая шкала отступов. */
.phone-col { display: flex; flex-direction: column; gap: 18px; }
.phone-cap-h { display: flex; flex-direction: column; gap: 5px; }
.phone-cap-t { font-family: var(--font-ui); font-size: 16px; font-weight: 600; }

.phone { padding: 8px; border-radius: 34px; background: var(--ink); border: 1px solid var(--ink-3); }

.phone-screen {
	display: flex;
	flex-direction: column;
	height: 624px;
	border-radius: 26px;
	background: var(--paper);
	color: var(--on-paper);
	overflow: hidden;
}

.phone-status { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px 6px; font-size: 11px; font-weight: 600; }

/* Верхняя панель — **без линейки**: в макете её нет, а кнопки это квадраты
   28 × 28 радиуса 8 со значком 17 внутри. Поля 2 / 10 / 8. */
.phone-bar { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 2px 10px 8px; }
.phone-ib { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--r-sm); flex-shrink: 0; }
.phone-bar .ico { color: var(--on-paper); }
.phone-bar-mid { display: flex; flex-direction: column; align-items: center; gap: 1px; flex: 1 1 auto; }
.phone-bar-t { font-size: 12px; font-weight: 600; }
.phone-bar-s { font-size: 10px; color: var(--on-paper-2); }
.phone-sm2 { font-size: 10.5px; color: var(--on-paper-2); }
.phone-h1 { font-family: var(--font-display); font-size: 15px; font-weight: 600; }
.phone-acts { display: flex; gap: 2px; }

/* Тело экрана. У читалки свои поля — 6 / 18 / 0 и зазор 14 между номером главы
   и первой строкой; у трёх списочных экранов поля 14 по бокам, а полосы
   (список и нижняя навигация) идут во всю ширину, потому что лежат рядом с
   телом, а не внутри него. */
.phone-body { display: flex; flex-direction: column; flex: 1 1 auto; overflow: hidden; padding: 4px 14px 0; gap: 12px; }
.phone-body-read { padding: 6px 18px 0; gap: 14px; }
.phone-body-book { padding-top: 2px; gap: 9px; }
.phone-ch { font-family: var(--font-display); font-size: 22px; font-weight: 600; }
.phone-prose { font-size: 13.5px; line-height: 1.62; overflow: hidden; }
/* Маркер имени в телефоне — **бледный**: на 13,5-м полный маркер съедает
   строку, и в макете здесь стоит `mark-soft`, а не `mark`, как на странице. */
.phone-prose .m-entity { padding: 1px 5px; border-radius: 4px; background: var(--mark-soft); }
.phone-opened { font-weight: 600; }

/* Шторка сущности: радиус 22 сверху, линейка только сверху, тень наверх
   0 −6 18 при 8 % чернил, поля 10 / 12 / 14, ручка 36 × 4. Подложка шторки —
   бумага, а карточка внутри неё — вторая бумага; до правки было наоборот, и
   карточка сливалась со шторкой. */
.phone-sheet {
	margin-top: auto;
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: 10px 12px 14px;
	border-radius: 22px 22px 0 0;
	background: var(--paper);
	border-top: 1px solid var(--rule-paper);
	box-shadow: 0 -6px 18px rgba(15, 15, 22, 0.08);
}

/* Ручка шторки, черта на корешке и полоса прочитанного — это `hr`, а не
   пустые `span`: узел без текста ловит сторож пустой разметки, и правильно
   ловит — пустой `span` это след несошедшихся данных, а черта носитель смысла
   не текстом. */
.phone-grip { align-self: center; width: 36px; height: 4px; margin: 0; border: 0; border-radius: 2px; background: var(--rule-paper); }

/* Карточка сущности внутри телефона — одна и та же в шторке читалки и в списке
   экрана книги: радиус 18, поля 9, зазор 7. */
.phone-card { display: flex; flex-direction: column; gap: 7px; padding: 9px; border-radius: var(--r-md); background: var(--paper-2); border: 1px solid var(--rule-paper); }
.phone-kind { padding: 3px 7px; border-radius: 5px; background: var(--accent); color: var(--ink); font-size: 9px; font-weight: 700; letter-spacing: 0.8px; text-transform: uppercase; }
.phone-name { align-self: flex-start; padding: 3px 6px; border-radius: 5px; font-family: var(--font-ui); font-size: 14px; font-weight: 600; }
.phone-mile { font-size: 11px; line-height: 1.45; }
.phone-cap { font-size: 9px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; color: var(--on-paper-2); }
.phone-alias { padding: 3px 6px; border-radius: 5px; background: var(--mark-soft); color: var(--on-paper); font-family: var(--font-ui); font-size: 10.5px; font-weight: 400; white-space: normal; }
.phone-rel { display: flex; align-items: center; gap: 8px; }
.phone-rel-role { width: 70px; flex-shrink: 0; font-size: 10.5px; color: var(--on-paper-2); }
.phone-rel-name { padding: 2px 5px; border-radius: 4px; background: var(--mark-soft); color: var(--on-paper); font-size: 10.5px; font-weight: 600; }

/* Обложка книги — чернильный прямоугольник с названием в нижнем углу и
   киноварной чертой, а не буква: буквы в макете нет ни на одной обложке. */
.phone-cover {
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	gap: 4px;
	width: 70px;
	height: 100px;
	padding: 8px;
	border-radius: var(--r-sm);
	background: var(--ink);
	color: var(--on-ink);
	flex-shrink: 0;
}

.phone-cover-t { font-family: var(--font-display); font-size: 9px; font-weight: 400; line-height: 1.25; }
.phone-cover-r { width: 22px; height: 2px; margin: 0; border: 0; background: var(--accent); }
/* В списках обложка меньше: 38 × 54 в каталоге, 30 × 42 в библиотеке, 42 × 60
   в карточке продолжения — и буква там как раз есть. */
.phone-cover-md, .phone-cover-sm, .phone-cover-lg { justify-content: space-between; padding: 6px; border-radius: 6px; }
.phone-cover-md { width: 38px; height: 54px; }
.phone-cover-sm { width: 30px; height: 42px; }
.phone-cover-lg { width: 42px; height: 60px; background: var(--ink-3); }
.phone-cover-l { font-family: var(--font-display); font-size: 14px; font-weight: 600; }
.phone-cover-md .phone-cover-r, .phone-cover-sm .phone-cover-r, .phone-cover-lg .phone-cover-r { width: 14px; }

.phone-title { font-family: var(--font-display); font-size: 16px; font-weight: 600; line-height: 1.2; }
.phone-auth { font-size: 11px; color: var(--on-paper-2); }
.phone-stats { gap: 5px; }
.phone-stat { padding: 4px 6px; border-radius: 6px; background: var(--paper-2); }
.phone-stat-n { font-size: 12px; font-weight: 700; }
.phone-stat-l { font-size: 9px; color: var(--on-paper-2); }

.phone-cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 8px 16px;
	border-radius: var(--r-sm);
	background: var(--ink);
	color: var(--on-ink);
	font-size: 13px;
	font-weight: 600;
}

.phone-tabs { gap: 6px; }
.phone-tab { padding: 7px 11px; border-radius: 14px; background: var(--paper-2); font-size: 11px; }
.phone-tab-on { background: var(--ink); color: var(--on-ink); font-weight: 600; }

/* Строка книги: поля 10 / 2, обложка, две-три строки данных, стрелка справа. */
.phone-list { margin: 0 -2px; }
.phone-list > * + * { border-top-color: var(--rule-paper); }
.phone-row { padding: 10px 2px; gap: 10px; }
.phone-row-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.phone-row-t { font-size: 12.5px; font-weight: 600; line-height: 1.25; }
.phone-row-a { font-size: 10px; color: var(--on-paper-2); }
.phone-row-n { font-size: 9.5px; color: var(--on-paper-2); }
.phone-row .ico { color: var(--on-paper-2); }
/* В библиотеке строка чуть мельче и с плашкой состояния вместо стрелки. */
.phone-row-lib { padding: 9px 2px; }
.phone-row-lib .phone-row-body { gap: 2px; }
.phone-row-lib .phone-row-t { font-size: 12px; }
.phone-row-lib .phone-row-a { font-size: 9.5px; }
.phone-state { padding: 4px 8px; border-radius: 10px; background: var(--paper-2); font-size: 9.5px; flex-shrink: 0; }

/* Карточка продолжения — чернильная, с полосой прочитанного и кнопкой во всю
   ширину: единственное место экрана, где кнопка залита маркером. */
.phone-resume { display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: var(--r-md); background: var(--ink); color: var(--on-ink); }
.phone-resume .phone-stat-l, .phone-resume .phone-auth { color: var(--on-ink-2); }
.phone-resume-lab { font-size: 9px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; color: var(--mark); }
.phone-resume-t { font-family: var(--font-display); font-size: 14px; font-weight: 600; }
.phone-resume-p { font-size: 10.5px; }
.phone-prog { display: block; height: 5px; border-radius: 3px; background: var(--ink-3); }
.phone-prog > hr { height: 5px; margin: 0; border: 0; border-radius: 3px; background: var(--mark); }

.phone-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 8px 14px;
	border-radius: var(--r-sm);
	background: var(--mark);
	color: var(--ink);
	font-size: 12.5px;
	font-weight: 600;
}

.phone-add { gap: 8px; padding: 10px 12px; border-radius: var(--r-sm); background: var(--paper-2); border: 1px solid var(--rule-paper); }
.phone-add .ico { color: var(--on-paper); }
.phone-add-t { font-size: 11.5px; font-weight: 600; }

.phone-tabbar { display: flex; padding: 9px 0 12px; border-top: 1px solid var(--rule-paper); }
.phone-tabbar-i { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; height: 34px; font-size: 9.5px; color: var(--on-paper-2); }
.phone-tabbar-on { color: var(--on-paper); font-weight: 600; }

/* ── Витрина настроек и образцы прозы ────────────────────────────────────── */

/* Витрина настроек: панель второй бумагой, радиус 28, поля 8 / 32 — числа
   макета. Восемь настроек стоят в **две колонки по четыре**, а колонки
   разделены не линейкой, а зазором 48. */
.set-show { padding: 8px 32px; border-radius: var(--r-lg); background: var(--paper-2); }
.set-cols { display: grid; grid-auto-flow: column; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: repeat(4, auto); column-gap: 48px; }

/* Линейка у настройки сверху, а не снизу, и её нет у первой в каждой колонке:
   счёт по месту в перечне, потому что настроек ровно восемь и порядок задан
   `readerCtlList`. */
.set-cols > * { padding: 18px 0; border-bottom: 0; }
.set-cols > *:not(:nth-child(1)):not(:nth-child(5)) { border-top: 1px solid var(--rule-paper); }

.set-show .ctl, .set-show .ctl-check { border-bottom-color: var(--rule-paper); }
.set-show .ctl-lab { font-size: 14px; }
.set-show .sm { font-size: 11.5px; line-height: 1.4; }

/* Плашка значения: высота 36, радиус 10, поля 8 / 12, кегль 12 — и подложка
   бумажная, а не прозрачная: панель уже вторая бумага, на ней прозрачная
   плашка была бы невидима. */
.set-show .seg-i span { min-height: 36px; padding: 8px 12px; border-radius: 10px; background: var(--paper); border-color: var(--rule-paper); color: var(--on-paper); }
.set-show .seg-i input:checked + span { background: var(--ink); border-color: var(--ink); color: var(--on-ink); font-weight: 600; }

/* Плашки темы — образцы самой темы, поэтому покрашены её цветами, а выбранная
   отмечена киноварным кольцом 2 px, а не заливкой: заливка стёрла бы образец. */
.set-show .seg-sw .seg-i span[data-v="light"] { background: var(--paper); color: var(--on-paper); }
.set-show .seg-sw .seg-i span[data-v="dark"] { background: #1a1a24; color: var(--on-ink); }
.set-show .seg-sw .seg-i span[data-v="sepia"] { background: var(--paper-2); color: var(--on-paper); }
.set-show .seg-sw .seg-i span[data-v="night"] { background: var(--ink); color: var(--on-ink); }
.set-show .seg-sw .seg-i span[data-v="outdoor"] { background: var(--paper); color: var(--ink); }
.set-show .seg-sw .seg-i input:checked + span { border: 2px solid var(--accent); font-weight: 600; }

/* Плашки гарнитур набраны каждая своей гарнитурой — в макете видно, чем
   отличается выбор, до нажатия. */
.set-show .seg-font .seg-i span { font-size: 12.5px; }
.set-show .seg-font .seg-i span[data-v="original"], .set-show .seg-font .seg-i span[data-v="serif"] { font-family: var(--font-prose); }
.set-show .seg-font .seg-i span[data-v="sans"] { font-family: var(--font-ui); }
.set-show .seg-font .seg-i span[data-v="iowan"] { font-family: var(--font-display); }

.set-show .cap { color: var(--on-paper-2); }

/* Три образца одного и того же куска прозы. Поля у каждого свои — 26, 20 и 28,
   и это не небрежность макета: у образца «на солнце» обводка 2 px, у тёмного
   поля меньше, потому что там нет светлой рамки. Между шапкой и прозой стоит
   линейка. */
.sample { display: flex; flex-direction: column; gap: 14px; min-height: 224px; padding: 26px; border-radius: var(--r-md); border: 1px solid var(--rule-paper); }
.sample-note { font-size: 11px; color: var(--on-paper-2); }
.sample-tag { padding: 4px 8px; border-radius: 6px; background: var(--paper-2); color: var(--on-paper); font-size: 10px; font-weight: 700; letter-spacing: 0.6px; text-transform: uppercase; }
.sample-rule { height: 1px; margin: 0; border: 0; background: var(--rule-paper); }
.sample-prose { font-family: var(--font-prose); font-size: 17px; line-height: 1.6; }
/* Значок на полях — тот же орган, что в читалке: киноварный квадрат 24 × 24 со
   значком кадра. В образце он показывает третий вид метки описания. */
.sample-ico { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; background: var(--accent); color: var(--ink); flex-shrink: 0; }

.sample-light { background: var(--paper); }

.sample-dark { padding: 20px; background: var(--ink); border-color: var(--rule-ink); color: var(--on-ink); }
.sample-dark .sample-note { color: var(--on-ink); }
.sample-dark .sample-prose { font-family: var(--font-ui); font-size: 15px; line-height: 1.5; }
.sample-dark .sample-tag { background: var(--ink-3); color: var(--on-ink); }
.sample-dark .sample-rule { background: var(--rule-ink); }

/* «На солнце» — бумага в чернильной обводке 2 px, а не выдуманный белый: тема
   светлая до предела, и рамка в макете именно чернильная. */
.sample-outdoor { padding: 28px; background: var(--paper); border: 2px solid var(--ink); }
.sample-outdoor .sample-tag { background: var(--ink); color: var(--on-ink); }
.sample-outdoor .sample-note { color: var(--ink); }
.sample-outdoor .sample-rule { background: var(--ink); }
.sample-outdoor .sample-prose { font-size: 20px; line-height: 1.7; font-weight: 600; }
/* Описание под маркером — четвёртое состояние метки: не подчёркивание и не
   значок, а заливка. */
.sample-fill { display: inline-block; padding: 3px 6px; border-radius: 4px; background: var(--mark-soft); color: var(--ink); }

/* ── Прочие страницы ─────────────────────────────────────────────────────── */

.feat { padding-bottom: 8px; }
.legal { max-width: 760px; }
.legal-list { }
.legal-list { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 8px; }
.contacts-lede { font-size: 22px; line-height: 1.6; }
.interest-claim { max-width: 900px; font-family: var(--font-ui); font-size: 26px; font-weight: 400; line-height: 1.55; }

.interest-card { padding: 24px 26px; border-radius: var(--r-md); background: var(--ink-2); border: 1px solid var(--rule-ink); }

/* ── Карточка состояния ──────────────────────────────────────────────────────
 *
 * «Состояние: пусто», «Письмо отправлено», «Готово» — в макете это **тёмные**
 * карточки, и не для красоты: их метка набрана маркером, а маркер на бумаге
 * даёт 1,54 : 1 при пороге 4,5. Замерено на живой странице. Тёмная подложка —
 * то, что нарисовано, и то, что проходит порог: маркер на чернилах даёт 10 : 1. */

/* Карточка формы и пустого состояния — **вторая бумага**, радиус 28, поля 36 и
   без обводки: числа макета страниц входа. Стояла бумага в линейке, радиус 18 и
   поля 26 / 28. */
.form-card, .empty {
	padding: 36px;
	border-radius: var(--r-lg);
	background: var(--paper-2);
}

/* Страница входа: три узла в сетке — шапка и форма в левой колонке 520,
   карточка выгод во второй колонке **во второй строке**, то есть ровно на
   уровне формы. Сдвиг числом (92 px) стоял здесь до правки и врал: высота
   шапки зависит от длины заголовка, и на регистрации карточка уезжала выше
   формы. */
.cols-auth {
	display: grid;
	grid-template-columns: 520px minmax(0, 1fr);
	column-gap: 64px;
	row-gap: 32px;
	align-items: start;
}

/* Места названы явно: без них автоматическая раскладка ставит шапку и форму
   рядом, а не одну под другой — замер поймал это сразу (форма оказалась в
   правой колонке шириной 664 вместо 520). */
.cols-auth > .auth-head { grid-area: 1 / 1; }
.cols-auth > .form-card { grid-area: 2 / 1; }
.cols-auth > .perk-card { grid-area: 2 / 2; }

/* Под 1080 всё в одну колонку, и правило стоит **сразу за определением**: в
   чужом медиазапросе выше по файлу оно проигрывало по порядку, и на 390 форма
   оставалась 520 при экране 350 — сорок узлов вылезали за край. */
@media (max-width: 1080px) {
	.cols-auth { grid-template-columns: minmax(0, 1fr); }
	.cols-auth > .auth-head, .cols-auth > .form-card, .cols-auth > .perk-card { grid-area: auto; }
}
.perk-card { padding: 36px; border-radius: var(--r-lg); background: var(--paper-2); }
.band-auth { padding: 80px var(--pad-page) 96px; }
/* Страницы отказа: верх 96 / 72, разделы 72, последний 96 снизу. */
.band-err-top { padding: 96px var(--pad-page) 72px; }
.band.band-b96 { padding-bottom: 96px; }
.kick-12 { font-size: 12px; }
.auth-note { font-family: var(--font-ui); font-size: 17px; line-height: 1.59; }

/* Кнопка формы — во всю ширину карточки: так нарисованы все формы входа. */
.form-card .btn { width: 100%; }

.band-ink .form-card, .on-ink .form-card, .band-ink .empty, .on-ink .empty {
	background: var(--ink-2);
	border-color: var(--rule-ink);
}

/* Тёмный остров на светлой полосе: карточка состояния. */
.card-ink {
	background: var(--ink);
	border-color: var(--ink);
	color: var(--on-ink);
}

.card-ink .dim, .card-ink .cap { color: var(--on-ink-2); }
.card-ink .cap.mark-txt { color: var(--mark); }
/* Опасное на чернилах — светлая мягкая, а не тёмная киноварь: `--danger` на
   `--ink` даёт 2,3 : 1, `--danger-soft` — 9,1 : 1. */
.card-ink .cap.danger-txt, .on-ink .danger-txt, .band-ink .danger-txt { color: var(--danger-soft); }
.card-ink .hair { background: var(--rule-ink); }
/* Второе состояние показывается **только после нажатия**: до него на странице
   нет ни слова о том, что уже посчитано. Признак ставит htmx после ответа. */
.interest-done { display: none; }
.interest[data-done] form { display: none; }
.interest[data-done] { border-color: var(--mark); }
.interest[data-done] .interest-done { display: flex; }

/* Оглавление документа липнет к верху: три юридических текста длиннее экрана.
   **Только в широкой ширине**: на 390 оглавление стоит первым в потоке, и
   липкий блок там ехал за экраном поверх текста (замечание владельца
   2026-09-04). */
.toc { position: sticky; top: 24px; }

@media (max-width: 720px) {
	.toc { position: static; }
}

/* ── Кабинет ─────────────────────────────────────────────────────────────────
 *
 * Числа этого раздела сняты из `.pen` — экраны «Кабинет · Мои книги»,
 * «Кабинет · Книга», «Загрузка книги» на 1440 и 390. Общее правило макета:
 * блок кабинета — **карточка второй бумаги**, а не текст в пустоте, и между
 * карточками стоит зазор. До правки блоки шли голым потоком и слипались
 * (замечания владельца 2026-09-06, пункты 3–6).
 *
 * Признак кабинета — класс `cab` у `body`, а не класс у каждой полосы: страниц
 * кабинета шесть, полос в них двадцать с лишним, и метка на каждой означала бы
 * двадцать мест, где однажды забудут. */

/* Полосы кабинета плотнее публичных: 64 против 88 на широком, 36/40 против 56
 * на узком. Шапка страницы — 72/48 и 36/28: числа макета. */
.cab .band { padding: 64px var(--pad-page); }
.cab .band-tight, .cab .band-tight-cab { padding: 72px var(--pad-page) 48px; }
/* Тело страницы книги начинается сразу под её шапкой: воздух уже дан снизу
   шапки (48 на широком, 28 на узком), и макет его не удваивает — замерено, до
   правки между автором и обложкой стояло 112 px против нарисованных 48. */
.cab .band-t0 { padding-top: 0; }
/* Последняя полоса перед подвалом — 88 снизу (44 на узком): так набраны все
   шесть страниц кабинета в макете. */
.cab main > section:last-child { padding-bottom: 88px; }
/* Шапка страницы книги начинается выше остальных — 40 против 72 (24 против 36
   на узком): над меткой стоит ссылка «Мои книги», и воздух отдан ей. */
.cab .band-t40 { padding-top: 40px; }

/* Страница книги: слева 812, справа 380, зазор 56 — числа макета (`cols-440`
   стоял здесь до правки и давал правой колонке лишние 60 px). Места названы
   явно ради **порядка на узком**: в макете 390 обложка идёт первой, до
   состояния обработки, а сложенная в одну колонку правая колонка уронила бы её
   в самый низ страницы. */
.book-cols {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 380px;
	grid-template-areas:
		"main cover"
		"main side";
	gap: 20px 56px;
	align-items: start;
}

.book-cols > .bookcover { grid-area: cover; }
.book-cols > .book-main { grid-area: main; }
.book-cols > .book-side { grid-area: side; }

@media (max-width: 1080px) {
	.book-cols {
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"cover"
			"main"
			"side";
		gap: 20px;
	}
}

/* Карточка блока кабинета: поля 32 и радиус 28 на широком, 22 и 18 на узком. */
.cab-card {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: 32px;
	border-radius: var(--r-lg);
	background: var(--paper-2);
}

/* Плашка «состояние меняется само» — овал с киноварной точкой, а не строка со
   значком: в макете это единственный элемент, который обещает живое обновление,
   и он нарисован плашкой. Точка — псевдоэлементом, чтобы разметка не носила
   пустой узел. */
.live-pill {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	width: fit-content;
	max-width: 100%;
	padding: 10px 16px;
	border-radius: 999px;
	background: var(--paper-2);
	font-family: var(--font-ui);
	font-size: 14px;
	line-height: 1.3;
}

.live-pill::before {
	content: "";
	width: 9px;
	height: 9px;
	border-radius: 999px;
	background: var(--accent);
	flex-shrink: 0;
}

.band-ink .live-pill, .on-ink .live-pill { background: var(--ink-2); color: var(--on-ink); }

/* Три числа книги — три карточки, а не строка цифр: поля 24, радиус 18,
   зазор 16 (на узком 16 / 18 / 10). */
.num-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }

.num-card {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 24px;
	border-radius: var(--r-md);
	background: var(--paper-2);
}

/* «Прочитано» — карточка со полосой заполнения: в макете доля прочитанного
   показана полосой, а не только числом. */
.read-card { display: flex; flex-direction: column; gap: 10px; padding: 24px; border-radius: var(--r-md); background: var(--paper-2); }
/* Рельс полосы — линейка, а не вторая бумага: на карточке второй бумаги полоса
   заполнения совпала бы с подложкой и была бы не видна вовсе (замерено на
   боевой после первой правки). */
.read-card .meter { background: var(--rule-paper); }

/* Обложка на странице книги: 380 × 500 в макете, то есть 19 : 25. Заглушка —
   та же рамка чернилами и буква названия маркером: пустая серая плита читается
   как незагрузившаяся картинка, а не как «обложки нет». */
.bookcover {
	width: 100%;
	aspect-ratio: 19 / 25;
	object-fit: cover;
	border-radius: var(--r-md);
	background: var(--paper-2);
}

/* Заглушка ниже настоящей обложки — 3 : 2 против 19 : 25. Причина замерена: на
   390 плита 19 : 25 занимает 460 px, то есть весь экран под одной буквой, и
   читатель прокручивает пустоту, чтобы дойти до состояния книги. */
.bookcover-none {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 3 / 2;
	background: var(--ink-2);
	color: var(--mark);
	font-family: var(--font-display);
	font-size: 96px;
	font-weight: 600;
}

/* «Читалка живёт в приложении» — тёмная карточка со значком маркером: то же
   место и тот же вид, что в макете. */
.app-note {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 20px;
	border-radius: var(--r-md);
	background: var(--ink);
	color: var(--on-ink);
}

.app-note .ico { color: var(--mark); flex-shrink: 0; margin-top: 2px; }

/* Оглавление книги: плашки радиуса 8 без разделителей, текущая глава залита.
   Разделители `.list` в макете есть только у покупок. */
.toc-book { display: flex; flex-direction: column; gap: 2px; }
.toc-book .toc-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 13px 14px;
	border-left: 0;
}

/* Киноварная черта слева — **только** у главы, до которой дочитано: в макете
   `strokeWidth` стоит у одной строки из семи, у остальных обводки нет вовсе.
   Заливка — вторая бумага: `--paper` совпал бы с фоном страницы, и текущая
   глава ничем бы не отличалась. */
.toc-book .toc-row-on {
	padding-left: 11px;
	border-left: 3px solid var(--accent);
	background: var(--paper-2);
}

/* Обложка-заглушка в строке списка — тёмная плита 52 × 72 с книжным значком
   маркером, как в макете; буквы там нет ни у одной книги. До правки на её
   месте стоял `.phone-cover` из макета телефона: плита чернилами с подписью в
   нижнем углу, и подпись в 64 × 92 обрезалась в чёрный квадрат. */
.bookrow-cover-none {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--ink-2);
	color: var(--mark);
	border-radius: var(--r-sm);
}

/* Остатки аккаунта — карточки на чернилах: 400 × 246 с полями 32 и радиусом 28
   на широком, 169 с полями 20 и радиусом 18 на узком. */
.unit-panel {
	padding: 32px;
	border-radius: var(--r-lg);
	background: var(--ink-2);
}

/* Полоска «первые 500 000 знаков бесплатно» на загрузке: радиус 8, поля 16/20,
   вторая бумага — в макете она стоит под заголовком, а не карточкой в колонке. */
.free-strip {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 16px 20px;
	border-radius: var(--r-sm);
	background: var(--paper-2);
	font-family: var(--font-ui);
	font-size: 16px;
	line-height: 1.5;
}

.free-strip .ico { color: var(--accent); flex-shrink: 0; margin-top: 2px; }

/* Зона выбора файла: 200 в высоту, радиус 18, чернила внутри тёмной карточки.
   Пунктир — свой, у макета его нет, но без него зона не читается как место для
   файла на однотонном фоне. */
.up-zone {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 14px;
	min-height: 200px;
	padding: 24px;
	border-radius: var(--r-md);
	border: 1px dashed var(--rule-ink);
	background: var(--ink);
	text-align: center;
}

.up-zone .ico { color: var(--mark); }

/* Родное поле файла спрятано, а не оформлено: кнопка браузера не поддаётся
   гарнитуре и радиусу, а `::file-selector-button` не убирает подпись «Файл не
   выбран» рядом с ней. Имя выбранного файла показывает `site.js`. */
.up-zone input[type="file"] {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

.up-zone input[type="file"]:focus-visible + .btn { box-shadow: 0 0 0 3px var(--mark); }
/* Кнопка выбора обжимает подпись: `.form-card .btn` тянет кнопки формы во всю
   ширину карточки, а в зоне выбора она нарисована по тексту (146 × 46). */
.up-zone .btn { width: fit-content; }
/* Имя выбранного файла: узел создаёт `site.js`, поэтому пустым он не бывает. */
.up-name { font-family: var(--font-ui); font-size: 15px; }

@media (max-width: 720px) {
	.cab .band { padding: 36px var(--pad-page) 40px; }
	.cab .band-tight, .cab .band-tight-cab { padding: 36px var(--pad-page) 28px; }
	.cab main > section:last-child { padding-bottom: 44px; }
	.cab .band-t0 { padding-top: 0; }
	.cab .band-t40 { padding-top: 24px; }
	.cab-card { padding: 22px; border-radius: var(--r-md); gap: 12px; }
	.num-cards { gap: 10px; }
	.num-card { padding: 16px; gap: 4px; }
	.num-card .mid { font-size: 26px; }
	.read-card, .app-note { padding: 18px; }
	.free-strip { padding: 14px 16px; font-size: 14px; }
	.unit-panel { padding: 20px; border-radius: var(--r-md); }
	/* Метка счётчика на узком 11-м: 12-м «ОБРАБОТКА КНИГ» рвётся на две строки
	   в карточке шириной 169. */
	.unit-panel .cap { font-size: 11px; letter-spacing: 1.2px; }
	.live-pill { padding: 10px 14px; font-size: 13px; }
	.bookcover-none { font-size: 64px; }
	.up-zone { min-height: 160px; padding: 20px; }

	/* Строка покупки — две строки по две ячейки, как в макете: вид с количеством
	   и цена сверху, дата и чек снизу. Четыре ячейки в одну строку на 350 px не
	   встают: замерено на боевой — плашка возврата уезжала за край экрана.
	   Шапка таблицы там же исчезает: без четырёх колонок она подписывает
	   ничего. */
	.buy-head { display: none; }

	.buy-line {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		gap: 10px 12px;
		align-items: center;
	}

	.buy-line > :nth-child(1) { grid-area: 1 / 1; }
	.buy-line > :nth-child(3) { grid-area: 1 / 2; }
	.buy-line > :nth-child(2) { grid-area: 2 / 1; }
	.buy-line > :nth-child(4) { grid-area: 2 / 2; justify-content: flex-end; }
	.buy-line .tag { white-space: normal; }

	/* Остатки на узком: два счётчика рядом, бесплатный объём — во всю ширину.
	   Одна колонка растила блок вдвое против нарисованного. */
	.unit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
	.unit-grid > :last-child { grid-column: 1 / -1; }

	/* Строка книги в списке: обложка над названием, а не рядом — на 350 рядом
	   остаётся 264 px, и плашка с подробностью в них не встают. */
	.bookrow { flex-direction: column; align-items: flex-start; gap: 14px; padding: 18px; }

	/* Шапка кабинета — две строки, как в макете (390 × 105): марка с меткой и
	   выход сверху, три пункта навигации снизу. Гамбургера в ней нет: три
	   пункта помещаются в строку, а раскрывающееся полотно ради них — механика
	   на пустом месте. */
	.hdr-ink {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		grid-template-areas: "brand act" "nav nav";
		align-items: center;
		height: auto;
		row-gap: 10px;
		padding: 14px var(--pad-page) 12px;
	}

	.hdr-ink > :first-child { grid-area: brand; }
	.hdr-ink > .nav { grid-area: nav; display: flex; gap: 22px; }
	.hdr-ink > .hdr-right { grid-area: act; }
	.hdr-ink .hdr-burger { display: none; }
	/* Почта в шапке кабинета на узком не показывается: она есть в профиле, а
	   в строку с маркой и выходом не встаёт. */
	.hdr-ink .hdr-mail { display: none; }
	/* Выход — круглая кнопка со значком: 44 × 44 в макете. */
	.hdr-ink form .btn { width: 44px; height: 44px; padding: 0; justify-content: center; }
	.hdr-ink .btn-lab { display: none; }
}

/* ── Страницы отказа ─────────────────────────────────────────────────────── */

.code-num { font-family: var(--font-display); font-size: 180px; font-weight: 600; line-height: 0.9; color: var(--on-paper-2); }
.err-row { gap: 10px; padding: 28px; border-radius: var(--r-md); background: var(--ink-2); }
.err-row .ico { color: var(--accent); flex-shrink: 0; }
.err-t { font-family: var(--font-ui); font-size: 18px; font-weight: 600; }
.err-x { font-family: var(--font-ui); font-size: 16px; line-height: 1.62; }
.err-dot { color: var(--accent); margin-top: 2px; }

@media (max-width: 720px) {
	.code-num { font-size: 92px; }
	.fmt-old, .fmt-new { font-size: 44px; }
	.interest-claim { font-size: 20px; }
	.contacts-lede { font-size: 18px; }
	/* Большой график в узкой ширине: значение 16-м. При 22-м «472» плюс поля
	   давали столбик 48 px, а на семь столбцов в 390 есть только 45 — график
	   вылезал за экран на 6 px. Замерено. */
	.bars-big .bar-val { font-size: 16px; }
	.bars-big { min-height: 220px; }
	/* Витрина настроек в узкой ширине — одна колонка, и ползунок сжимается по
	   месту: с шириной 130 px он вылезал за экран на 390 вместе с числом. */
	.set-show { padding: 8px 20px; }
	.set-cols { grid-auto-flow: row; grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
	.set-cols > *:nth-child(5) { border-top: 1px solid var(--rule-paper); }
	.ctl-range { min-width: 0; }
	.ctl-range input { width: auto; min-width: 0; flex: 1 1 auto; }
	/* Цены в узкой ширине: столбец суммы 400 не влезает в 350 — колонки
	   становятся одной, сумма 54-м, шкала знаков растягивается по месту. */
	.cols-400 { grid-template-columns: minmax(0, 1fr); }
	.vol-novel { width: 46%; }
	.vol-tome { width: 100%; }
	.vol-lab { width: 100%; }
	/* Шапка раздела на 390: номер 32, название 26, счётчик переносится строкой —
	   иначе три узла не влезают в 350. */
	.feat-no { font-size: 32px; }
	.feat-h { font-size: 26px; }
	.feat-cnt { padding: 5px 10px; font-size: 13px; }
	/* Счётчик демонстрации в узкой ширине: панель столбиком, подпись во всю
	   ширину, а сами столбики теснее — семь колонок в 350 иначе не влезают. */
	.chart-demo { flex-direction: column; align-items: stretch; padding: 20px; }
	.chart-demo .chart-note { width: auto; }
	.bars-demo { gap: 4px; }
	.bars-demo .bar-col { padding: 6px 2px; }
	.bars-demo .bar-val { font-size: 12px; }
	.bars-demo .bar-lab { font-size: 10px; }
	.bars-demo .bar-lab-w { display: none; }
}

/* ── Ползунки настроек и чекбокс ─────────────────────────────────────────────
 *
 * Отдельно от ползунка главы: тот стоит на чернилах и крупный, эти — в панели
 * настроек и мелкие. Без этих правил браузер рисует системный синий, которого
 * в регистре нет вовсе. */

.ctl-range input[type="range"] {
	-webkit-appearance: none;
	appearance: none;
	height: 18px;
	background: none;
	cursor: pointer;
	accent-color: var(--mark);
}

.ctl-range input[type="range"]::-webkit-slider-runnable-track {
	height: 3px;
	border-radius: 999px;
	background: var(--rule-ink);
}

.ctl-range input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none;
	width: 14px;
	height: 14px;
	margin-top: -6px;
	border-radius: 999px;
	background: var(--mark);
}

.ctl-range input[type="range"]::-moz-range-track { height: 3px; border-radius: 999px; background: var(--rule-ink); }
.ctl-range input[type="range"]::-moz-range-thumb { width: 14px; height: 14px; border: 0; border-radius: 999px; background: var(--mark); }

.set-show .ctl-range input[type="range"]::-webkit-slider-runnable-track { background: var(--rule-paper); }
.set-show .ctl-range input[type="range"]::-moz-range-track { background: var(--rule-paper); }
.set-show .ctl-range input[type="range"]::-webkit-slider-thumb { background: var(--ink); }
.set-show .ctl-range input[type="range"]::-moz-range-thumb { background: var(--ink); }

/* Переключатель подсветки имён — тумблер, как в макете, а не квадрат. */
.ctl-check input[type="checkbox"] {
	appearance: none;
	position: relative;
	width: 40px;
	height: 22px;
	border-radius: 999px;
	background: var(--rule-ink);
	cursor: pointer;
	transition: background var(--motion-hover) ease;
}

.ctl-check input[type="checkbox"]::after {
	content: "";
	position: absolute;
	top: 3px;
	left: 3px;
	width: 16px;
	height: 16px;
	border-radius: 999px;
	background: var(--on-ink-2);
	transition: transform var(--motion-hover) ease, background var(--motion-hover) ease;
}

.ctl-check input[type="checkbox"]:checked { background: var(--ink); }
.ctl-check input[type="checkbox"]:checked::after { transform: translateX(18px); background: var(--mark); }
.set-show .ctl-check input[type="checkbox"] { background: var(--rule-paper); }
.set-show .ctl-check input[type="checkbox"]:checked { background: var(--ink); }

/* ── Модификаторы цвета — в самом конце файла ───────────────────────────────
 *
 * Цвет-модификатор обязан побеждать цвет компонента, а специфичность у них
 * одинаковая — один класс против одного, — значит решает порядок. Поэтому все
 * они собраны здесь, последними.
 *
 * Замерено на живой странице, а не предположено: `.phone-cap` перебивал
 * `.mark-txt`, и подпись «Продолжить» на тёмной карточке продолжения
 * набиралась серым по чернилам — 2,6 : 1 при пороге 4,5. Тем же порядком
 * `.dim` перебивал цвет подписи на тёмной шторке генерации. */

/* Тон красит и вложенную метку со значком: в макете значок и подпись рядом
   всегда одного цвета, а `.cap` назначает себе свой — поэтому одного класса на
   строке мало, и тон обязан доставать до метки. */
.mark-txt, .mark-txt .cap { color: var(--mark); }
.acc-txt, .acc-txt .cap { color: var(--accent); }
.danger-txt, .danger-txt .cap { color: var(--danger); }

/* Опасное на чернилах — мягкая киноварь: `--danger` на `--ink` даёт 2,3 : 1,
   `--danger-soft` — 9,1 : 1. */
.on-ink .danger-txt, .band-ink .danger-txt, .card-ink .danger-txt {
	color: var(--danger-soft);
}

/* Тусклый текст на тёмных островах — своими чернилами, а не бумажными. */
.gen-bar .dim, .card-ink .dim, .phone-resume .dim, .phone-resume .phone-stat-l,
.curtain-body .dim, .step-body .dim {
	color: var(--on-ink-2);
}

/* ── Узкая ширина: заголовки блоков 5 и 6 ────────────────────────────────────
 *
 * Три замечания владельца 2026-09-04 про 390, и все три про переносы:
 * заголовок шлюза шёл в четыре строки с чертой во всю ширину экрана, а у «своей
 * книги» жёсткий `<br>` оставлял тире одно в конце строки. Правится раскладкой,
 * а не вторым текстом: строчная черта ложится по словам, поток отдаёт переносы
 * браузеру, `text-wrap: balance` уравнивает строки. */
@media (max-width: 720px) {
	#gate .h2 { display: block; }
	#gate .uline-mark {
		display: inline;
		padding-bottom: 3px;
		background-size: 100% 5px;
		-webkit-box-decoration-break: clone;
		box-decoration-break: clone;
	}

	#gate .h2, #own .h2 { text-wrap: balance; }
}

/* ── Узкая шапка: кнопка-значок и полноэкранное меню ─────────────────────────
 *
 * Два решения владельца 2026-09-04.
 *
 * **Кнопка становится значком.** Подпись «Начать бесплатно» при 15-м кегле и
 * полях 24 занимала 181 px из 390 и ломалась на две строки; макет 390 рисует её
 * подписью 14-м с полями 16, но владелец выбрал значок — «человек с плюсом»,
 * читаемый как «завести аккаунт». Подпись остаётся в разметке и её читает
 * читалка экрана: скрывается она, а не удаляется.
 *
 * **Меню полноэкранное.** Прежняя панель 220 × 262 с пятью подчёркнутыми
 * ссылками названа скудной. Раскрытый `details` растягивается на экран целиком;
 * скрипта на это не нужно ни строки. */

@media (max-width: 720px) {
	/* Кнопки регистрации в узкой шапке нет вовсе: она есть в герое во всю
	   ширину и в раскрытом меню. Подпись 181 px из 390 ломалась на две строки,
	   значок вместо неё владелец тоже отверг. */
	.hdr-cta { display: none; }

	/* Значок и крестик — одно место: показывается тот, что отвечает состоянию. */
	.burger-close { display: none; }
	.hdr-burger[open] > .burger-btn .burger-open { display: none; }
	.hdr-burger[open] > .burger-btn .burger-close { display: inline-flex; }

	/* Крестик **закреплён на экране** вместе с полотном. `position: relative`
	   здесь не годится: шапка не липкая, и меню, раскрытое после прокрутки,
	   оставалось без кнопки закрытия вовсе — поймано на снимке. */
	.hdr-burger[open] > .burger-btn {
		position: fixed;
		top: 14px;
		right: var(--pad-page);
		z-index: 41;
		border-color: var(--rule-ink);
		background: var(--ink-2);
		color: var(--on-ink);
	}

	/* Закрытое меню обязано быть **без геометрии**: содержимое закрытого
	   `details` браузер прячет от глаз, но размеры у `position: fixed` панели
	   остаются, и замер честно нашёл 25 узлов за краем экрана на каждой
	   странице. */
	.hdr-burger:not([open]) > .burger-sheet { display: none; }

	/* Фон за раскрытым меню не листается: прокрутку забирает полотно, а
	   документ её теряет. Держится это `:has()` без единой строки скрипта —
	   поведение «меню открыто, страница едет» владелец назвал некорректным. */
	html:has(.hdr-burger[open]) { overflow: hidden; }

	.burger-sheet {
		position: fixed;
		inset: 0;
		z-index: 40;
		overflow-y: auto;
		background: var(--ink);
		animation: fade var(--motion-hover) var(--ease) both;
	}

	.burger-in {
		display: flex;
		flex-direction: column;
		gap: 28px;
		min-height: 100%;
		padding: 96px 20px 40px;
	}

	/* Марка в полотне — **без маркерной заливки**: на чернилах она в 20-м кегле
	   съедала буквы (замерено глазами на снимке), а на бумаге шапки та же
	   заливка читается. */
	.burger-brand { align-self: flex-start; color: var(--on-ink); box-shadow: none; }
	.burger-cap { color: var(--on-ink-2); }

	.burger-nav { display: flex; flex-direction: column; }

	/* Пункт — строка на всю ширину: номер, название 30-м, стрелка справа.
	   Линейка снизу вместо подчёркивания подписи: подчёркнутая ссылка в
	   тридцатом кегле читается как опечатка. */
	.burger-i {
		display: grid;
		grid-template-columns: 34px minmax(0, 1fr) 20px;
		gap: 14px;
		align-items: center;
		padding: 18px 0;
		border-bottom: 1px solid var(--rule-ink);
		color: var(--on-ink);
		text-decoration: none;
	}

	.burger-i:first-child { border-top: 1px solid var(--rule-ink); }
	.burger-i .ico { color: var(--mark); }
	.burger-no { font-family: var(--font-ui); font-size: 13px; font-weight: 600; color: var(--on-ink-2); }
	.burger-t { font-family: var(--font-display); font-size: 30px; font-weight: 500; line-height: 1.15; }
	.burger-i:hover .burger-t { color: var(--mark); }

	.burger-foot { margin-top: auto; }

	/* Кнопка в меню — с подписью: места в полноэкранном полотне хватает. */
	/* Обе кнопки полотна во всю ширину и одной высоты. */
	.burger-foot .btn-full { width: 100%; height: 52px; }
}

/* Подсказка про свайп нужна только там, где есть свайп, и объявлена **до**
   своей узкой ветки: правило равного веса, стоящее позже, побеждает по порядку —
   замер поймал, что подсказка не показывалась вовсе. */
.swipe-hint { display: none; align-items: center; gap: 8px; }

@media (max-width: 720px) {
	.phones {
		display: flex;
		gap: 16px;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-snap-type: x mandatory;
		margin-inline: calc(-1 * var(--pad-page));
		padding: 0 var(--pad-page) 12px;
		scroll-padding-inline: var(--pad-page);
	}

	.phones > .phone-col {
		flex: 0 0 300px;
		scroll-snap-align: center;
	}

	.swipe-hint { display: flex; }
}


/* Спойлер настроек читалки на демонстрации. В широкой ширине его не видно
   вовсе: `summary` скрыт, а `open` стоит в разметке. */
.set-sum { display: none; }

@media (max-width: 720px) {
	.set-sum {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 12px;
		width: auto;
		height: auto;
		min-height: 56px;
		padding: 0 18px;
		border: 1px solid var(--rule-ink);
		border-radius: var(--r-md);
		background: var(--ink-2);
		color: var(--on-ink);
		cursor: pointer;
		list-style: none;
	}

	.set-sum::-webkit-details-marker { display: none; }
	.set-sum .ico { color: var(--mark); }
	.set-sum-t { font-family: var(--font-ui); font-size: 15px; font-weight: 600; }
	.set-fold[open] > .set-sum { margin-bottom: 16px; border-color: var(--mark); }
}

/* ── Узкая ширина: длинные слова в заголовках ────────────────────────────────
 *
 * «Политика конфиденциальности» рвала страницу по ширине: слово в 32-м кегле
 * не влезает в 350 px, переносить его негде, и `scrollWidth` документа
 * становился 478 при экране 390 — вся страница ездила вбок (замечание
 * владельца 2026-09-04).
 *
 * Сперва переносы по правилам языка, и только если их нет — разрыв слова: у
 * документа стоит `lang="ru"`, поэтому `hyphens: auto` даёт «конфиден-»
 * с дефисом, а не рубленое слово. */
@media (max-width: 720px) {
	h1, h2, h3, .h1, .h2, .h3, .h-hero, .h-page, .h-narrow, .h-xlong {
		hyphens: auto;
		overflow-wrap: break-word;
	}
}

/* ── Слой движения ──────────────────────────────────────────────────────────
 *
 * Замечание владельца 2026-09-04: «по всему сайту не хватает анимаций и
 * интерактивности, нет плавности вообще». До этой правки в регистре стояло
 * девять переходов и три кадровых анимации — вращение индикатора, полоса
 * генерации и подъём шторки, — то есть двигались ровно три места из двадцати
 * одной страницы.
 *
 * Механизмы взяты из корпуса, где каждый проверен по первоисточнику
 * (`docs/analysis/2026-09-04-site-references-and-stack/part-refs-motion-and-type.md`,
 * корзина 3): прокруточные анимации — Safari 26.0, в отдельном потоке с 26.4,
 * вердикт «с фолбэком»; `text-wrap: pretty` — Safari 26.0, «берём». Фолбэк
 * прокруточных нулевой: без `animation-timeline` правило не применяется вовсе
 * (оно под `@supports`), и содержимое просто стоит на месте.
 *
 * Всё, что ниже, обнуляется одним общим правилом `prefers-reduced-motion` в
 * начале файла — оно уже есть и снимает и длительности, и задержки. */

/* Появление при прокрутке. Анимируются **карточки, кадры и строки**, а не
   полосы: полоса — предок липкого оглавления, и `transform` на предке
   ломает `position: sticky`. */
/* Проявление: подменённый фрагмент и полотно меню. */
@keyframes fade {
	from { opacity: 0; }
}

@keyframes appear {
	from {
		opacity: 0;
		transform: translateY(18px);
	}
}

@supports (animation-timeline: view()) {
	@media (prefers-reduced-motion: no-preference) {
		.mosaic .shot,
		.idx-row,
		.gate-card,
		.next-shot,
		.step,
		.curtain,
		.own-step,
		.feat-i,
		.free-card,
		.err-row,
		.sample,
		.legal-part {
			animation: appear linear both;
			animation-timeline: view();
			animation-range: entry 8% entry 46%;
		}
	}
}

/* Подменённый фрагмент проявляется, а не возникает рывком: узлы после swap
   создаются заново, поэтому кадровая анимация играет сама, без обработчика. */
#who > *,
#gated > * { animation: fade var(--motion-card) var(--ease) both; }

/* Отклик на нажатие: кнопка чуть проседает под палец. */
.btn { transition: background var(--motion-hover) var(--ease), color var(--motion-hover) var(--ease), transform var(--motion-hover) var(--ease); }
.btn:active { transform: scale(0.98); }

/* Кликабельное в прозе отвечает наведением — до правки курсор обещал нажатие,
   а вид не менялся ничем. */
.m-entity,
.m-descr { transition: background var(--motion-hover) var(--ease), box-shadow var(--motion-hover) var(--ease); }
.m-entity:hover { box-shadow: 0 0 0 4px var(--mark-soft); }
.m-descr:hover { box-shadow: 0 2px 0 0 var(--accent); }

/* Кадр приближается под курсором: подпись остаётся на месте, двигается только
   картинка внутри своей рамки. */
.shot { overflow: hidden; }
.shot img { transition: transform var(--motion-sheet) var(--ease); }
.shot:hover img { transform: scale(1.04); }

/* Строки перечней и оглавления. */
.idx-row,
.item,
.set-sum { transition: background var(--motion-hover) var(--ease), border-color var(--motion-hover) var(--ease); }
.idx-row:hover { background: var(--ink-2); }
.set-sum:hover { border-color: var(--mark); }

/* Пункты полноэкранного меню появляются по одному: полотно открывается на
   240 мс, пункты догоняют его с шагом 40 мс. */
@media (max-width: 720px) {
	.hdr-burger[open] .burger-i {
		animation: appear var(--motion-sheet) var(--ease) both;
	}

	/* Шаг задержки считает сам CSS. `sibling-index()` — Safari 26.2, Chrome 138
	   (корпус, 3.16, вердикт «с фолбэком»); без него пункты проявятся все
	   разом, и это законный вид, а не поломка. */
	@supports (animation-delay: calc(1ms * sibling-index())) {
		.hdr-burger[open] .burger-i { animation-delay: calc(40ms * sibling-index()); }
	}
}

/* Проза переносится по правилам «pretty»: висячие строки и одинокие слова в
   конце абзаца — самый заметный дефект набора на 350 px. */
.prose,
.lede,
.lede-16,
.lede-18,
.lede-20 { text-wrap: pretty; }

/* ── Шапка липкая ───────────────────────────────────────────────────────────
 *
 * Часть того же замечания про «нет плавности»: страница длинная (Главная 13 466
 * px на 1440), и уехавшая шапка оставляла читателя без навигации и без кнопки —
 * особенно на 390, где кнопка регистрации из шапки убрана вовсе.
 *
 * Полоса и без того с фоном и линейкой снизу, поэтому нового облика это не
 * заводит: меняется только то, что она не уезжает. Якоря разделов и цели
 * прокрутки получают отступ на её высоту, иначе заголовок раздела приезжает
 * под неё. */
.hdr {
	position: sticky;
	top: 0;
	z-index: 30;
}

.band,
.legal-part,
[id] { scroll-margin-top: 112px; }

.toc { top: 120px; }

@media (max-width: 720px) {
	.band,
	.legal-part,
	[id] { scroll-margin-top: 86px; }
}
