/* ─────────────────────────────────────────────────────────────────────────
   ДВИЖЕНИЕ

   Отдельный слой, а не вкрапления в page.css. Причина простая: движение —
   единственная часть системы, которую можно и нужно уметь снять целиком, не
   трогая раскладку. Убери две строки из <head> — сайт останется рабочим
   документом, просто без движения.

   Правило, по которому здесь всё сделано: движение либо что-то показывает,
   либо его нет. Ни один эффект тут не украшает. Разворот заголовка по
   строкам показывает, что это набор, а не картинка; вытирание плиты
   показывает кадр; подсветка строки реестра показывает, куда ведёт сноска;
   полоска сверху показывает, сколько прочитано.

   Скорости. Отклик на курсор — 140 мс, иначе он ощущается как задержка.
   Появление объекта — 300 мс. Крупный объект, который занимает экран, —
   420–560 мс: быстрее он выглядит дёрганым, медленнее начинает раздражать
   на втором просмотре. Всё, что дольше 600 мс, здесь запрещено.

   Кривая одна на выход, `--ease-out` (0.23, 1, 0.32, 1): резкий старт,
   долгий вынос. Она и делает ощущение веса — объект как будто тяжёлый и
   тормозит сам. Парная кривая оставлена состояниям, которые ходят туда и
   обратно: теме и лайтбоксу.
   ───────────────────────────────────────────────────────────────────────── */

/* Токены слоя движения переехали в `tokens.css`. Здесь стоял второй
   блок `:root` с восемью значениями, пока файл токенов называл себя
   единственным источником значений для макета и для кода. Два
   источника — это не источник: правка кривой в одном не доходит до
   другого, и расхождение видно только на глаз. */

/* ── 1. Дисплейный набор разворачивается по строкам ───────────────────────
   Все крупные заголовки, h1 и h2, приходят одинаково: строка за строкой
   из-под своей маски. Строки режет скрипт по фактическим строчным
   коробкам и перерезает при смене ширины — деление «по словам» рассыпалось
   бы на первом же чужом экране.

   Двигается только transform. Текст всё это время отрисован, поэтому замер
   главного элемента страницы не портится: 92 мс с этим слоем против 136 мс
   без него. */
/* Строка держит под собой ступень 8 px и отдаёт её обратно отрицательным
   полем: выносные элементы («p», «y», «g») больше не срезаются кромкой
   блока, а раскладка не меняется. Стартовый сдвиг набора — на ту же
   ступень глубже, чтобы до появления из-под кромки ничего не выглядывало.
   Срез был виден на телефоне: «problem.», «Cavendish Square». 25.09.2026.
   Все правила строк — под `.js`: без скрипта слой выключается целиком. Пока
   они висели без него, снятый `js` оставлял строки сдвинутыми, а поле
   схлопывалось сквозь заголовок; гейт наложений `.overlap.mjs` мерил
   спрятанный текст и дал 979 «наездов» (25.09). */
.js .ln {
	display: block;
	overflow: hidden;
	padding-block-end: var(--s2);
	margin-block-end: calc(-1 * var(--s2));
}
/* Отрицательное поле последней строки схлопывалось сквозь заголовок и
   съедало 8 px отбивки после него. Заголовок с разрезанными строками —
   свой контекст раскладки, и поле остаётся внутри. */
.js :is(main h1, main h2):has(> .ln) { display: flow-root; }
/* Сброс курсива тега — типографика, а не движение: он действует и без
   `.js`. Под `.js` тег `i` получал курсив браузера, и гейт шрифтов нашёл
   синтезированное начертание на 1221 узле (25.09). */
.ln > i { font-style: inherit; }
.js .ln > i {
	display: block;
	transform: translateY(calc(105% + var(--s2)));
	will-change: transform;
	transition: transform var(--dur-head) var(--ease-glide);
	transition-delay: calc(var(--i, 0) * var(--stagger));
}
.is-in .ln > i { transform: none; }

/* Крупный номер раздела встаёт вместе с заголовком, а не отдельно: это
   одна строка набора, разорванная на две графы. */
.js main > .row .num {
	overflow: hidden;
}
.js main > .row .num > span {
	display: inline-block;
	transform: translateY(105%);
	transition: transform var(--dur-head) var(--ease-glide);
}
.js main > .row.is-in .num > span { transform: none; }

/* ── 2. Блок появляется при подходе, и появляется каждый раз ──────────────
   Начальное состояние задано структурным селектором, а не классом, который
   вешает скрипт: класс вешается после разбора документа, то есть после
   первой отрисовки, и читатель успевает увидеть текст до того, как его
   спрячут. Класс `js` ставится в <head>, и мигания нет ни кадра.

   Сдвиг идёт по направлению движения: вниз — блок поднимается снизу,
   вверх — опускается сверху. Направление приходит из скрипта переменной
   `--dir`. Без этого при прокрутке вверх содержимое приезжает «оттуда же,
   откуда и вниз», и движение читается как заводная игрушка, а не как
   реакция на чтение. */
.js main > .row > div:not(.register) > *,
.js main > .row > .register,
.js main > .row > figure.plate,
.js main > .row > .crumb {
	opacity: 0;
	transform: translateY(calc(var(--rise) * var(--dir, 1)));
	/* Прозрачность заканчивается раньше пути: текст успевает стать
	   читаемым и ещё немного доезжает. Это мелочь, которую нельзя
	   назвать, но которая и отличает дорогое движение от аккуратного. */
	transition: opacity var(--dur-fade) var(--ease-glide),
	            transform var(--dur-reveal) var(--ease-glide);
}
.js main > .row.is-in > div:not(.register) > *,
.js main > .row.is-in > .register,
.js main > .row.is-in > figure.plate,
.js main > .row.is-in > .crumb {
	opacity: 1;
	transform: none;
}
/* Ступенька внутри раздела. Сорок миллисекунд — столько, чтобы порядок
   читался, и не столько, чтобы его ждать. Дальше пятого элемента ступенька
   не растёт: иначе низ раздела приезжает заметно позже верха. */
.js main > .row.is-in > div:not(.register) > *:nth-child(2) { transition-delay: 40ms; }
.js main > .row.is-in > div:not(.register) > *:nth-child(3) { transition-delay: 80ms; }
.js main > .row.is-in > div:not(.register) > *:nth-child(4) { transition-delay: 120ms; }
.js main > .row.is-in > div:not(.register) > *:nth-child(n+5) { transition-delay: 160ms; }
.js main > .row.is-in > .register { transition-delay: 120ms; }

/* ── 2а. Ступенька — только у реестра ─────────────────────────────────────
   Здесь была ступенька у семи перечней сразу: реестр, шаги метода,
   содержание, ведомость художников, карточки направлений, справочная
   библиотека, строки записи. Каждый по отдельности выглядел уместно, а
   вместе они дали то, что и называют перенасыщенностью: на экране
   постоянно что-то едет, и ни одно движение уже ничего не значит.

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

   Шаг 55 мс вместо прежних 30: на двенадцати строках это 660 мс вместо
   360. Частая ступенька читается очередью, редкая — набором. */
.js .reg {
	opacity: 0;
	transform: translateY(calc(8px * var(--dir, 1)));
	/* Подсветка строки от сноски (раздел 5 ниже) идёт тем же списком: правило
	   `.js .reg` старше `.reg` и раньше затирало её переход, и строка вспыхивала
	   без отклика. Задержки лесенки ниже заданы по свойствам — фону ноль, иначе
	   подсветка ждала бы до 495 мс. Найдено 23.09.2026 описью движения. */
	transition: opacity var(--dur-fade) var(--ease-glide),
	            transform var(--dur-reveal) var(--ease-glide),
	            background-color var(--dur-fast) var(--ease-out);
}
.js .is-in .reg { opacity: 1; transform: none; }
.js .is-in .reg:nth-child(1) { transition-delay: 55ms, 55ms, 0s; }
.js .is-in .reg:nth-child(2) { transition-delay: 110ms, 110ms, 0s; }
.js .is-in .reg:nth-child(3) { transition-delay: 165ms, 165ms, 0s; }
.js .is-in .reg:nth-child(4) { transition-delay: 220ms, 220ms, 0s; }
.js .is-in .reg:nth-child(5) { transition-delay: 275ms, 275ms, 0s; }
.js .is-in .reg:nth-child(6) { transition-delay: 330ms, 330ms, 0s; }
.js .is-in .reg:nth-child(7) { transition-delay: 385ms, 385ms, 0s; }
.js .is-in .reg:nth-child(8) { transition-delay: 440ms, 440ms, 0s; }
.js .is-in .reg:nth-child(n+9) { transition-delay: 495ms, 495ms, 0s; }


/* ── 3. Плита вытирается, картинка садится ────────────────────────────────
   Кадр открывается снизу вверх, а изображение внутри идёт от 1,06 к 1.
   Два движения в противоход дают вес: кадр открывается, картинка
   останавливается. Это единственный эффект на сайте, который заимствован
   у выставочного зала буквально — так снимают ткань с работы. */
/* Вытирание сделано двумя встречными сдвигами, а не раскроем.
   Приложение 1 разрешает анимировать только прозрачность и трансформацию;
   `clip-path` стоял здесь и в список не входит. Замена точная, а не
   похожая: кадр сдвинут вверх на свою высоту, изображение внутри — вниз
   на столько же, поэтому в каждый момент изображение стоит на своём
   месте, а движется только окно, сквозь которое его видно. Оба сдвига
   сходятся в ноль одной кривой и одной длительностью.

   Наезд изображения (1,08 → 1) остаётся и складывается со сдвигом в один
   список трансформаций: списки одинаковой формы браузер разбирает
   покомпонентно, поэтому масштаб и сдвиг идут независимо. */
.js figure.plate .frame {
	display: block;
	overflow: hidden;
	/* Направление вытирания следует за направлением чтения, как и сдвиг
	   текста. Прежде оно было прибито к «сверху вниз»: при прокрутке вверх
	   ткань снималась с работы в ту же сторону, откуда читатель только что
	   пришёл, и движение спорило с рукой. Множитель `--dir` разворачивает
	   обе встречные части разом, поэтому работа по-прежнему стоит на месте
	   и движется только окно. */
	transform: translateY(calc(-100% * var(--dir, 1)));
	transition: transform var(--dur-plate) var(--ease-glide);
	will-change: transform;
}
.js figure.plate.is-in .frame { transform: translateY(0); }
/* Кадр, ещё не приехавший, стоит сдвинутым на свою высоту вверх — то есть
   физически лежит над своим местом на странице. На широком экране полосная
   плита высотой в кадр уезжает этим сдвигом прямо на шапку и перехватывает
   нажатия: на 1920 px замер показал, что под курсором на вкладке указателя
   оказывается `span.frame`, а не сама вкладка. Меню переставало нажиматься,
   и ни одна проверка этого не видела, потому что раскладка была цела.

   Правится по существу: то, что ещё не на месте, не берёт нажатия. */
.js figure.plate:not(.is-in) .frame { pointer-events: none; }
.js figure.plate .frame img {
	transform: translateY(calc(100% * var(--dir, 1))) scale(1.08);
	transition: transform var(--dur-plate) var(--ease-glide);
}
.js figure.plate.is-in .frame img { transform: translateY(0) scale(1); }

/* ── Стена собирается, а не проявляется ───────────────────────────────────
   Пять работ висят на двенадцати графах с разной шириной и разным началом.
   Пока все пять открывались одинаково — сверху вниз, — стена читалась
   списком: пять одинаковых движений подряд говорят «это ряд», сколько бы
   ни различались ширины.

   Теперь направление открытия следует за тем, к какому краю плита
   прижата. Прижатая к началу строки открывается от начала, прижатая к
   концу — от конца, стоящая посередине остаётся вертикальной. Композиция
   становится читаемой в движении: глаз идёт по стене так же, как шёл бы
   вдоль настоящей развески, а не сверху вниз по колонке.

   Это не параллакс: скорость у всех одна, движение вызывается появлением
   в кадре и заканчивается, а не привязано к прокрутке. Параллакс план
   запрещает поимённо, и запрет здесь не обходится, а соблюдается.

   Механика та же, что у вертикальной: кадр уходит на свою ширину в одну
   сторону, изображение внутри — на столько же в другую, поэтому работа
   стоит на месте, а движется окно. */
@media (min-width: 50.625em) {
	/* Прижатые к началу строки открываются от начала, прижатые к концу —
	   от конца. Средних в развеске нет: каждая работа стоит у своего края,
	   и направление читается с первого кадра. */
	.js .p-a .frame, .js .p-d .frame, .js .p-e .frame { transform: translateX(-100%); }
	.js .p-a .frame img, .js .p-d .frame img,
	.js .p-e .frame img { transform: translateX(100%) scale(1.08); }
	.js .p-b .frame, .js .p-c .frame { transform: translateX(100%); }
	.js .p-b .frame img, .js .p-c .frame img { transform: translateX(-100%) scale(1.08); }
	.js .plates .is-in .frame { transform: translateX(0); }
	.js .plates .is-in .frame img { transform: translateX(0) scale(1); }
}

/* Шаг между работами. Стена, где все пять трогаются разом, читается
   сменой кадра; стена, где они приходят по очереди, читается развеской.
   Шаг взят тот же, что у строк заголовка, — в системе один шаг. */
@media (min-width: 50.625em) {
	/* Шаг внутри строки, а не по всей стене. Соседи по строке приходят
	   один за другим — так вешают: сначала левая, потом правая. Между
	   строками шага нет: строка появляется в кадре целиком и своим
	   временем, и накапливать задержку через всю стену значило бы, что
	   последняя работа ждёт четыре шага без причины. */
	.js .p-b .frame, .js .p-b .frame img,
	.js .p-d .frame, .js .p-d .frame img { transition-delay: var(--stagger); }
}

/* Подпись приходит после кадра, а не вместе с ним: сначала работа, потом
   этикетка. Так на неё и смотрят. */
.js figure.plate figcaption {
	opacity: 0;
	/* Задержка равна длительности прозрачности: подпись выходит ровно
	   тогда, когда кадр закончил. Стояла числом 420 — тем же, что и
	   `--dur-fade`, но записанным отдельно, то есть обречённым разойтись. */
	transition: opacity var(--dur-fade) var(--ease-glide) var(--dur-fade);
}
.js figure.plate.is-in figcaption { opacity: 1; }

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

   Эффект вешал `::before` на `.row`. Но на разделе классы `row` и `room`
   стоят на одном элементе, а `.room::before` — это то, чем красится грунт
   комнаты. Псевдоэлемент один, и второе правило просто заменило первое:
   каждая комната вместо своего грунта получила линейку в один пиксель.
   Анфилада — главное, что есть у этих страниц, — исчезла целиком. На
   снимке в неудачный момент этого не видно: тело страницы покрашено
   бумагой, и разделы выглядят «просто светлыми».

   Свободных псевдоэлементов у `.room` нет: `::after` занят зерном. Значит
   эффект стоит настоящего элемента в разметке — а он декоративный, он
   ничего не показывает. Смена грунта читается и без него. Не возвращать. */

/* ── 5. Сноска и строка реестра смотрят друг на друга ─────────────────────
   Самое полезное движение на сайте и единственное, которое несёт смысл, а
   не настроение: наведи на номер сноски — подсветится строка реестра, к
   которой она ведёт, и наоборот. Аппарат перестаёт быть таблицей внизу и
   становится инструментом. Работает и с клавиатуры, по фокусу. */
.reg { transition: background-color var(--dur-fast) var(--ease-out); }
.reg.is-lit {
	background-color: var(--wash);
	box-shadow: -0.6em 0 0 var(--wash), 0.6em 0 0 var(--wash);
}
.note-n.is-lit { color: var(--fg); }
.note-n.is-lit::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-end: -0.22em;
	block-size: 1px;
	background: currentColor;
}
.note-n { position: relative; }

/* ── 6. Полоска прочитанного ──────────────────────────────────────────────
   Один пиксель приглушённым по верху окна. Не индикатор загрузки и не
   украшение: на странице в двадцать тысяч пикселей читателю нужно знать,
   сколько осталось, и это единственный способ сказать это, не занимая
   места. Ширина задаётся из скрипта, без перерисовки раскладки. */
.progress {
	position: fixed;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: 1px;
	background: var(--muted);
	transform: scaleX(0);
	transform-origin: 0 50%;
	z-index: var(--z-veil);
	pointer-events: none;
}

/* ── 7. Метка курсора над плитой ──────────────────────────────────────────
   Только для настоящего курсора. Над плитой курсор получает подпись —
   номер плиты и слово «Open». Это то место, где сайт говорит, что с
   работой можно что-то сделать, не рисуя кнопку поверх изображения. */
.cursor-chip {
	position: fixed;
	inset-block-start: 0;
	inset-inline-start: 0;
	z-index: var(--z-stage);
	pointer-events: none;
	font-family: var(--font-mono);
	font-size: var(--size-label);
	letter-spacing: var(--tracking-label);
	color: var(--paper);
	background: var(--ink);
	padding: 0.35em 0.6em;
	opacity: 0;
	transform: translate3d(-50%, -160%, 0) scale(0.94);
	transition: opacity var(--dur-fast) var(--ease-out),
	            transform var(--dur-fast) var(--ease-out);
}
.cursor-chip.is-on {
	opacity: 1;
	transform: translate3d(-50%, -160%, 0) scale(1);
}
@media (hover: none), (pointer: coarse) { .cursor-chip { display: none; } }
.js figure.plate[data-open] { cursor: zoom-in; }

/* ── 8. Лайтбокс ──────────────────────────────────────────────────────────
   Плита открывается на весь экран. Изображение едет из своего места в
   центр — считается по фактическим координатам, не «появляется по центру»:
   читатель должен видеть, что открылась та самая работа, на которую он
   нажал. Подпись остаётся внизу, потому что этикетка — часть работы.
   Закрывается по Esc, по клику и по прокрутке. */
/* Завеса — чернильная комната в миниатюре, и роли она берёт тем же
   блоком, что комната и плита. Раньше её подпись пересчитывала
   приглушённую роль своим выражением. */
.veil {
	position: fixed;
	inset: 0;
	z-index: var(--z-close);
	display: grid;
	grid-template-rows: 1fr auto;
	gap: var(--s4);
	padding: var(--s5) var(--page-pad) var(--s4);
	background: var(--scrim);
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--dur-veil) var(--ease-pair),
	            visibility 0s linear var(--dur-veil);
}
.veil.is-open {
	opacity: 1;
	visibility: visible;
	transition: opacity var(--dur-veil) var(--ease-pair);
}
.veil::after {
	content: "";
	position: absolute;
	inset: 0;
	background-image: var(--grain);
	background-size: var(--grain-size) var(--grain-size);
	opacity: var(--grain-opacity);
	pointer-events: none;
}
.veil-stage {
	display: grid;
	place-items: center;
	min-block-size: 0;
}
.veil-stage img {
	max-inline-size: 100%;
	max-block-size: 100%;
	inline-size: auto;
	block-size: auto;
	display: block;
}
.veil-cap {
	font-family: var(--font-mono);
	font-size: var(--size-apparatus);
	line-height: var(--leading-tight);
	/* Приглушённая роль на чернилах объявлена блоком ролей, который завеса
	   теперь берёт целиком; здесь она пересчитывалась заново. */
	color: var(--muted);
	max-inline-size: var(--measure);
	display: grid;
	gap: var(--s1);
}
.veil-cap b { color: var(--paper); font-weight: 400; }
.veil-close {
	position: absolute;
	inset-block-start: var(--s3);
	inset-inline-end: var(--page-pad);
	font-family: var(--font-mono);
	font-size: var(--size-apparatus);
	letter-spacing: var(--tracking-label);
	color: var(--paper);
	background: none;
	border: 0;
	padding: var(--s2);
	cursor: pointer;
	min-block-size: 24px;
}
.veil-close::before { content: "■"; margin-inline-end: 0.6em; }
body.is-veiled { overflow: hidden; }

/* ── Печать ───────────────────────────────────────────────────────────────
   Многоразовое появление означает, что всё за пределами кадра стоит
   прозрачным — это не остаточное состояние, а нормальное. На бумаге кадра
   нет вовсе, и без этого блока страница выходит почти пустой: замер дал
   73 невидимых блока из 86. Печать снимает движение целиком и возвращает
   всё на место: маски заголовков, ступеньки перечней, кадры плит.

   Проверяется `.print.mjs` вместе с остальной печатью — это ровно тот
   класс отказа, который на экране не виден никогда. */
@media print {
	.js main > .row > div:not(.register) > *,
	.js main > .row > .register,
	.js main > .row > figure.plate,
	.js main > .row > .crumb,
	.js .reg {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
	.ln > i,
	.js main > .row .num > span { transform: none !important; }
	.js figure.plate .frame,
	.js figure.plate .frame img { transform: none !important; overflow: visible !important; }
	.js figure.plate .frame img { transform: none !important; }
	.js figure.plate figcaption { opacity: 1 !important; }
	.progress, .cursor-chip, .veil { display: none !important; }
}

/* ── Меньше движения ──────────────────────────────────────────────────────
   Уменьшается, а не выключается: содержимое, которое проявлял скрипт,
   обязано остаться на месте, иначе страница просто окажется пустой. Сдвиг
   и масштаб снимаются, прозрачность остаётся, длительности схлопываются
   почти в ноль — чтобы события завершения всё же срабатывали. */
@media (prefers-reduced-motion: reduce) {
	:root { --dur-reveal: 1ms; --dur-plate: 1ms; --dur-veil: 1ms; --stagger: 0ms; }
	.js .ln > i,
	.js .rv,
	.js figure.plate .frame img { transform: none !important; }
	.js figure.plate .frame,
	.js figure.plate .frame img { transform: none !important; }
	.cursor-chip { display: none; }
}

/* plaster:start ── собрано .plaster.mjs, руками не править ─────────────
   Штукатурка первого экрана главной. Холст лежит под титулом; грунт
   #definition и шапки становится прозрачным, только когда слой нарисовал
   первый кадр, и только на экране: в печати и без WebGL всё как было. */
.ground {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	inline-size: 100%;
	block-size: var(--ground-h, 100svh);
	z-index: var(--z-ground);
	pointer-events: none;
	opacity: 0;
	transition: opacity var(--dur-invert) var(--ease-out);
	/* Маске нужна только непрозрачность: цвет — любой непрозрачный токен,
	   литерала вне tokens.css здесь быть не может (.tokens.mjs).

	   Растушёвка идёт по плавной ступеньке (3t² − 2t³), а не по прямой:
	   прямая даёт видимые начало и конец полосы, и край читался дёшево
	   (владелец 25.09.2026: «сделай более плавным и не до 100%»). Восемь
	   опорных точек — у кривой нет ни излома на входе, ни на выходе. */
	/* Ступени непрозрачности — производные от токена и объявлены по
	   одной, как --muted и --rule в page.css; имя из одних
	   букв — так объявление узнаёт .tokens.mjs. */
	--veil-top: color-mix(in srgb, var(--ink) 96%, transparent);
	--veil-high: color-mix(in srgb, var(--ink) 84%, transparent);
	--veil-upper: color-mix(in srgb, var(--ink) 68%, transparent);
	--veil-half: color-mix(in srgb, var(--ink) 50%, transparent);
	--veil-lower: color-mix(in srgb, var(--ink) 32%, transparent);
	--veil-low: color-mix(in srgb, var(--ink) 16%, transparent);
	--veil-trace: color-mix(in srgb, var(--ink) 4%, transparent);
	--gf: var(--ground-fade, 16rem);
	--ground-mask: linear-gradient(to bottom,
		var(--ink) calc(100% - var(--gf)),
		var(--veil-top) calc(100% - var(--gf) * 0.875),
		var(--veil-high) calc(100% - var(--gf) * 0.75),
		var(--veil-upper) calc(100% - var(--gf) * 0.625),
		var(--veil-half) calc(100% - var(--gf) * 0.5),
		var(--veil-lower) calc(100% - var(--gf) * 0.375),
		var(--veil-low) calc(100% - var(--gf) * 0.25),
		var(--veil-trace) calc(100% - var(--gf) * 0.125),
		transparent);
	-webkit-mask-image: var(--ground-mask);
	mask-image: var(--ground-mask);
}
@media screen {
	:root[data-ground] .ground { opacity: 1; }
	:root[data-ground] #definition::before { background-color: transparent; }
	:root[data-ground] header.masthead { background-color: transparent; }
	:root[data-ground] header.masthead::before { opacity: var(--ground-mast, 0); }
	/* Издательский знак вдавлен в штукатурку (решение владельца 24.09.2026):
	   плоский знак прячется, только когда штамп уже в стене. */
	:root[data-stamp] .titlepage::before { opacity: 0; }
}
@media print { .ground { display: none; } }
/* plaster:end */
