/*
 * Витрина genrate.kz.
 *
 * Тёмная база выбрана не для красоты: сервис — рабочий инструмент, в
 * котором продавец каждый день смотрит на цифры и графики. Панель тоже
 * тёмная, и витрина обязана обещать то, что человек увидит внутри.
 *
 * Прошлый лендинг ломался на телефоне по одной причине: шапка не умещалась
 * в 375 px и растягивала документ до 588. Здесь точки перелома заданы для
 * всех блоков, а шапка на узком экране сворачивается в меню.
 */

/* ── Палитра ──────────────────────────────────────────────────────────── */
:root {
  --ink:        #06070a;   /* фон страницы */
  --panel:      #0e1116;   /* поверхность блока */
  --line:       #1e2631;   /* волосяная линия */
  --line-soft:  #161c25;

  --text:       #e9eef5;
  --dim:        #93a0b1;
  /* Был #5d6a7a — контраст 3.65 на фоне страницы при норме 4.5.
     Ниже порога, и этим цветом набрано почти всё, что человек читает,
     когда УЖЕ заинтересовался: лимиты тарифов, список возможностей,
     подписи полей калькулятора, приписка под кнопками героя.
     Владелец: «текст как будто мелковат, прям приходится вглядываться»
     — вглядываться приходилось не в размер, а в этот цвет.
     #7d8998 даёт 5.66. Для сравнения: у Linear приглушённый держит
     6.13, у Vercel 8.13, у Resend 8.37. */
  --faint:      #7d8998;

  --accent:     #1cbb93;   /* фирменный, тот же что в панели */
  --accent-2:   #70e478;
  --accent-dim: rgba(28,187,147,.13);
  --accent-glow:rgba(28,187,147,.28);

  --rival:      #ff5a5a;   /* цена конкурента */
  --gold:       #f5b544;

  --r:    14px;
  --r-lg: 22px;
  --r-pill: 999px;

  /* Было 1180. Рабочая ширина выходила 1132 px — на 120–190 больше,
     чем у всех замеренных (Linear 1014, Attio 986, Resend 991,
     Supabase 938). Широкая колонка делает сетку из трёх карточек
     редкой, а текст в них — мелким относительно окружающего воздуха. */
  --shell: 1120px;

  /* Отклик на наведение. Было .35s — ВДВОЕ медленнее рынка: Vercel,
     Attio, Resend и Clerk, четыре независимые команды, держат .15s.
     350 мс — единственное место, где медленное читается не как
     «дорого», а как «тормозит»: курсор уже ушёл, а рамка догоняет. */
  --t: .18s cubic-bezier(0, 0, .2, 1);

  /* Только для подъёма кнопки: лёгкий перелёт, отклик читается
     физическим. Значение дословно снято с Mintlify. */
  --t-pop: .28s cubic-bezier(.34, 1.56, .64, 1);

  /* ══ Шкала набора: семь ступеней и ни одной больше ═══════════════
   *
   * Было шестнадцать значений, из них ОДИННАДЦАТЬ в диапазоне 13–21.
   * Человек не отличит 15 от 15.5, но каждое лишнее значение размывает
   * иерархию: страница выглядит не упорядоченной, а набранной как
   * попало. Именно это, а не кегль, читается как «мелко».
   *
   * Шаг между соседними ступенями не меньше 1.2 — иначе разницы не
   * видно. Новых ступеней не заводить, даже «на один раз».
   */
  --fs-display: clamp(40px, 6.2vw, 76px);  /* заголовок героя      */
  --fs-h2:      clamp(31px, 4.8vw, 52px);  /* заголовок раздела    */
  --fs-h3:      21px;                      /* карточка, шаг, тариф */
  --fs-lede:    21px;                      /* подзаголовок раздела */
  --fs-body:    18px;                      /* основной текст       */
  --fs-ui:      15px;                      /* подписи, поля, меню  */
  --fs-micro:   13px;                      /* ярлыки и надстрочное */

  /* ══ Насыщенности ═══════════════════════════════════════════════
   *
   * Главная находка обоих разборов. У нас всё крупное было 800 — и
   * заголовки, и цифры, и названия карточек. На замеренных сайтах:
   * Stripe 300, Vercel 400, Resend 400, Supabase 500, Linear 510,
   * Attio 600, Clerk 700. Из двенадцати ни один не идёт выше 700.
   *
   * Жирный крупный шрифт — язык распродажи, а не инструмента.
   * Премиальный контраст держится на РАЗМЕРЕ, а не на жире: у Linear
   * разница заголовок/текст — одна ступень насыщенности, у Vercel
   * заголовок вообще легче текста, у нас было четыре ступени.
   *
   * Manrope — переменный шрифт (200…800), поэтому промежуточные
   * значения настоящие, а не округляются браузером до 700.
   */
  --fw-display: 560;
  --fw-h3:      620;
  --fw-body:    400;
  --fw-ui:      500;
  --fw-micro:   600;

  --lh-display: 1.02;
  --lh-h2:      1.06;
  --lh-h3:      1.28;
  --lh-lede:    1.5;
  --lh-body:    1.55;
  --lh-ui:      1.45;

  /* Чем крупнее кегль, тем туже. Ниже 18 px не сжимаем вовсе: на
     мелком трекинг съедает разборчивость, а выигрыша не даёт.
     Прежние −0.035em стояли при насыщенности 800 — толстые штрихи
     сближались и слипались. Премиальная связка обратная: лёгкая
     насыщенность плюс тугой трекинг (Vercel: 400 и −0.06em). */
  --ls-display: -0.038em;
  --ls-h2:      -0.032em;
  --ls-h3:      -0.018em;
  --ls-body:    -0.006em;
  --ls-micro:    0.06em;   /* микротекст, наоборот, разряжаем */
}

/* ── Основа ───────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: Onest, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: var(--fs-body);
  font-weight: var(--fw-body);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
  -webkit-font-smoothing: antialiased;
  /* Страховка от повторения главной ошибки прошлой версии: что бы ни
     вылезло за край, документ вбок не поедет. */
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

.shell {
  width: 100%;
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 28px;
}

.mono {
  font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}

/* ── Свечение фона ────────────────────────────────────────────────────── */
.glow {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(ellipse 60% 45% at 50% -5%, rgba(28,187,147,.10) 0%, transparent 65%),
    radial-gradient(ellipse 45% 35% at 90% 15%, rgba(112,228,120,.05) 0%, transparent 60%);
}

/* ── Свет идёт за курсором ────────────────────────────────────────────── */
/*
 * Мягкое пятно на весь экран, а не подсветка отдельной карточки.
 * Подсветка была только у `.card` — шесть блоков из всей страницы
 * отзывались на мышь, остальное лежало мёртвым. Живой должна быть
 * страница, а не шесть её кусков.
 *
 * Слой отдельный и `fixed`: тогда за курсором едет свет, а не
 * перерисовывается содержимое. Прозрачность низкая намеренно — это
 * должно ощущаться, а не бросаться в глаза.
 *
 * Координаты приходят переменными: вычислить их в CSS нельзя. Пока
 * мыши не было, `--px`/`--py` не заданы, и `at 50% -20%` держит пятно
 * за верхним краем — то есть на телефоне и до первого движения мыши
 * никакого второго пятна нет.
 */
.spot {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0;
  transition: opacity .8s ease;
  background: radial-gradient(
    520px circle at var(--px, 50%) var(--py, -20%),
    rgba(28,187,147,.085) 0%,
    rgba(28,187,147,.03) 38%,
    transparent 70%);
}
.spot.is-live { opacity: 1; }

/* ── Полоса прочтения ─────────────────────────────────────────────────── */
/*
 * Волосяная линия под шапкой: сколько страницы позади. Не украшение —
 * длинная витрина без неё ощущается бесконечной, и человек уходит с
 * середины, не зная, много ли осталось.
 *
 * Ширина приходит переменной `--read` от скрипта; без него полоса
 * остаётся нулевой и не мешает.
 */
.read {
  position: absolute;
  left: 0; bottom: -1px;
  height: 2px;
  width: var(--read, 0%);
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-2) 100%);
  box-shadow: 0 0 12px -2px var(--accent-glow);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .spot { display: none; }
}

/* ── Шапка ────────────────────────────────────────────────────────────── */
.top {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(6,7,10,.72);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--t), background var(--t);
}
.top.is-stuck { border-bottom-color: var(--line-soft); background: rgba(6,7,10,.92); }

.top__inner {
  display: flex;
  align-items: center;
  gap: 16px;
  height: 66px;
}

.brand { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.brand img { width: 32px; height: 32px; }
.brand__name { font-size: 20px; font-weight: var(--fw-h3); letter-spacing: -.02em; line-height: 1; }
.brand__name span {
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-2) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.brand__sub {
  display: block; margin-top: 3px;
  font-size: 9px; letter-spacing: .16em; text-transform: uppercase; color: var(--faint);
}

.nav { display: flex; gap: 26px; margin-left: auto; }
/* `nowrap` не украшение. Меню — flex, и его пункты по умолчанию
   сжимаются: на 1024 px — самой ходовой ширине ноутбука — «Как
   работает» получало 82 px при нужных 100 и переносилось на две
   строки прямо в шапке. Высота ссылки при этом не менялась, поэтому
   вторая строка вылезала за неё. Замерено на живой странице. */
.nav a { font-size: 14px; color: var(--dim); transition: color var(--t); white-space: nowrap; }
.nav a:hover { color: var(--text); }

.top__cta { display: flex; align-items: center; gap: 10px; margin-left: 26px; flex-shrink: 0; }

.burger {
  display: none;
  margin-left: auto;
  width: 40px; height: 40px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
  align-items: center; justify-content: center;
}
.burger svg { width: 18px; height: 18px; }

/* ── Кнопки ───────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 20px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: 14px; font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: transform var(--t), box-shadow var(--t), background var(--t), border-color var(--t);
}
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.btn--primary {
  background: linear-gradient(135deg, var(--accent) 0%, #16a884 100%);
  color: #04120d;
  box-shadow: 0 6px 22px -8px var(--accent-glow);
}
.btn--primary:hover { box-shadow: 0 10px 30px -8px var(--accent-glow); }

.btn--ghost { border-color: var(--line); color: var(--text); background: transparent; }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }

.btn--quiet { color: var(--dim); background: transparent; padding-left: 12px; padding-right: 12px; }
.btn--quiet:hover { color: var(--text); }

.btn--lg { padding: 15px 30px; font-size: 16px; }
.btn--full { width: 100%; }

/* ── Секции ───────────────────────────────────────────────────────────── */
/* Поля разделов зависят от ВЕСА раздела, а не одинаковы у всех.
 *
 * Было 128 везде. Замер по премиальным: Resend 96, Attio 112, Linear
 * 128 — но у каждого есть разделы с другими полями. Плотный раздел
 * требует больше воздуха, лёгкий — меньше; одинаковые поля делают
 * страницу ровной, а ровность читается как безразличие.
 *
 * Шкала 96 / 128 / 160: 160 вокруг цитаты-утверждения (пауза должна
 * быть паузой), 96 вокруг тихой полосы чисел и частых вопросов. */
.section { position: relative; z-index: 1; padding: 128px 0; }
.section--tight { padding: 96px 0; }
.section--airy  { padding: 160px 0; }

@media (max-width: 720px) {
  .section { padding: 84px 0; }
  .section--tight { padding: 64px 0; }
  .section--airy  { padding: 104px 0; }
}
.section + .section { border-top: 1px solid var(--line-soft); }

.eyebrow {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 13px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--panel);
  font-size: var(--fs-micro); font-weight: var(--fw-micro); letter-spacing: var(--ls-micro);
  color: var(--dim);
  margin-bottom: 20px;
}
.eyebrow b { color: var(--accent); font-weight: 700; }

.h2 {
  font-size: var(--fs-h2);
  font-weight: var(--fw-display);
  letter-spacing: var(--ls-h2);
  line-height: var(--lh-h2);
  margin: 0 0 14px;
  text-wrap: balance;
}
.lede {
  font-size: var(--fs-lede);
  line-height: var(--lh-lede);
  color: var(--dim);
  max-width: 660px;
  margin: 0 0 44px;
}

/* ── Герой ────────────────────────────────────────────────────────────── */
.hero { position: relative; z-index: 1; padding: 74px 0 96px; }
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}
.hero h1 {
  font-size: var(--fs-display);
  font-weight: var(--fw-display);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-display);
  margin: 0 0 20px;
  text-wrap: balance;
}
.hero h1 em {
  font-style: normal;
  background: linear-gradient(100deg, var(--accent) 0%, var(--accent-2) 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.hero p {
  font-size: 18px;
  color: var(--dim);
  max-width: 52ch;
  margin: 0 0 32px;
}
.hero__cta { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.hero__note { margin-top: 18px; font-size: 13px; color: var(--faint); }

/* ── Живой репрайс ────────────────────────────────────────────────────── */
.ticker {
  background: linear-gradient(180deg, var(--panel) 0%, #0b0e13 100%);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: 0 30px 70px -40px rgba(0,0,0,.9);
}
.ticker__head {
  display: flex; align-items: center; gap: 10px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px; color: var(--dim);
}
.pulse {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 0 var(--accent-glow);
  animation: pulse 2.2s infinite;
  flex-shrink: 0;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 var(--accent-glow); }
  70%  { box-shadow: 0 0 0 9px rgba(28,187,147,0); }
  100% { box-shadow: 0 0 0 0 rgba(28,187,147,0); }
}
.ticker__sku { margin-left: auto; color: var(--faint); }

.row {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 18px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14px;
  /* Переезд строки на новое место по цене. Сдвиг вычисляется скриптом
     (приём FLIP), а вот ДЛИТЕЛЬНОСТЬ и кривая — оформление, и им место
     здесь: в проекте скрипт меняет класс, а не свойство. */
  transition: transform .55s cubic-bezier(.22,.61,.36,1);
}
/* Мгновенная установка без переезда: нужна на замере положения, чтобы
   незаконченное движение не попало в новый отсчёт. */
.row--jump { transition: none; }
.row__who { color: var(--dim); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row__price { margin-left: auto; font-size: 15px; font-weight: 600; white-space: nowrap; }
.row--rival .row__price { color: var(--rival); }
.row--you { background: var(--accent-dim); }
.row--you .row__who { color: var(--text); font-weight: 700; }
.row--you .row__price { color: var(--accent); }
.row.flash { animation: flash .7s ease-out; }
@keyframes flash { 0% { background: rgba(28,187,147,.28); } 100% { background: transparent; } }
.row--you.flash { animation: flashYou .7s ease-out; }
@keyframes flashYou { 0% { background: rgba(28,187,147,.4); } 100% { background: var(--accent-dim); } }

.badge {
  padding: 3px 9px;
  border-radius: var(--r-pill);
  font-size: 11px; font-weight: 700;
  background: var(--accent); color: #04120d;
  white-space: nowrap;
}
.badge--lost { background: rgba(255,90,90,.16); color: var(--rival); }

.ticker__log {
  padding: 12px 18px 16px;
  font-size: 12px;
  color: var(--faint);
  min-height: 64px;
}
.ticker__log div { margin-bottom: 4px; }
.ticker__log b { color: var(--dim); font-weight: 500; }

/* ── Полоса чисел ─────────────────────────────────────────────────────── */
.facts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  overflow: hidden;
  margin-top: 64px;
}
.fact { background: var(--ink); padding: 22px 20px; }
.fact__n { font-size: 30px; font-weight: var(--fw-display); letter-spacing: var(--ls-h2); color: var(--accent); }
.fact__t { font-size: var(--fs-ui); font-weight: var(--fw-ui); color: var(--faint); margin-top: 5px; }

/* ── Шаги ─────────────────────────────────────────────────────────────── */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.step {
  padding: 26px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  background: var(--panel);
}
.step__n {
  font-size: 12px; font-weight: 700; color: var(--accent);
  letter-spacing: .1em;
  margin-bottom: 12px;
}
.step h3 { font-size: var(--fs-h3); font-weight: var(--fw-h3); line-height: var(--lh-h3); margin: 0 0 9px; letter-spacing: var(--ls-h3); }
.step p { margin: 0; font-size: 17px; line-height: 1.5; color: var(--dim); }

/* ── Возможности ──────────────────────────────────────────────────────── */
.grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.card {
  padding: 26px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  background: var(--panel);
  transition: border-color var(--t), transform var(--t);
}
.card:hover { border-color: var(--line); transform: translateY(-2px); }
.card__ico {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 11px;
  background: var(--accent-dim);
  color: var(--accent);
  margin-bottom: 15px;
}
.card__ico svg { width: 19px; height: 19px; }
.card h3 { font-size: var(--fs-h3); font-weight: var(--fw-h3); line-height: var(--lh-h3); margin: 0 0 9px; letter-spacing: var(--ls-h3); }
.card p { margin: 0; font-size: 17px; line-height: 1.5; color: var(--dim); }
.card--new { position: relative; }
.card--new::after {
  content: "Новое";
  position: absolute; top: 18px; right: 18px;
  font-size: 10px; font-weight: 700; letter-spacing: .06em;
  padding: 3px 8px; border-radius: var(--r-pill);
  background: rgba(245,181,68,.14); color: var(--gold);
}

/* ── Калькулятор ──────────────────────────────────────────────────────── */
.calc {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--panel);
}
.calc__in { padding: 32px; border-right: 1px solid var(--line-soft); }
.calc__out { padding: 32px; background: #0b0e13; }

.field { margin-bottom: 18px; }
.field:last-child { margin-bottom: 0; }
.field label { display: block; font-size: 13px; color: var(--dim); margin-bottom: 7px; }
.field input {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--ink);
  color: var(--text);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  transition: border-color var(--t), box-shadow var(--t);
}
.field input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
.field__pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.out-row {
  display: flex; align-items: baseline; gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line-soft);
  font-size: 14px;
}
.out-row span { color: var(--dim); }
.out-row b { margin-left: auto; font-weight: 600; font-family: "JetBrains Mono", monospace; font-variant-numeric: tabular-nums; }
.out-row--minus b { color: var(--rival); }
.out-total {
  display: flex; align-items: baseline; gap: 12px;
  padding-top: 18px; margin-top: 6px;
}
.out-total span { color: var(--dim); font-size: 14px; }
.out-total b {
  margin-left: auto;
  font-size: 34px; font-weight: var(--fw-display); letter-spacing: var(--ls-h2);
  font-family: "JetBrains Mono", monospace; font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.out-total b.neg { color: var(--rival); }
.out-hint { margin-top: 14px; font-size: 13px; color: var(--faint); }
.out-hint b { color: var(--dim); font-weight: 600; }

/* ── Тарифы ───────────────────────────────────────────────────────────── */
.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; align-items: start; }
.plan {
  display: flex; flex-direction: column;
  padding: 26px 22px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r);
  background: var(--panel);
  position: relative;
}
.plan--featured {
  border-color: var(--accent);
  background: linear-gradient(180deg, rgba(28,187,147,.07) 0%, var(--panel) 45%);
  box-shadow: 0 24px 60px -40px var(--accent-glow);
}
.plan__badge {
  position: absolute; top: -10px; left: 22px;
  padding: 3px 11px; border-radius: var(--r-pill);
  background: var(--accent); color: #04120d;
  font-size: 11px; font-weight: 700;
}
.plan h3 { font-size: var(--fs-h3); font-weight: var(--fw-h3); line-height: var(--lh-h3); margin: 0 0 5px; letter-spacing: var(--ls-h3); }
.plan__blurb { font-size: var(--fs-ui); color: var(--faint); margin: 0 0 18px; min-height: 42px; }
.plan__price {
  font-size: 34px; font-weight: var(--fw-display); letter-spacing: var(--ls-h2);
  font-family: "JetBrains Mono", monospace; font-variant-numeric: tabular-nums;
  margin-bottom: 2px;
}
.plan__per { font-size: 13px; color: var(--faint); font-weight: 500; }
.plan__limits {
  display: flex; flex-direction: column; gap: 5px;
  margin: 18px 0;
  padding: 14px 0;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  font-size: 13px; color: var(--dim);
}
.plan__limits b { color: var(--text); font-weight: 700; font-variant-numeric: tabular-nums; }
/* Раскладка списка возможностей переехала ниже, к блоку «Карточка
 * тарифа: группы вместо столбца галочек». Здесь остаётся только то,
 * что держит карточку: список растягивается, чтобы кнопка
 * «Попробовать» у всех четырёх тарифов стояла на одной линии. */
.plan__feats { flex: 1; }

.discounts {
  margin-top: 26px;
  padding: 18px 24px;
  border: 1px dashed var(--line);
  border-radius: var(--r);
  text-align: center;
  font-size: 14px; color: var(--dim);
}
.discounts b { color: var(--accent); font-weight: 700; }

/* ── Заключительный призыв ────────────────────────────────────────────── */
.final {
  text-align: center;
  padding: 92px 0;
  border-top: 1px solid var(--line-soft);
  position: relative; z-index: 1;
}
.final h2 { font-size: var(--fs-h2); font-weight: var(--fw-display); line-height: var(--lh-h2); letter-spacing: var(--ls-h2); margin: 0 0 14px; }
.final p { color: var(--dim); margin: 0 0 30px; }
.final__cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* ── Подвал ───────────────────────────────────────────────────────────── */
.foot {
  border-top: 1px solid var(--line-soft);
  padding: 40px 0;
  position: relative; z-index: 1;
}
.foot__inner { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
/* Перенос обязателен.
 *
 * Без него ряд ссылок — одна нерушимая строка. Замер 24.09.2026 на
 * экране 375 px: ряд занимал 612 px и растягивал ВЕСЬ документ до
 * 627 — страница ехала вбок целиком, а не только подвал.
 *
 * Дыра была и раньше: пять ссылок требовали около 412 px, то есть
 * уже не помещались. Добавленные оферта и политика довели ряд до
 * 612 и сделали беду очевидной.
 *
 * Отсюда правило: ряду ссылок, который может пополниться, перенос
 * ставится сразу, а не когда он перестал влезать. */
.foot__links {
  display: flex; flex-wrap: wrap;
  gap: 12px 18px;
  margin-left: auto;
}
.foot__links a { font-size: 13px; color: var(--dim); transition: color var(--t); }
.foot__links a:hover { color: var(--accent); }
.foot__copy { width: 100%; font-size: 12px; color: var(--faint); margin-top: 20px; }

@media (max-width: 720px) {
  /* На телефоне ссылки идут своей строкой во всю ширину: прижимать их
     вправо к логотипу (margin-left: auto) на узком экране нечем — от
     логотипа до края остаётся меньше сотни точек. */
  .foot__links { margin-left: 0; width: 100%; }
  .foot__copy { margin-top: 14px; }
}

/* ── Появление при прокрутке ──────────────────────────────────────────── */
/* Начальное состояние ВИДИМОЕ: если наблюдатель не отработает, страница
   всё равно читается. Прячем только там, где скрипт точно жив. */
/* ══ Язык движения ══════════════════════════════════════════════════════
 *
 * Не набор эффектов, а СЛОВАРЬ: три способа появиться, одна лестница
 * длительностей, один каскад. Разрозненные эффекты читаются как
 * самодеятельность; повторяющийся приём — как почерк.
 *
 * Было: всё появлялось одинаково (14 px вверх, 0,6 с) и ОДНОВРЕМЕННО.
 * Шесть карточек выпрыгивали одной плитой — движение есть, ритма нет.
 * Каскад в 70 мс между соседями меняет ощущение сильнее, чем любая
 * отдельная анимация: глаз успевает прочесть порядок.
 *
 * Задержка приходит переменной `--d`, её расставляет скрипт: вычислить
 * её в CSS нельзя, а вписать руками в разметку — значит пересчитывать
 * при каждой правке порядка. Это ВЕЛИЧИНА, а не оформление, — то же
 * исключение, что у `--mx`/`--my` подсветки.
 *
 * Без скрипта не появляется НИЧЕГО из этого: класс `js` вешается первой
 * строкой, и до него блоки просто видимы. Текст, спрятанный до
 * срабатывания наблюдателя, — это текст, который кто-то не увидит.
 */
:root {
  /* Главное открытие замеров, и оно против интуиции: дорого
     ощущается не медленное движение, а КОРОТКОЕ ДВИЖЕНИЕ ЗА ДОЛГОЕ
     ВРЕМЯ. Считаем скорость — путь делим на длительность:

       Resend, большой скриншот   5 px за 1,5 с  =  3,3 px/с
       Attio, карточки            7–8 px за 0,6 с = 11,8 px/с
       Resend, строки героя      16 px за 1,0 с  = 16 px/с
       мы, обычный блок          18 px за 0,9 с  = 20 px/с
       мы, заголовок             28 px за 0,9 с  = 31 px/с

     Мы были самыми быстрыми в таблице при почти предельной
     длительности. Выходило «долго и при этом суетливо»: элемент едет
     далеко, всё время заметно движется, и глаз читает это как
     дёрганье, а не как вес. */
  --t-in:     .8s;    /* появление блока */
  --t-step:   90ms;   /* шаг каскада между соседями */
  --ease-soft: cubic-bezier(.16, 1, .3, 1);
}

.js .reveal { opacity: 0; transform: translateY(10px); }
.js .reveal.shown {
  opacity: 1;
  transform: none;
  transition:
    opacity   var(--t-in) var(--ease-soft) var(--d, 0ms),
    transform var(--t-in) var(--ease-soft) var(--d, 0ms),
    filter    var(--t-in) var(--ease-soft) var(--d, 0ms);
}

/* Заголовок наводится на резкость.
   Путь длиннее и с расфокусом: крупный текст, приехавший на тех же
   18 px, что и мелкая карточка, выглядит вялым. Размытие берём
   небольшое — на больших кеглях оно дорого обходится отрисовке. */
/* Размытие было 7 px. У Linear в появлении blur(2px), у Attio 1–3.
   Семь пикселей на заголовке в 76 выглядят не «наведением на
   резкость», а «текст расплылся» — и это самая дорогая операция на
   странице для слабого ноутбука. */
.js .reveal--head { transform: translateY(14px); filter: blur(3px); }
.js .reveal--head.shown { filter: blur(0); }

/* Карточка подаётся вперёд, а не просто всплывает. */
.js .reveal--card { transform: translateY(10px) scale(.99); }

@media (prefers-reduced-motion: reduce) {
  /* Просьбу о покое уважаем целиком: ни пути, ни расфокуса, ни каскада.
     Блоки просто на местах. */
  .js .reveal,
  .js .reveal--head,
  .js .reveal--card { opacity: 1; transform: none; filter: none; }
}

/* ── Точки перелома ───────────────────────────────────────────────────── */
/* ══ Шкала на узких экранах ═══════════════════════════════════════════
 *
 * Ключевое наблюдение, снятое с Linear: при переходе 1049 → 768 → 375
 * основной текст НЕ МЕНЯЕТСЯ — 15/24 на всех трёх ширинах. Меняются
 * только крупные кегли и межстрочный у них.
 *
 * Это правильно: читаемость абзаца от ширины окна не зависит, а
 * заголовок в три строки на телефоне — зависит. Уменьшать основной
 * текст на телефоне значит чинить не ту беду.
 *
 * Крупному на узком возвращается чуть больше насыщенности: мелкий
 * кегль при 560 выглядит блёклым, это не вкусовщина, а оптика.
 */
@media (max-width: 1199px) {
  :root {
    --lh-display: 1.06;
    --lh-h2:      1.10;
    --ls-display: -0.030em;
    --ls-h2:      -0.026em;
    --fs-lede:    20px;
  }
}

@media (max-width: 767px) {
  :root {
    --lh-display: 1.10;
    --lh-h2:      1.14;
    --ls-display: -0.024em;
    --ls-h2:      -0.020em;
    --fw-display: 580;
    --fs-lede:    18px;
    --fs-body:    17px;
    --fs-h3:      20px;
  }
}

@media (max-width: 1080px) {
  .plans { grid-template-columns: repeat(2, 1fr); }
  .facts { grid-template-columns: repeat(2, 1fr); }
  /* Меню — flex, и его пункты сжимаются молча. На 1024 px, самой
     ходовой ширине ноутбука, оно просило 614 px и получало 553:
     «Как работает» переносилось на две строки прямо в шапке, причём
     высота ссылки не менялась и вторая строка вылезала за неё.

     Бургер включается только на 760 px, поэтому промежуток между
     пунктами надо ужать раньше — прятать меню на ноутбуке было бы
     хуже. Пять промежутков по 8 px дают те самые 40 px. */
  .nav { gap: 18px; }
  .top__cta { margin-left: 18px; }
}

@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; gap: 42px; }
  .grid3, .steps { grid-template-columns: 1fr 1fr; }
  .calc { grid-template-columns: 1fr; }
  .calc__in { border-right: none; border-bottom: 1px solid var(--line-soft); }
}

@media (max-width: 760px) {
  /* Шапка: меню уезжает в выпадающий список, лишняя кнопка прячется.
     Именно здесь прошлая версия растягивала документ до 588 px. */
  .nav, .top__cta .btn--ghost { display: none; }
  /* На правовой странице кнопка в шапке — это ПЕРЕКЛЮЧАТЕЛЬ ЯЗЫКА, а
   * не вторая кнопка призыва, и прятать её нельзя: казахская версия
   * оферты станет недостижимой с телефона, а ссылку на неё человек
   * ниоткуда не возьмёт. Замер на 375 px: без этого правила кнопки
   * QAZ в шапке нет вовсе. */
  .legal-page .top__cta .btn--ghost { display: inline-flex; }
  .burger { display: inline-flex; }
  .top__cta { margin-left: 10px; }
  .nav.is-open {
    display: flex;
    position: absolute; top: 66px; left: 0; right: 0;
    flex-direction: column; gap: 0;
    padding: 8px 24px 16px;
    background: rgba(6,7,10,.97);
    border-bottom: 1px solid var(--line);
    backdrop-filter: blur(14px);
  }
  .nav.is-open a { padding: 12px 0; border-bottom: 1px solid var(--line-soft); }

  .section { padding: 72px 0; }
  .hero { padding: 48px 0 68px; }
  .grid3, .steps { grid-template-columns: 1fr; }
  .plans { grid-template-columns: 1fr; }
  .facts { margin-top: 44px; }
  .plan__blurb { min-height: 0; }
}

@media (max-width: 460px) {
  .shell { padding: 0 16px; }
  .facts { grid-template-columns: 1fr 1fr; }
  .fact { padding: 16px 14px; }
  .fact__n { font-size: 21px; }
  .calc__in, .calc__out { padding: 22px 18px; }
  .field__pair { grid-template-columns: 1fr; }
  .hero__cta .btn { width: 100%; }
  .btn--lg { padding: 14px 22px; }
  .row { padding: 11px 14px; font-size: 13px; }
  .ticker__head { padding: 11px 14px; }
  .ticker__sku { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Показ самого сервиса
   ═══════════════════════════════════════════════════════════════════════

   Скриншот, положенный плашмя, читается как картинка в отчёте. Тот же
   скриншот под углом, в рамке браузера и с подсветкой снизу читается как
   работающий экран. Разница — в ощущении, что за этим что-то живёт.

   Угол не декоративный: он уходит, когда блок попадает в окно. Получается
   движение «экран поворачивается к вам», а не статичная картинка.
   ═══════════════════════════════════════════════════════════════════════ */

.stage {
  position: relative;
  perspective: 1600px;
  perspective-origin: 50% 30%;
  margin-top: 16px;
  /* Поля по бокам — чтобы выноски висели ЗА краем экрана и не закрывали
     собой те самые цифры, ради которых они и нужны. */
  padding: 0 46px;
}

.screen {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  background: var(--panel);
  border: 1px solid var(--line);
  box-shadow:
    0 50px 100px -40px rgba(0,0,0,.95),
    0 0 90px -50px var(--accent-glow);
  transform: rotateX(13deg) rotateY(-14deg) rotateZ(1.2deg) scale(.93);
  transform-origin: 50% 50%;
  transition: transform 1.1s cubic-bezier(.16,.72,.28,1);
  will-change: transform;
}
.stage--right .screen { transform: rotateX(13deg) rotateY(14deg) rotateZ(-1.2deg) scale(.93); }

/* Класс вешает наблюдатель: экран «поворачивается» к читателю. */
.stage.faced .screen { transform: rotateX(2deg) rotateY(0deg) rotateZ(0deg) scale(1); }

.screen__bar {
  display: flex; align-items: center; gap: 7px;
  padding: 11px 14px;
  background: #0b0e13;
  border-bottom: 1px solid var(--line-soft);
}
.screen__bar i {
  width: 10px; height: 10px; border-radius: 50%;
  background: #2a323d;
  flex-shrink: 0;
}
.screen__bar i:first-child { background: #3a4450; }
.screen__url {
  margin: 0 auto;
  padding: 3px 14px;
  border-radius: var(--r-pill);
  background: var(--ink);
  border: 1px solid var(--line-soft);
  font-family: "JetBrains Mono", monospace;
  font-size: 11px;
  color: var(--faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 62%;
}

.screen__img {
  height: clamp(260px, 42vw, 520px);
  overflow: hidden;
  background: #0b0e13;
}
.screen__img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
}

/* Выноски поверх экрана. На узком экране они перекрыли бы картинку —
   там мы их прячем и показываем тем же текстом под ней. */
.pin {
  position: absolute;
  z-index: 3;
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 14px;
  border-radius: 12px;
  background: rgba(10,13,18,.92);
  border: 1px solid var(--line);
  backdrop-filter: blur(10px);
  box-shadow: 0 18px 40px -20px rgba(0,0,0,.9);
  /* Плавание убрано 24.09.2026.
   *
   * Подписи качались вверх-вниз на 7 px вечно. Это украшение: оно
   * ничего не сообщает и не отвечает на действие человека.
   *
   * Пока вечных движений было три, это сходило с рук. С появлением
   * конической кромки у выделенного тарифа их стало четыре, и правило
   * разбора сработало против нас: одно вечное движение читается как
   * метка «вот сюда», четыре — как беспокойный фон.
   *
   * Оставшиеся три осмысленны: точка пульсирует, потому что «работает
   * прямо сейчас»; лента цен едет, потому что показывает живой поток и
   * замирает под курсором; кромка отмечает рекомендуемый тариф.
   *
   * Неподвижная подпись вдобавок читается лучше: плавающая выглядит
   * наклейкой, стоящая — пояснением к макету. */
}
.pin b { font-size: 13px; font-weight: 700; color: var(--text); white-space: nowrap; }
.pin span { font-size: 11px; color: var(--faint); white-space: nowrap; }
.pin em {
  font-style: normal; color: var(--accent); font-weight: 700;
  font-family: "JetBrains Mono", monospace;
}
.pin--a { top: 9%;  left: 0; }
.pin--b { top: 44%; right: 0; }
.pin--c { bottom: 9%; left: 26px; }

.pins-plain { display: none; margin-top: 18px; }
.pins-plain li {
  display: flex; gap: 10px; align-items: baseline;
  font-size: 14px; color: var(--dim);
  padding: 9px 0;
  border-bottom: 1px solid var(--line-soft);
}
.pins-plain li b { color: var(--text); font-weight: 700; }

/* ── Бегущая строка цен ───────────────────────────────────────────────── */
/*
 * Тонкая полоса между разделами: реальные названия товаров и то, что с
 * ними делает бот. Задаёт ощущение, что сервис прямо сейчас работает.
 */
.tape {
  position: relative; z-index: 1;
  overflow: hidden;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
  background: #080a0e;
  padding: 13px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.tape__run {
  display: flex;
  gap: 40px;
  width: max-content;
  animation: run 42s linear infinite;
}
.tape:hover .tape__run { animation-play-state: paused; }
@keyframes run { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.tape__item {
  display: flex; align-items: center; gap: 9px;
  font-size: 13px; color: var(--faint);
  white-space: nowrap;
}
.tape__item b { color: var(--dim); font-weight: 600; }
.tape__item i {
  font-style: normal;
  font-family: "JetBrains Mono", monospace;
  font-weight: 700;
}
.tape__item .dn { color: var(--accent); }
.tape__item .up { color: var(--gold); }
.tape__item .hold { color: var(--faint); }

/* ── Подсветка за курсором на карточках ──────────────────────────────── */
/*
 * Карточка светится там, где мышь. Эффект работает только с курсором:
 * на телефоне переменные не задаются, и подсветки просто нет.
 */
.card { position: relative; overflow: hidden; }
.card::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  background: radial-gradient(
    240px circle at var(--mx, 50%) var(--my, 50%),
    rgba(28,187,147,.10),
    transparent 62%
  );
}
.card:hover::before { opacity: 1; }
.card > * { position: relative; z-index: 1; }

/* ── Точки перелома для нового ────────────────────────────────────────── */
@media (max-width: 1080px) {
  /* Места для выносок за краем уже не хватает — переводим их в список
     под экраном, а поля убираем. */
  .stage { padding: 0; }
  .pin { display: none; }
  .pins-plain { display: block; }
}

@media (max-width: 900px) {
  .screen { transform: rotateX(7deg) scale(.97); }
  .stage--right .screen { transform: rotateX(7deg) scale(.97); }
}

@media (max-width: 460px) {
  .screen__img { height: 220px; }
  .screen__url { font-size: 10px; max-width: 55%; }
  .tape__run { gap: 26px; animation-duration: 32s; }
}

/* ═══════════════════════════════════════════════════════════════════════
   Экраны сервиса, собранные разметкой
   ═══════════════════════════════════════════════════════════════════════

   Скриншот стареет вместе с интерфейсом: панель переделали — на витрине
   осталась прошлогодняя. Плюс он весит мегабайты, мылится на экранах с
   высокой плотностью и не умеет двигаться.

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

.screen__ui {
  padding: 16px;
  background:
    radial-gradient(ellipse 70% 60% at 20% 0%, rgba(28,187,147,.06), transparent 60%),
    #0a0d12;
  min-height: clamp(250px, 40vw, 430px);
}

/* ── Плитки показателей ───────────────────────────────────────────────── */
.ui-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.ui-tile {
  padding: 12px 13px;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: #0e1218;
}
.ui-tile__t {
  display: flex; align-items: center; gap: 5px;
  font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ui-tile__v {
  font-family: "JetBrains Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-size: 21px; font-weight: 700; letter-spacing: -.03em;
  line-height: 1;
}
.ui-tile__v.ok   { color: var(--accent); }
.ui-tile__v.bad  { color: var(--rival); }
.ui-tile__v.warn { color: var(--gold); }

/* ── График ───────────────────────────────────────────────────────────── */
.ui-chart {
  margin-top: 8px;
  padding: 14px;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
  background: #0e1218;
}
.ui-chart__head {
  display: flex; align-items: baseline; gap: 10px;
  margin-bottom: 10px;
}
.ui-chart__head b { font-size: 12px; font-weight: 700; }
.ui-chart__head span {
  margin-left: auto;
  font-family: "JetBrains Mono", monospace;
  font-size: 15px; font-weight: 700; color: var(--accent);
}
.ui-chart svg { width: 100%; height: 74px; display: block; }

/* ── Таблица товаров ──────────────────────────────────────────────────── */
.ui-table { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.ui-table th {
  text-align: left;
  padding: 8px 10px;
  font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--faint); font-weight: 600;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.ui-table td {
  padding: 10px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--dim);
  white-space: nowrap;
}
.ui-table tr:last-child td { border-bottom: none; }
.ui-table .name { color: var(--text); font-weight: 600; max-width: 190px; overflow: hidden; text-overflow: ellipsis; }
.ui-table .num {
  font-family: "JetBrains Mono", monospace;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.ui-table .num.mine { color: var(--accent); font-weight: 700; }
.ui-table .num.rival { color: var(--rival); }

.chip {
  display: inline-block;
  padding: 2px 7px;
  border-radius: var(--r-pill);
  font-size: 9.5px; font-weight: 700;
  white-space: nowrap;
}
.chip--first { background: rgba(28,187,147,.16); color: var(--accent); }
.chip--lose  { background: rgba(255,90,90,.14); color: var(--rival); }
.chip--a     { background: rgba(28,187,147,.16); color: var(--accent); }
.chip--b     { background: rgba(245,181,68,.14); color: var(--gold); }
.chip--c     { background: rgba(147,160,177,.14); color: var(--dim); }
/* Лестница залежалости: чем ниже по списку, тем тревожнее цвет.
   «В обороте» — приглушённый фирменный: отличается от яркого
   «Ходового», но не читается как предупреждение. */
.chip--fresh  { background: rgba(112,228,120,.12); color: var(--accent-2); }
.chip--normal { background: rgba(28,187,147,.10);  color: var(--accent); }
.chip--slow   { background: rgba(245,181,68,.12);  color: var(--gold); }
.chip--dead   { background: rgba(255,90,90,.12);   color: var(--rival); }

/* Узкий экран: лишние столбцы прячем, чтобы таблица не ужималась в кашу. */
@media (max-width: 720px) {
  .ui-tiles { grid-template-columns: repeat(2, 1fr); }
  .ui-tile__v { font-size: 18px; }
  .ui-table .hide-sm { display: none; }
  .ui-table th, .ui-table td { padding: 8px 7px; }
  .ui-table .name { max-width: 120px; }
}
@media (max-width: 460px) {
  .screen__ui { padding: 11px; }
  .ui-tile { padding: 9px 10px; }
  .ui-tile__v { font-size: 16px; }
  .ui-table { font-size: 10.5px; }
}

/* ── Отзывы ───────────────────────────────────────────────────────────── */
/* Правил здесь больше нет.

   Стояли три карточки-заглушки «Здесь будет отзыв клиента». Владелец
   убрал их 22.09.2026: пустые рамки на публичной витрине хуже
   отсутствующего раздела — они кричат, что наполнить его нечем.

   Оформление удалено вместе с разметкой, а не оставлено «на потом».
   Мёртвый CSS живёт годами и вводит в заблуждение: читающий считает,
   что раздел есть. Придут настоящие цитаты — правила вернутся из
   истории (git log -S quote--stub), уже под живой текст.
*/

/* ── Наши собственные цифры ───────────────────────────────────────────── */
/* Правил здесь больше нет: раздел доказательств снят целиком
   (23.09.2026). Мёртвый CSS живёт годами и вводит в заблуждение —
   читающий считает, что раздел есть. Поднимается из истории вместе с
   разметкой: git log -S ours-note */


/* ══ Шов между разделами ═══════════════════════════════════════════════
 *
 * Было `border-top: 1px solid var(--line-soft)`, а `--line-soft` даёт
 * контраст к фону 1.24 — то есть линии практически нет, и семь
 * разделов сливались в одну ленту. Человек, пролистав страницу,
 * помнил «было много текста», а не «было семь разделов».
 *
 * Работающий шов — три вещи сразу: линия, затухающая к краям; мягкое
 * свечение НАД ней; и то, что она не идёт во всю ширину окна. Глаз
 * читает это как стык двух плоскостей, а не как нарисованную черту.
 */
.section { position: relative; }
.section + .section { border-top: 0; }

.section + .section::before {
  content: "";
  position: absolute; top: 0; left: 50%;
  transform: translateX(-50%);
  width: min(var(--shell), 100%);
  height: 1px;
  background: linear-gradient(90deg,
      transparent 0%, #2a3442 14%, #2a3442 86%, transparent 100%);
}
.section + .section::after {
  content: "";
  position: absolute; top: -70px; left: 50%;
  transform: translateX(-50%);
  width: min(760px, 86%); height: 140px;
  pointer-events: none;
  background: radial-gradient(ellipse 50% 50% at 50% 50%,
      rgba(28,187,147,.055) 0%, transparent 70%);
}

/* ══ Номерной ярлык раздела ════════════════════════════════════════════
 *
 * Мелкая надстрочная метка перед заголовком: `01 · КАК РАБОТАЕТ`.
 *
 * Делает сразу две вещи. Показывает, что у страницы есть структура и
 * она КОНЕЧНА — «сейчас третий из семи», человек не боится, что это
 * бесконечная лента. И даёт третью ступень набора над заголовком: без
 * неё h2 висит в пустоте.
 *
 * Хвост-линия вправо — чтобы метка не выглядела обрубком.
 */
.tag {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 18px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: var(--fs-micro); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint);
}
.tag b { color: var(--accent); font-weight: 500; }
.tag::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, var(--line) 0%, transparent 70%);
}

/* ══ Крупная цитата-утверждение ════════════════════════════════════════
 *
 * Один разворот во всю ширину, одна фраза, много воздуха. Не отзыв —
 * собственное утверждение продукта.
 *
 * Это ПАУЗА. Между двумя плотными разделами человеку нужно место, где
 * глазу ничего не надо делать. Таких мест на витрине было ноль, и
 * именно это ощущалось как однообразие.
 *
 * Набрано ЛЕГЧЕ основного текста и ПРИГЛУШЁННЫМ цветом — в этом весь
 * приём. Замеры: Linear 40/44 весом 510 цветом `#8a8f98`, Attio 48/52
 * весом 400. Фраза не кричит, а звучит; светлым выделяется одно число
 * или слово.
 */
.claim {
  padding: 160px 0;
  text-align: center;
  position: relative; z-index: 1;
}
.claim p {
  margin: 0 auto;
  max-width: 900px;
  font-size: clamp(26px, 3.6vw, 44px);
  line-height: 1.18;
  letter-spacing: -.028em;
  font-weight: 460;
  color: var(--dim);
  text-wrap: balance;
}
.claim b {
  font-weight: 560;
  color: var(--text);
}
.claim .mono { color: var(--accent); font-weight: 500; }

@media (max-width: 767px) {
  .claim { padding: 96px 0; }
}

/* ══ Кромка, светящаяся под курсором ═══════════════════════════════════
 *
 * Рамка в 1 px, почти целиком стёртая маской. Не стёрт эллипс вокруг
 * курсора — и по кромке едет светящийся участок, как луч по краю
 * стекла. Приём снят с Linear дословно.
 *
 * Почему именно кромка. Светится КРАЙ, а не заливка. Край — это то,
 * чем предмет отделён от фона; подсвеченный край читается как
 * материал, как фаска на металле. У нас светилась заливка — пятно под
 * стеклом, приём куда более затасканный.
 *
 * Два эффекта не спорят: заливка даёт глубину, кромка — материал.
 * Оставляем оба.
 */
.card, .plan, .step, .fact { position: relative; }

.card::after, .plan::after, .step::after, .fact::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  border: 1px solid rgba(112, 228, 120, .55);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t);
  -webkit-mask-image: radial-gradient(
    ellipse 200px 200px at var(--mx, 50%) var(--my, 50%),
    #000 0%, #0009 30%, #0003 50%, #0000 70%);
          mask-image: radial-gradient(
    ellipse 200px 200px at var(--mx, 50%) var(--my, 50%),
    #000 0%, #0009 30%, #0003 50%, #0000 70%);
}
.card:hover::after, .plan:hover::after,
.step:hover::after, .fact:hover::after { opacity: 1; }

/* Палец не наводят. */
@media (hover: none) {
  .card::after, .plan::after, .step::after, .fact::after { display: none; }
}

/* ══ Сравнительная таблица ═════════════════════════════════════════════
 *
 * Единственный вид, в котором «чего у вас нет сейчас» читается без
 * хвастовства: человек сам видит пустую клетку слева. Мы ничего не
 * утверждаем — мы показываем.
 */
.vs {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-ui);
}
.vs th, .vs td {
  padding: 16px 18px;
  border-bottom: 1px solid var(--line-soft);
  text-align: left;
  vertical-align: middle;
}
.vs thead th {
  font-size: var(--fs-micro);
  font-weight: var(--fw-micro);
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
  color: var(--faint);
  border-bottom-color: var(--line);
}
.vs tbody td:first-child { color: var(--text); width: 40%; }
.vs td:not(:first-child) { text-align: center; width: 15%; }
.vs .no  { color: var(--faint); }
.vs .mid { color: var(--dim); font-size: var(--fs-micro); }
.vs .yes { color: var(--accent); font-weight: 700; }
/* Наша колонка выделена не цветом заливки, а плотностью: заливка
   спорила бы с фирменным зелёным в самих клетках. */
.vs th:last-child, .vs td:last-child { background: rgba(28,187,147,.05); }
.vs tbody tr:last-child td { border-bottom: 0; }

.vs-wrap { overflow-x: auto; }

/* Сноска под сравнением: кто такой «обычный репрайсер» и наше
   слабое место словами (1.9.124). */
.vs-note { margin-top: 18px; max-width: 72ch; font-size: var(--fs-micro); color: var(--dim); line-height: 1.6; }

/* На телефоне таблица РАЗВОРАЧИВАЕТСЯ В БЛОКИ, а не прокручивается.
 *
 * Владелец: «"Чего кабинет Kaspi не даёт" в мобильной версии не влезает
 * по горизонтали». Замер: таблице нужно 457 px, а места 343 — и за край
 * уезжала колонка GenRate, то есть ровно та, ради которой весь раздел.
 *
 * Боковая прокрутка внутри блока этого не чинит: человек видит «что
 * нужно продавцу» и «кабинет Kaspi», а ответ надо искать пальцем. Хуже
 * того, он может его и не найти — что там правее, ничто не подсказывает.
 *
 * Поэтому строка становится блоком: сверху название, под ним три
 * подписанные ячейки в строку. Подписи приходят из `data-h` — на
 * широком экране их не видно, там есть шапка. */
@media (max-width: 620px) {
  .vs, .vs tbody, .vs tr, .vs td { display: block; width: 100%; }
  .vs thead { display: none; }

  .vs tbody tr {
    padding: 15px 0;
    border-bottom: 1px solid var(--line-soft);
  }
  .vs tbody tr:last-child { border-bottom: 0; }

  .vs tbody td { border: 0; padding: 0; }
  .vs tbody td:first-child {
    width: auto;
    color: var(--text);
    margin-bottom: 10px;
  }
  .vs tbody td:not(:first-child) {
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
    width: auto;
    margin-right: 18px;
    text-align: left;
    font-size: var(--fs-micro);
  }
  .vs tbody td:not(:first-child)::before {
    content: attr(data-h);
    color: var(--faint);
  }
  /* Заливка нашей колонки на блоках не работает — она выделяла
     столбец, а столбцов больше нет. Выделяем значком. */
  .vs td:last-child { background: none; }
}

@media (max-width: 720px) and (min-width: 621px) {
  .vs th, .vs td { padding: 13px 12px; }
  .vs tbody td:first-child { width: auto; min-width: 200px; }
}


/* ══ Экраны с переключением ════════════════════════════════════════════
 *
 * Владелец: «маловато визуальных показов частей интерфейса
 * функционала, калькулятора к примеру, переводчика чатов, каких-то
 * ещё вещей».
 *
 * Показать пять экранов подряд — это пять экранов прокрутки и скука.
 * Пять экранов с переключателем — один экран и демонстрация. Разбор
 * называет этот приём единственным способом уместить продукт
 * целиком, не удлиняя страницу.
 *
 * Вкладки листаются сами, с полосой времени: человеку не надо
 * догадываться, что здесь можно нажать. Навёл курсор — листание
 * останавливается, потому что он начал читать.
 */
.tabs__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 22px;
}
.tabs__btn {
  position: relative;
  overflow: hidden;
  padding: 10px 17px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--dim);
  font: inherit;
  font-size: var(--fs-ui);
  font-weight: var(--fw-ui);
  cursor: pointer;
  transition: color var(--t), border-color var(--t), background var(--t);
}
.tabs__btn:hover { color: var(--text); border-color: var(--faint); }
.tabs__btn.is-on {
  color: var(--text);
  border-color: transparent;
  background: var(--accent-dim);
}
.tabs__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Полоса времени до следующей вкладки. Ширина приходит переменной от
   скрипта — вычислить её в CSS нельзя. */
.tabs__btn::after {
  content: "";
  position: absolute; left: 0; bottom: 0;
  height: 2px; width: var(--wait, 0%);
  background: var(--accent);
  opacity: .55;
}
.tabs__btn:not(.is-on)::after { width: 0; }

.tabs__panel { display: none; }
.tabs__panel.is-on { display: block; }
/* Без скрипта видны ВСЕ панели подряд: пусть страница будет длинной,
   но полной. Спрятать всё и понадеяться на скрипт — значит показать
   пустоту тем, у кого он не загрузился. */
.js .tabs__panel { display: none; }
.js .tabs__panel.is-on { display: block; }

.tabs__note {
  margin: 14px 0 0;
  font-size: var(--fs-ui);
  color: var(--faint);
}

/* ── Макет: журнал действий ──────────────────────────────────────────── */
.ui-log { display: flex; flex-direction: column; gap: 1px; }
.ui-log__row {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 13px;
  background: rgba(255,255,255,.015);
  font-size: 13px;
}
.ui-log__t { color: var(--faint); font-size: 12px; white-space: nowrap; }
.ui-log__txt { color: var(--dim); min-width: 0; flex: 1; }
.ui-log__txt b { color: var(--text); font-weight: 600; }
.ui-log__who {
  color: var(--faint); font-size: 12px; white-space: nowrap;
  padding: 3px 8px; border-radius: var(--r-pill);
  background: rgba(255,255,255,.04);
}
.ui-log__row.is-err .ui-log__txt b { color: var(--rival); }

/* ── Макет: аналитика ────────────────────────────────────────────────── */
.ui-kpi {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--line-soft);
}
.ui-kpi > div { background: var(--panel); padding: 13px 14px; }
.ui-kpi__t {
  font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--faint);
}
.ui-kpi__v { margin-top: 5px; font-size: 17px; font-weight: 600; }
.ui-kpi__v.minus { color: var(--rival); }
.ui-kpi__v.plus  { color: var(--accent); }

.ui-waterfall { display: flex; flex-direction: column; gap: 7px; margin-top: 13px; }
.ui-wf { display: flex; align-items: center; gap: 10px; font-size: 12.5px; }
.ui-wf__n { width: 116px; color: var(--dim); flex-shrink: 0; }
.ui-wf__bar { height: 9px; border-radius: 3px; background: var(--accent); }
.ui-wf__bar.minus { background: var(--rival); opacity: .65; }
.ui-wf__s { color: var(--faint); font-size: 12px; white-space: nowrap; }

/* ── Макет: чаты с переводом ─────────────────────────────────────────── */
.ui-chat { display: flex; flex-direction: column; gap: 10px; }
.ui-msg { max-width: 82%; }
.ui-msg__b {
  padding: 10px 13px;
  border-radius: 14px;
  font-size: 13.5px;
  background: rgba(255,255,255,.05);
  color: var(--text);
}
.ui-msg--mine { align-self: flex-end; }
.ui-msg--mine .ui-msg__b { background: var(--accent-dim); }
.ui-msg__tr {
  margin-top: 5px;
  padding-left: 13px;
  border-left: 2px solid var(--accent);
  font-size: 12.5px;
  color: var(--faint);
}
.ui-msg__tr i { font-style: normal; color: var(--accent); }

/* ── Макет: A/B-тест цены ────────────────────────────────────────────── */
.ui-ab { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ui-ab__c {
  padding: 13px;
  border: 1px solid var(--line-soft);
  border-radius: 10px;
}
.ui-ab__c.win { border-color: rgba(28,187,147,.4); background: rgba(28,187,147,.05); }
.ui-ab__h {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 12px; color: var(--faint);
}
.ui-ab__p { margin-top: 6px; font-size: 19px; font-weight: 600; }
.ui-ab__m { margin-top: 9px; font-size: 12.5px; color: var(--dim); }
.ui-ab__m b { color: var(--text); font-weight: 600; }
.ui-ab__c.win .ui-ab__p { color: var(--accent); }

@media (max-width: 720px) {
  .ui-kpi { grid-template-columns: repeat(2, 1fr); }
  .ui-ab  { grid-template-columns: 1fr; }
  .ui-log__who, .ui-log__t { display: none; }
  .ui-wf__n { width: 84px; }
}


/* ══ Бенто-сетка возможностей ══════════════════════════════════════════
 *
 * Три одинаковые карточки — это один элемент, повторённый трижды.
 * Плитки разного размера — разные элементы. Ровно против замечания
 * владельца «новых элементов вообще не вижу».
 *
 * Устройство: три ряда, в каждом одна широкая и две узкие. Широкая —
 * главная возможность смысловой тройки, узкие — спутницы. Человек
 * читает ряд как «вот это, и к нему ещё два», а не как список из
 * девяти равнозначных пунктов.
 *
 * Замер с Supabase: сетка на 12 колонок, дети по 4 / 6 / 8 / 12.
 */
.bento {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 14px;
}
/* 6 + 3 + 3 = 12. Сначала стояло 8 + 4 + 4 = 16 при двенадцати
   колонках, и вторая узкая плитка переносилась на новую строку —
   ряд разваливался. Поймано замером положений. */
.bento > * { grid-column: span 3; }
.bento > .is-wide { grid-column: span 6; }

@media (max-width: 900px) {
  .bento { grid-template-columns: repeat(6, 1fr); }
  .bento > *        { grid-column: span 3; }
  .bento > .is-wide { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .bento > *, .bento > .is-wide { grid-column: 1 / -1; }
}

/* Подпись смысловой тройки: узкая строка над рядом, во всю ширину. */
.bento__row {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 12px;
  margin-top: 10px;
  font-size: var(--fs-micro);
  font-weight: var(--fw-micro);
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
  color: var(--faint);
}
.bento__row:first-child { margin-top: 0; }
.bento__row::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, var(--line) 0%, transparent 70%);
}

/* На какой тариф открывается.
 *
 * Не украшение, а починка противоречия: раздел читался как «всё это
 * входит», а таблица тарифов ниже это опровергала — на одном экране
 * прокрутки. Уровень берётся из services/billing.py и сверяется
 * сторожем: вписать сюда тариф руками нельзя. */
.card__plan {
  display: inline-block;
  margin-top: 10px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  font-size: 11.5px;
  font-weight: var(--fw-ui);
  letter-spacing: .04em;
  color: var(--faint);
}
.card.is-wide h3 { font-size: 23px; }
.card.is-wide p  { max-width: 52ch; }


/* ══ Карточка тарифа: группы вместо столбца галочек ════════════════════
 *
 * Владелец: «описание тарифов как будто мало всего описано… не
 * выглядит это на премиум». Замер подтвердил: на карточках было 21
 * строка, тогда как в коде за тарифами стоит вчетверо больше. Тариф за
 * 49 990 ₸ описывался ОДНОЙ строкой прибавки.
 *
 * Стало 52 строки. Столбцом галочек такое не читают — нужны заголовки
 * групп, и видно по три строки в группе, остальное по нажатию.
 */
.plan__feats { margin: 22px 0; }

.plan__inherit {
  display: flex; align-items: center; gap: 9px;
  margin-bottom: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--fs-ui);
  color: var(--faint);
}
.plan__inherit svg { width: 15px; height: 15px; flex: none; color: var(--gold); }

.plan__group {
  margin: 17px 0 8px;
  font-size: var(--fs-micro);
  font-weight: var(--fw-micro);
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
  color: var(--faint);
}
.plan__group:first-child { margin-top: 0; }

.plan__feats ul { list-style: none; margin: 0; padding: 0; }
.plan__feats li {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 4px 0;
  font-size: var(--fs-ui);
  line-height: 1.45;
}
.plan__feats li svg {
  width: 15px; height: 15px; flex: none;
  margin-top: 3px;
  color: var(--accent);
}

/* Пояснение с новой строки и приглушённое: подпись должна читаться
 * при беглом просмотре, пояснение — при внимательном. Одной строкой
 * они сливаются, и не видно уже ни того, ни другого. */
.plan__feats li i {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: var(--fs-micro);
  line-height: 1.4;
  color: var(--faint);
}

/* Скрывает ТОЛЬКО при работающем скрипте — иначе разворачивать нечем. */
.js .plan__hidden { display: none; }
.js .plan.is-open .plan__hidden { display: flex; }

.plan__more {
  margin-top: 16px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fs-ui);
  font-weight: var(--fw-ui);
  color: var(--accent);
  cursor: pointer;
  transition: opacity var(--t);
}
.plan__more:hover { opacity: .72; }
html:not(.js) .plan__more { display: none; }



/* ══ Блок возражения ═══════════════════════════════════════════════════
 *
 * Две колонки: слева вопрос словами человека, справа ответ, который
 * можно потрогать.
 *
 * Почему отдельным блоком, а не внутри карточки шага: карточка — треть
 * ширины, около 180 px, и подписи ползунка налезали друг на друга до
 * полной нечитаемости. Замерено на предпросмотре.
 */
.objection {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: 40px;
  align-items: center;
  margin-top: 28px;
  padding: 32px 34px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--panel);
}
.objection__q h3 {
  margin: 0 0 10px;
  font-size: var(--fs-h3);
  font-weight: var(--fw-h3);
  letter-spacing: -.02em;
  text-wrap: balance;
}
.objection__q p {
  margin: 0;
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--dim);
}

@media (max-width: 820px) {
  .objection {
    grid-template-columns: 1fr;
    gap: 26px;
    padding: 26px 22px;
  }
}

/* ══ Ползунок «ваша минималка» ═════════════════════════════════════════
 *
 * Самое частое возражение к репрайсеру — «а он не сольёт мне всё в
 * ноль?». Абзацем на него отвечать бесполезно: человек читает обещание
 * и не верит. Пусть подвигает сам.
 *
 * Устройство простое до наглости: конкурент стоит на месте, бот хочет
 * встать на тенге ниже, а минималка — пол, ниже которого он не пойдёт.
 * Когда минималка поднимается выше желаемой цены, подпись меняется с
 * «бьёт конкурента» на «упёрся в ваш пол» — и возражение снимается
 * движением пальца.
 *
 * Демонстрация замкнута в себе: ни от тикера в герое, ни от чего
 * ещё она не зависит. Первая мысль была тянуть её к тикеру, но тикер
 * живёт на четыре экрана выше — человек двигал бы ползунок и не видел
 * последствий.
 */
.floor { margin-top: 18px; }

.floor__scale {
  position: relative;
  height: 40px;
  margin-bottom: 10px;
}
/* Полоса цены. Левый край — дёшево, правый — дорого. */
.floor__bar {
  position: absolute; left: 0; right: 0; top: 17px;
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(90deg,
    rgba(255,107,107,.30) 0%, rgba(255,107,107,.10) 38%,
    var(--line) 60%, var(--line) 100%);
}
/* Закрашенная часть — то, что минималка отрезала. */
.floor__cut {
  position: absolute; left: 0; top: 17px;
  height: 6px;
  border-radius: 3px 0 0 3px;
  background: var(--rival);
  opacity: .5;
  transition: width var(--t);
}
.floor__mark {
  position: absolute; top: 0;
  transform: translateX(-50%);
  font-size: var(--fs-micro);
  font-weight: var(--fw-micro);
  letter-spacing: var(--ls-micro);
  color: var(--faint);
  white-space: nowrap;
  transition: left var(--t), opacity var(--t);
}
.floor__mark b { display: block; color: var(--text); font-weight: var(--fw-ui); }
.floor__mark--bot { color: var(--accent); }
.floor__mark--bot b { color: var(--accent); }

.floor__range {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 22px;
  background: none;
  cursor: grab;
}
.floor__range:active { cursor: grabbing; }
.floor__range::-webkit-slider-runnable-track {
  height: 2px; background: var(--line); border-radius: 2px;
}
.floor__range::-moz-range-track {
  height: 2px; background: var(--line); border-radius: 2px;
}
/* Ручка крупная намеренно: по ней надо попасть пальцем на телефоне. */
.floor__range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 22px; height: 22px; margin-top: -10px;
  border-radius: 50%;
  background: var(--text);
  border: 5px solid var(--accent);
  box-shadow: 0 2px 10px rgba(0,0,0,.5);
  transition: transform var(--t-pop);
}
.floor__range::-moz-range-thumb {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--text);
  border: 5px solid var(--accent);
  box-shadow: 0 2px 10px rgba(0,0,0,.5);
}
.floor__range:hover::-webkit-slider-thumb { transform: scale(1.12); }
.floor__range:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.floor__out {
  margin-top: 10px;
  font-size: var(--fs-ui);
  line-height: 1.5;
  color: var(--dim);
}
.floor__out b { color: var(--text); font-weight: var(--fw-ui); }
.floor__out.is-floor b { color: var(--gold); }

/* ══ Переключатель «Выручка / Прибыль» ═════════════════════════════════
 *
 * Весь смысл раздела «честная прибыль» — что из выручки вычитается
 * комиссия, доставка, налог и упаковка. Абзацем это читают по
 * диагонали; одним нажатием, от которого линия проседает, — понимают.
 */
.ui-chart__sw {
  display: inline-flex;
  margin-left: auto;
  padding: 2px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: rgba(255,255,255,.02);
}
.ui-chart__sw button {
  padding: 3px 10px;
  border: 0; border-radius: var(--r-pill);
  background: none;
  font: inherit;
  font-size: 11px;
  font-weight: var(--fw-ui);
  color: var(--faint);
  cursor: pointer;
  transition: color var(--t), background var(--t);
}
.ui-chart__sw button.is-on {
  background: var(--accent-dim);
  color: var(--accent);
}
.ui-chart svg path, .ui-chart svg circle {
  transition: d .5s cubic-bezier(.4,0,.2,1),
              cy .5s cubic-bezier(.4,0,.2,1);
}

/* Подпись под макетом экрана.
 *
 * Картинка без подписи заставляет догадываться, подпись превращает её
 * в доказательство. У макетов в `#screens` такая строка есть с самого
 * начала (`.tabs__note`), а у главного экрана в `#inside` не было. */
.stage__note {
  margin: 14px 0 0;
  font-size: var(--fs-ui);
  line-height: 1.5;
  color: var(--faint);
}
.stage__note b { color: var(--dim); font-weight: var(--fw-ui); }

/* Числа в первом экране.
 *
 * У героя не было ни одной цифры, кроме бегущих в тикере, — а продукт
 * наш про числа. Строка заявляет жанр до того, как человек начнёт
 * читать.
 *
 * Числа проверяемые и взяты из кода, а не придуманы: четыре стратегии
 * (`strategy.py`), пятнадцать минут и минута (`tasks.py`,
 * `beat_schedule`). */
.hero__nums {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 8px 18px;
  margin: 20px 0 0;
  font-size: var(--fs-ui);
  color: var(--faint);
}
.hero__nums b {
  font-size: 17px;
  font-weight: var(--fw-ui);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.hero__nums span { display: inline-flex; align-items: baseline; gap: 7px; }



/* ── Шапка правовой страницы ────────────────────────────────────────────
 *
 * Не `.nav` с витрины: там пункты разделены только отступом, и три
 * длинных подряд на тёмном фоне сливаются в одну строку. Владелец
 * увидел это сразу: «выглядят как одна строка или одно предложение».
 *
 * На витрине приём работает, потому что пункты короткие («Тарифы»,
 * «Вопросы») и их шесть — глаз читает их как перечень. Здесь их три и
 * они длинные, и перечень перестаёт читаться перечнем. Значит нужна
 * граница у каждого: рамка.
 */
.lnav {
  display: flex; align-items: center; gap: 8px;
  margin-left: 26px;
}
.lnav__a {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: 14px;
  font-weight: var(--fw-ui);
  color: var(--dim);
  white-space: nowrap;
  transition: color var(--t), border-color var(--t), background var(--t);
}
.lnav__a:hover {
  color: var(--text);
  /* Чуть ярче `--line`. Отдельным токеном не заводим: осветление
     рамки при наведении нужно только здесь, а токен ради одного
     места — это имя, которое потом ищут по всему файлу. */
  border-color: rgba(255,255,255,.14);
  background: rgba(255,255,255,.03);
}
.lnav__a svg { width: 15px; height: 15px; flex: none; }

/* Открытая страница помечена заливкой, а не только цветом текста:
 * одного цвета мало, когда рядом такая же рамка. */
.lnav__a.is-on {
  color: var(--accent);
  border-color: var(--accent-dim);
  background: var(--accent-dim);
}

@media (max-width: 760px) {
  /* На телефоне «На главную» сворачивается до стрелки: три кнопки с
   * полными подписями требуют 430 px при доступных 343. Стрелка
   * понятна и без слова, а две оставшиеся подписи терять нельзя —
   * именно они отличают документы друг от друга. */
  /* На телефоне кнопки уходят ОТДЕЛЬНОЙ СТРОКОЙ под логотип.
   *
   * В одну строку с логотипом и переключателем языка они не влезают:
   * замер на 375 px — нужно около 390. С переносом внутри самой
   * полосы получалось хуже всего: шапка остаётся высотой 67 px, и
   * второй ряд кнопок вылезал за её край наполовину обрезанным.
   *
   * Строка под логотипом честнее: шапка вырастает ровно настолько,
   * сколько нужно, и ничего не обрезается. */
  /* Высота шапки задана жёстко (66 px), и перенесённый ряд кнопок
   * из неё ВЫПАДАЛ: сама полоса оставалась 67 px, а кнопки
   * оказывались под ней, на фоне страницы. При прокрутке они уехали
   * бы вместе с текстом, хотя шапка липкая. Замер: высота полосы 67
   * при кнопках на отметке 85.
   *
   * Поэтому на правовой странице высота становится минимальной, а
   * не фиксированной — полоса вырастает ровно под содержимое. */
  .legal-page .top__inner {
    flex-wrap: wrap;
    height: auto;
    min-height: 66px;
    padding-bottom: 12px;
  }
  .lnav {
    order: 3;
    flex-basis: 100%;
    margin: 10px 0 0;
    gap: 6px;
  }
  .lnav__a { padding: 6px 10px; font-size: 13px; }
  .lnav__a:first-child { padding: 6px 8px; font-size: 0; gap: 0; }
  .lnav__a:first-child svg { width: 17px; height: 17px; }
}

@media (max-width: 420px) {
  .lnav__a { padding: 5px 9px; font-size: 12.5px; }
}

/* ══ Правовые страницы ═════════════════════════════════════════════════
 *
 * Оферта и политика конфиденциальности. Стиль спокойный: это документ,
 * который читают внимательно и не любуются им. Ширина строки держится
 * у 70 знаков — длиннее глаз теряет начало следующей строки, а такие
 * тексты и без того читают через силу.
 */
.legal { max-width: 74ch; }
.legal h1 { margin-bottom: 6px; }
.legal__date {
  margin: 0 0 32px;
  font-size: var(--fs-ui);
  color: var(--faint);
}
.legal h2 {
  margin: 40px 0 14px;
  font-size: 23px;
  font-weight: var(--fw-h3);
  letter-spacing: -.02em;
}
.legal h3 {
  margin: 26px 0 10px;
  font-size: var(--fs-lede);
  font-weight: var(--fw-h3);
}
.legal p, .legal li {
  font-size: var(--fs-body);
  line-height: 1.62;
  color: var(--dim);
}
.legal p { margin: 0 0 14px; }
.legal b { color: var(--text); font-weight: var(--fw-ui); }
.legal ul { margin: 0 0 18px; padding-left: 22px; }
.legal li { margin-bottom: 8px; }
.legal a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }

/* Выноска «коротко, чтобы не читать всё». Главное — в начале: до
 * конца такого документа доходит один из десяти. */
.legal__note {
  margin: 0 0 32px;
  padding: 20px 24px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r) var(--r) 0;
  background: var(--accent-dim);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text);
}

/* Предупреждение, что документ не проверен юристом. Прятать его было
 * бы обманом: человек вправе знать, что читает проект. */
.legal__warn {
  margin: 40px 0 0;
  padding: 18px 22px;
  border: 1px solid var(--gold);
  border-radius: var(--r);
  font-size: var(--fs-ui);
  line-height: 1.55;
  color: var(--dim);
}
.legal__warn b { color: var(--gold); }

.legal__table {
  width: 100%;
  margin: 0 0 20px;
  border-collapse: collapse;
  font-size: var(--fs-ui);
}
.legal__table th, .legal__table td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--line-soft);
  text-align: left;
  vertical-align: top;
  color: var(--dim);
}
.legal__table thead th {
  color: var(--faint);
  font-size: var(--fs-micro);
  font-weight: var(--fw-micro);
  letter-spacing: var(--ls-micro);
  text-transform: uppercase;
}
.legal__table--req th { width: 34%; color: var(--faint); font-weight: var(--fw-body); }
.legal__table--req td { color: var(--text); }

/* Таблица реквизитов на телефоне разворачивается в строки: 34% ширины
 * под подпись на экране в 360 px — это два знака и перенос. */
@media (max-width: 620px) {
  .legal__table, .legal__table tbody, .legal__table tr, .legal__table td,
  .legal__table th { display: block; width: 100%; }
  .legal__table thead { display: none; }
  .legal__table tr { padding: 10px 0; border-bottom: 1px solid var(--line-soft); }
  .legal__table th, .legal__table td { border: 0; padding: 2px 0; }
  .legal__table--req th { width: auto; }
}

/* ══ Уведомление о cookie ══════════════════════════════════════════════
 *
 * Полоса внизу, поверх страницы, но НЕ перекрывающая её: ничего не
 * затемняет и ничего не блокирует. Строго необходимая cookie согласия
 * не требует, и окно «примите или уходите» ради неё было бы помехой
 * без причины.
 */
.cookie {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 80;
  padding: 14px 0;
  border-top: 1px solid var(--line);
  background: rgba(8,9,13,.92);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
}
.cookie[hidden] { display: none; }
.cookie__in {
  display: flex; align-items: center; gap: 20px;
  width: min(var(--shell), 100% - 56px);
  margin: 0 auto;
}
.cookie p {
  margin: 0;
  font-size: var(--fs-ui);
  line-height: 1.5;
  color: var(--dim);
}
.cookie b { color: var(--text); font-weight: var(--fw-ui); }
.cookie a { color: var(--accent); }
.cookie .btn { flex: none; }

@media (max-width: 720px) {
  .cookie__in {
    flex-direction: column; align-items: stretch; gap: 12px;
    width: calc(100% - 32px);
  }
}


/* ══ ДВИЖЕНИЕ ══════════════════════════════════════════════════════════
 *
 * Три приёма, снятые с премиальных витрин по замерам
 * (`docs/landing/03-движение.md`). Общее у всех трёх: они работают
 * ОДИН раз или не работают вовсе — ничего не считается каждый кадр,
 * кроме одной кромки на одном элементе.
 */

/* ── 1. Вход героя лестницей ────────────────────────────────────────────
 *
 * Элементы первого экрана входят по очереди сверху вниз.
 *
 * Зачем. Первый экран — единственное место, где человек ничего не
 * прокручивает и просто смотрит. Лестница даёт порядок чтения: глаз
 * ведут, а не бросают в готовую композицию. И она маскирует загрузку:
 * пока въезжает третий элемент, шрифты уже встали.
 *
 * Замер: Superhuman — задержки 100/300/500/600 мс при длительности
 * 300; Raycast — 1000 мс и второй с задержкой ровно 1000. Берём шаг
 * около 170 мс: у нас пять ступеней, при шаге 200 последняя ушла бы
 * на 820 мс, а это уже заметное ожидание.
 *
 * Макет входит ОТДЕЛЬНО и медленнее: 1,2 с на шесть точек. Он не
 * «влетает», он обретает вес — приём Resend с его 5 px за 1,5 с.
 *
 * Без скрипта класса `js` нет, и весь герой просто стоит на месте.
 */
@media (prefers-reduced-motion: no-preference) {
  .js .hero__copy > * {
    opacity: 0;
    transform: translateY(12px);
    animation: hero-in .85s cubic-bezier(0, 0, .2, 1) forwards;
  }
  .js .hero__copy > .eyebrow    { animation-delay:  60ms; }
  .js .hero__copy > h1          { animation-delay: 200ms; }
  .js .hero__copy > p           { animation-delay: 370ms; }
  .js .hero__copy > .hero__cta  { animation-delay: 500ms; }
  .js .hero__copy > .hero__nums { animation-delay: 600ms; }
  .js .hero__copy > .hero__note { animation-delay: 680ms; }

  .js .ticker {
    opacity: 0;
    transform: translateY(6px) scale(.985);
    animation: stage-in 1.2s cubic-bezier(0, 0, .2, 1) 700ms forwards;
  }
}
@keyframes hero-in  { to { opacity: 1; transform: none; } }
@keyframes stage-in { to { opacity: 1; transform: none; } }

/* ── 2. Ореол у края раздела ────────────────────────────────────────────
 *
 * Большое мягкое пятно фирменного цвета, приклеенное к краю. Не
 * движется вообще.
 *
 * Зачем. На тёмной витрине глубина берётся не из теней — тени на
 * чёрном не видно. Она берётся из света. Ореол за макетом даёт понять,
 * что предмет стоит НАД фоном, а не нарисован на нём.
 *
 * Замер снят с Attio дословно: `radial-gradient(90% 80% at 50% 100%)`
 * снизу и `70% 106.6667% at 50% 0%` сверху.
 *
 * Цена ноль: статичная картинка, ни одного кадра.
 *
 * Ставим ровно в двух местах — под герой и под тарифы. Третий ореол
 * превратил бы приём в фон.
 */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    90% 70% at 50% 100%,
    rgba(28, 187, 147, .10) 0%,
    rgba(28, 187, 147, .03) 45%,
    transparent 72%);
}
/* У тарифов свет идёт СВЕРХУ: выделенная карточка стоит в верхней
   половине раздела, и пятно снизу подсвечивало бы пустоту под ней.
 *
 * И это ФОН самого раздела, а не псевдоэлемент. У #pricing оба
 * псевдоэлемента уже заняты швом между разделами (`.section +
 * .section::before` рисует линию, `::after` — свечение над ней).
 * Правило с идентификатором перебило бы шов по весу и погасило его
 * молча — беда, которую на глаз не увидишь, потому что шов и так
 * еле заметен. */
#pricing {
  background: radial-gradient(
    70% 60% at 50% 0%,
    rgba(28, 187, 147, .09) 0%,
    rgba(28, 187, 147, .03) 50%,
    transparent 75%);
}

/* ── 3. Коническая кромка у выделенного тарифа ──────────────────────────
 *
 * Единственная рамка на странице, которая медленно переливается.
 *
 * Зачем. Одно вечное движение на всю страницу работает как метка:
 * «вот сюда». Если таких меток две — обе перестают работать. Поэтому
 * и только выделенный тариф.
 *
 * Восемь секунд — между Resend (6) и Superhuman (10). Медленнее
 * выглядит спокойнее, а тариф не то место, где нужна суета.
 *
 * Цена низкая, но не ноль: анимация угла заставляет браузер
 * перерисовывать градиент каждый кадр. На ОДНОМ элементе это
 * незаметно; на шести было бы заметно.
 *
 * Если `@property` не поддержан, градиент просто стоит под
 * фиксированным углом — выглядит нормально, просто не крутится.
 */
@property --ang {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

.plan--featured { position: relative; }
.plan--featured::after {
  content: '';
  position: absolute; inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(from var(--ang),
    transparent 0deg,
    var(--accent) 70deg,
    var(--accent-2) 110deg,
    transparent 180deg,
    transparent 360deg);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  animation: ang 8s linear infinite;
  pointer-events: none;
  z-index: 2;
}
@keyframes ang { to { --ang: 360deg; } }

@media (prefers-reduced-motion: reduce) {
  .plan--featured::after { animation: none; --ang: 120deg; }
}


/* ══ Закреплённая сцена ════════════════════════════════════════════════
 *
 * Макет дашборда стоит на месте, мимо едут три текста, каждый
 * подсвечивает свою часть экрана.
 *
 * Зачем. Прокрутка перестаёт быть перемоткой и становится
 * управлением: человек крутит колесо — продукт отвечает. Тот же
 * механизм, что делает тикер лучшей частью витрины, только рычаг в
 * руке у зрителя.
 *
 * Почему один экран, а не пять. Четыре из пяти уже живут в разделе
 * «Экраны» вкладками; поставить их сюда второй раз — показать одно и
 * то же дважды. А один экран, разобранный по частям, отвечает на
 * вопрос, которого не отвечают пять: «что тут вообще смотреть».
 */
.scene {
  display: grid;
  grid-template-columns: minmax(0, .82fr) minmax(0, 1.18fr);
  gap: 56px;
  align-items: start;
}

.scene__stick {
  position: sticky;
  /* Шапка 66 px плюс воздух, чтобы макет не лип к ней вплотную. */
  top: 90px;
}

/* Каждый шаг занимает почти экран: иначе два текста оказываются в
   середине одновременно, и подсветка мечется между ними. */
.scene__step {
  min-height: 78vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-right: 8px;
}
.scene__step h3 {
  margin: 0 0 12px;
  font-size: var(--fs-h3);
  font-weight: var(--fw-h3);
  letter-spacing: var(--ls-h3);
  text-wrap: balance;
}
.scene__step p {
  margin: 0;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--dim);
}

/* Приглушение работает ТОЛЬКО при живом скрипте.
 *
 * Без него ни один шаг не получит `is-live`, и все три остались бы
 * навсегда полупрозрачными — то есть хуже, чем были. */
.js .scene__step {
  opacity: .34;
  transition: opacity .35s cubic-bezier(0, 0, .2, 1);
}
.js .scene__step.is-live { opacity: 1; }

/* ── Подсветка частей макета ────────────────────────────────────────────
 *
 * Гасим НЕ названную часть, а не выделяем названную: выделение
 * заливкой или рамкой добавило бы на макет то, чего в продукте нет, —
 * то есть соврало бы о интерфейсе. Приглушение соседей ничего не
 * добавляет, только убирает.
 */
.js .scene__stick .ui-tile,
.js .scene__stick .ui-chart {
  transition: opacity .35s cubic-bezier(0, 0, .2, 1),
              filter   .35s cubic-bezier(0, 0, .2, 1);
}
/* Гасим ВСЕ плитки и график, а не только те, у кого есть роль.
 *
 * Сначала приглушались лишь помеченные, и плитки без роли — «На
 * продаже», «Заканчиваются» — оставались яркими наравне с названной.
 * Подсветка читалась случайной: непонятно, почему горят три вещи, а
 * говорят про одну. Замер на предпросмотре показал это сразу. */
.js .scene__stick[data-live] .ui-tile,
.js .scene__stick[data-live] .ui-chart {
  opacity: .28;
  filter: saturate(.35);
}
.js .scene__stick[data-live="profit"] [data-part="profit"],
.js .scene__stick[data-live="frozen"] [data-part="frozen"],
.js .scene__stick[data-live="places"] [data-part="places"] {
  opacity: 1;
  filter: none;
}

/* Значки-пояснения у макета привязаны к шагам так же. */
.js .scene__stick[data-live] .pin { opacity: .2; transition: opacity .35s; }
.js .scene__stick[data-live="profit"] .pin--a,
.js .scene__stick[data-live="frozen"] .pin--b,
.js .scene__stick[data-live="places"] .pin--c { opacity: 1; }

@media (max-width: 980px) {
  /* На узком экране закреплять нечего: макет и текст занимают всю
     ширину по очереди, и sticky превратился бы в «макет прилип и
     закрыл собой текст». Сцена разворачивается в обычную колонку. */
  .scene { grid-template-columns: 1fr; gap: 28px; }
  .scene__stick { position: static; top: auto; order: -1; }
  .scene__step { min-height: 0; padding: 0 0 26px; }
  .js .scene__step { opacity: 1; }
  .js .scene__stick[data-live] .ui-tile,
  .js .scene__stick[data-live] .ui-chart { opacity: 1; filter: none; }
  .js .scene__stick[data-live] .pin { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  /* Человеку, попросившему убрать движение, сцена показывается
     целиком и сразу: ни приглушения, ни переходов. */
  .js .scene__step { opacity: 1; transition: none; }
  .js .scene__stick[data-live] .ui-tile,
  .js .scene__stick[data-live] .ui-chart { opacity: 1; filter: none; }
  .js .scene__stick[data-live] .pin { opacity: 1; }
}


/* == Блок "Только у нас" ===============================================
 *
 * Четыре вещи, которых нет ни у кого из семи замеренных конкурентов.
 * До 1.9.97 на витрине о них не было НИ СЛОВА - проверено поиском по
 * разметке: ноль совпадений на автоввод кода, двухфакторку и
 * шифрование.
 *
 * Форма нарочно НЕ карточная. Карточек в три колонки на странице уже
 * три набора: шаги, возможности, тарифы. Четвёртый превратил бы
 * страницу в опись. Здесь список с крупным номером и волосяной линией
 * между записями - читается как перечень доводов, а не как витрина.
 */
.only { margin-top: 30px; }

.only__row {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr);
  gap: 22px;
  padding: 26px 0;
  border-top: 1px solid var(--line-soft);
}
.only__row:first-child { border-top: 0; padding-top: 6px; }

/* Номер крупный и приглушённый: он держит ритм списка, но не спорит с
   заголовком записи за внимание. */
.only__n {
  font-size: 30px;
  font-weight: 500;
  color: var(--line);
  line-height: 1;
  padding-top: 2px;
}

.only__body h3 {
  margin: 0 0 8px;
  font-size: var(--fs-h3);
  font-weight: var(--fw-h3);
  letter-spacing: var(--ls-h3);
  text-wrap: balance;
}
.only__body p {
  margin: 0;
  max-width: 64ch;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--dim);
}

/* Подписи с именами python-файлов под каждой записью УБРАНЫ
 * 24.09.2026. Владелец: «это внутренняя кухня, зачем это
 * показывать». Продавцу нечего делать с `services/totp.py`: подпись
 * выглядела уверенностью для нас и шумом для него.
 *
 * Вместе с ней ушла приписка, объяснявшая приём. Объяснение,
 * нужное приёму, — признак того, что приём не работает. */

@media (max-width: 640px) {
  /* Номер уходит над заголовком: 74 px под него на экране в 343 - это
     четверть ширины, отданная двум знакам. */
  .only__row { grid-template-columns: 1fr; gap: 6px; padding: 22px 0; }
  .only__n { font-size: 22px; }
}

/* ── Частые вопросы ───────────────────────────────────────────────────── */
/* На <details> — раскрывается без скрипта и находится поиском по странице. */
.faq { border-top: 1px solid var(--line-soft); }
.faq details {
  border-bottom: 1px solid var(--line-soft);
}
.faq summary {
  display: flex; align-items: center; gap: 14px;
  padding: 20px 4px;
  font-size: 16px; font-weight: 700;
  cursor: pointer;
  list-style: none;
  transition: color var(--t);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
.faq summary::after {
  content: '';
  margin-left: auto;
  width: 11px; height: 11px;
  border-right: 2px solid var(--faint);
  border-bottom: 2px solid var(--faint);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform var(--t), border-color var(--t);
  flex-shrink: 0;
}
.faq details[open] summary::after {
  transform: rotate(225deg) translate(-3px, -3px);
  border-color: var(--accent);
}
.faq details[open] summary { color: var(--accent); }
.faq p {
  margin: 0 0 22px;
  padding-right: 40px;
  font-size: 15px; color: var(--dim);
  max-width: 78ch;
}

@media (max-width: 900px) {
}
@media (max-width: 720px) {
  .faq summary { font-size: 15px; padding: 17px 2px; }
  .faq p { padding-right: 24px; }
}
