/* ══════════════════════════════════════════════════════════════════════════
   Соты — ВТОРАЯ ВЕРСИЯ: грамматика deepseek.com/harness.

   Значения ниже — не «в духе DSH», а СНЯТЫЕ с живой страницы 2026-08-26
   (Chrome, 1440×900, getComputedStyle; тот же метод, что у ref/warp-outline.json):

     грунт           ОДИН, #0a0a0a, сверху донизу (красит body, секции прозрачны)
     высота          5999px · 569 слов · 5 картинок · 1 видео
     контейнер       1280 max-width, ~1140 контента
     ритм            120/120 у всех секций; hero — исключение (0/0, ровно 900px)
     hero            900px = РОВНО один экран
     h1              46 / 500 / -0.92px / 55.2px
     h2              36 / 500 / -0.72px / 54px   ← ОДИН кегль на ВСЕ секции
     лид             18 / 500

   ЧТО ИСПРАВЛЕНО ПРОТИВ HANDOFF'а. Хендофф пишет «alignment: headings CENTRED
   ← ключевое расхождение с warp». Это НЕВЕРНО, и я перемерил: у DSH заголовки
   ЧЕРЕДУЮТСЯ. Замер 2026-08-26 по пяти секционным h2:
     thesis   center · design-approach start · video center · get-started start · closing center
   Hero тоже прижат ВЛЕВО. То есть грамматика DSH — не «всё по центру», а
   «центр ↔ лево через секцию», где центр достаётся тезису и призывам, а лево —
   секциям с механикой. Это скопировано здесь буквально.

   ОСОЗНАННОЕ ОТЛИЧИЕ ОТ РЕФЕРЕНСА: грунт у нас #151517 (графит), а не #0a0a0a.
   Это выбор Рустама после таблицы восьми референсов, и он не пересматривается
   сборкой страницы.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── грунт и поверхности ───────────────────────────────────────────────
     Лестница из ТРЁХ ступеней, как у DSH: грунт → карта → карта-в-карте.
     Всё это ОДИН фон в смысле гейта: секции прозрачны, красит body. */
  --bg:            #151517;
  --surface:       #1c1c1f;
  --surface-2:     #232326;
  --line:          rgb(255 255 255 / .09);
  --line-strong:   rgb(255 255 255 / .16);

  /* ── текст ─────────────────────────────────────────────────────────────
     Три роли и ни одной больше. Четвёртая всегда оказывается «почти как
     вторая» и разъезжается между секциями. */
  --fg:            #f5f6f7;
  --fg-2:          #a1a5ab;
  --fg-3:          #71767c;
  --fg-dim:        rgb(245 246 247 / .26);   /* погашенный шаг аккордеона */

  --accent:        #679efe;                  /* == --focus-on-dark боевой темы */
  --accent-soft:   rgb(103 158 254 / .14);
  --mint:          #e6faed;
  --mint-ink:      #233c2c;

  /* светлое полотно продукта — кадры приложения остаются СВЕТЛЫМИ, потому что
     приложение светлое. Тёмный «скриншот» тёмной страницы ради красоты был бы
     враньём о продукте. */
  --paper:         #fff;
  --paper-2:       #f1f3f5;
  --ink:           #0f1115;
  --ink-2:         #61666b;

  --font-display: 'Golos Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-body:    'Golos Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', monospace;

  /* Ритм DSH: 120/120. У нас на 8px-сетке — 120 ровно. */
  --rhythm: 120px;
  --gutter: 32px;
  --container: 1140px;
  --radius: 14px;                            /* карточный радиус DSH */
  --control: 48px;                           /* минимальная высота контрола */

  --mark-bg: #f7f6f3;                        /* канон знака — не палитра страницы */
  --mark-fg: #14181f;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  /* ОДИН ФОН НА ВСЮ СТРАНИЦУ. Секции прозрачны; ничего, кроме body, грунт не
     красит. Атмосфера первого экрана делается ЗАТУХАЮЩИМ градиентом внутри
     hero, а не второй заливкой — иначе появляется второй грунт. */
  background: var(--bg);
  color: var(--fg);
  font: 400 16px/1.6 var(--font-body);
  font-feature-settings: 'ss01' 1;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px;
}

.skip-link {
  position: absolute; left: -9999px; top: 12px; z-index: 200;
  padding: 12px 18px; background: var(--fg); color: var(--bg); border-radius: 10px;
}
.skip-link:focus { left: 12px; }

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* Базовый размер иконки. Без него <svg> без width/height растягивается по
   контейнеру: часы в подписи шага рисовались в 34px и ломали строку. Правило
   стоит ОДИН раз и здесь, а не в каждой секции. */
.ic { width: 17px; height: 17px; flex: 0 0 auto; }

/* ── типографская шкала ───────────────────────────────────────────────────
   h2 — ОДИН кегль на всю страницу. Это главный инвариант, ради которого
   вся перестройка и затевалась: семь из восьми измеренных референсов
   держат ровно один. Поэтому здесь h2 задаётся ОДИН раз и нигде больше
   не переопределяется — ни в секции, ни в медиазапросе, кроме одного
   мобильного шага для всех сразу. */
h1 {
  font-family: var(--font-display);
  font-size: clamp(2.125rem, 1.2rem + 2.6vw, 2.875rem);   /* 34 → 46 */
  font-weight: 500; letter-spacing: -.02em; line-height: 1.2;
}
h2 {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.15rem + 1.7vw, 2.25rem);    /* 28 → 36 */
  font-weight: 500; letter-spacing: -.02em; line-height: 1.2;
}
h3 {
  font-family: var(--font-display);
  font-size: 1.25rem; font-weight: 500; letter-spacing: -.014em; line-height: 1.3;
}

.lead {
  max-width: 62ch;
  color: var(--fg-2);
  font-size: 1.125rem; font-weight: 450; line-height: 1.55;
}

/* ── контейнер и ритм ─────────────────────────────────────────────────────
   Ритм — свойство СЕКЦИИ, не её содержимого, и он одинаков у всех. Как
   только ритм начинают править «по месту», страница возвращается к
   0/0, 0/96, 96/96 — ровно тому, из-за чего затевалась перестройка. */
.wrap { width: min(100% - var(--gutter) * 2, var(--container)); margin-inline: auto; }
.sec { padding-block: var(--rhythm); }

/* ── пилюля-ярлык секции: подпись DSH ─────────────────────────────────────
   Моноширинный, капсом, с разрядкой, на приподнятой плитке. У DSH это
   единственный «надзаголовок» на странице — он заменяет собой айброу и
   не спорит с h2, потому что читается как ярлык, а не как фраза. */
.pill {
  display: inline-flex; align-items: center; height: 32px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface);
  color: var(--fg-2);
  font-family: var(--font-mono); font-size: .75rem; font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
}

.sec__head { display: grid; gap: 20px; justify-items: start; }
/* justify-items: start — иначе .pill в grid-голове растягивается во всю
   ширину контейнера и читается как полоса, а не как ярлык. */
.sec__head--center { justify-items: center; text-align: center; }
.sec__head--center .lead { text-align: center; }
.sec__head h2 { max-width: 22ch; }
.sec__head--center h2 { max-width: 24ch; }

/* ── кнопки: пилюли DSH, 48px ─────────────────────────────────────────────
   У DSH ровно два вида: белая заливка (одна на экран) и тёмная плитка с
   рамкой. Третьего нет — и как только он появляется, страница перестаёт
   говорить, куда нажимать. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: var(--control); padding: 0 22px;
  border: 1px solid transparent; border-radius: 999px;
  font-size: .9375rem; font-weight: 500; letter-spacing: -.006em;
  transition: background-color .16s ease, border-color .16s ease, translate .1s ease;
}
.btn:active { translate: 0 1px; }        /* как в продукте: translate, не scale */
.btn--primary { background: var(--fg); color: #101013; }
.btn--primary:hover { background: #fff; }
.btn--ghost { background: var(--surface); border-color: var(--line); color: var(--fg); }
.btn--ghost:hover { background: var(--surface-2); border-color: var(--line-strong); }
.btn .ic { width: 17px; height: 17px; flex: 0 0 auto; }

/* ── шапка: ОДНА плавающая пилюля по центру ───────────────────────────────
   У DSH шапка — одна пилюля с блюром, а не два острова по углам. На боевой
   странице сейчас именно два: белая плитка логотипа слева и белая плитка
   кнопок справа, и на графите они читаются как два несвязанных объекта.
   Здесь — один объект. */
.mast {
  position: fixed; inset: 12px 0 auto; z-index: 90;
  display: flex; justify-content: center; pointer-events: none;
}
.mast__in {
  pointer-events: auto;
  display: flex; align-items: center; gap: 12px;
  width: min(100% - 24px, var(--container));
  height: 64px; padding: 0 8px 0 16px;
  border: 1px solid var(--line); border-radius: 999px;
  background: rgb(28 28 31 / .72);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
}
.mast__brand { display: flex; align-items: center; min-height: 48px; gap: 10px; font-family: var(--font-display);
  font-size: 1.0625rem; font-weight: 500; letter-spacing: -.03em; }
.mast__brand .mark { width: 28px; height: 28px; border-radius: 8px; }
.mast__chip {
  height: 24px; padding: 0 9px; display: inline-flex; align-items: center;
  border: 1px solid var(--line); border-radius: 999px; background: rgb(255 255 255 / .04);
  color: var(--fg-2); font-family: var(--font-mono); font-size: .6875rem; letter-spacing: .04em;
}
.mast__spacer { flex: 1 1 auto; }
.mast__login { display: inline-flex; align-items: center; min-height: 48px; padding: 0 14px;
  color: var(--fg-2); font-size: .875rem; }
.mast__login:hover { color: var(--fg); }
.mast__cta { min-height: 48px; padding: 0 18px; font-size: .875rem; }

/* ── 01 · HERO ────────────────────────────────────────────────────────────
   Раскладка боевой версии: одна центрованная колонка, кадр продукта под
   копией. Решение Рустама 26.08 — на телефоне колонка читается лучше сплита,
   и это видно: у сплита на 390px правая карта уезжает под копию и первый
   экран становится длиннее, чем один экран, всё равно.

   Отсюда ДВА следствия, которые важнее удобства:
   · Первого экрана ровно в 900px больше НЕТ. У DSH hero — ровно один экран,
     это был снятый инвариант; кадр под копией ломает его по построению.
     Высота теперь задаётся содержимым, как у боевой версии (1286px).
   · Айброу снят вместе со сплитом — раскладка боевой версии его не несёт,
     и решение 25.08 «айброу не нужен» снова в силе. */
.hero {
  position: relative;
  padding-block: 132px 0;
  overflow: clip;
}
/* Атмосфера первого экрана — ЗАТУХАЮЩИЙ слой поверх грунта, а не второй фон:
   он заканчивается ровно тем же #151517, поэтому обход предков находит один
   и тот же цвет, и гейт «фон один» остаётся честным. */
.hero::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(86% 62% at 78% 4%, rgb(103 158 254 / .24), transparent 62%),
    radial-gradient(64% 46% at 12% 2%, rgb(140 120 255 / .12), transparent 66%),
    linear-gradient(180deg, rgb(21 21 23 / 0) 46%, var(--bg) 88%);
}
/* Тонкая сетка первого экрана — приём референса. Второго фона не создаёт:
   линии полупрозрачные и гасятся маской, грунт под ними один и тот же. */
.hero::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    linear-gradient(rgb(255 255 255 / .026) 1px, transparent 1px) 0 0 / 100% 88px,
    linear-gradient(90deg, rgb(255 255 255 / .026) 1px, transparent 1px) 0 0 / 88px 100%;
  -webkit-mask-image: radial-gradient(110% 62% at 50% 6%, #000 8%, transparent 74%);
  mask-image: radial-gradient(110% 62% at 50% 6%, #000 8%, transparent 74%);
}
.hero__body {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
.hero h1 { max-width: 20ch; text-wrap: balance; }
.hero__lead { max-width: 54ch; margin-top: 20px; color: var(--fg-2);
  font-size: 1.125rem; font-weight: 450; line-height: 1.55; text-wrap: pretty; }
.hero .btn { margin-top: 30px; }
/* Кадр не во всю ширину контейнера: 940 вместо 1140. Он читается как ПРЕДМЕТ
   на графите, а не как фон, и мастер 2560px даёт на нём 2.7x вместо 2x. */
.hero__frame { width: min(100%, 940px); margin: 48px auto 0; }

/* ── рама окна: ОДНА на страницу ──────────────────────────────────────────
   Точки слева, пилюля адреса по центру. Сетка 1fr-auto-1fr, а не flex с
   margin:auto: flex центрировал бы пилюлю со сдвигом на ширину точек.
   Той же рамой одеты три кадра сцены — две разные рамы на одной странице
   читались бы как две разные грамматики. */
.window { overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 0 0 1px rgb(0 0 0 / .5), 0 24px 64px -12px rgb(0 0 0 / .62),
    0 48px 120px -24px rgb(0 0 0 / .45); }
.window__bar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  height: 44px; padding-inline: 14px;
  border-bottom: 1px solid var(--line); background: var(--surface-2); }
.window__dots { display: flex; gap: 7px; justify-self: start; }
.window__dots i { width: 9px; height: 9px; border-radius: 50%; background: rgb(255 255 255 / .16); }
.window__url { justify-self: center; padding: 4px 14px; border-radius: 999px;
  background: rgb(255 255 255 / .07); color: var(--fg-2);
  font-family: var(--font-mono); font-size: .75rem; letter-spacing: .01em; }
.window img { width: 100%; height: auto; }
.window__paper { padding: 20px; background: var(--paper); color: var(--ink); }

/* ── 02 · ТЕЗИС ──────────────────────────────────────────────────────────
   У DSH: моно-пилюля с формулой, гигантский логотип, центрованный h2,
   центрованный лид, три карточки с линейными иконками. Формула в пилюле —
   лучший ход всей страницы: она объясняет продукт одной строкой ДО того,
   как читатель прочёл хоть один абзац. */
.thesis__formula { justify-self: center; }
.thesis__cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; margin-top: 36px; }
.thesis__card { display: grid; justify-items: center; gap: 13px; padding: 34px 26px 30px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  text-align: center; }
.thesis__card .ic { width: 34px; height: 34px; color: var(--fg-2); }
.thesis__card h3 { color: var(--fg); }
.thesis__card p { color: var(--fg-2); font-size: .9375rem; line-height: 1.6; }

/* ── 03 · КАК ЭТО РАБОТАЕТ · подпись DSH ─────────────────────────────────
   Аккордеон, ведомый СКРОЛЛОМ: слева три шага, активный — белый, остальные
   погашены; справа липкий кадр продукта, который меняется под активный шаг.
   Это единственная механика страницы-референса, и она делает всю её живость.
   Табы боевой версии решают ту же задачу кликом; здесь — скроллом, то есть
   без единого лишнего интерактивного элемента в бюджете. */
/* Колонка текста УЖЕ, зазор МЕНЬШЕ — всё ради ширины кадра, и вот счёт.
   Было 420 + 112 + 608: кадр показывался в 512px. Снят он при окне 980 CSS,
   значит масштаб 512/980 = 0.52x, и текст приложения 14px приходил
   семипиксельным — та же болезнь, из-за которой переснимался первый экран,
   просто этажом ниже.
   Стало 360 + 80 + 700: внутри сцены остаётся ~604px, а кадры шагов сняты
   при окне 640 CSS (приложение само сужает колонку сообщений: 640→512,
   720→592, 900→748). 640 в 604 — это 0.94x, те же 14px приходят
   тринадцатипиксельными, вровень с первым экраном.
   360px под текст хватает: у шага две строки заголовка и три строки абзаца,
   мера 42ch всё равно не выбиралась. */
.how__grid { display: grid; grid-template-columns: minmax(0, 360px) minmax(0, 1fr); gap: 80px;
  margin-top: 52px; align-items: start; }
.how__steps { display: grid; }
.how__step { padding-block: 48px; }
.how__step:first-child { padding-top: 0; }
.how__step:last-child { padding-bottom: 0; }
.how__step > div { transition: opacity .35s ease; opacity: .2; }
.how__step[data-active='1'] > div { opacity: 1; }

/* ДЛИНА ПРОКРУТКИ НА ШАГ — вот в чём была поломка, а не в самой механике.
   Кадр действительно липкий и действительно меняется; закол при этом не
   читался, потому что читать было нечего. При padding 48px вся колонка из
   трёх шагов ~730px: все три помещаются на экране разом, кадр успевает
   смениться дважды за пол-оборота колеса, и «стоит на месте, пока текст
   идёт мимо» физически не наступает — нечему стоять.

   У референса соседние пункты разнесены примерно НА ЭКРАН. Отсюда 78svh:
   один шаг — один оборот, ровно один пункт зажжён, и кадр держится
   неподвижным целую высоту экрана. svh, а не vh: на телефонном Safari vh
   считается по РАЗВЁРНУТОМУ окну и при живой панели адреса шаг оказывается
   выше экрана. Здесь правило и так живёт только от 1020px, но единицу
   ставим правильную — она переживёт перенос.

   Контент прижат к ВЕРХУ коробки, а не центрован: центрование отодвинуло бы
   первый шаг на 39svh от заголовка секции, и вход в секцию читался бы дырой.
   Из этого следует, что активный шаг НЕЛЬЗЯ считать по коробке — её центр на
   39svh ниже текста, и шаг зажигался бы, когда его текст уже уехал за верх
   экрана. Движок поэтому меряет `.how__step > div`, а не саму секцию; правило
   и замер — одна пара, порознь они врут.

   Цена по высоте зафиксирована в ref/warp-outline.json →
   sotyTargets._volumeRationale вместе с замером референса. */
@media (min-width: 1020px) {
  /* 585px НА ШАГ — это не «примерно экран на глаз», а СНЯТОЕ с референса
     число. Замер deepseek.com/harness 2026-08-26, 1440×900, тем же способом,
     что и остальная шапка этого файла:

       вся страница        5999px
       секция аккордеона   1754px  → 1754 / 3 шага = 585px на шаг
       липкий кадр         615×384, top: 258px
       кадр стоит          1754 − 384 = 1370px  (78% от прокрутки шагов)

     Первая попытка правки поставила 78svh (702), вторая 70svh (630) плюс
     разбег 240 и выбег 320 — то есть кадр стоял 1973px при 1890px прокрутки
     шагов, 104%. Это БОЛЬШЕ, чем у референса, и лишние ~800px высоты не
     покупали ничего: закол уже читался. 65svh при 900px экрана даёт ровно
     585px, и доля неподвижности выходит 73% — вровень с 78% у DSH.

     svh, а не vh: на телефонном Safari vh считается по РАЗВЁРНУТОМУ окну, и
     при живой панели адреса шаг оказывается выше экрана. Правило живёт только
     от 1020px, но единица должна быть верной — она переживёт перенос. */
  .how__step { min-height: 65svh; padding-block: 0; }
  .how__step:last-child { min-height: 65svh; }

  /* РАЗБЕГ ЕСТЬ, ВЫБЕГА НЕТ — и то и другое посчитано, а не на глаз.

     Липкий элемент прикалывается на своих top:150 от верха сетки, а первый
     шаг подсвечен с самого входа в секцию. Без разбега на него приходилось
     ~170 прокрученных пикселей неподвижности: кадр стоял по-настоящему
     только под вторым шагом, отчего и казалось, что закола нет вовсе.
     Разбег 160 доводит первый шаг до ~330px.

     ВЫБЕГА НЕТ НАМЕРЕННО. Липкий элемент отрывается на СВОЮ высоту раньше
     конца контейнера — это устройство sticky, а не недосмотр, и у референса
     ровно так же: 1370px неподвижности при 1754px прокрутки, то есть третий
     шаг там тоже дочитывается уже отъезжающим кадром. Прошлая редакция
     добивала хвост выбегом 320px и доводила долю до 104% — больше, чем у
     референса, за 320px высоты, которых закол не просил.

     Замерено (scratchpad/pin2.js, 1440×900, устоявшаяся страница):
       БЫЛО:  кадр стоит 36px за всю секцию — сетка 513 при кадре 477
       СТАЛО: ~1440px неподвижности при 1755px прокрутки шагов (73%),
              против 1370/1754 (78%) у референса

     Разбег заодно чинит вход в секцию: заголовок и первый шаг больше не
     слипаются. Это следствие, а не повод — повод в числах выше. */
  .how__steps { padding-block: 160px 0; }
}
.how__step-head { display: flex; align-items: center; gap: 12px; }
.how__step-head .ic { width: 22px; height: 22px; color: var(--fg); }
.how__step-head h3 { font-size: 1.375rem; }
.how__step p { margin-top: 14px; color: var(--fg-2); font-size: 1rem; line-height: 1.65; max-width: 42ch; }
.how__step-meta { display: inline-flex; align-items: center; gap: 8px; margin-top: 16px;
  color: var(--fg-3); font-family: var(--font-mono); font-size: .75rem; letter-spacing: .05em;
  text-transform: uppercase; }

/* Кадр приколот по ЦЕНТРУ экрана, а не к его верху: у референса он держится
   на уровне глаз, и шаг слева меняется напротив него. top:120 прижимал кадр к
   шапке, и связь «этот текст — про этот кадр» приходилось достраивать самому.
   Высота кадра фиксирована (все три 3:2), поэтому центр считается один раз. */
.how__stage { position: sticky; top: max(96px, calc(50vh - 300px)); }
.how__frames { position: relative; }
.how__frame { transition: opacity .35s ease; }
.how__frame[hidden] { display: none; }

/* Полотно внутри рамы СВЕТЛОЕ, потому что приложение светлое: перекрасить
   его в тёмное ради единства страницы значило бы соврать о продукте. Рама и
   её поля удерживают светлое пятно внутри предмета, а не разливают его на всю
   ширину — именно этим боевая версия ломает собственное правило «один грунт».
   Сама рама объявлена выше, у первого экрана: она одна на страницу. */
.window { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  overflow: hidden; box-shadow: 0 24px 64px rgb(0 0 0 / .4); }
.window__bar { display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 14px;
  border-bottom: 1px solid var(--line); background: var(--surface-2); }
.window__dots { display: flex; gap: 6px; }
.window__dots i { width: 9px; height: 9px; border-radius: 50%; background: rgb(255 255 255 / .16); }
.window__title { color: var(--fg-3); font-family: var(--font-mono); font-size: .75rem; }
.window__paper { padding: 20px; background: var(--paper); color: var(--ink); }

/* содержимое светлого полотна — код-рендер, не растр из макета */
.paper-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px;
  align-items: baseline; padding: 12px 2px; border-bottom: 1px solid #ececee; }
.paper-row:last-child { border-bottom: 0; }
.paper-row > span { color: var(--ink-2); font-size: .875rem; }
.paper-row > strong { font-size: .875rem; font-weight: 500; color: var(--ink); }
.paper-row small { grid-column: 1 / -1; display: inline-flex; align-items: center; gap: 6px;
  margin-top: 3px; color: var(--ink-2); font-size: .75rem; }
.paper-row .ic { width: 13px; height: 13px; }
.paper-row.is-answer { background: var(--mint); color: var(--mint-ink); margin-inline: -20px;
  padding-inline: 20px; border-bottom-color: transparent; }
.paper-row.is-answer > span, .paper-row.is-answer small { color: var(--mint-ink); }
.paper-row.is-answer > strong { color: var(--mint-ink); }

.paper-head { display: flex; align-items: center; gap: 11px; padding-bottom: 14px;
  border-bottom: 1px solid #ececee; margin-bottom: 6px; }
.paper-head img { width: 34px; height: 34px; border-radius: 9px; object-fit: cover; background: var(--paper-2); }
.paper-head strong { display: block; font-size: .875rem; font-weight: 500; color: var(--ink); }
.paper-head span { display: block; color: var(--ink-2); font-size: .75rem; }
.paper-quote { padding: 12px 14px; border-radius: 10px; background: var(--paper-2);
  color: var(--ink); font-size: .875rem; line-height: 1.5; }
.paper-project { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 14px;
  align-items: center; padding: 12px 0; border-bottom: 1px solid #ececee; }
.paper-project img { width: 96px; height: 62px; border-radius: 8px; object-fit: cover; }
.paper-project h4 { margin: 0; font-family: var(--font-display); font-size: .9375rem;
  font-weight: 500; color: var(--ink); }
.paper-project p { color: var(--ink-2); font-size: .75rem; line-height: 1.45; margin-top: 2px; }
.paper-project b { display: block; margin-top: 4px; font-size: .8125rem; font-weight: 500; color: var(--ink); }
.paper-list { display: grid; gap: 12px; }
.paper-list li { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 10px; align-items: start; }
.paper-list .ic { width: 15px; height: 15px; margin-top: 3px; color: #1e40af; }
.paper-list strong { display: block; font-size: .875rem; font-weight: 500; color: var(--ink); }
.paper-list p { color: var(--ink-2); font-size: .8125rem; line-height: 1.5; }
.paper-ready { display: inline-flex; align-items: center; gap: 8px; margin-top: 14px;
  padding: 9px 13px; border-radius: 999px; background: var(--mint); color: var(--mint-ink);
  font-size: .8125rem; }
.paper-ready .ic { width: 14px; height: 14px; }

/* ── цитата: интерстишал, не секция ──────────────────────────────────────
   Без h2 — поэтому единственный кегль секционных заголовков не ломается.
   У DSH цитат нет вообще, но это наш самый сильный актив, и грамматика
   «крупное центрованное утверждение на голом грунте» у DSH ЕСТЬ — тезис
   второй секции устроен ровно так. */
/* Интерстишал берёт половину ритма: это не секция, у неё нет h2, и полный
   ритм с обеих сторон делал из неё лишнюю «секцию» по весу. */
.quote { padding-block: var(--rhythm); }
/* Мера 30ch стояла под ДРУГОЙ блок: пока под цитатой была пара «2–4 часа →
   30 минут», узкая колонка читалась как плита с опорой. Опору сняли (решение
   Рустама 26.08), и та же мера превратила цитату в десятистрочную стену.
   Цитата у нас 300 знаков — это не короткое центрованное утверждение
   референса, и мера должна считаться от ЕЁ длины: 820px при 26px — шесть
   строк, столько же, сколько у боевой версии. */
.quote blockquote { max-width: min(100%, 820px); margin-inline: auto; text-align: center;
  font-family: var(--font-display); font-size: clamp(1.1875rem, .85rem + 1.1vw, 1.625rem);
  font-weight: 500; letter-spacing: -.018em; line-height: 1.38; text-wrap: pretty; }
/* Первая цитата — сразу под первым экраном и КРУПНЕЕ второй. Две одинаковые
   центрованные цитаты на одной странице читались бы как повтор одного приёма;
   разный кегль говорит, что это разные показания, а не одно, разрезанное
   пополам.

   ОТСТУП СВЕРХУ — ДВОЙНОЙ, и это не украшение. Зазор, который человек видит,
   складывается из отступов ОБОИХ соседей. Снизу их два: свои 120 плюс 120 у
   тезиса — итого 240. Сверху сосед — hero, а у него `padding-block: 132px 0`,
   нижнего отступа нет вовсе: все 120 цитаты и есть весь зазор. Строка,
   стоявшая здесь раньше, утверждала «сверху ритм полный» — она считала СВОЙ
   отступ, а не расстояние, и потому была неверна: 120 против 240, цитата
   липла к кадру первого экрана. Правка ставится ЗДЕСЬ, а не нижним отступом
   у hero: первый экран — решение Рустама 26.08 целиком (копия, раскладка,
   кадр), и трогать его ритм значит переоткрывать закрытое.
   Оракул — scratchpad/spacing.js: gapAbove == gapBelow == 240. */
.quote--first { padding-block: calc(var(--rhythm) * 2) var(--rhythm); }
.quote--first blockquote { max-width: min(100%, 880px);
  font-size: clamp(1.3125rem, .9rem + 1.35vw, 1.875rem); line-height: 1.34; }
.quote__by { margin-top: 22px; text-align: center; color: var(--fg-3); font-size: .875rem; }

/* ── 04 · ЧЕК ────────────────────────────────────────────────────────────
   У DSH этот слот занимает видео: центрованный заголовок и ОДИН крупный
   объект под ним. Видео у нас нет (решение отложено), а объект есть — чек
   расчёта. Слот занят по назначению: один герой, ничего рядом. */
.receipt { width: min(100%, 700px); margin: 32px auto 0; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); color: var(--ink);
  box-shadow: 0 24px 64px rgb(0 0 0 / .4); }
/* Шапка чека — ТЁМНАЯ полоса внутри светлой карты.
   Все цвета текста здесь заданы ЯВНО и от токенов тёмной роли. На боевой
   странице этот же блок сломан: правило `.craft-proof .craft-receipt h3,
   strong { color: var(--ink) }` (base.css:1018) красит в #0f1115 ВЕСЬ чек,
   включая эту тёмную полосу, — и заголовок с суммой «200 000 ₽» становятся
   почти невидимыми на графите. Здесь такого сквозного правила нет
   по построению: тёмная полоса красит своё содержимое сама. */
.receipt__result { position: relative; overflow: hidden; padding: 22px 24px 20px;
  background: var(--bg); color: var(--fg); }
.receipt__result::after { content: ''; position: absolute; right: -80px; top: -120px;
  width: 230px; height: 230px; border-radius: 50%; background: var(--accent-soft);
  filter: blur(4px); pointer-events: none; }
.receipt__result > * { position: relative; z-index: 1; }
.receipt__label { display: flex; align-items: center; gap: 10px; color: var(--fg-2); font-size: .8125rem; }
.receipt__label img { width: 32px; height: 32px; border-radius: 9px; object-fit: cover;
  background: rgb(255 255 255 / .08); }
.receipt__result h3 { margin-top: 16px; max-width: 25ch; color: var(--fg); font-size: 1.375rem; }
.receipt__payment { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 12px; margin-top: 14px; }
.receipt__payment strong { color: var(--accent); font-family: var(--font-mono);
  font-size: clamp(2rem, 1.2rem + 2.4vw, 2.75rem); font-weight: 500; line-height: 1;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.receipt__payment span { color: var(--fg-2); font-size: .875rem; }
.receipt__next { display: flex; align-items: flex-start; gap: 8px; max-width: 50ch; margin-top: 18px;
  padding-top: 15px; border-top: 1px solid rgb(255 255 255 / .18); color: var(--fg-2); font-size: .8125rem;
  line-height: 1.45; }
.receipt__next .ic { width: 15px; height: 15px; flex: 0 0 auto; margin-top: 2px; }

.receipt__query { padding: 15px 22px; background: var(--paper-2); }
.receipt__query > span { display: block; color: var(--ink-2); font-size: .8125rem; }
.receipt__query p { margin-top: 6px; font-weight: 500; line-height: 1.5; }
.receipt__section { padding: 16px 22px 4px; color: var(--ink-2); font-size: .8125rem; }
.receipt__row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px;
  align-items: baseline; padding: 10px 22px; border-bottom: 1px solid #ececee; }
.receipt__row > span { color: var(--ink); font-size: .9375rem; }
.receipt__row > strong { font-size: .9375rem; font-weight: 500; text-align: right; }
/* Источник — ПОД ярлыком строки, в первой колонке, а не отдельной строкой во
   всю ширину: во всю ширину семь источников давали +175px в самой длинной
   секции страницы и разрывали пару «показатель ↔ значение». */
.receipt__row small { grid-column: 1; display: inline-flex; align-items: center; gap: 6px;
  color: var(--ink-2); font-size: .75rem; }
.receipt__row .ic { width: 13px; height: 13px; }
.receipt__row.is-total { background: var(--mint); color: var(--mint-ink); border-bottom-color: transparent; }
.receipt__row.is-total > span, .receipt__row.is-total > strong, .receipt__row.is-total small { color: var(--mint-ink); }
.receipt__row.is-empty { background: var(--paper-2); border-bottom: 0; }
.receipt__row.is-empty > strong { color: var(--ink-2); }
.receipt__formula { padding: 16px 22px 18px; border-top: 1px solid #ececee; background: var(--paper); }
.receipt__formula > span { display: flex; align-items: center; gap: 8px; color: var(--ink-2); font-size: .8125rem; }
.receipt__formula .ic { width: 15px; height: 15px; color: #1e40af; }
.receipt__formula ol { display: grid; gap: 7px; margin-top: 11px; }
.receipt__formula li { color: var(--ink-2); font-size: .8125rem; line-height: 1.5; }

/* ── 05 · С ЧЕГО НАЧАТЬ ──────────────────────────────────────────────────
   У DSH здесь ДВЕ карты рядом: «Quick start» и «Install from source». Слот
   ровно под два входа в продукт — и у нас их ровно два. */
.start__cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; margin-top: 36px; }
.start__card { display: grid; align-content: start; gap: 14px; padding: 32px 30px 30px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.start__card h3 { color: var(--fg); }
.start__card > p { color: var(--fg-2); font-size: .9375rem; line-height: 1.6; }
.start__price { display: flex; align-items: baseline; gap: 10px; }
.start__price strong { font-family: var(--font-display); font-size: 1.75rem; font-weight: 500;
  letter-spacing: -.025em; }
.start__price span { color: var(--fg-3); font-size: .875rem; }
.start__card ul { display: grid; gap: 9px; margin-top: 4px; }
.start__card li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 9px;
  color: var(--fg-2); font-size: .875rem; line-height: 1.5; }
.start__card li .ic { width: 15px; height: 15px; margin-top: 3px; color: var(--accent); }
.start__card .btn { margin-top: 8px; justify-self: start; }
.start__note { margin-top: 26px; color: var(--fg-3); font-size: .875rem; }
.start__note a { color: var(--accent); }

/* ── 06 · ВОПРОСЫ ────────────────────────────────────────────────────────*/
.faq__grid { display: grid; grid-template-columns: minmax(0, 320px) minmax(0, 1fr); gap: 64px;
  align-items: start; }
.faq__grid .sec__head { align-content: start; }
.faq__list { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden; }
.faq__list details { border-bottom: 1px solid var(--line); }
.faq__list details:last-child { border-bottom: 0; }
.faq__list summary { display: flex; align-items: center; justify-content: space-between; gap: 20px;
  min-height: 64px; padding: 14px 22px; color: var(--fg); font-size: 1rem; font-weight: 500;
  letter-spacing: -.012em; cursor: pointer; list-style: none; }
.faq__list summary::-webkit-details-marker { display: none; }
.faq__list summary::after { content: ''; flex: 0 0 auto; width: 15px; height: 15px;
  background: linear-gradient(var(--fg-3), var(--fg-3)) center / 13px 1.5px no-repeat,
              linear-gradient(var(--fg-3), var(--fg-3)) center / 1.5px 13px no-repeat; }
.faq__list details[open] summary::after { background: linear-gradient(var(--fg-3), var(--fg-3)) center / 13px 1.5px no-repeat; }
.faq__list summary:hover { background: var(--surface-2); }
.faq__list details > div { padding: 0 56px 20px 22px; color: var(--fg-2); font-size: .9375rem; line-height: 1.6; }
.faq__list details > div a { color: var(--accent); }
.faq__aside { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 20px;
  color: var(--fg-3); font-size: .875rem; }
.faq__aside a { display: inline-flex; align-items: center; min-height: 48px; color: var(--accent); }

/* ── 07 · ФИНАЛЬНЫЙ CTA ──────────────────────────────────────────────────
   Центрованный заголовок, лид, пилюли — как у DSH. Тихий звёздный слой,
   который начинается и заканчивается грунтом, чтобы фон остался один. */
.final { position: relative; padding-block: var(--rhythm); overflow: clip; }
.final::before { content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(70% 90% at 50% 100%, rgb(103 158 254 / .13), transparent 68%); }
.final > .wrap { position: relative; }
.final__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 28px; }
.final__note { margin-top: 24px; text-align: center; color: var(--fg-3); font-size: .875rem; }

/* ── футер: тонкий, как у DSH ────────────────────────────────────────────
   У DSH футер — узкая полоса со ссылками слева и справа. Мы обязаны нести
   больше (ИНН, четыре документа — чек-лист эквайера), но НЕ обязаны нести
   1000–1200px пустоты: именно столько сейчас на боевой странице, где
   min-height остался от снятой фотоплиты. Здесь высота — по содержимому. */
.foot { border-top: 1px solid var(--line); padding-block: 44px 16px; }
.foot__top { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 56px; }
.foot__brand { display: flex; align-items: center; gap: 11px; font-family: var(--font-display);
  font-size: 1.125rem; font-weight: 500; letter-spacing: -.03em; }
.foot__brand .mark { width: 30px; height: 30px; border-radius: 8px; }
.foot__top > div:first-child p { margin-top: 12px; max-width: 40ch; color: var(--fg-2);
  font-size: .875rem; line-height: 1.55; }
.foot nav { display: grid; grid-template-columns: repeat(3, minmax(120px, auto)); gap: 40px; }
.foot nav > div { display: grid; align-content: start; gap: 2px; }
.foot nav strong { margin-bottom: 8px; color: var(--fg-3); font-size: .75rem;
  font-weight: 500; letter-spacing: .04em; text-transform: uppercase; }
.foot nav a { display: inline-flex; align-items: center; min-height: 48px; color: var(--fg-2); font-size: .875rem; }
.foot nav a:hover { color: var(--fg); }
.foot__bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 4px 24px;
  margin-top: 32px; padding-top: 12px; border-top: 1px solid var(--line);
  color: var(--fg-3); font-size: .8125rem; }
.foot__bottom > div { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 18px; }
.foot__bottom a { display: inline-flex; align-items: center; min-height: 48px; }
.foot__bottom a:hover { color: var(--fg); }

/* ── появление секций ────────────────────────────────────────────────────*/

@media (prefers-reduced-motion: reduce) {
  .reveal, .how__step > div, .how__frame, .btn { transition: none; }
  .reveal { opacity: 1; translate: 0 0; }
  .how__step > div { opacity: 1; }
}

/* ── планшет ─────────────────────────────────────────────────────────────*/
@media (max-width: 1019px) {
  :root { --rhythm: 88px; }
  .hero { padding-block: 112px 0; }
  .hero__frame { margin-top: 40px; }
  .thesis__cards { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .how__grid { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  /* На одной колонке липкий кадр и погашенные шаги теряют смысл: сцена
     раскладывается стопкой «шаг → его кадр», и ни одно доказательство не
     прячется за состоянием, которого на телефоне не видно. */
  .how__stage { display: none; }
  .how__step { padding-block: 0 48px; }
  .how__step > div { opacity: 1; }
  .how__step-frame { margin-top: 24px; }
  .start__cards { grid-template-columns: minmax(0, 1fr); }
  .faq__grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .foot__top { grid-template-columns: minmax(0, 1fr); gap: 40px; }
}
@media (min-width: 1020px) { .how__step-frame { display: none; } }

/* ── телефон ─────────────────────────────────────────────────────────────*/
@media (max-width: 767px) {
  /* Поля 16, а не 20: мера первого экрана становится 358px — ровно как в
     боевой версии. Восемь пикселей здесь решают, влезает ли «ИИ-ассистент
     брокера» в одну строку; на 20px заголовок ломался на ЧЕТЫРЕ строки
     против трёх, и это ровно та разница, из-за которой раскладку боевой
     версии и просили перенести. */
  :root { --rhythm: 72px; --gutter: 16px; }
  .mast__in { height: 60px; padding-right: 6px; }
  .mast__chip, .mast__login { display: none; }
  /* Замер, а не глазомер: у боевой версии h1 начинается на 182px от верха
     окна, у второй начинался на 96. Разница видна как «текст прилип к шапке»
     и как отсутствие воздуха, из-за которого кнопка уезжала к нижней кромке —
     туда, где на боевом хосте стоит баннер согласия. Ставим ровно 182:
     совпадает и низ кнопки (449 против 445). */
  .hero { padding-block: 182px 0; }
  /* Кегль и интерлиньяж первого экрана — как в боевой версии (32px / 1.12),
     а не по общей шкале (34 / 1.2). Замер: 34/1.2 в 350px даёт 4 строки,
     32/1.12 в 358px — 3. Перенося раскладку, переносим и то, чем она
     измеряется. */
  .hero h1 { max-width: none; font-size: 2rem; line-height: 1.12; }
  .hero__lead { margin-top: 17px; font-size: .9375rem; line-height: 1.48; }
  /* Кнопка во всю ширину — как в боевой версии: на 390px пилюля по центру
     колонки читается как чип, а не как единственное действие экрана. */
  .hero .btn { width: 100%; margin-top: 24px; }
  .hero__frame { margin-top: 32px; }
      .receipt__row, .receipt__query, .receipt__section, .receipt__formula { padding-inline: 16px; }
  .receipt__result { padding: 22px 18px 20px; }
  .faq__list summary { padding-inline: 16px; }
  .faq__list details > div { padding: 0 40px 18px 16px; }
  .foot nav { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }
  .window__paper { padding: 16px; }
  .paper-project { grid-template-columns: 76px minmax(0, 1fr); }
  .paper-project img { width: 76px; height: 52px; }
}

/* ══════════════════════════════════════════════════════════════════════════
   СЦЕНА ДЛЯ КАДРОВ ПРОДУКТА (2026-08-26)

   Приём снят с warp.dev и переведён на язык DSH. У warp кадр продукта НИКОГДА
   не лежит на грунте страницы: он всегда стоит на цветной плите с полями
   вокруг — размытое радужное поле в первом экране, сиреневая точечная сетка
   в «Close the loop», три плоских цветных блока в «One platform». Правило
   одно: цвет несёт плита, кадр стоит НА ней предметом.

   Что берём и что нет. Берём плиту, поля и право кадра выходить за её край.
   НЕ берём радугу: три случайных пастельных блока — это язык warp, а у нас
   язык DSH, где акцент один. Поэтому туманность на всех сценах ОДНА и та же,
   брендовая синяя, и меняются только её положение и сила — сцены читаются как
   одна система, а не как три разных настроения.

   Зачем это вообще. Кадр 2560px в слоте 940px — это 0.37x: текст ~7px, а на
   телефоне серый шум. Сцена даёт кадру право быть ВЫРЕЗКОЙ в натуральную
   величину вместо целого экрана, сжатого до нечитаемости.
   ══════════════════════════════════════════════════════════════════════════ */
.stage {
  position: relative; isolation: isolate; overflow: hidden;
  border: 1px solid var(--line); border-radius: 20px;
  background: var(--surface);
  padding: clamp(14px, 3.2vw, 48px);
  display: grid; place-items: center;
}
/* Туманность одна на все сцены, меняется положение. Заканчивается прозрачным,
   поэтому обход предков находит под ней ту же плиту: лестница поверхностей
   остаётся из трёх ступеней, четвёртой не появляется. */
.stage::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(86% 76% at 84% 2%, rgb(103 158 254 / .58), transparent 62%),
    radial-gradient(70% 62% at 4% 98%, rgb(126 118 255 / .34), transparent 66%),
    linear-gradient(150deg, rgb(103 158 254 / .10), transparent 58%);
}
/* Тонкая сетка на плите — приём «Close the loop». Гасится к краям, иначе плита
   читается как миллиметровка. */
.stage::after {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(rgb(255 255 255 / .05) 1px, transparent 1px) 0 0 / 100% 64px,
    linear-gradient(90deg, rgb(255 255 255 / .05) 1px, transparent 1px) 0 0 / 64px 100%;
  -webkit-mask-image: radial-gradient(88% 82% at 50% 42%, #000 30%, transparent 92%);
  mask-image: radial-gradient(88% 82% at 50% 42%, #000 30%, transparent 92%);
}
.stage--b::before {
  background:
    radial-gradient(80% 70% at 8% 2%, rgb(103 158 254 / .52), transparent 64%),
    radial-gradient(72% 62% at 98% 92%, rgb(126 118 255 / .32), transparent 68%),
    linear-gradient(210deg, rgb(103 158 254 / .09), transparent 56%);
}
.stage--c::before {
  background:
    radial-gradient(96% 78% at 50% 112%, rgb(103 158 254 / .56), transparent 60%),
    radial-gradient(58% 52% at 90% -8%, rgb(126 118 255 / .34), transparent 68%),
    linear-gradient(20deg, rgb(103 158 254 / .09), transparent 56%);
}
/* Кадр на сцене поднят собственной тенью: он ПРЕДМЕТ на плите, а не её узор. */
.stage .window {
  width: 100%;
  box-shadow: 0 0 0 1px rgb(0 0 0 / .5), 0 18px 44px -10px rgb(0 0 0 / .58),
    0 44px 110px -30px rgb(0 0 0 / .5);
}
/* Сцена не меняет высоту при подмене кадра: иначе страница дёргается на каждом
   шаге аккордеона. */



/* ── 04 · РАСЧЁТЫ И ИСТОЧНИКИ, ПЕРЕСОБРАНО ───────────────────────────────
   Было: чек, нарисованный HTML'ом, — поверхность, которой в приложении не
   существует. Отсюда и «слоп»: страница про доверие показывала выдуманный
   интерфейс. Стало: НАСТОЯЩИЙ кадр продукта на сцене, а рядом — то, чего в
   кадре нет и быть не может: детерминированная формула, сходящаяся до рубля,
   и строка о границах каталога. Формула остаётся кодом, и это правильно —
   это не интерфейс, это арифметика. */
.proof__grid {
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: 24px; align-items: start; margin-top: 44px;
}
/* Колонка читается сверху вниз (запрос → расчёт → граница), поэтому блоки
   стоят подряд, а не разносятся по краям: space-between на двух карточках
   давал 300px дыры посередине и колонка распадалась на два обрубка. */
.proof__side { display: grid; gap: 16px; align-content: start; }
.reqline { padding: 18px 22px 20px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface-2); }
.reqline > span { display: block; color: var(--fg-3); font-size: .75rem;
  font-family: var(--font-mono); letter-spacing: .06em; text-transform: uppercase; }
.reqline p { margin-top: 8px; color: var(--fg); font-size: .9375rem; line-height: 1.5; }
.formula { padding: 24px 24px 26px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); }
.formula > span { display: flex; align-items: center; gap: 9px; color: var(--fg-2);
  font-size: .8125rem; }
.formula .ic { color: var(--accent); }
.formula ol { display: grid; gap: 11px; margin-top: 14px; }
.formula li { color: var(--fg); font-family: var(--font-mono); font-size: .8125rem;
  line-height: 1.55; overflow-wrap: anywhere; }
.honesty { display: grid; gap: 9px; padding: 22px 24px 24px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--surface); }
.honesty strong { display: flex; align-items: center; gap: 9px; font-size: .9375rem;
  font-weight: 500; }
.honesty strong .ic { color: var(--fg-3); }
.honesty p { color: var(--fg-2); font-size: .875rem; line-height: 1.55; }
@media (max-width: 1019px) { .proof__grid { grid-template-columns: minmax(0, 1fr); gap: 18px; } }

/* Подпись под кадром продукта — что именно на нём и откуда цифры. */
.shotnote { margin-top: 14px; color: var(--fg-3); font-size: .8125rem; line-height: 1.5;
  text-align: center; }
.shotnote b { color: var(--fg-2); font-weight: 400; }

/* ══════════════════════════════════════════════════════════════════════════
   ДВИЖЕНИЕ

   Появление по скроллу, как у референса. Три правила, каждое сознательное:

   1. Секция ВИДНА по умолчанию. Начальное состояние вешается через класс .js
      на корне, который ставит сам движок. Без JS — и в headless-рендере, и во
      вкладке, которая никогда не была активной, — страница отдаётся целиком:
      переход в скрытой вкладке не запускается, и страница, завязавшая
      видимость на него, уехала бы в публикацию белым листом.
   2. Кривая — ease-out-expo, без отскока. Отскок здесь театр, а страница
      обещает точность.
   3. Появление НЕ одинаковое у всех. Одна и та же анимация, налепленная на всё
      подряд, — главный признак машинной работы. Кадры продукта поднимаются и
      чуть доезжают по масштабу (они тяжелее), карточки идут каскадом,
      цитата только проявляется — показание брокера не слайд.
   ══════════════════════════════════════════════════════════════════════════ */
.js .reveal { opacity: 0; translate: 0 18px;
  transition: opacity .62s var(--ease-out-expo), translate .62s var(--ease-out-expo); }
.js .reveal[data-in='1'] { opacity: 1; translate: 0 0; }

.js .reveal .stage { opacity: 0; scale: .985; translate: 0 20px;
  transition: opacity .8s var(--ease-out-expo) .08s, scale .8s var(--ease-out-expo) .08s,
              translate .8s var(--ease-out-expo) .08s; }
.js .reveal[data-in='1'] .stage { opacity: 1; scale: 1; translate: 0 0; }

.js .reveal .thesis__card,
.js .reveal .start__card { opacity: 0; translate: 0 14px;
  transition: opacity .6s var(--ease-out-expo), translate .6s var(--ease-out-expo); }
.js .reveal[data-in='1'] .thesis__card,
.js .reveal[data-in='1'] .start__card { opacity: 1; translate: 0 0; }
.js .reveal[data-in='1'] .thesis__card:nth-child(2),
.js .reveal[data-in='1'] .start__card:nth-child(2) { transition-delay: .09s; }
.js .reveal[data-in='1'] .thesis__card:nth-child(3) { transition-delay: .18s; }

.js .quote.reveal { translate: none; transition: opacity .7s var(--ease-out-expo); }

@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .reveal .stage,
  .js .reveal .thesis__card,
  .js .reveal .start__card { opacity: 1; translate: none; scale: 1; transition: none; }
}

:root { --ease-out-expo: cubic-bezier(.16, 1, .3, 1); }

/* Секция расчётов: ОДИН кадр по центру. Правая колонка снята — она считала
   другой случай, чем показывал кадр, и это читалось как несобранность. */
/* 780, а не 900: кадр здесь высокий (ответ целиком), и на 900 он становится
   колонной, рядом с которой нечему стоять. На 780 он читается как предмет,
   а секция перестаёт быть одной длинной картинкой. */
.proof__figure { width: min(100%, 780px); margin: 44px auto 0; }
.proof__figure .shotnote { margin-top: 16px; }


/* Consent controls use the shared marketing-public.css. */
