/* BirthdayPartyPal signature moments (DESIGN_SYSTEM.md "Signature moments"), driven by
   ds/moments.js. Layered, so the page's own CSS always wins; transform and opacity only. */
@layer ds.moments {
  /* ---------------- invite opening: the ticket waits to be torn ---------------- */
  .op-ticket { position: relative; isolation: isolate; overflow: hidden; }
  .op-ticket::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; border-radius: inherit;
    background: linear-gradient(110deg, transparent 38%, rgb(255 255 255 / .55) 48%, rgb(255 255 255 / .15) 54%, transparent 62%); translate: -110% 0; animation: ds-foil 3.6s var(--ds-ease-in-out) 1.2s infinite; }
  .op-ticket .t-stub small { animation: ds-pulse 1.8s var(--ds-ease-in-out) infinite; }
  .op-gate::before { content: ""; position: absolute; inset: 15% 10%; border-radius: 50%; background: radial-gradient(closest-side, color-mix(in srgb, var(--gold) 45%, transparent), transparent); opacity: .5; pointer-events: none; animation: ds-glow 3.2s var(--ds-ease-in-out) infinite; }
  @keyframes ds-foil { 0% { translate: -110% 0; } 45%, 100% { translate: 110% 0; } }
  @keyframes ds-glow { 0%, 100% { opacity: .35; scale: .9; } 50% { opacity: .7; scale: 1.05; } }
  .ds-bloom { position: absolute; inset: -20%; z-index: 3; pointer-events: none; background: radial-gradient(closest-side, rgb(255 255 255 / .95), color-mix(in srgb, var(--gold) 60%, transparent) 45%, transparent 72%); opacity: 0; }
  /* the kid's name, letter by letter */
  .ds-letters { display: inline; }
  .ds-word { display: inline-block; white-space: nowrap; }
  .ds-word--long { display: inline; white-space: normal; }
  .ds-letter { display: inline-block; white-space: pre; animation: ds-letter var(--ds-dur-bounce) var(--ds-spring-bouncy) both; animation-delay: calc(120ms + var(--i) * 45ms); }
  @keyframes ds-letter { from { opacity: 0; translate: 0 .6em; scale: .4; rotate: -12deg; } }

  /* ---------------- RSVP yes: the stamp ---------------- */
  .ticket { position: relative; }
  .ds-stamp { position: absolute; z-index: 2; inset-block-start: 10px; inset-inline-end: calc(28% + 10px); padding: 3px 10px; border: 3px solid currentColor; border-radius: 10px; rotate: -12deg;
    color: var(--ds-danger, #d43a5c); background: color-mix(in srgb, #fff 82%, transparent); font: 800 .95rem/1.1 var(--ds-font-display); letter-spacing: .04em; text-transform: uppercase; white-space: nowrap; pointer-events: none; }

  /* ---------------- wizard theme picker: cards come alive ---------------- */
  .theme-grid { perspective: 900px; }
  /* A grid of 17 animated SVG skies relaid out every frame: now a card's sky only moves when
     it's alive (hover/focus) or chosen. Calmer to look at, and far cheaper. */
  .theme-card:not(.ds-alive):not(.on) .tc-art * { animation-play-state: paused !important; }
  .theme-card .tc-art svg { transition: scale 1.6s var(--ds-ease-out); transform-origin: 50% 60%; }
  .theme-card.ds-alive .tc-art svg { scale: 1.08; }
  .theme-card.ds-alive .tc-squad .critter { animation: ds-bob 1.1s var(--ds-ease-in-out) infinite; }
  .theme-card.ds-alive .tc-squad .critter:nth-child(2) { animation-delay: .14s; }
  .theme-card.ds-alive .tc-squad .critter:nth-child(3) { animation-delay: .28s; }
  .theme-card::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; background: linear-gradient(115deg, transparent 35%, rgb(255 255 255 / .35) 50%, transparent 65%); translate: -120% 0; }
  .theme-card.ds-alive::after { translate: 120% 0; transition: translate .9s var(--ds-ease-out); }

  /* ---------------- Party HQ celebrations ---------------- */
  .celebrate-card { position: relative; overflow: hidden; isolation: isolate; }
  .celebrate-card .cel-squad svg { display: inline-block; }

  @media (prefers-reduced-motion: reduce) {
    .op-ticket::after, .op-gate::before, .op-ticket .t-stub small, .ds-letter, .theme-card.ds-alive .tc-squad .critter { animation: none !important; }
    .theme-card.ds-alive .tc-art svg { scale: 1; }
    .theme-card::after { display: none; }
  }
}
