/* ==========================================================================
   Motion
   - Start states apply only under html.js-anim (set in <head>). If GSAP does
     not load, that class is removed and everything renders in final state.
   - Ambient loops (aurora, floats, marquee, seal, border glow) are CSS-only
     and transform/opacity based.
   - With prefers-reduced-motion, loops stop and GSAP falls back to fades.
   ========================================================================== */

@property --angle { syntax: "<angle>"; initial-value: 0deg; inherits: false; }

@keyframes ripple { 0% { transform: scale(.85); opacity: .9; } 100% { transform: scale(1.6); opacity: 0; } }
@keyframes pulse-ring { 0% { transform: scale(1); opacity: .5; } 100% { transform: scale(1.75); opacity: 0; } }
@keyframes marquee { to { transform: translateX(-50%); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes border-spin { to { --angle: 360deg; } }
@keyframes drift-a { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(-60px, 40px) scale(1.12); } }
@keyframes drift-b { 0%, 100% { transform: translate(0, 0) scale(1); } 50% { transform: translate(70px, -30px) scale(.92); } }
@keyframes drift-c { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-40px, 50px); } }
/* Bobbing animates --bob so cursor parallax (--px/--py, set in main.js) can
   combine with it in a single translate; GSAP entrances use transform. */
@property --bob { syntax: "<length>"; initial-value: 0px; inherits: false; }
@keyframes bob { 0%, 100% { --bob: 0px; } 50% { --bob: -12px; } }
@keyframes bob-r { 0%, 100% { --bob: 0px; } 50% { --bob: 10px; } }

.hm-chip, .hm-course, .hm-math, .am-stat, .brooke-badge {
  translate: var(--px, 0px) calc(var(--py, 0px) + var(--bob));
  transition: translate .5s var(--ease-out);
}

.aurora-a { animation: drift-a 14s ease-in-out infinite; }
.aurora-b { animation: drift-b 17s ease-in-out infinite; }
.aurora-c { animation: drift-c 12s ease-in-out infinite; }

/* Floating elements bob after their entrance */
.hm-chip-score, .hm-math-a, .am-stat, .brooke-badge { animation: bob 6s ease-in-out 1.6s infinite; }
.hm-chip-yt, .hm-math-c { animation: bob-r 7s ease-in-out 1.8s infinite; }
.hm-course, .hm-math-b { animation: bob 8s ease-in-out 2s infinite; }
.hm-orbit { animation: spin 60s linear infinite; }

/* Pause hero loops while off screen (toggled by main.js) */
.hero.is-offscreen *, .hero.is-offscreen .aurora { animation-play-state: paused; }

/* Start states ------------------------------------------------------------- */
.js-anim [data-hero],
.js-anim [data-chip],
.js-anim [data-reveal],
.js-anim [data-step],
.js-anim .hm-shape,
.js-anim .hm-rings svg,
.js-anim .hm-math { opacity: 0; }

/* Mask-reveal words: each word slides up inside a clipping wrapper */
.word { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .08em; margin-bottom: -.08em; }
.word-inner { display: inline-block; }
/* Hidden until split; GSAP then sets each word's start offset itself
   (a CSS start transform would be parsed into a lingering px offset). */
.js-anim [data-words]:not(.is-split),
.js-anim [data-split]:not(.is-split) { opacity: 0; }


/* Reduced motion ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
  }
  .marquee-track { transform: none; }
}

/* Instructor photo reveal (driven by main.js, works without GSAP) ------------ */
.brooke-media.ph-wait .brooke-photo { opacity: 0; transform: translateY(48px) scale(.96); clip-path: inset(22% 0 0 0 round 30px); }
.brooke-media.ph-wait .brooke-photo img { transform: scale(1.25); filter: blur(12px); }
.brooke-media.ph-wait .brooke-badge { opacity: 0; translate: 36px 0; }
.brooke-media.ph-wait .brooke-socials li { opacity: 0; translate: 0 18px; }
.brooke-media.ph-ready .brooke-photo { transition: opacity 1s ease-out, transform 1.4s cubic-bezier(.22, 1, .36, 1), clip-path 1.5s cubic-bezier(.65, 0, .35, 1); }
.brooke-media.ph-ready .brooke-photo img { transition: transform 2.2s cubic-bezier(.22, 1, .36, 1), filter 1.4s ease-out; }
.brooke-media.ph-ready .brooke-badge { transition: opacity .7s ease-out 1s, translate .9s cubic-bezier(.34, 1.56, .64, 1) 1s; }
.brooke-media.ph-ready .brooke-socials li { transition: opacity .5s ease-out, translate .6s cubic-bezier(.22, 1, .36, 1); }
.brooke-media.ph-ready .brooke-socials li:nth-child(1) { transition-delay: 1.1s; }
.brooke-media.ph-ready .brooke-socials li:nth-child(2) { transition-delay: 1.2s; }
.brooke-media.ph-ready .brooke-socials li:nth-child(3) { transition-delay: 1.3s; }
@media (prefers-reduced-motion: reduce) {
  /* No movement: a gentle fade only */
  .brooke-media.ph-wait .brooke-photo, .brooke-media.ph-wait .brooke-photo img { transform: none; filter: none; clip-path: none; }
  .brooke-media.ph-wait .brooke-badge, .brooke-media.ph-wait .brooke-socials li { translate: none; }
  .brooke-media.ph-ready .brooke-photo, .brooke-media.ph-ready .brooke-badge, .brooke-media.ph-ready .brooke-socials li { transition: opacity 1.2s ease-out !important; transition-delay: 0s !important; }
}

/* Hero photo reveal (driven by main.js, works without GSAP) ----------------- */
/* Hidden from first paint while JS runs; if the script never adds .hp-in, a
   fallback keyframe shows the photo after 3s. Uses scale (not transform) so it
   does not fight the pointer tilt. */
.js [data-hero-photo]:not(.hp-in) { opacity: 0; scale: .82; clip-path: circle(0% at 50% 55%); animation: hp-fallback .01s 3s forwards; }
.js [data-hero-photo]:not(.hp-in) img { scale: 1.35; filter: blur(14px); animation: hp-fallback-img .01s 3s forwards; }
[data-hero-photo].hp-in { transition: opacity .9s ease-out .15s, scale 1.5s cubic-bezier(.22, 1, .36, 1) .15s, clip-path 1.5s cubic-bezier(.65, 0, .35, 1) .15s; }
[data-hero-photo].hp-in img { transition: scale 2.4s cubic-bezier(.22, 1, .36, 1) .15s, filter 1.5s ease-out .15s; }
@keyframes hp-fallback { to { opacity: 1; scale: 1; clip-path: circle(75% at 50% 55%); } }
@keyframes hp-fallback-img { to { scale: 1; filter: none; } }
@media (prefers-reduced-motion: reduce) {
  .js [data-hero-photo]:not(.hp-in), .js [data-hero-photo]:not(.hp-in) img { scale: none; filter: none; clip-path: none; }
  [data-hero-photo].hp-in, [data-hero-photo].hp-in img { transition: opacity 1.2s ease-out !important; }
  /* Keep the 3s safety fallback: the global reduced-motion rule zeroes delays */
  .js [data-hero-photo]:not(.hp-in), .js [data-hero-photo]:not(.hp-in) img { animation-duration: .01s !important; animation-delay: 3s !important; }
}
