/* ─────────────────────────────────────────────────────────────────────────
   Сайт Юны. Дизайн по макету «stitch_yuna_desktop_ai_assistant» (Cosmic
   Minimalist), переложенному на свой CSS.

   Обновлено 26.08.2026 по второму макету владельца (Yuna_Purple_Style_Preview):

   * основа #0B0A16, карточки СПЛОШНЫЕ (#151226) вместо стекла с размытием -
     контраст текста выше, а рисуется дешевле: backdrop-filter стоит отдельного
     прохода растеризации на каждой карточке;
   * рамки #2B254D, с фиолетовым подтоном, вместо белого альфа-канала;
   * акцент #9B72FF - только главные действия и состояния;
   * заголовки разделов капсом, трекинг -0.02em; на h1 капса нет намеренно -
     длинная фраза первого экрана капсом читается заметно медленнее;
   * кнопки капсом, у главной - свечение и подъём на 2px при наведении;
   * один радиус на всю систему (12px) вместо разнобоя 8/16/24;
   * первый экран во всю высоту: текст слева, фигура справа во весь рост.

   Из макета НЕ взят его шрифт заголовков Space Grotesk: у него нет кириллицы,
   и русские заголовки в самом предпросмотре рисовались системным шрифтом.
   Onest - тот же геометрический гротеск, но с русскими буквами.

   Тема одна, тёмная, намеренно. Раз одна - фон и цвета проставлены явно,
   чтобы страница не подхватывала чужой.
   ───────────────────────────────────────────────────────────────────────── */

:root{
  --bg:#0B0A16;
  --bg-nav:rgba(11,10,22,.85);
  /* Карточки стали СПЛОШНЫМИ (макет 26.08.2026). Стекло с размытием красиво на
     скриншоте, но на тёмном фоне даёт низкий контраст текста, а backdrop-filter
     стоит отдельного прохода растеризации на каждой карточке. Плотная заливка
     читается лучше и рисуется дешевле. */
  --bg-card:#151226;
  --glass:#151226;
  --glass-line:#2B254D;      /* рамка с фиолетовым подтоном, а не белый альфа */
  --glass-strong:#1B1733;

  --accent:#9B72FF;          /* главные действия */
  --accent-hover:#B493FF;
  --accent-soft:#D0BCFF;     /* заголовки-акценты, значки */
  --accent-line:rgba(155,114,255,.55);

  --text:#FFFFFF;
  --body:#CBC3D7;
  --dim:#958EA0;
  --ok:#34D399;

  --glow:0 0 40px rgba(155,114,255,.15);
  --glow-accent:0 4px 20px rgba(155,114,255,.3);

  --ui:'Onest','Manrope','Segoe UI',system-ui,sans-serif;
  --mono:'JetBrains Mono',ui-monospace,Consolas,monospace;

  --page:1440px;
  --gutter:24px;
  --side:64px;

  /* Радиусы сведены к одному значению: в макете вся система на 12px, и разнобой
     8/16/24 читался как несколько разных наборов элементов на одной странице. */
  --r-sm:10px;
  --r-lg:12px;
  --r-xl:14px;
}

*{box-sizing:border-box}
/* Атрибут hidden в браузерном стиле - это всего лишь display:none, и любой наш
   display его перебивает по правилам каскада. Ровно так в шапке одновременно
   светились «Войти» и «Выйти»: у .account стоит display:flex. */
[hidden]{display:none!important}
html{scroll-behavior:smooth}
body{
  margin:0; background:var(--bg); color:var(--body);
  font-family:var(--ui); font-size:16px; line-height:1.6;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
img{max-width:100%;height:auto;display:block}
a{color:var(--accent-soft);text-decoration:none}
a:hover{color:#E9DDFF}
h1,h2,h3{margin:0;color:var(--text);text-wrap:balance;letter-spacing:-.02em}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:6px}
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  html{scroll-behavior:auto}
}

.glass{
  background:var(--bg-card); border:1px solid var(--glass-line);
  border-radius:var(--r-lg);
}

.label{
  font-family:var(--mono); font-size:12px; font-weight:500;
  letter-spacing:.05em; text-transform:uppercase; color:var(--dim);
}

/* ── Шапка ────────────────────────────────────────────────────────────── */
.nav{
  position:fixed; top:0; left:0; right:0; z-index:50; height:72px;
  background:var(--bg-nav); backdrop-filter:blur(20px);
  border-bottom:1px solid var(--glass-line);
}
.nav-inner{
  height:100%; max-width:var(--page); margin:0 auto;
  padding:0 var(--gutter); display:flex; align-items:center; gap:24px;
}
.brand{display:flex;align-items:center;gap:10px;color:var(--accent-soft);font-weight:700;font-size:19px;letter-spacing:.06em}
.brand img{width:30px;height:30px;border-radius:8px}
.nav-links{display:flex;gap:28px;margin-left:20px}
.nav-links a{color:var(--body);font-size:15px}
.nav-links a:hover{color:var(--text)}
.who{margin-left:auto;display:flex;align-items:center;gap:14px}
.account{display:flex;align-items:center;gap:12px}
.account-mail{color:var(--body);font-size:14px;max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chip{
  font-family:var(--mono); font-size:11px; letter-spacing:.05em; text-transform:uppercase;
  padding:5px 11px; border-radius:999px;
  background:rgba(155,114,255,.2); color:var(--accent-soft);
}
.chip.free{background:transparent;border:1px solid var(--glass-line);color:var(--dim)}
.linkish{background:none;border:0;padding:0;color:var(--dim);font:inherit;font-size:14px;cursor:pointer}
.linkish:hover{color:var(--body)}
@media (max-width:900px){ .nav-links{display:none} }

/* ── Кнопки ───────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  font:inherit; font-weight:700; cursor:pointer; text-align:center;
  text-transform:uppercase; letter-spacing:.03em;
  padding:14px 28px; border-radius:var(--r-lg); border:1px solid transparent;
  transition:background-color .2s ease, box-shadow .2s ease,
             border-color .2s ease, transform .1s ease;
}
.btn svg{width:18px;height:18px}
.btn.big{padding:16px 32px;font-size:17px}
.btn.small{padding:9px 20px;font-size:14px}
.btn.wide{display:flex;width:100%}
.btn.primary{background:var(--accent);color:#fff;box-shadow:var(--glow-accent)}
.btn.primary:hover{
  background:var(--accent-hover); color:#fff; transform:translateY(-2px);
  box-shadow:0 6px 25px rgba(155,114,255,.4);
}
.btn.primary:active{transform:translateY(0)}
.btn.ghost{background:var(--glass);border-color:var(--accent-line);color:var(--text)}
.btn.ghost:hover{background:var(--glass-strong);color:var(--text)}
.btn.off{opacity:.45;pointer-events:none}
.cta{display:flex;gap:14px;flex-wrap:wrap;margin:32px 0 18px}
.cta.center{justify-content:center;margin:40px 0 14px}

/* ── Раскладка ────────────────────────────────────────────────────────── */
main{position:relative;z-index:1;max-width:var(--page);margin:0 auto}
.band{padding:80px var(--gutter)}
.band-head{text-align:center;margin-bottom:48px}
/* Капс - главный приём макета. На h1 его НЕТ намеренно: длинная фраза первого
   экрана капсом читается заметно медленнее. */
h2.title{
  font-size:clamp(26px,3.4vw,34px); font-weight:700; line-height:1.1;
  text-transform:uppercase; letter-spacing:-.02em;
}
.band-head p{color:var(--body);max-width:60ch;margin:14px auto 0}
.fineprint{font-size:14px;color:var(--dim);margin:8px 0}
.fineprint.center{text-align:center;max-width:70ch;margin-left:auto;margin-right:auto}
code{font-family:var(--mono);font-size:.85em;color:var(--body);word-break:break-all}

/* ── Первый экран ─────────────────────────────────────────────────────── */
.hero{
  position:relative; min-height:min(100vh,900px); padding:120px var(--gutter) 40px;
  max-width:var(--page); margin:0 auto;
  display:grid; grid-template-columns:1fr 1fr; gap:40px; align-items:center;
}
/* Радиальное свечение вместо заливки - подсвечивает зону, не рисуя края. */
.hero::before{
  content:''; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(circle at center,rgba(155,114,255,.1) 0%,transparent 70%);
}
.hero > *{position:relative;z-index:1}
.hero h1{
  font-size:clamp(38px,5.4vw,60px); font-weight:700; line-height:1.08;
  letter-spacing:-.025em; margin-bottom:26px;
}
.hero .lead{color:var(--body);font-size:17px;max-width:46ch;margin:0}
.note-accent{color:var(--accent-soft);font-size:15px;font-weight:600;margin:10px 0 0}

/* Предупреждение Windows. Свёрнуто по умолчанию намеренно: развёрнутый абзац
   про антивирус на первом экране продаёт хуже, чем строка, которую человек
   откроет сам - и откроет ровно тогда, когда предупреждение уже увидел. */
.warn{margin:18px 0 0;max-width:52ch;font-size:14px;color:var(--dim)}
.warn summary{
  cursor:pointer; color:var(--body); list-style:none;
  padding:10px 14px; border:1px solid var(--glass-line); border-radius:10px;
  background:var(--glass);
}
.warn summary::-webkit-details-marker{display:none}
.warn summary::before{content:'▸ ';color:var(--accent-soft)}
.warn[open] summary::before{content:'▾ '}
.warn summary:hover{color:var(--text)}
.warn-body{padding:14px 14px 2px}
.warn-body p{margin:0 0 10px}
.warn-body b{color:var(--body)}
.warn .mono{font-family:var(--mono);font-size:12px;color:var(--body);word-break:break-all}

/* Фигура во весь рост - главный приём макета. Свечение под ней, никакой рамки:
   она стоит в пустоте, как стоит поверх окон на рабочем столе. */
.figure{position:relative;display:flex;justify-content:center;align-items:flex-end;height:min(78vh,760px)}
/* Свечение радиальным градиентом, а не filter:blur(100px). Выглядит так же,
   но блюр в сто пикселей - это отдельный проход растеризации рядом с холстом,
   который перерисовывается каждый кадр. */
.figure::before{
  content:''; position:absolute; left:50%; bottom:6%; transform:translateX(-50%);
  width:min(520px,100%); aspect-ratio:1; border-radius:50%;
  background:radial-gradient(circle,rgba(155,114,255,.3) 0%,rgba(155,114,255,.12) 45%,transparent 70%);
}
.figure img{
  position:absolute; inset:0; margin:auto; height:100%; width:auto; z-index:2;
  transition:opacity .55s ease;
}
/* Картинка лежит СВЕРХУ холста и гаснет, когда модель ожила. Наоборот нельзя:
   проявление холста через opacity гасит и саму модель - полупрозрачная фигура
   смешивается с фоном и выцветает. Померено на рендере: пиксель лица
   (151,129,145) во время перехода против (254,227,216) без него. */
.figure img.gone{opacity:0;pointer-events:none}
/* Холст по форме фигуры, а не во всю колонку. Растянутый на колонку, он на
   две трети состоял из пустоты, которую видеокарта всё равно перерисовывала
   каждый кадр: 700x760 против 274x760 - это втрое больше заливки ни за что.
   Отношение чуть шире самой фигуры (0.283), чтобы её не срезало на покачивании.

   drop-shadow здесь тоже был и тоже убран: тень считается от альфа-канала
   заново на КАЖДОМ кадре. На этой машине она стоила немного, но на встроенной
   графике такое - первое, что роняет частоту. Ореол даёт свечение под фигурой. */
/* Ширину холста задаёт сам вьювер (CANVAS_ASPECT), PIXI проставляет её
   элементу в пикселях - здесь только высота и место в потоке. */
#live2d{position:relative;z-index:1;flex:0 0 auto;height:100%}
.live2d-canvas{display:block}
@media (max-width:900px){
  .hero{grid-template-columns:1fr;min-height:0;padding-top:100px;text-align:center}
  .hero .lead{margin:0 auto}
  .cta{justify-content:center}
  .figure{height:min(60vh,460px);order:-1}
}


/* ── Где размывать подложку, а где не за что платить ─────────────────────
   Макет требует «стекло» вместо сплошных заливок, и на шапке с окном входа
   это работает: под ними едет содержимое страницы, размытие видно.

   На карточках - нет. За ними ровный тёмный фон плюс очень мягкое свечение,
   и blur(20px) по нему не меняет ни пикселя. Зато стоит: элемент с
   backdrop-filter браузер выносит в отдельную поверхность, а вместе со
   скрытым состоянием появления (opacity:0 + transform) таких поверхностей
   набирается три десятка.

   Замер на настоящей странице, без vsync, dpr 2: 8.3 мс на кадр против 4.8
   без размытия, худший кадр 28.2 против 9.0. Плата за эффект, которого не
   видно.
   ───────────────────────────────────────────────────────────────────────── */

/* ── Карточки возможностей ───────────────────────────────────────────── */
/* Ровно три в ряд, как в макете. auto-fit на широком экране раскладывал шесть
   карточек как 4+2 - вторая строка повисала неряшливым огрызком. */
.cards{display:grid;grid-template-columns:1fr;gap:var(--gutter)}
@media (min-width:680px){ .cards{grid-template-columns:repeat(2,1fr)} }
@media (min-width:1040px){ .cards{grid-template-columns:repeat(3,1fr)} }
.card{
  background:var(--bg-card); border:1px solid var(--glass-line);
  border-radius:var(--r-lg); padding:36px 28px; text-align:center;
  transition:box-shadow .3s ease, transform .3s ease, border-color .3s ease;
}
.card:hover{box-shadow:var(--glow);transform:translateY(-5px);border-color:var(--accent)}
.card .ico{width:36px;height:36px;color:var(--accent-soft);margin:0 auto 20px}
.card h3{font-size:22px;font-weight:600;margin-bottom:12px;color:#E6E0F1}
.card p{margin:0;color:var(--body);font-size:15px}
.card .step-no{
  font-family:var(--mono); font-size:13px; letter-spacing:.14em;
  color:var(--accent); margin:0 0 14px;
}

/* ── Тарифы ───────────────────────────────────────────────────────────── */
.plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--gutter);align-items:start}
.plan{
  position:relative; display:flex; flex-direction:column;
  background:var(--bg-card); border:1px solid var(--glass-line);
  border-radius:var(--r-lg); padding:40px 32px;
  transition:border-color .3s ease;
}
.plan:hover{border-color:var(--accent-line)}
.plan.best{
  background:rgba(155,114,255,.05); border-color:var(--accent);
  box-shadow:var(--glow-accent); z-index:2;
}
.tag{
  position:absolute; top:-13px; left:50%; transform:translateX(-50%); white-space:nowrap;
  background:var(--accent); color:#fff; padding:5px 16px; border-radius:999px;
  font-family:var(--mono); font-size:11px; letter-spacing:.05em; text-transform:uppercase;
}
.plan h3{font-size:22px;font-weight:600;margin-bottom:8px;color:#E6E0F1}
.plan.best h3{color:var(--accent-soft)}
.price{font-size:34px;font-weight:600;color:var(--text);margin:0;font-variant-numeric:tabular-nums}
.price small{font-size:15px;font-weight:400;color:var(--body);margin-left:6px}
.term{color:var(--dim);font-size:14px;margin:8px 0 26px}
.perks{list-style:none;margin:0 0 32px;padding:0;flex-grow:1}
.perks li{display:flex;align-items:flex-start;gap:11px;margin-bottom:12px;color:var(--body);font-size:15px;line-height:1.5}
.perks .mark{flex:0 0 auto;color:var(--accent-soft);margin-top:4px}
.perks .mark svg{width:14px;height:14px;display:block}
.perks b{color:#E6E0F1;font-weight:600}

/* ── Условия: карточка с акцентной гранью, как в макете ──────────────── */
.notice{
  position:relative; overflow:hidden; max-width:900px; margin:0 auto;
  background:var(--glass); border:1px solid var(--glass-line);
  border-left:4px solid var(--accent-line);
  border-radius:var(--r-lg); padding:40px 36px;
}
.notice::before{
  content:''; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(90deg,rgba(155,114,255,.05),transparent);
}
.notice-body{position:relative;z-index:1;display:flex;gap:24px;align-items:flex-start}
.notice-body > svg{width:26px;height:26px;flex:0 0 auto;color:var(--accent-soft);margin-top:2px}
.notice h2{font-size:24px;font-weight:600;margin-bottom:22px}
.terms{margin:0;display:grid;gap:16px}
.terms > div{display:grid;grid-template-columns:190px 1fr;gap:20px}
.terms dt{color:#E6E0F1;font-weight:600;font-size:15px}
.terms dd{margin:0;color:var(--body);font-size:15px}
.terms b{color:#E6E0F1}
@media (max-width:720px){ .terms > div{grid-template-columns:1fr;gap:4px} .notice-body{gap:16px} }

/* ── Поддержка ────────────────────────────────────────────────────────── */
.contacts{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:var(--gutter);max-width:700px;margin:0 auto}
.contact{
  background:var(--glass); border:1px solid var(--glass-line);
  border-radius:var(--r-xl); padding:32px 24px; text-align:center;
}
.contact svg{width:30px;height:30px;margin:0 auto 14px;display:block}
.contact .tg{color:#2AABEE}
.contact .mail{color:var(--accent-soft)}
.contact b{display:block;color:#E6E0F1;font-size:17px;margin-bottom:6px}
.contact a{font-size:15px;word-break:break-all}

/* ── Подвал ───────────────────────────────────────────────────────────── */
footer{
  position:relative; z-index:1; border-top:1px solid var(--glass-line);
  padding:40px var(--gutter);
}
.foot{
  max-width:var(--page); margin:0 auto; display:flex; flex-wrap:wrap;
  align-items:center; gap:24px 40px;
}
.foot .brand{font-size:16px}
.foot-links{display:flex;flex-wrap:wrap;gap:26px;margin:0 auto}
.foot-links a{color:var(--body);font-size:14px}
.foot-links a:hover{color:var(--accent-soft)}
.foot .rights{color:var(--dim);font-size:13px}
.seller{
  max-width:var(--page); margin:28px auto 0; padding-top:22px;
  border-top:1px solid var(--glass-line); color:var(--dim); font-size:13px; line-height:1.8;
}

/* ── Окно входа и покупки ─────────────────────────────────────────────── */
.sheet{
  position:fixed; inset:0; z-index:60; display:grid; place-items:center;
  background:rgba(6,4,12,.8); backdrop-filter:blur(8px); padding:20px;
}
.sheet[hidden]{display:none}
.sheet-box{
  position:relative; width:min(430px,100%);
  background:rgba(20,18,29,.9); border:1px solid var(--glass-line);
  border-top:1px solid var(--accent-line);
  backdrop-filter:blur(20px); border-radius:var(--r-xl); padding:34px 30px 26px;
  box-shadow:0 30px 90px rgba(0,0,0,.6);
}
.sheet-box h3{font-size:22px;font-weight:600;margin-bottom:10px}
.sheet-lead{color:var(--body);font-size:15px;margin:0 0 24px}
.sheet-box .btn.wide{margin-bottom:12px}
.sheet-hint{color:var(--dim);font-size:13px;margin:16px 0 0}
.sheet-status{color:var(--body);font-size:14px;margin:20px 0 8px}
.sheet-close{
  position:absolute; top:14px; right:16px; background:none; border:0; cursor:pointer;
  color:var(--dim); font-size:26px; line-height:1; padding:2px 8px;
}
.sheet-close:hover{color:var(--text)}
.code{
  font-family:var(--mono); font-size:42px; font-weight:700; letter-spacing:.3em;
  text-align:center; color:var(--accent-soft); margin:22px 0 4px; padding-left:.3em;
}

/* ── Документы (terms.html / privacy.html) ───────────────────────────── */
.doc{position:relative;z-index:1;max-width:820px;margin:0 auto;padding:120px 24px 72px}
.doc h1{font-size:34px;font-weight:700;letter-spacing:-.02em;margin:0 0 28px}
.doc h2{font-size:22px;font-weight:600;margin:38px 0 12px}
.doc h3{font-size:17px;margin:24px 0 8px}
.doc p,.doc li{color:var(--body)}
.doc hr{border:0;border-top:1px solid var(--glass-line);margin:32px 0}
.doc .back{display:inline-block;margin-bottom:28px;font-weight:600}

@media (max-width:720px){
  .band{padding:56px var(--gutter)}
  .card,.plan{padding:32px 24px}
  .notice{padding:32px 24px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   Движение

   Три правила, от которых не отступаем.

   1. Анимируются ТОЛЬКО transform и opacity. Их считает композитор, не трогая
      раскладку и не перерисовывая слой. Всё остальное (высота, тени, фильтры)
      на живой странице с Live2D-моделью рядом стоит кадров - см. замеры в
      docs/SITE.md.
   2. Скрытое начальное состояние живёт ТОЛЬКО внутри
      prefers-reduced-motion: no-preference. Иначе человек с выключенной
      анимацией открыл бы пустую страницу: общее правило ниже гасит переходы,
      а opacity:0 осталось бы навсегда.
   3. Ничего анимированного поверх холста модели. Ореол под ней - отдельный
      слой позади, он дышит своим ритмом и холста не касается.
   ═══════════════════════════════════════════════════════════════════════════ */

@keyframes rise{from{opacity:0;transform:translateY(16px)}}
@keyframes settle{from{transform:translateY(22px) scale(.985)}}
@keyframes halo{
  0%,100%{transform:translateX(-50%) scale(1);opacity:1}
  50%{transform:translateX(-50%) scale(1.09);opacity:.78}
}
@keyframes sheet-in{from{opacity:0}}
@keyframes box-in{from{opacity:0;transform:translateY(12px) scale(.97)}}
@keyframes step-in{from{opacity:0;transform:translateY(6px)}}
@keyframes digit-in{from{opacity:0;transform:translateY(-10px)}}
@keyframes pop{from{opacity:0;transform:translate(-50%,6px) scale(.9)}}
@keyframes dot{0%,80%,100%{opacity:.25;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}

@media (prefers-reduced-motion:no-preference){
  /* ── Первый экран: текст поднимается лесенкой ─────────────────────────── */
  .hero h1{animation:rise .6s cubic-bezier(.22,.61,.36,1) .04s both}
  .hero .lead{animation:rise .6s cubic-bezier(.22,.61,.36,1) .13s both}
  .hero .cta{animation:rise .6s cubic-bezier(.22,.61,.36,1) .22s both}
  .hero #dl-meta{animation:rise .6s cubic-bezier(.22,.61,.36,1) .3s both}
  .hero .note-accent{animation:rise .6s cubic-bezier(.22,.61,.36,1) .36s both}

  /* Фигура едет БЕЗ прозрачности: она самый крупный элемент экрана, то есть
     кандидат в LCP, и появление из нуля отодвинуло бы отметку «страница
     показалась» на всю длину анимации. Сдвиг такой цены не несёт. */
  .figure{animation:settle .8s cubic-bezier(.22,.61,.36,1) both}

  /* Ореол дышит - тем же медленным ритмом, что и сама модель. */
  .figure::before{animation:halo 9s ease-in-out infinite}

  /* ── Появление при прокрутке ──────────────────────────────────────────── */
  /* Класс js ставит встроенный скрипт в <head>, и только если браузер умеет
     IntersectionObserver. Не умеет - значит всё видно сразу, без «сюрпризов». */
  .js .band-head,.js .card,.js .plan,.js .notice,.js .contact{
    opacity:0; transform:translateY(20px);
  }
  .js .band-head.in,.js .card.in,.js .plan.in,.js .notice.in,.js .contact.in{
    opacity:1; transform:none;
    transition:opacity .55s cubic-bezier(.22,.61,.36,1),
               transform .55s cubic-bezier(.22,.61,.36,1);
  }
  /* Бейдж «Популярный» появляется чуть позже своей карточки - глаз успевает
     дойти до неё и поймать подсказку, а не увидеть их одновременно. */
  .js .plan.best.in .tag{animation:pop .4s cubic-bezier(.2,.8,.3,1) .35s both}

  /* ── Окно входа ───────────────────────────────────────────────────────── */
  .sheet{animation:sheet-in .2s ease-out both}
  .sheet-box{animation:box-in .28s cubic-bezier(.2,.8,.3,1) both}
  .sheet [data-step]:not([hidden]){animation:step-in .26s cubic-bezier(.22,.61,.36,1) both}
  .code i{animation:digit-in .34s cubic-bezier(.2,.8,.3,1) both}
}

/* ── Шапка отделяется от страницы, когда та уехала вверх ────────────────── */
.nav{transition:background-color .25s ease, box-shadow .25s ease}
.nav.scrolled{background:rgba(11,9,20,.92);box-shadow:0 8px 30px rgba(0,0,0,.4)}

/* ── Мелкая отзывчивость управления ─────────────────────────────────────── */
.btn{transition:background-color .3s ease, box-shadow .3s ease, border-color .3s ease,
     transform .18s cubic-bezier(.2,.8,.3,1)}
.btn svg{transition:transform .22s cubic-bezier(.2,.8,.3,1)}
.btn.primary:hover{transform:translateY(-1px)}
.btn:active{transform:translateY(1px)}
/* Стрелка у «Скачать» подсказывает направление, а не просто украшает. */
#download:hover svg{transform:translateY(3px)}
.card{transition:box-shadow .3s ease, transform .3s cubic-bezier(.22,.61,.36,1)}
.contact{transition:border-color .3s ease, transform .3s cubic-bezier(.22,.61,.36,1)}
.contact:hover{border-color:var(--accent-line);transform:translateY(-3px)}
.nav-links a,.foot-links a{transition:color .2s ease}

/* Цифры кода - каждая своим прыжком, чтобы взгляд задержался на том, что надо
   сверить с чужим экраном. */
.code i{display:inline-block;font-style:normal}

/* ── «Ждём подтверждения» ───────────────────────────────────────────────── */
/* Поллинг ходит раз в две секунды, и без признака жизни окно выглядит
   зависшим. Точки - это ответ на вопрос «оно вообще работает?». */
.dots{display:inline-flex;gap:4px;margin-left:6px;vertical-align:middle}
.dots i{width:5px;height:5px;border-radius:50%;background:var(--accent-soft);opacity:.25}
@media (prefers-reduced-motion:no-preference){
  .dots i{animation:dot 1.4s ease-in-out infinite}
  .dots i:nth-child(2){animation-delay:.18s}
  .dots i:nth-child(3){animation-delay:.36s}
}
