/* =============================================================
   GLOSSLAB — «Свет проявляет поверхность»
   Система описана в DESIGN.md. Исходный референс — design/REFERENCE-vivid-co.md.
   Тема одна: тёмная. Светлого варианта нет намеренно (сцена — тёмный бокс).
   ============================================================= */

/* ---------- Onest Variable, self-hosted, SIL OFL 1.1 (fonts/OFL-Onest.txt) ---------- */
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-display: swap;
  font-weight: 400 700;
  src: url("../fonts/onest-cyrillic-400-700.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-display: swap;
  font-weight: 400 700;
  /* latin-ext несёт знак рубля U+20BD — без него цены падают на системный шрифт */
  src: url("../fonts/onest-latin-ext-400-700.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308,
    U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
    U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Onest";
  font-style: normal;
  font-display: swap;
  font-weight: 400 700;
  src: url("../fonts/onest-latin-400-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304,
    U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ================= TOKENS ================= */
:root {
  /* палитра */
  --c-obsidian: #101010;
  --c-bone: #fffdf9;
  --c-graphite: #495764;
  --c-ash: #403f3f;
  --c-fog: #6f879c;
  --c-pure-black: #000000;

  /* семантика */
  --surface: var(--c-obsidian);
  --text-primary: var(--c-bone);
  --text-secondary: var(--c-fog);   /* 5.09:1 — от 16px */
  --text-quiet: #93a4b4;            /* 7.44:1 — подписи 13–15px */
  --text-soft: #c3ccd5;             /* 11.7:1 — вторичный текст поверх фотографии */
  --line: var(--c-ash);             /* только декоративные линии */
  --line-strong: rgba(255, 253, 249, 0.22);
  --line-hover: rgba(255, 253, 249, 0.44);
  --focus: var(--c-bone);

  /* типографика */
  --font: "Onest", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --t-display: clamp(2.75rem, 1.42rem + 5.93vw, 6.75rem);   /* 44 → 108px */
  --t-h2: clamp(2rem, 1.06rem + 4.18vw, 4.25rem);           /* 32 → 68px */
  --t-h3: clamp(1.375rem, 1.11rem + 1.18vw, 2.0625rem);     /* 22 → 33px */
  --t-h4: clamp(1.125rem, 1.05rem + 0.33vw, 1.3125rem);     /* 18 → 21px */
  --t-lead: clamp(1.0625rem, 0.99rem + 0.37vw, 1.3125rem);  /* 17 → 21px */
  --t-body: clamp(1rem, 0.95rem + 0.23vw, 1.1875rem);       /* 16 → 19px */
  --t-small: clamp(0.9375rem, 0.92rem + 0.09vw, 1rem);      /* 15 → 16px */
  --t-meta: clamp(0.8125rem, 0.8rem + 0.09vw, 0.875rem);    /* 13 → 14px */
  --t-num: clamp(2rem, 1.5rem + 2vw, 3rem);                  /* 32 → 48px */

  /* трекинг: плотно на крупном, почти нейтрально на мелких метках капсом */
  --track-h2: -0.025em;     /* заголовки разделов */
  --track-h3: -0.015em;     /* названия услуг, тарифов, этапов */
  --track-label: 0.02em;    /* навигация, CTA, метки капсом, «До / После» */

  /* ритм */
  --gutter: 20px;
  --shell-max: 1440px;
  --section-gap: 64px;
  --masthead-h: 68px;

  /* форма */
  --r-media: 15px;
  --r-nav: 5px;

  /* движение — одна система на весь сайт, правила в DESIGN.md */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);       /* вход, выход, нажатие, меню */
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);   /* перемещение по экрану */
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);    /* панель во весь экран (drawer); сейчас не нужна */
  --ease-cinematic: cubic-bezier(0.52, 0.01, 0, 1); /* только сцена hero */

  --d-press: 140ms;   /* отклик на нажатие */
  --d-hover: 160ms;   /* линия, стрелка, цвет текста при наведении */
  --d-fill: 180ms;    /* инверсия заливки: навигация, CTA, строки */
  --d-ui: 220ms;      /* смена состояния, вход панели меню */
  --d-enter: 300ms;   /* появление текста и карточек — потолок интерфейсного бюджета */
  --d-media: 560ms;   /* проявление кадра: marketing-бюджет, не UI */
  --stagger: 45ms;    /* шаг каскада в группе */

  color-scheme: dark;
  accent-color: var(--c-bone);
  scrollbar-color: var(--c-ash) var(--c-obsidian);
}

@media (min-width: 768px) {
  :root { --gutter: 32px; --section-gap: 80px; --masthead-h: 76px; }
}
@media (min-width: 1024px) {
  :root { --gutter: 48px; --section-gap: 108px; --masthead-h: 84px; }
}
@media (min-width: 1280px) {
  :root { --gutter: 64px; }
}

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--masthead-h) + 16px);
  -webkit-text-size-adjust: 100%;
  /* системная вспышка при касании (в мобильном Chrome — бирюзовая) не из
     палитры; отклик на нажатие у кнопок, строк и ссылок — свои :active */
  -webkit-tap-highlight-color: transparent;
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

svg { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: square; stroke-linejoin: miter; }
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* поверхности, которые рисует браузер, — тоже часть системы */
::selection { background: var(--c-bone); color: var(--c-obsidian); }
:where(input, textarea) { caret-color: var(--c-bone); }

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

.skip-link {
  position: fixed; left: 0; top: 0; z-index: 999;
  transform: translateY(-120%);
  background: var(--c-bone); color: var(--c-obsidian);
  padding: 12px 20px; font-size: var(--t-meta);
  letter-spacing: var(--track-label); text-transform: uppercase;
}
.skip-link:focus { transform: none; }

/* наши display-правила перебивают [hidden] из UA-стилей — возвращаем приоритет */
[hidden] { display: none !important; }

.shell {
  width: 100%;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section-gap); }
.section:first-child { padding-top: 0; }

/* ================= TYPE PRIMITIVES ================= */
/* Заголовки разделов — в одном весе с H1 (600): все шесть читаются как
   одна система, а иерархия между H1 и H2 держится масштабом. */
.section-title {
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: var(--track-h2);
  text-wrap: balance;
}

.section-note {
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
  font-weight: 500;
}

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 32px;
  flex-wrap: wrap;
  padding-bottom: 24px;
  margin-bottom: 44px;
  border-bottom: 1px solid var(--line);
}
@media (min-width: 1024px) { .section-head { margin-bottom: 60px; } }

/* ================= ACTIONS ================= */
/* CTA в покое — контур без заливки. Наведение инвертирует его: заливка bone,
   текст obsidian; размеры, рамка и вес шрифта не меняются.
   Заливка перетекает за --d-fill (цвет — обычный ease), а цвет подписи
   переключается разом — в точке, где светлый и тёмный текст на промежуточном
   фоне читаются одинаково (не ниже 4.3:1). Одновременное перетекание обоих
   цветов на середине давало серое на сером: подпись на миг исчезала.
   На выходе точка позже, чем на входе, — фон темнеет по той же кривой. */
.cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px 28px;
  border: 1px solid var(--c-bone);
  border-radius: 0;
  background-color: transparent;
  color: var(--c-bone);
  font-size: var(--t-meta);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  white-space: nowrap;
  transition:
    background-color var(--d-fill) ease,
    color 0s linear calc(var(--d-fill) * 0.33),
    transform var(--d-press) var(--ease-out);
}
.cta-arrow { width: 16px; height: 16px; flex: none; transition: transform var(--d-hover) var(--ease-out); }
/* физический отклик: кнопка проминается под пальцем, а не гаснет */
.cta:active { transform: scale(0.98); }

@media (hover: hover) and (pointer: fine) {
  .cta:hover {
    background-color: var(--c-bone);
    color: var(--c-obsidian);
    transition:
      background-color var(--d-fill) ease,
      color 0s linear calc(var(--d-fill) * 0.26),
      transform var(--d-press) var(--ease-out);
  }
  .cta:hover .cta-arrow { transform: translateX(3px); }
}

.cta--nav {
  padding: 10px 16px;
  border-radius: var(--r-nav);
  font-size: 0.8125rem;
}

.cta--form { align-self: flex-start; margin-top: 8px; }

/* Вторичные ссылки. Тонкая линия видна всегда — по ней ссылку узнают и на
   touch, где наведения нет. На наведении поверх неё проявляется яркая линия:
   scaleX от левого края и прозрачность. Начало координат не меняется, поэтому
   быстрый уход указателя сворачивает линию туда же, откуда она вышла. */
.link-action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--t-meta);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--c-bone);
}

:is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear) {
  position: relative;
  transition: color var(--d-hover) ease, opacity var(--d-press) ease;
}
:is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear)::before,
:is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 1px;
  pointer-events: none;
}
:is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear)::before {
  background: var(--line-strong);
}
:is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear)::after {
  background: var(--c-bone);
  opacity: 0;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--d-hover) var(--ease-out), opacity var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  :is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear):hover::after {
    opacity: 1;
    transform: scaleX(1);
  }
}
/* у текстовых ссылок отклик — прозрачность: scale на строке текста выглядит дёшево */
:is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear):active { opacity: 0.68; }

/* ================= MASTHEAD ================= */
.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid transparent;
  transition: background-color var(--d-ui) ease, border-color var(--d-ui) ease;
}
.masthead.is-scrolled {
  background: rgba(16, 16, 16, 0.88);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
}

.masthead-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  height: var(--masthead-h);
}

.wordmark {
  display: flex;
  flex-direction: column;
  gap: 5px;
  line-height: 1.1;
  transition: opacity var(--d-press) ease;
}
.wordmark-name { font-size: 1.125rem; line-height: 1; letter-spacing: 0.01em; }
.wordmark-sub {
  font-size: 0.6875rem;
  letter-spacing: 0.03em;
  color: var(--text-quiet);
  transition: color var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  .wordmark:hover .wordmark-sub { color: var(--c-bone); }
}
.wordmark:active { opacity: 0.68; }

.nav { display: none; }
/* Padding зарезервирован и в покое, и на наведении: заливка появляется
   вокруг уже стоящего слова, ширина пунктов не меняется. Вес шрифта на
   наведении не трогаем — иначе слова «дышат» и сдвигают соседей. */
.nav-link {
  position: relative;
  display: inline-block;
  padding: 8px 12px;
  border-radius: var(--r-nav);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
  background-color: transparent;
  /* заливка перетекает, цвет слова переключается в точке равного контраста —
     как у CTA (раздел ACTIONS); для приглушённого текста точки свои */
  transition:
    color 0s linear calc(var(--d-fill) * 0.41),
    background-color var(--d-fill) ease,
    opacity var(--d-press) ease;
}
/* Активный раздел — линия под словом, отдельно от наведения.
   Цвет линии — currentColor: на инверсии она остаётся видна тёмной. */
.nav-link::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 3px;
  height: 1px;
  background: currentColor;
  opacity: 0;
  transition: opacity var(--d-hover) ease;
}
.nav-link.is-active { color: var(--c-bone); }
.nav-link.is-active::after { opacity: 1; }
.nav-link:active { opacity: 0.82; }

.masthead-actions { display: flex; align-items: center; gap: 12px; }

.nav-toggle {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-right: -8px;
  border: 1px solid var(--line);
  background-color: transparent;
  color: var(--c-bone);
  transition:
    background-color var(--d-fill) ease,
    border-color var(--d-fill) ease,
    color 0s linear calc(var(--d-fill) * 0.33),
    transform var(--d-press) var(--ease-out);
}
.nav-toggle:active { transform: scale(0.94); }
@media (hover: hover) and (pointer: fine) {
  .nav-toggle:hover {
    background-color: var(--c-bone);
    border-color: var(--c-bone);
    color: var(--c-obsidian);
    transition:
      background-color var(--d-fill) ease,
      border-color var(--d-fill) ease,
      color 0s linear calc(var(--d-fill) * 0.26),
      transform var(--d-press) var(--ease-out);
  }
}
.nav-toggle-icon { width: 20px; height: 20px; }
.nav-toggle-icon--close { display: none; }
.masthead.is-open .nav-toggle-icon--menu { display: none; }
.masthead.is-open .nav-toggle-icon--close { display: block; }

/* Мобильная панель меню — выпадающая, а не выезжающая: она опускается на 8px
   из-под шапки, поэтому идёт на --ease-out, как dropdown.
   Панель — transition, а не keyframes: её открывают и закрывают подряд,
   а transition разворачивается из текущего положения. display участвует
   в переходе (allow-discrete), поэтому выход виден целиком, а после него
   панель уходит из потока. Из табуляции закрытая панель уходит сразу —
   скрипт ставит ей inert в момент закрытия, не дожидаясь конца выхода. */
@media (max-width: 1023px) {
  .masthead.is-open {
    background: var(--c-obsidian);
    border-bottom-color: var(--line);
  }
  .masthead .nav {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--c-obsidian);
    border-bottom: 1px solid var(--line);
    padding: 8px 0 24px;
    opacity: 0;
    transform: translateY(-8px);
    /* выход короче входа и тем же путём: вверх на 8px с угасанием */
    transition:
      opacity var(--d-hover) var(--ease-out),
      transform var(--d-hover) var(--ease-out),
      display var(--d-hover) allow-discrete;
  }
  .masthead.is-open .nav {
    display: flex;
    opacity: 1;
    transform: none;
    transition:
      opacity var(--d-ui) var(--ease-out),
      transform var(--d-ui) var(--ease-out),
      display var(--d-ui) allow-discrete;
  }
  @starting-style {
    .masthead.is-open .nav { opacity: 0; transform: translateY(-8px); }
  }
  /* закрытие с клавиатуры (Escape) — без задержки: это keyboard-initiated action */
  .masthead[data-close="instant"] .nav { transition-duration: 0s; }

  /* Вид пунктов не зависит от .is-open: во время выхода класс уже снят,
     и пункты не должны менять размер, пока панель гаснет.
     Строка во всю ширину панели — попасть пальцем можно в любом месте. */
  .nav-link {
    padding: 18px var(--gutter);
    border-radius: 0;
    border-bottom: 1px solid var(--line);
    font-size: 1rem;
    color: var(--c-bone);
  }
  .nav-link::after { display: none; }
  .nav-link.is-active { text-decoration: underline; text-underline-offset: 6px; }
  .nav-link:focus-visible { outline-offset: -2px; }
  @media (hover: hover) and (pointer: fine) {
    .nav-link:hover { background-color: rgba(255, 253, 249, 0.05); }
  }
}

@media (min-width: 1024px) {
  .nav { display: flex; align-items: center; gap: 4px; }
  .nav-toggle { display: none; }
}
@media (min-width: 1024px) and (hover: hover) and (pointer: fine) {
  .nav-link:hover {
    background-color: var(--c-bone);
    color: var(--c-obsidian);
    transition:
      color 0s linear calc(var(--d-fill) * 0.2),
      background-color var(--d-fill) ease,
      opacity var(--d-press) ease;
  }
}

/* ================= HERO ================= */
.hero {
  position: relative;
  /* уходит под липкую шапку, чтобы кадр начинался от самого верха окна */
  margin-top: calc(var(--masthead-h) * -1);
  padding-top: var(--masthead-h);
  isolation: isolate;
}

.hero-frame {
  position: relative;
  height: 42svh;
  min-height: 260px;
  max-height: 440px;
  overflow: hidden;
  background: var(--c-pure-black);
}
/* низкий экран (телефон в landscape, 200% zoom): кадр не забирает весь
   первый экран — заголовок виден сразу, а не начинается на сгибе */
@media (max-width: 899px) and (max-height: 480px) {
  .hero-frame { min-height: 160px; }
}
.hero-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}
/* На мобильном текста поверх кадра нет — он стоит ниже, на обсидиане.
   Поэтому затемнение здесь только вводит кадр под шапку и растворяет
   его нижний край в странице; сам автомобиль почти не притушен. */
.hero-scrim {
  position: absolute;
  inset: 0;
  /* растворение нижнего края нелинейное: колёса и пол остаются видны,
     а к самой кромке кадр всё равно плавно уходит в обсидиан без шва */
  background: linear-gradient(180deg, rgba(16, 16, 16, 0.3) 0%, rgba(16, 16, 16, 0) 34%,
      rgba(16, 16, 16, 0.08) 62%, rgba(16, 16, 16, 0.35) 84%, var(--c-obsidian) 100%);
}
.hero-sweep {
  position: absolute;
  inset: -10% -30%;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(104deg,
      rgba(255, 253, 249, 0) 36%,
      rgba(255, 253, 249, 0.07) 45%,
      rgba(255, 253, 249, 0.18) 50%,
      rgba(255, 253, 249, 0.07) 55%,
      rgba(255, 253, 249, 0) 64%);
}

.hero-body { position: relative; padding-top: 32px; }
.hero-copy { position: relative; }

/* Вес 600 — на всём заголовке, а не на отдельных словах: заголовок
   редактируется в админке, и акцент не должен зависеть от разметки внутри.
   Onest вариативный, 600 — настоящая точка оси, не синтетический жирный. */
.hero-title {
  font-size: var(--t-display);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.025em;
  text-wrap: balance;
  /* оптическая компенсация верхнего свеса Display-строки (исключение из шага 4px) */
  margin-top: -0.08em;
}

.hero-lead {
  margin-top: 16px;
  max-width: 46ch;
  font-size: var(--t-lead);
  line-height: 1.3;
  letter-spacing: 0;
  color: var(--text-soft);
  text-wrap: pretty;
}

.hero-actions {
  display: flex;
  align-items: center;
  gap: 16px 28px;
  flex-wrap: wrap;
  margin-top: 36px;
}

.hero-rail {
  position: relative;
  margin-top: 48px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}
.hero-rail-note {
  font-size: var(--t-small);
  line-height: 1.3;
  letter-spacing: 0;
  color: var(--text-quiet);
  margin-bottom: 20px;
  max-width: 52ch;
}
.hero-rail-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px 24px;
}
/* Название и пояснение — одна группа: 4px между ними и собственный
   межстрочный интервал вместо унаследованного 1.5 от body. */
.hero-rail-name {
  display: block;
  font-size: var(--t-small);
  line-height: 1.25;
  letter-spacing: 0;
}
.hero-rail-text {
  display: block;
  margin-top: 4px;
  font-size: var(--t-meta);
  line-height: 1.3;
  color: var(--text-quiet);
}

@media (min-width: 900px) {
  .hero {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    min-height: min(94svh, 900px);
    padding-bottom: 40px;
  }
  .hero-frame {
    position: absolute;
    inset: 0;
    height: auto;
    max-height: none;
    z-index: -1;
  }
  .hero-img { object-position: 74% 50%; }
  /* Автомобиль справа почти не притушен. Текст защищён не общим
     затемнением кадра, а там, где он стоит:
       — полоса под шапкой: навигация читается и над софтбоксом;
       — полоса под нижним рядом: кадр растворяется в странице;
       — горизонтальный спад: колонка текста слева, машина справа;
       — поле непосредственно за текстом (.hero-copy::before ниже).
     Полосы заданы в пикселях от краёв: они следуют за шапкой и нижним
     рядом при любой высоте hero, а не за процентом от кадра. */
  .hero-scrim {
    background:
      linear-gradient(180deg,
        rgba(16, 16, 16, 0.9) 0,
        rgba(16, 16, 16, 0.8) var(--masthead-h),
        rgba(16, 16, 16, 0) calc(var(--masthead-h) + 120px)),
      linear-gradient(0deg,
        var(--c-obsidian) 0,
        rgba(16, 16, 16, 0.9) 150px,
        rgba(16, 16, 16, 0) 330px),
      linear-gradient(90deg,
        rgba(16, 16, 16, 0.88) 0%,
        rgba(16, 16, 16, 0.72) 30%,
        rgba(16, 16, 16, 0.46) 52%,
        rgba(16, 16, 16, 0.16) 74%,
        rgba(16, 16, 16, 0.08) 100%);
  }
  .hero-body {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-top: 56px;
    padding-bottom: 40px;
  }
  /* Блок текста по ширине содержимого — поле за ним повторяет его размер
     на любой ширине окна и при любом тексте из админки. */
  .hero-copy { align-self: flex-start; max-width: 100%; }
  .hero-copy::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: -80px -200px -80px -80px;
    background: radial-gradient(closest-side,
      rgba(16, 16, 16, 0.65) 0%,
      rgba(16, 16, 16, 0.5) 60%,
      rgba(16, 16, 16, 0) 100%);
    pointer-events: none;
  }
  .hero-title { max-width: 15ch; line-height: 0.98; letter-spacing: -0.035em; }
  .hero-lead { margin-top: 20px; max-width: 38ch; }
  .hero-rail { margin-top: 0; }
  .hero-rail-list { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px 32px; }
}

@media (min-width: 1200px) {
  /* Колонка текста — 60% ширины shell. Процент от всей ширины hero на
     1920px сжимал её до 608px, и H1 ломался на три строки. */
  .hero-body { padding-right: calc(min(100%, var(--shell-max)) * 0.4); }
}

/* ================= SERVICES ================= */
.services { display: grid; gap: 48px; }

@media (min-width: 1000px) {
  .services {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
    gap: 64px;
    align-items: start;
  }
}

.ledger-item:first-child .ledger-row { border-top: 1px solid var(--line); }

/* Строки услуг и тарифов — общий язык состояний:
   наведение подсвечивает строку тонким светлым фоном и проясняет разделитель,
   сама строка под курсором не «ездит»; нажатие даёт едва заметную просадку
   от левого края, где начинается текст. Фон — отдельный слой с прозрачностью:
   он выходит за край текста на 12px и не сдвигает вёрстку. */
.ledger-row,
.tier {
  position: relative;
  isolation: isolate;
  width: 100%;
  text-align: left;
  border-bottom: 1px solid var(--line);
  transform-origin: left center;
  transition: border-color var(--d-fill) ease, transform var(--d-press) var(--ease-out);
}
.ledger-row::before,
.tier::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0 -12px;
  background: var(--c-bone);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fill) ease;
}
.ledger-row:active,
.tier:active { transform: scale(0.995); }
@media (hover: hover) and (pointer: fine) {
  .ledger-row:hover,
  .tier:hover { border-bottom-color: var(--line-hover); }
  .ledger-row:hover::before,
  .tier:hover::before { opacity: 0.05; }
}

.ledger-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "name  price"
    "desc  state";
  column-gap: 24px;
  row-gap: 6px;
  padding: 22px 0;
}
.ledger-name {
  grid-area: name;
  font-size: var(--t-h4);
  letter-spacing: var(--track-h3);
  line-height: 1.15;
}
.ledger-desc {
  grid-area: desc;
  font-size: var(--t-small);
  line-height: 1.35;
  color: var(--text-secondary);
  max-width: 46ch;
}
.ledger-price {
  grid-area: price;
  justify-self: end;
  font-size: var(--t-small);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ledger-state {
  grid-area: state;
  justify-self: end;
  align-self: end;
  font-size: var(--t-meta);
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
  transition: color var(--d-press) ease;
}

@media (hover: hover) and (pointer: fine) {
  .ledger-row:hover .ledger-state { color: var(--c-bone); }
}
.ledger-row[aria-pressed="true"] { border-bottom-color: var(--c-bone); }
.ledger-row[aria-pressed="true"] .ledger-state { color: var(--c-bone); }

.services-media {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
.frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-media);
  background: var(--c-pure-black);
}
.frame img { width: 100%; height: 100%; object-fit: cover; }

/* Фото из контента: пока неизвестно, что в кадре, он остаётся тёмным,
   а новое фото проявляется, когда загрузилось. Заглушка «фото не загружено»
   не мелькает перед настоящим кадром (js/content-loader.js). */
img[data-field-attr="src"] { transition: opacity var(--d-enter) var(--ease-out); }
img[data-media="loading"] { opacity: 0; }

.frame--services-a { grid-column: 1 / 5; aspect-ratio: 4 / 5; }
.frame--services-b {
  grid-column: 3 / 7;
  aspect-ratio: 1 / 1;
  margin-top: -18%;
  z-index: 1;
  /* не декоративная тень, а обсидиановое паспарту: отделяет верхний кадр от нижнего */
  box-shadow: 0 0 0 10px var(--c-obsidian);
}

@media (max-width: 999px) {
  .services-media { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
  .frame--services-a, .frame--services-b {
    grid-column: auto;
    aspect-ratio: 4 / 5;
    margin-top: 0;
    box-shadow: none;
  }
}

/* ================= PROCESS ================= */
.steps { display: grid; gap: 0; }
.step {
  padding: 22px 0 30px;
  border-top: 1px solid var(--line);
}
/* Номер этапа — метка порядка, а не заголовок: компактный, один стиль
   на все четыре. Цифры пропорциональные — у Onest они такие по умолчанию,
   и «01» не расползается на ширину табличной единицы. Цены, наоборот,
   остаются табличными: там цифры выравниваются в колонку. */
.step-num {
  display: block;
  font-size: var(--t-num);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.035em;
  font-variant-numeric: lining-nums proportional-nums;
  color: var(--text-secondary);
  margin-bottom: 10px;
}
.step-title {
  font-size: var(--t-h4);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: var(--track-h3);
  margin-bottom: 6px;
}
.step-text {
  font-size: var(--t-small);
  line-height: 1.35;
  letter-spacing: 0;
  color: var(--text-secondary);
  max-width: 34ch;
}

@media (min-width: 820px) {
  .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: 32px; }
  .step { padding-bottom: 8px; }
}

/* ================= BEFORE / AFTER ================= */
.proof { display: grid; gap: 24px; }
@media (min-width: 768px) { .proof { gap: 32px; } }

.proof-row { display: grid; gap: 24px; }
@media (min-width: 768px) {
  .proof-row--two { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; }
  .proof-row--three { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; }
}

.compare { display: block; }

.compare-media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--r-media);
  background: var(--c-pure-black);
}
.compare--lead .compare-media { aspect-ratio: 16 / 9; }

.compare-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
.compare-img--before { clip-path: inset(0 50% 0 0); }

.compare-tag {
  position: absolute;
  top: 14px;
  font-size: 0.75rem;
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--c-bone);
  padding: 5px 10px;
  background: rgba(16, 16, 16, 0.72);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  pointer-events: none;
}
.compare-tag--before { left: 14px; }
.compare-tag--after { right: 14px; }

.compare-divider {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--c-bone);
  pointer-events: none;
}
.compare-knob {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  background: rgba(16, 16, 16, 0.72);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid var(--c-bone);
  color: var(--c-bone);
}
.compare-knob svg { width: 18px; height: 18px; }

/* Ручка отвечает на захват, но само сравнение к ней не привязано:
   clip-path и позиция разделителя ставятся мгновенно, без инерции. */
.compare-knob {
  transition: transform var(--d-press) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .compare-media:has(.compare-range:hover) .compare-knob { transform: translate(-50%, -50%) scale(1.06); }
}
.compare-media:has(.compare-range:focus-visible) .compare-knob { transform: translate(-50%, -50%) scale(1.06); }
.compare-media:has(.compare-range:active) .compare-knob { transform: translate(-50%, -50%) scale(0.94); }

.compare-range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: transparent;
  opacity: 0;
  cursor: ew-resize;
  /* вертикальная прокрутка страницы на touch остаётся браузерной */
  touch-action: pan-y;
  -webkit-appearance: none;
  appearance: none;
}
.compare-range::-webkit-slider-thumb { -webkit-appearance: none; width: 1px; height: 100%; }
.compare-range::-moz-range-thumb { width: 1px; height: 100%; border: 0; }
.compare-range:focus { outline: none; }
.compare-range:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

.compare-missing {
  position: absolute;
  left: 14px;
  bottom: 14px;
  right: 14px;
  font-size: var(--t-meta);
  color: var(--c-bone);
  background: rgba(16, 16, 16, 0.78);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  padding: 8px 12px;
  pointer-events: none;
}

/* нечего сравнивать — не делаем вид, что есть */
.compare.is-unpaired .compare-divider,
.compare.is-unpaired .compare-range,
.compare.is-unpaired .compare-tag { display: none; }
.compare.is-unpaired .compare-img--before { clip-path: none; opacity: 0; }

.compare-caption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
}
.compare-label { font-size: var(--t-small); line-height: 1.3; letter-spacing: 0; }
.compare:not(.compare--lead) .compare-hint { display: none; }
.compare-hint {
  font-size: var(--t-meta);
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
}

/* ================= APPROACH ================= */
.approach { display: grid; gap: 48px; }

.approach-lead { display: grid; gap: 24px; }
@media (min-width: 900px) {
  .approach-lead {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 48px;
    align-items: end;
  }
  .approach-copy { padding-bottom: 8px; }
}

.frame--approach-lead { aspect-ratio: 16 / 10; }
.frame--approach { aspect-ratio: 4 / 5; }

.approach-title {
  font-size: var(--t-h3);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: var(--track-h3);
  text-wrap: balance;
}
.approach-title--sm { font-size: var(--t-h4); margin-top: 20px; }
.approach-text {
  margin-top: 14px;
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--text-secondary);
  max-width: 42ch;
  text-wrap: pretty;
}
.approach-title--sm + .approach-text { margin-top: 6px; font-size: var(--t-small); line-height: 1.35; }

.approach-pair { display: grid; gap: 40px; }
@media (min-width: 700px) {
  .approach-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 32px; }
}
@media (min-width: 900px) {
  /* Пара уходит вправо от ведущего кадра — асимметрия вместо ровной сетки.
     Ширина задана явно: с auto-отступом элемент сетки иначе сжимается по
     содержимому, и пока ленивые кадры не загружены, пара была уже на 62px,
     а при загрузке прыгала вместе со всей страницей ниже (+77px высоты). */
  .approach-pair { width: 100%; max-width: 62%; margin-left: auto; gap: 40px; }
}

/* ================= PRICING ================= */
.tier-item:first-child .tier { border-top: 1px solid var(--line); }

/* общая механика состояний строки — в разделе SERVICES (.ledger-row, .tier) */
.tier {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "head  price"
    "desc  state";
  column-gap: 24px;
  row-gap: 10px;
  padding: 28px 0;
}
.tier-head {
  grid-area: head;
  display: flex;
  align-items: baseline;
  gap: 8px 16px;
  flex-wrap: wrap;
}
.tier-name {
  font-size: var(--t-h3);
  line-height: 1.15;
  letter-spacing: var(--track-h3);
}
.tier-mark {
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
}
.tier-mark:empty { display: none; }
.tier-price {
  grid-area: price;
  justify-self: end;
  font-size: var(--t-h4);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.tier-state {
  grid-area: state;
  justify-self: end;
  align-self: end;
  font-size: var(--t-meta);
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
  transition: color var(--d-press) ease;
}
.tier-desc {
  grid-area: desc;
  font-size: var(--t-small);
  line-height: 1.35;
  color: var(--text-secondary);
  max-width: 52ch;
}

@media (hover: hover) and (pointer: fine) {
  .tier:hover .tier-state { color: var(--c-bone); }
}
.tier[aria-pressed="true"] { border-bottom-color: var(--c-bone); }
.tier[aria-pressed="true"] .tier-state { color: var(--c-bone); }

.tiers-note {
  margin-top: 24px;
  font-size: var(--t-small);
  color: var(--text-secondary);
  max-width: 60ch;
}

/* ================= CONTACT ================= */
.contact { display: grid; gap: 56px; }
@media (min-width: 900px) {
  .contact {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
    gap: 64px;
    align-items: start;
  }
}

/* размер, вес и трекинг — от .section-title */
.contact-title { max-width: 16ch; }
.contact-note {
  margin-top: 16px;
  font-size: var(--t-lead);
  line-height: 1.35;
  color: var(--text-secondary);
  max-width: 40ch;
}

.facts {
  display: grid;
  gap: 0;
  margin-top: 40px;
  border-top: 1px solid var(--line);
}
.fact {
  display: grid;
  grid-template-columns: minmax(0, 10rem) minmax(0, 1fr);
  gap: 8px 24px;
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}
@media (max-width: 519px) {
  .fact { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}
.fact-label {
  font-size: var(--t-meta);
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
}
.fact-value { font-size: var(--t-small); line-height: 1.35; }
/* ссылка по ширине текста: линия под ней не тянется на всю колонку.
   Линия и отклик — общий паттерн вторичных ссылок (раздел ACTIONS) */
.fact-value--link { justify-self: start; }

.channels { display: flex; flex-wrap: wrap; gap: 10px 24px; margin-top: 28px; }
.channel {
  display: inline-block;
  font-size: var(--t-meta);
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.channels:empty, .channels.is-empty { display: none; }

/* ---- form ---- */
.form { display: flex; flex-direction: column; gap: 20px; }

/* Чип выбора появляется далеко от места клика — без мягкого входа
   он телепортируется в форму и читается как сбой вёрстки. */
.form-pick {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--c-bone);
  font-size: var(--t-small);
  line-height: 1.35;
  transition: opacity var(--d-ui) ease, transform var(--d-ui) var(--ease-out);
}
@starting-style {
  .form-pick { opacity: 0; transform: translateY(-4px); }
}
.form-pick-clear {
  font-size: var(--t-meta);
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
  flex: none;
}
@media (hover: hover) and (pointer: fine) {
  .form-pick-clear:hover { color: var(--c-bone); }
}

.field { display: flex; flex-direction: column; gap: 8px; }
.field-label {
  font-size: var(--t-meta);
  line-height: 1.3;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
  transition: color var(--d-hover) ease;
}
/* поле в работе — подпись светлеет вместе с линией */
.field:focus-within .field-label { color: var(--c-bone); }
.field-input {
  width: 100%;
  padding: 12px 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  /* не меньше 16px: иначе iOS Safari увеличивает страницу при фокусе */
  font-size: max(1rem, var(--t-small));
  transition: border-color var(--d-hover) ease;
}
.field-input::placeholder { color: var(--text-quiet); }
@media (hover: hover) and (pointer: fine) {
  .field-input:hover { border-bottom-color: var(--line-hover); }
}
.field-input:focus { outline: none; border-bottom-color: var(--c-bone); }
.field-input:focus-visible { outline: 2px solid var(--focus); outline-offset: 4px; }
.field.is-invalid .field-input { border-bottom-color: var(--c-bone); }

/* Ошибка проявляется, а не выпрыгивает: заметно, но без тряски.
   Цвет — светлее подписи: ошибку должны прочитать, а не заметить краем глаза. */
.field-error {
  font-size: var(--t-meta);
  line-height: 1.35;
  color: var(--text-soft);
  transition: opacity var(--d-ui) ease, transform var(--d-ui) var(--ease-out);
}
@starting-style {
  .field-error { opacity: 0; transform: translateY(-4px); }
}

/* Отправка идёт: кнопка остаётся на месте и в фокусе, но повторно не
   срабатывает — это держит скрипт, а вид говорит «подождите». */
.cta[aria-busy="true"] { opacity: 0.6; cursor: progress; }

/* Ответ формы меняется на месте. Короткое затемнение и возврат показывают,
   что текст обновился, — иначе подмена строки проходит незамеченной.
   Transition, а не keyframes: кнопку можно нажать несколько раз подряд. */
.form-result {
  font-size: var(--t-small);
  line-height: 1.45;
  color: var(--text-soft);
  min-height: 1.45em;
  max-width: 46ch;
  opacity: 1;
  transition: opacity var(--d-ui) ease;
}
.form-result.is-updating { opacity: 0.3; transition-duration: 60ms; }
.form-result a {
  color: var(--c-bone);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 4px;
  transition: text-decoration-color var(--d-hover) ease;
}
@media (hover: hover) and (pointer: fine) {
  .form-result a:hover { text-decoration-color: var(--c-bone); }
}

/* ================= FOOTER ================= */
.footer {
  border-top: 1px solid var(--line);
  padding-block: 28px 36px;
}
.footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 32px;
  flex-wrap: wrap;
}
.footer-copy, .footer-legal a {
  font-size: var(--t-meta);
  line-height: 1.35;
  letter-spacing: 0;
}
.footer-copy { color: var(--text-quiet); }
.footer-legal { display: flex; flex-wrap: wrap; gap: 10px 28px; }
/* линия и отклик — общий паттерн вторичных ссылок (раздел ACTIONS) */
.footer-legal a {
  display: inline-block;
  color: var(--text-quiet);
}
@media (hover: hover) and (pointer: fine) {
  .footer-legal a:hover { color: var(--c-bone); }
}

/* ================= LEGAL PAGES ================= */
.legal-main { padding-block: 56px 96px; }
.legal-back {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: var(--t-meta);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-quiet);
  margin-bottom: 44px;
  transition: color var(--d-hover) ease, opacity var(--d-press) ease;
}
@media (hover: hover) and (pointer: fine) { .legal-back:hover { color: var(--c-bone); } }
.legal-back:active { opacity: 0.68; }

/* заголовок правовой страницы — в масштабе и весе заголовка раздела */
.legal-title {
  font-size: var(--t-h2);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: var(--track-h2);
  max-width: 20ch;
  text-wrap: balance;
}
.legal-updated {
  margin-top: 16px;
  padding-bottom: 40px;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-small);
  color: var(--text-quiet);
}
.legal-body {
  max-width: 68ch;
  margin-top: 48px;
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--text-secondary);
}
.legal-body h2 {
  margin: 44px 0 14px;
  font-size: var(--t-h4);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: var(--track-h3);
  color: var(--c-bone);
}
.legal-body h2:first-child { margin-top: 0; }
.legal-body p { margin: 0 0 16px; }
.legal-body ul {
  margin: 0 0 18px;
  padding-left: 20px;
  list-style: disc;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.legal-body strong { color: var(--c-bone); font-weight: 400; }
.legal-body a {
  color: var(--c-bone);
  text-decoration: underline;
  text-underline-offset: 4px;
}

@media (max-width: 640px) {
  .legal-main { padding-block: 40px 72px; }
  .legal-back { margin-bottom: 28px; }
}

/* ================= MOTION =================
   Классы .reveal ставит только JS и только после того, как убедился,
   что умеет их снять. Без JS страница видна целиком.

   Язык один, роли разные:
     --rise   заголовки и текстовые блоки — задают иерархию;
     --soft   карточки и строки списков — идут каскадом;
     --media  кадр — проявляется, а не выезжает;
     --fade   финал страницы — только прозрачность, без движения.
   Появление проигрывается один раз: наблюдатель снимает элемент с учёта. */
.reveal {
  opacity: 0;
  transition:
    opacity var(--d-enter) var(--ease-out) var(--reveal-delay, 0ms),
    transform var(--d-enter) var(--ease-out) var(--reveal-delay, 0ms);
}
.reveal--rise { transform: translateY(12px); }
.reveal--soft { transform: translateY(8px); }
.reveal--fade { transform: none; }

/* Кадр не едет по экрану — он «проявляется» снизу вверх.
   Клип живёт на самом изображении, а не на рамке: рамка держит скругление,
   обрезку и обсидиановое паспарту (box-shadow), а clip-path на ней срезал бы
   паспарту вместе с тенью. Бюджет здесь marketing, а не UI: это большая
   поверхность, на которую смотрят. */
.reveal--media {
  transform: scale(1.012);
  clip-path: inset(0 0 18% 0);
  transition:
    opacity var(--d-media) var(--ease-out) var(--reveal-delay, 0ms),
    transform var(--d-media) var(--ease-out) var(--reveal-delay, 0ms),
    clip-path var(--d-media) var(--ease-out) var(--reveal-delay, 0ms);
}

.reveal.is-in { opacity: 1; transform: none; }
.reveal--media.is-in { clip-path: inset(0 0 0 0); }
/* фокус с клавиатуры попал в ещё не показанный блок — показываем сразу:
   фокус не ждёт декоративного появления */
.reveal.is-instant { transition: none; }

/* печать и сохранение в PDF — без недоигранных появлений */
@media print {
  .reveal { opacity: 1 !important; transform: none !important; clip-path: none !important; }
}

/* ---- Сцена hero ----
   Единственный сильный кинематографический момент на сайте: один проход
   света по кадру. Стартует детерминированно на первом кадре — не ждёт
   ответа API, поэтому ритм сцены не зависит от скорости сети.
   Проигрывается один раз: класс снимается по окончании прохода. */
.hero.is-lit .hero-sweep { animation: heroSweep 1100ms var(--ease-cinematic) 420ms forwards; }
@keyframes heroSweep {
  0% { transform: translate3d(-42%, 0, 0); opacity: 0; }
  18% { opacity: 1; }
  82% { opacity: 1; }
  100% { transform: translate3d(42%, 0, 0); opacity: 0; }
}

.hero.is-lit .hero-img { animation: heroSettle 900ms var(--ease-cinematic) both; }
@keyframes heroSettle {
  from { transform: scale(1.025); }
  to { transform: scale(1); }
}

@media (max-width: 899px) {
  .hero.is-lit .hero-img { animation: none; }
}

/* ---- Reduced motion ----
   Режим «спокойнее», а не «выключено»: пропадает перемещение в пространстве
   (сцена, каскад, выезд панели, просадка при нажатии, сдвиг стрелки, выезд
   линии), остаются переходы цвета и прозрачности, по которым читаются
   состояния, — короткие, до 100ms. Работает и тогда, когда настройку
   включили уже после загрузки страницы: правила ниже живые. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --d-press: 100ms;
    --d-hover: 100ms;
    --d-fill: 100ms;
    --d-ui: 100ms;
    --d-enter: 100ms;
  }

  html { scroll-behavior: auto; }

  /* страховка: даже если классы появления окажутся навешаны — ничего не скрыто */
  .reveal {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }

  .hero.is-lit .hero-sweep,
  .hero.is-lit .hero-img { animation: none !important; }

  /* панель меню остаётся понятной: мягкое проявление без выезда */
  .masthead .nav,
  .masthead.is-open .nav {
    transform: none;
    transition-property: opacity, display;
  }
  @starting-style {
    .masthead.is-open .nav { transform: none; }
    .form-pick, .field-error { transform: none; }
  }

  /* отклик на нажатие сохраняем, но без физического сдвига */
  .cta:active,
  .nav-toggle:active,
  .ledger-row:active,
  .tier:active { transform: none; opacity: 0.82; }

  .cta:hover .cta-arrow { transform: none; }

  /* линия вторичной ссылки не выезжает, а проявляется на месте */
  :is(.link-action, .fact-value--link, .channel, .footer-legal a, .form-pick-clear)::after { transform: none; }

  .compare-media:has(.compare-range:hover) .compare-knob,
  .compare-media:has(.compare-range:focus-visible) .compare-knob,
  .compare-media:has(.compare-range:active) .compare-knob { transform: translate(-50%, -50%); }
}
