/* ============================================================
   OKROUTER.RU — блоки лендинга «Готовый роутер с VPN»
   Подключается ПОСЛЕ styles.css и дополняет дизайн-систему.
   ============================================================ */

/* страница никогда не скроллится вбок — только внутренние карусели */
html{overflow-x:clip}

/* ---------- Герой: строка про скорость ---------- */
.hero__speednote{
  margin-top:16px; max-width:470px;
  font-size:14px; color:var(--muted); line-height:1.55;
}

/* ---------- Герой: режим «сеть OkRouter» ---------- */
.device[data-mode="alisa"] .device__glow{
  background:radial-gradient(60% 60% at 50% 45%,rgba(200,107,214,.3),rgba(124,108,245,0) 70%);
}
.device[data-mode="alisa"] .device__wave{color:var(--magenta)}
.device[data-mode="alisa"] .meter__fill{background:linear-gradient(90deg,var(--indigo-500),var(--magenta))}

/* ---------- Лента сервисов с логотипами ---------- */
.chip--svc{gap:9px; padding:0 16px 0 10px}
.chip--svc img{width:22px; height:22px; border-radius:6px; display:block}
.chip--svc i{display:none}

/* ---------- «Настроили до вас» — окно заводской настройки ---------- */
.setup{margin-top:24px; border-radius:var(--r-lg); overflow:hidden;
  border:1px solid var(--border); box-shadow:var(--shadow-sm); background:#fff}
.setup{position:relative}
.setup__bar{display:flex; align-items:center; gap:10px; padding:11px 14px; background:#F4F5F9;
  border-bottom:1px solid var(--border)}
.setup__box{display:flex; align-items:center; justify-content:center; width:26px; height:26px;
  border-radius:8px; background:var(--indigo-50); color:var(--indigo-600)}
.setup__box svg{width:16px; height:16px}
.setup__name{font-size:12.5px; color:var(--muted); font-weight:500}

/* штамп «Готов к работе» — шлёпается в конце цикла */
.setup__stamp{position:absolute; right:16px; bottom:14px; z-index:2;
  padding:7px 14px; border:2.5px solid #1E7A54; border-radius:10px;
  color:#1E7A54; background:rgba(231,246,238,.85);
  font-family:var(--font-display); font-size:13px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase;
  transform:rotate(-8deg) scale(1.7); opacity:0; pointer-events:none}
.setup.is-stamped .setup__stamp{animation:stampIn .5s var(--ease-out) forwards}
@keyframes stampIn{
  0%{opacity:0; transform:rotate(-8deg) scale(1.7)}
  60%{opacity:1; transform:rotate(-8deg) scale(.94)}
  100%{opacity:1; transform:rotate(-8deg) scale(1)}
}
.setup__body{padding:8px 18px}
.setup__row{display:flex; align-items:flex-start; gap:13px; padding:13px 0;
  border-bottom:1px solid var(--border-2);
  opacity:.4; transform:translateX(-4px);
  transition:opacity .5s var(--ease), transform .5s var(--ease-out)}
.setup__row:last-child{border-bottom:0}
.setup__row.is-done{opacity:1; transform:none}
.setup__check{position:relative; flex:none; width:23px; height:23px; margin-top:1px; border-radius:50%;
  background:#EFF0F5; transition:background .45s var(--ease), transform .45s var(--ease-out)}
.setup__check::after{content:''; position:absolute; inset:0;
  background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5.5 10.2 8.4 13l6-6.4' stroke='%231E7A54' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/15px no-repeat;
  opacity:0; transform:scale(.5); transition:opacity .4s var(--ease), transform .45s var(--ease-out)}
.setup__row.is-done .setup__check{background:var(--mint); animation:pop .55s var(--ease-out)}
.setup__row.is-done .setup__check::after{opacity:1; transform:none}
.setup__row b{display:block; font-size:14.5px; font-weight:600; letter-spacing:-.01em}
.setup__row span{display:block; margin-top:2px; font-size:13px; color:var(--muted)}

/* ---------- Сцена «один кабель» ---------- */
.cablescene{margin-top:24px}
.cablescene svg{width:100%; height:auto; display:block}
.cs-cable{fill:none; stroke:#F2B01E; stroke-width:6; stroke-linecap:round}
/* сигнал бежит по кабелю; период совпадает с волнами Wi-Fi — «дошёл → сеть ожила» */
.cs-flow{fill:none; stroke:rgba(255,255,255,.9); stroke-width:6; stroke-linecap:round;
  stroke-dasharray:16 178; stroke-dashoffset:0; animation:csFlow 4.2s linear infinite}
@keyframes csFlow{to{stroke-dashoffset:-194}}
.cs-waves circle{stroke:#7C6CF5; stroke-width:1.6; opacity:0; transform-origin:500px 150px;
  animation:csWave 4.2s ease-out infinite}
.cs-waves circle:nth-child(2){animation-delay:.35s}
@keyframes csWave{0%{opacity:.5; transform:scale(.4)}55%,100%{opacity:0; transform:scale(1)}}
.cs-led{animation:ledBlink 2.4s ease-in-out infinite}
.cs-led:nth-of-type(2){animation-delay:.3s; opacity:.62}
.cs-led:nth-of-type(3){animation-delay:.6s; opacity:.42}

.cablescene__labels{display:flex; justify-content:space-between; gap:16px; padding:0 6px}
.cablescene__label{flex:1; max-width:46%}
.cablescene__label b{display:block; font-family:var(--font-display); font-size:15.5px;
  font-weight:700; letter-spacing:-.04em}
.cablescene__label span{display:block; margin-top:3px; font-size:13px; color:var(--muted); line-height:1.45}
.cablescene__label--ok{text-align:right}
.cablescene__label--ok b{color:var(--indigo-600)}
/* мобильная вертикальная сцена кабеля (включается в media ≤700) */
.cablem{display:none; margin-top:20px}
.cablem__row{display:flex; align-items:center; gap:14px}
.cablem__ic{flex:none; width:64px}
.cablem__ic svg{width:64px; height:auto; display:block}
.cablem__text b{display:block; font-family:var(--font-display); font-size:15.5px;
  font-weight:700; letter-spacing:-.04em}
.cablem__row:last-of-type .cablem__text b{color:var(--indigo-600)}
.cablem__text span{display:block; margin-top:2px; font-size:13px; color:var(--muted)}
.cablem__wire{position:relative; display:block; width:5px; height:42px; margin:6px 0 6px 30px;
  border-radius:3px; background:#F2B01E; overflow:hidden}
.cablem__wire i{position:absolute; left:0; right:0; height:10px; border-radius:3px;
  background:rgba(255,255,255,.85); animation:cablemFlow 2.2s linear infinite}
@keyframes cablemFlow{0%{top:-10px}100%{top:42px}}

.cablescene__chip{display:flex; align-items:center; gap:8px; width:fit-content; margin:16px auto 0;
  height:34px; padding:0 15px; background:#fff; border:1px solid var(--border);
  border-radius:var(--r-pill); box-shadow:var(--shadow-sm);
  font-size:13px; font-weight:600; color:var(--ink-2)}
.cablescene__chip i{width:9px; height:9px; border-radius:50%; background:#F2B01E}

/* ---------- Шаги: мини-анимации ---------- */
.step__plug{animation:plugIn 3.4s ease-in-out infinite}
@keyframes plugIn{
  0%,12%{transform:translateX(14px); opacity:0}
  32%,82%{transform:translateX(0); opacity:1}
  100%{transform:translateX(14px); opacity:0}
}
.step__cord{stroke-dasharray:80; stroke-dashoffset:80; animation:cordDraw 3.4s ease-in-out infinite}
@keyframes cordDraw{
  0%,10%{stroke-dashoffset:80}
  45%,88%{stroke-dashoffset:0}
  100%{stroke-dashoffset:80}
}
.steps__foot{margin-top:34px; text-align:center; font-size:16.5px; color:var(--ink-2); font-weight:600}

/* ---------- Две сети: iPhone ---------- */
.twonet{display:grid; grid-template-columns:.92fr 1.08fr; gap:48px; align-items:center;
  max-width:1020px; margin:0 auto}
/*
 * min-width:0 — иначе колонка не сжимается ниже своего содержимого.
 *
 * У элемента сетки по умолчанию `min-width:auto`: он раздувается под
 * внутренний минимум и вылезает за родителя. На экране 320 px карточка
 * «Дома — две сети Wi-Fi» становилась 333 px и уезжала вправо — вместе с
 * меткой «Как раньше», счётчиком «4 из 8» и подписью под полосой. Прокрутки
 * вбок нет, значит прочитать их было нельзя вовсе.
 */
.twonet__left{display:flex; flex-direction:column; align-items:center; gap:18px; min-width:0}
.iphone__note{max-width:300px; text-align:center}

.iphone{position:relative; width:100%; max-width:320px; margin:0 auto;
  padding:11px; border-radius:52px;
  background:linear-gradient(160deg,#3A3A40,#131316 40%,#26262C);
  box-shadow:0 24px 60px rgba(16,18,40,.32), inset 0 0 0 2px #4C4C55, inset 0 0 0 5px #101013}
/* Пропорция экрана — как у живого телефона: 393 на 852.
   Была задана высотой в пикселях, и при ширине 308 выходило 440 — отношение
   0.70 вместо 0.46. Макет получался почти в полтора раза шире, чем бывает,
   и выглядел приплюснутым. Отношение сторон держится на любой ширине. */
.iphone__screen{position:relative; overflow:hidden; border-radius:42px;
  background:#F2F2F7; padding:14px 16px 20px; aspect-ratio:393/852;
  font-family:-apple-system,BlinkMacSystemFont,'SF Pro Text','Segoe UI',system-ui,sans-serif;
  -webkit-user-select:none; user-select:none}

/* Строка статуса: время слева, островок посередине, значки справа.
   Островок — обычный элемент строки, а не наложенный поверх: наложенный
   центрировался по экрану, а время и значки разной ширины, и справа зазор
   выходил втрое меньше левого — вся строка читалась как сжатая.
   Боковые колонки равной ширины, поэтому островок стоит ровно по центру
   экрана при любой его ширине. */
/* Строка статуса: время слева, островок посередине, значки справа.
   Сетка, а не гибкая строка: у гибкой ширина колонок зависит от содержимого,
   и значки, которые шире времени, утягивали островок влево — до экрана слева
   оставалось 80px, справа 108. Строка читалась как сжатая.
   У сетки колонки заданы долями и содержимого не слушают, поэтому островок
   стоит ровно по центру экрана при любой его ширине. */
.ios-status{display:grid; grid-template-columns:minmax(0,1fr) 39% minmax(0,1fr);
  align-items:center; gap:8px;
  padding:4px 10px 0; margin-bottom:18px; color:#0B0B12}
.ios-island{width:100%; aspect-ratio:126/37; border-radius:999px; background:#0B0B0E}
.ios-status__time{font-size:15px; font-weight:600; letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.ios-status__icons{display:inline-flex; align-items:center; justify-content:flex-end;
  gap:5px; color:#0B0B12}
/* Значки сети и батареи занимают на настоящем айфоне около пятой части
   ширины экрана. Здесь они были вчетверть — и раздвигали строку, утягивая
   островок из центра. */
.ios-status__icons svg{height:11px; width:auto; display:block}

.ios-nav{display:inline-flex; align-items:center; gap:5px; margin:6px 0 2px;
  font-size:15px; color:#007AFF}
.ios-nav svg{width:11px; height:18px; display:block}
.ios-title{font-family:inherit; font-size:31px; font-weight:700; letter-spacing:-.02em;
  color:#0B0B12; margin:2px 0 16px; line-height:1.1}

.ios-group{background:#fff; border-radius:12px; overflow:hidden;
  box-shadow:0 0 0 .5px rgba(0,0,0,.04)}
.ios-row{display:flex; align-items:center; justify-content:space-between; padding:11px 14px}
.ios-row__label{font-size:16px; color:#0B0B12}
.ios-switch{position:relative; flex:none; width:50px; height:30px; border-radius:var(--r-pill); background:#34C759}
.ios-switch i{position:absolute; top:2px; right:2px; width:26px; height:26px; border-radius:50%;
  background:#fff; box-shadow:0 2px 5px rgba(0,0,0,.22)}

.ios-caption{margin:18px 4px 7px; font-size:12.5px; font-weight:500; letter-spacing:.04em;
  text-transform:uppercase; color:#7C7C85}
.ios-sep{height:.5px; margin-left:44px; background:rgba(0,0,0,.12)}

/* Строки сетей в макете айфона — настоящие кнопки: по ним и переключают
   демонстрацию. Выходило 42 px, два пикселя до нужного пальцу. */
.ios-net{position:relative; display:flex; align-items:center; gap:2px; width:100%; min-height:44px;
  padding:11px 14px 11px 10px; border:0; background:transparent; cursor:pointer;
  font-family:inherit; text-align:left;
  transition:background-color .18s var(--ease)}
.ios-net:active,.ios-net.is-pressed{background:#E4E4EA}
.ios-net__check{position:relative; flex:none; width:26px; height:22px; color:#007AFF}
.ios-net__tick{position:absolute; inset:0; margin:auto; width:17px; height:17px;
  opacity:0; transform:scale(.55); transition:opacity .3s var(--ease), transform .35s var(--ease-out)}
.ios-net.is-active .ios-net__tick{opacity:1; transform:none}
.ios-net__spin{position:absolute; inset:0; margin:auto; width:15px; height:15px; border-radius:50%;
  border:2px solid rgba(0,0,0,.14); border-top-color:#8E8E93;
  opacity:0; animation:spin .8s linear infinite}
.ios-net.is-connecting .ios-net__spin{opacity:1}
.ios-net.is-connecting .ios-net__tick{opacity:0; transform:scale(.55)}
.ios-net__name{flex:1; min-width:0; font-size:16px; color:#0B0B12; line-height:1.25}
.ios-net__name em{display:block; font-style:normal; font-size:12px; color:#8E8E93; margin-top:1px}
.ios-net[data-net="alisa"] .ios-net__name em{color:#5B4BE8; font-weight:500}
.ios-net__aux{display:inline-flex; align-items:center; gap:9px; color:#3C3C43; opacity:.7}
.ios-net__aux svg{width:17px; height:17px; display:block}

/* Цвет подписи в макете айфона. Был ровно эппловский #8E8E93 — на их же
   светло-сером фоне это 2.9:1, и строка «Подключено к сети ...» читалась
   хуже всего на странице. А это и есть развязка демонстрации: человек
   нажимает на сеть и по этой строке понимает, что переключился. Берём
   тёмный оттенок из той же палитры — 4.6:1, вид остаётся айфоновским. */
.ios-foot{margin:10px 6px 0; font-size:12.5px; color:#6E6E73; min-height:18px;
  transition:opacity .3s var(--ease)}

/* чужие сети — для реализма списка, некликабельны */
.ios-group--other .ios-net{cursor:default}
.ios-group--other .ios-net:active{background:transparent}
.ios-net--other .ios-net__name{color:#48484E; opacity:.8}
.ios-net--other .ios-net__aux{opacity:.5}
.ios-homebar{position:absolute; bottom:8px; left:50%; transform:translateX(-50%);
  width:120px; height:5px; border-radius:3px; background:#0B0B12; opacity:.85}

/* палец-курсор демонстрации */
.tapdot{position:absolute; z-index:5; width:34px; height:34px; border-radius:50%;
  background:rgba(60,60,67,.28); border:1.5px solid rgba(255,255,255,.85);
  box-shadow:0 4px 14px rgba(0,0,0,.22);
  opacity:0; pointer-events:none; transform:translate(-50%,-50%) scale(1);
  transition:left .7s var(--ease-out), top .7s var(--ease-out),
             opacity .35s var(--ease), transform .2s var(--ease)}
.tapdot.is-visible{opacity:1}
.tapdot.is-pressing{transform:translate(-50%,-50%) scale(.72)}

.twonet__points{display:flex; flex-direction:column}
.netpoint{display:flex; gap:16px; padding:19px 0; border-bottom:1px solid var(--border-2)}
.twonet__points .netpoint:last-child,
.supp__points .netpoint:last-child{border-bottom:0}
.netpoint__icon{flex:none; width:46px; height:46px; border-radius:var(--r-md);
  background:var(--bg); color:var(--fg);
  display:flex; align-items:center; justify-content:center}
.netpoint__icon svg{width:23px; height:23px}
.netpoint h3{font-size:17px; letter-spacing:-.04em}
.netpoint p{margin-top:6px; font-size:14.5px; color:var(--muted); line-height:1.55}

/* ---------- Поддержка: чат ---------- */
.supp{display:grid; grid-template-columns:1.02fr .98fr; gap:44px; align-items:center;
  max-width:1040px; margin:0 auto}
.supp__points{display:flex; flex-direction:column}

.chat{border-radius:var(--r-xl); overflow:hidden; background:var(--surface);
  border:1px solid var(--border); box-shadow:var(--shadow-md)}
.chat__bar{display:flex; align-items:center; gap:12px; padding:15px 18px;
  background:linear-gradient(135deg,var(--indigo-500),var(--indigo-700)); color:#fff}
.chat__ava{flex:none; width:40px; height:40px; border-radius:50%;
  background:rgba(255,255,255,.16); display:flex; align-items:center; justify-content:center}
.chat__ava svg{width:19px; height:15px; display:block}
.chat__who b{display:block; font-size:15px; font-weight:600; letter-spacing:-.01em}
.chat__who span{display:flex; align-items:center; gap:6px; margin-top:1px; font-size:12.5px; color:rgba(255,255,255,.75)}
.chat__who i{width:6px; height:6px; border-radius:50%; background:#7CF5B2; animation:blink 2s infinite}
/* высота фиксируется скриптом по полному диалогу — блок не прыгает во время анимации;
   сообщения прижаты к низу, как в настоящем мессенджере */
.chat__body{display:flex; flex-direction:column; justify-content:flex-end; gap:10px;
  padding:18px; min-height:262px; overflow:hidden}

.msg{max-width:84%; padding:10px 14px; border-radius:16px;
  font-size:14px; line-height:1.5; animation:msgIn .45s var(--ease-out) both}
/* Заливка темнее прежней: на светлом конце градиента белое время
   в углу пузыря не дотягивало до порога читаемости. */
.msg--user{align-self:flex-end; border-bottom-right-radius:6px; color:#fff;
  background:linear-gradient(135deg,var(--indigo-600),#3A2BB8)}
.msg--op{align-self:flex-start; border-bottom-left-radius:6px; background:#F1F2F7; color:var(--ink-2)}
.msg__time{display:block; margin-top:3px; font-size:10.5px; opacity:.6; text-align:right}
/* Время — мелкое, поэтому в цветном пузыре гасим его слабее. */
.msg--user .msg__time{opacity:.85}
@keyframes msgIn{from{opacity:0; transform:translateY(8px)}to{opacity:1; transform:none}}

.typing{align-self:flex-start; display:inline-flex; gap:4px; padding:13px 15px;
  background:#F1F2F7; border-radius:16px; border-bottom-left-radius:6px;
  animation:msgIn .3s var(--ease-out) both}
.typing i{width:6px; height:6px; border-radius:50%; background:#A9B0C2; animation:typBounce 1.1s ease-in-out infinite}
.typing i:nth-child(2){animation-delay:.15s}
.typing i:nth-child(3){animation-delay:.3s}
@keyframes typBounce{0%,60%,100%{transform:none; opacity:.55}30%{transform:translateY(-4px); opacity:1}}

/* ---------- Цена: три тарифа аренды ---------- */
.plans--three{max-width:1120px}
.plans--three .plan__price b{font-size:34px}
@media (min-width:1001px){
  .plans--three{grid-template-columns:repeat(3,1fr)}
}

/* ---------- Герой: строка доверия ---------- */
.hero__trust{display:flex; flex-wrap:wrap; gap:6px 22px; margin-top:16px;
  font-size:13px; color:var(--muted)}
.hero__trust span{position:relative; padding-left:20px}
.hero__trust span::before{content:''; position:absolute; left:0; top:50%; margin-top:-7px;
  width:14px; height:14px; border-radius:50%;
  background:var(--mint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5.5 10.2 8.4 13l6-6.4' stroke='%231E7A54' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/10px no-repeat}

/* ---------- Живость героя: панель «дышит» ---------- */
.device{animation:deviceBreath 7s ease-in-out infinite}
@keyframes deviceBreath{50%{transform:translateY(-7px)}}

/* iPhone в герое: по центру колонки, свечение и волны из-за корпуса */
.hero__stage{position:relative; display:flex; flex-direction:column; align-items:center; gap:18px}
.hero__stage::before{content:''; position:absolute; z-index:0; left:50%; top:150px;
  width:440px; height:440px; transform:translateX(-50%); border-radius:50%;
  background:radial-gradient(circle,rgba(124,108,245,.3),rgba(200,107,214,.12) 55%,rgba(124,108,245,0) 72%);
  filter:blur(26px); pointer-events:none}
.hero__stage .waves{top:150px}
.hero__stage .iphone{position:relative; z-index:1}
.hero__stage .stage__note{position:relative; z-index:1; max-width:380px; text-align:center; margin-top:0}
/* панель в блоке «Две сети» */
.twonet__left .device{width:100%}
.twonet__left .stage__note{text-align:center; margin-top:0}

/* ---------- Лого-марка роутера ---------- */
.logo__mark--router{width:29px; height:26px}

/* ---------- Лента: подпись и второй ряд ---------- */
.marquee-label{margin:0 0 14px; text-align:center;
  font-size:13.5px; font-weight:600; color:var(--muted)}
.marquee--second{margin-top:12px}
.marquee__row--rev{animation-direction:reverse}

/* ---------- Дом — зона комфорта ---------- */
.comfort{display:grid; grid-template-columns:repeat(3,1fr); gap:20px}
.comfort-card{padding:24px; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--r-xl); box-shadow:var(--shadow-sm);
  transition:transform .45s var(--ease-out), box-shadow .45s var(--ease)}
.comfort-card:hover{transform:translateY(-4px); box-shadow:var(--shadow-md)}
.comfort-card h3{font-size:18px; margin:18px 0 8px; letter-spacing:-.04em}
.comfort-card p{font-size:14.5px; color:var(--muted); line-height:1.55}
.comfort-card__art{height:116px; border-radius:var(--r-md);
  background:linear-gradient(160deg,#F6F6FB,#F2F6F4);
  display:flex; align-items:center; justify-content:center; overflow:hidden; position:relative}

.art-tv{position:relative; display:flex; flex-direction:column; align-items:center; gap:10px}
.art-tv__frame{width:98px; height:58px; border-radius:12px; overflow:hidden;
  box-shadow:0 8px 20px rgba(16,18,40,.14); animation:beat 3.4s ease-in-out infinite}
.art-tv__frame svg{width:100%; height:100%; display:block}
.art-tv__bar{width:98px; height:5px; border-radius:3px; background:#E4E7EF; overflow:hidden}
.art-tv__bar i{display:block; height:100%; border-radius:3px; background:#E8322C; animation:play 7s linear infinite}
.art-tv__q{position:absolute; top:-4px; right:-30px; padding:3px 8px; border-radius:6px;
  background:#E8322C; color:#fff; font-size:11px; font-weight:700}

.art-talk{display:flex; flex-direction:column; align-items:center; gap:11px}
.art-talk__wave{display:flex; align-items:center; gap:3px; height:34px}
.art-talk__wave i{width:3.5px; border-radius:2px; background:#22A56F; animation:vu 1.15s ease-in-out infinite}
.art-talk__ok{font-size:11.5px; font-weight:600; color:var(--mint-fg); background:var(--mint);
  padding:3px 10px; border-radius:var(--r-pill)}

.art-play svg{width:150px; height:auto; display:block}
.art-play__dot{animation:blink 1.6s ease-in-out infinite}
.art-play__dot:last-child{animation-delay:.5s}

.comfort__foot{max-width:640px; margin:32px auto 0; text-align:center;
  font-size:16.5px; color:var(--muted)}
.comfort__foot b{color:var(--ink)}

/* ---------- Замки: дужка отпирается перед исчезновением ---------- */
.lock__sh{transform-origin:16px 10.5px;
  transition:transform .28s var(--ease-out)}
.tile.is-open .tile__lock .lock__sh,
.sc-tile.is-on .sc-tile__lock .lock__sh{transform:rotate(26deg)}
.tile.is-open .tile__lock{transition-delay:.2s}
.sc-tile.is-on .sc-tile__lock{transition-delay:.22s}

/* ---------- Витрина: состояние и подписи плиток ---------- */
.showcase__main{display:flex; flex-direction:column; gap:16px; min-width:0}
.showcase__state{display:flex; align-items:center; gap:10px;
  font-family:var(--font-display); font-size:17px; font-weight:700; letter-spacing:-.035em;
  color:rgba(255,255,255,.55); transition:color .5s var(--ease)}
.showcase__state i{width:10px; height:10px; border-radius:50%; flex:none;
  background:#E05A5A; transition:background .5s var(--ease); animation:blink 2s infinite}
.showcase__state.is-on{color:#fff}
.showcase__state.is-on i{background:#7CF5B2}
.sc-tile__name b{display:block; font-size:12.5px; font-weight:600}
.sc-tile__name span{display:block; margin-top:1px; font-size:10.5px; opacity:.75}

/* ---------- Шаги: линия-прогресс ---------- */
@media (min-width:1001px){
  .step{position:relative}
  .step:not(:last-child)::after{content:''; position:absolute; top:50%; right:-21px;
    width:22px; border-top:2px dashed #C9CEE2}
}
.step__sticker-t{font-family:var(--font-body); font-size:9px; font-weight:700;
  letter-spacing:-.01em; fill:var(--ink)}
.step__sticker-t--sub{font-size:8.5px; font-weight:500; fill:var(--muted)}
/* галочка наклейки анимируется из своего центра, а не из общего */
.step__check--sticker{transform-origin:96px 59px}

/* ---------- Умная система: по проводам бегут иконки ---------- */
.rt-wire i{width:22px; height:22px; border-radius:7px; top:-11px;
  background-color:#fff; background-position:center; background-repeat:no-repeat; background-size:16px;
  border:1px solid var(--border); box-shadow:0 3px 10px rgba(16,18,40,.14)}
.rt-wire--direct i{background-image:url('assets/icons/sber.svg')}
.rt-wire--secure i{background-image:url('assets/icons/youtube.svg')}
@media (max-width:1000px){
  .rt-wire i{left:-11px}
}

/* ---------- Банки работают — плашка ---------- */
.bankok{display:flex; align-items:center; gap:18px; max-width:820px; margin:22px auto 0;
  padding:20px 24px; background:linear-gradient(135deg,#F2FBF6,#fff 70%);
  border:1px solid #CDE9DA; border-radius:var(--r-xl); box-shadow:var(--shadow-sm)}
.bankok__badge{flex:none; display:flex; align-items:center; justify-content:center;
  width:52px; height:52px; border-radius:16px; background:var(--mint); color:var(--mint-fg)}
.bankok__badge svg{width:27px; height:27px}
.bankok__text{font-size:15px; color:var(--muted); line-height:1.55}
.bankok__text b{display:block; margin-bottom:2px; font-family:var(--font-display);
  font-size:16.5px; letter-spacing:-.035em; color:var(--ink)}

/* ---------- Чат: кнопка ---------- */
.chat__cta{padding:0 18px 18px}

/* ---------- Тарифы: пиктограмма жилья ---------- */
.plan__note{display:flex; align-items:center; gap:9px}
.plan__home{flex:none; display:flex; align-items:center; justify-content:center;
  width:34px; height:34px; border-radius:10px; background:var(--indigo-50); color:var(--indigo-600)}
.plan__home svg{width:19px; height:19px}
.plan--vip .plan__home{background:rgba(255,255,255,.16); color:#fff}

/* ---------- CTA: три факта ---------- */
.cta__facts{display:flex; flex-wrap:wrap; justify-content:center; gap:12px 34px; margin-top:24px}
.cta__facts li{display:inline-flex; align-items:center; gap:9px;
  font-size:14.5px; font-weight:600; color:rgba(255,255,255,.88)}
.cta__facts svg{width:20px; height:20px; color:rgba(255,255,255,.75)}

/* ---------- iPhone: уведомление ---------- */
.ios-notif{position:absolute; top:46px; left:12px; right:12px; z-index:4;
  display:flex; align-items:center; gap:11px; padding:11px 13px;
  background:rgba(250,250,252,.92); backdrop-filter:blur(14px);
  border-radius:17px; box-shadow:0 10px 28px rgba(0,0,0,.18);
  opacity:0; transform:translateY(-16px) scale(.96); pointer-events:none;
  transition:opacity .4s var(--ease), transform .45s var(--ease-out)}
.ios-notif.is-show{opacity:1; transform:none}
.ios-notif__icon{flex:none; width:34px; height:34px; border-radius:9px; overflow:hidden}
.ios-notif__icon img{width:100%; height:100%; display:block}
.ios-notif__text b{display:block; font-size:13.5px; color:#0B0B12}
.ios-notif__text span{display:block; font-size:12.5px; color:#5C5C66}

/* ---------- Заголовок «вспыхивает» при подключении телефона ---------- */
.grad{transition:filter .55s var(--ease)}
.grad.is-pulse{filter:saturate(1.7) brightness(1.14)}
.sup--title{font-size:.32em; vertical-align:top; margin-left:4px}

/* ---------- Подсветка текущего раздела в меню ---------- */
.nav a.is-active{color:var(--ink); background:rgba(91,75,232,.09)}

/* ---------- «Почему аренда, а не покупка?» ---------- */
.whyrent{max-width:820px; margin:20px auto 0}

/* ---------- Всплывающая сноска ---------- */
/* Начальное место обязательно.
   Подсказка создаётся при загрузке страницы и до первого показа не имеет
   координат — а `absolute` без них встаёт туда, где элемент оказался в
   разметке: в самый конец. Невидимая (opacity:0) и некликаемая, она всё равно
   удлиняла страницу на свою высоту: на узком экране это 147 пикселей пустоты
   под подвалом, куда человек прокручивает и упирается. */
.tipbox{position:absolute; top:0; left:0; z-index:95; max-width:320px; padding:13px 16px;
  background:#191C2B; color:rgba(255,255,255,.92);
  font-size:12.5px; line-height:1.55; border-radius:12px;
  box-shadow:0 14px 40px rgba(10,12,30,.35);
  opacity:0; transform:translateY(5px); pointer-events:none;
  transition:opacity .25s var(--ease), transform .3s var(--ease-out)}
.tipbox.is-show{opacity:1; transform:none}
.tipbox::before{content:''; position:absolute; top:-5px; left:var(--arrow,18px);
  width:10px; height:10px; transform:rotate(45deg); background:#191C2B}

/* Спрятанное атрибутом остаётся спрятанным.
   `hidden` — это правило браузера, и любое авторское `display:block` его
   перебивает. Один раз наступили на это с окном чата (закрытое окно висело
   на экране) и с ошибкой «выберите способ доставки», которая показывалась
   человеку до того, как он что-то сделал. */
[hidden]{display:none !important}

/* ---------- Sticky-CTA на мобильном ---------- */
.stickycta{position:fixed; left:0; right:0; bottom:0; z-index:80; display:none;
  padding:10px 14px calc(10px + env(safe-area-inset-bottom));
  background:linear-gradient(180deg,rgba(247,248,251,0),rgba(247,248,251,.94) 40%);
  transform:translateY(110%); transition:transform .45s var(--ease-out)}
.stickycta.is-show{transform:none}
.stickycta .btn{box-shadow:0 12px 34px rgba(74,56,220,.4)}
@media (max-width:700px){
  .stickycta{display:block}
}

/* ---------- Адаптив ---------- */
@media (max-width:1000px){
  .twonet{grid-template-columns:1fr; gap:34px}
  .supp{grid-template-columns:1fr; gap:30px}
  .comfort{grid-template-columns:1fr}
}
@media (max-width:700px){
  .hero__speednote{max-width:none}
  /* Одна прокручиваемая строка с прилипанием вместо двух рваных рядов.
     Шесть сроков в строку не помещаются ни на одном телефоне, а перенос
     внутри скруглённой плашки выглядит как недоделанная вёрстка. */
  .periods{
    width:100%; justify-content:flex-start; flex-wrap:nowrap;
    overflow-x:auto; scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch; scrollbar-width:none;
    border-radius:22px; padding:6px;
  }
  .periods::-webkit-scrollbar{display:none}
  .periods__btn{
    flex:0 0 auto; justify-content:center; padding:0 14px; height:46px;
    scroll-snap-align:center; flex-direction:column; gap:1px; line-height:1.15;
  }
  .periods__btn i{font-size:10.5px; padding:1px 5px}
  .chat__body{min-height:230px}
  .setup__body{padding:6px 14px}
  .cablescene__labels{flex-direction:column; gap:12px}
  .cablescene__label{max-width:none}
  .cablescene__label--ok{text-align:left}
  .bankok{flex-direction:column; align-items:flex-start; gap:12px}
  .comfort-card{padding:20px}
}

/* ============================================================
   МОБИЛЬНАЯ ВЕРСИЯ — спроектирована отдельно, а не сжата
   ============================================================ */

/* точки-индикаторы каруселей (создаёт app.js) */
.hdots{display:none}

@media (max-width:700px){

  /* ---------- свайп-карусели: одна карточка + краешек следующей ---------- */
  .hswipe{display:flex; flex-wrap:nowrap; gap:12px;
    overflow-x:auto; overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch;
    margin:0 -18px; padding:4px 18px 6px;
    scrollbar-width:none}
  .hswipe::-webkit-scrollbar{display:none}
  .hswipe>*{flex:0 0 84%; min-width:0; scroll-snap-align:center}

  /* карточки в карусели видны сразу — reveal по горизонтали не срабатывает */
  .hswipe>.reveal{opacity:1; transform:none; transition:none}

  .hdots{display:flex; justify-content:center; gap:7px; margin-top:16px}
  .hdots i{width:7px; height:7px; border-radius:4px; background:#C9CEE2;
    transition:width .3s var(--ease), background-color .3s var(--ease)}
  .hdots i.is-on{width:20px; background:var(--indigo-500)}

  /* ---------- герой: телефон сразу после заголовка (переносит app.js) ---------- */
  .hero{padding:20px 0 8px}
  /* колонка не шире контейнера: 1fr = minmax(auto,1fr) распирается контентом */
  .hero__grid{grid-template-columns:minmax(0,1fr)}
  .hero__grid>*{min-width:0}
  /* пилюля: многострочная, точка на первой строке */
  .pill{height:auto; min-height:34px; padding:8px 14px 8px 12px; margin-bottom:20px;
    align-items:flex-start; border-radius:18px; font-size:12.5px; line-height:1.45}
  .pill__dot{flex:none; margin-top:5px}
  .hero__grid{gap:0}
  .hero__trust{display:none}
  .hero__copy .hero__stage{margin:26px auto 6px; gap:14px}
  .hero__stage::before{width:320px; height:320px; top:120px}
  .hero__speednote{margin-top:12px; font-size:14px}
  .hero__sub{margin-top:24px; font-size:16px}
  .hero__cta{margin-top:20px; gap:10px}
  /* факты — ровная стопка строк, а не рваные столбики */
  .hero__facts{flex-direction:column; gap:9px; margin-top:22px; padding-top:18px}
  .hero__facts li{flex-direction:row; align-items:baseline; gap:8px}
  .hero__facts b{font-size:15px; letter-spacing:-.03em; white-space:nowrap}
  .hero__facts span{font-size:13px}
  /* звёздочки-сноски: honest тач-зона */
  a.sup{padding:8px; margin:-8px}
  .iphone{max-width:300px}

  /* ---------- лента: один ряд ---------- */
  .marquee-wrap{padding:16px 0 4px}
  .marquee--second{display:none}
  .marquee-label{margin-bottom:10px}

  /* ---------- секции плотнее ---------- */
  .section{padding:54px 0}
  .section--dark{padding:60px 0}
  .section__head{margin-bottom:30px}
  .section__lead{font-size:15px}

  /* ---------- комфорт и шаги: карточки одинаковой высоты в карусели ---------- */
  .comfort-card,.step{display:flex; flex-direction:column}
  .comfort-card__art,.step__art{flex:none}
  .comfort__foot{margin-top:24px; font-size:15px}
  .steps__foot{margin-top:22px; font-size:15px}

  /* ---------- тёмная витрина: сетка 4×2 только из иконок ----------
     подписи 9px нечитаемы — убираем: бренды узнаются по иконкам,
     а словами их называют заголовок-состояние и статы ниже */
  .showcase{gap:22px}
  .showcase__grid{grid-template-columns:repeat(4,1fr); gap:9px}
  .sc-tile{border-radius:16px; gap:0}
  .sc-tile__icon{width:32px; height:32px}
  .sc-tile__name{display:none}
  .sc-tile__lock{top:6px; right:6px; width:12px; height:12px}
  .showcase__state{font-size:16px}
  .showcase__stats{flex-direction:row; flex-wrap:wrap; gap:12px 22px}
  .showcase__stats b{font-size:20px}
  .showcase__stats li{flex:1 1 40%; padding-left:12px}
  .showcase__stats span{font-size:13px}
  .showcase__note{font-size:13.5px}

  /* ---------- сцена кабеля: на мобиле вертикальная версия ---------- */
  .cablescene > svg,
  .cablescene__labels{display:none}
  .cablem{display:block}
  .bankok{margin-top:18px; padding:18px}

  /* ---------- окно настройки: штамп компактнее, не наезжает на текст ---------- */
  .setup__stamp{right:10px; bottom:8px; padding:5px 11px; font-size:11.5px; border-width:2px}
  .setup__row span{font-size:12.5px}

  /* ---------- панель «две сети»: шапка в одну строку ---------- */
  .device__head{gap:10px; padding-bottom:14px}
  .device__name{font-size:14px; white-space:nowrap}
  .device__ssid{display:none}
  .device__status{height:24px; padding:0 10px; font-size:11px; white-space:nowrap}

  /* ---------- тарифы: карусель, карточка почти на экран ---------- */
  .plans.hswipe>*{flex-basis:86%}
  .plan{padding:26px 22px}
  .plans--three .plan__price b{font-size:31px}
  .periods{margin-bottom:20px}

  /* ---------- финальный CTA: факты столбиком ---------- */
  .cta__facts{flex-direction:column; align-items:center; gap:10px; margin-top:20px}

  /* ---------- подвал ---------- */
  .footer{padding:44px 0 26px}
}

@media (prefers-reduced-motion:reduce){
  .device{animation:none}
}


/* ==========================================================================
   ПЛАВНОСТЬ
   Отдельным блоком в конце: это сквозная правка поверх готовой вёрстки, и
   держать её вместе понятнее, чем растащить по разделам.
   ========================================================================== */

/* Страницу НЕ прячем.
   Была попытка проявлять её целиком: `body{opacity:0}` и показ из скрипта,
   когда приедут шрифты. На быстром компьютере смотрится хорошо, на телефоне —
   это белый экран на всё время загрузки шрифтов, а если скрипт где-то упадёт,
   то навсегда. Видимость страницы не должна зависеть от скрипта: он может не
   выполниться, а прочитать текст человек должен в любом случае. */

/* --------------------------------------------------- РАСКРЫТИЕ ---------- */
/* Высоту анимируем через сетку: `0fr → 1fr` — единственный способ доехать до
   «сколько нужно», не зная этой высоты заранее и не считая её скриптом. */
details.smooth > summary{cursor:pointer; list-style:none}
details.smooth > summary::-webkit-details-marker{display:none}
details.smooth > .smooth__body{
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .42s var(--ease-out), opacity .32s var(--ease-out);
  opacity:0;
}
details.smooth[open] > .smooth__body{grid-template-rows:1fr; opacity:1}
details.smooth > .smooth__body > *{overflow:hidden; min-height:0}

/* Стрелка поворачивается вместе с раскрытием — по ней видно состояние,
   даже когда содержимое ещё едет. */
details.smooth > summary .chev{transition:transform .42s var(--ease-out)}
details.smooth[open] > summary .chev{transform:rotate(180deg)}

/* --------------------------------------------------- ЗАГОЛОВКИ ---------- */
/* Появление заметнее: заголовок приходит снизу, а под ним дорисовывается
   черта. Без неё раздел «просто есть» и глазом не отмечается. */
.section__head{position:relative}
.section__head.reveal{transform:translateY(30px)}
.section__head.reveal.is-in{transform:none}
.section__head .section__title{position:relative; display:inline-block}
.section__head .section__title::after{
  content:''; position:absolute; left:50%; bottom:-10px; height:3px; width:0;
  transform:translateX(-50%); border-radius:2px;
  background:linear-gradient(90deg,var(--indigo-500),var(--violet, #A78BFA));
  transition:width .6s var(--ease-out) .25s;
}
.section__head.is-in .section__title::after{width:56px}
.section__head--light .section__title::after{
  background:linear-gradient(90deg,#fff,rgba(255,255,255,.35))
}

/* --------------------------------------------------- ТЁМНАЯ СЕКЦИЯ ------ */
/* Фиолетовый натекает сверху и стекает снизу: край плитки превращается в
   смену света. */
.section--dark::before{
  content:''; position:absolute; left:0; right:0; top:-64px; height:64px;
  pointer-events:none; z-index:1;
  background:linear-gradient(180deg,transparent,rgba(36,24,115,.10) 55%,rgba(36,24,115,.28));
}
.section--dark{border-radius:28px 28px 0 0}
.section--dark + *{position:relative}
.section--dark + *::before{
  content:''; position:absolute; left:0; right:0; top:0; height:56px;
  pointer-events:none;
  background:linear-gradient(180deg,rgba(22,15,76,.20),transparent);
}

/* --------------------------------------------------- ЛЕНТЫ -------------- */
@media (max-width:760px){
  /* Появление внутри лент НЕ включаем.
     Такая попытка здесь уже была и стоила страницы: карточки в ленте
     обрезаны горизонтальной прокруткой, наблюдатель считает их невидимыми и
     не включает им появление никогда. Вторая и третья карточки — в том числе
     тарифы VIP и Бизнес — оставались прозрачными, пока человек сам не
     пролистает ленту. На их месте он видел пустоту.
     Правило `.hswipe>.reveal{opacity:1}` выше по файлу написано ровно об
     этом, и переписывать его нельзя. */
}

/* --------------------------------------------------- ШАГИ --------------- */
/* По очереди, а не все разом: так видно, что шагов три и они последовательны. */
.step.reveal{transform:translateY(26px)}
.step.reveal.is-in{transform:none}
.step:nth-child(2).reveal{transition-delay:.12s}
.step:nth-child(3).reveal{transition-delay:.24s}

@media (prefers-reduced-motion:reduce){
  body{opacity:1}
  details.smooth > .smooth__body{transition:none}
  .section__head .section__title::after{transition:none}
}


/* Выгоду показываем только там, где она есть: пустая плашка «−0%» хуже, чем
   её отсутствие. Заполняет её сервер из той же таблицы, по которой считает
   касса, — вписанный в разметку процент однажды разошёлся бы с ценой. */
.periods__btn i:empty{display:none}


/* ==========================================================================
   ПЕРВЫЙ ЭКРАН НА ТЕЛЕФОНЕ
   Кнопка «Арендовать» обязана быть видна без прокрутки. Пока до неё шло
   четыре блока текста, она уезжала за край: человек видел, что предлагают,
   но не видел, куда нажать.
   ========================================================================== */
@media (max-width:760px){
  /* Порядок: заголовок → одна мысль → КНОПКА → телефон → мелочи.
     Телефон уходит под кнопку: он объясняет, а объяснение нужно после
     предложения, а не вместо него. */
  .hero__grid{display:flex; flex-direction:column}
  /* Колонке не даём раздуваться шире отведённого: декоративные волны за
     корпусом телефона в полтора раза шире экрана, и без этого они тянут за
     собой весь первый экран, прижимая текст к краям. */
  .hero__copy{display:flex; flex-direction:column; max-width:100%; min-width:0}
  .hero__copy .pill{order:1}
  .hero__title{order:2}
  .hero__speednote{order:3}
  .hero__sub{order:4}
  .hero__cta{order:5}
  .hero__stage{order:6; margin-top:24px}
  .hero__trust{order:7}
  .hero__facts{order:8}

  /* Плотнее: каждый лишний отступ здесь стоит человеку прокрутки. */
  .hero__title{margin-top:14px}
  .hero__speednote{margin-top:10px}
  .hero__sub{margin-top:14px; font-size:15.5px; line-height:1.5}
  .hero__cta{margin-top:18px}

  /* Телефон выглядывает, а не занимает экран: чтобы понять, что там показ
     живой сети, хватает верхней трети. */
  .hero__stage .iphone{max-width:268px}
  /* Экран телефона не должен схлопываться, когда содержимое ещё грузится:
     иначе герой прыгает на глазах у человека. */
  .iphone__screen{min-height:440px}
}


/* ==========================================================================
   ПЕРВЫЙ ЭКРАН НА ТЕЛЕФОНЕ — ВТОРОЙ ЗАХОД
   Стена текста до кнопки и игрушечный телефон под ней.
   ========================================================================== */
@media (max-width:760px){
  /* Плашка и строка про скорость — на широком экране, где есть место.
     На телефоне их смысл слово в слово повторяют разделы ниже, а здесь они
     превращают первый экран в сплошной текст. */
  .hero__copy .pill,
  .hero__speednote{display:none}

  /* Размер по ширине экрана, но с запасом: при 9.2vw строка «Без ограничений.»
     упиралась в правый край, а сноска за ним и вовсе не помещалась. */
  /*
   * Нижняя граница 30px не давала заголовку сжаться.
   *
   * «Без ограничений.*» связано неразрывно, чтобы звёздочка не оторвалась от
   * слова, — и при 30px этот кусок занимает 321 px. Доступно 284: колонка
   * раздувалась на 37 px, и весь первый экран вставал вплотную к краям
   * телефона, а слева срезался на пиксель. Опускаем нижнюю границу: на 320
   * выходит 26 px — заголовок остаётся крупным, но помещается.
   */
  .hero__title{margin-top:6px; font-size:clamp(26px,8.2vw,40px); line-height:1.07}

  /* Сноска висела отдельной точкой над строкой — читалась как соринка на
     экране. Прижимаем к тексту и опускаем на уровень строчных. */
  .sup--title{font-size:.36em; vertical-align:super; margin-left:2px}
  .hero__sub{margin-top:16px; font-size:16px; line-height:1.5; max-width:none}
  .hero__cta{margin-top:22px; gap:10px}

  /* Телефон почти во всю ширину: 268 пикселей при экране 390 выглядели
     игрушкой. Нижним краем уходит за сгиб — по этому и понятно, что
     страница продолжается. */
  .hero__stage{margin-top:26px}
  .hero__stage .iphone{max-width:330px}

  /* Мелочи под кнопками — в одну строку, без переносов в столбик. */
  .hero__trust{margin-top:16px; font-size:13px}
}


/* ==========================================================================
   ПРОКРУТКА КАК ВРЕМЯ
   Всё ниже включается только там, где браузер умеет привязывать анимацию к
   прокрутке. Где не умеет — не включается ничего, и человек видит обычную
   страницу. Прятать содержимое ради эффекта нельзя: один раз уже пробовал,
   и страница осталась белой.
   ========================================================================== */

/* Кривая одна на всю страницу: разные читаются как небрежность. */
:root{ --sc-ease:cubic-bezier(.22,1,.36,1) }

@keyframes sc-block-in{
  from{ opacity:0; transform:translateY(16px) }
  to  { opacity:1; transform:none }
}
/* Заготовка переливается и растворяется ОДНОЙ анимацией: блик проходит по
   ней ровно за то время, пока раздел подходит к экрану. Двумя анимациями
   через запятую не выйдет — список тайм-лайнов браузер не принимает, и тогда
   не работает ни одна. */
@keyframes sc-skeleton{
  0%  { opacity:1; background-position:-140% 0, 0 0 }
  55% { opacity:1 }
  100%{ opacity:0; background-position:240% 0, 0 0 }
}

@supports (animation-timeline: view()){
  @media (max-width:760px) and (prefers-reduced-motion:no-preference){

    /* ---------------------------------------------- блок за блоком ------- */
    /* Содержимое раздела приезжает снизу, когда раздел подходит к экрану.
       `both` держит начальное состояние до входа и конечное после — без него
       блок мигал бы обратно, уходя вверх. */
    .section > .container{
      /* Отдельными свойствами, а не сокращением: у анимации, которую ведёт
         прокрутка, длительность обязана быть `auto`. Сокращение подставляет
         ноль, анимация отыгрывает мгновенно и застывает в конечном виде —
         именно так блок и «появлялся» сразу весь. */
      animation-name:sc-block-in;
      animation-duration:auto;
      animation-timing-function:var(--sc-ease);
      animation-fill-mode:both;
      animation-timeline:view();
      animation-range:entry 5% entry 55%;
    }

    /* Заготовка на месте ещё не пришедшего блока: по ней видно, что дальше
       есть содержимое. Растворяется ровно тогда, когда содержимое приезжает. */
    .section{ position:relative }
    .section::after{
      content:''; position:absolute; inset:24px 16px; z-index:0;
      border-radius:24px; pointer-events:none;
      background:
        linear-gradient(100deg,
          rgba(255,255,255,0) 20%,
          rgba(255,255,255,.55) 50%,
          rgba(255,255,255,0) 80%),
        var(--sc-sk, rgba(124,108,245,.07));
      background-size:220% 100%, auto;
      animation-name:sc-skeleton;
      animation-duration:auto;
      animation-timing-function:linear;
      animation-fill-mode:both;
      animation-timeline:view();
      animation-range:entry 0% entry 60%;
    }
    /* Тёмный раздел — заготовка светлее фона, иначе её просто не видно. */
    .section--dark{ --sc-sk:rgba(255,255,255,.06) }
    .section > .container{ position:relative; z-index:1 }

    /* ---------------------------------------------- ленты от прокрутки --- */
    /* Ход ленты привязан к тому, как раздел проходит через экран: человек
       прокручивает вниз — карточки идут вбок. Пальцем тоже можно: родная
       прокрутка ленты остаётся, просто её больше не подменяет таймер. */
    .comfort.hswipe,
    .steps.hswipe{
      animation-name:sc-strip;
      animation-duration:auto;
      animation-timing-function:linear;
      animation-fill-mode:both;
      animation-timeline:view();
      /* От «лента целиком на экране» до «начала уходить»: ровно то время,
         пока человек её видит. Уже — и карточки пролетают, шире — половина
         хода происходит, когда ленты на экране ещё нет. */
      animation-range:contain 0% contain 100%;
      overflow-x:visible;          /* ход даёт сдвиг, а не полоса прокрутки */
      scroll-snap-type:none;
      /* Ширина карточки — 84% внутренней ширины ленты, а сдвиг в `translateX`
         считается от внешней: с боковыми полями по 18px это разные числа, и на
         четырёх карточках лента промахивалась на 90px — последняя уезжала за
         край экрана вместо того, чтобы встать на место первой. Полосы прокрутки
         здесь нет, компенсировать полями нечего: обнуляем, и обе величины
         начинают считаться от одного. Отступ по краям даёт сам раздел. */
      margin-inline:0;
      padding-inline:0;
    }
    /* Сколько шагов вбок должна пройти лента — это «карточек минус одна».
       Число стояло вписанным руками, и когда шагов стало четыре, лента
       по-прежнему доезжала до третьего: последняя карточка не показывалась
       никому и никогда, молча. Теперь оно выводится из самой ленты — каждое
       следующее правило перекрывает предыдущее, побеждает то, до которого
       карточек хватило. */
    .hswipe{ --sc-last:0 }
    .hswipe:has(> :nth-child(2)){ --sc-last:1 }
    .hswipe:has(> :nth-child(3)){ --sc-last:2 }
    .hswipe:has(> :nth-child(4)){ --sc-last:3 }
    .hswipe:has(> :nth-child(5)){ --sc-last:4 }
    .hswipe:has(> :nth-child(6)){ --sc-last:5 }

    /* Обрезает уехавшее вбок контейнер раздела — но `clip`, а не `hidden`.
       `hidden` сам по себе делает элемент контейнером прокрутки, и привязка
       к прокрутке начинает считаться по нему: он никогда не прокручивается,
       и лента застывает в конечном положении. `clip` обрезает, но
       контейнером прокрутки не становится. */
    .section:has(.comfort.hswipe) > .container,
    .section:has(.steps.hswipe) > .container{ overflow:clip }

    @keyframes sc-strip{
      from{ transform:translateX(0) }
      to  { transform:translateX(calc(-1 * var(--sc-last) * (84% + 12px))) }
    }
  }
}


/* ==========================================================================
   ОФОРМЛЕНИЕ ЗАКАЗА
   Перенесено из макета владельца как есть: разметка, вид и поведение.
   Подключение к серверу — в app.js.
   ========================================================================== */
/* ============================================================
   ЧЕКАУТ — воронка после «Арендовать»
   ============================================================ */
.checkout{position:fixed; inset:0; z-index:100; display:none}
.checkout.is-open{display:block}
.checkout__backdrop{position:absolute; inset:0; background:rgba(11,11,18,.5);
  backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
  opacity:0; transition:opacity .35s var(--ease)}
.checkout.is-open .checkout__backdrop{opacity:1}
.checkout__panel{position:absolute; left:50%; top:50%; transform:translate(-50%,-48%) scale(.97);
  width:min(460px, calc(100% - 28px)); max-height:calc(100dvh - 40px); overflow-y:auto;
  padding:26px 26px 24px; background:var(--surface); border-radius:var(--r-xl);
  box-shadow:0 30px 90px rgba(11,11,18,.35);
  opacity:0; transition:opacity .35s var(--ease), transform .4s var(--ease-out);
  scrollbar-width:none}
.checkout__panel::-webkit-scrollbar{display:none}
.checkout.is-open .checkout__panel{opacity:1; transform:translate(-50%,-50%) scale(1)}
.checkout__close{position:absolute; top:14px; right:14px; z-index:2;
  width:38px; height:38px; border:0; border-radius:50%; cursor:pointer;
  background:#F1F2F7; color:var(--muted);
  display:flex; align-items:center; justify-content:center;
  transition:background .2s var(--ease), color .2s var(--ease)}
.checkout__close:hover{background:#E7E9F1; color:var(--ink)}
.checkout__close svg{width:17px; height:17px}

/* индикатор шагов */
/* индикатор шагов */
.co-steps{display:flex; align-items:center; gap:8px; margin:2px 40px 20px 2px}
.co-steps__dot{flex:none; width:26px; height:26px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:#F1F2F7; color:var(--muted-2);
  font-family:var(--font-display); font-size:12px; font-weight:700;
  transition:background .3s var(--ease), color .3s var(--ease)}
.co-steps__dot.is-on{background:linear-gradient(135deg,var(--indigo-500),var(--indigo-700)); color:#fff}
.co-steps i{flex:1; height:2px; border-radius:1px; background:#E8EAF2}
/* у «Бизнеса» два шага — оплаты и аккаунта нет, заявка уходит менеджеру */
.co-steps--two .co-steps__dot:nth-of-type(n+3),
.co-steps--two i:nth-of-type(n+2){display:none}

/* плавное раскрытие: высота анимируется через grid-rows, без рывков */
.co-reveal{display:grid; grid-template-rows:0fr; opacity:0;
  transition:grid-template-rows .55s var(--ease-out), opacity .45s var(--ease)}
.co-reveal__in{overflow:hidden; min-height:0}
.co-reveal.is-open{grid-template-rows:1fr; opacity:1}
/* после раскрытия clip снимается — ховеры и тени кнопок не обрезаются */
.co-reveal.is-done>.co-reveal__in{overflow:visible}
.co-ship-err{display:block; margin:8px 2px 0; font-style:normal; font-size:12.5px; color:#C24B4B}

.co-mailbtn{margin-top:10px}
.co-authback{display:inline-flex; align-items:center; gap:6px; margin:2px 0 14px;
  padding:7px 12px 7px 8px; border:0; border-radius:var(--r-pill); cursor:pointer;
  background:transparent; font-family:var(--font-body); font-size:13.5px; font-weight:600;
  color:#229ED9; transition:background-color .2s var(--ease)}
.co-authback:hover{background:rgba(34,158,217,.08)}
.co-authback svg{width:14px; height:14px}

.co-sub{margin:-6px 0 16px; font-size:13.5px; color:var(--muted); line-height:1.5}

/* вход через Telegram */
.co-tg--auth{width:100%; border:0; cursor:pointer; font-family:var(--font-body); margin-bottom:0}

/* пароль с глазком */
.co-pass{position:relative; display:block}
.co-pass input{padding-right:48px}
.co-eye{position:absolute; right:6px; top:50%; transform:translateY(-50%);
  width:40px; height:40px; border:0; background:transparent; cursor:pointer;
  color:var(--muted-2); display:flex; align-items:center; justify-content:center;
  border-radius:50%; transition:color .2s var(--ease)}
.co-eye:hover{color:var(--ink)}
.co-eye.is-on{color:var(--indigo-600)}
.co-eye svg{width:20px; height:20px}

/* «что входит» — плотнее обычного списка доверия */
.co-trust--inc{margin:0 0 4px; gap:7px}
.co-trust--inc li{color:var(--ink-2)}
.co-trust--inc li b{color:var(--indigo-600)}

.co-step{display:none}
.co-step.is-on{display:block; animation:coIn .4s var(--ease-out)}
@keyframes coIn{from{opacity:0; transform:translateX(14px)}to{opacity:1; transform:none}}

.co-title{font-size:21px; letter-spacing:-.04em; margin-bottom:16px}
.co-label{margin:16px 0 8px; font-size:12.5px; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:var(--muted)}

/* шаг 1: тарифы и сроки */
/* ------------------------------------------------ ЗАГЛУШКА ЗАГРУЗКИ -- */
/* Полоска той же высоты, что и строка тарифа. Без неё блок схлопывается на
   время запроса, и всё, что ниже, прыгает вверх и обратно. */
.co-skel{display:flex; align-items:center; gap:11px;
  height:50px; padding:12px 14px; margin-bottom:8px;
  border:1.5px solid var(--border); border-radius:var(--r-md); background:#fff}
.co-skel span{display:block; height:11px; border-radius:5px;
  background:linear-gradient(90deg, #EDEFF6 25%, #F6F7FB 50%, #EDEFF6 75%);
  background-size:200% 100%; animation:coShimmer 1.2s linear infinite}
.co-skel span:first-child{flex:1}
.co-skel span:last-child{width:64px}
@keyframes coShimmer{from{background-position:200% 0}to{background-position:-200% 0}}
@media (prefers-reduced-motion:reduce){ .co-skel span{animation:none} }

/* Пока считаем — число не мигает, а гаснет: замена цифры на другую цифру
   читается как ошибка, а приглушённая цифра как «ещё считаем». */
.is-busy{opacity:.45; transition:opacity .2s var(--ease)}

.co-plans{display:flex; flex-direction:column; gap:8px}
/* Способ доставки отделён от адреса снизу: без этого «Самовывоз» и «Город»
   слипались в один блок, и человек не видел, где кончается выбор. Отступ на
   самом списке, а не на строке ошибки, — она спрятана до первого промаха. */
#coShip .co-reveal__in{padding-bottom:18px}
.co-plan{display:flex; align-items:center; gap:11px; padding:12px 14px;
  border:1.5px solid var(--border); border-radius:var(--r-md); cursor:pointer;
  background:#fff; font-family:var(--font-body); text-align:left; width:100%;
  transition:border-color .25s var(--ease), background-color .25s var(--ease)}
.co-plan.is-on{border-color:var(--indigo-500); background:var(--indigo-50)}
.co-plan__radio{flex:none; width:20px; height:20px; border-radius:50%;
  border:2px solid #C9CEE2; position:relative; transition:border-color .25s var(--ease)}
.co-plan.is-on .co-plan__radio{border-color:var(--indigo-500)}
.co-plan.is-on .co-plan__radio::after{content:''; position:absolute; inset:3px;
  border-radius:50%; background:var(--indigo-500)}
.co-plan__name{flex:1; min-width:0}
.co-plan__name b{display:block; font-size:15px; font-weight:600; letter-spacing:-.01em}
.co-plan__name span{display:block; font-size:12.5px; color:var(--muted)}
.co-plan__price{flex:none; font-family:var(--font-display); font-size:15px;
  font-weight:700; letter-spacing:-.03em; white-space:nowrap}

.co-periods{display:grid; grid-template-columns:repeat(3,1fr); gap:8px}
.co-period{height:40px; border:1.5px solid var(--border); border-radius:var(--r-pill);
  background:#fff; cursor:pointer; font-family:var(--font-body);
  font-size:13.5px; font-weight:600; color:var(--ink-2);
  transition:border-color .25s var(--ease), background-color .25s var(--ease), color .25s var(--ease)}
.co-period.is-on{border-color:var(--indigo-500); background:var(--indigo-50); color:var(--indigo-600)}

.co-total{display:flex; align-items:baseline; justify-content:space-between;
  margin:18px 0 4px; padding-top:16px; border-top:1px dashed var(--border)}
.co-total span{font-size:14px; color:var(--muted)}
.co-total b{font-family:var(--font-display); font-size:25px; letter-spacing:-.04em}

.co-trust{display:flex; flex-direction:column; gap:8px; margin:14px 0 18px}
.co-trust li{position:relative; padding-left:26px; font-size:13.5px; color:var(--muted); line-height:1.5}
.co-trust li b{color:var(--ink-2)}
.co-trust li::before{content:''; position:absolute; left:0; top:2px; width:17px; height:17px; border-radius:50%;
  background:var(--mint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5.5 10.2 8.4 13l6-6.4' stroke='%231E7A54' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/11px no-repeat}

/* шаг 2: поля */
.co-field{display:block; margin-bottom:14px}
.co-field span{display:block; margin-bottom:6px; font-size:13.5px; font-weight:600; color:var(--ink-2)}
.co-field input{width:100%; height:52px; padding:0 16px;
  border:1.5px solid var(--border); border-radius:var(--r-md); outline:none;
  font-family:var(--font-body); font-size:16px; color:var(--ink);
  transition:border-color .25s var(--ease), box-shadow .25s var(--ease)}
.co-field input:focus{border-color:var(--indigo-400); box-shadow:0 0 0 4px rgba(91,75,232,.12)}
.co-field em{display:none; margin-top:6px; font-style:normal; font-size:12.5px; color:#C24B4B}
/* Два узких поля в один ряд. Ниже 340 px разъезжаются обратно в столбик:
   поле шириной в 140 px на телефоне заполнить сложнее, чем прокрутить. */
.co-pair{display:grid; grid-template-columns:1fr 1fr; gap:0 10px}
@media (max-width:340px){ .co-pair{grid-template-columns:1fr} }

/* Подсказка к полю: видна всегда, в отличие от текста ошибки. */
.co-field .co-tip{display:block; margin-top:6px; font-style:normal;
  font-size:12.5px; color:var(--muted)}
.co-field.is-err .co-tip{display:none}
.co-field.is-err input,
.co-field.is-err textarea{border-color:#DFA1A1}
.co-field.is-err em{display:block}
.co-hint{margin:2px 0 16px; font-size:13px; color:var(--muted)}

.co-field--area textarea{width:100%; min-height:64px; padding:12px 16px; resize:vertical;
  border:1.5px solid var(--border); border-radius:var(--r-md); outline:none;
  font-family:var(--font-body); font-size:16px; color:var(--ink); line-height:1.45;
  transition:border-color .25s var(--ease), box-shadow .25s var(--ease)}
.co-field--area textarea:focus{border-color:var(--indigo-400); box-shadow:0 0 0 4px rgba(91,75,232,.12)}
.co-field span i{font-style:normal; font-weight:500; color:var(--muted-2)}

/* «позвоните мне» — по умолчанию выключено: не беспокоим занятых */
.co-callme{display:flex; align-items:flex-start; gap:11px; margin:2px 0 18px;
  padding:13px 14px; border:1.5px solid var(--border); border-radius:var(--r-md);
  cursor:pointer; transition:border-color .25s var(--ease), background-color .25s var(--ease)}
.co-callme:has(input:checked){border-color:var(--indigo-400); background:var(--indigo-50)}
.co-callme input{position:absolute; opacity:0; pointer-events:none}
.co-callme__box{flex:none; width:22px; height:22px; margin-top:1px; border-radius:7px;
  border:2px solid #C9CEE2; color:#fff; display:flex; align-items:center; justify-content:center;
  transition:background-color .2s var(--ease), border-color .2s var(--ease)}
.co-callme__box svg{width:13px; height:13px; opacity:0; transition:opacity .2s var(--ease)}
.co-callme:has(input:checked) .co-callme__box{background:var(--indigo-500); border-color:var(--indigo-500)}
.co-callme:has(input:checked) .co-callme__box svg{opacity:1}
.co-callme__text{font-size:14px; color:var(--ink-2); line-height:1.45}
.co-callme__text em{display:block; margin-top:2px; font-style:normal; font-size:12.5px; color:var(--muted)}

/* привязка Telegram и трек заказа */
.co-track{display:flex; align-items:center; gap:6px; margin:0 0 16px}
.co-track span{flex:none; padding:5px 10px; border-radius:var(--r-pill);
  background:#F1F2F7; color:var(--muted); font-size:11.5px; font-weight:600}
.co-track span.is-on{background:var(--indigo-50); color:var(--indigo-600)}
.co-track i{flex:1; height:2px; border-radius:1px; background:#E8EAF2}

.co-tg{display:flex; align-items:center; justify-content:center; gap:9px;
  height:52px; border-radius:var(--r-pill); margin-bottom:8px;
  background:#229ED9; color:#fff; font-size:15px; font-weight:600;
  box-shadow:0 10px 26px rgba(34,158,217,.35);
  transition:transform .25s var(--ease), box-shadow .25s var(--ease)}
.co-tg:hover{transform:translateY(-2px); box-shadow:0 14px 34px rgba(34,158,217,.45)}
.co-tg svg{width:20px; height:20px}
.co-tg__hint{margin:0 0 18px; font-size:12.5px; color:var(--muted); text-align:center; line-height:1.5}

.co-back{display:block; margin:12px auto 0; padding:8px 14px; border:0; background:transparent;
  cursor:pointer; font-family:var(--font-body); font-size:14px; color:var(--muted);
  border-radius:var(--r-pill); transition:color .2s var(--ease)}
.co-back:hover{color:var(--ink)}

/* шаг 3: сводка */
.co-summary{margin-bottom:18px; padding:16px 18px; border-radius:var(--r-md);
  background:#F6F7FB; display:flex; flex-direction:column; gap:8px}
.co-summary .row{display:flex; justify-content:space-between; gap:12px; font-size:14px; color:var(--muted)}
.co-summary .row b{color:var(--ink); font-weight:600; text-align:right}
.co-summary .row--total{padding-top:8px; border-top:1px dashed var(--border); font-size:15px}
.co-summary .row--total b{font-family:var(--font-display); font-size:18px; letter-spacing:-.03em}
.co-summary .row--off{color:var(--mint-fg, #1B7A4B)}
.co-summary .row--off b{color:inherit}
.co-secure{margin-top:12px; font-size:12.5px; color:var(--muted-2); text-align:center; line-height:1.5}

/* Чем платить. Сначала валюта — двумя вкладками, потом способ — списком:
   один общий перечень отказывает тому, у кого нет карты. */
#coPayWays{margin-top:18px}
#coPayWays .co-label{margin-top:0}

.co-cur{display:grid; grid-template-columns:1fr 1fr; gap:6px; padding:4px;
  margin-bottom:10px; background:#F2F3F9; border-radius:var(--r-md)}
.co-cur__item{height:40px; border:0; border-radius:calc(var(--r-md) - 4px);
  background:transparent; cursor:pointer;
  font-family:var(--font-body); font-size:14px; font-weight:600; color:var(--muted);
  transition:background .2s var(--ease), color .2s var(--ease)}
.co-cur__item.is-on{background:#fff; color:var(--ink); box-shadow:0 1px 3px rgba(16,18,40,.1)}

.co-ways{display:flex; flex-direction:column; gap:8px}
.co-way{display:block; width:100%; padding:13px 16px; text-align:left;
  border:1.5px solid var(--border); border-radius:var(--r-md);
  background:#fff; cursor:pointer;
  transition:border-color .2s var(--ease), background .2s var(--ease)}
.co-way:hover{border-color:var(--indigo-300, #B9B0F5)}
.co-way.is-on{border-color:var(--indigo-500); background:var(--indigo-50)}
.co-way__t{display:block; font-family:var(--font-body); font-size:15px;
  font-weight:600; color:var(--ink)}
.co-way__h{display:block; margin-top:2px; font-size:12.5px; color:var(--muted)}

.co-paynote{margin:10px 0 0; font-size:13px; color:var(--muted); line-height:1.5}

/* Промокод свёрнут в ссылку: он есть у меньшинства, а пустое поле «промокод»
   у остальных вызывает чувство, что они переплачивают. */
/* [hidden] должен побеждать display: без этого кнопка «у меня есть
   промокод» остаётся висеть под уже раскрытым полем. */
.co-promotoggle[hidden]{display:none}
.co-promotoggle{display:inline-flex; align-items:center; gap:7px; margin-top:14px;
  padding:0; border:0; background:none; cursor:pointer;
  font-family:var(--font-body); font-size:13.5px; font-weight:600; color:var(--indigo-600)}
.co-promotoggle svg{width:17px; height:17px}
.co-promotoggle:hover{color:var(--indigo-700, #4438C8)}

.co-promo{display:flex; gap:8px; margin-top:12px}
.co-promo input{flex:1; min-width:0; height:48px; padding:0 14px;
  border:1.5px solid var(--border); border-radius:var(--r-md); outline:none;
  font-family:var(--font-body); font-size:16px; font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; color:var(--ink);
  transition:border-color .25s var(--ease)}
.co-promo input:focus{border-color:var(--indigo-400); box-shadow:0 0 0 4px rgba(91,75,232,.12)}
.co-promo .btn{flex:none; height:48px}

.co-promomsg{margin-top:8px; font-size:13px; color:#C24B4B}
.co-promomsg.is-ok{color:var(--mint-fg, #1B7A4B)}

/* шаг 4: готово */
.co-step--final{text-align:center; padding-top:6px}
.co-ordernum{display:inline-block; margin:-6px 0 14px; padding:6px 15px;
  background:var(--indigo-50); color:var(--indigo-600); border-radius:var(--r-pill);
  font-family:var(--font-display); font-size:13.5px; font-weight:700; letter-spacing:-.01em}
.co-summary--final{text-align:left; margin-bottom:16px}
.co-done{display:flex; align-items:center; justify-content:center; width:64px; height:64px;
  margin:0 auto 16px; border-radius:50%; background:var(--mint); color:var(--mint-fg);
  animation:pop .6s var(--ease-out)}
.co-done svg{width:30px; height:30px}
.co-final{display:flex; flex-direction:column; gap:10px; margin:16px 0 22px; text-align:left}
.co-final li{position:relative; padding-left:26px; font-size:14.5px; color:var(--muted); line-height:1.55}
.co-final li b{color:var(--ink-2)}
.co-final li::before{content:''; position:absolute; left:0; top:3px; width:17px; height:17px; border-radius:50%;
  background:var(--mint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none'%3E%3Cpath d='M5.5 10.2 8.4 13l6-6.4' stroke='%231E7A54' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/11px no-repeat}

body.co-lock{overflow:hidden}

@media (max-width:700px){
  /* на телефоне чекаут — шторка снизу во весь экран */
  .checkout__panel{left:0; right:0; top:auto; bottom:0; transform:translateY(6%);
    width:100%; max-height:calc(100dvh - 24px);
    border-radius:24px 24px 0 0; padding:22px 18px calc(18px + env(safe-area-inset-bottom))}
  .checkout.is-open .checkout__panel{transform:none}
}

/* ==========================================================================
   ПОДДЕРЖКА СБОКУ
   Кнопка висит в углу и едет со страницей: человек, у которого что-то не
   работает, не должен листать наверх к шапке или искать раздел «Поддержка».
   На широком экране это плашка с подписью, на телефоне — кружок: там каждый
   пиксель у нижнего края занят.
   ========================================================================== */
.helper{position:fixed; right:20px; bottom:20px; z-index:90;
  display:flex; flex-direction:column; align-items:flex-end; gap:12px}

.helper__btn{display:inline-flex; align-items:center; gap:9px;
  height:52px; padding:0 20px 0 16px; border:0; border-radius:26px; cursor:pointer;
  background:var(--indigo-600, #4A38DC); color:#fff;
  font:600 15px/1 var(--font-body, inherit);
  box-shadow:0 14px 34px rgba(74,56,220,.34);
  transition:transform .22s var(--ease-out, cubic-bezier(.22,1,.36,1)), box-shadow .22s ease}
.helper__btn:hover{transform:translateY(-2px); box-shadow:0 18px 42px rgba(74,56,220,.42)}
.helper__btn:active{transform:none}
.helper__btn:focus-visible{outline:3px solid rgba(74,56,220,.4); outline-offset:3px}
.helper__ico{display:grid; place-items:center; width:22px; height:22px}
.helper__ico svg{width:22px; height:22px}

/* Открытое окно и кнопка одновременно ни к чему: кнопка превращается в
   «свернуть», а закрывает окно крестик в его шапке. */
.helper.is-open .helper__btn{display:none}

/* Окно чата. Колонкой и с потолком по высоте: лента внутри прокручивается
   сама, а окно, растущее с каждым сообщением, к десятому закроет страницу. */
.helper__panel{display:flex; flex-direction:column;
  width:min(360px, calc(100vw - 32px)); max-height:min(74vh, 620px);
  background:#fff; border-radius:20px; overflow:hidden;
  box-shadow:0 26px 70px rgba(12,14,36,.24);
  animation:helperIn .26s var(--ease-out, cubic-bezier(.22,1,.36,1))}
@keyframes helperIn{from{opacity:0; transform:translateY(14px) scale(.98)}to{opacity:1; transform:none}}
/* Своё `display` перебивает атрибут `hidden`: правило браузера слабее
   авторского, и закрытое окно осталось бы на экране. */
.helper__panel[hidden]{display:none}

.helper__head{flex:none; display:flex; align-items:center; gap:11px; padding:14px 14px 14px 16px;
  background:linear-gradient(135deg,#5B4BE8,#4A38DC); color:#fff}
.helper__ava{flex:none; display:grid; place-items:center; width:38px; height:38px;
  border-radius:13px; background:rgba(255,255,255,.16)}
.helper__ava svg{width:24px; height:22px}
.helper__who{flex:1; min-width:0; display:flex; flex-direction:column; gap:2px}
.helper__who b{font-size:14.5px; line-height:1.2}
.helper__who span{display:flex; align-items:center; gap:6px; font-size:12px; opacity:.86}
.helper__who i{width:7px; height:7px; border-radius:50%; background:#5BE49B}
/* Крестик — 40 пикселей: меньше на телефоне не попадают пальцем, а
   промахнуться по «закрыть» — значит нажать что-то в переписке. */
.helper__x{flex:none; width:40px; height:40px; display:grid; place-items:center;
  border:0; border-radius:10px; background:rgba(255,255,255,.14); color:#fff; cursor:pointer;
  transition:background .18s ease}
.helper__x:hover{background:rgba(255,255,255,.26)}
.helper__x svg{width:16px; height:16px}

.helper__body{display:flex; flex-direction:column; min-height:0; padding:14px 14px 12px}
.helper__lead{margin:0 0 14px; font-size:13.5px; line-height:1.5; color:var(--muted, #6B7189)}

/* Лента переписки. Высота задана и ограничена: окно, растущее с каждым
   сообщением, к десятому закрывает страницу целиком. */
.helper__feed{flex:1; min-height:0; max-height:min(46vh, 340px); overflow-y:auto;
  display:flex; flex-direction:column; gap:8px; margin:-2px -4px 10px; padding:2px 4px;
  scrollbar-width:thin; scrollbar-color:#D7DAE8 transparent; overscroll-behavior:contain}
.helper__feed::-webkit-scrollbar{width:6px}
.helper__feed::-webkit-scrollbar-thumb{background:#D7DAE8; border-radius:3px}
.helper__feed:empty{display:none}

/* Сообщение в окне помощника. Своё — справа и цветом, чужое — слева и белым:
   это единственный способ понять с одного взгляда, кто что сказал.

   Правила привязаны к `.helper__feed` намеренно. Раньше они были общими для
   класса `.msg` — и, стоя в файле ниже, перебивали фон пузырей в
   демонстрации переписки на главной: там у реплики клиента оставался белый
   текст, а градиент заменялся на светло-серый #F2F3F9. Белым по белому —
   ровно то, что увидел владелец. Специфичность у `.msg` и `.msg--user`
   одинаковая, поэтому побеждал тот, кто ниже. */
.helper__feed .msg{max-width:86%; align-self:flex-start; display:flex; flex-direction:column; gap:2px;
  padding:9px 12px; border-radius:14px 14px 14px 5px;
  background:#F2F3F9; font-size:13.5px; line-height:1.45}
.helper__feed .msg--mine{align-self:flex-end; border-radius:14px 14px 5px 14px;
  background:var(--indigo-600, #4A38DC); color:#fff}
.helper__feed .msg__who{font-size:11.5px; font-weight:600; color:var(--indigo-600, #4A38DC)}
.helper__feed .msg__text{white-space:pre-wrap; word-break:break-word}
.helper__feed .msg__state{align-self:flex-end; font-style:normal; font-size:10.5px; opacity:.62}
.helper__feed .msg--mine .msg__state{color:#fff}
.msg__state--err{opacity:1; color:#D2453B}
.msg--mine .msg__state--err{color:#FFD6D2}

/* Служебная строка — по центру и мельче: это не собеседник, а пометка. */
.chatline{margin:2px 0; text-align:center; font-size:11.5px; color:var(--muted, #6B7189)}

/* Уйти в Telegram — значком в шапке, рядом с крестиком: там его ищут, и он
   не стоит на пути к полю ввода. Строкой в списке он предлагал человеку,
   который уже открыл чат, уйти писать в другое место. */
.helper__tgbox{flex:none; display:flex}
.helper__tg{display:grid; place-items:center; width:40px; height:40px;
  border-radius:12px; background:rgba(255,255,255,.14); color:#fff;
  transition:background .18s ease}
.helper__tg:hover{background:rgba(255,255,255,.26)}
.helper__tg svg{width:19px; height:19px}

/* Строка ввода. Поле и кнопка в одной рамке: два отдельных прямоугольника
   рядом читаются как «поле и что-то ещё», а не как «написать и отправить». */
.helper__send{display:flex; align-items:flex-end; gap:6px; padding:5px;
  border:1px solid var(--border-2, #E6E8F0); border-radius:16px; background:#fff;
  transition:border-color .18s ease, box-shadow .18s ease}
.helper__send:focus-within{border-color:var(--indigo-500, #6A57EA);
  box-shadow:0 0 0 3px rgba(106,87,234,.14)}
.helper__send textarea{flex:1; min-width:0; height:34px; max-height:96px; padding:8px 0 7px;
  border:0; outline:none; resize:none; background:transparent; color:inherit;
  font:inherit; font-size:14px; line-height:1.35}
.helper__send button{flex:none; display:grid; place-items:center; width:36px; height:36px;
  border:0; border-radius:12px; cursor:pointer;
  background:var(--indigo-600, #4A38DC); color:#fff;
  transition:opacity .18s ease}
.helper__send button:hover{opacity:.88}
.helper__send svg{width:18px; height:18px}

/* Скрепка — тихая: она рядом с отправкой, и две одинаково яркие кнопки
   заставляют выбирать там, где выбора нет. Размер как у отправки — по пальцу,
   а не по значку. */
#helperPick{background:transparent; color:var(--muted, #6B7189)}
#helperPick:hover{background:var(--surface-2, #F2F3F9); color:var(--ink, #1B1E2B); opacity:1}

/* Что приложено — видно до отправки. Без предпросмотра человек не уверен, что
   выбрал тот самый файл, и прикладывает ещё раз. */
.helper__clip{display:flex; align-items:center; gap:8px; margin-bottom:6px; padding:5px 6px;
  border:1px solid var(--border-2, #E6E8F0); border-radius:12px; background:#fff}
.helper__clip img{flex:none; width:34px; height:34px; object-fit:cover; border-radius:8px}
.helper__clip span{flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; font-size:12px; color:var(--muted, #6B7189)}
.helper__clip button{flex:none; display:grid; place-items:center; width:28px; height:28px;
  border:0; border-radius:8px; cursor:pointer; background:transparent;
  color:var(--muted, #6B7189)}
.helper__clip button:hover{background:var(--surface-2, #F2F3F9); color:#D2453B}
.helper__clip svg{width:15px; height:15px}

/* Картинка в переписке. Снимок экрана вытянут по вертикали, и без ограничения
   высоты один такой занимает всё окно, выталкивая разговор. */
.msg__img{max-width:100%; max-height:220px; width:auto; border-radius:9px;
  object-fit:cover; background:rgba(0,0,0,.05)}

.helper__note{margin:8px 0 0; font-size:12px; line-height:1.45; color:var(--muted, #6B7189)}
.helper__note:empty{display:none}
.helper__note--err{color:#D2453B}

@media (max-width:700px){
  /* Липкая полоса «Заказать роутер» стоит у самого низа — кнопка садится над
     ней, иначе они накладываются и обе становятся неудобными. */
  .helper{right:14px; bottom:78px; gap:10px}
  .helper__label{display:none}
  .helper__btn{width:52px; padding:0; justify-content:center}
}

@media (prefers-reduced-motion:reduce){
  .helper__panel{animation:none}
  .helper__btn:hover{transform:none}
}

/* FE-01: каталог не подтверждён сервером (пустой /api/shop/plans или сеть
   недоступна) — цена CTA становится необоснованным обещанием. Класс ставится
   из app.js::heroPricesSync(); правило здесь (не в styles.css), потому что
   .btn--primary в этом файле переопределяет opacity позже по каскаду. */
body.is-catalog-unavailable [data-checkout]{opacity:.72 !important; transition:opacity .2s var(--ease)}
body.is-catalog-unavailable [data-checkout]:hover{opacity:.86 !important}

/* --------------------------------------------- ПОДПИСИ НА ПЛИТКАХ -------
   Подпись под названием сервиса («видео», «нейросети», «музыка») была
   10,5 px и погашена до .75 — формально контраст проходил, а глазом
   на светлой плитке это читалось как серая дымка.

   Гасить текст свойством `opacity` вообще плохая привычка: оно не видно
   ни в одной проверке цвета и легко уезжает вместе с фоном. Берём
   честный цвет и чуть крупнее кегль. */
.sc-tile__name span{opacity:1; font-size:11.5px; color:rgba(255,255,255,.72)}

/* Включённая плитка белая в ОБЕИХ темах — значит и текст на ней должен
   быть тёмным в обеих. Раньше он брался из `--ink-2`, а этот токен ночью
   переворачивается в светлый: получалось светло-серое по белому, и
   названия сервисов пропадали. Здесь тема не при чём, цвет прибит. */
.sc-tile.is-on .sc-tile__name{color:#2B2E3D}
.sc-tile.is-on .sc-tile__name span{color:#5A5870}

/* ============================================================
   ГДЕ СПРОСИТЬ — выбор между чатом на сайте и Телеграмом
   ============================================================ */
.vybor{position:fixed; inset:0; z-index:120; display:grid; place-items:center;
  padding:16px; padding-bottom:calc(16px + env(safe-area-inset-bottom,0px))}
.vybor[hidden]{display:none}
.vybor__fon{position:absolute; inset:0; background:rgba(16,12,44,.52);
  backdrop-filter:blur(3px); animation:vyborFon .2s ease both}
.vybor__okno{position:relative; width:min(420px,100%); max-height:100%; overflow:auto;
  background:var(--card,#fff); color:var(--ink,#14121F);
  border-radius:20px; padding:26px 22px 22px;
  box-shadow:0 24px 60px rgba(16,12,44,.3);
  animation:vyborOkno .26s var(--ease-out,cubic-bezier(.2,.8,.2,1)) both}
@keyframes vyborFon{from{opacity:0}to{opacity:1}}
@keyframes vyborOkno{from{opacity:0; transform:translateY(14px) scale(.98)}to{opacity:1; transform:none}}
@media (prefers-reduced-motion:reduce){
  .vybor__fon,.vybor__okno{animation:none}
}

.vybor__x{position:absolute; top:10px; right:10px; width:44px; height:44px;
  display:grid; place-items:center; cursor:pointer;
  border:0; background:transparent; color:var(--muted,#6B7086); border-radius:50%}
.vybor__x svg{width:20px; height:20px}
.vybor__x:hover{background:rgba(0,0,0,.05); color:var(--ink,#14121F)}

.vybor__title{margin:0 40px 4px 0; font-family:var(--font-display); font-size:21px; letter-spacing:-.02em}
.vybor__lead{margin:0 0 18px; font-size:14px; color:var(--muted,#6B7086); line-height:1.5}

.vybor__put{display:flex; width:100%; gap:13px; align-items:flex-start; text-align:left;
  margin:0 0 10px; padding:14px; min-height:44px; cursor:pointer;
  font:inherit; color:inherit; text-decoration:none;
  background:var(--paper,#F6F6FB); border:1px solid transparent; border-radius:14px;
  transition:border-color .16s, background .16s, transform .16s}
.vybor__put:last-child{margin-bottom:0}
.vybor__put:hover{border-color:var(--indigo-500,#5B4BE8); transform:translateY(-1px)}
.vybor__put:focus-visible{outline:3px solid var(--indigo-500,#5B4BE8); outline-offset:2px}
.vybor__put[hidden]{display:none}

.vybor__ikona{flex:none; width:40px; height:40px; border-radius:11px;
  display:grid; place-items:center; color:#fff}
.vybor__ikona svg{width:21px; height:21px}
.vybor__ikona--sajt{background:linear-gradient(135deg,var(--indigo-500,#5B4BE8),var(--indigo-600,#4A38DC))}
.vybor__ikona--tg{background:linear-gradient(135deg,#3FA9E4,#1E88C7)}

.vybor__txt{display:flex; flex-direction:column; gap:2px; min-width:0}
.vybor__txt b{font-size:15.5px; font-weight:700}
.vybor__txt span{font-size:13px; line-height:1.45; color:var(--muted,#6B7086)}
