/*
Theme Name: Neudahin
Theme URI: https://neudahin.com
Author: Alexander Neudahin
Author URI: https://neudahin.com
Description: Кастомная тема сайта-визитки neudahin.com. Только представление: шаблоны, секции, ассеты. Вся доменная логика (Заявки, Отзывы, Кейсы, Публикации, Свидетельства, Гранты) живёт в плагине neudahin-core — тема деградирует корректно без него.
Version: 0.3.0
Requires at least: 6.6
Tested up to: 6.9
Requires PHP: 8.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: neudahin
Tags: portfolio, one-column, custom-colors, translation-ready, block-styles
*/

/* -------------------------------------------------------------------------
   Шрифты. Самохостинг вместо внешнего CDN: никаких сторонних запросов —
   скорость, приватность и доступность. Вариативные woff2 из Fontsource
   (Inter 5.3.0, JetBrains Mono 5.3.0, лицензия OFL). На каждое семейство —
   два подмножества; unicode-range не даёт браузеру скачивать файл, если
   таких символов на странице нет (EN-версия не грузит кириллицу и наоборот).
   ---------------------------------------------------------------------- */

@font-face {
	font-family: "Inter";
	font-style: normal;
	font-display: swap;
	font-weight: 100 900;
	src: url("assets/fonts/inter-cyrillic-wght-normal.woff2") format("woff2");
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
	font-family: "Inter";
	font-style: normal;
	font-display: swap;
	font-weight: 100 900;
	src: url("assets/fonts/inter-latin-wght-normal.woff2") format("woff2");
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: "JetBrains Mono";
	font-style: normal;
	font-display: swap;
	font-weight: 100 800;
	src: url("assets/fonts/jetbrains-mono-cyrillic-wght-normal.woff2") format("woff2");
	unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
	font-family: "JetBrains Mono";
	font-style: normal;
	font-display: swap;
	font-weight: 100 800;
	src: url("assets/fonts/jetbrains-mono-latin-wght-normal.woff2") format("woff2");
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -------------------------------------------------------------------------
   Токены. Единственный источник правды — theme.json; здесь только короткие
   алиасы, чтобы не тащить var(--wp--preset--…) через весь файл.
   ---------------------------------------------------------------------- */

:root {
	/* Тема тёмная: `--paper` — фон страницы, `--ink` — текст. Роли токенов те же,
	   что были в светлой версии, поменялись только значения — поэтому перекраска
	   не потребовала править ни одного правила ниже.

	   Проверенный контраст (WCAG 2.x): ink/paper 15.87, ink/surface 14.52,
	   ink-soft/paper 7.17, accent/paper 7.05, accent/surface 6.44,
	   accent/accent-soft 6.14 — все выше 4.5 для текста;
	   line-strong/paper 3.69 и line-strong/surface 3.38 — выше 3 по 1.4.11. */
	--ink: var( --wp--preset--color--ink );
	--ink-soft: var( --wp--preset--color--ink-soft );
	--paper: var( --wp--preset--color--paper );
	--surface: var( --wp--preset--color--surface );
	--line: var( --wp--preset--color--line );
	/* Границы интерактивных элементов: `--line` даёт к фону контраст 1.30,
	   а WCAG 1.4.11 требует от них 3:1. Декоративные разделители остаются
	   на `--line` — к ним требование не относится. */
	--line-strong: var( --wp--preset--color--line-strong );
	/* Акцент — середина брендового градиента прежнего сайта (#3EA7FF → #8E72FF),
	   осветлённая до 4.5:1 на тёмном фоне. Сам градиент не переносится: цвет
	   везде сплошной. */
	--accent: var( --wp--preset--color--accent );
	--accent-soft: var( --wp--preset--color--accent-soft );

	--edge: var( --wp--preset--spacing--edge );
	--wide: var( --wp--style--global--wide-size, 72rem );

	--header-height: 4.5rem;

	/* Чтобы нативные элементы браузера — полосы прокрутки, автозаполнение,
	   выпадающие списки — не остались светлыми островами на тёмной странице. */
	color-scheme: dark;
}

/* -------------------------------------------------------------------------
   Сброс
   ---------------------------------------------------------------------- */

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

body {
	margin: 0;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

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

:focus-visible {
	outline: 2px solid var( --accent );
	outline-offset: 3px;
	border-radius: 2px;
}

/* Плавная прокрутка к якорям из меню (и кнопке «наверх» — она скроллит
 * через JS с той же проверкой). Цель якоря выведена из-под закреплённой
 * шапки правилами scroll-margin-top ниже. При prefers-reduced-motion
 * прокрутка остаётся мгновенной. */
@media ( prefers-reduced-motion: no-preference ) {
	html {
		scroll-behavior: smooth;
	}
}

/* -------------------------------------------------------------------------
   Раскладка
   ---------------------------------------------------------------------- */

.wrap {
	width: 100%;
	max-width: var( --wide );
	margin-inline: auto;
	padding-inline: var( --edge );
}

.site-main {
	flex: 1 0 auto;
}

/* Канва оборачивает шапку, содержимое и подвал в `.wp-site-blocks`
   (`wp-includes/template-canvas.php`). На PHP-пути такой обёртки нет, поэтому
   правило ниже относится только к блочной отрисовке; на PHP-пути оно не
   находит ни одного элемента.

   `flex: 1 0 auto` — чтобы обёртка занимала высоту окна и прижимала подвал
   вниз: без неё растягиваться внутри `body` нечему, и короткая страница
   получает подвал посреди экрана вместо низа. `display: flex` с колонкой —
   чтобы `.site-main` продолжал расти уже внутри обёртки. */
.wp-site-blocks {
	display: flex;
	flex-direction: column;
	flex: 1 0 auto;
}

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	background: var( --ink );
	color: var( --paper );
	padding: 0.75rem 1.25rem;
	text-decoration: none;
}

.skip-link:focus {
	left: 0;
}

/* Ссылка «к содержимому» на блочном пути печатается ядром
   (`_block_template_add_skip_link`, `wp-includes/block-template.php`): свою
   канва не подключает — она не печатает `header.php`, где та лежит. Ядро
   берёт цель из `id` нашей `<main>`, текст совпадает, но к классу `skip-link`
   добавляется `screen-reader-text`, а на фокус ядро задаёт свою плашку —
   светлую и со сдвигом 5px. Правило ниже возвращает ссылке оформление темы:
   специфичность та же, а `style.css` подключается позже инлайнового стиля
   ядра. На PHP-пути селектор не совпадает ни с одним элементом. */
.skip-link.screen-reader-text:focus {
	left: 0;
	top: 0;
	background: var( --ink );
	color: var( --paper );
	line-height: inherit;
	padding: 0.75rem 1.25rem;
}

/* -------------------------------------------------------------------------
   Шапка
   ---------------------------------------------------------------------- */

.site-header {
	border-bottom: 1px solid var( --line );
	background: var( --paper );
}

/* Шапка закреплена на всех страницах: и на главной, и на внутренних.

   И только там, где строка шапки заведомо помещается в один ряд: ниже 56rem
   меню переносится на вторую строку, и закреплённая шапка съедала бы половину
   экрана телефона. Фон непрозрачный, без размытия — контент под ней не
   просвечивает. */
@media ( min-width: 56rem ) {
	.site-header {
		position: fixed;
		inset-inline: 0;
		top: 0;
		z-index: 10;
	}

	.site-main {
		padding-top: var( --header-height );
	}

	/* Якорь из меню не должен приезжать под закреплённую шапку. Секции главной
	   приходят из содержимого страницы, а его ядро оборачивает в
	   `.wp-block-post-content` (`core/post-content`): прямых детей `<main>`
	   для них мало — отсюда второе правило. */
	.site-main > section[id],
	.wp-block-post-content > section[id] {
		scroll-margin-top: calc( var( --header-height ) + var( --wp--preset--spacing--sm ) );
	}

	/* У залогиненного администратора панель WordPress прибита к верху окна
	   и наезжала бы на шапку: уступаем ей. Посетители админ-бар не видят —
	   класса на body нет, правило не срабатывает. */
	.admin-bar .site-header {
		top: var( --wp-admin--admin-bar--height, 32px );
	}
}

.site-header__inner {
	min-height: var( --header-height );
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var( --wp--preset--spacing--md );
}

/* Марка набрана моноширинным: домен читается как адрес/командная строка, а
   не как логотип-надпись. Кегль и вес ниже заголовочных — шапка остаётся
   тише hero, которому принадлежит первое впечатление. */
.site-brand {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--base );
	font-weight: 550;
	letter-spacing: -0.01em;
	color: var( --ink );
	text-decoration: none;
}

.site-brand__mark {
	flex: none;
	width: auto;
	height: 1.35em;
	color: var( --accent );
}

.site-brand__dot {
	color: var( --accent );
}

.site-nav ul {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --wp--preset--spacing--md );
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-nav a {
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
	text-decoration: none;
}

.site-nav a:hover,
.site-nav .current-menu-item > a {
	color: var( --ink );
	text-decoration: underline;
	text-decoration-color: var( --accent );
	text-decoration-thickness: 1px;
	text-underline-offset: 0.45em;
}

/* Пункт, чей блок сейчас в зоне видимости, — подсвечивает site.js
   (scroll-spy). Отличается от наведения цветом: активный раздел читается
   как «где я», наведение — как «куда пойду». Правило идёт после :hover,
   чтобы акцентный цвет сохранялся и под курсором. */
.site-nav a.is-active {
	color: var( --accent );
	text-decoration: underline;
	text-decoration-color: var( --accent );
	text-decoration-thickness: 1px;
	text-underline-offset: 0.45em;
}

.site-header__right {
	display: flex;
	align-items: center;
	gap: var( --wp--preset--spacing--md );
}

/* Ниже 56rem строка шапки в один ряд не помещается: пункты меню начинали
   переноситься внутри своей колонки и наползали на логотип. Разносим на две
   строки — марка сверху, меню и переключатель языка под ней. Гамбургер не
   заводим: пунктов мало, двух строк хватает. */
@media ( max-width: 56rem ) {
	.site-header__inner {
		flex-wrap: wrap;
		align-items: baseline;
		padding-block: 0.85rem;
		gap: 0.6rem var( --wp--preset--spacing--sm );
	}

	.site-header__right {
		width: 100%;
		flex-wrap: wrap;
		justify-content: space-between;
		gap: 0.6rem var( --wp--preset--spacing--sm );
	}

	.site-nav ul {
		gap: 0.5rem var( --wp--preset--spacing--sm );
	}
}

/* --- Переключатель языка --- */

.lang__list {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 550;
	letter-spacing: 0.04em;
}

.lang__item + .lang__item::before {
	content: '/';
	margin-right: 0.5rem;
	color: var( --line );
}

.lang__link {
	color: var( --ink-soft );
	text-decoration: none;
}

.lang__link:hover {
	color: var( --ink );
}

.lang__current {
	color: var( --accent );
}

/* -------------------------------------------------------------------------
   Секции главной
   ---------------------------------------------------------------------- */

.section__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var( --wp--preset--spacing--sm );
	margin-bottom: var( --wp--preset--spacing--md );
}

/* Номера перед заголовками секций убраны: секции главной не образуют
   последовательности, а номер читается как утверждение порядка. */
.section__heading {
	margin: 0;
}

.section__lede {
	margin: 0.4rem 0 var( --wp--preset--spacing--md );
	max-width: 52ch;
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--lg );
}

/* Ссылка «Подробнее» — абзац с одной ссылкой внутри: ссылка блоком быть не
   может, а абзац в шапке секции не мешает — она и раньше была флексом
   с выравниванием по базовой линии. Оформление живёт на самой ссылке,
   а `margin: 0` — на абзаце: отступ по умолчанию сдвинул бы шапку секции. */
.section__link {
	margin: 0;
	font-size: var( --wp--preset--font-size--sm );
}

.section__link a {
	color: var( --ink-soft );
	text-decoration: none;
	border-bottom: 1px solid var( --line );
}

.section__link a:hover {
	color: var( --accent );
	border-color: var( --accent );
}

/* --- Первый экран --- */

/* «Миллиметровка» на фоне секции: линии с альфой 3.5% едва различимы, но
   дают глазу структуру — научный журнал, а не консоль разработчика. К низу
   сетка растворяется, чтобы не спорить с текстом идущих следом секций.
   `isolation` держит декор с отрицательным z-index внутри секции: без него
   он уехал бы под фон страницы. */
.hero {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	padding-block: var( --wp--preset--spacing--xl );
}

.hero::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-image:
		linear-gradient( color-mix( in srgb, var( --ink ) 3.5%, transparent ) 1px, transparent 1px ),
		linear-gradient( 90deg, color-mix( in srgb, var( --ink ) 3.5%, transparent ) 1px, transparent 1px );
	background-size: 2.75rem 2.75rem;
	-webkit-mask-image: linear-gradient( to bottom, black 50%, transparent 100% );
	mask-image: linear-gradient( to bottom, black 50%, transparent 100% );
	pointer-events: none;
}

.hero__inner {
	display: grid;
	grid-template-columns: minmax( 0, 1.4fr ) minmax( 0, 1fr );
	align-items: center;
	gap: var( --wp--preset--spacing--lg );
}

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

/* Надзаголовок — моноширинный «лабораторный» ярлык: широкий трекинг и капс
   считываются мгновенно, а моно созвучен метрике, чипам стека и нумерации
   секций — одна система мелких технических подписей. */
.hero__eyebrow {
	margin: 0 0 var( --wp--preset--spacing--sm );
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 450;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var( --accent );
}

/* Размер подобран по фактической метрике заголовка, а не на глаз: строка
   «Мультимодальный AI:» при xxxl (4.5rem) занимает ~788px и не лезет в
   текстовую колонку сетки (~588px на десктопе) — заголовок ломался на
   четыре строки с висячим предлогом. Потолок 3.25rem — максимум, при
   котором эта фраза держится одной строкой; наклон 2.2vw продолжает
   уменьшать её быстрее, чем сужается колонка, поэтому и на промежуточных
   ширинах перенос ложится в три строки: «Мультимодальный AI:» /
   «от научной статьи» / «до production» (предлог в начале строки, а не
   в конце). На мобильных минимум 2rem подобран под колонку 375px: при нём
   «статьи до production» умещается одной строкой, а при 2.25rem — уже нет,
   и предлог снова повисал в конце строки. `text-wrap: balance` подравнивает
   длины строк; браузеры без поддержки просто оставят обычные переносы. */
.hero__heading {
	margin: 0 0 var( --wp--preset--spacing--sm );
	font-size: clamp( 2rem, 1.25rem + 2.2vw, 3.25rem );
	text-wrap: balance;
}

.hero__lede {
	margin: 0;
	max-width: 48ch;
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--lg );
}

.hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --wp--preset--spacing--md );
	margin: var( --wp--preset--spacing--md ) 0 0;
}

.hero__secondary {
	color: var( --ink );
	text-decoration: none;
	border-bottom: 2px solid var( --accent );
	padding-bottom: 1px;
}

.hero__secondary:hover {
	color: var( --accent );
}

/* Свечение за портретом: акцент с альфой 12% и мягким радиальным спадом.
   Связывает светлый rim-контур снимка (реальная засветка от экрана на
   исходном фото) с палитрой страницы — силуэт «подсвечен из-за», а не
   обрезан от мира. Вылет за картинку больше по горизонтали: свечение
   должно охватывать фигуру, а не стоять пятном строго над ней. */
.hero__media {
	position: relative;
}

.hero__media::before {
	content: "";
	position: absolute;
	inset: -10% -22%;
	z-index: -1;
	background: radial-gradient( closest-side, color-mix( in srgb, var( --accent ) 12%, transparent ), transparent 72% );
	pointer-events: none;
}

/* Без рамки: в hero стоит вырезанный портрет на прозрачном фоне, и рамка
   очерчивала бы пустой прямоугольник вокруг фигуры. Нижний край растворяет
   маска на самом img, а не пиксели файла: фон страницы просвечивает сквозь
   прозрачную часть градиента, и портрет растёт из секции без жёсткой линии
   среза — плюс его можно перекроить без перегенерации картинки.

   Класс стоит на группе-картинке (`figure.wp-block-image`), а геометрия —
   на самом снимке: блок оборачивает `img` в `figure`, и `width` с `height`
   на обёртке оставили бы снимок прежнего размера. `margin: 0` снимает
   отступ, который `figure` получает от стилей ядра: в сетке первого экрана
   он сдвигал бы портрет вверх на его величину. */
.hero__photo {
	margin: 0;
}

.hero__photo img {
	width: 100%;
	max-height: 37rem;
	object-fit: contain;
	object-position: bottom;
	-webkit-mask-image: linear-gradient( to bottom, black 70%, transparent 99% );
	mask-image: linear-gradient( to bottom, black 70%, transparent 99% );
}

/* --- Цифры и факты --- */

/* На тёмном фоне одни только линии сверху и снизу почти не читаются, и полоса
   фактов теряется между hero и услугами. Ступенька фона возвращает ей вес
   ленты, не добавляя ни рамок, ни заливок остальным секциям. */
.stats {
	padding-block: var( --wp--preset--spacing--lg );
	border-block: 1px solid var( --line );
	background: var( --surface );
}

/* `auto-fill`, а не `auto-fit`: фактов может быть два, и растягивать их на всю
   ширину, оставляя между ними полполосы пустоты, не нужно — пустые колонки
   сохраняются, а факты выстраиваются слева. */
.stats__list {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( 11rem, 1fr ) );
	gap: var( --wp--preset--spacing--md );
	margin: 0;
}

.stats__item {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
}

/* Значения — моноширинным: «15+», «6», «13», «к.т.н.» читаются как показания
   прибора, а не как ещё один заголовок. Tabular-nums держит разрядность.

   Абзац внутри dt/dd: текст в блоках всегда абзац, и его отступ по умолчанию
   разъехался бы со строкой значения. */
.stats__value {
	margin: 0;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--xxl );
	font-weight: 550;
	letter-spacing: -0.02em;
	line-height: 1;
	font-variant-numeric: tabular-nums;
}

.stats__value > p,
.stats__label > p {
	margin: 0;
}

.stats__label {
	margin: 0;
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--sm );
	max-width: 22ch;
}

/* --- Услуги --- */

.services,
.formats,
.process,
.featured-cases,
.tech-stack {
	padding-block: var( --wp--preset--spacing--xl );
}

/* Колонка широкая намеренно: услуг четыре, и при узких колонках последняя
   оставалась одна во второй строке. На 24rem их помещается две — сетка
   раскладывается ровным прямоугольником.

   `min(24rem, 100%)`, а не голые `24rem`: на телефоне минимум колонки шире
   экрана, и сетка выпирала бы за край, добавляя странице горизонтальную
   прокрутку. Тот же приём — во всех сетках ниже с крупным минимумом. */
.services__list {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 24rem, 100% ), 1fr ) );
	gap: var( --wp--preset--spacing--md );
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Направления — карточки с волосяным бордером. Верхняя кромка толще и темнее
   остальных: она задаёт «крышку» карточки, на ховере окрашивается акцентом —
   единственный цветной отклик, без заливок и теней. Нумерацию направлений
   внутри карточек не заводим: она спорила бы с нумерацией секций, а две
   моноширинные цифры разных масштабов рядом — шум. */
.service {
	padding: var( --wp--preset--spacing--md );
	border: 1px solid var( --line );
	border-top: 2px solid var( --line-strong );
	background: var( --surface );
	transition: border-color 0.15s ease-in-out;
}

.service:hover {
	border-color: var( --line-strong );
	border-top-color: var( --accent );
}

.service__title {
	margin: 0 0 0.4rem;
	font-size: var( --wp--preset--font-size--xl );
}

.service__description {
	margin: 0;
	max-width: 46ch;
	color: var( --ink-soft );
}

/* --- Форматы работы --- */

/* Та же сетка карточек, что у направлений, и по той же причине: пунктов
   четыре, и на 24rem они раскладываются ровным прямоугольником, а
   `min( 24rem, 100% )` не даёт колонке выпирать за экран телефона. */
.formats__list {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 24rem, 100% ), 1fr ) );
	gap: var( --wp--preset--spacing--md );
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Карточка формата — тот же приём, что у `.service`: волосяной бордер,
   верхняя кромка толще и темнее, на ховере уходит в акцент. Нумерации
   внутри нет намеренно: у форматов нет порядка, а моноширинная цифра
   на карточке читалась бы как номер шага. */
.format {
	padding: var( --wp--preset--spacing--md );
	border: 1px solid var( --line );
	border-top: 2px solid var( --line-strong );
	background: var( --surface );
	transition: border-color 0.15s ease-in-out;
}

.format:hover {
	border-color: var( --line-strong );
	border-top-color: var( --accent );
}

.format__title {
	margin: 0 0 0.4rem;
	font-size: var( --wp--preset--font-size--xl );
}

.format__description {
	margin: 0;
	max-width: 46ch;
	color: var( --ink-soft );
}

/* Строка о первом шаге — не пятый формат, а то, что происходит до выбора
   формата. Она отвечает на вопрос «с чего начать», поэтому идёт после списка,
   набрана основным цветом текста и заметно отбита от карточек: это обещание
   порядка работы, а не сноска под ним. */
.formats__step {
	margin: var( --wp--preset--spacing--lg ) 0 0;
	max-width: 52ch;
	font-size: var( --wp--preset--font-size--lg );
}

/* --- Как мы работаем --- */

.process__list {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 15rem, 1fr ) );
	gap: var( --wp--preset--spacing--md );
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: step;
}

/* Линия сверху — тот же приём, что у `.service`, но тоньше: шаги подчинены
   услугам, а не спорят с ними за вес. */
.process__step {
	counter-increment: step;
	padding-top: var( --wp--preset--spacing--sm );
	border-top: 1px solid var( --line-strong );
}

/* Номер шагам, в отличие от услуг, нужен по смыслу — это последовательность.
   Но он остаётся подписью к линии кеглем мелкого текста, а не бейджем
   «01 / 06» во весь блок. */
.process__step::before {
	content: counter( step, decimal-leading-zero );
	display: block;
	margin-bottom: 0.35rem;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 450;
	font-variant-numeric: tabular-nums;
	color: var( --accent );
}

.process__title {
	margin: 0 0 0.4rem;
	font-size: var( --wp--preset--font-size--lg );
}

.process__description {
	margin: 0;
	color: var( --ink-soft );
}

/* --- Стек технологий --- */

.tech-stack {
	border-top: 1px solid var( --line );
}

.tech-stack__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.tech-stack__item a {
	display: inline-block;
	padding: 0.3rem 0.7rem;
	border: 1px solid var( --line-strong );
	background: var( --surface );
	color: var( --ink );
	text-decoration: none;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--sm );
	transition: border-color 0.15s ease-in-out, color 0.15s ease-in-out;
}

.tech-stack__item a:hover {
	border-color: var( --accent );
	color: var( --accent );
}

/* --- Основание: наука одной секцией --- */

/* Секция заняла место трёх научных витрин и отделяется от витрины кейсов
   той же волосяной линией, что стек и форма ниже. */
.foundation {
	padding-block: var( --wp--preset--spacing--xl );
	border-top: 1px solid var( --line );
}

/* Строки-регалии — та же колонка, что у публикаций и грантов в архивах:
   длинная библиографическая строка читается быстрее на 52rem, чем врасплох
   по всему экрану. Маркеры списка не нужны: строки и так разделены линиями,
   а точка перед каждой — шум. */
.foundation__list {
	margin: 0;
	padding: 0;
	max-width: 52rem;
	list-style: none;
}

/* Волосяная линия между строками — как у грантов в архиве: строки держатся
   вместе, но не сливаются. */
.foundation__row + .foundation__row {
	border-top: 1px solid var( --line );
}

.foundation__row {
	padding-block: var( --wp--preset--spacing--sm );
}

/* Ссылка на архив — тем же приёмом, что «Подробнее» у кейсов: мягкий цвет,
   волосяное подчёркивание, акцент на ховере. `nowrap` не даёт ей оторваться
   от своей строки при переносе. */
.foundation__link {
	color: var( --ink-soft );
	text-decoration: none;
	border-bottom: 1px solid var( --line );
	white-space: nowrap;
}

.foundation__link:hover {
	color: var( --accent );
	border-color: var( --accent );
}

/* -------------------------------------------------------------------------
   Шапка архива
   ---------------------------------------------------------------------- */

.archive-head {
	padding-block: var( --wp--preset--spacing--lg ) var( --wp--preset--spacing--md );
}

.archive-head__title {
	margin: 0 0 var( --wp--preset--spacing--xs );
}

.archive-head__lede {
	margin: 0;
	max-width: 52ch;
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--lg );
}

.archive-empty {
	padding-block: var( --wp--preset--spacing--lg );
	color: var( --ink-soft );
}

/* -------------------------------------------------------------------------
   Кейсы: сетка и карточка
   ---------------------------------------------------------------------- */

.case-grid {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( min( 20rem, 100% ), 1fr ) );
	gap: var( --wp--preset--spacing--lg ) var( --wp--preset--spacing--md );
	padding-block: var( --wp--preset--spacing--md ) var( --wp--preset--spacing--xl );
}

.case-card {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
}

.case-card__link {
	color: inherit;
	text-decoration: none;
	display: block;
}

.case-card__media {
	margin-bottom: 0.9rem;
	border: 1px solid var( --line );
	background: var( --surface );
	aspect-ratio: 16 / 10;
	overflow: hidden;
}

.case-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.case-card__title {
	margin: 0;
	font-size: var( --wp--preset--font-size--xl );
}

.case-card__link:hover .case-card__title {
	color: var( --accent );
}

.case-card__excerpt {
	margin: 0;
	color: var( --ink-soft );
}

.case-card__stack,
.case__stack {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin: 0.2rem 0 0;
	padding: 0;
	list-style: none;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
}

.case-card__stack li,
.case__stack li {
	padding: 0.1rem 0.5rem;
	border: 1px solid var( --line );
}

.case__stack a {
	color: inherit;
	text-decoration: none;
}

.case__stack a:hover {
	color: var( --accent );
}

/* --- Отдельный кейс --- */

.case__head {
	padding-block: var( --wp--preset--spacing--lg ) var( --wp--preset--spacing--md );
}

.case__back {
	margin: 0 0 var( --wp--preset--spacing--sm );
	font-size: var( --wp--preset--font-size--sm );
}

.case__back a {
	color: var( --ink-soft );
	text-decoration: none;
}

.case__back a:hover {
	color: var( --accent );
}

.case__title {
	margin: 0 0 var( --wp--preset--spacing--xs );
	max-width: 22ch;
}

.case__lede {
	margin: 0 0 var( --wp--preset--spacing--sm );
	max-width: 54ch;
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--lg );
}

.case__links {
	display: flex;
	flex-wrap: wrap;
	gap: var( --wp--preset--spacing--sm );
	margin: var( --wp--preset--spacing--sm ) 0 0;
}

.case__link {
	color: var( --ink );
	text-decoration: none;
	border-bottom: 2px solid var( --accent );
	padding-bottom: 1px;
}

.case__link:hover {
	color: var( --accent );
}

.case__media {
	margin-bottom: var( --wp--preset--spacing--md );
}

.case__media img {
	width: 100%;
	border: 1px solid var( --line );
}

.case__body {
	padding-bottom: var( --wp--preset--spacing--xl );
}

/* По левому краю, как и шапка кейса: центрированная колонка визуально
   отъезжала от заголовка. */
.case__body > * {
	max-width: 44rem;
}

/* Подписи «Задача» и «Результат» — тем же мелким капслоком, что подписи
   контактов: это ярлыки к тексту, а не ещё два заголовка, спорящих с названием
   кейса. Обоих блоков может не быть — каждый выводится только при значении. */
.case__challenge-title,
.case__result-title {
	margin: 0 0 0.35rem;
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 550;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var( --ink-soft );
}

.case__challenge {
	margin-top: var( --wp--preset--spacing--md );
	max-width: 54ch;
}

.case__challenge-text {
	margin: 0;
	white-space: pre-line;
}

.case__result {
	margin-top: var( --wp--preset--spacing--md );
	padding-top: var( --wp--preset--spacing--sm );
	border-top: 1px solid var( --line );
}

.case__result-text {
	margin: 0;
	font-size: var( --wp--preset--font-size--xl );
	letter-spacing: -0.01em;
}

/* -------------------------------------------------------------------------
   Обычная страница (юридические документы)
   ---------------------------------------------------------------------- */

.page__head {
	padding-block: var( --wp--preset--spacing--lg ) var( --wp--preset--spacing--md );
}

.page__title {
	margin: 0;
	max-width: 22ch;
}

.page__body {
	padding-bottom: var( --wp--preset--spacing--xl );
}

/* По левому краю, как и шапка страницы: та же строка чтения, что и в теле
   Кейса. */
.page__body > * {
	max-width: 44rem;
}

/* Gutenberg-блоки приходят без собственных отступов между собой. */
.page__body > * + * {
	margin-top: var( --wp--preset--spacing--sm );
}

/* Документ из десяти разделов, а не маркетинговый блок: шапочные кегли h2/h3
   из theme.json рассчитаны на заголовки секций главной и в правовом тексте
   дробят чтение — здесь заголовкам достаточно шаг ниже. */
.page__body h2 {
	margin-top: var( --wp--preset--spacing--md );
	font-size: var( --wp--preset--font-size--xl );
}

.page__body h3 {
	margin-top: var( --wp--preset--spacing--sm );
	font-size: var( --wp--preset--font-size--lg );
}

.page__body ul {
	margin: 0;
	padding-left: 1.25rem;
}

/* -------------------------------------------------------------------------
   Отзывы
   ---------------------------------------------------------------------- */

.review-grid {
	display: grid;
	grid-template-columns: repeat( auto-fill, minmax( min( 22rem, 100% ), 1fr ) );
	gap: var( --wp--preset--spacing--md );
	padding-block: var( --wp--preset--spacing--md ) var( --wp--preset--spacing--lg );
}

.review {
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
	margin: 0;
	padding: var( --wp--preset--spacing--md );
	border: 1px solid var( --line );
	background: var( --surface );
}

/* Избранный отзыв выделен ребром, а не цветной заливкой: цвет тут
   ничего не значил бы, а полоса читается как «вот это важное». */
.review--featured {
	border-left: 3px solid var( --accent );
}

.review__rating {
	margin: 0;
	color: var( --accent );
	letter-spacing: 0.1em;
}

.review__text {
	margin: 0;
	quotes: none;
	white-space: pre-line;
}

.review__author {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	margin-top: auto;
	padding-top: 0.5rem;
	border-top: 1px solid var( --line );
	font-size: var( --wp--preset--font-size--sm );
}

.review__name {
	font-weight: 600;
}

.review__position {
	color: var( --ink-soft );
}

.review-form-section {
	padding-block: var( --wp--preset--spacing--lg ) var( --wp--preset--spacing--xl );
	border-top: 1px solid var( --line );
	scroll-margin-top: var( --wp--preset--spacing--md );
}

.review-form-section__inner {
	max-width: 46rem;
}

/* --- Шкала оценки --- */

.rating {
	border: 0;
	margin: 0;
	padding: 0;
}

.rating legend {
	padding: 0;
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 550;
}

.rating__scale {
	display: flex;
	gap: 0.4rem;
	margin-top: 0.4rem;
}

/* Прозрачный `input` спозиционирован абсолютно — без этого он отсчитывался бы
   от корня страницы и уезжал за правый край, добавляя всей странице
   горизонтальную прокрутку. */
.rating__option {
	position: relative;
}

.rating__option input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
}

.rating__option span {
	display: grid;
	place-items: center;
	width: 2.6rem;
	height: 2.6rem;
	border: 1px solid var( --line-strong );
	border-radius: 2px;
	background: var( --surface );
	cursor: pointer;
	font-variant-numeric: tabular-nums;
}

.rating__option input:checked + span {
	border-color: var( --ink );
	background: var( --ink );
	color: var( --paper );
}

.rating__option input:focus-visible + span {
	outline: 2px solid var( --accent );
	outline-offset: 2px;
}

/* -------------------------------------------------------------------------
   Гранты
   ---------------------------------------------------------------------- */

.grants {
	padding-block: var( --wp--preset--spacing--md ) var( --wp--preset--spacing--xl );
}

/* Ширину ограничивает группа, а не сам .wrap: иначе колонка центрировалась бы
   отдельно от заголовка страницы и визуально от него отъезжала. */
.grant-group {
	max-width: 52rem;
}

.grant-group + .grant-group {
	margin-top: var( --wp--preset--spacing--lg );
}

.grant-group__title {
	margin: 0 0 var( --wp--preset--spacing--sm );
	padding-bottom: 0.4rem;
	border-bottom: 1px solid var( --line );
	font-size: var( --wp--preset--font-size--xl );
}

.grant-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.grant {
	display: flex;
	gap: var( --wp--preset--spacing--sm );
	padding-block: 0.7rem;
}

.grant + .grant {
	border-top: 1px solid var( --line );
}

.grant__year {
	flex: 0 0 3.5rem;
	font-variant-numeric: tabular-nums;
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
	padding-top: 0.15rem;
}

.grant__body {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	min-width: 0;
	overflow-wrap: anywhere;
}

.grant__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.3rem 0.8rem;
}

.grant__title a {
	color: inherit;
	text-decoration: none;
	border-bottom: 1px solid var( --line );
}

.grant__title a:hover {
	color: var( --accent );
	border-color: var( --accent );
}

.grant__status {
	padding: 0.05rem 0.45rem;
	border: 1px solid var( --line-strong );
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
	white-space: nowrap;
}

/* Полученный грант — единственный статус с победной окраской. */
.grant__status--received {
	border-color: var( --accent );
	color: var( --accent );
}

/* Поданная заявка — ожидание решением, а не результат: бейдж намеренно
   нейтральный, пунктирная рамка читается как «не финализировано». */
.grant__status--applied {
	border-style: dashed;
	background: var( --surface );
}

.grant__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.15rem 0.5rem;
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
}

.grant__num {
	font-family: var( --wp--preset--font-family--mono );
}

/* -------------------------------------------------------------------------
   Публикации
   ---------------------------------------------------------------------- */

.publications {
	padding-block: var( --wp--preset--spacing--md ) var( --wp--preset--spacing--xl );
}

/* Ширину ограничивает группа, а не сам .wrap: иначе колонка центрировалась бы
   отдельно от заголовка страницы и визуально от него отъезжала. */
.publication-group {
	max-width: 52rem;
}

.publication-group + .publication-group {
	margin-top: var( --wp--preset--spacing--lg );
}

.publication-group__title {
	margin: 0 0 var( --wp--preset--spacing--sm );
	padding-bottom: 0.4rem;
	border-bottom: 1px solid var( --line );
	font-size: var( --wp--preset--font-size--xl );
}

.publication-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Моноширинный шрифт — осознанное исключение, как .tech-stack__item:
   библиографическая строка читается по символам, а не по абзацу. */
.publication {
	display: flex;
	gap: var( --wp--preset--spacing--sm );
	padding-block: 0.7rem;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--sm );
	line-height: 1.6;
}

.publication + .publication {
	border-top: 1px solid var( --line );
}

.publication__year {
	flex: 0 0 3.5rem;
	font-variant-numeric: tabular-nums;
	color: var( --ink-soft );
	padding-top: 0.15rem;
}

.publication__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.3rem;
	min-width: 0;
	overflow-wrap: anywhere;
}

.publication__line a {
	color: inherit;
	text-decoration: none;
	border-bottom: 1px solid var( --line );
}

.publication__line a:hover {
	color: var( --accent );
	border-color: var( --accent );
}

.publication__vak {
	padding: 0.05rem 0.45rem;
	border: 1px solid var( --line-strong );
	color: var( --ink-soft );
}

/* -------------------------------------------------------------------------
   Форма заявки
   ---------------------------------------------------------------------- */

.zayavka {
	padding-block: var( --wp--preset--spacing--xl );
	border-top: 1px solid var( --line );
	scroll-margin-top: var( --wp--preset--spacing--md );
}

/* Колонка прижата к левому краю контентной области, а не центрирована.
   Ширину ограничивает вложенный блок, а не сам .wrap: иначе колонка
   центрировалась бы отдельно от шапки и остальных секций. */
.zayavka__inner {
	max-width: 46rem;
}

.zayavka__title {
	margin: 0 0 var( --wp--preset--spacing--xs );
}

/* Без ограничения по ширине: подзаголовок занимает всю колонку, вровень
   с полями формы под ним. */
.zayavka__lede {
	margin: 0 0 var( --wp--preset--spacing--md );
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--lg );
}

/* Вторая дверь рядом с формой: короткая строка со ссылкой на Telegram.
   Подтянута к лиду отрицательным отступом — это продолжение вступления,
   а не отдельный блок. Слова и адрес правятся в «Общих данных», ник —
   в настройках; ник пуст — строки нет вовсе (ADR 0012). */
.zayavka__telegram {
	margin: calc( -1 * var( --wp--preset--spacing--sm ) ) 0 var( --wp--preset--spacing--md );
	color: var( --ink-soft );
}

.zayavka__telegram a {
	color: var( --ink-soft );
	text-decoration: underline;
	text-decoration-color: var( --accent );
	text-decoration-thickness: 1px;
	text-underline-offset: 0.35em;
}

.zayavka__telegram a:hover {
	color: var( --accent );
}

.zayavka__alert {
	margin: 0 0 var( --wp--preset--spacing--md );
	padding: 0.75rem 1rem;
	border: 1px solid var( --accent );
	background: var( --accent-soft );
	color: var( --accent );
}

.zayavka__done {
	padding-block: var( --wp--preset--spacing--md );
	border-left: 3px solid var( --accent );
	padding-left: var( --wp--preset--spacing--md );
}

.zayavka__done p {
	margin: 0;
	max-width: 48ch;
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--lg );
}

/* Сайты на CMS и интеграции 1С — к студии. Строка стоит под формой в обоих
   состояниях секции: после отправки человеку тоже есть куда пойти. Слова,
   подпись и адрес — из «Общих данных». */
.zayavka__studio {
	margin: var( --wp--preset--spacing--md ) 0 0;
	max-width: 48ch;
	color: var( --ink-soft );
	font-size: var( --wp--preset--font-size--sm );
}

.zayavka__studio a {
	color: var( --ink-soft );
	text-decoration: underline;
	text-decoration-color: var( --accent );
	text-decoration-thickness: 1px;
	text-underline-offset: 0.35em;
}

.zayavka__studio a:hover {
	color: var( --accent );
}

/* --- Поля --- */

.zayavka-form {
	display: grid;
	grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	gap: var( --wp--preset--spacing--md ) var( --wp--preset--spacing--sm );
}

@media ( max-width: 40rem ) {
	.zayavka-form {
		grid-template-columns: minmax( 0, 1fr );
	}
}

.field {
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
}

.field--wide,
.zayavka-form__submit,
.zayavka-form__trap {
	grid-column: 1 / -1;
}

.field label {
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 550;
}

.field__required {
	color: var( --accent );
}

.field input,
.field select,
.field textarea {
	width: 100%;
	padding: 0.7rem 0.85rem;
	border: 1px solid var( --line-strong );
	border-radius: 2px;
	background: var( --surface );
	color: inherit;
	font: inherit;
	font-size: var( --wp--preset--font-size--base );
}

.field textarea {
	resize: vertical;
	min-height: 9rem;
}

/* Нативная стрелка select даже при color-scheme: dark рисуется светлым
   виджетом другой высоты. Рисуем свою — в цвете вторичного текста, как у
   подписей полей. */
.field select {
	appearance: none;
	padding-right: 2.4rem;
	background-image: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%23A0A0AD' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E" );
	background-repeat: no-repeat;
	background-position: right 0.85rem center;
	cursor: pointer;
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
	outline: 2px solid var( --accent );
	outline-offset: 1px;
	border-color: transparent;
}

.field--invalid input,
.field--invalid select,
.field--invalid textarea {
	border-color: var( --accent );
}

.field__error {
	font-size: var( --wp--preset--font-size--sm );
	color: var( --accent );
}

.field__hint {
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
}

.field input[type="file"] {
	padding: 0.55rem 0.6rem;
	background: transparent;
	border-style: dashed;
	font-size: var( --wp--preset--font-size--sm );
	cursor: pointer;
}

.field input[type="file"]::file-selector-button {
	margin-right: 0.75rem;
	padding: 0.4rem 0.9rem;
	border: 1px solid var( --line-strong );
	border-radius: 2px;
	background: var( --paper );
	color: inherit;
	font: inherit;
	font-size: var( --wp--preset--font-size--sm );
	cursor: pointer;
}

.field input[type="file"]::file-selector-button:hover {
	border-color: var( --ink );
}

/* Согласие: чекбокс и подпись в одну строку. Ссылки на документы — под
   подписью, но вне `label`: клик по ссылке внутри переключал бы галочку. */
.field--consent label {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 0.6rem;
}

.field--consent .field__consent-text {
	min-width: 0;
}

/* Стандартное `.field input` растягивает поле на всю колонку — для
   галочки это неверно, держим её фиксированного размера. */
.field--consent input[type="checkbox"] {
	flex: 0 0 auto;
	width: 1.15rem;
	height: 1.15rem;
	margin: 0;
	padding: 0;
	accent-color: var( --accent );
}

.field__consent-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem 1rem;
	font-size: var( --wp--preset--font-size--sm );
}

.zayavka-form__submit {
	margin: 0;
}

.button {
	display: inline-block;
	padding: 0.85rem 1.75rem;
	border: 1px solid var( --ink );
	border-radius: 2px;
	background: var( --ink );
	color: var( --paper );
	font: inherit;
	font-size: var( --wp--preset--font-size--base );
	font-weight: 550;
	/* Глобальное подчёркивание ссылок из theme.json на сплошной кнопке читается
	   как ошибка вёрстки — форма и так говорит, что по этому можно кликнуть. */
	text-decoration: none;
	cursor: pointer;
}

.button:hover {
	background: var( --accent );
	border-color: var( --accent );
}

/* Вторичная кнопка — та же геометрия, обратный тон: рамка вместо заливки.
   Стоит рядом с главной (первый экран: форма и Telegram), поэтому не должна
   спорить с ней за внимание. Приём не новый: так же одета кнопка
   cookie-баннера — «рамка `line-strong`, прозрачный фон, акцент на наведении». */
.button--secondary {
	background: transparent;
	border-color: var( --line-strong );
	color: var( --ink );
}

.button--secondary:hover {
	background: transparent;
	border-color: var( --accent );
	color: var( --accent );
}

/* -------------------------------------------------------------------------
   Подвал
   ---------------------------------------------------------------------- */

.site-footer {
	margin-top: var( --wp--preset--spacing--xl );
	border-top: 1px solid var( --line );
	padding-block: var( --wp--preset--spacing--lg );
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
	/* Пункт «Контакты» ведёт сюда: правило для `.site-main > section[id]` до
	   подвала не достаёт, а под закреплённой шапкой якорь без этого приезжает
	   под неё. */
	scroll-margin-top: calc( var( --header-height ) + var( --wp--preset--spacing--sm ) );
}

/* --- Контакты --- */

.contacts__list {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 14rem, 1fr ) );
	gap: var( --wp--preset--spacing--md );
	margin: 0;
	padding: 0;
	list-style: none;
}

.contacts__item {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
}

.contacts__label {
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 550;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var( --ink-soft );
}

/* Значения — моноширинным: контактные строки — «технические», их естественно
   читать посимвольно. Кегль lg вместо xl: моно шире гротеска,
   и длинная строка в узкой колонке разрывалась бы посередине. */
.contacts__value {
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--lg );
	color: var( --ink );
	text-decoration: none;
}

.contacts__value:hover {
	color: var( --accent );
}

.site-footer__contacts + .site-footer__inner {
	margin-top: var( --wp--preset--spacing--lg );
	padding-top: var( --wp--preset--spacing--md );
	border-top: 1px solid var( --line );
}

.site-footer__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var( --wp--preset--spacing--sm );
}

.site-footer p {
	margin: 0;
}

/* --- Юридические ссылки --- */

/* Мелкая строка под копирайтом: ссылки переносятся, когда на телефоне не
   хватает ширины, и остаются читаемыми в одну-две строки. */
.site-footer__legal {
	margin-top: var( --wp--preset--spacing--sm );
}

.site-footer__legal-list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem var( --wp--preset--spacing--sm );
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-footer__legal-list a {
	color: var( --ink-soft );
	text-decoration: underline;
	text-underline-offset: 2px;
}

.site-footer__legal-list a:hover {
	color: var( --accent );
}

/* На страницах не на русском: документы существуют только в русской редакции. */
.site-footer__legal-note {
	margin-top: 0.5rem;
	color: var( --ink-soft );
}

/* --- Ссылка на студию --- */

/* Кнопка ядра здесь несёт только ссылку: вид правовой строки, без плашки.
   Ядро рисует `.wp-block-button__link` фоном, отступами и скруглением —
   обнуляем их, оставляя типографику подвала. Подпись и адрес приходят
   связкой `neudahin/site` из «Общих данных». */
.site-footer__studio {
	margin-top: 0.5rem;
}

.site-footer__studio .wp-block-button {
	display: block;
	margin: 0;
}

.site-footer__studio .wp-block-button__link {
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	color: var( --ink-soft );
	font: inherit;
	font-size: var( --wp--preset--font-size--sm );
	text-decoration: underline;
	text-decoration-color: var( --accent );
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
}

.site-footer__studio .wp-block-button__link:hover {
	background: none;
	color: var( --accent );
}

/* -------------------------------------------------------------------------
   Кнопка «наверх»
   ---------------------------------------------------------------------- */

/* Видимость ведёт site.js через класс .is-visible; в разметке кнопка несёт
   атрибут hidden — без JS её нет ни глазам, ни клавиатуре, ни скринридеру.
   Правило [hidden] нужно явно: display из author-CSS перебивал бы
   пользовательский стиль ядра. */
.to-top {
	position: fixed;
	right: max( 1.25rem, env( safe-area-inset-right ) );
	bottom: max( 1.25rem, env( safe-area-inset-bottom ) );
	z-index: 10;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	border: 1px solid var( --line-strong );
	border-radius: 50%;
	background: var( --paper );
	color: var( --ink-soft );
	cursor: pointer;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transform: translateY( 0.75rem );
	transition:
		opacity 0.25s ease,
		transform 0.25s ease,
		visibility 0.25s,
		color 0.15s ease,
		border-color 0.15s ease;
}

.to-top[hidden] {
	display: none;
}

.to-top.is-visible {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transform: none;
}

.to-top:hover {
	color: var( --accent );
	border-color: var( --accent );
}

/* -------------------------------------------------------------------------
   Cookie-баннер
   ---------------------------------------------------------------------- */

/* Тонкая информирующая полоса внизу экрана: согласие она не собирает и
   счётчик Метрики не блокирует (docs/legal/03, раздел 5.2 — решение
   владельца). Видима по умолчанию; скрытие ведёт site.js после клика или
   при найденной в localStorage метке закрытого уведомления. */
.cookie-notice {
	position: fixed;
	inset-inline: 0;
	bottom: 0;
	z-index: 30;
	border-top: 1px solid var( --line );
	background: var( --paper );
	padding-block: 0.65rem;
	/* Нижний отступ с запасом на жестовую зону мобильных браузеров. */
	padding-block-end: max( 0.65rem, env( safe-area-inset-bottom ) );
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
}

.cookie-notice__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem var( --wp--preset--spacing--sm );
}

.cookie-notice__text {
	margin: 0;
}

.cookie-notice__text a {
	color: var( --accent );
	text-underline-offset: 2px;
}

/* Компактный родственник .button: та же рамка, радиус и поведение при
   наведении, меньший кегль — баннер не должен весить больше строки. */
.cookie-notice__accept {
	flex: 0 0 auto;
	padding: 0.45rem 1.1rem;
	border: 1px solid var( --line-strong );
	border-radius: 2px;
	background: transparent;
	color: var( --ink );
	font: inherit;
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 550;
	cursor: pointer;
}

.cookie-notice__accept:hover {
	border-color: var( --accent );
	color: var( --accent );
}

/* Пока баннер открыт, «наверх» поднимается над полосой, чтобы не прятаться
   под ней и не мешать кнопке «Понятно». В браузерах без :has() остаётся
   прежнее поведение: до закрытия баннера кнопка уходит под него. */
body:has( .cookie-notice:not( [hidden] ) ) .to-top {
	bottom: calc( max( 1.25rem, env( safe-area-inset-bottom ) ) + 3.5rem );
}

/* На телефоне текст занимает всю строку, кнопка переносится под него. */
@media ( max-width: 40rem ) {
	.cookie-notice__inner {
		flex-direction: column;
		align-items: flex-start;
	}
}

/* -------------------------------------------------------------------------
   Свидетельства
   ---------------------------------------------------------------------- */

.certificates {
	display: grid;
	/* auto-fill, а не auto-fit: карточек может быть три, и растягивать их на
	   всю ширину не нужно — узкая колонка читается быстрее широкой. */
	grid-template-columns: repeat( auto-fill, minmax( min( 19rem, 100% ), 1fr ) );
	gap: var( --wp--preset--spacing--lg ) var( --wp--preset--spacing--md );
	margin: 0;
	padding-block: var( --wp--preset--spacing--md ) var( --wp--preset--spacing--xl );
	list-style: none;
}

.certificate {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	min-width: 0;
}

/* Превью — ссылка на полный размер: без JS она открывает изображение в новой
   вкладке, с JS клик перехватывает лайтбокс. Рамка и фон — как у обложки
   кейса; скан живёт в собственной пропорции, без кропа под сетку. */
.certificate__media {
	border: 1px solid var( --line );
	background: var( --surface );
}

.certificate__media img {
	width: 100%;
	height: auto;
}

.certificate__media:hover {
	border-color: var( --accent );
}

/* Номер — визитная карточка свидетельства: моноширинный и крупный, как
   показания приборов в блоке цифр. */
.certificate__number {
	margin: 0.3rem 0 0;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--xl );
	line-height: 1.2;
	font-weight: 450;
	font-variant-numeric: tabular-nums;
	overflow-wrap: anywhere;
}

/* Название программы — обычный заголовок карточки, а не шапочный кегль
   темы: рядом с крупным номером 2.5rem спорили бы с ним. */
.certificate__title {
	margin: 0;
	font-size: var( --wp--preset--font-size--lg );
	font-weight: 550;
}

.certificate__owner,
.certificate__authors {
	margin: 0;
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
}

/* Даты — «технические» строки, как контакты в подвале: моноширинные,
   табличные цифры. */
.certificate__dates {
	display: flex;
	flex-wrap: wrap;
	gap: 0.15rem 1rem;
	margin: 0;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
}

/* Пометка к авторам — тот же тельняшечный тег, что «ВАК» у публикаций. */
.certificate__coauthored {
	padding: 0.05rem 0.45rem;
	border: 1px solid var( --line-strong );
	color: var( --ink-soft );
}

/* Действия прижаты к низу карточки: ряд карточек разной высоты получает
   ровную линию кнопок. */
.certificate__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: auto 0 0;
	padding-top: 0.7rem;
}

.certificate__action {
	display: inline-block;
	padding: 0.45rem 1.1rem;
	border: 1px solid var( --line-strong );
	border-radius: 2px;
	background: transparent;
	color: var( --ink );
	font: inherit;
	font-size: var( --wp--preset--font-size--sm );
	font-weight: 550;
	text-decoration: none;
	cursor: pointer;
}

.certificate__action:hover {
	border-color: var( --accent );
	color: var( --accent );
}

/* -------------------------------------------------------------------------
   Лайтбокс свидетельств
   ---------------------------------------------------------------------- */

/* Диалог собирает site.js: без JS его не существует, превью остаётся обычной
   ссылкой на изображение. Esc закрывается нативно, затемнение — ::backdrop.
   Ширина не задаётся вовсе: диалог обжимается по картинке, которую держат
   viewport-ограничения. */
.certificate-lightbox {
	max-width: calc( 100vw - 2rem );
	padding: 1rem;
	border: 1px solid var( --line-strong );
	background: var( --paper );
	color: var( --ink );
}

.certificate-lightbox::backdrop {
	background: color-mix( in srgb, #000 70%, transparent );
}

.certificate-lightbox__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var( --wp--preset--spacing--sm );
	margin: 0 0 0.7rem;
}

.certificate-lightbox__caption {
	min-width: 0;
	font-family: var( --wp--preset--font-family--mono );
	font-size: var( --wp--preset--font-size--sm );
	color: var( --ink-soft );
	overflow-wrap: anywhere;
}

.certificate-lightbox__close {
	flex: 0 0 auto;
	padding: 0.1rem 0.6rem;
	border: 1px solid var( --line-strong );
	border-radius: 2px;
	background: transparent;
	color: var( --ink );
	font: inherit;
	font-size: var( --wp--preset--font-size--lg );
	line-height: 1.2;
	cursor: pointer;
}

.certificate-lightbox__close:hover {
	border-color: var( --accent );
	color: var( --accent );
}

/* Скан живёт в собственной пропорции; рамка отделяет белое поле документа
   от тёмного фона диалога. */
.certificate-lightbox__image {
	max-width: 100%;
	max-height: 80vh;
	width: auto;
	height: auto;
	border: 1px solid var( --line );
}
