/* ==========================================================================
   VOIR AI — premium.css  (Premium Visual Upgrade, 31.10.2026)
   --------------------------------------------------------------------------
   АДДИТИВНЫЙ слой поверх design-system.css и стилей страниц. Ничего не
   ломает: только усиливает существующие компоненты (панели, кнопки, карточки
   отделов, тарифы, hero). Все эффекты:
     - уважают prefers-reduced-motion (глобальный guard в конце файла);
     - отключаются на coarse-pointer / узких экранах, где тяжёлые;
     - не создают горизонтального переполнения (слои inset:0 + background,
       без вылезающих rect);
     - композиторные (transform/opacity/background-position), без layout-thrash.
   Тёмная премиальная эстетика сохранена (ink-800/900 + amber-акцент).
   ========================================================================== */

/* --------------------------------------------------------------------------
   0a. CLS-фикс: резерв высоты под шапку. i18n.js собирает [data-header] в
       рантайме, поэтому при первой отрисовке хост пустой (0px), а после
       вставки .site-header весь контент сдвигается вниз на 68px — крупнейший
       одиночный layout-shift на всех страницах (замер 0.0531 из 0.0715 CLS
       ещё ДО визуального апгрейда). Резервируем высоту хоста токеном
       дизайн-системы — сдвиг исчезает, sticky-поведение шапки не меняется.
   -------------------------------------------------------------------------- */
[data-header] { min-block-size: var(--header-h, 4.25rem); }

/* --------------------------------------------------------------------------
   0. Токены премиум-слоя (локальные, не трогают глобальные)
   -------------------------------------------------------------------------- */
:root {
  --px-glow-soft: 0 0 0 1px rgb(245 176 62 / 0.14), 0 18px 60px -30px rgb(245 176 62 / 0.5);
  --px-edge: linear-gradient(140deg, rgb(255 220 163 / 0.5), rgb(245 176 62 / 0.05) 38%, rgb(51 64 107 / 0.12) 70%, rgb(245 176 62 / 0.35));
  --px-sheen: linear-gradient(110deg, transparent 20%, rgb(255 255 255 / 0.22) 42%, rgb(255 220 163 / 0.28) 50%, transparent 72%);
  --px-scan: linear-gradient(180deg, transparent, rgb(245 176 62 / 0.1), transparent);
  --px-dur: 0.6s;
}

/* --------------------------------------------------------------------------
   1. Курсорный ambient-ореол (только десктоп, тонкий указатель).
      Один фиксированный radial-слой; координаты пишет premium.js в --cx/--cy.
      pointer-events:none, z-index поверх фона но под контентом не мешает.
   -------------------------------------------------------------------------- */
.px-cursor-glow {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
  background: radial-gradient(
    420px circle at var(--cx, 50%) var(--cy, 50%),
    rgb(245 176 62 / 0.07),
    rgb(245 176 62 / 0.03) 32%,
    transparent 62%
  );
  mix-blend-mode: screen;
  will-change: background-position;
}
.px-cursor-glow.is-live { opacity: 1; }

/* --------------------------------------------------------------------------
   2. Прогресс-рельс чтения (тонкая янтарная линия вверху). Композиторная
      ширина через transform: scaleX — без layout.
   -------------------------------------------------------------------------- */
.px-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 60;
  pointer-events: none;
  background: linear-gradient(90deg, var(--accent-lo), var(--accent-hi));
  transform: scaleX(var(--px-progress, 0));
  transform-origin: 0 50%;
  box-shadow: 0 0 12px rgb(245 176 62 / 0.5);
  opacity: 0.9;
}

/* --------------------------------------------------------------------------
   3. Анимированная градиентная рамка панелей/карточек.
      Рамка рисуется слоем padding-box/border-box через background-clip;
      вращение — через background-position (композитор), без mask-трюков,
      которые режут контент. Активируется у .panel/.tier/.dept при hover ИЛИ
      когда premium.js ставит .px-edge-live (для ключевых блоков).
   -------------------------------------------------------------------------- */
.panel,
.tier,
.dept,
.os-core__layer,
.ceo-hero__card,
.cta-final {
  position: relative;
}

/* Тонкая «живая» кромка поверх существующей границы — только усиление */
.px-edge-anim::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: var(--px-edge);
  background-size: 300% 300%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.45s var(--ease-out, ease);
  pointer-events: none;
  z-index: 1;
}
.px-edge-anim:hover::before,
.px-edge-anim:focus-within::before,
.px-edge-anim.is-active::before {
  opacity: 1;
  animation: px-edge-flow 6s linear infinite;
}
@keyframes px-edge-flow {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* --------------------------------------------------------------------------
   4. Sheen-пробег по primary-кнопке при hover (усиление магнитной кнопки).
      .btn не использует ::after — слой свободен.
   -------------------------------------------------------------------------- */
.btn--primary { overflow: hidden; }
.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--px-sheen);
  background-size: 260% 100%;
  background-position: 180% 0;
  opacity: 0;
  pointer-events: none;
  border-radius: inherit;
}
.btn--primary:hover::after,
.btn--primary:focus-visible::after {
  opacity: 1;
  animation: px-sheen-run 0.9s var(--ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1)) forwards;
}
@keyframes px-sheen-run {
  from { background-position: 180% 0; }
  to { background-position: -60% 0; }
}

/* --------------------------------------------------------------------------
   5. Кинетический акцент H1: медленное «дыхание» янтарного слова + мягкое
      свечение. Только для .hero__title-accent / .os-hero__accent /
      .ceo-hero__accent — акцентные спаны заголовков.
   -------------------------------------------------------------------------- */
.hero__title-accent,
.os-hero__accent,
.ceo-hero__accent,
.led-hero__accent {
  position: relative;
  /* БЕЗ display:inline-block — акцент остаётся inline-фрагментом строки,
     иначе весь спан становится неразрывным и H1 рвётся на 3 строки. */
}
.px-kinetic-accent {
  animation: px-accent-breathe 6s ease-in-out infinite;
}
/* Свечение мягкое, не «неоновое»: только на пике цикла и низкой плотностью */
@keyframes px-accent-breathe {
  0%, 100% { text-shadow: 0 0 0 rgb(245 176 62 / 0); }
  50% { text-shadow: 0 0 18px rgb(245 176 62 / 0.18); }
}

/* --------------------------------------------------------------------------
   Переносы в hero-заголовках (лечит известный дефект «операци/онная»).
   Автор разбивает H1 вручную на .line-строки, но самая длинная строка
   («Одна AI-операционная» ≈909px) шире своей колонки (587px при 1280).
   Базовый overflow-wrap:anywhere (design-system.css:281) из-за этого рвёт
   длинное слово ПОСЕРЕДИНЕ без дефиса. Полный запрет переноса (overflow-wrap:
   normal) обрезал бы строку — потеря контента, ещё хуже.
   Решение: разрешить перенос, но включить ЯЗЫКОВУЮ расстановку дефисов
   (hyphens:auto) — браузер ставит дефис на границе слога («опера-ционная»)
   вместо голого разрыва. html[lang] на страницах задан, Chromium знает
   русские и английские правила переноса.
   -------------------------------------------------------------------------- */
.hero h1, .os-hero h1, .ceo-hero h1, .led-hero h1 {
  hyphens: auto;
  -webkit-hyphens: auto;
}
.hero h1 .line, .os-hero h1 .line, .ceo-hero h1 .line, .led-hero h1 .line {
  overflow-wrap: break-word;
  /* БЕЗ text-wrap:balance — балансировка форсит перенос строки, которая
     помещается целиком, и гейт hero-line-mask («1 маска = 1 строка») падает.
     Автор разбивает H1 на строки ВРУЧНУЮ: каждая .line обязана остаться
     одной визуальной строкой. */
}
/* Зазор до карточки схемы обеспечен сеткой hero (колонка копии 629px,
   схема начинается с 682px) — padding не нужен, он только сужал строку. */

/* --------------------------------------------------------------------------
   CLS-фикс №2: ch-ширины lead/thesis-абзацев hero. Единица ch = ширине «0»
   ТЕКУЩЕГО шрифта, поэтому до swap'а абзац уже (fallback), после — шире
   (Golos Text) → reflow и сдвиг карточки-«ядра» (замер ai-os: 0.05–0.135).
   Фиксируем ширину в em по замеру РЕАЛЬНОГО Golos: 52ch = 32.24em при
   fs 21.1px (.hero__lead/.os-hero__lead/.ceo-hero__lead/.led-hero__lead),
   thesis 52ch = 32.225em при 17.3px. em от шрифта не зависит → ширина
   одинакова до и после swap, reflow исчезает. Визуально идентично
   (та же ширина той же строки тем же шрифтом).
   -------------------------------------------------------------------------- */
/* ch:em для Golos Text ≈ 0.62 (замер: 52ch = 32.24em при fs 21.1px,
   46ch = 28.52em; отношение не зависит от кегля — только от гарнитуры). */
.hero__lead { max-inline-size: 28.52em; }        /* было 46ch */
.os-hero__lead,
.ceo-hero__lead,
.led-hero__lead { max-inline-size: 32.24em; }    /* было 52ch */
.os-hero__thesis { max-inline-size: 32.23em; }   /* было 52ch */
.hero__actions,
.os-hero__status,
.ceo-hero__status { max-inline-size: 32.24em; }  /* было 52ch */

/* --------------------------------------------------------------------------
   H1 в первом экране + CTA-in-fold (P1 из live-QA 31.10).
   Базовый --step-7 (99.2px при 1280) не помещает АВТОРСКИЕ строки H1 в
   колонку копии (587px): «Одна AI-операционная» = 909px → строка ломается,
   заголовок занимает 6 экранных строк (631px) и выдавливает CTA ниже сгиба
   (btn--primary bottom=1159 при вьюпорте 800).
   Решение — флюидный кегль, при котором авторская строка помещается ЦЕЛИКОМ
   (без переносов вообще), + чуть более широкая колонка копии на desktop.
   Контент, разметка и SEO не меняются — только типографика (визуальный слой).
   -------------------------------------------------------------------------- */
@media (min-width: 56.25rem) {
  .hero__inner { grid-template-columns: minmax(0, 1.18fr) minmax(0, 1fr); }
}
/* ВСЕ hero: кегль H1 через КОНТЕЙНЕРНУЮ единицу (тот же приём, что на главной).
   Причина — CLS: vw-кегель подбирался под РЕАЛЬНЫЙ Unbounded, но первая
   отрисовка идёт fallback-шрифтом, который УЖЕ на ~27% (замер: width 1727
   против 2204 на том же тексте). Строка, помещавшаяся fallback'ом, после
   swap не помещается Unbounded → перенос → сдвиг всего экрана (0.07–0.27
   CLS на ai-os/ai-ceo). cqw-кегель привязан к ширине колонки и калиброван
   ПО METRIKAM REАЛЬНОГО ШРИФТА (замеры longest@100px: ai-os en 1489 →
   ≤6.72cqw, ai-ceo en 1232 → ≤8.12cqw, pricing en 1019 → ≤9.81cqw; берём
   с запасом 3–5%), поэтому строка помещается и fallback'ом, и Unbounded —
   swap проходит без изменения числа строк.

   Главная: кегль H1 через КОНТЕЙНЕРНУЮ единицу — пропорционален реальной
   ширине колонки копии, поэтому авторская строка «Одна AI-операционная»
   помещается ЦЕЛИКОМ (ровно 1 визуальная строка в маске) на ЛЮБОМ вьюпорте:
   629px@1280 → 50px, 343px@375 → 27px. Без переносов вообще → гейты
   hero-line-mask и word-break проходят честно, а не через hyphens-компромисс.
   8cqw подобрано замером: естественная ширина строки ≈ 12.07 × fs. */
@supports (container-type: inline-size) {
  .hero__copy, .os-hero__copy, .ceo-hero__copy, .led-hero__copy { container-type: inline-size; }
  .os-hero h1 { font-size: clamp(1.4rem, 6.5cqw, 4.4rem); max-inline-size: none; }
  .ceo-hero h1 { font-size: clamp(1.4rem, 7.8cqw, 4.4rem); max-inline-size: none; }
  .led-hero h1 { font-size: clamp(1.5rem, 9.4cqw, 4.6rem); max-inline-size: none; }
  /* Кегль = доля ширины колонки, поэтому АВТОРСКАЯ строка помещается в одну
     визуальную строку на любом вьюпорте (гейт hero-line-mask = 1 маска/1 строка).
     Замеры: RU «Одна AI-операционная» = 14.26×fs, EN «Your entire business.» =
     12.29×fs → порог 7.0cqw / 8.14cqw. Берём 6.8 / 7.9cqw (запас ~3%),
     чтобы строка точно не переносилась. Раздельно по lang: RU-строка длиннее. */
  .hero h1 { font-size: clamp(1.4rem, 6.8cqw, 3.4rem); max-inline-size: none; }
  :lang(en) .hero h1 { font-size: clamp(1.4rem, 7.9cqw, 3.9rem); }
}
@supports not (container-type: inline-size) {
  /* graceful fallback (браузеры до 2022): флюидный кегль + hyphens:auto —
     строка может перенестись по слогам, но не порвётся посреди слова */
  @media (min-width: 56.25rem) {
    .os-hero h1, .ceo-hero h1, .led-hero h1 { font-size: clamp(3rem, 1.55rem + 3.1vw, 4.4rem); }
  }
  @media (max-width: 56.24rem) {
    .os-hero h1, .ceo-hero h1, .led-hero h1 { font-size: clamp(2rem, 1.1rem + 4vw, 3rem); max-inline-size: none; }
  }
  @media (min-width: 56.25rem) {
    .hero h1 { font-size: clamp(2.7rem, 1.45rem + 2.55vw, 3.9rem); }
  }
  @media (max-width: 56.24rem) {
    .hero h1 { font-size: clamp(2rem, 1.1rem + 4vw, 3rem); }
  }
}
/* (кейфреймы px-accent-breathe определены выше, в секции кинетического
   акцента — мягкое свечение без неона) */

/* --------------------------------------------------------------------------
   6. Scanline-развёртка для «приборных» блоков (AI OS core, AI CEO card).
      Тонкая световая полоса проходит сверху вниз по контейнеру.
   -------------------------------------------------------------------------- */
.px-scanline { position: relative; overflow: hidden; }
.px-scanline::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 42%;
  top: -45%;
  background: var(--px-scan);
  pointer-events: none;
  opacity: 0.55;
  animation: px-scan-move 7s linear infinite;
  z-index: 0;
}
@keyframes px-scan-move {
  0% { transform: translateY(0); opacity: 0; }
  12% { opacity: 0.55; }
  88% { opacity: 0.55; }
  100% { transform: translateY(320%); opacity: 0; }
}
/* Контент блока должен быть поверх scan-слоя */
.px-scanline > * { position: relative; z-index: 1; }

/* --------------------------------------------------------------------------
   7. HUD-уголки командного пункта (AI CEO). Четыре уголка рисуются
      background-градиентами одного слоя — без лишних rect.
   -------------------------------------------------------------------------- */
.px-hud { position: relative; }
.px-hud::before {
  content: '';
  position: absolute;
  inset: 8px;
  pointer-events: none;
  z-index: 1;
  background:
    linear-gradient(var(--accent), var(--accent)) left top / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) left top / 2px 16px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right top / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right top / 2px 16px no-repeat,
    linear-gradient(var(--accent), var(--accent)) left bottom / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) left bottom / 2px 16px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right bottom / 16px 2px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right bottom / 2px 16px no-repeat;
  opacity: 0.7;
  transition: opacity 0.4s ease;
}
.px-hud:hover::before, .px-hud:focus-within::before { opacity: 0.7; }

/* --------------------------------------------------------------------------
   8. Radar-sweep для колец AI CEO hero (.ceo-hero__rings уже существует).
      Вращающийся конус света поверх колец — композиторный transform.
   -------------------------------------------------------------------------- */
.ceo-hero__rings { position: relative; }
.px-radar {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* -1: над rings(-2) и, т.к. DOM-позиция ПОСЛЕ glow(-1), над световым
     пятном — но под контентом (контент в потоке рисуется выше negative-z). */
  z-index: -1;
  background:
    radial-gradient(circle at 82% 18%, transparent 0 74px, rgb(245 176 62 / 0.3) 74px 76px, transparent 75px 148px, rgb(245 176 62 / 0.22) 148px 150px, transparent 149px 236px, rgb(245 176 62 / 0.16) 236px 238px, transparent 237px),
    conic-gradient(from 0deg at 82% 18%, transparent 0deg, rgb(245 176 62 / 0.22) 22deg, rgb(245 176 62 / 0.06) 44deg, transparent 70deg);
  transform-origin: 82% 18%;
  animation: px-radar-spin 9s linear infinite;
}
/* origin в центре колец (82% 18%): концентрические кольца rotationally-
   симметричны вокруг этой точки, поэтому при вращении стоят на месте,
   а конус-развёртка крутится вокруг своей вершины — как локатор. */
@keyframes px-radar-spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
   9. Pricing: bento-glow под карточкой тарифа + «подъём» при hover.
      Усиливает существующий tilt; glow — отдельный слой под карточкой.
   -------------------------------------------------------------------------- */
.tier { transition: transform 0.4s var(--ease-out, ease), box-shadow 0.4s var(--ease-out, ease), border-color 0.4s ease; }
.tier::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(60% 80% at 50% 0%, rgb(245 176 62 / 0.08), transparent 70%);
  opacity: 0;
  transition: opacity 0.45s ease;
}
.tier:hover::after, .tier--featured::after, .tier.is-featured::after, .tier:focus-within::after { opacity: 1; }
.tier:hover, .tier:focus-within { box-shadow: var(--px-glow-soft); }
.tier > * { position: relative; z-index: 1; }

/* «Рекомендуемый» тариф подсвечивается пульсирующей кромкой.
   Фактический класс на странице — .tier--featured (ru/pricing.html:493). */
.tier--featured,
.tier.is-featured,
.tier[data-featured='true'] { border-color: rgb(245 176 62 / 0.45); }
.tier--featured { box-shadow: var(--px-glow-soft); }

/* Динамическая типографика цифры цены: мягкое появление + tabular-nums */
.tier__amount {
  font-variant-numeric: tabular-nums;
  transition: color 0.3s ease, text-shadow 0.3s ease;
}
.tier:hover .tier__amount { text-shadow: 0 0 22px rgb(245 176 62 / 0.3); }

/* --------------------------------------------------------------------------
   10. (УДАЛЕНО) Reveal секций — дублировал VoirFX scrollReveal и давал риск
       невидимого контента (opacity:0 при позднем IO). Mask/reveal-переходы
       секций обеспечивает scrollReveal/lineMaskReveal из animations.js.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   11. Ambient-сеть (canvas) — хост для AI OS hero. Сам canvas рисуется
       премиум-JS; хост inset:0, z-index ниже контента, без rect-переполнения.
   -------------------------------------------------------------------------- */
.px-net-host {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.px-net-host canvas { display: block; width: 100%; height: 100%; }

/* --------------------------------------------------------------------------
   12. Живой статус-тик (real-time feel) для приборных строк hero.
       Точка-индикатор мягко пульсирует (существующие ::before усилены).
   -------------------------------------------------------------------------- */
/* Пульсирует ТОЛЬКО точка-индикатор (::before), не весь статус-пункт —
   иначе scale() всего элемента наезжает на соседние пункты. */
.px-live-dot::before { animation: px-live-pulse 2.4s ease-in-out infinite; transform-origin: center; }
@keyframes px-live-pulse {
  0%, 100% { opacity: 0.5; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1.3); }
}

/* --------------------------------------------------------------------------
   13. 404 / корень: минимальная полировка — медленный дрейф фона, без
       тяжёлых эффектов. Селекторы целевые (не требуют JS): фон секций 404
       и экрана выбора языка получает мягкое янтарное свечение, цифра 404 —
       редкое «дыхание» (только когда motion разрешён).
   -------------------------------------------------------------------------- */
.px-ambient-drift {
  background-size: 200% 200%;
  animation: px-drift 22s ease-in-out infinite;
}
@keyframes px-drift {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

/* Ambient-свечение рисуется background-слоями САМИХ блоков (без ::before с
   отрицательным inset — такой слой создавал бы rect за пределами вьюпорта и
   горизонтальное переполнение; ср. комментарий gradientMesh в home.css). */
.lang-pick,
.section:has(.notfound) {
  /* Свечение — на ПОЛНУЮ ширину родительской секции, а не на узком блоке
     .notfound (shell--narrow): прямоугольная кромка узкого блока читалась
     как «шов/заплатка». .lang-pick сам полноширинный (100dvh), ему ок.
     :has() — Chromium 105+/Safari 15.4+/FF 121+; без поддержки просто
     нет свечения (graceful). */
  background-image:
    radial-gradient(46% 40% at 50% 36%, rgb(245 176 62 / 0.055), transparent 72%),
    radial-gradient(36% 32% at 24% 76%, rgb(51 64 107 / 0.12), transparent 72%),
    radial-gradient(36% 32% at 76% 76%, rgb(51 64 107 / 0.09), transparent 72%);
  background-size: 200% 200%;
  background-repeat: no-repeat;
  animation: px-drift 26s ease-in-out infinite;
}
.notfound__code { animation: px-404-glow 7s ease-in-out infinite; }
@keyframes px-404-glow {
  0%, 100% { filter: drop-shadow(0 0 0 rgb(245 176 62 / 0)); }
  50% { filter: drop-shadow(0 0 18px rgb(245 176 62 / 0.28)); }
}
@media (prefers-reduced-motion: reduce) {
  .notfound__code { animation: none; }
}

/* --------------------------------------------------------------------------
   14. AI OS — «живая архитектура системы».
       14a. Scroll-позвоночник разреза: вертикальная линия сквозь три страты
            (Control → Agentic → Execution) заполняется янтарем по мере
            скролла; узлы-точки загораются, когда слой входит во вьюпорт.
       14b. Граф «AI CEO → 8 отделов» (SVG): scroll-triggered СБОРКА —
            лучи прорисовываются по очереди (stroke-dashoffset), узлы
            всплывают, затем по связям идут пакеты-задачи. Hover карточки
            отдела подсвечивает его луч и узел.
   -------------------------------------------------------------------------- */
.os-strata { position: relative; }
.px-spine {
  position: absolute;
  left: -0.875rem;
  top: 0.5rem;
  bottom: 0.5rem;
  width: 2px;
  pointer-events: none;
  z-index: 2;
  background: linear-gradient(180deg, rgb(51 64 107 / 0.35), rgb(51 64 107 / 0.35));
}
.px-spine__fill {
  position: absolute;
  inset: 0;
  transform: scaleY(var(--px-spine, 0));
  transform-origin: 50% 0%;
  background: linear-gradient(180deg, var(--accent-hi), var(--accent-lo));
  box-shadow: 0 0 10px rgb(245 176 62 / 0.45);
}
.px-spine__node {
  position: absolute;
  left: 50%;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--ink-600);
  border: 1px solid var(--ink-400);
  transition: background 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease;
}
.px-spine__node.is-lit {
  background: var(--accent);
  border-color: var(--accent-hi);
  box-shadow: 0 0 14px rgb(245 176 62 / 0.6);
}
@media (max-width: 79.99rem) { .px-spine { display: none; } }

/* --- 14b. Граф отделов --- */
/* Обёртка на всю ширину контейнера; высота — кламп. SVG c preserveAspectRatio
   «meet» сам центрирует граф по горизонтали. (Раньше aspect-ratio вместе с
   max-block-size сжимал ширину до ~746px и прижимал граф к левому краю.) */
/* Слот резервирует ТОТ ЖЕ бокс, что и заполненный граф — zero CLS при
   вставке SVG после paint. Пустой слот (без JS / до загрузки premium.js)
   выглядит как отступ между заголовком секции и карточками отделов. */
.px-graph-slot,
.px-graph-wrap {
  position: relative;
  inline-size: 100%;
  margin-block-end: var(--sp-xl, 2.5rem);
  block-size: clamp(260px, 36vh, 420px);
}
.px-graph { inline-size: 100%; block-size: 100%; display: block; }
.px-graph .px-edge {
  stroke: rgb(140 152 178 / 0.5);
  stroke-width: 1.8;
  stroke-dasharray: var(--len, 400);
  stroke-dashoffset: var(--len, 400);
  transition: stroke 0.3s ease, stroke-width 0.3s ease;
}
.px-graph.is-assembled .px-edge {
  animation: px-edge-draw 0.8s var(--ease-out, ease) forwards;
  animation-delay: var(--d, 0ms);
}
@keyframes px-edge-draw { to { stroke-dashoffset: 0; } }
.px-graph .px-node {
  fill: var(--ink-750, #0d1220);
  stroke: rgb(150 163 190 / 0.75);
  stroke-width: 1.8;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0.4);
  transition: fill 0.3s ease, stroke 0.3s ease, filter 0.3s ease;
}
.px-graph .px-node-label {
  fill: var(--light-200, #dfe6f2);
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-anchor: middle;
  dominant-baseline: middle;
  opacity: 0;
  transition: fill 0.3s ease;
}
.px-graph.is-assembled .px-node,
.px-graph.is-assembled .px-node-label {
  animation: px-node-in 0.5s var(--ease-out, cubic-bezier(0.16, 1, 0.3, 1)) forwards;
  animation-delay: var(--d, 0ms);
}
@keyframes px-node-in { to { opacity: 1; transform: scale(1); } }
.px-graph .px-hub {
  fill: #10162a;
  stroke: var(--accent);
  stroke-width: 2;
  filter: drop-shadow(0 0 18px rgb(245 176 62 / 0.35));
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: none;
}
.px-graph.is-assembled .px-hub {
  animation: px-node-in 0.6s var(--ease-out, cubic-bezier(0.16, 1, 0.3, 1)) forwards;
}
.px-graph .px-hub-label {
  fill: var(--accent-hi);
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-anchor: middle;
  dominant-baseline: middle;
  opacity: 0;
}
.px-graph.is-assembled .px-hub-label {
  animation: px-fade-in 0.6s ease 0.5s forwards;
}
@keyframes px-fade-in { to { opacity: 1; } }
/* подсветка луча при hover карточки отдела */
.px-graph .px-g.is-hot .px-edge { stroke: var(--accent); stroke-width: 2; }
.px-graph .px-g.is-hot .px-node {
  fill: rgb(245 176 62 / 0.25);
  stroke: var(--accent-hi);
  filter: drop-shadow(0 0 8px rgb(245 176 62 / 0.55));
}
.px-graph .px-g.is-hot .px-node-label { fill: var(--accent-hi); }
.px-graph .px-packet { fill: var(--accent-hi); opacity: 0; }
.px-graph.is-live .px-packet { opacity: 1; }

/* --------------------------------------------------------------------------
   15. AI CEO — живой контур управления: подсветка активного узла цикла
       (состояние, не движение: янтарная кромка + мягкий glow + метка).
   -------------------------------------------------------------------------- */
.ceo-loop__node {
  transition: border-color 0.5s ease, box-shadow 0.5s ease, transform 0.5s var(--ease-out, ease);
}
.ceo-loop__node.px-cycle-live {
  border-color: rgb(245 176 62 / 0.55);
  box-shadow: 0 0 0 1px rgb(245 176 62 / 0.22), 0 22px 60px -34px rgb(245 176 62 / 0.55);
  transform: translate3d(0, -2px, 0);
}
/* Бегущий огонёк по нижней кромке активного узла: длительность = шагу цикла
   (2s), поэтому видно, что контур ЖИВОЙ, а не статичная рамка. Композиторно
   (transform: scaleX), без layout. */
.ceo-loop__node.px-cycle-live::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  border-radius: inherit;
  background: linear-gradient(90deg, transparent, var(--accent-hi), var(--accent), transparent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  animation: px-cycle-run 2s linear;
  pointer-events: none;
  z-index: 2;
}
@keyframes px-cycle-run { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* Ритм сетки: название этапа в 2 строки не должно ломать базовые линии
   карточек 4/5/6 — резервируем высоту под подпись этапа. */
.ceo-loop__name { min-block-size: 2em; }

/* Моно-текст (verb-подписи, плашка цикла) — контраст выше на ~12% */
.ceo-loop__verb { color: var(--light-300, #b9c4d9); }
.ceo-loop__node.px-cycle-live .ceo-loop__idx {
  background: var(--accent);
  color: var(--accent-contrast);
  border-color: var(--accent);
  box-shadow: 0 0 16px rgb(245 176 62 / 0.5);
}
.ceo-loop__idx { transition: background 0.45s ease, color 0.45s ease, border-color 0.45s ease, box-shadow 0.45s ease; }

/* --------------------------------------------------------------------------
   16. Pricing — bento-композиция, пересчёт VU/MC, анимированный градиент.
       16a. Bento: 6 плиток (5 тарифов + пополнение) на широких экранах
            раскладываются 3×2; рекомендуемый тариф приподнят и светится.
       16b. px-value-flash: короткая янтарная вспышка значения при пересчёте
            калькулятора (600ms, один раз на изменение — не постоянное
            движение).
       16c. px-plans-veil: медленный анимированный градиент под секцией
            тарифов (один inset:0-слой, background-position — композитор).
   -------------------------------------------------------------------------- */
/* Bento 3×2 — только от 88rem (1408px): при 1280px три колонки слишком
   узки (бейдж «Команды» переносится и ломает базовые линии цен).
   Lift рекомендуемого тарифа — через margin, т.к. tiltCard пишет
   transform инлайном (inline всегда побеждает CSS). */
@media (min-width: 88rem) {
  .tiers {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: stretch;
  }
  .tier { display: flex; flex-direction: column; }
  .tier__foot { margin-block-start: auto; }
  /* Bento-колонка ~437px: базовый 3-колоночный .pack (12rem+10rem+1fr)
     схлопывает колонку примечания в 0px → вертикальный текст. Перекладываем:
     имя + цена в одну строку, примечание — на всю ширину ниже. */
  #topup .pack {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 0.15rem;
  }
  #topup .pack__note { grid-column: 1 / -1; }
  #topup .pack__price { white-space: nowrap; }
  /* Featured НЕ поднимаем margin'ом — это ломало базовую линию подвала
     (subgrid выравнивает ряды, а -6px уводил foot на 6px вверх). Вместо
     подъёма — tint-фон + усиленное янтарное свечение: карточка читается
     как рекомендуемая, не ломая выравнивание. */
}
/* Рекомендуемый тариф: тёплый tint-фон, усиленная кромка и свечение —
   выделяется среди соседей без изменения контента и без ломки базовых линий. */
.tier--featured {
  background:
    linear-gradient(180deg, rgb(245 176 62 / 0.09) 0%, rgb(245 176 62 / 0.03) 40%, transparent 70%),
    var(--surface);
  border-color: rgb(245 176 62 / 0.5);
  box-shadow: 0 0 0 1px rgb(245 176 62 / 0.2), 0 28px 70px -34px rgb(245 176 62 / 0.6);
}
.tier--featured .tier__amount { color: var(--accent-hi); }
.tier--featured .tier__no { color: var(--accent); }
/* Единая высота шапки тарифа: бейдж «Планируется» одинаков во всех карточках,
   но при узкой колонке переносится на 2-ю строку и уводит цену вниз — базовые
   линии цен в ряду разъезжаются. Резервируем высоту шапки. */
/* SUBGRID: карточки тарифов наследуют ряды общей сетки — шапка, описание,
   цена, сноска и подвал выравниваются ПО ВСЕМ колонкам ряда, а не «на глаз».
   Это единственная честная альтернатива min-height-магии: контент остаётся
   видимым полностью (никакого clamp), а базовые линии совпадают по построению.
   Поддержка: Chromium 117+, Safari 16+, Firefox 71+. Fallback ниже — если
   subgrid не поддерживается, остаются резервы высоты (min-block-size). */
@supports (grid-template-rows: subgrid) {
  .tiers { grid-auto-rows: auto; }
  .tier {
    display: grid;
    grid-row: span 6;
    grid-template-rows: subgrid;
    align-content: start;
  }
  .tier__foot { margin-block-start: auto; }
  /* Bento-колонка ~437px: базовый 3-колоночный .pack (12rem+10rem+1fr)
     схлопывает колонку примечания в 0px → вертикальный текст. Перекладываем:
     имя + цена в одну строку, примечание — на всю ширину ниже. */
  #topup .pack {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 0.15rem;
  }
  #topup .pack__note { grid-column: 1 / -1; }
  #topup .pack__price { white-space: nowrap; }
  /* Карточка «пополнение VU» (#topup) структурно другая: 4 ребёнка
     (head/for/packs/foot), а не 6. Оставляем её В subgrid — иначе шапка и
     подвал выпадают из общих рядов (рассинхрон на 60px в ряду 2). Пакетный
     список явно растягиваем на строки 3–5 (price/annual/incl соседей),
     чтобы subgrid не «размазывал» его space-between'ом. */
  .tier#topup .packs {
    grid-row: 3 / 6;
    align-content: start;
  }
}
/* Fallback (без subgrid) — резервы высоты: бейдж «Планируется» одинаковый,
   но переносы и разная длина .tier__for разъезжали цены на 5–9px. */
.tier__head {
  min-block-size: 5.2rem;
  align-content: center;
}
.tier__head .badge { white-space: nowrap; }
/* a11y: кнопки-степперы калькулятора задаются 44px (--tap-min), но flex-
   контейнер сжимает их до 41px (live-QA tap-targets FAIL — pre-existing).
   Запрет сжатия + явный минимум восстанавливают tap-target 44×44. */
.stepper__btn {
  flex-shrink: 0;
  min-inline-size: var(--tap-min);
  min-block-size: var(--tap-min);
}
.tier__for { min-block-size: 4.4rem; }
.px-value-flash {
  animation: px-value-flash 0.65s var(--ease-out, ease);
  border-radius: var(--r-sm, 6px);
}
@keyframes px-value-flash {
  0% { background-color: rgb(245 176 62 / 0.28); color: var(--accent-hi); text-shadow: 0 0 14px rgb(245 176 62 / 0.5); }
  100% { background-color: transparent; text-shadow: none; }
}
.px-plans-veil {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background:
    radial-gradient(60% 50% at 18% 22%, rgb(245 176 62 / 0.05), transparent 70%),
    radial-gradient(50% 44% at 82% 30%, rgb(88 205 223 / 0.045), transparent 70%),
    radial-gradient(56% 48% at 50% 88%, rgb(127 179 216 / 0.04), transparent 70%);
  background-size: 180% 180%;
  animation: px-veil-drift 24s ease-in-out infinite alternate;
}
@keyframes px-veil-drift {
  from { background-position: 0% 0%, 100% 10%, 40% 100%; }
  to { background-position: 30% 20%, 60% 40%, 70% 60%; }
}
#plans > .shell { position: relative; z-index: 1; }

/* ==========================================================================
   GUARDS — доступность и адаптив (ОБЯЗАТЕЛЬНО в конце, чтобы перебить)
   ========================================================================== */

/* prefers-reduced-motion: убрать ВСЁ движение премиум-слоя, оставить статику */
@media (prefers-reduced-motion: reduce) {
  .px-cursor-glow,
  .px-radar,
  .px-radar::after,
  .px-kinetic-accent,
  .px-scanline::after,
  .px-edge-anim:hover::before,
  .px-edge-anim:focus-within::before,
  .px-edge-anim.is-active::before,
  .px-ambient-drift,
  .px-live-dot::before,
  .px-graph .px-edge,
  .px-graph .px-node,
  .px-graph .px-node-label,
  .px-graph .px-hub,
  .px-graph .px-hub-label,
  .ceo-loop__node.px-cycle-live::after,
  .notfound,
  .lang-pick,
  .section:has(.notfound) { animation: none !important; }
  /* subgrid-сборка графа: в reduced-режиме JS сам ставит is-assembled —
     элементы видны сразу, без анимации (каскадные animation-delay тоже
     гасятся этим правилом). */
  .px-graph .px-edge { stroke-dashoffset: 0 !important; }
  .px-graph .px-node, .px-graph .px-node-label,
  .px-graph .px-hub, .px-graph .px-hub-label { opacity: 1 !important; transform: none !important; }
  .px-cursor-glow { display: none; }

  .px-net-host { display: none; }
  .btn--primary::after { display: none; }
  .ceo-loop__node.px-cycle-live::after { display: none; }
  .ceo-loop__node.px-cycle-live { transform: none; }
  .px-plans-veil { animation: none; }
  .px-value-flash { animation: none; }
}

/* Coarse-pointer (тач) или узкий экран: убрать курсор-ореол и сеть */
@media (hover: none), (pointer: coarse), (max-width: 768px) {
  .px-cursor-glow { display: none; }
  .px-net-host { display: none; }
  .px-radar { animation-duration: 14s; }
}
