/* ===========================================================
   Pogosov studio — база: токены, типографика, каркас, кнопки,
   шапка и меню, форма, диалоги, cookie-плашка, появление
   при прокрутке.

   Движение: только transform / opacity / clip-path. Исключения — рост высоты карточек FAQ
   (css/home.css): карточка физически раздвигает соседей, и мозаика манифеста: её клетки рисует
   <canvas> по прогрессу прокрутки (js/manifest.js), а слова там проявляются через opacity.
   Кривые — три токена ниже, своих не изобретаем (исключение — --faq-ease у FAQ, см. css/home.css).
   prefers-reduced-motion: остаётся мягкое появление (opacity),
   пропадает сдвиг, маски и счётчики.
   =========================================================== */

:root {
	color-scheme: light;

	/* палитра: тёплая бумага + чернила + один акцент */
	--paper: #FAF9F7;
	--paper-2: #F3F1ED;
	--white: #FFFFFF;
	--ink: #141311;
	--ink-2: #47443F;
	--ink-3: #6B6760;
	--line: #E6E3DD;
	--line-strong: #D3CFC7;
	--accent: #FE6D41;
	--accent-tint: #FFEDE6;

	/* тёмный блок (форма + футер) */
	--night: #141311;
	--on-night: #FAF9F7;
	--on-night-2: rgba(250, 249, 247, .66);
	--night-line: rgba(250, 249, 247, .16);

	/* шрифты: два семейства, оба самохостинг */
	--font-display: "Manrope", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
	--font-text: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

	/* размеры: плавные, без скачков между брейкпоинтами */
	--fs-display: clamp(3rem, 1.2rem + 7.6vw, 9rem);
	--fs-h2: clamp(2.25rem, 1rem + 4.2vw, 5rem);
	--fs-h3: clamp(1.25rem, 1.05rem + .7vw, 1.75rem);
	--fs-lead: clamp(1.0625rem, .98rem + .4vw, 1.375rem);

	/* движение */
	--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
	--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
	--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);

	/* каркас */
	--gutter: clamp(20px, 4.4vw, 72px);
	--maxw: 1440px;
	--section-y: clamp(96px, 13vw, 192px);
	--section-y-close: clamp(56px, 7vw, 112px);   /* короткая пауза: раздел продолжает мысль предыдущего, а не переключает тему */
	--header-h: 72px;
}

/* ---------- сброс ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
	-webkit-text-size-adjust: 100%;
	scroll-padding-top: calc(var(--header-h) + 16px);
	scrollbar-gutter: stable;
	/* Обычно корень — цвет бумаги, как у страницы. Цвет корня браузер показывает на ещё не отрисованных кусках страницы при быстрой
	   прокрутке (в том числе при прыжке по ссылке через весь длинный экран), и оранжевый там мигал бы. Бумагу страницы рисует сам корень:
	   у body фона нет (см. body) */
	background-color: var(--paper);
}
/* «Резинка»: когда страницу докрутили до упора и тянут дальше (вверх или вниз), браузер показывает за краем цвет корня — там должно быть
   чисто и оранжево. Поэтому пока страница стоит у верхнего или нижнего края, корень оранжевый (класс ставит js/overscroll.js), а бумагу
   страницы тогда держит подложка по коробке html: она ровно по странице, за её краем остаётся оранжевый цвет.
   Почему body прозрачный: Safari берёт цвет «резинки» из смеси фонов html и body, и непрозрачный body перебил бы оранжевый.
   Safari 26 ещё смотрит, что стоит у самого края экрана: если там sticky/fixed-элемент во всю ширину (сверху — шапка), «резинка» —
   цвет корня; если обычный блок — тянет его цвет (снизу выходил тёмный футер). Поэтому у нижнего края стоит такая же sticky-полоска,
   как шапка сверху (.edge-bar, ниже). */
html.is-edge {
	background-color: var(--accent);
	background-image: linear-gradient(var(--paper), var(--paper));
	background-repeat: no-repeat;
	background-size: 100% 100%;
}
/* без полосы прокрутки (открыто меню или диалог) «резинки» нет, а место под полосу (scrollbar-gutter) красится цветом корня —
   держим бумагу, чтобы при открытом диалоге справа не было оранжевой полосы */
html.menu-open, html:has(dialog[open]) { background: var(--paper); }
@media (prefers-reduced-motion: no-preference) {
	html { scroll-behavior: smooth; }
}

body {
	margin: 0;
	min-height: 100vh; min-height: 100dvh;   /* даже короткая страница занимает весь экран: оранжевое видно только за краем страницы */
	background: none;                        /* прозрачный, см. html выше: бумагу под страницей рисует он */
	color: var(--ink);
	font: 400 1rem/1.6 var(--font-text);
	font-synthesis: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	overflow-x: clip;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; }
h1, h2, h3, h4, p, ul, ol, figure, blockquote, dl, dd { margin: 0; }
ul, ol { padding: 0; list-style: none; }
button, input, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 {
	font-family: var(--font-display);
	font-weight: 300;
	letter-spacing: -.03em;
	line-height: 1.05;
	text-wrap: balance;
}
p { text-wrap: pretty; }

/* касание: у кнопок, карточек FAQ, бургера и галочек есть свой отклик на нажатие (сжатие, заливка, крест) — серую
   вспышку-прямоугольник, которой телефон подсвечивает нажатый элемент, там убираем: на таблетках и скруглённых карточках она не по форме */
.btn, .burger, .dialog__close, .check, .cookie-notice__btn, .faq__card, .faq__btn, .stats__cta, .menu__link { -webkit-tap-highlight-color: transparent; }

::selection { background: var(--accent); color: var(--ink); }
/* .on-accent — блок на оранжевом фоне: оранжевое выделение там не видно, поэтому чернильное (кольцо курсора — см. ниже) */
.on-accent::selection, .on-accent ::selection { background: var(--ink); color: var(--paper); }

:focus-visible {
	outline: 2px solid var(--ink);
	outline-offset: 3px;
	border-radius: 4px;
}
.on-night :focus-visible { outline-color: var(--on-night); }

.sr-only {
	position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
	overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* «к содержимому» — ссылка для клавиатуры: видна только пока на ней фокус (Tab с самого верха страницы). Прячем прозрачностью, а не
   сдвигом за край экрана: fixed браузер оставляет на месте, и когда страницу оттягивают «резинкой» у верха, сдвинутая кнопка
   выезжала в оранжевую зону. pointer-events: none — чтобы невидимая ссылка не перекрывала логотип под собой */
.skip-link {
	position: fixed; top: 12px; left: 12px; z-index: 100;
	padding: 12px 18px; border-radius: 999px;
	background: var(--ink); color: var(--paper); font-size: .875rem; font-weight: 500;
	opacity: 0; pointer-events: none;
	transform: translateY(-8px);
	transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.skip-link:focus-visible { opacity: 1; pointer-events: auto; transform: none; outline-color: var(--accent); }

/* ---------- каркас ---------- */
.container {
	width: 100%;
	max-width: var(--maxw);
	margin-inline: auto;
	padding-inline: var(--gutter);
}
.section { padding-block: var(--section-y); }

.grid {
	display: grid;
	grid-template-columns: repeat(12, minmax(0, 1fr));
	column-gap: clamp(16px, 2vw, 32px);
}

.eyebrow {
	display: inline-flex; align-items: center; gap: 6px;
	font: 600 .75rem/1 var(--font-text);
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--ink-3);
}
/* маркер — слэш из вордмарка (img/header/logo.svg): та же наклонная плашка, пропорция 0.339 (87 × 257 в логотипе),
   высота по заглавным Inter (.727em), поэтому стоит от базовой линии до верха заглавных; строка центрируется по ним же */
.eyebrow::before {
	content: ""; flex: none; height: .727em; width: .2465em;
	background: var(--accent);
	clip-path: polygon(52.7% 0, 100% 0, 47.3% 100%, 0 100%);
}
.on-night .eyebrow { color: var(--on-night-2); }

.h2 { font-size: var(--fs-h2); font-weight: 300; letter-spacing: -.04em; line-height: 1.02; }
.h3 { font-size: var(--fs-h3); font-weight: 500; letter-spacing: -.02em; line-height: 1.2; }

.slash { color: var(--accent); }                /* слэш из вордмарка — только как графика */
.nw { white-space: nowrap; }                    /* составное слово через дефис, которое нельзя рвать («дизайн-макет»): заголовки выравниваются (balance) и иначе ломали его на дефисе */
.brace { color: var(--accent); font-weight: 300; }

.rule { height: 1px; background: var(--line); border: 0; }
.on-night .rule { background: var(--night-line); }

/* ---------- ссылки ---------- */
.link {
	background:
		linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat,
		linear-gradient(var(--line-strong), var(--line-strong)) 0 100% / 100% 1px no-repeat;
	padding-bottom: 3px;
	transition: background-size 320ms var(--ease-out);
}
.on-night .link {
	background:
		linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat,
		linear-gradient(var(--night-line), var(--night-line)) 0 100% / 100% 1px no-repeat;
}
@media (hover: hover) and (pointer: fine) {
	.link:hover { background-size: 100% 1px, 100% 1px; }
}

/* ---------- кнопки ---------- */
.btn {
	--bg: var(--accent); --fg: var(--ink);
	--bg-h: var(--ink); --fg-h: var(--paper);
	--btn-h: 54px;
	position: relative; isolation: isolate; overflow: hidden;
	display: inline-flex; align-items: center; justify-content: center; gap: .7em;
	min-height: var(--btn-h); padding: 0 1.9rem;
	border: 0; border-radius: 999px;
	background: var(--bg); color: var(--fg);
	font: 500 .9375rem/1 var(--font-text);
	letter-spacing: .005em; white-space: nowrap;
	transition: transform 160ms var(--ease-out), color 220ms var(--ease-out);
}
.btn::before,
.btn__fill {
	content: ""; position: absolute; inset: 0; z-index: -1;
	background: var(--bg-h);
	/* заливка растёт из точки, где указатель вошёл в кнопку, и втягивается к точке выхода: --fx / --fy пишет
	   js/cursor.js. Без скрипта (и на телефоне) остаётся прежняя — снизу. */
	clip-path: circle(0 at var(--fx, 50%) var(--fy, 130%));
	transition: clip-path 480ms var(--ease-out);
}
/* Слой заливки с копией подписи и стрелки в цветах наведения (собирает js/cursor.js — только для мыши). Лежит поверх
   содержимого и обрезан тем же кругом, поэтому цвет текста и стрелки меняется ровно по краю заливки. С одной заливкой
   под текстом цвет менялся во всей кнопке сразу и быстрее, чем до него доходил круг: на полпути подпись и стрелка
   пропадали (тёмное на тёмном), а при уходе — светлое на светлом, и стрелку «дёргало». Раскладка — та же, что у кнопки. */
.btn__fill {
	z-index: 1; pointer-events: none;
	display: flex; align-items: inherit; justify-content: inherit; gap: inherit; padding: inherit;
	color: var(--fg-h);
}
.btn.has-fill::before { content: none; }
.btn.has-fill.is-loading::after { z-index: 2; }   /* крутилка — поверх слоя заливки */
.btn:active { transform: scale(.97); }
.btn__icon { width: 16px; height: 16px; flex: none; transition: transform 220ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
	.btn:hover { color: var(--fg-h); }
	.btn.has-fill:hover { color: var(--fg); }      /* цвет наведения несёт слой заливки, а не вся кнопка */
	.btn.has-fill.is-loading:hover::after { color: var(--fg-h); }
	.btn:hover::before, .btn:hover .btn__fill { clip-path: circle(150% at var(--fx, 50%) var(--fy, 130%)); }
	.btn:hover .btn__icon { transform: translateX(3px); }
	.btn:hover .btn__icon--up { transform: translateY(-3px); }   /* «наверх» в футере: стрелка приподнимается, а не уходит вбок */
}
/* js/cursor.js ставит этот класс на миг при входе: заливка без анимации встаёт кругом нулевого радиуса в точку входа,
   и только потом :hover её раскрывает — иначе центр «доезжал» бы от места прошлого выхода. Стоит после :hover ради порядка. */
.btn.is-fill-reset::before,
.btn.is-fill-reset .btn__fill { transition: none; clip-path: circle(0 at var(--fx, 50%) var(--fy, 130%)); }
.btn--ink { --bg: var(--ink); --fg: var(--paper); --bg-h: var(--accent); --fg-h: var(--ink); }
.btn--ghost { --bg: transparent; --fg: var(--ink); --bg-h: var(--ink); --fg-h: var(--paper); box-shadow: inset 0 0 0 1px var(--line-strong); }
.on-night .btn--ghost { --fg: var(--on-night); --bg-h: var(--on-night); --fg-h: var(--ink); box-shadow: inset 0 0 0 1px var(--night-line); }
.on-night .btn--primary { --bg-h: var(--on-night); --fg-h: var(--ink); }   /* тёмная заливка на тёмном фоне не видна → белая */
.btn--sm { --btn-h: 44px; padding: 0 1.4rem; font-size: .875rem; }

/* оранжевая кнопка: стрелка лежит в белом круге у правого края.
   Круг отступает от таблетки одинаково сверху, снизу и справа (--btn-gap): диаметр = высота − 2 отступа,
   поэтому он концентричен скруглению таблетки. Текст и его левый отступ остаются прежними. */
.btn--primary {
	--btn-gap: 6px;
	--btn-dot: calc(var(--btn-h) - 2 * var(--btn-gap));
	gap: 1.25rem; padding-right: var(--btn-gap);
}
.btn__arrow {
	flex: none; display: grid; place-items: center; margin-left: auto;   /* в растянутой кнопке (меню) круг остаётся у правого края */
	width: var(--btn-dot); height: var(--btn-dot);
	border-radius: 50%; background: var(--white); color: var(--ink);   /* стрелка тёмная и при наведении */
	transition: background-color 220ms var(--ease-out);
}
.btn--primary .btn__icon { width: 18px; height: 18px; transition-duration: 300ms; }
@media (hover: hover) and (pointer: fine) {
	.btn--primary:hover .btn__icon { transform: rotate(-45deg); }      /* → становится ↗ */
	.on-night .btn--primary:not(.has-fill):hover .btn__arrow { background: var(--accent); }   /* плашка белая → круг оранжевый */
}
/* со слоем заливки круг оранжевый только в копии: белый сменяется оранжевым по краю заливки */
.on-night .btn--primary .btn__fill .btn__arrow { background: var(--accent); }

.btn[disabled] { cursor: progress; }
.btn.is-loading .btn__label, .btn.is-loading .btn__icon, .btn.is-loading .btn__arrow { opacity: 0; }
.btn.is-loading::after {
	content: ""; position: absolute; left: 50%; top: 50%;
	width: 20px; height: 20px; margin: -10px 0 0 -10px;
	border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
	animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- шапка ---------- */
/* Не fixed, а sticky. Когда страницу докрутили до упора и тянут дальше, браузер сдвигает саму страницу и открывает за ней «резинку»
   (оранжевый фон корня, см. html). fixed-элементы при этом стоят на месте и ложатся поверх неё; sticky лежит внутри прокручиваемого
   содержимого и уезжает вместе со страницей, поэтому зона за краем остаётся пустой. Отрицательный margin-bottom возвращает прежнюю
   раскладку: шапка занимает место в потоке, но контент лежит под ней, как и под fixed. */
.header {
	position: sticky; top: 0; z-index: 50;
	height: var(--header-h);
	margin-bottom: calc(var(--header-h) * -1);
	--h-dur: 240ms;   /* смена темы: цвета перетекают, а не щёлкают */
}

/* Тема шапки — цвет раздела прямо под ней: бумага, оранжевый («accent») или чёрный («night»). Ставит её js/header-tone.js
   в data-tone: над портфолио и тёмным блоком формы — на всю шапку; над сценами с мозаикой (манифест, «почему выбирают»)
   фон шапки прозрачный (.is-scene), клетки растут прямо под ней, и тему получает каждая часть отдельно ([data-tone-part]:
   буквы логотипа, слэш, пункты меню, кнопка, бургер) — когда мозаика накрыла её больше чем наполовину.
   Всё в шапке красится от переменных --h-*, поэтому тема — это только набор значений.
   Открытое мобильное меню бумажное: поверх него шапка всегда в обычной теме (html.menu-open — сильнее тем). */
.header, .header [data-tone="paper"], html.menu-open .header[data-tone], html.menu-open .header [data-tone] {
	--h-bg: var(--paper); --h-line: var(--line);
	--h-ink: var(--ink); --h-ink-2: var(--ink-2); --h-slash: var(--accent);
	--h-btn: var(--ink); --h-btn-fg: var(--paper); --h-btn-hover: var(--accent); --h-btn-fg-hover: var(--ink);
}
/* оранжевый: буквы и кнопка чернильные (6.6:1), меню — чернила 82 % (5.1:1; --ink-2 дал бы 3.45:1); слэш и бургер белые —
   оранжевые на оранжевом пропали бы; заливка кнопки при наведении — бумага (оранжевая слилась бы с фоном); линии снизу нет */
.header[data-tone="accent"], .header [data-tone="accent"] {
	--h-bg: var(--accent); --h-line: transparent;
	--h-ink: var(--ink); --h-ink-2: color-mix(in srgb, var(--ink) 82%, var(--accent)); --h-slash: var(--white);
	--h-btn: var(--ink); --h-btn-fg: var(--paper); --h-btn-hover: var(--paper); --h-btn-fg-hover: var(--ink);
}
/* чёрный: буквы бумажные, меню — как текст тёмного блока, слэш остаётся оранжевым; кнопка выворачивается в бумажную —
   чёрная на чёрном пропала бы */
.header[data-tone="night"], .header [data-tone="night"] {
	--h-bg: var(--night); --h-line: transparent;
	--h-ink: var(--on-night); --h-ink-2: var(--on-night-2); --h-slash: var(--accent);
	--h-btn: var(--on-night); --h-btn-fg: var(--ink); --h-btn-hover: var(--accent); --h-btn-fg-hover: var(--ink);
}
.header :focus-visible { outline-color: var(--h-ink); }

.header__bg {
	position: absolute; inset: 0;
	background: var(--h-bg);
	border-bottom: 1px solid var(--h-line);
	opacity: 0;
	transition: opacity 250ms var(--ease-out), background-color var(--h-dur) var(--ease-out), border-color var(--h-dur) var(--ease-out);
}
.header.is-scrolled .header__bg { opacity: 1; }
.header.is-scene .header__bg { opacity: 0; }   /* над сценой с мозаикой фона нет: клетки растут прямо под шапкой */
.header__bar {
	position: relative; z-index: 2;
	height: 100%;
	display: flex; align-items: center; gap: clamp(20px, 3vw, 48px);
}
.header__logo { display: block; flex: none; padding-block: 14px; }   /* цель нажатия от 44 px: знак высотой ~18 px, поле невидимое — шапка выше */
/* логотип встроен в страницу (не <img>), чтобы буквы и слэш перекрашивались отдельно; геометрия — img/header/logo.svg */
.header__logo svg { width: clamp(118px, 11vw, 158px); height: auto; }
.header__logo-ink { fill: var(--h-ink); transition: fill var(--h-dur) var(--ease-out); }
.header__logo-slash { fill: var(--h-slash); transition: fill var(--h-dur) var(--ease-out); }

.header__nav { display: flex; gap: clamp(20px, 2.6vw, 40px); margin-left: auto; }
.header__nav a {
	position: relative; padding: 8px 0;
	font-size: .875rem; font-weight: 500; color: var(--h-ink-2);
	transition: color var(--h-dur) var(--ease-out);
}
.header__nav a::after {
	content: ""; position: absolute; left: 0; right: 0; bottom: 2px; height: 1px;
	background: currentColor;
	transform: scaleX(0); transform-origin: left;
	transition: transform 300ms var(--ease-out);
}
.header__nav a[aria-current="true"] { color: var(--h-ink); }
.header__nav a[aria-current="true"]::after { transform: scaleX(1); }
@media (hover: hover) and (pointer: fine) {
	.header__nav a:hover { color: var(--h-ink); }
	.header__nav a:hover::after { transform: scaleX(1); }
}
/* кнопка «заказать» в шапке — цвета из темы (.btn читает --bg/--fg/--bg-h/--fg-h), фон при смене темы перетекает */
.header .header__cta {
	--bg: var(--h-btn); --fg: var(--h-btn-fg); --bg-h: var(--h-btn-hover); --fg-h: var(--h-btn-fg-hover);
	transition: transform 160ms var(--ease-out), color 220ms var(--ease-out), background-color var(--h-dur) var(--ease-out);
}

.burger {
	display: none; position: relative; flex: none;
	width: 44px; height: 44px; margin-left: auto; margin-right: -10px;
	border: 0; background: transparent; border-radius: 50%;
}
/* иконка — «//» из вордмарка: два наклонных слэша вместо линий бутерброда; на открытии сводятся в крест */
/* толщина — scaleX от базовых 2px (толщина креста): в покое ×1.5, на открытии едет к ×1 — только transform, без layout-свойств */
/* концы острые и срезаны горизонтально, как у слэша в логотипе: rotate(15°) skewY(−15°) scaleY(1/cos 15° = 1.0353) — это
   наклон skewX(−15°), то есть параллелограмм с горизонтальными торцами, а высота та же 22px. Функции в покое и на открытии одни
   и те же (translateX rotate skewY scale) — переход в крест идёт по каждой отдельно, без пересчёта матриц */
.burger span {
	position: absolute; top: 11px; bottom: 11px; left: 21px; width: 2px;
	background: var(--h-slash);   /* тот же слэш, что в логотипе, — и цвет по теме шапки тот же */
	transform: translateX(-6px) rotate(15deg) skewY(-15deg) scale(1.5, 1.0353);
	transition: transform 320ms var(--ease-out), background-color var(--h-dur) var(--ease-out);
}
.burger span:nth-child(2) { transform: translateX(6px) rotate(15deg) skewY(-15deg) scale(1.5, 1.0353); }
.menu-open .burger span:nth-child(1) { transform: translateX(0) rotate(45deg) skewY(0deg) scale(1, 1); }
.menu-open .burger span:nth-child(2) { transform: translateX(0) rotate(-45deg) skewY(0deg) scale(1, 1); }

/* мобильное меню: раскрывается кругом из точки бургера */
.menu {
	position: fixed; inset: 0; z-index: 1;
	display: flex; flex-direction: column; justify-content: space-between;
	padding: calc(var(--header-h) + 32px) var(--gutter) 32px;
	/* не поместилось по высоте (телефон на боку) — меню листается само; страница под ним стоит (html.menu-open) */
	overflow-y: auto; overscroll-behavior: contain;
	background: var(--paper);
	clip-path: circle(0 at calc(100% - 32px) 36px);
	visibility: hidden;
	transition: clip-path 500ms var(--ease-drawer), visibility 0s linear 500ms;
}
.menu-open .menu {
	clip-path: circle(150vmax at calc(100% - 32px) 36px);
	visibility: visible;
	transition: clip-path 500ms var(--ease-drawer), visibility 0s;
}
.menu__nav { display: grid; }
.menu__link {
	display: flex; align-items: baseline; justify-content: space-between;
	padding: 18px 0; border-bottom: 1px solid var(--line);
	padding-block: clamp(12px, 2.6svh, 18px);   /* на невысоком телефоне пункты плотнее — меню с кнопкой и контактами помещается в экран */
	font: 300 clamp(2rem, 8vw, 3rem)/1.1 var(--font-display); letter-spacing: -.035em;
	opacity: 0; transform: translateY(18px);
	transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.menu__link small { font: 500 .75rem/1 var(--font-text); letter-spacing: .12em; color: var(--ink-3); }
.menu-open .menu__link {
	opacity: 1; transform: none;
	transition: opacity 500ms var(--ease-out), transform 600ms var(--ease-out);
	transition-delay: calc(160ms + var(--i, 0) * 60ms);
}
.menu__foot { display: grid; gap: 18px; opacity: 0; transition: opacity 200ms var(--ease-out); }
.menu-open .menu__foot { opacity: 1; transition: opacity 500ms var(--ease-out) 420ms; }
/* почта и телефон — строки по 44 px (цель нажатия); отрицательные поля возвращают блоку прежние отступы сверху и снизу */
.menu__contacts { display: grid; justify-items: start; font-size: .9375rem; color: var(--ink-2); margin-block: calc((1lh - 44px) / 2); }
.menu__contacts a { display: flex; align-items: center; min-height: 44px; }
html.menu-open { overflow: hidden; }

@media (max-width: 860px) {
	:root { --header-h: 64px; }
	.header__nav, .header__cta { display: none; }
	.burger { display: block; }
}

/* ---------- тёмный блок: форма + футер ---------- */
.night {
	position: relative;
	background: var(--night); color: var(--on-night);
	border-radius: clamp(28px, 4vw, 56px) clamp(28px, 4vw, 56px) 0 0;
	/* последний блок страницы: добивает её высоту до целого пикселя (js/overscroll.js пишет --page-round), иначе в покое под футером
	   виднелась доля пикселя оранжевого корня */
	padding-bottom: var(--page-round, 0px);
}

.footer { padding-block: clamp(56px, 8vw, 112px) clamp(28px, 3vw, 44px); border-top: 1px solid var(--night-line); }
.footer__contacts { display: grid; gap: clamp(8px, 1vw, 16px); justify-items: start; }
/* адрес — одно неделимое слово (≈ 10.62em при этом начертании и трекинге): на телефоне кегль подстраивается под ширину
   контейнера, чтобы он не рвался посреди слова («…gmail.co / m»), — тот же приём, что у «POGOSOV/STUDIO?» в .why .h2.
   Сменится адрес — пересчитать делитель (ширина строки в em + запас); overflow-wrap остаётся на случай запасного шрифта */
.footer__mail {
	font: 200 clamp(1.75rem, 1rem + 4.6vw, 5rem)/1.05 var(--font-display);
	font-size: min(clamp(1.75rem, 1rem + 4.6vw, 5rem), calc((100vw - 2 * var(--gutter)) / 10.7));
	letter-spacing: -.045em; overflow-wrap: anywhere;
	transition: color 200ms var(--ease-out);
}
.footer__phone {
	font: 300 clamp(1.25rem, 1rem + 1.4vw, 2.25rem)/1.2 var(--font-display);
	letter-spacing: -.03em; color: var(--on-night-2);
	margin-top: clamp(4px, .7vw, 10px);                    /* к зазору сетки: у почты выносные (p, g) подходят к цифрам почти вплотную */
	transition: color 200ms var(--ease-out);
}
/* Цели нажатия от 44 px. На телефоне строка почты и телефона ниже: добираем высоту невидимым полем сверху и снизу и тут же
   возвращаем его отрицательным отступом — раскладка и вид те же, растёт только площадь нажатия. 1lh — высота строки самого
   элемента; где этой единицы нет, правила не применятся и всё останется как было */
.footer__mail, .footer__phone { padding-block: max(0px, (44px - 1lh) / 2); margin-bottom: min(0px, (1lh - 44px) / 2); }
.footer__mail { margin-top: min(0px, (1lh - 44px) / 2); }
.footer__phone { margin-top: calc(clamp(4px, .7vw, 10px) + min(0px, (1lh - 44px) / 2)); }
/* на тёмном акцент читается (контраст ≈ 6.6:1), поэтому здесь им можно красить текст */
@media (hover: hover) and (pointer: fine) { .footer__mail:hover, .footer__phone:hover { color: var(--accent); } }
.footer__bottom {
	display: grid; grid-template-columns: auto 1fr auto auto;
	gap: 24px clamp(24px, 4vw, 64px); align-items: end;
	margin-top: clamp(56px, 8vw, 120px); padding-top: clamp(28px, 3vw, 40px);
	border-top: 1px solid var(--night-line);
	font-size: .8125rem; line-height: 1.6; color: var(--on-night-2);
}
.footer__req { display: grid; gap: 2px; }
.footer__legal { display: grid; gap: 6px; justify-items: start; }
.footer__legal a { transition: color 200ms var(--ease-out); }
@media (hover: hover) and (pointer: fine) { .footer__legal a:hover { color: var(--on-night); } }

/* Низ ряда — низ кнопки; к нему приставлены и остальные: плоский низ букв STUDIO (T, D, I), базовая линия последней строки
   обоих текстовых блоков и нижняя кромка кнопки лежат на одной линии. По коробкам это не так: в SVG под буквами пустое поле
   (48 из 372 единиц), а у строки текста под базовой линией — запас на выносные (.446em при line-height 1.6 у Inter).
   Логотип и текст опущены на эти запасы отрицательным margin-bottom; где браузер умеет text-box, текст срезается по базовой
   линии сам, и запас не зависит от метрик шрифта. В столбик (≤860 px) выравнивать нечего — там всё сброшено. */
.footer__logo { --w: clamp(96px, 9vw, 132px); width: var(--w); height: auto; margin-bottom: calc(var(--w) * -.0889); }   /* 48 / 540 */
.footer__req p:last-child, .footer__legal a:last-child { margin-bottom: -.446em; }
@supports (text-box-trim: trim-end) {
	.footer__req p:last-child, .footer__legal a:last-child { margin-bottom: 0; text-box: trim-end text alphabetic; }
}
@media (max-width: 860px) {
	.footer__bottom { grid-template-columns: 1fr; align-items: start; }
	.footer__bottom .btn { justify-self: start; }
	.footer__logo { margin-bottom: 0; }
	.footer__req p:last-child, .footer__legal a:last-child { margin-bottom: 0; text-box: normal; }
	/* цели нажатия от 44 px: ссылки на документы — строки по 44 px (было 21 + 6); отрицательные поля держат прежние отступы блока */
	.footer__legal { gap: 0; margin-block: calc((1lh - 44px) / 2); }
	.footer__legal a { display: flex; align-items: center; min-height: 44px; }
}

/* ---------- форма ---------- */
.form {
	--f-ink: var(--ink); --f-mute: var(--ink-3);
	--f-line: var(--line-strong); --f-focus: var(--ink); --f-err: #C2410C;
	display: grid; gap: clamp(20px, 2.4vw, 32px);
}
.on-night .form, .form--night {
	--f-ink: var(--on-night); --f-mute: var(--on-night-2);
	--f-line: var(--night-line); --f-focus: var(--accent); --f-err: #FF9A78;
}
.field { display: grid; gap: 10px; }
.field__label {
	font: 600 .75rem/1 var(--font-text); letter-spacing: .14em; text-transform: uppercase;
	color: var(--f-mute);
}
.field__control { position: relative; }
.field__input {
	appearance: none; -webkit-appearance: none;
	width: 100%; padding: 6px 0 16px;
	border: 0; border-bottom: 1px solid var(--f-line); border-radius: 0;
	background: transparent; color: var(--f-ink);
	font: 300 clamp(1.5rem, 1.1rem + 1.4vw, 2.25rem)/1.2 var(--font-display);
	letter-spacing: -.02em;
	outline: 0;
	transition: border-color 200ms var(--ease-out);
}
.field__input::placeholder { color: var(--f-mute); opacity: .5; }
.field__line {
	position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
	background: var(--f-focus);
	transform: scaleX(0); transform-origin: left;
	transition: transform 400ms var(--ease-out);
}
.field__control:focus-within .field__line { transform: scaleX(1); }
.field__error {
	min-height: 1.4em; font: 500 .8125rem/1.4 var(--font-text); color: var(--f-err);
	opacity: 0; transform: translateY(-4px);
	transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out);
}
.field.is-invalid .field__error { opacity: 1; transform: none; }
.field.is-invalid .field__input { border-bottom-color: var(--f-err); animation: nudge 360ms var(--ease-out); }
@keyframes nudge { 20% { transform: translateX(-5px); } 55% { transform: translateX(4px); } 85% { transform: translateX(-2px); } }

.consents { display: grid; gap: 14px; }
.check {
	/* цель нажатия от 44 px: строка согласия — 21 px. Невидимое поле сверху и снизу (padding) и такой же отрицательный margin:
	   между согласиями поля встречаются посередине зазора (7 + 7 = 14), у первого и последнего уходят в свободное место
	   над и под блоком. Раскладка и вид не меняются */
	--hit-top: 7px; --hit-bottom: 7px;
	position: relative; display: grid; grid-template-columns: 20px 1fr; gap: 14px; align-items: start;
	padding-block: var(--hit-top) var(--hit-bottom); margin-block: calc(var(--hit-top) * -1) calc(var(--hit-bottom) * -1);
	font-size: .8125rem; line-height: 1.5; color: var(--f-mute); cursor: pointer;
}
.check:first-child { --hit-top: 16px; }
.check:last-child { --hit-bottom: 16px; }
.check input { position: absolute; left: 0; top: var(--hit-top); width: 20px; height: 20px; margin: 0; opacity: 0; cursor: pointer; }
.check__box {
	display: grid; place-items: center; width: 20px; height: 20px; margin-top: 1px;
	border: 1px solid var(--f-mute); border-radius: 50%;
	transition: background-color 200ms var(--ease-out), border-color 200ms var(--ease-out), transform 160ms var(--ease-out);
}
.check__box svg {
	/* 10 px, линия 2.2 из 12 единиц viewBox = ~1.8 px на экране (было 12 px и 2.6 px — слишком жирно) */
	width: 10px; height: 10px; fill: none; stroke: var(--ink); stroke-width: 2.2;
	stroke-linecap: round; stroke-linejoin: round;
	stroke-dasharray: 16; stroke-dashoffset: 16;
	transition: stroke-dashoffset 280ms var(--ease-out) 60ms;
}
.check input:checked + .check__box { background: var(--accent); border-color: var(--accent); }
.check input:checked + .check__box svg { stroke-dashoffset: 0; }
.check:active .check__box { transform: scale(.92); }
.check input:focus-visible + .check__box { outline: 2px solid var(--f-ink); outline-offset: 3px; }
.check a { color: var(--f-ink); background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat; padding-bottom: 1px; }
.check.is-invalid { color: var(--f-err); }
.check.is-invalid .check__box { border-color: var(--f-err); animation: nudge 360ms var(--ease-out); }
.form__actions { display: grid; gap: 22px; justify-items: start; }

/* ---------- диалоги (нативный <dialog>) ---------- */
.dialog {
	position: fixed; inset: 0; margin: auto;
	width: min(600px, calc(100vw - 24px)); max-height: calc(100dvh - 24px);
	padding: 0; border: 0; background: transparent; color: var(--ink);
	overflow: visible;
	opacity: 0; transform: translateY(14px) scale(.98);
	transition: opacity 250ms var(--ease-out), transform 250ms var(--ease-out);
}
.dialog[open] { opacity: 1; transform: none; }
@starting-style { .dialog[open] { opacity: 0; transform: translateY(14px) scale(.98); } }
.dialog::backdrop {
	background: rgba(20, 19, 17, 0);
	transition: background-color 250ms var(--ease-out);
}
.dialog[open]::backdrop { background: rgba(20, 19, 17, .5); }
@starting-style { .dialog[open]::backdrop { background: rgba(20, 19, 17, 0); } }
@supports (transition-behavior: allow-discrete) {
	.dialog {
		transition: opacity 250ms var(--ease-out), transform 250ms var(--ease-out),
			overlay 250ms allow-discrete, display 250ms allow-discrete;
	}
	.dialog::backdrop {
		transition: background-color 250ms var(--ease-out), overlay 250ms allow-discrete, display 250ms allow-discrete;
	}
}
html:has(dialog[open]) { overflow: hidden; }
.dialog__panel {
	position: relative; max-height: calc(100dvh - 24px); overflow: auto;
	padding: clamp(28px, 4.5vw, 52px);
	background: var(--paper); border-radius: clamp(24px, 3vw, 32px);
}
.dialog__close {
	position: absolute; top: 14px; right: 14px; z-index: 2;
	width: 44px; height: 44px; border: 0; border-radius: 50%; background: transparent;
	transition: background-color 200ms var(--ease-out), transform 160ms var(--ease-out);
}
.dialog__close::before, .dialog__close::after {
	content: ""; position: absolute; left: 13px; right: 13px; top: 50%; height: 1.5px; margin-top: -.75px;
	background: var(--ink); border-radius: 2px;
}
.dialog__close::before { transform: rotate(45deg); }
.dialog__close::after { transform: rotate(-45deg); }
.dialog__close:active { transform: scale(.94); }
@media (hover: hover) and (pointer: fine) { .dialog__close:hover { background: var(--paper-2); } }
.dialog__title { font-size: clamp(2rem, 1.4rem + 2.6vw, 3.25rem); font-weight: 300; letter-spacing: -.04em; margin: 8px 0 clamp(24px, 3vw, 36px); padding-right: 40px; }
.dialog__lead { color: var(--ink-2); margin: -12px 0 clamp(24px, 3vw, 36px); }

.status { display: grid; gap: 14px; padding-top: 8px; }
.status__mark { width: 30px; height: auto; margin-bottom: 18px; }
.status__title { font-size: clamp(2.25rem, 1.4rem + 3.4vw, 4rem); font-weight: 200; letter-spacing: -.045em; }
.status__text { max-width: 30ch; font-size: var(--fs-lead); line-height: 1.45; color: var(--ink-2); }
.status__mark path { transform-origin: 50% 100%; animation: mark-in 700ms var(--ease-out) 120ms both; }
@keyframes mark-in { from { opacity: 0; transform: translateY(16px) skewX(-6deg); } }

/* ---------- cookie-плашка (логика — js/cookie-notice.js, без изменений) ---------- */
/* Плашка лежит в «доке» — нулевой высоты sticky-полоске в самом конце страницы: она держится у нижнего края экрана, как fixed,
   но, в отличие от fixed, уезжает вместе со страницей, когда ту тянут за нижний край, и не ложится на «резинку» (см. шапку) */
.cookie-dock { position: sticky; bottom: 0; z-index: 60; height: 0; }
.cookie-notice {
	position: absolute; left: 50%; bottom: 20px; z-index: 60;
	width: min(680px, calc(100vw - 24px));
	display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px 24px;
	padding: 16px 16px 16px 24px;
	background: rgba(255, 255, 255, .92);
	-webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
	border: 1px solid var(--line); border-radius: 26px;
	box-shadow: 0 8px 32px rgba(20, 19, 17, .06);
	font-size: .8125rem; line-height: 1.5; color: var(--ink-2);
	opacity: 0; visibility: hidden; pointer-events: none;
	transform: translate(-50%, 16px);
	transition: opacity 300ms var(--ease-out), transform 450ms var(--ease-out), visibility 0s linear 450ms;
}
.cookie-notice.is-visible {
	opacity: 1; visibility: visible; pointer-events: auto; transform: translate(-50%, 0);
	transition: opacity 400ms var(--ease-out), transform 600ms var(--ease-out), visibility 0s;
}
.cookie-notice__text { flex: 1 1 280px; }
.cookie-notice__text a { color: var(--ink); background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat; }
.cookie-notice__actions { display: flex; gap: 8px; }
.cookie-notice__btn {
	min-height: 40px; padding: 0 18px; border: 0; border-radius: 999px;
	background: var(--ink); color: var(--paper);
	font: 500 .8125rem/1 var(--font-text);
	transition: transform 160ms var(--ease-out), background-color 200ms var(--ease-out);
}
.cookie-notice__btn--ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line-strong); }
.cookie-notice__btn:active { transform: scale(.96); }
@media (max-width: 860px) { .cookie-notice__btn { min-height: 44px; } }   /* цель нажатия на телефоне */
@media (hover: hover) and (pointer: fine) {
	.cookie-notice__btn:hover { background: var(--accent); color: var(--ink); }
	.cookie-notice__btn--ghost:hover { background: var(--paper-2); color: var(--ink); }
}

/* ===========================================================
   Появление при прокрутке.
   Скрытое состояние включается только когда JS жив (.js на <html>),
   иначе контент остаётся видимым.
   =========================================================== */
.js [data-reveal] {
	opacity: 0; transform: translateY(28px);
	transition: opacity 900ms var(--ease-out), transform 1000ms var(--ease-out);
	transition-delay: calc(var(--d, 0ms) + var(--i, 0) * 80ms);
}
.js [data-reveal="fade"] { transform: none; }
.js [data-reveal="fade-left"] { transform: translateX(-24px); }
.js [data-reveal="words"] { opacity: 1; transform: none; transition: none; }
.js [data-reveal="rule"] { opacity: 1; transform: scaleX(0); transform-origin: left; transition: transform 1200ms var(--ease-in-out); transition-delay: calc(var(--d, 0ms)); }
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* «раскрытие» блока: clip-path анимируется у детей, а IntersectionObserver следит за родителем.
   Нельзя вешать clip-path на сам наблюдаемый элемент: Chromium считает его обрезанную
   площадь при расчёте пересечения, и полностью скрытый блок никогда не «войдёт» в экран. */
.js [data-clip] .clip-item {
	clip-path: inset(0 0 100% 0 round var(--r, 0px));
	transition: clip-path 1100ms var(--ease-in-out);
	transition-delay: calc(var(--d, 0ms) + var(--i, 0) * 120ms);
}
.js [data-clip].is-in .clip-item { clip-path: inset(0 0 0 0 round var(--r, 0px)); }
/* «по одному» (телефон): список стоит столбиком выше экрана — js/main.js ставит на него .is-each и открывает каждого
   ребёнка, когда до него долистали (.is-in на самом ребёнке). Эффект тот же, каскадной задержки нет. То же — у [data-stagger] ниже */
.js [data-clip].is-each .clip-item { transition-delay: var(--d, 0ms); }
.js [data-clip].is-each .clip-item.is-in { clip-path: inset(0 0 0 0 round var(--r, 0px)); opacity: 1; }

/* дочерние блоки появляются каскадом (30–80 мс между соседями) */
.js [data-stagger] > * {
	opacity: 0; transform: translateY(24px);
	transition: opacity 800ms var(--ease-out), transform 900ms var(--ease-out);
	transition-delay: calc(var(--d, 0ms) + var(--i, 0) * 70ms);
}
.js [data-stagger].is-in > * { opacity: 1; transform: none; }
.js [data-stagger].is-each > * { transition-delay: var(--d, 0ms); }
.js [data-stagger].is-each > .is-in { opacity: 1; transform: none; }
[data-stagger] > :nth-child(1) { --i: 0; } [data-stagger] > :nth-child(2) { --i: 1; }
[data-stagger] > :nth-child(3) { --i: 2; } [data-stagger] > :nth-child(4) { --i: 3; }
[data-stagger] > :nth-child(5) { --i: 4; } [data-stagger] > :nth-child(6) { --i: 5; }
[data-stagger] > :nth-child(7) { --i: 6; } [data-stagger] > :nth-child(8) { --i: 7; }

/* заголовки по словам: слово выезжает из-под маски */
.w {
	display: inline-block; overflow: hidden; vertical-align: top;
	padding: .1em .06em .2em; margin: -.1em -.06em -.2em;
}
.w__in {
	display: inline-block;
	transition: transform 1000ms var(--ease-out);
	transition-delay: calc(var(--d, 0ms) + var(--w, 0) * 70ms);
}
.js [data-reveal="words"] .w__in { transform: translateY(112%); }
.js [data-reveal="words"].is-in .w__in { transform: none; }

/* до готовности шрифтов hero не стартует — иначе смена шрифта посреди анимации даст скачок */
.js:not(.is-ready) [data-hero] { visibility: hidden; }

@media (prefers-reduced-motion: reduce) {
	.js [data-reveal], .js [data-stagger] > *, .js [data-reveal="words"] .w__in {
		transform: none; transition: opacity 300ms ease; transition-delay: 0ms;
	}
	.js [data-reveal="words"] .w__in { opacity: 0; }
	.js [data-reveal="words"].is-in .w__in { opacity: 1; }
	.js [data-clip] .clip-item { clip-path: none; opacity: 0; transition: opacity 300ms ease; transition-delay: 0ms; }
	.js [data-clip].is-in .clip-item { opacity: 1; }
	.js [data-reveal="rule"] { transform: none; opacity: 0; }
	.js [data-reveal="rule"].is-in { opacity: 1; }
	.menu, .menu-open .menu { transition-duration: 200ms; }
	.menu { clip-path: none; opacity: 0; }
	.menu-open .menu { opacity: 1; }
	.dialog, .dialog[open] { transform: none; }
	.status__mark path, .field.is-invalid .field__input, .check.is-invalid .check__box { animation: none; }
	.btn::before, .btn__fill { transition: opacity 200ms ease; clip-path: none; opacity: 0; }
	.btn:hover::before, .btn:hover .btn__fill { opacity: 1; }
	.btn--primary .btn__icon, .btn__arrow { transition: none; }
}

/* ---------- курсор-кольцо (js/cursor.js) ---------- */
/* Кольцо летит за указателем, родной курсор остаётся. Позицию и масштаб пишет скрипт; над .btn и .field
   кольцо схлопывается и гаснет. Создаётся только для мыши и без prefers-reduced-motion.
   [popover] — чтобы стоять над модальными <dialog> (top layer); сбрасываем его стили по умолчанию. */
.cursor-ring {
	position: fixed; inset: auto; left: 0; top: 0; margin: 0; padding: 0; overflow: visible;
	width: 34px; height: 34px; border: 1.5px solid var(--accent); border-radius: 50%;
	background: rgba(254, 109, 65, .12);
	pointer-events: none; z-index: 1000;
	opacity: 0; will-change: transform, opacity;
	transition: opacity 320ms ease, border-color 200ms ease, background-color 200ms ease;
}
/* над .on-accent оранжевое кольцо на оранжевом не видно — там оно чернильное (класс ставит js/cursor.js) */
.cursor-ring.is-on-accent { border-color: var(--ink); background: rgba(20, 19, 17, .1); }
@media print { .cursor-ring { display: none !important; } }

/* ---------- служебное ---------- */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.sentinel { position: absolute; top: 0; left: 0; width: 1px; height: 8px; pointer-events: none; }
/* полоски js/overscroll.js: верхняя — как .sentinel, нижняя — нулевой высоты в самом конце документа (места не занимает) */
.edge-sentinel { pointer-events: none; }
.edge-sentinel--top { position: absolute; top: 0; left: 0; width: 1px; height: 8px; }
.edge-sentinel--end { height: 0; }
/* Нижняя «шапка» для Safari 26 (см. html.is-edge): прозрачная sticky-полоска во всю ширину у нижнего края — как шапка у верхнего.
   Найдя её у края, Safari красит «резинку» цветом корня (оранжевым), а не тянет цвет футера. Как и шапка, она лежит в содержимом
   страницы (не fixed) и при оттяжке уезжает вместе с ним, зона за краем остаётся пустой. Места не занимает (margin-top = −высота);
   есть, только пока страница у нижнего края (html.is-bottom, js/overscroll.js): тогда она лежит на пустом нижнем поле футера и
   ничего не загораживает, а в середине страницы не висела бы над контентом. 12 px: Safari ищет такие элементы в 4–6 px от края */
.edge-bar { display: none; position: sticky; bottom: 0; z-index: 50; height: 12px; margin-top: -12px; }
html.is-bottom .edge-bar { display: block; }
.js [data-reveal="lines"] { opacity: 1; transform: none; transition: none; }
