/* Вывески — signboard.pro
   ---------------------------------------------------------------------------
   Вывеска работает в темноте: она светится, когда вокруг темно. Отсюда
   основной тон страницы — тёмный, а свет приходит от фотографий и подсветки
   на границах карточек. Светлые полосы расставлены между тёмными, чтобы глаз
   отдыхал и разделы не сливались в одну ленту.

   Цвета и отступы — только из общих токенов. Хардкод здесь появляться
   не должен: он разойдётся с остальными сайтами при первой правке брендбука. */

/* Жёлтый служит здесь двум задачам: пометки о недостающих данных
   и блок про закон. Держим в одном месте, чтобы оттенки не разошлись. */
:root {
  --warn-line: rgb(255 196 0 / 55%);
}

/* Атрибут `hidden` — это всего лишь `display: none` из таблицы браузера,
   и любой наш `display` его молча перебивает. Ошибка тихая: в разметке
   элемент скрыт, в свойствах скрыт, а на экране виден — проверка кода
   её не ловит, ловит только снимок. Закрываем правилом на весь сайт. */
[hidden] {
  display: none !important;
}

/* ── Общее ────────────────────────────────────────────────────────────────── */

.wrap {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

.band {
  padding-block: clamp(3.5rem, 7vw, 6rem);
}

.band--dark {
  background: var(--bg);
  color: var(--ink);
}

.band--light {
  background: var(--lt-bg);
  color: var(--lt-ink);
}

.band--strip {
  background: var(--bg-deep);
  color: var(--ink);
  padding-block: clamp(2.5rem, 4vw, 3.5rem);
}

.h2 {
  font-size: var(--fs-h2);
  line-height: var(--lh-heading);
  letter-spacing: -0.02em;
  margin: 0 0 var(--space-4);
}

.h2--quiet {
  font-size: var(--fs-lg);
  color: var(--ink-muted);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  margin-bottom: var(--space-6);
}

.band--light .lead {
  color: var(--lt-ink-2);
}

.lead {
  margin: 0 0 var(--space-7);
}

/* ── Шапка ────────────────────────────────────────────────────────────────── */

.topbar {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: rgb(11 26 48 / 82%);
  backdrop-filter: blur(var(--glass-blur));
  border-bottom: 1px solid var(--line);
}

.topbar__in {
  max-width: var(--container);
  margin-inline: auto;
  padding: 0.75rem clamp(1.25rem, 4vw, 2.5rem);
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.topbar__logo {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  color: var(--ink);
  text-decoration: none;
  flex: 0 0 auto;
}

/* Фирменный знак, а не текстовая заглушка. Файл общий для всех сайтов
   направлений: логотип один, и копия у каждого сайта разошлась бы
   при первой же правке брендбука. */
.topbar__logo img {
  height: 2rem;
  width: auto;
  display: block;
}

/* Направление подписью рядом со знаком: сам логотип у всех сайтов одинаковый,
   различает их именно эта подпись. */
.topbar__dept {
  color: var(--ink-muted);
  font-weight: 400;
  font-size: var(--fs-sm);
  white-space: nowrap;
  padding-left: 0.625rem;
  margin-left: 0.125rem;
  border-left: 1px solid var(--line);
}

.nav {
  display: flex;
  /* Пунктов семь: на обычном ноутбучном экране полный отступ выталкивал
     кнопку заявки за край. Сжимаем промежутки, а не прячем пункты. */
  gap: clamp(var(--space-3), 1.1vw, var(--space-5));
  margin-inline: auto;
}

.nav a {
  color: var(--ink-2);
  text-decoration: none;
  font-size: var(--fs-sm);
  white-space: nowrap;
  padding-block: 0.25rem;
  border-bottom: 2px solid transparent;
  transition: color var(--dur-fast) var(--ease-out-quart),
    border-color var(--dur-fast) var(--ease-out-quart);
}

.nav a:hover {
  color: var(--ink);
  border-bottom-color: var(--asp-teal);
}

.topbar__act {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex: 0 0 auto;
}

.topbar__tel {
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
}

.topbar__tel:hover {
  color: var(--asp-teal-light);
}

.topbar__max {
  color: var(--ink-2);
  text-decoration: none;
  font-size: var(--fs-sm);
  white-space: nowrap;
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  transition: border-color var(--dur-fast) var(--ease-out-quart),
    color var(--dur-fast) var(--ease-out-quart);
}

.topbar__max:hover {
  color: var(--ink);
  border-color: var(--asp-teal);
}

/* Черновая цена: значение временное, заказчик пришлёт точные. Отдельного
   вида ей не даём — на странице она должна выглядеть как настоящая, иначе
   первый экран снова перестанет отвечать на главный вопрос. Найти её потом
   можно по атрибуту. */

.btn--sm {
  padding: 0.5rem 1.125rem;
  font-size: var(--fs-sm);
}

/* Шапка длинная: знак, подпись направления, шесть пунктов, телефон, MAX
   и кнопка. Убираем по одному, начиная с наименее нужного.

   Подпись «вывески» держим до последнего: логотип у всех семи сайтов
   направлений одинаковый, и без подписи шапка не говорит, куда человек
   попал. Раньше она пряталась первой — это было верно, пока рядом стояло
   слово «Вывески» текстом, и перестало быть верным, как только на её место
   встал общий знак. */
@media (max-width: 1480px) {
  .topbar__max { display: none; }
}

@media (max-width: 1180px) {
  .topbar__dept { display: none; }
}

@media (max-width: 1110px) {
  .nav { gap: var(--space-4); }
  .nav a { font-size: var(--fs-xs); }
}

@media (max-width: 1050px) {
  .nav { display: none; }
}

@media (max-width: 560px) {
  .topbar__tel { display: none; }
}

/* ── Первый экран: липкая сцена ───────────────────────────────────────────── */

/* Высота секции задаёт длину прокрутки сцены: три акта — три экрана сверх
   первого. Меньше — акты сменяются рывком, больше — прокрутка кажется
   зависшей. */
.stage {
  position: relative;
  background: var(--bg-deep);
}

:root[data-motion='on'] .stage {
  /* Было 340svh на три акта. Акт про включение переехал в «Типы подсветки»,
     и лишняя высота осталась бы молчаливым хвостом: человек крутит,
     а на экране ничего не меняется. */
  height: 190svh;
}

.stage__sticky {
  position: relative;
  overflow: clip;
  min-height: min(88svh, 46rem);
  display: grid;
  align-items: end;
}

:root[data-motion='on'] .stage__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  /* Две колонки: модель слева, текст справа. У каждого своя половина —
     подбирать положение модели отступами и прицелом камеры оказалось гиблым
     делом, она то лезла на заголовок, то на кнопки. Своя колонка снимает
     вопрос: модель встаёт по её центру сама. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  align-items: stretch;
}

/* Свечение фона идёт за светом на модели: переменную двигает сцена.
   Центр — над моделью, слева: свет должен исходить от вывески, а не висеть
   отдельным пятном посреди экрана. */
.stage__sticky::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      38rem 26rem at 26% 52%,
      rgb(120 190 255 / calc(var(--glow, 0) * 30%)),
      transparent 72%
    ),
    radial-gradient(
      60rem 40rem at 20% 40%,
      rgb(41 121 255 / 10%),
      transparent 70%
    );
  pointer-events: none;
}

/* Мягкая тень под моделью: без неё конструкция висит в пустоте и выглядит
   вырезанной. Пятно, а не резкая тень — источник у нас рассеянный. */
:root[data-motion='on'] .stage__canvas::after {
  content: '';
  position: absolute;
  left: 12%;
  right: 12%;
  bottom: 14%;
  height: 3rem;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgb(0 0 0 / 55%), transparent);
  filter: blur(14px);
  pointer-events: none;
  z-index: -1;
}

/* Постер: он же запасной вариант, он же то, что видно до первого кадра
   сцены. Убираем его только когда сцена действительно поднялась — иначе
   на месте канваса окажется пустота. */
.stage__still {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Текст лежит поверх снимка целиком, а не рядом с ним, поэтому глушим
     яркость: белое по светлым участкам вывески читается на пределе. */
  filter: brightness(0.5) saturate(0.92);
  transition: opacity var(--dur-slow) var(--ease-out-quart);
}

.stage[data-scene='сцена'] .stage__still {
  opacity: 0;
}

.stage__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Заглушка на время загрузки сцены: стоит в полосе холста и уходит,
   когда появился первый кадр. В запасном режиме не нужна — там работает
   фотография. */
.stage__preview {
  display: none;
}

:root[data-motion='on'] .stage__preview {
  display: block;
  grid-area: 1 / 1 / 2 / 3;
  width: 100%;
  height: 100%;
  /* Как холст: тот заполняет полосу целиком, и заглушка должна вести себя
     так же — иначе при подмене модель заметно подпрыгивает в размере. */
  object-fit: cover;
  object-position: center;
}

/* Заглушка уходит и когда сцена поднялась, и когда она не состоялась:
   в запасном режиме работает фотография, и две картинки друг на друге
   не нужны. */
:root[data-motion='on'] .stage[data-scene='сцена'] .stage__preview,
:root[data-motion='on'] .stage[data-scene='постер'] .stage__preview {
  display: none;
}

/* В режиме сцены фотография не участвует: текст стоит над моделью, а не
   поверх снимка, и снимок только тянул бы двести килобайт впустую.
   Возвращается, если сцена не поднялась. */
:root[data-motion='on'] .stage__still {
  display: none;
}

:root[data-motion='on'] .stage[data-scene='постер'] .stage__still {
  display: block;
}

/* В режиме сцены холст занимает нижнюю полосу, а не весь экран. */
/* Холст занимает весь экран, а не колонку. Двигать модель по горизонтали
   умеет сама сцена, и делает это плавно; переставлять же холст между
   колонками прокруткой нельзя — области сетки не анимируются. */
:root[data-motion='on'] .stage__canvas {
  position: relative;
  inset: auto;
  grid-area: 1 / 1 / 2 / 3;
  z-index: var(--z-base);
  isolation: isolate;
}

:root[data-motion='on'] .stage__in {
  grid-area: 1 / 1;
  z-index: var(--z-raised);
  /* На разборке текст поднимается: вывеска выходит в центр, и низ экрана
     отдаётся ей и развилке. Переменную двигает сцена. */
  transform: translate3d(0, calc(var(--razbor, 0) * -15vh), 0);
  align-self: center;
  justify-items: start;
  text-align: left;
  max-width: none;
  margin-inline: 0;
  padding-block: var(--space-6);
  /* Левый край текста совпадает с общей сеткой страницы, а не с краем окна:
     иначе заголовок не встаёт под логотип в шапке, и это сразу видно.
     Считаем так же, как контейнер: половина остатка ширины плюс его отступ. */
  padding-inline-start: calc(max(0px, 100vw - var(--container)) / 2 + clamp(1.25rem, 4vw, 2.5rem));
  padding-inline-end: var(--space-5);
}

:root[data-motion='on'] .act {
  align-self: center;
}

/* В сцене заголовок живёт в половине экрана, да ещё с отступом по сетке.
   Полный display-кегль там ломается на четыре строки и выпихивает блок
   за пределы липкого экрана — надстрочная строка уезжает под шапку.
   Поэтому в сцене он меньше, чем на обычной странице. */
:root[data-motion='on'] .act__h {
  font-size: clamp(2.1rem, 1.1rem + 2.6vw, 3.4rem);
  max-width: 16ch;
}

:root[data-motion='on'] .act + .act .act__h {
  font-size: clamp(1.8rem, 1rem + 2vw, 2.7rem);
}

:root[data-motion='on'] .act__p {
  font-size: var(--fs-base);
  max-width: 42ch;
}

/* На разборке вывеска выходит в центр, и колонка текста должна ужаться,
   иначе последние строки упираются в каркас. */
:root[data-motion='on'] .act + .act .act__p {
  max-width: 34ch;
}

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

   Размывать здесь есть что: за плашками проходит свечение сцены, и они ловят
   его краем. */
:root[data-motion='on'] .hero__facts {
  gap: var(--space-3);
  justify-items: stretch;
}

:root[data-motion='on'] .hero__facts li {
  position: relative;
  padding: var(--space-4) var(--space-4) calc(var(--space-4) - 0.15rem);
  border-radius: var(--radius);
  background: rgb(12 24 44 / 46%);
  border: 1px solid rgb(255 255 255 / 7%);
  backdrop-filter: blur(14px) saturate(1.1);
  box-shadow:
    0 1px 0 rgb(255 255 255 / 6%) inset,
    0 18px 44px -34px rgb(0 0 0 / 90%);
  transition: border-color var(--dur) var(--ease-out-quart),
    background var(--dur) var(--ease-out-quart);
}

:root[data-motion='on'] .hero__facts li:hover {
  border-color: rgb(29 233 182 / 34%);
  background: rgb(16 32 58 / 58%);
}

/* Блик по верхней кромке — так стекло читается стеклом, а не заливкой. */
:root[data-motion='on'] .hero__facts li::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    160deg,
    rgb(255 255 255 / 7%) 0%,
    transparent 46%
  );
  pointer-events: none;
}

/* Узкий экран: колонок нет, текст ложится поверх, модель — фоном под ним.
   На телефоне сцена и так не запускается, но окно можно сузить и на ноутбуке. */
@media (max-width: 1000px) {
  :root[data-motion='on'] .stage__sticky {
    grid-template-columns: minmax(0, 1fr);
  }


  :root[data-motion='on'] .stage__in {
    padding-inline: clamp(1.25rem, 4vw, 2.5rem);
  }

  :root[data-motion='on'] .stage__canvas,
  :root[data-motion='on'] .stage__preview,
  :root[data-motion='on'] .stage__in {
    grid-area: 1 / 1;
  }

  :root[data-motion='on'] .stage__in {
    padding-inline: clamp(1.25rem, 4vw, 2.5rem);
    z-index: var(--z-overlay);
  }
}

/* Без сцены канвас — пустой прямоугольник поверх постера. */
:root:not([data-motion='on']) .stage__canvas,
.stage[data-scene='постер'] .stage__canvas {
  display: none;
}

/* Затемнение сверху вниз: текст стоит наверху, и плотный фон нужен именно
   там. Внизу оставляем прозрачным — там вывеска, ради неё всё и затевалось. */
.stage__sticky::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgb(6 18 36 / 92%) 0%,
    rgb(6 18 36 / 78%) 34%,
    rgb(6 18 36 / 28%) 62%,
    rgb(6 18 36 / 0%) 85%
  );
  pointer-events: none;
}

.stage__in {
  position: relative;
  z-index: var(--z-raised);
  max-width: var(--container);
  margin-inline: auto;
  width: 100%;
  /* Сверху — высота липкой шапки плюс воздух: иначе надстрочная строка
     уезжает под неё. */
  padding: clamp(5rem, 11vh, 7rem) clamp(1.25rem, 4vw, 2.5rem) clamp(1.5rem, 3vw, 2.5rem);
  /* Текст по центру, а не колонкой слева: так первый экран читается как
     объявление, а не как страница с картинкой сбоку. Модель при этом
     уходит вниз, под текст, — иначе они спорят за одно место. */
  text-align: center;
  display: grid;
  justify-items: center;
}

/* Акты лежат друг на друге и сменяются прокруткой. Без сцены — обычным
   потоком, друг за другом: тогда это просто три абзаца о вывеске. */
:root[data-motion='on'] .acts {
  display: grid;
}

:root[data-motion='on'] .act {
  grid-area: 1 / 1;
  will-change: opacity, transform;
}

/* Второй и третий акты скрыты СРАЗУ, до того как модуль сцены поднимется.
   Прозрачностью дальше управляет скрипт, но до его запуска состояние обязана
   задать разметка: иначе при загрузке все три акта секунду лежат друг на друге
   нечитаемой кашей. Ровно та же ошибка, что решалась признаком data-motion,
   только уровнем ниже — там от неё прыгала раскладка, здесь налезает текст. */
:root[data-motion='on'] .act + .act {
  opacity: 0;
}

/* Сцена не поднялась — значит скрипт прозрачность так и не тронет, и акты
   остались бы невидимыми навсегда. Возвращаем их в обычный поток: два абзаца
   из трёх важнее, чем красивая смена кадров. */
.stage[data-scene='постер'] .acts {
  display: block;
}

/* Без сцены постер не должен растягиваться на все три акта: снимок во весь
   блок с текстом поверх читается как поломка, а не как замысел. Оставляем
   его первому экрану, остальное ложится на обычный тёмный фон. */
.stage[data-scene='постер'] .stage__still,
:root:not([data-motion='on']) .stage__still,
.stage[data-scene='постер'] .stage__sticky::after,
:root:not([data-motion='on']) .stage__sticky::after {
  height: min(86svh, 44rem);
  bottom: auto;
}

/* Без сцены весь текст ложится прямо на снимок, а вывеска на нём светлая —
   подписи под цифрами оказывались на пределе читаемости. В режиме со сценой
   этой беды нет: там текст стоит над моделью, а не поверх неё. */
.stage[data-scene='постер'] .stage__still,
:root:not([data-motion='on']) .stage__still {
  filter: brightness(0.3) saturate(0.85);
}

.stage[data-scene='постер'] .stage__sticky::after,
:root:not([data-motion='on']) .stage__sticky::after {
  background: linear-gradient(
    to bottom,
    rgb(6 18 36 / 82%) 0%,
    rgb(6 18 36 / 74%) 55%,
    rgb(6 18 36 / 96%) 100%
  );
}

.stage[data-scene='постер'] .act + .act {
  opacity: 1;
  margin-top: var(--space-7);
}

:root:not([data-motion='on']) .act + .act {
  margin-top: var(--space-7);
}

.act__over {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asp-teal-light);
}

.act__h {
  margin: 0 0 var(--space-4);
  max-width: 20ch;
  font-size: var(--fs-display);
  line-height: var(--lh-tight);
  letter-spacing: -0.03em;
  color: #fff;
  text-wrap: balance;
}

/* Второй и третий акты — не главный заголовок, и кричать им незачем. */
.act + .act .act__h {
  font-size: var(--fs-h2);
  max-width: 18ch;
}

.act__p {
  margin: 0 0 var(--space-6);
  max-width: 46ch;
  font-size: var(--fs-lg);
  line-height: var(--lh-body);
  color: var(--ink-2);
}

.hero__facts {
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-5) var(--space-6);
}

.hero__facts li {
  display: grid;
  gap: 0.125rem;
  /* Каждая цифра со своей подписью — как отдельный столбик, чтобы при
     переносе они не слипались в сплошную строку. */
  min-width: 8.5rem;
  max-width: 11rem;
}

/* В половине экрана четыре цифры в строку не помещаются и ломаются 3 + 1 —
   последняя повисает одна. Раскладываем парами. */
:root[data-motion='on'] .hero__facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  justify-items: center;
}

:root[data-motion='on'] .hero__facts li {
  max-width: none;
  text-align: left;
}

:root[data-motion='on'] .hero__act {
  justify-content: flex-start;
}

.hero__facts b {
  font-size: var(--fs-h3);
  line-height: 1.1;
  color: #fff;
}

.hero__facts span {
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.hero__act {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-4);
}

/* На узком экране делить нечего: постер уходит на весь фон, и вот тут его
   приходится глушить — текст всё равно ложится поверх. */
@media (max-width: 860px) {
  .stage__still {
    filter: brightness(0.4) saturate(0.9);
  }
}

/* Ссылка на отдельную страницу про закон: внутри раскрытия её человек
   не видит, пока не откроет, — поэтому дублируем строкой над ним. */
.law__page {
  margin: var(--space-4) 0 0;
  font-weight: 600;
}

.band--light .law__page a { color: var(--asp-blue-deep); }

/* ── Подписи слоёв ────────────────────────────────────────────────────────── */

/* Стоят по краям экрана, а не вплотную к деталям: вплотную они закрывали
   саму вывеску — ради которой всё и затевалось. К детали ведёт линия,
   её концы считает сцена. */
.marks,
.marks__lines {
  display: none;
}

:root[data-motion='on'] .marks,
:root[data-motion='on'] .marks__lines {
  display: block;
  position: absolute;
  inset: 0;
  grid-area: 1 / 1 / 2 / 3;
  pointer-events: none;
  z-index: var(--z-raised);
}

:root[data-motion='on'] .marks {
  margin: 0;
  padding: 0;
  list-style: none;
}

.marks__lines {
  width: 100%;
  height: 100%;
  opacity: var(--lines-on, 0);
  transition: opacity var(--dur) var(--ease-out-quart);
}

.marks__lines line {
  stroke: rgb(160 205 255 / 55%);
  stroke-width: 1;
}

.marks__lines circle {
  fill: var(--asp-teal-light);
}

.marks li {
  position: absolute;
  opacity: var(--on, 0);
  display: grid;
  gap: 0.1rem;
  padding: 0.55rem 0.8rem;
  border-radius: var(--radius-sm);
  background: rgb(9 20 38 / 82%);
  border: 1px solid rgb(255 255 255 / 10%);
  backdrop-filter: blur(10px);
  white-space: nowrap;

  /* Горизонтальный сдвиг считает сцена: подпись едет за своей деталью.
     Переход только на прозрачности — сдвиг меняется каждый кадр, и плавность
     на нём означала бы, что подпись всегда отстаёт от того, что описывает. */
  transform: translate3d(var(--dx, 0px), 0, 0);
  transition: opacity var(--dur) var(--ease-out-quart);
}

/* Стартовое место — у краёв кадра. Дальше сцена подтягивает подпись
   к своей детали, а край остаётся ограничителем: за него не выпускаем. */
.marks li[data-side='left'] { left: clamp(1.25rem, 4vw, 3rem); }
.marks li[data-side='right'] { right: clamp(1.25rem, 4vw, 3rem); }
/* Слоёв стало семь, и каждому нужна своя строка: подписи стоят по краям
   кадра, и без разведения по вертикали они наезжают друг на друга. */
.marks li[data-row='1'] { top: 17%; }
.marks li[data-row='2'] { top: 32%; }
.marks li[data-row='3'] { top: 47%; }
.marks li[data-row='4'] { top: 62%; }

.marks b {
  font-size: var(--fs-sm);
  color: var(--ink);
  font-weight: 600;
}

.marks span {
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

/* ── Развилка ─────────────────────────────────────────────────────────────── */

.fork {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

/* Внутри сцены развилка стоит внизу липкого экрана и выезжает на разборке:
   человек уже понял, из чего вывеска, и следующий его вопрос — про себя. */
:root[data-motion='on'] .fork {
  position: absolute;
  grid-area: 1 / 1 / 2 / 3;
  left: 0;
  right: 0;
  top: auto;
  bottom: clamp(1.5rem, 3vh, 2.5rem);
  z-index: var(--z-raised);
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
  opacity: var(--fork-on, 0);
  transform: translate3d(0, calc((1 - var(--fork-on, 0)) * 18px), 0);
  transition: opacity var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
  pointer-events: var(--fork-hit, none);
}

.fork__card {
  display: grid;
  gap: 0.4rem;
  align-content: start;
  padding: var(--space-4) var(--space-5);
  border: 1px solid rgb(255 255 255 / 8%);
  border-radius: var(--radius-lg);
  background: rgb(12 24 44 / 58%);
  backdrop-filter: blur(14px) saturate(1.1);
  box-shadow:
    0 1px 0 rgb(255 255 255 / 6%) inset,
    0 22px 54px -38px rgb(0 0 0 / 90%);
  transition: border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.fork__card:hover {
  border-color: var(--asp-teal);
  transform: translateY(-3px);
}

.fork__who {
  margin: 0;
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asp-teal-light);
}

.fork__h {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: var(--lh-heading);
  color: var(--ink);
}

.fork__p {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
  max-width: 42ch;
}

.fork__go {
  justify-self: start;
  margin-top: var(--space-2);
  color: var(--ink);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-decoration: none;
  border-bottom: 1px solid var(--asp-teal);
  padding-bottom: 2px;
}

.fork__go:hover { color: var(--asp-teal-light); }

/* Без сцены развилка — обычный блок под первым экраном. */
:root:not([data-motion='on']) .fork {
  margin-top: var(--space-7);
}

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

   Правило стоит здесь, а не в общем медиазапросе первого экрана: тот идёт
   выше по файлу, и описание подписей его перебивало. */
@media (max-width: 1000px) {
  :root[data-motion='on'] .marks {
    display: none;
  }

  :root[data-motion='on'] .fork {
    position: static;
    opacity: 1;
    transform: none;
    pointer-events: auto;
    margin-top: var(--space-6);
    align-self: end;
  }
}

@media (prefers-reduced-motion: reduce) {
  .fork__card,
  .marks li { transition: none; }
}

/* ── Виды вывесок ─────────────────────────────────────────────────────────── */

.vidy {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.vid {
  display: flex;
  flex-direction: column;
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.vid:hover {
  border-color: var(--asp-teal);
  transform: translateY(-3px);
}

/* Галерея карточки: лента кадров со scroll-snap. Листается пальцем
   и без скрипта; стрелки и точки добавляет vidy.js. */
.vid__gal {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--bg-deep);
}

.vid__track {
  display: flex;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  outline: none;
}

.vid__track::-webkit-scrollbar { display: none; }

.vid__track:focus-visible {
  box-shadow: inset 0 0 0 3px var(--asp-teal);
}

.vid img {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

.vid__arrow {
  position: absolute;
  top: 50%;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  margin-top: -1.25rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(8 14 28 / 62%);
  backdrop-filter: blur(6px);
  color: #fff;
  cursor: pointer;
  transition: opacity var(--dur) var(--ease-out-quart),
    background var(--dur-fast) var(--ease-out-quart);
}

.vid__arrow--prev { left: 0.6rem; }
.vid__arrow--next { right: 0.6rem; }

.vid__arrow svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.vid__arrow:hover { background: rgb(8 14 28 / 85%); }
/* Стрелки видны всегда: по ним видно, что фото в карточке не одно.
   На краю ленты стрелка гаснет, но место не освобождает. */
.vid__arrow:disabled { opacity: 0.3; cursor: default; }
.vid__arrow:focus-visible { outline: 2px solid var(--asp-teal); outline-offset: 2px; }

.vid__dots {
  position: absolute;
  left: 50%;
  bottom: 0.7rem;
  display: flex;
  gap: 0.35rem;
  padding: 0.3rem 0.5rem;
  border-radius: var(--radius-pill);
  background: rgb(8 14 28 / 45%);
  backdrop-filter: blur(6px);
  transform: translateX(-50%);
  pointer-events: none;
}

.vid__dots i {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: rgb(255 255 255 / 45%);
  transition: background var(--dur-fast), width var(--dur) var(--ease-out-quart);
}

.vid__dots i.is-on {
  width: 1rem;
  border-radius: var(--radius-pill);
  background: #fff;
}

.vid__body {
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  gap: var(--space-3);
}

.vid__body h3 {
  margin: 0;
  font-size: var(--fs-xl);
  line-height: var(--lh-heading);
}

/* Цена стоит внизу карточки, отдельным блоком со сроком, и отделена чертой.

   Раньше она шла сразу под названием, мелкой строкой вровень с описанием.
   Но приходят сюда именно за ней: человек сравнивает шесть конструкций
   и смотрит на суммы, а не читает подряд. Внизу и крупно её видно, не читая
   карточку целиком.

   `margin-top: auto` прижимает блок к низу: описания у карточек разной длины,
   и без этого цены встали бы на разной высоте — сравнивать глазом стало бы
   заметно труднее. */
.vid__cost {
  margin: auto 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--glass-line);
  display: grid;
  gap: 0.15rem;
}

.vid__sum {
  font-size: var(--fs-xl);
  font-weight: 700;
  line-height: 1.15;
  color: var(--asp-teal-light);
  letter-spacing: -0.01em;
}

.vid__term {
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* Пустая строка всё равно занимает высоту: у одной конструкции второй строки
   нет, и без этого её блок с ценой оказывался короче соседних — черта
   в ряду вставала вразнобой. */
.vid__term:empty::before {
  content: ' ';
}

/* ── Виды вывесок на светлой полосе ────────────────────────────────────────
   Карточки здесь стеклянные, как везде, но стекло рассчитано на тёмный фон:
   светлая плёнка поверх светлого не видна вовсе. Поэтому на этой полосе
   даём карточкам белую подложку и обычную рамку. */
.band--light .vid {
  background: var(--lt-bg-2);
  border-color: var(--lt-line);
  box-shadow: 0 18px 40px -34px rgb(19 26 45 / 45%);
}

.band--light .vid:hover {
  border-color: var(--asp-blue-deep);
}

.band--light .vid__cost {
  border-top-color: var(--lt-line);
}

.band--light .vid__term {
  color: var(--lt-ink-muted);
}

/* Цена — то, ради чего сюда приходят, и на светлом фоне бирюза с ней
   не справляется: она задумана как акцент на тёмном. Берём глубокий синий —
   он держит контраст и остаётся фирменным. */
.band--light .vid__sum {
  color: var(--asp-navy-calm);
}

.band--light .vid__list {
  color: var(--lt-ink-2);
}

.band--light .vid__go {
  color: var(--lt-ink);
  border-bottom-color: var(--asp-blue-deep);
}

.band--light .vidy__note {
  color: var(--lt-ink-muted);
}

.vidy__eyebrow {
  margin: 0 0 0.6rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asp-navy-calm);
}

/* Заголовок в две краски: первая половина держит смысл, вторая уходит
   в полутон. Так фраза читается как одна мысль, а не как два утверждения. */
.vidy__h {
  color: var(--lt-ink-2);
}

.vidy__h b {
  color: var(--lt-ink);
  font-weight: inherit;
}

.vid__about {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--ink-2);
}

.band--light .vid__about {
  color: var(--lt-ink-2);
}

/* Основание расчёта под списком видов. Тон приглушённый: это оговорка
   к ценам, а не самостоятельное утверждение, и спорить с ними за внимание
   она не должна. */
.vidy__note {
  margin: clamp(1.25rem, 3vw, 2rem) 0 0;
  max-width: 62ch;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--ink-muted);
}

.vid__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.4rem;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
  flex: 1 1 auto;
}

.vid__list li {
  padding-left: 1.1rem;
  position: relative;
}

.vid__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--asp-teal);
}

.vid__go {
  align-self: flex-start;
  color: var(--ink);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-decoration: none;
  border-bottom: 1px solid var(--asp-teal);
  padding-bottom: 2px;
}

.vid__go:hover {
  color: var(--asp-teal-light);
}

/* Пометки о недостающих данных должны быть заметны в вёрстке и невозможны
   к пропуску при вычитке. Когда цены приедут, правило удаляется вместе
   с атрибутами. */
[data-todo] {
  background: rgb(255 196 0 / 18%);
  outline: 1px dashed var(--warn-line);
  padding: 0 0.35em;
  border-radius: 3px;
}

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

/* Проверка по закону — светлая полоса, а содержимое в отдельной плашке.

   Полоса светлая потому, что перед ней уже стоят подряд смета и виды: третий
   тёмный экран сливался бы с ними в одно полотно. Плашка нужна затем же,
   зачем и на бумаге: это не рассказ о компании, а инструмент, и у инструмента
   должны быть границы. */
.band--law {
  background: var(--lt-bg);
  color: var(--lt-ink);
  border-block: 1px solid var(--lt-line);
}

.band--law .law {
  padding: clamp(1.5rem, 4vw, 3rem);
  border: 1px solid var(--lt-line);
  border-radius: var(--radius-lg);
  background: var(--lt-bg-2);
  box-shadow: 0 24px 60px -46px rgb(19 26 45 / 55%);
}

.band--law .law__note {
  border-left-color: var(--asp-navy-calm);
  color: var(--lt-ink-2);
}

/* Жёлтый на белом не держит контраст — он задуман как акцент на тёмном.
   Берём тот же синий, что и у цен. */
.band--law .law__note b {
  color: var(--asp-navy-calm);
}

.band--law .check__hint {
  color: var(--lt-ink-muted);
}

/* «Подробнее о законе». Стрелка своя: браузерный треугольник у `summary`
   выглядит по-разному в каждом браузере и не поддаётся выравниванию. */
.law__more {
  margin-top: var(--space-4);
}

.law__more > summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.15rem 0;
  color: var(--asp-navy-calm);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.law__more > summary::-webkit-details-marker {
  display: none;
}

.law__more > summary::after {
  content: '';
  width: 0.45rem;
  height: 0.45rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-0.1rem, -0.1rem);
  transition: transform var(--dur) var(--ease-out-quart);
}

.law__more[open] > summary::after {
  transform: rotate(-135deg) translate(-0.05rem, -0.05rem);
}

.law__more > summary:hover {
  text-decoration: underline;
}

.law__more > summary:focus-visible {
  outline: 2px solid var(--asp-blue-deep);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

.law__more > p {
  margin-top: var(--space-3);
}

/* Результат проверки на светлом фоне.

   Текст ответа набран приглушённым тоном для тёмной темы, и на белом он
   пропадал: заголовок читался, а объяснение под ним — нет. А объяснение
   здесь и есть ответ, ради него человек и отмечал галочки. */
.band--law .check__out span {
  color: var(--lt-ink-2);
}

/* Заголовки результата тоже перекрашиваем: бирюза и жёлтый рассчитаны
   на тёмный фон. Смысл цвета сохраняем — зелёный «не о вас», янтарный
   «менять придётся», — но берём тона, читаемые на белом. */
.band--law .check__out[data-kind='ok'] {
  border-color: rgb(13 138 106 / 40%);
  background: rgb(29 233 182 / 12%);
}

.band--law .check__out[data-kind='ok'] b {
  color: #0a7a5c;
}

.band--law .check__out[data-kind='warn'] {
  border-color: rgb(176 128 0 / 45%);
  background: rgb(255 196 0 / 14%);
}

.band--law .check__out[data-kind='warn'] b {
  color: #7a5800;
}

/* Метка «действует с…» на светлом: жёлтая заливка теряется, а сообщение
   в ней срочное. Делаем её тёмной по янтарю. */
.band--law .law__tag {
  background: rgb(255 196 0 / 22%);
  border-color: rgb(176 128 0 / 45%);
  color: #7a5800;
}

.band--law .law__small {
  color: var(--lt-ink-muted);
}

/* Слова-примеры набраны моноширинным и на тёмном читались подсветкой.
   На светлом ту же роль играет мягкая заливка. */
.band--law .law__word {
  background: rgb(19 26 45 / 7%);
  color: var(--lt-ink);
}

/* Карточка проверки лежит уже внутри плашки, поэтому своя подложка ей
   не нужна — хватит рамки. Иначе получается коробка в коробке. */
.band--law .check {
  background: transparent;
  border-color: var(--lt-line);
}

.band--law .check__item {
  border-color: var(--lt-line);
  color: var(--lt-ink-2);
}

.band--law .check__item:hover {
  border-color: var(--asp-blue-deep);
  background: rgb(41 121 255 / 5%);
}

.band--law .check__item:has(input:checked) {
  border-color: var(--asp-blue-deep);
  background: rgb(41 121 255 / 8%);
  color: var(--lt-ink);
}

.law {
  display: grid;
  gap: var(--space-6) var(--space-8);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: start;
}

.law__tag {
  display: inline-block;
  margin: 0 0 var(--space-3);
  padding: 0.3rem 0.75rem;
  border-radius: var(--radius-pill);
  background: rgb(255 196 0 / 16%);
  border: 1px solid rgb(255 196 0 / 45%);
  color: #ffd968;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
}

.law__side .h2 {
  margin-bottom: 0;
}

.law__body p {
  margin: 0 0 var(--space-4);
  color: var(--ink-2);
  max-width: 58ch;
}

.law__word {
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.92em;
  background: rgb(255 255 255 / 8%);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.1em 0.4em;
}

.law__note {
  padding-left: var(--space-4);
  border-left: 2px solid var(--warn-line);
  /* Без `!important`: раньше он был нужен, чтобы перебить общий тон полосы,
     но теперь полоса светлая и правило само себе мешало — абзац оставался
     светлым на белом и не читался. */
  color: var(--ink);
}

.law__note b { color: #ffd968; }

.law__small {
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

/* ── Проверка по 168-ФЗ ─────────────────────────────────────────────────────
   Не пугалка, а разбор: три условия должны совпасть все сразу. Вердикт
   появляется только после первой отметки — до неё отвечать не на что. */

.check {
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  display: grid;
  gap: var(--space-3);
}

.check__h {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-lg);
  line-height: var(--lh-heading);
}

.check__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4);
  align-items: start;
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur) var(--ease-out-quart),
    background var(--dur) var(--ease-out-quart);
}

.check__item:hover {
  border-color: var(--line-strong);
  background: rgb(255 255 255 / 4%);
}

.check__item:has(input:checked) {
  border-color: var(--warn-line);
  background: rgb(255 196 0 / 8%);
  color: var(--ink);
}

.check__item i {
  font-style: normal;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  font-size: 0.92em;
}

.check__item input {
  /* Размер задаём явно: браузерный по умолчанию мельче, чем нужно пальцу. */
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  accent-color: var(--asp-blue-deep);
  cursor: pointer;
}

.check__out {
  display: grid;
  gap: 0.35rem;
  padding: var(--space-4);
  border-radius: var(--radius);
  border: 1px solid var(--line);
  font-size: var(--fs-sm);
  line-height: var(--lh-body);
}

.check__out b { font-size: var(--fs-lg); line-height: var(--lh-heading); }
.check__out span { color: var(--ink-2); }

/* Зелёный — «требование не о вас», жёлтый — «менять придётся». Цвет несёт
   смысл, поэтому дублируем его текстом заголовка: одного цвета мало. */
.check__out[data-kind='ok'] {
  border-color: rgb(29 233 182 / 45%);
  background: rgb(29 233 182 / 10%);
}

.check__out[data-kind='ok'] b { color: var(--asp-teal-light); }

.check__out[data-kind='warn'] {
  border-color: var(--warn-line);
  background: rgb(255 196 0 / 10%);
}

.check__out[data-kind='warn'] b { color: #ffd968; }

.check__hint {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.btn--warn {
  background: #f0b429;
  color: #221a05;
}

.btn--warn:hover { background: #ffc94a; }

@media (prefers-reduced-motion: reduce) {
  .check__item { transition: none; }
}

@media (max-width: 860px) {
  .law {
    grid-template-columns: 1fr;
  }
}

/* ── Дополнительные услуги ────────────────────────────────────────────────── */

.uslugi {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
}

.uslugi li {
  background: var(--lt-bg-2);
  border: 1px solid var(--lt-line);
  border-radius: var(--radius);
  padding: var(--space-5);
}

.uslugi h3 {
  margin: 0 0 var(--space-2);
  font-size: var(--fs-lg);
  line-height: var(--lh-heading);
  color: var(--lt-ink);
}

.uslugi p {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--lt-ink-2);
}

/* ── Согласование ─────────────────────────────────────────────────────────── */

/* Слева иллюстрация, справа рассказ и правила.

   Раскладку задаём размещением в сетке, а не порядком в разметке: в разметке
   сначала идёт текст, и это правильно — программа чтения с экрана и узкий
   экран должны получить сперва суть, а картинку следом. Менять порядок ради
   вида значило бы испортить одно ради другого. */
.soglas {
  display: grid;
  gap: var(--space-6) var(--space-8);
  align-items: start;
}

@media (min-width: 901px) {
  .soglas {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto auto auto 1fr;
  }

  /* Во всю ширину только заголовок. Ниже слева сравнение, справа столбиком
     рассказ, правила города и кнопки — вместе они набирают высоту картинки.

     Тянуть во всю ширину ещё и абзацы смысла нет: у строки есть предел
     длины, за которым её перестают читать, и правая половина всё равно
     осталась бы пустой. */
  .soglas__h {
    grid-column: 1 / -1;
    grid-row: 1;
  }

  .soglas__figure {
    grid-column: 1;
    grid-row: 2 / span 3;
    align-self: start;
  }

  .soglas__text {
    grid-column: 2;
    grid-row: 2;
  }

  .soglas__case {
    grid-column: 2;
    grid-row: 3;
  }

  .soglas__go {
    grid-column: 2;
    grid-row: 4;
    align-self: start;
  }
}

.soglas__text p {
  color: var(--lt-ink-2);
  max-width: 52ch;
}

/* Чертёж и результат. Картинка широкая, 2:1, и в колонке текста смотрится
   уместнее любого квадрата: она читается слева направо, как и сам рассказ —
   от замысла к установленной вывеске. */
.soglas__figure {
  margin: 0;
}

/* Кнопки заполняют низ правой колонки — там, где текст кончается раньше
   соседнего столбца. Переносим их на новую строку, если не помещаются:
   на узком экране две кнопки в ряд ужимаются до нечитаемых. */
.soglas__go {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

/* «Призрачная» кнопка рассчитана на тёмный фон: там она белым по прозрачному.
   На светлой полосе от неё оставалась одна бледная рамка, и вторая кнопка
   просто пропадала. Перекрашиваем — это ровно тот случай, о котором говорит
   правило: перенос на светлое требует ревизии каждого элемента, а не блока
   целиком. */
.band--light .btn--ghost {
  border-color: var(--lt-line);
  color: var(--lt-ink);
}

.band--light .btn--ghost:hover {
  background: rgb(41 121 255 / 6%);
  border-color: var(--asp-blue-deep);
}

.soglas__figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--lt-line);
}

.soglas__figure figcaption {
  margin-top: var(--space-3);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--lt-ink-muted);
  max-width: 52ch;
}

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

   Была с синей полосой слева — приём из тех времён, когда тени считались
   тяжёлыми и акцент ставили линией. Рядом с карточками цен, у которых мягкая
   тень и одинаковое скругление, она читалась чужой. */
.soglas__case {
  background: var(--lt-bg-2);
  border: 1px solid var(--lt-line);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow:
    0 1px 0 rgb(255 255 255 / 90%) inset,
    0 18px 40px -30px rgb(19 26 45 / 42%);
}

.soglas__tag {
  margin: 0 0 var(--space-4);
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asp-blue-deep);
  font-weight: 600;
}

.soglas__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--lt-ink);
}

.soglas__list li {
  /* Отступ под галочку: она крупнее прежнего квадратика. */
  padding-left: 1.75rem;
  position: relative;
  line-height: var(--lh-body);
}

/* Галочка вместо квадратика. Это перечень того, что мы **учли**, а не просто
   список: галочка говорит это сама, без единого слова. Рисуем фоном —
   лишний элемент в разметке ради значка не нужен. */
.soglas__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.15em;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 50%;
  background: rgb(41 121 255 / 10%) no-repeat center / 0.7rem
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232962ff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 12 6 6L20 6'/%3E%3C/svg%3E");
}

.soglas__note {
  margin: var(--space-4) 0 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--lt-line);
  font-size: var(--fs-sm);
  color: var(--lt-ink-muted);
}

@media (max-width: 860px) {
  .soglas { grid-template-columns: 1fr; }
}

/* ── Работы: карта ───────────────────────────────────────────────────────── */

.map {
  margin: 0 0 var(--space-6);
  display: grid;
  gap: var(--space-3);
}

.map__canvas {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background:
    radial-gradient(40rem 22rem at 30% 45%, rgb(41 121 255 / 14%), transparent 70%),
    var(--bg-deep);
  /* Место под карту занято заранее: иначе раздел подпрыгивает, когда
     приезжают данные. Пропорция — как у кадра в map.js. */
  aspect-ratio: 1200 / 704;
  overflow: hidden;
}

.map__canvas svg { display: block; width: 100%; height: 100%; }

.map__land {
  fill: rgb(120 180 255 / 12%);
  stroke: rgb(150 200 255 / 34%);
  stroke-width: 1;
  stroke-linejoin: round;
}

.map__note {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

/* Полосы из Кирова. Линия рисуется через pathLength="1": длина у всех
   дуг одна и та же единица, и одной анимацией обходятся все шестнадцать. */
.map__arc-line {
  fill: none;
  stroke: var(--asp-teal);
  stroke-width: 1.6;
  stroke-linecap: round;
  opacity: 0.5;
}

.map__arc-head {
  fill: none;
  stroke: var(--asp-teal);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.8;
}

/* Бегущий блик по полосе: груз едет из цеха. Только у открытого города —
   шестнадцать бликов разом превращают карту в гирлянду. */
.map__arc-flow {
  fill: none;
  stroke: var(--asp-teal-light);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 0.08 0.92;
  stroke-dashoffset: 0.08;
  opacity: 0;
}

.map__arc {
  transition: opacity var(--dur) var(--ease-out-quart);
}

.map__arc.is-off { opacity: 0.1; }

.map__arc.is-current .map__arc-line { opacity: 1; stroke-width: 2.4; }
.map__arc.is-current .map__arc-head { opacity: 1; stroke-width: 2.4; }

@media (prefers-reduced-motion: no-preference) {
  .map__arc.is-current .map__arc-flow {
    opacity: 1;
    animation: map-flow 2.2s linear infinite;
  }

  /* Вылет: пока карта не в кадре, полосы свёрнуты в Киров и острия спрятаны. */
  .map:not([data-полёт]) .map__arc-line { stroke-dasharray: 1; stroke-dashoffset: 1; }
  .map:not([data-полёт]) .map__arc-head,
  .map:not([data-полёт]) .map__pin:not(.map__pin--base) { opacity: 0; }

  .map[data-полёт] .map__arc-line {
    stroke-dasharray: 1;
    animation: map-draw 1.1s var(--ease-out-quart) calc(var(--i) * 70ms) both;
  }

  .map[data-полёт] .map__arc-head,
  .map[data-полёт] .map__pin:not(.map__pin--base) {
    animation: map-appear 0.4s var(--ease-out-quart) calc(var(--i) * 70ms + 0.8s) both;
  }

  .map__pin--base .map__halo {
    transform-box: fill-box;
    transform-origin: center;
    animation: map-pulse 2.6s var(--ease-out-quart) infinite;
  }
}

@keyframes map-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes map-appear { from { opacity: 0; } }
@keyframes map-flow { from { stroke-dashoffset: 1.08; } to { stroke-dashoffset: 0.08; } }
@keyframes map-pulse {
  0% { transform: scale(1); opacity: 0.45; }
  70%, 100% { transform: scale(2.2); opacity: 0; }
}

/* Точки городов */
.map__pin { cursor: pointer; outline: none; }
.map__hit { fill: transparent; }
.map__halo { fill: var(--asp-blue); opacity: 0.3; transition: opacity var(--dur-fast); }
.map__dot {
  fill: #fff;
  stroke: var(--bg-deep);
  stroke-width: 2;
  transition: fill var(--dur-fast) var(--ease-out-quart);
}

.map__pin--base .map__dot { fill: var(--asp-teal-light); }
.map__pin--base .map__halo { fill: var(--asp-teal); }

.map__name {
  fill: var(--ink-2);
  font-size: 17px;
  font-weight: 600;
  paint-order: stroke;
  stroke: var(--bg-deep);
  stroke-width: 4px;
  stroke-linejoin: round;
  transition: fill var(--dur-fast) var(--ease-out-quart);
}

.map__k { fill: var(--asp-teal-light); font-weight: 700; }

.map__pin:hover .map__name,
.map__pin:focus-visible .map__name { fill: #fff; }
.map__pin:hover .map__halo { opacity: 0.6; }

.map__pin:focus-visible .map__dot { stroke: var(--asp-teal-light); stroke-width: 3; }

.map__pin.is-current .map__dot { fill: var(--asp-teal-light); }
.map__pin.is-current .map__halo { fill: var(--asp-teal); opacity: 0.5; }
.map__pin.is-current .map__name { fill: #fff; }

.map__pin.is-off { opacity: 0.3; }

/* На телефоне карта в треть ширины, подписи в 17 единиц превращаются
   в шестипиксельную пыль. Оставляем подпись только открытому городу
   и Кирову, зато крупно; выбирать удобнее вкладками под картой. */
@media (max-width: 40rem) {
  .map__name { display: none; font-size: 40px; stroke-width: 8px; }
  .map__pin--base .map__name,
  .map__pin.is-current .map__name { display: inline; }
  .map__k { display: none; }
  .map__arc-line, .map__arc-head { stroke-width: 3; }
  .map__arc.is-current .map__arc-line,
  .map__arc.is-current .map__arc-head { stroke-width: 4.5; }
}

.map[data-state='нет-карты'] .map__canvas { display: none; }

/* ── Работы: кейсы ───────────────────────────────────────────────────────── */

.keisy { display: grid; gap: var(--space-4); }

.keisy__vidy {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.keisy__vid {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.95rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: rgb(255 255 255 / 3%);
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out-quart),
    background var(--dur-fast) var(--ease-out-quart),
    color var(--dur-fast) var(--ease-out-quart);
}

.keisy__vid:hover { border-color: var(--line-strong); color: var(--ink); }

.keisy__vid[aria-pressed='true'] {
  border-color: var(--asp-teal);
  background: rgb(29 233 182 / 14%);
  color: #fff;
}

.keisy__vid:focus-visible,
.keisy__tab:focus-visible,
.keisy__reset:focus-visible,
.keis__thumb:focus-visible {
  outline: 2px solid var(--asp-teal-light);
  outline-offset: 2px;
}

.keisy__count {
  min-width: 1.5em;
  padding: 0.05rem 0.4rem;
  border-radius: var(--radius-pill);
  background: rgb(255 255 255 / 8%);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--ink-muted);
}

.keisy__vid[aria-pressed='true'] .keisy__count {
  background: rgb(29 233 182 / 22%);
  color: #fff;
}

.keisy__nav { display: grid; gap: var(--space-3); min-width: 0; }

.keisy__gorod {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.8rem;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.keisy__reset {
  padding: 0.2rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: none;
  font: inherit;
  font-size: var(--fs-xs);
  color: var(--asp-teal-light);
  cursor: pointer;
}

.keisy__reset:hover { border-color: var(--asp-teal); }

/* Вкладки — одним рядом с прокруткой: двадцать проектов в три строки
   и есть та «портянка», от которой уходили. */
.keisy__tabs {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding-bottom: 0.4rem;
  scroll-snap-type: x proximity;
  scrollbar-width: thin;
  scrollbar-color: rgb(255 255 255 / 18%) transparent;
  mask-image: linear-gradient(90deg, #000 calc(100% - 3rem), transparent);
}

.keisy__tab {
  flex: none;
  display: grid;
  gap: 0.05rem;
  padding: 0.55rem 0.95rem;
  border: 1px solid rgb(255 255 255 / 8%);
  border-radius: var(--radius);
  background: rgb(12 24 44 / 70%);
  font: inherit;
  text-align: left;
  color: var(--ink-2);
  cursor: pointer;
  scroll-snap-align: start;
  transition: border-color var(--dur-fast) var(--ease-out-quart),
    background var(--dur-fast) var(--ease-out-quart);
}

.keisy__tab b { font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; }
.keisy__tab span { font-size: var(--fs-xs); color: var(--ink-muted); white-space: nowrap; }

.keisy__tab:hover { border-color: var(--line-strong); }

.keisy__tab[aria-selected='true'] {
  border-color: var(--asp-teal);
  background: rgb(29 233 182 / 12%);
  color: #fff;
}

/* Карточка кейса. Без скрипта — список карточек друг под другом. */
.keisy__list { display: grid; gap: var(--space-5); }

.keis {
  display: grid;
  gap: var(--space-5);
  padding: var(--space-4);
  border: 1px solid rgb(255 255 255 / 8%);
  border-radius: var(--radius-lg);
  background: rgb(12 24 44 / 84%);
  box-shadow:
    0 1px 0 rgb(255 255 255 / 6%) inset,
    0 30px 60px -36px rgb(0 0 0 / 90%);
}

@media (min-width: 60rem) {
  .keis {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
    gap: var(--space-6);
    padding: var(--space-5);
  }
}

@media (prefers-reduced-motion: no-preference) {
  [data-keisy='js'] .keis:not([hidden]) {
    animation: keis-in 0.45s var(--ease-out-quart) both;
  }
}

@keyframes keis-in {
  from { opacity: 0; transform: translateY(10px); }
}

.keis__gal { display: grid; gap: 0.6rem; align-content: start; min-width: 0; }

.keis__main {
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-deep);
}

/* Кадры нарезаны квадратом заранее, с фокусом на вывеске: обрезка
   браузером по центру отрезала бы надписи у широких снимков. */
.keis__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.keis__thumbs {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.5rem;
}

.keis__thumb {
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  overflow: hidden;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity var(--dur-fast) var(--ease-out-quart),
    border-color var(--dur-fast) var(--ease-out-quart);
}

.keis__thumb img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
}

.keis__thumb:hover { opacity: 0.9; }

.keis__thumb[aria-pressed='true'] {
  opacity: 1;
  border-color: var(--asp-teal);
}

.keis__body {
  display: grid;
  gap: var(--space-3);
  align-content: start;
  min-width: 0;
}

.keis__meta {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.8rem;
  align-items: baseline;
  font-size: var(--fs-sm);
}

.keis__client {
  font-weight: 700;
  color: var(--asp-teal-light);
  letter-spacing: 0.02em;
}

.keis__place { color: var(--ink-muted); }

.keis__h {
  margin: 0;
  font-size: var(--fs-h3);
  line-height: var(--lh-heading);
  text-wrap: balance;
}

.keis__lead {
  margin: 0;
  color: var(--ink-2);
  max-width: 60ch;
}

.keis__nums {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 9.5rem), 1fr));
  gap: var(--space-3);
}

.keis__nums li {
  display: grid;
  gap: 0.15rem;
  align-content: start;
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}

/* Значение длиннее колонки переносится по словам, а не наезжает на соседнее. */
.keis__nums b {
  overflow-wrap: break-word;
  font-size: var(--fs-xl);
  line-height: 1.1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.keis__nums span {
  font-size: var(--fs-xs);
  line-height: 1.35;
  color: var(--ink-muted);
}

.keis__more {
  border-top: 1px solid var(--line);
  padding-top: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.keis__more summary {
  cursor: pointer;
  width: fit-content;
  font-weight: 600;
  color: var(--asp-teal-light);
}

.keis__more p { margin: var(--space-3) 0 0; max-width: 62ch; }
.keis__more b { color: var(--ink); }
.keis__more ul { margin: var(--space-3) 0 0; padding-left: 1.1rem; display: grid; gap: 0.3rem; }

@media (max-width: 40rem) {
  /* Семь кнопок видов в столбик занимают экран целиком — на телефоне
     они идут лентой, как и вкладки. */
  .keisy__vidy {
    flex-wrap: nowrap;
    overflow-x: auto;
    margin-inline: -1.25rem;
    padding: 0 1.25rem 0.3rem;
    scrollbar-width: none;
  }
  .keisy__vid { flex: none; }

  .keis { padding: var(--space-3); }
  .keis__thumbs { gap: 0.35rem; }
}

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

/* Сетка плиток: каждый логотип в своей ячейке, все — одним белым цветом.
   Цветные логотипы разных сетей спорят между собой; в одном цвете полоса
   читается как список заказчиков, а не как витрина чужих брендов.

   Высоту логотипа задаёт --h в разметке, посчитанная из пропорций файла
   на равную площадь: при одной высоте на всех узкий «Банк Хлынов» терялся,
   а почти квадратный РЖД выпирал. */
.logos {
  list-style: none;
  margin: 0;
  padding: 0.35rem;
  display: grid;
  gap: 0.35rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid rgb(255 255 255 / 6%);
  border-radius: calc(var(--radius-lg) + 0.35rem);
  background: rgb(255 255 255 / 2%);
}

@media (min-width: 40rem) {
  .logos { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 60rem) {
  .logos { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

.logos li {
  display: grid;
  place-items: center;
  min-height: clamp(4.5rem, 8vw, 5.75rem);
  padding: var(--space-4);
  border: 1px solid rgb(255 255 255 / 7%);
  border-radius: var(--radius-lg);
  background: rgb(8 12 22 / 70%);
  transition: border-color var(--dur) var(--ease-out-quart),
    background var(--dur) var(--ease-out-quart);
}

.logos img {
  display: block;
  width: auto;
  height: calc(var(--h, 1.2rem) * 1.25);
  max-width: 78%;
  object-fit: contain;
  /* Любой цвет файла → чистый белый. */
  filter: brightness(0) invert(1);
  opacity: 0.86;
  transition: opacity var(--dur) var(--ease-out-quart);
}

.logos li:hover {
  border-color: rgb(255 255 255 / 16%);
  background: rgb(14 20 34 / 80%);
}

.logos li:hover img { opacity: 1; }

/* ── Этапы ────────────────────────────────────────────────────────────────── */

/* ── Полоса шагов ──────────────────────────────────────────────────────────
   Восемь шагов на общей линии. Линия одна на всю полосу и лежит позади
   кружков: рисовать её кусочками между соседями значит городить восемь
   отрезков, которые разъедутся на первом же переносе.

   Заполнение — второй слой поверх серого, шириной от нуля до целого. */
.shagi {
  position: relative;
  list-style: none;
  margin: clamp(2rem, 5vw, 3.5rem) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-5) var(--space-4);
}

.shagi::before,
.shagi::after {
  content: none;
}

.shagi > li {
  position: relative;
  display: grid;
  gap: 0.35rem;
  justify-items: start;
}

/* Кружок со значком. Номер стоит рядом мелко: значок узнаётся быстрее,
   а номер отвечает на вопрос «сколько ещё осталось». */
.shagi__znak {
  position: relative;
  z-index: 1;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--lt-line);
  background: var(--lt-bg-2);
  color: var(--asp-navy-calm);
  box-shadow: 0 8px 20px -14px rgb(19 26 45 / 55%);

  /* До своей очереди кружок бледный и чуть меньше. Перебор с масштабом здесь
     ни к чему: значок должен «включиться», а не выпрыгнуть — это спокойная
     схема процесса, а не заставка. */
  opacity: 0.35;
  transform: scale(0.86);
  transition:
    opacity 0.45s var(--ease-out-quart) var(--шаг, 0s),
    transform 0.45s cubic-bezier(0.34, 1.4, 0.64, 1) var(--шаг, 0s),
    border-color 0.45s var(--ease-out-quart) var(--шаг, 0s),
    color 0.45s var(--ease-out-quart) var(--шаг, 0s);
}

.shagi[data-виден='да'] .shagi__znak {
  opacity: 1;
  transform: none;
  border-color: rgb(41 121 255 / 35%);
}

.shagi[data-виден='да'] .shagi__znak b {
  opacity: 1;
  transform: none;
}

.shagi__znak svg {
  width: 1.3rem;
  height: 1.3rem;
}

.shagi__znak b {
  opacity: 0;
  transform: scale(0.7);
  transition:
    opacity 0.35s var(--ease-out-quart) calc(var(--шаг, 0s) + 0.12s),
    transform 0.35s cubic-bezier(0.34, 1.4, 0.64, 1) calc(var(--шаг, 0s) + 0.12s);
  position: absolute;
  right: -0.35rem;
  bottom: -0.35rem;
  min-width: 1.2rem;
  padding: 0 0.2rem;
  border-radius: var(--radius-pill);
  background: var(--asp-blue-deep);
  color: #fff;
  font-size: 0.65rem;
  font-weight: 700;
  line-height: 1.25rem;
  text-align: center;
}

.shagi h3 {
  margin: 0.35rem 0 0;
  font-size: var(--fs-base);
  line-height: var(--lh-heading);
}

.shagi p {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--lt-ink-2);
}

/* Широкий экран: два ряда по четыре шага.

   В одну линию восемь колонок влезали, но описания сжимались до пяти-шести
   строк в столбик шириной с ладонь. Два ряда дают вдвое больше места на шаг,
   и текст снова читается строкой, а не лесенкой.

   Линию рисуем отрезками у каждого шага, а не одной полосой на весь блок:
   полоса протянулась бы и через разрыв между рядами, соединив восьмой шаг
   с первым. Отрезок принадлежит шагу и переносится вместе с ним. */
@media (min-width: 901px) {
  .shagi {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    /* Два ряда по три полосы: кружки, названия, описания. Общие ряды нужны,
       иначе у каждого шага своя сетка и подписи встают на разной высоте. */
    grid-template-rows: repeat(2, auto auto auto);
    row-gap: var(--space-6);
  }

  .shagi > li {
    grid-row: span 3;
    grid-template-rows: subgrid;
    gap: 0.35rem;
  }

  .shagi > li::before,
  .shagi > li::after {
    content: '';
    position: absolute;
    top: 1.375rem;
    height: 2px;
    left: 3.35rem;
    right: calc(-1 * var(--space-4));
    transform: translateY(-1px);
    pointer-events: none;
  }

  .shagi > li::before { background: var(--lt-line); }

  /* Заполнение — тот же отрезок, растянутый от левого края. Считаем
     преобразованием, а не шириной: ширину браузер пересчитывает раскладкой
     на каждом кадре, преобразование — нет. */
  .shagi > li::after {
    background: var(--asp-blue-deep);
    transform: translateY(-1px) scaleX(0);
    transform-origin: left center;
    /* Отрезок трогается уже после того, как загорелся кружок слева от него:
       сначала шаг, потом путь к следующему. */
    transition: transform 0.75s var(--ease-out-quart) calc(var(--шаг, 0s) + 0.2s);
  }

  .shagi[data-виден='да'] > li::after {
    transform: translateY(-1px) scaleX(1);
  }

  /* Последний в ряду никуда не ведёт. */
  .shagi > li:nth-child(4n)::before,
  .shagi > li:nth-child(4n)::after {
    content: none;
  }
}

/* Очередь: каждый следующий шаг ждёт своей доли секунды. Восемь шагов
   разворачиваются примерно за три с половиной секунды — быстрее не успеваешь
   проследить порядок, ради которого полоса и нужна. */
.shagi > li:nth-child(1) { --шаг: 0s; }
.shagi > li:nth-child(2) { --шаг: 0.45s; }
.shagi > li:nth-child(3) { --шаг: 0.9s; }
.shagi > li:nth-child(4) { --шаг: 1.35s; }
.shagi > li:nth-child(5) { --шаг: 1.8s; }
.shagi > li:nth-child(6) { --шаг: 2.25s; }
.shagi > li:nth-child(7) { --шаг: 2.7s; }
.shagi > li:nth-child(8) { --шаг: 3.15s; }

/* Узкий экран: полоса встаёт вертикально, линия идёт по левому краю.
   Восемь колонок там не помещаются, а рвать путь на два ряда — терять
   главное, ради чего полоса и нужна. */
@media (max-width: 900px) {
  .shagi > li {
    grid-template-columns: 2.75rem minmax(0, 1fr);
    grid-template-areas:
      'знак имя'
      'знак текст';
    column-gap: var(--space-4);
    align-items: start;
  }

  .shagi__znak { grid-area: знак; }
  .shagi h3 { grid-area: имя; margin: 0.4rem 0 0; }
  .shagi p { grid-area: текст; }

  .shagi::before,
  .shagi::after {
    content: '';
    position: absolute;
    pointer-events: none;
    left: 1.375rem;
    width: 2px;
    transform: translateX(-1px);
    top: 1.375rem;
    bottom: 2.75rem;
  }

  .shagi::before { background: var(--lt-line); }

  .shagi::after {
    background: var(--asp-blue-deep);
    bottom: auto;
    height: 0;
    transition: height 1.6s var(--ease-out-quart);
  }

  .shagi[data-виден='да']::after {
    height: calc(100% - 5.5rem);
  }
}

/* Человек попросил меньше движения — показываем всё сразу и без переходов. */
@media (prefers-reduced-motion: reduce) {
  .shagi::after,
  .shagi > li::after,
  .shagi__znak,
  .shagi__znak b {
    transition: none;
  }

  .shagi__znak,
  .shagi__znak b {
    opacity: 1;
    transform: none;
  }
}


/* ── Производство ─────────────────────────────────────────────────────────── */

.prod {
  display: grid;
  gap: var(--space-6) var(--space-8);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
}

.prod__text p {
  color: var(--ink-2);
  max-width: 52ch;
}

.prod__facts {
  list-style: none;
  margin: var(--space-6) 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
}

.prod__facts li {
  display: grid;
  gap: 0.125rem;
  padding-left: var(--space-4);
  border-left: 2px solid var(--asp-teal);
}

.prod__facts b {
  font-size: var(--fs-lg);
  color: #fff;
}

.prod__facts span {
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

.prod__addr {
  font-size: var(--fs-sm);
  color: var(--ink-muted) !important;
}

/* Галерея цеха — те же лента, стрелки и точки, что в карточках видов
   (vidy.js находит её по data-gal). Кадр 4:3, скруглён как карточки. */
.prod__gal {
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
}

.prod__gal img {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

@media (max-width: 860px) {
  .prod {
    grid-template-columns: 1fr;
  }
}

/* ── Вопросы ──────────────────────────────────────────────────────────────── */

.faq {
  display: grid;
  gap: 0;
  max-width: var(--container-narrow);
}

.faq details {
  border-bottom: 1px solid var(--lt-line);
}

.faq summary {
  padding: var(--space-4) 2.5rem var(--space-4) 0;
  cursor: pointer;
  font-weight: 600;
  font-size: var(--fs-lg);
  color: var(--lt-ink);
  position: relative;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

/* Знак раскрытия рисуем сами: встроенный треугольник в разных браузерах
   выглядит по-разному и не поддаётся выравниванию. */
.faq summary::after {
  content: '';
  position: absolute;
  right: 0.5rem;
  top: 50%;
  width: 0.7rem;
  height: 0.7rem;
  margin-top: -0.45rem;
  border-right: 2px solid var(--asp-blue-deep);
  border-bottom: 2px solid var(--asp-blue-deep);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease-out-quart);
}

.faq details[open] summary::after {
  transform: rotate(-135deg);
  margin-top: -0.15rem;
}

.faq p {
  margin: 0 0 var(--space-5);
  max-width: 62ch;
  color: var(--lt-ink-2);
}

/* ── Заявка ───────────────────────────────────────────────────────────────── */

.lead-grid {
  display: grid;
  gap: var(--space-7) var(--space-8);
  /* `minmax(0, …)`, а не `1fr`: иначе широкое содержимое формы растягивает
     колонку и ломает раскладку на узком экране. На аренде это уже случалось. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
}

.lead-pitch p {
  color: var(--ink-2);
  max-width: 46ch;
}

.lead-pitch__mark {
  font-size: var(--fs-sm);
  color: var(--ink-muted) !important;
  padding-top: var(--space-4);
  border-top: 1px solid var(--line);
}

.lead-contacts {
  list-style: none;
  margin: var(--space-5) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}

.lead-contacts li {
  display: grid;
  gap: 0.125rem;
}

.lead-contacts a {
  font-size: var(--fs-xl);
  font-weight: 600;
  color: #fff;
  text-decoration: none;
}

.lead-contacts a:hover {
  color: var(--asp-teal-light);
}

.lead-contacts span {
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.lead-form {
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  display: grid;
  gap: var(--space-5);
  align-content: start;
}

/* ── Подборщик ────────────────────────────────────────────────────────────── */

.pick {
  display: grid;
  gap: var(--space-5);
}

.pick__h {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: var(--lh-heading);
  color: var(--ink);
}

.pick__q {
  border: 0;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.pick__q legend {
  padding: 0;
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.pick__opts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Кнопки вместо выпадающих списков: на телефоне выбор одним касанием,
   и все варианты видны сразу — не приходится открывать, чтобы узнать,
   что вообще предлагают. */
.pick__opts label {
  position: relative;
  display: inline-flex;
}

.pick__opts input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
  margin: 0;
}

.pick__opts span {
  display: inline-block;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  transition: border-color var(--dur-fast) var(--ease-out-quart),
    background var(--dur-fast) var(--ease-out-quart),
    color var(--dur-fast) var(--ease-out-quart);
}

.pick__opts label:hover span {
  border-color: var(--line-strong);
  color: var(--ink);
}

.pick__opts input:checked + span {
  border-color: var(--asp-teal);
  background: rgb(29 233 182 / 14%);
  color: #fff;
}

/* Клавиатурный фокус обязан быть виден: сам кружок мы спрятали,
   и без этого человек, идущий табом, не поймёт, где он находится. */
.pick__opts input:focus-visible + span {
  outline: 2px solid var(--asp-teal-light);
  outline-offset: 2px;
}

.pick__out {
  display: grid;
  gap: 0.3rem;
  padding: var(--space-4);
  border-radius: var(--radius);
  border: 1px solid rgb(29 233 182 / 40%);
  background: rgb(29 233 182 / 8%);
  font-size: var(--fs-sm);
}

.pick__out b { color: var(--asp-teal-light); }
.pick__out span { color: var(--ink); line-height: var(--lh-body); }

.pick__hint {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

@media (prefers-reduced-motion: reduce) {
  .pick__opts span { transition: none; }
}


@media (max-width: 860px) {
  .lead-grid {
    grid-template-columns: 1fr;
  }
}

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

.foot {
  background: var(--bg-deep);
  color: var(--ink-2);
  padding-block: var(--space-7) var(--space-5);
  border-top: 1px solid var(--line);
}

.foot__in {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
}

.foot__logo {
  height: 1.9rem;
  width: auto;
  display: block;
  margin-bottom: var(--space-4);
}

.foot__name {
  margin: 0 0 var(--space-3);
  font-weight: 600;
  color: var(--ink);
}

.foot__head {
  margin: 0 0 var(--space-3);
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.foot__small {
  margin: 0 0 0.35rem;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}

.foot__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
  font-size: var(--fs-sm);
}

.foot__list a {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.foot__list a:hover {
  color: var(--ink);
  border-bottom-color: var(--asp-teal);
}

.foot__todo {
  color: #ffd968;
  outline: 1px dashed var(--warn-line);
  border-radius: 3px;
  padding: 0 0.35em;
}

.foot__bottom {
  max-width: var(--container);
  margin: var(--space-6) auto 0;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

/* ── Движение ─────────────────────────────────────────────────────────────── */

/* Кому движение мешает — тому его не показываем. Это не украшение,
   от которого можно отказаться на глаз: для части людей анимация
   вызывает физическое недомогание. */
@media (prefers-reduced-motion: reduce) {
  .vid,
  .logos img,
  .faq summary::after {
    transition: none;
  }

  .vid:hover {
    transform: none;
  }
}

/* ── Типы подсветки ────────────────────────────────────────────────────────
   Липкий раздел: слева четыре карточки, справа один и тот же фасад с одной
   и той же вывеской. Прокрутка переключает тип подсветки — сравнивать можно
   только так, четыре разных снимка ничего не доказывают.

   Без движения раздел остаётся обычным списком: карточки читаются сами по
   себе, а холст в этом режиме не поднимается вовсе. */
.fasad {
  position: relative;
  background: var(--bg-deep);
}

:root[data-motion='on'] .fasad {
  height: 420svh;
}

.fasad__sticky {
  position: relative;
  overflow: clip;
  padding: clamp(3rem, 7vw, 6rem) 0;
}

:root[data-motion='on'] .fasad__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  padding: 0;
  display: grid;
  /* Своя колонка тексту, своя — фасаду. Тот же приём, что на первом экране:
     подбирать положение модели отступами — гиблое дело. */
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  align-items: center;
}

/* Без движения раздел ведёт себя как обычная полоса: те же поля, что
   у `.wrap`, — иначе текст ложится вплотную к краю окна. */
.fasad__text {
  position: relative;
  z-index: 2;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

:root[data-motion='on'] .fasad__text {
  max-width: none;
  margin: 0;
  padding-inline: clamp(1.25rem, 5vw, 4.5rem);
}

.fasad__eyebrow {
  margin: 0 0 0.5rem;
  color: var(--asp-teal);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.fasad__list {
  list-style: none;
  margin: clamp(1.5rem, 3vw, 2.5rem) 0 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}

.fasad__list li { display: grid; }

/* Карточка — кнопка: по ней переключают тип подсветки, и с клавиатуры
   до неё тоже надо доходить. Оформление то же, что у развилки на первом
   экране: одна страница — один вид карточки.

   Фон плотнее, чем там. Развилка лежит на ровном тёмном фоне, а эти —
   поверх освещённой ночной сцены: на витрине и на отсвете стены
   полупрозрачная плашка текст не держала. */
.fasad__card {
  position: relative;
  display: grid;
  gap: 0.4rem;
  align-content: start;
  width: 100%;
  padding: var(--space-4) var(--space-5);
  border: 1px solid rgb(255 255 255 / 8%);
  border-radius: var(--radius-lg);
  background: rgb(12 24 44 / 84%);
  backdrop-filter: blur(14px) saturate(1.1);
  box-shadow:
    0 1px 0 rgb(255 255 255 / 6%) inset,
    0 22px 54px -30px rgb(0 0 0 / 92%);
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.fasad__card:hover {
  border-color: var(--asp-teal);
  transform: translateY(-3px);
}

.fasad__card:focus-visible {
  outline: 2px solid var(--asp-teal);
  outline-offset: 3px;
}

.fasad__card h3 {
  margin: 0;
  font-size: var(--fs-lg);
  line-height: var(--lh-heading);
  color: var(--ink);
}

.fasad__card p {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
  max-width: 42ch;
}

/* Выбранный тип: рамка бирюзой, как на наведении. Гаснут только неактивные,
   и гаснут текстом — фон остаётся плотным, иначе на светлом куске сцены
   карточка перестаёт читаться совсем. */
:root[data-motion='on'] .fasad__card {
  opacity: calc(0.62 + 0.38 * var(--on, 0));
  border-color: rgb(29 233 182 / calc(8% + 82% * var(--on, 0)));
  transition: opacity var(--dur) var(--ease-out-quart),
    border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.fasad__tag {
  justify-self: start;
  margin-top: var(--space-2);
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: rgb(29 233 182 / 12%);
  color: var(--asp-teal);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.03em;
}

.fasad__canvas,
.fasad__preview {
  display: none;
}

:root[data-motion='on'] .fasad__canvas {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

:root[data-motion='on'] .fasad__preview {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

:root[data-motion='on'] .fasad[data-scene='сцена'] .fasad__preview,
:root[data-motion='on'] .fasad[data-scene='постер'] .fasad__preview {
  display: none;
}

/* Невысокий экран. Липкая колонка ровно в высоту окна, и семь блоков текста
   в неё не влезают: заголовок уезжает под шапку, последняя карточка — под
   нижний край. Ноутбук с окном 1280 × 800 — это не редкий случай, а самый
   обычный, поэтому ужимаем, а не прячем. */
@media (min-width: 901px) and (max-height: 900px) {
  /* Липкий слой начинается под самой шапкой, и на невысоком экране надзаголовок
     уезжает ей за спину. Сдвигаем содержимое ровно на её высоту. */
  :root[data-motion='on'] .fasad__sticky { padding-top: 3.5rem; }
  :root[data-motion='on'] .fasad .h2 { font-size: clamp(1.6rem, 3vw, 2.1rem); }
  :root[data-motion='on'] .fasad .lead { font-size: 0.95rem; }
  :root[data-motion='on'] .fasad__list { margin-top: 1.1rem; gap: 0.35rem; }
  :root[data-motion='on'] .fasad__card { padding: 0.6rem 0.9rem; }
  :root[data-motion='on'] .fasad__card h3 { font-size: 0.98rem; }
  :root[data-motion='on'] .fasad__card p { font-size: 0.86rem; line-height: 1.4; }
  :root[data-motion='on'] .fasad__tag { margin-top: 0.35rem; }
}

/* Узкий экран: липкость и холст выключены выше, здесь только раскладка. */
@media (max-width: 900px) {
  .fasad__card p { font-size: 0.9rem; }
}

/* ── Прозрачная смета ──────────────────────────────────────────────────────
   Две колонки: слева вводная и минимальная сумма, справа состав. Разбивка —
   главное, ради чего блок стоит, поэтому ей отдана большая половина. */
.smeta {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

@media (min-width: 901px) {
  .smeta {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  }
}

.smeta__eyebrow {
  margin: 0 0 0.6rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asp-teal-light);
}

/* Минимальная сумма — отдельной карточкой: это не пункт сметы, а порог входа,
   и в общем списке он читался бы как ещё одна статья расходов. */
.smeta__min {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  padding: var(--space-5);
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
}

.smeta__min-label {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

.smeta__min-sum {
  margin: 0.35rem 0 0.6rem;
  font-size: clamp(1.9rem, 4vw, 2.6rem);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--asp-teal-light);
}

.smeta__min-note {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--ink-2);
}

.smeta__list {
  margin: 0;
  display: grid;
  gap: 0.6rem;
}

/* Название и содержание — в две колонки: так глаз бежит по названиям
   и останавливается на нужном, не читая всё подряд. На узком экране
   колонки складываются. */
.smeta__row {
  display: grid;
  gap: 0.35rem;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
}

@media (min-width: 601px) {
  .smeta__row {
    grid-template-columns: minmax(8rem, 0.4fr) minmax(0, 1fr);
    gap: var(--space-4);
    align-items: baseline;
  }
}

.smeta__row dt {
  margin: 0;
  font-weight: 600;
}

.smeta__row dd {
  margin: 0;
  color: var(--ink-2);
  line-height: 1.6;
}

/* ── Панели услуг ──────────────────────────────────────────────────────────
   Раскрывающийся ряд: активная панель забирает семь долей ширины, остальные
   по одной. Ширину считает флексбокс, движение — переходы; скрипту остаётся
   переставить `aria-pressed`.

   Состояние живёт в атрибуте, а не в классе, намеренно: `aria-pressed` нужен
   и без стилей — программе чтения с экрана, — и держать рядом второй,
   декоративный признак того же самого значило бы иметь два источника правды. */
.vybor {
  list-style: none;
  margin: clamp(1.75rem, 4vw, 3rem) 0 0;
  padding: 0;
  display: flex;
  gap: 0.35rem;
  height: clamp(20rem, 45vh, 26rem);
  overflow: hidden;
}

.vybor > li {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  transition: flex-grow var(--dur-slow, 700ms) var(--ease-out-quart);
}

.vybor > li:has([aria-pressed='true']) {
  flex-grow: 7;
}

.vybor__panel {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  gap: var(--space-3);
  padding: var(--space-4);
  border: 2px solid transparent;
  border-radius: var(--radius);
  background-color: #16181d;
  /* Сам снимок приходит из разметки: относительный путь внутри `var()`
     считается **от файла стилей**, а не от страницы, и превращался
     в `assets/css/assets/img/…`. Подставленный в атрибут элемента —
     считается от документа, как и ожидаешь. */
  background-size: auto 120%;
  background-position: center;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--dur) var(--ease-out-quart),
    background-size var(--dur-slow, 700ms) var(--ease-out-quart),
    box-shadow var(--dur) var(--ease-out-quart);

  /* Въезд по очереди при появлении раздела. */
  opacity: 0;
  transform: translateX(-2.5rem);
}

[data-vybor][data-виден='да'] .vybor__panel {
  opacity: 1;
  transform: none;
  transition: opacity 0.7s var(--ease-out-quart) var(--задержка, 0s),
    transform 0.7s var(--ease-out-quart) var(--задержка, 0s),
    border-color var(--dur) var(--ease-out-quart),
    background-size var(--dur-slow, 700ms) var(--ease-out-quart);
}

/* Затемнение снизу — под подпись. Без него белый текст ложится на светлые
   участки фотографии и пропадает: снимки у нас разные, и рассчитывать
   на удачный кадр нельзя. */
.vybor__panel::after {
  content: '';
  position: absolute;
  inset: auto 0 0;
  height: 70%;
  background: linear-gradient(to top, rgb(6 10 18 / 88%), transparent);
  pointer-events: none;
}

.vybor__panel[aria-pressed='true'] {
  border-color: rgb(255 255 255 / 85%);
  background-size: auto 100%;
  box-shadow: 0 20px 60px rgb(0 0 0 / 50%);
}

.vybor__panel:focus-visible {
  outline: 2px solid var(--asp-teal);
  outline-offset: 3px;
}

.vybor__ikonka {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 2px solid rgb(255 255 255 / 28%);
  background: rgb(20 24 32 / 78%);
  backdrop-filter: blur(10px);
}

.vybor__ikonka svg {
  width: 1.35rem;
  height: 1.35rem;
}

/* Подпись видна только у раскрытой панели: в свёрнутой на неё просто нет
   места, а обрезанный на полуслове заголовок хуже, чем никакого. */
.vybor__text {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 0.15rem;
  min-width: 0;
  opacity: 0;
  transform: translateX(1.5rem);
  transition: opacity var(--dur-slow, 700ms) var(--ease-out-quart),
    transform var(--dur-slow, 700ms) var(--ease-out-quart);
}

.vybor__panel[aria-pressed='true'] .vybor__text {
  opacity: 1;
  transform: none;
}

.vybor__imya {
  font-size: var(--fs-lg);
  font-weight: 700;
  line-height: var(--lh-heading);
  white-space: nowrap;
}

.vybor__opis {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 34rem;
}

/* Узкий экран: ряд не помещается, и раскрывать нечего — панели становятся
   обычными карточками, подписи видны у всех сразу. */
@media (max-width: 900px) {
  .vybor {
    flex-direction: column;
    height: auto;
    gap: 0.6rem;
  }

  .vybor > li,
  .vybor > li:has([aria-pressed='true']) {
    flex: 0 0 auto;
  }

  .vybor__panel {
    min-height: 9.5rem;
    background-size: cover;
    transform: none;
  }

  .vybor__text {
    opacity: 1;
    transform: none;
  }

  .vybor__imya {
    white-space: normal;
  }

  /* Затемнение на всю карточку, а не только снизу: подпись здесь стоит
     посередине, а снимки светлые — «Пятёрочка» на солнце съедала текст. */
  .vybor__panel::after {
    height: 100%;
    background: linear-gradient(to top, rgb(6 10 18 / 92%), rgb(6 10 18 / 55%));
  }
}

/* Человек попросил меньше движения — показываем всё сразу и без въездов. */
@media (prefers-reduced-motion: reduce) {
  .vybor__panel,
  .vybor__text,
  .vybor > li {
    transition: none;
  }

  .vybor__panel {
    opacity: 1;
    transform: none;
  }
}

/* ── Сравнение «чертёж — готово» ───────────────────────────────────────────
   Два кадра друг на друге, верхний обрезан по положению ручки. Положение
   держится в `--поз`; скрипт только переписывает её, всё остальное считают
   стили. */
.sravn {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--lt-line);
  line-height: 0;
}

.sravn__kadr {
  display: block;
  width: 100%;
  height: auto;
  border: 0;
  border-radius: 0;
}

/* Верхний кадр лежит поверх и обрезается справа. `inset` вместо ширины:
   так кадр не сжимается, а именно открывается — иначе фасад «худеет»
   на глазах, и сравнивать становится нечего. */
.sravn__kadr--do {
  position: absolute;
  inset: 0;
  clip-path: inset(0 calc(100% - var(--поз, 50%)) 0 0);
}

.sravn__liniya {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--поз, 50%);
  width: 3px;
  margin-left: -1.5px;
  background: #fff;
  box-shadow: 0 0 0 1px rgb(0 0 0 / 18%);
  pointer-events: none;
}

.sravn__metka {
  position: absolute;
  top: var(--space-3);
  z-index: 2;
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-pill);
  background: rgb(6 10 18 / 72%);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.2;
  pointer-events: none;
}

.sravn__metka--do { left: var(--space-3); }
.sravn__metka--posle { right: var(--space-3); }

/* Ползунок растянут на весь кадр и невидим, кроме бегунка: тянуть можно
   в любом месте картинки, а не целиться в тонкую полоску. */
.sravn__ruchka {
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  margin: 0;
  padding: 0;
  appearance: none;
  background: transparent;
  cursor: ew-resize;
}

.sravn__ruchka:focus-visible {
  outline: 2px solid var(--asp-blue-deep);
  outline-offset: 3px;
}

/* Бегунок и есть кружок на линии. Оформляем оба движка: правила
   `::-webkit-slider-thumb` и `::-moz-range-thumb` нельзя объединить
   в один список — браузер отбрасывает всё правило целиком, если хоть
   один селектор ему незнаком. */
.sravn__ruchka::-webkit-slider-thumb {
  appearance: none;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  border: 3px solid var(--asp-blue-deep);
  background: #fff no-repeat center / 1.1rem
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232962ff' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M9 6 4 12l5 6M15 6l5 6-5 6'/%3E%3C/svg%3E");
  box-shadow: 0 6px 18px rgb(0 0 0 / 35%);
  cursor: ew-resize;
}

.sravn__ruchka::-moz-range-thumb {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  border: 3px solid var(--asp-blue-deep);
  background: #fff no-repeat center / 1.1rem
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232962ff' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M9 6 4 12l5 6M15 6l5 6-5 6'/%3E%3C/svg%3E");
  box-shadow: 0 6px 18px rgb(0 0 0 / 35%);
  cursor: ew-resize;
}

.sravn__ruchka::-webkit-slider-runnable-track { background: transparent; }
.sravn__ruchka::-moz-range-track { background: transparent; }

/* Подпись стоит вне рамки: внутри её срезало бы скругление и обрезка. */

/* ── Форма Битрикса на тёмной полосе ───────────────────────────────────────
   Форма приходит со своим светлым оформлением, рассчитанным на белую
   страницу: на нашей тёмной полосе она встаёт белым прямоугольником
   с невидимыми подписями.

   Перекрашиваем через `!important` — иначе не выйдет: Битрикс раздаёт стили
   инлайном и своим таблицей стилей, загруженной после нашей. Правила держим
   узкими, по классам самой формы, чтобы не задеть остальную страницу.
   Порядок тот же, что на rentvk.pro, — одна и та же CRM, одни и те же классы. */
.b24-mount {
  color-scheme: dark;
}

/* Карточку уже нарисовала страница — своя подложка форме не нужна. */
.b24-mount .b24-form,
.b24-mount .b24-form-wrapper,
.b24-mount .b24-form-content,
.b24-mount .b24-form-padding-side,
.b24-mount .b24-form-header-padding {
  background: transparent !important;
  box-shadow: none !important;
}

.b24-mount .b24-form-control {
  /* Именно `background-color`, а не сокращённое `background`: сокращённая
     запись сбрасывает и `background-image`, которой Битрикс рисует стрелку
     у раскрывающихся списков. */
  background-color: rgb(255 255 255 / 6%) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--radius) !important;
  color: var(--ink) !important;
}

.b24-mount .b24-form-control::placeholder {
  color: var(--ink-muted) !important;
}

/* Автозаполнение браузера. Яндекс и Chrome подставляют имя и телефон сами
   и красят такое поле своим стилем: тёмный текст на светлой заливке, поверх
   нашего color. Цвет перебивается только text-fill-color, а заливку —
   внутренней тенью: фон автозаполнения обычным background не снять. */
.b24-mount .b24-form-control:-webkit-autofill,
.b24-mount .b24-form-control:-webkit-autofill:hover,
.b24-mount .b24-form-control:-webkit-autofill:focus,
.b24-mount .b24-form-control:autofill {
  -webkit-text-fill-color: var(--ink) !important;
  caret-color: var(--ink);
  box-shadow: 0 0 0 1000px color-mix(in srgb, var(--bg) 90%, #fff) inset !important;
  transition: background-color 9999s ease-out 0s;
}

.b24-mount .b24-form-control {
  -webkit-text-fill-color: var(--ink) !important;
  caret-color: var(--ink);
}

.b24-mount .b24-form-control:focus {
  border-color: var(--asp-teal) !important;
  outline: none !important;
}

/* Подписи — только по своим классам. Цвет обязательной звёздочки не трогаем:
   он несёт смысл, а не оформление. */
.b24-mount .b24-form-control-label,
.b24-mount .b24-form-control-desc,
.b24-mount .b24-form-control-comment,
.b24-mount .b24-form-field-agreement {
  color: var(--ink-2) !important;
}

.b24-mount input[type='checkbox'],
.b24-mount input[type='radio'] {
  accent-color: var(--asp-teal);
}

.b24-mount button {
  background: var(--asp-blue-deep) !important;
  border-color: var(--asp-blue-deep) !important;
  color: #fff !important;
  border-radius: var(--radius) !important;
  font-weight: 600 !important;
}

.b24-mount,
.b24-mount input,
.b24-mount textarea,
.b24-mount select,
.b24-mount button {
  font-family: var(--font) !important;
}

/* Раскрытый список рисует браузер поверх страницы, и прозрачный фон там
   превращается в белый текст на белом. Ставим явно. */
.b24-mount select option {
  background: var(--bg-deep);
  color: var(--ink);
}

.form-note {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-2);
}

/* ── Заявка ────────────────────────────────────────────────────────────────
   Одна карточка на два столбца: слева обещание, проверяемые факты и прямые
   контакты, справа подборщик и форма. Приём тот же, что на rentvk.pro, —
   и не ради единообразия: человек в этот момент решает, отдавать ли номер,
   и доводы должны быть у него перед глазами, а не в подвале страницы. */
.zayavka {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  padding: clamp(1.25rem, 3vw, 2.25rem);
  border-radius: var(--radius-lg);
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  scroll-margin-top: 6rem;
}

@media (min-width: 901px) {
  .zayavka {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    align-items: start;
  }
}

.zayavka__pitch {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.zayavka__pitch .lead {
  margin: 0;
  max-width: 38ch;
  font-size: var(--fs-base);
}

.zayavka__form {
  display: grid;
  gap: var(--space-5);
  min-width: 0;
}

/* Четыре проверяемых факта. Не «качество и профессионализм», а то, что можно
   сверить: год, адрес, документы, реквизиты. */
.proof {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(45%, 11rem), 1fr));
  gap: 0.625rem;
}

.proof li {
  display: grid;
  gap: 0.15rem;
  padding: var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 3%);
}

.proof__icon {
  width: 1.25rem;
  height: 1.25rem;
  color: var(--asp-teal);
  margin-bottom: 0.35rem;
}

.proof b {
  font-size: var(--fs-sm);
}

.proof span {
  font-size: var(--fs-xs);
  color: var(--ink-2);
  line-height: 1.45;
}

/* Прямые контакты. Пунктир вместо сплошной рамки: это не карточка наравне
   с фактами, а приписка к ним. */
.zayavka__direct {
  padding: 1rem 1.125rem;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

.zayavka__direct p {
  margin: 0 0 0.75rem;
  font-size: var(--fs-xs);
  color: var(--ink-muted);
}

.zayavka__direct ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
}

.zayavka__direct a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* 44 px тач-цели: по этим ссылкам звонят с телефона. */
  min-height: 44px;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur) var(--ease-out-quart);
}

.zayavka__direct a:hover {
  color: var(--asp-teal-light);
}

.zayavka__ico {
  display: grid;
  place-items: center;
  width: 1.85rem;
  height: 1.85rem;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: rgb(255 255 255 / 4%);
  color: var(--asp-teal);
}

.zayavka__ico svg {
  width: 1rem;
  height: 1rem;
}

/* ── Соседние направления ──────────────────────────────────────────────────
   Карточки с кадром вместо текстовых ссылок: по слову «аренда» не понять,
   что за ним настоящее производство. Разметка и стили те же, что на аренде, —
   это один и тот же блок на разных сайтах, и расходиться им незачем. */
.sosedi {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: clamp(0.75rem, 2vw, 1.5rem);
}

.sosedi a {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  text-decoration: none;
  color: var(--ink);
  transition: color var(--dur) var(--ease-out-quart);
}

.sosedi img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  transition: border-color var(--dur) var(--ease-out-quart),
    transform var(--dur) var(--ease-out-quart);
}

.sosedi span {
  font-size: var(--fs-sm);
  font-weight: 600;
}

/* Стрелка показывает, что это переход на другой сайт, а не якорь. */
.sosedi span::after {
  content: ' →';
  color: var(--asp-teal);
}

@media (hover: hover) {
  .sosedi a:hover { color: var(--asp-teal-light); }

  .sosedi a:hover img {
    border-color: var(--asp-teal);
    transform: translateY(-2px);
  }
}

.sosedi a:focus-visible {
  outline: 2px solid var(--asp-teal);
  outline-offset: 4px;
  border-radius: var(--radius);
}

.measure { max-width: 62ch; }

/* ── Страницы документов ───────────────────────────────────────────────────
   Согласие, политика и СОУТ. Светлая тема: это не витрина, а текст, который
   читают подряд и иногда распечатывают, — тёмный фон тут только мешает.

   Переменные тона переопределены локально, чтобы общие правила сайта,
   рассчитанные на тёмный фон, сами встали как надо и не пришлось перекрывать
   каждое из них по отдельности. */
.doc-page {
  background: var(--lt-bg);
  color: var(--lt-ink);
  --ink: var(--lt-ink);
  --ink-2: var(--lt-ink-2);
  --ink-muted: var(--lt-ink-muted);
  --line: var(--lt-line);
  /* Иначе призрачная кнопка получает белую рамку тёмной темы и на светлом
     фоне выглядит без границ вовсе. */
  --line-strong: rgb(15 26 46 / 28%);
}

/* Подвал страниц-документов: реквизиты мелким шрифтом. */
.doc-foot {
  border-top: 1px solid var(--lt-line);
  background: var(--lt-bg-2);
  padding-block: var(--space-6);
  font-size: var(--fs-sm);
}

.doc-foot .muted {
  margin: 0;
  color: var(--lt-ink-muted);
}

.doc-top {
  border-bottom: 1px solid var(--lt-line);
  background: var(--lt-bg-2);
}

.doc-top__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
  font-size: var(--fs-sm);
}

.doc-top__back {
  text-decoration: none;
  font-weight: 600;
}

.doc-top__back:hover {
  color: var(--asp-blue-deep);
}

.doc-top__phone {
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
}

.doc {
  padding-block: var(--space-8);
}

.doc__inner {
  max-width: var(--container-narrow);
}

.doc h1 {
  font-size: var(--fs-h2);
  margin-bottom: var(--space-2);
}

.doc h2 {
  font-size: var(--fs-h3);
  margin-top: var(--space-7);
}

.doc__meta {
  margin-bottom: var(--space-7);
}

.doc p,
.doc li {
  max-width: 68ch;
}

.doc li {
  margin-bottom: 0.375rem;
}

.doc a {
  color: var(--asp-navy-calm);
}

/* Таблица в документе. Прокручивается вбок в своей рамке: три колонки
   с длинными формулировками на телефон не помещаются никак, а резать
   юридический текст переносами нельзя. */
.doc__table {
  width: 100%;
  min-width: 34rem;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.doc__table th,
.doc__table td {
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--lt-line);
  text-align: left;
  vertical-align: top;
  color: var(--lt-ink-2);
}

.doc__table thead th {
  background: var(--lt-bg);
  color: var(--lt-ink);
  font-weight: 600;
}

.doc .tablewrap {
  margin-block: var(--space-5);
  /* Своя прокрутка вбок: три колонки с юридическими формулировками
     на телефон не помещаются, а резать текст нельзя. tabindex в разметке
     делает рамку доступной с клавиатуры. */
  overflow-x: auto;
  border: 1px solid var(--lt-line);
  border-radius: var(--radius);
}

.doc .tablewrap:focus-visible {
  outline: 2px solid var(--asp-blue-deep);
  outline-offset: 2px;
}

/* Ссылки внутри документа специфичнее кнопки и перекрывали её белый текст:
   синее по синему давало 1,76:1. */
.doc a.btn {
  color: #fff;
}

/* Призрачная кнопка на светлой странице: белый текст правила выше делал
   её невидимой — белым по белому. */
.doc a.btn--ghost {
  color: var(--lt-ink);
}

/* Выходы со страницы 404. Список, а не кнопки в ряд: вариантов три,
   и у каждого нужно пояснение — куда он ведёт. */
.err__links {
  margin: var(--space-5) 0;
  padding-left: 1.25rem;
}

.err__links li {
  margin-bottom: 0.5rem;
}

.doc__file {
  margin-block: var(--space-5);
}

/* Смотрелка PDF: высота от экрана, но не выше него — иначе страница
   превращается в один документ без начала и конца. */
.doc__pdf {
  display: block;
  width: 100%;
  height: min(80vh, 46rem);
  border: 1px solid var(--lt-line);
  border-radius: var(--radius);
  background: var(--lt-bg);
}

/* ── Файлы cookie ════════════════════════════════════════════════════════════
   Панель фиксированная, поэтому её появление не двигает раскладку — сдвиг
   здесь был бы обиднее всего: баннер видят все и в первую секунду.

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

.cookie {
  position: fixed;
  inset: auto 0 0;
  /* Выше липкой панели телефона: она тоже прижата к низу. */
  z-index: var(--z-toast);
  padding-block: 1rem;
  background: rgb(11 17 31 / 96%);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  color: var(--ink);
}

.cookie__inner {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
  flex-wrap: wrap;
}

.cookie__text {
  flex: 1 1 22rem;
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--ink-2);
}

.cookie__text a {
  color: var(--asp-teal-light);
}

.cookie__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Третья кнопка не должна спорить за внимание с первыми двумя: она ведёт
   не к решению, а к выбору его состава. */
.btn--quiet {
  border-color: transparent;
  background: none;
  color: var(--ink-2);
}

.btn--quiet:hover {
  border-color: var(--line-strong);
  color: var(--ink);
}

.cookie__tune {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}

.cookie__cats {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

.cookie__cats li {
  padding: 0.875rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: rgb(255 255 255 / 4%);
}

.cookie__cats label {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  /* 44 px тач-цели набираем самой строкой: галочку жмут пальцем. */
  min-height: 44px;
  cursor: pointer;
}

.cookie__cats input:disabled {
  cursor: default;
}

.cookie__cats li:has(input:disabled) label {
  cursor: default;
}

.cookie__cats b {
  font-size: var(--fs-sm);
}

.cookie__cats span {
  display: block;
  font-size: var(--fs-xs);
  line-height: 1.45;
  color: var(--ink-muted);
}

/* На телефоне кнопки баннера растягиваются в строку: в них попадают пальцем. */
@media (max-width: 900px) {
  .cookie__actions .btn {
    flex: 1 1 auto;
    justify-content: center;
  }
}

/* Кнопка, которая ведёт себя как ссылка: повторный выбор в подвале — это
   не действие на странице, а вызов того же баннера. Вид — как у соседних
   ссылок подвала. */
.foot__link {
  padding: 0;
  border: 0;
  border-bottom: 1px solid transparent;
  background: none;
  font: inherit;
  color: var(--ink-2);
  text-align: left;
  cursor: pointer;
}

.foot__link:hover {
  color: var(--ink);
  border-bottom-color: var(--asp-teal);
}
