/* ============================================================================
   ORB ANIMATION PRESETS — 11 styles, plus a flurry.

   float drift orbit breathe wander  (Joshua's five, already present)
   + pulse sway tumble ripple spiral cascade
   + flurry

   Two hard rules, both learned the hard way on this project:

   1. A PRESET MUST CHANGE THE PATH, NOT THE SPEED. Five variants that differ only in
      duration all read as "the same thing, faster" and the operator cannot tell them
      apart. Every keyframe below moves on a different geometric path.

   2. ONE SOURCE OF TRUTH. These names are mirrored in orb_picker.js PRESETS and in the
      per-preset dot rules below. Three lists is how a menu ends up naming an animation
      that does not exist — the exact bug that made the original float/pulse pair do
      nothing. When you add a preset, add it in all three places in the same edit.
   ============================================================================ */

/* --- the original five ---------------------------------------------------- */
@keyframes orb-drift {           /* slow, large, horizontal wander: no rotation, calmest */
  0%   { transform: translate(0, 0) scale(1); }
  25%  { transform: translate(60px, -20px) scale(1.06); }
  50%  { transform: translate(110px, 30px) scale(1); }
  75%  { transform: translate(40px, 60px) scale(1.08); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes orb-orbit {           /* circular path, even size: reads as orbiting */
  0%   { transform: translate(0, 0) scale(1); }
  25%  { transform: translate(45px, -45px) scale(1.05); }
  50%  { transform: translate(0, -90px) scale(1.1); }
  75%  { transform: translate(-45px, -45px) scale(1.05); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes orb-breathe {         /* almost no movement; scale is the whole effect */
  0%, 100% { transform: translate(0, 0) scale(0.92); }
  50%      { transform: translate(0, 0) scale(1.22); }
}
@keyframes orb-wander {          /* erratic multi-point path: most "alive" */
  0%   { transform: translate(0, 0) scale(1); }
  20%  { transform: translate(-70px, -40px) scale(1.14); }
  40%  { transform: translate(50px, -80px) scale(0.94); }
  60%  { transform: translate(90px, 20px) scale(1.08); }
  80%  { transform: translate(-30px, 70px) scale(0.98); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes orb-float-site {      /* the site's own float, under a distinct name */
  0%   { transform: translate(0, 0) scale(1); }
  33%  { transform: translate(30px, -50px) scale(1.1); }
  66%  { transform: translate(-20px, 20px) scale(0.9); }
  100% { transform: translate(0, 0) scale(1); }
}

/* --- five more, each a genuinely different geometry ----------------------- */
@keyframes orb-pulse {           /* sharp in/out beat: fast expand, slow settle */
  0%   { transform: translate(0, 0) scale(0.85); }
  15%  { transform: translate(0, 0) scale(1.28); }
  30%  { transform: translate(0, 0) scale(0.98); }
  60%  { transform: translate(0, 0) scale(1.06); }
  100% { transform: translate(0, 0) scale(0.85); }
}
@keyframes orb-sway {            /* pendulum: side to side on an arc, tilting */
  0%   { transform: translate(-55px, 0) rotate(-6deg) scale(1); }
  25%  { transform: translate(-20px, -18px) rotate(-2deg) scale(1.03); }
  50%  { transform: translate(55px, 0) rotate(6deg) scale(1); }
  75%  { transform: translate(20px, 18px) rotate(2deg) scale(1.03); }
  100% { transform: translate(-55px, 0) rotate(-6deg) scale(1); }
}
@keyframes orb-tumble {          /* slow full rotation with a drifting centre */
  0%   { transform: translate(0, 0) rotate(0deg) scale(1); }
  25%  { transform: translate(35px, -35px) rotate(90deg) scale(1.08); }
  50%  { transform: translate(0, -70px) rotate(180deg) scale(1); }
  75%  { transform: translate(-35px, -35px) rotate(270deg) scale(1.08); }
  100% { transform: translate(0, 0) rotate(360deg) scale(1); }
}
@keyframes orb-ripple {          /* concentric expand-and-fade, water-drop style */
  0%   { transform: translate(0, 0) scale(0.7); opacity: .35; }
  40%  { transform: translate(0, 0) scale(1.35); opacity: .85; }
  70%  { transform: translate(0, 0) scale(1.1); opacity: .6; }
  100% { transform: translate(0, 0) scale(0.7); opacity: .35; }
}
@keyframes orb-spiral {          /* orbit whose radius GROWS and shrinks — a spiral, not a circle */
  0%   { transform: translate(0, 0) scale(1); }
  20%  { transform: translate(25px, -25px) scale(1.04); }
  40%  { transform: translate(0, -80px) scale(1.1); }
  60%  { transform: translate(-60px, -20px) scale(1.02); }
  80%  { transform: translate(20px, 40px) scale(1.06); }
  100% { transform: translate(0, 0) scale(1); }
}
@keyframes orb-cascade {         /* stepped descent: falls in discrete drops, like liquid */
  0%   { transform: translate(0, 0) scale(1.05); }
  16%  { transform: translate(15px, 70px) scale(1); }
  32%  { transform: translate(-10px, 130px) scale(1.04); }
  50%  { transform: translate(25px, 60px) scale(0.97); }
  70%  { transform: translate(-15px, 120px) scale(1.03); }
  85%  { transform: translate(10px, 40px) scale(1); }
  100% { transform: translate(0, 0) scale(1.05); }
}

/* --- FLURRY: not one motion but a burst. High-frequency, many small steps, with the
       opacity flickering in and out so the layer reads as weather rather than drift. ---- */
@keyframes orb-flurry {
  0%   { transform: translate(0, 0) scale(0.9);  opacity: .30; }
  8%   { transform: translate(40px, -55px) scale(1.1);  opacity: .85; }
  17%  { transform: translate(-35px, -30px) scale(1.0);  opacity: .45; }
  26%  { transform: translate(65px, 15px) scale(1.15);  opacity: .9; }
  35%  { transform: translate(-50px, 45px) scale(0.95); opacity: .4; }
  44%  { transform: translate(30px, -70px) scale(1.2);  opacity: .95; }
  53%  { transform: translate(-60px, -10px) scale(1.0);  opacity: .5; }
  62%  { transform: translate(45px, 60px) scale(1.1);   opacity: .85; }
  71%  { transform: translate(-25px, -45px) scale(0.9);  opacity: .35; }
  80%  { transform: translate(55px, 25px) scale(1.18);  opacity: .9; }
  90%  { transform: translate(-40px, -60px) scale(1.0);  opacity: .5; }
  100% { transform: translate(0, 0) scale(0.9);  opacity: .30; }
}

/* preset class on the wrapper selects the path for all four orbs */
#ops-orbs.p-float   .orb { animation-name: orb-float-site; }
#ops-orbs.p-drift   .orb { animation-name: orb-drift; }
#ops-orbs.p-orbit   .orb { animation-name: orb-orbit; }
#ops-orbs.p-breathe .orb { animation-name: orb-breathe; }
#ops-orbs.p-wander  .orb { animation-name: orb-wander; }
#ops-orbs.p-pulse   .orb { animation-name: orb-pulse; }
#ops-orbs.p-sway    .orb { animation-name: orb-sway; }
#ops-orbs.p-tumble  .orb { animation-name: orb-tumble; }
#ops-orbs.p-ripple  .orb { animation-name: orb-ripple; }
#ops-orbs.p-spiral  .orb { animation-name: orb-spiral; }
#ops-orbs.p-cascade .orb { animation-name: orb-cascade; }
#ops-orbs.p-flurry  .orb { animation-name: orb-flurry;
  animation-timing-function: linear; }   /* flurry is weather: linear, not eased */

/* ---- ten more paths: 10 preset animations, each a distinct geometry ---- */
@keyframes orb-lissajous {
  0%   { transform: translate(0, 0) scale(1); }
  25%  { transform: translate(34px, -18px) scale(1.06); }
  50%  { transform: translate(0, -36px) scale(1); }
  75%  { transform: translate(-34px, -18px) scale(0.94); }
  100% { transform: translate(0, 0) scale(1); }
}

@keyframes orb-helix {
  0%   { transform: translate(0, 0) rotate(0deg) scale(1); }
  25%  { transform: translate(26px, -22px) rotate(90deg) scale(1.05); }
  50%  { transform: translate(0, -44px) rotate(180deg) scale(0.95); }
  75%  { transform: translate(-26px, -22px) rotate(270deg) scale(1.05); }
  100% { transform: translate(0, 0) rotate(360deg) scale(1); }
}

@keyframes orb-pendulum {
  0%   { transform: translateX(-38px) rotate(-7deg); }
  46%  { transform: translateX(38px) rotate(7deg); }
  54%  { transform: translateX(38px) rotate(7deg); }
  100% { transform: translateX(-38px) rotate(-7deg); }
}

@keyframes orb-bloom {
  0%   { transform: scale(0.72); opacity: .35; }
  40%  { transform: scale(1.18); opacity: 1; }
  70%  { transform: scale(1.02); opacity: .8; }
  100% { transform: scale(0.72); opacity: .35; }
}

@keyframes orb-shear {
  0%   { transform: translate(0, 0) skewX(0deg); }
  33%  { transform: translate(30px, -24px) skewX(-12deg); }
  66%  { transform: translate(-24px, -12px) skewX(10deg); }
  100% { transform: translate(0, 0) skewX(0deg); }
}

@keyframes orb-twinkle {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  12%  { transform: translate(9px, -7px) scale(1.04); opacity: .55; }
  24%  { transform: translate(-7px, 5px) scale(0.97); opacity: 1; }
  40%  { transform: translate(6px, 8px) scale(1.03); opacity: .6; }
  56%  { transform: translate(-10px, -6px) scale(0.98); opacity: 1; }
  74%  { transform: translate(8px, 4px) scale(1.02); opacity: .7; }
  100% { transform: translate(0, 0) scale(1); opacity: 1; }
}

@keyframes orb-vortex {
  0%   { transform: rotate(0deg) translateX(34px) scale(1); }
  50%  { transform: rotate(240deg) translateX(10px) scale(0.78); }
  100% { transform: rotate(540deg) translateX(34px) scale(1); }
}

@keyframes orb-bob {
  0%, 100% { transform: translateY(0) scaleX(1.02); }
  45%      { transform: translateY(-26px) scaleX(0.98); }
  62%      { transform: translateY(-14px) scaleX(1.01); }
}

@keyframes orb-glide {
  0%   { transform: translate(-48px, 0); opacity: .5; }
  50%  { transform: translate(48px, -14px); opacity: 1; }
  100% { transform: translate(-48px, 0); opacity: .5; }
}

@keyframes orb-deepfall {
  0%   { transform: translateY(0) scale(1); }
  35%  { transform: translateY(-30px) scale(1.08); }
  50%  { transform: translateY(-40px) scale(0.94); }
  78%  { transform: translateY(-12px) scale(1.03); }
  100% { transform: translateY(0) scale(1); }
}

#ops-orbs.p-lissajous .orb { animation-name: orb-lissajous; }
#ops-orbs.p-helix .orb { animation-name: orb-helix; }
#ops-orbs.p-pendulum .orb { animation-name: orb-pendulum; }
#ops-orbs.p-bloom .orb { animation-name: orb-bloom; }
#ops-orbs.p-shear .orb { animation-name: orb-shear; }
#ops-orbs.p-twinkle .orb { animation-name: orb-twinkle; }
#ops-orbs.p-vortex .orb { animation-name: orb-vortex; }
#ops-orbs.p-bob .orb { animation-name: orb-bob; }
#ops-orbs.p-glide .orb { animation-name: orb-glide; }
#ops-orbs.p-deepfall .orb { animation-name: orb-deepfall; }
