/* face-keyframes.css — CARTOON expressions for the face (alt) gallery.
   MAXIMUM motion: every visible state stacks motion across all 5 layers
   (.face / .eyes / .eye / .dot / .mouth / .smile / .open) so the face is
   NEVER perfectly still. Co-prime periods make idle loops feel organic.

   Layering:
     state-keyframes.css → overlay / light feedback animations (kept)
     face-keyframes.css  → everything else (loaded LAST, wins on conflict) */

/* === defaults === */
.face            { transform-origin: center center; }
.face .smile     { opacity: 1; transform: scale(1); transform-origin: center center; }
.face .mouth     { transform-origin: center center; }
.face .mouth .open { opacity: 0; }

/* ============ A · System & power ============ */

/* === A1_off — Off === */
.st-A1_off .smile, .st-A1_off .open { opacity: 0; }

/* === A2_wake — it simply APPEARS, like the wake-word perk-up but without the
   startle: a quick squash-and-stretch pop that settles to rest, smiling. === */
@keyframes face-A2-grp {
  0%        { opacity: 0; transform: scale(1, 1) translateY(7px); }
  9%        { opacity: 1; transform: scale(1.09, .93) translateY(2px); }   /* land + squash */
  17%       { transform: scale(.96, 1.08) translateY(-4px); }              /* stretch up */
  25%       { transform: scale(1.03, 1) translateY(-1px); }
  33%, 88%  { opacity: 1; transform: scale(1, 1) translateY(0); }          /* settle + hold */
  97%, 100% { opacity: 0; transform: scale(1, 1) translateY(7px); }
}
.st-A2_wake .face {
  animation: face-A2-grp calc(var(--spd) * 4000ms) cubic-bezier(.3, 1.3, .4, 1) infinite both;
}
/* the eyes + smile just ride the appear (open + smiling) */
.st-A2_wake .eyes { animation: none; }
.st-A2_wake .eye  { animation: none; }
.st-A2_wake .dot  { animation: none; }
.st-A2_wake .smile { animation: none; opacity: 1; }
.st-A2_wake .open { opacity: 0; }

/* === A3_idle — a curious face looking around. ONE choreographed 9s loop drives
   every layer off the SAME timeline so they read as a single performance, not
   competing oscillators: the gaze darts (fast) to a spot and fixates (holds) —
   left, right, up, down — the head leans gently toward where it looks, blinks
   land on the gaze shifts, and a calm breath underlies it all.
   Saccade = tight keyframe gap (fast move); fixation = wide gap (hold);
   the small overshoot-then-settle after each dart is the natural saccade landing. */
@keyframes idleGaze {
  0%, 7% { transform: translate(0, 0); }
  12%    { transform: translate(-17px, 3px); }   /* dart LEFT */
  15%    { transform: translate(-15px, 3px); }   /* settle (saccade landing) */
  29%    { transform: translate(-15px, 4px); }   /* fixate left */
  34%    { transform: translate(15px, 1px); }    /* dart RIGHT */
  37%    { transform: translate(13px, 1px); }    /* settle */
  49%    { transform: translate(13px, 2px); }    /* fixate right */
  54%    { transform: translate(3px, -8px); }    /* glance UP (curious) */
  57%    { transform: translate(2px, -6px); }    /* settle */
  69%    { transform: translate(2px, -6px); }    /* hold up */
  74%    { transform: translate(-7px, 5px); }    /* glance down-left */
  87%    { transform: translate(-7px, 5px); }    /* hold */
  93%    { transform: translate(0, 0); }         /* ease home */
  100%   { transform: translate(0, 0); }
}
.st-A3_idle .eyes {
  animation: idleGaze calc(var(--spd) * 9000ms) cubic-bezier(.45, 0, .25, 1) infinite both;
}
.st-A3_idle .eye { animation: none; }
/* head: calm breath + a gentle lean TOWARD the gaze — same beats as idleGaze */
@keyframes idleHead {
  0%, 7% { transform: scale(1) translate(0, 0) rotate(0); }
  15%    { transform: scale(1.015) translate(-5px, 1px) rotate(-1deg); }   /* lean left */
  29%    { transform: scale(1.025) translate(-5px, 1px) rotate(-1deg); }
  37%    { transform: scale(1.03)  translate(5px, 0)   rotate(1deg); }     /* lean right */
  49%    { transform: scale(1.02)  translate(4px, 0)   rotate(.8deg); }
  57%    { transform: scale(1.04)  translate(1px, -2px) rotate(0); }       /* lift, looking up */
  69%    { transform: scale(1.03)  translate(1px, -2px) rotate(0); }
  74%    { transform: scale(1.02)  translate(-3px, 1px) rotate(-.6deg); }
  87%    { transform: scale(1.02)  translate(-3px, 1px) rotate(-.6deg); }
  93%    { transform: scale(1) translate(0, 0) rotate(0); }
  100%   { transform: scale(1) translate(0, 0) rotate(0); }
}
.st-A3_idle .face {
  animation: idleHead calc(var(--spd) * 9000ms) cubic-bezier(.45, 0, .25, 1) infinite both;
}
/* blinks land ON the gaze shifts (we blink when we change where we look) */
@keyframes idleBlink {
  0%, 10%  { transform: scaleY(1); }
  11.5%    { transform: scaleY(.08); }   /* blink into the left dart */
  13%      { transform: scaleY(1); }
  52%      { transform: scaleY(1); }
  53.5%    { transform: scaleY(.08); }   /* blink into the up-glance */
  55%      { transform: scaleY(1); }
  91%      { transform: scaleY(1); }
  92.5%    { transform: scaleY(.08); }   /* blink on the way home */
  94%      { transform: scaleY(1); }
  100%     { transform: scaleY(1); }
}
.st-A3_idle .dot {
  animation: idleBlink calc(var(--spd) * 9000ms) cubic-bezier(.3, 0, .3, 1) infinite both;
}
/* the mouth drifts WITH the gaze (smaller), so the whole face turns together */
@keyframes idleMouth {
  0%, 7% { transform: translate(0, 0); }
  15%    { transform: translate(-7px, 1px); }
  29%    { transform: translate(-7px, 1px); }
  37%    { transform: translate(6px, 0); }
  49%    { transform: translate(6px, 0); }
  57%    { transform: translate(1px, 1px); }
  69%    { transform: translate(1px, 1px); }
  74%    { transform: translate(-3px, 1px); }
  87%    { transform: translate(-3px, 1px); }
  93%    { transform: translate(0, 0); }
  100%   { transform: translate(0, 0); }
}
.st-A3_idle .mouth {
  animation: idleMouth calc(var(--spd) * 9000ms) cubic-bezier(.45, 0, .25, 1) infinite both;
}
/* calm relaxed smile breath on the same loop */
@keyframes idleSmile {
  0%   { transform: scale(1) translateY(0); }
  50%  { transform: scale(1.04) translateY(-1px); }
  100% { transform: scale(1) translateY(0); }
}
.st-A3_idle .smile {
  animation: idleSmile calc(var(--spd) * 9000ms) ease-in-out infinite both;
}
/* gentle breath for the JS-driven idle face (face.js applies this to .face) */
@keyframes idleBreath {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.04); }
}

/* === A4_clock — fluid hand-off: the face fades out while the clock fades in (and
   back when leaving), like the reminder's eyes-fade morph rather than a hard swap === */
.st-A4_clock .face  { opacity: 0; }            /* fades out (transition on .face) */
.st-A4_clock .eyes  { display: flex; }         /* cancel state-keyframes' display:none so it fades, not snaps */
.st-A4_clock .clock { opacity: 1; }            /* fades in over the face */

/* ============ B · Conversation turn-taking ============ */

/* === B1_speaking — big head bob, eyes squint with bigs, mouth phonemes === */
@keyframes face-B1-grp {
  0%   { transform: scale(1)   translateY(0)   rotate(0); }
  7%   { transform: scale(1.07) translateY(-5px) rotate(.8deg); }
  13%  { transform: scale(1.02) translateY(-1px) rotate(0); }
  21%  { transform: scale(1.1)  translateY(-7px) rotate(-1deg); }
  28%  { transform: scale(1.03) translateY(-2px) rotate(0); }
  36%  { transform: scale(1.08) translateY(-5px) rotate(.6deg); }
  44%  { transform: scale(1.02) translateY(-1px) rotate(0); }
  52%  { transform: scale(1.12) translateY(-8px) rotate(-.8deg); }
  60%  { transform: scale(1.04) translateY(-2px) rotate(0); }
  68%  { transform: scale(1.09) translateY(-6px) rotate(.6deg); }
  76%  { transform: scale(1.03) translateY(-2px) rotate(0); }
  84%  { transform: scale(1.08) translateY(-5px) rotate(-.6deg); }
  92%  { transform: scale(1.04) translateY(-2px) rotate(0); }
  100% { transform: scale(1)   translateY(0)   rotate(0); }
}
/* occasional head turn left/right while speaking — on the `rotate` property (independent
   of the bob's `transform`), on a co-prime period so it reads as casual/random */
@keyframes face-B1-turn {
  0%, 16%   { rotate: 0deg; }
  24%, 36%  { rotate: 6deg; }    /* turn a little right, hold */
  44%, 58%  { rotate: 0deg; }
  66%, 78%  { rotate: -6deg; }   /* turn a little left, hold */
  86%, 100% { rotate: 0deg; }
}
.st-B1_speaking .face {
  animation: face-B1-grp calc(var(--spd) * 3400ms) ease-in-out infinite both,
             face-B1-turn calc(var(--spd) * 8700ms) ease-in-out infinite both;
}
.st-B1_speaking .eyes { animation: none; }
@keyframes face-B1-dot {         /* eyes squint slightly on the biggest beats */
  0%, 6%  { transform: scaleY(1); }
  8%      { transform: scaleY(.7); }
  10%     { transform: scaleY(1); }
  20%     { transform: scaleY(1); }
  22%     { transform: scaleY(.55); }   /* "AAH" squint */
  24%     { transform: scaleY(1); }
  51%     { transform: scaleY(1); }
  53%     { transform: scaleY(.5); }    /* "OOH" squint */
  55%     { transform: scaleY(1); }
  68%     { transform: scaleY(1); }
  69%     { transform: scaleY(.07); }   /* mid-speech blink */
  70.5%   { transform: scaleY(1); }
  100%    { transform: scaleY(1); }
}
.st-B1_speaking .dot {
  animation: face-B1-dot calc(var(--spd) * 3400ms) cubic-bezier(.4, 0, .6, 1) infinite both;
}
@keyframes face-B1-smile-hide { 0%, 100% { opacity: 0; } }
@keyframes face-B1-open {        /* a calm talking mouth: ~5 open/close beats per cycle
                                    (not frantic), vowels open wide/tall between closes */
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(.55, .2); }   /* closed */
  9%   { transform: translate(-50%, -47%) scale(1.05, .88); }             /* open */
  18%  { transform: translate(-50%, -50%) scale(.55, .22); }              /* close */
  27%  { transform: translate(-50%, -46%) scale(.9, 1.05); }              /* tall OOH */
  36%  { transform: translate(-50%, -50%) scale(.55, .2); }               /* close */
  45%  { transform: translate(-50%, -46%) scale(1.18, .8); }              /* wide AAH */
  54%  { transform: translate(-50%, -50%) scale(.55, .22); }              /* close */
  63%  { transform: translate(-50%, -47%) scale(.95, .92); }              /* open */
  72%  { transform: translate(-50%, -50%) scale(.55, .2); }               /* close */
  81%  { transform: translate(-50%, -48%) scale(.85, .62); }              /* small open, trailing */
  90%  { transform: translate(-50%, -50%) scale(.55, .22); }              /* close */
  100% { opacity: 1; transform: translate(-50%, -50%) scale(.55, .2); }   /* shut */
}
.st-B1_speaking .smile {
  animation: face-B1-smile-hide calc(var(--spd) * 3800ms) infinite both;
}
.st-B1_speaking .open {
  animation: face-B1-open calc(var(--spd) * 3800ms) cubic-bezier(.3, 0, .4, 1) infinite both;
}

/* === B2_listening — alert, eyes at NORMAL size. Over a long cycle it does two
   "I'm with you" things, once each, not constantly: a NOD (whole face down/up,
   smooth, no bounce) and then a curious HEAD-TILT to the right (held, then back). === */
@keyframes face-B2-grp {
  0%   { transform: translateY(0) rotate(0); }
  16%  { transform: translateY(0) rotate(0); }
  22%  { transform: translateY(14px) rotate(0); }      /* nod down (whole face) */
  29%  { transform: translateY(0) rotate(0); }          /* up */
  34%  { transform: translateY(12px) rotate(0); }       /* down again */
  41%  { transform: translateY(0) rotate(0); }          /* up */
  54%  { transform: translateY(0) rotate(9deg); }       /* tilt head to the right */
  72%  { transform: translateY(0) rotate(9deg); }       /* hold the curious tilt */
  86%  { transform: translateY(0) rotate(0); }          /* back upright */
  100% { transform: translateY(0) rotate(0); }
}
/* listening lifts the face up (room for the notepad) — applied via JS inline `top`
   in face.js (applyFeatured); the `top` transition on .face eases it back fluidly. */
.st-B2_listening .face {
  animation: face-B2-grp calc(var(--spd) * 7000ms) ease-in-out infinite both;
}
.st-B2_listening .eyes { animation: none; transform: scale(1); }
@keyframes face-B2-dot {
  0%, 54% { transform: scaleY(1); }      /* eyes rest at normal size */
  54.8%   { transform: scaleY(.07); }    /* rare crisp blink */
  55.6%   { transform: scaleY(1); }
  100%    { transform: scaleY(1); }
}
.st-B2_listening .dot {
  animation: face-B2-dot calc(var(--spd) * 9000ms) cubic-bezier(.4, 0, .6, 1) infinite both;
}
@keyframes face-B2-mouth {
  0%, 100% { transform: translateY(0); }
  33%      { transform: translateY(-2px); }
  66%      { transform: translateY(2px); }
}
.st-B2_listening .mouth {
  animation: face-B2-mouth calc(var(--spd) * 2900ms) ease-in-out infinite both;
}
@keyframes face-B2-smile {
  0%, 100% { transform: scale(.78); }
  50%      { transform: scale(.84) translateY(1px); }
}
.st-B2_listening .smile {
  animation: face-B2-smile calc(var(--spd) * 2900ms) ease-in-out infinite both;
}

/* === B3_thinking — pondering: head tilts both ways, eyes scan, mouth purses === */
@keyframes face-B3-grp {
  0%   { transform: rotate(0) translate(0, 0); }
  15%  { transform: rotate(-11deg) translate(7px, -4px); }
  30%  { transform: rotate(-10deg) translate(8px, -4px); }   /* hold left tilt */
  50%  { transform: rotate(0) translate(0, -2px); }          /* through center */
  65%  { transform: rotate(8deg) translate(-6px, -3px); }    /* swing other way */
  80%  { transform: rotate(7deg) translate(-6px, -3px); }
  100% { transform: rotate(0) translate(0, 0); }
}
.st-B3_thinking .face {
  animation: face-B3-grp calc(var(--spd) * 2000ms) cubic-bezier(.4, 0, .2, 1) infinite both;
}
.st-B3_thinking .eyes { animation: none; }
/* thinking: a true ARC OF A CIRCLE with a CONSTANT RADIUS (same circle: centre 100,-12,
   r=90, bottom fixed at y=78). The arc EXTENDS and RETRACTS along that circle — its
   endpoints slide out/in so the span grows and shrinks, but the curvature never changes.
   Morphs because every keyframe is `M .. A 90 90 0 0 1 .. ..` (same structure). */
.st-B3_thinking .mouth { animation: none; }
.st-B3_thinking .smile { animation: none; }
@keyframes face-B3-arc {
  0%   { d: path("M36.4 51.6 A 90 90 0 0 0 163.6 51.6"); }   /* medium span */
  35%  { d: path("M22.1 33 A 90 90 0 0 0 177.9 33"); }       /* extends (longer arc) */
  70%  { d: path("M55 65.9 A 90 90 0 0 0 145 65.9"); }       /* retracts (shorter arc) */
  100% { d: path("M36.4 51.6 A 90 90 0 0 0 163.6 51.6"); }
}
.st-B3_thinking .smile path {
  animation: face-B3-arc calc(var(--spd) * 2400ms) ease-in-out infinite both;
}

/* ============ C · Feedback & confirmation ============ */

/* === C1_confirm — like the reminder: the face is gently "sucked in", the check
   appears in its place, holds, then the face snaps back smoothly (no jarring pop) === */
@keyframes face-C1-grp {
  0%   { transform: scale(1); }
  12%  { transform: scale(.55); }      /* sucked in (anticipation) — the check appears */
  80%  { transform: scale(.55); }      /* hold while the check shows */
  90%  { transform: scale(1.1); }      /* snap back, slight overshoot */
  96%  { transform: scale(.98); }
  100% { transform: scale(1); }        /* settle at normal — no loop jump */
}
.st-C1_confirm .face {
  animation: face-C1-grp calc(var(--spd) * 2400ms) cubic-bezier(.4, 0, .2, 1) infinite both;
}
.st-C1_confirm .eyes { animation: none; }
@keyframes face-C1-dot {
  0%   { opacity: 1; transform: scale(1); }
  12%  { opacity: 0; transform: scale(.5); }     /* eyes fade while the check shows */
  80%  { opacity: 0; transform: scale(.5); }
  90%  { opacity: 1; transform: scale(1.1); }    /* fade back with the face */
  96%  { transform: scale(.98); }
  100% { opacity: 1; transform: scale(1); }
}
.st-C1_confirm .dot {
  animation: face-C1-dot calc(var(--spd) * 2400ms) cubic-bezier(.4, 0, .2, 1) infinite both;
}
@keyframes face-C1-smile {
  0%   { opacity: 1; transform: scale(1); }
  12%  { opacity: 0; transform: scale(.5); }
  80%  { opacity: 0; transform: scale(.5); }
  90%  { opacity: 1; transform: scale(1.1); }    /* return, slight overshoot */
  96%  { transform: scale(.98); }
  100% { opacity: 1; transform: scale(1); }       /* settle at normal */
}
.st-C1_confirm .smile {
  animation: face-C1-smile calc(var(--spd) * 2400ms) cubic-bezier(.4, 0, .2, 1) infinite both;
}

/* === C2_didnt_catch — confused: bigger wobble, eyes tilt, mouth shakes === */
@keyframes face-C2-grp {
  0%   { transform: rotate(0) translateY(0); }
  3%   { transform: rotate(-11deg) translateY(2px); }
  6%   { transform: rotate(9deg) translateY(-1px); }
  9%   { transform: rotate(-7deg) translateY(2px); }
  12%  { transform: rotate(5deg) translateY(-1px); }
  17%  { transform: rotate(0) translateY(0); }
  100% { transform: rotate(0) translateY(0); }
}
.st-C2_didnt_catch .face {
  animation: face-C2-grp calc(var(--spd) * 1800ms) cubic-bezier(.4, .2, .3, 1) infinite both;
}
/* eyes unchanged for "wrong" — just speed them up to match the quicker animation */
.st-C2_didnt_catch .eye,
.st-C2_didnt_catch .eye .dot { animation-duration: calc(var(--spd) * 1800ms); }
/* the mouth starts as a SMILE, quickly curls into the wavy "confused" line (like the
   dizzy emoji), talks briefly, then snaps right back to the smile. Both shapes share
   the same M + 3×Q structure so the CSS `d` morph is smooth. */
@keyframes face-C2-mouthD {
  0%, 8%    { d: path("M26 28 Q 50 70 76 78 Q 100 84 124 78 Q 150 70 174 28"); }   /* smile */
  22%, 34%  { d: path("M26 44 Q 50 22 76 44 Q 100 66 124 44 Q 150 24 174 44"); }   /* curls (wavy), briefly */
  48%, 100% { d: path("M26 28 Q 50 70 76 78 Q 100 84 124 78 Q 150 70 174 28"); }   /* back to smiling right away */
}
.st-C2_didnt_catch .smile path {
  animation: face-C2-mouthD calc(var(--spd) * 1800ms) ease-in-out infinite both;
}
@keyframes face-C2-smile {       /* quick talking pulse while the mouth is wavy */
  0%, 12%  { transform: scaleY(1); }
  22%      { transform: scaleY(1.5); }
  30%      { transform: scaleY(.85); }
  38%      { transform: scaleY(1.4); }
  46%, 100% { transform: scaleY(1); }
}
.st-C2_didnt_catch .smile {
  animation: face-C2-smile calc(var(--spd) * 1800ms) ease-in-out infinite both;
}

/* ============ D · Proactive moments ============ */

/* === D1_reminder — anticipation tremble → bell pops → snap back smiling === */
@keyframes face-D1-grp {
  0%   { transform: scale(1) rotate(0); }
  6%   { transform: scale(.6) rotate(0); }              /* sucked in */
  20%  { transform: scale(.6) rotate(-2deg); }          /* tremble */
  30%  { transform: scale(.62) rotate(2deg); }
  40%  { transform: scale(.6) rotate(-2deg); }
  50%  { transform: scale(.62) rotate(2deg); }
  60%  { transform: scale(.6) rotate(-2deg); }
  70%  { transform: scale(.6) rotate(2deg); }
  82%  { transform: scale(.6) rotate(0); }
  90%  { transform: scale(1.22) rotate(0); }            /* snap back overshoot */
  96%  { transform: scale(.96); }
  100% { transform: scale(1); }
}
.st-D1_reminder .face {
  animation: face-D1-grp calc(var(--spd) * 3200ms) cubic-bezier(.4, 1.6, .4, 1) infinite both;
}
@keyframes face-D1-smile {
  0%   { opacity: 1; transform: scale(1); }
  12%  { opacity: 0; transform: scale(.5); }
  82%  { opacity: 0; transform: scale(.5); }
  92%  { opacity: 1; transform: scale(1.25); }
  100% { opacity: 1; transform: scale(1); }
}
.st-D1_reminder .smile {
  animation: face-D1-smile calc(var(--spd) * 3200ms) cubic-bezier(.4, 1.6, .4, 1) infinite both;
}

/* === D2_wakeword — attentive perk-up (gentle, not a fright): small squash → modest
   lift → settle. Eyes widen only a little, mouth makes a small "o". === */
@keyframes face-D2-grp {
  0%   { transform: scale(1, 1) translateY(0); }
  4%   { transform: scale(1.1, .9) translateY(0); }            /* gentle squash */
  11%  { transform: scale(.94, 1.14) translateY(-6px); }       /* modest lift */
  18%  { transform: scale(1.05, 1.03) translateY(-2px); }
  26%  { transform: scale(1.07, 1.07) translateY(-4px); }
  86%  { transform: scale(1.07, 1.07) translateY(-4px); }
  94%  { transform: scale(1.05, 1.02) translateY(-1px); }
  100% { transform: scale(1, 1) translateY(0); }
}
.st-D2_wakeword .face {
  animation: face-D2-grp calc(var(--spd) * 3400ms) cubic-bezier(.22, 1.6, .36, 1) infinite both;
}
.st-D2_wakeword .eyes { animation: none; }
@keyframes face-D2-dot {
  0%   { transform: scale(1); }
  10%  { transform: scale(1.15); }      /* eyes widen only a little */
  18%  { transform: scale(1.04); }
  25%  { transform: scale(1.08); }
  86%  { transform: scale(1.08); }
  100% { transform: scale(1); }
}
.st-D2_wakeword .dot {
  animation: face-D2-dot calc(var(--spd) * 3400ms) cubic-bezier(.22, 1.6, .36, 1) infinite both;
}
@keyframes face-D2-open {        /* a small surprised "o", then it gives way to the smile */
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.35); }
  8%   { opacity: 1; transform: translate(-50%, -50%) scale(.8); }    /* small "o" */
  14%  { opacity: 1; transform: translate(-50%, -50%) scale(.65); }
  22%  { opacity: 0; transform: translate(-50%, -50%) scale(.4); }    /* fades fast */
  100% { opacity: 0; }
}
.st-D2_wakeword .open {
  animation: face-D2-open calc(var(--spd) * 3400ms) cubic-bezier(.22, 1.6, .36, 1) infinite both;
}
@keyframes face-D2-smile {       /* smile blooms in right after the surprise — no delay */
  0%, 16% { opacity: 0; transform: scale(.5); }
  26%     { opacity: 1; transform: scale(1.18); }   /* pops in immediately */
  34%     { transform: scale(1); }
  100%    { opacity: 1; transform: scale(1); }
}
.st-D2_wakeword .smile {
  animation: face-D2-smile calc(var(--spd) * 3400ms) cubic-bezier(.34, 1.5, .4, 1) infinite both;
}

/* ============ E · Personality ============ */

/* === E2_quirk — big head turn left + tiny shake → turn right + shake → snap back === */
@keyframes face-E2-grp {
  0%   { transform: rotate(0) translate(0, 0); }
  8%   { transform: rotate(-16deg) translate(-9px, 3px); }
  12%  { transform: rotate(-15deg) translate(-10px, 4px); }       /* tiny shake */
  16%  { transform: rotate(-17deg) translate(-9px, 3px); }
  21%  { transform: rotate(16deg) translate(9px, -3px); }
  25%  { transform: rotate(15deg) translate(10px, -4px); }
  29%  { transform: rotate(17deg) translate(9px, -3px); }
  35%  { transform: rotate(0) translate(0, 0); }
  100% { transform: rotate(0) translate(0, 0); }
}
.st-E2_quirk .face {
  animation: face-E2-grp calc(var(--spd) * 4200ms) cubic-bezier(.4, 0, .2, 1) infinite both;
}
.st-E2_quirk .eyes { animation: none; }

/* === E4_wink — playful nod + smile lift; eyes do the wink === */
@keyframes face-E4-grp {
  0%   { transform: rotate(0) translateY(0); }
  18%  { transform: rotate(6deg) translateY(-3px); }
  46%  { transform: rotate(6deg) translateY(-3px); }
  56%  { transform: rotate(0) translateY(0); }
  100% { transform: rotate(0) translateY(0); }
}
.st-E4_wink .face {
  animation: face-E4-grp calc(var(--spd) * 2600ms) cubic-bezier(.4, 0, .35, 1) infinite both;
}
@keyframes face-E4-smile {
  0%, 14% { transform: scale(1); }
  20%     { transform: scale(1.18) skewY(-5deg); }
  46%     { transform: scale(1.18) skewY(-5deg); }
  56%     { transform: scale(1); }
  100%    { transform: scale(1); }
}
.st-E4_wink .smile {
  animation: face-E4-smile calc(var(--spd) * 2600ms) cubic-bezier(.4, 0, .35, 1) infinite both;
}
