/* ==========================================================================
   Constructor animations — МАКРО-поведение кнопок «Да»/«Нет».
   Реестр: static/js/constructor-animations.js
   Подключается только на /create и /meeting/v/* (см. constructor.html,
   invitation_view.html) поверх base.css.

    Что здесь:
    - «Да»: idle (.anim-pulse/.anim-glow) + реакции на клик (.anim-shake,
      .anim-pulse-hit, .anim-glow-burst) — выбор в пикерах «Анимация "Да"»
      (yesAnim: shake|pulse|glow|none) и «Анимация "Нет"»
      (noAnim: dodge|shrink|teleport|none).
   - touch-action: none для убегающих кнопок (dodge нужна честная физика
     pointermove/touch без скролла браузера).

   Что НЕ здесь (остаётся в base.css):
   - МИКРО-эффекты button-fx.js: .btn-ripple, .ring, .sweep, .squish,
     .hearts/.heart (burst/swarm), hover-сердечки логотипа.
   - .floating-heart / @keyframes float-heart — общие для конструктора,
     превью, страницы получателя И финального билета (ticket.html), поэтому
     живут в base.css, а ConstructorAnimations.spawnHearts их переиспользует.
   - .confetti-piece (confetti.js).
   ========================================================================== */

/* --- «Да»: тряска (одноразовая реакция на клик) --- */
@keyframes shake-pop {
  0%, 100% { transform: scale(1) rotate(0); }
  20% { transform: scale(1.08) rotate(-3deg); }
  40% { transform: scale(0.96) rotate(3deg); }
  60% { transform: scale(1.1) rotate(-2deg); }
  80% { transform: scale(1.02) rotate(1deg); }
}
.anim-shake { animation: shake-pop 0.5s ease; }

/* --- «Да»: пульс (постоянная idle-анимация, пока получатель решает) --- */
@keyframes btn-heartbeat {
  0%, 100% { transform: scale(1); }
  14% { transform: scale(1.07); }
  28% { transform: scale(1); }
  42% { transform: scale(1.07); }
  70% { transform: scale(1); }
}
.anim-pulse { animation: btn-heartbeat 1.8s ease-in-out infinite; }
.anim-pulse:active { animation-play-state: paused; }
/* Каноническое имя из первой версии пикера — алиас, чтобы старые сохранённые
   страницы/кэш не мигнули без анимации. Новые вызовы используют .anim-pulse. */
.btn-heartbeat { animation: btn-heartbeat 1.8s ease-in-out infinite; }
.btn-heartbeat:active { animation-play-state: paused; }

/* --- «Да»: реакция на клик при пульсе — один сильный удар ---
   (позже .anim-pulse в файле, поэтому перебивает idle на время хита) */
@keyframes pulse-hit {
  0%   { transform: scale(1); }
  25%  { transform: scale(1.16); }
  45%  { transform: scale(.97); }
  65%  { transform: scale(1.1); }
  100% { transform: scale(1); }
}
.anim-pulse-hit { animation: pulse-hit .6s ease-out; }

/* --- «Да»: сияние (непрерывное, как пульс) --- */
@keyframes btn-glow {
  0%   { box-shadow: 0 8px 20px rgba(225,29,116,.28), 0 0 0 0 rgba(223,79,139,.55); }
  70%  { box-shadow: 0 8px 20px rgba(225,29,116,.28), 0 0 0 14px rgba(223,79,139,0); }
  100% { box-shadow: 0 8px 20px rgba(225,29,116,.28), 0 0 0 0 rgba(223,79,139,0); }
}
.anim-glow { animation: btn-glow 1.8s ease-out infinite; }

/* --- «Да»: реакция на клик при сиянии — двойная волна колец ---
   (позже .anim-glow в файле, поэтому перебивает idle на время вспышки) */
@keyframes glow-burst {
  0%   { box-shadow: 0 8px 20px rgba(225,29,116,.28), 0 0 0 0 rgba(223,79,139,.7), 0 0 0 0 rgba(223,79,139,.45); }
  100% { box-shadow: 0 8px 20px rgba(225,29,116,.28), 0 0 0 22px rgba(223,79,139,0), 0 0 0 46px rgba(223,79,139,0); }
}
.anim-glow-burst { animation: glow-burst .7s ease-out; }

/* --- «Нет»: уменьшение (shrink идёт по шагам из JS, финальное исчезновение
   оформлено классом, чтобы motion-язык был в CSS, а не в инлайн-стилях) --- */
@keyframes anim-shrink-away {
  to { transform: translate(var(--shrink-tx, 0px), var(--shrink-ty, 0px)) scale(0); opacity: 0; }
}
.anim-shrink { animation: anim-shrink-away 0.25s ease forwards; }
@media (prefers-reduced-motion: reduce) {
  .anim-shrink { animation-duration: 0.01ms; }
}

/* Убегающей кнопке нужен честный pointermove/touch без вмешательства
   скролла — иначе dodge дёргается на тачскринах.
   Превью (phone-mock) здесь намеренно нет: previewNo зафиксирована и не
   убегает, ей скролл жестом нужен как обычно. */
#demoNoBtn,
.invitation-no { touch-action: none; }

/* ==========================================================================
   Always-play при prefers-reduced-motion.
   Демо-пикер обязан показывать выбранную анимацию при любой настройке ОС:
   это осознанный предпросмотр (и ответ получателя), а не фоновый декор —
   та же философия, что RESPECT_REDUCED_MOTION=false в button-fx.js.
   ВАЖНО: глобальное приглушение base.css — это селектор специфичностью
   (0,6,0) с !important, поэтому голый класс (0,1,0) его НЕ перебивает даже
   с !important. Здесь — ID-селекторы (1,1,0): демо-кнопки конструктора
   лежат в form#constructorForm, кнопки получателя — в div#step1, а кнопка
   «Да» из phone-screen — в .preview-pane ВНЕ формы (см. constructor.html:
   </form> идёт раньше <aside class="preview-pane">), поэтому её спасает
   отдельный селектор #previewYes.anim-* — без него сияние/пульс гаснут
   в превью, хотя в anim-demo продолжают играть.
   Порядок: этот блок — последний в файле.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  #constructorForm .anim-shake, #step1 .anim-shake, #previewYes.anim-shake { animation: shake-pop 0.5s ease !important; }
  #constructorForm .anim-pulse-hit, #step1 .anim-pulse-hit, #previewYes.anim-pulse-hit { animation: pulse-hit .6s ease-out !important; }
  #constructorForm .anim-glow-burst, #step1 .anim-glow-burst, #previewYes.anim-glow-burst { animation: glow-burst .7s ease-out !important; }
  #constructorForm .anim-pulse, #step1 .anim-pulse, #previewYes.anim-pulse { animation: btn-heartbeat 1.8s ease-in-out infinite !important; }
  #constructorForm .anim-glow, #step1 .anim-glow, #previewYes.anim-glow { animation: btn-glow 1.8s ease-out infinite !important; }
}

/* ============================================================
   Кнопки мастера (.wizard-nav): переливы + леденцовые полоски.
   Навешиваются из wizard-substeps.js: «Продолжить» — fx-flow2 +
   fx-stripes, «Назад» — fx-tint.
   Изоляция от остальных стилей кнопок (этот пункт важен):
   - селекторы скоуплены под .wizard-nav .btn-next/.btn-back (0,3,0) —
     классы .anim-* («Да»/«Нет»: shake/pulse/glow/dodge/shrink/
     teleport), демо, phone-превью и билет их не матчат даже при
     совпадении имён классов;
   - свои keyframes (fxFlow2/fxStripes/fxTint) — общих имён ни с
     base.css, ни с этим файлом нет;
   - fx-stripes рисует только в ::after (button-fx ripple живёт в
     span.btn-ripple, .ring/.sweep — в своих слоях, не пересекаются);
   - always-play блок выше НЕ трогает fx-* — при
     prefers-reduced-motion они честно гаснут (см. медиа-запрос ниже),
     а не форсятся обратно, как .anim-*.
   ============================================================ */

/* «Продолжить» — сильные переливы градиента */
.wizard-nav .btn-next.fx-flow2 {
  background: linear-gradient(120deg, #ff85b3, #e63d86, #8e4bd3, #ff6aa5, #ff85b3);
  background-size: 400% 400%;
  animation: fxFlow2 4s ease-in-out infinite;
}
@keyframes fxFlow2 {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

/* «Продолжить» — леденцовые полоски, едут по диагонали.
   Складывается с fx-flow2 (фон + ::after-оверлей не конфликтуют);
   убери класс fx-stripes с кнопки, если нужен только перелив. */
.wizard-nav .btn-next.fx-stripes {
  position: relative;
  overflow: hidden;
}
.wizard-nav .btn-next.fx-stripes::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(45deg,
    rgba(255, 255, 255, .16) 25%, transparent 0 50%,
    rgba(255, 255, 255, .16) 0 75%, transparent 0);
  background-size: 26px 26px;
  animation: fxStripes 1.8s linear infinite;
  pointer-events: none;
}
@keyframes fxStripes {
  to { background-position: 26px 0; }
}

/* «Назад» — белый фон едва колышется розовым */
.wizard-nav .btn-back.fx-tint {
  --tint-base: var(--card, #fff); /* подхватит вашу переменную, если есть */
  background: linear-gradient(120deg, var(--tint-base), rgba(223, 79, 139, .28), var(--tint-base));
  background-size: 250% 250%;
  animation: fxTint 4.5s ease-in-out infinite;
}
@keyframes fxTint {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}

/* Отключение анимаций в ОС пользователя */
@media (prefers-reduced-motion: reduce) {
  .wizard-nav .btn-next.fx-flow2, .wizard-nav .btn-back.fx-tint { animation: none; }
  .wizard-nav .btn-next.fx-stripes::after { animation: none; background-position: 0 0; }
}
