/* =====================================================================
   choreo.css — the lobby choreography (Loading Screen guide §5), shared by
   the front page (index.html) and the course lobby (app/index.html).

   Everything on the screen appears together on the first paint; there is
   no timed entrance. What moves is idle and slow: the camera drift, particle
   motes and the button's pulse. Nothing here runs under prefers-reduced-motion.

   The world is .world (app) or .screen__world (front page); the top bar is
   .top or .gtop; the parts carry the same class names on both pages.
   ===================================================================== */

/* No staged entrance: the whole screen paints at once, so the first frame never
   reads as a slow server. (The fade-from-black, push-in and phased UI were
   removed in round 38.) The primary button keeps its slow idle pulse. */
.hud__cta, .cta { animation: cta-pulse 2.6s ease-in-out infinite; }

/* ---- Persistent idle: camera drift and motes ---- */
.world__ground, .screen__ground { transform-origin: 50% 60%; }
.is-idle .world__ground, .is-idle .screen__ground { animation: drift 46s ease-in-out infinite alternate; }
@keyframes drift { from { transform: scale(1) translate(0, 0); } to { transform: scale(1.035) translate(-0.6%, -0.4%); } }
/* The hall maps its UI onto the picture, so its picture does not drift. */
body.is-hall .world__ground { animation: none; transform: none; }

.motes { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.motes i { position: absolute; width: 4px; height: 4px; border-radius: 50%; background: radial-gradient(circle, rgba(255, 236, 190, 0.95), rgba(255, 236, 190, 0) 70%); opacity: 0; animation: mote 14s linear infinite; left: var(--x); top: var(--y); animation-delay: var(--d); animation-duration: var(--t); transform: scale(var(--s)); }
@keyframes mote { 0% { opacity: 0; transform: translate(0, 0) scale(var(--s)); } 10% { opacity: 0.9; } 90% { opacity: 0.6; } 100% { opacity: 0; transform: translate(40px, -120px) scale(var(--s)); } }

/* ---- Hover: the energy sweep on the primary button ---- */
.hud__cta, .cta { position: relative; overflow: hidden; }
.hud__cta::after, .cta::after { content: ""; position: absolute; inset: 0; background: linear-gradient(110deg, transparent 30%, rgba(255, 255, 255, 0.45) 50%, transparent 70%); transform: translateX(-120%); pointer-events: none; }
.hud__cta:hover::after, .cta:hover::after { animation: sweep 600ms ease-out both; }
@keyframes sweep { to { transform: translateX(120%); } }

@media (prefers-reduced-motion: reduce) {
  .hud__cta, .cta, .is-idle .world__ground, .is-idle .screen__ground, .motes i, .hud__cta::after, .cta::after { animation: none !important; }
}

@keyframes cta-pulse { 0%, 100% { box-shadow: 0 12px 30px -8px rgba(20, 103, 239, 0.9), 0 0 0 0 rgba(56, 165, 255, 0.5); } 50% { box-shadow: 0 12px 30px -8px rgba(20, 103, 239, 0.9), 0 0 0 10px rgba(56, 165, 255, 0); } }
