/* =========================================================================
   LIFE OS — creatures.jsx
   Hand-built animated SVG sprites. One <CreatureSprite emo mood size/>.
   Bodies keyed by emo.body; faces react to mood. Also exports tiny shared
   UI atoms (Meter, Coin) and a moodFromCare() helper.
   ========================================================================= */
(function () {
  const { useEffect } = React;

  // inject creature animation keyframes once
  if (!document.getElementById('creature-anim')) {
    const s = document.createElement('style');
    s.id = 'creature-anim';
    s.textContent = `
    .csprite{display:inline-block;will-change:transform}
    .csprite.bob{animation:cbob 2.6s ease-in-out infinite}
    .csprite.bob.b1{animation-duration:2.1s}.csprite.bob.b2{animation-duration:3.1s}
    @keyframes cbob{0%,100%{transform:translateY(0) rotate(-1.5deg)}50%{transform:translateY(-7%) rotate(1.5deg)}}
    .csprite.jit{animation:cjit .16s steps(2) infinite}
    @keyframes cjit{0%{transform:translate(0,0)}50%{transform:translate(1px,-1px) rotate(.6deg)}100%{transform:translate(-1px,1px)}}
    .csprite.sad{animation:csad 4s ease-in-out infinite}
    @keyframes csad{0%,100%{transform:translateY(2%)}50%{transform:translateY(5%)}}
    .csprite .blink{transform-box:fill-box;transform-origin:center;animation:cblink 4.5s infinite}
    .csprite .blink.b2{animation-delay:.15s}
    @keyframes cblink{0%,94%,100%{transform:scaleY(1)}96%,98%{transform:scaleY(.1)}}
    .csprite .flick{transform-box:fill-box;transform-origin:bottom center;animation:cflick .5s ease-in-out infinite alternate}
    @keyframes cflick{from{transform:scaleY(1) scaleX(1)}to{transform:scaleY(1.06) scaleX(.95)}}
    .csprite .orbit{transform-box:fill-box;transform-origin:50px 52px;animation:corbit 3s linear infinite}
    @keyframes corbit{to{transform:rotate(360deg)}}
    .csprite .shine{transform-box:fill-box;transform-origin:center;animation:cshine 3s ease-in-out infinite}
    @keyframes cshine{0%,100%{opacity:.5}50%{opacity:.95}}
    .csprite .ground{animation:cground 2.6s ease-in-out infinite}
    @keyframes cground{0%,100%{opacity:.22;transform:scaleX(1)}50%{opacity:.14;transform:scaleX(.82)}}
    `;
    document.head.appendChild(s);
  }

  function moodFromCare(c, shadow) {
    if (shadow) return 'shadow';
    const avg = (c.fed + c.rested + c.seen) / 3;
    if (c.rested < 22) return 'sleepy';
    if (avg >= 78) return 'happy';
    if (avg >= 52) return 'content';
    if (avg >= 30) return 'neutral';
    return 'worried';
  }

  // ---- face overlay -------------------------------------------------------
  function Face({ mood, cx = 50, cy = 50, w = 34, dark }) {
    const eyeY = cy - 2, ex = w * 0.28;
    const pupil = dark ? '#0b0b12' : '#2B2434';
    const white = dark ? '#C9BBDD' : '#fff';
    let mouth;
    const my = cy + 11;
    if (mood === 'happy')      mouth = <path d={`M${cx-9} ${my-1} Q${cx} ${my+8} ${cx+9} ${my-1}`} stroke={pupil} strokeWidth="2.4" fill="none" strokeLinecap="round"/>;
    else if (mood === 'content') mouth = <path d={`M${cx-7} ${my} Q${cx} ${my+4} ${cx+7} ${my}`} stroke={pupil} strokeWidth="2.2" fill="none" strokeLinecap="round"/>;
    else if (mood === 'neutral') mouth = <line x1={cx-6} y1={my+1} x2={cx+6} y2={my+1} stroke={pupil} strokeWidth="2.2" strokeLinecap="round"/>;
    else if (mood === 'worried') mouth = <path d={`M${cx-7} ${my+2} Q${cx-2} ${my-2} ${cx+1} ${my+2} T${cx+8} ${my+2}`} stroke={pupil} strokeWidth="2" fill="none" strokeLinecap="round"/>;
    else if (mood === 'sleepy')  mouth = <ellipse cx={cx} cy={my+1} rx="3" ry="3.4" fill={pupil}/>;
    else if (mood === 'sad')     mouth = <path d={`M${cx-8} ${my+4} Q${cx} ${my-3} ${cx+8} ${my+4}`} stroke={pupil} strokeWidth="2.2" fill="none" strokeLinecap="round"/>;
    else mouth = <path d={`M${cx-8} ${my} l4 -3 l4 3 l4 -3 l4 3`} stroke={pupil} strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/>; // shadow zigzag

    if (mood === 'sleepy')
      return (<g>
        <path d={`M${cx-ex-4} ${eyeY} q4 4 8 0`} stroke={pupil} strokeWidth="2.2" fill="none" strokeLinecap="round"/>
        <path d={`M${cx+ex-4} ${eyeY} q4 4 8 0`} stroke={pupil} strokeWidth="2.2" fill="none" strokeLinecap="round"/>
        {mouth}
      </g>);

    if (mood === 'shadow')
      return (<g>
        <circle className="shine" cx={cx-ex} cy={eyeY} r="4.2" fill="#FF6EA8"/>
        <circle className="shine" cx={cx+ex} cy={eyeY} r="4.2" fill="#FF6EA8"/>
        {mouth}
      </g>);

    if (mood === 'happy')
      return (<g>
        <path d={`M${cx-ex-4} ${eyeY+2} q4 -6 8 0`} stroke={pupil} strokeWidth="2.6" fill="none" strokeLinecap="round"/>
        <path d={`M${cx+ex-4} ${eyeY+2} q4 -6 8 0`} stroke={pupil} strokeWidth="2.6" fill="none" strokeLinecap="round"/>
        <circle cx={cx-w*0.42} cy={cy+6} r="3" fill="#FF9EC0" opacity=".55"/>
        <circle cx={cx+w*0.42} cy={cy+6} r="3" fill="#FF9EC0" opacity=".55"/>
        {mouth}
      </g>);

    const eyeR = mood==='worried' ? 4 : 4.6;
    const py = mood==='worried' ? eyeY-1 : eyeY;
    return (<g>
      <g className="blink"><circle cx={cx-ex} cy={eyeY} r={eyeR} fill={white}/></g>
      <g className="blink b2"><circle cx={cx+ex} cy={eyeY} r={eyeR} fill={white}/></g>
      <circle cx={cx-ex} cy={py} r="2.4" fill={pupil}/>
      <circle cx={cx+ex} cy={py} r="2.4" fill={pupil}/>
      <circle cx={cx-ex+1.4} cy={py-1.4} r="1" fill="#fff"/>
      <circle cx={cx+ex+1.4} cy={py-1.4} r="1" fill="#fff"/>
      {mood==='worried' && <path d={`M${cx-ex-5} ${eyeY-7} q5 -3 9 0`} stroke={pupil} strokeWidth="1.6" fill="none" strokeLinecap="round"/>}
      {mood==='worried' && <path d={`M${cx+ex-4} ${eyeY-7} q5 -3 9 0`} stroke={pupil} strokeWidth="1.6" fill="none" strokeLinecap="round" transform={`scale(-1,1) translate(${-2*cx},0)`}/>}
      {mouth}
    </g>);
  }

  // ---- body drawing -------------------------------------------------------
  function body(emo, mood, id) {
    const [a, b] = emo.c;
    const g = `grad-${id}`;
    const dark = emo.shadow || emo.family === 'dark';
    const defs = (
      <defs>
        <radialGradient id={g} cx="38%" cy="32%" r="75%">
          <stop offset="0%" stopColor={a}/>
          <stop offset="100%" stopColor={b}/>
        </radialGradient>
        <radialGradient id={g+'h'} cx="38%" cy="30%" r="40%">
          <stop offset="0%" stopColor="#fff" stopOpacity=".55"/>
          <stop offset="100%" stopColor="#fff" stopOpacity="0"/>
        </radialGradient>
      </defs>
    );
    const fill = `url(#${g})`, hi = `url(#${g+'h'})`;
    const T = emo.body;
    let shape;

    if (T === 'drop') shape = <path d="M50 16 C66 38 74 52 74 64 a24 24 0 0 1 -48 0 C26 52 34 38 50 16 Z" fill={fill}/>;
    else if (T === 'flame') shape = <g className="flick"><path d="M50 14 C64 30 70 40 70 56 a20 20 0 0 1 -40 0 C30 42 40 36 44 24 C46 34 52 30 50 14 Z" fill={fill}/></g>;
    else if (T === 'ghost') shape = <path d="M26 54 a24 24 0 0 1 48 0 v20 q-6 -6 -12 0 q-6 6 -12 0 q-6 -6 -12 0 q-6 6 -12 0 Z" fill={fill}/>;
    else if (T === 'shield') shape = <path d="M50 22 L74 30 V52 C74 66 62 76 50 80 C38 76 26 66 26 52 V30 Z" fill={fill}/>;
    else if (T === 'star') shape = <path d="M50 18 L58 40 L82 41 L63 56 L70 79 L50 65 L30 79 L37 56 L18 41 L42 40 Z" fill={fill}/>;
    else if (T === 'spark') shape = <g className="shine"><path d="M50 16 L56 38 L78 30 L60 48 L84 56 L58 58 L66 82 L50 62 L34 82 L42 58 L16 56 L40 48 L22 30 L44 38 Z" fill={fill}/></g>;
    else if (T === 'cloud') shape = <path d="M32 64 a14 14 0 0 1 0 -22 a16 16 0 0 1 30 -6 a14 14 0 0 1 6 28 Z" fill={fill}/>;
    else if (T === 'prism') shape = <path d="M50 18 L78 38 L68 76 L32 76 L22 38 Z" fill={fill}/>;
    else if (T === 'void') shape = <g><circle cx="50" cy="52" r="30" fill={fill}/><circle cx="50" cy="52" r="30" fill="#000" opacity=".35"/><circle className="orbit" cx="50" cy="22" r="3.4" fill="#B6A4EE"/></g>;
    else if (T === 'mirror') shape = <g><path d="M50 16 L74 40 L50 84 L26 40 Z" fill={fill}/><path d="M50 16 L62 40 L50 84 Z" fill="#fff" opacity=".28"/></g>;
    else if (T === 'swirl') shape = <g><circle cx="50" cy="52" r="30" fill={a}/><path d="M50 22 a30 30 0 0 1 0 60 a15 15 0 0 1 0 -30 a15 15 0 0 0 0 -30 Z" fill={b}/></g>;
    else if (T === 'jitter') shape = <g className=""><path d="M28 40 l8 -4 l-3 -9 l11 5 l6 -8 l4 9 l10 -3 l-4 10 l9 6 l-9 5 l3 10 l-10 -4 l-6 8 l-5 -9 l-10 3 l4 -10 l-8 -6 l8 -5 Z" fill={fill}/></g>;
    else if (T === 'bloom') shape = <g>{[0,72,144,216,288].map((d,i)=><ellipse key={i} cx="50" cy="32" rx="10" ry="16" fill={i%2?b:a} transform={`rotate(${d} 50 52)`} opacity=".92"/>)}<circle cx="50" cy="52" r="11" fill="#FFE9A8"/></g>;
    else if (T === 'phoenix') shape = <g className="shine"><path d="M50 24 C30 24 18 40 22 56 C30 46 38 46 44 52 C30 60 26 74 34 82 C40 70 48 70 50 72 C52 70 60 70 66 82 C74 74 70 60 56 52 C62 46 70 46 78 56 C82 40 70 24 50 24 Z" fill={fill}/></g>;
    else if (T === 'orb') shape = <g><circle cx="50" cy="52" r="28" fill={fill}/><ellipse className="orbit" cx="50" cy="52" rx="34" ry="11" fill="none" stroke="#fff" strokeOpacity=".5" strokeWidth="2"/></g>;
    else if (T === 'comet') shape = <g>
        {/* streaking tail */}
        <path d="M50 52 C30 60 16 74 8 92 C24 84 40 74 54 64 Z" fill={a} opacity=".35"/>
        <path d="M50 52 C34 58 24 70 18 86 C30 78 42 70 52 60 Z" fill={b} opacity=".55"/>
        {/* glowing head */}
        <circle cx="52" cy="48" r="26" fill={fill}/>
        <circle cx="52" cy="48" r="26" fill="none" stroke="#fff" strokeOpacity=".35" strokeWidth="1.5"/>
        {/* orbiting curiosity spark */}
        <g className="orbit"><circle cx="52" cy="18" r="3.4" fill="#fff" opacity=".9"/></g>
        <g className="shine"><circle cx="78" cy="30" r="2.2" fill="#fff"/></g>
      </g>;
    else /* blob */ shape = <path d="M50 20 C66 20 80 32 80 50 C80 66 70 82 50 82 C30 82 20 66 20 50 C20 32 34 20 50 20 Z" fill={fill}/>;

    // face anchor roughly center for most; lower for drop/flame/star
    const fy = (T==='drop'||T==='shield') ? 54 : (T==='star'||T==='spark') ? 48 : (T==='flame') ? 50 : (T==='comet') ? 46 : 50;
    return { defs, shape, hi, fy, dark };
  }

  function CreatureSprite({ emo, mood = 'content', size = 64, idle = true }) {
    const id = React.useMemo(() => Math.random().toString(36).slice(2, 7), []);
    if (!emo) return null;
    const { defs, shape, hi, fy, dark } = body(emo, mood, id);
    const cls = ['csprite'];
    if (idle) {
      if (mood === 'shadow' || mood === 'worried') cls.push('sad');
      else if (emo.body === 'jitter' && mood !== 'sleepy') cls.push('jit');
      else cls.push('bob', 'b' + (1 + (id.charCodeAt(0) % 2)));
    }
    return (
      <span className={cls.join(' ')} style={{ width: size, height: size }}>
        <svg viewBox="0 0 100 100" width={size} height={size} style={{ overflow: 'visible' }}>
          {defs}
          <ellipse className="ground" cx="50" cy="90" rx="22" ry="5" fill="#2B2434"/>
          {shape}
          <ellipse cx="44" cy="38" rx="16" ry="12" fill={hi}/>
          <Face mood={mood} cx={50} cy={fy} dark={dark}/>
        </svg>
      </span>
    );
  }

  // ---- shared atoms -------------------------------------------------------
  function Meter({ v, color = 'var(--pink)', h = 9 }) {
    return <div className="meter" style={{ height: h }}><i style={{ width: Math.max(0, Math.min(100, v)) + '%', background: color }}/></div>;
  }
  function Coin({ kind, size = 16 }) {
    const map = {
      energy: { bg: 'linear-gradient(135deg,#FFD45E,#FF9E2C)', s: '⚡', c:'#7a4a00' },
      clarity:{ bg: 'linear-gradient(135deg,#B6A4EE,#8C77D6)', s: '◆', c:'#fff' },
      fucks:  { bg: 'linear-gradient(135deg,#FF9EC0,#FF7FA6)', s: '⊘', c:'#7a2540' },
      gpp:    { bg: 'linear-gradient(135deg,#7FD0B0,#54B98A)', s: '✦', c:'#08402c' },
      wonder: { bg: 'linear-gradient(135deg,#7FF0E8,#2BA8C8)', s: '◇', c:'#063a44' },
    };
    const m = map[kind] || map.energy;
    return <span style={{ width:size, height:size, borderRadius:'50%', background:m.bg, display:'inline-grid', placeItems:'center', fontSize:size*0.62, color:m.c, flex:'none', boxShadow:'inset 0 -1px 2px rgba(0,0,0,.2)' }}>{m.s}</span>;
  }

  window.LifeArt = { CreatureSprite, Face, Meter, Coin, moodFromCare };
})();
