/* global React */
/*
* LunaMascot — SVG mascot
* props:
* state: 'idle' | 'happy' | 'sleep' | 'think' | 'angry' | 'focus'
* look: 'center' | 'left' | 'right'
* size: number (px width)
* talk: bool — adds a subtle scale pulse
*/
const { useEffect, useState, useRef } = React;
function LunaMascot({ state = 'idle', look = 'center', size = 280, talk = false, idleAnim = true }) {
// built-in idle look cycle (frontal → left → right) so the mascot feels alive
const [autoLook, setAutoLook] = useState('center');
useEffect(() => {
if (!idleAnim) return;
const sequence = ['center', 'center', 'left', 'center', 'right', 'center'];
let i = 0;
const t = setInterval(() => {
setAutoLook(sequence[i % sequence.length]);
i += 1;
}, 1600);
return () => clearInterval(t);
}, [idleAnim]);
const lookDir = look === 'center' && idleAnim ? autoLook : look;
const lookX = lookDir === 'left' ? -4 : lookDir === 'right' ? 4 : 0;
const lookY = state === 'think' ? -3 : 0;
// pupil scaling for blink/sleep
const eyeOpen = state !== 'sleep';
// mouth path varies with state
let mouth = null;
if (state === 'happy') {
mouth = ;
} else if (state === 'angry') {
mouth = ;
} else if (state === 'think') {
mouth = ;
} else if (state === 'sleep') {
mouth = ;
}
// eyebrows for emotional states
let brows = null;
if (state === 'angry') {
brows = (
);
} else if (state === 'think') {
brows = (
);
}
// accessory above (zZ, ?, !)
let accessory = null;
if (state === 'sleep') {
accessory = (
z
Z
);
} else if (state === 'think') {
accessory = (
?
?
?
);
} else if (state === 'angry') {
accessory = (
!
!
!
);
} else if (state === 'happy') {
accessory = (
✓
);
}
const pulseClass = talk ? 'luna-talk' : '';
return (
);
}
window.LunaMascot = LunaMascot;