/* ============================================================================
   China Motors — дизайн-система v2 «Груз в пути»
   ----------------------------------------------------------------------------
   Живёт РЯДОМ со style.css, не вместо него: страницы переезжают по одной
   (см. guidelines/prod-migration-plan.md). Пока переехал не весь сайт, оба
   файла подключены одновременно — это временно и снимается на шаге 7.

   Страница включает v2, добавляя class="v2" на <body>: тогда применяется
   v2-фон и типографика, а common.js грузит partials/navbar-v2.html и
   partials/footer-v2.html вместо v1-партиалов.

   Шрифты (подключаются <link>'ом на странице):
     Oswald            — уже на проде, гарнитура не меняется, меняется роль
     IBM Plex Sans     400/500/600  · текст
     IBM Plex Mono     400/500/600  · ВСЕ числа, табличные цифры
   Archivo НЕ подключается — вариант B отклонён.
   ============================================================================ */

/* ============================================================================
   1. ТОКЕНЫ · цвет
   Источник: tokens/v2-colors.css
   ============================================================================ */
:root {
  /* --- АСФАЛЬТ · холодный бетон и дорожное покрытие ---------------------- */
  --asphalt-900: #16181C;   /* тёмная земля: hero, футер, панель статуса */
  --asphalt-800: #1E2126;
  --asphalt-700: #2A2E35;   /* тёмные панели, шапка таблицы */
  --asphalt-500: #5A616B;   /* вторичный текст */
  --asphalt-400: #868D97;   /* подписи, единицы измерения */
  --asphalt-200: #D5D8DD;   /* ВСЕ линейки и разделители */
  --asphalt-100: #E6E8EB;
  --asphalt-050: #F2F3F5;   /* фон страницы — бетон, не крем */
  --paper: #FFFFFF;

  /* Намеренно тёмная поверхность (шапка, футер, панель статуса).
     ОТДЕЛЬНО от --asphalt-900: та ступень работает ещё и как цвет текста
     и в тёмной теме обязана светлеть — а поверхность обязана остаться тёмной. */
  --surface-inverse: #16181C;
  --on-inverse: #FFFFFF;

  /* --- СИГНАЛ · «действие / вы здесь». Максимум два в кадре -------------- */
  --signal-500: #E1281F;
  --signal-600: #B81F19;
  /* Ореол пульсации CTA. Отдельно от --signal-tint (10%) намеренно: tint
     рассчитан на светлый бетон и под активный узел рейки, а этот ореол
     расходится вокруг заливки на асфальте hero — на 10% его там не видно
     вообще. Значение одно на обе темы: hero в обеих тёмный. */
  --signal-halo: rgba(225, 40, 31, 0.34);
  /* Заливка кнопки отдельно: --signal-500 в тёмной теме светлеет ради
     читаемости текста, а заливка обязана остаться фирменной. */
  --signal-fill: #E1281F;
  --signal-fill-hover: #B81F19;
  --on-signal: #FFFFFF;
  --signal-tint: rgba(225, 40, 33, 0.10);

  /* --- ОПАСНОСТЬ / В ПУТИ · «не закрыто, требует внимания» --------------- */
  --hazard-400: #F5A524;
  --hazard-tint: rgba(245, 165, 36, 0.14);

  /* --- ЧЕРНИЛА · «официальное и завершённое» ----------------------------- */
  --ink-700: #1E2A5A;
  --ink-500: #33448C;
  --ink-tint: rgba(30, 42, 90, 0.08);

  /* --- ОЧИЩЕНО · «закрыто успешно» -------------------------------------- */
  --clear-600: #157A4A;
  --clear-400: #3ECB86;   /* светлая ступень — для текста на тёмной плашке */
  --clear-tint: rgba(21, 122, 74, 0.12);

  /* --- Семантика --------------------------------------------------------- */
  --v2-page: var(--asphalt-050);
  --v2-panel: var(--paper);
  --v2-panel-dark: var(--asphalt-900);
  --v2-text: var(--asphalt-900);
  --v2-text-secondary: var(--asphalt-500);
  --v2-text-label: var(--asphalt-400);
  --v2-text-on-dark: var(--paper);
  --v2-text-on-dark-secondary: rgba(255, 255, 255, 0.62);

  /* Линейки. Теней в системе нет — глубина передаётся линейкой и тоном. */
  --rule-hair: 1px solid var(--asphalt-200);
  --rule-hair-dark: 1px solid rgba(255, 255, 255, 0.14);
  --rule-heavy: 2px solid var(--asphalt-900);
  --rule-rail: 2px;

  --v2-scrim: linear-gradient(90deg, rgba(22,24,28,.94) 0%, rgba(22,24,28,.86) 46%, rgba(22,24,28,.55) 100%);
  --hazard-chevron: repeating-linear-gradient(45deg, var(--hazard-400) 0 6px, var(--asphalt-900) 6px 12px);

  /* --- ТОКЕНЫ · типографика (tokens/v2-typography.css) ------------------- */
  --type-display: 'Oswald', sans-serif;
  --type-body: 'IBM Plex Sans', sans-serif;
  --type-mono: 'IBM Plex Mono', monospace;
  /* Oswald сжатый сам и оси ширины не имеет. Значение оставлено, чтобы
     Archivo можно было подставить без правок разметки. */
  --display-stretch: 100%;

  --fs-13: 13px;
  --fs-15: 15px;
  --fs-17: 17px;
  --fs-20: 20px;
  --fs-28: 28px;
  --fs-36: 36px;
  --fs-40: 40px;
  --fs-56: 56px;

  --ls-display: 0.005em;
  --ls-mono-label: 0.08em;
  --ls-mono-btn: 0.06em;

  --v2-hero: 700 var(--fs-56)/1.02 var(--type-display);
  --v2-page-title: 700 var(--fs-36)/1.05 var(--type-display);
  --v2-section: 700 var(--fs-28)/1.1 var(--type-display);
  --v2-card-title: 600 var(--fs-20)/1.15 var(--type-display);
  --v2-body-lg: 400 var(--fs-17)/1.6 var(--type-body);
  --v2-body: 400 var(--fs-15)/1.6 var(--type-body);
  --v2-small: 400 var(--fs-13)/1.5 var(--type-body);
  --v2-label: 500 11px/1.4 var(--type-mono);
  --v2-data: 400 var(--fs-15)/1.4 var(--type-mono);
  --v2-price: 600 30px/1.1 var(--type-mono);

  /* --- ТОКЕНЫ · отступы (tokens/v2-space.css) --------------------------- */
  --space-48: 48px;
  --space-64: 64px;
  --space-96: 96px;
  --space-128: 128px;

  --radius-0: 0px;
  --radius-2: 2px;
  --radius-4: 4px;

  --v2-grid-max: 1240px;
  --v2-gutter: 24px;
  --v2-section-y: 96px;

  --v2-btn-h: 52px;
  --v2-btn-h-sm: 40px;
  --v2-dial: 56px;

  --rail-node: 10px;
  --rail-node-active: 12px;
  --rail-tick: 6px;
}

/* ============================================================================
   2. ТЁМНАЯ ТЕМА
   Источник: tokens/v2-dark.css. Отдельных тёмных макетов нет — тема
   работает на тех же компонентах через токены.

   Асфальтовая шкала — это ШКАЛА, а не семантика, поэтому вслепую она не
   инвертируется: иначе намеренно тёмные поверхности стали бы светлыми.
   ============================================================================ */
html.dark {
  --v2-page: #0E1013;        /* глубже asphalt-900: панели должны читаться поверх */
  --v2-panel: #181B20;
  --v2-panel-dark: #0A0C0F;
  --paper: #181B20;          /* «бумага» в тёмной теме — панель, не белый */

  --surface-inverse: #1F2329; /* чуть светлее фона, иначе сливается в пятно */
  --on-inverse: #F2F3F5;

  --v2-text: #F2F3F5;
  --v2-text-secondary: #A8AFB9;
  --v2-text-label: #7C848F;
  --v2-text-on-dark: #F2F3F5;
  --v2-text-on-dark-secondary: rgba(255, 255, 255, 0.62);

  /* Компоненты ссылаются на шкалу напрямую — переопределяем «текстовые»
     ступени, чтобы тема применилась без правок разметки. */
  --asphalt-900: #F2F3F5;
  --asphalt-700: #C9CED6;
  --asphalt-500: #A8AFB9;
  --asphalt-400: #7C848F;
  --asphalt-200: #2C3138;
  --asphalt-100: #232830;
  --asphalt-050: #0E1013;

  /* #E1281F на #0E1013 даёт 3,9:1 — мало для текста. Светлее — 5,9:1. */
  --signal-500: #FF5A4F;
  --signal-600: #FF7A70;   /* hover на тёмном светлеет, а не темнеет */
  --signal-tint: rgba(255, 90, 79, 0.16);
  /* Заливка кнопки НЕ светлеет — остаётся фирменной в обеих темах. */
  --signal-fill: #E1281F;
  --signal-fill-hover: #B81F19;
  --on-signal: #FFFFFF;
  --signal-halo: rgba(255, 90, 79, 0.30);

  --hazard-tint: rgba(245, 165, 36, 0.20);   /* сам hazard на тёмном 8,9:1 — как есть */

  --ink-700: #8DA0E0;      /* чернильный #1E2A5A на тёмном нечитаем */
  --ink-500: #A5B4EA;
  --ink-tint: rgba(141, 160, 224, 0.14);

  --clear-600: #3ECB86;
  --clear-tint: rgba(62, 203, 134, 0.16);

  --rule-hair: 1px solid #2C3138;
  --rule-hair-dark: 1px solid rgba(255, 255, 255, 0.10);
  --rule-heavy: 2px solid #4A515B;
  --v2-scrim: linear-gradient(90deg, rgba(8,9,11,.96) 0%, rgba(8,9,11,.90) 46%, rgba(8,9,11,.62) 100%);
  --hazard-chevron: repeating-linear-gradient(45deg, var(--hazard-400) 0 6px, #0A0C0F 6px 12px);
}

/* ============================================================================
   3. ТАБЛИЧНЫЕ ЦИФРЫ
   Половина визуального эффекта v2 и самая дешёвая его часть. Вешается на
   все цены, массы, годы, курс.
   ============================================================================ */
.num,
.v2-num,
[data-v2-num] {
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ============================================================================
   3.5. ЧТО ПЕРЕЖИЛО style.css (шаг 7.3)
   ----------------------------------------------------------------------------
   Не наследие «чтобы не сломать», а десять правил, без которых страница
   действительно меняется. Найдены замером: два дерева рядом, одно со
   style.css, второе без него, и сверка вычисленных стилей у каждого элемента
   на всех 15 страницах. 31 первопричина, свёрнутая до этого блока.

   Селекторы намеренно БЕЗ `body.v2` и стоят выше всех компонентов v2 —
   ровно там, где они были, когда style.css грузился первым. Поднять их
   специфичность до `body.v2 .section` значит сравнять её с обходами вроде
   `body.v2 .blog-article`, и порядок в файле начнёт решать то, что сейчас
   решает специфичность. Не трогать.
   ============================================================================ */

/* Сброс. Первые шесть строк v1; ничего специфичного для v1 в нём не было.
   Первым без него ломается плавающий круг связи: UA возвращает кнопке свои
   отступы, и .v2-dial перестаёт быть кругом. */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* overflow-x перенесён как был. Он же прячет настоящее переполнение (см.
   врезку про scrollWidth в плане), и снять его стоит — но отдельным шагом
   и со своим обходом переполнения, а не заодно с удалением файла: без него
   ширина страницы меняется на всех 15 страницах разом. */
html {
  scroll-behavior: smooth;
  overflow-x: hidden;
}

body { overflow-x: hidden; }

/* Перекрестие солнца и луны в переключателе темы. Живёт в партиале v2, но
   до 7.3 держалось на v1 — единственное место, где новая шапка зависела от
   старого файла. Без этих правил оба значка встают рядом и не переключаются.

   Цвет НЕ перенесён намеренно. В v1 тут стоял `color: #12172a` — тёмно-синий
   значок на тёмной шапке v2, контраст 1.00:1, то есть значок не виден вообще
   ни в одной теме. Кнопка `.theme-toggle` уже красится в `--on-inverse`;
   убрав цвет, значок наследует белый и даёт 17.8:1. */
.theme-toggle .icon {
  position: absolute;
  font-size: 16px;
  transition: transform .35s ease, opacity .35s ease;
}

.theme-toggle .sun  { opacity: 1; transform: scale(1); }
.theme-toggle .moon { opacity: 0; transform: scale(0.4); }
html.dark .theme-toggle .sun  { opacity: 0; transform: scale(0.4); }
html.dark .theme-toggle .moon { opacity: 1; transform: scale(1); }

/* Ширина секций главной. `.v2-sec` задаёт ритм по вертикали, но не
   контейнер, — меру строки держал v1. Без них секции разъезжаются на всю
   ширину окна. */
.hp-route    { max-width: 1200px; margin: 0 auto; padding: 44px 20px 10px; }
.hp-services { max-width: 1200px; margin: 0 auto; padding: 70px 20px 0; }
.hp-process  { max-width: 1200px; margin: 0 auto; padding: 70px 20px; }
.hp-trust    { max-width: 1200px; margin: 0 auto; padding: 10px 20px 40px; }
.hp-vehicles { max-width: 1200px; margin: 0 auto; padding: 0 20px 70px; }

/* Фотография героя на главной лежала в v1: `.v2-hero` фон не задаёт. */
.hp-hero {
  align-items: center;
  background: url('https://res.cloudinary.com/dkita2qyq/image/upload/v1756128166/%D0%98%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_WhatsApp_2025-05-27_%D0%B2_18.33.35_cbb88195_nxd0wv.jpg') no-repeat center center/cover;
}

/* `.section` — главная (две секции), блог, избранное, privacy-policy, terms.
   Центрирование остаётся: три обхода в v2 (`.blog-article`, `.fav-cta-banner`,
   `.blog-card`) написаны против него и держат левый край там, где он нужен
   системе. Снять правило и обходы разом — отдельная правка с пересмотром
   этих пяти страниц, а не побочный эффект удаления файла. */
.section {
  padding: 0 0 60px;
  text-align: center;
}

/* Ступени увеличения текста. Вёрстка в px, поэтому масштабируем через zoom —
   так растёт весь интерфейс целиком, а не только шрифт. Поправка для
   .v2-dial-wrap уже есть ниже, в блоке плавающих контактов. */
html.cm-font-lg body { zoom: 1.15; }
html.cm-font-xl body { zoom: 1.30; }

/* Значок «?» у строк разбивки калькулятора и его всплывающая подсказка.
   Рисует js/calculator.js (hintFor), в v2 их не было вовсе.
   Значения дословные, как у всего остального в 7.2.5. Единственное
   отступление — ховер: в v1 значок заливался красным, а подсказка не значит
   ни «действие», ни «вы здесь», так что по правилу красного ей полагается
   асфальт. Заливка в покое, размеры и шрифт — как были. */
.cm-hint {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: 6px;
  border-radius: 50%;
  background: #6b7280;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  cursor: help;
  vertical-align: middle;
}

.cm-hint:hover,
.cm-hint:focus { background: var(--asphalt-900); outline: none; }

.cm-hint-pop {
  position: absolute;
  z-index: 10000;
  background: #1f2937;
  color: #fff;
  padding: 14px 38px 14px 16px;
  border-radius: 12px;
  font-size: 15px;
  line-height: 1.5;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .3);
}

.cm-hint-pop__x {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, .15);
  color: #fff;
  font-size: 13px;
  cursor: pointer;
}

.cm-hint-pop__x:hover { background: rgba(255, 255, 255, .28); }

/* Плашка ответа формы на контактах — дословно. Перекрасить её в
   clear-600/signal и сузить скругление до шкалы v2 напрашивается, но это
   правка дизайна: здесь только уборка. */
#formStatus {
  display: none;
  margin-top: 15px;
  padding: 10px;
  border-radius: 6px;
  color: #fff;
}

#formStatus.success { background-color: #28a745; }
#formStatus.error   { background-color: #dc3545; }


/* ============================================================================
   3.6. ХРОМ v2 И ОСНОВА СТРАНИЦ НА СВОИХ НОГАХ (шаг 7.2.5)
   ----------------------------------------------------------------------------
   Шапка, шторка и футер v2 писались как ПЕРЕКРАСКА поверх навигации v1, а не
   с нуля: 348 правил style.css держали их и основу страниц на всех 15
   страницах. Здесь эта опора перенесена целиком.

   Правила идут ДОСЛОВНО и в СТРОГОМ ИСХОДНОМ ПОРЯДКЕ v1, селекторы без
   `body.v2`. И то и другое обязательно:

   — специфичность должна остаться прежней, иначе перекраска v2 начнёт
     проигрывать перенесённой основе;
   — порядок должен остаться прежним, потому что часть правил перебивает
     друг друга только им. Первая версия этого блока группировала правила
     по @media, и `.btn{padding:.55rem .85rem}` уехал ВЫШЕ медиазапроса,
     который в v1 идёт до него. На 390px кнопка каталога стала на 2.4px
     выше — единственное, что об этом сказало.

   Исключения ровно два, оба описаны в 3.5: цвет в `.theme-toggle .icon`
   и заливка `.task-btn.active`.
   ============================================================================ */

html.dark .nav-links a {
  color: #cfd4dd;
}
html.dark .nav-links li.nav-pill a {
  background: rgba(255,255,255,0.08);
  color: #fff;
}
html.dark .nav-links a:hover, html.dark .nav-links a.active {
  color: #E12821;
}
html.dark .nav-links li.nav-pill a:hover, html.dark .nav-links li.nav-pill a.active {
  background: #E12821;
  color: #fff;
}
html.dark .card, html.dark .feature-card, html.dark .gallery-card, html.dark .review-card, html.dark .calc-card, html.dark .contact-form {
  background: #1e1e1e;
  color: #f5f5f5;
}
html.dark h3, html.dark .card i, html.dark h4, html.dark .gallery-card p, html.dark .card p, html.dark .calc-card__title, html.dark .calc-card label, html.dark .calc-card .summary-line strong, html.dark .summary-line, html.dark .contact-form label, html.dark .review-caption, .contact-form input, .contact-form textarea {
  color: #fff;
}
html.dark .calc-card input[type="text"], html.dark .calc-card input[type="number"], html.dark .calc-card select, html.dark .meta-row {
  background: #1f1f1f;
  color: #fff;
}
html.dark .section, html.dark .container, html.dark .contact-form input, html.dark .contact-form textarea, html.dark #contact, html.dark #calculator {
  background-color: #121212;
}
:root {
  --primary-blue: #1F1F1F;
  --secondary-blue: #1F1F1F;
  --accent-orange: #E12821;
  --white: #FFFFFF;
  --shadow-sm: 0 5px 15px rgba(0, 0, 0, 15);
  --shadow-md: 0 10px 20px rgba(0, 0, 0, 0.2);
  --accent:#E12821;
  --accent-2:#2f6fed;
}
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 28px;
  list-style: none;
  margin: 0;
  padding: 0;
  justify-content: center;
}
.nav-links a {
  color: #4b5165;
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  position: relative;
  transition: color 0.2s ease;
}
.nav-links a:hover, .nav-links a.active {
  color: #E12821;
}
.nav-links li.nav-pill a {
  background: #f5f6f8;
  color: #12172a;
  padding: 10px 22px;
  border-radius: 999px;
  font-weight: 600;
}
.nav-links li.nav-pill a:hover, .nav-links li.nav-pill a.active {
  background: #E12821;
  color: #ffffff;
}
.nav-links i {
  margin-right: 8px;
}
h2, .blue-title, .white-title {
  /* Голые заголовки: v2 описывает типографику только через классы, но
     страховка нужна — иначе любой h2 без класса падает в системный шрифт.
     Раньше здесь стоял Montserrat из v1; теперь — дисплейная гарнитура v2. */
  font-family: var(--type-display);
  font-size: 36px;
  margin-bottom: 40px;
  position: relative;
}
.white-title {
  color: var(--white);
}
.white-title::after {
  background: var(--white);
}
h3, h4 {
  font-family: var(--type-display);
  color: var(--primary-blue);
}
h3 {
  font-size: 20px;
  margin-bottom: 10px;
}
h4 {
  font-size: 18px;
  margin-bottom: 10px;
}
.white-title-h3 {
  color: var(--white);
  font-size: 20px;
  margin-bottom: 10px;
}
p {
  /* Тот же случай, что у голых заголовков: было 'Open Sans' из v1. */
  font-family: var(--type-body);
  font-size: 16px;
  margin-bottom: 10px;
  max-width: 800px;
  margin-left: auto;
  margin-right: auto;
  color: #fff;
}
#about .container {
  background: transparent;
  padding: 0 20px;
  border-radius: 0;
  box-shadow: none;
  max-width: 980px;
}
.feature-grid, .gallery-grid, .reviews-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 30px;
  margin-top: 30px;
}
.card, .gallery-card, .review-card {
  border-radius: 15px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
  text-align: center;
}
.card:hover, .review-card:hover {
  transform: translateY(-5px);
  box-shadow: var(--shadow-md);
}
.card {
  background: rgba(255, 255, 255, 0.95);
  padding: 25px;
}
.card i {
  color: var(--accent);
  font-size: 40px;
  margin-bottom: 15px;
}
.card p {
  color: #000;
}
.gallery-card {
  overflow: hidden;
}
.gallery-card:hover {
  transform: translateY(-5px);
}
.gallery-img {
  width: 100%;
  height: 250px;
  object-fit: cover;
  border-radius: 15px 15px 0 0;
  transition: opacity 0.3s ease;
}
.gallery-card:hover .gallery-img {
  opacity: 0.9;
}
.gallery-card p {
  margin: 15px;
  font-size: 14px;
  color: var(--primary-blue);
  font-weight: 500;
}
#reviews {
  background: #ffffff;
  padding: 70px 0;
}
#reviews .container {
  background: transparent;
  padding: 0 20px;
  border-radius: 0;
  box-shadow: none;
}
#reviews p, #reviews .White-p, #reviews .cta-text {
  color: #4b5165;
}
.review-card {
  background: rgba(255, 255, 255, 0.95);
  padding: 20px;
}
.review-img, .review-card video {
  max-width: 100%;
  min-width: 100%;
  min-height: 250px;
  max-height: 300px;
  object-fit: cover;
  border-radius: 10px;
  margin-bottom: 15px;
  display: block;
  border: none;
}
.review-caption {
  font-size: 14px;
  color: #000;
  padding: 0 10px;
  font-weight: 500;
}
.btn {
  display: inline-block;
  background: linear-gradient(90deg, var(--secondary-blue), #1F1F1F);
  color: var(--white);
  padding: 10px 20px;
  text-decoration: none;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  transition: background 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
  border: none;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(18, 130, 162, 0.3);
}
.btn:hover {
  background: var(--signal-fill-hover);
  transform: translateY(-3px);
  box-shadow: 0 4px 15px rgba(249, 87, 56, 0.4);
}
.btn.instagram {
  background: linear-gradient(90deg, #E4405F, #E1306C);
}
.btn.instagram:hover {
  background: linear-gradient(90deg, #F56040, #FF7E6D);
}
.btn.tiktok {
  background: linear-gradient(90deg, #000000, #111111);
}
.btn.tiktok:hover {
  background: linear-gradient(90deg, #111111, #222222);
}
.btn i {
  margin-right: 8px;
}
#contact {
  background: #f9f9f9;
}
.contact-form {
  max-width: 600px;
  margin: 20px auto;
  padding: 30px;
  background: #fff;
  border-radius: 15px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s ease;
}
.contact-form label {
  display: block;
  font-size: 16px;
  color: var(--primary-blue);
  font-weight: 500;
  margin-bottom: 8px;
}
.contact-form input, .contact-form textarea {
  width: 100%;
  padding: 12px;
  font-size: 14px;
  border: 2px solid var(--primary-blue);
  border-radius: 6px;
  margin-bottom: 20px;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
  color: #1F1F1F;
  background: #ffffffff;
}
html.dark .contact-form input, html.dark .contact-form textarea {
  color: #fff;
}
.contact-form input:focus, .contact-form textarea:focus {
  border-color: var(--accent-orange);
  box-shadow: 0 0 8px rgba(249, 87, 56, 0.3);
  outline: none;
}
.contact-form textarea {
  height: 150px;
  resize: vertical;
}
.contact-form .btn {
  display: block;
  margin: 0 auto;
  background-color: #1F1F1F;
}

@media (max-width: 768px) {
  .navbar .container {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    position: relative;
  }
  .navbar .logo {
    font-size: 24px;
  }
  .nav-links {
    position: fixed;
    top: 0;
    right: -100%;
    width: 70%;
    height: 100vh;
    background: linear-gradient(90deg, var(--primary-blue), #1f1f1f);
    flex-direction: column;
    gap: 25px;
    padding: 60px 20px;
    transition: right 0.5s ease-in-out;
    z-index: 99;
  }
  html.dark .nav-links {
    background: #000;
  }
  .nav-links.active {
    right: 0;
    display: flex;
  }
  .nav-links .close-btn {
    position: absolute;
    top: 20px;
    right: 20px;
    font-size: 24px;
    color: var(--white);
    cursor: pointer;
    background: none;
    border: none;
    padding: 5px 10px;
  }
  .nav-links .close-btn::before {
    content: "←";
  }
  .feature-grid, .gallery-grid, .reviews-grid {
    grid-template-columns: 1fr;
  }
  #about, #reviews {
    background-attachment: scroll;
  }
  .container {
    padding: 10px;
  }
  .btn {
    padding: 10px 16px;
    font-size: 14px;
  }
  #about .container, #reviews .container {
    padding: 30px;
  }
  .gallery-img {
    height: 200px;
  }
  .review-img, .review-card video {
    height: 200px;
  }
  .reviews-grid {
    gap: 20px;
    margin-top: 30px;
    margin-bottom: 30px;
  }
  .contact-form {
    padding: 20px;
  }
}

@media (max-width: 480px) {
  h3 {
    font-size: 16px;
  }
  h4 {
    font-size: 14px;
  }
  p {
    font-size: 14px;
  }
  .card, .gallery-card, .review-card {
    padding: 15px;
  }
  .gallery-img {
    height: 150px;
  }
  .review-img, .review-card video {
    height: 150px;
  }
  .btn {
    padding: 8px 12px;
    font-size: 12px;
    min-width: 90px;
  }
  .contact-form input, .contact-form textarea {
    padding: 10px;
    font-size: 12px;
  }
}
.calc-card {
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.08);
  padding: 24px;
  margin-bottom: 20px;
}
.calc-card h3 {
  font-size: 20px;
  margin-bottom: 15px;
  font-weight: 600;
  color: #222;
}
.calc-card label {
  font-weight: 600;
  color: #444;
  margin-bottom: 6px;
}
.calc-card input, .calc-card select {
  border: 1px solid #ccc;
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 14px;
  transition: all .2s ease;
}
.calc-card input:focus, .calc-card select:focus {
  border-color: #E12821;
  box-shadow: 0 0 0 3px rgba(225,40,33,0.2);
  outline: none;
}
.summary-card {
  background: #fff;
  border-radius: 16px;
  padding: 24px;
  box-shadow: 0 8px 20px rgba(0,0,0,0.1);
}
.summary-title {
  font-size: 22px;
  font-weight: 700;
  margin-bottom: 18px;
  color: #111;
  border-bottom: 2px solid #eee;
  padding-bottom: 8px;
}
.summary-line {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px dashed #ddd;
  font-size: 15px;
  color: #333;
}
.summary-line:last-of-type {
  border-bottom: none;
}
.summary-total {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 18px;
  padding-top: 12px;
  border-top: 2px solid #ccc;
  font-size: 18px;
  font-weight: 700;
  color: #111;
}
.summary-total strong {
  font-size: 22px;
  color: #E12821;
}
#calcForm .btn, .summary-card .btn {
  background: var(--signal-fill);
  border: none;
  padding: 12px 20px;
  border-radius: 10px;
  font-weight: 600;
  font-size: 15px;
  box-shadow: 0 6px 14px rgba(225,40,33,0.25);
  transition: transform .15s ease, box-shadow .15s ease;
}
#calcForm .btn:hover, .summary-card .btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 18px rgba(225,40,33,0.35);
}
.calc-sections {
  display:flex;
  flex-direction:column;
  gap:16px;
}
.calc-card {
  background: rgba(255, 255, 255, 0.95);
  border:1px solid #223044;
  border-radius:16px;
  padding:18px;
  box-shadow:0 8px 22px rgba(0,0,0,.28);
}
.calc-card__title {
  margin:0 0 10px 0;
  font-size:18px;
  font-weight:800;
  color: #1f1f1f;
}
.calc-actions {
  display:flex;
  gap:10px;
  flex-wrap:wrap;
  margin-top:6px;
}
.btn.btn--ghost {
  background:#1f2631;
  color:#e7edf6;
  box-shadow:none;
  border:1px solid #2a3444;
}
.btn.btn--ghost:hover {
  filter:brightness(1.05);
}
.summary-card--dark {
  background:#0b0e13;
  border:1px solid #232b39;
  border-radius:16px;
  padding:22px;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.02), 0 12px 30px rgba(0,0,0,.35);
}
.summary-card--dark .summary-title {
  font-size:22px;
  font-weight:800;
  margin-bottom:14px;
  color:#fff;
  border-bottom:1px solid #1f2733;
  padding-bottom:10px;
}
.summary-card--dark .summary-line {
  display:flex;
  justify-content:space-between;
  gap:12px;
  padding:10px 0;
  border-bottom:1px dashed #2a3445;
  color:#e2e8f0;
}
.summary-card--dark .summary-line:last-of-type {
  border-bottom:none;
}
.summary-card--dark .summary-total {
  display:flex;
  justify-content:space-between;
  align-items:center;
  margin-top:16px;
  padding-top:12px;
  border-top:2px solid #2a3445;
  color:#fff;
}
.summary-card--dark .summary-total strong {
  font-size:24px;
  color:#ff6b61;
}
.summary-card--dark .summary-sub {
  color:#9fb2cc;
  margin-top:6px;
}
.calc-card input[type="text"], .calc-card input[type="number"], .calc-card select {
  width:100%;
  padding:12px;
  border-radius:12px;
  background: rgba(255, 255, 255, 0.95);
  color: #545454;
  border:1px solid #2b3648;
  outline:none;
  transition:border .15s, box-shadow .15s, background .15s;
}
.calc-card input:focus, .calc-card select:focus {
  border-color:#365cff;
  box-shadow:0 0 0 3px rgba(54,92,255,.18);
}
.calc-hint {
  color:#aab4c5;
  font-size:13px;
  margin:6px 0 8px;
  position: relative;
}
.calc-card .summary-line {
  background:transparent;
  border:1px dashed #2a3445;
  padding:10px;
  border-radius:12px;
}
.calc-card .summary-line strong {
  color:#1f1f1f;
}

@media (max-width:980px) {
  #calcGrid {
    display:block;
  }
  .summary-card--dark {
    margin-top:16px;
  }
  .calc-actions .btn {
    width:100%;
    justify-content:center;
  }
}
.summary-actions {
  display:flex;
  gap:10px;
  flex-wrap:wrap;
  margin-top:18px;
}
.summary-actions .btn {
  min-width: 180px;
}

@media (max-width:980px) {
  .summary-actions .btn {
    flex:1;
  }
}
#rateInfo.ok {
  color:#22c55e;
}
#rateInfo.err {
  color:#ef4444;
}
.summary-actions {
  display:flex;
  gap:10px;
  flex-wrap:wrap;
  margin-top:18px;
}
.summary-actions .btn {
  min-width: 180px;
}

@media (max-width:980px) {
  .summary-actions .btn {
    flex:1;
  }
}
#calcGrid {
  display:grid;
  grid-template-columns: minmax(0,1fr) 420px;
  gap:20px;
  align-items:start;
}

@media (max-width:980px) {
  #calcGrid {
    display:block;
  }
}
.calc-sections {
  display:flex;
  flex-direction:column;
  gap:16px;
}
.calc-card {
  background:#fff;
  border-radius:16px;
  box-shadow:0 6px 18px rgba(0,0,0,.08);
  padding:24px;
}
.calc-card__title {
  font-size:22px;
  font-weight:700;
  margin-bottom:10px;
}
.summary-card {
  background:#1f1f1f;
  color:white;
  border-radius:18px;
  padding:24px;
  box-shadow:0 12px 28px rgba(0,0,0,.2);
  position:sticky;
  top:88px;
}
.summary-card--dark .summary-title {
  font-size:22px;
  font-weight:800;
  margin:0 0 12px;
}
.summary-card--dark .summary-line {
  display:flex;
  justify-content:space-between;
  gap:12px;
  padding:10px 0;
  border-bottom:1px dashed #ffffffff;
  color:#e2e8f0;
}
.summary-card--dark .summary-line:last-of-type {
  border-bottom:none;
}
.summary-card--dark .summary-total {
  display:flex;
  justify-content:space-between;
  align-items:center;
  margin-top:16px;
  padding-top:12px;
  border-top:2px solid #ffffffff;
  color:#fff;
}
.summary-card--dark .summary-total strong {
  font-size:24px;
  color:#ff6b61;
}
.summary-sub {
  color:#9fb2cc;
  margin-top:6px;
}
.summary-actions {
  display:flex;
  gap:10px;
  flex-wrap:wrap;
  margin-top:18px;
}
.summary-actions .btn {
  min-width:180px;
}
.btn {
  cursor:pointer;
  border-radius:10px;
  padding:.55rem .85rem;
  font-weight:600;
  border:1px solid #d9d9d9;
  background: var(--signal-fill);
}
.btn:disabled {
  opacity:.5;
  cursor:not-allowed;
}
.btn-primary {
  background: var(--signal-fill);
  color: var(--on-signal);
  border-color: var(--signal-fill);
}
.btn-outline {
  background:transparent;
}
.btn.js-open-gallery {
  background: #1f1f1f;
  border: 1px solid #e8eaee;
}
#search {
  flex: 1 1 250px;
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 16px;
}

@media (max-width: 600px) {
  .calc-card label {
    display: flex;
    justify-content: center;
  }
  .summary-actions .btn {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .calc-card__title {
    display: flex;
    justify-content: center;
  }
  .summary-card--dark .summary-title {
    display: flex;
    justify-content: center;
  }
  .card-actions {
    justify-content: space-evenly;
  }
}
html.dark #search {
  background: #1f1f1f;
  border-color: #333;
  color: #fff;
}
html.dark #themeToggle {
  color: #ffd700;
}
html.dark #langSwitch {
  background: #1f1f1f;
  color: #fff;
  border: 1px solid #333;
}
#themeToggle {
  background: none;
  border: none;
  font-size: 18px;
  cursor: pointer;
  color: #fff;
}
#langSwitch {
  padding: 4px 6px;
  border-radius: 6px;
}

@media (max-width: 920px) {
  .nav-links, #langSwitch, .nav-auth-link {
    display: none !important;
  }
  .menu-toggle {
    display: flex !important;
  }
}
.menu-toggle {
  display: none;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid #e4e6eb;
  background: #fff;
  cursor: pointer;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  padding: 0;
  flex-shrink: 0;
}
html.dark .menu-toggle {
  background: #2a2a2a;
  border-color: rgba(255,255,255,.12);
}
.menu-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: #12172a;
}
html.dark .menu-toggle span {
  background: #f5f5f5;
}
.nav-drawer-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(13,17,32,0.5);
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease, visibility .25s ease;
}
.nav-drawer-overlay.active {
  opacity: 1;
  visibility: visible;
}
.nav-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 201;
  width: min(84vw, 320px);
  background: #fff;
  box-shadow: -12px 0 40px rgba(13,17,32,0.2);
  transform: translateX(100%);
  transition: transform .28s cubic-bezier(.4,0,.2,1);
  display: flex;
  flex-direction: column;
}
.nav-drawer.active {
  transform: translateX(0);
}
html.dark .nav-drawer {
  background: #1e1e1e;
}
.nav-drawer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px;
  border-bottom: 1px solid #e4e6eb;
  flex-shrink: 0;
}
html.dark .nav-drawer__header {
  border-color: rgba(255,255,255,.08);
}
.nav-drawer__logo {
  font-family: 'Oswald', sans-serif;
  font-weight: 700;
  font-size: 17px;
  color: #12172a;
}
html.dark .nav-drawer__logo {
  color: #f5f5f5;
}
.nav-drawer__logo .logo-china {
  color: #E12821;
}
.nav-drawer__close {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid #e4e6eb;
  background: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  line-height: 1;
  color: #12172a;
}
html.dark .nav-drawer__close {
  background: #2a2a2a;
  border-color: rgba(255,255,255,.12);
  color: #f5f5f5;
}
.nav-drawer__nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 12px;
  overflow-y: auto;
  gap: 2px;
}
.nav-drawer__nav a {
  padding: 14px 12px;
  border-radius: 10px;
  font-size: 15px;
  font-weight: 500;
  color: #12172a;
  text-decoration: none;
}
html.dark .nav-drawer__nav a {
  color: #f5f5f5;
}
.nav-drawer__nav a.active {
  font-weight: 600;
  color: #E12821;
  background: #f5f6f8;
}
html.dark .nav-drawer__nav a.active {
  background: rgba(225,40,33,0.15);
}
.nav-drawer__footer {
  padding: 16px 20px;
  border-top: 1px solid #e4e6eb;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex-shrink: 0;
}
html.dark .nav-drawer__footer {
  border-color: rgba(255,255,255,.08);
}
.nav-drawer__phone {
  text-align: center;
  font-size: 13.5px;
  font-weight: 600;
  color: #12172a;
  text-decoration: none;
}
html.dark .nav-drawer__phone {
  color: #f5f5f5;
}
.nav-drawer__footer #langSwitch, .nav-drawer__footer #themeToggle, .nav-drawer__footer .nav-auth-link {
  display: flex !important;
  width: 100%;
}
.nav-drawer__footer .lang-toggle {
  width: 100%;
  justify-content: space-between;
}
.nav-drawer__footer .nav-auth-link {
  justify-content: center;
  padding: 14px;
  max-width: none;
}
.nav-drawer__footer #themeToggle {
  justify-content: flex-start;
  gap: 10px;
  padding: 10px 4px;
}
.nav-links li {
  white-space: nowrap;
}
.nav-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}
.nav-auth-link {
  background: #12172a;
  color: #fff !important;
  padding: 11px 24px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 13.5px;
  text-decoration: none;
  white-space: nowrap;
  transition: background .2s ease;
}
.nav-auth-link:hover {
  background: #1c2340;
  color: #fff !important;
}
html.dark .nav-auth-link {
  background: #E12821;
}
html.dark .nav-auth-link:hover {
  background: #c81e2c;
}
.theme-toggle {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid #e4e6eb;
  background: #fff;
  cursor: pointer;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .25s ease;
}
.theme-toggle:hover {
  background: #f5f6f8;
}
.nav-icon-btn {
  position: relative;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid #e4e6eb;
  background: #fff;
  color: #12172a;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  text-decoration: none;
  flex-shrink: 0;
}
.nav-icon-btn:hover {
  background: #f5f6f8;
}
.nav-icon-btn.active i {
  color: #E12821;
}
.nav-fav-count {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: #E12821;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 17px;
  text-align: center;
}
html.dark .nav-fav-count {
  box-shadow: 0 0 0 2px #12172a;
}
.lang-switch {
  position: relative;
}
.lang-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid #e4e6eb;
  background: #fff;
  color: #12172a;
  font-weight: 600;
  font-size: 13px;
  cursor: pointer;
  transition: background .2s ease;
}
.lang-toggle:hover {
  background: #f5f6f8;
}
.lang-toggle i {
  font-size: 10px;
  color: #4b5165;
  transition: transform .2s ease;
}
.lang-switch.open .lang-toggle i {
  transform: rotate(180deg);
}
/* Список языка раскрывается переходом, а не подменой display: display
   анимировать нечем, а переключатель стоит в шапке и срабатывает по
   каждому нажатию — мгновенная подмена там читается как подёргивание.
   Закрытое состояние держит visibility, а не display: элемент остаётся в
   раскладке (он абсолютный, места не занимает), но не ловит курсор и не
   попадает ни в Tab, ни в скринридер. Задержка на visibility нужна, чтобы
   меню исчезло ПОСЛЕ того, как погасло, а не в первом же кадре. */
.lang-switch__menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: #fff;
  border: 1px solid #e4e6eb;
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(18,23,42,0.14);
  padding: 6px;
  min-width: 160px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  z-index: 200;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  pointer-events: none;
  transition: opacity .16s ease, transform .16s ease, visibility 0s linear .16s;
}
.lang-switch.open .lang-switch__menu {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition: opacity .16s ease, transform .16s ease, visibility 0s;
}
.lang-switch__menu button {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: none;
  background: transparent;
  border-radius: 8px;
  font-size: 13.5px;
  color: #12172a;
  text-align: left;
  cursor: pointer;
  font-family: var(--type-body);
}
.lang-switch__menu button:hover {
  background: #f5f6f8;
}
.lang-switch__menu button.active {
  color: #E12821;
  font-weight: 600;
}
html.dark .theme-toggle, html.dark .nav-icon-btn, html.dark .lang-toggle {
  background: #1e1e1e;
  border-color: #333;
}
html.dark .theme-toggle .icon {
  color: #f5f5f5;
}
html.dark .nav-icon-btn {
  color: #f5f5f5;
}
html.dark .lang-toggle {
  color: #f5f5f5;
}
html.dark .lang-switch__menu {
  background: #1e1e1e;
  border-color: #333;
}
html.dark .lang-switch__menu button {
  color: #f5f5f5;
}
html.dark .lang-switch__menu button:hover {
  background: #171717;
}
.privacy-date {
  font-size: 14px;
  color: #777;
  margin-bottom: 30px;
}
html.dark .privacy-date {
  color: #aaa;
}
.why-us {
  background: #f9f9f9;
}
html.dark .why-us {
  background: #121212;
}
.why-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 24px;
  margin-top: 30px;
}
.why-card {
  background: #ffffff;
  border-radius: 16px;
  padding: 24px 20px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.08);
  transition: transform .2s ease, box-shadow .2s ease;
  text-align: center;
}
.why-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 24px rgba(0,0,0,0.15);
}
.why-card i {
  font-size: 36px;
  color: #E12821;
  margin-bottom: 14px;
}
.why-card h4 {
  font-size: 18px;
  margin-bottom: 8px;
}
.why-card p {
  font-size: 14px;
  color: #333;
}
html.dark .why-card {
  background: #1e1e1e;
}
html.dark .why-card p {
  color: #e0e0e0;
}
html.dark #about, html.dark #reviews {
  background: #171717;
}
html.dark #about p, html.dark #about .White-p, html.dark #reviews p, html.dark #reviews .White-p, html.dark #reviews .cta-text {
  color: #cfd4dd;
}
.calc-disclaimer {
  max-width: 900px;
  margin: 20px auto 0;
  font-size: 13px;
  color: #666;
  text-align: center;
}
html.dark .calc-disclaimer {
  color: #aaa;
}
.btn.js-open-gallery:hover {
  background: var(--signal-fill-hover);
  transform: translateY(-3px);
  box-shadow: 0 4px 15px rgba(249, 87, 56, 0.4);
}
.btn-outline {
  padding: 10px 18px;
  border: 1.5px solid #ff3b30;
  border-radius: 999px;
  color: #ff3b30;
  font-weight: 600;
  font-size: 14px;
}
.btn-outline {
  padding: 9px 16px;
  border-radius: 999px;
  border: 1.5px solid #e53935;
  color: #e53935;
  font-size: 14px;
  font-weight: 600;
}
.blog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}
.blog-card {
  background: #fff;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 4px 24px rgba(18,23,42,0.06);
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: #12172a;
  transition: transform .2s ease, box-shadow .2s ease;
}
.blog-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 10px 28px rgba(18,23,42,0.15);
}
html.dark .blog-card {
  background: #1e1e1e;
  color: #f5f5f5;
}
.blog-card__icon {
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #12172a, #1c2440);
  color: #E12821;
  font-size: 32px;
}
.blog-card__body {
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}
.blog-card__date {
  font-size: 11.5px;
  color: #8a8f9c;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.blog-card__title {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  font-size: 18px;
  line-height: 1.3;
}
.blog-card__excerpt {
  font-size: 14px;
  color: #4b5165;
  line-height: 1.55;
}
html.dark .blog-card__excerpt {
  color: #aab4c5;
}
.blog-card__cta {
  margin-top: auto;
  padding-top: 8px;
  color: #E12821;
  font-weight: 600;
  font-size: 13.5px;
}
.blog-article {
  max-width: 760px;
  margin: 0 auto;
  padding: 40px 24px 80px;
}
.blog-article__meta {
  font-size: 13px;
  color: #8a8f9c;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 12px;
}
.blog-article h1 {
  font-family: 'Oswald', sans-serif;
  font-size: clamp(26px, 4vw, 34px);
  font-weight: 700;
  line-height: 1.25;
  margin-bottom: 24px;
  color: #12172a;
}
html.dark .blog-article h1 {
  color: #f5f5f5;
}
.blog-article h2 {
  font-family: 'Oswald', sans-serif;
  font-size: 21px;
  font-weight: 600;
  margin: 32px 0 12px;
  color: #12172a;
}
html.dark .blog-article h2 {
  color: #f5f5f5;
}
.blog-article p {
  font-size: 16px;
  line-height: 1.75;
  color: #333;
  margin-bottom: 16px;
}
html.dark .blog-article p {
  color: #e0e0e0;
}
.blog-article ul {
  margin: 0 0 16px 20px;
}
.blog-article li {
  font-size: 16px;
  line-height: 1.7;
  color: #333;
  margin-bottom: 8px;
}
html.dark .blog-article li {
  color: #e0e0e0;
}
.blog-article li strong {
  color: #12172a;
}
html.dark .blog-article li strong {
  color: #f5f5f5;
}
.blog-article__cta {
  background: #12172a;
  border-radius: 16px;
  padding: 28px;
  margin-top: 40px;
  text-align: center;
}
.blog-article__cta p {
  color: #fff;
  margin-bottom: 16px;
}
.blog-article__cta .btn {
  display: inline-block;
}
.blog-back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: #8a8f9c;
  text-decoration: none;
  margin-bottom: 20px;
}
.blog-back-link:hover {
  color: #E12821;
}
.logo-mark {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: #12172a;
  color: #fff;
  font-family: 'Oswald', sans-serif;
  font-weight: 700;
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
}
.logo-mark::before {
  content: '';
  position: absolute;
  inset: 0;
  background: #E12821;
  clip-path: polygon(0 0, 62% 0, 0 100%);
}
.logo-mark span, .logo-mark {
  z-index: 1;
}
.footer-brand .logo-mark {
  width: 40px;
  height: 40px;
  border-radius: 11px;
  background: #fff;
  color: #12172a;
}
.btn-outline-light {
  border: 1.5px solid rgba(255,255,255,0.6);
  color: #fff;
  padding: 12px 26px;
  border-radius: 999px;
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  display: inline-block;
}
.hp-calc-widget {
  background: #fff;
  border-radius: 20px;
  padding: 24px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.35);
  color: #12172a;
}
.hp-calc-widget__title {
  font-family: 'Oswald', sans-serif;
  font-weight: 600;
  font-size: 17px;
  margin-bottom: 16px;
}
.hp-calc-widget label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: #8a8f9c;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}
.hp-calc-widget .hp-field {
  margin-bottom: 14px;
}
.hp-calc-widget select, .hp-calc-widget input {
  width: 100%;
  box-sizing: border-box;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid #e4e6eb;
  font-size: 14px;
  font-family: var(--type-body);
  color: #12172a;
  background: #fff;
}
.hp-calc-widget button {
  width: 100%;
  margin-top: 6px;
  background: #12172a;
  color: #fff;
  border: none;
  padding: 14px;
  border-radius: 10px;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  font-family: inherit;
}
.hp-calc-widget button:hover {
  background: #1c2340;
}
.hp-calc-widget__note {
  text-align: center;
  font-size: 12px;
  color: #8a8f9c;
  margin-top: 10px;
}
.hp-stats {
  background: #12172a;
  padding: 50px 20px;
}
.hp-stats-inner {
  max-width: 1200px;
  margin: 0 auto;
}
.hp-stats-label {
  font-family: 'Oswald', sans-serif;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 2px;
  color: #E12821;
  text-align: center;
  margin-bottom: 30px;
}
.hp-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 20px;
}
.hp-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
}
.hp-stat strong {
  font-family: 'Oswald', sans-serif;
  font-weight: 700;
  font-size: 28px;
  color: #fff;
}
.hp-stat span {
  font-size: 13px;
  color: rgba(255,255,255,0.6);
}
html.dark .hp-calc-widget {
  background: #1e1e1e;
  color: #f5f5f5;
}
html.dark .hp-calc-widget select, html.dark .hp-calc-widget input {
  background: #1f1f1f;
  color: #fff;
  border-color: #333;
}
html.dark .hp-calc-widget label {
  color: #aab4c5;
}
.hp-filter-card {
  max-width: 1200px;
  margin: 24px auto 8px;
  padding: 0 20px;
}
.hp-filter-card__inner {
  background: #fff;
  border-radius: 16px;
  padding: 20px;
  box-shadow: 0 4px 24px rgba(18,23,42,0.06);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px;
  align-items: end;
}
.hp-filter-card__inner .f-search {
  grid-column: 1 / -1;
}
.hp-filter-card label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: #8a8f9c;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}
.hp-filter-card input, .hp-filter-card select {
  width: 100%;
  box-sizing: border-box;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid #e4e6eb;
  font-size: 13.5px;
  font-family: var(--type-body);
  color: #12172a;
  background: #fff;
}
html.dark .hp-filter-card__inner {
  background: #1e1e1e;
}
html.dark .hp-filter-card input, html.dark .hp-filter-card select {
  background: #1f1f1f;
  color: #fff;
  border-color: #333;
}
html.dark .hp-filter-card label {
  color: #aab4c5;
}
.calc-card__title {
  display: flex;
  align-items: center;
  gap: 12px;
}
.hp-calc-step {
  width: 26px;
  height: 26px;
  border-radius: 999px;
  background: #E12821;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  flex-shrink: 0;
}
.summary-card {
  background: #12172a;
}
.summary-card--dark {
  background: #12172a;
}
.simple-calc {
  max-width: 720px;
  margin: 0 auto 28px;
}
.simple-calc__title {
  font-size: 26px;
  margin: 0 0 6px;
}
.simple-calc__sub {
  color: #6b7280;
  margin: 0 0 22px;
  font-size: 17px;
}
.simple-calc__label {
  display: block;
  font-weight: 700;
  font-size: 17px;
  margin: 20px 0 10px;
}
.simple-calc__choices {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.sc-choice {
  padding: 14px 20px;
  border: 2px solid #d8dbe2;
  background: #fff;
  border-radius: 12px;
  font-size: 16px;
  cursor: pointer;
  min-height: 52px;
}
.sc-choice:hover {
  border-color: #E12821;
}
.sc-choice.active {
  background: #E12821;
  border-color: #E12821;
  color: #fff;
  font-weight: 700;
}
.simple-calc__input {
  width: 100%;
  padding: 14px 16px;
  font-size: 17px;
  border: 2px solid #d8dbe2;
  border-radius: 12px;
  margin-bottom: 12px;
  min-height: 52px;
}
.simple-calc__send {
  width: 100%;
  padding: 16px;
  font-size: 18px;
  margin-top: 10px;
  min-height: 56px;
}
.simple-calc__status {
  margin-top: 12px;
  font-size: 16px;
}
.simple-calc__status.ok {
  color: #16a34a;
}
.simple-calc__status.err {
  color: #e74c3c;
}
.simple-calc__or {
  text-align: center;
  margin-top: 22px;
}
.simple-calc__link {
  background: none;
  border: none;
  color: #6b7280;
  font-size: 16px;
  text-decoration: underline;
  cursor: pointer;
  padding: 10px;
}
.simple-calc__link:hover {
  color: #E12821;
}
html.dark .simple-calc__sub {
  color: #aab4c5;
}
html.dark .sc-choice {
  background: #1e1e1e;
  border-color: rgba(255, 255, 255, .16);
  color: #f5f5f5;
}
html.dark .simple-calc__input {
  background: #1e1e1e;
  border-color: rgba(255, 255, 255, .16);
  color: #f5f5f5;
}
html.dark .simple-calc__link {
  color: #aab4c5;
}
.cat-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 44px 20px;
}
.cat-empty h3 {
  /* Гарнитуру задаём явно: без неё заголовок доставался голому `h3` из v1
     и набирался Montserrat. Oswald — как у `.v2-empty__title`. */
  font-family: var(--type-display);
  font-size: 21px;
  margin: 0 0 10px;
}
.cat-empty p {
  font-family: var(--type-body);
  color: #6b7280;
  font-size: 16px;
  max-width: 520px;
  margin: 0 auto 20px;
  line-height: 1.55;
}
.cat-empty__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}
html.dark .cat-empty p {
  color: #aab4c5;
}
.contact-ok {
  display: flex;
  flex-direction: column;
  gap: 8px;
  text-align: left;
}
.contact-ok strong {
  font-size: 17px;
}
.contact-ok__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
}
.hp-route__step {
  position: relative;
  display: block;
  background: #fff;
  border: 1px solid #eceef3;
  border-radius: 16px;
  padding: 26px 22px 22px;
  text-decoration: none;
  color: inherit;
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.hp-route__step:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 28px rgba(0, 0, 0, .1);
  border-color: #E12821;
}
.hp-route__n {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #E12821;
  color: #fff;
  font-size: 19px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
}
.hp-route__step h3 {
  margin: 0 0 8px;
  font-size: 19px;
}
.hp-route__step p {
  margin: 0 0 14px;
  color: #6b7280;
  font-size: 15px;
  line-height: 1.55;
}
.hp-route__go {
  color: #E12821;
  font-weight: 700;
  font-size: 15px;
}
html.dark .hp-route__head p {
  color: #aab4c5;
}
html.dark .hp-route__step {
  background: #1e1e1e;
  border-color: rgba(255, 255, 255, .08);
}
html.dark .hp-route__step h3 {
  color: #f5f5f5;
}
html.dark .hp-route__step p {
  color: #aab4c5;
}
.task-filter {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px 6px;
}
.task-filter__head {
  font-size: 19px;
  font-weight: 700;
  margin-bottom: 12px;
}
.task-filter__row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.task-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 18px;
  border: 2px solid #d8dbe2;
  background: #fff;
  border-radius: 12px;
  font-size: 15px;
  cursor: pointer;
  min-height: 50px;
  text-align: left;
}
.task-btn i {
  font-size: 18px;
  color: #E12821;
}
.task-btn:hover {
  border-color: #E12821;
}
/* Только насыщенность: заливка/рамка/цвет тут были красными,
   их перебивает body.v2 .v2-chip.active, и по правилу красного
   активному чипу полагается асфальт. */
.task-btn.active {
  font-weight: 700;
}
.task-btn.active i {
  color: #fff;
}
.task-filter__more {
  margin-top: 12px;
  background: none;
  border: none;
  color: #6b7280;
  text-decoration: underline;
  font-size: 15px;
  cursor: pointer;
  padding: 8px 0;
}
.task-filter__more:hover {
  color: #E12821;
}
html.dark .task-btn {
  background: #1e1e1e;
  border-color: rgba(255, 255, 255, .16);
  color: #f5f5f5;
}
html.dark .task-filter__more {
  color: #aab4c5;
}

@media (max-width: 640px) {
  .task-btn {
    flex: 1 1 100%;
    font-size: 15px;
  }
}
.summary-plain {
  margin: 10px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, .75);
}

/* ============================================================================
   4. ОСНОВАНИЕ СТРАНИЦЫ v2
   Включается классом .v2 на <body> — только на переехавших страницах.
   ============================================================================ */
body.v2 {
  background: var(--v2-page);
  color: var(--v2-text);
  font-family: var(--type-body);
  font-size: var(--fs-15);
  line-height: 1.6;
}

/* v1 держит `html.dark body{background:#121212}` — по специфичности (0,1,2)
   это сильнее, чем `body.v2` (0,1,1), и тёмная страница уезжала в v1-серый.
   Пока оба файла живут рядом, перебиваем явно; на шаге 7 правило уйдёт
   вместе со style.css. */
html.dark body.v2 {
  background: var(--v2-page);
  color: var(--v2-text);
}

body.v2 .v2-wrap {
  max-width: var(--v2-grid-max);
  margin: 0 auto;
  padding: 0 var(--v2-gutter);
}

/* Заголовки страницы — Oswald капсом, с трекингом и разрядкой слов:
   сжатый шрифт съедает межсловные пробелы на кириллице. */
body.v2 .v2-page-title {
  font: var(--v2-page-title);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0;
}

body.v2 .v2-section-title {
  font: var(--v2-section);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0;
}

/* Моно-ярлык капсом — деталь, которая переводит интерфейс из «сайта»
   в «документ». */
body.v2 .v2-label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--v2-text-label);
}

/* Служебная линейка раздела: индекс + название + справка справа */
body.v2 .v2-rule {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding-bottom: 10px;
  border-bottom: var(--rule-heavy);
}

body.v2 .v2-rule__index {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  color: var(--signal-500);
}

body.v2 .v2-rule__title {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--v2-text);
}

body.v2 .v2-rule__aside {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  color: var(--v2-text-label);
  margin-left: auto;
}

/* ============================================================================
   5. ШАПКА v2 (partials/navbar-v2.html)
   Тёмная, асфальтовая. ID элементов те же, что в v1 — на них завязаны
   темизация, язык, авторизация, избранное и мобильная шторка в common.js.
   ============================================================================ */
body.v2 .v2-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--surface-inverse);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

body.v2 .v2-nav__inner {
  max-width: var(--v2-grid-max);
  margin: 0 auto;
  padding: 0 var(--v2-gutter);
  height: 78px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

/* --- Логотип: «CM» стоит на отрезке маршрута с тремя узлами -------------- */
body.v2 .v2-logo {
  display: flex;
  align-items: center;
  gap: 14px;
  text-decoration: none;
  flex-shrink: 0;
}

body.v2 .v2-logo__mark {
  position: relative;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  display: block;
}

body.v2 .v2-logo__cm {
  position: absolute;
  inset: 0 0 auto 0;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--type-display);
  font-weight: 700;
  font-size: 27px;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--on-inverse);
}

body.v2 .v2-logo__rail {
  position: absolute;
  top: 34px;
  left: 0;
  right: 0;
  height: var(--rule-rail);
  background: rgba(255, 255, 255, 0.28);
}

body.v2 .v2-logo__node {
  position: absolute;
  top: 33px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
}

.v2-logo__node--1 { left: calc(18% - 2.5px); background: rgba(255, 255, 255, 0.45); }
.v2-logo__node--2 { left: calc(50% - 2.5px); background: var(--ink-500); }
.v2-logo__node--3 { left: calc(82% - 2.5px); background: var(--signal-500); }

body.v2 .v2-logo__text {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

body.v2 .v2-logo__name {
  font-family: var(--type-display);
  font-weight: 700;
  font-size: 21px;
  line-height: 1;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--on-inverse);
}

body.v2 .v2-logo__sub {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.5);
}

/* --- Пункты меню: моно капсом, активный подчёркнут сигнальным ------------ */
body.v2 .v2-nav .nav-links {
  display: flex;
  align-items: center;
  gap: 30px;
  list-style: none;
  margin: 0;
  padding: 0;
}

body.v2 .v2-nav .nav-links a {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  padding-bottom: 3px;
  color: rgba(255, 255, 255, 0.55);
  border-bottom: 2px solid transparent;
  transition: color .15s ease, border-color .15s ease;
}

.v2-nav .nav-links a:hover { color: var(--on-inverse); }

body.v2 .v2-nav .nav-links a.active {
  color: var(--on-inverse);
  border-bottom-color: var(--signal-500);
}

body.v2 .v2-nav__right {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* Кабинет — secondary на тёмном: не красный, не конкурирует с primary CTA */
body.v2 .v2-nav .nav-auth-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--v2-btn-h-sm);
  padding: 0 18px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: var(--radius-4);
  background: transparent;
  color: var(--on-inverse);
  text-decoration: none;
  font-family: var(--type-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  white-space: nowrap;
}

.v2-nav .nav-auth-link:hover { border-color: var(--on-inverse); }

/* Язык, тема, избранное, бургер — единая тёмная кнопка */
body.v2 .v2-nav .lang-toggle,
body.v2 .v2-nav .theme-toggle,
body.v2 .v2-nav .nav-icon-btn,
body.v2 .v2-nav .menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 40px;
  height: 40px;
  padding: 0 10px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: var(--radius-4);
  background: transparent;
  color: var(--on-inverse);
  cursor: pointer;
  font-family: var(--type-mono);
  font-size: 12px;
  letter-spacing: var(--ls-mono-btn);
  text-decoration: none;
  position: relative;
}

body.v2 .v2-nav .menu-toggle {
  flex-direction: column;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0;
  display: none;
}

body.v2 .v2-nav .menu-toggle span {
  display: block;
  width: 20px;
  height: 2px;
  background: var(--on-inverse);
}

body.v2 .v2-nav .nav-fav-count {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  /* Счётчик — не действие и не «вы здесь», поэтому не сигнальный красный:
     иначе в шапке появляется третье красное пятно рядом с узлом логотипа. */
  background: var(--ink-500);
  color: #fff;
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums;
  font-size: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Курс — моно, табличные цифры; тихая справка, не акцент */
body.v2 .v2-nav__rate {
  font: var(--v2-label);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.45);
  white-space: nowrap;
}

/* Выпадающий список языка */
.v2-nav .lang-switch { position: relative; }

body.v2 .v2-nav .lang-switch__menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 168px;
  background: var(--surface-inverse);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-4);
  padding: 6px;
  display: flex;
  flex-direction: column;
  z-index: 120;
}

/* Само раскрытие (opacity/transform/visibility) описано один раз выше, у
   .lang-switch__menu, и наследуется сюда: тёмная шапка меняет только вид
   панели, а не то, как она появляется. */

body.v2 .v2-nav .lang-switch__menu button {
  padding: 10px 12px;
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, 0.82);
  text-align: left;
  cursor: pointer;
  font-family: var(--type-body);
  font-size: var(--fs-15);
  border-radius: var(--radius-2);
}

.v2-nav .lang-switch__menu button:hover { background: rgba(255, 255, 255, 0.08); }

/* ============================================================================
   6. МОБИЛЬНАЯ ШТОРКА v2
   Брейкпойнт 920px — тот же, что в v1, и на него завязан
   initMobileNavControls (переносит язык/тему/вход в подвал шторки).
   ============================================================================ */
@media (max-width: 920px) {
  .v2-nav__inner { height: 66px; gap: 12px; }
  .v2-nav .nav-links { display: none; }
  .v2-nav .menu-toggle { display: flex; }
  .v2-nav__rate { display: none; }
  .v2-logo__sub { display: none; }
  .v2-logo__mark { width: 38px; height: 38px; }
  .v2-logo__cm { height: 29px; font-size: 23px; }
  .v2-logo__rail { top: 29px; }
  .v2-logo__node { top: 28px; }
  .v2-logo__name { font-size: 18px; }
}

body.v2 .nav-drawer-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(8, 9, 11, 0.72);
  opacity: 0;
  visibility: hidden;
  transition: opacity .15s ease, visibility .15s ease;
}

body.v2 .nav-drawer-overlay.active { opacity: 1; visibility: visible; }

body.v2 .nav-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 201;
  width: min(86vw, 340px);
  background: var(--surface-inverse);
  border-left: 1px solid rgba(255, 255, 255, 0.12);
  transform: translateX(100%);
  transition: transform .28s cubic-bezier(.4, 0, .2, 1);
  display: flex;
  flex-direction: column;
}

body.v2 .nav-drawer.active { transform: translateX(0); }

body.v2 .nav-drawer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  flex-shrink: 0;
}

body.v2 .nav-drawer__logo {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  color: rgba(255, 255, 255, 0.45);
}

body.v2 .nav-drawer__close {
  width: 38px;
  height: 38px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: var(--radius-4);
  background: transparent;
  color: var(--on-inverse);
  cursor: pointer;
  font-size: 15px;
}

body.v2 .nav-drawer__nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 10px;
  overflow-y: auto;
}

body.v2 .nav-drawer__nav a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 12px;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
}

body.v2 .nav-drawer__nav a.active { color: var(--signal-500); }

body.v2 .nav-drawer__footer {
  padding: 16px 20px 22px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

body.v2 .nav-drawer__phone {
  flex: 1 1 100%;
  order: 9;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: var(--v2-btn-h);
  background: var(--signal-fill);
  color: var(--on-signal);
  text-decoration: none;
  border-radius: var(--radius-4);
  font-family: var(--type-mono);
  font-size: 13px;
  letter-spacing: var(--ls-mono-btn);
  font-variant-numeric: tabular-nums;
}

/* ============================================================================
   7. ФУТЕР v2 (partials/footer-v2.html)
   По верхней кромке — волосяная рейка с двумя конечными узлами:
   ХОРГОС ● ── ● АЛМАТЫ. Тихая подпись, не декор.
   ============================================================================ */
body.v2 .v2-footer {
  background: var(--surface-inverse);
  color: var(--on-inverse);
}

body.v2 .v2-footer__inner {
  max-width: var(--v2-grid-max);
  margin: 0 auto;
  padding: 0 var(--v2-gutter);
}

/* --- Рейка «Хоргос — Алматы» -------------------------------------------- */
body.v2 .v2-rail {
  display: flex;
  align-items: flex-start;
  width: 100%;
  padding-top: 28px;
}

body.v2 .v2-rail__seg {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
}

body.v2 .v2-rail__line {
  display: flex;
  align-items: center;
  width: 100%;
  height: var(--rail-node-active);
}

body.v2 .v2-rail__line::before,
body.v2 .v2-rail__line::after {
  content: "";
  flex: 1;
  height: var(--rule-rail);
  background: rgba(255, 255, 255, 0.22);
}

body.v2 .v2-rail__seg:first-child .v2-rail__line::before,
.v2-rail__seg:last-child .v2-rail__line::after { background: transparent; }

body.v2 .v2-rail__node {
  width: var(--rail-node);
  height: var(--rail-node);
  border-radius: 50%;
  box-sizing: border-box;
  flex-shrink: 0;
  border: 2px solid rgba(255, 255, 255, 0.45);
  background: transparent;
}

body.v2 .v2-rail__label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  margin-top: 8px;
}

body.v2 .v2-footer__grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 32px;
  padding: 48px 0;
}

body.v2 .v2-footer__about {
  font: var(--v2-body);
  color: rgba(255, 255, 255, 0.5);
  max-width: 34ch;
  margin: 18px 0 0;
}

body.v2 .v2-footer__col-title {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  padding-bottom: 12px;
  border-bottom: var(--rule-hair-dark);
  margin: 0 0 14px;
}

body.v2 .v2-footer__list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}

body.v2 .v2-footer__list a,
body.v2 .v2-footer__list span {
  font: var(--v2-body);
  font-size: 14px;
  color: rgba(255, 255, 255, 0.66);
  text-decoration: none;
}

.v2-footer__list a:hover { color: var(--on-inverse); }

body.v2 .v2-footer__bottom {
  border-top: var(--rule-hair-dark);
  padding: 18px 0 28px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}

body.v2 .v2-footer__bottom span,
body.v2 .v2-footer__bottom a {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  color: rgba(255, 255, 255, 0.35);
  text-decoration: none;
}

.v2-footer__bottom a:hover { color: rgba(255, 255, 255, 0.6); }

@media (max-width: 920px) {
  .v2-footer__grid { grid-template-columns: 1fr 1fr; gap: 28px; }
}

@media (max-width: 560px) {
  .v2-footer__grid { grid-template-columns: 1fr; }
}

/* ============================================================================
   8. КАТАЛОГ · сетка
   ОБЯЗАТЕЛЬНО auto-fill / minmax(240px, 1fr). Жёсткие колонки дают дефект,
   который уже дважды чинили в макете: карточка сжимается уже своего подвала
   и цена ломается на две строки.
   ============================================================================ */
body.v2 .v2-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
  margin-top: 32px;
}

/* ============================================================================
   9. КАТАЛОГ · паспорт единицы техники (VehiclePassport)
   Порядок сверху вниз: фото 4:3 с тегами локации/наличия по нижней кромке →
   тяжёлая линейка → название → ряды данных → тяжёлая линейка → цена + кнопка.
   Теней нет; ховер утемняет рамку.
   ============================================================================ */
body.v2 .vp {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--asphalt-200);
  border-radius: var(--radius-2);
  text-decoration: none;
  color: var(--asphalt-900);
  transition: transform .18s ease, border-color .18s ease;
  position: relative;
}

/* Растянутая ссылка. Карточка — <article>, а не <a>: в подвале стоят две
   настоящие кнопки, а вложенные <a> невалидны. Переход на страницу техники
   даёт ::after заголовка, перекрывающий карточку целиком, — для мыши всё
   осталось как было, а для клавиатуры и скринридера в табуляции теперь одна
   осмысленная ссылка с названием техники вместо ссылки на всю карточку. */
body.v2 .vp__link {
  color: inherit;
  text-decoration: none;
}

body.v2 .vp__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* Всё, что кликается само, живёт над перекрытием. */
body.v2 .vp__fav,
body.v2 .vp__actions { position: relative; z-index: 1; }

/* Фокус видно на всей карточке, а не на строке заголовка: перекрытие
   растянуто на неё целиком, и обводка вокруг текста показывала бы не ту
   область, которая на самом деле сработает. */
body.v2 .vp__link:focus-visible { outline: none; }
body.v2 .vp:has(.vp__link:focus-visible) { outline: 2px solid var(--asphalt-900); outline-offset: 2px; }

/* Подъём на 2px — ровно столько, чтобы карточка отзывалась на курсор, и не
   столько, чтобы сетка каталога ходила ходуном. Тот же жест, что у
   .hp-route__step, только тише: там карточек шесть, здесь — вся выдача. */
.vp:hover { border-color: var(--asphalt-900); transform: translateY(-2px); }

body.v2 .vp__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--asphalt-100);
}

body.v2 .vp__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Теги по нижней кромке фото: локация слева, наличие справа */
body.v2 .vp__tag {
  position: absolute;
  bottom: 0;
  display: flex;
  align-items: center;
  height: 26px;
  padding: 0 12px;
  background: var(--surface-inverse);
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  white-space: nowrap;
}

.vp__tag--place { left: 0; color: var(--on-inverse); }
.vp__tag--avail { right: 0; }

/* Один цвет — один смысл: «в наличии» это закрытый успешный статус (clear),
   «под заказ» — ещё не закрыто (hazard). Красный здесь не участвует. */
.vp__tag--in_stock { color: var(--clear-400); }
.vp__tag--on_order { color: var(--hazard-400); }
.vp__tag--in_transit { color: var(--hazard-400); }
.vp__tag--out_of_stock { color: rgba(255, 255, 255, 0.55); }

/* Избранное — функциональность v1, сохранена. Не сигнальный цвет:
   красный зарезервирован за действием и активным узлом маршрута. */
body.v2 .vp__fav {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--radius-4);
  background: rgba(22, 24, 28, 0.62);
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  padding: 0;
}

.vp__fav:hover { background: rgba(22, 24, 28, 0.85); }
.vp__fav.active { color: var(--hazard-400); }

body.v2 .vp__head {
  padding: 16px 18px 0;
  border-top: var(--rule-heavy);
}

body.v2 .vp__title {
  font-family: var(--type-display);
  font-weight: 600;
  font-size: var(--fs-20);
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  word-spacing: 0.06em;
  margin: 0;
}

body.v2 .vp__sub {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin-top: 5px;
}

.vp__rows { padding: 12px 18px 0; }

/* Ряд данных — примитив всей системы: моно-ярлык слева, табличное значение
   справа. Значения выравниваются в колонку по всей сетке, и карточки
   читаются как строки одного каталога-манифеста. */
body.v2 .vp__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 0;
  border-bottom: var(--rule-hair);
}

body.v2 .vp__row-label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

body.v2 .vp__row-value {
  font: var(--v2-data);
  font-variant-numeric: tabular-nums;
  color: var(--asphalt-900);
  text-align: right;
  white-space: nowrap;
}

body.v2 .vp__foot {
  margin-top: auto;
  padding: 16px 18px 18px;
  border-top: var(--rule-heavy);
}

body.v2 .vp__price-label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  white-space: nowrap;
}

/* Цена — главное число карточки, поэтому nowrap: при сжатии колонки
   валюта не должна уезжать на вторую строку. */
body.v2 .vp__price {
  font: var(--v2-price);
  font-size: 22px;
  font-variant-numeric: tabular-nums;
  margin: 4px 0 14px;
  white-space: nowrap;
}

/* Две кнопки в столбик, а не в ряд. В ряд они помещались бы только на
   широкой карточке: сетка держит колонку от 240px, и «ПОЛУЧИТЬ КП» рядом с
   «РАСЧЁТ ПОД КЛЮЧ» на такой ширине рвёт nowrap. Столбик заодно повторяет
   порядок на странице техники — КП сверху, разбор цены под ним. */
body.v2 .vp__actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

body.v2 .vp__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--v2-btn-h-sm);
  padding: 10px 12px;
  font-family: var(--type-mono);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-4);
  white-space: nowrap;
  background: transparent;
  color: var(--asphalt-900);
  border: 1.5px solid var(--asphalt-900);
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}

/* Заливка на КАЖДОЙ карточке сетки — намеренное исключение из правила
   «один сигнальный красный в кадре», принятое ради конверсии и записанное
   в guidelines/redesign-plan.md §1.1. В кадре каталога таких заливок
   бывает 4–8 одновременно, и это ожидаемое поведение, а не регрессия:
   следующий замер не должен считать её нарушением.
   Границы исключения — только `.vp__cta--kp` и только в сетке карточек.
   На остальных экранах правило продолжает действовать как прежде. */
body.v2 .vp__cta--kp {
  background: var(--signal-fill);
  color: var(--on-signal);
  border-color: var(--signal-fill);
}

/* Ховер повешен на саму кнопку, а не на карточку. Пока кнопка была одна,
   `.vp:hover .vp__cta` читалось как «карточка кликабельна»; с двумя
   кнопками тот же селектор подсвечивал бы обе разом и показывал бы не то,
   что сработает по клику. Отклик карточки на курсор остался — рамка и
   подъём на 2px выше. */
.vp__cta:hover { background: var(--asphalt-900); color: var(--paper); border-color: var(--asphalt-900); }
.vp__cta--kp:hover { background: var(--signal-fill-hover); border-color: var(--signal-fill-hover); color: var(--on-signal); }

/* Избранное (favorites.js) осталось на прежней карточке: там .vp — это по-
   прежнему одна ссылка целиком, а .vp__cta внутри неё — <span>, не кнопка.
   Разводить КП по избранному в эту задачу не входило, поэтому прежний жест
   «наведение на карточку заливает её единственную кнопку» сохраняется ровно
   для той формы. Селектор `a.vp` не заденет карточку каталога — она теперь
   <article>. Когда избранное переедет на две кнопки, правило уйдёт вместе с
   последней карточкой-ссылкой. */
a.vp:hover .vp__cta { background: var(--asphalt-900); color: var(--paper); }

/* ============================================================================
   10. КАТАЛОГ · фильтры
   Чипы задач: активный — ЗАЛИТЫЙ АСФАЛЬТ, не красный. Иначе в сетке
   окажется несколько красных пятен и правило «максимум два signal-500
   в кадре» рассыплется.
   ============================================================================ */
body.v2 .v2-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

body.v2 .v2-chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 46px;
  padding: 0 16px;
  cursor: pointer;
  border: 1px solid var(--asphalt-200);
  background: var(--paper);
  color: var(--asphalt-900);
  border-radius: var(--radius-4);
  font-family: var(--type-body);
  font-size: var(--fs-15);
  text-align: left;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.v2-chip:hover { border-color: var(--asphalt-900); }

body.v2 .v2-chip.active {
  background: var(--asphalt-900);
  border-color: var(--asphalt-900);
  color: var(--paper);
}

/* Счётчик моно с табличными цифрами — ряд не «прыгает» при смене фильтра. */
body.v2 .v2-chip__count {
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  color: var(--asphalt-400);
}

.v2-chip.active .v2-chip__count { color: rgba(255, 255, 255, 0.55); }

/* --- Ведомость уточняющих фильтров: моно-ярлык над контролом ------------- */
body.v2 .v2-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 16px;
  margin-top: 24px;
  padding-top: 24px;
  border-top: var(--rule-hair);
}

.v2-field { display: block; }

body.v2 .v2-field__label {
  display: block;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin-bottom: 7px;
}

body.v2 .v2-field select,
body.v2 .v2-field input {
  width: 100%;
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  background: var(--paper);
  color: var(--asphalt-900);
  padding: 11px 12px;
  font: var(--v2-body);
  outline: none;
  cursor: pointer;
}

.v2-field input { cursor: text; }
body.v2 .v2-field select:focus,
.v2-field input:focus { border-color: var(--asphalt-900); }

/* Текстовая кнопка-действие (сброс, «показать уточнения») */
body.v2 .v2-link-btn {
  background: none;
  border: 0;
  padding: 10px 0;
  color: var(--asphalt-500);
  font-family: var(--type-mono);
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.v2-link-btn:hover { color: var(--signal-500); }

/* ============================================================================
   11. КАТАЛОГ · пустое состояние
   ============================================================================ */
body.v2 .v2-empty {
  grid-column: 1 / -1;
  padding: 56px 24px;
  background: var(--paper);
  border: var(--rule-hair);
  text-align: center;
}

body.v2 .v2-empty__title {
  font: var(--v2-section);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 10px;
}

body.v2 .v2-empty p {
  font: var(--v2-body-lg);
  color: var(--asphalt-500);
  max-width: 52ch;
  margin: 0 auto 24px;
}

body.v2 .v2-empty__actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
}

/* ============================================================================
   12. КНОПКИ v2
   Primary — один на экран. Формулировка = результат, не действие.
   ============================================================================ */
body.v2 .v2-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--v2-btn-h);
  padding: 0 24px;
  border-radius: var(--radius-4);
  font-family: var(--type-mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  border: 1.5px solid transparent;
  white-space: nowrap;
}

body.v2 .v2-btn--primary {
  background: var(--signal-fill);
  color: var(--on-signal);
  border-color: var(--signal-fill);
}

.v2-btn--primary:hover { background: var(--signal-fill-hover); border-color: var(--signal-fill-hover); }

body.v2 .v2-btn--secondary {
  background: transparent;
  color: var(--asphalt-900);
  border-color: var(--asphalt-900);
}

.v2-btn--secondary:hover { background: var(--asphalt-900); color: var(--paper); }

/* Пульсирующий ореол у единственного CTA экрана — тот же жест, что у
   активного узла рейки (§25), и сделан теми же средствами: расходящееся
   кольцо в ::after, сама кнопка не движется и не мигает. Заливка, текст и
   рамка при любых условиях остаются на месте, поэтому без анимации
   (prefers-reduced-motion, старый браузер) кнопка выглядит ровно как
   обычный primary — это не декор, который что-то держит.

   Отличие от узла рейки одно: у узла есть статичный ореол 4px, от кромки
   которого кольцо и расходится. У кнопки статичного ореола нет — иначе
   вокруг заливки появилось бы постоянное красное гало 4px, а это второе
   красное пятно там, где по правилу разрешено одно. Кольцо стартует от
   самой кромки кнопки.

   Ставится вручную классом, а не на все .v2-btn--primary: primary есть на
   каждой странице, а «дышать» должен ровно один CTA — тот, на который
   страница действительно ведёт. */
body.v2 .v2-btn--pulse { position: relative; }

body.v2 .v2-btn--pulse::after {
  content: "";
  position: absolute;
  inset: -1.5px;                 /* поверх рамки: кольцо идёт от края заливки */
  border-radius: var(--radius-4);
  pointer-events: none;
  animation: v2-btn-pulse 2.2s ease-out infinite;
}

/* Стартовая непрозрачность 0 — как у узла рейки: в момент перезапуска цикла
   кольцо не накладывается само на себя и кромка не темнеет раз в 2,2 с. */
@keyframes v2-btn-pulse {
  0%   { box-shadow: 0 0 0 0 var(--signal-halo);  opacity: 0; }
  20%  { opacity: 1; }
  100% { box-shadow: 0 0 0 12px var(--signal-halo); opacity: 0; }
}

/* ============================================================================
   13. ШАПКА СТРАНИЦЫ КАТАЛОГА
   ============================================================================ */
/* Только вертикальные отступы: шапка страницы одновременно .v2-wrap,
   а сокращённая запись padding обнулила бы боковой жёлоб и прижала
   заголовок к краю окна. */
body.v2 .v2-page-head {
  padding-top: 40px;
  padding-bottom: 8px;
}

.v2-page-head__title { margin: 10px 0 6px; }

body.v2 .v2-page-head__sub {
  font: var(--v2-body-lg);
  color: var(--asphalt-500);
  margin: 0;
}

@media (max-width: 560px) {
  .v2-page-head { padding-top: 28px; }
  body.v2 .v2-page-title { font-size: var(--fs-28); }
  .v2-chip { flex: 1 1 100%; }
}

/* ============================================================================
   14. CONTACT DIAL (v2)
   Один свёрнутый круг, раскрывается вверх. НИКОГДА не красный: сигнальный
   красный зарезервирован за primary CTA и активным узлом маршрута, иначе
   правило «максимум два signal-500 в кадре» рассыпается.

   Позиция — слева внизу, а не справа, как в макете: справа на проде висит
   чат tawk.to и круг лёг бы прямо на него. Радиус 999 здесь разрешён —
   контакт-виджет и статус-чипы единственные исключения из шкалы 0/2/4/6.
   ============================================================================ */
body.v2 .v2-dial-wrap {
  position: fixed;
  left: 24px;
  bottom: 24px;
  z-index: 9998;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

body.v2 .v2-dial__items {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

body.v2 .v2-dial__items[hidden] { display: none; }

body.v2 .v2-dial__item {
  display: flex;
  align-items: center;
  gap: 12px;
  height: 46px;
  padding: 0 20px 0 16px;
  background: var(--surface-inverse);
  color: var(--on-inverse);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 999px;
  font-family: var(--type-mono);
  font-size: 12px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}

body.v2 .v2-dial__item:hover { border-color: rgba(255, 255, 255, .38); }

body.v2 .v2-dial__row {
  display: flex;
  align-items: center;
  gap: 10px;
}

body.v2 .v2-dial {
  width: var(--v2-dial);
  height: var(--v2-dial);
  border-radius: 50%;
  background: var(--surface-inverse);
  color: var(--on-inverse);
  border: 1px solid rgba(255, 255, 255, .16);
  cursor: pointer;
  font-size: 19px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

body.v2 .v2-dial:hover { border-color: rgba(255, 255, 255, .4); }

/* Управление размером текста — не из дизайн-системы, но это работающая
   доступность с прода. Держим подчинённым к набору: меньше и тише круга. */
body.v2 .v2-dial__font {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--paper);
  color: var(--asphalt-900);
  border: 1px solid var(--asphalt-200);
  cursor: pointer;
  font-family: var(--type-mono);
  font-size: 15px;
  font-weight: 600;
  flex-shrink: 0;
}

body.v2 .v2-dial__font sup { font-size: 10px; }
body.v2 .v2-dial__font:hover { border-color: var(--asphalt-900); }

/* Правило из v1, обязательное к сохранению: при открытой шторке плавающие
   контакты и чат прячутся, иначе лежат поверх пунктов меню. */
html.cm-drawer-open body.v2 .v2-dial-wrap { visibility: hidden; opacity: 0; }

/* Виджет не раздуваем вместе со страницей при увеличенном тексте —
   он и так крупный, а иначе перекрывает контент. */
html.cm-font-lg body.v2 .v2-dial-wrap { zoom: 0.87; }
html.cm-font-xl body.v2 .v2-dial-wrap { zoom: 0.77; }

@media (max-width: 640px) {
  body.v2 .v2-dial-wrap { left: 12px; bottom: 12px; }
  body.v2 .v2-dial { width: 48px; height: 48px; font-size: 17px; }
  body.v2 .v2-dial__font { width: 40px; height: 40px; font-size: 14px; }
  body.v2 .v2-dial__item { height: 42px; font-size: 11px; }
}

/* ============================================================================
   15. ПЕРЕБИВАЕМ id-ПРАВИЛА v1
   Класс не бьёт id ни при какой вложенности, поэтому девять правил вида
   `html.dark #foo` в style.css перебивают любое v2-правило на классах.
   Три из них целятся в элементы, которые уже отрисованы на v2-страницах
   (шапка и ведомость фильтров), — их нужно перекрыть на том же уровне.

   `body.v2 #foo` весит столько же, сколько `html.dark #foo`, а style-v2.css
   подключён вторым — ничья решается в пользу v2. Правила уйдут вместе
   со style.css на шаге 7.
   ============================================================================ */

/* Поиск в ведомости фильтров: v1 красил его в #1f1f1f с рамкой #333. */
body.v2 #search {
  background: var(--paper);
  border: var(--rule-hair);
  color: var(--asphalt-900);
}

body.v2 #search:focus { border-color: var(--asphalt-900); }

/* Переключатель темы: в v1 иконка в тёмной теме золотая (#ffd700) —
   это язык v1. В v2 управляющие элементы шапки одного тона с ней. */
body.v2 #themeToggle { color: var(--on-inverse); }

/* Переключатель языка — только обёртка для позиционирования выпадающего
   списка; v1 рисовал ей фон и рамку, из-за чего в шапке появлялась коробка. */
body.v2 #langSwitch {
  background: transparent;
  border: 0;
}

/* ============================================================================
   16. КАРТОЧКА ТЕХНИКИ (шаг 2)
   Паспорт единицы: галерея слева, спецификация и одно действие — справа.
   Рейка «путь этой единицы» НЕ переносится: она требует Vehicle.route_stage,
   которого в модели нет, а выводить её эвристикой из availability — врать
   (см. backend-requirements-v2.md §3).
   ============================================================================ */
body.v2 .v2-crumbs {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-top: 28px;
  padding-bottom: 18px;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

body.v2 .v2-crumbs a { color: var(--asphalt-400); text-decoration: none; }
body.v2 .v2-crumbs a:hover { color: var(--asphalt-900); }
body.v2 .v2-crumbs__current { color: var(--asphalt-900); }

body.v2 .v2-product {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) 420px;
  gap: 32px;
  align-items: start;
}

/* --- Галерея ------------------------------------------------------------ */
body.v2 .v2-shot {
  position: relative;
  border: var(--rule-hair);
  background: var(--paper);
}

body.v2 .v2-shot img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  cursor: zoom-in;
}

/* Теги по нижней кромке — те же, что в паспорте каталога */
body.v2 .v2-shot .vp__tag { height: 30px; padding: 0 14px; }

body.v2 .v2-thumbs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-top: 8px;
}

body.v2 .v2-thumbs img {
  width: 100%;
  height: 78px;
  object-fit: cover;
  display: block;
  cursor: pointer;
  border: 2px solid transparent;
  opacity: .72;
}

body.v2 .v2-thumbs img.active { border-color: var(--asphalt-900); opacity: 1; }

/* --- Панель (комплектация, «как проходит покупка») ---------------------- */
body.v2 .v2-panel {
  background: var(--paper);
  border: var(--rule-hair);
  margin-top: 28px;
}

body.v2 .v2-panel--pad { padding: 26px; margin-top: 0; }

body.v2 .v2-panel__head {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-900);
  padding: 24px 26px 12px;
  border-bottom: var(--rule-heavy);
  margin-bottom: 16px;
}

body.v2 .v2-panel--pad .v2-panel__head { padding: 0 0 12px; }

body.v2 .v2-panel__body {
  font: var(--v2-body-lg);
  color: var(--asphalt-500);
  padding: 0 26px 24px;
  margin: 0;
  white-space: pre-line;
}

/* --- Правая колонка ----------------------------------------------------- */
body.v2 .v2-product__aside {
  position: sticky;
  top: 102px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

body.v2 .v2-product__meta {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin-bottom: 8px;
}

body.v2 .v2-product__titlerow {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

body.v2 .v2-product__title {
  font-family: var(--type-display);
  font-weight: 700;
  font-size: var(--fs-36);
  line-height: 1.05;
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 22px;
}

body.v2 .v2-icon-btn {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--asphalt-200);
  border-radius: var(--radius-4);
  background: var(--paper);
  color: var(--asphalt-900);
  cursor: pointer;
  font-size: 15px;
}

body.v2 .v2-icon-btn:hover { border-color: var(--asphalt-900); }
body.v2 .v2-icon-btn.active { color: var(--hazard-400); }

body.v2 .v2-owner-badge {
  display: inline-block;
  margin-bottom: 12px;
  padding: 4px 10px;
  background: var(--ink-tint);
  color: var(--ink-700);
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
}

body.v2 .v2-product__rows { padding-top: 4px; border-top: var(--rule-heavy); }

body.v2 .v2-product__pricebox {
  margin-top: 22px;
  padding-top: 18px;
  border-top: var(--rule-heavy);
}

body.v2 .v2-product__price-label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

body.v2 .v2-product__price {
  font: var(--v2-price);
  font-variant-numeric: tabular-nums;
  color: var(--asphalt-900);
  margin: 6px 0 4px;
}

body.v2 .v2-product__price-note {
  font: var(--v2-small);
  color: var(--asphalt-400);
  margin-bottom: 18px;
}

body.v2 .v2-btn--block { display: flex; width: 100%; }
body.v2 .v2-btn--block + .v2-btn--block { margin-top: 10px; }

/* --- Ведомость «как проходит покупка» ----------------------------------- */
body.v2 .v2-ledger__row { padding: 13px 0; border-bottom: var(--rule-hair); }
body.v2 .v2-ledger__row:last-child { border-bottom: 0; }

body.v2 .v2-ledger__t {
  font: var(--v2-body);
  font-weight: 600;
  color: var(--asphalt-900);
  margin-bottom: 3px;
}

body.v2 .v2-ledger__d { font: var(--v2-small); color: var(--asphalt-500); }

@media (max-width: 1000px) {
  body.v2 .v2-product { grid-template-columns: 1fr; }
  body.v2 .v2-product__aside { position: static; }
}

@media (max-width: 560px) {
  body.v2 .v2-product__title { font-size: var(--fs-28); }
  body.v2 .v2-panel--pad { padding: 20px; }
  body.v2 .v2-thumbs img { height: 60px; }
}

/* ============================================================================
   17. КАЛЬКУЛЯТОР (шаг 3)
   Разбивка стоимости И ЕСТЬ маршрут: каждая группа расходов стоит в той
   точке пути, где деньги реально уходят. Источник: CostBreakdown.jsx +
   RouteRailVertical. Формулы не тронуты — переносится только подача.

   Узлы рейки нарисованы состоянием `done` (ink-700), как в CostBreakdown:
   это точки расхода, а не прогресс конкретной сделки, поэтому здесь нет
   зависимости от Vehicle.route_stage и нет активного красного узла.
   ============================================================================ */

/* --- Панель разбивки ----------------------------------------------------- */
body.v2 .v2-breakdown {
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  padding: 28px;
}

/* Секции внутри рейки — не карточки: одна панель, пять групп. */
body.v2 .v2-breakdown .calc-card {
  background: transparent;
  color: var(--asphalt-900);
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
}

/* --- Сегмент рейки: узел + линия слева, содержимое справа ---------------- */
body.v2 .v2-railv {
  display: grid;
  grid-template-columns: var(--rail-node-active) 1fr;
  column-gap: 18px;
  position: relative;
  padding-bottom: 26px;
}

body.v2 .v2-railv > * { grid-column: 2; min-width: 0; }

body.v2 .v2-railv::before {
  content: '';
  grid-column: 1;
  grid-row: 1;
  width: var(--rail-node-active);
  height: var(--rail-node-active);
  border-radius: 50%;
  background: var(--ink-700);
  margin-top: 1px;
}

body.v2 .v2-railv::after {
  content: '';
  position: absolute;
  left: calc(var(--rail-node-active) / 2 - var(--rule-rail) / 2);
  top: calc(var(--rail-node-active) + 6px);
  bottom: 0;
  width: var(--rule-rail);
  background: var(--ink-700);
}

body.v2 .v2-railv:last-child { padding-bottom: 0; }
body.v2 .v2-railv:last-child::after { content: none; }

/* --- Заголовок группы: индекс · этап маршрута · название раздела --------- */
body.v2 .v2-railv__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 12px;
  /* Заголовок рейки намеренно не выглядит заголовком: размер и начертание
     приравнены к тексту. Гарнитуру правило не задавало — и её решало голое
     `h2` из v1. Наследуем явно; весь видимый текст всё равно лежит в
     дочерних спанах со своим `font: var(--v2-label)`. */
  font-family: inherit;
  font-size: inherit;
  font-weight: 400;
}

/* v1 рисовал номер шага красным кружком — пять таких заливок в кадре
   разносят правило «максимум два signal-500». Номер становится моно-индексом. */
body.v2 .v2-railv__head .hp-calc-step {
  display: inline;
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  color: var(--asphalt-400);
}

body.v2 .v2-railv__label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-900);
}

body.v2 .v2-railv__sub {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

body.v2 .v2-breakdown .calc-hint {
  font: var(--v2-small);
  color: var(--asphalt-500);
  margin: 0 0 10px;
}

body.v2 .v2-breakdown .readonly-note {
  font: var(--v2-small);
  color: var(--asphalt-500);
  opacity: 1;
  margin: 0 0 10px;
}

/* --- Строка расхода: подпись — точечный поводок — сумма ------------------ */
body.v2 .bill {
  margin-top: 0;
  border: 0;
  border-radius: 0;
  background: none;
}

body.v2 .bill h4 {
  padding: 0 0 8px;
  border-bottom: 0;
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

body.v2 .bill ul { padding: 0; }

body.v2 .bill li,
body.v2 .v2-breakdown .summary-line {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  gap: 12px;
  padding: 8px 0;
  border: 0;
  border-bottom: var(--rule-hair);
  border-radius: 0;
  background: none;
  font: var(--v2-body);
  color: var(--asphalt-900);
}

/* Поводок — псевдоэлемент между подписью и суммой: разметку строк
   рисует calculator.js, и его трогать не нужно. */
body.v2 .bill li::before,
body.v2 .v2-breakdown .summary-line::before {
  content: '';
  order: 1;
  flex: 1 1 24px;
  border-bottom: 1px dotted var(--asphalt-200);
  transform: translateY(-4px);
}

body.v2 .bill li > .sum,
body.v2 .v2-breakdown .summary-line strong {
  order: 2;
  font: var(--v2-data);
  font-variant-numeric: tabular-nums;
  color: var(--asphalt-900);
  white-space: nowrap;
}

body.v2 .bill li:last-child { border-bottom: 0; }
body.v2 .bill .muted { opacity: 1; color: var(--asphalt-900); }

/* --- Форма ввода --------------------------------------------------------- */
body.v2 .calc-sections { gap: 24px; }

body.v2 #calcGrid { gap: 32px; }

body.v2 #calcForm > .calc-card,
body.v2 #simpleCalc {
  background: var(--paper);
  color: var(--asphalt-900);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  box-shadow: none;
  padding: 28px;
}

body.v2 #calcForm > .calc-card > .calc-card__title {
  font: var(--v2-card-title);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  margin: 0 0 18px;
}

body.v2 .calc-card label {
  display: block;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin-bottom: 7px;
}

/* Согласия и флажки — обычный текст: капсом моно читается как ярлык поля,
   а здесь это предложение, которое человек должен прочесть. */
body.v2 .calc-card label:has(input[type="checkbox"]) {
  display: flex;
  font: var(--v2-body);
  letter-spacing: normal;
  text-transform: none;
  color: var(--asphalt-900);
}

body.v2 .calc-card input[type="text"],
body.v2 .calc-card input[type="number"],
body.v2 .calc-card input[type="tel"],
body.v2 .calc-card select {
  width: 100%;
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  background: var(--paper);
  color: var(--asphalt-900);
  padding: 11px 12px;
  font: var(--v2-body);
  outline: none;
  box-shadow: none;
}

body.v2 .calc-card input:focus,
body.v2 .calc-card select:focus { border-color: var(--asphalt-900); }

body.v2 .calc-card input[type="checkbox"] { width: auto; }

body.v2 .calc-card hr {
  border: 0;
  border-top: var(--rule-hair);
  margin: 8px 0;
  grid-column: 1 / -1;
}

body.v2 .calc-card h3 {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin: 0 0 8px;
}

body.v2 .calc-card small { font: var(--v2-small); color: var(--asphalt-500); }

/* v1 держал `#calcForm .btn` с id — обычным классом это не перебить. */
body.v2 #calcForm .btn {
  background: transparent;
  color: var(--asphalt-900);
  border: 1.5px solid var(--asphalt-900);
  border-radius: var(--radius-4);
  box-shadow: none;
  font-family: var(--type-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  padding: 0 16px;
  min-height: var(--v2-btn-h-sm);
  white-space: nowrap;
}

body.v2 #calcForm .btn:hover {
  background: var(--asphalt-900);
  color: var(--paper);
  transform: none;
  box-shadow: none;
}

/* --- Итог ---------------------------------------------------------------- */
body.v2 .summary-card {
  background: var(--paper);
  color: var(--asphalt-900);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  box-shadow: none;
  padding: 28px 28px 0;
  overflow: hidden;
  position: sticky;
  top: 102px;
}

body.v2 .summary-card .summary-title {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  border-bottom: 0;
  padding: 0 0 14px;
  margin: 0;
}

body.v2 .summary-card .summary-line {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  gap: 12px;
  padding: 9px 0;
  border: 0;
  border-bottom: var(--rule-hair);
  color: var(--asphalt-900);
  font: var(--v2-body);
}

body.v2 .summary-card .summary-line::before {
  content: '';
  order: 1;
  flex: 1 1 24px;
  border-bottom: 1px dotted var(--asphalt-200);
  transform: translateY(-4px);
}

body.v2 .summary-card .summary-line strong {
  order: 2;
  font: var(--v2-data);
  font-variant-numeric: tabular-nums;
  color: var(--asphalt-900);
  white-space: nowrap;
}

/* Асфальтовая плашка во всю ширину панели — как `margin: 0 -28px` в
   CostBreakdown.jsx. */
body.v2 .v2-total__box {
  margin: 0 -28px;
  background: var(--surface-inverse);
  color: var(--on-inverse);
  padding: 0 28px 28px;
}

/* Шевронная лента — одно из двух мест в системе, где она вообще появляется. */
body.v2 .v2-total__chevron {
  height: 6px;
  margin: 0 -28px 24px;
  background: var(--hazard-chevron);
}

body.v2 .summary-card .summary-total {
  display: block;
  margin: 0;
  padding: 0;
  border-top: 0;
  color: var(--on-inverse);
}

body.v2 .summary-card .summary-total span {
  display: block;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

body.v2 .summary-card .summary-total strong {
  display: block;
  font: var(--v2-price);
  font-variant-numeric: tabular-nums;
  color: var(--on-inverse);
  margin-top: 8px;
  white-space: nowrap;
}

body.v2 .v2-total__secondary {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 8px;
}

body.v2 .summary-card .summary-sub {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  color: rgba(255, 255, 255, 0.5);
  margin: 0;
}

/* Объяснение суммы обычным языком — ключевое поведение бренда,
   поэтому живёт прямо под итогом, а не в сноске. */
body.v2 .summary-card .summary-plain {
  font: var(--v2-body);
  color: rgba(255, 255, 255, 0.62);
  margin: 14px 0 0;
  max-width: 380px;
}

body.v2 .summary-card .summary-actions { margin-top: 20px; }

body.v2 .summary-card .summary-actions .btn {
  min-width: 0;
  background: var(--signal-fill);
  border: 1.5px solid var(--signal-fill);
  border-radius: var(--radius-4);
  box-shadow: none;
}

body.v2 .summary-card .summary-actions .btn:hover {
  background: var(--signal-fill-hover);
  border-color: var(--signal-fill-hover);
  transform: none;
  box-shadow: none;
}

/* --- Простой режим: логика та же, подача — v2 ---------------------------- */
body.v2 #simpleCalc { max-width: 720px; margin: 0 auto 32px; }

body.v2 #simpleCalc .simple-calc__title {
  font: var(--v2-section);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  margin: 0 0 8px;
}

body.v2 #simpleCalc .simple-calc__sub {
  font: var(--v2-body-lg);
  color: var(--asphalt-500);
  margin: 0 0 24px;
}

body.v2 #simpleCalc .simple-calc__label {
  display: block;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin: 22px 0 10px;
}

body.v2 #simpleCalc .sc-choice {
  min-height: 46px;
  padding: 0 16px;
  border: 1px solid var(--asphalt-200);
  border-radius: var(--radius-4);
  background: var(--paper);
  color: var(--asphalt-900);
  font: var(--v2-body);
}

body.v2 #simpleCalc .sc-choice:hover { border-color: var(--asphalt-900); }

/* Выбранный вариант — залитый асфальт, не красный: сигнальный цвет
   зарезервирован за одним действием в кадре. */
body.v2 #simpleCalc .sc-choice.active {
  background: var(--asphalt-900);
  border-color: var(--asphalt-900);
  color: var(--paper);
  font-weight: 400;
}

body.v2 #simpleCalc .simple-calc__input {
  width: 100%;
  min-height: 46px;
  padding: 11px 12px;
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  background: var(--paper);
  color: var(--asphalt-900);
  font: var(--v2-body);
  margin-bottom: 10px;
}

body.v2 #simpleCalc .simple-calc__input:focus { border-color: var(--asphalt-900); outline: none; }

/* Раскрытие подробного расчёта. #calcGrid переключается через display, а его
   анимировать нельзя — поэтому в момент показа вешается одноразовый класс
   (см. initSimpleMode в calculator.js), и блок проявляется, а не возникает.
   Высоту не трогаем: страница и так подпрыгивает на всю высоту формы, и
   тянуть её 180 мс значило бы 180 мс дёргать всё, что ниже.
   Класс тот же, что у «Уточнить» в каталоге: раскрытие свёрнутого блока —
   один жест системы, и вешает его один хелпер (cmRevealToggle). */
body.v2 #calcGrid.is-revealing,
body.v2 .is-revealing { animation: v2-reveal .18s ease-out; }

@keyframes v2-reveal {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

body.v2 #simpleCalc .simple-calc__send {
  display: flex;
  width: 100%;
  min-height: var(--v2-btn-h);
  margin-top: 14px;
  padding: 0 24px;
  background: var(--signal-fill);
  border: 1.5px solid var(--signal-fill);
  border-radius: var(--radius-4);
  box-shadow: none;
  font-family: var(--type-mono);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
}

body.v2 #simpleCalc .simple-calc__send:hover {
  background: var(--signal-fill-hover);
  border-color: var(--signal-fill-hover);
  transform: none;
  box-shadow: none;
}

body.v2 #simpleCalc .simple-calc__status { font: var(--v2-body); margin-top: 12px; }
body.v2 #simpleCalc .simple-calc__status.ok { color: var(--clear-600); }
body.v2 #simpleCalc .simple-calc__status.err { color: var(--signal-500); }

body.v2 #simpleCalc .simple-calc__or {
  text-align: center;
  margin-top: 24px;
  padding-top: 20px;
  border-top: var(--rule-hair);
}

body.v2 #simpleCalc .simple-calc__link {
  color: var(--asphalt-500);
  font-family: var(--type-mono);
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  text-underline-offset: 3px;
}

body.v2 #simpleCalc .simple-calc__link:hover { color: var(--signal-500); }

body.v2 .calc-disclaimer {
  max-width: var(--v2-grid-max);
  margin: 0 auto;
  padding: 0 var(--v2-gutter) 48px;
  font: var(--v2-small);
  color: var(--asphalt-400);
}

@media (max-width: 980px) {
  body.v2 .summary-card { position: static; margin-top: 24px; }
}

@media (max-width: 560px) {
  body.v2 .v2-breakdown,
  body.v2 #calcForm > .calc-card,
  body.v2 #simpleCalc,
  body.v2 .summary-card { padding-left: 20px; padding-right: 20px; }
  body.v2 .summary-card { padding-top: 20px; }
  body.v2 .v2-total__box { margin: 0 -20px; padding: 0 20px 20px; }
  body.v2 .v2-total__chevron { margin: 0 -20px 20px; }
  body.v2 .v2-railv { column-gap: 12px; }
  body.v2 #simpleCalc .simple-calc__title { font-size: var(--fs-20); }
}

/* ============================================================================
   18. ГЛАВНАЯ (шаг 4)
   Hero держит одну мысль, услуги стали ведомостью, кружки 1-2-3-4-5 —
   рейкой, которая идёт сквозь контент. Источники: redesign-plan §4.1, §4.2,
   §4.5; компоненты RouteRail, WorkLedger, SectionRule, VehiclePassport.
   ============================================================================ */

/* --- Служебное ----------------------------------------------------------- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Секция страницы ----------------------------------------------------- */
body.v2 .v2-sec {
  background: transparent;
  padding: var(--v2-section-y) 0;
}

body.v2 .v2-sec--tight { padding-bottom: 64px; }

body.v2 .v2-sec__rule { margin-bottom: 26px; }

body.v2 .v2-sec .v2-section-title { margin: 0 0 12px; }

body.v2 .v2-sec__lead {
  font: var(--v2-body-lg);
  color: var(--asphalt-500);
  margin: 0 0 32px;
  max-width: 62ch;
}

body.v2 .v2-rule__aside a {
  color: var(--asphalt-400);
  text-decoration: none;
}

body.v2 .v2-rule__aside a:hover { color: var(--signal-500); }

/* --- Hero ---------------------------------------------------------------- */
body.v2 .v2-hero {
  position: relative;
  min-height: 620px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  padding: 96px 0 0;
}

/* Скрим системы вместо синего градиента v1. */
body.v2 .v2-hero__scrim {
  position: absolute;
  inset: 0;
  background: var(--v2-scrim);
}

body.v2 .v2-hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-bottom: 56px;
}

body.v2 .v2-hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin-bottom: 22px;
  min-height: 16px;
}

body.v2 .v2-hero__meta-item {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

body.v2 .v2-hero__meta-item b {
  font-weight: 500;
  color: var(--paper);
}

/* Разделитель между показаниями — точка, как на приборной шкале. */
body.v2 .v2-hero__meta-item + .v2-hero__meta-item::before {
  content: "·";
  margin-right: 22px;
  color: rgba(255, 255, 255, 0.35);
}

/* 24ch даёт разрыв из вайрфрейма (§4.1) на десктопе: «СПЕЦТЕХНИКА ИЗ
   КИТАЯ» / «С ЦЕНОЙ ДО ТЕНГЕ». На 16ch заголовок ломался на четыре строки
   с огрызком «ТЕНГЕ» в 183px.
   Ровность строк держится не `text-wrap: balance`, а неразрывными
   пробелами после коротких предлогов в самих строках словаря: замер
   показал, что на 390px balance делает длинную строку ДЛИННЕЕ жадного
   переноса, а предлог на конце строки он всё равно не запрещает. */
body.v2 .v2-hero__title {
  font: var(--v2-hero);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper);
  margin: 0 0 20px;
  max-width: 24ch;
  /* Китайский текст пробелов не имеет и рвётся посимвольно — на 24ch
     последний иероглиф уезжал на отдельную строку. keep-all разрешает
     перенос только по пунктуации, то есть по запятой в середине фразы.
     На кириллицу и латиницу не влияет: там перенос и так идёт по пробелам. */
  word-break: keep-all;
}

body.v2 .v2-hero__sub {
  font: var(--v2-body-lg);
  color: rgba(255, 255, 255, 0.72);
  margin: 0 0 32px;
  max-width: 58ch;
}

body.v2 .v2-hero__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

/* Secondary на тёмном: обводка белым, заливки нет — не конкурирует
   с единственным primary страницы. */
body.v2 .v2-btn--ghost-light {
  background: transparent;
  color: var(--paper);
  border-color: rgba(255, 255, 255, 0.5);
}

body.v2 .v2-btn--ghost-light:hover {
  background: var(--paper);
  color: var(--asphalt-900);
  border-color: var(--paper);
}

/* Рейка срезает нижнюю кромку hero. */
body.v2 .v2-hero__rail {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-bottom: 30px;
}

/* --- Рейка с подписями: тик + подпись + уточнение ------------------------ */
body.v2 .v2-rail__tick {
  width: 1px;
  height: var(--rail-tick);
  background: rgba(255, 255, 255, 0.3);
}

body.v2 .v2-rail--labeled .v2-rail__label { margin-top: 6px; }

body.v2 .v2-rail__sub {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  color: rgba(255, 255, 255, 0.32);
  margin-top: 2px;
  white-space: nowrap;
}

/* --- 01 Маршрут по сайту ------------------------------------------------- */
body.v2 .hp-route__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 16px;
}

body.v2 .hp-route__step {
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  box-shadow: none;
  padding: 24px 22px 20px;
  text-decoration: none;
}

body.v2 .hp-route__step:hover { border-color: var(--asphalt-900); }

/* v1 рисовал номер шага красным кружком — четыре заливки в одном ряду.
   Номер становится моно-индексом, как во всей системе. */
body.v2 .hp-route__n {
  position: static;
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  color: var(--signal-500);
  margin-bottom: 12px;
}

body.v2 .hp-route__step h3 {
  font: var(--v2-card-title);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 8px;
}

body.v2 .hp-route__step p {
  font: var(--v2-body);
  color: var(--asphalt-500);
  margin: 0 0 14px;
}

body.v2 .hp-route__go {
  font-family: var(--type-mono);
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  color: var(--asphalt-900);
  border-bottom: 1px solid var(--asphalt-200);
  padding-bottom: 2px;
}

body.v2 .hp-route__step:hover .hp-route__go { border-bottom-color: var(--signal-500); }

/* --- 02 Ведомость «что входит» ------------------------------------------ */
body.v2 .v2-ledger-wrap {
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  overflow-x: auto;
}

body.v2 table.v2-ledger {
  width: 100%;
  border-collapse: collapse;
  min-width: 520px;
}

body.v2 table.v2-ledger th {
  text-align: left;
  padding: 14px 20px;
  border-bottom: var(--rule-heavy);
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  white-space: nowrap;
}

body.v2 table.v2-ledger th:first-child { width: 190px; }
body.v2 table.v2-ledger th:last-child { text-align: right; width: 120px; }

/* position: relative обязателен: внутри ячейки лежит .sr-only с
   position: absolute, и без позиционированного предка он якорится к
   документу — вылезает из прокручиваемой обёртки и растягивает страницу
   по горизонтали на узких экранах. */
body.v2 table.v2-ledger td {
  position: relative;
  padding: 15px 20px;
  border-bottom: var(--rule-hair);
  font: var(--v2-body);
  color: var(--asphalt-900);
  vertical-align: top;
}

body.v2 table.v2-ledger tr:last-child td { border-bottom: 0; }

body.v2 table.v2-ledger .v2-ledger__stage {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  white-space: nowrap;
}

/* «Включено» — clear-600 по смыслу «закрыто успешно», не красный. */
body.v2 table.v2-ledger .v2-ledger__ok {
  text-align: right;
  color: var(--clear-600);
  font-size: 14px;
}

/* --- 03 Рейка сквозь контент -------------------------------------------- */
body.v2 .v2-flow {
  display: grid;
  grid-template-rows: auto auto auto;
  margin-top: 8px;
}

body.v2 .v2-flow__cards {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 20px;
  align-items: end;
}

body.v2 .v2-flow__cards--bottom { align-items: start; }

body.v2 .v2-flow__card {
  position: relative;
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  padding: 18px;
}

body.v2 .v2-flow__card--1 { grid-column: 1; }
body.v2 .v2-flow__card--2 { grid-column: 2; }
body.v2 .v2-flow__card--3 { grid-column: 3; }
body.v2 .v2-flow__card--4 { grid-column: 4; }
body.v2 .v2-flow__card--5 { grid-column: 5; }

/* Тик от карточки к оси — карточка «висит» на маршруте, а не лежит рядом. */
body.v2 .v2-flow__cards--top .v2-flow__card::after,
body.v2 .v2-flow__cards--bottom .v2-flow__card::before {
  content: "";
  position: absolute;
  left: 50%;
  width: 1px;
  height: 18px;
  background: var(--asphalt-200);
}

body.v2 .v2-flow__cards--top .v2-flow__card::after { top: 100%; }
body.v2 .v2-flow__cards--bottom .v2-flow__card::before { bottom: 100%; }

body.v2 .v2-flow__i {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  color: var(--asphalt-400);
  margin-bottom: 8px;
}

body.v2 .v2-flow__card h4 {
  font: var(--v2-body);
  font-weight: 600;
  text-transform: none;
  color: var(--asphalt-900);
  margin: 0 0 6px;
}

body.v2 .v2-flow__card p {
  font: var(--v2-small);
  color: var(--asphalt-500);
  margin: 0;
}

/* Ось на светлом фоне — та же рейка, но линии и узлы асфальтовые. */
body.v2 .v2-flow__axis { padding: 18px 0; }

body.v2 .v2-flow__axis .v2-rail__line::before,
body.v2 .v2-flow__axis .v2-rail__line::after { background: var(--asphalt-200); }

body.v2 .v2-flow__axis .v2-rail__node {
  border-color: var(--asphalt-200);
  background: var(--v2-page);
}

body.v2 .v2-flow__axis .v2-rail__tick { background: var(--asphalt-200); }

body.v2 .v2-flow__axis .v2-rail__label { color: var(--asphalt-400); }

/* --- 04 Почему это безопасно -------------------------------------------- */
body.v2 .hp-trust__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}

body.v2 .hp-trust__item {
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  padding: 22px;
}

body.v2 .hp-trust__item h4 {
  font: var(--v2-card-title);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 8px;
}

body.v2 .hp-trust__item p {
  font: var(--v2-body);
  color: var(--asphalt-500);
  margin: 0;
}

/* --- 06 Числа ------------------------------------------------------------ */
body.v2 .hp-stats {
  background: var(--surface-inverse);
  color: var(--on-inverse);
  padding: 64px 0;
}

body.v2 .hp-stats .v2-rule { border-bottom-color: rgba(255, 255, 255, 0.22); }

body.v2 .hp-stats .hp-stats-label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  text-align: left;
  margin: 0;
}

body.v2 .hp-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 24px;
}

body.v2 .hp-stat {
  display: block;
  text-align: left;
  border-left: var(--rule-hair-dark);
  padding-left: 18px;
}

body.v2 .hp-stat strong {
  display: block;
  font: var(--v2-price);
  font-variant-numeric: tabular-nums;
  color: var(--on-inverse);
  margin-bottom: 6px;
}

body.v2 .hp-stat span {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

/* --- 07 Галерея ---------------------------------------------------------- */
body.v2 #gallery,
body.v2 #reviews { background: transparent; }

body.v2 .gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
}

body.v2 .gallery-card,
body.v2 .review-card {
  background: var(--paper);
  color: var(--asphalt-900);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  box-shadow: none;
  padding: 0;
  overflow: hidden;
}

body.v2 .gallery-card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  border-radius: 0;
}

body.v2 .gallery-card p,
body.v2 .review-caption {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0;
  padding: 13px 16px;
  border-top: var(--rule-hair);
}

/* --- 08 Отзывы ----------------------------------------------------------- */
body.v2 .reviews-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
}

body.v2 .review-card img,
body.v2 .review-card iframe {
  width: 100%;
  display: block;
  border: 0;
  border-radius: 0;
}

body.v2 .review-card img { aspect-ratio: 4 / 3; object-fit: cover; }

/* Закрывающий шаг */
body.v2 .v2-close {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-top: 40px;
  padding-top: 28px;
  border-top: var(--rule-heavy);
}

body.v2 .v2-close__t {
  font: var(--v2-body-lg);
  color: var(--asphalt-900);
  margin: 0;
  max-width: 52ch;
}

/* --- Адаптив ------------------------------------------------------------- */
@media (max-width: 1100px) {
  body.v2 .v2-hero__title { font-size: var(--fs-40); }
}

@media (max-width: 900px) {
  /* Рейка со сквозными карточками не читается в узкой колонке: ось
     снимается, карточки выстраиваются в порядке шагов. `display: contents`
     возвращает им исходный порядок 01…05, который в сетке был разнесён
     по двум рядам. */
  body.v2 .v2-flow { display: flex; flex-direction: column; gap: 12px; }
  body.v2 .v2-flow__cards { display: contents; }
  body.v2 .v2-flow__axis { display: none; }
  body.v2 .v2-flow__card { grid-column: auto; }
  body.v2 .v2-flow__card--1 { order: 1; }
  body.v2 .v2-flow__card--2 { order: 2; }
  body.v2 .v2-flow__card--3 { order: 3; }
  body.v2 .v2-flow__card--4 { order: 4; }
  body.v2 .v2-flow__card--5 { order: 5; }
  body.v2 .v2-flow__cards--top .v2-flow__card::after,
  body.v2 .v2-flow__cards--bottom .v2-flow__card::before { content: none; }
}

@media (max-width: 760px) {
  body.v2 .v2-sec { padding: 64px 0; }
  body.v2 .v2-hero { min-height: 520px; padding-top: 72px; }
  body.v2 .v2-hero__title { font-size: var(--fs-36); max-width: none; }
  /* Шесть подписей в ряд на телефоне не помещаются — рейка остаётся
     шкалой без подписей, как в футере. */
  body.v2 .v2-hero__rail .v2-rail__label,
  body.v2 .v2-hero__rail .v2-rail__sub,
  body.v2 .v2-hero__rail .v2-rail__tick { display: none; }
  body.v2 .v2-hero__cta .v2-btn { flex: 1 1 100%; }
}

@media (max-width: 560px) {
  body.v2 .v2-hero__title { font-size: var(--fs-28); }
  body.v2 .hp-stat { border-left: 0; border-top: var(--rule-hair-dark); padding: 14px 0 0; }
}

/* v1 держит `html.dark #reviews p` (1,1,2) — обычным классом это не
   перебить, поэтому подписи и закрывающий текст адресуем через тот же id. */
body.v2 #reviews .review-caption {
  color: var(--asphalt-900);
}

body.v2 #reviews .v2-close__t {
  color: var(--asphalt-900);
}

/* На телефоне ведомость не влезает и уходит в горизонтальную прокрутку.
   Колонка «Включено» снимается первой: во всех строках стоит одна и та же
   галочка, а сам заголовок секции — «Что входит», так что информации она
   там не несёт. Остаются этап и работа, и таблица помещается целиком. */
@media (max-width: 620px) {
  body.v2 table.v2-ledger { min-width: 0; }
  body.v2 table.v2-ledger th:last-child,
  body.v2 table.v2-ledger td:last-child { display: none; }
  body.v2 table.v2-ledger th:first-child { width: 120px; }
  body.v2 table.v2-ledger th,
  body.v2 table.v2-ledger td { padding: 13px 14px; }
}

/* ============================================================================
   19. КОНТАКТЫ, ВХОД, РЕГИСТРАЦИЯ, БЛОГ (шаг 5)
   Источник: prod-migration-plan §5. Ветвление регистрации по пяти ролям и
   тексты пояснений перенесены дословно — меняется только подача.
   ============================================================================ */

/* --- Общая форма (контакты + авторизация) -------------------------------- */
body.v2 .contact-form {
  max-width: none;
  margin: 0;
  padding: 0;
  background: transparent;
  box-shadow: none;
  border-radius: 0;
}

body.v2 .contact-form label {
  display: block;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin: 16px 0 7px;
}

body.v2 .contact-form label:first-of-type { margin-top: 0; }

/* v1 держит `.contact-form input, .contact-form textarea { color: #fff }`
   БЕЗ префикса html.dark — то есть белый текст и в светлой теме.
   Задаём цвет явно, иначе ввод не виден на белой бумаге. */
body.v2 .contact-form input,
body.v2 .contact-form textarea,
body.v2 .contact-form select {
  width: 100%;
  box-sizing: border-box;
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  background: var(--paper);
  color: var(--asphalt-900);
  padding: 11px 12px;
  font: var(--v2-body);
  outline: none;
  box-shadow: none;
  margin: 0;
}

body.v2 .contact-form textarea { min-height: 110px; resize: vertical; }

body.v2 .contact-form input:focus,
body.v2 .contact-form textarea:focus,
body.v2 .contact-form select:focus { border-color: var(--asphalt-900); }

/* Единственный primary на экране формы. Ширину и типографику задаём здесь:
   раньше их держал постраничный <style> страниц входа и регистрации,
   который снят при переносе. */
body.v2 .contact-form .btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--v2-btn-h);
  padding: 0 24px;
  margin-top: 22px;
  background: var(--signal-fill);
  color: var(--on-signal);
  border: 1.5px solid var(--signal-fill);
  border-radius: var(--radius-4);
  box-shadow: none;
  font-family: var(--type-mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
}

body.v2 .contact-form .btn:hover {
  background: var(--signal-fill-hover);
  border-color: var(--signal-fill-hover);
  transform: none;
  box-shadow: none;
}

/* text-align досталось от v1 (`.form-note{text-align:center}`) и в правило v2
   не попало — тот же недосмотр, что у .cf-hp выше. Оговорка под формой
   центрируется; без этой строки она уезжает влево на контактах. */
body.v2 .form-note {
  font: var(--v2-small);
  color: var(--asphalt-400);
  margin: 12px 0 0;
  text-align: center;
}

body.v2 #formStatus,
body.v2 #loginStatus,
body.v2 #personStatus,
body.v2 #companyStatus,
body.v2 #serviceStatus,
body.v2 #bankStatus,
body.v2 #partnerStatus {
  font: var(--v2-body);
  margin-top: 12px;
  color: var(--asphalt-500);
}

body.v2 .contact-ok { color: var(--clear-600); }

/* Ловушка для ботов — остаётся невидимой.

   `top` и `opacity` тут были потеряны при переносе на шаге 5, и до 7.2.5
   их подставлял v1: у него `.cf-hp` задаёт обе оси. Заметно это стало
   только замером — без style.css поле уезжало за экран лишь по горизонтали,
   оставалось в потоке формы и добавляло 40px высоты на контактах.

   Это не косметика. Ловушка обязана быть недосягаема для человека: она
   намеренно не `display:none`, чтобы бот её заполнил, — а бот отсеивается
   по непустому полю. Поле, которое видно и в которое можно попасть табом,
   отсеивало бы живых людей. */
body.v2 .cf-hp {
  position: absolute;
  left: -9999px;
  top: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}

/* --- Контакты ------------------------------------------------------------ */
body.v2 .v2-contacts {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 32px;
  align-items: start;
  padding-top: 32px;
  padding-bottom: 80px;
}

/* Прямые контакты — асфальтовая панель (prod-migration-plan §5) */
body.v2 .v2-reach {
  background: var(--surface-inverse);
  color: var(--on-inverse);
  border-radius: var(--radius-2);
  padding: 26px;
}

body.v2 .v2-reach__head {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  padding-bottom: 14px;
  border-bottom: var(--rule-hair-dark);
}

body.v2 .v2-reach__row {
  display: block;
  padding: 14px 0;
  border-bottom: var(--rule-hair-dark);
  text-decoration: none;
  color: var(--on-inverse);
}

body.v2 .v2-reach__label {
  display: block;
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 5px;
}

body.v2 .v2-reach__value { font: var(--v2-body); color: var(--on-inverse); }

a.v2-reach__row:hover .v2-reach__value { color: var(--signal-500); }

body.v2 .v2-reach__wa { margin-top: 22px; }

body.v2 .v2-reach__social {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: var(--rule-hair-dark);
}

body.v2 .v2-reach__social a {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
  text-decoration: none;
}

body.v2 .v2-reach__social a:hover { color: var(--on-inverse); }

/* --- Вход и регистрация -------------------------------------------------- */
/* Постраничные <style> этих страниц сняты — всё описано здесь. */
body.v2.auth-body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

body.v2 .auth-page {
  flex: 1;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: clamp(32px, 6vw, 72px) var(--v2-gutter);
  background: var(--v2-page);
}

body.v2 .auth-card,
body.v2 .auth-card--wide {
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  box-shadow: none;
  padding: 36px;
  width: 100%;
  box-sizing: border-box;
}

body.v2 .auth-card { max-width: 420px; }
body.v2 .auth-card--wide { max-width: 560px; }

body.v2 .auth-card__logo { display: flex; justify-content: center; margin-bottom: 20px; }

body.v2 .auth-card__logo .logo-mark {
  width: 52px;
  height: 52px;
  border-radius: var(--radius-2);
  background: var(--surface-inverse);
  color: var(--on-inverse);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--type-display);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: var(--ls-display);
}

body.v2 .auth-card h1,
body.v2 .auth-card--wide h1 {
  font: var(--v2-section);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asphalt-900);
  text-align: center;
  margin: 0 0 8px;
}

body.v2 .auth-card__sub {
  font: var(--v2-body);
  color: var(--asphalt-500);
  text-align: center;
  margin: 0 0 26px;
}

/* Выбор роли — чипы. Активный ЗАЛИТЫЙ АСФАЛЬТ, не красный: единственный
   primary на экране — кнопка «Создать аккаунт». */
body.v2 .auth-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 22px;
  padding-bottom: 22px;
  border-bottom: var(--rule-hair);
}

body.v2 .auth-tabs button {
  padding: 9px 14px;
  border: 1px solid var(--asphalt-200);
  border-radius: var(--radius-4);
  background: var(--paper);
  color: var(--asphalt-900);
  font-family: var(--type-mono);
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  cursor: pointer;
}

body.v2 .auth-tabs button:hover { border-color: var(--asphalt-900); }

body.v2 .auth-tabs button.active {
  background: var(--asphalt-900);
  border-color: var(--asphalt-900);
  color: var(--paper);
}

body.v2 .auth-type-select { display: none; }

/* Пояснение к роли — текст переносится дословно, меняется только оправа. */
body.v2 .auth-note {
  background: var(--asphalt-050);
  border: 0;
  border-left: 2px solid var(--asphalt-200);
  border-radius: 0;
  padding: 13px 16px;
  font: var(--v2-small);
  color: var(--asphalt-500);
  margin: 0 0 22px;
  max-width: none;
  text-align: left;
}

body.v2 .auth-note strong { color: var(--asphalt-900); }

body.v2 .auth-link {
  display: block;
  text-align: center;
  margin-top: 20px;
  padding-top: 18px;
  border-top: var(--rule-hair);
  font: var(--v2-small);
  color: var(--asphalt-500);
  text-decoration: none;
}

body.v2 .auth-link:hover { color: var(--signal-500); }

/* --- Блог ---------------------------------------------------------------- */
/* minmax(300px, …), а не 240px как в каталоге: у карточек блога подвал
   длиннее (заголовок + анонс + «Читать»), и в 240px он ломается. */
body.v2 .blog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}

/* v1 держит `.section { text-align: center }`, а секция блога — .section;
   в системе ведомости выравниваются по левому краю. */
body.v2 .blog-card {
  background: var(--paper);
  color: var(--asphalt-900);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  box-shadow: none;
  overflow: visible;
  text-align: left;
}

body.v2 .blog-card:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--asphalt-900);
}

body.v2 .blog-card__body { padding: 22px; gap: 0; }

/* Кикер — метка рубрики, а не действие и не «вы здесь»: три красных
   пятна подряд в одном ряду карточек размывают смысл сигнального цвета
   (тот же разбор, что и со счётчиком избранного на шаге 2). */
body.v2 .blog-card__date {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin-bottom: 12px;
}

body.v2 .blog-card__title {
  font: var(--v2-card-title);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin-bottom: 10px;
}

body.v2 .blog-card__excerpt {
  font: var(--v2-body);
  color: var(--asphalt-500);
  margin-bottom: 16px;
}

body.v2 .blog-card__cta {
  margin-top: auto;
  font-family: var(--type-mono);
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  color: var(--asphalt-900);
}

body.v2 .blog-card:hover .blog-card__cta { color: var(--signal-500); }

/* --- Статья -------------------------------------------------------------- */
/* max-width 760px из v1 сохраняется: это мера строки для чтения, а не сетка
   страницы, поэтому .v2-wrap здесь НЕ применяется. */
body.v2 .blog-article { padding: 8px 24px 80px; }

body.v2 .blog-back-link {
  display: inline-block;
  font-family: var(--type-mono);
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  color: var(--asphalt-500);
  text-decoration: none;
  margin-bottom: 26px;
}

body.v2 .blog-back-link:hover { color: var(--signal-500); }

body.v2 .blog-article__meta {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  padding-bottom: 12px;
  border-bottom: var(--rule-heavy);
  margin-bottom: 22px;
}

body.v2 .blog-article h1 {
  font: var(--v2-page-title);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 24px;
}

body.v2 .blog-article h2 {
  font: var(--v2-card-title);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 36px 0 12px;
}

body.v2 .blog-article p,
body.v2 .blog-article li {
  font: var(--v2-body-lg);
  color: var(--asphalt-700);
}

body.v2 .blog-article p { margin: 0 0 16px; }
body.v2 .blog-article li { margin-bottom: 8px; }
body.v2 .blog-article li strong { color: var(--asphalt-900); }

/* v1 рисовал здесь тёмно-синюю коробку со скруглением 16px и центровкой —
   ровно то, от чего система уходит. Остаётся тяжёлая линейка и левый край. */
body.v2 .blog-article__cta {
  background: transparent;
  border-radius: 0;
  padding: 26px 0 0;
  margin-top: 40px;
  border-top: var(--rule-heavy);
  text-align: left;
}

body.v2 .blog-article__cta p {
  font: var(--v2-body-lg);
  color: var(--asphalt-900);
  margin: 0 0 18px;
}

body.v2 .blog-article__cta .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--v2-btn-h);
  padding: 0 24px;
  background: var(--signal-fill);
  color: var(--on-signal);
  border: 1.5px solid var(--signal-fill);
  border-radius: var(--radius-4);
  box-shadow: none;
  font-family: var(--type-mono);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
}

body.v2 .blog-article__cta .btn:hover {
  background: var(--signal-fill-hover);
  border-color: var(--signal-fill-hover);
  transform: none;
  box-shadow: none;
}

@media (max-width: 900px) {
  body.v2 .v2-contacts { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  body.v2 .auth-card,
  body.v2 .auth-card--wide { padding: 24px; }
  body.v2 .v2-reach { padding: 20px; }
}

/* v1 держит `#contact { background: #f9f9f9 }` — id-правило, классом его не
   перебить, из-за чего под секцией контактов оставалась светлая плашка,
   не относящаяся к сетке v2. */
body.v2 #contact { background: transparent; }

/* Статья лежит внутри .section, который в v1 центрирует текст. */
body.v2 .blog-article { text-align: left; }

/* ============================================================================
   20. ИЗБРАННОЕ (отдельный шаг после 5)
   Не зависит от route[] с бэкенда и использует тот же VehiclePassport, что
   каталог, поэтому переносится, не дожидаясь кабинета.
   ============================================================================ */

/* Загрузка и ошибка — в той же оправе, что и пустое состояние, но без
   отступов в полэкрана: это временные строки, а не тупик. */
body.v2 #favGrid .v2-empty { padding: 26px 24px; }
body.v2 #favGrid .v2-empty p { margin-bottom: 0; }
body.v2 .v2-empty--error p { color: var(--signal-500); }

/* Один следующий шаг на весь список */
/* Секция избранного — .section, а он в v1 центрирует текст. */
body.v2 .fav-cta-banner {
  background: transparent;
  border-radius: 0;
  padding: 28px 0 0;
  margin-top: 40px;
  text-align: left;
}

body.v2 .fav-cta-banner__sub {
  font: var(--v2-body);
  color: var(--asphalt-500);
  margin-top: 6px;
  max-width: 52ch;
}

/* v1 держал `#favEmpty` скрытым инлайном и показывал через style.display —
   логика не тронута, поэтому пустое состояние остаётся блоком сетки. */
body.v2 #favEmpty { margin-top: 0; }

/* Отсутствие фото рисуется системой, а не картинкой-заглушкой: файла
   /img/no-photo.png в репозитории нет и не было, поэтому у техники без
   снимка в каталоге, на главной, в избранном и на странице техники
   показывался битый <img>. Токены вместо бинарника — и заглушка сама
   собой работает в обеих темах. */
body.v2 .vp__noimg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--asphalt-100);
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

/* На странице техники кадр крупнее — плашка держит те же пропорции 4:3,
   что и <img>, иначе галерея схлопнется в ноль высоты. */
body.v2 .v2-shot .vp__noimg { position: relative; aspect-ratio: 4 / 3; }

/* ============================================================================
   21. ЛИЧНЫЙ КАБИНЕТ (шаг 6)
   Живая рейка: узлы и их состояния приходят с бэкенда в deal.route[].
   Кабинет менеджера (.mgr-*) в перенос НЕ входит — он внутренний инструмент
   и остаётся на постраничных стилях v1; здесь ему даётся только оправа,
   чтобы он не выглядел сломанным рядом с перенесёнными блоками.
   ============================================================================ */

body.v2 .account-page {
  background: var(--v2-page);
  padding: 40px 0 80px;
}

body.v2 .account-header {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 32px;
}

body.v2 .v2-acc__rule { margin-bottom: 12px; }
body.v2 .account-header-left { display: block; }
body.v2 .account-header h1 { margin: 0 0 6px; color: var(--asphalt-900); }

body.v2 #accountRoleLine {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

body.v2 .account-grid { display: block; }

/* --- Панель статуса сделки ---------------------------------------------- */
body.v2 .v2-deal__status {
  background: var(--surface-inverse);
  color: var(--on-inverse);
  border-radius: var(--radius-2);
  overflow: hidden;
}

/* Шевронная лента — второе и последнее место в системе, где она есть. */
body.v2 .v2-deal__chevron { height: 6px; background: var(--hazard-chevron); }

body.v2 .v2-deal__status-body { padding: 26px 28px 32px; }

body.v2 .v2-deal__status-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 28px;
}

body.v2 .v2-deal__meta {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  margin-bottom: 10px;
}

body.v2 .v2-deal__title {
  font: var(--v2-page-title);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-inverse);
  margin: 0;
}

/* «СЕЙЧАС — ТАМОЖНЯ» красным, «ПРОСРОЧЕНО — ТАМОЖНЯ» — hazard: просрочка
   это не действие и не «вы здесь», у неё свой смысл и свой цвет. */
body.v2 .v2-deal__now {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--signal-500);
  text-align: right;
}

body.v2 .v2-deal__now.is-late { color: var(--hazard-400); }

/* --- Рейка сделки: состояния узлов --------------------------------------- */
body.v2 .v2-rail--deal .v2-rail__seg.is-first .v2-rail__line::before,
body.v2 .v2-rail--deal .v2-rail__seg.is-last .v2-rail__line::after {
  background: transparent;
}

body.v2 .v2-rail--deal .v2-rail__line.is-passed::before { background: var(--ink-700); }

body.v2 .v2-rail__node--done {
  border: 0;
  background: var(--ink-700);
}

body.v2 .v2-rail__node--active,
body.v2 .v2-rail__node--overdue {
  width: var(--rail-node-active);
  height: var(--rail-node-active);
  border: 0;
}

body.v2 .v2-rail__node--active {
  background: var(--signal-500);
  box-shadow: 0 0 0 4px var(--signal-tint);
  position: relative;
}

/* Активный узел — единственный на рейке, и единственный, который дышит.
   Пульсирует ТОЛЬКО ореол, и не тот, что нарисован на самом узле выше, а
   отдельное кольцо в ::after: статичные 4px остаются на месте при любых
   условиях, поэтому без анимации (reduced-motion, старый браузер) узел
   выглядит ровно так же, как выглядел. Само пятно и подпись не двигаются —
   иначе «вы здесь» превращается в мигающую лампочку.
   done / todo / overdue не трогаем: у просрочки свой цвет и свой смысл,
   мигать ей незачем. */
body.v2 .v2-rail__node--active::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
  animation: v2-rail-pulse 2.2s ease-out infinite;
}

/* Кольцо расходится от кромки статичного ореола (4px) наружу и гаснет.
   Старт с opacity 0 — иначе в момент перезапуска цикла оно накладывалось бы
   на статичный ореол и тот заметно темнел бы раз в 2,2 с. */
@keyframes v2-rail-pulse {
  0%   { box-shadow: 0 0 0 4px var(--signal-tint);  opacity: 0; }
  20%  { opacity: 1; }
  100% { box-shadow: 0 0 0 13px var(--signal-tint); opacity: 0; }
}

body.v2 .v2-rail__node--overdue {
  background: var(--hazard-400);
  box-shadow: 0 0 0 4px var(--hazard-tint);
}

body.v2 .v2-rail--deal .v2-rail__label { color: rgba(255, 255, 255, 0.75); }

body.v2 .v2-rail--deal .v2-rail__seg:has(.v2-rail__node--active) .v2-rail__label,
body.v2 .v2-rail--deal .v2-rail__seg:has(.v2-rail__node--overdue) .v2-rail__label {
  color: var(--on-inverse);
}

body.v2 .v2-rail__sub--overdue { color: var(--hazard-400); font-weight: 500; }
body.v2 .v2-rail__sub--active { color: rgba(255, 255, 255, 0.62); }

/* --- Карточка сделки ----------------------------------------------------- */
body.v2 .deal-list { display: flex; flex-direction: column; gap: 28px; }

body.v2 .deal-card {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  color: var(--asphalt-900);
  display: flex;
  flex-direction: column;
  gap: 20px;
}

body.v2 .deal-card__head {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin: 0;
}

body.v2 .deal-card .deal-meta {
  font: var(--v2-label);
  font-weight: 400;
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin: 0;
}

body.v2 .deal-status-pill {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  background: var(--asphalt-100);
  color: var(--asphalt-900);
  padding: 6px 12px;
  border-radius: var(--radius-2);
}

/* --- Панели внутри сделки ------------------------------------------------ */
body.v2 .deal-card > div:not(.v2-deal__status):not(.deal-card__head) {
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  padding: 20px 22px;
}

body.v2 .deal-card h4,
body.v2 .deal-card .block-head {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: var(--rule-heavy);
}

body.v2 .assignment-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 11px 0;
  border-bottom: var(--rule-hair);
  color: var(--asphalt-900);
}

body.v2 .assignment-row:last-child { border-bottom: 0; }
body.v2 .assignment-role { font: var(--v2-body); color: var(--asphalt-900); }

body.v2 .assignment-status {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--radius-2);
  background: var(--asphalt-100);
  color: var(--asphalt-400);
  margin-left: auto;
}

body.v2 .assignment-status.DONE { background: var(--clear-tint); color: var(--clear-600); }
body.v2 .assignment-status.IN_PROGRESS { background: var(--hazard-tint); color: #8A5A00; }

/* --- Личные данные и остальные карточки кабинета ------------------------- */
body.v2 .cab-card {
  background: var(--paper);
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  box-shadow: none;
  padding: 22px;
  margin-bottom: 24px;
}

body.v2 .cab-card-head h2 {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: var(--rule-heavy);
}

body.v2 .profile-grid label {
  display: block;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin: 14px 0 7px;
}

body.v2 .profile-grid input,
body.v2 .cab-card input[type="text"],
body.v2 .cab-card input[type="email"],
body.v2 .cab-card input[type="password"],
body.v2 .cab-card select,
body.v2 .cab-card textarea {
  width: 100%;
  box-sizing: border-box;
  border: var(--rule-hair);
  border-radius: var(--radius-2);
  background: var(--paper);
  color: var(--asphalt-900);
  padding: 11px 12px;
  font: var(--v2-body);
  outline: none;
}

body.v2 .cab-card input:focus,
body.v2 .cab-card select:focus,
body.v2 .cab-card textarea:focus { border-color: var(--asphalt-900); }

/* Кабинет менеджера остаётся на v1 — ему нужна только оправа, чтобы он не
   выглядел сломанным рядом с перенесёнными блоками. */
body.v2 .mgr-section { background: var(--paper); }

@media (max-width: 760px) {
  body.v2 .v2-deal__status-body { padding: 20px; }
  body.v2 .v2-deal__title { font-size: var(--fs-28); }
  body.v2 .v2-deal__now { text-align: left; }
  /* Шесть подписей в ряд на телефоне не помещаются — рейка остаётся шкалой,
     а даты уходят: они есть в журнале событий строкой ниже. */
  body.v2 .v2-rail--deal .v2-rail__sub { display: none; }
  body.v2 .v2-rail--deal .v2-rail__label { font-size: 9px; letter-spacing: 0.04em; }
}

/* Заголовки блоков внутри сделки: моно-капс на тяжёлой линейке.
   Иконки FontAwesome сняты — в v2 роль подписи несёт сама типографика. */
body.v2 .dc-block__head,
body.v2 .comments-block__head,
body.v2 .dc-head {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: var(--rule-heavy);
}

body.v2 .dc-block__head i,
body.v2 .comments-block__head i { display: none; }

body.v2 .dc-internal {
  font-weight: 400;
  color: var(--asphalt-400);
  letter-spacing: var(--ls-mono-label);
}

/* Кнопки кабинета — те же, что во всей системе, вместо красных «пилюль» v1.
   Заливки здесь нет НИ У ОДНОЙ: кабинет это экран наблюдения, а сигнальный
   красный значит «действие, которого от вас ждут сейчас». Сохранить свой
   e-mail или отправить сообщение менеджеру — не тот случай, и три красных
   пятна в кадре обесценили бы цвет на всех остальных экранах. */
body.v2 .account-page .btn,
body.v2 .account-page button.btn {
  background: transparent;
  color: var(--asphalt-900);
  border: 1.5px solid var(--asphalt-900);
  border-radius: var(--radius-4);
  box-shadow: none;
  font-family: var(--type-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  min-height: var(--v2-btn-h-sm);
  padding: 0 18px;
}

body.v2 .account-page .btn:hover {
  background: var(--asphalt-900);
  color: var(--paper);
  transform: none;
  box-shadow: none;
}

/* Второстепенные действия внутри сделки не заливаются: единственный красный
   на экране — то действие, которого от человека ждут сейчас. */
body.v2 .deal-card .btn,
body.v2 #btnLogout,
body.v2 .account-page .btn--ghost {
  background: transparent;
  color: var(--asphalt-900);
  border: 1.5px solid var(--asphalt-900);
  border-radius: var(--radius-4);
  box-shadow: none;
  font-family: var(--type-mono);
  font-weight: 500;
  font-size: 12px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  min-height: var(--v2-btn-h-sm);
  padding: 0 18px;
}

body.v2 .deal-card .btn:hover,
body.v2 #btnLogout:hover {
  background: var(--asphalt-900);
  color: var(--paper);
  transform: none;
}

body.v2 .empty-note {
  font: var(--v2-body);
  color: var(--asphalt-400);
  text-align: left;
  margin: 0;
}

/* Вкладки «Активные / Завершённые» — чипы системы */
body.v2 .deal-tabs button,
body.v2 .deal-tab {
  border: 1px solid var(--asphalt-200);
  border-radius: var(--radius-4);
  background: var(--paper);
  color: var(--asphalt-900);
  font-family: var(--type-mono);
  font-size: 11px;
  letter-spacing: var(--ls-mono-btn);
  text-transform: uppercase;
  padding: 9px 14px;
  box-shadow: none;
}

body.v2 .deal-tabs button.active,
body.v2 .deal-tab.active {
  background: var(--asphalt-900);
  border-color: var(--asphalt-900);
  color: var(--paper);
}

/* Бейдж подтверждения — статус-чип. Радиус 999 здесь разрешён (чипы статуса
   и контакт-виджет — единственные исключения из шкалы 0/2/4/6), но цвета
   берутся из токенов, а не задаются вручную, как было в v1. */
body.v2 .account-badge {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  padding: 5px 12px;
}

body.v2 .account-badge.verified { background: var(--clear-tint); color: var(--clear-600); }
body.v2 .account-badge.not-verified { background: var(--hazard-tint); color: #8A5A00; }

/* Аккаунт на подтверждении — не тупик и не ошибка: hazard значит «ждёт
   действия», и это ровно тот случай. */
body.v2 .v2-empty--pending {
  border-left: 2px solid var(--hazard-400);
  text-align: left;
  padding: 26px 24px;
}

body.v2 .v2-empty--pending p { margin: 0; max-width: 60ch; }

/* ============================================================================
   22. ЮРИДИЧЕСКИЕ СТРАНИЦЫ (шаг 7.1)
   Переносятся ПЕРВЫМИ в шаге 7 — до удаления style.css. Задача та же, что у
   .blog-article: мера строки для чтения и типографика документа. Белая
   карточка со скруглением 18px и тенью уходит — это была последняя такая
   на публичной части сайта.
   ============================================================================ */
body.v2 .privacy-page { background: var(--v2-page); }

body.v2 .privacy-container {
  max-width: 760px;
  margin: 0 auto;
  padding: 40px 24px 80px;
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  text-align: left;
}

body.v2 .privacy-container h1 {
  font: var(--v2-page-title);
  letter-spacing: var(--ls-display);
  word-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 0 0 12px;
}

body.v2 .privacy-date {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  padding-bottom: 12px;
  border-bottom: var(--rule-heavy);
  margin: 0 0 26px;
}

body.v2 .privacy-container h3 {
  font: var(--v2-card-title);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  color: var(--asphalt-900);
  margin: 34px 0 12px;
}

body.v2 .privacy-container p,
body.v2 .privacy-container li {
  font: var(--v2-body-lg);
  color: var(--asphalt-700);
}

body.v2 .privacy-container p { margin: 0 0 16px; }
body.v2 .privacy-container ul { margin: 0 0 16px 20px; }
body.v2 .privacy-container li { margin-bottom: 8px; }

body.v2 .privacy-container a { color: var(--ink-500); text-underline-offset: 3px; }
body.v2 .privacy-container a:hover { color: var(--signal-500); }

/* Футер на узких экранах.
   Сетка футера так и оставалась четырёхколоночной на телефоне: колонки
   «Контакты» и «Соцсети» уезжали за правый край (left 370 и 510 при ширине
   окна 390) и обрезались правилом `overflow-x: hidden` из v1. Проверка по
   document.scrollWidth этого не ловила — страница не прокручивалась, потому
   что содержимое было именно ОБРЕЗАНО, — а на телефоне из футера пропадали
   телефон и почта компании. */
@media (max-width: 900px) {
  body.v2 .v2-footer__grid { grid-template-columns: 1fr 1fr; gap: 28px 24px; }
}

@media (max-width: 560px) {
  body.v2 .v2-footer__grid { grid-template-columns: 1fr; gap: 26px; }
  body.v2 .v2-footer__about { max-width: none; }
}

/* `.v2-ledger` на главной — <table> с min-width 520px, а на карточке техники
   так же названа ведомость «как проходит покупка» в колонке 420px. Правила
   таблицы теперь адресованы самому элементу table, иначе они растягивали
   ведомость шире её колонки, и та обрезалась `overflow-x: hidden`. */

/* ============================================================================
   23. КОММЕРЧЕСКОЕ ПРЕДЛОЖЕНИЕ (kp.html)

   Страница ведёт себя как документ, а не как лендинг: разделы идут в том же
   порядке, что в PDF-шаблоне компании (core/kp.py), ярлыки моноширинные
   капсом, все суммы — табличными цифрами по правому краю. Человек, который
   получал бумажное КП, должен узнать бумагу.

   Красное здесь ровно одно — «СКАЧАТЬ PDF». Всё остальное (поделиться,
   телефон, «написать менеджеру») ведёт дальше по сайту и стоит обводкой:
   правило «один сигнальный красный — одно действие».
   ============================================================================ */
body.v2 .kp {
  padding-bottom: var(--space-96);
  max-width: 900px;   /* мера строки документа: 1240px читается как таблица */
}

body.v2 .kp__head { padding-bottom: 0; }

/* Реквизиты шапки — в строку на просторе, в столбик на телефоне. */
body.v2 .kp__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 40px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: var(--rule-heavy);
}

body.v2 .kp__meta-item { display: flex; flex-direction: column; gap: 4px; }

body.v2 .kp__meta-label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
}

body.v2 .kp__meta-value {
  font: var(--v2-data);
  font-variant-numeric: tabular-nums;
  color: var(--asphalt-900);
}

/* align-items: start — подписи под кнопками разной длины, и по центру
   кнопки бы разъехались по вертикали. */
body.v2 .kp__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 12px 16px;
  margin: 24px 0 8px;
}

/* Кнопка со своей подписью. Подпись объясняет, чем два скачивания
   отличаются: без неё «с подписью» и «как на сайте» — загадка. */
body.v2 .kp__dl {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* 26ch — чтобы самая длинная подпись («с печатью компании · скоро») встала
   в одну строку и кнопки не разъезжались по высоте. Мера, а не nowrap: в
   других языках подпись длиннее, и рвать её лучше по словам, чем упирать
   в край. */
body.v2 .kp__dl-note {
  font: var(--v2-small);
  color: var(--asphalt-400);
  max-width: 26ch;
}

/* Выключенная кнопка. Не серая заливка, а приглушённая обводка: документа
   пока нет, но кнопка — не поломка, поэтому она читается как «здесь будет»,
   а не как «здесь сломалось». */
body.v2 .v2-btn.is-disabled,
body.v2 .v2-btn:disabled {
  color: var(--asphalt-400);
  border-color: var(--asphalt-200);
  background: transparent;
  cursor: not-allowed;
}

body.v2 .v2-btn.is-disabled:hover,
body.v2 .v2-btn:disabled:hover {
  color: var(--asphalt-400);
  border-color: var(--asphalt-200);
  background: transparent;
}

/* Значок мессенджера у «Поделиться». Иконка — сосед текста, а не внутри
   элемента с data-i18n: смена языка переписывает textContent, и вложенный
   значок при переключении пропал бы. */
body.v2 .kp__share { gap: 8px; }
body.v2 .kp__share .fa-whatsapp { font-size: 16px; line-height: 1; }

/* Подтверждение копирования. Не alert и не всплывашка поверх страницы:
   строка рядом с кнопкой, которая гаснет сама. role="status" в разметке —
   значит скринридер её тоже произнесёт. */
body.v2 .kp__toast {
  font: var(--v2-small);
  color: var(--clear-600);
  opacity: 0;
  transition: opacity .18s ease;
}

body.v2 .kp__toast.is-on { opacity: 1; }

body.v2 .kp__block { margin-top: 24px; }

body.v2 .kp__seller-name {
  font-family: var(--type-display);
  font-weight: 600;
  font-size: var(--fs-20);
  line-height: 1.2;
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  margin-bottom: 4px;
}

/* Реквизиты и характеристики — длинные значения (адрес банка, SWIFT), и
   nowrap из .vp__row-value их бы обрезал. Здесь значение переносится, а
   выравнивание по правому краю сохраняется. */
body.v2 .kp__rows .vp__row-value {
  white-space: normal;
  text-align: right;
  overflow-wrap: anywhere;
}

body.v2 .kp__rows .vp__row-label { flex: 0 0 auto; }

body.v2 .kp__subject {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 24px;
  align-items: start;
}

/* Техника без снимка — обычное дело в каталоге, и на КП это не должно
   ломать раскладку. Скрытая <figure> выпадает из потока грида, описание
   становится ПЕРВЫМ элементом и садится в колонку 280px, отведённую под
   фото: таблица цен уезжает в горизонтальную прокрутку на пустом месте.
   Поэтому без фото колонка одна. */
body.v2 .kp__subject:has(.kp__photo[hidden]) { grid-template-columns: 1fr; }

body.v2 .kp__photo {
  margin: 0;
  border: var(--rule-hair);
  background: var(--asphalt-100);
  aspect-ratio: 4 / 3;
  overflow: hidden;
}

body.v2 .kp__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* min-width: 0 — иначе элемент грида не может стать уже своего содержимого
   (у элементов грида min-width по умолчанию auto), и `min-width: 380px`
   таблицы цен распирает колонку до 380px внутри окна в 390px. Страница при
   этом не прокручивается — `overflow-x: hidden` на body молча обрезает
   правый край, и потеря заметна только замером. С нулём колонка сжимается,
   а прокрутка достаётся самой таблице, как и задумано. */
body.v2 .kp__subject-body { min-width: 0; }

body.v2 .kp__subject-title {
  font-family: var(--type-display);
  font-weight: 600;
  font-size: var(--fs-20);
  line-height: 1.15;
  letter-spacing: var(--ls-display);
  word-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0 0 8px;
}

body.v2 .kp__subject-note {
  font: var(--v2-body);
  color: var(--asphalt-500);
  margin: 0 0 16px;
}

body.v2 .kp__avail {
  font: var(--v2-small);
  color: var(--clear-600);
  margin: 12px 0 0;
}

/* Таблица «количество / цена» скроллится внутри себя, а не растягивает
   страницу: четыре колонки с суммами на 390px иначе не помещаются. */
body.v2 .kp__table-wrap { overflow-x: auto; }

body.v2 .kp__table {
  width: 100%;
  min-width: 380px;
  border-collapse: collapse;
}

body.v2 .kp__table th {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--v2-text-on-dark);
  background: var(--asphalt-700);
  text-align: right;
  padding: 9px 12px;
  white-space: nowrap;
}

body.v2 .kp__table th:first-child,
body.v2 .kp__table td:first-child { text-align: center; }

body.v2 .kp__table td {
  font: var(--v2-data);
  font-variant-numeric: tabular-nums;
  text-align: right;
  padding: 12px;
  border-bottom: var(--rule-hair);
  white-space: nowrap;
}

body.v2 .kp__specs { margin-top: 26px; }

body.v2 .kp__subhead {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--asphalt-400);
  margin-bottom: 8px;
}

/* --- Разбивка расчёта ---------------------------------------------------- */
/* Группа = точка маршрута, где уходят деньги. Та же нарезка, что в
   CostBreakdown на калькуляторе, и те же подписи строк: одно и то же число
   не должно называться в двух местах по-разному. */
body.v2 .kp__group { margin-bottom: 22px; }
body.v2 .kp__group:last-child { margin-bottom: 0; }

body.v2 .kp__group-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0 0 4px;
  padding-bottom: 8px;
  border-bottom: var(--rule-heavy);
}

body.v2 .kp__group-n {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  color: var(--signal-500);
}

body.v2 .kp__group-title {
  font-family: var(--type-display);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  flex: 1 1 auto;
}

body.v2 .kp__group-sum {
  font: var(--v2-data);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Подписи строк расхода — предложения, а не ярлыки полей: капс и трекинг
   ярлыка на них не ставим, иначе «Утилизационный сбор (25 т)» читается по
   складам. */
body.v2 .kp__row-label {
  font: var(--v2-body);
  color: var(--asphalt-500);
  letter-spacing: normal;
  text-transform: none;
}

/* Итог — асфальтовая плашка с шевронной лентой по верхней кромке, как
   «Итого» на калькуляторе. Одно из двух мест в системе, где лента вообще
   появляется. */
body.v2 .kp__total {
  margin-top: 26px;
  padding: 22px 24px 24px;
  background: var(--v2-panel-dark);
  border-top: 6px solid transparent;
  border-image: var(--hazard-chevron) 6;
}

body.v2 .kp__total-label {
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  text-transform: uppercase;
  color: var(--v2-text-on-dark-secondary);
}

body.v2 .kp__total-value {
  font: var(--v2-price);
  font-variant-numeric: tabular-nums;
  color: var(--v2-text-on-dark);
  margin: 6px 0 4px;
}

body.v2 .kp__total-alt {
  font: var(--v2-data);
  font-variant-numeric: tabular-nums;
  color: var(--v2-text-on-dark-secondary);
  white-space: pre-wrap;
}

body.v2 .kp__total-note {
  font: var(--v2-small);
  color: var(--v2-text-on-dark-secondary);
  margin-top: 10px;
}

/* --- Условия и сроки ----------------------------------------------------- */
body.v2 .kp__terms {
  font: var(--v2-body-lg);
  font-weight: 600;
  color: var(--asphalt-900);
  margin-bottom: 20px;
}

body.v2 .kp__timeline { margin: 0; padding: 0; list-style: none; counter-reset: kp-step; }

body.v2 .kp__timeline-item {
  position: relative;
  counter-increment: kp-step;
  padding: 11px 0 11px 40px;
  border-bottom: var(--rule-hair);
  font: var(--v2-body);
  color: var(--asphalt-700);
}

body.v2 .kp__timeline-item:last-child { border-bottom: 0; }

/* Номер шага — моно табличными, чтобы двузначные не сдвигали текст. */
body.v2 .kp__timeline-item::before {
  content: counter(kp-step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: 12px;
  font: var(--v2-label);
  letter-spacing: var(--ls-mono-label);
  font-variant-numeric: tabular-nums;
  color: var(--asphalt-400);
}

body.v2 .kp__service { font: var(--v2-body); color: var(--asphalt-700); margin: 0; }

body.v2 .kp__foot { margin-top: 32px; padding-top: 24px; border-top: var(--rule-heavy); }

body.v2 .kp__foot-note { font: var(--v2-body); color: var(--asphalt-500); margin: 0 0 16px; }

body.v2 .kp__foot-actions { display: flex; flex-wrap: wrap; gap: 12px; }

body.v2 .kp__state { padding: 64px 0 96px; }

body.v2 .kp__state-text {
  font: var(--v2-body-lg);
  color: var(--asphalt-500);
}

@media (max-width: 720px) {
  /* Фото уходит наверх во всю ширину: на телефоне колонка 280px съедала
     больше половины строки, и характеристики набирались в два слова. */
  body.v2 .kp__subject { grid-template-columns: 1fr; }
  body.v2 .kp__photo { max-width: 380px; }
  body.v2 .kp__meta { gap: 12px 28px; }
}

@media (max-width: 560px) {
  /* Растягивается пара «кнопка + подпись» целиком, а не кнопка внутри неё:
     иначе подпись остаётся узкой колонкой сбоку от полноширинной кнопки. */
  body.v2 .kp__dl { flex: 1 1 100%; }
  body.v2 .kp__dl .v2-btn { width: 100%; }
  body.v2 .kp__dl-note { max-width: none; }
  body.v2 .kp__foot-actions .v2-btn { flex: 1 1 100%; }
  body.v2 .kp__total-value { font-size: 24px; }
}

/* ============================================================================
   ПЕЧАТЬ КП
   «Скачать PDF» до появления эндпоинта печатает страницу, и лист должен
   выглядеть документом, а не скриншотом сайта: с него уходят шапка, футер,
   плавающий круг связи и сами кнопки — нажать их на бумаге нельзя.
   Правила ограничены телом КП: печать остальных страниц сайта не трогаем.
   ============================================================================ */
@media print {
  /* .v2-dial-wrap — весь плавающий блок целиком: и круг связи, и кнопка
     размера шрифта. Скрывать .v2-dial отдельно недостаточно, это только
     круг, а «A+» остаётся стоять поверх характеристик. */
  body.v2 #siteHeader,
  body.v2 #siteFooter,
  body.v2 .kp__actions,
  body.v2 .kp__foot-actions,
  body.v2 .v2-dial-wrap { display: none !important; }

  /* Печатаем на белом при любой теме: тёмная заливка съедает картридж, а
     светлый бетон фона страницы на бумаге выходит грязно-серой заливкой
     под всем документом. Документ печатается чёрным по белому. */
  html, body.v2,
  html.dark, html.dark body.v2 { background: #fff; }

  body.v2 .kp { max-width: none; padding: 0; }

  body.v2 .kp__block {
    border: 0;
    padding: 0;
    margin-top: 18px;
    /* Раздел не разрывается между листами, если помещается целиком. */
    break-inside: avoid;
  }

  body.v2 .kp__group { break-inside: avoid; }

  /* Итог на бумаге — рамкой, а не заливкой: та же роль, без сплошного
     чёрного прямоугольника на весь лист. */
  body.v2 .kp__total {
    background: transparent;
    border: 2px solid #16181C;
    border-top: 6px solid #16181C;
    border-image: none;
  }

  body.v2 .kp__total-label,
  body.v2 .kp__total-value,
  body.v2 .kp__total-alt,
  body.v2 .kp__total-note { color: #16181C; }

  body.v2 .kp__table th { background: transparent; color: #16181C; border-bottom: 2px solid #16181C; }
}

/* ============================================================================
   ДВИЖЕНИЕ СИСТЕМЫ
   Всё, что двигается по своей воле, а не по наведению курсора, собрано
   здесь: проявление при прокрутке, отклик закладки, видео в hero. Курсорные
   жесты (подъём карточки, hover кнопки) остаются рядом со своими блоками —
   они часть внешнего вида компонента, а не отдельный слой.

   Правило системы: покоем управляет CSS, событием — JS. Классы .cm-reveal
   и .cm-bump вешает скрипт; в разметке их нет, поэтому страница без JS
   показывает всё содержимое сразу и ничего не теряет.
   ========================================================================= */

/* --- Проявление при прокрутке ------------------------------------------- */
/* 12px вверх — тот же порядок сдвига, что у v2-reveal (6px) и подъёма
   карточки (2–5px). Больше двадцати страница начинает «ехать», и на
   длинной сетке каталога это читается как рывок, а не как проявление.

   Переход только по opacity и transform: обе анимируются композитором, без
   пересчёта раскладки. Тянуть height/margin на секциях главной значило бы
   дёргать всё, что ниже, все 500 мс.

   --cm-reveal-delay ставит JS: соседи в одной пачке проявляются лесенкой
   по 70 мс. По умолчанию 0, чтобы одиночный элемент не ждал впустую. */
.cm-reveal {
  opacity: 0;
  transform: translateY(12px);
}

.cm-reveal--in {
  opacity: 1;
  transform: none;
  transition:
    opacity .5s cubic-bezier(.22, .61, .36, 1) var(--cm-reveal-delay, 0ms),
    transform .5s cubic-bezier(.22, .61, .36, 1) var(--cm-reveal-delay, 0ms);
}

/* Карточка каталога проявляется быстрее секции: их на экране до дюжины, и
   полсекунды на каждую превращают выдачу в затянутое слайд-шоу. */
.vp.cm-reveal--in,
.gallery-card.cm-reveal--in {
  transition-duration: .34s;
}

/* Подъём карточки по наведению живёт на том же transform, что и проявление
   (.vp, .gallery-card, .review-card, .hp-route__step — у всех hover тянет
   translateY). Пока карточка ещё спрятана, hover обязан молчать: курсор,
   случайно оказавшийся над ней до проявления, иначе выдёргивал бы её
   наверх раньше времени, а после — обрывал переход на середине.
   body.v2 в селекторе не для темы, а ради веса: подъёмы объявлены и так,
   и без него правило проигрывало бы им по специфичности. */
body.v2 .cm-reveal:hover,
.cm-reveal:hover { transform: translateY(12px); }

/* --- Отклик закладки «в избранное» --------------------------------------- */
/* 1 → 1.15 → 1 за 150 мс: короткий толчок, подтверждающий нажатие. Дольше
   150 мс это уже не отклик, а анимация, и на списке избранного, где
   карточка после нажатия уезжает, они накладываются друг на друга. */
.cm-bump { animation: cm-bump .15s ease-out; }

@keyframes cm-bump {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.15); }
  100% { transform: scale(1); }
}

/* --- Видео в hero -------------------------------------------------------- */
/* Фон .hp-hero остаётся фотографией и никуда не девается: видео ложится
   поверх и проявляется, только когда действительно пошло. Поэтому любой
   отказ — reduced-motion, экономия трафика, отсутствие кодека, ошибка
   сети — это просто «остались с фотографией», без пустого чёрного экрана
   и без единой строки обработки ошибок в разметке.

   Порядок слоёв: фото (фон секции) → видео (z-index 0) → скрим (1) →
   текст (2). Скрим написан для фотографии и одинаково работает поверх
   кадра — контраст заголовка от подмены фона не зависит. */
body.v2 .v2-hero__video {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Кадр снят под ту же композицию, что и фотография: центр по горизонтали,
     чуть выше центра по вертикали, чтобы техника не уходила под текст. */
  object-position: center 40%;
  opacity: 0;
  transition: opacity .6s ease-out;
  pointer-events: none;
}

/* Класс ставит JS по событию playing — не по canplay и не по loadeddata:
   до первого показанного кадра проявлять нечего, и на медленной сети
   видно, как проступает чёрный прямоугольник вместо фотографии. */
body.v2 .v2-hero__video.is-playing { opacity: 1; }

/* ============================================================================
   PREFERS-REDUCED-MOTION
   Системная настройка «меньше движения» — не пожелание, а требование: её
   включают при вестибулярных расстройствах, когда от параллакса и разъездов
   реально укачивает. Поэтому правило одно на весь лист и универсальное: любая
   новая анимация в системе выключается им автоматически, и не нужно помнить
   про неё в каждом следующем коммите.

   Длительности гасятся до 0.01ms, а не в none, намеренно: событие
   animationend/transitionend при этом продолжает приходить, и код, который
   на него завязан, не зависает. На этом стоит снятие класса .is-revealing
   у подробного расчёта.

   Три вещи сюда не попадают, потому что гасить длительность им мало —
   их проверяет сам JS через matchMedia:
     • счётчики чисел (cmCountUp) — сразу ставят конечное значение;
     • проявление при прокрутке (cmReveal) — вообще не вешает скрывающий
       класс, то есть секции никогда не оказываются спрятанными;
     • видео в hero — не получает src и не запускается, на экране остаётся
       фотография-постер.
   Правило ниже остаётся сеткой безопасности для всего остального.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Видео при этой настройке не запускается вовсе (см. initHeroVideo), но
     если элемент всё же оказался в кадре — он не должен перекрывать
     фотографию, ради которой всё и затевалось. */
  body.v2 .v2-hero__video { display: none; }
}
