/* =========================================================================
   APPLICATION PORTAL — animations.css
   All keyframes + the elements whose animation is purely CSS-driven.
   JS-driven motion (bubbles, mouse forces) lives in the JS modules.
   Everything here animates transform / opacity / filter only.
   ========================================================================= */

/* -------------------------------------------------------------------------
   WATER SURFACE — three independent SVG wave layers
   Each path is drawn twice as wide as the viewport and slid horizontally
   for a seamless, continuous flow. Layers differ in speed, direction,
   amplitude (baked into the path) and opacity.
   ------------------------------------------------------------------------- */
.wave {
  position: absolute;
  left: 0;
  top: 0;
  width: 1200%;
  height: 180%;
  will-change: transform;
}
.wave--back {
  opacity: 0.26;
  animation: wave-drift-l calc(var(--wave-duration) * 1.7) linear infinite;
}
.wave--mid {
  opacity: 0.42;
  animation: wave-drift-r calc(var(--wave-duration) * 1.15) linear infinite;
}
.wave--front {
  opacity: 0.53;
  animation: wave-drift-l var(--wave-duration) linear infinite;
}

@keyframes wave-drift-l {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
@keyframes wave-drift-r {
  from { transform: translate3d(-50%, 0, 0); }
  to   { transform: translate3d(0, 0, 0); }
}

/* -------------------------------------------------------------------------
   CAUSTICS — slow crawl of the light net
   ------------------------------------------------------------------------- */
.scene__caustics::before {
  animation: caustic-drift var(--caustic-duration) linear infinite alternate;
}
@keyframes caustic-drift {
  from { transform: translate3d(0, 0, 0)      scale(1);    }
  to   { transform: translate3d(6%, 4%, 0)    scale(1.15); }
}

/* -------------------------------------------------------------------------
   GOD RAYS — each ray sways on its own timing for a living light field
   ------------------------------------------------------------------------- */
.ray { animation: ray-sway var(--ray-duration) ease-in-out infinite alternate; }
.ray--1 { animation-duration: 11s; }
.ray--2 { animation-duration: 14s; animation-delay: -3s; }
.ray--3 { animation-duration: 9s;  animation-delay: -6s; }
.ray--4 { animation-duration: 13s; animation-delay: -2s; }
.ray--5 { animation-duration: 16s; animation-delay: -8s; }

@keyframes ray-sway {
  0%   { transform: rotate(-4deg) skewX(-3deg); opacity: 0.06; }
  50%  { opacity: 0.15; }
  100% { transform: rotate(5deg)  skewX(4deg);  opacity: 0.08; }
}

/* -------------------------------------------------------------------------
   FOG — very slow, large-scale drift
   ------------------------------------------------------------------------- */
.fog--1 { animation: fog-drift-a var(--fog-duration) ease-in-out infinite alternate; }
.fog--2 { animation: fog-drift-b calc(var(--fog-duration) * 1.3) ease-in-out infinite alternate; }

@keyframes fog-drift-a {
  from { transform: translate3d(0, 0, 0)      scale(1);   }
  to   { transform: translate3d(18vw, -6vh, 0) scale(1.2); }
}
@keyframes fog-drift-b {
  from { transform: translate3d(0, 0, 0)       scale(1.1); }
  to   { transform: translate3d(-16vw, 5vh, 0) scale(1);   }
}

/* -------------------------------------------------------------------------
   PARTICLES — suspended dust; per-particle params come from inline vars
   ------------------------------------------------------------------------- */
.particle {
  position: absolute;
  width: var(--size, 3px);
  height: var(--size, 3px);
  border-radius: 50%;
  background: radial-gradient(circle,
      rgba(255,255,255,0.9) 0%, rgba(255,255,255,0) 70%);
  opacity: var(--opacity, 0.5);
  will-change: transform, opacity;
  animation: particle-float var(--dur, 22s) ease-in-out infinite alternate;
  animation-delay: var(--delay, 0s);
}
@keyframes particle-float {
  0%   { transform: translate3d(0, 0, 0); }
  50%  { transform: translate3d(var(--dx, 12px), var(--dy, -18px), 0); }
  100% { transform: translate3d(calc(var(--dx, 12px) * -0.6),
                                var(--dy2, -32px), 0); }
}

/* -------------------------------------------------------------------------
   CARD SWAY — gentle, independent bob. Feeds --sway-x / --sway-rot only,
   so it composes with hover-scale and mouse-tilt without conflict.
   Per-card variation (duration + delay) keeps cards from moving in unison.
   ------------------------------------------------------------------------- */
.card__link {
  animation: card-sway var(--sway-duration) ease-in-out infinite alternate;
}
.card:nth-child(1) .card__link { animation-duration: 6.5s; animation-delay: -0.2s; }
.card:nth-child(2) .card__link { animation-duration: 8.2s; animation-delay: -1.6s; }
.card:nth-child(3) .card__link { animation-duration: 7.1s; animation-delay: -3.1s; }
.card:nth-child(4) .card__link { animation-duration: 9.0s; animation-delay: -0.9s; }
.card:nth-child(5) .card__link { animation-duration: 7.8s; animation-delay: -2.4s; }
.card:nth-child(6) .card__link { animation-duration: 6.9s; animation-delay: -4.0s; }

@keyframes card-sway {
  0%   { --sway-x: -14px; --sway-rot: -1.8deg; }
  100% { --sway-x:  14px; --sway-rot:  1.8deg; }
}

/* Pause the idle bob while hovering/focused so the card sits still to read */
.card__link:hover,
.card__link:focus-visible { animation-play-state: paused; }

/* -------------------------------------------------------------------------
   GLASS SHIMMER — light sweep across a card on hover
   ------------------------------------------------------------------------- */
@keyframes glass-shimmer {
  from { background-position: 150% 0; }
  to   { background-position: -150% 0; }
}

/* -------------------------------------------------------------------------
   TITLE SHIMMER — a bright highlight passes across the text periodically,
   then rests off-screen for most of the cycle ("occasionally").
   ------------------------------------------------------------------------- */
.title::before {
  animation: title-shimmer var(--shimmer-cycle) ease-in-out infinite;
}
@keyframes title-shimmer {
  0%   { background-position: 180% 0; }
  18%  { background-position: -80% 0; }
  100% { background-position: -80% 0; }  /* rest off-screen until next cycle */
}

/* -------------------------------------------------------------------------
   FOOTER REFLECTION — slow band of light (referenced from style.css)
   ------------------------------------------------------------------------- */
@keyframes footer-reflect {
  from { background-position: 180% 0; }
  to   { background-position: -80% 0; }
}

/* -------------------------------------------------------------------------
   RIPPLES — expanding rings spawned on card hover (ripple.js)
   Animates transform + opacity only; removed on animationend.
   ------------------------------------------------------------------------- */
.ripple {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  margin: -20px 0 0 -20px;
  border: 2px solid rgba(255, 255, 255, 0.75);
  border-radius: 50%;
  opacity: 0.9;
  transform: translate3d(0,0,0) scale(0.2);
  will-change: transform, opacity;
  animation: ripple-expand 1.2s ease-out forwards;
}
@keyframes ripple-expand {
  to { transform: translate3d(0,0,0) scale(4); opacity: 0; }
}
