
/* ================================================================
   ИТ-РЕЕСТР — дизайн «Вариант В»: графит + тёплый синий, Onest / IBM Plex Mono.
   Один акцент, минимальный радиус 3px, структура на тонких линиях.
   ================================================================ */
:root{
  --bg:#101217; --core:#1F2740; --edge:#0C0D11;
  --surf:rgba(255,255,255,.045); --surf2:rgba(255,255,255,.08);
  --line:rgba(255,255,255,.11); --line2:rgba(255,255,255,.06);
  --tx:#F3F4F8; --tx2:#A3A8B6; --tx3:#6D7282;
  --acc:#5C82F7; --acc-d:#5C82F7;
  --red:#F7635C;   /* зеркальный акцентному синему — только для крестиков/знака внимания в блоке «не подходит» */
  --sans:'Onest',system-ui,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,monospace;
  --r:3px;
  --t:.4s cubic-bezier(.4,0,.2,1);
  --max:1280px;
  /* Единый слой сетки/линий: один размер (--grid-pitch), прибит к вьюпорту
     (background-attachment:fixed → все блоки на ОДНОЙ решётке, «переходят» друг в друга),
     не зависит от ширины/масштаба окна (px, не vw/%). Правишь тут — меняется во всех блоках. */
  --grid-pitch:164px;
  --grid-vw:2px; --grid-hw:1px;
  --grid-line:rgba(255,255,255,.10);
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;overflow-x:hidden}
/* overflow-x:clip (не hidden!) режет горизонт, но НЕ делает body скроллером —
   поэтому window.scrollY растёт и док-меню срабатывает. */
body{background:var(--bg);color:var(--tx);font:400 16px/1.55 var(--sans);
     -webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums;overflow-x:clip}
a{color:inherit;text-decoration:none}
img{max-width:100%;height:auto;display:block}
.wrap{max-width:var(--max);margin:0 auto;padding-left:clamp(16px,4vw,48px);padding-right:clamp(16px,4vw,48px)}
.mono{font:500 11px/1.4 var(--mono);letter-spacing:.14em;text-transform:uppercase}
.acc{color:var(--acc)}
@media(min-width:1700px){:root{--max:1400px}}
@media(min-width:2200px){:root{--max:1560px}}

/* ── ШАПКА: sticky, при скролле собирается в плавающую пилюлю у верха ── */
.top{position:sticky;top:0;z-index:120;background:rgba(16,18,23,.62);
     -webkit-backdrop-filter:blur(18px) saturate(140%);backdrop-filter:blur(18px) saturate(140%);
     border-bottom:1px solid var(--line);
     transition:transform .5s cubic-bezier(.65,0,.35,1),background .35s,border-color .35s}
.top__in{display:flex;align-items:center;justify-content:space-between;height:76px;gap:20px;
         transition:height .4s cubic-bezier(.65,0,.35,1),gap .4s,padding .4s,background .35s,border-color .35s,box-shadow .4s,transform .45s cubic-bezier(.65,0,.35,1)}
/* При скролле полоса растворяется, а .top__in становится плавающей плашкой, опущенной вниз.
   Опускаем transform-ом (не margin) — margin-top схлопывается сквозь sticky-шапку и не работает. */
.top--dock .top__in{
     margin:0 auto;transform:translateY(20px);pointer-events:auto;
     background:rgba(16,18,23,.82);
     -webkit-backdrop-filter:blur(22px) saturate(150%);backdrop-filter:blur(22px) saturate(150%);
     border:1px solid rgba(255,255,255,.16);border-radius:var(--r);
     box-shadow:0 16px 46px rgba(0,0,0,.55)}
/* прозрачная полоса на всю ширину не должна ловить клики — их ловит только плашка */
.top--dock{background:transparent;border-bottom-color:transparent;pointer-events:none;
     -webkit-backdrop-filter:none;backdrop-filter:none}
.logo{display:flex;align-items:baseline;gap:9px;font-weight:900;font-size:19px;letter-spacing:-.04em;
      text-transform:uppercase;background:none;border:0;cursor:pointer;color:var(--tx);white-space:nowrap}
.logo b{color:var(--acc)}
.logo small{font:500 9.5px/1 var(--mono);letter-spacing:.12em;color:var(--tx3);text-transform:uppercase}
.nav{display:flex;gap:4px;align-items:center;margin:0 -8px}
/* Перемотка текста при наведении (уезжает вверх, снизу выезжает дубль в акценте) +
   плашка на пару тонов светлее фона позади текста.
   ::after стоит в состоянии покоя ЗА нижним краем кнопки (top:100%) — там он гарантированно
   спрятан обрезкой overflow:hidden. На hover обе строки едут на одинаковое расстояние
   --nav-shift (= паддинг сверху + высота строки), поэтому дубль въезжает ровно на место
   исходного текста без нахлёста. Прежний вариант (сдвиг только на высоту строки, без
   учёта паддинга) оставлял нижний край дубля внутри видимой зоны кнопки. */
.nav a,.nav button{--nav-lh:20px;--nav-shift:calc(8px + var(--nav-lh));position:relative;overflow:hidden;
     color:var(--tx2);font-size:14px;font-weight:500;
     background:none;border:0;cursor:pointer;font-family:var(--sans);white-space:nowrap;
     padding:8px 14px;border-radius:var(--r);line-height:var(--nav-lh);
     transition:color .2s,background .2s}
.nav a>span,.nav button>span{display:block;transition:transform .34s cubic-bezier(.4,0,.2,1)}
.nav a::after,.nav button::after{content:attr(data-label);position:absolute;left:14px;top:100%;color:var(--acc);
     transition:transform .34s cubic-bezier(.4,0,.2,1)}
.nav a:hover,.nav button:hover{background:rgba(255,255,255,.09)}
.nav a:hover>span,.nav button:hover>span{transform:translateY(calc(-1 * var(--nav-shift)))}
.nav a:hover::after,.nav button:hover::after{transform:translateY(calc(-1 * var(--nav-shift)))}
.nav button.active{color:var(--acc)}
.nav button.active:hover{background:rgba(92,130,247,.12)}
.nav button.active:hover{background:rgba(92,130,247,.12)}
.top__cta{padding:9px 18px;font-size:14px;white-space:nowrap}
.burger{display:none;flex-direction:column;gap:4px;width:38px;height:38px;border:1px solid var(--line);
        border-radius:var(--r);background:var(--surf);cursor:pointer;align-items:center;justify-content:center}
.burger span{width:17px;height:1.6px;background:var(--tx);transition:.25s}
.mnav{display:none}
@media(max-width:960px){
  .nav{display:none}
  .top .top__cta{display:none}   /* спецсел., чтобы победить .btn{display:inline-flex} ниже по каскаду */
  .burger{display:flex}
  .top--dock .top__in{max-width:none;margin:0;transform:none;height:76px;border-radius:0;border:0;box-shadow:none;background:rgba(16,18,23,.9)}
  /* мобильное выезжающее меню */
  .mnav{display:block;position:fixed;inset:0 0 0 auto;width:min(320px,86vw);z-index:200;
        background:#14161C;border-left:1px solid var(--line);padding:26px 24px;
        transform:translateX(100%);transition:transform .4s cubic-bezier(.4,0,.2,1);overflow-y:auto}
  .mnav.open{transform:none;box-shadow:-30px 0 80px rgba(0,0,0,.6)}
  .mnav a,.mnav button{display:block;width:100%;text-align:left;background:none;border:0;color:var(--tx);
       font:600 17px/1 var(--sans);padding:14px 0;border-bottom:1px solid var(--line2);cursor:pointer}
  .mnav .mnav__x{border:0;color:var(--tx2);font-size:26px;padding:0 0 14px;text-align:right}
  .mnav .mnav__phone{color:var(--acc);font-family:var(--mono);font-size:16px;margin-top:18px;border:0}
  .mnav__ov{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:190;opacity:0;visibility:hidden;transition:.3s}
  .mnav__ov.open{opacity:1;visibility:visible}
}

/* ── КНОПКИ ── */
/* Без стекла/блюра/свечения. На наведении инверсная заливка вдвигается СПРАВА.
   ::before — базовая заливка, ::after — инверсный слой, выезжающий справа налево. */
.btn{position:relative;overflow:hidden;isolation:isolate;
     display:inline-flex;align-items:center;gap:8px;padding:15px 28px;border-radius:var(--r);
     font-weight:700;font-size:15px;cursor:pointer;font-family:var(--sans);
     background:transparent;color:#fff;border:1px solid var(--acc);
     outline:none;transition:color .35s,transform .35s}
/* Увеличение при наведении — на ВСЕХ кнопках сайта (запрос 26.07). transform не влияет на
   поток, поэтому соседи не разъезжаются. Живёт вместе с инверсной заливкой из ::after:
   псевдоэлемент масштабируется вместе с кнопкой, конфликта трансформов нет. */
.btn:hover{transform:scale(1.04)}
/* .btn--wide — кнопка формы во всю ширину. Ей масштаб мягче: 4% от ~400px это +16px, и она
   вылезла бы за край формы. 1.5% держится в пределах отступов контейнера. */
.btn--wide:hover{transform:scale(1.015)}
/* Без этого браузер рисует свой прямоугольный focus-контур поверх кнопки (виден как
   «второй контур» на тёмном фоне) — заменяем на аккуратное кольцо в акцентном цвете,
   но только для клавиатурной навигации (:focus-visible), не при клике мышью. */
.btn:focus-visible{outline:2px solid var(--acc);outline-offset:3px}
.btn::before{content:"";position:absolute;inset:0;z-index:-2;background:var(--acc)}
.btn::after{content:"";position:absolute;inset:0;z-index:-1;background:#fff;
     transform:translateX(-101%);transition:transform .35s cubic-bezier(.4,0,.2,1)}
.btn:hover{color:var(--acc)}
.btn:hover::after{transform:translateX(0)}
/* вторичная: контурная → инверсная заливка светлым, тоже справа */
/* вторичная кнопка: в исходном состоянии стеклянная заливка, на hover — светлая заливка справа */
.btn--gh{color:var(--tx);border-color:rgba(255,255,255,.28);
     background:rgba(255,255,255,.08);-webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%)}
.btn--gh::before{background:transparent}
.btn--gh::after{background:var(--tx)}
.btn--gh:hover{color:var(--bg)}
.btn--wide{width:100%;justify-content:center}

/* ── ТИПОГРАФИКА ── */
h1{font-weight:900;font-size:clamp(2.05rem,5.1vw,4rem);line-height:.96;letter-spacing:-.05em;
   text-transform:uppercase;margin-bottom:24px}
h1 em{font-style:normal;color:var(--acc)}
h2{font-weight:900;font-size:clamp(1.6rem,3.1vw,2.6rem);line-height:1.03;letter-spacing:-.045em;
   text-transform:uppercase}
h2 em{font-style:normal;color:var(--acc)}
.lede{color:var(--tx2);font-size:clamp(15px,1.25vw,17px);max-width:56ch;margin-bottom:28px}

/* ── СЕКЦИИ ── */
/* Линий между блоками нет: ритм задают выделенные блоки (--lit / --striped) */
.sec{padding-top:clamp(50px,6.5vw,92px);padding-bottom:clamp(50px,6.5vw,92px)}
.sec__hd{margin-bottom:clamp(26px,3.4vw,42px)}
.sec__hd .mono{color:var(--acc);display:block;margin-bottom:12px}
.sec__hd p{color:var(--tx2);max-width:60ch;font-size:15px;margin-top:14px}

/* Выделенный блок: синяя заливка 10% + мягкий засвет как будто из-под блока,
   медленно блуждающий из стороны в сторону */
.sec--lit{position:relative;overflow:hidden;border-radius:var(--r);background:rgba(92,130,247,.10)}
/* inset вынесен за границы + filter:blur — засвет получается заметно мягче и без чёткой кромки */
.sec--lit::before{content:"";position:absolute;inset:-20% -15% -35%;z-index:0;pointer-events:none;
   background:radial-gradient(42% 52% at 50% 88%, rgba(92,130,247,.36) 0%, rgba(92,130,247,.11) 45%, transparent 75%);
   filter:blur(55px);
   animation:wander 20s ease-in-out infinite}
@keyframes wander{0%,100%{transform:translateX(-14%)}50%{transform:translateX(14%)}}
.sec--lit>*{position:relative;z-index:1}

/* Блок с «ореолом» как в герое: тот же радиальный градиент, посаженный в зону заголовка */
.sec--halo{position:relative;overflow:hidden}
.sec--halo::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
   background:radial-gradient(58% 90% at 26% 32%, rgba(31,39,64,.95) 0%, rgba(23,27,40,.5) 45%, transparent 100%)}
/* Сетка блока убрана (запрос) — у «Преимуществ» остаётся только ореол-градиент ::before. */
.sec--halo>*{position:relative;z-index:1}

/* Блок с вертикальными полосками — тот же приём, что в герое.
   overflow не ставим — иначе обрежутся полноэкранные линии .edge-* */
.sec--striped{position:relative}
.sec--striped::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
   background-image:linear-gradient(90deg,rgba(255,255,255,.08) 2px,transparent 2px);
   background-size:164px 100%;
   -webkit-mask-image:radial-gradient(80% 95% at 50% 50%,#000 0%,transparent 85%);
           mask-image:radial-gradient(80% 95% at 50% 50%,#000 0%,transparent 85%)}
.sec--striped>*{position:relative;z-index:1}

/* Вертикальные полоски как в хиро, отдельным слоем — чтобы не конфликтовать с линиями .edge-* (::before/::after) */
.sec--vstripes{position:relative}
.vstripes{position:absolute;inset:0;z-index:0;pointer-events:none;
   background-image:linear-gradient(90deg,rgba(255,255,255,.08) 2px,transparent 2px);
   background-size:164px 100%;
   -webkit-mask-image:radial-gradient(80% 95% at 50% 50%,#000 0%,transparent 85%);
           mask-image:radial-gradient(80% 95% at 50% 50%,#000 0%,transparent 85%)}
.sec--vstripes>.two{position:relative;z-index:1}

/* Полноэкранные горизонтальные линии — уходят за контентную колонку до краёв экрана.
   Ставятся на элемент классами .edge-top / .edge-bottom (используют разные псевдоэлементы). */
.edge-top,.edge-bottom{position:relative}
.edge-top::before,.edge-bottom::after{content:"";position:absolute;left:50%;transform:translateX(-50%);
   width:100vw;height:1px;background:var(--line);pointer-events:none;z-index:2}
.edge-top::before{top:0}
.edge-bottom::after{bottom:0}

/* Каталожный блок: ДВА засвета из противоположных углов, оба медленно хаотично блуждают */
/* Синий фон каталога. Этот слой — усиление в левом верхнем углу (зона заголовка); ровная
   синева НА ВЕСЬ блок, включая фото стоек, идёт отдельным слоем ::after (см. ниже) — фоном
   секции её не дать, <img> рисуется поверх фона.
   Блуждающие засветы сняты: любое движение выносило синеву на картинку. */
.sec--lit-cat{background:
   radial-gradient(78% 92% at 4% 2%, rgba(92,130,247,.30) 0%, rgba(92,130,247,.10) 38%, transparent 68%),
   linear-gradient(rgba(255,255,255,.022),rgba(255,255,255,.022)),
   var(--bg)}
/* Синий засвет в левом верхнем углу. Второй слой параллакса: едет НАВСТРЕЧУ фото стоек
   (--cat-glow-y, вдвое короче) — расхождение двух слоёв и читается как глубина.
   Сам засвет размыт на 72px и вылезает за края блока на десятки процентов, поэтому
   смещение на ±32px кромок не обнажает. */
.sec--lit-cat::before{inset:-34% 44% 26% -24%;
   background:radial-gradient(56% 62% at 36% 36%, rgba(92,130,247,.44) 0%, rgba(92,130,247,.13) 46%, transparent 76%);
   filter:blur(72px);
   animation:none;
   transform:translateY(var(--cat-glow-y,0px))}
/* Синяя маска НА ВЕСЬ блок (запрос 26.07). Плоская заливка на ::after, а не в background
   секции: иллюстрация стоек — это <img>-ребёнок, она рисуется ПОВЕРХ фона секции, и фоном
   её не подкрасить. ::after лежит в дереве после .cat-rack при одинаковом z-index:0 →
   перекрывает фото; карточкам поднят z-index:1 (см. ниже) → остаются сверху и видят эту
   синеву через свой backdrop-filter. Блок синеет целиком, текст не мутнеет.
   Крутилка насыщенности — альфа ниже. */
.sec--lit-cat::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
   background:rgba(92,130,247,.20)}
/* ОБЯЗАТЕЛЬНО: позиционированный ::after (z-index:0) по правилам порядка отрисовки ложится
   ПОВЕРХ статичного контента, т.е. завесил бы заголовок и карточки. Поднимаем весь контент
   секции на z-index:1 — кроме самой картинки, ей место под маской. */
.sec--lit-cat>*:not(.cat-rack){position:relative;z-index:1}
@keyframes wanderPerimeter{
   0%{transform:translate(-24%,-20%)}
   16%{transform:translate(22%,-14%)}
   30%{transform:translate(26%,8%)}
   48%{transform:translate(14%,22%)}
   62%{transform:translate(-16%,18%)}
   80%{transform:translate(-26%,2%)}
   100%{transform:translate(-24%,-20%)}}
@keyframes wanderPerimeter2{
   0%{transform:translate(24%,20%)}
   18%{transform:translate(-20%,16%)}
   34%{transform:translate(-26%,-10%)}
   52%{transform:translate(-8%,-22%)}
   68%{transform:translate(18%,-18%)}
   84%{transform:translate(26%,-2%)}
   100%{transform:translate(24%,20%)}}
/* плашки каталога — подложка «Импортозамещения» (.subst .cell). Альфа заливки за 26.07
   искалась подбором: .05/.012 → .026/.005 (прозрачнее) → .07/.022 (плотнее) →
   .045/.012 (текущее, между двумя крайними). Крутить только эти две цифры, они же
   продублированы в :hover ниже. Рамка .12 не тронута — без неё карточки теряют границы.
   Блик по кромке и синее пятно-свечение остаются снятыми. */
/* Иллюстрация серверных стоек VEGMAN — подложка НА ВЕСЬ блок, отцентрована (запрос 26.07;
   раньше «выглядывала» справа: right:-4%, width:auto, маска-растворение слева).
   Сейчас (запрос 26.07): полный кадр catalog-rack.webp 2200×2175 (весь
   Downloads\23456123.png, без обрезки полосы), посажен по высоте блока и СДВИНУТ ВПРАВО так,
   что ровно 20% его ширины уходит за правый край и срезается, остальные 80% видны.
   Как сделано и почему именно так: элемент сам получает размер картинки (width:auto +
   height:100%, object-fit не нужен), прижимается к правому краю (right:0; left:auto) и
   сдвигается transform:translateX(20%). Процент у translate считается от СОБСТВЕННОЙ ширины
   элемента — поэтому 20% остаются ровно 20% кадра на любой высоте блока. Через right:-20%
   так не выйдет: у right проценты считаются от ширины блока (1246px), а не картинки (641px),
   и вместо 20% получилось бы 39%. Через object-position тоже можно, но там пришлось бы
   зашивать пиксели, зависящие от высоты блока.
   ЦЕНА: кадр почти квадратный, по высоте блока он ~641px из 1246, видимая часть 80% = ~513px,
   значит слева остаётся ~733px тёмного фона. Заполнить блок целиком можно только увеличив
   кадр в 2.4 раза, а это уже сильный кроп по высоте — тот самый вариант, что был отвергнут.
   Перебранные и отвергнутые варианты, чтобы не крутить по кругу:
     • cover на полном кадре — раздувает по высоте вдвое, теряется верх и низ;
     • ассет, обрезанный полосой под пропорцию блока (2200×1118, 1.968:1) + cover —
       заполняет блок ровно 1:1, но кадр обрезан;
     • тот же приём + width:125% и ассет 2400×975 (2.46:1) — фото сдвинуто вправо, ровно
       20% ширины уходит за правый край.
   Скрипты пересборки ассета лежат в scratchpad: conv_rack.py (полный кадр, текущий),
   crop_rack.py / crop_rack2.py (полосы под два варианта cover), analyze_rack.py (поиск
   самой тёмной полосы). Менять вариант = перегнать ассет + поправить object-fit/width тут.
   height:100% — ровно по высоте блока. ПОБОЧНЫЙ ЭФФЕКТ: запас за краями исчез, а параллакс
   фото жил именно из него, поэтому ход фото нулевой — JS сам выставляет амплитуду 0
   (amp = max(0, min(AMP, запас−6))), пустых полос не появится. Двигается только синий
   засвет. Нужен ход фото — вернуть height 104–110%.
   Центрирующий -50% и смещение — обязательно ОДНИМ calc: второе объявление transform
   затрёт первое и картинка спрыгнет вниз на пол-высоты (--cat-y при height:100% всегда 0,
   но calc оставлен, чтобы возврат запаса не требовал правок здесь).
   Маска — растворение только у ЛЕВОГО края (видимая кромка кадра); правый уходит за границу
   блока и срезается, растворять там нечего.
   max-width:none обязателен: глобальное img{max-width:100%} иначе прибьёт width:auto.
   Уходит под карточки и под синюю маску (z-index:0), справа обрезается секцией
   (overflow:hidden уже на .sec--lit). */
/* Картинка вытянута дальше влево через height (width:auto, кадр почти квадратный ~1:1) — это
   единственный рычаг, чтобы кадр доходил до границы 1-й и 2-й карточки, а не торчал маленьким
   пятном только у правого края над верхней парой карточек.
   265% (первая попытка) был подобран и проверен ТОЛЬКО на широком экране (секция ~1550-1560px,
   --max:1560 при ≥2200px) — и вылезал далеко за левую карточку на обычном дисплее (запрос
   «выходит за рамку»): картинка растёт от ВЫСОТЫ блока, а высота блока (контент: заголовок +
   2 строки карточек) почти не меняется между тарифами --max (1280/1400/1560 — см. :root),
   тогда как ШИРИНА блока между ними падает вплоть до 1280px. Одна и та же картинка в пикселях
   в узкой секции закрывает БОЛЬШУЮ долю ширины — при 265% на --max:1280 (самый частый десктопный
   случай, у него нет медиа-порога, это дефолт) левый край кадра оказывался всего в ~30px от
   края блока, то есть под картинкой оказывалась вообще вся 1-я карточка.
   215% подобран под этот БАЗОВЫЙ тариф (--max:1280, дефолт без медиа-запроса) — граница
   растворения (12% маски) там ложится точно на границу 1-й/2-й карточки.
   ВАЖНО, разобрался позже (по референсу «как на картинке»): высота блока (666px) не меняется
   между тарифами --max вообще — это проверено напрямую (подменял --max через инлайн-стиль на
   :root и мерил getBoundingClientRect у трёх тарифов). Значит один процент высоты НЕ может
   одинаково выглядеть на всех тарифах: ширина растёт (1280→1400→1560), а высота блока и,
   следов, размер картинки — нет, и та же картинка в пикселях покрывает всё меньшую долю
   более широкой секции. Поэтому размер задан ПО ЧИСЛУ НА КАЖДЫЙ ТАРИФ (те же точки, что уже
   определяют --max в :root).

   КАК ПОСЧИТАНЫ ЧИСЛА (чтобы не подбирать вслепую, если снова попросят сдвинуть):
   картинка прижата к правому краю и сдвинута наружу на translateX от СОБСТВЕННОЙ ширины,
   значит её левая кромка = secW − (1 − tx)·W_img. Целевая композиция по референсу — кромка на
   ~35% ширины блока (сразу правее колонки 1: правый край 1-й карточки = 33.8% ширины, зазор
   до 2-й — 34.2%). При прежнем tx=30% это давало W_img = 0.929·secW и высоты 176/193/215
   для secW 1280/1400/1560 (высота = W_img / 1.0115, пропорции файла 2200×2175, в % от secH).

   Затем кадр уменьшен ещё на 20% «за правый верхний угол» (запрос) — то есть ЛЕВАЯ кромка
   обязана остаться на тех же 35%, ужиматься должен правый край. Одной высотой так не выйдет:
   при неизменном tx=30% уменьшение утащило бы левую кромку вправо (до ~48%) и сбило бы уже
   выверенную композицию. Поэтому tx пересчитан из условия «левая кромка не двигается»:
   W_new = 0.8·W_old → (1 − tx_new)·0.8 = (1 − 0.30) → tx_new = 12.5%.
   Высоты соответственно ×0.8: 176/193/215 → 141/154/172.
   Видимая на экране область при этом та же (кадр по-прежнему уходит за правый край блока,
   теперь на 12.5% своей ширины вместо 30%) — меняется только масштаб содержимого.
   Проверка масштаба по самому кадру: в нём ~6 корпусов, один ≈15% высоты файла — сейчас в
   высоту блока попадает ~4 корпуса (было ~3.3 до уменьшения на 20%).

   Запас за краями блока (для JS-параллакса --cat-y) всё ещё с большим запасом — не проблема:
   амплитуда там жёстко зажата константой AMP_RACK=64px независимо от размера запаса (см. JS
   ниже по файлу), лишний запас просто обрезается overflow:hidden. */
.sec--lit-cat .cat-rack{position:absolute;z-index:0;pointer-events:none;
   left:auto;right:0;top:50%;transform:translate(12.5%,calc(-50% + var(--cat-y,0px)));
   will-change:transform;
   width:auto;height:141%;max-width:none;opacity:.92;
   -webkit-mask-image:linear-gradient(to right,transparent 0%,#000 12%);
           mask-image:linear-gradient(to right,transparent 0%,#000 12%)}
@media(min-width:1700px){.sec--lit-cat .cat-rack{height:154%}}
@media(min-width:2200px){.sec--lit-cat .cat-rack{height:172%}}
@media(max-width:900px){.sec--lit-cat .cat-rack{opacity:.6}}
@media(max-width:600px){.sec--lit-cat .cat-rack{display:none}}
.sec--lit-cat .grid3{background:none;border:0;gap:12px}
/* ПОДЛОЖКА — один в один как в «Направлениях работы» (запрос 26.07), см. подробные
   комментарии у .sec--laws .cell: в покое заливки нет вообще, рамка невидима и её роль играет
   градиентное кольцо ::after (тёмное → светлое по оси 160deg), фрост 5px; на наведении фрост
   10px + мягкий белый засвет сверху-справа + увеличение 1.03, без задней подсветки.
   Значения продублированы, а не вынесены в общий селектор, намеренно: у каталога свой
   каскадный контекст (см. ниже про защиту background) и своя иллюстрация под карточками —
   объединять их одним правилом значит связать два блока, которые заказчик правит порознь.
   overflow:visible + inset:-1px у кольца — по той же причине, что в «Направлениях»: при
   overflow:hidden и дробной высоте карточки нижняя полоса кольца попадает на неполный
   пиксель и стирается. */
/* ЗАТЕМНЕНИЕ ПОДЛОЖКИ (запрос 26.07). Отличие каталога от трёх остальных блоков единого
   рецепта: только здесь под карточками лежит фото стоек, и на его светлых участках текст
   пропадал — сильнее всего в карточке «Сеть». Поэтому подложка НЕ полностью прозрачная, а с
   тёмной плёнкой rgba(16,18,23,.60) — цвет фона --bg, чтобы не вносить новый оттенок.
   Альфа .60 подобрана НЕ по средней яркости, а по худшему локальному участку под текстом —
   именно из-за него текст и пропадал точечно. Замеры при десктопной яркости фото (opacity .92),
   худшая пара — подпись карточки «ПО и ИБ»: без плёнки 1.70, при .38 → 3.22, при .46 → 3.71,
   при .54 → 4.27, при .60 → 4.74 (первое значение выше порога AA 4.5), при .66 → 5.23.
   Меньше .60 ставить нельзя — на светлых салазках стоек текст снова начнёт тонуть.
   На наведении плёнка ОБЯЗАНА остаться: там она лежит нижним слоем, а белый засвет — верхним
   (в background два слоя, цвет всегда последним). Уберёте её из :hover — текст снова утонет
   на светлых стойках. */
.sec--lit-cat .cell{position:relative;overflow:visible;border-radius:var(--r);
   background:rgba(16,18,23,.60);border:1px solid transparent;
   -webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);
   transition:transform .3s ease,box-shadow .3s ease,background .3s ease,backdrop-filter .3s ease}
/* блик по кромке снят; ::after теперь занят градиентной окантовкой */
.sec--lit-cat .cell::before{content:none}
/* СТРЕЛКА КЛИКАБЕЛЬНОСТИ (запрос 26.07). Живёт на ::before самой карточки, а не отдельным
   элементом в разметке: так она появляется сразу во всех шести карточках и её не надо
   дублировать шесть раз в HTML (::after занят градиентной окантовкой).
   Позиция: right/bottom в пикселях внутренних отступов карточки (24px и 28px). bottom:28px
   ставит стрелку ровно на уровень последней строки текста — отступы абсолютного потомка
   считаются от padding-box, поэтому 28px = высота нижнего padding = нижняя кромка контента.
   Движение: в покое стрелка СТАТИЧНА (запрос 26.07 — сначала кивала постоянно, 2.2s), кивок
   вправо на 5px включается только на наведении, цикл 1.1s. Поэтому animation объявлена в
   :hover-правиле, а не в базовом: так в покое анимации нет вообще, а не «стоит на паузе».
   Уважает prefers-reduced-motion (ниже).
   Тексту добавлен padding-right, иначе длинная последняя строка подползала бы под стрелку. */
.sec--lit-cat .cell--link::before{content:"→";position:absolute;z-index:1;pointer-events:none;
   right:24px;bottom:28px;
   font:500 16px/1 var(--mono);color:var(--acc)}
.sec--lit-cat .cell--link:hover::before{color:#bcccff;animation:catGo 1.1s ease-in-out infinite}
.sec--lit-cat .cell--link p{padding-right:28px}
@keyframes catGo{0%,100%{transform:translateX(0)}50%{transform:translateX(5px)}}
@media(prefers-reduced-motion:reduce){.sec--lit-cat .cell--link:hover::before{animation:none}}
.sec--lit-cat .cell::after{content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;
   pointer-events:none;
   background:linear-gradient(160deg, rgba(255,255,255,.04) 0%, rgba(255,255,255,.12) 48%, rgba(255,255,255,.30) 100%);
   -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}
.sec--lit-cat .cell>*{position:relative;z-index:1}
/* Увеличение 1.03 (как в «Типовых проблемах»); z-index:2 не нужен — при 1.03 прирост 5.6px
   в сторону против половины зазора 6px, на соседей карточка не залезает.
   Заливка-засвет здесь ещё и ЗАЩИТА, убирать её нельзя: правила каталога стоят ВЫШЕ по файлу,
   чем глобальное .cell:hover{background:#171A24}, а специфичность у них равная (0-2-0) —
   без своего background на наведении победило бы глобальное и залило карточку сплошным
   тёмным, спрятав иллюстрацию стоек. Этим каталог отличается от «Направлений»: те объявлены
   НИЖЕ глобального правила и в такой защите не нуждаются. */
.sec--lit-cat .cell:hover{transform:scale(1.03);box-shadow:none;
   background:radial-gradient(78% 48% at 62% 0%, rgba(255,255,255,.042) 0%, rgba(255,255,255,.013) 45%, transparent 94%),
              rgba(16,18,23,.60);
   -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}

/* ПЕРЕЛИВ ОКАНТОВКИ НА НАВЕДЕНИИ — статичный, БЕЗ анимации (запрос 26.07).
   Приём: на hover кольцу подменяется градиент — вместо ровного «тёмное → светлое» встаёт
   многостоповый с холодным блеском (#bcccff), провалом, акцентным синим и светлым выходом.
   Ощущение перелива даёт сам момент переключения, а не движение: никаких @keyframes здесь
   нет (прежний borderflow с бегущей полосой был удалён и не вернулся).
   Побочно и удобно: градиенты в покое и на hover имеют разное число стопов (3 против 5),
   поэтому браузер их НЕ интерполирует и переключение честно мгновенное, даже при том, что
   background у карточки анимируется через transition.
   Правило общее для «Направлений работы» и «Каталога» — их подложки специально сведены
   к одному виду, так что перелив обязан быть одинаковым. */
.sec--laws .cell:hover::after,
.sec--lit-cat .cell:hover::after,
.sec--risks .cell:hover::after,
.sec--halo .cell:hover::after,
.nf-item:hover::after{
   background:linear-gradient(160deg,
      rgba(255,255,255,.10) 0%,
      rgba(188,204,255,.44) 24%,
      rgba(255,255,255,.14) 45%,
      rgba(92,130,247,.40) 68%,
      rgba(255,255,255,.52) 100%)}

/* Блок формы: засвет ×2, статичный, в правом верхнем углу */
.sec--lit-form::before{inset:-45% -38% -55%;
   background:radial-gradient(60% 66% at 88% 4%, rgba(92,130,247,.4) 0%, rgba(92,130,247,.12) 46%, transparent 74%);
   filter:blur(85px);
   animation:none;transform:none}

/* ── 1. ПЕРВЫЙ ЭКРАН ── */
/* Слои снизу вверх: фото ЦОД (правая часть кадра) → фирменный радиальный градиент
   → защита заголовка слева → растворение в фон внизу. Полоски идут поверх (::before). */
.hero{position:relative;overflow:hidden;background-color:var(--bg);
   background-image:
      linear-gradient(to bottom, transparent 55%, var(--bg) 100%),
      linear-gradient(90deg, rgba(16,18,23,.82) 0%, rgba(16,18,23,.6) 34%, rgba(16,18,23,.2) 62%, rgba(16,18,23,0) 100%),
      radial-gradient(58% 90% at 30% 38%, rgba(31,39,64,.3) 0%, rgba(23,27,40,.15) 45%, rgba(12,13,17,.32) 100%),
      url('assets/hero-photo.jpg');
   background-size:100% 100%, 100% 100%, 100% 100%, cover;
   background-position:center, center, center, center right;
   background-repeat:no-repeat}
.hero::before{content:"";position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(90deg,var(--grid-line) var(--grid-vw),transparent var(--grid-vw));
  background-size:var(--grid-pitch) 100%;background-attachment:fixed;background-position:0 0;
  -webkit-mask-image:radial-gradient(88% 96% at 40% 50%,#000 0%,transparent 88%);
          mask-image:radial-gradient(88% 96% at 40% 50%,#000 0%,transparent 88%)}
.hero__in{position:relative;display:grid;grid-template-columns:minmax(0,1fr) 400px;gap:56px;
          align-items:center;padding-top:clamp(44px,6vw,88px);padding-bottom:clamp(44px,6vw,88px)}
.hero__in>*{min-width:0}
@media(max-width:1040px){
  .hero__in{grid-template-columns:1fr;gap:40px}
  /* Хиро схлопнулся в одну колонку: текст идёт во всю ширину. Показываем ЛЕВУЮ, тёмную
     часть кадра — иначе cover обрезает до стоек и заголовок ложится на блики. */
  .hero{background-position:center, center, center, left center}
}
.hero__chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:30px}
.hero__chips .lbl{flex:0 0 100%;font:500 10px/1 var(--mono);letter-spacing:.18em;text-transform:uppercase;color:var(--tx3);margin-bottom:4px}
.chip{padding:7px 14px;border:1px solid rgba(255,255,255,.18);background:rgba(255,255,255,.10);
   -webkit-backdrop-filter:blur(12px) saturate(140%);backdrop-filter:blur(12px) saturate(140%);
   font-size:12.5px;color:var(--tx);border-radius:var(--r)}
.cta{display:flex;gap:14px;flex-wrap:wrap;align-items:center}

/* слайдер категорий */
/* Карточка слайдера: фрост 10 (запрос 27.07, второй раунд). Заливки-стекла нет, только блюр
   фона под карточкой — рамка и радиус остаются контуром. */
.slider__vp{position:relative;overflow:hidden;border-radius:var(--r);border:1px solid rgba(255,255,255,.16);
   background:none;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.slider__track{display:flex;transition:transform .5s cubic-bezier(.4,0,.2,1)}
/* текст слайда прижат к низу карточки */
/* position:relative — под абсолютную картинку слайда; overflow:hidden — чтобы её «выглядывающая»
   часть обрезалась КРАЕМ СВОЕГО слайда, а не уезжала на соседний. Без этого при перелистывании
   хвост картинки «Серверов» наползал бы на слайд СХД: слайды лежат вплотную в одном флекс-треке,
   а клип у .slider__vp совпадает с краем только активного слайда. */
.slide{flex:0 0 100%;min-width:0;padding:30px;min-height:300px;display:flex;flex-direction:column;
       position:relative;overflow:hidden;
       justify-content:flex-end;text-align:left;background:none;border:0;color:var(--tx);cursor:pointer;font-family:var(--sans)}
/* Фото оборудования в слайде — общее правило для ВСЕХ слайдов (по схеме заказчика):
   кадр живёт в узкой полосе в верхней части карточки (полоса — 12%..33% высоты, это и есть
   отмеченный прямоугольник) и отцентрован в ней по обеим осям.
   Полоса задана КАК БОКС (85% × 21%), а кадр вписан в неё через object-fit:contain — это
   принципиально, потому что пропорции техники разъезжаются очень сильно: сервер ~5.4:1,
   коммутатор ~10:1, 4U-СХД «Аэродиск» ~2.9:1. Привязка по одной стороне тут не работает:
   при height:21% коммутатор растянуло бы до ~630px при слайде 398px (вылез бы за оба края),
   а при width:85% с авто-высотой 4U-СХД выросла бы до ~118px и налезла на заголовок.
   contain держит и то и другое внутри полосы без искажений: широкие кадры упираются в
   ширину, высокие — в высоту, лишнее место остаётся пустым.
   Точка привязки — ЦЕНТР полосы (top:22.5% = 12% + 21%/2) плюс translate(-50%,-50%): тогда
   кадр стоит в полосе ровно посередине, а не свисает от её верхнего края.
   Центровка через left/top + translate, а не margin:auto: элемент абсолютный, авто-поля
   работают только при заданных ОБОИХ краях.
   Обрезает край сам слайд (.slide{overflow:hidden}) — иначе хвост наползал бы на соседний слайд.
   Затемнение — filter:brightness, а не плёнка поверх: фон кадра прозрачный, плёнка закрасила бы
   и пустоту вокруг техники. Полоса отнесена от текста, поэтому гасим слабее прежнего (.4→.8).
   Конкретный файл подставляет JS (см. «ФОТО ТЕХНИКИ В СЛАЙДЕРЕ» в конце) — набор задаётся
   атрибутом data-shots, а в src лежит первый кадр как запасной при отключённом JS. */
.slide__img{position:absolute;z-index:0;pointer-events:none;
   left:50%;top:22.5%;transform:translate(-50%,-50%);
   width:85%;height:21%;max-width:none;
   object-fit:contain;object-position:center;
   filter:brightness(.8) saturate(.9)}
/* Текст обязан быть выше картинки: без z-index непозиционированный контент красится ДО
   позиционированной картинки с z-index:0, и кадр лёг бы поверх заголовка.
   :not(.slide__img) ОБЯЗАТЕЛЕН — иначе это правило (0-2-0) перебивает position:absolute
   у .slide__img (0-1-0), картинка остаётся флекс-элементом в потоке, ширину зажимает
   контентный бокс, а right/translate работают не от края слайда. На этом уже наступили. */
.slide>*:not(.slide__img){position:relative;z-index:1}
.slide h3{font-weight:900;font-size:1.7rem;text-transform:uppercase;letter-spacing:-.045em;margin:0 0 10px;line-height:1}
.slide p{color:var(--tx2);font-size:14px;line-height:1.45}
.slide__spec{margin-top:16px;padding-top:14px;border-top:1px solid var(--line);display:flex;
   justify-content:space-between;gap:12px;font:400 11.5px/1.3 var(--mono);color:var(--tx3)}
.slide__spec b{color:var(--acc);font-weight:500;white-space:nowrap}
.slider__nav{display:flex;align-items:center;justify-content:flex-end;margin-top:16px}
.slider__arrows{display:flex;gap:8px}
.slider__arrows button{width:46px;height:46px;border-radius:var(--r);border:1px solid rgba(255,255,255,.16);
   background:rgba(255,255,255,.04);color:var(--tx);cursor:pointer;display:grid;place-items:center;
   transition:background .2s,border-color .2s,color .2s,transform .2s}
/* стрелки маленькие (46px), поэтому масштаб крупнее кнопочного — иначе прирост не читается */
.slider__arrows button:hover{background:var(--acc-d);border-color:var(--acc-d);color:#fff;transform:scale(1.08)}
.slider__arrows svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

/* ── ЛОГОТИПЫ ДОВЕРИЯ ── */
/* три равные колонки, логотип строго по центру каждой */
.trust{display:grid;grid-template-columns:repeat(3,1fr)}
.trust__i{display:flex;align-items:center;justify-content:center;min-height:118px;padding:34px 24px}
.trust__i img{height:44px;width:auto;filter:brightness(0) invert(1);opacity:.7;transition:opacity .25s}
.trust__i:hover img{opacity:1}
@media(max-width:640px){
  .trust{grid-template-columns:1fr}
  .trust__i{min-height:92px;padding:22px}
  .trust__i img{height:34px}}

/* ── ФАКТЫ: цифра со светом ── */
.facts__hd{display:flex;justify-content:space-between;align-items:flex-end;gap:30px;flex-wrap:wrap;margin-bottom:clamp(22px,3vw,34px)}
.facts__hd h2{max-width:none}
.facts__hd p{color:var(--tx2);max-width:44ch;font-size:15px}
.hero-num{position:relative;display:inline-block;line-height:.82;font-weight:900;letter-spacing:-.05em;
   font-size:clamp(5.5rem,18vw,16rem);color:#1D2233;user-select:none}
.hero-num span{position:absolute;inset:0;color:transparent;-webkit-background-clip:text;background-clip:text;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='751' height='751'%3E%3Cdefs%3E%3Cfilter id='f' x='0' y='0' width='751' height='751' filterUnits='userSpaceOnUse'%3E%3CfeGaussianBlur stdDeviation='110'/%3E%3C/filter%3E%3C/defs%3E%3Ccircle cx='375' cy='375' r='150' fill='%235C82F7' filter='url(%23f)'/%3E%3C/svg%3E");
  background-size:150% 300%;background-repeat:no-repeat;animation:sweep 7s ease-in-out infinite}
@keyframes sweep{0%,100%{background-position:-20% 50%}50%{background-position:120% 50%}}
.hero-num small{position:absolute;left:calc(100% + 20px);bottom:16%;white-space:nowrap;
   font:500 12px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--tx2)}
@media(max-width:700px){.hero-num small{position:static;display:block;margin-top:10px}}
/* линии сверху/снизу задаются классами .edge-top .edge-bottom (во всю ширину экрана) */
.counts{display:grid;grid-template-columns:repeat(4,1fr);margin-top:clamp(22px,3vw,38px)}
.counts>div{padding:24px 26px;border-right:1px solid var(--line)}
.counts>div:first-child{padding-left:0}
.counts>div:last-child{border-right:0}
.counts b{display:block;font-weight:800;font-size:clamp(1.6rem,2.6vw,2.2rem);letter-spacing:-.04em;line-height:1}
.counts b i{font-style:normal;color:var(--acc)}
/* «44 | 223 | 275»: браузер переносит после «|», и ячейка выбивалась по высоте
   из соседних. Держим в одну строку — по ширине влезает на всех брейкпойнтах. */
.counts__laws{white-space:nowrap}
.counts span{display:block;margin-top:8px;color:var(--tx3);font-size:13px;line-height:1.4}
@media(max-width:860px){.counts{grid-template-columns:repeat(2,1fr)}
  .counts>div:nth-child(2n){border-right:0}
  .counts>div:nth-child(-n+2){border-bottom:1px solid var(--line)}
  .counts>div{padding-left:0}}

/* ── КАРТОЧКИ-СЕТКА (законы / преимущества / категории) ── */
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line)}
@media(max-width:900px){.grid3{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.grid3{grid-template-columns:1fr}}
.cell{background:var(--bg);padding:28px 24px;transition:background .25s;display:flex;flex-direction:column}
.cell:hover{background:#171A24}
.cell__pill{display:inline-block;align-self:flex-start;padding:4px 12px;border:1px solid var(--line);
   border-radius:var(--r);font:600 11px/1 var(--mono);letter-spacing:.12em;color:var(--acc);margin-bottom:16px}
.cell__k{font:500 10.5px/1.3 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--tx3);margin-bottom:12px}
.cell h3{font-weight:700;font-size:1.05rem;letter-spacing:-.02em;margin-bottom:9px;line-height:1.25}
.cell p{color:var(--tx2);font-size:13.5px;line-height:1.6}
/* .cell .cell__fix — спецсел., чтобы акцент победил .cell p{color:var(--tx2)} */
.cell .cell__fix{margin-top:auto;padding-top:14px;color:var(--acc);font-size:13.5px;display:flex;gap:8px}
/* Знак перед решением: "→" → "!" → "✓" (26.07). Восклицательный знак оказался слишком резким,
   и по смыслу он вообще спорный: .cell__fix — это строка РЕШЕНИЯ («Составляем ТЗ и отвечаем
   за формулировки»), а не сама проблема. Галочка и спокойнее по тону, и точнее по контексту:
   проблема названа выше красным, а здесь — что мы с ней делаем.
   Правило глобальное по имени, но .cell__fix встречается ТОЛЬКО в «Типовых проблемах»
   (6 штук, проверено) — поэтому правка никуда больше не протекает.
   font-weight:800 оставлен: галочка в акцентном синем читается как знак, а не как символ текста.
   Увеличение при наведении на карточку — через transform, он не влияет на поток, поэтому
   строка решения не дёргается; transition уже был на месте.
   display НЕ указываю: .cell__fix — флекс-контейнер, а флекс-элементы блокифицируются
   автоматически, так что transform применяется и без подсказки (сначала поставил тут
   inline-block «чтобы scale заработал» — лишнее, computed всё равно даёт block). */
.cell__fix::before{content:"✓";flex:none;font-weight:800;transition:transform .25s}
/* рост уменьшен 1.75 → 1.4: на восклицательном знаке крупный скачок выглядел резко, галочке
   хватает сдержанного увеличения. Вернуть прежний размах — одна цифра. */
.sec--risks .cell:hover .cell__fix::before{transform:scale(1.4)}

/* Блок «Что может сломать закупку»: карточки разведены равными отступами (вместо линий-разделителей
   на общем фоне), у каждой своя рамка. При наведении фон переливается тем же приёмом, что «1200» —
   мягкое размытое пятно акцента, плывущее туда-обратно. */
/* Подложка блока убрана (запрос) — слоя .sec--risks::before больше нет, фон блока голый.
   Две строки ниже ОСТАВЛЕНЫ намеренно, хотя ставились под тот слой: position:relative и подъём
   контента на z-index:1 теперь держат порядок отрисовки для линии .edge-bottom::after (она
   позиционированная, без подъёма красилась бы поверх контента). Убирать их заодно не стоит. */
.sec--risks{position:relative}
.sec--risks>*{position:relative;z-index:1}
.sec--risks .grid3{gap:14px;background:none;border:0}
/* ЕДИНЫЙ РЕЦЕПТ КАРТОЧКИ (26.07). Четыре блока — «Типовые проблемы», «Направления работы»,
   «Результаты в цифрах», «Преимущества» — приведены к тому же виду, что «Импортозамещение»
   (.subst .cell), и ничего сверх этого набора у них больше нет:
     подложка   заливка .05→.012 по диагонали 160deg, рамка .12, blur(16px) saturate(140%);
     наведение  увеличение 1.03 + мягкая задняя подсветка 0 0 14px rgba(92,130,247,.07).
   Что при этом вычищено из ЭТОГО блока: блик по кромке, синее свечение с блужданием
   cellSweep, «треснувшее стекло» (.crack + crack--1…6 + разметка <i> в HTML), смена заливки
   и рамки на наведении, увеличение 1.10 с z-index:2, подпрыгивающая стрелка arrowpoint,
   а также .cell>*{z-index:1} — он был нужен только ради снятых псевдоэлементов.
   ВАЖНО про каскад: базовая заливка обязана быть объявлена НИЖЕ глобального
   .cell:hover{background:#171A24} (строка 466) — специфичность у них равная (0-2-0), спасает
   только порядок. Поэтому эти правила нельзя переносить выше по файлу. Именно так работает
   и .subst — «иммунитет» у него не магический, а от позиции в файле. */
/* ПОДЛОЖКА — как в «Направлениях работы» (запрос 26.07): заливки в покое нет, рамка невидима
   и её роль играет градиентное кольцо ::after, фрост 5px; на наведении фрост 10px + мягкий
   белый засвет сверху-справа + увеличение 1.03, задней подсветки нет.
   overflow:visible + inset:-1px у кольца — обязательная пара: при overflow:hidden и дробной
   высоте карточки нижняя полоса кольца попадает на неполный пиксель и стирается (этот баг
   уже ловили в «Направлениях»).
   box-shadow:none на hover нужен явно — подсветка 0 0 14px приходит из общего правила
   единого рецепта, молча она не исчезнет. */
.sec--risks .cell{position:relative;overflow:visible;border-radius:var(--r);
   background:transparent;border:1px solid transparent;
   -webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);
   transition:transform .3s ease,box-shadow .3s ease,background .3s ease,backdrop-filter .3s ease}
.sec--risks .cell::after{content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;
   pointer-events:none;
   background:linear-gradient(160deg, rgba(255,255,255,.04) 0%, rgba(255,255,255,.12) 48%, rgba(255,255,255,.30) 100%);
   -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}
/* Заливка НЕ задаётся здесь намеренно: с 26.07 плашки этого блока приравнены к «Направлениям
   работы», и обе заливки (покой и наведение) живут в одном общем правиле ниже по файлу —
   .sec--laws .cell,.sec--risks .cell. Один источник истины, чтобы блоки не разъезжались при
   следующей правке тона. Здесь остаётся только геометрия, фрост и увеличение. */
.sec--risks .cell:hover{transform:scale(1.03);box-shadow:none;
   -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
/* Трещины (.crack + crack--1…6), их SVG-шаблон и @keyframes cellSweep удалены 26.07
   вместе с приведением карточек к единому рецепту. Разметка <i class="crack"> из HTML
   тоже убрана — мёртвых элементов не осталось. */

/* Сетка ПОДЛОЖКИ САМОГО БЛОКА (не карточек) — та же, что в «Результатах в цифрах»:
   164px (размер линий хедера), полоса сверху, растушёвана вниз полукругом (а не со всех
   сторон к центру). ::after, не ::before — ::before на .sec--lit уже занят синим
   засветом-«облаком». Секция сама с overflow:hidden — растушёвка идёт к краям блока.
   attachment:scroll — сетка едет ВМЕСТЕ с блоком (запрос 26.07 «убери параллакс»). Раньше
   был fixed: слой стоял прибитым к вьюпорту, контент шёл сквозь него, и это читалось как
   параллакс. Та же правка уже сделана в «Результатах». ЦЕНА: этот слой выпал из общей фазовой
   стыковки сеток — у хиро фаза считается от вьюпорта, здесь от края блока, шаг тот же 164px,
   но линии двух блоков уже не совпадут. */
/* Яркость сетки возвращена к общей (26.07): локальный override --grid-line .20 снят,
   блок снова берёт значение из :root (.10) и выглядит как хиро/риски/результаты.
   Если снова понадобится сделать её заметнее — вернуть строку
   .sec--laws{--grid-line:rgba(255,255,255,.20)} здесь, а НЕ править :root. */
/* Высота полосы 280px → 460px (26.07). Причина: карточки занимают 171–401px от верха блока,
   а маска гасила сетку в ноль уже к 258px — сквозь прозрачную на наведении плашку смотреть
   было не на что. Теперь решётка доживает до низа ряда карточек. Яркость линий не поднимал:
   она осталась общей (.10 из :root), как вы и просили. */
/* Вертикальные полоски как в хиро (запрос, третий раунд 27.07), во всю ширину экрана
   (тот же приём выноса, что .sec--risks::before: left:50%/width:100vw/margin-left:-50vw).
   К низу блока исчезают — линейная маска сверху вниз, а не радиальная, как у хиро/рисков. */
/* Боковые полосы убраны (запрос): к вертикальному растворению добавлено горизонтальное —
   у левого и правого краёв блока полосы гаснут, крайние столбцы больше не упираются в кромку.
   Два слоя маски пересекаются (mask-composite:intersect / -webkit- source-in) — тот же приём,
   что у колец карточек ниже; сложением слоёв по умолчанию получилось бы наоборот, объединение.
   Геометрия при этом переведена с 100vw обратно на бокс блока (inset:0): проценты в маске
   обязаны считаться от КРАЁВ БЛОКА, а не от вьюпорта, иначе фейд встал бы за пределами
   видимой (клипованной overflow:hidden) области и полос у кромки не убрал. На положение самих
   полос это не влияет — background-attachment:fixed держит их фазу от вьюпорта, элемент лишь
   окно. Крутилки — стопы 12%/88%: больше значение, шире съедаемая с боков зона. */
/* attachment fixed → scroll (запрос — «сначала одна сетка, потом другая» при загрузке):
   выше по странице лежат тяжёлые картинки (hero-photo.jpg, catalog-rack.webp), их догрузка
   меняет высоту страницы и сдвигает блок; у fixed-сетки позиция считается от вьюпорта, а не
   от блока, поэтому в момент этого сдвига она визуально «перескакивала» на новую фазу —
   читалось как замена одной сетки на другую. На scroll сетка прибита к самому блоку и такого
   скачка нет. Та же правка уже делалась для сеток «Результатов»/«Преимуществ» по аналогичной
   причине. ЦЕНА обычная: фазовая стыковка с хиро (который остаётся fixed) больше не гарантирована. */
.sec--laws::after{content:"";position:absolute;inset:0;
   z-index:0;pointer-events:none;
   background-image:linear-gradient(90deg,var(--grid-line) var(--grid-vw),transparent var(--grid-vw));
   background-size:var(--grid-pitch) 100%;background-attachment:scroll;background-position:0 0;
   -webkit-mask-image:linear-gradient(to bottom,#000 0%,transparent 100%),
                      linear-gradient(90deg,transparent 0%,#000 12%,#000 88%,transparent 100%);
   -webkit-mask-composite:source-in;
           mask-image:linear-gradient(to bottom,#000 0%,transparent 100%),
                      linear-gradient(90deg,transparent 0%,#000 12%,#000 88%,transparent 100%);
           mask-composite:intersect}
/* То же расстояние между карточками (14px + своя рамка у каждой), что в блоке «Что может
   сломать закупку» — применено к законам и преимуществам (сами .nf-grid/.subst/.res
   правятся ниже, в их собственных правилах — иначе более поздние по каскаду исходные
   определения с тем же селектором их перебивали). Без hover-переливания — здесь не просили. */
.sec--laws .grid3,.sec--halo .grid3{gap:14px;background:none;border:0}
/* прежняя строка .sec--laws .cell,.sec--halo .cell{border:1px solid var(--line);border-radius}
   удалена как лишняя: рамку и радиус теперь задаёт единый рецепт ниже, а это правило стояло
   выше по каскаду и всё равно перебивалось — только путало. */
/* Преимущества: переливающаяся окантовка + задняя подсветка при наведении — как у плиток
   площадок (.plat div): тот же мягкий синий box-shadow вокруг карточки.
   Подложка — прозрачное стекло, Frost(blur)=25px. */
/* «Преимущества» и «Направления работы» — тот же единый рецепт (см. .sec--risks выше).
   Вычищено здесь: у «Преимуществ» — статичные угловые засветы (.cell::before, два
   радиальных пятна .28 и .14), переливающаяся окантовка (.cell::after + borderflow),
   блюр 25px и подсветка 22px/.14; у «Направлений» — своя заливка .03/.006, блюр 20px,
   увеличение 1.10 с z-index:2. У обоих снят .cell>*{z-index:1} — он держал текст поверх
   удалённых псевдоэлементов и без них не нужен.
   @keyframes borderflow НЕ удаляю: он ещё нужен плашкам «Процесса» и плиткам площадок. */
/* 26.07: «Преимуществам» задан ТОТ ЖЕ набор, что у «Направлений работы». Раз оба блока теперь
   выглядят одинаково, отдельный override для .sec--laws больше не нужен — рецепт перенесён
   прямо в это общее правило, а дублирующие строки ниже удалены. Так у двух блоков один
   источник истины, а не «общее правило плюс перебивка».
   Подложка: заливки нет, рамка невидима (её роль играет градиентное кольцо ::after), фрост
   5px в покое и 10px на наведении. Эффект: увеличение 1.03 + мягкий белый засвет сверху-справа
   + статичный перелив окантовки. Задней подсветки нет.
   overflow:visible + inset:-1px у кольца — обязательная пара, иначе на дробной высоте карточки
   нижняя полоса кольца попадает на неполный пиксель и стирается.
   ВАЖНО: background в :hover нужен явно — иначе вступит глобальное
   .cell:hover{background:#171A24} (0-2-0) и зальёт карточку тёмным.
   ПРИЧИНА бага «фрост несколько секунд не виден при загрузке» (запрос): этот же .cell —
   элемент появления rv-stagger (см. .fade-up.rv-stagger>*{opacity:0}, анимация rvUp:
   opacity+translate). Хромиум иногда не успевает построить композитный слой backdrop-filter
   К СТАРТУ анимации opacity/transform на том же элементе — карточка уже видна (opacity:1),
   а фрост «подтягивается» только на следующий репейнт (скролл/hover/что угодно), отсюда
   пустые на вид плашки первые секунды. will-change:backdrop-filter форсирует слой заранее,
   до начала анимации, и лечит именно это — свойство ничего не анимирует, просто держит layer. */
.sec--halo .cell,.sec--laws .cell{position:relative;overflow:visible;border-radius:var(--r);
   background:transparent;border:1px solid transparent;
   -webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);
   will-change:backdrop-filter;
   transition:transform .3s ease,box-shadow .3s ease,background .3s ease,backdrop-filter .3s ease}
.sec--halo .cell:hover,.sec--laws .cell:hover{transform:scale(1.03);box-shadow:none;
   background:radial-gradient(78% 48% at 62% 0%, rgba(255,255,255,.042) 0%, rgba(255,255,255,.013) 45%, transparent 94%);
   -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
/* «НАПРАВЛЕНИЯ РАБОТЫ» — исключение из единого рецепта (запросы 26.07). У подложки не
   осталось НИЧЕГО, кроме фроста; из эффектов — только увеличение.
   Убрано относительно общего рецепта: заливка-стекло .05→.012 (и в покое, и на наведении —
   плашка прозрачная всегда, сквозь неё видна сетка блока), saturate(140%) у фроста, задняя
   подсветка box-shadow на наведении. Оставлены рамка .12 и радиус: это контур карточки, без
   него она перестаёт читаться как карточка.
   Фрост инвертирован: в ПОКОЕ 5px, на НАВЕДЕНИИ 10px — то есть при наведении стекло
   «затуманивается» сильнее, а не наоборот.
   Три вещи, которые тут легко сломать:
     1) правила обязаны стоять НИЖЕ общего рецепта — специфичность равная (0-2-0), спасает
        только порядок;
     2) background:transparent на :hover нужен явно, иначе в дело вступит глобальное
        .cell:hover{background:#171A24} (0-2-0) и зальёт карточку тёмным;
     3) box-shadow:none на :hover тоже обязателен явно — подсветка приходит из общего
        правила .sec--halo .cell:hover, .sec--laws .cell:hover, молча она не исчезнет.
   Frost задаётся blur(...), а не none — none не интерполируется, переход щёлкал бы.
   История подбора, чтобы не ходить по кругу: сплошной белый #fff → пришлось инвертировать
   текст (заголовок --tx на белом давал 1.1:1, описание --tx2 — 2.4:1, текст исчезал);
   затем alpha .02 («прозрачность 98%») → инверсия снята; затем полная прозрачность.
   Заодно стоит помнить: --acc-d в :root РАВЕН --acc (#5C82F7), «тёмного акцента» в палитре
   нет — на светлом фоне он даёт лишь 3.5:1, ниже порога AA. */
/* (прежний override .sec--laws .cell с transparent/frost 5px удалён 26.07 — его значения
   переехали в общее правило выше, когда «Преимущества» получили тот же вид)
   Затем «Направления» попросили сделать КАК КАТАЛОГ — а каталог отличается ровно одним:
   тёмной плёнкой rgba(16,18,23,.60) под текстом. Поэтому override вернулся, но теперь в нём
   только это одно свойство. На «Преимущества» плёнка НЕ распространяется — просили только
   «Направления».
   Внимание на побочный эффект: плёнка .60 пропускает лишь 40% того, что за ней, поэтому сетка
   блока, которую мы специально продлевали под ряд карточек, за плашкой почти перестанет
   читаться — её эффективная альфа падает с .10 до ~.04. Если сетка важнее затемнения, плёнку
   надо убрать или опустить до ~.25. */
/* Плашка в ПОКОЕ светлее (запрос 26.07): тёмная плёнка ослаблена .60 → .40 и добавлена ровная
   белая .03. Двумя слоями, а не просто снятием плёнки: убрать плёнку целиком мало — под ней
   тёмный фон секции, плашка стала бы не светлее, а просто «как фон» и потеряла бы границу.
   Плёнку .60 здесь можно ослаблять безопасно, в отличие от «Каталога»: там она держит контраст
   текста над светлыми участками фото, а тут под карточками фото нет. */
/* Заливка подложки убрана (запрос): в покое плашка снова прозрачна, как до 26.07 — держат
   карточку только рамка-кольцо (::after) и фрост. */
.sec--laws .cell,.sec--risks .cell{background:transparent}
/* На наведении подложка светлеет на пару тонов ЦЕЛИКОМ (запрос 26.07), а не только под
   засветом. Сделано третьим слоем: сверху точечный засвет сверху-справа, под ним ровная белая
   плёнка .055 на всю плашку, в самом низу тёмная плёнка .60. Порядок в background важен —
   цвет обязан идти последним, градиенты рисуются поверх него.
   Почему не осветлением тёмной плёнки: она держит контраст текста, трогать её нельзя. */
/* Осветление на наведении убрано на тон: ровная белая плёнка .055 → .048, а поскольку в покое
   плашка теперь уже светлее (.03), фактический ПРИРОСТ на наведении упал с .055 до .018 —
   то есть подсветка стала заметно сдержаннее, как и просили.
   Плёнка .40 обязана совпадать с состоянием покоя, иначе на наведении плашка дёрнула бы
   яркость скачком. Точечный засвет сверху-справа не менял. */
/* Второй засвет снизу: зеркало верхнего — те же альфы .042/.013 и тот же размер 78% 48%,
   но у нижнего края (y:100%) и смещён от центра к ЛЕВОМУ краю (x:38%, верхний был 62%
   вправо). Цвет был акцентный синий, по запросу заменён обратно на белый — оба засвета
   теперь белые, различаются только позицией.
   «Преимущества» (.sec--halo) добавлены в этот же список (запрос): раньше у них была своя,
   более старая версия фона (строка 701, только верхний засвет) — теперь оба блока управляются
   отсюда, старое правило продолжает давать transform/box-shadow/blur, background оно больше
   не решает — эта строка её перебивает как более поздняя при равной специфичности. */
.sec--halo .cell:hover,.sec--laws .cell:hover,.sec--risks .cell:hover{
   background:radial-gradient(78% 48% at 62% 0%, rgba(255,255,255,.042) 0%, rgba(255,255,255,.013) 45%, transparent 94%),
              radial-gradient(78% 48% at 38% 100%, rgba(255,255,255,.042) 0%, rgba(255,255,255,.013) 45%, transparent 94%)}
/* «Направления работы» на тон светлее остальных на hover: те же два засвета, альфы подняты
   .042/.013 → .062/.033. Правило стоит НИЖЕ общего — побеждает по порядку при равной
   специфичности (0-2-0). Здесь ОБА засвета яркие; «Преимущества» отделены ниже. */
.sec--laws .cell:hover{
   background:radial-gradient(78% 48% at 62% 0%, rgba(255,255,255,.062) 0%, rgba(255,255,255,.033) 45%, transparent 94%),
              radial-gradient(78% 48% at 38% 100%, rgba(255,255,255,.062) 0%, rgba(255,255,255,.033) 45%, transparent 94%)}
/* «Преимущества» отделены от «Направлений» (запрос «нижнее свечение приглушить на тон»):
   ВЕРХНИЙ засвет остался прежним .062/.033, а НИЖНИЙ опущен на ступень до .042/.013 — это
   ровно тот шаг, которым в этом файле уже мерялся «тон» (им же раньше поднимали оба засвета).
   «Направления» обязаны сохранить прежнюю яркость обоих, поэтому бывшее общее правило пришлось
   разбить на два: одним селектором разная яркость нижнего засвета уже не выражается. */
.sec--halo .cell:hover{
   background:radial-gradient(78% 48% at 62% 0%, rgba(255,255,255,.062) 0%, rgba(255,255,255,.033) 45%, transparent 94%),
              radial-gradient(78% 48% at 38% 100%, rgba(255,255,255,.042) 0%, rgba(255,255,255,.013) 45%, transparent 94%)}
/* Окантовка — градиентная, от тёмного к светлому по той же оси 160deg, что и заливки в этом
   макете: «стеклянная» кромка, которая гаснет в одном углу и набирает свет в противоположном.
   Одним свойством border такое не делается, поэтому рамку рисует ::after: заливка-градиент +
   маска, вычитающая внутреннюю область (mask-composite:exclude) — остаётся ровно контур 1px.
   Сам border при этом обнулён по цвету (border-color:transparent), иначе поверх градиента
   виднелась бы вторая, сплошная кромка.
   БАГ, который тут уже был и почему сделано именно так (26.07): сначала кольцо стояло
   inset:0 при overflow:hidden у карточки — и НИЖНЯЯ кромка пропадала. Причина не в цвете
   (внизу как раз максимальная альфа .30), а в дробных высотах карточек: 229.459px и
   208.189px. Кольцо лежало вплотную к padding-box, а overflow:hidden режет ровно по этой
   дробной границе, поэтому нижняя полоса 1px попадала на неполный пиксель и стиралась.
   На наведении карточка масштабируется 1.03, граница уходит с дробной позиции — и кромка
   появлялась, отсюда «на hover нормально, в покое нет».
   Лечение: overflow:visible у карточки (в этом блоке клипить больше нечего — блик, трещины
   и фото давно сняты) + inset:-1px, чтобы кольцо легло ровно на border-box и вообще не
   зависело от границы клипа. Радиус оставлен inherit: формально внешний радиус должен быть
   на 1px больше, но при 3px разница не читается.
   Поднимать контент через >*{z-index:1} не нужно: маска делает центр полностью прозрачным,
   накрыть текст этот слой физически не может. */
.sec--halo .cell::after,.sec--laws .cell::after{content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;
   pointer-events:none;
   background:linear-gradient(160deg, rgba(255,255,255,.04) 0%, rgba(255,255,255,.12) 48%, rgba(255,255,255,.30) 100%);
   -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}
/* На наведении подложка «подсвечивается сверху мягким белым светом» (запрос 26.07):
   радиальный градиент — светлее всего у верхней кромки, к низу и к бокам уходит в ноль.
   Взят радиальный, а не линейный: линейный дал бы ровную плёнку по всей ширине, а нужен
   именно источник сверху с мягким спадом.
   Подбор шёл в три шага (каждый раз «мягче и меньше»): 120%×82% at 50% / .10→.035 →
   92%×58% at 50% / .055→.018 → текущее 78%×48% at 62% / .042→.013, спад растянут до 94%.
   Источник сдвинут вправо (62% вместо 50%) — по просьбе.
   Это единственная заливка, которая осталась у блоков: в покое подложка полностью прозрачна.
   ВАЖНО: заливка здесь ещё и перебивает глобальное .cell:hover{background:#171A24}, так что
   убирать её нельзя — только менять значения. Крутилки — три альфы.
   Сами значения живут в общем правиле .sec--halo .cell:hover, .sec--laws .cell:hover выше;
   отдельного правила для «Направлений» больше нет — блоки одинаковые. */

/* Блок «Что получают наши клиенты»: сетка сверху, растворяется к центру блока полукругом
   (radial-gradient «ellipse at top» — видна только нижняя половина эллипса, растущего
   от верхнего края вниз, отсюда и форма полукруга), в центре сетки — еле заметный синий засвет. */
.sec--results{position:relative;overflow:hidden}
/* Сетка едет ВМЕСТЕ с блоком (запрос 26.07: «убери параллакс у подложки»). Раньше слой был
   на background-attachment:fixed — прибит к вьюпорту, контент шёл сквозь него, и это читалось
   как параллакс. Теперь scroll + якорь 0 0 от собственного верхнего левого угла блока: сетка
   стоит относительно контента, при скролле не смещается.
   ЦЕНА: этот слой выпал из общей фазовой стыковки с сетками хиро/рисков/госзакупок — те
   по-прежнему fixed и считают фазу от вьюпорта, а этот от края блока. Шаг тот же
   (--grid-pitch), но вертикальные линии «Результатов» с ними уже не совпадут.
   Прежний JS-параллакс --results-y удалён ещё раньше (transform ломал fixed) — не вернулся. */
.sec--results::before{content:"";position:absolute;left:0;right:0;top:0;height:280px;z-index:0;pointer-events:none;
   background-image:linear-gradient(var(--grid-line) var(--grid-hw),transparent var(--grid-hw)),
                     linear-gradient(90deg,var(--grid-line) var(--grid-vw),transparent var(--grid-vw));
   background-size:var(--grid-pitch) var(--grid-pitch);background-attachment:scroll;background-position:0 0;
   -webkit-mask-image:radial-gradient(60% 100% at 50% 0%,#000 0%,transparent 75%);
           mask-image:radial-gradient(60% 100% at 50% 0%,#000 0%,transparent 75%)}
/* Засвет «магнитится» к курсору: JS (см. «МАГНИТНЫЙ ЗАСВЕТ» в конце файла) двигает
   --glow-x/--glow-y, пока курсор в радиусе притяжения; дальше — отлипает и едет обратно
   к якорю (0,0). transition один на оба случая — и подтягивание, и возврат одинаково плавные.
   Крупнее, размытее и прозрачнее прежнего — мягкое разлитое пятно, а не яркое пятно. */
.sec--results::after{content:"";position:absolute;left:50%;top:-60px;width:640px;height:340px;
   transform:translate(calc(-50% + var(--glow-x,0px)),var(--glow-y,0px));z-index:0;pointer-events:none;
   background:radial-gradient(closest-side, rgba(92,130,247,.1) 0%, transparent 75%);
   filter:blur(48px);transition:transform .5s cubic-bezier(.2,.8,.2,1)}
.sec--results>*{position:relative;z-index:1}
/* блок рисков: заголовки-последствия красным; стрелка «тычет» в свой текст при наведении */
.sec--risks .cell__k{color:var(--red)}
.cell--link{cursor:pointer}
.cell--link .cell__go{margin-top:16px;font:500 12px/1 var(--mono);letter-spacing:.1em;color:var(--acc);transition:transform .2s}
.cell--link:hover .cell__go{transform:translateX(4px)}

/* ── ПРОЦЕСС (шаги) ── */
.steps{position:relative;display:grid;grid-template-columns:repeat(5,1fr);gap:0}
/* путь между иконками: тянется от центра первой до центра последней (колонка = 20% → центры на 10% и 90%) */
.steps::before,.steps::after{content:"";position:absolute;top:31px;left:10%;right:10%;height:2px;pointer-events:none}
.steps::before{background:var(--line);z-index:0}
/* бегущая подсветка по пути слева направо */
.steps::after{z-index:1;background:linear-gradient(90deg,transparent,var(--acc),transparent);
   background-size:38% 100%;background-repeat:no-repeat;animation:pathflow 3.4s linear infinite}
@keyframes pathflow{0%{background-position:-38% 0}100%{background-position:138% 0}}
@media(max-width:820px){.steps{grid-template-columns:repeat(2,1fr);gap:30px 0}
  .steps::before,.steps::after{display:none}}
@media(max-width:500px){.steps{grid-template-columns:1fr}}
.step{padding:0 12px;text-align:center;position:relative;z-index:2}
/* плашка прозрачна на 85% (заливка .15), на ховере до 60% (заливка .40) + блестящая окантовка */
.step__ic{width:64px;height:64px;margin:0 auto 18px;border-radius:var(--r);display:grid;place-items:center;
   background:rgba(92,130,247,.15);border:1px solid rgba(124,154,255,.35);position:relative;z-index:2;
   -webkit-backdrop-filter:blur(10px) saturate(140%);backdrop-filter:blur(10px) saturate(140%);
   box-shadow:0 10px 28px -10px rgba(92,130,247,.35);
   transition:background .3s,border-color .3s,box-shadow .3s,transform .3s}
/* увеличение при наведении усилено 1.08 → 1.18 (запрос 26.07, заодно с карточками
   «Направлений работы»). Здесь запас большой: плашка 64px стоит по центру колонки шире
   200px, соседей рядом нет, поэтому упереться можно только в вкус, не в геометрию. */
.step:hover .step__ic{background:rgba(92,130,247,.40);border-color:rgba(124,154,255,.5);
   box-shadow:0 10px 30px -8px rgba(92,130,247,.5);transform:scale(1.18)}
/* переливающаяся окантовка: градиент, обрезанный маской в рамку 1px */
.step__ic::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;
   background:linear-gradient(90deg,transparent,var(--acc),#bcccff,var(--acc),transparent);
   background-size:220% 100%;
   -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 .3s}
.step:hover .step__ic::after{opacity:1;animation:borderflow 50s linear infinite}
/* 50s на полный проход (было 1.8s) — за обычные пару секунд наведения окантовка почти не
   успевает сдвинуться, читается как статичный переливающийся край, а не бегущая полоса. */
@keyframes borderflow{0%{background-position:220% 0}100%{background-position:-220% 0}}
.step__ic svg{width:30px;height:30px;fill:none;stroke:#fff;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.step h3{font-weight:700;font-size:1.1rem;letter-spacing:-.02em;margin-bottom:8px}
.step p{color:var(--tx2);font-size:14px;line-height:1.6}

/* ── анимации иконок процесса ── */
.ic-mail .flap{transform-box:fill-box;transform-origin:center top;animation:mailflap 3.2s ease-in-out infinite}
@keyframes mailflap{0%,55%,100%{transform:scaleY(1)}25%,35%{transform:scaleY(.14)}}
.ic-search .glass{animation:scan 3.6s ease-in-out infinite}
@keyframes scan{0%,100%{transform:translate(0,0)}25%{transform:translate(2.5px,-2px)}50%{transform:translate(-2.5px,1.5px)}75%{transform:translate(2px,2px)}}
.ic-doc line{stroke-dasharray:12;stroke-dashoffset:12;animation:linedraw 3.6s ease-in-out infinite}
.ic-doc line:nth-of-type(2){animation-delay:.22s}
.ic-doc line:nth-of-type(3){animation-delay:.44s}
@keyframes linedraw{0%{stroke-dashoffset:12}30%,72%{stroke-dashoffset:0}96%,100%{stroke-dashoffset:12}}
.ic-trophy{animation:bob 3s ease-in-out infinite}
@keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
.ic-check .tick{stroke-dasharray:16;stroke-dashoffset:16;animation:tickdraw 3.2s ease-in-out infinite}
@keyframes tickdraw{0%{stroke-dashoffset:16}35%,78%{stroke-dashoffset:0}96%,100%{stroke-dashoffset:16}}

/* ── БЛОК «НЕ ПОДХОДИТ» ── */
.nf__hd{display:flex;align-items:center;gap:10px;margin-bottom:22px}
.nf__hd h2{font-size:clamp(1.3rem,2.4vw,1.8rem)}
.nf-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;background:none;border:0}
@media(max-width:860px){.nf-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.nf-grid{grid-template-columns:1fr}}
/* Плашка приведена к рецепту «Направления работы» (запрос): заливки в покое нет, рамка
   невидима — её роль играет градиентное кольцо ::after (см. ниже), фрост 5px в покое / 10px
   на hover, на hover — два белых точечных засвета (тот же common-рецепт .sec--laws .cell:hover).
   Тряска (nfCardShake) НЕ трогается — она держит только transform, а новый hover-рецепт
   держит background/backdrop-filter/box-shadow: разные свойства, конфликта нет (тот же приём,
   что уже описан в файле для .fade-up.rv-stagger — «появление на animation, интерактив на
   transition, они не пересекаются свойствами»). transform остаётся в transition — он
   отвечает за плавный возврат в scale(1) ПОСЛЕ ухода курсора, когда animation снимается. */
/* Лёгкая красная подкраска стекла (#DD5955 при альфе .05) живёт ТОЛЬКО в :hover (запрос) —
   в покое подложка снова полностью прозрачна. Появление плавное само собой: background уже
   есть в transition ниже, так что тон наплывает за .3s, а не возникает щелчком.
   Тон намеренно НЕ взят из --red (#F7635C): тот ярче и зарезервирован под крестики/знак
   внимания, здесь нужен приглушённый. */
.nf-item{position:relative;overflow:visible;border-radius:var(--r);
   background:transparent;border:1px solid transparent;
   -webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);
   will-change:backdrop-filter;
   padding:20px;display:flex;gap:12px;align-items:flex-start;font-size:13.5px;color:var(--tx2);line-height:1.5;
   transition:transform .3s ease,box-shadow .3s ease,background .3s ease,backdrop-filter .3s ease}
.nf-item::after{content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;
   pointer-events:none;
   background:linear-gradient(160deg, rgba(255,255,255,.04) 0%, rgba(255,255,255,.12) 48%, rgba(255,255,255,.30) 100%);
   -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}
/* При наведении — сначала увеличение, ПОТОМ дребезг (запрос): 0→15% — чистый рост scale
   до 1.04 без единого px по translateX, тряска стартует только после этого, на уже
   увеличенной карточке. Раньше (первая правка) рост и тряска шли ОДНОВРЕМЕННО с 8% кадра —
   это делало увеличение мгновенным, но не давало ему читаться как отдельная первая фаза,
   как сейчас просят. 15% от .7s — это ~105мс, заметная, но короткая фаза роста.
   forwards держит финальный кадр, пока курсор не ушёл — тогда transition выше плавно вернёт
   как было. Рядом с тряской ещё и подсветка. */
.nf-item:hover{animation:nfCardShake .7s ease-out forwards;
   background:radial-gradient(78% 48% at 62% 0%, rgba(255,255,255,.042) 0%, rgba(255,255,255,.013) 45%, transparent 94%),
              radial-gradient(78% 48% at 38% 100%, rgba(255,255,255,.042) 0%, rgba(255,255,255,.013) 45%, transparent 94%),
              rgba(221,89,85,.05);
   -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
@keyframes nfCardShake{
   0%{transform:scale(1)    translateX(0)}
   15%{transform:scale(1.04) translateX(0)}
   25%{transform:scale(1.04) translateX(-6px)}
   35%{transform:scale(1.04) translateX(5px)}
   45%{transform:scale(1.04) translateX(-4px)}
   55%{transform:scale(1.04) translateX(3px)}
   65%{transform:scale(1.04) translateX(-2px)}
   75%{transform:scale(1.04) translateX(1px)}
   100%{transform:scale(1.04) translateX(0)}}
.nf-item i{flex:none;width:20px;height:20px;border-radius:50%;display:grid;place-items:center;
   background:rgba(247,99,92,.14);color:var(--red);font-style:normal;font-size:12px;font-weight:700}
/* ✕ крутится при наведении/тапе (класс .spin вешает JS — см. «АНИМАЦИИ ИКОНОК» в конце
   файла, чтобы работало и на тач-устройствах, где :hover ненадёжен), несколько секунд,
   резкая дуга замедления в конце — «постепенно останавливается», а не обрывается. */
.nf-item i.spin{animation:nfIconSpin 2.4s cubic-bezier(.11,.82,.24,1) 1}
@keyframes nfIconSpin{to{transform:rotate(1080deg)}}
.nf__hd .warn{flex:none;transition:transform .3s ease,filter .3s ease}
/* Треугольник трясётся пару секунд при наведении на заголовок блока, оседая крупнее и ярче
   (forwards держит последний кадр, пока курсор не ушёл — тогда transition плавно вернёт как было). */
.nf__hd:hover .warn{animation:nfWarnShake 1.8s ease-out forwards}
@keyframes nfWarnShake{
   0%{transform:rotate(0) scale(1);filter:brightness(1)}
   8%{transform:rotate(-10deg) scale(1.1);filter:brightness(1.4)}
   16%{transform:rotate(9deg) scale(1.1)}
   24%{transform:rotate(-9deg) scale(1.1)}
   32%{transform:rotate(8deg) scale(1.1)}
   40%{transform:rotate(-7deg) scale(1.1)}
   48%{transform:rotate(6deg) scale(1.1)}
   56%{transform:rotate(-5deg) scale(1.1)}
   64%{transform:rotate(4deg) scale(1.1)}
   72%{transform:rotate(-3deg) scale(1.1)}
   80%{transform:rotate(2deg) scale(1.1)}
   88%{transform:rotate(-1deg) scale(1.1)}
   100%{transform:rotate(0) scale(1.1);filter:brightness(1.3)}}

/* ── ПАНЕЛЬ CTA (стекло) ── */
.act{margin-top:clamp(28px,4vw,44px);border:1px solid rgba(255,255,255,.16);border-radius:var(--r);
     background:radial-gradient(80% 140% at 12% 20%, rgba(92,130,247,.13) 0%, transparent 62%),rgba(255,255,255,.05);
     -webkit-backdrop-filter:blur(20px) saturate(135%);backdrop-filter:blur(20px) saturate(135%);
     padding:clamp(20px,3vw,32px) clamp(24px,3.6vw,40px);display:grid;grid-template-columns:minmax(0,1fr) auto;gap:36px;align-items:center}
@media(max-width:860px){.act{grid-template-columns:1fr;gap:20px;justify-items:start}}
/* заголовок внутри плашки — меньше обычного h2 (это акцент внутри блока, не заголовок секции) */
.act h2{margin-bottom:10px;max-width:none;font-size:clamp(1.25rem,2vw,1.7rem)}
.act p{color:var(--tx2);max-width:48ch;font-size:15px}

/* ── БЕГУЩИЕ ЛОГОТИПЫ ── */
.mq{overflow:hidden;position:relative;padding:26px 0}
/* Линия закрывает только блок КЛИЕНТОВ (.mq--clients) — класс .mq общий для двух разных
   маркиз (клиенты и производители), border-bottom на общем .mq зацепил бы обе. Не через
   .edge-bottom: тот класс тоже метит ::after, а он у .mq уже занят градиентом-затемнением
   по правому краю (см. ниже) — та же ловушка с общим псевдоэлементом, что уже была у
   .sec--risks/.edge-top. .mq и так на всю ширину экрана (вне .wrap), обычный border
   справляется без 100vw-трюка. */
.mq--clients{border-bottom:1px solid var(--line)}
.mq__lbl{text-align:center;font:500 10px/1 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--tx3);margin-bottom:18px}
/* затемнение по краям доведено до ширины контентной колонки (--max):
   логотипы видны только в пределах контента, за ним — фон */
.mq::before,.mq::after{content:"";position:absolute;top:0;bottom:0;z-index:2;pointer-events:none;
   width:max(70px, calc((100% - var(--max))/2 + 60px))}
.mq::before{left:0;background:linear-gradient(90deg,var(--bg) calc(100% - 60px),transparent)}
.mq::after{right:0;background:linear-gradient(-90deg,var(--bg) calc(100% - 60px),transparent)}
.mq__track{display:flex;align-items:center;width:max-content;animation:mqmove 90s linear infinite}
.mq__track:hover{animation-play-state:paused}
.mq__track.rev{animation-duration:105s;animation-direction:reverse}
.mq__i{display:flex;align-items:center;justify-content:center;padding:0 34px;height:50px;flex-shrink:0;opacity:.55;transition:opacity .25s}
.mq__i:hover{opacity:1}
.mq__i img{height:28px;width:auto;max-width:130px;object-fit:contain;filter:brightness(0) invert(1)}
.mq__i span{font-weight:800;font-size:17px;letter-spacing:.04em;color:var(--tx2);text-transform:uppercase}
@keyframes mqmove{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* ── ИМПОРТОЗАМЕЩЕНИЕ ── */
/* Огромные фоновые слова — тот же приём, что вотермарка «ИТ·РЕЕСТР» в подвале, но по центру
   блока (не подрезаны снизу) И обрезаны по границам САМОГО БЛОКА — за линией сверху/снизу
   их быть не должно, только параллакс-движение внутри секции. Секция сама — «.wrap» с
   max-width, поэтому overflow:hidden прямо на ней не годится (обрежет по краю контентной
   колонки, а не экрана). Решение — отдельная накладка .imp-wrap: по ширине 100vw (весь экран,
   как полосы .sec--risks) — горизонтальный выход к краям остаётся, а по высоте top:0/bottom:0
   ровно как у секции (auto-высота секции корректно резолвится браузером для абсолютного
   потомка) + overflow:hidden — вертикально режет строго по границам блока. */
.sec--import{position:relative}
/* Селектор с доп. классом (не просто .imp-wrap) — иначе .sec--import>*{position:relative}
   ниже по каскаду перебивает position:absolute той же специфичностью, побеждая по порядку
   (та же ловушка, что уже была с .sec--risks::before/.edge-top::before, см. хендовер). */
.sec--import>.imp-wrap{position:absolute;left:50%;top:0;bottom:0;width:100vw;transform:translateX(-50%);
   overflow:hidden;pointer-events:none;z-index:0}
/* --imp-y — вертикальное смещение слов от параллакса (двигает JS при скролле, см. секцию
   «ПАРАЛЛАКС ИМПОРТОЗАМЕЩЕНИЯ» в конце файла) — переменная объявлена на .sec--import
   (родитель), а читают её потомки внутри .imp-wrap, т.к. CSS custom properties наследуются;
   в покое / без JS остаётся 0px. */
.imp-wrap::before{content:"ИМПОРТОЗАМЕЩЕНИЕ";position:absolute;left:50%;top:50%;
   transform:translate(-50%,calc(-50% + var(--imp-y,0px)));
   pointer-events:none;white-space:nowrap;
   font-weight:900;font-size:9.5vw;letter-spacing:-.04em;text-transform:uppercase;
   color:rgba(255,255,255,.05);line-height:1}
.sec--import>*{position:relative;z-index:1}
.subst{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:14px;background:none;border:0}
/* плашки — жидкое стекло: сильно прозрачнее обычного (карточки почти сливаются с фоном секции,
   сквозь них должны читаться и слово-вотермарка, и полосы) — тот же блюр, что у risks/каталога,
   но альфа заметно ниже. */
.subst .cell{border:1px solid rgba(255,255,255,.12);border-radius:var(--r);
   background:linear-gradient(160deg, rgba(255,255,255,.05) 0%, rgba(255,255,255,.012) 100%);
   -webkit-backdrop-filter:blur(16px) saturate(140%);backdrop-filter:blur(16px) saturate(140%)}
.subst .cell{padding:24px 22px}
.subst .cell{position:relative;overflow:hidden;transition:transform .3s ease,box-shadow .3s ease}
/* При наведении — чуть крупнее (не обрезается родителем: overflow:hidden только у самой
   карточки, не у сетки) + задняя подсветка, как у плиток площадок в «Тендерной работе».
   Подсветка ослаблена 26.07: радиус 22px → 14px, альфа .14 → .07. Ровно вдвое по яркости
   и почти вдвое по размеху пятна — свечение читается как намёк, а не как ореол.
   Увеличение 1.03 не тронуто, просили только подсветку. */
.subst .cell:hover{transform:scale(1.03);box-shadow:0 0 14px rgba(92,130,247,.07)}
.subst .cell>*{position:relative;z-index:1}
.subst__cat{font-weight:800;font-size:.95rem;text-transform:uppercase;letter-spacing:-.01em;margin-bottom:14px}
/* Карточка сразу полного размера — место под скрытые строки зарезервировано всегда
   (никакого max-height/схлопывания), меняется только opacity/цвет/clip-path, высота карточки
   не скачет. Раскрывает не :hover, а класс .is-open (ставит JS при первом наведении —
   см. «РАСКРЫТИЕ КАРТОЧЕК ИМПОРТОЗАМЕЩЕНИЯ» в конце файла): один раз открылось — остаётся
   открытым, пока не обновить страницу (:hover тут не годится — он гаснет при уходе курсора). */
.subst__old{font-size:13px;color:var(--tx);line-height:1.55;
   text-decoration-line:line-through;text-decoration-color:transparent;
   transition:color .35s ease,text-decoration-color .35s ease}
.subst .cell.is-open .subst__old{color:var(--tx3);text-decoration-color:rgba(163,168,182,.45)}
.subst__ar{font:400 9.5px/1 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--tx3);
   margin-top:11px;opacity:0;transform:translateY(-8px);
   transition:opacity .3s ease .15s,transform .3s ease .15s}
.subst .cell.is-open .subst__ar{opacity:1;transform:translateY(0)}
/* Новые вендоры — без white-space:nowrap: если не помещается по ширине карточки, переносится
   на вторую строку как обычный текст. min-height резервирует место под ДВЕ строки заранее
   (даже когда реально влезает в одну) — иначе перенос при раскрытии сам сдвинул бы высоту
   карточки, а её менять нельзя. «Печатается» — не посимвольно (это требовало бы nowrap и
   ломало перенос), а слева направо через clip-path — работает и на перенесённом тексте. */
.subst__new{display:block;font-size:13px;color:var(--acc);line-height:1.6;font-weight:500;
   margin-top:11px;min-height:3.2em;opacity:0;transform:translateY(-8px);
   clip-path:inset(0 100% 0 0);
   transition:opacity .3s ease .4s,transform .3s ease .4s,clip-path .5s ease .55s}
.subst .cell.is-open .subst__new{opacity:1;transform:translateY(0);clip-path:inset(0 0 0 0)}

/* ── ПЛОЩАДКИ / РЕЗУЛЬТАТЫ ── */
.two{display:grid;grid-template-columns:1fr 1fr;gap:clamp(32px,5vw,64px);align-items:center}
@media(max-width:860px){.two{grid-template-columns:1fr;gap:36px}}
.plat{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
/* гласморфные плашки: стекло с блюром, на ховере — переливающаяся окантовка */
.plat div{position:relative;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.07);
   -webkit-backdrop-filter:blur(14px) saturate(140%);backdrop-filter:blur(14px) saturate(140%);
   border-radius:var(--r);padding:16px 8px;text-align:center;font-size:13px;font-weight:600;color:var(--tx2);
   transition:background .3s,color .3s,box-shadow .3s,transform .3s}
.plat div:hover{background:rgba(255,255,255,.12);color:var(--tx);box-shadow:0 0 22px rgba(92,130,247,.28);transform:scale(1.04)}
.plat div::after{content:"";position:absolute;inset:0;border-radius:inherit;padding:1px;pointer-events:none;
   background:linear-gradient(90deg,transparent,var(--acc),#bcccff,var(--acc),transparent);
   background-size:220% 100%;
   -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 .3s}
.plat div:hover::after{opacity:1;animation:borderflow 50s linear infinite}
.res{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;background:none;border:0}
/* «Результаты в цифрах» — тот же единый рецепт (см. .sec--risks). Вычищено: рамка на
   var(--line) вместо .12, hover с background:transparent (он существовал только чтобы
   погасить глобальное .cell:hover{background:#171A24} — теперь эту роль играет собственная
   заливка рецепта) и transition на background. Два правила .res .cell слиты в одно —
   padding остался свой, 32px 26px: под крупные цифры .res__num нужен больший внутренний
   отступ, чем 24px 22px у «Импортозамещения». Это вёрстка, а не эффект. */
.res .cell{position:relative;overflow:hidden;border-radius:var(--r);padding:32px 26px;
   border:1px solid rgba(255,255,255,.12);
   background:linear-gradient(160deg, rgba(255,255,255,.05) 0%, rgba(255,255,255,.012) 100%);
   -webkit-backdrop-filter:blur(16px) saturate(140%);backdrop-filter:blur(16px) saturate(140%);
   transition:transform .3s ease,box-shadow .3s ease,background .3s ease}
/* Подкраска плашки акцентным синим на наведении: --acc #5C82F7 при альфе .05.
   Точечные засветы (два радиальных пятна «как в Направлениях») здесь БЫЛИ и убраны по запросу —
   в «Результатах» на наведении остаётся только подкраска. Если понадобится вернуть, рецепт
   живёт в .sec--laws .cell:hover ниже по файлу.
   ПОРЯДОК СЛОЁВ: стеклянный градиент 160deg обязан идти первым, цвет — последним (цвет в
   background всегда последний). Если задать только цвет, градиент затрётся и плашка на
   наведении потеряет своё «стекло».
   background вернули в transition — выше по файлу он был оттуда убран как ненужный, теперь
   он снова при деле: без него тон возникал бы щелчком, а не наплывал за .3s.
   box-shadow (задняя подсветка 14px) — отдельный эффект, его не трогали. */
.res .cell:hover{transform:scale(1.03);box-shadow:0 0 14px rgba(92,130,247,.07);
   background:linear-gradient(160deg, rgba(255,255,255,.05) 0%, rgba(255,255,255,.012) 100%),
              rgba(92,130,247,.05)}
@media(max-width:700px){.res{grid-template-columns:1fr}}
.res__num{font-weight:900;font-size:2.8rem;line-height:1;letter-spacing:-.04em;color:var(--acc);margin-bottom:10px}

/* ── ТАБЛИЦА СРАВНЕНИЯ ── */
.tbl-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
table.cmp{border-collapse:collapse;width:100%;min-width:560px;border:1px solid var(--line)}
table.cmp th{padding:14px 20px;text-align:left;font:500 10px/1.3 var(--mono);letter-spacing:.14em;text-transform:uppercase;color:var(--tx3);border-bottom:1px solid var(--line);background:var(--surf)}
table.cmp th:nth-child(2){color:var(--red)}
table.cmp th:nth-child(3){color:var(--acc)}
table.cmp td{padding:13px 20px;font-size:13.5px;color:var(--tx2);border-bottom:1px solid var(--line2);line-height:1.5;
   transition:padding .25s ease,font-size .25s ease,background .25s ease}
table.cmp td:nth-child(3){color:var(--tx)}
table.cmp tr:last-child td{border-bottom:0}
/* «Увеличивать строки» — не transform:scale на <tr>: со border-collapse рамки соседних
   ячеек рассинхронизируются и на стыке остаётся видимый артефакт-щель. Растим через
   padding+font-size самих ячеек — таблице ничего не режет. */
table.cmp tbody tr:hover td{padding-top:17px;padding-bottom:17px;font-size:14.5px;background:rgba(255,255,255,.04)}
.cmp .bad::before{content:"✕ ";color:var(--red);font-weight:700}
.cmp .good::before{content:"✓ ";color:var(--acc);font-weight:700}

/* ── ФОРМА ── */
.form-box{background:rgba(255,255,255,.04);border:1px solid var(--line);border-radius:var(--r);
   padding:clamp(26px,4vw,44px);max-width:680px;margin:0 auto;
   -webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}
.form-note-top{background:rgba(92,130,247,.08);border-left:2px solid var(--acc);padding:12px 16px;font-size:13px;color:var(--tx2);line-height:1.6;margin-bottom:24px;border-radius:0 var(--r) var(--r) 0}
.fg{margin-bottom:16px}
.fg>label{display:block;font:500 10px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--tx3);margin-bottom:8px}
.fg input,.fg select,.fg textarea{width:100%;background:rgba(255,255,255,.03);border:1px solid var(--line);border-radius:var(--r);
   padding:12px 14px;font:400 14px/1.4 var(--sans);color:var(--tx);outline:none;transition:border-color .2s,box-shadow .2s;appearance:none}
.fg textarea{resize:vertical;min-height:78px}
.fg input::placeholder,.fg textarea::placeholder{color:var(--tx3)}
.fg input:focus,.fg select:focus,.fg textarea:focus{border-color:var(--acc);box-shadow:0 0 0 3px rgba(92,130,247,.14)}
.fg select option{background:#1A1D26;color:var(--tx)}
.frow{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:560px){.frow{grid-template-columns:1fr}}
.radio-group{display:grid;grid-template-columns:1fr 1fr;gap:8px}
@media(max-width:560px){.radio-group{grid-template-columns:1fr}}
.radio-label{display:flex;align-items:flex-start;gap:9px;background:var(--surf);border:1px solid var(--line);border-radius:var(--r);
   padding:11px 13px;cursor:pointer;transition:border-color .2s,background .2s,color .2s;font-size:13px;line-height:1.4;color:var(--tx2)}
.radio-label:hover{border-color:rgba(92,130,247,.4)}
.radio-label input{display:none}
.radio-box{width:13px;height:13px;flex:none;border:1px solid var(--tx3);margin-top:2px;border-radius:2px;transition:.2s}
.radio-label:has(input:checked){border-color:var(--acc);background:rgba(92,130,247,.08);color:var(--tx)}
.radio-label:has(input:checked) .radio-box{background:var(--acc);border-color:var(--acc)}
.budget-warning{display:none;background:rgba(255,255,255,.04);border-left:2px solid var(--tx3);padding:11px 14px;font-size:13px;color:#A3A8B6;margin-bottom:16px;line-height:1.5;border-radius:0 var(--r) var(--r) 0}
.budget-warning.show{display:block}
.form-note{font:400 11px/1.5 var(--mono);color:var(--tx3);text-align:center;margin-top:14px}
.form-note a{color:var(--tx2);text-decoration:underline}
.success-box{display:none;text-align:center;padding:40px 20px}
.success-box h3{font-weight:900;font-size:1.5rem;text-transform:uppercase;letter-spacing:-.03em;color:var(--acc);margin-bottom:10px}
.success-box p{color:var(--tx2);font-size:14px;line-height:1.6}

/* ── ВНУТРЕННИЕ СТРАНИЦЫ ── */
.page{display:none}
.page.active{display:block;animation:pin .3s ease}
@keyframes pin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.phero{position:relative;overflow:hidden;padding:clamp(48px,7vw,86px) 0 clamp(36px,5vw,60px);
   background:radial-gradient(60% 100% at 50% 0%, rgba(92,130,247,.08) 0%, transparent 60%)}
.phero h1{font-size:clamp(1.9rem,4.4vw,3.2rem)}
.phero .lede{margin-top:6px}
.note-line{border:1px solid var(--line);border-left:2px solid var(--acc);border-radius:0 var(--r) var(--r) 0;
   padding:12px 16px;font-size:13.5px;color:var(--tx2);line-height:1.6;margin:20px 0 30px;background:var(--surf);max-width:70ch}
.vgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}
.vcard{background:var(--bg);padding:14px 16px;font-size:13px;color:var(--tx2);display:flex;align-items:center;gap:10px;transition:background .2s}
.vcard:hover{background:#171A24;color:var(--tx)}
.vcard::before{content:"";width:5px;height:5px;background:var(--acc);border-radius:50%;flex:none}
.vcard b{margin-left:auto;font:400 11px/1 var(--mono);color:var(--tx3);white-space:nowrap;font-weight:400}
.cta-band{margin-top:44px;border:1px solid var(--line);border-radius:var(--r);
   background:radial-gradient(80% 160% at 15% 20%,rgba(92,130,247,.09),transparent 60%),var(--surf);
   padding:clamp(24px,4vw,40px);display:flex;flex-wrap:wrap;gap:20px;align-items:center;justify-content:space-between}
.cta-band p{color:var(--tx2);font-size:15px;max-width:52ch;line-height:1.6}

/* ── ПО (каталог) ── */
.sw-cat{font:600 11px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--acc);margin:32px 0 14px;padding-bottom:8px;border-bottom:1px solid var(--line)}
.sw-cat:first-of-type{margin-top:0}
.sw-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line)}
@media(max-width:768px){.sw-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:480px){.sw-grid{grid-template-columns:1fr}}
.sw-item{background:var(--bg);padding:16px 18px;transition:background .2s}
.sw-item:hover{background:#171A24}
.sw-item b{display:block;font-size:14px;font-weight:700;color:var(--tx);margin-bottom:3px}
.sw-item i{display:block;font-style:normal;font-size:11.5px;color:var(--tx3);margin-bottom:7px}
.sw-item p{font-size:12px;color:var(--tx2);line-height:1.5}

/* ── КОНТАКТЫ ── */
.cbox{background:var(--surf);border:1px solid var(--line);border-radius:var(--r);padding:24px}
.cbox .k{font:500 10px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--tx3);margin-bottom:12px}
.cbox a.tel{font-weight:700;font-size:17px;color:var(--tx)}
.mini-form{background:var(--surf);border:1px solid var(--line);border-radius:var(--r);padding:26px;display:flex;flex-direction:column;gap:12px;position:relative}
.mini-form input,.mini-form select,.mini-form textarea{width:100%;background:rgba(255,255,255,.03);border:1px solid var(--line);border-radius:var(--r);
   padding:12px 14px;font:400 14px/1.4 var(--sans);color:var(--tx);outline:none;transition:border-color .2s}
.mini-form input:focus,.mini-form select:focus,.mini-form textarea:focus{border-color:var(--acc)}
.mini-form textarea{resize:vertical;min-height:78px}
.mini-form select option{background:#1A1D26;color:var(--tx)}
.mini-form input::placeholder,.mini-form textarea::placeholder{color:var(--tx3)}

/* ── FAQ ── */
.faq{border:1px solid var(--line)}
.faq-item{border-bottom:1px solid var(--line)}
.faq-item:last-child{border-bottom:0}
.faq-q{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 24px;cursor:pointer;
   font-weight:700;font-size:15px;color:var(--tx);transition:background .2s}
.faq-q:hover{background:var(--surf)}
.faq-ic{width:18px;height:18px;flex:none;position:relative}
.faq-ic::before,.faq-ic::after{content:"";position:absolute;background:var(--acc);top:50%;left:50%}
.faq-ic::before{width:11px;height:1.6px;transform:translate(-50%,-50%)}
.faq-ic::after{width:1.6px;height:11px;transform:translate(-50%,-50%);transition:transform .3s,opacity .3s}
.faq-item.open .faq-ic::after{transform:translate(-50%,-50%) rotate(90deg);opacity:0}
.faq-item.open .faq-q{color:var(--acc)}
.faq-a{max-height:0;overflow:hidden;transition:max-height .35s ease,padding .3s}
.faq-item.open .faq-a{max-height:340px;padding:0 24px 18px}
.faq-a p{font-size:14px;color:var(--tx2);line-height:1.7}

/* ── ФУТЕР ── */
footer{position:relative;overflow:hidden;padding:40px 0 30px;background:rgba(92,130,247,.1)}
/* Огромный бренд-текст «ИТ·РЕЕСТР» на задней плашке подвала: И и Р уходят за края экрана,
   надпись утоплена вниз — видна только верхняя половина, цвет на 2–3 тона светлее заливки подвала */
footer::before{content:"ИТ·РЕЕСТР";position:absolute;left:50%;bottom:0;transform:translate(-50%,50%);
   z-index:0;pointer-events:none;white-space:nowrap;
   font-weight:900;font-size:24vw;letter-spacing:-.06em;text-transform:uppercase;
   color:rgba(255,255,255,.07);line-height:1}
footer>.wrap{position:relative;z-index:1}
.foot{display:flex;flex-wrap:wrap;justify-content:space-between;gap:24px}
.foot__logo{font-weight:900;font-size:19px;text-transform:uppercase;letter-spacing:-.04em;margin-bottom:6px}
.foot__logo b{color:var(--acc)}
.foot__reg{font-size:12.5px;color:var(--tx3);line-height:1.5}
.foot__c{display:flex;flex-direction:column;gap:6px;align-items:flex-end}
@media(max-width:640px){.foot__c{align-items:flex-start}}
.foot__c a{font:600 15px/1 var(--mono);color:var(--tx)}
.foot__email{-webkit-mask-image:linear-gradient(to right,#000 65%,transparent 92%);mask-image:linear-gradient(to right,#000 65%,transparent 92%);transition:-webkit-mask-image .35s,mask-image .35s}
.foot__email.is-revealed{-webkit-mask-image:none;mask-image:none}
.foot__c span{font:400 11px/1 var(--mono);color:var(--tx3)}
.foot__legal{display:flex;flex-wrap:wrap;align-items:center;gap:10px 20px;margin-top:26px;padding-top:20px}
.foot__legal .lbl{font:500 10px/1 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--tx3)}
.foot__legal a{font-size:13px;color:var(--tx2);border-bottom:1px solid transparent;transition:.2s}
.foot__legal a:hover{color:var(--acc);border-bottom-color:var(--acc)}

/* ── COOKIE ── */
.cookie{position:fixed;left:16px;right:16px;bottom:16px;max-width:720px;margin:0 auto;z-index:150;
   background:rgba(20,22,28,.96);border:1px solid var(--line);border-radius:var(--r);padding:16px 20px;
   display:flex;align-items:center;gap:18px;box-shadow:0 20px 60px rgba(0,0,0,.55);
   -webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);
   transform:translateY(180%);transition:transform .5s cubic-bezier(.16,1,.3,1)}
.cookie.show{transform:none}
.cookie p{font-size:12.5px;color:var(--tx2);line-height:1.55;flex:1}
.cookie p a{color:var(--acc)}
.cookie button{position:relative;overflow:hidden;isolation:isolate;color:#fff;border:1px solid var(--acc);background:transparent;padding:11px 24px;border-radius:var(--r);font:700 13px/1 var(--sans);cursor:pointer;white-space:nowrap;transition:color .35s,transform .35s}
.cookie button::before{content:"";position:absolute;inset:0;z-index:-2;background:var(--acc)}
.cookie button::after{content:"";position:absolute;inset:0;z-index:-1;background:#fff;transform:translateX(-101%);transition:transform .35s cubic-bezier(.4,0,.2,1)}
.cookie button:hover{color:var(--acc);transform:scale(1.04)}
.cookie button:hover::after{transform:translateX(0)}
@media(max-width:600px){.cookie{flex-direction:column;align-items:stretch;text-align:center}}

/* ── НАВЕРХ ── */
#btt{position:fixed;bottom:22px;right:22px;width:42px;height:42px;border-radius:var(--r);border:1px solid var(--line);
   background:rgba(20,22,28,.9);color:var(--tx);cursor:pointer;display:grid;place-items:center;z-index:130;
   opacity:0;transform:translateY(10px);pointer-events:none;transition:opacity .3s,transform .3s,background .2s,border-color .2s;
   -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
#btt.show{opacity:1;transform:none;pointer-events:auto}
/* масштаб вешаем на #btt.show:hover, а не на #btt:hover — у самой кнопки transform занят
   показом/скрытием (translateY(10px) → none), и правило без .show перебило бы состояние
   появления. В скрытом виде hover невозможен (pointer-events:none), так что .show достаточно. */
#btt:hover{background:var(--acc-d);border-color:var(--acc-d);color:#fff}
#btt.show:hover{transform:scale(1.08)}
#btt svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}

/* ── АНИМАЦИИ ПОЯВЛЕНИЯ ──
   СИСТЕМА, а не набор разных анимаций (запрос 26.07: «креативно, но системно и спокойно
   предсказуемо для корпоративного стиля; одна стилистика в разных дополняющих исполнениях»).
   Устройство: единые токены времени/кривой/дистанции + четыре исполнения одного языка.
   Кривая одна на все варианты — ease-out без отскока, движение всегда короткое и в одну
   сторону, ничего не крутится и не пружинит. Меняется только СПОСОБ проявления, а не характер.
     .fade-up            базовое: подъём на --rv-shift + проявление. Заголовки, одиночные блоки.
     .fade-up.rv-stagger дети выходят по очереди с шагом --rv-step. Сетки карточек: даёт ритм,
                         но порядок жёстко предсказуем — слева вправо, сверху вниз.
     .fade-up.rv-wipe    раскрытие «шторкой» слева через clip-path, БЕЗ смещения. Широкие
                         блоки во всю ширину (таблица, площадки) — им сдвиг по вертикали
                         читается как прыжок.
     .fade-up.rv-soft    только прозрачность, без движения. Текстоёмкие блоки (FAQ, форма):
                         самый спокойный вариант, ничего не отвлекает от чтения.
   Все четыре включаются ОДНИМ И ТЕМ ЖЕ классом .visible от существующего IntersectionObserver —
   отдельного JS не добавлено.
   Шаг стагтера задан на :nth-child, а не переменной из JS: детей в сетках максимум 8, зато
   разметка остаётся чистой и порядок виден прямо в CSS.
   КРИТИЧНО: сдвиг делается отдельным свойством translate, а НЕ transform. Первая версия была
   на transform — и убила hover-увеличение во всех сетках карточек: правило
   .fade-up.rv-stagger.visible>*{transform:none} имеет ту же специфичность 0-3-0, что и
   .sec--lit-cat .cell:hover{transform:scale(1.03)}, но объявлено ниже по файлу и побеждало
   порядком. translate — независимое свойство, оно с transform не конфликтует, поэтому подъём
   при появлении и масштаб при наведении живут одновременно.
   Если translate не поддерживается (старые браузеры), блок просто проявится без подъёма —
   opacity отработает всё равно, контент не останется скрытым. */
:root{
  --rv-dur:.62s;
  --rv-ease:cubic-bezier(.22,.65,.24,1);
  --rv-shift:18px;
  --rv-step:70ms;
}
/* ПОЯВЛЕНИЕ РАБОТАЕТ НА @keyframes, А НЕ НА transition — это принципиально.
   Первая версия была на transition, и она ломала плавность наведения во всех сетках карточек:
   правило .fade-up.rv-stagger>* задаёт transition целиком, специфичность у него 0-2-0 — та же,
   что у .sec--lit-cat .cell и прочих правил карточек, но объявлено оно ниже по файлу и
   побеждало порядком. В итоге у карточки в списке transition оставались только opacity и
   translate, а transform оттуда выпадал — и hover-увеличение срабатывало мгновенным скачком.
   («Направления работы» тогда уцелели случайно: там fade-up висит на самих карточках, а его
   специфичность 0-1-0 ниже правил карточки.)
   Теперь ответственность разделена: появление — animation, интерактив — transition. Они не
   пересекаются ни одним свойством, поэтому конфликт невозможен в принципе.
   Сдвиг внутри кейфреймов — свойством translate, а не transform: transform остаётся свободным
   для hover-масштаба. */
/* fill-mode = BACKWARDS, не both. Это принципиально, на both уже наступили 26.07:
   при both анимация после окончания продолжает «держать» свои значения на элементе, и она
   остаётся в силе бесконечно. Последствия были такие:
     • у площадок («Тендерная работа») навсегда оставался clip-path:inset(0 0 0 0) от шторки —
       он резал по границе контейнера и свечение box-shadow, и увеличение плитки на наведении;
     • у шагов «Процесса работы» залипшая анимация opacity/translate создавала контекст
       наложения, и линия-коннектор .steps::before (z-index:0) переставала уходить за плашки.
   При backwards анимация применяет значения ТОЛЬКО до старта (это нужно для задержек стагтера,
   иначе ребёнок мигнёт до своей очереди), а после финиша полностью отпускает элемент: clip-path
   и translate возвращаются к none, контекст наложения исчезает.
   Поэтому конечное состояние держим не кейфреймом, а обычным opacity:1 в самих правилах
   .visible — иначе после отпускания блок снова стал бы прозрачным. */
.fade-up{opacity:0}
/* opacity ОТДЕЛЕНА от animation: видимость держит обычное объявление (действует всегда, в т.ч.
   после .rv-done), а анимацию несёт правило с :not(.rv-done) — оно снимается по завершении.
   Иначе done-элемент терял бы opacity:1 вместе с анимацией и снова становился прозрачным. */
.fade-up.visible{opacity:1}
.fade-up.visible:not(.rv-done){animation:rvUp var(--rv-dur) var(--rv-ease) backwards}

/* исполнение 2 — последовательный выход детей.
   Контейнер НЕ делаем видимым заранее (была ошибка 26.07: стояло opacity:1). У контейнеров
   бывают собственные декорации — например линия-коннектор .steps::before/::after в «Процессе
   работы» — и при opacity:1 они проявлялись РАНЬШЕ детей: при скролле была видна голая линия
   без плашек, что читалось как «линия проходит сквозь карточки».
   Теперь контейнер прячется вместе с блоком (opacity:0 из .fade-up) и на появлении лишь мягко
   проявляется через rvSoft — без подъёма, иначе сдвиг сложился бы со сдвигом детей и они
   проехали бы двойную дистанцию. Селектор 0-4-0, чтобы перебить общее правило rvUp (0-3-0). */
.fade-up.rv-stagger>*{opacity:0}
.fade-up.rv-stagger.visible:not(.rv-done){animation:rvSoft var(--rv-dur) var(--rv-ease) backwards}
/* Анимация появления снимается НАВСЕГДА после первого проигрыша — класс .rv-done вешает JS
   по событию animationend (см. блок _fadeIO ниже). Это единственный надёжный способ развязать
   конфликт со свойством animation у интерактивных анимаций (тряска .nf-item:hover и т.п.):
   свойство animation на элемент одно, и пока правило появления держит на нём rvUp, hover-анимация
   не может его забрать (специфичность появления 0-3-0 против 0-2-0 у hover).
   Прошлые НЕВЕРНЫЕ попытки, чтобы не повторять:
     • both fill-mode → значения залипали после финиша (клип резал тени в «Тендерной»,
       контекст наложения ломал линию в «Процессе»);
     • :not(:hover) → на mouseleave rvUp навешивался ЗАНОВО и с задержкой стагтера+backwards
       карточка исчезала на время задержки. Это и был баг «исчезают после наведения».
   Механика rv-done — через :not(.rv-done), а НЕ через animation:none с высокой специфичностью.
   Тонкость каскада: правило появления для детей = 0-3-0, hover-тряска .nf-item:hover = 0-2-0.
   Если гасить появление отдельным .rv-done{animation:none}, оно должно быть >0-3-0 (иначе не
   перебьёт rvUp) — но тогда оно же >0-2-0 и задавит тряску на hover. Неразрешимо одним весом.
   Поэтому reveal-правило само СНИМАЕТСЯ с завершённых карточек через :not(.rv-done): как только
   JS повесил .rv-done, правило перестаёт матчиться, свойство animation свободно, и hover-тряска
   (единственное оставшееся правило animation) применяется при любой своей специфичности.
   .rv-done ставится ОДИН раз и не снимается — повторного запуска rvUp, как было с :not(:hover),
   не будет. */
.fade-up.rv-stagger.visible>*{opacity:1}
.fade-up.rv-stagger.visible>*:not(.rv-done){animation:rvUp var(--rv-dur) var(--rv-ease) backwards}
.fade-up.rv-stagger.visible>*:nth-child(1){animation-delay:0ms}
.fade-up.rv-stagger.visible>*:nth-child(2){animation-delay:calc(var(--rv-step)*1)}
.fade-up.rv-stagger.visible>*:nth-child(3){animation-delay:calc(var(--rv-step)*2)}
.fade-up.rv-stagger.visible>*:nth-child(4){animation-delay:calc(var(--rv-step)*3)}
.fade-up.rv-stagger.visible>*:nth-child(5){animation-delay:calc(var(--rv-step)*4)}
.fade-up.rv-stagger.visible>*:nth-child(6){animation-delay:calc(var(--rv-step)*5)}
.fade-up.rv-stagger.visible>*:nth-child(7){animation-delay:calc(var(--rv-step)*6)}
.fade-up.rv-stagger.visible>*:nth-child(8){animation-delay:calc(var(--rv-step)*7)}

/* исполнение 3 — «шторка» слева, без вертикального сдвига.
   clip-path задаётся ТОЛЬКО внутри кейфрейма и нигде больше: так после финиша он гарантированно
   вернётся к none и не будет обрезать тени/масштаб дочерних плиток. */
.fade-up.rv-wipe.visible{opacity:1}
.fade-up.rv-wipe.visible:not(.rv-done){animation:rvWipe var(--rv-dur) var(--rv-ease) backwards}

/* исполнение 4 — только проявление, самый спокойный */
.fade-up.rv-soft.visible{opacity:1}
.fade-up.rv-soft.visible:not(.rv-done){animation:rvSoft var(--rv-dur) var(--rv-ease) backwards}

@keyframes rvUp{from{opacity:0;translate:0 var(--rv-shift)}to{opacity:1;translate:none}}
@keyframes rvWipe{from{opacity:0;clip-path:inset(0 100% 0 0)}to{opacity:1;clip-path:inset(0 0 0 0)}}
@keyframes rvSoft{from{opacity:0}to{opacity:1}}

/* Блок появляется внахлёст на предыдущий (приподнят и чуть уменьшен) и мягко
   опускается на своё место. Секции идут позже по DOM, поэтому position:relative
   достаточно, чтобы рисоваться поверх предыдущей. Класс .rise-in вешает IO. */
#page-home>section.sec,main>section.sec{position:relative;opacity:0;
   transform:translateY(-62px) scale(.985);
   transition:opacity .5s ease,transform .8s cubic-bezier(.22,1,.36,1)}
#page-home>section.sec.rise-in,main>section.sec.rise-in{opacity:1;transform:none}

@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
  /* гасим ВСЕ четыре исполнения. Глобальное animation:none!important выше отключает кейфреймы,
     а вместе с ними и их конечное состояние (fill:both) — поэтому opacity и clip-path надо
     вернуть руками, иначе блок останется невидимым или обрезанным шторкой. */
  .fade-up,.fade-up.rv-stagger>*{opacity:1;translate:none}
  .fade-up.rv-wipe,.fade-up.rv-wipe.visible{clip-path:none}
  #page-home>section.sec,main>section.sec{opacity:1;transform:none}
  .hero-num span{animation:none;background-position:50% 50%}
}


/* ── СТРАХОВКА ДЛЯ СТРАНИЦ ПРОИЗВОДИТЕЛЕЙ ─────────────────────────
   На лендинге .fade-up и main>section.sec стартуют с opacity:0, и класс
   .visible вешает IntersectionObserver из index.html. На отдельной странице
   этого скрипта нет: без сброса ниже страница отдала бы 200 с полной
   разметкой и показала пустой экран — ошибка не видна ни в консоли, ни в логах.
   Файл собран автоматически из index.html, руками не править.
   ───────────────────────────────────────────────────────────────────── */
body.bp .fade-up,body.bp main>section.sec,body.bp #page-home>section.sec{
  opacity:1!important;transform:none!important;visibility:visible!important}
