/* landing_kit/motion.css · микро-интеракции обязательным слоем (Claude_Landings_KB СПРАВОЧНИК 8).
   Четыре примитива: пульс целевой кнопки · подтверждение ответа · дыхание карточек в покое ·
   радость выбора с притуханием остальных. Плюс подсказка прокрутки (стили .listwrap/.peek в layout.css,
   логика в motion.js). ⛔ Внизу ветка prefers-reduced-motion: у выбора остаётся статический признак. */

/* ⛔ БЕСКОНЕЧНЫЕ ЦИКЛЫ ТОЛЬКО НА transform/opacity (стандарт 7 `review-animations`, внедрено 14.09.2026).
   box-shadow в цикле перекрашивается каждый кадр: на слабом мобильном это пропущенные кадры, а
   трафик у нас мобильный. Приём один на все свечения ниже: тень СТАТИЧНАЯ и лежит на ::after,
   анимируется только его opacity, поэтому слой композитится. Вид не меняется: гейт
   `landing_qc.py` ловит возврат к прямой анимации тени. */

/* пульс: подсказывает верный путь; ⛔ не больше одного пульсирующего элемента в кадре */
.pulse{position:relative}
.pulse::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  box-shadow:0 0 0 1px color-mix(in srgb,var(--cta-bot) 55%,transparent),0 0 22px color-mix(in srgb,var(--cta-bot) 45%,transparent);
  opacity:0;animation:hint 2.6s var(--ease) infinite}
@keyframes hint{50%{opacity:1}}

/* подтверждение ответа: рывок, вспышка контура, галочка, затем переход (motion.js снимает класс) */
.win{animation:win .34s var(--ease) forwards}
@keyframes win{
  0%{transform:scale(1)}
  45%{transform:scale(1.06);box-shadow:0 0 0 2px var(--ink),0 0 34px color-mix(in srgb,var(--cta-bot) 75%,transparent)}
  100%{transform:scale(1);box-shadow:0 0 0 2px color-mix(in srgb,var(--ok) 80%,transparent)}}
.tick{position:absolute;right:14px;top:50%;translate:0 -50%;width:24px;height:24px;border-radius:50%;
  background:var(--ink);display:grid;place-items:center;opacity:0;scale:.6;pointer-events:none}
.tick svg{width:14px;height:14px;display:block} /* ⛔ SVG без размера рисуется 300×150 и вылезает за экран, поймано landing_qc 10.09.2026 */
.win .tick{animation:tickIn .3s var(--ease) .1s forwards}
@keyframes tickIn{to{opacity:1;scale:1}}

/* дыхание в покое: все карточки синхронно, слабо.
   ⛔ Кадр карточки клипуется своим `.ph`, а не карточкой: иначе `overflow:hidden` срезал бы
   внешнее свечение ::after и дыхание пропало бы (правка 14.09.2026, см. layout.css). */
.breathe{position:relative}
.breathe::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:3;
  box-shadow:0 6px 26px #00000073,0 0 14px color-mix(in srgb,var(--bg-grad) 40%,transparent);
  border:1px solid #ffffff40;border-radius:inherit;opacity:0;animation:breathe 3s var(--ease) infinite}
@keyframes breathe{0%,100%{opacity:0}50%{opacity:1}}

/* радость выбора: выбранный крупнее и светится, остальные притухают; искры и галочка в углу */
.chosen{z-index:5;animation:joy .42s var(--ease) forwards}
@keyframes joy{
  0%{transform:scale(1)}
  50%{transform:scale(1.07);box-shadow:0 0 0 2px var(--ink),0 0 40px color-mix(in srgb,var(--cta-bot) 85%,transparent)}
  100%{transform:scale(1.045);box-shadow:0 0 0 2px var(--ink),0 0 30px color-mix(in srgb,var(--cta-bot) 60%,transparent)}}
.dim{transform:scale(.965);opacity:.42;filter:saturate(.65)}
.tickbig{position:absolute;right:8px;top:8px;z-index:3;width:26px;height:26px;border-radius:50%;
  background:var(--ink);display:grid;place-items:center;opacity:0;scale:.5;pointer-events:none}
.tickbig svg{width:15px;height:15px}
.chosen .tickbig{animation:tickIn .3s var(--ease) .08s forwards}
.spark{position:absolute;width:6px;height:6px;border-radius:50%;background:var(--ink);opacity:0;left:50%;top:50%;pointer-events:none;z-index:4}
.chosen .spark{animation:spark .5s var(--ease) forwards}
.chosen .spark:nth-of-type(1){--tx:-46px;--ty:-40px;animation-delay:.04s}
.chosen .spark:nth-of-type(2){--tx:44px;--ty:-34px;animation-delay:.08s}
.chosen .spark:nth-of-type(3){--tx:-38px;--ty:42px;animation-delay:.06s}
.chosen .spark:nth-of-type(4){--tx:40px;--ty:44px;animation-delay:.1s}
@keyframes spark{0%{opacity:0;translate:0 0;scale:.4}35%{opacity:1}100%{opacity:0;translate:var(--tx) var(--ty);scale:1}}

/* точка online и покачивание счётчика прокрутки.
   ⛔ Волна точки это масштаб ::after, а не растущий spread тени: spread красится каждый кадр. */
.dot{position:relative;width:7px;height:7px;border-radius:50%;background:var(--ok);display:inline-block;
  box-shadow:0 0 0 3px color-mix(in srgb,var(--ok) 26%,transparent)}
.dot::after{content:"";position:absolute;inset:-3px;border-radius:50%;pointer-events:none;
  box-shadow:0 0 0 5px color-mix(in srgb,var(--ok) 26%,transparent);
  opacity:1;transform:scale(.4);animation:pulseDot 2.2s var(--ease) infinite}
@keyframes pulseDot{50%{opacity:0;transform:scale(1)}100%{opacity:0;transform:scale(1)}}
@keyframes peekBob{50%{transform:translateY(3px)}}

/* ⛔ reduced-motion: анимации выключены, признак выбора остаётся контуром */
@media (prefers-reduced-motion:reduce){
  .pulse,.breathe,.dot,.peek,.win,.chosen,.chosen .spark,.chosen .tickbig{animation:none}
  .pulse::after,.breathe::after,.dot::after{animation:none;opacity:0}
  .chosen{box-shadow:0 0 0 2px var(--ink)}
  .win{box-shadow:0 0 0 2px var(--ink)}
}

/* ===== Примитив 5: появление лесенкой (.stagger-in) =====
   Сетка карточек, которая просто «есть», читается мёртвой (кейс 10.09.2026, стена лиц HeyFans).
   Разовое появление снизу с задержкой по элементам оживляет экран и НЕ спорит с пульсацией
   целевой кнопки: оно заканчивается, а пульс остаётся единственным постоянным движением. */
.stagger-in > *{animation:riseIn .52s var(--ease) both}
.stagger-in > *:nth-child(1){animation-delay:.04s}
.stagger-in > *:nth-child(2){animation-delay:.11s}
.stagger-in > *:nth-child(3){animation-delay:.18s}
.stagger-in > *:nth-child(4){animation-delay:.25s}
.stagger-in > *:nth-child(5){animation-delay:.32s}
.stagger-in > *:nth-child(6){animation-delay:.39s}
.stagger-in > *:nth-child(7){animation-delay:.46s}
.stagger-in > *:nth-child(8){animation-delay:.53s}
@keyframes riseIn{from{opacity:0;transform:translateY(14px) scale(.94)}to{opacity:1;transform:none}}

/* ===== Примитив 6: два блока по очереди (.glow-block + .charged) =====
   Блок карточек светится ЦЕЛИКОМ и разом, гаснет, потом загорается целевая кнопка, потом заново.
   Решение владельца 11.09.2026: поочерёдная подсветка карточек выглядела рвано, нужно ровно два
   такта: «все фото» и «кнопка».
   ⛔ Цвета разные по смыслу: карточки светятся ФОНОМ (`--bg-grad`), то есть проявляются из фона,
   кнопка светится тёплым CTA-цветом (`--cta-top`), то есть зовёт нажать. Один цвет на оба такта
   стирает разницу между «смотри» и «жми».
   ⛔ Такты не пересекаются: карточки гаснут к 38% цикла, кнопка загорается с 42%. Наложение
   читается как «мигает всё сразу» (кейс 11.09.2026). Меняешь длительность: проверь стык.
   Цикл 4 с: разгорание 0.48 с (быстрое), затухание к 1.5 с, кнопка с 1.7 по 3.3 с, дальше по кругу.
   ⛔ Паузы в начале круга нет: пик карточек стоит на 12%, а не на трети цикла (правка 11.09.2026). */
/* ⛔ Оба такта берут общий старт из `--beat-start`: если у карточек есть задержка появления,
   а у кнопки нет, такты наезжают друг на друга (кейс 11.09.2026: замер показал одновременное
   свечение фото 0.22 и кнопки 0.13 на 3.5 с). Задаётся один раз на body страницы. */
.glow-block > *{position:relative}
.glow-block > *::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:2;
  box-shadow:0 0 34px 7px color-mix(in srgb, var(--bg-grad) 62%, transparent);
  opacity:0;animation:blockGlow 4s ease-in-out var(--beat-start,0s) infinite}
@keyframes blockGlow{0%{opacity:0}12%{opacity:1}38%,100%{opacity:0}}

/* Кнопка: тёплое жёлтое свечение во второй такт. ⛔ Ставится ВМЕСТО `pulse`, не вместе. */
.charged{position:relative}
.charged::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  box-shadow:0 0 30px 5px color-mix(in srgb, var(--cta-top) 60%, transparent);
  opacity:0;animation:charged 4s ease-in-out var(--beat-start,0s) infinite}
@keyframes charged{0%,42%{opacity:0}55%{opacity:1}82%,100%{opacity:0}}

/* Появление и такты вместе: лесенка разово на самом элементе, свечение на его ::before.
   ⛔ Раньше оба лежали на одном элементе списком из двух анимаций, и пара «задержка лесенки +
   задержка такта» держалась в одной строке `animation-delay`: порядок в списке можно было
   сдвинуть правкой и получить одновременное появление (кейс 11.09.2026). Теперь они на разных
   слоях и перепутать их нечем. */
.stagger-in.glow-block > *{animation:riseIn .52s var(--ease) both}

@media (prefers-reduced-motion:reduce){
  .stagger-in > *,.glow-block > *,.stagger-in.glow-block > *,.charged{animation:none;opacity:1;transform:none;box-shadow:none}
  .glow-block > *::before,.charged::after,.pulse::after,.breathe::after,.dot::after{animation:none;opacity:0}
}
