/* ================================================================
   THE SALES NERD FOX — MOTION LIBRARY  (fox-motion.css)
   Movement @keyframes. Loaded on movement pages + the library.
   Every movement drives .fox-shadow so the ground shadow is truthful
   under the fox everywhere (scales + darkens with weight/height).

   Selectors are `.demo-<slug> .<part>` where `.demo-<slug>` sits on
   the <svg>. The rig CSS + face rules come from fox-engine.js.

   Motion bar: weight (squash on impact) · anticipation · follow-through
   (tail lags body, hand lags forearm, head settles late) · arcs ·
   slow-in/out with asymmetric per-segment easing · no dead symmetry.
   ================================================================ */

/* ---------- shared shadow keyframes (assigned per movement duration) ---------- */
/* grounded subtle breathe */
@keyframes sh-breathe{0%,100%{transform:scale(1);opacity:.30}50%{transform:scale(1.05);opacity:.34}}
/* walk: two footfalls per cycle -> two darkenings */
@keyframes sh-step{0%,50%,100%{transform:scale(1.04);opacity:.34}25%,75%{transform:scale(.96);opacity:.28}}

/* ============================================================
   IDLE + WAVE roots share the layered breathing base.
   ============================================================ */
.demo-idle .fox-bob{animation:id-breathe 3.8s ease-in-out infinite}
.demo-idle .fox-root{animation:id-shift 7s ease-in-out infinite}
.demo-idle .fox-pivot{animation:id-roll 7s ease-in-out infinite}
.demo-idle .tail{animation:id-tail 2.7s ease-in-out infinite}
.demo-idle .arm-l{animation:id-arml 4.6s ease-in-out infinite}
.demo-idle .arm-r{animation:id-armr 5.3s ease-in-out infinite}
.demo-idle .head{animation:id-head 9s ease-in-out infinite}
.demo-idle .fox-shadow{animation:sh-breathe 3.8s ease-in-out infinite}
@keyframes id-breathe{0%{transform:translateY(1px) scale(1,1);animation-timing-function:cubic-bezier(.4,0,.5,1)}42%{transform:translateY(-3px) scale(.99,1.02);animation-timing-function:cubic-bezier(.45,0,.55,1)}100%{transform:translateY(1px) scale(1,1)}}
@keyframes id-shift{0%,100%{transform:translateX(-3px)}50%{transform:translateX(3px)}}
@keyframes id-roll{0%,100%{transform:rotate(-1.4deg)}50%{transform:rotate(1.4deg)}}
@keyframes id-tail{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(11deg)}}
@keyframes id-arml{0%,100%{transform:rotate(-3deg)}50%{transform:rotate(3deg)}}
@keyframes id-armr{0%,100%{transform:rotate(3deg)}50%{transform:rotate(-3deg)}}
@keyframes id-head{0%,100%{transform:rotate(0)}30%{transform:rotate(-4deg)}55%{transform:rotate(3deg)}80%{transform:rotate(-2deg)}}

/* ---------- WAVE — BIG, high, glad-to-see-you. Arm up over the head,
   whole body lifts into it, fast excited tail wag, quick wrist waves. ---------- */
.demo-wave .fox-bob{animation:wv-bob 1.9s ease-in-out infinite}
.demo-wave .fox-pivot{animation:wv-lean 3.6s ease-in-out infinite}
.demo-wave .tail{animation:wv-tailwag 1.05s ease-in-out infinite}
.demo-wave .head{animation:wv-head 3.6s ease-in-out infinite}
.demo-wave .arm-r{animation:wv-arm 3.6s ease-in-out infinite}
.demo-wave .forearm-r{animation:wv-fore 3.6s ease-in-out infinite}
.demo-wave .hand-r{animation:wv-hand 3.6s ease-in-out infinite}
.demo-wave .arm-l{animation:id-arml 4.6s ease-in-out infinite}
.demo-wave .fox-shadow{animation:sh-breathe 3.8s ease-in-out infinite}
/* fling the arm UP HIGH over the head (anticipate low, overshoot up), hold, wrist sways */
@keyframes wv-arm{0%{transform:rotate(10deg);animation-timing-function:cubic-bezier(.3,1.5,.6,1)}6%{transform:rotate(18deg)}14%{transform:rotate(-152deg)}82%{transform:rotate(-150deg)}94%,100%{transform:rotate(10deg)}}
@keyframes wv-fore{0%{transform:rotate(8deg)}14%,82%{transform:rotate(22deg)}94%,100%{transform:rotate(8deg)}}
@keyframes wv-hand{0%,16%{transform:rotate(-6deg)}26%{transform:rotate(30deg)}38%{transform:rotate(-24deg)}50%{transform:rotate(22deg)}62%{transform:rotate(-16deg)}74%{transform:rotate(10deg)}84%{transform:rotate(-4deg)}100%{transform:rotate(-6deg)}}
@keyframes wv-head{0%,100%{transform:rotate(-2deg)}18%{transform:rotate(5deg)}60%{transform:rotate(3deg)}}
@keyframes wv-bob{0%,100%{transform:translateY(1px) scale(1,1)}14%{transform:translateY(-4px) scale(.99,1.02)}50%{transform:translateY(-2px) scale(1,1)}}
@keyframes wv-lean{0%,100%{transform:rotate(-1.5deg)}50%{transform:rotate(2deg)}}
@keyframes wv-tailwag{0%,100%{transform:rotate(-14deg)}50%{transform:rotate(16deg)}}

/* ============================================================
   SWING — FIXED for glide.  Single overhead grip; the body
   pendulums smoothly beneath a fixed branch (the pivot origin
   sits at the top). Proper pendulum easing: FLOAT at each apex,
   WHIP through the bottom (ease-in down, ease-out up), with the
   pivot + body-arc keyframe TIMES aligned so nothing fights.
   Tail + legs trail (follow-through); head stays level.
   ============================================================ */
.demo-swing .fox-pivot{animation:sw-pend 1.7s infinite;transform-origin:50% 7%}
.demo-swing .fox-bob{animation:sw-arc 1.7s ease-in-out infinite}
.demo-swing .arm-l{animation:sw-armL 1.7s ease-in-out infinite}
.demo-swing .arm-r{animation:sw-armR 1.7s ease-in-out infinite}
.demo-swing .forearm-l{animation:sw-foreL 1.7s ease-in-out infinite}
.demo-swing .forearm-r{animation:sw-foreR 1.7s ease-in-out infinite}
.demo-swing .hand-l{animation:sw-grip 1.7s ease-in-out infinite}
.demo-swing .hand-r{animation:sw-grip 1.7s ease-in-out infinite}
.demo-swing .leg-l{animation:sw-legL 1.7s ease-in-out infinite}
.demo-swing .leg-r{animation:sw-legR 1.7s ease-in-out infinite}
.demo-swing .shin-l{animation:sw-shin 1.7s ease-in-out infinite}
.demo-swing .shin-r{animation:sw-shin 1.7s ease-in-out infinite}
.demo-swing .tail{animation:sw-tail 1.7s ease-in-out infinite}
.demo-swing .head{animation:sw-head 1.7s ease-in-out infinite}
.demo-swing .fox-shadow{animation:sw-shadow 1.7s ease-in-out infinite}
/* pendulum: apex float -> accelerate down -> whip -> decelerate up */
@keyframes sw-pend{
 0%   {transform:rotate(-21deg);animation-timing-function:cubic-bezier(.42,0,1,.62)}
 25%  {transform:rotate(0deg);  animation-timing-function:cubic-bezier(0,.4,.58,1)}
 50%  {transform:rotate(21deg); animation-timing-function:cubic-bezier(.42,0,1,.62)}
 75%  {transform:rotate(0deg);  animation-timing-function:cubic-bezier(0,.4,.58,1)}
 100% {transform:rotate(-21deg)}
}
/* body rides highest (near-weightless) at each apex, lowest at the bottom; times aligned to the pendulum */
@keyframes sw-arc{0%,50%,100%{transform:translateY(-10px)}25%,75%{transform:translateY(5px)}}
/* both arms straight UP gripping the overhead bar, HELD (tiny give so it breathes) */
@keyframes sw-armR{0%,100%{transform:rotate(-171deg)}25%{transform:rotate(-173deg)}50%{transform:rotate(-171deg)}75%{transform:rotate(-169deg)}}
@keyframes sw-armL{0%,100%{transform:rotate(171deg)}25%{transform:rotate(169deg)}50%{transform:rotate(171deg)}75%{transform:rotate(173deg)}}
@keyframes sw-foreR{0%,100%{transform:rotate(-2deg)}50%{transform:rotate(-4deg)}}
@keyframes sw-foreL{0%,100%{transform:rotate(2deg)}50%{transform:rotate(4deg)}}
@keyframes sw-grip{0%,100%{transform:rotate(0deg)}50%{transform:rotate(-2deg)}}
/* legs HANG and trail the swing (follow-through), lagging the body ~12% */
@keyframes sw-legL{0%{transform:rotate(6deg)}20%{transform:rotate(9deg)}55%{transform:rotate(-7deg)}70%{transform:rotate(-9deg)}100%{transform:rotate(6deg)}}
@keyframes sw-legR{0%{transform:rotate(-3deg)}20%{transform:rotate(0deg)}55%{transform:rotate(-11deg)}70%{transform:rotate(-13deg)}100%{transform:rotate(-3deg)}}
@keyframes sw-shin{0%,100%{transform:rotate(4deg)}50%{transform:rotate(9deg)}}
/* tail streams behind, whips past the apex; lags body ~12% */
@keyframes sw-tail{0%{transform:rotate(26deg)}14%{transform:rotate(20deg)}50%{transform:rotate(-24deg)}64%{transform:rotate(-30deg)}82%{transform:rotate(-6deg)}100%{transform:rotate(26deg)}}
/* head counter-rotates to stay roughly level */
@keyframes sw-head{0%,100%{transform:rotate(11deg)}25%{transform:rotate(0deg)}50%{transform:rotate(-11deg)}75%{transform:rotate(0deg)}}
/* shadow: smallest+lightest under the apexes (body high), biggest at the bottom */
@keyframes sw-shadow{0%,50%,100%{transform:scale(.7);opacity:.2}25%,75%{transform:scale(1.06);opacity:.34}}

/* ============================================================
   WALK — FIXED: grounded natural walk. Swagger dialed WAY down
   (pelvic roll ±1deg), stride shortened, feet re-timed so the
   plant reads flat and the swing foot clears with a knee bend.
   ============================================================ */
.demo-walk .fox-pivot{animation:wk-pivot 1.08s ease-in-out infinite}
.demo-walk .fox-bob{animation:wk-bob 1.08s ease-in-out infinite}
.demo-walk .leg-l{animation:wk-legA 1.08s cubic-bezier(.42,.05,.25,1) infinite}
.demo-walk .leg-r{animation:wk-legB 1.08s cubic-bezier(.42,.05,.25,1) infinite}
.demo-walk .shin-l{animation:wk-shinA 1.08s ease-in-out infinite}
.demo-walk .shin-r{animation:wk-shinB 1.08s ease-in-out infinite}
.demo-walk .foot-l{animation:wk-footA 1.08s ease-in-out infinite}
.demo-walk .foot-r{animation:wk-footB 1.08s ease-in-out infinite}
.demo-walk .arm-l{animation:wk-armB 1.08s ease-in-out infinite}
.demo-walk .arm-r{animation:wk-armA 1.08s ease-in-out infinite}
.demo-walk .forearm-l{animation:wk-foreB 1.08s ease-in-out infinite}
.demo-walk .forearm-r{animation:wk-foreA 1.08s ease-in-out infinite}
.demo-walk .head{animation:wk-head 1.08s ease-in-out infinite}
.demo-walk .tail{animation:wk-tail 1.08s ease-in-out infinite}
.demo-walk .fox-shadow{animation:sh-step 1.08s ease-in-out infinite}
/* weighted bob: dips just after each contact, up at mid-stance. Modest. */
@keyframes wk-bob{0%{transform:translateY(-3px) scale(1,1)}14%{transform:translateY(3px) scale(1.015,.985)}38%{transform:translateY(-4px) scale(1,1)}50%{transform:translateY(-3px) scale(1,1)}64%{transform:translateY(3px) scale(1.015,.985)}88%{transform:translateY(-4px) scale(1,1)}100%{transform:translateY(-3px) scale(1,1)}}
/* pelvic roll almost gone (±1deg) + micro forward lean — NOT a swagger */
@keyframes wk-pivot{0%{transform:rotate(1deg)}25%{transform:rotate(-0.6deg)}50%{transform:rotate(1deg)}75%{transform:rotate(-0.6deg)}100%{transform:rotate(1deg)}}
/* hips: modest stride, legs a half-cycle apart, ballistic swing */
@keyframes wk-legA{0%,100%{transform:rotate(17deg)}50%{transform:rotate(-16deg)}}
@keyframes wk-legB{0%,100%{transform:rotate(-16deg)}50%{transform:rotate(17deg)}}
/* knee: bends on the passing (swing) leg to clear the ground, near-straight on the plant */
@keyframes wk-shinA{0%,50%,100%{transform:rotate(-3deg)}72%{transform:rotate(-38deg)}}
@keyframes wk-shinB{0%,100%{transform:rotate(-3deg)}22%{transform:rotate(-38deg)}}
/* foot roll timed to contact: heel-strike toe-up on plant, toe-off push at end of stance */
@keyframes wk-footA{0%{transform:rotate(-9deg)}12%{transform:rotate(2deg)}38%{transform:rotate(6deg)}50%{transform:rotate(14deg)}62%{transform:rotate(-9deg)}100%{transform:rotate(-9deg)}}
@keyframes wk-footB{0%{transform:rotate(6deg)}12%{transform:rotate(14deg)}24%{transform:rotate(-9deg)}62%{transform:rotate(-9deg)}88%{transform:rotate(6deg)}100%{transform:rotate(6deg)}}
/* arms counter-swing, modest, lag the legs */
@keyframes wk-armA{0%,100%{transform:rotate(15deg)}56%{transform:rotate(-14deg)}}
@keyframes wk-armB{0%,100%{transform:rotate(-14deg)}56%{transform:rotate(15deg)}}
@keyframes wk-foreA{0%,100%{transform:rotate(16deg)}60%{transform:rotate(6deg)}}
@keyframes wk-foreB{0%,100%{transform:rotate(6deg)}60%{transform:rotate(16deg)}}
/* head stays level, tiny counter-nod */
@keyframes wk-head{0%,50%,100%{transform:rotate(-1.5deg)}28%,78%{transform:rotate(1.5deg)}}
/* tail sways opposite the hips, lags ~12% */
@keyframes wk-tail{0%{transform:rotate(-5deg)}30%{transform:rotate(-12deg)}55%{transform:rotate(9deg)}80%{transform:rotate(13deg)}100%{transform:rotate(-5deg)}}

/* ============================================================
   JUMP — repeated vertical hops (Mike round 6): anticipation crouch ->
   launch (stretch) -> apex (airborne, shadow shrinks+fades) -> land
   (squash) -> settle -> hop again. Pure up/down, no travel. Jacks hop
   is the weight reference. Single-hop loop, so it reads as continuous
   hopping. Timing: rise decelerates to the apex, fall accelerates.
   ============================================================ */
.demo-jump .fox-root{animation:jp-root 1.3s ease-in-out infinite}
.demo-jump .fox-bob{animation:jp-bob 1.3s ease-in-out infinite}
.demo-jump .leg-l{animation:jp-legL 1.3s ease-in-out infinite}
.demo-jump .leg-r{animation:jp-legR 1.3s ease-in-out infinite}
.demo-jump .shin-l{animation:jp-shin 1.3s ease-in-out infinite}
.demo-jump .shin-r{animation:jp-shin 1.3s ease-in-out infinite}
.demo-jump .arm-l{animation:jp-armL 1.3s ease-in-out infinite}
.demo-jump .arm-r{animation:jp-armR 1.3s ease-in-out infinite}
.demo-jump .forearm-l{animation:jp-foreL 1.3s ease-in-out infinite}
.demo-jump .forearm-r{animation:jp-foreR 1.3s ease-in-out infinite}
.demo-jump .head{animation:jp-head 1.3s ease-in-out infinite}
.demo-jump .tail{animation:jp-tail 1.3s ease-in-out infinite}
.demo-jump .fox-shadow{animation:jp-shadow 1.3s ease-in-out infinite}
@keyframes jp-root{0%{transform:translateY(0)}10%{transform:translateY(8%);animation-timing-function:cubic-bezier(.3,0,.5,1)}18%{transform:translateY(2%);animation-timing-function:cubic-bezier(.15,.6,.4,1)}40%{transform:translateY(-20%);animation-timing-function:cubic-bezier(.5,0,.7,.4)}60%{transform:translateY(0)}64%{transform:translateY(6%)}72%{transform:translateY(0)}100%{transform:translateY(0)}}
@keyframes jp-bob{0%{transform:scale(1,1)}10%{transform:scale(1.12,.86)}18%{transform:scale(.95,1.06)}40%{transform:scale(.92,1.1)}60%{transform:scale(1,1)}64%{transform:scale(1.14,.84)}72%{transform:scale(1,1)}100%{transform:scale(1,1)}}
@keyframes jp-legR{0%{transform:rotate(3deg)}10%{transform:rotate(15deg)}40%{transform:rotate(-6deg)}60%{transform:rotate(4deg)}64%{transform:rotate(13deg)}72%{transform:rotate(3deg)}100%{transform:rotate(3deg)}}
@keyframes jp-legL{0%{transform:rotate(-3deg)}10%{transform:rotate(-15deg)}40%{transform:rotate(6deg)}60%{transform:rotate(-4deg)}64%{transform:rotate(-13deg)}72%{transform:rotate(-3deg)}100%{transform:rotate(-3deg)}}
@keyframes jp-shin{0%{transform:rotate(-4deg)}10%{transform:rotate(-40deg)}18%{transform:rotate(-10deg)}40%{transform:rotate(-22deg)}58%{transform:rotate(0)}64%{transform:rotate(-32deg)}72%{transform:rotate(-4deg)}100%{transform:rotate(-4deg)}}
@keyframes jp-armR{0%{transform:rotate(-6deg)}10%{transform:rotate(28deg)}18%{transform:rotate(-22deg)}40%{transform:rotate(-50deg)}60%{transform:rotate(0)}64%{transform:rotate(18deg)}72%{transform:rotate(-6deg)}100%{transform:rotate(-6deg)}}
@keyframes jp-armL{0%{transform:rotate(6deg)}10%{transform:rotate(-28deg)}18%{transform:rotate(22deg)}40%{transform:rotate(50deg)}60%{transform:rotate(0)}64%{transform:rotate(-18deg)}72%{transform:rotate(6deg)}100%{transform:rotate(6deg)}}
@keyframes jp-foreR{0%{transform:rotate(8deg)}10%{transform:rotate(22deg)}40%{transform:rotate(-8deg)}60%{transform:rotate(8deg)}100%{transform:rotate(8deg)}}
@keyframes jp-foreL{0%{transform:rotate(-8deg)}10%{transform:rotate(-22deg)}40%{transform:rotate(8deg)}60%{transform:rotate(-8deg)}100%{transform:rotate(-8deg)}}
@keyframes jp-head{0%{transform:rotate(0)}10%{transform:rotate(7deg)}40%{transform:rotate(-8deg)}60%{transform:rotate(3deg)}72%{transform:rotate(0)}100%{transform:rotate(0)}}
@keyframes jp-tail{0%{transform:rotate(-6deg)}10%{transform:rotate(-22deg)}40%{transform:rotate(26deg)}60%{transform:rotate(-4deg)}72%{transform:rotate(-6deg)}100%{transform:rotate(-6deg)}}
/* shadow: big+dark in the crouch/land, tiny+faint at the apex */
@keyframes jp-shadow{0%{transform:scale(1);opacity:.32}10%{transform:scale(1.05);opacity:.34}40%{transform:scale(.5);opacity:.14}60%{transform:scale(1.06);opacity:.36}64%{transform:scale(1.08);opacity:.38}72%{transform:scale(1);opacity:.32}100%{transform:scale(1);opacity:.32}}

/* ============================================================
   TALK — reusable talking mouth (Mike round 6). The jaw cycles
   speech shapes (closed -> ah -> mid -> closed) so it reads as
   speaking, for future VO / lip-sync. Pairs with the `talk` face.
   Subtle head + breath + tail life on top. tk-mouth is the reusable
   primitive: attach `.tk-jaw` + this keyframe to any face's mouth.
   ============================================================ */
.demo-talk .fox-bob{animation:tk-breath 3.4s ease-in-out infinite}
.demo-talk .head{animation:tk-head 2.9s ease-in-out infinite}
.demo-talk .tail{animation:tk-tail 3.4s ease-in-out infinite}
.demo-talk .tk-jaw{animation:tk-mouth .82s ease-in-out infinite}
/* eye life while talking: brows rise/fall, eyes look around (reused from listen) */
.demo-talk .fx-gaze{animation:ls-gaze 6.8s linear infinite}
.demo-talk .fx-brow{animation:ls-brow 4.6s ease-in-out infinite}
@keyframes tk-mouth{0%{transform:scaleY(.16)}16%{transform:scaleY(1.5)}30%{transform:scaleY(.55)}46%{transform:scaleY(1.7)}60%{transform:scaleY(.32)}76%{transform:scaleY(1.25)}90%{transform:scaleY(.5)}100%{transform:scaleY(.16)}}
@keyframes tk-breath{0%,100%{transform:scale(1,1)}50%{transform:scale(1.006,.994)}}
@keyframes tk-head{0%,100%{transform:rotate(-1.2deg)}30%{transform:rotate(1deg)}55%{transform:rotate(-0.4deg)}80%{transform:rotate(1.4deg)}}
@keyframes tk-tail{0%,100%{transform:rotate(-5deg)}50%{transform:rotate(3deg)}}

/* ============================================================
   SURPRISED — a startle beat (Mike round 6). Tiny anticipation
   dip, then a sharp POP: body pops up + recoils, head jerks back,
   arms flare, tail puffs; holds the wide-eyed alert look, relaxes,
   loops. Pairs with the `surprised` face (wide eyes, o-mouth).
   ============================================================ */
.demo-surprised .fox-root{animation:su-root 1.9s ease-out infinite}
.demo-surprised .fox-bob{animation:su-bob 1.9s ease-out infinite}
.demo-surprised .head{animation:su-head 1.9s ease-out infinite}
.demo-surprised .arm-l{animation:su-armL 1.9s ease-out infinite}
.demo-surprised .arm-r{animation:su-armR 1.9s ease-out infinite}
.demo-surprised .forearm-l{animation:su-foreL 1.9s ease-out infinite}
.demo-surprised .forearm-r{animation:su-foreR 1.9s ease-out infinite}
.demo-surprised .tail{animation:su-tail 1.9s ease-out infinite}
.demo-surprised .fox-shadow{animation:su-shadow 1.9s ease-out infinite}
.demo-surprised .fox-pivot{animation:su-jolt 1.9s ease-out infinite}
@keyframes su-root{0%{transform:translateY(0)}7%{transform:translateY(1%)}11%{transform:translateY(-4%);animation-timing-function:cubic-bezier(.2,.9,.3,1)}20%{transform:translateY(-1.5%)}30%{transform:translateY(-2%)}80%{transform:translateY(-2%)}92%{transform:translateY(0)}100%{transform:translateY(0)}}
@keyframes su-bob{0%{transform:scale(1,1)}7%{transform:scale(.98,1.02)}11%{transform:scale(1.07,.95);animation-timing-function:cubic-bezier(.2,.9,.3,1)}17%{transform:scale(1.01,.99)}30%{transform:scale(1.04,.97)}80%{transform:scale(1.04,.97)}92%{transform:scale(1,1)}100%{transform:scale(1,1)}}
/* recoil, THEN a quick head shake/jolt (14-19%) before settling -- more motion
   than the pose alone, so the surprise reads as a real reaction not a hold */
@keyframes su-head{0%{transform:rotate(0)}7%{transform:rotate(3deg)}11%{transform:rotate(-14deg);animation-timing-function:cubic-bezier(.2,.9,.3,1)}14%{transform:rotate(7deg)}16%{transform:rotate(-9deg)}18%{transform:rotate(3deg)}20%{transform:rotate(-6deg)}30%{transform:rotate(-6deg)}80%{transform:rotate(-6deg)}92%{transform:rotate(0)}100%{transform:rotate(0)}}
@keyframes su-jolt{0%,100%{transform:rotate(0)}11%{transform:rotate(-3deg)}14%{transform:rotate(2.5deg)}16%{transform:rotate(-2deg)}19%,80%{transform:rotate(0)}}
@keyframes su-armR{0%{transform:rotate(0)}11%{transform:rotate(-32deg);animation-timing-function:cubic-bezier(.2,.9,.3,1)}20%{transform:rotate(-17deg)}30%{transform:rotate(-20deg)}80%{transform:rotate(-20deg)}92%{transform:rotate(0)}100%{transform:rotate(0)}}
@keyframes su-armL{0%{transform:rotate(0)}11%{transform:rotate(32deg);animation-timing-function:cubic-bezier(.2,.9,.3,1)}20%{transform:rotate(17deg)}30%{transform:rotate(20deg)}80%{transform:rotate(20deg)}92%{transform:rotate(0)}100%{transform:rotate(0)}}
@keyframes su-foreR{0%{transform:rotate(0)}11%{transform:rotate(-22deg)}30%{transform:rotate(-15deg)}80%{transform:rotate(-15deg)}100%{transform:rotate(0)}}
@keyframes su-foreL{0%{transform:rotate(0)}11%{transform:rotate(22deg)}30%{transform:rotate(15deg)}80%{transform:rotate(15deg)}100%{transform:rotate(0)}}
@keyframes su-tail{0%{transform:rotate(-6deg)}11%{transform:rotate(22deg)}26%{transform:rotate(8deg)}80%{transform:rotate(8deg)}100%{transform:rotate(-6deg)}}
@keyframes su-shadow{0%{transform:scale(1);opacity:.32}11%{transform:scale(.93);opacity:.27}30%{transform:scale(.97);opacity:.3}80%{transform:scale(.97);opacity:.3}100%{transform:scale(1);opacity:.32}}

/* ============================================================
   SAD — a slow, heavy beat (Mike round 6). Head drooped forward,
   shoulders slumped, a slow sinking sigh; arms hang limp, tail
   droops low. Pairs with the `sad` face (worried brows, half-lidded
   eyes, downturned mouth). Everything slow + minimal = weight of mood.
   ============================================================ */
.demo-sad .fox-root{animation:sd-root 3.4s ease-in-out infinite}
.demo-sad .fox-bob{animation:sd-bob 3.4s ease-in-out infinite}
.demo-sad .head{animation:sd-head 3.4s ease-in-out infinite}
.demo-sad .arm-l{animation:sd-armL 3.4s ease-in-out infinite}
.demo-sad .arm-r{animation:sd-armR 3.4s ease-in-out infinite}
.demo-sad .forearm-l{animation:sd-foreL 3.4s ease-in-out infinite}
.demo-sad .forearm-r{animation:sd-foreR 3.4s ease-in-out infinite}
.demo-sad .tail{animation:sd-tail 3.4s ease-in-out infinite}
.demo-sad .fox-shadow{animation:sd-shadow 3.4s ease-in-out infinite}
@keyframes sd-root{0%{transform:translateY(0)}48%{transform:translateY(3%)}100%{transform:translateY(0)}}
@keyframes sd-bob{0%{transform:scale(1,1)}48%{transform:scale(1.025,.972)}100%{transform:scale(1,1)}}
@keyframes sd-head{0%{transform:rotate(7deg)}48%{transform:rotate(12deg)}100%{transform:rotate(7deg)}}
@keyframes sd-armR{0%{transform:rotate(-7deg)}48%{transform:rotate(-4deg)}100%{transform:rotate(-7deg)}}
@keyframes sd-armL{0%{transform:rotate(7deg)}48%{transform:rotate(4deg)}100%{transform:rotate(7deg)}}
@keyframes sd-foreR{0%{transform:rotate(6deg)}48%{transform:rotate(10deg)}100%{transform:rotate(6deg)}}
@keyframes sd-foreL{0%{transform:rotate(-6deg)}48%{transform:rotate(-10deg)}100%{transform:rotate(-6deg)}}
@keyframes sd-tail{0%{transform:rotate(15deg)}48%{transform:rotate(19deg)}100%{transform:rotate(15deg)}}
@keyframes sd-shadow{0%{transform:scale(1);opacity:.3}48%{transform:scale(1.03);opacity:.33}100%{transform:scale(1);opacity:.3}}

/* ---- SAD TEARS (D1) — drops fall from each eye and collect in a small
   puddle on the floor. World-space overlay (post-art, like idea-bulb),
   staggered left/right so they don't fall in lockstep. ---- */
.tear{transform-box:fill-box;transform-origin:50% 0%}
.tear-puddle{transform-box:fill-box;transform-origin:50% 50%}
.demo-sad .tear-l{animation:sd-tearL 2.6s ease-in infinite}
.demo-sad .tear-r{animation:sd-tearR 2.6s ease-in infinite 1.3s}
.demo-sad .puddle-l{animation:sd-puddle 2.6s ease-out infinite}
.demo-sad .puddle-r{animation:sd-puddle 2.6s ease-out infinite 1.3s}
@keyframes sd-tearL{0%,20%{opacity:0;transform:translateY(0) scale(.6)}28%{opacity:1;transform:translateY(4px) scale(1)}82%{opacity:1;transform:translateY(176px) scale(1.15)}88%,100%{opacity:0;transform:translateY(176px) scale(.9)}}
@keyframes sd-tearR{0%,20%{opacity:0;transform:translateY(0) scale(.6)}28%{opacity:1;transform:translateY(4px) scale(1)}82%{opacity:1;transform:translateY(176px) scale(1.15)}88%,100%{opacity:0;transform:translateY(176px) scale(.9)}}
@keyframes sd-puddle{0%,80%{opacity:0;transform:scale(.3)}86%{opacity:.55;transform:scale(1)}96%{opacity:.5;transform:scale(1.08)}100%{opacity:.5;transform:scale(1.08)}}

/* ============================================================
   HAPPY — a warm brighten beat (Mike round 6). Gentle buoyant
   rise, a small head lift (chin up), arms sway up, tail wags
   quicker (double-time). Everything soft + upbeat = content, not
   hyper. Pairs with the `happy` face (up brows, happy eyes, smile).
   ============================================================ */
.demo-happy .fox-root{animation:hp-root 2.6s ease-in-out infinite}
.demo-happy .fox-bob{animation:hp-bob 2.6s ease-in-out infinite}
.demo-happy .head{animation:hp-head 2.6s ease-in-out infinite}
.demo-happy .arm-l{animation:hp-armL 2.6s ease-in-out infinite}
.demo-happy .arm-r{animation:hp-armR 2.6s ease-in-out infinite}
.demo-happy .tail{animation:hp-tail 1.3s ease-in-out infinite}
.demo-happy .fox-shadow{animation:hp-shadow 2.6s ease-in-out infinite}
@keyframes hp-root{0%{transform:translateY(0)}50%{transform:translateY(-3.5%)}100%{transform:translateY(0)}}
@keyframes hp-bob{0%{transform:scale(1,1)}50%{transform:scale(1.012,.988)}100%{transform:scale(1,1)}}
@keyframes hp-head{0%{transform:rotate(-2deg)}50%{transform:rotate(-6deg)}100%{transform:rotate(-2deg)}}
@keyframes hp-armR{0%{transform:rotate(-4deg)}50%{transform:rotate(-12deg)}100%{transform:rotate(-4deg)}}
@keyframes hp-armL{0%{transform:rotate(4deg)}50%{transform:rotate(12deg)}100%{transform:rotate(4deg)}}
@keyframes hp-tail{0%{transform:rotate(-16deg)}50%{transform:rotate(8deg)}100%{transform:rotate(-16deg)}}
@keyframes hp-shadow{0%{transform:scale(1);opacity:.32}50%{transform:scale(.96);opacity:.29}100%{transform:scale(1);opacity:.32}}

/* ============================================================
   HIGH FIVE — the right arm winds down/back, then swings UP to slap
   an incoming partner paw. FK-solved so the fox paw lands at ~(218,92)
   where the partner's fingers arrive (contact by construction, like
   the push). Contact = body pop + head snap + shake + a starburst
   flash; both paws recoil. Partner paw + impact are world objects.
   ============================================================ */
.demo-highfive .fox-root{animation:hf-root 2.2s ease-in-out infinite}
.demo-highfive .fox-bob{animation:hf-bob 2.2s ease-in-out infinite}
.demo-highfive .head{animation:hf-head 2.2s ease-in-out infinite}
.demo-highfive .arm-r{animation:hf-armR 2.2s cubic-bezier(.5,0,.6,1) infinite}
.demo-highfive .forearm-r{animation:hf-foreR 2.2s cubic-bezier(.5,0,.6,1) infinite}
.demo-highfive .hand-r{animation:hf-handR 2.2s ease-in-out infinite}
.demo-highfive .arm-l{animation:hf-armL 2.2s ease-in-out infinite}
.demo-highfive .forearm-l{animation:hf-foreL 2.2s ease-in-out infinite}
.demo-highfive .tail{animation:hf-tail 2.2s ease-in-out infinite}
.demo-highfive .fox-shadow{animation:hf-shadow 2.2s ease-in-out infinite}
.demo-highfive .hf-paw{transform-box:view-box;transform-origin:0 0;animation:hf-paw 2.2s ease-in-out infinite}
.demo-highfive .hf-impact{transform-box:view-box;transform-origin:0 0;animation:hf-impact 2.2s ease-out infinite}
@keyframes hf-armR{0%{transform:rotate(-4deg)}10%{transform:rotate(24deg)}22%{transform:rotate(-72deg)}28%{transform:rotate(-112deg)}33%{transform:rotate(-104deg)}42%{transform:rotate(-110deg)}70%{transform:rotate(-110deg)}84%{transform:rotate(-34deg)}100%{transform:rotate(-4deg)}}
@keyframes hf-foreR{0%{transform:rotate(30deg)}10%{transform:rotate(12deg)}22%{transform:rotate(-14deg)}28%{transform:rotate(-36deg)}33%{transform:rotate(-44deg)}42%{transform:rotate(-34deg)}70%{transform:rotate(-34deg)}84%{transform:rotate(16deg)}100%{transform:rotate(30deg)}}
@keyframes hf-handR{0%{transform:rotate(0)}28%{transform:rotate(10deg)}33%{transform:rotate(-6deg)}42%{transform:rotate(6deg)}70%{transform:rotate(6deg)}100%{transform:rotate(0)}}
@keyframes hf-armL{0%{transform:rotate(4deg)}28%{transform:rotate(16deg)}40%{transform:rotate(10deg)}100%{transform:rotate(4deg)}}
@keyframes hf-foreL{0%{transform:rotate(-4deg)}28%{transform:rotate(-14deg)}100%{transform:rotate(-4deg)}}
@keyframes hf-root{0%{transform:translate(0,0)}10%{transform:translate(-1%,.5%)}22%{transform:translate(0,-1%)}28%{transform:translate(2.5%,0)}30%{transform:translate(-1.5%,.4%)}32%{transform:translate(1%,0)}35%{transform:translate(0,0)}100%{transform:translate(0,0)}}
@keyframes hf-bob{0%{transform:scale(1,1)}10%{transform:scale(1.02,.98)}28%{transform:scale(1.05,.95)}35%{transform:scale(1,1)}100%{transform:scale(1,1)}}
@keyframes hf-head{0%{transform:rotate(0)}10%{transform:rotate(4deg)}28%{transform:rotate(-7deg)}40%{transform:rotate(-3deg)}70%{transform:rotate(-3deg)}100%{transform:rotate(0)}}
@keyframes hf-tail{0%{transform:rotate(-6deg)}28%{transform:rotate(16deg)}45%{transform:rotate(2deg)}100%{transform:rotate(-6deg)}}
@keyframes hf-shadow{0%{transform:scale(1);opacity:.32}28%{transform:scale(1.04);opacity:.35}100%{transform:scale(1);opacity:.32}}
@keyframes hf-paw{0%{transform:translate(430px,128px)}14%{transform:translate(392px,128px)}25%{transform:translate(332px,130px)}28%{transform:translate(295px,131px)}33%{transform:translate(322px,130px)}42%{transform:translate(410px,128px)}55%{transform:translate(430px,128px)}100%{transform:translate(430px,128px)}}
@keyframes hf-impact{0%,26%{transform:translate(268px,132px) scale(.2);opacity:0}28%{transform:translate(268px,132px) scale(1);opacity:1}33%{transform:translate(268px,132px) scale(1.5);opacity:0}100%{transform:translate(268px,132px) scale(.2);opacity:0}}

/* ---- HIGH-FIVE JUMP variant — same reach, but he leaves the ground to meet
   the palm at the top of the arc. Reuses the arm/hand/paw/impact timing from
   the standing high-five; only fox-root + shadow change to add real air. ---- */
.demo-highfivejump .fox-root{animation:hfj-root 2.2s ease-in-out infinite}
.demo-highfivejump .fox-bob{animation:hf-bob 2.2s ease-in-out infinite}
.demo-highfivejump .head{animation:hf-head 2.2s ease-in-out infinite}
.demo-highfivejump .arm-r{animation:hf-armR 2.2s cubic-bezier(.5,0,.6,1) infinite}
.demo-highfivejump .forearm-r{animation:hf-foreR 2.2s cubic-bezier(.5,0,.6,1) infinite}
.demo-highfivejump .hand-r{animation:hf-handR 2.2s ease-in-out infinite}
.demo-highfivejump .arm-l{animation:hf-armL 2.2s ease-in-out infinite}
.demo-highfivejump .forearm-l{animation:hf-foreL 2.2s ease-in-out infinite}
.demo-highfivejump .tail{animation:hf-tail 2.2s ease-in-out infinite}
.demo-highfivejump .fox-shadow{animation:hfj-shadow 2.2s ease-in-out infinite}
.demo-highfivejump .hf-paw{transform-box:view-box;transform-origin:0 0;animation:hf-paw 2.2s ease-in-out infinite}
.demo-highfivejump .hf-impact{transform-box:view-box;transform-origin:0 0;animation:hf-impact 2.2s ease-out infinite}
@keyframes hfj-root{0%,100%{transform:translateY(0)}10%{transform:translateY(6px)}22%{transform:translateY(-40px)}28%{transform:translateY(-44px)}40%{transform:translateY(0)}}
@keyframes hfj-shadow{0%,100%{transform:scale(1);opacity:.32}10%{transform:scale(1.08);opacity:.36}22%{transform:scale(.5);opacity:.12}28%{transform:scale(.46);opacity:.1}40%{transform:scale(1.1);opacity:.38}}

/* ============================================================
   LISTEN — eye life (Mike round 6b). Brows rise and fall; the eyes
   dart to different focus points with holds (saccades + fixations)
   so the fox reads as attentively LISTENING. Attentive idle body on
   top. ls-gaze / ls-brow are the reusable primitives (attach .fx-gaze
   / .fx-brow to any face's open eyes). Gaze is LINEAR so darts snap.
   ============================================================ */
.demo-listen .fox-bob{animation:ls-breath 4.6s ease-in-out infinite}
.demo-listen .head{animation:ls-head 8s ease-in-out infinite}
.demo-listen .tail{animation:ls-tail 5s ease-in-out infinite}
.demo-listen .fx-gaze{animation:ls-gaze 6.8s linear infinite}
.demo-listen .fx-brow{animation:ls-brow 4.6s ease-in-out infinite}
/* saccade to a focus point (1% dart), hold, dart to the next... */
@keyframes ls-gaze{0%,12%{transform:translate(0,0)}13%,28%{transform:translate(-5px,2px)}29%,44%{transform:translate(5px,-3px)}45%,58%{transform:translate(-4px,0)}59%,73%{transform:translate(4px,3px)}74%,88%{transform:translate(0,-3px)}89%,100%{transform:translate(0,0)}}
/* brows rise and fall, with an occasional bigger interested lift */
@keyframes ls-brow{0%{transform:translateY(0)}18%{transform:translateY(-2.5px)}32%{transform:translateY(0)}50%{transform:translateY(-1px)}66%{transform:translateY(-4px)}80%{transform:translateY(-.5px)}100%{transform:translateY(0)}}
@keyframes ls-breath{0%,100%{transform:scale(1,1)}50%{transform:scale(1.008,.992)}}
@keyframes ls-head{0%{transform:rotate(0)}25%{transform:rotate(-1.6deg)}50%{transform:rotate(1deg)}75%{transform:rotate(-.8deg)}100%{transform:rotate(0)}}
@keyframes ls-tail{0%,100%{transform:rotate(-6deg)}50%{transform:rotate(2deg)}}

/* ============================================================
   SOMERSAULT — a forward tuck-flip in place. SPLIT RIG so it reads
   smooth: the up-and-over ARC rides fox-root (a gravity curve), the
   full 360deg SPIN rides fox-pivot re-centred (ONE continuous eased
   rotation, no per-keyframe pulsing). Limbs tuck into a ball around
   the apex and extend to catch on landing, then a short rest beat.
   Front-facing rig, but the tuck + full rotation read as a
   somersault (the 2D unlock: each clip picks the motion that reads).
   Joint scheme mirrors jump: mirrored legs/arms, shared shins.
   ============================================================ */
.demo-somersault .fox-root{animation:so-arc 4.8s linear infinite}
.demo-somersault .fox-pivot{transform-origin:50% 54%;animation:so-spin 4.8s cubic-bezier(.5,.02,.5,.98) infinite}
.demo-somersault .fox-bob{animation:so-bob 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .leg-l{animation:so-legL 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .leg-r{animation:so-legR 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .shin-l{animation:so-shin 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .shin-r{animation:so-shin 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .arm-l{animation:so-armL 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .arm-r{animation:so-armR 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .forearm-l{animation:so-foreL 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .forearm-r{animation:so-foreR 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .hand-l{animation:so-handL 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .hand-r{animation:so-handR 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .head{animation:so-head 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .tail{animation:so-tail 4.8s cubic-bezier(.37,0,.63,1) infinite}
.demo-somersault .fox-shadow{animation:so-shadow 4.8s cubic-bezier(.37,0,.63,1) infinite}
/* arc: sink/load, then a gravity hop — decelerate up to the apex (ease-out),
   accelerate down (ease-in), soft-settle the landing, hold for the rest beat.
   rotation lives on the pivot, so this is a clean vertical arc with no spin. */
@keyframes so-arc{0%{transform:translate(0,0)}8%{transform:translate(0,4%);animation-timing-function:cubic-bezier(.4,0,.6,1)}15%{transform:translate(0,6%);animation-timing-function:cubic-bezier(.22,.55,.32,1)}40%{transform:translate(2%,-33%);animation-timing-function:cubic-bezier(.6,0,.72,.5)}62%{transform:translate(0,0);animation-timing-function:cubic-bezier(.34,1.3,.64,1)}68%{transform:translate(0,1.6%);animation-timing-function:cubic-bezier(.4,0,.6,1)}74%,100%{transform:translate(0,0)}}
/* spin: hold flat through the crouch, ONE continuous eased 360 from launch to
   landing (single segment => no pulsing), hold flat through the rest beat. */
@keyframes so-spin{0%,15%{transform:rotate(0)}62%,100%{transform:rotate(360deg)}}
/* bob: crouch(wide+short) -> launch stretch -> ball -> land squash -> settle */
@keyframes so-bob{0%{transform:scale(1,1)}8%{transform:scale(1.05,.9)}15%{transform:scale(1.08,.86)}19%{transform:scale(.84,1.2)}40%{transform:scale(1,1)}58%{transform:scale(.9,1.12)}62%{transform:scale(1.12,.84)}68%{transform:scale(.98,1.03)}74%{transform:scale(1,1)}84%{transform:scale(.99,1.01)}92%{transform:scale(1.004,.996)}100%{transform:scale(1,1)}}
/* near leg: bend -> push -> fold knee to chest for the tuck (held over the apex) -> extend to land */
@keyframes so-legR{0%{transform:rotate(0)}8%{transform:rotate(12deg)}15%{transform:rotate(18deg)}19%{transform:rotate(-8deg)}34%{transform:rotate(124deg)}46%{transform:rotate(124deg)}58%{transform:rotate(22deg)}62%{transform:rotate(-8deg)}68%{transform:rotate(6deg)}74%,100%{transform:rotate(0)}}
@keyframes so-legL{0%{transform:rotate(0)}8%{transform:rotate(-12deg)}15%{transform:rotate(-18deg)}19%{transform:rotate(8deg)}34%{transform:rotate(-124deg)}46%{transform:rotate(-124deg)}58%{transform:rotate(-22deg)}62%{transform:rotate(8deg)}68%{transform:rotate(-6deg)}74%,100%{transform:rotate(0)}}
/* shins (shared): bend back on load, fold hard so heels tuck under, absorb on land */
@keyframes so-shin{0%{transform:rotate(0)}8%{transform:rotate(-16deg)}15%{transform:rotate(-24deg)}19%{transform:rotate(20deg)}34%{transform:rotate(106deg)}46%{transform:rotate(106deg)}58%{transform:rotate(28deg)}62%{transform:rotate(-14deg)}68%{transform:rotate(6deg)}74%,100%{transform:rotate(0)}}
/* near arm: wind up -> throw -> wrap the tuck (held) -> out for balance on land */
@keyframes so-armR{0%{transform:rotate(0)}8%{transform:rotate(-30deg)}15%{transform:rotate(-50deg)}19%{transform:rotate(20deg)}34%{transform:rotate(98deg)}46%{transform:rotate(98deg)}58%{transform:rotate(50deg)}62%{transform:rotate(-24deg)}68%{transform:rotate(-8deg)}74%,100%{transform:rotate(0)}}
@keyframes so-armL{0%{transform:rotate(0)}8%{transform:rotate(30deg)}15%{transform:rotate(50deg)}19%{transform:rotate(-20deg)}34%{transform:rotate(-98deg)}46%{transform:rotate(-98deg)}58%{transform:rotate(-50deg)}62%{transform:rotate(24deg)}68%{transform:rotate(8deg)}74%,100%{transform:rotate(0)}}
@keyframes so-foreR{0%{transform:rotate(0)}8%{transform:rotate(10deg)}19%{transform:rotate(-10deg)}34%{transform:rotate(94deg)}46%{transform:rotate(94deg)}58%{transform:rotate(30deg)}62%{transform:rotate(10deg)}74%,100%{transform:rotate(0)}}
@keyframes so-foreL{0%{transform:rotate(0)}8%{transform:rotate(-10deg)}19%{transform:rotate(10deg)}34%{transform:rotate(-94deg)}46%{transform:rotate(-94deg)}58%{transform:rotate(-30deg)}62%{transform:rotate(-10deg)}74%,100%{transform:rotate(0)}}
@keyframes so-handR{0%{transform:rotate(0)}34%{transform:rotate(22deg)}46%{transform:rotate(22deg)}58%{transform:rotate(6deg)}62%{transform:rotate(-6deg)}74%,100%{transform:rotate(0)}}
@keyframes so-handL{0%{transform:rotate(0)}34%{transform:rotate(-22deg)}46%{transform:rotate(-22deg)}58%{transform:rotate(-6deg)}62%{transform:rotate(6deg)}74%,100%{transform:rotate(0)}}
/* head: dip -> look up on launch -> tuck with the ball -> up to spot the landing */
@keyframes so-head{0%{transform:rotate(0)}8%{transform:rotate(-8deg)}19%{transform:rotate(10deg)}34%{transform:rotate(29deg)}46%{transform:rotate(29deg)}54%{transform:rotate(-13deg)}62%{transform:rotate(-4deg)}74%,100%{transform:rotate(0)}}
/* tail: anticipation, whip up on launch, curl into the ball, counter on land */
/* tail LAGS the body: curls last (40%), uncurls last (62%), and keeps drifting
   through the previously-dead rest beat (82/92%) so the hold breathes home */
@keyframes so-tail{0%{transform:rotate(0)}8%{transform:rotate(-18deg)}19%{transform:rotate(30deg)}40%{transform:rotate(90deg)}48%{transform:rotate(86deg)}62%{transform:rotate(18deg)}68%{transform:rotate(-16deg)}76%{transform:rotate(7deg)}86%{transform:rotate(-4deg)}93%{transform:rotate(2deg)}100%{transform:rotate(0)}}
/* shadow: weight on load, tiny+faint at apex, snaps big+dark on impact */
@keyframes so-shadow{0%{transform:scale(1);opacity:.30}8%{transform:scale(1.06);opacity:.36}19%{transform:scale(.8);opacity:.24}40%{transform:scale(.3);opacity:.12}58%{transform:scale(.74);opacity:.24}62%{transform:scale(1.16);opacity:.44}68%{transform:scale(1);opacity:.32}74%,100%{transform:scale(1);opacity:.30}}
/* EYE ACTING (Mike: "so much opportunity with the eyes you aren't using"). For the
   flip, swap the flat happy-curve eyes for the round pupils so they can ACT: widen
   + look up INTO the launch (anticipation), hold wide through the airborne apex
   (exhilaration), a quick blink on the landing, settle. Grin mouth + raised brows
   stay, so it reads as a wide-eyed delighted grin, not a new expression. */
.foxsvg.demo-somersault .p-e-happy{opacity:0}
.foxsvg.demo-somersault .fx-pupil{opacity:1;transform-box:fill-box;transform-origin:center;animation:so-eyes 4.8s cubic-bezier(.37,0,.63,1) infinite}
@keyframes so-eyes{0%{transform:scale(1) translateY(0)}8%{transform:scale(1.16) translateY(-1px)}19%{transform:scale(1.22) translateY(-1.5px)}40%{transform:scale(1.16) translateY(-1px)}56%{transform:scale(1.1) translateY(0)}61%{transform:scaleX(1.12) scaleY(.14)}65%{transform:scale(1.06)}74%,100%{transform:scale(1)}}

/* ============================================================
   CARTWHEEL — the somersault's extended-limb sibling. Same split
   rig, but the limbs hold a spread STAR instead of a tuck and the
   wheel spins evenly (linear) while swaying side to side, so it
   reads as a cartwheel rather than a tuck-flip. Continuous: the
   even 0->360 wheel loops seamlessly, no rest beat.
   ============================================================ */
.demo-cartwheel .fox-root{animation:cw-arc 3.6s ease-in-out infinite}
.demo-cartwheel .fox-pivot{transform-origin:50% 54%;animation:cw-spin 3.6s linear infinite}
.demo-cartwheel .fox-bob{animation:cw-bob 3.6s ease-in-out infinite}
.demo-cartwheel .leg-l{animation:cw-legL 3.6s ease-in-out infinite}
.demo-cartwheel .leg-r{animation:cw-legR 3.6s ease-in-out infinite}
.demo-cartwheel .shin-l{animation:cw-shin 3.6s ease-in-out infinite}
.demo-cartwheel .shin-r{animation:cw-shin 3.6s ease-in-out infinite}
.demo-cartwheel .arm-l{animation:cw-armL 3.6s ease-in-out infinite}
.demo-cartwheel .arm-r{animation:cw-armR 3.6s ease-in-out infinite}
.demo-cartwheel .forearm-l{animation:cw-foreL 3.6s ease-in-out infinite}
.demo-cartwheel .forearm-r{animation:cw-foreR 3.6s ease-in-out infinite}
.demo-cartwheel .head{animation:cw-head 3.6s ease-in-out infinite}
.demo-cartwheel .tail{animation:cw-tail 3.6s ease-in-out infinite}
.demo-cartwheel .fox-shadow{animation:cw-shadow 3.6s ease-in-out infinite}
/* even wheel: one linear 360, seamless */
@keyframes cw-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
/* sway right-up / center-down / left-up, net-zero so the loop closes */
/* rolling-wheel arc: DIP the leading limb onto the ground at the contact
   frames (25% hand-plant, 75% foot-plant), rise over the inverted pass (50%).
   Small X oscillation so it reads as rolling, returns to 0 for a clean loop. */
@keyframes cw-arc{0%{transform:translate(0,2%)}25%{transform:translate(3%,17%)}50%{transform:translate(0,-9%)}75%{transform:translate(-3%,17%)}100%{transform:translate(0,2%)}}
/* ground-press squash at the two contacts (weight lands on the planted limb) */
/* harder ground-press snap at the contacts; float taller through the pass */
@keyframes cw-bob{0%,100%{transform:scale(1,1)}25%{transform:scale(1.15,.83)}50%{transform:scale(.94,1.06)}75%{transform:scale(1.15,.83)}}
/* legs held in a wide split star, slight reach at the contacts */
/* wider split at the inverted pass (the wheel opens more) */
@keyframes cw-legR{0%{transform:rotate(42deg)}25%{transform:rotate(28deg)}50%{transform:rotate(54deg)}75%{transform:rotate(28deg)}100%{transform:rotate(42deg)}}
@keyframes cw-legL{0%{transform:rotate(-42deg)}25%{transform:rotate(-28deg)}50%{transform:rotate(-54deg)}75%{transform:rotate(-28deg)}100%{transform:rotate(-42deg)}}
@keyframes cw-shin{0%,100%{transform:rotate(6deg)}50%{transform:rotate(-4deg)}}
/* arms reach overhead/out to complete the star */
@keyframes cw-armR{0%{transform:rotate(-128deg)}50%{transform:rotate(-140deg)}100%{transform:rotate(-128deg)}}
@keyframes cw-armL{0%{transform:rotate(128deg)}50%{transform:rotate(140deg)}100%{transform:rotate(128deg)}}
@keyframes cw-foreR{0%,100%{transform:rotate(-6deg)}50%{transform:rotate(6deg)}}
@keyframes cw-foreL{0%,100%{transform:rotate(6deg)}50%{transform:rotate(-6deg)}}
@keyframes cw-head{0%,100%{transform:rotate(0)}25%{transform:rotate(-6deg)}75%{transform:rotate(6deg)}}
/* tail flings wider on centrifugal force and LAGS the body (peaks ~10% after the
   contacts), overshooting before it recovers - was a linear metronome */
@keyframes cw-tail{0%{transform:rotate(-40deg)}35%{transform:rotate(44deg)}60%{transform:rotate(-12deg)}85%{transform:rotate(40deg)}100%{transform:rotate(-40deg)}}
/* shadow tracks the planted contact: right under the hand-plant (25%), left
   under the foot-plant (75%), pressing big+dark; small+faint + centred at the
   airborne inverted pass (50%). Contact point travels, like a real cartwheel. */
@keyframes cw-shadow{0%,100%{transform:translate(0,0) scale(1);opacity:.3}25%{transform:translate(120%,0) scale(1.15);opacity:.42}50%{transform:translate(0,0) scale(.66);opacity:.16}75%{transform:translate(-120%,0) scale(1.15);opacity:.42}}

/* ============================================================
   POINT / EXPLAIN — the teaching pose (ported from v3).
   ============================================================ */
.demo-point .fox-pivot{animation:pt-lean 4.4s ease-in-out infinite}
.demo-point .arm-r{animation:pt-arm 4.4s ease-in-out infinite}
.demo-point .forearm-r{animation:pt-fore 4.4s ease-in-out infinite}
.demo-point .hand-r{animation:pt-hand 4.4s ease-in-out infinite}
.demo-point .arm-l{animation:pt-farm 4.4s ease-in-out infinite}
.demo-point .head{animation:pt-head 4.4s ease-in-out infinite}
.demo-point .tail{animation:pt-tail 3s ease-in-out infinite}
.demo-point .fox-bob{animation:id-breathe 3.8s ease-in-out infinite}
.demo-point .fox-shadow{animation:sh-breathe 4.4s ease-in-out infinite}
/* C2 look-to-a-target: the eyes lead the point, glancing toward the pt-target
   BEFORE the arm arrives, then holding on it for the duration of the point */
.demo-point .fx-gaze{animation:pt-gaze 4.4s ease-in-out infinite}
@keyframes pt-gaze{0%,22%{transform:translate(0,0)}30%{transform:translate(7px,-3px)}86%{transform:translate(7px,-3px)}96%,100%{transform:translate(0,0)}}
@keyframes pt-lean{0%,20%{transform:rotate(0)}30%{transform:rotate(-3deg)}42%{transform:rotate(4deg)}86%{transform:rotate(3deg)}100%{transform:rotate(0)}}
@keyframes pt-arm{0%,22%{transform:rotate(8deg)}30%{transform:rotate(22deg);animation-timing-function:cubic-bezier(.45,0,.15,1)}42%{transform:rotate(-86deg);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}50%{transform:rotate(-75deg)}86%{transform:rotate(-77deg)}96%{transform:rotate(12deg)}100%{transform:rotate(8deg)}}
@keyframes pt-fore{0%,30%{transform:rotate(28deg)}42%{transform:rotate(-4deg)}50%{transform:rotate(2deg)}86%{transform:rotate(-3deg)}96%{transform:rotate(28deg)}100%{transform:rotate(28deg)}}
@keyframes pt-hand{0%,34%{transform:rotate(14deg)}46%{transform:rotate(-18deg)}58%{transform:rotate(-13deg)}72%{transform:rotate(-16deg)}86%{transform:rotate(-14deg)}96%{transform:rotate(14deg)}100%{transform:rotate(14deg)}}
@keyframes pt-head{0%,18%{transform:rotate(0)}28%{transform:rotate(4deg)}40%{transform:rotate(-11deg)}48%{transform:rotate(-8deg)}86%{transform:rotate(-10deg)}100%{transform:rotate(0)}}
@keyframes pt-farm{0%,100%{transform:rotate(0)}42%{transform:rotate(9deg)}86%{transform:rotate(7deg)}}
@keyframes pt-tail{0%,100%{transform:rotate(-6deg)}50%{transform:rotate(8deg)}}

/* ============================================================
   GESTURE FAMILY — shared living base (breath + shadow) + a
   named arm/head gesture. Each loops with a hold + settle.
   ============================================================ */
[class*="demo-"].g-base .fox-bob{animation:id-breathe 3.9s ease-in-out infinite}
[class*="demo-"].g-base .fox-shadow{animation:sh-breathe 3.9s ease-in-out infinite}
[class*="demo-"].g-base .tail{animation:id-tail 2.9s ease-in-out infinite}

/* ---- PRESENT — both arms sweep open, palms out, "here it is" ---- */
.demo-present .arm-r{animation:pr-armR 4s ease-in-out infinite}
.demo-present .arm-l{animation:pr-armL 4s ease-in-out infinite}
.demo-present .forearm-r{animation:pr-foreR 4s ease-in-out infinite}
.demo-present .forearm-l{animation:pr-foreL 4s ease-in-out infinite}
.demo-present .head{animation:pr-head 4s ease-in-out infinite}
.demo-present .fox-pivot{animation:pr-lean 4s ease-in-out infinite}
@keyframes pr-armR{0%,14%{transform:rotate(4deg)}30%{transform:rotate(-52deg);animation-timing-function:cubic-bezier(.34,1.4,.64,1)}82%{transform:rotate(-48deg)}96%,100%{transform:rotate(4deg)}}
@keyframes pr-armL{0%,14%{transform:rotate(-4deg)}30%{transform:rotate(52deg);animation-timing-function:cubic-bezier(.34,1.4,.64,1)}82%{transform:rotate(48deg)}96%,100%{transform:rotate(-4deg)}}
@keyframes pr-foreR{0%,14%{transform:rotate(6deg)}30%,82%{transform:rotate(-26deg)}96%,100%{transform:rotate(6deg)}}
@keyframes pr-foreL{0%,14%{transform:rotate(-6deg)}30%,82%{transform:rotate(26deg)}96%,100%{transform:rotate(-6deg)}}
@keyframes pr-head{0%,100%{transform:rotate(0)}30%{transform:rotate(-3deg)}60%{transform:rotate(2deg)}}
@keyframes pr-lean{0%,20%{transform:rotate(0)}32%{transform:rotate(-2deg)}100%{transform:rotate(0)}}

/* ---- THUMBSUP — near forearm pops up, hand cocks to a thumbs-up, held ---- */
.demo-thumbsup .arm-r{animation:tu-arm 3.4s ease-in-out infinite}
.demo-thumbsup .forearm-r{animation:tu-fore 3.4s ease-in-out infinite}
.demo-thumbsup .hand-r{animation:tu-hand 3.4s ease-in-out infinite}
.demo-thumbsup .arm-l{animation:id-arml 4.6s ease-in-out infinite}
.demo-thumbsup .head{animation:pr-head 3.4s ease-in-out infinite}
/* thumb swings OUT to the side (arm out, forearm barely folded) instead of
   folding up in front of the chest */
@keyframes tu-arm{0%,16%{transform:rotate(4deg)}30%{transform:rotate(-58deg);animation-timing-function:cubic-bezier(.34,1.5,.64,1)}84%{transform:rotate(-54deg)}96%,100%{transform:rotate(4deg)}}
@keyframes tu-fore{0%,16%{transform:rotate(10deg)}30%,84%{transform:rotate(42deg)}96%,100%{transform:rotate(10deg)}}
@keyframes tu-hand{0%,30%{transform:rotate(0)}40%{transform:rotate(-30deg)}84%{transform:rotate(-28deg)}96%,100%{transform:rotate(0)}}

/* ---- NOD (yes) — head dips down-up twice, tiny body agree-bob ---- */
.demo-nod .head{animation:nd-head 2.2s ease-in-out infinite}
.demo-nod .fox-bob{animation:nd-bob 2.2s ease-in-out infinite}
.demo-nod .fox-pivot{animation:nd-body 2.2s ease-in-out infinite}
.demo-nod .fox-shadow{animation:sh-breathe 2.2s ease-in-out infinite}
.demo-nod .arm-r{animation:id-armr 5s ease-in-out infinite}
.demo-nod .arm-l{animation:id-arml 4.6s ease-in-out infinite}
.demo-nod .tail{animation:id-tail 2.6s ease-in-out infinite}
/* a real vertical (X-axis) 3D nod: NO picture-plane rotate (that read as the
   "Indian head nod" side tilt). Instead a scaleY foreshorten + translateY, the
   same trick shake uses on the horizontal axis (scaleX). The body (fox-pivot)
   dips along with the head so the whole figure reads as tilting toward camera. */
@keyframes nd-head{0%,100%{transform:translateY(0) scaleY(1)}12%{transform:translateY(11px) scaleY(.86)}24%{transform:translateY(-3px) scaleY(1.04)}40%{transform:translateY(11px) scaleY(.86)}54%{transform:translateY(0) scaleY(1)}}
@keyframes nd-body{0%,100%{transform:rotate(0)}12%,40%{transform:rotate(4deg)}24%{transform:rotate(-1deg)}54%{transform:rotate(0)}}
@keyframes nd-bob{0%,100%{transform:scale(1,1)}12%,40%{transform:scale(1.015,.985)}24%{transform:scale(.99,1.01)}54%{transform:scale(1,1)}}

/* ---- SHAKE (no) — a real head TURN on the vertical axis (yaw), not a
   sideways tilt. Simulated 3D: horizontal foreshorten (scaleX) as the face
   turns away + a shift + slight counter-rotate. Robust everywhere (true
   rotateY on SVG groups is unreliable), and it reads as turning side to side. ---- */
.demo-shake .head{animation:sk-yaw 2s ease-in-out infinite}
.demo-shake .fox-bob{animation:id-breathe 3.9s ease-in-out infinite}
.demo-shake .fox-pivot{animation:sk-body 2s ease-in-out infinite}
.demo-shake .fox-shadow{animation:sh-breathe 3.9s ease-in-out infinite}
.demo-shake .tail{animation:sk-tail 2s ease-in-out infinite}
.demo-shake .arm-r{animation:id-armr 5s ease-in-out infinite}
.demo-shake .arm-l{animation:id-arml 4.6s ease-in-out infinite}
@keyframes sk-yaw{
 0%,100%{transform:translateX(0) scaleX(1) rotate(0)}
 13%{transform:translateX(-4px) scaleX(.92) rotate(-1.5deg)}
 27%{transform:translateX(-9px) scaleX(.78) rotate(-2.5deg)}
 50%{transform:translateX(0) scaleX(1) rotate(0)}
 73%{transform:translateX(9px) scaleX(.78) rotate(2.5deg)}
 87%{transform:translateX(4px) scaleX(.92) rotate(1.5deg)}
}
@keyframes sk-body{0%,100%{transform:rotate(0)}27%{transform:rotate(-1.6deg)}73%{transform:rotate(1.6deg)}}
@keyframes sk-tail{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(8deg)}}

/* ---- SHRUG — shoulders lift, arms open palms-up, head tilt, hold ("who knows") ---- */
.demo-shrug .arm-r{animation:sh-armR 3.6s ease-in-out infinite}
.demo-shrug .arm-l{animation:sh-armL 3.6s ease-in-out infinite}
.demo-shrug .forearm-r{animation:sh-foreR 3.6s ease-in-out infinite}
.demo-shrug .forearm-l{animation:sh-foreL 3.6s ease-in-out infinite}
.demo-shrug .fox-bob{animation:sh-bob 3.6s ease-in-out infinite}
.demo-shrug .head{animation:sh-head 3.6s ease-in-out infinite}
.demo-shrug .fox-shadow{animation:sh-breathe 3.6s ease-in-out infinite}
@keyframes sh-armR{0%,18%{transform:rotate(4deg)}38%{transform:rotate(-38deg)}82%{transform:rotate(-35deg)}96%,100%{transform:rotate(4deg)}}
@keyframes sh-armL{0%,18%{transform:rotate(-4deg)}38%{transform:rotate(38deg)}82%{transform:rotate(35deg)}96%,100%{transform:rotate(-4deg)}}
@keyframes sh-foreR{0%,18%{transform:rotate(8deg)}38%,82%{transform:rotate(-58deg)}96%,100%{transform:rotate(8deg)}}
@keyframes sh-foreL{0%,18%{transform:rotate(-8deg)}38%,82%{transform:rotate(58deg)}96%,100%{transform:rotate(-8deg)}}
/* body lifts hard (shoulders up) while the head sinks down into them = ears */
@keyframes sh-bob{0%,18%{transform:translateY(0)}38%,82%{transform:translateY(-9px)}96%,100%{transform:translateY(0)}}
@keyframes sh-head{0%,18%{transform:rotate(0) translateY(0)}38%,82%{transform:rotate(8deg) translateY(5px)}96%,100%{transform:rotate(0) translateY(0)}}

/* ---- THINK — near hand to chin, look up, small taps, hold ---- */
.demo-think .arm-r{animation:th-arm 5s ease-in-out infinite}
.demo-think .forearm-r{animation:th-fore 5s ease-in-out infinite}
.demo-think .hand-r{animation:th-hand 5s ease-in-out infinite}
.demo-think .head{animation:th-head 5s ease-in-out infinite}
.demo-think .arm-l{animation:id-arml 4.6s ease-in-out infinite}
.demo-think .fox-bob{animation:id-breathe 4s ease-in-out infinite}
.demo-think .fox-shadow{animation:sh-breathe 5s ease-in-out infinite}
.demo-think .tail{animation:id-tail 3s ease-in-out infinite}
@keyframes th-arm{0%,16%{transform:rotate(6deg)}30%{transform:rotate(24deg)}86%{transform:rotate(24deg)}96%,100%{transform:rotate(6deg)}}
@keyframes th-fore{0%,16%{transform:rotate(10deg)}30%{transform:rotate(104deg)}86%{transform:rotate(104deg)}96%,100%{transform:rotate(10deg)}}
@keyframes th-hand{0%,32%{transform:rotate(0)}44%{transform:rotate(-10deg)}56%{transform:rotate(0)}68%{transform:rotate(-10deg)}86%{transform:rotate(0)}}
@keyframes th-head{0%,16%{transform:rotate(0)}34%{transform:rotate(-7deg)}86%{transform:rotate(-6deg)}100%{transform:rotate(0)}}

/* ---- IDEA — "aha!": near arm shoots straight up (finger), body pops, held ---- */
.demo-idea .arm-r{animation:ia-arm 3.6s ease-in-out infinite}
.demo-idea .forearm-r{animation:ia-fore 3.6s ease-in-out infinite}
.demo-idea .hand-r{animation:ia-hand 3.6s ease-in-out infinite}
.demo-idea .fox-bob{animation:ia-bob 3.6s ease-in-out infinite}
.demo-idea .head{animation:ia-head 3.6s ease-in-out infinite}
.demo-idea .arm-l{animation:id-arml 4.6s ease-in-out infinite}
.demo-idea .fox-shadow{animation:ia-shadow 3.6s ease-in-out infinite}
.demo-idea .tail{animation:id-tail 2.6s ease-in-out infinite}
@keyframes ia-arm{0%,22%{transform:rotate(6deg)}32%{transform:rotate(-168deg);animation-timing-function:cubic-bezier(.34,1.5,.64,1)}84%{transform:rotate(-166deg)}94%,100%{transform:rotate(6deg)}}
@keyframes ia-fore{0%,22%{transform:rotate(10deg)}32%,84%{transform:rotate(-4deg)}94%,100%{transform:rotate(10deg)}}
@keyframes ia-hand{0%,84%{transform:rotate(0)}90%{transform:rotate(8deg)}100%{transform:rotate(0)}}
@keyframes ia-bob{0%,22%{transform:translateY(0) scale(1,1)}30%{transform:translateY(-6px) scale(.98,1.03)}40%{transform:translateY(0) scale(1,1)}100%{transform:translateY(0)}}
@keyframes ia-head{0%,22%{transform:rotate(0)}32%{transform:rotate(-5deg)}84%{transform:rotate(-4deg)}100%{transform:rotate(0)}}
@keyframes ia-shadow{0%,22%{transform:scale(1);opacity:.3}30%{transform:scale(.9);opacity:.26}40%,100%{transform:scale(1);opacity:.3}}

/* ---- CELEBRATE — arms up in a V, little hops, grin ---- */
.demo-celebrate .arm-r{animation:cl-armR 1.6s ease-in-out infinite}
.demo-celebrate .arm-l{animation:cl-armL 1.6s ease-in-out infinite}
.demo-celebrate .forearm-r{animation:cl-foreR 1.6s ease-in-out infinite}
.demo-celebrate .forearm-l{animation:cl-foreL 1.6s ease-in-out infinite}
.demo-celebrate .fox-root{animation:cl-hop 1.6s ease-in-out infinite}
.demo-celebrate .fox-bob{animation:cl-bob 1.6s ease-in-out infinite}
.demo-celebrate .head{animation:cl-head 1.6s ease-in-out infinite}
.demo-celebrate .tail{animation:cl-tail 0.8s ease-in-out infinite}
.demo-celebrate .fox-shadow{animation:cl-shadow 1.6s ease-in-out infinite}
@keyframes cl-hop{0%,100%{transform:translateY(0)}30%{transform:translateY(-26px)}55%{transform:translateY(0)}}
@keyframes cl-bob{0%{transform:scale(1,1)}18%{transform:scale(1.06,.92)}30%{transform:scale(.96,1.06)}55%{transform:scale(1.05,.95)}70%{transform:scale(1,1)}100%{transform:scale(1,1)}}
@keyframes cl-armR{0%,100%{transform:rotate(-142deg)}30%{transform:rotate(-150deg)}}
@keyframes cl-armL{0%,100%{transform:rotate(142deg)}30%{transform:rotate(150deg)}}
@keyframes cl-foreR{0%,100%{transform:rotate(-6deg)}30%{transform:rotate(-12deg)}}
@keyframes cl-foreL{0%,100%{transform:rotate(6deg)}30%{transform:rotate(12deg)}}
@keyframes cl-head{0%,100%{transform:rotate(0)}30%{transform:rotate(-4deg)}}
@keyframes cl-tail{0%,100%{transform:rotate(-12deg)}50%{transform:rotate(12deg)}}
@keyframes cl-shadow{0%,100%{transform:scale(1);opacity:.32}30%{transform:scale(.6);opacity:.16}55%{transform:scale(1.06);opacity:.34}}

/* ---- CLAP — forearms swing in, hands meet at center front, repeat ---- */
.demo-clap .arm-r{animation:cp-armR 0.62s ease-in-out infinite}
.demo-clap .arm-l{animation:cp-armL 0.62s ease-in-out infinite}
.demo-clap .forearm-r{animation:cp-foreR 0.62s ease-in-out infinite}
.demo-clap .forearm-l{animation:cp-foreL 0.62s ease-in-out infinite}
.demo-clap .hand-r{animation:cp-handR 0.62s ease-in-out infinite}
.demo-clap .hand-l{animation:cp-handL 0.62s ease-in-out infinite}
.demo-clap .head{animation:pr-head 3.4s ease-in-out infinite}
.demo-clap .fox-bob{animation:id-breathe 3.9s ease-in-out infinite}
.demo-clap .fox-shadow{animation:sh-breathe 3.9s ease-in-out infinite}
.demo-clap .tail{animation:id-tail 2.4s ease-in-out infinite}
/* HORIZONTAL clap (Mike 2026-07-15: "more in and out rather than up and down").
   Two-joint move solved so each hand travels LATERALLY at a constant chest height
   (~y235): apart the elbow lifts up-and-out and the forearm folds a touch more;
   together the arm drops near-vertical and the hands meet at centre (x150). The
   upper-arm swing cancels the forearm arc's vertical component, so the dominant
   read is hands converging IN and pulling OUT, not travelling up/down. */
@keyframes cp-armR{0%,100%{transform:rotate(-40deg)}50%{transform:rotate(-3deg)}}
@keyframes cp-armL{0%,100%{transform:rotate(40deg)}50%{transform:rotate(3deg)}}
@keyframes cp-foreR{0%,100%{transform:rotate(102deg)}50%{transform:rotate(80deg)}}
@keyframes cp-foreL{0%,100%{transform:rotate(-102deg)}50%{transform:rotate(-80deg)}}
@keyframes cp-handR{0%,100%{transform:rotate(2deg)}50%{transform:rotate(-6deg)}}
@keyframes cp-handL{0%,100%{transform:rotate(-2deg)}50%{transform:rotate(6deg)}}

/* HIGHFIVE lives up top with the round-6 batch (partner paw + impact). */

/* ---- SKEPTIC / INTRIGUED (C1) — one brow raised, one flat (p-b-skeptic),
   a head tilt toward the raised side, and a slow considering blink. The
   raised brow (.fx-b-l) gets its OWN small idle lift on top of the base
   pose -- proof the two brows now animate independently, not just as a
   matched pair. ---- */
.demo-skeptic .head{animation:sk2-head 3.4s ease-in-out infinite}
.demo-skeptic .fox-pivot{animation:sk2-lean 3.4s ease-in-out infinite}
.demo-skeptic .fox-bob{animation:id-breathe 3.9s ease-in-out infinite}
.demo-skeptic .fox-shadow{animation:sh-breathe 3.9s ease-in-out infinite}
.demo-skeptic .tail{animation:id-tail 2.8s ease-in-out infinite}
.demo-skeptic .fx-b-l{animation:sk2-brow 3.4s ease-in-out infinite}
@keyframes sk2-head{0%,100%{transform:rotate(0)}20%{transform:rotate(-8deg)}70%{transform:rotate(-9deg)}90%{transform:rotate(-3deg)}}
@keyframes sk2-lean{0%,100%{transform:rotate(0)}20%{transform:rotate(-2deg)}70%{transform:rotate(-2deg)}}
/* the single raised brow lifts a touch further, holds, then eases -- driven
   independently of the flat brow on the other side */
@keyframes sk2-brow{0%,14%{transform:translateY(0)}30%{transform:translateY(-1.6px)}68%{transform:translateY(-1.2px)}88%,100%{transform:translateY(0)}}

/* ============================================================
   EYE VOCABULARY (C2 — the headline ask: the eyes carry as much
   personality as the body). Each is its own idle-bodied beat so it can
   be dropped in anywhere idle would go. fx-pupil-l / fx-pupil-r let the
   two eyes move independently (cross-eyed); fx-gaze still moves them
   together (side-eye, eye-roll, blink).
   ============================================================ */
.demo-blink .fox-bob{animation:id-breathe 3.9s ease-in-out infinite}
.demo-blink .fox-shadow{animation:sh-breathe 3.9s ease-in-out infinite}
.demo-blink .fx-pupil-l,.demo-blink .fx-pupil-r{animation:bl-blink 2.4s ease-in-out infinite}
@keyframes bl-blink{0%,40%{transform:scaleY(1)}44%{transform:scaleY(.06)}48%{transform:scaleY(1)}86%{transform:scaleY(1)}90%{transform:scaleY(.06)}94%{transform:scaleY(1)}100%{transform:scaleY(1)}}

/* wide-eyed POP — a startled/delighted eye-widen with a spring overshoot,
   not just a static wide-eye hold (surprised owns the held version) */
.demo-eyepop .head{animation:ep-head 2.2s ease-in-out infinite}
.demo-eyepop .fox-bob{animation:ep-bob 2.2s ease-in-out infinite}
.demo-eyepop .fox-shadow{animation:sh-breathe 3.4s ease-in-out infinite}
.demo-eyepop .fx-pupil-l,.demo-eyepop .fx-pupil-r{animation:ep-eye 2.2s cubic-bezier(.3,0,.6,1) infinite}
@keyframes ep-head{0%,22%{transform:rotate(0)}30%{transform:rotate(-3deg);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}80%{transform:rotate(-1deg)}100%{transform:rotate(0)}}
@keyframes ep-bob{0%,22%{transform:scale(1,1)}30%{transform:scale(.97,1.05)}44%{transform:scale(1,1)}100%{transform:scale(1,1)}}
@keyframes ep-eye{0%,22%{transform:scale(1)}30%{transform:scale(1.55);animation-timing-function:cubic-bezier(.34,1.56,.64,1)}44%{transform:scale(1.3)}80%{transform:scale(1.32)}100%{transform:scale(1)}}

/* narrow / skeptical SQUINT — a slow suspicious clamp-down + hold, distinct
   from the skeptic single-brow beat (this is symmetric, eyes-only) */
.demo-narroweyes .head{animation:nw-head 3.2s ease-in-out infinite}
.demo-narroweyes .fox-pivot{animation:nw-lean 3.2s ease-in-out infinite}
.demo-narroweyes .fox-bob{animation:id-breathe 3.6s ease-in-out infinite}
.demo-narroweyes .fox-shadow{animation:sh-breathe 3.6s ease-in-out infinite}
@keyframes nw-head{0%,100%{transform:rotate(0)}30%,80%{transform:rotate(2deg)}}
@keyframes nw-lean{0%,100%{transform:rotate(0)}30%,80%{transform:rotate(3deg)}}

/* SIDE-EYE — a hard glance to one side WITHOUT turning the head, held,
   caught, then a quick guilty snap back to center */
.demo-sideeye .fox-bob{animation:id-breathe 3.2s ease-in-out infinite}
.demo-sideeye .fox-shadow{animation:sh-breathe 3.2s ease-in-out infinite}
.demo-sideeye .fx-gaze{animation:se-gaze 3.2s cubic-bezier(.4,0,.2,1) infinite}
@keyframes se-gaze{0%,10%{transform:translate(0,0)}22%{transform:translate(11px,1px)}70%{transform:translate(11px,1px)}84%{transform:translate(0,0)}100%{transform:translate(0,0)}}

/* EYE-ROLL — a full circular sweep (up, over, down, around) */
.demo-eyeroll .fox-bob{animation:id-breathe 2.6s ease-in-out infinite}
.demo-eyeroll .fox-shadow{animation:sh-breathe 2.6s ease-in-out infinite}
.demo-eyeroll .fx-gaze{animation:er-gaze 2.6s ease-in-out infinite}
@keyframes er-gaze{
  0%,8%{transform:translate(0,0)}
  20%{transform:translate(-4px,-8px)}
  35%{transform:translate(5px,-9px)}
  50%{transform:translate(9px,-2px)}
  65%{transform:translate(5px,5px)}
  80%{transform:translate(-4px,4px)}
  92%,100%{transform:translate(0,0)}
}

/* CROSS-EYED — each pupil pulls IN toward the nose independently, holds
   for a beat (comedic), then pops back out */
.demo-crosseyed .fox-bob{animation:id-breathe 2.8s ease-in-out infinite}
.demo-crosseyed .fox-shadow{animation:sh-breathe 2.8s ease-in-out infinite}
.demo-crosseyed .fx-pupil-l{animation:cx-pupilL 2.8s cubic-bezier(.4,0,.2,1) infinite}
.demo-crosseyed .fx-pupil-r{animation:cx-pupilR 2.8s cubic-bezier(.4,0,.2,1) infinite}
@keyframes cx-pupilL{0%,14%{transform:translateX(0)}30%{transform:translateX(7px)}74%{transform:translateX(7px)}90%{transform:translateX(0)}}
@keyframes cx-pupilR{0%,14%{transform:translateX(0)}30%{transform:translateX(-7px)}74%{transform:translateX(-7px)}90%{transform:translateX(0)}}

/* CONFUSED move removed (Mike 2026-07-15: "cut entirely"). The `confused` FACE
   state stays in fox-engine.js -- it is still used as a face on other moves,
   e.g. setBeat('think','confused'). Only the standalone Confused MOVE is gone. */

/* ---- SLEEP — very slow breath, head droops, Zzz (drawn as post art) ---- */
.demo-sleep .fox-bob{animation:sl-breathe 5.4s ease-in-out infinite}
.demo-sleep .head{animation:sl-head 5.4s ease-in-out infinite}
.demo-sleep .fox-shadow{animation:sl-shadow 5.4s ease-in-out infinite}
.demo-sleep .tail{animation:sl-tail 6s ease-in-out infinite}
.demo-sleep .arm-r{animation:sl-arm 5.4s ease-in-out infinite}
.demo-sleep .zzz{animation:sl-zzz 3.6s ease-in-out infinite}
@keyframes sl-breathe{0%{transform:translateY(0) scale(1,1)}50%{transform:translateY(-2px) scale(.99,1.02)}100%{transform:translateY(0) scale(1,1)}}
@keyframes sl-head{0%,100%{transform:rotate(10deg)}50%{transform:rotate(13deg)}}
@keyframes sl-tail{0%,100%{transform:rotate(-4deg)}50%{transform:rotate(4deg)}}
@keyframes sl-arm{0%,100%{transform:rotate(2deg)}50%{transform:rotate(4deg)}}
@keyframes sl-shadow{0%,100%{transform:scale(1);opacity:.3}50%{transform:scale(1.03);opacity:.32}}
@keyframes sl-zzz{0%{opacity:0;transform:translate(0,0) scale(.7)}30%{opacity:1}100%{opacity:0;transform:translate(10px,-26px) scale(1.1)}}

/* ============================================================
   TASK / PROP FAMILY — v2. Props are now rig-attached OBJECTS
   (engine grip-r/grip-l/chest) or world objects the hands go TO.
   The arms move the prop by moving the hand/body it's glued to;
   we no longer translate a floating prop to fake a hold.
   ============================================================ */

/* ---- CARRY — a box held at the chest, both hands framing it underneath ---- */
.demo-carry .arm-r{animation:ca-armR 2.2s ease-in-out infinite}
.demo-carry .arm-l{animation:ca-armL 2.2s ease-in-out infinite}
.demo-carry .forearm-r{animation:ca-foreR 2.2s ease-in-out infinite}
.demo-carry .forearm-l{animation:ca-foreL 2.2s ease-in-out infinite}
.demo-carry .fox-bob{animation:ca-bob 2.2s ease-in-out infinite}
.demo-carry .head{animation:wk-head 2.2s ease-in-out infinite}
.demo-carry .fox-shadow{animation:sh-breathe 2.2s ease-in-out infinite}
@keyframes ca-armR{0%,100%{transform:rotate(13deg)}50%{transform:rotate(12deg)}}
@keyframes ca-armL{0%,100%{transform:rotate(-13deg)}50%{transform:rotate(-12deg)}}
@keyframes ca-foreR{0%,100%{transform:rotate(58deg)}50%{transform:rotate(60deg)}}
@keyframes ca-foreL{0%,100%{transform:rotate(-58deg)}50%{transform:rotate(-60deg)}}
@keyframes ca-bob{0%,100%{transform:translateY(0)}25%{transform:translateY(2px)}50%{transform:translateY(-2px)}75%{transform:translateY(2px)}}

/* ---- HANDOFF — TOSSES the box to the viewer. Winds up with the box at the
   chest (grip-r), then releases it at 46% -- it detaches and grows toward
   camera (scale + downward arc), like throw's release but aimed AT you
   instead of across the screen. ---- */
.demo-handoff .arm-r{animation:ho-armR 4s ease-in-out infinite}
.demo-handoff .arm-l{animation:ho-armL 4s ease-in-out infinite}
.demo-handoff .forearm-r{animation:ho-foreR 4s ease-in-out infinite}
.demo-handoff .forearm-l{animation:ho-foreL 4s ease-in-out infinite}
.demo-handoff .fox-pivot{animation:ho-lean 4s ease-in-out infinite}
.demo-handoff .head{animation:ho-head 4s ease-in-out infinite}
.demo-handoff .fox-bob{animation:id-breathe 4s ease-in-out infinite}
.demo-handoff .fox-shadow{animation:sh-breathe 4s ease-in-out infinite}
.demo-handoff .handoff-hold{animation:ho-hold 4s linear infinite}
.demo-handoff .handoff-toss{transform-box:view-box;animation:ho-toss 4s linear infinite}
/* wind up, swing the arm out to release point, then follow through */
@keyframes ho-armR{0%,18%{transform:rotate(13deg)}40%{transform:rotate(-30deg);animation-timing-function:cubic-bezier(.4,0,.7,1)}46%{transform:rotate(-14deg)}82%{transform:rotate(-12deg)}96%,100%{transform:rotate(13deg)}}
@keyframes ho-foreR{0%,18%{transform:rotate(54deg)}40%{transform:rotate(8deg)}46%,82%{transform:rotate(18deg)}96%,100%{transform:rotate(54deg)}}
@keyframes ho-armL{0%,100%{transform:rotate(-11deg)}46%{transform:rotate(-9deg)}}
@keyframes ho-foreL{0%,100%{transform:rotate(-50deg)}46%{transform:rotate(-42deg)}}
@keyframes ho-lean{0%,18%{transform:rotate(0)}40%{transform:rotate(-6deg)}46%,82%{transform:rotate(-3deg)}100%{transform:rotate(0)}}
@keyframes ho-head{0%,100%{transform:rotate(0)}46%{transform:rotate(-3deg)}}
@keyframes ho-hold{0%,40%{opacity:1}40.5%,100%{opacity:0}}
@keyframes ho-toss{
  0%,40%{opacity:0;transform:translate(198px,238px) scale(1)}
  40.5%{opacity:1;transform:translate(198px,238px) scale(1);animation-timing-function:cubic-bezier(.2,.4,.5,1)}
  62%{opacity:1;transform:translate(160px,220px) scale(1.9) rotate(-8deg)}
  82%{opacity:1;transform:translate(120px,180px) scale(3.1) rotate(-14deg)}
  92%{opacity:0;transform:translate(96px,140px) scale(4) rotate(-18deg)}
  100%{opacity:0;transform:translate(96px,140px) scale(4) rotate(-18deg)}
}

/* ---- TYPE — a real keyboard (world), hands travel DOWN onto the keys ---- */
.demo-type .arm-r{animation:ty-armR 2.4s ease-in-out infinite}
.demo-type .arm-l{animation:ty-armL 2.4s ease-in-out infinite}
.demo-type .forearm-r{animation:ty-foreR 2.4s ease-in-out infinite}
.demo-type .forearm-l{animation:ty-foreL 2.4s ease-in-out infinite}
.demo-type .hand-r{animation:ty-handR .32s ease-in-out infinite}
.demo-type .hand-l{animation:ty-handL .32s ease-in-out infinite}
.demo-type .head{animation:ty-head 5s ease-in-out infinite}
.demo-type .fox-pivot{animation:ty-lean 6s ease-in-out infinite}
.demo-type .fox-bob{animation:id-breathe 4.4s ease-in-out infinite}
.demo-type .fox-shadow{animation:sh-breathe 4.4s ease-in-out infinite}
/* arms in + forearms slightly extended so the hands sit low over the keys */
@keyframes ty-armR{0%,100%{transform:rotate(10deg)}}
@keyframes ty-armL{0%,100%{transform:rotate(-10deg)}}
@keyframes ty-foreR{0%,100%{transform:rotate(4deg)}}
@keyframes ty-foreL{0%,100%{transform:rotate(-4deg)}}
@keyframes ty-handR{0%,100%{transform:rotate(4deg)}50%{transform:rotate(-14deg)}}
@keyframes ty-handL{0%,100%{transform:rotate(-14deg)}50%{transform:rotate(4deg)}}
@keyframes ty-head{0%,100%{transform:rotate(6deg)}50%{transform:rotate(4deg)}}
@keyframes ty-lean{0%,100%{transform:rotate(1.5deg)}}

/* ---- READ — ONE-HANDED: LEFT hand holds the page raised to HEAD LEVEL and clear
   of the face; the ELBOW sits BELOW the wrist (upper arm near-vertical, forearm
   rises up to the raised hand -- a natural "holding a page up to read" pose). The
   OTHER (right) arm rests DOWN BY HIS SIDE, not pointing. (Mike 2026-07-15: elbow
   below the wrist; the arm without the page by his side.) The left WRIST
   counter-rotates so the page stays UPRIGHT/readable. Solved against the live rig. */
.demo-read .arm-l{animation:rd-armL 6s ease-in-out infinite}
.demo-read .forearm-l{animation:rd-foreL 6s ease-in-out infinite}
.demo-read .hand-l{animation:rd-handL 6s ease-in-out infinite}
.demo-read .head{animation:rd-head 6s ease-in-out infinite}
.demo-read .fox-bob{animation:id-breathe 4.4s ease-in-out infinite}
.demo-read .fox-shadow{animation:sh-breathe 4.4s ease-in-out infinite}
/* upper arm near-vertical (elbow stays low), forearm folds UP so the wrist/page
   rise to head level ABOVE the elbow; wrist counter-rotates to keep the page
   upright. Right arm carries no read animation -> rests at its side. */
@keyframes rd-armL{0%,100%{transform:rotate(88deg)}50%{transform:rotate(92deg)}}
@keyframes rd-foreL{0%,100%{transform:rotate(143deg)}50%{transform:rotate(147deg)}}
@keyframes rd-handL{0%,100%{transform:rotate(123deg)}50%{transform:rotate(127deg)}}
@keyframes rd-head{0%,100%{transform:rotate(11deg)}22%{transform:rotate(13deg)}70%{transform:rotate(10deg)}}

/* ---- CHECK — holds a clipboard (chest), right hand ticks it, tick draws on ---- */
.demo-check .arm-r{animation:ck-armR 3.2s ease-in-out infinite}
.demo-check .forearm-r{animation:ck-foreR 3.2s ease-in-out infinite}
.demo-check .hand-r{animation:ck-handR 3.2s ease-in-out infinite}
.demo-check .arm-l{animation:ck-armL 3.2s ease-in-out infinite}
.demo-check .forearm-l{animation:ck-foreL 3.2s ease-in-out infinite}
.demo-check .ck-tick{animation:ck-tick 3.2s ease-in-out infinite}
.demo-check .head{animation:nd-head 3.2s ease-in-out infinite}
.demo-check .fox-bob{animation:id-breathe 4.4s ease-in-out infinite}
.demo-check .fox-shadow{animation:sh-breathe 4.4s ease-in-out infinite}
@keyframes ck-armL{0%,100%{transform:rotate(-14deg)}}
@keyframes ck-foreL{0%,100%{transform:rotate(-56deg)}}
@keyframes ck-armR{0%,100%{transform:rotate(22deg)}40%{transform:rotate(26deg)}}
@keyframes ck-foreR{0%,100%{transform:rotate(66deg)}40%{transform:rotate(72deg)}}
@keyframes ck-handR{0%,30%{transform:rotate(0)}40%{transform:rotate(-12deg)}52%{transform:rotate(-5deg)}64%{transform:rotate(-12deg)}80%{transform:rotate(0)}}
/* the tick lives INSIDE the clipboard object now (.ck-tick); it draws on */
@keyframes ck-tick{0%,32%{opacity:0;transform:scale(.3)}44%{opacity:1;transform:scale(1)}92%{opacity:1;transform:scale(1)}100%{opacity:1;transform:scale(1)}}


/* ---- THROW (new) — wind up, whip, the box DETACHES and arcs to the far
   side with gravity. Held copy (grip-r) hides at release; free copy
   (world) appears at release and flies + tumbles down to the far side. ---- */
.demo-throw .fox-pivot{animation:tw-lean 3s ease-in-out infinite}
.demo-throw .arm-r{animation:tw-arm 3s ease-in-out infinite}
.demo-throw .forearm-r{animation:tw-fore 3s ease-in-out infinite}
.demo-throw .hand-r{animation:tw-hand 3s ease-in-out infinite}
.demo-throw .arm-l{animation:id-arml 4.6s ease-in-out infinite}
.demo-throw .head{animation:tw-head 3s ease-in-out infinite}
.demo-throw .fox-bob{animation:id-breathe 3.9s ease-in-out infinite}
.demo-throw .fox-shadow{animation:sh-breathe 3.9s ease-in-out infinite}
.demo-throw .throw-hold{animation:tw-hold 3s linear infinite}
.demo-throw .throw-fly{transform-box:view-box;animation:tw-fly 3s linear infinite}
@keyframes tw-lean{0%,10%{transform:rotate(0)}22%{transform:rotate(8deg)}34%{transform:rotate(-9deg)}50%{transform:rotate(-3deg)}100%{transform:rotate(0)}}
/* cock up-and-back, whip over the top and down across the body */
@keyframes tw-arm{0%,10%{transform:rotate(8deg)}24%{transform:rotate(-155deg);animation-timing-function:cubic-bezier(.5,0,.9,.55)}30%{transform:rotate(-150deg)}34%{transform:rotate(-52deg);animation-timing-function:cubic-bezier(.3,0,.35,1)}42%{transform:rotate(28deg)}56%{transform:rotate(14deg)}100%{transform:rotate(8deg)}}
@keyframes tw-fore{0%,10%{transform:rotate(10deg)}24%{transform:rotate(-38deg)}34%{transform:rotate(-2deg)}42%{transform:rotate(34deg)}100%{transform:rotate(10deg)}}
@keyframes tw-hand{0%,30%{transform:rotate(0)}34%{transform:rotate(-26deg)}42%{transform:rotate(8deg)}100%{transform:rotate(0)}}
@keyframes tw-head{0%,10%{transform:rotate(0)}24%{transform:rotate(-7deg)}34%{transform:rotate(7deg)}50%{transform:rotate(3deg)}100%{transform:rotate(0)}}
/* release at 32% -- mid-swing, where the arm is actually passing through the
   forward throw angle (tw-arm goes -150deg -> -52deg across 30-34%), not at
   34% where the swing has already settled into follow-through */
@keyframes tw-hold{0%,32%{opacity:1}32.5%,100%{opacity:0}}
/* launch up-right from the hand, sail up-and-over CLEAR of the head, then
   gravity down to the far (left) side of the screen, tumbling the whole way */
@keyframes tw-fly{
  0%,32%{opacity:0;transform:translate(214px,182px) scale(.8) rotate(0deg)}
  32.5%{opacity:1;transform:translate(210px,176px) scale(.8) rotate(-20deg);animation-timing-function:cubic-bezier(.2,.5,.55,1)}
  42%{transform:translate(176px,104px) scale(.79) rotate(-120deg)}
  50%{transform:translate(120px,50px) scale(.77) rotate(-210deg);animation-timing-function:cubic-bezier(.4,0,.72,.5)}
  62%{transform:translate(74px,118px) scale(.75) rotate(-320deg)}
  74%{transform:translate(40px,232px) scale(.73) rotate(-420deg);animation-timing-function:cubic-bezier(.55,.15,.82,1)}
  83%{opacity:1;transform:translate(16px,338px) scale(.72) rotate(-486deg)}
  87%,100%{opacity:0;transform:translate(10px,360px) scale(.72) rotate(-500deg)}
}

/* ---- residual post-art origins (still pre/post, not held objects) ---- */
.pt-target{transform-box:fill-box;transform-origin:50% 50%}
.zzz{transform-box:fill-box;transform-origin:50% 100%}
.idea-bulb{transform-box:fill-box;transform-origin:50% 100%}
.demo-idea .idea-bulb{animation:ia-bulb 3.6s ease-in-out infinite}
@keyframes ia-bulb{0%,26%{opacity:0;transform:scale(.4)}36%{opacity:1;transform:scale(1)}84%{opacity:1;transform:scale(1)}92%,100%{opacity:0;transform:scale(.9)}}

/* ============================================================
   CLICK-TO-HOP — a one-shot, in-place, weighty jump triggered by
   INTERACTION (fox-interactive.html), not an entrance like `jump`.
   Full weight arc: anticipation crouch -> explosive launch -> airborne
   tuck+hover -> landing squash -> rebound -> settle. Starts AND ends
   at rest (0%==100%) so the page hands straight back to idle. Single
   iteration, fill:both so it holds the rest pose the instant it ends.
   ============================================================ */
.demo-hop .fox-root  {animation:hop-root  .9s ease-in-out 1 both}
.demo-hop .fox-bob   {animation:hop-bob   .9s ease-in-out 1 both}
.demo-hop .leg-l     {animation:hop-legL  .9s ease-in-out 1 both}
.demo-hop .leg-r     {animation:hop-legR  .9s ease-in-out 1 both}
.demo-hop .shin-l    {animation:hop-shin  .9s ease-in-out 1 both}
.demo-hop .shin-r    {animation:hop-shin  .9s ease-in-out 1 both}
.demo-hop .foot-l    {animation:hop-foot  .9s ease-in-out 1 both}
.demo-hop .foot-r    {animation:hop-foot  .9s ease-in-out 1 both}
.demo-hop .arm-l     {animation:hop-armL  .9s ease-in-out 1 both}
.demo-hop .arm-r     {animation:hop-armR  .9s ease-in-out 1 both}
.demo-hop .tail      {animation:hop-tail  .9s ease-in-out 1 both}
.demo-hop .fox-shadow{animation:hop-shadow .9s ease-in-out 1 both}

/* ---- HOP (D4) — a light, subtle, IN-PLACE double-bounce, distinct from
   Jump's big traveling arc entrance. Two small low bounces (apex ~-4% of
   body height, vs. jump's full arc) with no travel and no big landing
   squash -- buoyant punctuation, not a weighty landing. ---- */
@keyframes hop-root{
  0%,100%{transform:translate(0,0)}
  10% {transform:translate(0,2%)}    /* small crouch */
  22% {transform:translate(0,-4.5%)} /* bounce 1 apex */
  34% {transform:translate(0,1%)}    /* light touch-down */
  44% {transform:translate(0,1.5%)}  /* small crouch 2 */
  56% {transform:translate(0,-3.5%)} /* bounce 2 apex (slightly smaller) */
  68% {transform:translate(0,.6%)}
  80% {transform:translate(0,0)}
}
@keyframes hop-bob{
  0%,100%{transform:scale(1,1)}
  10% {transform:scale(1.04,.96)}
  22% {transform:scale(.97,1.04)}
  34% {transform:scale(1.05,.95)}
  44% {transform:scale(1.03,.97)}
  56% {transform:scale(.98,1.03)}
  68% {transform:scale(1.03,.97)}
  80% {transform:scale(1,1)}
}
@keyframes hop-legR{0%,100%{transform:rotate(0)}10%{transform:rotate(3deg)}22%{transform:rotate(-4deg)}44%{transform:rotate(3deg)}56%{transform:rotate(-3deg)}}
@keyframes hop-legL{0%,100%{transform:rotate(0)}10%{transform:rotate(-3deg)}22%{transform:rotate(4deg)}44%{transform:rotate(-3deg)}56%{transform:rotate(3deg)}}
@keyframes hop-shin{0%,100%{transform:rotate(0)}10%{transform:rotate(-8deg)}22%{transform:rotate(3deg)}44%{transform:rotate(-7deg)}56%{transform:rotate(3deg)}}
@keyframes hop-foot{0%,100%{transform:rotate(0)}22%{transform:rotate(-4deg)}56%{transform:rotate(-3deg)}}
@keyframes hop-armR{0%,100%{transform:rotate(0)}10%{transform:rotate(6deg)}22%{transform:rotate(-10deg)}44%{transform:rotate(5deg)}56%{transform:rotate(-8deg)}}
@keyframes hop-armL{0%,100%{transform:rotate(0)}10%{transform:rotate(-6deg)}22%{transform:rotate(10deg)}44%{transform:rotate(-5deg)}56%{transform:rotate(8deg)}}
@keyframes hop-tail{0%,100%{transform:rotate(0)}10%{transform:rotate(6deg)}22%{transform:rotate(-8deg)}44%{transform:rotate(5deg)}56%{transform:rotate(-6deg)}}
/* ground shadow: two shallow pulses, never fully vanishing (he barely leaves the ground) */
@keyframes hop-shadow{0%,100%{transform:scale(1);opacity:1}10%{transform:scale(1.03);opacity:1}22%{transform:scale(.82);opacity:.7}34%{transform:scale(1.04);opacity:1}56%{transform:scale(.86);opacity:.75}68%{transform:scale(1.02);opacity:1}}


/* ============================================================
   JUMPING JACKS — front-view open/close with a small hop. The easy
   front-view contrast case: legs splay, arms sweep to a Y overhead,
   a hop on each transition. Own bob/shadow/tail (no g-base).
   ============================================================ */
.demo-jumpingjacks .fox-root{animation:jj-jump 1.5s ease-in-out infinite}
.demo-jumpingjacks .fox-bob{animation:jj-bob 1.5s ease-in-out infinite}
.demo-jumpingjacks .fox-shadow{animation:jj-shadow 1.5s ease-in-out infinite}
.demo-jumpingjacks .leg-r{animation:jj-legR 1.5s ease-in-out infinite}
.demo-jumpingjacks .leg-l{animation:jj-legL 1.5s ease-in-out infinite}
.demo-jumpingjacks .shin-r{animation:jj-shinR 1.5s ease-in-out infinite}
.demo-jumpingjacks .shin-l{animation:jj-shinL 1.5s ease-in-out infinite}
.demo-jumpingjacks .arm-r{animation:jj-armR 1.5s ease-in-out infinite}
.demo-jumpingjacks .arm-l{animation:jj-armL 1.5s ease-in-out infinite}
.demo-jumpingjacks .forearm-r{animation:jj-foreR 1.5s ease-in-out infinite}
.demo-jumpingjacks .forearm-l{animation:jj-foreL 1.5s ease-in-out infinite}
.demo-jumpingjacks .head{animation:jj-head 1.5s ease-in-out infinite}
.demo-jumpingjacks .tail{animation:jj-tail 1.5s ease-in-out infinite}
/* hop apex at the 25%/75% transitions; grounded (open/closed) at 0/50/100 */
/* takeoff crouch (8/58%) loads each hop before it leaves the ground */
@keyframes jj-jump{0%{transform:translateY(0)}8%{transform:translateY(4%)}25%{transform:translateY(-13%)}50%{transform:translateY(0)}58%{transform:translateY(4%)}75%{transform:translateY(-13%)}100%{transform:translateY(0)}}
@keyframes jj-bob{0%,50%,100%{transform:scale(1,1)}8%,58%{transform:scale(1.06,.92)}25%,75%{transform:scale(1.02,.97)}44%,94%{transform:scale(1.05,.93)}}
@keyframes jj-shadow{0%,50%,100%{transform:scale(1);opacity:.32}25%,75%{transform:scale(.72);opacity:.18}}
/* feet TOGETHER at 0/100 (rotate toward centre), splayed WIDE at 50%. SVG +rot
   swings a hanging limb toward centre, so foot-out = negative on the right leg. */
/* spread is ~85% open by the hop apex (25/75%), completing on the ground (50%) */
@keyframes jj-legR{0%,100%{transform:rotate(6deg)}25%{transform:rotate(-22deg)}50%{transform:rotate(-28deg)}75%{transform:rotate(-22deg)}}
@keyframes jj-legL{0%,100%{transform:rotate(-6deg)}25%{transform:rotate(22deg)}50%{transform:rotate(28deg)}75%{transform:rotate(22deg)}}
@keyframes jj-shinR{0%,100%{transform:rotate(0)}50%{transform:rotate(-6deg)}}
@keyframes jj-shinL{0%,100%{transform:rotate(0)}50%{transform:rotate(6deg)}}
@keyframes jj-armR{0%,100%{transform:rotate(-6deg)}25%{transform:rotate(-116deg)}50%{transform:rotate(-134deg)}75%{transform:rotate(-116deg)}}
@keyframes jj-armL{0%,100%{transform:rotate(6deg)}25%{transform:rotate(116deg)}50%{transform:rotate(134deg)}75%{transform:rotate(116deg)}}
@keyframes jj-foreR{0%,100%{transform:rotate(0)}50%{transform:rotate(-6deg)}}
@keyframes jj-foreL{0%,100%{transform:rotate(0)}50%{transform:rotate(6deg)}}
/* head lags the hop (peaks after the apex); tail flicks on each landing */
@keyframes jj-head{0%,50%,100%{transform:translateY(0)}30%,80%{transform:translateY(-3%)}}
@keyframes jj-tail{0%,100%{transform:rotate(-4deg)}45%{transform:rotate(8deg)}52%{transform:rotate(-6deg)}64%{transform:rotate(1deg)}95%{transform:rotate(8deg)}}

/* ============================================================
   PUSH-UPS — dedicated SIDE-PROFILE plank (body art = PUSHUPS_BODY in
   fox-engine.js). The fox faces RIGHT in a ~30deg plank; the whole rigid
   body dips at the back-toe pivot and presses back up, while the near
   forearm bends to keep the front paw planted. The front rig can't plank
   (symmetric limbs bunch, hands+toes never share a ground line), so this
   move carries its own profile body + this press loop. Redesigned
   2026-07-15 (Mike: side-on profile, "planked out parallel to the ground").
   Press-pose angles at 50% tuned by live-rig probe (hand stays planted).
   ============================================================ */
.pu-plank{transform-box:view-box;transform-origin:38px 353px}
.pu-uarm{transform-box:view-box;transform-origin:198px 250px}
.pu-fore{transform-box:view-box;transform-origin:210px 303px}
.pu-head{transform-box:view-box;transform-origin:208px 246px}
.pu-tail{transform-box:view-box;transform-origin:104px 292px}
.demo-pushups .pu-plank{animation:pux-dip 2.2s ease-in-out infinite}
.demo-pushups .pu-uarm{animation:pux-uarm 2.2s ease-in-out infinite}
.demo-pushups .pu-fore{animation:pux-fore 2.2s ease-in-out infinite}
.demo-pushups .pu-head{animation:pux-head 2.2s ease-in-out infinite}
.demo-pushups .pu-tail{animation:pux-tail 2.2s ease-in-out infinite}
.demo-pushups .fox-shadow{animation:pux-shadow 2.2s ease-in-out infinite}
/* whole body dips at the toe (front lowers), presses back up */
@keyframes pux-dip{0%,100%{transform:rotate(0deg)}50%{transform:rotate(6deg)}}
/* upper arm lifts the elbow relative to the plank; forearm bends back so the
   planted paw stays put (a real elbow bend, not a slide) */
@keyframes pux-uarm{0%,100%{transform:rotate(0deg)}50%{transform:rotate(-6deg)}}
@keyframes pux-fore{0%,100%{transform:rotate(0deg)}50%{transform:rotate(26deg)}}
/* nose dips toward the floor on the way down; tail counter-sways */
@keyframes pux-head{0%,100%{transform:rotate(0deg)}50%{transform:rotate(4deg)}}
@keyframes pux-tail{0%,100%{transform:rotate(-3deg)}50%{transform:rotate(6deg)}}
@keyframes pux-shadow{0%,100%{transform:translate(-24px,-6px) scaleX(1.9);opacity:.3}50%{transform:translate(-24px,-6px) scaleX(1.9);opacity:.42}}

/* ============================================================
   HANDSTAND — invert onto the hands (hand-balance). The fox flips
   180°, arms extend so the hands plant on the ground (inverted, body-up
   = world-down), legs point up, with a small balance wobble. The cartwheel
   pass showed the rig makes a clean inverted shape; this tests holding it.
   ============================================================ */
.demo-handstand .fox-root{animation:hs-place 3s ease-in-out infinite}
.demo-handstand .fox-pivot{transform-origin:50% 46%;animation:hs-invert 3s ease-in-out infinite}
.demo-handstand .arm-r{animation:hs-armR 3s ease-in-out infinite}
.demo-handstand .arm-l{animation:hs-armL 3s ease-in-out infinite}
.demo-handstand .forearm-r{animation:hs-foreR 3s ease-in-out infinite}
.demo-handstand .forearm-l{animation:hs-foreL 3s ease-in-out infinite}
.demo-handstand .leg-r{animation:hs-legR 3s ease-in-out infinite}
.demo-handstand .leg-l{animation:hs-legL 3s ease-in-out infinite}
.demo-handstand .shin-r{animation:hs-shinR 3s ease-in-out infinite}
.demo-handstand .shin-l{animation:hs-shinL 3s ease-in-out infinite}
.demo-handstand .head{animation:hs-head 3s ease-in-out infinite}
.demo-handstand .fox-shadow{animation:hs-shadow 3s ease-in-out infinite}
/* inverted hold + tiny balance wobble; lower so the planted hands meet ground */
/* off-kilter over-correction (not a clean sine): over-tip then catch back */
@keyframes hs-invert{0%{transform:rotate(179deg)}30%{transform:rotate(187deg)}55%{transform:rotate(176deg)}80%{transform:rotate(183deg)}100%{transform:rotate(179deg)}}
@keyframes hs-place{0%,100%{transform:translateY(11%)}50%{transform:translateY(11%)}}
/* arms extend nearly overhead (body space) so, inverted, the hands plant
   straight down under the head; kept just short of the 180° wrap */
@keyframes hs-armR{0%,100%{transform:rotate(-150deg)}50%{transform:rotate(-154deg)}}
@keyframes hs-armL{0%,100%{transform:rotate(150deg)}50%{transform:rotate(154deg)}}
/* fast fine tremor in the wrists - hands working to hold the balance */
@keyframes hs-foreR{0%{transform:rotate(-11deg)}18%{transform:rotate(-14deg)}36%{transform:rotate(-9deg)}54%{transform:rotate(-13deg)}72%{transform:rotate(-9deg)}90%{transform:rotate(-13deg)}100%{transform:rotate(-11deg)}}
@keyframes hs-foreL{0%{transform:rotate(11deg)}18%{transform:rotate(14deg)}36%{transform:rotate(9deg)}54%{transform:rotate(13deg)}72%{transform:rotate(9deg)}90%{transform:rotate(14deg)}100%{transform:rotate(11deg)}}
/* legs point up, gentle scissor wobble for balance */
/* legs scissor ASYMMETRICALLY (one forward while the other back, swapping) and
   lead the saves - the expressive part of a balance */
@keyframes hs-legR{0%{transform:rotate(-6deg)}35%{transform:rotate(-22deg)}65%{transform:rotate(6deg)}100%{transform:rotate(-6deg)}}
@keyframes hs-legL{0%{transform:rotate(6deg)}35%{transform:rotate(-4deg)}65%{transform:rotate(20deg)}100%{transform:rotate(6deg)}}
@keyframes hs-shinR{0%,100%{transform:rotate(-8deg)}50%{transform:rotate(4deg)}}
@keyframes hs-shinL{0%,100%{transform:rotate(8deg)}50%{transform:rotate(-4deg)}}
@keyframes hs-head{0%,100%{transform:rotate(0)}50%{transform:rotate(3deg)}}
@keyframes hs-shadow{0%{transform:scale(1);opacity:.34}30%{transform:scale(1.03);opacity:.38}55%{transform:scale(.96);opacity:.3}80%{transform:scale(1.02);opacity:.36}100%{transform:scale(1);opacity:.34}}

/* BREAKDANCE move removed entirely (Mike 2026-07-15: "REMOVE entirely", same
   treatment as dragdrop/bowarrow). No demo-breakdance selectors or bd-* keyframes
   remain; the move is gone from fox-moves.json too. */

/* ============================================================
   PUSH — the fox shoves a heavy box to the right. Anticipation (rock
   back + load), DRIVE (lean in, push arm + back leg extend, box slides),
   STRAIN hold, the heavy box resists (slips back a touch), recover.
   Effortful and characterful. Box is a world prop it pushes.
   ============================================================ */
.demo-push .fox-root{animation:ps-root 2.4s ease-in-out infinite}
.demo-push .fox-pivot{transform-origin:50% 82%;animation:ps-lean 2.4s ease-in-out infinite}
.demo-push .fox-bob{animation:ps-bob 2.4s ease-in-out infinite}
.demo-push .arm-r{animation:ps-armR 2.4s ease-in-out infinite}
.demo-push .forearm-r{animation:ps-foreR 2.4s ease-in-out infinite}
.demo-push .hand-r{animation:ps-handR 2.4s ease-in-out infinite}
.demo-push .arm-l{animation:ps-armL 2.4s ease-in-out infinite}
.demo-push .forearm-l{animation:ps-foreL 2.4s ease-in-out infinite}
.demo-push .leg-r{animation:ps-legR 2.4s ease-in-out infinite}
.demo-push .shin-r{animation:ps-shinR 2.4s ease-in-out infinite}
.demo-push .leg-l{animation:ps-legL 2.4s ease-in-out infinite}
.demo-push .shin-l{animation:ps-shinL 2.4s ease-in-out infinite}
.demo-push .head{animation:ps-head 2.4s ease-in-out infinite}
.demo-push .tail{animation:ps-tail 2.4s ease-in-out infinite}
.demo-push .fox-shadow{animation:ps-shadow 2.4s ease-in-out infinite}
/* --ps-contact = THE contact knob: px the box seat is nudged left toward the paw so
   the paw fingertip visibly plants on the box near-face. Bigger = tighter contact,
   smaller = more air. 12 lands the fingertip mid-face. Dial one number to taste. */
.demo-push .ps-box{--ps-contact:12px;transform-box:view-box;transform-origin:0 0;animation:ps-boxslide 2.4s ease-in-out infinite}

/* PUSH v2 — physics-solved. Feet planted APART (rig_kinematics: toe-gap 33->62px,
   provably never crossing); the right paw is FK-solved onto the box near-face
   (contact by construction, not by eye); the box advances ONLY while the paw
   drives it, and the body travels right WITH it. Beats: ready 0, gather/load
   back-left 12-22, DRIVE onto box 45, STRAIN peak 58, creep 70, recover+lift 82. */

/* lean into the box (pivot at the hips, + = lean right); rock back to load first */
@keyframes ps-lean{0%{transform:rotate(2deg)}12%{transform:rotate(-9deg)}22%{transform:rotate(-11deg)}45%{transform:rotate(15deg)}58%{transform:rotate(19deg)}70%{transform:rotate(15deg)}82%{transform:rotate(4deg)}100%{transform:rotate(2deg)}}
/* body advances right with the box on the drive, rocks back a touch on the load */
@keyframes ps-root{0%,100%{transform:translate(0,0)}22%{transform:translate(-1.2%,0)}45%{transform:translate(3%,0.4%)}58%{transform:translate(4.4%,0.6%)}70%{transform:translate(3.6%,0.4%)}82%{transform:translate(1%,0)}}
/* weight: compress on the load, press down on the strain (squash), settle back */
@keyframes ps-bob{0%,100%{transform:scale(1,1)}22%{transform:scale(1.02,.97)}45%{transform:scale(1.03,.97)}58%{transform:scale(1.05,.95)}70%{transform:scale(1.03,.97)}88%{transform:scale(1.005,.995)}}
/* right arm: cocked back on the load, driven down-right onto the box face on the
   push (FK contact arm=-8/fore=-5), then LIFTS OFF on recovery to re-plant each heave */
@keyframes ps-armR{0%{transform:rotate(-6deg)}12%{transform:rotate(2deg)}22%{transform:rotate(5deg)}38%{transform:rotate(-8deg)}45%{transform:rotate(-14deg)}58%{transform:rotate(-16deg)}70%{transform:rotate(-14deg)}78%{transform:rotate(-10deg)}82%{transform:rotate(3deg)}90%{transform:rotate(-2deg)}100%{transform:rotate(-6deg)}}
@keyframes ps-foreR{0%{transform:rotate(14deg)}12%{transform:rotate(40deg)}22%{transform:rotate(48deg)}38%{transform:rotate(14deg)}45%{transform:rotate(4deg)}58%{transform:rotate(2deg)}70%{transform:rotate(4deg)}82%{transform:rotate(34deg)}100%{transform:rotate(14deg)}}
/* paw presses FLAT on the box face through the drive */
@keyframes ps-handR{0%{transform:rotate(-6deg)}45%{transform:rotate(-12deg)}58%{transform:rotate(-14deg)}70%{transform:rotate(-12deg)}82%{transform:rotate(-2deg)}100%{transform:rotate(-6deg)}}
/* off arm (left) trails BACK-left as the counterweight to the rightward drive */
@keyframes ps-armL{0%{transform:rotate(12deg)}22%{transform:rotate(8deg)}45%{transform:rotate(20deg)}58%{transform:rotate(24deg)}78%{transform:rotate(16deg)}100%{transform:rotate(12deg)}}
@keyframes ps-foreL{0%{transform:rotate(-8deg)}45%{transform:rotate(-18deg)}58%{transform:rotate(-20deg)}100%{transform:rotate(-8deg)}}
/* front leg (right) braces near-vertical, knee bends to take weight; back leg
   (left) DRIVES out wide-left and extends (foot planted, pushing the body right) */
@keyframes ps-legR{0%{transform:rotate(2deg)}22%{transform:rotate(6deg)}45%{transform:rotate(-8deg)}58%{transform:rotate(-12deg)}70%{transform:rotate(-9deg)}100%{transform:rotate(2deg)}}
@keyframes ps-shinR{0%{transform:rotate(-2deg)}22%{transform:rotate(-2deg)}45%{transform:rotate(8deg)}58%{transform:rotate(10deg)}70%{transform:rotate(8deg)}100%{transform:rotate(-2deg)}}
@keyframes ps-legL{0%{transform:rotate(4deg)}12%{transform:rotate(2deg)}22%{transform:rotate(0deg)}45%{transform:rotate(22deg)}58%{transform:rotate(28deg)}70%{transform:rotate(24deg)}82%{transform:rotate(12deg)}100%{transform:rotate(4deg)}}
@keyframes ps-shinL{0%{transform:rotate(-2deg)}45%{transform:rotate(-6deg)}58%{transform:rotate(-8deg)}100%{transform:rotate(-2deg)}}
/* head drops to sight the box on the gather, cranes into the effort on the strain */
@keyframes ps-head{0%{transform:rotate(-4deg)}12%{transform:rotate(-9deg)}22%{transform:rotate(-10deg)}45%{transform:rotate(12deg)}58%{transform:rotate(16deg)}70%{transform:rotate(12deg)}82%{transform:rotate(-2deg)}100%{transform:rotate(-4deg)}}
/* tail lags the body and whips through (follow-through overshoot ~68%) */
@keyframes ps-tail{0%{transform:rotate(-6deg)}16%{transform:rotate(-20deg)}45%{transform:rotate(8deg)}58%{transform:rotate(16deg)}68%{transform:rotate(20deg)}80%{transform:rotate(-4deg)}100%{transform:rotate(-6deg)}}
/* shadow grows + darkens as weight drives into the ground on the strain */
@keyframes ps-shadow{0%,100%{transform:scale(1.05);opacity:.34}45%{transform:scale(1.12);opacity:.4}58%{transform:scale(1.16);opacity:.44}82%{transform:scale(1.06);opacity:.34}}
/* box (scale 1.5): RESISTS through the early drive, BREAKS LOOSE ~52%, is driven
   right to +15px at the strain while the paw stays on its face, then HOLDS there
   through the whole contact phase (58-82%). It only eases back to start once the
   paw has LIFTED OFF (82-100%) - so the box no longer springs back WHILE it's being
   pushed (Mike: "the box still jumps back"). A seamless loop still has to return the
   box to start each cycle; moving that reset into the paw-off recovery is the fix. */
@keyframes ps-boxslide{0%{transform:translate(calc(305px - var(--ps-contact,0px)),322px) scale(1.5)}12%{transform:translate(calc(305px - var(--ps-contact,0px)),322px) scale(1.5)}38%{transform:translate(calc(303px - var(--ps-contact,0px)),322px) scale(1.5);animation-timing-function:cubic-bezier(.7,0,.9,.4)}45%{transform:translate(calc(306px - var(--ps-contact,0px)),322px) scale(1.5)}52%{transform:translate(calc(313px - var(--ps-contact,0px)),322px) scale(1.5)}58%{transform:translate(calc(320px - var(--ps-contact,0px)),322px) scale(1.5)}82%{transform:translate(calc(320px - var(--ps-contact,0px)),322px) scale(1.5);animation-timing-function:cubic-bezier(.4,0,.7,1)}90%{transform:translate(calc(314px - var(--ps-contact,0px)),322px) scale(1.5)}100%{transform:translate(calc(305px - var(--ps-contact,0px)),322px) scale(1.5)}}
