/* ==========================================================================
   KEYFRAMES
   ========================================================================== */
@keyframes loaderPulse{
  0%,100%{ opacity:.3; } 50%{ opacity:1; }
}
@keyframes blink{
  0%,49%{ opacity:1; } 50%,100%{ opacity:0; }
}
@keyframes dotPulse{
  0%,100%{ box-shadow:0 0 0 3px rgba(20,184,166,.18); }
  50%{ box-shadow:0 0 0 6px rgba(20,184,166,.10); }
}
@keyframes scrollCue{
  0%{ top:-30%; } 100%{ top:100%; }
}
@keyframes marqueeScroll{
  0%{ transform:translateX(0); } 100%{ transform:translateX(-50%); }
}
@keyframes fadeIn{
  from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:translateY(0); }
}
@keyframes rippleAnim{
  to{ transform:scale(3); opacity:0; }
}
@keyframes blobFloatA{
  0%,100%{ transform:translate(0,0) scale(1); }
  33%{ transform:translate(40px,60px) scale(1.08); }
  66%{ transform:translate(-30px,20px) scale(.94); }
}
@keyframes blobFloatB{
  0%,100%{ transform:translate(0,0) scale(1); }
  33%{ transform:translate(-50px,30px) scale(.92); }
  66%{ transform:translate(30px,-40px) scale(1.1); }
}
@keyframes blobFloatC{
  0%,100%{ transform:translate(0,0) scale(1); }
  50%{ transform:translate(20px,-50px) scale(1.12); }
}
@keyframes gradientShift{
  0%{ background-position:0% 50%; } 50%{ background-position:100% 50%; } 100%{ background-position:0% 50%; }
}
@keyframes floatY{
  0%,100%{ transform:translateY(0); } 50%{ transform:translateY(-10px); }
}

/* ==========================================================================
   APPLIED ANIMATIONS
   ========================================================================== */
.blob-a{ animation:blobFloatA 18s ease-in-out infinite; }
.blob-b{ animation:blobFloatB 22s ease-in-out infinite; }
.blob-c{ animation:blobFloatC 16s ease-in-out infinite; }
.grad-text{ animation:gradientShift 6s ease-in-out infinite; }

/* scroll reveal: JS toggles .is-visible when element enters viewport */
.reveal-up{
  opacity:0; transform:translateY(28px); transition:opacity .7s var(--ease), transform .7s var(--ease);
  transition-delay:calc(var(--stagger, 0) * 90ms);
}
.reveal-up[data-delay="1"]{ --stagger:1; }
.reveal-up[data-delay="2"]{ --stagger:2; }
.reveal-up[data-delay="3"]{ --stagger:3; }
.reveal-up[data-delay="4"]{ --stagger:4; }
.reveal-up[data-delay="5"]{ --stagger:5; }
.reveal-up[data-delay="6"]{ --stagger:6; }
.reveal-up[data-delay="7"]{ --stagger:7; }
.reveal-up[data-delay="8"]{ --stagger:8; }
.reveal-up.is-visible{ opacity:1; transform:translateY(0); }

/* character split heading reveal */
.hero-title .line{ }
.hero-title .char{
  display:inline-block; opacity:0; transform:translateY(110%) rotate(4deg);
  transition:opacity .6s var(--ease), transform .6s var(--ease);
}
.hero-title .char.is-in{ opacity:1; transform:translateY(0) rotate(0deg); }

/* project card entry */
.project-card.reveal-up{ transform:translateY(36px) scale(.98); }
.project-card.reveal-up.is-visible{ transform:translateY(0) scale(1); }
