/* ============================================================================
   Notix — главная страница (переработка 2026-10-05, v2)
   Структура: hero → источник → хаб → CRM → шаги+форма → FAQ → CTA
   Ссылка на task/2026-10-05/002-landing-redesign-v2.md
   ========================================================================== */

.landing {
    --ink: #0A1F44;
    --ink-2: #132D5E;
    --ink-3: #1B3A75;
    --gold: #fbc708;
    --gold-2: #fcd535;
    --paper: #fdfdfd;
    --mist: #F4F6FB;
    --slate: #4a628a;
    --line: #E3E8F2;
    --ok: #10B981;

    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    color: var(--ink);
    overflow-x: hidden;
}

.lx2-wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; }

/* Ровный якорь при переходе по #features / #how-start / #faq / #data из футера */
.landing section[id] { scroll-margin-top: 96px; }

/* ── Появление при скролле ─────────────────────────────────────────────── */
.rv { opacity: 0; transform: translateY(26px); transition: opacity .7s cubic-bezier(.22,1,.36,1), transform .7s cubic-bezier(.22,1,.36,1); }
.rv.rv-on { opacity: 1; transform: none; }
.rv-d1 { transition-delay: .08s; } .rv-d2 { transition-delay: .16s; }
.rv-d3 { transition-delay: .24s; } .rv-d4 { transition-delay: .32s; }
/* d5/d6 — нужны только сетке из 6 карточек секции 2 */
.rv-d5 { transition-delay: .40s; } .rv-d6 { transition-delay: .48s; }

/* ── Общие элементы ─────────────────────────────────────────────────────── */
.lx2-sec { padding: 96px 0; }
.lx2-sec-head { max-width: 760px; margin: 0 auto 44px; text-align: center; }

.lx2-tag {
    display: inline-block; margin-bottom: 16px; padding: 6px 14px;
    border-radius: 100px; background: var(--mist); border: 1px solid var(--line);
    font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
    color: var(--ink-3);
}
.lx2-em { color: var(--gold); font-style: normal; }

.lx2-sec h2, .lx2-final h2 {
    font-size: clamp(28px, 4.2vw, 46px); line-height: 1.12;
    font-weight: 800; letter-spacing: -.02em; margin: 0 0 16px;
}
.lx2-sub { font-size: 17px; line-height: 1.6; color: var(--slate); margin: 0 auto; max-width: 640px; }

.lx2-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 14px 26px; border-radius: 12px; font-size: 15px; font-weight: 700;
    text-decoration: none; border: 1.5px solid transparent; cursor: pointer;
    transition: transform .2s ease, box-shadow .25s ease, background .2s ease, border-color .2s ease;
}
.lx2-btn:hover { transform: translateY(-2px); }
.lx2-btn-gold { background: var(--gold); color: var(--ink); box-shadow: 0 10px 26px -10px rgba(251,199,8,.75); }
.lx2-btn-gold:hover { background: var(--gold-2); }
.lx2-btn-line { background: #fff; color: var(--ink); border-color: var(--line); }
.lx2-btn-line:hover { border-color: var(--ink-3); }
.lx2-btn-lg { padding: 17px 34px; font-size: 16px; }

.lx2-more { display: inline-block; margin-top: 6px; font-weight: 700; color: var(--ink); text-decoration: none; }
.lx2-more:hover { color: var(--gold); }

/* Рамка «браузера» вокруг скриншотов */
.lx2-browser { background: #fff; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; box-shadow: 0 24px 60px -28px rgba(10,31,68,.35); }
.lx2-browser-bar { display: flex; align-items: center; gap: 6px; padding: 10px 14px; background: #F7F9FD; border-bottom: 1px solid var(--line); }
.lx2-browser-bar i { width: 9px; height: 9px; border-radius: 50%; background: #D6DEEC; }
.lx2-browser-bar span { margin-left: 10px; font-size: 11px; color: var(--slate); }
.lx2-browser img { display: block; width: 100%; height: auto; }
.lx2-shotbox img { display: block; width: 100%; height: auto; }

/* ═══ 1. HERO ═══ */
/* Правка 2, обязательное условие для sticky-бара плашек.
   `.landing` (общий блок, css 7-22, править нельзя) объявлен как
   `overflow-x: hidden`, а по спецификации одно скрытое значение превращает
   вторую ось в `auto` — то есть `.landing` становится scroll-контейнером.
   Для position:sticky ближайший scrollport — именно он, а он никогда не
   скроллится, поэтому липкий ряд не прилипал ни при каком scrollY.
   `overflow-x: clip` даёт ту же обрезку по горизонтали, но контейнером
   не становится. Селектор намеренно .landing.lx2 — только эта страница,
   остальные 6 вьюх с классом .landing не затронуты (hidden оставлен
   фолбэком для старых браузеров — там sticky просто не работает). */
.landing.lx2 { overflow-x: hidden; overflow-x: clip; }

/* Плавное раскрытие FAQ на нативном <details>: ::details-content переводит
   block-size 0 → auto, а интерполировать auto можно только если у предка
   разрешена интерполяция keyword-значений (interpolate-size). Живёт здесь,
   на .landing.lx2, а не в общем блоке .landing — тот обслуживает ещё 5
   страниц, которым это не нужно. Без поддержки обе директивы просто
   игнорируются и FAQ раскрывается мгновенно. */
.landing.lx2 { interpolate-size: allow-keywords; }

/* HERO: ровно один экран (100svh — без «прыгающего» адресной строки на мобильных).
   Фон светлый, снизу тёплое золотое свечение (::after) и мягкие пятна, поверх —
   canvas со звёздной пылью и созвездиями. Порядок слоёв: пятна 1 → glow 1 →
   частицы 2 → контент 3 → плашки 4. Правка 4: сетка-подложка (::before) и
   10 SVG-фигур убраны — заказчик просил только звёзды. */
.lx2-hero {
    position: relative;
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    align-items: center;
    /* clip, а не hidden: sticky внутри overflow:hidden не работает — такой
       предок становится scroll-контейнером, а он не скроллится (правка 2).
       clip обрезает так же, но скролл-контейнер не создаёт.
       hidden оставлен перед clip как фолбэк для старых браузеров. */
    overflow: hidden;
    overflow: clip;
    /* гасим глобальное `section { padding: 100px 24px }` из welcome.css —
       свои отступы считает .lx2-hero-inner, иначе hero не влезает в экран */
    padding: 0;
    background:
        radial-gradient(ellipse 70% 42% at 50% 104%, rgba(251,199,8,.34) 0%, rgba(251,199,8,.12) 42%, transparent 70%),
        linear-gradient(180deg, #fff 0%, var(--mist) 62%, var(--mist) 100%);
}
/* Золотое свечение снизу (з 1). Прежде здесь был тёмный клин clip-path —
   он удалён, функцию свечения взял на себя этот псевдоэлемент. */
.lx2-hero::after {
    content: '';
    position: absolute; left: -10%; right: -10%; bottom: -18%; height: 62%;
    z-index: 1;
    background: radial-gradient(ellipse 60% 100% at 50% 100%, rgba(251,199,8,.34) 0%, rgba(251,199,8,.13) 45%, transparent 72%);
    filter: blur(6px);
    pointer-events: none;
    animation: lx2-glow 11s ease-in-out infinite;
}
/* Цветные пятна (з 1) — геометрия референса, цвета из токенов. Размытые
   краски держат глубину фона, на которой читается пыль: без них звёзды
   «висят» на ровном белом. */
.lx2-blob { position: absolute; z-index: 1; border-radius: 50%; filter: blur(80px); opacity: .5; pointer-events: none; }
.lx2-blob-1 { width: 560px; height: 560px; top: -150px; left: -150px; background: radial-gradient(closest-side, rgba(27,58,117,.20), transparent 70%); animation: lx2-morph 14s ease-in-out infinite; }
.lx2-blob-2 { width: 600px; height: 600px; bottom: -180px; right: -180px; background: radial-gradient(closest-side, rgba(251,199,8,.30), transparent 70%); animation: lx2-morph 18s ease-in-out infinite reverse; }
.lx2-blob-3 { width: 360px; height: 360px; top: 35%; left: 55%; background: radial-gradient(closest-side, rgba(19,45,94,.14), transparent 70%); animation: lx2-morph 22s ease-in-out infinite; }

/* Canvas сети частиц (з 2) */
.lx2-canvas-bg { position: absolute; inset: 0; z-index: 2; width: 100%; height: 100%; pointer-events: none; opacity: .9; touch-action: manipulation; }

/* Контент (з 3) */
.lx2-hero-inner { position: relative; z-index: 3; width: 100%; max-width: 1200px; margin: 0 auto; padding: 96px 24px 44px; /* 96 = fixed-шапка 74px + зазор */ }
.lx2-hero-core { display: flex; flex-direction: column; align-items: center; text-align: center; }

/* Бейдж-пилюля над заголовком */
.lx2-pill-badge {
    display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px; border-radius: 100px;
    background: rgba(255,255,255,.82); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
    border: 1px solid var(--line); font-size: 12px; font-weight: 700; letter-spacing: .14em;
    text-transform: uppercase; color: var(--ink-3);
    transition: transform .35s cubic-bezier(.2,.8,.2,1), box-shadow .35s ease;
}
.lx2-pill-badge:hover { transform: translateY(-2px); box-shadow: 0 14px 32px -12px rgba(251,199,8,.6); }
.lx2-pill-badge i { width: 7px; height: 7px; border-radius: 50%; background: var(--gold); animation: lx2-pulse 1.8s ease-in-out infinite; }

/* Заголовок = canvas-текст. Размер/шрифт живут в canvas, .lx2-h1 — контейнер.
   aspect-ratio (Р-12) держит высоту до загрузки JS — иначе контент прыгает. */
/* width:100% обязателен — в flex-колонке с align-items:center h1 иначе
   схлопывается до shrink-to-fit, и canvas не имеет от чего считать 100% */
.lx2-h1 { margin: 26px 0 24px; width: 100%; }
.lx2-h1-canvas { display: block; width: 100%; max-width: 1000px; height: auto; aspect-ratio: 1000 / 218; margin: 0 auto; touch-action: manipulation; }

.lx2-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
/* Canvas не собрался (getImageData/CSP) — показываем текстовый дубль,
   заголовок не должен пропадать никогда. */
.lx2-h1.is-fallback .lx2-h1-canvas { display: none; }
.lx2-h1.is-fallback .lx2-sr-only {
    position: static; width: auto; height: auto; margin: 0; clip: auto; clip-path: none; white-space: normal;
    font-size: clamp(34px, 5.4vw, 62px); font-weight: 900; line-height: 1.06; letter-spacing: -.03em;
}

.lx2-lead { font-size: 18px; line-height: 1.62; color: var(--slate); margin: 0 0 22px; max-width: 900px; }
.lx2-lead strong { color: var(--ink); font-weight: 700; }

.lx2-cta { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; margin-bottom: 14px; }
.lx2-cta-note { font-size: 13px; color: var(--slate); margin: 0; }

/* ── 4 плашки-аккордеона (з 4) ──────────────────────────────────────── */
/* Правка 2: ряд переключателей (.lx2-pills-bar) отделён от тел и сделан
   sticky — раньше гола плашки жила внутри тела и уезжала с описанием за
   верхний край. Собственного containing block у бара нет намеренно:
   .lx2-hero-pills остаётся блоком, иначе грид-строка зажала бы sticky. */
.lx2-hero-pills { position: relative; z-index: 4; margin-top: 30px; }

.lx2-pills-bar {
    position: sticky; top: 74px; z-index: 5;   /* 74px — высота fixed-шапки NAV.nav */
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px;
    margin: -10px -16px 6px; padding: 10px 16px 14px;
    /* Заказчик (после этапа 1D): фон под рядом плашек убран ПОЛНОСТЬЮ — ни
       подложки, ни градиента, ни backdrop-filter. Плашки стоят на фоне hero
       сами по себе. Побочный эффект, который нужно помнить: при прокрутке
       текст описания виден в зазорах грида между плашками и обрезается по
       нижней кромке табов. Минус-поля (-10px/-16px) и padding оставлены,
       чтобы плашки не липлали к краям экрана. */
}
/* Б4: зарезервированная высота под тела. Значение кладёт JS (модуль 17) в
   --pill-min-h на .lx2-hero-pills; фолбэк 0px — до первого замера блок
   ведёт себя как раньше, без резерва.
   Д1 (этап 1D): position:relative — containing block для тел вне потока ниже.
   Именно из-за него прыгала страница при переключении плашек: закрывающееся
   тело (grid-template-rows 1fr→0fr за .32s) и открывающееся (0fr→1fr) были
   ОДНОВРЕМЕННО в потоке грида, поэтому .lx2-pill-bodies на середине кросс-фейда
   был ~= 471px вместо резерва 381px, и документ рос на ~90px (замерено:
   6796 → 6886 → 6796). Тело вне .is-open выведено из потока, в потоке остаётся
   ровно одно — открытое; контейнер держится на min-height резерва, прыжка нет. */
.lx2-pill-bodies { position: relative; display: grid; grid-template-columns: 1fr; gap: 14px; min-height: var(--pill-min-h, 0px); }
/* Служебный режим замера: тела раскрыты без анимации, поэтому offsetHeight
   сразу равен натуральной высоте (transition дал бы промежуточное значение).
   offsetHeight у абсолютно позиционированного элемента тоже равен его
   border-box, поэтому замер по-прежнему видит натуру каждого тела. */
.lx2-hero-pills.is-measuring .lx2-pill-body { transition: none; }
/* Д1: на время замера тела возвращаются в поток (position:static). Иначе
   абсолютное тело с inset:0 отдавало бы offsetHeight = высоте контейнера, и
   замер модуля 17 подтверждал бы сам себя (всегда 381px), а не натуру.
   align-self:start (см. выше) не даёт строкам растянуться до min-height. */
.lx2-hero-pills.is-measuring .lx2-pill-body:not(.is-open) { grid-template-rows: 1fr; position: static; inset: auto; }

.lx2-pill-tab {
    position: relative; overflow: hidden; text-align: left;
    display: flex; align-items: center; gap: 12px; width: 100%; min-width: 0;
    padding: 16px 18px; background: linear-gradient(180deg, rgba(255,255,255,.92), rgba(255,255,255,.7));
    border: 1px solid var(--line); border-radius: 16px;
    font: inherit; color: inherit; cursor: pointer;
    will-change: transform;
    /* lx2-float анимирует отдельное свойство translate, чтобы не спорить
       с transform от 3D-tilt, который ставит JS (модуль 14) */
    animation: lx2-float var(--fdur, 6s) ease-in-out infinite;
    animation-delay: var(--fdelay, 0s);
    transition: opacity .6s ease, box-shadow .35s ease, border-color .35s ease;
}
/* Активная плашка в ряду: золотая полоса слева + подъём. Остальные приглушены,
   чтобы взгляд шёл в открытую. */
.lx2-pill-tab::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; z-index: 2; background: linear-gradient(180deg, var(--gold-2), var(--gold)); transition: width .35s ease; }
.lx2-pill-tab::after { content: ''; position: absolute; inset: 0; z-index: 1; background: radial-gradient(300px circle at var(--mx,50%) var(--my,50%), rgba(251,199,8,.20), transparent 45%); opacity: 0; transition: opacity .35s ease; pointer-events: none; }
.lx2-pill-tab:not(.is-open) { background: linear-gradient(180deg, rgba(255,255,255,.72), rgba(255,255,255,.5)); }
.lx2-pill-tab:not(.is-open) .lx2-pill-titles b { color: var(--slate); }
.lx2-pill-tab.is-open { background: linear-gradient(180deg, rgba(255,255,255,.98), rgba(255,255,255,.86)); border-color: rgba(251,199,8,.5); box-shadow: 0 14px 30px -16px rgba(10,31,68,.32); }
.lx2-pill-tab.is-open::before { width: 6px; }
/* Б2: тёмно-синяя рамка (--ink-3) читалась на светлом фоне как жёсткая «рама»
   рядом с золотой полосой слева. Акцент оставляем один — золотой, но мягкий. */
.lx2-pill-tab:hover { box-shadow: 0 24px 50px -18px rgba(10,31,68,.22); border-color: rgba(251,199,8,.34); }
.lx2-pill-tab:hover::before { width: 6px; }
.lx2-pill-tab:hover::after { opacity: 1; }
.lx2-pill-tab:focus-visible { outline: 3px solid var(--gold); outline-offset: -3px; border-radius: 16px; }

.lx2-pill-ico { position: relative; z-index: 3; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 42px; height: 42px; border-radius: 12px; background: var(--mist); color: var(--ink); }
.lx2-pill-ico svg { width: 24px; height: 24px; }
.lx2-pill-titles { position: relative; z-index: 3; min-width: 0; }
.lx2-pill-titles b { display: block; font-size: 15px; font-weight: 800; line-height: 1.2; }
.lx2-pill-titles span { display: block; margin-top: 3px; font-size: 12px; line-height: 1.35; color: var(--slate); }
.lx2-pill-chev { position: relative; z-index: 3; flex: 0 0 auto; margin-left: auto; width: 9px; height: 9px; border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3); transform: rotate(45deg); transition: transform .35s ease; }
.lx2-pill-tab.is-open .lx2-pill-chev { transform: rotate(225deg); }

/* Аккордеон через grid-template-rows 0fr→1fr: плавно и без замеров
   scrollHeight. [hidden] конфликтует с display:grid — гасим явно.
   Б4: переход сокращён .42s → .32s — на 11.5 fps этого окружения длинная
   анимация высоты читалась как лаг (CLOSE_MS в JS держим тем же).
   Г1 (этап 1D): opacity у тела снят — прозрачность держит сама карточка
   (-in). Иначе при переключении два наложенных fade'а (тело + карточка)
   давали бы «грязь» вместо кросс-фейда, а по таблице Г3 уход старого
   содержимого должен занять .18s, а не .3s. */
.lx2-pill-body { display: grid; grid-template-rows: 0fr;
    /* Д2 (этап 1D): transition-property перечислен явно, без `all` — `all`
       тянул бы в переход и position/inset, из-за чего закрывающееся тело
       анимировало бы свою абсолютную позицию и «ползло» по карточке. */
    transition-property: grid-template-rows;
    transition-duration: .32s;
    transition-timing-function: cubic-bezier(.22,1,.36,1);
    /* align-self:start — тело не растягивается на зарезервированную высоту
       .lx2-pill-bodies. Визуально ничего не меняется (внутри align-items:start),
       но рамка тела перестаёт накрывать пустую зону резерва: под контентом
       остаётся честный фон hero, без «карточки» в DOM. */
    align-self: start; }
.lx2-pill-body.is-open { grid-template-rows: 1fr; }
.lx2-pill-body[hidden] { display: none; }
/* Д1: тело вне .is-open — вне потока (см. комментарий у .lx2-pill-bodies).
   В потоке остаётся ровно одно тело, поэтому контейнер не может вырасти
   выше резерва и страница не дёргается на кросс-фейде. Закрывающееся тело
   сворачивается и гаснет поверх открывающегося — это и есть кросс-фейд.
   inset:0 — чтобы тело растягивалось на ширину колонки, как при grid-flow. */
.lx2-pill-body:not(.is-open) { position: absolute; inset: 0; z-index: 0; }
.lx2-pill-body.is-open { position: relative; z-index: 1; }
/* Г1: белая карточка вернулась как оформленный элемент — рамка, мягкая
   двойная тень (внешняя + внутренний блик) и золотой акцент сверху
   (приём .lx2-src-card::before). overflow:hidden + min-height:0 обязательны
   для анимации 0fr→1fr.
   margin-top отодвигает карточку от липкого ряда; он входит в margin-box,
   который замеряет резерв высоты (landing.js, модуль 17) — поэтому резерв
   считается по .lx2-pill-body, а не по .lx2-pill-body-in. */
.lx2-pill-body > .lx2-pill-body-in {
    position: relative; overflow: hidden; min-height: 0;
    margin-top: 14px; padding: 30px 32px;
    background: linear-gradient(180deg, #fff 0%, #FDFCF8 100%);
    border: 1px solid var(--line); border-radius: 22px;
    box-shadow: 0 30px 70px -34px rgba(10,31,68,.30), 0 2px 0 rgba(255,255,255,.9) inset;
}
/* Золотой верхний акцент — короткий, с отступом от углов, чтобы читался как
   «шапка» карточки, а не как обводка. */
.lx2-pill-body-in::before {
    content: ''; position: absolute; left: 22px; right: 22px; top: 0; height: 3px;
    border-radius: 0 0 3px 3px; background: linear-gradient(90deg, var(--gold-2), var(--gold));
}
.lx2-pill-body-in { display: grid; grid-template-columns: 1.15fr minmax(0, 430px); gap: 26px; align-items: start; }
/* Скрин в колонке 430px всегда выше текста (~300px против ~180px), поэтому при
   align-items:start низ карточки оставался пустым белым прямоугольником. Текст
   центрируем по вертикали — в одну колонку (стек на ≤900px) это no-op. */
.lx2-pill-copy { min-width: 0; align-self: center; }
/* Шапка услуги: иконка 34px в квадрате 44×44 + золотая надпись-надзаголовок
   и собственный заголовок карточки. */
.lx2-pill-head { display: flex; align-items: center; gap: 14px; }
.lx2-pill-head-ico {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border-radius: 12px; background: var(--mist); color: var(--ink);
}
.lx2-pill-head-ico svg { width: 34px; height: 34px; }
.lx2-pill-head-text { min-width: 0; }
.lx2-pill-eyebrow {
    display: block; font-size: 11px; font-weight: 800; line-height: 1.2;
    letter-spacing: .14em; text-transform: uppercase; color: var(--gold);
}
.lx2-pill-title {
    margin: 3px 0 0; font-size: 19px; font-weight: 800; line-height: 1.2;
    letter-spacing: -.015em; color: var(--ink);
}
.lx2-pill-copy > p { margin: 14px 0 0; font-size: 15.5px; line-height: 1.55; color: var(--slate); }
/* Буллиты — капсулы-чипы с золотой точкой, а не голые жёлтые квадраты
   (диагноз заказчика: «выглядит дёшево»). inline-flex + gap — маркер списка
   не нужен, ::before рисует точку 6px с мягким свечением. */
.lx2-pill-list { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.lx2-pill-list li {
    display: inline-flex; align-items: center; gap: 8px; padding: 7px 14px;
    border-radius: 999px; background: var(--mist); border: 1px solid var(--line);
    font-size: 13px; font-weight: 600; line-height: 1.35; color: var(--ink);
}
.lx2-pill-list li::before {
    content: ''; flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%;
    background: var(--gold); box-shadow: 0 0 0 3px rgba(251,199,8,.18);
}
.lx2-pill-shot { margin: 0; }
/* Фиксированные пропорции у <img>, а не у .lx2-browser: у контейнера в
   пропорции входит шапка с точками, и contain оставлял бы белые поля по
   бокам. aspect-ratio на картинке даёт ту же детерминированную высоту, но
   скрин не обрезается ни снизу, ни сбоку. */
.lx2-pill-shot .lx2-browser {
    display: flex; flex-direction: column;
    box-shadow: 0 24px 60px -28px rgba(10,31,68,.35), 0 1px 0 0 rgba(251,199,8,.35) inset;
}
.lx2-pill-shot .lx2-browser-bar { flex: 0 0 auto; }
.lx2-pill-shot .lx2-browser img { flex: 0 0 auto; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: contain; }

/* ── Г3. Анимация появления содержимого карточки ─────────────────────────
   Порядок и тайминги — таблица ТЗ (Г3): карточка → шапка → описание →
   буллиты по очереди → скрин. Только CSS-transition от стартового
   состояния к .is-open, без JS и без нового rAF.
   Задержки объявлены ТОЛЬКО в целевом состоянии — тогда при закрытии
   transition идёт без задержек, и переключение плашек читается как
   кросс-фейд (старый уходит .18s, новый приходит по таблице).
   Все анимации — только opacity/transform, поэтому зарезервированная
   высота (.lx2-pill-bodies) не прыгает: dH/dY/dDoc = 0.
   Д2 (этап 1D): transition-property перечислен явно (opacity, transform),
   без `all`. `all` тянул бы в переход и grid/flex-метрики, из-за чего
   появление содержимого считало бы лишний layout в каждом кадре.        */
.lx2-pill-body > .lx2-pill-body-in { opacity: 0; transform: translateY(18px);
    transition-property: opacity, transform; transition-duration: .18s; transition-timing-function: ease; }
.lx2-pill-head, .lx2-pill-copy > p, .lx2-pill-list li, .lx2-pill-shot {
    transition-property: opacity, transform; transition-duration: .18s; transition-timing-function: ease;
}
.lx2-pill-head { opacity: 0; transform: translateX(-10px); }
.lx2-pill-copy > p { opacity: 0; transform: translateY(8px); }
.lx2-pill-list li { opacity: 0; transform: translateY(6px); }
.lx2-pill-shot { opacity: 0; transform: scale(.965); }

.lx2-pill-body.is-open > .lx2-pill-body-in { opacity: 1; transform: none; transition-duration: .42s; transition-timing-function: cubic-bezier(.22,1,.36,1); }
.lx2-pill-body.is-open .lx2-pill-head { opacity: 1; transform: none; transition-duration: .38s; transition-delay: .06s; }
.lx2-pill-body.is-open .lx2-pill-copy > p { opacity: 1; transform: none; transition-duration: .34s; transition-delay: .12s; }
.lx2-pill-body.is-open .lx2-pill-list li { opacity: 1; transform: none; transition-duration: .30s; }
.lx2-pill-body.is-open .lx2-pill-list li:nth-child(1) { transition-delay: .16s; }
.lx2-pill-body.is-open .lx2-pill-list li:nth-child(2) { transition-delay: .23s; }
.lx2-pill-body.is-open .lx2-pill-list li:nth-child(3) { transition-delay: .30s; }
.lx2-pill-body.is-open .lx2-pill-shot { opacity: 1; transform: none; transition-duration: .48s; transition-delay: .10s; }
/* Больше трёх буллитов в $heroPills не бывает, но правило на nth-child(4+)
   держит каскад для лишних пунктов, а не обрушивает их в opacity:1. */
.lx2-pill-body.is-open .lx2-pill-list li:nth-child(n+4) { transition-delay: .37s; }

/* ── Полноэкранный drawer плашки hero (этап 1C) ────────────────────────────
   Базовое правило — единственное место вне @media: на десктопе drawer не
   рендерится вообще (display:none), раскрытие на месте сохраняется полностью.
   Все остальные свойства drawer'а живут в @media (max-width: 760px) ниже —
   граница режима одна и та же на CSS и на JS.                            */
.lx2-drawer { display: none; }

/* Переключение читается как действие: раскрытие тела (grid-template-rows
   .32s) + появление содержимого карточки по таблице Г3 + золотая полоса у
   плашки (.lx2-pill-tab.is-open::before). */

/* Появление плашек при первом попадании hero в зону видимости (.is-in вешает
   модуль 11 — во всех трёх ветках, включая reduceMotion и без IO).
   Движение — на самом баре, плашкам только прозрачность со сдвигом по времени:
   transform у плашки занят 3D-tilt из JS (инлайн), reveal с ним бы конфликтовал. */
.lx2-pills-bar { opacity: 0; transform: translateY(18px); transition: opacity .7s cubic-bezier(.22,1,.36,1), transform .7s cubic-bezier(.22,1,.36,1); }
.lx2-pill-tab { opacity: 0; }
.lx2-hero.is-in .lx2-pills-bar { opacity: 1; transform: none; }
.lx2-hero.is-in .lx2-pill-tab { opacity: 1; }
.lx2-hero.is-in .lx2-pills-bar .lx2-pill-tab:nth-child(1) { transition-delay: .05s; }
.lx2-hero.is-in .lx2-pills-bar .lx2-pill-tab:nth-child(2) { transition-delay: .13s; }
.lx2-hero.is-in .lx2-pills-bar .lx2-pill-tab:nth-child(3) { transition-delay: .21s; }
.lx2-hero.is-in .lx2-pills-bar .lx2-pill-tab:nth-child(4) { transition-delay: .29s; }

/* ═══ 2. ИСТОЧНИК ═══ */
/* Алиас-якорь #data (ссылка «Продукт → Интеграции» в футере — футер вне скоупа).
   Стоит первым потомком .lx2-wrap, т.е. уже ПОСЛЕ внутреннего padding-top секции
   (96px). Значение подобрано так, чтобы шапка секции попадала на 96px от
   верхнего края экрана: -96px (как в ТЗ) уводил заголовок на 192px выше
   видимой области — после клика из футера он был не виден. */
.lx2-anchor { display: block; height: 0; scroll-margin-top: 96px; }

.lx2-source { background: var(--mist); }
.lx2-src-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.lx2-src-card {
    position: relative; overflow: hidden;
    background: #fff; border: 1px solid var(--line); border-radius: 20px; padding: 26px 24px;
    transition: transform .35s cubic-bezier(.22,1,.36,1), box-shadow .35s ease, border-color .35s ease;
}
/* Золотая полоса сверху — приём референса (.why-card): от нуля слева направо */
.lx2-src-card::before {
    content: ''; position: absolute; left: 0; right: 0; top: 0; height: 3px; z-index: 1;
    background: linear-gradient(90deg, var(--gold-2), var(--gold));
    transform: scaleX(0); transform-origin: left;
    transition: transform .4s cubic-bezier(.22,1,.36,1);
}
.lx2-src-card:hover {
    transform: translateY(-6px);
    box-shadow: 0 24px 50px -18px rgba(10,31,68,.22);
    border-color: var(--ink-3);
}
.lx2-src-card:hover::before { transform: scaleX(1); }
.lx2-src-ico {
    position: relative; z-index: 1;
    display: flex; align-items: center; justify-content: center;
    width: 56px; height: 56px; margin-bottom: 16px; border-radius: 16px;
    background: var(--mist); color: var(--ink);
    transition: transform .35s cubic-bezier(.22,1,.36,1), background .35s ease;
}
.lx2-src-ico svg { width: 28px; height: 28px; }
.lx2-src-card:hover .lx2-src-ico { transform: rotate(-6deg) scale(1.08); background: #fff; }
.lx2-src-card h3 { font-size: 18px; font-weight: 800; letter-spacing: -.01em; margin: 0 0 8px; }
.lx2-src-card p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--slate); }
/* Карточка «Свой API» — единственная с золотой обводкой и мягким подтоном */
.lx2-src-card.is-accent { border-color: rgba(251,199,8,.5); background: linear-gradient(180deg, #fff, #fffdf2); }

/* Вывод секции: тёмный блок во всю ширину — визуальный «якорь» на светлом фоне */
.lx2-src-outcome {
    display: flex; align-items: center; gap: 24px;
    margin-top: 20px; padding: 34px 38px; border-radius: 24px;
    background: var(--ink); color: #fff;
}
.lx2-src-outcome-ico {
    flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
    width: 64px; height: 64px; border-radius: 50%;
    background: rgba(251,199,8,.14); color: var(--gold);
}
.lx2-src-outcome-ico svg { width: 40px; height: 40px; }
.lx2-src-outcome p { margin: 0; font-size: 21px; line-height: 1.5; font-weight: 600; }
.lx2-src-outcome b { color: var(--gold); font-weight: 800; }

/* Свои брейкпоинты секции 2 (900 / 600) — не совпадают с общими 1100 / 760,
   поэтому правила живут рядом с секцией, а не в общем адаптивном блоке. */
@media (max-width: 899px) {
    .lx2-src-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 599px) {
    .lx2-src-grid { grid-template-columns: 1fr; }
    .lx2-src-outcome { flex-direction: column; align-items: flex-start; gap: 18px; padding: 28px 24px; }
    .lx2-src-outcome p { font-size: 18px; }
}

/* ═══ 3. ХАБ ═══ */
.lx2-hub { background: var(--paper); }

/* Сцена — общий контейнер орбиты и панели. Именно отсюда панель
   позиционируется absolute, поэтому её центр совпадает с центром орбиты
   («точка схлопывания», Р-6) независимо от позиции страницы. */
.lx2-hub-scene { position: relative; }

/* --hub-r — радиус орбиты в px. Должен совпадать с кольцом в SVG:
   viewBox 320 (радиус 160) и circle r=118 → 118/160 = 0.7375 от полуширины.
   При max-width 700 полуширина 350 → 350 * 0.7375 ≈ 258px. */
.lx2-orbit {
    --hub-r: 258px;
    position: relative; width: 100%; max-width: 700px; aspect-ratio: 1 / 1; margin: 0 auto;
    /* Схлопывание крутит 10 transform'ов разом — изолируем компоновку и
       отрисовку орбиты (производительность, п.7). Узлы и кольцо в неё
       вписываются, клиппить нечего. */
    contain: layout paint;
}

/* Вихрь — единственный «чёрный дырой» акцент: вспышка в центре на время
   схлопывания. Один элемент, одна анимация, стоимость нулевая. */
.lx2-vortex {
    position: absolute; left: 50%; top: 50%; width: 40px; height: 40px;
    margin: -20px 0 0 -20px; border-radius: 50%; pointer-events: none; opacity: 0;
    background: radial-gradient(circle, rgba(10,31,68,.9), rgba(251,199,8,.25) 55%, transparent 72%);
}
.lx2-hub-scene[data-state="collapsing"] .lx2-vortex { animation: lx2-vortex .52s cubic-bezier(.4,0,.6,1) 1; }
@keyframes lx2-vortex {
    0%   { transform: scale(0);  opacity: 0; }
    22%  { opacity: .9; }
    100% { transform: scale(26); opacity: 0; }
}

.lx2-wires { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
/* Задержки схлопывания задаём на каждой линии (у неё свой --i), поэтому
   transform/opacity анимируются построчно, а не на всём SVG разом: иначе
   стаггер невозможен, а втягивание «щёткой» читается хуже. */
.lx2-wire {
    stroke: #C7D3E8; stroke-width: 1.6; stroke-dasharray: 118; stroke-dashoffset: 118;
    /* ВАЖНО: transform-origin у SVG-элементов по умолчанию 0 0 — это начало
       пользовательской системы, а viewBox начинается с -160, то есть ровно
       центр орбиты. Если написать 50% 50%, Chrome считает проценты от
       border-box и поворот на SVG-атрибуте rotate(a) «уезжает» (линии
       рисуются не туда). 0 0 нужен ещё и для схлопывания: scale(.03)
       должен стягивать линии в центр, а не в угол. */
    transform-origin: 0 0;
    transition: stroke-dashoffset .7s cubic-bezier(.22,1,.36,1) calc(var(--i) * 70ms + 200ms),
                stroke .3s, stroke-width .3s,
                transform .48s cubic-bezier(.5,0,.75,0), opacity .3s linear;
}
.lx2-orbit.is-in .lx2-wire { stroke-dashoffset: 0; }
.lx2-wire.is-hot { stroke: var(--gold); stroke-width: 2.5; }
.lx2-hub-scene[data-state="collapsing"] .lx2-wire {
    transition: transform .48s cubic-bezier(.5,0,.75,0) calc(var(--i) * 8ms),
                opacity .3s linear calc(var(--i) * 8ms);
}
.lx2-wire-ring {
    fill: none; stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 7;
    transform-origin: 0 0; transition: transform .48s cubic-bezier(.5,0,.75,0) .1s, opacity .3s linear .1s;
}
.lx2-hub-scene:not([data-state="idle"]) .lx2-wire { transform: scale(.03) rotate(60deg); opacity: 0; }
.lx2-hub-scene:not([data-state="idle"]) .lx2-wire-ring { transform: scale(.03) rotate(60deg); opacity: 0; }
/* Пока идёт схлопывание, повторные клики по узлам не должны запускать его
   заново — орбита не принимает указатель. */
.lx2-hub-scene[data-state="collapsing"] .lx2-orbit { pointer-events: none; }
/* Орбита спрятана на время панели: узлы долетели до центра и не должны
   просвечивать сквозь растущую карточку (состояния opening/open/closing/
   expanding — ТЗ 5.2). visibility, а не display: сцена сохраняет высоту. */
.lx2-orbit.is-collapsed { visibility: hidden; }

.lx2-core {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
    width: 180px; height: 180px; border-radius: 50%;
    background: radial-gradient(circle at 30% 25%, var(--ink-2), var(--ink)); color: #fff;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 4px; text-align: center; box-shadow: 0 20px 60px -18px rgba(10,31,68,.6);
    transition: transform .42s ease-in, filter .42s ease-in, opacity .42s ease-in;
}
.lx2-core b { font-size: 30px; font-weight: 900; letter-spacing: -.03em; }
.lx2-core small { font-size: 11px; color: rgba(255,255,255,.62); max-width: 130px; line-height: 1.35; }
.lx2-core-ring { position: absolute; inset: -16px; border: 2px dashed rgba(251,199,8,.5); border-radius: 50%; animation: lx2-spin 42s linear infinite; }
.lx2-hub-scene:not([data-state="idle"]) .lx2-core { transform: translate(-50%,-50%) scale(.06) rotate(-90deg); filter: blur(8px); opacity: 0; }

.lx2-node {
    position: absolute; left: 50%; top: 50%;
    transform: rotate(var(--a)) translate(var(--hub-r)) rotate(calc(-1 * var(--a))) translate(-50%,-50%);
    width: 92px; text-align: center; text-decoration: none; color: var(--ink);
    background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
    will-change: transform;
    transition: transform .35s cubic-bezier(.22,1,.36,1);
}
/* Roving tabindex (ТЗ 5.7): в Tab-поток орбиты попадает только активный узел,
   остальные закрыты tabindex="-1" — их выбирает JS. */
.lx2-node-ico { display: flex; align-items: center; justify-content: center; width: 62px; height: 62px; margin: 0 auto 8px; border-radius: 50%; background: #fff; border: 1.5px solid var(--line); font-size: 26px; box-shadow: 0 10px 26px -14px rgba(10,31,68,.4); transition: transform .3s cubic-bezier(.22,1,.36,1), border-color .3s, background .3s, box-shadow .3s; }
/* Иконки узлов — инлайн SVG вместо эмодзи (Д-4), задаём размер svg */
.lx2-node-ico svg { width: 26px; height: 26px; }
.lx2-node-lbl { display: block; font-size: 12px; font-weight: 700; line-height: 1.25; }
.lx2-node:hover { transform: rotate(var(--a)) translate(var(--hub-r)) rotate(calc(-1 * var(--a))) translate(-50%,-50%) scale(1.08); }
.lx2-node:hover .lx2-node-ico, .lx2-node:focus-visible .lx2-node-ico { transform: scale(1.12); border-color: var(--gold); background: #fffbe9; box-shadow: 0 14px 34px -12px rgba(251,199,8,.7); }

/* ── Панель «чёрная дыра» (ТЗ 5.1-5.4) ────────────────────────────────────
   absolute, а не fixed: центр панели = центр орбиты (см. .lx2-hub-scene). */
/* grid-template-rows: minmax(0,1fr) — обязателен, а не украшение. Импульсная
   строка грида по умолчанию растёт под min-content карточки: на 375×667 это
   732px при высоте панели 667px, и place-items:center центрирует карточку уже
   внутри этой строки — то есть на 33px НИЖЕ центра экрана, нижние 9px
   карточки уезжают под сгиб (замерено). С фиксированной строкой карточка
   центрируется по реальной высоте панели. */
.lx2-vp { position: absolute; inset: 0; z-index: 200; display: grid; grid-template-rows: minmax(0, 1fr); place-items: center; --vp-out: 10px; --vp-in: -8px; }
/* [hidden] конфликтует с display:grid/flex — без этого правила панель и её
   ссылка «протекают» наружу */
.lx2-vp[hidden], .lx2-vp [hidden] { display: none; }
/* Заказчик: серый фон подложки убран — панель висит на чистом фоне секции.
   Элемент остаётся: на нём держится клик-закрытие (data-vp-close в JS) и
   он перехватывает клики мимо карточки. Без него клик по фону во время
   открытой панели проваливался бы в хаб под ней. */
.lx2-vp-backdrop { position: absolute; inset: 0; border: 0; padding: 0; background: none; cursor: default; }
/* overflow:auto переносим с карточки на .lx2-vp-grid: иначе кнопка закрытия
   «над окном» (top/right: -14px) обрезалась бы этим же overflow (Р-6).
   max-height ограничен и высотой сцены, и вьюпортом — карточка не должна
   вылезать за экран на невысоких ноутбуках. Точную верхнюю границу задаёт
   медиазапрос 1100px ниже (шапка + крестик + воздух). */
.lx2-vp-card {
    position: relative; z-index: 1; display: flex; flex-direction: column;
    width: 100%; max-width: 660px;
    max-height: min(calc(100% - 48px), calc(100vh - 48px));
    background: #fff; border: 1px solid var(--line); border-radius: 22px;
    box-shadow: 0 40px 90px -30px rgba(10,31,68,.55);
    padding: 24px 24px 18px;
}
.lx2-vp-close {
    position: absolute; top: -14px; right: -14px; z-index: 3;
    width: 44px; height: 44px; border-radius: 50%;
    border: 1.5px solid var(--line); background: var(--ink); color: var(--gold);
    font-size: 17px; line-height: 1; cursor: pointer;
    transition: transform .22s ease, box-shadow .22s ease;
}
.lx2-vp-close:hover { transform: rotate(90deg); box-shadow: 0 12px 26px -12px rgba(10,31,68,.6); }
.lx2-vp-grid {
    display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 24px; align-items: start;
    /* overscroll-behavior намеренно НЕ contain: скролл страницы на время
       открытой панели больше не блокируется (см. landing.js, модуль 16), и
       contain ловил бы колесо на границе карточки — на невысоких экранах
       страница переставала бы скроллиться, пока указатель над карточкой.
       Цепочка прокрутки (scroll chaining) здесь как раз нужна: докрутил
       текст в карточке → поехала страница → блок хаба ушёл из вьюпорта →
       панель сворачивается (IntersectionObserver в landing.js). */
    overflow: auto; min-height: 0; padding-right: 4px;
}
/* Резерв под самый длинный слайд: без него высота карточки гуляла бы на
   ~70px при каждом переходе (длинные тексты отличаются на 1–3 строки), а
   панель центрирована — край дёргался бы вверх-вниз. 410px = замер по всем
   10 слайдам (max 406) + запас; если текст окажется длиннее, высота честно
   вырастет, а не уедет под обрез.

   min-height АДАПТИВНЫЙ (Р-6): жёсткие 410px не давали карточке сжаться на
   невысоких ноутбуках — при max-height карточки ниже её содержимого грид
   вылезал за карточку, а прокрутить его было нельзя (overflow живёт на гриде,
   но растягивать его сверху не давал min-height). На 1366×700 это 42vh = 294px:
   лишнее уходит во внутренний скролт, стрелки «Назад/Вперёд» (вне грида)
   остаются на месте и всегда достижимы. */
.lx2-vp-grid { min-height: min(410px, 42vh); }
.lx2-vp-shot { margin: 0; transition: opacity .2s ease-out, transform .2s ease-out; }
/* Пропорции фиксированы aspect-ratio, а не замером: каждый слайд подставляет
   скрин 2880×1800, и без этого высота панели прыгала бы. 3/2 ≈ 1.6 — исходное
   соотношение сторон скринов, поэтому cover почти не обрезает кадр. */
.lx2-vp-shot .lx2-browser img { width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; object-position: top center; transition: opacity .2s ease; }
.lx2-vp-shot.is-loading .lx2-browser img { opacity: .35; }
.lx2-vp-copy { min-width: 0; transition: opacity .2s ease-out, transform .2s ease-out; }
.lx2-vp-copy.is-out, .lx2-vp-shot.is-out { opacity: 0; transform: translateX(var(--vp-out)); transition-duration: .16s; transition-timing-function: ease-in; }
.lx2-vp-copy.is-in, .lx2-vp-shot.is-in { opacity: 1; transform: translateX(var(--vp-in)); }
.lx2-vp-count { margin-bottom: 12px; font-variant-numeric: tabular-nums; }
.lx2-vp-copy h3 { margin: 0 0 10px; font-size: 24px; line-height: 1.15; font-weight: 800; letter-spacing: -.02em; color: var(--ink); }
.lx2-vp-copy p { margin: 0 0 12px; font-size: 15px; line-height: 1.55; color: var(--ink-3); font-weight: 600; }
.lx2-vp-body { margin: 0 0 18px; font-size: 14px; line-height: 1.6; color: var(--slate); }
.lx2-vp-nav { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.lx2-vp-arrow {
    display: inline-flex; align-items: center; gap: 8px;
    background: none; border: 1.5px solid var(--line); border-radius: 100px;
    padding: 9px 18px; font: inherit; font-size: 14px; font-weight: 700;
    color: var(--ink); cursor: pointer;
    transition: border-color .2s, background .2s, transform .2s;
}
.lx2-vp-arrow:hover { border-color: var(--ink-3); background: var(--mist); transform: translateY(-1px); }
.lx2-vp-arrow i { width: 9px; height: 9px; border-top: 2px solid currentColor; border-right: 2px solid currentColor; }
.lx2-vp-arrow[data-vp-prev] i { transform: rotate(-135deg); }
.lx2-vp-arrow[data-vp-next] i { transform: rotate(45deg); }
/* Точки — только индикатор (не 10 кнопок в Tab-порядке): навигация стрелками */
.lx2-vp-dots { display: flex; align-items: center; gap: 6px; }
.lx2-vp-dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--line); transition: background .2s, transform .2s; }
.lx2-vp-dots i.is-on { background: var(--gold); transform: scale(1.35); }

/* Фокус-кольцо на всех интерактивных элементах хаба (ТЗ 5.7) */
.lx2-node:focus-visible, .lx2-hub-open:focus-visible,
.lx2-vp button:focus-visible, .lx2-vp a:focus-visible {
    outline: 3px solid var(--gold); outline-offset: 3px; border-radius: 12px;
}

/* Тот же контент списком: <1100px вместо орбиты + SEO-дубль */
.lx2-hub-list { display: none; list-style: none; margin: 0; padding: 0; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.lx2-hub-list li { background: #fff; border: 1px solid var(--line); border-radius: 16px; overflow: hidden; transition: opacity .18s ease; }
/* Нажатая карточка «схлопывается в свою точку», остальные притухают (ТЗ 5.9) */
.lx2-hub-list.is-dim li { opacity: .3; }
.lx2-hub-open {
    display: grid; grid-template-columns: 40px minmax(0, 1fr) 12px; gap: 14px;
    align-items: start; width: 100%; padding: 16px;
    background: none; border: 0; font: inherit; text-align: left; color: var(--ink); cursor: pointer;
}
.lx2-hub-ico { display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: 12px; background: var(--mist); border: 1px solid var(--line); color: var(--ink-3); transition: border-color .2s, background .2s, color .2s; }
.lx2-hub-ico svg { width: 22px; height: 22px; }
.lx2-hub-body b { display: block; margin-bottom: 4px; font-size: 15px; font-weight: 800; }
.lx2-hub-body span { font-size: 13px; line-height: 1.5; color: var(--slate); }
.lx2-hub-chev { width: 10px; height: 10px; margin-top: 6px; border-top: 2px solid var(--slate); border-right: 2px solid var(--slate); transform: rotate(45deg); }
.lx2-hub-open:hover .lx2-hub-ico { border-color: var(--gold); background: rgba(251,199,8,.14); color: var(--ink); }

/* ═══ 4. CRM ═══ */
/* Асимметричный сплит (ТЗ «Референс 8081» → п.6: секция 4 — сплит со
   сдвинутым вторым скрином). Фон --mist — чередуется с бумажным хабом
   (секция 3) и бумажной секцией 5. */
.lx2-crm { background: var(--mist); }
.lx2-crm-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr); gap: 52px; align-items: center; }
.lx2-crm .lx2-sub { margin: 0; max-width: 560px; }

/* 7 пунктов — спецификация в две колонки: тонкая черта сверху + золотой
   штрих вместо сплошного квадрата. Ритм не тот, что у карточек секции 2
   (там белый блок с иконкой), поэтому блок не читается копией. */
.lx2-points {
    list-style: none; margin: 30px 0; padding: 0;
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 26px;
}
.lx2-points li { position: relative; padding: 15px 0 0 24px; border-top: 1.5px solid var(--line); }
.lx2-points li::before { content: ''; position: absolute; left: 0; top: -3px; width: 18px; height: 4px; border-radius: 3px; background: var(--gold); }
/* Последний пункт — «один источник = одна доска», он замыкает список и
   тянулся бы на всю ширину: одна короткая строка на весь ряд читалась бы
   пустотой справа. */
.lx2-points li:last-child { grid-column: 1 / -1; }
.lx2-points b { display: block; font-size: 15px; font-weight: 800; letter-spacing: -.01em; margin-bottom: 4px; }
.lx2-points span { font-size: 14px; line-height: 1.55; color: var(--slate); }
.lx2-crm-cta { display: flex; gap: 12px; flex-wrap: wrap; }

.lx2-crm-shot { display: flex; flex-direction: column; gap: 26px; }
.lx2-shotbox { margin: 0; }
.lx2-shotbox figcaption { margin-top: 12px; text-align: center; font-size: 13px; color: var(--slate); }
/* Второй скрин смещён влево — колонка читается ступенчаткой, а не стопкой. */
.lx2-shotbox-sm { width: 82%; }
/* Высота скрина держится aspect-ratio на рамке + object-fit на картинке:
   лейаут не прыгает при загрузке, пропорции не искажаются (у обеих картинок
   ratio совпадает с натуральным, поэтому object-fit: cover ничего не режет).
   width/height на <img> в разметке дублируют это для ленивой загрузки. */
.lx2-shot-frame { position: relative; width: 100%; aspect-ratio: 16 / 10; background: #F7F9FD; }
.lx2-shot-frame-pipe { aspect-ratio: 36 / 13; }
.lx2-crm-shot .lx2-browser img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top center; }

/* ═══ 5. ШАГИ + ФОРМА ═══ */
/* Мягкое золотое пятно за карточкой формы: на --paper белый блок иначе
   сливается с фоном (секция 4 и 3 — на --mist, там белый читается сам). */
.lx2-start-sec {
    background: var(--paper);
    background-image: radial-gradient(620px circle at 82% 20%, rgba(251,199,8,.10), transparent 70%);
}
.lx2-start-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.06fr) minmax(0, .94fr);
    grid-template-areas: "steps form" "cta form";
    grid-template-rows: auto 1fr;
    column-gap: 52px; row-gap: 32px; align-items: start;
}
.lx2-steps { grid-area: steps; position: relative; list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 28px; }
/* Вертикальная шина между шагами: список читается как лестница шагов,
   а не как три строки. Линия на самом <ol>, а не на <li> — не зависит от
   числа пунктов. */
.lx2-steps::before { content: ''; position: absolute; left: 22px; top: 24px; bottom: 24px; width: 1.5px; background: linear-gradient(180deg, var(--gold), var(--line)); opacity: .6; }
.lx2-steps li { position: relative; display: flex; gap: 18px; align-items: flex-start; }
.lx2-steps li > i {
    position: relative; z-index: 1; flex: 0 0 auto;
    width: 46px; height: 46px; border-radius: 50%;
    background: var(--ink); color: var(--gold); border: 3px solid var(--paper);
    display: flex; align-items: center; justify-content: center;
    font-size: 17px; font-weight: 800; font-style: normal;
    box-shadow: 0 12px 26px -16px rgba(10,31,68,.75);
}
.lx2-steps b { display: block; font-size: 18px; font-weight: 800; letter-spacing: -.01em; margin: 5px 0 5px; }
.lx2-steps span { font-size: 14.5px; line-height: 1.6; color: var(--slate); }
.lx2-start-cta { grid-area: cta; align-self: end; display: flex; gap: 12px; flex-wrap: wrap; padding-top: 24px; }

.lx2-formcard {
    grid-area: form;
    position: relative; overflow: hidden;
    background: #fff; border: 1px solid var(--line); border-radius: 22px;
    padding: 34px 30px 28px;
    box-shadow: 0 34px 70px -46px rgba(10,31,68,.6);
}
.lx2-formcard::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 4px; background: linear-gradient(90deg, var(--gold), var(--gold-2)); }
.lx2-formcard h3 { font-size: 22px; font-weight: 800; letter-spacing: -.02em; margin: 0 0 8px; }
.lx2-formcard > p { font-size: 14px; line-height: 1.6; color: var(--slate); margin: 0 0 22px; }
.lx2-field { margin-bottom: 16px; }
.lx2-field label { display: block; font-size: 13px; font-weight: 700; color: var(--ink-3); margin-bottom: 7px; }
.lx2-field input, .lx2-field textarea {
    width: 100%; padding: 13px 14px; border: 1.5px solid var(--line);
    border-radius: 12px; background: var(--paper);
    font: inherit; font-size: 15px; color: var(--ink); resize: vertical;
    transition: border-color .2s ease, background .2s ease, box-shadow .2s ease;
}
.lx2-field input::placeholder, .lx2-field textarea::placeholder { color: var(--slate); opacity: .75; }
.lx2-field input:focus, .lx2-field textarea:focus { outline: none; border-color: var(--gold); background: #fff; box-shadow: 0 0 0 4px rgba(251,199,8,.18); }
.lx2-submit {
    width: 100%; padding: 16px; border: none; border-radius: 12px;
    background: var(--gold); color: var(--ink);
    font: inherit; font-size: 15px; font-weight: 800; cursor: pointer;
    box-shadow: 0 12px 28px -14px rgba(251,199,8,.85);
    transition: background .2s ease, transform .2s ease, box-shadow .25s ease;
}
.lx2-submit:hover { background: var(--gold-2); transform: translateY(-1px); }
.lx2-form-note { margin: 14px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--slate); text-align: center; }
.lx2-form-ok { display: none; text-align: center; padding: 26px 0; }
.lx2-form-ok.show { display: block; }
.lx2-form-ok b { display: block; font-size: 19px; margin-bottom: 8px; }
.lx2-form-ok span { font-size: 14px; color: var(--slate); }
.lx2-form.is-sent { display: none; }

/* ═══ 6. FAQ ═══ */
/* Одна колонка с нумерацией (ТЗ «Референс» → п.6): список вопросов, а не
   сетка карточек — иначе секция повторяла бы секцию 2. */
.lx2-faq-sec { background: var(--mist); }
/* Подпись и ссылка «Посмотреть тарифы →» — под заголовком, с воздухом:
   в шапке секции .lx2-sub идёт последним, без нижнего отступа. */
.lx2-faq-sec .lx2-more { margin-top: 16px; }
.lx2-faq { max-width: 900px; margin: 0 auto; display: flex; flex-direction: column; gap: 12px; }
.lx2-faq-item {
    background: #fff; border: 1px solid var(--line); border-radius: 16px;
    padding: 0 20px;
    transition: border-color .2s ease, box-shadow .25s ease;
}
.lx2-faq-item:hover { border-color: rgba(27,58,117,.22); }
.lx2-faq-item[open] { border-color: rgba(251,199,8,.55); box-shadow: 0 18px 44px -32px rgba(10,31,68,.55); }
.lx2-faq-item summary {
    position: relative; display: flex; gap: 16px; align-items: baseline;
    list-style: none; cursor: pointer;
    padding: 19px 36px 19px 0;
    font-size: 16.5px; font-weight: 700; line-height: 1.45; letter-spacing: -.01em;
}
.lx2-faq-item summary::-webkit-details-marker { display: none; }
.lx2-faq-item summary:focus-visible { outline: 3px solid var(--gold); outline-offset: -3px; border-radius: 16px; }
/* Номер — не золото: золото на белом даёт контраст 1.58 и номер почти не
   читается. Синий ink-3 (9.1:1) держит нумерацию читаемой, а золотой акцент
   остаётся на шевроне и на рамке открытого пункта. */
.lx2-faq-num { flex: 0 0 auto; font-variant-numeric: tabular-nums; font-size: 13px; font-weight: 800; letter-spacing: .08em; color: var(--ink-3); }
.lx2-faq-q { min-width: 0; }
/* Шеврон — одна рамка, повёрнутая на 45°; при открытии доворачивается на
   180°, поэтому состояние видно без второго символа. */
.lx2-faq-item summary::after {
    content: ''; position: absolute; right: 6px; top: 28px;
    width: 10px; height: 10px;
    border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3);
    transform: rotate(45deg); transform-origin: center;
    transition: transform .3s ease, border-color .3s ease;
}
.lx2-faq-item[open] summary::after { transform: rotate(225deg); border-color: var(--gold); }
.lx2-faq-item > p { margin: 0 0 20px; padding-left: 42px; max-width: 780px; font-size: 14.5px; line-height: 1.65; color: var(--slate); }
/* Плавное раскрытие — целиком на CSS, без JS: ::details-content позволяет
   анимировать содержимое нативного <details>, а interpolate-size (ниже) даёт
   интерполяцию до height:auto. Где поддержки нет — правило отбрасывается,
   раскрытие мгновенное (деградация допустима, Р-9). */
.lx2-faq-item::details-content {
    block-size: 0; overflow: hidden;
    transition: block-size .34s cubic-bezier(.22,1,.36,1), content-visibility .34s allow-discrete;
    transition-behavior: allow-discrete;
}
.lx2-faq-item[open]::details-content { block-size: auto; }

/* ═══ 7. ФИНАЛЬНЫЙ CTA ═══ */
/* Секция тёмная (--ink), внутри — скруглённая карточка 24px с золотой
   подсветкой снизу: блок читается формой, а не заливкой во всю ширину. */
.lx2-final {
    background: var(--ink); color: #fff; text-align: center; padding: 88px 0;
    background-image: radial-gradient(760px circle at 50% 120%, rgba(251,199,8,.26), transparent 68%);
}
.lx2-final-card {
    max-width: 820px; margin: 0 auto;
    padding: 56px 40px 44px;
    border-radius: 24px;
    border: 1px solid rgba(251,199,8,.28);
    background: linear-gradient(180deg, rgba(27,58,117,.55), rgba(19,45,94,.32));
    box-shadow: 0 40px 90px -54px rgba(0,0,0,.85);
}
.lx2-final h2 { color: #fff; }
.lx2-final p { font-size: 17px; line-height: 1.6; color: rgba(255,255,255,.74); max-width: 620px; margin: 0 auto 30px; }
/* Селектор с классом, а не только .lx2-final-note: правило выше бьёт по
   любому <p> внутри секции и без .lx2-final у него специфичность выше. */
.lx2-final .lx2-final-note { margin: 24px auto 0; font-size: 13px; line-height: 1.5; color: rgba(255,255,255,.58); }

/* ═══ АНИМАЦИИ ═══ */
@keyframes lx2-morph {
    0%, 100% { border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; transform: translate(0,0) scale(1); }
    50% { border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; transform: translate(20px,-26px) scale(1.08); }
}
@keyframes lx2-spin { to { transform: rotate(360deg); } }
@keyframes lx2-glow { 0%, 100% { opacity: .75; transform: translateY(0); } 50% { opacity: 1; transform: translateY(-14px); } }
@keyframes lx2-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: .55; } }
@keyframes lx2-float { 0%, 100% { translate: 0 0; } 50% { translate: 0 -10px; } }

/* ═══ АДАПТИВ ═══ */
@media (max-width: 1100px) {
    /* Секции 4 и 5: сплит → стек. Сетка секции 5 становится одноколоночной
       и переключает порядок зон явно (иначе areas «steps form» / «cta form»
       не помещаются в одну колонку). */
    .lx2-crm-grid { grid-template-columns: minmax(0, 1fr); gap: 34px; }
    /* В одну колонку высоты строк задаёт только содержимое: на десктопе вторую
       строку растягивал бы fr (там он нужен, чтобы кнопки встали по низу
       карточки формы), здесь это дало бы пустоту перед формой. */
    .lx2-start-grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "steps" "cta" "form"; grid-template-rows: auto auto auto; row-gap: 26px; }
    .lx2-start-cta { align-self: auto; padding-top: 0; }
    .lx2-crm .lx2-sub { margin: 0 auto; }
    /* Плашки hero: 2 колонки в баре, плавание выключено (как .hero-stat-card в референсе) */
    .lx2-pills-bar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .lx2-pill-tab { animation: none; }
}

/* Секция 4: спецификация 2×N → 1 колонка, второй скрин без смещения. */
@media (max-width: 760px) {
    .lx2-points { grid-template-columns: minmax(0, 1fr); gap: 16px; }
    .lx2-shotbox-sm { width: 100%; }
    .lx2-steps::before { left: 20px; }
    .lx2-formcard { padding: 28px 20px 24px; border-radius: 20px; }
    .lx2-final { padding: 64px 0; }
    .lx2-final-card { padding: 40px 20px 32px; }
}

/* Хаб: орбита → список. Граница 1099px, а не 1100px, потому что на JS тот же
   режим определяется как matchMedia('(min-width: 1100px)') — при 1100 ровно
   CSS и JS обязаны сойтись, иначе схлопывается несуществующая орбита. */
@media (max-width: 1099px) {
    .lx2-orbit { display: none; }
    .lx2-hub-list { display: grid; }
    /* Орбиты нет — «точка схлопывания» это центр экрана, поэтому панель
       становится полноэкранной (fixed) и растёт из центра вьюпорта. */
    .lx2-vp { position: fixed; }
    .lx2-vp-grid { grid-template-columns: 1fr; gap: 18px; }
    .lx2-vp-card { padding: 20px 18px 14px; }
}

/* Невысокие ноутбуки (1366×768 и подобные): орбита 700px + панель в её высоте
   не влезают по вертикали. Уменьшаем орбиту пропорционально — вместе с
   --hub-r, иначе узлы и кольцо разъедутся (Р-6). */
@media (min-width: 1100px) and (max-height: 820px) {
    .lx2-orbit { max-width: 600px; --hub-r: 221px; }
}

/* Верхняя граница карточки панели на десктопе. Панель растёт из центра
   орбиты (position:absolute внутри сцены), поэтому её положение задаёт не
   вьюпорт, а точка схлопывания: 100vh - 48px позволял карточке уехать под
   фиксированную шапку. 132 = шапка 74 + крестик над карточкой 14 + воздух 28
   сверху и 16 снизу. Полоса «шапка → низ экрана» = vh - 104, то есть
   карточка по высоте гарантированно в неё влезает; landing.js (fitPanel)
   подкручивает страницу так, чтобы центр орбиты встал в эту полосу.
   На <1100px панель fixed и шапки над ней нет — правило не применяется. */
@media (min-width: 1100px) {
    .lx2-vp-card { max-height: min(calc(100% - 48px), calc(100vh - 132px)); }
}

/* Г1: карточка двухколоночная на ≥900px. Ниже текстовая колонка (1.15fr) и
   колонка скрина (до 430px) делят 768px и дают ~200px текста — уходим в
   стек раньше, чем текст начнёт рваться по словам. */
@media (max-width: 900px) {
    .lx2-pill-body-in { grid-template-columns: 1fr; gap: 20px; }
}

/* ═══ МОБИЛЬНЫЙ HERO (этап 1C, задача №2c) ═══
   Граница режима ровно одна и та же на CSS и на JS (landing.js, mobileMQ):
   max-width: 760px. Другого брейкпоинта для drawer'а быть не должно, иначе
   разметка и поведение разойдутся.
   Что здесь происходит: hero умещается в один экран, плашки стоят 2×2 у самого
   низа золотого фона, а тап по плашке открывает полноэкранный drawer вместо
   раскрытия на месте. Десктоп (≥761px) этими правилами не затронут.        */
@media (max-width: 760px) {
    .lx2-sec { padding: 64px 0; }
    .lx2-hub-list { grid-template-columns: 1fr; }
    .lx2-cta .lx2-btn { width: 100%; }
    .lx2-cta { gap: 10px; margin-bottom: 8px; }
    .lx2-cta .lx2-btn { padding: 11px 20px; }
    .lx2-cta-note { font-size: 12px; line-height: 1.3; }
    .lx2-lead { font-size: 15px; line-height: 1.45; margin-bottom: 12px; }
    /* В1: min-height:auto снимает растягивание до 100svh. При flex-center
       остаток высоты уходил бы поровну вверх и вниз, а плашки должны стоять
       у самого низа фона (замечание 2: «плашки — это конец»). Отступы
       теперь целиком считает .lx2-hero-inner, дубль 44/40 у hero убран. */
    .lx2-hero { min-height: auto; align-items: flex-start; padding: 0; }
    .lx2-hero-inner { padding: 78px 16px 20px; }
    .lx2-pill-badge { padding: 4px 10px; font-size: 11px; }
    .lx2-h1 { margin: 10px 0 10px; }
    /* В1.1: 4 плашки в 2×2 — 2 строки вместо 4 (≈346px → ≈190px). Отступы таба,
       иконки и кегли ужаты: в колонке ~166px «AI-Разработчик» с hint'ом иначе
       переносился бы в 4 строки и ломал ровную сетку (критерий 4 — ≤2 строки).
       display:contents у .lx2-pill-titles кладёт <b> и подпись в разные строки
       грида: подпись получает всю ширину таба, а не остаток после иконки, и
       таб не растёт в высоту. Шеврон спрятан — на мобильном таб открывает
       drawer на весь экран, а не раскрывает тело, и стрелка «вниз» врала бы. */
    .lx2-pills-bar { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .lx2-pill-tab {
        display: grid; grid-template-columns: 36px minmax(0, 1fr);
        column-gap: 8px; row-gap: 3px; padding: 10px; gap: 0;
    }
    .lx2-pill-ico { width: 36px; height: 36px; border-radius: 10px; grid-column: 1; grid-row: 1 / span 2; }
    .lx2-pill-ico svg { width: 20px; height: 20px; }
    .lx2-pill-titles { display: contents; }
    .lx2-pill-titles b { grid-column: 2; grid-row: 1; font-size: 14px; }
    .lx2-pill-titles span { grid-column: 2; grid-row: 2; margin-top: 0; font-size: 11px; line-height: 1.3; }
    .lx2-pill-chev { display: none; }
    .lx2-hero-pills { margin-top: 12px; }
    /* В1.4: пустоты под плашками внутри hero больше нет. Минус-отступ бара съедает
       нижний padding .lx2-hero-inner (20px), поэтому barBottom == heroBottom
       (критерий 3), а сами 20px остаются золотым свечением под плашками.
       Статичный бар и без подложки — из правки 2: на мобильном липкий ряд
       перекрывал бы пол-экрана, переключение и так в шаге от .is-open таба. */
    .lx2-pills-bar {
        position: static; margin: 0 -16px -20px; padding: 0 16px 20px;
        background: none; -webkit-backdrop-filter: none; backdrop-filter: none;
        border-bottom: 0; box-shadow: none;
    }
    /* Этап 1B, решение заказчика: резерв под панель на мобильном УБРАН.
       Причина: 4 плашки в столбец (≈380px) + резерв 444px = 824px при экране
       667px — две трети пустого золота под свёрнутыми плашками. На 1920 и 768
       все 4 тела равны 291px, то есть там резерв и так был no-op. Этап 1C
       убрал и сам столбец (2×2), но правило остаётся: на мобильном тела
       закрыты и открывает их drawer, резервировать под них нечего. */
    .lx2-pill-bodies { min-height: 0; }
    /* Скрин под текстом, вертикальный стек (ТЗ: «на <1100px») */
    .lx2-pill-body-in { grid-template-columns: 1fr; gap: 18px; }

    /* ── В2: полноэкранный drawer плашки hero ────────────────────────────
       Узел лежит в разметке один раз (welcome.blade.php), наполняется
       переносом существующих .lx2-pill-shot / .lx2-pill-copy активной
       плашки — контент в DOM не дублируется. На десктопе всё это скрыто
       правилом .lx2-drawer { display: none } выше.                        */
    .lx2-drawer {
        display: block;
        position: fixed; inset: 0; z-index: 200;   /* выше шапки NAV.nav (100) */
        background: var(--paper);
        opacity: 0; transform: translateY(18px);
        transition: opacity .26s ease, transform .26s cubic-bezier(.22,1,.36,1);
    }
    .lx2-drawer[hidden] { display: none; }
    .lx2-drawer.is-open { opacity: 1; transform: none; }
    /* prefers-reduced-motion: открытие/закрытие мгновенно (флаг из JS) */
    .lx2-drawer.is-instant { transition: none; }
    .lx2-drawer-backdrop { position: absolute; inset: 0; z-index: 0; }
    .lx2-drawer-close {
        position: absolute; z-index: 2;
        top: calc(8px + env(safe-area-inset-top)); right: 10px;
        width: 44px; height: 44px; border-radius: 50%;   /* минимальная зона нажатия */
        border: 1px solid var(--line); background: var(--paper);
        color: var(--ink); font-size: 17px; line-height: 1; cursor: pointer;
    }
    .lx2-drawer-close:focus-visible { outline: 3px solid var(--gold); outline-offset: 2px; }
    .lx2-drawer-scroll {
        position: relative; z-index: 1; height: 100%;
        overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
        padding: calc(66px + env(safe-area-inset-top)) 16px calc(28px + env(safe-area-inset-bottom));
    }
    /* Порядок: крестик → заголовок → скрин → текст → буллиты (критерий 6) */
    .lx2-drawer-title {
        margin: 0 0 14px; font-size: 21px; line-height: 1.2; font-weight: 800;
        letter-spacing: -.02em; color: var(--ink);
    }
    .lx2-drawer-shot { margin: 0 0 16px; }
    .lx2-drawer-copy p { font-size: 15px; line-height: 1.55; color: var(--slate); margin: 0 0 14px; }
    .lx2-drawer-copy .lx2-pill-list li { font-size: 14px; }
    /* Г1: заголовок карточки в drawer'е не нужен — он уже есть шапкой диалога
       (.lx2-drawer-title, ею же подписан aria-labelledby). Прячем только h3,
       иконка и золотая надпись-надзаголовок остаются: они не дублируют
       заголовок, а держат ритм карточки. */
    .lx2-drawer-copy .lx2-pill-head { margin-bottom: 10px; }
    .lx2-drawer-copy .lx2-pill-title { display: none; }
    /* Д3 (исправление регрессии этапа 1D): на мобильном тело на месте не
       раскрывается, поэтому целевого состояния .lx2-pill-body.is-open
       не бывает НИКОГДА — а стартовые opacity:0/transform из блока Г3
       (шапка, описание, буллиты) остаются на перенесённых в drawer узлах
       навсегда. Замерено на 375×667: описание и все буллиты opacity:0,
       скрин виден (у него отдельный контекст), текста в drawer нет.
       Поэтому внутри drawer содержимое принудительно в финальном виде —
       каскад появления там и не нужен, открытие анимирует сам .lx2-drawer. */
    .lx2-drawer .lx2-pill-shot,
    .lx2-drawer .lx2-pill-head,
    .lx2-drawer .lx2-pill-copy > p,
    .lx2-drawer .lx2-pill-list li {
        opacity: 1; transform: none;
    }
}

/* ═══ ДОСТУПНОСТЬ: отключаем движение ═══ */
@media (prefers-reduced-motion: reduce) {
    .landing *, .landing *::before, .landing *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    .rv { opacity: 1; transform: none; }
    .lx2-wire { stroke-dashoffset: 0; }
    /* Панель хаба: переходы и анимации снимаются целиком. Глобальное правило
       выше обнуляет только duration — WAAPI-анимации панели (их длительность
       задаёт JS) оно не трогает, поэтому дублируем флаг reduceMotion в JS
       и явно глушим CSS-часть здесь. */
    .lx2-vp-card, .lx2-vp-copy, .lx2-vp-shot, .lx2-node,
    .lx2-wire, .lx2-wire-ring, .lx2-core, .lx2-vortex {
        transition: none !important; animation: none !important;
    }
    /* Канвы рисуют один статичный кадр (JS тоже не крутит rAF) */
    .lx2-pill-tab, .lx2-pill-chev, .lx2-pill-badge i { animation: none !important; transition: none !important; }
    .lx2-pills-bar, .lx2-pill-tab { opacity: 1; transform: none; }
    /* Г3/Д3: содержимое карточки видно сразу, без каскада. Стартовые opacity:0
       из блока Г3 иначе оставили бы текст невидимым до .is-open, а задержки
       таблицы при нулевых duration всё равно держали бы кадр пустым.
       Список классов расширен на Д3: заголовок, надпись-надзаголовок, сама
       колонка текста и буллиты (в т.ч. перенесённые в мобильный drawer —
       правило работает и там, потому что классы те же). */
    .lx2-pill-body > .lx2-pill-body-in,
    .lx2-pill-copy, .lx2-pill-head,
    .lx2-pill-eyebrow, .lx2-pill-title,
    .lx2-pill-copy > p, .lx2-pill-list li, .lx2-pill-shot {
        opacity: 1 !important; transform: none !important;
        transition: none !important; animation: none !important;
    }
}

