/* Living Buddy™ — transform/opacity only. Robotic feel: crisp eased moves with a tiny settle, no cartoon bounce. */
mj-buddy{display:block;position:relative;aspect-ratio:var(--mjb-ar,745/1312);overflow:hidden;--mjb-rx:0deg;--mjb-ry:0deg;--mjb-gx:0px;--mjb-gy:0px;contain:layout paint}
.mjb-stage{position:absolute;inset:0;perspective:1100px}
.mjb-body{position:absolute;transform-origin:50% 38%;transform:rotateX(var(--mjb-rx)) rotateY(var(--mjb-ry));transition:transform .62s cubic-bezier(.2,.9,.25,1.04);will-change:transform}
.mjb-body>img,.mjb-svg,.mjb-sheen{position:absolute;inset:0;width:100%;height:100%;display:block}
/* Visible from the first paint (the approved master is the page's main image); the power-on is a brightening + settle, not a fade from invisible */
.mjb-body>img{object-fit:fill;transform:translateY(10px) scale(.99);filter:brightness(.6) saturate(.85);transition:opacity .25s ease,transform 1.2s cubic-bezier(.2,.8,.2,1),filter 1.2s ease}
.mjb-body>img:not(.mjb-master){opacity:0}
.mjb-ready .mjb-body>img{opacity:1;transform:none;filter:none}
mj-buddy[data-frame=soft] .mjb-body{-webkit-mask-image:radial-gradient(ellipse 50% 50% at 50% 48%,#000 60%,transparent 100%);mask-image:radial-gradient(ellipse 50% 50% at 50% 48%,#000 60%,transparent 100%)}
mj-buddy[crop=face],mj-buddy[crop=bust]{border-radius:inherit}
.mjb-svg{overflow:visible}

/* Breathing: tiny vertical servo drift on the whole robot */
.mjb-stage{animation:mjbBreath 5.6s ease-in-out infinite}
@keyframes mjbBreath{0%,100%{transform:translateY(0)}50%{transform:translateY(-1.1%)}}

/* Lighting: a specular sweep that follows head yaw */
.mjb-sheen{background:linear-gradient(105deg,transparent 30%,rgba(221,214,254,.13) 46%,rgba(255,255,255,.18) 50%,transparent 62%);mix-blend-mode:screen;transform:translateX(calc(var(--mjb-ry) * -2.4));transition:transform .62s cubic-bezier(.2,.9,.25,1.04);pointer-events:none;opacity:.8}

/* Face: power-on, gaze, moods */
.mjb-face{opacity:0;transition:opacity .25s ease}
.mjb-ready[data-face=vector] .mjb-face{opacity:1}
/* exact approved master on top at rest; cleared-visor art beneath for expression moods */
.mjb-body>img.mjb-master{z-index:1}
.mjb-svg,.mjb-sheen{z-index:2}
.mjb-ready[data-face=vector] .mjb-body>img.mjb-master{opacity:0;transition:opacity .25s ease}
.mjb-gaze{transform:translate(var(--mjb-gx),var(--mjb-gy));transition:transform .38s cubic-bezier(.3,1,.4,1)}
.mjb-eye [class^=f-],.mjb-mouth [class^=f-]{opacity:0;transition:opacity .22s ease}
.mjb-blink{transform-box:fill-box;transform-origin:center;transition:transform .07s linear}
.mjb-blinking .mjb-blink{transform:scaleY(.08)}
.mjb-dots,.mjb-sparks{opacity:0;transition:opacity .3s}

/* mood → which features show */
[data-mood=idle] .f-pill,[data-mood=idle] .f-smile,
[data-mood=happy] .f-arc,[data-mood=happy] .f-smile,
[data-mood=wave] .f-arc,[data-mood=wave] .f-smile,
[data-mood=signature] .f-arc,[data-mood=signature] .f-smile,
[data-mood=thinking] .f-pill,[data-mood=thinking] .f-flat,
[data-mood=listening] .f-wide,[data-mood=listening] .f-smile,
[data-mood=speaking] .f-pill,[data-mood=speaking] .f-talk,
[data-mood=celebrate] .f-star,[data-mood=celebrate] .f-smile,
[data-mood=calm] .f-soft,[data-mood=calm] .f-flat,
[data-mood=surprised] .f-ring,[data-mood=surprised] .f-o{opacity:1}
[data-mood=thinking] .mjb-dots,[data-mood=celebrate] .mjb-sparks{opacity:1}
.mjb-dots circle{animation:mjbDot 1.1s ease-in-out infinite}
@keyframes mjbDot{0%,100%{opacity:.25}50%{opacity:1}}
.mjb-sparks path{transform-box:fill-box;transform-origin:center;animation:mjbSpark 1.6s ease-in-out infinite}
.mjb-sparks path:nth-child(2n){animation-delay:.5s}.mjb-sparks path:nth-child(3n){animation-delay:.9s}
@keyframes mjbSpark{0%,100%{opacity:0;scale:.5}50%{opacity:1;scale:1}}
.f-talk{transform-box:fill-box;transform-origin:center;animation:mjbTalk .26s steps(2,end) infinite alternate}
@keyframes mjbTalk{from{transform:scaleY(.35)}to{transform:scaleY(1.15)}}
[data-mood=celebrate] .mjb-eye{animation:mjbPop .5s ease-out}
@keyframes mjbPop{0%{scale:.6}70%{scale:1.12}100%{scale:1}}

/* Emblem glows */
.mjb-chest{opacity:.55;animation:mjbPulse 3.4s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
.mjb-ear{opacity:.35;animation:mjbPulse 4.2s ease-in-out infinite .8s;transform-box:fill-box;transform-origin:center}
[data-mood=speaking] .mjb-ear{animation-duration:.9s;opacity:.6}
[data-mood=celebrate] .mjb-chest{opacity:1;animation-duration:1.2s}
@keyframes mjbPulse{0%,100%{opacity:.35;scale:.94}50%{opacity:.85;scale:1.04}}

/* Wave: a quick robotic nod-tilt when greeting */
[data-mood=wave] .mjb-body{animation:mjbNod 1.4s cubic-bezier(.3,1,.4,1) 1}
@keyframes mjbNod{0%{transform:rotateZ(0)}30%{transform:rotateZ(-2.2deg) translateY(-1%)}60%{transform:rotateZ(1deg)}100%{transform:rotateZ(0)}}

@media (prefers-reduced-motion:reduce){
  .mjb-stage,.mjb-dots circle,.mjb-sparks path,.f-talk,.mjb-chest,.mjb-ear,[data-mood=wave] .mjb-body,[data-mood=celebrate] .mjb-eye{animation:none}
  .mjb-body,.mjb-gaze,.mjb-sheen,.mjb-body>img,.mjb-face{transition:none}
}

/* Real-time 3D Buddy (progressive enhancement): crossfade from the 2D layers once the first frame is ready. */
.mjb3{position:absolute;inset:0 -32%;opacity:0;transition:opacity .9s ease;pointer-events:auto}
mj-buddy.mjb-3d{overflow:visible;contain:layout}
.mjb3 canvas{display:block;width:100%;height:100%;touch-action:pan-y}
.mjb-3d .mjb3{opacity:1}
.mjb-3d .mjb-stage{opacity:0;transition:opacity .9s ease}
mj-buddy.mjb-3d[data-frame=soft]{-webkit-mask-image:none;mask-image:none}

/* Articulated rig: a canvas that re-composes the master part by part (identical at rest, so the crossfade is invisible).
   The rig owns all motion, so the flat whole-image tilt, breathing, sheen and SVG face are switched off underneath it. */
.mjb-body>canvas.mjb-rig{position:absolute;inset:0;width:100%;height:100%;display:block;z-index:3;opacity:0;transition:opacity .3s ease;pointer-events:none}
mj-buddy.mjb-rig-on .mjb-body>canvas.mjb-rig{opacity:1}
mj-buddy.mjb-rig-on .mjb-body{transform:none;transition:none}
mj-buddy.mjb-rig-on .mjb-stage{animation:none}
mj-buddy.mjb-rig-on .mjb-svg,mj-buddy.mjb-rig-on .mjb-sheen{display:none}

/* Characters without a rig: gestures fall back to gentle whole-figure motion (not articulation). */
mj-buddy[data-gesture=nod] .mjb-body{animation:mjbFNod .45s ease-in-out 2}
mj-buddy[data-gesture=shake] .mjb-body{animation:mjbFShake .5s ease-in-out 2}
mj-buddy[data-gesture=tilt] .mjb-body,mj-buddy[data-gesture=shrug] .mjb-body{transform:rotateZ(3deg)}
mj-buddy[data-gesture=lean-in] .mjb-body{transform:scale(1.035) translateY(1%)}
mj-buddy[data-gesture=turn-left] .mjb-body{transform:rotateY(-7deg)}
mj-buddy[data-gesture=turn-right] .mjb-body{transform:rotateY(7deg)}
@keyframes mjbFNod{50%{transform:translateY(1.2%) rotateX(-4deg)}}
@keyframes mjbFShake{25%{transform:rotateY(-6deg)}75%{transform:rotateY(6deg)}}
@media (prefers-reduced-motion:reduce){mj-buddy[data-gesture] .mjb-body{animation:none;transform:none}}
