/* Тема 8vision — оформление публичного сайта 8vision.ru.
 *
 * Палитра и типографика приходят переменными из tokens.yaml, поэтому здесь
 * нет ни одного цвета «в лоб»: смена оформления сайта не требует правки темы.
 *
 * ─── Шрифт ───────────────────────────────────────────────────────────
 *
 * Inter Tight, только самохост: ни fonts.googleapis.com, ни любого другого
 * CDN. Сайт компании не должен показывать своих посетителей чужому серверу и
 * зависеть от его доступности.
 *
 * Файлы вариативные — один файл покрывает всю шкалу насыщенности от 100 до
 * 900, поэтому их три, а не тридцать. Деление на три — по алфавитам
 * (unicode-range): браузер скачивает кириллицу и не трогает латиницу
 * расширенную, пока на странице нет её символов. Прежний сайт грузил
 * четырнадцать файлов, включая курсив и греческий, которых нет в макете.
 *
 * font-display: swap — текст показывается системным шрифтом сразу и
 * подменяется, когда файл доехал. Иначе первый экран пустует до загрузки
 * шрифта, а на медленной сети это секунды.
 */

@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/inter-tight-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter Tight';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/inter-tight-latin.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: 'Inter Tight';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url(fonts/inter-tight-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Здесь НЕТ правил для тегов разметки: ни размеров заголовков, ни полей у
   абзацев. Всё это задаёт автор в настройках блока, а сброс умолчаний
   браузера живёт в theme.BaseCSS и встраивается прямо в страницу. Правило
   темы, стилизующее h1 или p, означало бы отступ, которого нет ни в одной
   настройке, — объяснить его в редакторе было бы нечем. */

.wrap {
  max-width: var(--layout-max-width);
  margin: 0 auto;
  padding: 0 24px;
}
.muted { color: var(--color-text-muted); }

/* Подвал прижат к низу окна, а не висит посреди экрана на короткой странице.
   Это раскладка ДОКУМЕНТА, а не оформление блоков: колонка во всю высоту,
   содержимое растягивается, подвал остаётся под ним.

   :has(.site-main) ограничивает правило страницами сайта — в полотне
   редактора этого элемента нет, и раскладка там не меняется: расхождение
   редактора с сайтом хуже висящего подвала. */
body:has(.site-main) {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
body:has(.site-main) .site-main { flex: 1 0 auto; }

/* ─── Шапка, подвал и область содержимого ──────────────────────────────

   Оформления у них НЕТ, и это не упущение.

   Было: рамка, фон, ограничение ширины, поля 24px по бокам и 18px сверху и
   снизу, промежуток между блоками, а у подвала ещё отступ в 64px и свой
   размер шрифта. Тонкая полоса навигации превращалась на сайте в широкую
   плашку, и найти эти отступы автору было негде — в настройках блока их нет,
   потому что их задавала тема.

   Шапка и подвал — такие же области блоков, как тело страницы: что в них
   стоит, решает владелец сайта. Нужна полоса с фоном и полями — положите
   туда контейнер и задайте их; там они будут видны и правимы.

   Теги <header> и <footer> при этом остаются: они не оформление, а
   ориентиры для экранного диктора — по ним можно перейти сразу к навигации
   или к подвалу. */

/* ─── Блоки ────────────────────────────────────────────────────────── */

/* У блока НЕТ собственных отступов: их задаёт автор в настройках блока, и
   любое значение из темы пришлось бы перебивать. Воздух даёт только контейнер
   страницы — иначе первый блок упирался бы в шапку. */
.block { padding: 0; margin: 0; }

/* Никаких отступов у области содержимого: любой из них выглядел бы в
   редакторе как необъяснимое поле по краям. Воздух вокруг блоков — дело
   их собственных настроек. */
.site-main { padding: 0; }

/* ─── Подпись под картинкой и роликом ─────────────────────────────────
   Мелко и приглушённо, как подписи к кадрам на прежнем сайте. Цвет —
   приглушённый текст темы: на белом он держит контраст 4.5:1. */
.ev-fig { margin: 0; }
.ev-fig__cap {
  margin: 8px 0 0;
  font-size: 13px; line-height: 1.4;
  color: var(--color-text-muted, #767676);
}

/* ─── Проигрыватель видео ──────────────────────────────────────────────
   Оформление СВОЕГО плеера: родные кнопки браузера перекрасить нельзя,
   поэтому их нет, а эти нарисованы разметкой блока.

   Всё здесь — оформление темы, а не настройки автора: настройки блока
   ложатся на .ev-player инлайном и перебивают написанное ниже. */

.ev-player {
  position: relative;
  display: block;
  overflow: hidden;
  background: #02050B;
  border-radius: var(--layout-radius);
  /* Пропорции — на случай, если автор их не задал: без них до загрузки
     метаданных блок имеет нулевую высоту и страница прыгает. */
  aspect-ratio: 16 / 9;
}

.ev-player video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #02050B;
}

/* Крупная кнопка поверх обложки. Пропадает во время воспроизведения:
   держать её над кадром незачем, пауза есть по щелчку и в полосе. */
.ev-player__big {
  position: absolute; inset: 0; margin: auto;
  width: 72px; height: 72px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: rgba(2, 5, 11, .55);
  backdrop-filter: blur(6px);
  color: #fff; cursor: pointer;
  transition: opacity .18s, transform .18s, background .18s;
}
.ev-player__big:hover { background: rgba(2, 5, 11, .75); transform: scale(1.06); }
.ev-player__big svg { width: 34px; height: 34px; fill: currentColor; margin-left: 4px; }
.ev-player.is-playing .ev-player__big { opacity: 0; pointer-events: none; transform: scale(.9); }

/* Полоса управления: видна на паузе и при наведении, уезжает во время
   просмотра — кадру ничего не мешает. */
.ev-player__bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  background: linear-gradient(transparent, rgba(2, 5, 11, .85));
  color: #fff;
  opacity: 1; transform: translateY(0);
  transition: opacity .18s, transform .18s;
}
.ev-player.is-playing .ev-player__bar { opacity: 0; transform: translateY(6px); }
.ev-player.is-playing:hover .ev-player__bar,
.ev-player.is-playing:focus-within .ev-player__bar { opacity: 1; transform: translateY(0); }

.ev-player__bar button {
  display: grid; place-items: center;
  width: 32px; height: 32px; flex: 0 0 auto;
  border: 0; border-radius: 8px;
  background: transparent; color: #fff; cursor: pointer;
  transition: background .12s;
}
.ev-player__bar button:hover { background: rgba(255, 255, 255, .16); }
.ev-player__bar svg { width: 20px; height: 20px; fill: currentColor; stroke: currentColor; stroke-width: 0; }
.ev-player__bar [data-act="full"] svg,
.ev-player__bar .i-mute { fill: none; stroke-width: 2; stroke-linecap: round; }

/* Пары значков «играет / на паузе» и «звук / без звука»: показываем нужный
   из пары по состоянию, отдельных классов на кнопках для этого не нужно. */
.ev-player .i-pause, .ev-player .i-mute { display: none; }
.ev-player.is-playing .i-play { display: none; }
.ev-player.is-playing .i-pause { display: block; }
.ev-player.is-muted .i-sound { display: none; }
.ev-player.is-muted .i-mute { display: block; }

.ev-player__time {
  font-variant-numeric: tabular-nums;
  font-size: 13px; opacity: .9; flex: 0 0 auto;
}

/* Ползунок перемотки — обычный input[type=range]: перетаскивание, клавиатура
   и доступность достаются от браузера, красить остаётся только вид. */
.ev-player__seek {
  flex: 1 1 auto; min-width: 0;
  appearance: none; -webkit-appearance: none;
  height: 4px; border-radius: 2px;
  background: linear-gradient(to right,
    #fff var(--ev-progress, 0%), rgba(255, 255, 255, .3) var(--ev-progress, 0%));
  cursor: pointer;
}
.ev-player__seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 13px; height: 13px; border-radius: 50%;
  background: #fff; border: 0;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .5);
}
.ev-player__seek::-moz-range-thumb {
  width: 13px; height: 13px; border-radius: 50%;
  background: #fff; border: 0;
}

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

   Ни размеров шрифта, ни цвета текста здесь не задано специально: подпись
   наследует их от блока, поэтому раздел «Текст» в настройках работает. */

.ev-audio {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 14px;
  background: var(--color-surface-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--layout-radius);
}

/* Как и у кнопки, значения читаются из переменных с запасными: незаданная
   настройка означает вид по умолчанию. Переменные объявляет карточка —
   инлайновым стилем до вложенной картинки не дотянуться. */
.ev-audio__cover {
  width: var(--ev-cover-size, 56px);
  height: var(--ev-cover-size, 56px);
  flex: 0 0 auto;
  border-radius: var(--ev-cover-radius, calc(var(--layout-radius) - 2px));
  object-fit: var(--ev-cover-fit, cover);
  filter: var(--ev-cover-shadow, none);
  background: var(--color-border);
}

/* Значения читаются из переменных с запасными: незаданная настройка блока
   означает вид по умолчанию, а не пустоту. Сами переменные объявляет карточка
   инлайном — до вложенных элементов и до псевдоэлементов ползунка иначе не
   дотянуться. */
.ev-audio__play {
  display: grid; place-items: center;
  width: var(--ev-play-size, 44px); height: var(--ev-play-size, 44px);
  flex: 0 0 auto;
  border: 0; border-radius: var(--ev-play-radius, 50%);
  background: var(--ev-play-bg, var(--color-accent));
  color: var(--ev-play-fg, var(--color-accent-contrast));
  cursor: pointer;
  transition: transform .12s, filter .12s;
}
.ev-audio__play:hover { transform: scale(1.06); filter: brightness(1.08); }
/* Значок вполовину кнопки: при её увеличении он обязан расти вместе с ней,
   иначе крупная кнопка выглядит пустой. */
.ev-audio__play svg {
  width: calc(var(--ev-play-size, 44px) / 2);
  height: calc(var(--ev-play-size, 44px) / 2);
  fill: currentColor;
}
/* У кнопки воспроизведения значок сдвинут: у треугольника центр тяжести
   левее геометрического центра, и без сдвига он выглядит смещённым. */
.ev-audio__play .i-play { margin-left: 3px; }

.ev-audio__body { flex: 1 1 auto; min-width: 0; }

.ev-audio__title {
  font-weight: 600;
  margin: 0 0 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.ev-audio__row { display: flex; align-items: center; gap: 10px; }

.ev-audio__time {
  font-variant-numeric: tabular-nums;
  font-size: 13px; opacity: .65; flex: 0 0 auto;
}

.ev-audio__mute {
  display: grid; place-items: center;
  width: 34px; height: 34px; flex: 0 0 auto;
  border: 0; border-radius: 8px;
  background: transparent; color: inherit; opacity: .6;
  cursor: pointer; transition: opacity .12s, background .12s;
}
.ev-audio__mute:hover { opacity: 1; background: rgba(0, 0, 0, .06); }
.ev-audio__mute svg { width: 20px; height: 20px; fill: currentColor; }
.ev-audio__mute .i-mute { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

/* Пары значков — по состоянию, как и у видео. */
.ev-audio .i-pause, .ev-audio .i-mute { display: none; }
.ev-audio.is-playing .i-play { display: none; }
.ev-audio.is-playing .i-pause { display: block; }
.ev-audio.is-muted .i-sound { display: none; }
.ev-audio.is-muted .i-mute { display: block; }

/* Пройденная часть закрашивается градиентом, а не отдельным элементом:
   у input[type=range] нет портируемого способа покрасить «до бегунка», а
   доля проигранного всё равно известна скрипту — он кладёт её в --ev-progress. */
.ev-audio__seek {
  flex: 1 1 auto; min-width: 0;
  appearance: none; -webkit-appearance: none;
  height: var(--ev-track-h, 4px);
  border-radius: calc(var(--ev-track-h, 4px) / 2);
  background: linear-gradient(to right,
    var(--ev-play-bg, var(--color-accent)) var(--ev-progress, 0%),
    var(--ev-track, #D1D5DB) var(--ev-progress, 0%));
  cursor: pointer;
}
/* Бегунок растёт вместе с полосой: на восьмипиксельной полосе
   тринадцатипиксельный кружок выглядит утонувшим. */
.ev-audio__seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: calc(var(--ev-track-h, 4px) + 9px);
  height: calc(var(--ev-track-h, 4px) + 9px);
  border-radius: 50%;
  background: var(--ev-play-bg, var(--color-accent));
  border: 2px solid var(--color-surface);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .25);
}
.ev-audio__seek::-moz-range-thumb {
  width: calc(var(--ev-track-h, 4px) + 9px);
  height: calc(var(--ev-track-h, 4px) + 9px);
  border-radius: 50%;
  background: var(--ev-play-bg, var(--color-accent));
  border: 2px solid var(--color-surface);
}

/* Узкая колонка: обложка и подпись остаются, а карточка перестраивается —
   на телефоне четыре элемента в ряд не помещаются. */
@media (max-width: 480px) {
  .ev-audio { flex-wrap: wrap; }
  .ev-audio__body { flex-basis: 100%; order: 3; }
}

/* ─── Меню ─────────────────────────────────────────────────────────────
   Значения читаются из переменных с запасными: незаданная настройка блока
   означает вид по умолчанию. Объявляет их сам <nav> — инлайновым стилем до
   вложенных ссылок не дотянуться. */

.ev-menu__list {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--ev-menu-gap, 20px);
  list-style: none; margin: 0; padding: 0;
}
.ev-menu--col .ev-menu__list { flex-direction: column; align-items: flex-start; }

.ev-menu__link {
  display: inline-block;
  padding: var(--ev-menu-pad, 0);
  border-radius: var(--ev-menu-radius, 8px);
  color: var(--ev-menu-fg, var(--color-text));
  text-decoration: none;
  transition: color .12s, background .12s;
}
.ev-menu__link:hover { color: var(--ev-menu-hover, var(--color-accent)); }

/* Текущая страница: цвет и фон — по настройкам, насыщенность — всегда.
   Одного цвета мало: при слабом зрении и на чёрно-белой печати он не читается,
   а начертание видно всегда. */
.ev-menu__link.is-current {
  color: var(--ev-menu-current, var(--color-accent));
  background: var(--ev-menu-current-bg, transparent);
  font-weight: 600;
}

/* ── Раздел с подразделами ──────────────────────────────────────────
   <details> вместо всегда раскрытого списка: полоса навигации иначе
   растёт на высоту всех подразделов и перестаёт быть полосой. */

.ev-menu__item { position: relative; }

.ev-menu__summary {
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; user-select: none;
  list-style: none; /* убираем родной треугольник браузера… */
}
.ev-menu__summary::-webkit-details-marker { display: none; } /* …и его же в WebKit */

/* Свой указатель: он поворачивается при раскрытии, поэтому сразу видно, что
   раздел открыт, — родной треугольник этого не показывает в строке. */
.ev-menu__summary::after {
  content: ''; width: 6px; height: 6px; flex: 0 0 auto;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .15s;
}
.ev-menu__drop[open] > .ev-menu__summary::after { transform: translateY(1px) rotate(-135deg); }

/* Выпадающий список НАКРЫВАЕТ страницу, а не раздвигает её: иначе при каждом
   раскрытии всё содержимое ниже прыгает вниз. */
.ev-menu__sub {
  position: absolute; z-index: 20; top: calc(100% + 8px); left: 0;
  display: flex; flex-direction: column;
  gap: calc(var(--ev-menu-gap, 20px) / 2);
  min-width: max(100%, 180px);
  list-style: none; margin: 0; padding: 10px 12px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--layout-radius);
  box-shadow: 0 8px 24px rgba(2, 5, 11, .12);
}
.ev-menu__link--sub { font-size: .9em; }

/* В колонке накрывать нечего — меню и так вертикальное, поэтому подразделы
   раскрываются на месте, со сдвигом вправо. */
.ev-menu--col .ev-menu__sub {
  position: static; margin: 6px 0 0; padding: 0 0 0 14px;
  background: none; border: 0; box-shadow: none; min-width: 0;
}

/* На узком экране выпадающий список упёрся бы в край. Там он тоже
   раскрывается на месте — прыжок содержимого меньшее зло, чем панель,
   уехавшая за границу экрана. */
@media (max-width: 640px) {
  .ev-menu__sub {
    position: static; margin: 6px 0 0; padding: 0 0 0 14px;
    background: none; border: 0; box-shadow: none; min-width: 0;
  }
}

/* Черновик виден ТОЛЬКО в редакторе — на сайте таких пунктов нет вовсе.
   Пунктир и приглушённость говорят «этой страницы посетитель не увидит». */
.ev-menu__link.is-draft {
  opacity: .5;
  text-decoration: underline dashed;
  text-underline-offset: 3px;
}

/* ─── Контакты ─────────────────────────────────────────────────────────
   Как и у остальных составных блоков, значения читаются из переменных с
   запасными: их объявляет сам <address> настройками блока — инлайновым
   стилем до вложенных строк не дотянуться.

   Ни фона, ни полей, ни скругления здесь НЕТ: они приходят заготовкой
   блока и стоят в инспекторе, где их видно и можно стереть. */

.ev-contacts {
  display: flex;
  flex-direction: var(--ev-ct-dir, column);
  /* Перенос всегда: в строку строки контактов не влезают на узком экране, а
     без переноса они выдавливают карточку за край. */
  flex-wrap: wrap;
  gap: var(--ev-ct-gap, 14px);
  font-style: normal; /* <address> курсивит по умолчанию — не наш выбор */
}

/* Заголовок и ссылка на карту занимают всю строку и в горизонтальной
   раскладке: заголовок посреди адреса и телефона читается как ещё одна
   строка контактов, а не как заголовок. */
.ev-contacts__title,
.ev-contacts__map { flex-basis: 100%; }

.ev-contacts__title { font-weight: 600; margin: 0; }

.ev-contacts__row { display: flex; align-items: flex-start; gap: 12px; }

.ev-contacts__icon {
  width: var(--ev-ct-icon-size, 20px);
  height: var(--ev-ct-icon-size, 20px);
  flex: 0 0 auto; margin-top: 2px;
  color: var(--ev-ct-icon, var(--color-accent));
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

.ev-contacts__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.ev-contacts__label {
  font-size: .75em; line-height: 1.4;
  color: var(--ev-ct-label, var(--color-text-muted));
}

.ev-contacts__value { overflow-wrap: anywhere; }

.ev-contacts__link { color: inherit; text-decoration: none; }
.ev-contacts__link:hover { color: var(--ev-ct-icon, var(--color-accent)); }

.ev-contacts__map {
  align-self: flex-start;
  color: var(--ev-ct-icon, var(--color-accent));
  text-decoration: none; font-weight: 500;
}
.ev-contacts__map:hover { text-decoration: underline; }


/* ─── Блок «Шапка» ─────────────────────────────────────────────────────
   Значения читаются из переменных с запасными: незаданная настройка блока
   означает вид по умолчанию, а не пустоту. */

.ev-hd {
  display: flex; align-items: center;
  gap: var(--ev-hd-gap, 24px);
  flex-wrap: wrap;
  /* Линия ТОЛЬКО снизу: общая настройка «Толщина рамки» рисует рамку со всех
     сторон сразу, и полосу под шапкой ею не задать. */
  border-bottom: 1px solid var(--ev-hd-line, transparent);
}
/* «Закрепить при прокрутке» вешается на ОБЁРТКУ блока, а не на него самого.
   position: sticky прижимает элемент только В ПРЕДЕЛАХ РОДИТЕЛЯ, а родитель
   у блока — section.block ровно по высоте шапки: закрепляться негде, и
   полоса уезжает вместе с ней. Липкой должна стать коробка, которая тянется
   на всю страницу, — область шапки сайта либо секция в потоке страницы.

   :has() позволяет сделать это, не заводя блоку способа дотянуться до своей
   обёртки: правило принадлежит теме и смотрит на содержимое. */
.site-header:has(.ev-hd.is-sticky),
.block:has(> .ev-hd.is-sticky) { position: sticky; top: 0; z-index: 50; }

/* Три расположения — переключаются одной переменной, без правки разметки. */
.ev-hd { justify-content: space-between; }
.ev-hd[style*="--ev-hd-layout:center"] { justify-content: center; text-align: center; }
.ev-hd[style*="--ev-hd-layout:stack"] { flex-direction: column; align-items: flex-start; }

/* Меню слева, знак по центру полосы, действие справа.

   Знак прижимается к середине не порядком элементов, а absolute: иначе его
   положение зависело бы от длины меню и от того, есть ли кнопка, — и середина
   уезжала бы при каждой правке состава меню. */
.ev-hd[style*="--ev-hd-layout:mark-center"] {
  position: relative;
  justify-content: flex-start;
}
.ev-hd[style*="--ev-hd-layout:mark-center"] .ev-hd__brand {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
}
.ev-hd[style*="--ev-hd-layout:mark-center"] .ev-hd__action { margin-left: auto; }

/* На узком экране знак ПО ЦЕНТРУ не работает: меню проходит прямо сквозь
   него. Возвращаем обычный порядок — знак слева, меню за ним, кнопка справа.

   Граница — 1024, а не 700, как было. Замер 14 сентября: между 701 и 1000
   меню из восьми пунктов длиннее левой половины полосы при любых разумных
   промежутках, и знак стоял поверх «Решений» и «Продуктов», а «Контакты»
   переезжали на вторую строку. Прежний сайт на 1024 тоже показывает кнопку
   «Меню» вместо строки пунктов. Граница обязана совпадать с границей кнопки
   ниже: иначе в промежутке знак встанет на место, а меню ещё будет строкой. */
@media (max-width: 1024px) {
  .ev-hd[style*="--ev-hd-layout:mark-center"] { flex-wrap: wrap; }
  .ev-hd[style*="--ev-hd-layout:mark-center"] .ev-hd__brand {
    position: static; transform: none;
  }
  .ev-hd[style*="--ev-hd-layout:mark-center"] .ev-hd__nav {
    order: 3; flex-basis: 100%;
  }
}

/* Зачин абзаца — цветом акцента. Приём с прежнего сайта: первая фраза лида
   набрана фирменным фиолетовым, продолжение обычным цветом, и обе части идут
   ОДНОЙ строкой. Двумя блоками так не собрать: они встали бы двумя абзацами. */
.ev-accent-head { color: var(--color-accent); }

/* ─── Кнопка-меню на узком экране ──────────────────────────────────────
   Восемь пунктов в строку телефона не влезают: меню переносилось на три ряда
   и вместе с ними шапка занимала 247 пикселей — 29% экрана до первой строки
   содержимого.

   Переключатель — ФЛАЖОК, хотя подразделы этого же меню сделаны на <details>,
   и однородность требовала бы того же. Причина в том, чем оборачивается
   отказ. Содержимое закрытого <details> прячет САМ БРАУЗЕР, и вернуть его
   правилом display нельзя — проверено в браузере: у закрытого <details>
   высота содержимого 0, помогает только ::details-content, а он появился в
   Chrome 131, Safari 18.4 и Firefox 139. В браузере постарше меню исчезло бы
   и на ШИРОКОМ экране — сайт остался бы без навигации вовсе. У флажка отказ
   обратный: display:none приходит из этой таблицы, и если она не применилась,
   меню просто видно всегда, как было до правки.

   Скрипта по-прежнему нет: политика содержимого запрещает встроенные скрипты,
   и меню обязано работать без них. */

/* Не display:none и не hidden: так флажок перестаёт получать фокус, и по
   шапке нельзя пройти клавишей. Убираем с глаз, оставляя в порядке обхода. */
.ev-hd__toggle {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none; margin: 0;
}
.ev-hd__burger { display: none; }
/* А на широком экране флажок не нужен вовсе: меню раскрыто, кнопки «Меню»
   нет, и Tab приводил на невидимый флажок без имени (замер axe-core). Граница
   — та же 1024, что у кнопки ниже. */
@media (min-width: 1025px) {
  .ev-hd__toggle { display: none; }
}

/* Граница кнопки «Меню» — та же, что у знака по центру выше (1024, как у
   прежнего сайта). Разойтись им нельзя: в промежутке между ними шапка либо
   показала бы знак слева рядом с развёрнутым меню, либо спрятала бы меню, не
   вернув знак на место. Совпадение держит тест. */
@media (max-width: 1024px) {
  .ev-hd__burger {
    display: inline-flex; align-items: center; gap: 8px;
    flex: 0 0 auto; cursor: pointer; user-select: none;
    padding: 0 4px; min-height: 44px; /* наименьшая цель для пальца */
    font-size: var(--ev-menu-size, 13px);
    color: var(--ev-menu-fg, var(--color-text));
  }
  /* Три черты: средняя — сам элемент, крайние — его псевдоэлементы. */
  .ev-hd__burger-lines { position: relative; }
  .ev-hd__burger-lines,
  .ev-hd__burger-lines::before,
  .ev-hd__burger-lines::after {
    content: ''; display: block;
    width: 18px; height: 2px; background: currentColor;
  }
  .ev-hd__burger-lines::before { position: absolute; top: -6px; }
  .ev-hd__burger-lines::after  { position: absolute; top: 6px; }

  /* След фокуса: сам флажок с глаз убран, и без этого правила переход
     клавишей по шапке был бы невидим. */
  .ev-hd__toggle:focus-visible ~ .ev-hd__burger {
    outline: 2px solid currentColor; outline-offset: 2px; border-radius: 4px;
  }

  .ev-hd .ev-hd__nav { display: none; }
  .ev-hd__toggle:checked ~ .ev-hd__nav { display: block; }

  /* Раскрытое меню — столбец во всю ширину и В ПОТОКЕ, а не накрывающая
     панель: шапка липкая, и панель поверх страницы потребовала бы z-index
     поверх её собственного, а при раскрытии подраздела ещё и обрезалась бы
     по высоте шапки. В потоке она просто отодвигает содержимое вниз. */
  .ev-hd__toggle:checked ~ .ev-hd__nav .ev-menu__list {
    flex-direction: column; align-items: flex-start;
    gap: 4px; padding: 8px 0 4px;
  }
  .ev-hd__toggle:checked ~ .ev-hd__nav .ev-menu__link { padding: 8px 0; }
  /* Подраздел раскрывается НА МЕСТЕ: выпадающая панель внутри столбца
     накрыла бы соседние пункты. */
  .ev-hd__toggle:checked ~ .ev-hd__nav .ev-menu__sub {
    position: static; margin: 4px 0 0; padding: 0 0 0 14px;
    background: none; border: 0; box-shadow: none; min-width: 0;
  }
}

/* Кнопка справа в шапке: та же пилюля, что и на страницах. */
.ev-hd__action {
  flex: 0 0 auto;
  display: inline-flex; align-items: center;
  padding: 8px 20px;
  border-radius: 100px;
  background: var(--ev-hd-action-bg, #251737);
  color: var(--ev-hd-action-fg, #fff);
  font-size: 14px; line-height: 1.29;
  text-decoration: none;
  transition: opacity var(--ev-hover-speed, .2s);
}
.ev-hd__action:hover { opacity: .85; }

.ev-hd__brand {
  display: inline-flex; align-items: center; gap: 12px;
  color: inherit; text-decoration: none; min-width: 0;
}
.ev-hd__logo {
  width: var(--ev-hd-logo, 40px); height: var(--ev-hd-logo, 40px);
  flex: 0 0 auto; object-fit: contain;
}
.ev-hd__title {
  font-size: var(--ev-hd-title, 20px);
  font-weight: 600; line-height: 1.2;
}
.ev-hd__nav { min-width: 0; }

/* ─── Блок «Карточка» ──────────────────────────────────────────────────
   Карточкой целиком может быть ссылка, поэтому оформление висит на корне,
   каким бы тегом он ни оказался. */

.ev-card {
  display: flex; flex-direction: column;
  gap: var(--ev-card-gap, 10px);
  color: inherit; text-decoration: none;
  min-width: 0;
}
.ev-card__img {
  width: 100%;
  aspect-ratio: var(--ev-card-ratio, 4 / 3);
  object-fit: var(--ev-card-fit, cover);
  border-radius: var(--ev-card-img-radius, 10px);
  display: block;
}
.ev-card__title {
  font-size: var(--ev-card-title, 20px);
  color: var(--ev-card-title-color, inherit);
  font-weight: 600; line-height: 1.25;
}
.ev-card__text { line-height: 1.5; }

/* Отклика на курсор здесь НЕТ, и это не забывчивость.
   Раньше тема сама приподнимала карточку-ссылку и красила заголовок — а в
   разделе «При наведении» стояли пустые поля. Автор видел движение и не
   находил его ни в одной настройке: ровно та шаблонность, от которой мы
   избавлялись в блоках.
   Теперь сдвиг и плавность приходят ЗАГОТОВКОЙ блока и стоят в инспекторе —
   их видно, правят и стирают. */

/* ─── Блок «Полоса с призывом» ─────────────────────────────────────────
   Ни цветов, ни полей здесь нет: они приходят заготовкой блока и стоят в
   инспекторе. Тема отвечает только за раскладку частей. */

.ev-cta {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--ev-cta-gap, 20px);
  justify-content: flex-start;
}

/* Текст занимает ВСЮ строку, а кнопка переносится под него. Иначе блок
   текста сжимался по содержимому, полоса центрировала эту узкую коробку, и
   «Выравнивание: слева» было нечего выравнивать — текст всё равно оставался
   посередине. Теперь горизонтальное положение текста решает ровно одна
   настройка: «Выравнивание» в разделе «Текст». */
.ev-cta__body {
  flex: 1 1 100%;
  display: flex; flex-direction: column; gap: 6px; min-width: 0;
}

/* «Расположение» решает только, ГДЕ кнопка. */
.ev-cta[style*="--ev-cta-layout:center"] { justify-content: center; }
.ev-cta[style*="--ev-cta-layout:split"] { justify-content: space-between; }
.ev-cta[style*="--ev-cta-layout:split"] .ev-cta__body { flex: 1 1 320px; }
.ev-cta__title {
  margin: 0; font-weight: 700; line-height: 1.2;
  font-size: var(--ev-cta-title, 28px);
}
/* Прозрачности здесь НЕТ намеренно. Она тут была — тема гасила пояснение на
   десять процентов, и заданный автором цвет текста получался не тем, что он
   выбрал в поле. Ровно та шаблонность, от которой уходит вся система: и
   «Цвет текста», и «Прозрачность» есть в инспекторе, и приглушить пояснение
   автор волен сам, видя это в настройке. */
.ev-cta__text { margin: 0; }

.ev-cta__btn {
  flex: 0 0 auto;
  display: inline-block;
  padding: var(--ev-cta-btn-pad, 14px) calc(var(--ev-cta-btn-pad, 14px) * 1.8);
  border-radius: var(--ev-cta-btn-radius, 8px);
  background: var(--ev-cta-btn-bg, #FFFFFF);
  color: var(--ev-cta-btn-fg, var(--color-accent));
  font-weight: 600; text-decoration: none;
  /* Только смена цвета, без движения: цвет под курсором — НАСТРОЙКА, её
     видно в инспекторе, а приподнимание было правилом темы, которого автор
     не нашёл бы ни в одном поле. */
  transition: background .15s;
}
.ev-cta__btn:hover {
  background: var(--ev-cta-btn-hover, var(--ev-cta-btn-bg, #FFFFFF));
}

/* ─── Блок «Текст с иллюстрацией» ──────────────────────────────────────
   Части переносятся САМИ: flex-wrap плюс минимальная ширина у каждой. На
   узком экране картинка и текст встают друг под другом без брейкпоинтов. */

.ev-sp {
  display: flex; flex-wrap: wrap;
  flex-direction: var(--ev-sp-dir, row);
  align-items: var(--ev-sp-align, center);
  gap: var(--ev-sp-gap, 32px);
}
.ev-sp__img {
  flex: 1 1 var(--ev-sp-share, 50%);
  min-width: 260px;
  aspect-ratio: var(--ev-sp-ratio, 4 / 3);
  object-fit: cover;
  border-radius: var(--ev-sp-radius, 12px);
  display: block; width: 100%;
}
.ev-sp__body {
  flex: 1 1 300px; min-width: 260px;
  display: flex; flex-direction: column; gap: 12px;
}
.ev-sp__title {
  margin: 0; font-weight: 700; line-height: 1.2;
  font-size: var(--ev-sp-title, 28px);
}
.ev-sp__text { margin: 0; line-height: 1.6; }
.ev-sp__link { align-self: flex-start; font-weight: 500; text-decoration: none; }
.ev-sp__link:hover { text-decoration: underline; }

/* ─── Блок «Карусель фотографий» ───────────────────────────────────────
   Прокрутка родная, с прилипанием: свайп на телефоне и жест трекпада
   работают без единой строки кода. Скрипт нужен только стрелкам. */

.ev-gal { position: relative; }

.ev-gal__strip {
  display: flex;
  gap: var(--ev-gal-gap, 16px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Полосу прокрутки прячем: лента листается свайпом и стрелками, а серая
     черта под снимками только мешает смотреть. */
  scrollbar-width: none;
}
.ev-gal__strip::-webkit-scrollbar { display: none; }
/* Лента в обходе клавишей (tabindex в шаблоне): без стрелок иначе снимки
   дальше первого экрана клавиатуре недоступны. Попав в неё, человек должен
   видеть, где он, — рамка внутрь, чтобы не обрезалась соседней полосой. */
.ev-gal__strip:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* Кадр — <figure> со снимком и подписью. Ширина, пропорции и скругление
   общие на всю ленту: набор разной формы выглядит рваным. */
.ev-gal__item {
  flex: 0 0 var(--ev-gal-w, 320px);
  scroll-snap-align: start;
  margin: 0; min-width: 0;
  display: flex; flex-direction: column; gap: 8px;
}
.ev-gal__img {
  width: 100%;
  aspect-ratio: var(--ev-gal-ratio, 4 / 3);
  object-fit: var(--ev-gal-fit, cover);
  border-radius: var(--ev-gal-radius, 12px);
  display: block;
}
.ev-gal__cap {
  font-size: var(--ev-gal-cap-size, 14px);
  color: var(--ev-gal-cap-color, var(--color-text-muted));
  line-height: 1.4;
}

/* ─── Рамка окна программы (настройка «Рамка окна программы») ──────────
   Скрин интерфейса без рамки — белая таблица на белой странице без краёв.
   Рамка рисуется на самом <img>, без лишней разметки: полоса сверху — это
   внутренний отступ, в нём виден фон элемента, а точки — три круга
   градиентом по этому фону. Картинка при этом остаётся одной <img> со своим
   srcset, а пропорции кадра считаются по рамке целиком (border-box), так
   что ряд скринов в рамке и без неё выравнивается по одной линейке.
   Скругление обрезает и сам снимок: у замещаемого элемента содержимое
   режется по внутреннему радиусу. */
.ev-img--window,
.ev-gal--window .ev-gal__img {
  box-sizing: border-box;
  padding-top: 26px;
  border: 1px solid rgba(37, 23, 55, .12);
  border-radius: 10px;
  background:
    radial-gradient(circle at 16px 13px, #D3CFDA 4px, transparent 4.5px),
    radial-gradient(circle at 30px 13px, #D3CFDA 4px, transparent 4.5px),
    radial-gradient(circle at 44px 13px, #D3CFDA 4px, transparent 4.5px),
    #F2F1F5;
  background-repeat: no-repeat;
  box-shadow: 0 1px 2px rgba(37, 23, 55, .06), 0 20px 40px -20px rgba(37, 23, 55, .35);
}
/* Лента обрезает всё, что за её краем, — и тень под кадром тоже. */
.ev-gal--window .ev-gal__strip { padding-bottom: 24px; }

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

   Различается ровно одно — переменная фона, потому что настройка «Цвет
   стрелок» у каждой карусели своя. Двойного запасного значения
   (var(--a, var(--b, …))) здесь быть не должно: карусель фотографий внутри
   слайда карусели-контейнера — законная вложенность, и переменная внешней
   протекла бы во внутреннюю.

   Область действия «гашения у края» тоже остаётся РАЗДЕЛЬНОЙ по той же
   причине: класс at-end внешней ленты не должен гасить стрелку вложенной. */
.ev-gal__arrow,
.ev-slider__arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 5;
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 0; border-radius: 50%;
  color: var(--color-text);
  box-shadow: 0 2px 10px rgba(2, 5, 11, .18);
  cursor: pointer;
  transition: opacity .15s;
}
.ev-gal__arrow { background: var(--ev-gal-arrow-bg, #FFFFFF); }
.ev-slider__arrow { background: var(--ev-sl-arrow-bg, #FFFFFF); }

.ev-gal__arrow svg,
.ev-slider__arrow svg {
  width: 20px; height: 20px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.ev-gal__arrow--prev,
.ev-slider__arrow--prev { left: 8px; }
.ev-gal__arrow--next,
.ev-slider__arrow--next { right: 8px; }

/* Стрелка гаснет у своего края: нажимать её там незачем. */
.ev-gal.at-start .ev-gal__arrow--prev,
.ev-gal.at-end .ev-gal__arrow--next,
.ev-slider.at-start .ev-slider__arrow--prev,
.ev-slider.at-end .ev-slider__arrow--next { opacity: 0; pointer-events: none; }

/* На узком экране лента листается пальцем, и стрелки только закрывают кадр. */
@media (max-width: 640px) {
  .ev-gal__arrow,
  .ev-slider__arrow { display: none; }

  /* И кадр не шире самого экрана.

     Ширину кадра задаёт автор (по умолчанию 420 пикселей — под колонку
     настольного макета), и на телефоне шириной 390 снимок не помещался
     НИКОГДА: правый край срезан у каждого кадра, и не видно, что он
     срезан — лента и должна выходить за край.

     Так же поступает лента карточек: на узком экране она встаёт в одну
     колонку независимо от настройки. Это не оформление вместо автора, а
     предел, за которым его настройка перестаёт что-либо значить. */
  .ev-gal__item { flex-basis: min(var(--ev-gal-w, 320px), 100%); }
}

/* «За кадрами»: лента и кнопки встают в ряд, и место под кнопки отводится
   честно. Сдвиг наружу отрицательным отступом не годится — у края экрана
   такая кнопка уезжает за границу и становится недоступной. */
.ev-gal[style*="--ev-gal-arrows:outside"] {
  /* Перенос обязателен: без него точки-указатели не уходят на свою строку, а
     сжимаются в тот же ряд справа от стрелки. */
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
/* База НОЛЬ, а не auto: перенос строк во flex решается по базовому размеру,
   а не по итоговому. С базой по содержимому лента «не влезает» и уезжает на
   свою строку раньше, чем успевает сжаться, — стрелки оказываются над и под
   ней вместо боков. */
.ev-gal[style*="--ev-gal-arrows:outside"] .ev-gal__strip { flex: 1 1 0; min-width: 0; }
.ev-gal[style*="--ev-gal-arrows:outside"] .ev-gal__arrow {
  position: static; transform: none; flex: 0 0 auto;
}
/* Кнопка «назад» стоит в разметке ПОСЛЕ ленты — ей место слева. */
.ev-gal[style*="--ev-gal-arrows:outside"] .ev-gal__arrow--prev { order: -1; }

/* ─── Блок «Карусель-контейнер» ────────────────────────────────────────
   Слайд — это вложенный блок целиком, поэтому кадром служит его обычная
   section.block. Прокрутка родная, с прилипанием. */

.ev-slider { position: relative; }

.ev-slider__strip {
  display: flex;
  /* Без промежутка: слайды во всю ширину, и зазор между ними в кадр не
     попадает — в нём всегда ровно один слайд. */
  gap: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.ev-slider__strip::-webkit-scrollbar { display: none; }

/* Слайд — колонка, чтобы содержимое можно было прижать к краю или поставить
   посередине. Без выбранного положения — stretch, то есть блок во всю ширину,
   как и было: настройка ничего не меняет, пока её не тронули. */
.ev-slider__strip > .block {
  /* Всегда во всю ширину: слайд здесь — самостоятельная страница, а не кадр
     ленты. Дробная ширина превращала бы карусель в подглядывание следующего
     слайда, для чего есть «Карусель фотографий». */
  flex: 0 0 100%;
  scroll-snap-align: start;
  min-width: 0;
  display: flex; flex-direction: column;
  align-items: var(--ev-sl-align, stretch);
  justify-content: center;
}

/* Вид стрелок — выше, общим набором с каруселью фотографий. Здесь только то,
   что у ленты слайдов своё. */

/* «За кадрами» — тем же приёмом, что и у карусели фотографий: лента и кнопки
   встают в ряд, место под кнопки отводится честно. */
.ev-slider[style*="--ev-sl-arrows:outside"] {
  /* Перенос обязателен: без него точки-указатели не уходят на свою строку. */
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.ev-slider[style*="--ev-sl-arrows:outside"] .ev-slider__strip { flex: 1 1 0; min-width: 0; }
.ev-slider[style*="--ev-sl-arrows:outside"] .ev-slider__arrow {
  position: static; transform: none; flex: 0 0 auto;
}
.ev-slider[style*="--ev-sl-arrows:outside"] .ev-slider__arrow--prev { order: -1; }
/* Точки в ряду со стрелками заняли бы место сбоку — им положена своя строка. */
.ev-slider[style*="--ev-sl-arrows:outside"] .ev-slider__dots { flex-basis: 100%; order: 3; }
/* То же у карусели фотографий: в ряду со стрелками точкам не место. */
.ev-gal[style*="--ev-gal-arrows:outside"] .ev-gal__dots { flex-basis: 100%; order: 3; }

/* Точки-указатели — общие для обеих каруселей: разметку им строит один и тот
   же скрипт, и два одинаковых набора правил разошлись бы при первой правке. */
.ev-slider__dots,
.ev-gal__dots {
  display: flex; justify-content: center;
  margin-top: 4px;
}
/* Скрипт прячет ряд атрибутом hidden — при одном кадре и когда кадров больше
   двенадцати. Но браузерное [hidden] { display: none } слабее любого правила
   по классу, и display: flex выше его перебивало: ряд НЕ прятался никогда.
   На выкаченном сайте это выглядело так: 35 точек у галереи «Музея Жукова»
   сжимались до нуля–двух пикселей в серую полоску — ровно то, от чего предел
   должен был избавить. А когда у точки появилась минимальная ширина, та же
   полоска вылезла за экран и дала прокрутку вбок на одиннадцати страницах.
   Совпадение атрибута и этого правила держит тест. */
.ev-slider__dots[hidden],
.ev-gal__dots[hidden] { display: none; }
/* Точка — это КНОПКА 24×24, а видимый кружок 8×8 нарисован внутри неё.
   Раньше кнопкой был сам кружок: 10×10 с шагом 17, и замер на телефоне
   показал, что по точке листают все каталоги — а попасть пальцем в десять
   пикселей нельзя, нажатие уходит соседке или в пустоту. 24 — нижняя граница
   цели для пальца по WCAG 2.5.8; расстояние между кружками при этом осталось
   прежним на глаз, потому что его теперь задаёт ширина кнопки, а не gap.

   Кнопке разрешено сжиматься (flex 0 1): у карусели до двенадцати точек, и
   двенадцать по 24 — это 288 пикселей, шире колонки на экране в 320. Лучше
   чуть тесные цели, чем ряд, вылезающий за край. Отступ сверху уменьшен на
   столько же, насколько выросла кнопка: иначе ряд уехал бы от снимков. */
.ev-dot {
  flex: 0 1 24px; min-width: 16px; height: 24px; padding: 0;
  display: inline-grid; place-items: center;
  border: 0; background: none;
  cursor: pointer;
}
.ev-dot::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%;
  background: var(--color-border-strong, #D1D5DB);
  transition: background .15s, transform .15s;
}
.ev-dot.is-on::before {
  background: var(--ev-dot, var(--color-accent));
  transform: scale(1.25);
}
.ev-dot:focus-visible { outline: 2px solid var(--ev-dot, var(--color-accent)); outline-offset: -4px; border-radius: 50%; }

/* ─── Кадр с пропорцией занимает место ДО загрузки ─────────────────────

   Блок «Картинка» с выбранной пропорцией пишет её инлайн, а ширину не
   задаёт. У картинки, которая ещё не загрузилась, собственной ширины нет, и
   кадр был шириной 0 — значит, и высотой 0. Снимки ниже первого экрана
   грузятся отложенно, поэтому при прокрутке каждый появлялся из ничего и
   толкал текст под пальцем: замер 14 сентября нашёл 321 такой кадр из 816
   на 68 страницах. Метрика «при загрузке» этого почти не видит — сдвиги
   случаются позже, во время прокрутки.

   Кадр с пропорцией — это кадр во всю колонку, так он и выглядел после
   загрузки: сравнение раскладочной ширины со страницами до правки нашло
   единственное отличие — снимки косой ленты на телефоне стояли в своём
   натуральном размере, 390 в колонке 398. Ширина, заданная автором в
   инспекторе, пишется инлайн и это правило перебивает.

   Селектор по атрибуту, а не по классу: инлайн-пропорцию у <img> пишет
   только этот блок, у карточек и каруселей она задаётся переменными. */
img[style*="aspect-ratio"] { width: 100%; }

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

   Картинка лежит абсолютно, а не в потоке: она фон по роли, но <img> по
   разметке — так у неё остаются alt, приоритет загрузки и место в выдаче
   поисковика (см. комментарий в шаблоне блока).

   Высота задаётся min-height, а не height: длинный лид обязан растянуть
   экран, а не вылезти за него. */
.ev-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: var(--ev-hero-align, flex-end);
  gap: var(--ev-hero-gap, 24px);
  overflow: hidden;
}
.ev-hero[style*="--ev-hero-layout:cover"],
.ev-hero[style*="--ev-hero-layout:bottom"] { min-height: var(--ev-hero-min-h, 560px); }

/* «Название по центру» — первый экран страницы проекта: крупное название
   посреди затемнённого фото, над ним раздел и год.

   Название не шире 1080 и переносится РОВНЫМИ строками (balance): без предела
   оно шло во всю ширину окна, и на 1440 последнее слово повисало одно на
   второй строке. Тень под буквами — страховка на светлых местах кадра;
   главную работу делает затемнение, у этого вида оно по умолчанию 0.5.

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

   Фон должен быть БЕЗ надписей: белое название поверх экранов с текстом
   сливается при любом затемнении (замер на странице музея космоса). */
.ev-hero[style*="--ev-hero-layout:centered"] {
  min-height: var(--ev-hero-min-h, 85vh);
  justify-content: center;
  text-align: center;
}
.ev-hero[style*="--ev-hero-layout:centered"] .ev-hero__body {
  align-items: center;
  width: 100%;
  max-width: 1080px;
  margin-inline: auto;
  gap: 16px;
}
.ev-hero[style*="--ev-hero-layout:centered"] .ev-hero__title {
  font-size: var(--ev-hero-title, 56px);
  line-height: 1.08;
  text-wrap: balance;
  text-shadow: 0 2px 24px rgba(0, 0, 0, .35);
}
.ev-hero[style*="--ev-hero-layout:centered"] .ev-hero__kicker {
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  opacity: .85;
}
.ev-hero[style*="--ev-hero-layout:centered"] .ev-hero__lead {
  font-size: var(--ev-hero-lead, 18px);
  line-height: 1.45;
  max-width: 56ch;
  text-wrap: pretty;
}
.ev-hero[style*="--ev-hero-layout:centered"] .ev-hero__shade { opacity: var(--ev-hero-shade, .5); }

.ev-hero__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* Точка кадра задаётся в настройках первого экрана (hero_focus). */
  object-position: var(--ev-hero-pos, center);
  z-index: 0;
}
/* Заглавное видео встаёт тем же слоем, что снимок (.ev-hero__img), и
   своего размера не задаёт. Отличие одно: это фон, а не проигрыватель, и
   нажатие по нему не должно ничего включать — останавливают его кнопкой. */
.ev-hero__video { pointer-events: none; }

/* Кнопка паузы заглавного видео. В правом нижнем углу, над затемнением и
   текстом: её должно быть видно на любом кадре, поэтому своя подложка. 44 —
   норма попадания пальцем. Значок рисуется рамками: шрифтовые ▶ и ❚❚ в
   разных системах разной ширины и цвета. */
.ev-hero__pause {
  position: absolute; right: 16px; bottom: 16px; z-index: 3;
  width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, .45); cursor: pointer;
}
.ev-hero__pause::before {
  content: ''; position: absolute; left: 16px; top: 14px;
  width: 4px; height: 16px; border-left: 4px solid #fff; border-right: 4px solid #fff;
  box-sizing: content-box;
}
.ev-hero__pause.is-paused::before {
  left: 17px; top: 13px; width: 0; height: 0;
  border-style: solid; border-width: 9px 0 9px 14px;
  border-color: transparent transparent transparent #fff;
}
.ev-hero__pause:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* «Кадр целиком» — вертикальный снимок или ролик по центру без обрезки, по
   бокам его размытое продолжение. Фон — отдельный слой той же картинки
   (у ролика — обложки), размытый и притемнённый; кадр поверх него вписан
   целиком (contain). Раньше такие поля «запекали» в файл обложки — теперь это
   настройка, и исходный кадр остаётся исходным.

   Порядок слоёв — порядком в разметке (фон раньше кадра) при одинаковом
   z-index: отрицательный увёл бы фон под подложку страницы. scale, а не
   transform: размытие у краёв светлеет, и слой чуть больше экрана прячет это
   за его границу, не трогая transform, которым hero.js ведёт масштаб кадра. */
.ev-hero__backdrop {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0; pointer-events: none;
  filter: blur(40px) brightness(.55) saturate(1.1);
  scale: 1.15;
}
.ev-hero__img--whole { object-fit: contain; }

/* Затемнение — свой слой поверх снимка и под текстом. Прозрачность нуль
   означает «без затемнения», и слой тогда ничего не делает, а не исчезает:
   убирать его из разметки ради этого пришлось бы шаблону, и настройка
   перестала бы включаться обратно без перезагрузки страницы. */
.ev-hero__shade {
  position: absolute; inset: 0;
  background: #000;
  opacity: var(--ev-hero-shade, 0);
  z-index: 1;
}
/* Плексус — холст во всю полосу под текстом. Цвет сети — цвет текста
   экрана (currentColor): на белом фоне тёмный текст даёт тёмную сеть, и
   второй настройки цвета, которую забыли бы согласовать, не нужно. Нажатия
   проходят сквозь него к форме. */
.ev-hero__plexus {
  position: absolute; inset: 0; width: 100%; height: 100%;
  z-index: 0; pointer-events: none;
}
.ev-hero__body { position: relative; z-index: 2; display: flex; flex-direction: column;
  gap: var(--ev-hero-gap, 24px); align-items: flex-start; }

/* Выравнивание текста первого экрана тянет за собой и сам столбец.

   Без этого «по центру» в инспекторе давало странное: заголовок и лид
   оставались у левого края, а текст внутри них ездил по своей ширине —
   настройка выглядела применённой и не делала того, что обещает. Тот же приём
   с чтением инлайнового стиля, что и у раскладки первого экрана выше. */
.ev-hero[style*="text-align:center"] .ev-hero__body { align-items: center; }
.ev-hero[style*="text-align:right"] .ev-hero__body { align-items: flex-end; }
.ev-hero__title {
  font-size: var(--ev-hero-title, 32px);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
/* Надзаголовок первого экрана: мельче названия и приглушён — он подводка,
   а не заголовок. Нижнее поле маленькое: пара «род — имя» читается как одно
   целое, и большой зазор разбил бы её на два сообщения. */
.ev-hero__kicker {
  margin: 0 0 8px;
  font-size: 14px;
  opacity: .75;
}

.ev-hero__lead {
  font-size: var(--ev-hero-lead, 28px);
  line-height: 1.2;
  max-width: 46ch;
}
.ev-hero__btn {
  display: inline-block;
  padding: var(--ev-hero-btn-pad, 17px) calc(var(--ev-hero-btn-pad, 17px) * 2.8);
  background: var(--ev-hero-btn-bg, #FFFFFF);
  color: var(--ev-hero-btn-fg, #251737);
  border-radius: var(--ev-hero-btn-radius, 100px);
  text-decoration: none;
  transition: background var(--ev-hover-speed, .3s);
}
.ev-hero__btn:hover { background: var(--ev-hero-btn-hover, #F7F7F7); }

/* Текст слева, фото справа: картинка выходит из абсолютного слоя в колонку
   рядом. Сетка, а не flex — колонки обязаны быть равными независимо от
   длины текста. */
@media (min-width: 900px) {
  .ev-hero[style*="--ev-hero-layout:split"] {
    display: grid; grid-template-columns: 1fr 1fr; align-items: center;
  }
  .ev-hero[style*="--ev-hero-layout:split"] .ev-hero__img {
    /* Снимок возвращается в поток колонкой рядом с текстом — закрепление и
       ширина во весь экран тут не при чём. */
    position: static; order: 2; width: auto; height: 100%; transform: none;
  }
  .ev-hero[style*="--ev-hero-layout:split"] .ev-hero__shade { display: none; }
}
/* ── Заглавная картинка стоит на месте, содержимое наезжает ─────────

   Замер прежнего сайта: снимок первого экрана там закреплён во весь экран
   (position:fixed, 100vw на 100vh, object-fit:cover), не прокручивается
   вместе со страницей и медленно уменьшается — масштаб от 1.3 к 1.0, — а
   следующий раздел наползает сверху. Масштаб задаёт hero.js переменной
   --ev-hero-zoom; без скрипта она равна единице, и приём работает всё равно.

   ЗАГЛАВНАЯ — это первый экран СТРАНИЦЫ, а не всякий первый экран со
   снимком. На главной их два: фотография во весь экран сверху и фотополоса
   ниже. Закрепить обе — значит показать вторую поверх всего, что стоит выше
   неё: закреплённый снимок рисуется по окну, а не по своему месту в потоке.

   Всё правило держится на :has(). Браузер, который его не понимает, получает
   прежний первый экран целиком — и это правильно: закрыть закреплённый
   снимок ему нечем, а фотография под текстом делает текст нечитаемым.
   Полприёма хуже, чем его отсутствие. */
.site-main > .block:first-of-type:has(.ev-hero__img) .ev-hero__img {
  position: fixed;
  top: 0; left: 0;
  width: 100vw; height: 100vh;
  transform: scale(var(--ev-hero-zoom, 1));
  will-change: transform;
}
/* Единицы динамической высоты там, где они есть: на телефоне адресная строка
   то появляется, то прячется, и 100vh на ней означает «выше экрана». */
@supports (height: 100dvh) {
  .site-main > .block:first-of-type:has(.ev-hero__img) .ev-hero__img { height: 100dvh; }
}
/* Затемнение ходит вместе со снимком: уехав отдельно, оно затемняло бы уже не
   снимок, а следующий раздел. */
.site-main > .block:first-of-type:has(.ev-hero__img) .ev-hero__shade {
  position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
}
/* Размытый фон «Кадра целиком» стоит вместе с кадром: уехав с прокруткой,
   он оставил бы кадр на голой подложке. */
.site-main > .block:first-of-type:has(.ev-hero__img) .ev-hero__backdrop {
  position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
}
/* Содержимое ПОСЛЕ заглавного экрана непрозрачно и лежит выше: снимок никуда
   не уезжает, и без этого он просвечивал бы сквозь весь текст страницы. Фон
   ставится обёртке блока, а не его содержимому: раздел со своим фоном
   закрасит её сам. flow-root держит отступы детей ВНУТРИ обёртки: иначе
   нижний отступ заголовка в полосе без нижнего поля схлопывается наружу, и
   между двумя белыми разделами остаётся прозрачная щель со снимком в ней. */
.site-main > .block:first-of-type:has(.ev-hero__img) ~ .block,
.site-footer {
  position: relative;
  z-index: 1;
  display: flow-root;
  background: var(--color-surface);
}
/* Закрепляется только снимок-ФОН. В раскладках «Текст слева, фото справа» и
   «Текст под фото» снимок — часть содержимого: колонка рядом с текстом или
   строка над ним. Правило закрепления сильнее их по селектору, и без этой
   оговорки заглавный экран с такой раскладкой уводил снимок во весь экран
   под текст, а затемнение у этих раскладок выключено — белый заголовок
   оставался на голой фотографии. Вертикальному ролику нужна как раз колонка. */
.site-main > .block:first-of-type .ev-hero[style*="--ev-hero-layout:bottom"] .ev-hero__img {
  position: static; width: 100%; height: auto; transform: none; will-change: auto;
}
@media (min-width: 900px) {
  .site-main > .block:first-of-type .ev-hero[style*="--ev-hero-layout:split"] .ev-hero__img {
    position: static; width: auto; height: 100%; transform: none; will-change: auto;
  }
}

/* ── Снимок направления, проступающий под ссылкой ────────────────────

   На первом экране прежней главной четыре направления стоят поверх фото, и
   наведение на любое сменяет фотографию под ним. Замер прежнего сайта: четыре
   снимка лежат слоями, три с прозрачностью 0, переход opacity 0.3s, анимации
   нет вовсе — то есть это НЕ перелистывание, а именно смена по наведению.

   Слой лежит ВНУТРИ ссылки, поэтому им правит обычный `a:hover img`: ни
   :has(), ни скрипта, ни правила, знающего про соседей.

   Почему fixed, а не absolute. Ссылка лежит в .ev-hero__body, а у него
   position: relative — absolute привязался бы к текстовой колонке, а не к
   экрану.

   Опора у слоя — САМО ОКНО, и первый экран трансформацию себе больше не
   ставит. Ставил: она делала его опорой для fixed-потомков и заодно обрезала
   слой по первому экрану. Но ровно этим она ломала бы закреплённый снимок —
   тот тоже fixed, и с трансформацией у предка он перестал бы стоять на месте
   и поехал бы вместе со страницей. Приём владелец просил именно на главной,
   а слой наведения живёт только там же — то есть выбор был между ними, а не
   рядом.

   Потери нет: слой виден только пока на ссылку наведена мышь, а навести её
   можно лишь пока первый экран на экране. Стоят снимок и слой теперь по
   одной опоре — окну, — и не разъезжаются при прокрутке.

   Затемнение снимку не достаётся: он лежит выше слоя тени, внутри тела
   экрана. Поэтому та же доля снимается яркостью — для чёрной плёнки с
   прозрачностью α это в точности одно и то же (цвет × (1 − α)), и берётся
   она из ТОЙ ЖЕ настройки, а не из второй, которую забыли бы согласовать. */

/* <picture> вокруг слоя наведения не должен создавать свою коробку: сам слой
   позиционирован fixed и в потоке не участвует, а пустая строчная обёртка
   добавила бы ссылке высоту строки. display:contents убирает её из раскладки,
   оставляя ребёнка на прежнем месте. */
.ev-link__hover-box { display: contents; }

/* Вне первого экрана настройка не делает ничего: всплывающий во весь блок
   снимок у ссылки посреди текста был бы поломкой, а не видом. */
.ev-link__hover { display: none; }
.ev-hero .ev-link__hover {
  display: block;
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  filter: brightness(calc(1 - var(--ev-hero-shade, 0)));
  transition: opacity var(--ev-hover-speed, 0.3s);
  pointer-events: none;
}
.ev-hero a:hover .ev-link__hover,
.ev-hero a:focus-visible .ev-link__hover { opacity: 1; }

/* Подпись поднимается над снимком: оба лежат в одной ссылке, и без этого
   текст закрыло бы фотографией. */
.ev-link__label { position: relative; }

/* Кому движение мешает — тому смена мгновенная, а не отменённая: снимок
   направления это содержимое, а не украшение. */
@media (prefers-reduced-motion: reduce) {
  .ev-hero .ev-link__hover { transition: none; }
}

/* Текст под фото: снимок в потоке, текст за ним, затемнение не нужно. */
.ev-hero[style*="--ev-hero-layout:bottom"] .ev-hero__img { position: static; height: auto; }
.ev-hero[style*="--ev-hero-layout:bottom"] .ev-hero__shade { display: none; }

/* ─── Цифры ─────────────────────────────────────────────────────────────

   auto-fit с minmax, а не жёсткое число колонок: заданное автором значение
   остаётся верхним пределом, а на узком экране ряд перестраивается сам, без
   отдельного правила под каждый размер. */
.ev-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--ev-stats-gap, 32px);
}
/* Две ступени, а не одна. Раньше с 900 сразу ставилось столько колонок,
   сколько задал автор, — и четыре цифры в полуколонке «О нас» и главной не
   помещались до ~1040: колонка `1fr` не уже своего содержимого, а самое
   длинное в ячейке — слово «международные» плюс отступ у линии, 122 пикселя.
   Сетка вылезала за экран, и страница прокручивалась вбок на 900–1000.

   Промежуточная ступень — две колонки, а не «сколько влезет»: у четырёх
   цифр «сколько влезет» на 1024 дало бы три и одну под ними. 1200 — ширина,
   с которой полуколонка вмещает четыре цифры с запасом (568 против 494). */
@media (min-width: 900px) {
  .ev-stats { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1200px) {
  .ev-stats { grid-template-columns: repeat(var(--ev-stats-cols, 4), 1fr); }
}
.ev-stats__item {
  display: flex; flex-direction: column; gap: 16px;
  /* Линия слева, а не разделитель между ячейками: у сетки его нет, а рамка
     каждой ячейки дала бы двойную линию посередине. Первой колонке линия
     снимается ниже. */
  padding-left: 20px;
  border-left: 1px solid var(--ev-stats-divider, transparent);
}
.ev-stats__item:first-child { padding-left: 0; border-left: 0; }
.ev-stats__value {
  margin: 0;
  font-size: var(--ev-stats-value, 48px);
  line-height: 1.125;
  color: var(--ev-stats-value-color, inherit);
  letter-spacing: -0.02em;
  /* Подпись стоит в разметке первой (см. шаблон), а на экране идёт второй. */
  order: 1;
}
.ev-stats__label {
  font-size: var(--ev-stats-label, 14px);
  line-height: 1.23;
  color: var(--ev-stats-label-color, inherit);
  order: 2;
}

/* ─── Логотипы ──────────────────────────────────────────────────────────

   Плитка держит пропорцию, а логотип вписывается в неё по высоте: файлы
   приходят и квадратными, и вытянутыми, и без общей высоты ряд выглядит
   рваным. */
.ev-logos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--ev-logos-gap, 16px);
  list-style: none;
}
@media (min-width: 900px) {
  .ev-logos { grid-template-columns: repeat(var(--ev-logos-cols, 5), 1fr); }
}
.ev-logos__tile {
  display: flex; align-items: center; justify-content: center;
  padding: var(--ev-logos-pad, 32px);
  background: var(--ev-logos-bg, #F7F7F7);
  aspect-ratio: var(--ev-logos-ratio, auto);
}
.ev-logos__img {
  max-height: var(--ev-logos-h, 40px);
  width: auto; max-width: 100%;
  object-fit: contain;
  filter: var(--ev-logos-gray, none);
}

/* ── Плитка, сменяющая логотипы ──────────────────────────────────────

   Замер прежнего сайта: окно высотой в одну ячейку с overflow: hidden,
   внутри дорожка колонкой, animation 10s linear infinite, колонки сдвинуты
   на 0,1 с друг от друга. Кадры не плавные, а ШАГОВЫЕ: логотип стоит две
   секунды, за полсекунды уезжает на ячейку, и так по кругу.

   Отличие от прежнего сайта одно, и оно намеренное. Там дорожка кончается
   пустотой: четыре ячейки, а последний шаг уводит на -560px, то есть за
   край, и круг замыкается рывком через пустое окно. У нас в конце дорожки
   стоит КОПИЯ первого логотипа — последний шаг приводит к ней, и мгновенный
   возврат в начало глазу неотличим.

   Высота ячейки берётся из пропорций плитки, а не из отдельной настройки:
   ширину плитке задаёт сетка, пропорции — уже имеющееся «Пропорции плитки»,
   и вторая настройка про высоту неминуемо разошлась бы с первой. */
.ev-logos__tile--cycle {
  display: block;
  overflow: hidden;
  padding: 0;
}
.ev-logos__track {
  display: flex;
  flex-direction: column;
  height: 300%;
  animation: ev-logos-cycle 5s linear infinite;
}
.ev-logos__cell {
  flex: 0 0 33.3333%;
  display: flex; align-items: center; justify-content: center;
  padding: var(--ev-logos-pad, 32px);
}
@keyframes ev-logos-cycle {
  0%, 40%  { transform: translateY(0); }
  50%, 90% { transform: translateY(-33.3333%); }
  100%     { transform: translateY(-66.6667%); }
}

/* Соседние плитки сменяются не разом: на прежнем сайте колонки сдвинуты на
   десятую долю секунды, и ряд «дышит», а не щёлкает целиком. */
.ev-logos__tile--cycle:nth-child(3n + 2) .ev-logos__track { animation-delay: 0.1s; }
.ev-logos__tile--cycle:nth-child(3n) .ev-logos__track { animation-delay: 0.2s; }

/* Кому движение мешает — тому первый логотип и покой. Список клиентов при
   этом не теряется: вторые имена читает диктор, они есть в разметке. */
@media (prefers-reduced-motion: reduce) {
  .ev-logos__track { animation: none; }
}

/* ── Наклонённый ряд ─────────────────────────────────────────────────

   Полоса работ на «Услугах» прежнего сайта идёт по диагонали. Замер: весь
   ряд повёрнут матрицей, которая раскладывается в rotate(-3deg), снимки
   573 пикселя друг от друга, и оттого каждый следующий на 30 пикселей выше —
   tan(3°) × 573 = 30. Никакой анимации и никаких пяти отдельных сдвигов.

   Поворот открыл бы по углам пустые треугольники, поэтому содержимому дано
   возмещение: оно шире блока и вылезает за него сверху и снизу, а блок
   обрезает лишнее.

   Возмещение задано в ПРОЦЕНТАХ, и это не вкусовщина. Процент у полей всегда
   считается от ШИРИНЫ родителя, а нужный вылет — это ровно половина ширины,
   умноженная на тангенс угла: tan(3°)/2 = 2,62%. Одно и то же число верно и
   на широком экране, и на телефоне, а «-37px» подошло бы одной ширине.

   Наклоняется ПЕРВЫЙ УРОВЕНЬ вложенности, а не сам блок: блок обязан
   остаться прямым, иначе обрезать наклонённое ему пришлось бы в своих же
   повёрнутых осях, и обрезка поехала бы вместе с содержимым. */
[style*="--ev-tilt:"] { overflow: hidden; }
[style*="--ev-tilt:"] > * {
  transform: rotate(var(--ev-tilt));
  width: 106%;
  margin: -2.62% -3%;
}

/* ─── Шаги ──────────────────────────────────────────────────────────────

   Линия НАД пунктом, а не между: над первым она тоже нужна — так секция
   отделяется от предыдущей, и ряд не выглядит висящим. */
.ev-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--ev-steps-gap, 48px);
  list-style: none;
}
@media (min-width: 900px) {
  .ev-steps { grid-template-columns: repeat(var(--ev-steps-cols, 3), 1fr); }
}
.ev-steps__item {
  display: flex; flex-direction: column; gap: 12px;
  padding-top: 20px;
  border-top: 1px solid var(--ev-steps-line, transparent);
}
.ev-steps__num {
  font-size: 13px;
  color: var(--ev-steps-num-color, inherit);
}
.ev-steps__title {
  font-size: var(--ev-steps-title, 20px);
  line-height: 1.2;
  color: var(--ev-steps-title-color, inherit);
}
.ev-steps__text {
  font-size: var(--ev-steps-text, 14px);
  line-height: 1.4;
  color: var(--ev-steps-text-color, inherit);
}

/* Название слева, описание справа — перечень услуг на прежнем сайте.

   Пункт становится сеткой из двух равных колонок, а сам список — одной
   колонкой: две колонки пунктов, в каждой ещё по две, дали бы четыре столбца
   текста поперёк экрана. Поэтому число колонок здесь задаётся правилом, а не
   остаётся за автором: настройка «Колонок» и настройка «в две колонки»
   противоречат друг другу, и разрешать противоречие должен не читатель. */
@media (min-width: 900px) {
  .ev-steps--split { grid-template-columns: 1fr !important; }
  .ev-steps--split .ev-steps__item {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 0; row-gap: 4px;
    /* По БАЗОВОЙ ЛИНИИ, а не по верху коробки. Кегли в колонках разные —
       название 16, цена 22, — и выравнивание по верху разводит сами строки
       текста на несколько пикселей: коробки стоят вровень, а буквы нет.
       Глазу видна именно строка, поэтому равнять надо её. */
    align-items: baseline;
  }
  /* Колонки идут ВПРИТЫК, как на прежнем сайте: в правой половине полосы
     шириной 688 это два столбца по 344, и описание начинается ровно на
     середине. Промежуток сдвигал бы описание и сужал оба столбца.

     Чтобы название и описание не сталкивались буквами, воздух даёт поле
     самого названия, а не промежуток сетки: поле не двигает границу столбца. */
  .ev-steps--split .ev-steps__title { padding-right: 20px; }
  .ev-steps--split .ev-steps__num { grid-column: 1 / -1; }
}

/* Сетка на узком экране — в одну колонку.

   !important здесь неизбежен: число колонок приходит инлайновым стилем от
   автора, и правило без него не действует. Тот же приём и по той же причине,
   что у правил наведения.

   700 пикселей — граница, за которой две колонки текста становятся двумя
   колонками по сорок знаков в строке, то есть нечитаемыми. */
@media (max-width: 700px) {
  .ev-grid { grid-template-columns: 1fr !important; }
}

/* Содержимое левой колонки не упирается в правую.

   Промежутка между колонками у двухколоночных разделов НЕТ намеренно: на
   прежнем сайте правая колонка начинается ровно с середины полосы, и
   промежуток сдвинул бы её на каждом развороте сайта. Расчёт был на то, что
   слева стоит один короткий заголовок со знаком, которому до середины далеко.

   Расчёт не оправдался: на главной слева стоит лид в две строки кеглем 28, и
   он доходит до самой середины — то есть впритык к правому столбцу. Читается
   это как слипшиеся колонки.

   Поэтому отступ ВНУТРИ колонки, а не между ними: граница столбцов остаётся
   на середине, как на прежнем сайте, а текст останавливается на 48 пикселей
   раньше. Правило общее — оно нужно всякой левой колонке, включая те, что
   соберёт редактор в админке.

   Только на широком экране: ниже 700 колонки встают друг под друга, и отступ
   справа стал бы просто кривым полем.

   Образец числа колонок написан целиком («repeat(2,minmax(0,1fr))»), а не
   обрывком «repeat(2,»: во-первых, так он не поймает сетку на три колонки с
   тем же началом, во-вторых — у обрывка не закрыта скобка, и проверка темы
   справедливо считает такой селектор разорванным. */
@media (min-width: 701px) {
  .ev-grid[style*="repeat(2,minmax(0,1fr))"] > .block:first-child { padding-right: 48px; }
  /* Отступ нужен ТЕКСТУ, а не снимку. В паре картинок он делал левую на 48
     пикселей уже правой — на странице проекта это видно сразу, пары там на
     каждом шагу. Отмена отдельным правилом, а не условием в правиле выше:
     браузер без :has() её просто пропустит и оставит прежний отступ.

     Только у колонки, где снимок и НЕТ текста. Первая версия снимала отступ
     у любой колонки с картинкой — и на «О нас» и главной лид, под которым
     стоит снимок, упёрся в правый столбец (владелец: «слишком близко»). */
  .ev-grid[style*="repeat(2,minmax(0,1fr))"] > .block:first-child:has(img, video):not(:has(p, h1, h2, h3, h4, li)) { padding-right: 0; }
}

/* Крупный шрифт на экране поуже.

   Автор выбирает кегль заголовка для НАСТОЛЬНОГО экрана: 48 у названия
   страницы, 32 у названия раздела. Дальше кегль убавляется ступенями — и
   ступеней ДВЕ, а не одна.

   Так у прежнего сайта, и это снято не с одной страницы, а со всех его
   правил разом: на ≤1024 крупные заголовки уменьшаются (44 → 32, 32 → 28),
   на ≤640 ещё раз (32 → 20). Одна наша ступень на 700 оставляла планшет и
   небольшой ноутбук с настольными кеглями — а это самый частый экран между
   телефоном и монитором.

   Границы взяты те же: 1024 и 640. Величины — только из именованной шкалы
   (32, 28, 20), потому что «на глаз чуть меньше» — это и есть тот способ,
   которым в вёрстке заводятся двадцать шесть разных кеглей.

   !important и здесь неизбежен по той же причине, что у сетки: кегль
   приходит инлайновым стилем от автора, и правило без него не действует.

   Подвал ступени слушается НАРАВНЕ с телом страницы. Сначала он был из них
   исключён — считалось, что он «набран своими размерами». Замер на 390 это
   опроверг: заголовки подвала («Бесплатная консультация», «Контакты») набраны
   теми же 32px, что и заголовки разделов, и на телефоне подвал становился
   КРУПНЕЕ названия самой страницы — 32 против 28. Самый большой текст на
   экране оказывался у призыва в подвале, а не у того, ради чего страницу
   открыли.

   Шапка ступеней не слушается, и вот почему это не та же ошибка: заголовков
   уровня h1–h2 в ней нет вовсе — там знак, меню 13-м кеглем и кнопка. */
@media (max-width: 1024px) {
  .site-main h1, .site-footer h1 { font-size: 32px !important; }
  .site-main h2, .site-footer h2 { font-size: 28px !important; }
}
@media (max-width: 640px) {
  .site-main h1, .site-footer h1 { font-size: 28px !important; }
  .site-main h2, .site-footer h2 { font-size: 20px !important; }
  /* Направления на первом экране главной (44px): на телефоне они вставали
     столбиком по одному и занимали весь первый экран — галерея проектов под
     ними начиналась ниже сгиба. 28 ставит их в две строки по два. */
  .ev-hero__body a[style*="font-size:44px"] { font-size: 28px !important; }
}

/* Знак раздела: кружок с радужным градиентом и белым ромбом внутри.

   Им на 8vision.ru отмечено начало каждого раздела. Нарисован стилем, без
   файла: круг, градиент и повёрнутый на 45° квадрат внутри. Картинкой он был
   бы ещё одним файлом, который надо не потерять при переносе темы.

   Градиент снят с оригинала — четыре точки от зелёного к пурпурному через
   синий. Он единственное место на сайте, где цвет не из фирменной пары, и
   поэтому бросается в глаза даже в 36 пикселей. */
.ev-marked {
  display: flex; align-items: center; gap: 12px;
}
.ev-mark {
  flex: 0 0 auto;
  position: relative;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: linear-gradient(115deg, #3FFF35 0%, #298CD2 36%, #3832EB 70%, #DD1BAC 100%);
}
.ev-mark::after {
  content: "";
  position: absolute; left: 50%; top: 50%;
  width: 16px; height: 16px;
  margin: -8px 0 0 -8px;
  background: #fff;
  transform: rotate(45deg);
}

/* Есть в разметке, нет на странице.
   Не display:none и не visibility:hidden — те убирают текст и от экранного
   диктора тоже, а он-то как раз должен его прочитать. Приём стандартный:
   элемент в один пиксель с обрезкой содержимого. */
.ev-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Подсказка под полем формы: что именно примут. Мельче подписи и приглушена —
   это уточнение, а не второе название поля.

   Приглушается ЦВЕТ САМОЙ ФОРМЫ, а не берётся серый из палитры. Та же
   причина, что у подписи согласия ниже: форма живёт и на белой странице, и
   поверх фиолетового снимка, где текст белый. Серый из палитры годится
   только для первого случая — на снимке он сливается с фоном (замер: 1,8 к
   одному, а когда серый подняли до #767676 ради белого фона, стало 1,05,
   то есть подсказка исчезла бы совсем).

   Запасное правило строкой выше — для браузеров без color-mix: там
   останется прежний серый. */
.ev-form__hint {
  display: block;
  margin-top: 6px;
  font-size: 12px;
  color: var(--color-text-muted);
  color: color-mix(in srgb, currentColor 72%, transparent);
}

/* Подпись про телефон и почту: правило «одно из двух» разметкой не
   выражается, поэтому оно сказано словами. Тем же кеглем, что подсказки у
   полей, и без верхнего отступа — она идёт сразу под парой полей. */
.ev-form__note {
  margin: 0;
  font-size: 12px;
  color: var(--color-text-muted);
  color: color-mix(in srgb, currentColor 72%, transparent);
}
.ev-form__field input[type="file"] {
  font-size: 13px;
  padding: 8px 0;
}

/* Полоса отбора над лентой.

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

   Выбранный вариант отмечен заливкой, а не одним лишь цветом текста: цвет —
   единственный признак читается плохо при слабом зрении и вовсе пропадает
   при чёрно-белой печати. */
.ev-feed-filter {
  display: flex; flex-direction: column; gap: 12px;
  margin-bottom: 32px;
}
.ev-feed-filter__row {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 20px;
}
.ev-feed-filter__label {
  font-size: 13px;
  color: var(--color-text-muted);
  margin-right: 4px;
}
/* Варианты — ПРОСТОЙ ТЕКСТ, без рамок и заливки.

   Обведённые пилюли читались как кнопки, а полоса — как панель управления;
   на прежнем сайте это строка вида «Все /29  Выставки /6  Музеи /10», и
   выбранное отличается от остального только цветом. Разница не косметическая:
   рамки делали полосу тяжелее сетки, ради которой она и стоит. */
.ev-feed-filter__item {
  font-size: 14px;
  text-decoration: none;
  color: var(--color-text-muted);
  transition: color .2s ease;
}
.ev-feed-filter__item:hover { color: var(--color-text); }
.ev-feed-filter__item.is-current { color: var(--color-text); }
/* Число всегда бледнее названия, даже у выбранного: это подпись к варианту, а
   не второе название. */
.ev-feed-filter__count { color: var(--color-text-muted); }
.ev-feed-empty {
  font-size: 14px;
  color: var(--color-text-muted);
  margin: 0 0 24px;
}

/* ─── Лента карточек ────────────────────────────────────────────────────

   Ссылка занимает карточку целиком и сама раскладывает содержимое: так
   область нажатия совпадает с тем, что видно, а не с одной подписью. */
.ev-feed {
  display: grid;
  /* 256 — не круглое число, а сумма: самое длинное слово названия (128,
     «Contemporary»), промежуток 16 и подпись «/2023 — Museums» (110), которая
     не переносится. При 240 на телефоне в альбомной ориентации лента вставала
     в три колонки по 247, и подпись вылезала из карточки на 7–8 пикселей на
     пятнадцати страницах. То же число стоит в правиле для широкого экрана
     ниже — иначе карточка сузилась бы там, где его уже нет.

     auto-fill, а не auto-fit: auto-fit схлопывает пустые колонки, и одна
     карточка в «Похожих проектах» раздела из двух работ вставала квадратом
     во всю полосу — 1392 пикселя на 1440. */
  grid-template-columns: repeat(auto-fill, minmax(256px, 1fr));
  gap: var(--ev-feed-gap, 32px);
  list-style: none;
}
/* Колонок столько, сколько задал автор, но МЕНЬШЕ, если карточке становится
   тесно. Раньше с 900 ставилось ровно столько, сколько задано, а карточка
   не уже своего содержимого: названия с длинным словом и подписи, которая
   не переносится. Четыре карточки влезали только с ~1020, и на 900–1000
   лента на двадцати страницах уезжала за экран.

   Приём — колонка «не уже 256 и не уже доли от N колонок»: пока доля шире
   256, колонок ровно N; когда уже — auto-fill ставит столько, сколько влезает
   по 256 (откуда 256 — см. правило выше). Считается от ширины САМОЙ ленты, а
   не окна: лента бывает и во всю полосу, и в колонке, и граница по окну была
   бы верна только для одного из этих мест. */
@media (min-width: 900px) {
  .ev-feed {
    grid-template-columns: repeat(auto-fill, minmax(max(256px,
      calc((100% - (var(--ev-feed-cols, 4) - 1) * var(--ev-feed-gap, 32px)) / var(--ev-feed-cols, 4))), 1fr));
  }
}
/* Две колонки на телефоне — настройка «Колонок на телефоне». Для коротких
   подборок: «Похожие проекты» из четырёх квадратов столбиком занимали на
   390 пикселях 1650 — полтора экрана прокрутки ради четырёх ссылок.

   Карточка при этом ~160 пикселей, а 256 выше взято ровно под название
   рядом с неразрывной припиской. Поэтому приписка уходит ПОД название, а
   название чуть мельче: крупный шрифт в узкой колонке рвёт слова на слоги.
   Опора — строка в атрибуте style, как у первого экрана: значение
   переменной CSS не умеет менять направление строки. */
@media (max-width: 899px) {
  .ev-feed[style*="--ev-feed-cols-phone:2"] {
    grid-template-columns: repeat(auto-fill,
      minmax(min(256px, calc((100% - var(--ev-feed-gap, 32px)) / 2)), 1fr));
  }
  .ev-feed[style*="--ev-feed-cols-phone:2"] .ev-feed__row {
    flex-direction: column; gap: 4px;
  }
  .ev-feed[style*="--ev-feed-cols-phone:2"] .ev-feed__title {
    font-size: min(var(--ev-feed-title, 20px), 16px);
  }
}
.ev-feed__link {
  display: flex; flex-direction: column; gap: 12px;
  text-decoration: none; color: inherit;
}

/* Название и приписка в одну строку: название слева, год с разделом справа.

   Приписка не сжимается и не переносится (flex: 0 0 auto плюс nowrap): она
   короткая и служит опорой для глаза — у всех карточек ряда она стоит на
   одной вертикали. Название переносится свободно. */
.ev-feed__row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; width: 100%;
}
.ev-feed__img {
  width: 100%;
  aspect-ratio: var(--ev-feed-ratio, 1 / 1);
  object-fit: cover;
  /* Приподнимание карточки под курсором — НАСТРОЙКА блока (раздел «При
     наведении»), а не правило темы. Здесь только плавность самой картинки:
     без неё перерисовка при наведении выглядит рывком. */
  transition: opacity var(--ev-hover-speed, .3s);
}
.ev-feed__link:hover .ev-feed__img { opacity: .88; }

/* Знак заказчика поверх снимка: спокойная карточка его не показывает, под
   курсором он проступает за треть секунды.

   Занимает ровно место снимка, а не всей карточки: подпись под снимком должна
   остаться читаемой. Отсюда та же пропорция, что у картинки, и привязка к
   верху ссылки.

   Ссылке при этом нужен position: relative — он объявлен здесь, а не в
   настройках блока: это не оформление, а способ положить один слой на другой. */
.ev-feed__link { position: relative; }
.ev-feed__logo {
  position: absolute; top: 0; left: 0;
  width: 100%; aspect-ratio: var(--ev-feed-ratio, 1 / 1);
  object-fit: cover;
  opacity: 0;
  transition: opacity var(--ev-hover-speed, .3s);
  pointer-events: none;
}
.ev-feed__link:hover .ev-feed__logo { opacity: 1; }

/* Под знаком — затемнение и матовое стекло. Знак белый, а снимок пёстрый:
   голым поверх фотографии он читался только на тёмных кадрах (владелец:
   «текст не видно»). Слой ложится ровно на место снимка, под знак, и только
   у карточек со знаком — без знака затемнять нечего. Фиолетовый — цвет
   бренда (#251737), а не чёрный: затенённый кадр остаётся в тоне сайта. */
.ev-feed__link:has(.ev-feed__logo)::before {
  content: ""; position: absolute; top: 0; left: 0;
  width: 100%; aspect-ratio: var(--ev-feed-ratio, 1 / 1);
  background: rgba(37, 23, 55, .55);
  -webkit-backdrop-filter: blur(8px) saturate(.8);
  backdrop-filter: blur(8px) saturate(.8);
  opacity: 0;
  transition: opacity var(--ev-hover-speed, .3s);
  pointer-events: none;
  /* Порядок слоёв задан явно: снимок под курсором полупрозрачен (.88), а
     прозрачность выносит его в свой слой поверх всего, что раньше в
     разметке, — без z-index затемнение оказывалось ПОД снимком. */
  z-index: 1;
}
.ev-feed__link:has(.ev-feed__logo):hover::before { opacity: 1; }
.ev-feed__link .ev-feed__logo { z-index: 2; }
/* Кому движение мешает — показываем знак и затемнение сразу, без проявления. */
@media (prefers-reduced-motion: reduce) {
  .ev-feed__logo,
  .ev-feed__link:has(.ev-feed__logo)::before { transition: none; }
}

/* ── Стили текста («Стиль текста» у блока «Текст») ──────────────────────

   Именованное оформление: блок хранит имя, кегль и интервал живут здесь.
   Поменять лид проектов на всех восьмидесяти страницах — одна строка тут, а
   не восемьсот правок абзацев. Встроенных размеров у блока со стилем нет
   (их не выводит Instance.Style), поэтому !important не нужен.

   Ступень на телефоне — та же логика, что у заголовков ниже: крупный лид в
   24 на 390 занимал полэкрана. */
.ev-ts-lead { font-size: 24px; line-height: 1.25; font-weight: 500; letter-spacing: -0.01em; }
.ev-ts-body { font-size: 18px; line-height: 1.5; font-weight: 400; }
@media (max-width: 640px) {
  .ev-ts-lead { font-size: 20px; }
  .ev-ts-body { font-size: 16px; }
}

/* ── Галерея WebGL (лента с «Галерея WebGL», сцену рисует projects3d.js) ──

   Высота задана обёртке СРАЗУ, до скрипта: подмена списка сценой не двигает
   страницу. Без скрипта или без WebGL в той же высоте стоит обычная лента
   одной строкой, которую листают вбок, — не пусто и не сетка на три экрана.

   Со сценой список остаётся в разметке, но убран с глаз (как у ev-hidden):
   по нему ходят с клавиатуры, и фокус на ссылке подводит её карточку к
   середине. display:none выкинул бы ссылки и из порядка обхода. */
.ev-g3d {
  position: relative;
  width: 100%;
  height: var(--ev-g3d-h, clamp(420px, calc(100svh - 190px), 900px));
  overflow: hidden;
  background: var(--color-surface, #FFFFFF);
}
.ev-g3d:not(.is-3d) .ev-feed {
  display: flex; gap: 16px; height: 100%;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity;
}
.ev-g3d:not(.is-3d) .ev-feed__item { flex: 0 0 min(320px, 78vw); scroll-snap-align: start; }
.ev-g3d.is-3d .ev-feed {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* pan-y: вертикальный жест листает страницу, горизонтальный тянет ленту. */
.ev-g3d__canvas { position: absolute; inset: 0; display: block; touch-action: pan-y; cursor: grab; }
.ev-g3d__label {
  position: absolute; left: 0; top: 0; z-index: 2;
  display: flex; flex-direction: column; gap: 2px;
  max-width: 320px; padding: 10px 14px; border-radius: 12px;
  background: rgba(255, 255, 255, .94); color: var(--color-ink, #251737);
  box-shadow: 0 8px 30px rgba(37, 23, 55, .16);
  font-size: 15px; font-weight: 500; line-height: 1.3;
  pointer-events: none;
}
.ev-g3d__note { font-size: 13px; font-weight: 400; color: #767676; }

/* ─── «Анфилада 3D» (вид ленты, enfilade.js) ─────────────────────────────
   Устроена как галерея WebGL: высота у обёртки сразу, до скрипта; без
   WebGL — лента одной строкой вбок; со сценой список убран клипом, а не
   display:none (по ссылкам ходят с клавиатуры). Высота — та же настройка
   «Высота галереи»; по умолчанию — первый экран под шапкой.
   Подпись проекта, шкала номеров с залами и кнопки рисуются поверх сцены;
   кнопка «Вниз» есть и без сцены — к следующему блоку. */
.ev-enf {
  position: relative;
  width: 100%;
  height: var(--ev-g3d-h, clamp(480px, calc(100svh - 67px), 1100px));
  overflow: hidden;
  background: #EEEAF1;
  color: #251737;
  font-family: 'Inter Tight', 'Segoe UI', Arial, sans-serif;
}
.ev-enf:focus-visible { outline: 2px solid #9846FF; outline-offset: -4px; }
.ev-enf:not(.is-3d) .ev-feed {
  display: flex; gap: 16px; height: calc(100% - 72px); padding: 24px 24px 0;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity;
}
.ev-enf:not(.is-3d) .ev-feed__item { flex: 0 0 min(320px, 78vw); scroll-snap-align: start; }
.ev-enf.is-3d .ev-feed {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.ev-enf__canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; touch-action: pan-y; cursor: grab; }
.ev-enf__ui { position: absolute; inset: 0; pointer-events: none; }
/* Светлая дымка снизу: подпись и шкала читаются и на белом полу, и на воде. */
.ev-enf__ui::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 46%;
  background: linear-gradient(to top, rgba(238, 234, 241, .9), rgba(238, 234, 241, .55) 45%, rgba(238, 234, 241, 0));
  pointer-events: none;
}
.ev-enf__ui > * { pointer-events: auto; }
.ev-enf__cap {
  position: absolute; left: 28px; bottom: 112px; width: min(560px, calc(100% - 56px));
  display: grid; grid-template-columns: auto 1fr; column-gap: 20px; align-items: end;
  pointer-events: none;
}
.ev-enf__cap a { pointer-events: auto; }
.ev-enf__n { grid-row: span 3; font-size: clamp(56px, 7vw, 104px); font-weight: 500; line-height: .82; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.ev-enf__cap small { font-size: 12px; font-weight: 500; letter-spacing: .2em; text-transform: uppercase; color: #6F6A7A; }
.ev-enf__cap b { margin-top: 8px; font-size: clamp(18px, 1.8vw, 26px); font-weight: 500; line-height: 1.15; letter-spacing: -0.01em; text-wrap: balance; }
.ev-enf__cap a { margin-top: 10px; justify-self: start; color: #9846FF; text-decoration: none; font-size: 12px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase; }
.ev-enf__cap a:hover, .ev-enf__cap a:focus-visible { text-decoration: underline; }
.ev-enf__play {
  position: absolute; right: 24px; bottom: 112px; height: 36px; padding: 0 16px; border-radius: 36px; cursor: pointer;
  border: 1px solid rgba(37, 23, 55, .22); background: rgba(255, 255, 255, .62); color: #251737; backdrop-filter: blur(8px);
  font-family: inherit; font-size: 11px; font-weight: 500; line-height: 1; letter-spacing: .14em; text-transform: uppercase;
}
.ev-enf__bottom { position: absolute; left: 28px; right: 28px; bottom: 20px; }
.ev-enf__secs { position: relative; height: 22px; margin-bottom: 8px; }
.ev-enf__secs button {
  position: absolute; top: 0; height: 22px; padding: 0 0 0 8px; border: 0; border-left: 1px solid rgba(37, 23, 55, .22);
  background: none; color: #6F6A7A; cursor: pointer; white-space: nowrap;
  font-family: inherit; font-size: 11px; font-weight: 500; line-height: 22px; letter-spacing: .16em; text-transform: uppercase;
}
.ev-enf__secs button[aria-current="true"] { color: #251737; }
.ev-enf__rail { position: relative; height: 34px; }
.ev-enf__rail input { position: absolute; inset: 0; width: 100%; height: 34px; margin: 0; opacity: 0; cursor: pointer; }
.ev-enf__rail input:focus-visible + .ev-enf__track { outline: 2px solid #9846FF; outline-offset: 4px; border-radius: 4px; }
.ev-enf__track { position: absolute; inset: 0; pointer-events: none; }
.ev-enf__ticks { position: absolute; left: 0; right: 0; top: 0; height: 10px; }
.ev-enf__ticks i { position: absolute; top: 0; width: 1px; height: 6px; background: rgba(37, 23, 55, .22); }
.ev-enf__ticks i.maj { height: 10px; background: #6F6A7A; }
.ev-enf__fill { position: absolute; left: 0; top: 0; height: 2px; background: #9846FF; }
.ev-enf__cur { position: absolute; top: -3px; width: 3px; height: 16px; margin-left: -1px; background: #9846FF; border-radius: 2px; transition: left .15s; }
.ev-enf__nums { position: absolute; left: 0; right: 0; top: 16px; font-size: 11px; font-weight: 500; color: #6F6A7A; font-variant-numeric: tabular-nums; }
.ev-enf__nums span { position: absolute; transform: translateX(-50%); }
/* «Вниз» — по центру над шкалой; есть и без сцены. */
.ev-enf__down {
  position: absolute; left: 50%; bottom: 112px; transform: translateX(-50%); z-index: 3;
  display: inline-flex; align-items: center; gap: 8px; height: 40px; padding: 0 18px 0 20px; border-radius: 40px; cursor: pointer;
  border: 1px solid rgba(37, 23, 55, .22); background: rgba(255, 255, 255, .7); color: #251737; backdrop-filter: blur(8px);
  font-family: inherit; font-size: 12px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
}
.ev-enf__down svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; }
.ev-enf__down:hover, .ev-enf__play:hover { border-color: #9846FF; color: #9846FF; }
.ev-enf__down:focus-visible, .ev-enf__play:focus-visible, .ev-enf__secs button:focus-visible { outline: 2px solid #9846FF; outline-offset: 3px; }
@media (prefers-reduced-motion: no-preference) {
  .ev-enf__down svg { animation: ev-enf-bob 1.8s ease-in-out infinite; }
}
@keyframes ev-enf-bob { 50% { transform: translateY(3px); } }
@media (max-width: 760px) {
  .ev-enf__cap { left: 16px; bottom: 164px; width: calc(100% - 32px); column-gap: 14px; }
  .ev-enf__play { right: 16px; bottom: 104px; }
  .ev-enf__down { left: 16px; transform: none; bottom: 104px; }
  .ev-enf__bottom { left: 16px; right: 16px; }
  .ev-enf__secs button { font-size: 9px; letter-spacing: .08em; }
  .ev-enf__nums span:not(.keep) { display: none; }
}
.ev-feed__title {
  font-size: var(--ev-feed-title, 20px);
  line-height: 1.2;
  color: var(--ev-feed-title-color, inherit);
}
.ev-feed__note {
  flex: 0 0 auto;
  font-size: 13px;
  line-height: 1.23;
  white-space: nowrap;
  color: var(--ev-feed-note-color, inherit);
}
.ev-feed__text {
  font-size: 14px;
  line-height: 1.43;
  color: var(--ev-feed-note-color, #767676);
}

/* ─── Лента с ведущей карточкой ─────────────────────────────────────────

   Две колонки: слева одна карточка во всю высоту, справа остальные строками.
   Правая колонка — ВЛОЖЕННЫЙ список, а не соседние ячейки общей сетки:
   растянуть первую карточку на все ряды нечем, grid-row: 1 / -1 считает ряды
   явной сетки, а их здесь столько, сколько нашлось записей.

   На узком экране всё это отменяется правилом ниже: колонок нет, и ведущая
   карточка становится обычной. */
@media (min-width: 900px) {
  .ev-feed--lead {
    grid-template-columns: var(--ev-feed-lead-w, 1fr) 1fr;
    align-items: stretch;
  }
  .ev-feed__rest-list {
    display: flex; flex-direction: column;
    gap: var(--ev-feed-gap, 32px);
    list-style: none;
    height: 100%;
  }

  /* Ведущая: снимок заполняет карточку целиком, подпись лежит на нём внизу.
     Текст идёт обычным потоком с прижимом к низу, а не абсолютом: у названия
     бывает и одна строка, и три, и подгонять отступ снизу под их число
     значит промахиваться при каждом новом заголовке. */
  .ev-feed__item--lead .ev-feed__link {
    position: relative; height: 100%; min-height: 480px;
    justify-content: flex-end;
    padding: 40px; gap: 12px;
  }
  .ev-feed__item--lead .ev-feed__img {
    position: absolute; inset: 0;
    width: 100%; height: 100%; aspect-ratio: auto;
  }
  /* Затемнение — слоем между снимком и подписью. Отдельным элементом в
     разметке его заводить незачем: он ничего не значит и мешал бы наведению. */
  .ev-feed__item--lead .ev-feed__link::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(rgba(255,255,255,0) 40%, rgba(38,24,56,.5) 74%, #251737 100%);
  }
  .ev-feed__item--lead .ev-feed__row,
  .ev-feed__item--lead .ev-feed__text { position: relative; z-index: 3; }
  /* Снимок главной карточки — во всю карточку, и затемнение под знаком тоже. */
  .ev-feed__item--lead .ev-feed__link:has(.ev-feed__logo)::before {
    height: 100%; aspect-ratio: auto;
  }
  .ev-feed__item--lead .ev-feed__title { font-size: 28px; line-height: 1.14; color: #fff; }
  .ev-feed__item--lead .ev-feed__note { color: #E6E5E5; }
  .ev-feed__item--lead .ev-feed__text { color: #E6E5E5; }

  /* Остальные — строкой: картинка слева, текст справа.

     Ряды объявлены ЯВНО («auto 1fr»): без этого лишняя высота, которую даёт
     картинка на два ряда, делится между рядами поровну, и между названием и
     описанием повисает пустая полоса в полсотни пикселей. */
  .ev-feed__rest .ev-feed__link {
    display: grid;
    grid-template-columns: var(--ev-feed-thumb, 330px) 1fr;
    grid-template-rows: auto 1fr;
    column-gap: 20px; row-gap: 8px;
  }
  .ev-feed__rest .ev-feed__img { grid-row: 1 / -1; aspect-ratio: 1 / 1; }
}

/* Пометка чернового раздела видна только в редакторе: на сайте таких
   карточек нет. Цвет акцентный — это состояние, а не украшение. */
.ev-feed__draft {
  align-self: flex-start;
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 100px;
  background: var(--color-accent);
  color: #fff;
}

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

   Поля без рамок, только линия снизу — как на прежнем сайте: рамка вокруг
   каждого превращает форму в решётку. */
.ev-form {
  display: flex; flex-direction: column;
  gap: var(--ev-form-gap, 16px);
  color: var(--ev-form-color, inherit);
}
.ev-form__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--ev-form-gap, 16px);
}
@media (min-width: 700px) {
  .ev-form__grid { grid-template-columns: repeat(var(--ev-form-cols, 2), 1fr); }
  .ev-form__field--wide { grid-column: 1 / -1; }
}
.ev-form__field { display: flex; flex-direction: column; gap: 6px; }
.ev-form__label { font-size: 13px; opacity: .7; }
.ev-form input[type="text"],
.ev-form input[type="tel"],
.ev-form input[type="email"],
.ev-form select,
.ev-form textarea {
  width: 100%;
  padding: 8px 0;
  font: inherit;
  color: inherit;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--ev-form-line, #E6E5E5);
  border-radius: 0;
}
/* Пункты выпадающего списка рисует ОПЕРАЦИОННАЯ СИСТЕМА на своём фоне —
   почти всегда белом, — а цвет они наследуют от <select>. Форма стоит на
   тёмном снимке, текст в ней белый, и список выходил белым по белому: пять
   услуг были на месте, и не видно было ни одной. Видно было только тот пункт,
   под которым система рисует свою синюю подсветку, — из-за чего и выглядело,
   будто список пуст, а одна строка взялась ниоткуда.

   Поэтому цвет и фон пунктам задаются ЯВНО. Наследование здесь — ловушка:
   правило «цвет как у родителя» верно для поля ввода, которое рисуем мы, и
   неверно для списка, который рисует не браузер. */
.ev-form select option {
  color: var(--color-text, #251737);
  background: #FFFFFF;
}

.ev-form textarea { resize: vertical; }
.ev-form :is(input, select, textarea):focus-visible {
  outline: none;
  border-bottom-color: var(--color-accent);
  /* Вторая линия под первой — тенью, а не толщиной рамки: рамка толще на
     пиксель сдвинула бы всё, что ниже поля, при каждом переходе клавишей.
     Одной линии в пиксель цветом акцента было мало: форма стоит на тёмном
     снимке, и обход клавишей показал, что у полей след фокуса не заметен —
     у ссылок и кнопок рядом он виден сразу. */
  box-shadow: 0 1px 0 0 var(--color-accent);
}

/* На телефоне поле мельче 16 пикселей Safari при нажатии УВЕЛИЧИВАЕТ
   страницу — и после ввода телефона человеку приходится уменьшать её
   руками. Шрифт полей наследуется от формы, а у формы на сайте 14.
   max(16px, 1em): крупнее заданный автором шрифт остаётся как есть, мельче —
   поднимается ровно до порога. Только на узком экране: на широком Safari
   так не делает, и вид полей не меняется. */
@media (max-width: 700px) {
  .ev-form :is(input[type="text"], input[type="tel"], input[type="email"], select, textarea) {
    font-size: max(16px, 1em);
  }
}

/* Ловушка для роботов. Скрыта СМЕЩЕНИЕМ, а не display:none: часть роботов
   пропускает поля, спрятанные очевидным способом. Экранный диктор её не
   читает (aria-hidden в разметке), клавишей до неё не дойти (tabindex=-1). */
.ev-form__trap {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.ev-form__consent {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 13px; line-height: 1.4;
  /* Тот же цвет, что у надписей полей: согласие стоит внутри формы, и когда
     форма лежит на тёмном снимке, ссылка фирменным фиолетовым по фиолетовому
     не читается вовсе. Цвет полей автор задаёт одной настройкой на всю форму —
     значит и здесь берём её. */
  color: var(--ev-form-color, inherit);
}
.ev-form__consent a { color: inherit; }
/* Флажок согласия у браузера по умолчанию 13×13 — на телефоне в него
   трудно даже просто прицелиться глазом, хотя нажимается вся подпись
   (флажок лежит внутри <label>). 18 — размер, при котором отметка видна
   без присматривания. Цвет отметки — тот же, что у кнопки формы: иначе на
   тёмном снимке она выходила системной синей, чужой для всего остального. */
.ev-form__consent input {
  flex: 0 0 auto;
  width: 18px; height: 18px; margin: 0;
  accent-color: var(--ev-form-btn-bg, var(--color-accent));
}

.ev-form__btn {
  align-self: flex-start;
  width: var(--ev-form-btn-width, auto);
  padding: 14px 40px;
  font: inherit;
  color: var(--ev-form-btn-fg, #fff);
  background: var(--ev-form-btn-bg, #251737);
  border: 0;
  border-radius: var(--ev-form-btn-radius, 100px);
  cursor: pointer;
  transition: opacity var(--ev-hover-speed, .3s);
}
.ev-form__btn:hover { opacity: .88; }

/* Ответ на отправку. Показывает страница, а не блок: пометка приходит
   параметром адреса и относится ко всей странице, а форм на ней может быть
   несколько. */
.ev-form-note {
  padding: 16px 24px;
  border-radius: 8px;
  font-size: 15px;
}
.ev-form-note--ok { background: #EEF7EE; color: #1E5B2A; }
.ev-form-note--err { background: #FDECEC; color: #8A1F1F; }
