/* Стили лендинга.
 *
 * Вынесены из inline-<style> в views/landing.ejs: 31 КБ правил приезжали
 * заново с каждым запросом главной (46% веса документа) и не могли быть
 * закэшированы отдельно. Теперь файл отдаётся с immutable-кэшем на год, а
 * его URL версионируется через asset() (см. src/services/assets.js).
 */

/* ── Шрифты (самохостинг — CSP разрешает font-src только 'self') ────── */
    @font-face {
      font-family: 'Inter';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url('/fonts/Inter-latin.woff2') format('woff2');
      unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
    }
    @font-face {
      font-family: 'Inter';
      font-style: normal;
      font-weight: 100 900;
      font-display: swap;
      src: url('/fonts/Inter-cyrillic.woff2') format('woff2');
      unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
    }
    @font-face {
      font-family: 'Manrope';
      font-style: normal;
      font-weight: 200 800;
      font-display: swap;
      src: url('/fonts/Manrope-latin.woff2') format('woff2');
      unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
    }
    @font-face {
      font-family: 'Manrope';
      font-style: normal;
      font-weight: 200 800;
      font-display: swap;
      src: url('/fonts/Manrope-cyrillic.woff2') format('woff2');
      unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
    }

    /* ── Дизайн-токены лендинга (Vibrant Glass: тёплый мятно-белый фон +
       бирюза/фиолет/оранжевый акценты) — переопределяются на body, т.к.
       кастомные свойства наследуются по дереву DOM и не требуют трогать общий
       style.css, используемый в дашборде/admin. --c-bg/--c-surface/--c-border
       намеренно НЕ переопределяются: превью дашборда в hero (те же классы,
       что и в dashboard/progress.ejs) должно выглядеть как настоящий UI, а не
       как часть маркетингового «стекла» — стекло живёт в отдельных
       --glass/--glass-border, применённых только к декоративным карточкам. */
    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      /* --c-primary/--c-accent-2/--c-accent-3 — затемнены в светлой теме
         относительно исходной палитры (#0d9488/#7c3aed/#ea580c), т.к. как
         текст/ссылки/пилюли они не проходили WCAG AA 4.5:1 (были ~3.0–3.5:1).
         Токена --c-grad-3 здесь больше нет: он существовал ради градиентной
         заливки hero-заголовка, а она убрана — акцент в системе делается весом
         и кеглем. В blog-styles.ejs своя копия тройки, её это не касается.
         --c-*-btn — тёмный, ОДИНАКОВЫЙ в обеих темах оттенок для сплошной
         заливки под белым текстом/иконками (кнопки, чипы, логотип): яркий
         бирюзовый/оранжевый из тёмной темы (--c-primary и т.д.) отлично
         читается как текст на тёмном фоне, но белый текст поверх него самого
         не проходит 4.5:1 — отдельный токен решает это без потери яркости
         акцентов в тёмной теме. */
      --c-primary:  #0c6e63;
      --c-text:     #0f2e2b;
      --c-muted:    #4b6b67;
      --c-info-bg:  #e6fbf6;
      --radius:     10px;
      --c-accent-2: #6d28d9;
      --c-accent-3: #9a3412;
      --c-primary-btn:  #0c6e63;
      --c-accent-2-btn: #6d28d9;
      --c-accent-3-btn: #9a3412;
      /* Заливка главной кнопки внизу лендинга. Отдельная тройка токенов, потому
         что здесь перевёрнута сама схема: не белый текст на тёмной заливке, а
         ТЁМНЫЙ текст на яркой. Причина физическая — тёплый цвет, проходящий с
         белым 4.5:1, обязан быть настолько тёмным, что становится кирпичным
         (--c-accent-3-btn #9a3412 и был таким). С тёмной охрой поверх можно
         взять звонкий янтарь: 8.43:1, и кнопка наконец выглядит живой.
         --c-cta-edge нужен только светлой теме: сама по себе яркая заливка на
         почти белом фоне даёт менее 3:1 по границе, то есть кнопка перестаёт
         читаться как объект (WCAG 1.4.11). Обводка тем же цветом, уведённым в
         глубину, возвращает границу, не трогая цвет заливки.
         Объявлены ОДИН раз и намеренно не повторяются в тематических блоках
         ниже: связка «заливка + текст + граница» самодостаточна, от темы
         страницы не зависит и расходиться между темами не должна. */
      --c-cta-btn:  #f59e0b;
      --c-cta-ink:  #231205;
      --c-cta-edge: #b26f04;
      --glass:        rgba(255,255,255,.65);
      --glass-border: rgba(255,255,255,.8);
      --blob1: rgba(124,58,237,.14);
      --blob2: rgba(234,88,12,.12);
      --blob3: rgba(13,148,136,.14);
      /* Ролевая типографическая шкала — единая для лендинга и блога (см.
         DESIGN.md Typography). display/headline объявлены прямо на h1/h2,
         остальное — общие роли, чтобы одинаковые по смыслу тексты (пункты
         меню, подписи карточек и т.д.) не расходились в 13/13.5/14px без
         причины. */
      /* Display — верх шкалы. Раньше значение жило литералом прямо в .hero h1;
         вынесено в роль, когда финальный блок лендинга потребовал тот же кегль
         (страница открывается и закрывается одним размером — это осознанные
         скобки, а не совпадение). */
      --fs-display: clamp(28px, 4.2vw, 52px);
      /* Numeral — крупные числа-доказательства в финальном блоке. Отдельная
         роль, а не Display: числа обязаны быть заметно мельче заголовка рядом,
         иначе два акцента в одной карточке дерутся за внимание. */
      --fs-numeral: clamp(30px, 3vw, 40px);
      --fs-lead:   17px;
      --fs-title:  16px;
      --fs-sub:    15px;
      --fs-body:   14px;
      --fs-label:  13px;
      --fs-meta:   12px;
      --fs-mono:   12px;
      /* Эти градиенты остаются рабочим фоном сами по себе: WebGL-слой ложится
         поверх них, а если он не запустился (нет контекста, отключён JS),
         страница выглядит ровно так, как выглядела. */
      background:
        radial-gradient(560px 380px at 12% 0%, var(--blob1), transparent 60%),
        radial-gradient(620px 420px at 92% 8%, var(--blob2), transparent 60%),
        radial-gradient(760px 520px at 50% 28%, var(--blob3), transparent 60%),
        var(--c-bg);
    }

    /* Световой слой. z-index: -1 ставит его НАД фоном страницы (фон корня
       рисуется раньше любого стека) и ПОД всем контентом. fixed — свет не
       уезжает со скроллом, а остаётся ровным полем, сквозь которое видно
       страницу; это и есть «смотреть сквозь стену контрольной комнаты». */
    .bg-shader {
      position: fixed;
      inset: 0;
      z-index: -1;
      display: block;
      width: 100%;
      height: 100%;
      pointer-events: none;
    }
    @media (prefers-color-scheme: dark) {
      body {
        --c-primary:  #2dd4bf;
        --c-text:     #eaf6f3;
        --c-muted:    #93a8a3;
        --c-info-bg:  #10302b;
        --c-accent-2: #a78bfa;
        --c-accent-3: #fb923c;
        --c-primary-btn:  #0c6e63;
        --c-accent-2-btn: #6d28d9;
        --c-accent-3-btn: #9a3412;
        --glass:        rgba(255,255,255,.055);
        --glass-border: rgba(255,255,255,.12);
        --blob1: rgba(167,139,250,.22);
        --blob2: rgba(251,146,60,.16);
        --blob3: rgba(45,212,191,.18);
      }
    }
    html[data-theme="dark"] body {
      --c-primary:  #2dd4bf;
      --c-text:     #eaf6f3;
      --c-muted:    #93a8a3;
      --c-info-bg:  #10302b;
      --c-accent-2: #a78bfa;
      --c-accent-3: #fb923c;
      --c-primary-btn:  #0c6e63;
      --c-accent-2-btn: #6d28d9;
      --c-accent-3-btn: #9a3412;
      --glass:        rgba(255,255,255,.055);
      --glass-border: rgba(255,255,255,.12);
      --blob1: rgba(167,139,250,.22);
      --blob2: rgba(251,146,60,.16);
      --blob3: rgba(45,212,191,.18);
    }
    html[data-theme="light"] body {
      --c-primary:  #0c6e63;
      --c-text:     #0f2e2b;
      --c-muted:    #4b6b67;
      --c-info-bg:  #e6fbf6;
      --c-accent-2: #6d28d9;
      --c-accent-3: #9a3412;
      --c-primary-btn:  #0c6e63;
      --c-accent-2-btn: #6d28d9;
      --c-accent-3-btn: #9a3412;
      --glass:        rgba(255,255,255,.65);
      --glass-border: rgba(255,255,255,.8);
      --blob1: rgba(124,58,237,.14);
      --blob2: rgba(234,88,12,.12);
      --blob3: rgba(13,148,136,.14);
    }

    h1, h2, h3, .topbar-logo {
      font-family: 'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      letter-spacing: -.02em;
    }

    html { color-scheme: light dark; }
    html[data-theme="dark"]  { color-scheme: dark; }
    html[data-theme="light"] { color-scheme: light; }

    @media (prefers-reduced-motion: reduce) {
      html { scroll-behavior: auto; }
      /* Отмена подъёма при «уменьшить движение» живёт в КОНЦЕ файла, а не
         здесь: у `.catalog-chip:hover` и у переопределения одинаковая
         специфичность, поэтому побеждает то, что объявлено ниже. Пока блок
         стоял тут, отмена молча не работала — подъём играл и у тех, кто
         просил её отключить. */
    }
    @media (prefers-reduced-motion: no-preference) {
      html { scroll-behavior: smooth; }
    }

    /* ── Пропуск навигации для клавиатуры/скринридеров ────────────────── */
    .skip-link {
      position: absolute;
      left: 12px;
      top: -48px;
      background: var(--c-primary-btn);
      color: #fff;
      padding: 10px 16px;
      border-radius: var(--radius);
      font-size: var(--fs-label);
      font-weight: 600;
      z-index: 500;
      transition: top .15s;
    }
    .skip-link:focus { top: 12px; }

    /* ── Общий фокус ───────────────────────────────────────────────────── */
    a:focus-visible, button:focus-visible, .catalog-chip:focus-visible {
      outline: 2px solid var(--c-primary);
      outline-offset: 2px;
      border-radius: 4px;
    }

    /* ── Хедер ─────────────────────────────────────────────────────────── */
    .topbar.landing-nav {
      position: sticky;
      top: 0;
      z-index: 100;
      background: var(--glass);
      backdrop-filter: blur(16px);
      -webkit-backdrop-filter: blur(16px);
      border-bottom: 1px solid var(--glass-border);
      box-shadow: none;
    }
    .landing-nav .topbar-logo { font-weight: 700; display: inline-flex; align-items: center; gap: 9px; }
    .landing-nav .topbar-logo .mark {
      width: 26px;
      height: 26px;
      border-radius: 8px;
      /* Светлый тонированный фон вместо тёмной сплошной заливки: color-mix с
         transparent, текст тем же акцентом — легче и воздушнее, чем плотный
         тёмный градиент. (Тот же приём носили hero-пилюли статистики, пока их
         не сменил шильдик; здесь он остаётся оправданным — это марка бренда,
         а не третий цветной объект в ряду.) */
      background: linear-gradient(135deg, color-mix(in srgb, var(--c-primary) 22%, transparent), color-mix(in srgb, var(--c-accent-2) 22%, transparent));
      background: linear-gradient(135deg in oklch, color-mix(in srgb, var(--c-primary) 22%, transparent), color-mix(in srgb, var(--c-accent-2) 22%, transparent));
      border: 1px solid color-mix(in srgb, var(--c-primary) 26%, transparent);
      color: var(--c-primary);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      font-family: 'Manrope', sans-serif;
      font-weight: 800;
      font-size: 12.5px;
    }
    .landing-nav-links {
      display: flex;
      align-items: center;
      gap: 20px;
      margin-left: auto;
    }
    .landing-nav-links a {
      color: var(--c-muted);
      font-size: var(--fs-label);
      font-weight: 500;
    }
    .landing-nav-links a:hover { color: var(--c-text); text-decoration: none; }
    /* Кнопки .btn внутри шапки не должны наследовать серый цвет ссылок —
       .landing-nav-links a (класс+тег) иначе перебивает .btn-primary (один класс)
       по специфичности, и белый текст кнопки становился блёкло-серым. */
    .landing-nav-links a.btn,
    .landing-nav-links a.btn:hover {
      color: #fff;
    }
    .landing-nav-links a.btn, .hero-actions a.btn, .cta-card a.btn {
      border-radius: 10px;
    }
    /* .btn-primary в общем style.css красит фон в var(--c-primary) с белым
       текстом — в тёмной теме здесь это яркая бирюза, на которой белый текст
       не проходит 4.5:1. --c-primary-btn — тот же оттенок в обеих темах,
       достаточно тёмный под белый текст. */
    .btn-primary { background: var(--c-primary-btn); }

    section { padding: 72px 32px; }
    .wrap { max-width: 1360px; margin: 0 auto; }
    #how, #catalogs { scroll-margin-top: 68px; }

    .eyebrow {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      font-size: var(--fs-meta);
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: .08em;
      color: var(--c-primary);
      margin-bottom: 10px;
    }
    .eyebrow::before {
      content: '';
      width: 7px;
      height: 7px;
      border-radius: 50%;
      background: var(--c-primary);
    }
    h2 {
      font-size: clamp(22px, 3.4vw, 30px);
      font-weight: 700;
      letter-spacing: -.01em;
      text-wrap: balance;
      margin-bottom: 12px;
    }
    .section-sub {
      font-size: var(--fs-sub);
      color: var(--c-muted);
      max-width: 600px;
      line-height: 1.6;
    }

    /* ── Hero ──────────────────────────────────────────────────────────────
       Композиция — асимметричная пара, а не центрированный столбик: довод
       набран флеш-лефт узкой колонкой, справа от него панель прогресса идёт
       прогон. Центрированная стопка «заголовок → подзаголовок → кнопка →
       пилюли → мокап» читается как заготовка независимо от содержания, а
       здесь у страницы есть что показать в первом же экране. */
    .hero {
      padding: 88px 32px 80px;
      position: relative;
    }
    /* Экран под колонкой текста — плата за то, что читаемая зона уехала из
       центра.
       Световой слой (bg-shader.js) гасит себя ТОЛЬКО к центру экрана:
       scrim = smoothstep(0.46, 0.96, cx). Правило выведено для центрированного
       hero, и пока текст стоял по центру, оно работало — замер там даёт
       5.17:1 при норме 4.5. Колонка слева попадает в противоположную зону, где
       свет идёт в полную силу, и тот же замер обваливается до 1.71:1 (тёмная
       тема, 1280px). Поднимать порог smoothstep нельзя: это глобальный слой, и
       на всей остальной странице свет тогда исчезнет.
       Поэтому экран локальный: мягкое пятно цветом --c-bg под текстом, свет
       остаётся жить справа — вокруг непрозрачной панели, где текста нет.
       После правки худшая точка: 5.85 тёмная / 4.90 светлая (1280px);
       на 1920px — 6.97 / 5.39. Плотность (94% → 78% → 0) — это потолок по
       замеру, а не настройка на глаз: слабее 88/66 светлая тема проходит уже
       без запаса. Геометрия эллипса (58% × 63% при 24% 50%) подобрана так,
       чтобы плотность падала до нуля ВНУТРИ вытянутой на 260px коробки —
       иначе на границе секции появляется горизонтальный шов. */
    .hero::before {
      content: '';
      position: absolute;
      inset: -260px 0;
      z-index: 0;
      pointer-events: none;
      background: radial-gradient(58% 50% at 24% 50%,
        color-mix(in srgb, var(--c-bg) 94%, transparent) 0%,
        color-mix(in srgb, var(--c-bg) 78%, transparent) 50%,
        transparent 100%);
    }
    .hero-grid {
      position: relative;
      z-index: 1;
      max-width: 1240px;
      margin: 0 auto;
      display: grid;
      grid-template-columns: minmax(0, 1.14fr) minmax(0, 1fr);
      align-items: center;
      gap: 56px;
    }
    .hero h1 {
      font-size: var(--fs-display);
      font-weight: 800;
      letter-spacing: -.015em;
      line-height: 1.12;
      text-wrap: balance;
      margin: 0 0 20px;
    }
    /* Число в заголовке — единственная типографическая тонкость, которая тут
       нужна: моноширинные цифры не дают «53» разъехаться относительно
       соседних слов. Прежняя градиентная заливка убрана — акцент в системе
       делается весом и кеглем, а трёхцветный градиент по тексту читается
       как штамп, а не как приём. */
    .hero h1 .num { font-variant-numeric: tabular-nums; }
    .hero-sub {
      color: var(--c-muted);
      font-size: var(--fs-lead);
      max-width: 48ch;
      margin: 0 0 32px;
      line-height: 1.65;
    }
    .hero-actions {
      display: flex;
      align-items: center;
      gap: 20px;
      flex-wrap: wrap;
    }
    /* Главная кнопка страницы — крупнее остальных .btn-primary (nav/cta-card),
       чтобы у hero был один явный фокус, а не набор одинаковых кнопок. */
    .hero-actions .btn { touch-action: manipulation; -webkit-tap-highlight-color: transparent; padding: 14px 32px; font-size: var(--fs-title); font-weight: 600; }
    .hero-actions .text-link { color: var(--c-muted); font-size: var(--fs-body); }
    .hero-actions .text-link:hover { color: var(--c-text); }

    /* Шильдик: три факта в строку через тонкие разделители. Не «крупное число
       над мелкой подписью» — тот приём здесь дал бы вторую точку внимания
       рядом с заголовком и вернул бы страницу в шаблон. */
    .hero-spec {
      display: flex;
      flex-wrap: wrap;
      list-style: none;
      margin: 40px 0 0;
      padding: 18px 0 0;
      /* --c-border, а не --glass-border: шильдик — не стеклянная карточка, а
         текст прямо на фоне. В светлой теме --glass-border это почти белый
         (rgba(255,255,255,.8)), и линейка на #f7f8fa пропадает совсем. */
      border-top: 1px solid var(--c-border);
      font-size: var(--fs-label);
      color: var(--c-muted);
      line-height: 1.45;
    }
    .hero-spec li { flex: 1 1 0; min-width: 120px; padding-right: 18px; }
    .hero-spec li + li { padding-left: 18px; border-left: 1px solid var(--c-border); }
    .hero-spec b {
      display: block;
      font-family: 'Manrope', sans-serif;
      font-size: var(--fs-sub);
      font-weight: 700;
      font-variant-numeric: tabular-nums;
      color: var(--c-text);
      margin-bottom: 2px;
    }

    /* ── Мини-превью реального дашборда ─────────────────────────────────
       Панель непрозрачная и по цветам повторяет настоящий экран: поле —
       var(--c-bg), строки — var(--c-surface). Стекла и блюра здесь нет
       сознательно (DESIGN.md, The Glass-Not-Shadow Rule): это не декоративная
       карточка, а честное представление продукта. */
    .preview-wrap { min-width: 0; }
    .preview-card {
      background: var(--c-bg);
      border: 1px solid var(--c-border);
      border-radius: 12px;
      box-shadow: 0 1px 2px rgba(15,23,42,.04), 0 20px 50px -20px color-mix(in srgb, var(--c-primary) 30%, transparent);
      overflow: hidden;
    }
    /* Шапка панели говорит то же, что настоящий экран прогресса. Прежняя
       имитация окна браузера (три точки + псевдо-адресная строка) убрана: у
       продукта нет такого интерфейса, то есть рамка сообщала «это макет»
       ровно в том месте, где нужно обратное. */
    .preview-head {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      padding: 12px 16px;
      border-bottom: 1px solid var(--c-border);
      background: var(--c-surface);
    }
    .preview-head__title { font-size: var(--fs-label); font-weight: 600; color: var(--c-text); }
    .preview-live {
      display: flex;
      align-items: center;
      gap: 7px;
      flex: none;
      font-size: var(--fs-label);
      color: var(--c-muted);
    }
    .preview-live i { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--c-primary); }
    .preview-body { padding: 18px 20px; }
    /* Длинное имя каталога из реестра не должно ломать строку превью. */
    .preview-body .sub-row__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .preview-body .progress-summary { margin-bottom: 16px; }
    .preview-body .sub-list { gap: 6px; }
    .preview-body .sub-row { padding: 10px 14px; }

    /* ── Единственный авторский момент страницы ───────────────────────────
       Превью использует ТЕ ЖЕ классы, что и настоящий дашборд (.sub-row,
       .badge--running и т.д.), поэтому анимация объявлена узко через
       `.preview-body …` — иначе она незаметно уехала бы на реальный
       dashboard/progress.ejs у залогиненных пользователей, где статусы и
       так меняются вживую через Socket.io. Идея: посетитель должен один раз
       увидеть, как бот проходит каталоги один за другим — это не декор,
       а буквальная визуализация того, что продукт делает. */
    @media (prefers-reduced-motion: no-preference) {
      /* Прибытие hero. Заголовок сюда СОЗНАТЕЛЬНО не входит: он почти наверняка
         LCP-элемент страницы, а появление через opacity сдвигает саму метрику —
         браузер засчитывает отрисовку только когда элемент видим. Остальной
         блок приходит одной короткой волной (не «каждая секция выезжает»), а
         дальше слово берёт превью. */
      .hero-sub, .hero-actions, .hero-spec, .preview-wrap {
        animation: rb-rise .42s cubic-bezier(0.16, 1, 0.3, 1) both;
      }
      .hero-sub     { animation-delay: .05s; }
      .hero-actions { animation-delay: .12s; }
      .hero-spec    { animation-delay: .19s; }
      .preview-wrap { animation-delay: .26s; animation-duration: .52s; }

      .preview-body .sub-row {
        animation: rb-row-in .4s cubic-bezier(0.16, 1, 0.3, 1) both;
      }
      .preview-body .sub-list .sub-row:nth-child(1) { animation-delay: .38s; }
      .preview-body .sub-list .sub-row:nth-child(2) { animation-delay: .44s; }
      .preview-body .sub-list .sub-row:nth-child(3) { animation-delay: .50s; }
      .preview-body .sub-list .sub-row:nth-child(4) { animation-delay: .56s; }
      .preview-body .sub-list .sub-row:nth-child(5) { animation-delay: .62s; }

      /* Пульс привязан к СОСТОЯНИЮ, а не к таймеру: он живёт ровно столько,
         сколько строка остаётся running, и гаснет, когда та стала success.
         Бесконечный цикл останавливается, когда превью уходит из вида —
         кадры за пределами экрана не тратятся (см. .rb-paused ниже). */
      .preview-body .badge--running {
        animation: rb-live-pulse 1.6s ease-in-out infinite;
      }
      .preview-body.rb-paused .badge--running { animation-play-state: paused; }

      /* Смена статуса — не подмена текста, а видимый переход одного и того же
         объекта в новое состояние. */
      .preview-body .badge.rb-swap { animation: rb-badge-swap .34s cubic-bezier(0.16, 1, 0.3, 1); }
      .preview-body .rb-tick { animation: rb-tick .3s cubic-bezier(0.16, 1, 0.3, 1); }

      /* Шкала догоняет ступенями, синхронно с подтверждениями. scaleX, а не
         width: ширина — свойство, вызывающее перекладку макета. */
      .preview-body.rb-playing .summary-bar__fill {
        transition: transform .55s cubic-bezier(0.16, 1, 0.3, 1);
      }
    }
    @keyframes rb-rise {
      from { opacity: 0; transform: translateY(14px); }
      to   { opacity: 1; transform: translateY(0); }
    }
    @keyframes rb-row-in {
      from { opacity: 0; transform: translateY(6px); }
      to   { opacity: 1; transform: translateY(0); }
    }
    @keyframes rb-live-pulse {
      0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c-primary) 35%, transparent); }
      50%      { box-shadow: 0 0 0 4px color-mix(in srgb, var(--c-primary) 35%, transparent); }
    }
    @keyframes rb-badge-swap {
      from { opacity: 0; transform: scale(.86); }
      to   { opacity: 1; transform: scale(1); }
    }
    @keyframes rb-tick {
      from { opacity: .35; transform: translateY(-3px); }
      to   { opacity: 1; transform: translateY(0); }
    }

    /* ── Шаги ──────────────────────────────────────────────────────────── */
    .steps-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 20px;
      margin-top: 40px;
    }
    .step-card {
      background: var(--glass);
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      border: 1px solid var(--glass-border);
      border-radius: 12px;
      box-shadow: 0 1px 2px rgba(15,23,42,.04);
      padding: 24px;
    }
    /* Реакции при наведении у карточки шагов нет намеренно: это <div> с
       текстом, он никуда не ведёт. Подъём и свечение читаются как «нажми
       меня» — обещание, которого элемент не выполняет. Движение здесь было
       привычкой, а не решением. */
    .step-chip {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 32px;
      height: 32px;
      border-radius: 8px;
      /* Светлый тонированный фон вместо тёмной сплошной заливки — см.
         The Vivid Gradient Rule и комментарий у .mark выше. */
      background: linear-gradient(135deg, color-mix(in srgb, var(--c-primary) 20%, transparent), color-mix(in srgb, var(--c-accent-2) 20%, transparent));
      background: linear-gradient(135deg in oklch, color-mix(in srgb, var(--c-primary) 20%, transparent), color-mix(in srgb, var(--c-accent-2) 20%, transparent));
      border: 1px solid color-mix(in srgb, var(--c-primary) 22%, transparent);
      color: var(--c-primary);
      font-weight: 700;
      font-size: 14px;
      font-variant-numeric: tabular-nums;
      margin-bottom: 14px;
    }
    .step-card h3 { font-size: var(--fs-title); font-weight: 600; margin-bottom: 6px; }
    .step-card p { font-size: var(--fs-body); color: var(--c-muted); line-height: 1.6; }

    /* ── Фичи ──────────────────────────────────────────────────────────── */
    .features-grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 16px;
      margin-top: 40px;
    }
    .feature-card {
      background: var(--glass);
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      border: 1px solid var(--glass-border);
      border-radius: 12px;
      box-shadow: 0 1px 2px rgba(15,23,42,.04);
      padding: 22px;
    }
    /* Тоже статичная карточка — см. комментарий у .step-card. */
    .feature-icon {
      width: 40px;
      height: 40px;
      border-radius: 8px;
      /* Светлый тонированный фон вместо тёмной сплошной заливки — см.
         The Vivid Gradient Rule и комментарий у .mark выше. */
      background: linear-gradient(135deg, color-mix(in srgb, var(--c-accent-2) 20%, transparent), color-mix(in srgb, var(--c-primary) 20%, transparent));
      background: linear-gradient(135deg in oklch, color-mix(in srgb, var(--c-accent-2) 20%, transparent), color-mix(in srgb, var(--c-primary) 20%, transparent));
      border: 1px solid color-mix(in srgb, var(--c-accent-2) 22%, transparent);
      color: var(--c-accent-2);
      display: flex;
      align-items: center;
      justify-content: center;
      margin-bottom: 14px;
    }
    .feature-icon svg { width: 20px; height: 20px; }
    .feature-card h3 { font-size: var(--fs-title); font-weight: 600; margin-bottom: 6px; }
    .feature-card p { font-size: var(--fs-body); color: var(--c-muted); line-height: 1.6; }

    /* ── Каталоги ──────────────────────────────────────────────────────── */
    .catalogs-bg { background: transparent; }
    .catalog-list {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
      gap: 10px;
      margin-top: 32px;
      list-style: none;
    }
    .catalog-chip {
      display: flex;
      align-items: center;
      gap: 10px;
      background: var(--glass);
      backdrop-filter: blur(10px);
      -webkit-backdrop-filter: blur(10px);
      border: 1px solid var(--glass-border);
      border-radius: 10px;
      padding: 8px 14px 8px 8px;
      font-size: var(--fs-label);
      font-weight: 500;
      color: var(--c-text);
      transition: transform .14s ease-out, box-shadow .14s ease-out, border-color .14s ease-out;
    }
    /* Единый отклик для всего, что ведёт по ссылке (чипы каталогов, тизеры
       блога). Раньше каждая карточка изобретала свой подъём: 4px здесь, 2px
       там, 1px на /catalogs — при том что смысл везде один «сюда можно
       нажать». Теперь одно движение на всех.
       140мс, а не 200: наведение — это обратная связь, а она обязана быть
       мгновенной; на 200мс курсор успевает уйти раньше, чем карточка
       договорит. Ведущий сигнал — подсветка границы: она очерчивает область,
       по которой реально сработает клик. Подъём оставлен минимальный, тень
       мягкая: на живом световом фоне крупное цветное свечение стало лишним
       шумом. */
    .catalog-chip:hover {
      transform: translateY(-2px);
      border-color: color-mix(in srgb, var(--c-primary) 55%, transparent);
      box-shadow: 0 6px 18px -10px color-mix(in srgb, var(--c-primary) 30%, transparent);
      text-decoration: none;
    }
    .catalog-chip__avatar {
      flex: none;
      width: 30px;
      height: 30px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
      font-family: 'Manrope', sans-serif;
      font-weight: 700;
      font-size: 13px;
    }
    .catalog-chip__name {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    /* ── Сворачивание списка каталогов на мобильном ───────────────────────
       58 плашек в 1–2 колонки — это экран за экраном скролла на телефоне
       до следующей секции. На узких экранах показываем первые 10 и даём
       развернуть остальные — чистый CSS (checkbox-hack), без JS, тот же
       принцип, что и у FAQ (<details>) выше по странице: прогрессивное
       раскрытие вместо вываливания всего списка сразу. */
    .catalog-expand-toggle {
      position: absolute;
      opacity: 0;
      width: 1px;
      height: 1px;
      pointer-events: none;
    }
    .catalog-expand-label { display: none; }
    @media (max-width: 760px) {
      .catalog-list-wrap { position: relative; }
      .catalog-expand-toggle:not(:checked) ~ .catalog-list li:nth-child(n+11) {
        display: none;
      }
      /* Раскрытые плашки не должны просто "выскакивать" разом — тот же приём,
         что у превью дашборда в hero (rb-row-in): элемент, ставший видимым
         из display:none, запускает анимацию заново. Стаггер только у первых
         рядов (у "линии сгиба"), дальше — общая задержка, чтобы не тянуть
         каскад на 40+ плашек (см. Timing/Cap the total delay). */
      @media (prefers-reduced-motion: no-preference) {
        .catalog-expand-toggle:checked ~ .catalog-list li:nth-child(n+11) {
          animation: rb-row-in .35s cubic-bezier(0.16, 1, 0.3, 1) both;
        }
        .catalog-expand-toggle:checked ~ .catalog-list li:nth-child(12) { animation-delay: .04s; }
        .catalog-expand-toggle:checked ~ .catalog-list li:nth-child(13) { animation-delay: .08s; }
        .catalog-expand-toggle:checked ~ .catalog-list li:nth-child(14) { animation-delay: .12s; }
        .catalog-expand-toggle:checked ~ .catalog-list li:nth-child(15) { animation-delay: .16s; }
        .catalog-expand-toggle:checked ~ .catalog-list li:nth-child(16) { animation-delay: .2s; }
        .catalog-expand-toggle:checked ~ .catalog-list li:nth-child(n+17) { animation-delay: .22s; }
      }
      .catalog-expand-label {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 6px;
        margin-top: 16px;
        padding: 11px 20px;
        background: var(--glass);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
        border: 1px solid var(--glass-border);
        border-radius: 10px;
        font-size: var(--fs-label);
        font-weight: 600;
        color: var(--c-primary);
        cursor: pointer;
        transition: border-color .15s ease-out;
      }
      .catalog-expand-label:hover { border-color: var(--c-primary); }
      .catalog-expand-toggle:focus-visible ~ .catalog-expand-label {
        outline: 2px solid var(--c-primary);
        outline-offset: 2px;
      }
      .catalog-expand-label .show-less { display: none; }
      .catalog-expand-toggle:checked ~ .catalog-expand-label .show-more { display: none; }
      .catalog-expand-toggle:checked ~ .catalog-expand-label .show-less { display: inline; }
    }

    /* ── CTA ───────────────────────────────────────────────────────────── */
    /* Финальный блок — пик страницы, поэтому у него собственный ритм: воздуха
       заметно больше, чем у соседних секций (72px), и карточка идёт во всю
       ширину контейнера, а не сжимается до 720px по центру, как раньше. Узкая
       коробка в конце широкой страницы читалась как сноска, а не как вывод. */
    .cta-section { padding: 96px 32px 104px; }
    .cta-card {
      display: grid;
      grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
      gap: 56px;
      align-items: center;
      /* Нижний слой — подложка цветом страницы. Без неё стекло (в тёмной теме
         это всего 5.5% белого) почти не экранирует, и световой слой фона
         проходит карточку насквозь: замер показал падение контраста подписи
         с 4.99 до 4.31 при норме 4.5. Экранировать содержимое — прямая работа
         стеклянной карточки, поэтому чиним здесь, а не гасим фон всей
         страницы ради одного абзаца. */
      background:
        linear-gradient(135deg, color-mix(in srgb, var(--c-primary) 12%, transparent), color-mix(in srgb, var(--c-accent-2) 10%, transparent)),
        var(--glass),
        color-mix(in srgb, var(--c-bg) 78%, transparent);
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      border: 1px solid var(--glass-border);
      border-radius: 14px;
      padding: 56px 48px;
    }
    /* Реестр каталогов недоступен — цифр нет, и карточке незачем держать
       пустую вторую колонку. */
    .cta-card--solo { grid-template-columns: minmax(0, 1fr); }

    .cta-title {
      font-size: var(--fs-display);
      font-weight: 800;
      letter-spacing: -.015em;
      line-height: 1.1;
      margin-bottom: 16px;
    }
    .cta-sub {
      color: var(--c-muted);
      font-size: var(--fs-sub);
      line-height: 1.65;
      max-width: 46ch;
      margin-bottom: 28px;
    }
    .cta-btn { padding: 13px 30px; font-size: var(--fs-sub); }
    /* Плоская заливка вместо прежнего градиента в затемнение: градиент к
       чёрному был попыткой добавить объём тусклому кирпичу, а на чистом ярком
       оранжевом он только мутит цвет — ровно та грязь, из-за которой кнопка и
       выглядела нездорово. */
    .cta-card .btn-primary {
      background: var(--c-cta-btn);
      color: var(--c-cta-ink);
      border: 1px solid var(--c-cta-edge);
    }
    /* Общий .btn гасит кнопку до opacity .88 — на яркой заливке это читается
       как «выключено», то есть ровно наоборот смыслу наведения.
       Осветляем, а не затемняем: с тёмным текстом поверх затемнение съедает
       контраст, а осветление его наоборот поднимает. Плюс «ярче под курсором»
       для маяка-CTA честнее по смыслу, чем «темнее». */
    .cta-card .btn-primary:hover {
      opacity: 1;
      background: color-mix(in srgb, var(--c-cta-btn) 88%, white);
    }
    .cta-fine {
      color: var(--c-muted);
      font-size: var(--fs-body);
      margin-top: 18px;
    }

    /* Правая колонка — счёт ручной работы. Отделена волосяной линией, а не
       вложенной карточкой: карточка в карточке дала бы лишний уровень рамок
       там, где хватает одной линии. */
    .cta-ledger {
      border-left: 1px solid var(--glass-border);
      padding-left: 48px;
    }
    .cta-ledger-title {
      font-size: var(--fs-meta);
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: .08em;
      color: var(--c-muted);
      margin-bottom: 20px;
    }
    .ledger-row {
      display: grid;
      /* Колонка чисел фиксированной ширины, число прижато вправо: так 366, 26
         и 20 выстраиваются по разряду единиц и читаются как столбец итогов, а
         не как три случайные величины. Ширина в пикселях, а НЕ в ch: ch
         считается от кегля самой строки (15px), а не от кегля числа (40px) —
         дорожка выходила втрое уже нужного, и число наезжало на подпись.
         max-content держит выравнивание, если чисел когда-нибудь станет
         четырёхзначное: дорожка общая для всех строк. */
      grid-template-columns: minmax(76px, max-content) 1fr;
      align-items: baseline;
      gap: 20px;
      padding: 16px 0;
      border-bottom: 1px solid var(--glass-border);
    }
    .ledger-row:first-child { padding-top: 0; }
    .ledger-row:last-child { border-bottom: 0; padding-bottom: 0; }
    .ledger-num {
      font-family: Manrope, Inter, -apple-system, sans-serif;
      font-size: var(--fs-numeral);
      font-weight: 800;
      line-height: 1;
      letter-spacing: -.02em;
      text-align: right;
      font-variant-numeric: tabular-nums;
      font-feature-settings: 'tnum' 1;
    }
    /* Триада акцентов в закреплённых ролях: числа — текст на стекле, поэтому
       берут текстовые варианты (--c-*), а не заливочные --c-*-btn. */
    .ledger-num--1 { color: var(--c-primary); }
    .ledger-num--2 { color: var(--c-accent-2); }
    .ledger-num--3 { color: var(--c-accent-3); }
    .ledger-label {
      margin: 0;
      color: var(--c-text);
      font-size: var(--fs-sub);
      line-height: 1.45;
    }
    .ledger-note {
      margin-top: 20px;
      color: var(--c-muted);
      font-size: var(--fs-body);
      line-height: 1.5;
    }
    .ledger-note a { color: var(--c-primary); }

    @media (max-width: 900px) {
      .cta-card { grid-template-columns: minmax(0, 1fr); gap: 36px; padding: 40px 28px; }
      .cta-ledger { border-left: 0; border-top: 1px solid var(--glass-border); padding-left: 0; padding-top: 32px; }
      .cta-sub { max-width: none; }
    }

    /* ── Блог (тизер последних статей) ────────────────────────────────── */
    .blog-teaser-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 20px;
      margin-top: 40px;
    }
    .blog-teaser-card {
      display: flex;
      flex-direction: column;
      background: var(--glass);
      backdrop-filter: blur(14px);
      -webkit-backdrop-filter: blur(14px);
      border: 1px solid var(--glass-border);
      border-radius: 12px;
      overflow: hidden;
      /* Растянутая ссылка (см. ::after у заголовка) требует точки отсчёта. */
      position: relative;
      transition: transform .14s ease-out, box-shadow .14s ease-out, border-color .14s ease-out;
    }
    /* Ссылкой был только заголовок, а приподнималась вся карточка: курсор в
       середине показывал стрелку, но клик там не срабатывал. Псевдоэлемент
       растягивает область ссылки на карточку целиком — теперь подъём
       соответствует тому, что реально нажимается. */
    .blog-teaser-card h3 a::after {
      content: '';
      position: absolute;
      inset: 0;
    }
    .blog-teaser-card:hover {
      transform: translateY(-2px);
      border-color: color-mix(in srgb, var(--c-primary) 55%, transparent);
      box-shadow: 0 6px 18px -10px color-mix(in srgb, var(--c-primary) 30%, transparent);
    }
    .blog-teaser-card:hover h3 a { color: var(--c-primary); }
    /* Клавиатура: фокус приходит на саму ссылку, а кольцо вокруг текста
       заголовка не показывает, что нажимается вся карточка. Переносим
       обводку на карточку. */
    .blog-teaser-card:focus-within {
      border-color: color-mix(in srgb, var(--c-primary) 55%, transparent);
      outline: 2px solid var(--c-primary);
      outline-offset: 2px;
    }
    .blog-teaser-card h3 a:focus-visible { outline: none; }
    .blog-teaser-card img,
    .blog-teaser-cover { width: 100%; height: 140px; object-fit: cover; display: block; }
    .blog-teaser-cover { background: linear-gradient(135deg, var(--c-primary), var(--c-accent-2)); }
    .blog-teaser-cover { background: linear-gradient(135deg in oklch, var(--c-primary), var(--c-accent-2)); }
    .blog-teaser-card__body { padding: 18px 20px 20px; }
    .blog-teaser-card__cat {
      display: inline-block;
      font-size: var(--fs-meta);
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: .04em;
      color: var(--c-primary);
      margin-bottom: 6px;
    }
    .blog-teaser-card h3 { font-size: var(--fs-title); font-weight: 600; margin-bottom: 8px; line-height: 1.35; }
    .blog-teaser-card h3 a { color: var(--c-text); }
    .blog-teaser-card h3 a:hover { color: var(--c-primary); }
    .blog-teaser-card p { font-size: var(--fs-body); color: var(--c-muted); line-height: 1.55; }
    .blog-teaser-more { text-align: center; margin-top: 32px; }

    /* ── FAQ ───────────────────────────────────────────────────────────── */
    /* Две колонки, а не одна узкая: блок был зажат в 760px посреди секции
       шириной 1360 и читался как чужая вставка. Растягивать список в одну
       колонку на всю ширину нельзя — строка ответа ушла бы под 130 символов;
       поэтому ширину набирают две колонки, а мера ответа держится отдельно
       (см. max-width у .faq-item p).
       align-items: start обязателен: без него карточки в строке растягиваются
       по высоте самой высокой, и закрытый вопрос рядом с открытым получает
       пустое поле в половину экрана. */
    .faq-list {
      margin: 40px 0 0;
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      align-items: start;
      gap: 10px 20px;
    }
    @media (max-width: 900px) {
      .faq-list { grid-template-columns: minmax(0, 1fr); }
    }
    .faq-item {
      background: var(--glass);
      backdrop-filter: blur(12px);
      -webkit-backdrop-filter: blur(12px);
      border: 1px solid var(--glass-border);
      border-radius: 10px;
      padding: 4px 20px;
    }
    .faq-item summary {
      cursor: pointer;
      list-style: none;
      padding: 16px 0;
      font-weight: 600;
      font-size: var(--fs-sub);
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
    }
    .faq-item summary::-webkit-details-marker { display: none; }
    .faq-item summary::after {
      content: '+';
      flex: none;
      font-size: 20px;
      font-weight: 400;
      color: var(--c-primary);
      transition: transform .15s ease-out;
    }
    .faq-item[open] summary::after { transform: rotate(45deg); }
    /* Мера ответа задана в пикселях, а не в ch: единица ch считается от кегля
       самого элемента (здесь 14px), и на глаз она обманывает — на этой же
       странице такая ошибка уже приводила к рассогласованию колонок. 520px
       при 14px Inter — это примерно 72 символа, верх читаемого диапазона. */
    .faq-item p {
      font-size: var(--fs-body);
      color: var(--c-muted);
      line-height: 1.6;
      padding: 0 0 18px;
      max-width: 520px;
    }
    /* Ответ у нативного <details> появляется без перехода — при открытии
       контент идёт из "не отрендерен" в "отрендерен" (как display:none→block),
       поэтому анимация запускается заново тем же приёмом, что и у каталогов
       выше (rb-row-in), без JS. */
    @media (prefers-reduced-motion: no-preference) {
      .faq-item[open] p { animation: rb-row-in .3s cubic-bezier(0.16, 1, 0.3, 1) both; }
    }

    /* ── Футер ─────────────────────────────────────────────────────────── */
    .landing-footer {
      border-top: 1px solid var(--glass-border);
      max-width: 1360px;
      margin: 0 auto;
      padding: 48px 32px 24px;
    }
    .footer-cols {
      display: flex;
      justify-content: space-between;
      gap: 32px;
      flex-wrap: wrap;
      padding-bottom: 32px;
    }
    .footer-brand { max-width: 280px; }
    .footer-brand p { font-size: var(--fs-label); color: var(--c-muted); line-height: 1.6; margin-top: 10px; }
    .footer-col-title { font-size: var(--fs-meta); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--c-muted); margin-bottom: 12px; }
    .footer-col { display: flex; flex-direction: column; gap: 9px; }
    .footer-col a { font-size: var(--fs-label); color: var(--c-text); }
    .footer-col a:hover { color: var(--c-primary); }
    .landing-footer-bottom {
      border-top: 1px solid var(--glass-border);
      padding-top: 20px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
      flex-wrap: wrap;
    }
    .landing-footer-bottom p { font-size: var(--fs-label); color: var(--c-muted); }

    /* Пара «довод + панель» держится, пока каждой колонке хватает ширины:
       панели нужно место под имя каталога и бейдж в одну строку, доводу —
       мера около 45 знаков. Ниже — колонки в стопку, но выключка остаётся
       левой: возврат к центру вернул бы ровно ту симметрию, от которой
       страница уходила. */
    @media (max-width: 1000px) {
      .hero-grid { grid-template-columns: minmax(0, 1fr); gap: 44px; max-width: 720px; }
      .hero-sub { max-width: none; }
    }
    /* В стопку колонка занимает всю ширину, и боковой экран смысла не имеет —
       гасить нужно ровно там, где текст, то есть везде. Полоса вместо пятна:
       у стопки hero выше вьюпорта, и эллипс в процентах от блока перестаёт
       попадать в нижние строки (замер: шильдик 2.91:1 при 780px). Замер после
       правки: 6.47 тёмная / 5.15 светлая на 780px.
       Ниже 760px экрана нет вовсе: там WebGL-слой не запускается (см.
       bg-shader.js), остаются два приглушённых статических пятна по углам,
       которые уже замерены отдельно — гасить их значит убирать фон без причины. */
    @media (min-width: 761px) and (max-width: 1000px) {
      .hero::before {
        inset: -160px 0;
        background: linear-gradient(to bottom,
          transparent 0%,
          color-mix(in srgb, var(--c-bg) 90%, transparent) 13%,
          color-mix(in srgb, var(--c-bg) 90%, transparent) 87%,
          transparent 100%);
      }
    }
    @media (max-width: 760px) {
      .hero::before { display: none; }
    }
    @media (max-width: 760px) {
      section { padding: 48px 20px; }
      .hero { padding: 56px 20px 48px; }
      .cta-section { padding: 48px 20px; }
      .cta-card { padding: 32px 24px; }
      .steps-grid { grid-template-columns: 1fr; }
      .features-grid { grid-template-columns: 1fr; }
      .catalog-list { grid-template-columns: 1fr 1fr; }
      .blog-teaser-grid { grid-template-columns: 1fr; }
      .footer-cols { flex-direction: column; gap: 24px; }
      .landing-footer-bottom { flex-direction: column; text-align: center; }
      /* Крупная hero-кнопка (14px/32px, см. .hero-actions .btn выше) на узком
         экране рискует не влезть в один ряд с длинным текстом ("Зарегистрировать
         компанию →") — возвращаем к стандартному размеру .btn. */
      .hero-actions .btn { padding: 12px 22px; font-size: var(--fs-body); }
    }
    /* Три ячейки шильдика в ряд ниже этой ширины дают по 2–3 строки в каждой
       и рвутся на 2+1 с осиротевшим разделителем. Ряд становится столбцом,
       разделитель — горизонтальным, число уходит в строку к подписи. */
    @media (max-width: 560px) {
      .hero-spec { display: block; }
      .hero-spec li { padding: 9px 0; min-width: 0; }
      .hero-spec li:first-child { padding-top: 0; }
      .hero-spec li:last-child { padding-bottom: 0; }
      .hero-spec li + li { padding-left: 0; border-left: 0; border-top: 1px solid var(--c-border); }
      .hero-spec b { display: inline; margin: 0 6px 0 0; }
    }
    @media (max-width: 640px) {
      .topbar.landing-nav { padding: 10px 16px; }
      .landing-nav-links { gap: 12px; }
      /* Якорные ссылки уступали место кнопке входа, когда вся навигация жила
         одним рядом в шапке. С бургером ряда больше нет: ссылки лежат в
         панели, места там достаточно, а прятать «Как работает» — значит
         оставлять телефон без ссылки на главный раздел страницы. Поэтому
         скрытие осталось только для случая без JS, где панели не существует
         и всё по-прежнему выстраивается в один ряд. */
      html:not(.has-js) .landing-nav-links a[href^="#"] { display: none; }
    }
    @media (max-width: 480px) {
      /* Последняя страховка: на очень узких экранах (длинный e-mail в
         "Личный кабинет" не бывает, но узкие Android-экраны — да) кнопки
         шапки уходят на вторую строку, а не вылезают за край. */
      .landing-nav-links { flex-wrap: wrap; justify-content: flex-end; row-gap: 8px; }
      .catalog-list { grid-template-columns: 1fr; }
    }


/* ── Новые контентные блоки (зачем / сравнение / ограничения) ──────────────
   Первая версия задавала этим секциям собственную ширину 860px, из-за чего
   они были на 500px уже остальной страницы (.wrap на лендинге — 1360px), и
   оформление было голым текстом на фоне стеклянных карточек всего лендинга.
   Теперь ширина общая, а читаемая мера ограничивает только текстовые абзацы;
   карточки повторяют язык .feature-card (стекло, та же граница и радиус). */

/* Мера в пикселях и прямо на абзацах. Обёртка-контейнер тут не годится: её
   легко случайно растянуть на соседние блоки (в первой версии незакрытый div
   поглотил сетку карточек и зажал её в ширину текста). Пиксели, а не ch —
   единица ch считается от кегля элемента, поэтому одно и то же значение у
   lead-абзаца и обычного давало разную ширину и рваный правый край. */
.lead-p {
  max-width: 760px;
  font-size: var(--fs-lead);
  line-height: 1.65;
  color: var(--c-text);
  margin: 24px 0 0;
}

.note-p {
  font-size: var(--fs-sub);
  line-height: 1.65;
  color: var(--c-muted);
  margin: 32px 0 0;
  padding: 18px 22px;
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  max-width: 760px;
}

/* ── «Зачем»: карточки в языке .feature-card ─────────────────────────────── */
.why-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
  margin-top: 40px;
}
.why-item {
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(15,23,42,.04);
  padding: 22px;
}
/* Реакции при наведении нет: карточка не кликабельна — см. .step-card. */
.why-item h3 {
  font-size: var(--fs-title);
  font-weight: 600;
  margin: 0 0 8px;
  color: var(--c-text);
}
.why-item p {
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--c-muted);
  margin: 0;
}

/* ── Сравнение: таблица как одна стеклянная карточка ─────────────────────── */
.compare-card {
  margin-top: 40px;
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(15,23,42,.04);
  overflow: hidden;
}
.compare-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.compare-table {
  width: 100%;
  min-width: 680px;
  border-collapse: collapse;
  font-size: var(--fs-body);
  text-align: left;
}
.compare-table th,
.compare-table td {
  padding: 16px 22px;
  vertical-align: top;
  line-height: 1.55;
  border-bottom: 1px solid var(--glass-border);
}
.compare-table tbody tr:last-child th,
.compare-table tbody tr:last-child td { border-bottom: 0; }
.compare-table thead th {
  font-size: var(--fs-meta);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--c-muted);
  background: color-mix(in srgb, var(--c-primary) 6%, transparent);
  white-space: nowrap;
}
.compare-table tbody th {
  font-weight: 600;
  color: var(--c-text);
  width: 26%;
}
.compare-table td { width: 37%; color: var(--c-muted); }
/* Колонка продукта выделена заливкой, а не только цветом текста: именно её
   читают для сравнения, и без опоры взгляд терял, где чей столбец. */
.compare-table .col-rb {
  color: var(--c-text);
  background: color-mix(in srgb, var(--c-primary) 5%, transparent);
}
.compare-table thead .col-rb {
  color: var(--c-primary);
  background: color-mix(in srgb, var(--c-primary) 10%, transparent);
}

/* ── «Когда не поможет»: сетка карточек ─────────────────────────────────── */
.limits-list {
  list-style: none;
  padding: 0;
  margin: 40px 0 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 18px;
}
.limits-list li {
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--glass-border);
  border-radius: 12px;
  padding: 22px;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--c-muted);
}
.limits-list b {
  display: block;
  color: var(--c-text);
  font-weight: 600;
  font-size: var(--fs-title);
  margin-bottom: 8px;
  line-height: 1.35;
}


/* ── Стекло должно экранировать ────────────────────────────────────────────
   За карточками теперь живёт световой слой (public/js/bg-shader.js), а не
   ровная заливка. Токен --glass задумывался под спокойный фон и держит всего
   65% белого в светлой теме и 5.5% в тёмной — сквозь такое стекло свет
   проходит почти без потерь и садится под текст. Замер поймал два провала:
   подпись в финальной карточке 4.99 → 4.31 и список «когда не поможет»
   7.19 → 4.32 при норме 4.5.

   Правильное место починки — сама карточка, а не яркость фона: экранировать
   содержимое это прямая работа стеклянной поверхности. Подкладываем под
   стекло цвет страницы, поэтому карточки остаются полупрозрачными на вид
   (свет за ними по-прежнему читается и подкрашивает края), но перестают
   пропускать его насквозь.

   background-color, а не сокращённое background: правило идёт последним и
   должно добавить подложку, не стирая градиенты, объявленные выше. */
.step-card,
.feature-card,
.blog-teaser-card,
.faq-item,
.why-item,
.compare-card,
.limits-list li {
  background-color: color-mix(in srgb, var(--c-bg) 78%, transparent);
}

/* ── «Уменьшить движение»: только движение ─────────────────────────────────
   Блок обязан стоять ПОСЛЕ всех :hover-правил. У `.catalog-chip:hover` и у
   его отмены одинаковая специфичность (класс + псевдокласс), поэтому решает
   порядок объявления. Раньше отмена стояла в начале файла и молча не
   работала — подъём играл в том числе у тех, кто просил анимации отключить.

   Убирается ровно подъём. Подсветка границы и мягкая тень остаются: это не
   анимация ради красоты, а сообщение «отсюда сработает клик», и человеку с
   вестибулярной чувствительностью оно нужно ничуть не меньше. */
@media (prefers-reduced-motion: reduce) {
  .catalog-chip,
  .blog-teaser-card,
  .cat-card {
    transition: box-shadow .14s ease-out, border-color .14s ease-out;
  }
  .catalog-chip:hover,
  .blog-teaser-card:hover,
  .cat-card:hover {
    transform: none;
  }
}

/* ── Палец вместо курсора ──────────────────────────────────────────────────
   Кнопки лендинга берут размеры из общего .btn в style.css и увеличиваются
   вместе с ним. Здесь остаётся то, что есть только тут: ссылки шапки, чипы
   каталогов и вопросы FAQ.
   Как и в style.css — по способу ввода, а не по ширине экрана, и в конце
   файла: специфичность равная, решает порядок (на этом уже один раз молча
   не сработала отмена движения выше). */
@media (pointer: coarse) {
  /* Та же шкала на шаг вверх, что и в style.css: у лендинга собственная копия
     ролевых токенов. Без этой строки его карточки и подписи остались бы на
     13–14px, пока остальной продукт перешёл на 14–15px. */
  body { --fs-sub: 16px; --fs-body: 15px; --fs-label: 14px; }

  /* Цель растёт полями, а обратный отрицательный отступ оставляет раскладку
     шапки прежней — иначе строка ссылок выросла бы вдвое. */
  .landing-nav-links a:not(.btn) {
    padding: 12px 6px;
    margin: -12px -6px;
  }
  .catalog-chip { min-height: 44px; }
  .faq-item summary { padding-top: 18px; padding-bottom: 18px; }
  /* Раскрывающий чекбокс списка каталогов — целью служит его метка-кнопка. */
  .catalog-expand-label { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ── Свет на узком экране ───────────────────────────────────────────────────
   Правило системы («свет держится у краёв, плотность гасится к центру»)
   на телефоне нарушалось самой геометрией: пятна размером 560–760px
   рассчитаны на колонку в 1440px, а на 390px все три целиком ложатся на
   первый экран — краёв не остаётся, всё поле становится центром.
   Замер это подтвердил: вторичный текст под hero давал 3.64:1 при норме 4.5,
   тогда как на десктопе то же место — 5.25:1.

   Поэтому на узком экране остаются ДВА пятна по верхним углам, а
   центральное (оно и лежало под текстом) убрано; размеры заданы в vw/vh,
   чтобы они масштабировались вместе с экраном, а не жили в пикселях
   десктопа. Плотность снижена вдвое. */
@media (max-width: 760px) {
  body {
    --blob1: rgba(124,58,237,.07);
    --blob2: rgba(234,88,12,.06);
    background:
      radial-gradient(62vw 22vh at 0% 0%,   var(--blob1), transparent 64%),
      radial-gradient(62vw 24vh at 100% 4%, var(--blob2), transparent 64%),
      var(--c-bg);
  }
  @media (prefers-color-scheme: dark) {
    body { --blob1: rgba(167,139,250,.12); --blob2: rgba(251,146,60,.09); }
  }
  html[data-theme="dark"] body { --blob1: rgba(167,139,250,.12); --blob2: rgba(251,146,60,.09); }
  html[data-theme="light"] body { --blob1: rgba(124,58,237,.07); --blob2: rgba(234,88,12,.06); }
}
