/* Motion language.
 *
 * The design names five gestures and they all mean something:
 *   rise    — a screen or a card arriving
 *   unveil  — a revealed answer coming out of blur, one card after another
 *   bloom   — a moment that landed (submitted, saved)
 *   ring    — an expanding halo behind an icon, for a commitment
 *   breathe — patient work in progress; deliberately NOT a spinner, because AI
 *             generation takes minutes and a spinner reads as "about to finish"
 * Everything here is decoration: the reduced-motion block at the bottom removes all
 * of it, and no state is legible only while something is moving.
 */

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

@keyframes rise {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

@keyframes unveil {
  from { opacity: 0; filter: blur(8px); transform: translateY(7px); }
  to { opacity: 1; filter: blur(0); transform: none; }
}

@keyframes bloom {
  0% { transform: scale(0.8); opacity: 0; }
  45% { opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

@keyframes ring {
  0% { transform: scale(0.55); opacity: 0.6; }
  100% { transform: scale(2.2); opacity: 0; }
}

@keyframes breathe {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}

@keyframes pop {
  0% { transform: scale(0.7); }
  60% { transform: scale(1.16); }
  100% { transform: scale(1); }
}

@keyframes grow-y {
  from { transform: scaleY(0); }
  to { transform: scaleY(1); }
}

@keyframes shimmer {
  0% { background-position: 140% 0; }
  100% { background-position: -140% 0; }
}

@keyframes sheet-up {
  from { transform: translateY(100%); }
  to { transform: none; }
}

@keyframes shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(3px); }
  30%, 50%, 70% { transform: translateX(-5px); }
  40%, 60% { transform: translateX(5px); }
}

@keyframes heart-float {
  from { transform: translateY(0) scale(1); opacity: 1; }
  to { transform: translateY(-120px) scale(0.6) rotate(12deg); opacity: 0; }
}

@keyframes spin { to { transform: rotate(360deg); } }

.anim-rise { animation: rise var(--dur-entrance) var(--ease) both; }
.anim-bloom { animation: bloom 500ms var(--ease) both; }
.anim-breathe { animation: breathe 2.4s ease-in-out infinite; }
.anim-shake { animation: shake 500ms both; }
.anim-pop { animation: pop 550ms var(--ease) both; }
.spin { animation: spin 1s linear infinite; }

/* Kept as an alias so v1 call sites (the admin panel, a few leftovers) still animate. */
.anim-fade-up { animation: rise var(--dur-entrance) var(--ease) both; }

/* The expanding halo. Sized by whatever it sits behind; see .ring-host. */
.ring-host { position: relative; display: grid; place-items: center; }
.ring-host > .ring {
  position: absolute;
  inline-size: 100%;
  block-size: 100%;
  border-radius: 26px;
  border: 2px solid var(--accent);
  animation: ring 1.9s ease-out infinite;
  pointer-events: none;
}

/* List stagger: js sets --i per child. */
.stagger > * {
  animation: rise var(--dur-entrance) var(--ease) both;
  animation-delay: calc(var(--i, 0) * 40ms);
}

/* The reveal: each answer card comes out of blur in turn. Used only where both
   people have committed — it is the payoff of the whole quiz ceremony. */
.unveil > * {
  animation: unveil 500ms ease both;
  animation-delay: calc(var(--i, 0) * 60ms);
}

/* Screen transitions (View Transitions API, where the WebView has it). */
::view-transition-old(root) { animation: fade-in var(--dur-micro) reverse both; }
::view-transition-new(root) { animation: rise var(--dur-std) var(--ease) both; }

/* --- celebration overlays ------------------------------------------------------ */

#celebrate {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
  overflow: hidden;
}
#celebrate .h {
  position: absolute;
  font-size: 24px;
  animation: heart-float 1s var(--ease) both;
}

/* The committed-a-quiz moment: a heart inside an opening ring, over a scrim. */
#seal {
  position: fixed;
  inset: 0;
  z-index: 92;
  display: grid;
  place-items: center;
  background: var(--scrim);
  pointer-events: none;
}
#seal .box {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
  padding: var(--s6) 40px;
  background: var(--bg-2);
  border: 1px solid var(--line-2);
  border-radius: 28px;
  animation: bloom 500ms var(--ease) both;
}
#seal .glyph { font-size: 36px; color: var(--accent); animation: pop 550ms ease both; }
#seal .label { font-family: var(--font-display); font-size: 1.32rem; color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  /* The halo exists only as motion, so it becomes a plain quiet outline. */
  .ring-host > .ring { animation: none !important; opacity: 0.2; }
}
