/* Mascots: painted poses in three frames (full body, bust, small head), plus their acting. Motion is transform only, plus one brightness flash:
   the span acts (pop, hop, flash, chomp, shake, tilt, bob, hello sway), the image breathes; a pose swap is a cut (chars.js).
   needs: tokens.css (--shade, --ease-out, --ease-in-out); provides: .chr, .chr-art */
.chr{position:relative;display:block;width:100%;height:100%;isolation:isolate;transform-origin:50% 100%;
  transition:translate 160ms var(--ease-in-out),rotate 300ms var(--ease-out)}
.chr-art{position:absolute;max-width:none;pointer-events:none;user-select:none;-webkit-user-select:none;-webkit-user-drag:none;
  transform-origin:50% 100%}

/* full: the whole body, feet on a soft contact shadow */
.chr.v-full .chr-art{inset:0 0 3%;width:100%;height:97%;object-fit:contain;object-position:50% 100%}
.chr.v-full::before{content:"";position:absolute;z-index:-1;left:50%;bottom:0;height:7%;aspect-ratio:6;translate:-50% 0;border-radius:50%;
  background:radial-gradient(closest-side,rgb(var(--shade)/.34),rgb(var(--shade)/.12) 60%,transparent)}
/* bust and small head: framed on the head of each image, so it keeps its place and size from pose to pose. --hx is the head's
   centre across the image, --hy its top and --hh its height (ear tips to chin), as shares of the image, and --hk the image height
   as a share of the frame: all set inline per image from ART.head (chars.js). The head fills --hs of a bust (76% at most, less
   for a wide head so its ears stay inside a round frame), its top 3% down plus half of what a smaller head leaves free, lowered by
   --ho when tufts, glasses or a hat rise above that, so nothing clips. A small head is the same frame at 80/76 scale from 9% down */
.chr:is(.v-bust,.lod-s){overflow:hidden}
.chr:is(.v-bust,.lod-s) .chr-art{--hs:calc(var(--hk) * var(--hh));left:50%;width:auto;translate:calc(var(--hx) * -100%) 0;
  top:calc(max(3% + (.76 - var(--hs)) * 50%, var(--ho) * var(--hs) * 100%) - var(--hy) * var(--hk) * 100%);height:calc(var(--hk) * 100%)}
.chr.v-bust{-webkit-mask-image:linear-gradient(#000 72%,transparent 97%);mask-image:linear-gradient(#000 72%,transparent 97%)} /* the crop melts away instead of ending on a hard line */
.chr.lod-s{border-radius:50%;background:radial-gradient(circle at 50% 40%,var(--paper),var(--paper-2))}
.chr.lod-s .chr-art{top:calc(max(9% + (.76 - var(--hs)) * 50% * 80 / 76, var(--ho) * var(--hs) * 80% / .76) - var(--hy) * var(--hk) * 80% / .76);
  height:calc(var(--hk) * 80% / .76)}
.chr{--hx:.55;--hy:0;--hh:.46;--hk:1.652;--ho:0}

/* acting, one beat per mood: happy pops once, cheer hops twice, wow swells with a flash of light, eat chomps, a slip shakes,
   think tilts, talk bobs in time with the voice. The pop stretches at the top and falls with gravity into a squash */
.chr[data-mood="happy"]{animation:chrPop 380ms var(--ease-out)}
.chr[data-mood="cheer"]{animation:chrPop 300ms var(--ease-out) 2}
@keyframes chrPop{40%{translate:0 max(-14px,-10%);scale:.98 1.04;animation-timing-function:cubic-bezier(.11,0,.5,0)}72%{translate:0 0;scale:1.05 .95}}
.chr[data-mood="wow"]{animation:chrWow 420ms var(--ease-out)}
@keyframes chrWow{30%{scale:1.12;filter:brightness(1.15)}60%{scale:.98;filter:brightness(1)}}
.chr[data-mood="eat"]{animation:chrChomp 120ms var(--ease-in-out) 2}
@keyframes chrChomp{30%{scale:1.08 .9}60%{scale:.96 1.05}}
.chr:is([data-mood="oops"],[data-mood="sad"]){animation:chrShake 340ms var(--ease-out)}
@keyframes chrShake{20%{translate:-4px 0;rotate:-2deg}45%{translate:4px 0;rotate:2deg}70%{translate:-2px 0;rotate:-1deg}}
.chr[data-mood="think"]{rotate:-4deg}
.chr[data-mood="talk"]{animation:chrTalk 340ms var(--ease-in-out) infinite alternate} /* a soft bob in time with the voice */
@keyframes chrTalk{to{translate:0 max(-3px,-2%)}}
.chr[data-mood="wave"]{animation:chrHello 900ms var(--ease-in-out)}
@keyframes chrHello{25%{rotate:-4deg}55%{rotate:3deg}80%{rotate:-1deg}}

/* idle life: breathing only on the big hero holders, never on the play face or small avatars */
:is(#hero-char,#wd-preview,#r-face,#w-face) .chr-art{animation:chrBreathe 3.2s ease-in-out infinite}
@keyframes chrBreathe{50%{scale:1 1.015}}
@media (prefers-reduced-motion:reduce){.chr,.chr-art{animation:none !important}.chr{transition:none;translate:none;rotate:none}}
body.bg-paused :is(.chr,.chr-art){animation-play-state:paused}
