/* global React */
const { useState, useEffect, useRef } = React;

// ============================================================
// LUCIUS THE LEARNING T-REX — chibi mascot, 14 moods, props, chaos
// ============================================================
// Moods:
//   idle, idle-wave, idle-dance, idle-yawn       — home screen rotation
//   ready                                        — quiz setup (eager hop + pencil)
//   thinking                                     — answering question
//   mild-happy                                   — first correct
//   fire-streak                                  — 3+ in a row (sparkles + flame)
//   sympathetic                                  — wrong twice (oof, head shake, sweat)
//   sad                                          — wrong once
//   passed-cheer                                 — quiz passed (jump + cap + trophy)
//   barely-passed                                — squeaked by (relieved sweat + thumbs up)
//   failed-sad                                   — failed (drooping + tear)
//   celebrate                                    — generic celebration (alias for passed-cheer)
//   sleepy                                       — late at night / inactive
// ============================================================

function Mascot({ mood = 'idle', size = 120 }) {
  const p = { body: '#FF8A5C', belly: '#FFD7B8', spike: '#FFD86B', stroke: '#3D1F1A', sw: 2.5 };

  // ---- pick wrapper animation per mood ----
  const animClass = (() => {
    switch (mood) {
      case 'passed-cheer':
      case 'celebrate':       return 'jump-cheer';
      case 'fire-streak':     return 'fire-vibe';
      case 'sympathetic':     return 'head-shake';
      case 'idle-wave':       return 'wave-body';
      case 'idle-dance':      return 'dance';
      case 'idle-yawn':
      case 'sleepy':          return 'yawn-breathe';
      case 'failed-sad':      return 'droop';
      case 'ready':           return 'ready-hop';
      case 'sad':             return 'shake';
      case 'mild-happy':      return 'wiggle';
      case 'barely-passed':   return 'wave-body';
      default:                return 'float-y';
    }
  })();

  // ============== EYE ==============
  const eye = (() => {
    switch (mood) {
      case 'mild-happy':
      case 'passed-cheer':
      case 'celebrate':
      case 'fire-streak':
        // closed-up smile arcs ^_^
        return <path d="M 88 42 Q 92 36 96 42" fill="none" stroke={p.stroke} strokeWidth="3" strokeLinecap="round"/>;
      case 'sad':
      case 'failed-sad':
      case 'sympathetic':
        return <path d="M 88 44 Q 92 49 96 44" fill="none" stroke={p.stroke} strokeWidth="2.5" strokeLinecap="round"/>;
      case 'thinking':
        return (
          <g>
            <circle cx="92" cy="43" r="2.6" fill={p.stroke} />
            <circle cx="93" cy="42" r="0.9" fill="#fff" />
          </g>
        );
      case 'sleepy':
      case 'idle-yawn':
        return <path d="M 88 43 Q 92 41 96 43" fill="none" stroke={p.stroke} strokeWidth="2.5" strokeLinecap="round"/>;
      case 'idle-wave':
      case 'idle-dance':
      case 'ready':
      case 'barely-passed':
        return (
          <g>
            <circle cx="92" cy="42" r="3.4" fill={p.stroke} />
            <circle cx="93.4" cy="40.8" r="1.2" fill="#fff" />
          </g>
        );
      default:
        return (
          <g>
            <circle cx="92" cy="42" r="3.2" fill={p.stroke} />
            <circle cx="93.2" cy="41" r="1.1" fill="#fff" />
          </g>
        );
    }
  })();

  // ============== MOUTH ==============
  const mouth = (() => {
    switch (mood) {
      case 'mild-happy':
        return (
          <g>
            <path d="M 100 56 Q 106 60 110 55" fill="none" stroke={p.stroke} strokeWidth="2.4" strokeLinecap="round"/>
            <path d="M 104 56 L 105 59 L 106 56 Z" fill="#fff" stroke={p.stroke} strokeWidth="0.8"/>
          </g>
        );
      case 'passed-cheer':
      case 'celebrate':
        // wide open laugh
        return (
          <g>
            <path d="M 99 53 Q 106 64 113 53 Q 106 59 99 53 Z" fill={p.stroke} strokeLinejoin="round"/>
            <path d="M 102 54 L 103 58 L 104 54 Z" fill="#fff"/>
            <path d="M 107 54 L 108 58 L 109 54 Z" fill="#fff"/>
            <path d="M 105 60 Q 107 63 109 60" fill="#FF6B8E"/>{/* tongue */}
          </g>
        );
      case 'fire-streak':
        // determined open mouth, baring teeth
        return (
          <g>
            <path d="M 99 54 Q 106 60 112 54 L 112 58 Q 106 62 99 58 Z" fill={p.stroke} strokeLinejoin="round"/>
            <path d="M 101 55 L 102 58 L 103 55 Z" fill="#fff"/>
            <path d="M 105 55 L 106 58 L 107 55 Z" fill="#fff"/>
            <path d="M 109 55 L 110 58 L 111 55 Z" fill="#fff"/>
          </g>
        );
      case 'sad':
      case 'failed-sad':
        return (
          <g>
            <path d="M 100 58 Q 106 53 110 58" fill="none" stroke={p.stroke} strokeWidth="2.5" strokeLinecap="round"/>
            <path d="M 104 56.5 L 105 59 L 106 56.5 Z" fill="#fff" stroke={p.stroke} strokeWidth="0.6"/>
          </g>
        );
      case 'sympathetic':
        // small awkward grimace
        return <path d="M 100 57 Q 104 56 108 57" fill="none" stroke={p.stroke} strokeWidth="2.2" strokeLinecap="round"/>;
      case 'thinking':
        return <path d="M 102 56 L 110 56" fill="none" stroke={p.stroke} strokeWidth="2.2" strokeLinecap="round"/>;
      case 'sleepy':
      case 'idle-yawn':
        // big O for yawn
        return <ellipse cx="106" cy="56" rx="4.5" ry="3" fill={p.stroke}/>;
      case 'ready':
        // determined smirk
        return (
          <g>
            <path d="M 99 56 Q 106 60 112 55" fill="none" stroke={p.stroke} strokeWidth="2.6" strokeLinecap="round"/>
            <path d="M 105 56 L 106 59 L 107 56 Z" fill="#fff" stroke={p.stroke} strokeWidth="0.8"/>
          </g>
        );
      case 'idle-wave':
      case 'idle-dance':
      case 'barely-passed':
        return (
          <g>
            <path d="M 100 56 Q 106 60 110 55" fill="none" stroke={p.stroke} strokeWidth="2.4" strokeLinecap="round"/>
            <path d="M 104 56 L 105 59 L 106 56 Z" fill="#fff" stroke={p.stroke} strokeWidth="0.8"/>
          </g>
        );
      default:
        return (
          <g>
            <path d="M 100 56 Q 106 58 110 55" fill="none" stroke={p.stroke} strokeWidth="2.2" strokeLinecap="round"/>
            <path d="M 104 56 L 105 58 L 106 56 Z" fill="#fff" stroke={p.stroke} strokeWidth="0.6"/>
          </g>
        );
    }
  })();

  // ============== ARM POSE ==============
  // Default arm tucked. Several moods raise / extend the arm.
  const arm = (() => {
    if (mood === 'idle-wave') {
      // raised hand waving (the iconic tiny T-rex hello)
      return (
        <g>
          {/* shoulder->elbow up */}
          <path d="M 70 62 Q 72 52 78 50" fill="none" stroke={p.stroke} strokeWidth={p.sw * 1.3} strokeLinecap="round"/>
          {/* hand */}
          <path d="M 78 50 L 82 46 M 78 50 L 80 44 M 78 50 L 75 44"
                fill="none" stroke={p.stroke} strokeWidth={p.sw * 0.8} strokeLinecap="round"/>
        </g>
      );
    }
    if (mood === 'passed-cheer' || mood === 'celebrate' || mood === 'fire-streak') {
      // arm raised in triumph
      return (
        <g>
          <path d="M 70 62 Q 64 52 60 42" fill="none" stroke={p.stroke} strokeWidth={p.sw * 1.3} strokeLinecap="round"/>
          <path d="M 60 42 L 57 39 M 60 42 L 60 38 M 60 42 L 63 38"
                fill="none" stroke={p.stroke} strokeWidth={p.sw * 0.8} strokeLinecap="round"/>
        </g>
      );
    }
    if (mood === 'barely-passed') {
      // thumbs up (kinda)
      return (
        <g>
          <path d="M 70 64 Q 64 60 60 56" fill="none" stroke={p.stroke} strokeWidth={p.sw * 1.3} strokeLinecap="round"/>
          {/* fist + thumb */}
          <circle cx="58" cy="55" r="2.5" fill={p.body} stroke={p.stroke} strokeWidth={p.sw * 0.7}/>
          <path d="M 58 53 L 58 49" fill="none" stroke={p.stroke} strokeWidth={p.sw * 0.8} strokeLinecap="round"/>
        </g>
      );
    }
    if (mood === 'ready') {
      // pencil clutched
      return (
        <g>
          <path d="M 70 64 Q 62 64 56 70" fill="none" stroke={p.stroke} strokeWidth={p.sw * 1.3} strokeLinecap="round"/>
          {/* pencil — yellow shaft, pink eraser, dark tip */}
          <rect x="46" y="64" width="14" height="4" fill="#FFD93D" stroke={p.stroke} strokeWidth="1" rx="1"/>
          <rect x="44" y="64" width="3" height="4" fill="#FF6B8E" stroke={p.stroke} strokeWidth="1" rx="0.5"/>
          <path d="M 60 64 L 64 66 L 60 68 Z" fill={p.stroke}/>
        </g>
      );
    }
    if (mood === 'sympathetic' || mood === 'failed-sad') {
      // arm hanging limp
      return (
        <g>
          <path d="M 70 64 Q 66 70 64 78" fill="none" stroke={p.stroke} strokeWidth={p.sw * 1.3} strokeLinecap="round"/>
          <path d="M 64 78 L 61 78 M 64 78 L 62 80 M 64 78 L 63 82"
                fill="none" stroke={p.stroke} strokeWidth={p.sw * 0.8} strokeLinecap="round"/>
        </g>
      );
    }
    // default tucked arm
    return (
      <g>
        <path d="M 70 64 Q 64 66 60 72" fill="none" stroke={p.stroke} strokeWidth={p.sw * 1.3} strokeLinecap="round"/>
        <path d="M 60 72 L 56 76" fill="none" stroke={p.stroke} strokeWidth={p.sw * 1.1} strokeLinecap="round"/>
        <path d="M 56 76 L 53 76 M 56 76 L 54 78 M 56 76 L 55 80"
              fill="none" stroke={p.stroke} strokeWidth={p.sw * 0.8} strokeLinecap="round"/>
      </g>
    );
  })();

  // ============== HEAD ACCESSORY (cap / glasses / etc) ==============
  const headProp = (() => {
    if (mood === 'passed-cheer' || mood === 'celebrate') {
      // graduation cap
      return (
        <g>
          <path d="M 78 18 L 100 12 L 122 18 L 100 24 Z" fill={p.stroke}/>
          <path d="M 100 24 L 100 30" stroke={p.stroke} strokeWidth="1.5"/>
          <circle cx="100" cy="30" r="2" fill={p.spike}/>
          <path d="M 122 18 L 122 26" stroke={p.stroke} strokeWidth="1.5"/>
          <path d="M 122 26 L 124 28 L 124 30 L 120 30 L 120 28 Z" fill={p.spike} stroke={p.stroke} strokeWidth="0.8"/>
        </g>
      );
    }
    if (mood === 'thinking') {
      // round reading glasses
      return (
        <g>
          <circle cx="92" cy="43" r="6" fill="none" stroke={p.stroke} strokeWidth="1.6"/>
          <circle cx="105" cy="40" r="5" fill="none" stroke={p.stroke} strokeWidth="1.6"/>
          <path d="M 98 42 L 100 40" stroke={p.stroke} strokeWidth="1.4"/>
        </g>
      );
    }
    return null;
  })();

  // ============== OVERLAY EFFECTS ==============
  const overlays = (
    <g>
      {/* sweat drop — sympathetic / barely-passed */}
      {(mood === 'sympathetic' || mood === 'barely-passed') && (
        <g className="drip" style={{ transformOrigin: '78px 22px' }}>
          <path d="M 78 18 Q 75 24 78 28 Q 81 24 78 18 Z" fill="#7DC8E8" stroke={p.stroke} strokeWidth="0.8"/>
        </g>
      )}

      {/* tear — failed-sad */}
      {mood === 'failed-sad' && (
        <g>
          <path d="M 90 48 Q 88 54 91 56 Q 94 54 92 48 Z" fill="#7DC8E8" stroke={p.stroke} strokeWidth="0.8"/>
        </g>
      )}

      {/* fire flames around body — fire-streak */}
      {mood === 'fire-streak' && (
        <g className="sparkle-pop">
          <path d="M 8 70 Q 6 60 12 56 Q 10 64 16 64 Q 14 72 8 70 Z" fill="#FF4F1F" stroke={p.stroke} strokeWidth="1.2"/>
          <path d="M 8 70 Q 8 64 12 62" fill="#FFD86B"/>
          <path d="M 116 80 Q 116 70 110 66 Q 112 74 106 74 Q 108 82 116 80 Z" fill="#FF4F1F" stroke={p.stroke} strokeWidth="1.2"/>
          <path d="M 116 80 Q 114 74 110 72" fill="#FFD86B"/>
        </g>
      )}

      {/* big sparkles + stars — passed-cheer / celebrate */}
      {(mood === 'passed-cheer' || mood === 'celebrate') && (
        <g>
          <path d="M 14 46 L 18 50 L 14 54 L 10 50 Z" fill="var(--tertiary)" className="sparkle-pop"/>
          <path d="M 6 78 L 9 82 L 6 86 L 3 82 Z" fill="var(--accent)" className="sparkle-pop" style={{ animationDelay: '0.3s' }}/>
          <circle cx="118" cy="52" r="3" fill="var(--secondary)" className="sparkle-pop" style={{ animationDelay: '0.5s' }}/>
          {/* trophy at feet */}
          <g>
            <path d="M 32 100 L 40 100 L 39 108 L 33 108 Z" fill={p.spike} stroke={p.stroke} strokeWidth="1.2"/>
            <rect x="30" y="108" width="12" height="3" fill={p.stroke}/>
            <path d="M 32 102 Q 26 102 26 96 L 28 96 Q 28 100 32 100" fill="none" stroke={p.stroke} strokeWidth="1.4"/>
            <path d="M 40 102 Q 46 102 46 96 L 44 96 Q 44 100 40 100" fill="none" stroke={p.stroke} strokeWidth="1.4"/>
            <text x="33.5" y="106.5" fontFamily="'Fraunces', serif" fontSize="5" fontWeight="900" fill={p.stroke}>1</text>
          </g>
        </g>
      )}

      {/* mild sparkles for mild-happy */}
      {mood === 'mild-happy' && (
        <g>
          <circle cx="118" cy="40" r="2" fill="var(--tertiary)" className="sparkle-pop"/>
          <circle cx="74" cy="20" r="1.5" fill="var(--accent)" className="sparkle-pop" style={{ animationDelay: '0.4s' }}/>
        </g>
      )}

      {/* zzz for sleepy / idle-yawn */}
      {(mood === 'sleepy' || mood === 'idle-yawn') && (
        <g>
          <text x="110" y="24" fontFamily="'Fraunces', serif" fontSize="14" fontWeight="900" fill={p.stroke}>z</text>
          <text x="118" y="14" fontFamily="'Fraunces', serif" fontSize="10" fontWeight="900" fill={p.stroke} opacity="0.65">z</text>
        </g>
      )}

      {/* thought bubble for thinking */}
      {mood === 'thinking' && (
        <g>
          <circle cx="116" cy="14" r="6" fill={p.belly} stroke={p.stroke} strokeWidth="1.4"/>
          <circle cx="108" cy="22" r="2" fill={p.belly} stroke={p.stroke} strokeWidth="1"/>
          <text x="113" y="17" fontFamily="'Fraunces', serif" fontSize="9" fontWeight="900" fill={p.stroke}>?</text>
        </g>
      )}

      {/* "hi!" speech for idle-wave */}
      {mood === 'idle-wave' && (
        <g>
          <path d="M 14 24 Q 14 14 26 14 L 50 14 Q 60 14 60 24 L 60 30 Q 60 38 50 38 L 32 38 L 26 44 L 28 38 Q 14 38 14 30 Z"
                fill={p.belly} stroke={p.stroke} strokeWidth="1.4"/>
          <text x="22" y="32" fontFamily="'Fraunces', serif" fontSize="14" fontWeight="900" fill={p.stroke}>hi!</text>
        </g>
      )}

      {/* music notes for dance */}
      {mood === 'idle-dance' && (
        <g className="sparkle-pop">
          <path d="M 8 30 L 8 18 Q 14 16 14 22 Q 14 26 10 26 Q 8 26 8 24" fill={p.stroke}/>
          <path d="M 110 50 L 110 38 Q 116 36 116 42 Q 116 46 112 46 Q 110 46 110 44" fill={p.stroke} opacity="0.7"/>
        </g>
      )}

      {/* eager exclamation for ready */}
      {mood === 'ready' && (
        <g>
          <text x="34" y="40" fontFamily="'Fraunces', serif" fontSize="22" fontWeight="900" fill={p.spike} stroke={p.stroke} strokeWidth="1">!</text>
        </g>
      )}

      {/* cheek blush for happy moods */}
      {(mood === 'mild-happy' || mood === 'passed-cheer' || mood === 'celebrate' || mood === 'idle-wave' || mood === 'idle-dance' || mood === 'barely-passed') && (
        <ellipse cx="86" cy="50" rx="3.4" ry="1.9" fill={p.spike} opacity="0.55"/>
      )}

      {/* sympathetic forehead lines */}
      {mood === 'sympathetic' && (
        <g>
          <path d="M 86 32 L 90 30 M 92 30 L 96 28 M 98 28 L 102 26"
                stroke={p.stroke} strokeWidth="1.3" strokeLinecap="round" fill="none"/>
        </g>
      )}
    </g>
  );

  // ============== RENDER ==============
  return (
    <div className={animClass} style={{ width: size, height: size, display: 'inline-block' }}>
      <svg viewBox="0 0 130 120" width={size} height={size} style={{ overflow: 'visible' }}>
        {/* ground shadow */}
        <ellipse cx="60" cy="110" rx="42" ry="4" fill="rgba(0,0,0,0.22)" />

        {/* TAIL */}
        <path
          d="M 36 78 Q 18 76 8 60 Q 4 50 12 48 Q 16 56 22 62 Q 28 70 38 72 Z"
          fill={p.body} stroke={p.stroke} strokeWidth={p.sw} strokeLinejoin="round"
        />

        {/* BACK LEG */}
        <path
          d="M 64 78 Q 66 88 70 96 Q 72 102 78 102 Q 84 102 84 96 Q 84 88 80 80 Z"
          fill={p.body} stroke={p.stroke} strokeWidth={p.sw} strokeLinejoin="round" opacity="0.85"
        />
        <path d="M 72 100 Q 86 100 86 104 Q 86 106 80 106 L 72 106 Z" fill={p.body} stroke={p.stroke} strokeWidth={p.sw} strokeLinejoin="round" opacity="0.85"/>
        <path d="M 86 105 L 89 107 M 84 106 L 86 109 M 80 106 L 81 109" stroke={p.stroke} strokeWidth={p.sw * 0.7} strokeLinecap="round" fill="none"/>

        {/* BODY */}
        <path
          d="M 30 70 Q 28 50 46 42 Q 64 36 78 44 Q 88 50 86 70 Q 84 86 64 88 Q 40 88 30 78 Z"
          fill={p.body} stroke={p.stroke} strokeWidth={p.sw} strokeLinejoin="round"
        />

        {/* BELLY */}
        <path
          d="M 38 76 Q 38 64 50 60 Q 66 58 76 68 Q 80 80 68 84 Q 50 86 38 76 Z"
          fill={p.belly} stroke="none"
        />

        {/* SPIKES */}
        <path d="M 32 56 L 35 50 L 38 56 Z" fill={p.spike} stroke={p.stroke} strokeWidth={p.sw * 0.6} strokeLinejoin="round"/>
        <path d="M 44 48 L 47 42 L 50 48 Z" fill={p.spike} stroke={p.stroke} strokeWidth={p.sw * 0.6} strokeLinejoin="round"/>
        <path d="M 58 44 L 61 38 L 64 44 Z" fill={p.spike} stroke={p.stroke} strokeWidth={p.sw * 0.6} strokeLinejoin="round"/>
        <path d="M 72 46 L 75 40 L 78 46 Z" fill={p.spike} stroke={p.stroke} strokeWidth={p.sw * 0.6} strokeLinejoin="round"/>

        {/* ARM (mood-dependent) */}
        {arm}

        {/* FRONT LEG */}
        <path
          d="M 50 78 Q 50 90 54 98 Q 56 104 62 104 Q 68 104 68 98 Q 68 90 64 80 Z"
          fill={p.body} stroke={p.stroke} strokeWidth={p.sw} strokeLinejoin="round"
        />
        <path d="M 54 102 Q 70 102 70 106 Q 70 108 64 108 L 54 108 Z" fill={p.body} stroke={p.stroke} strokeWidth={p.sw} strokeLinejoin="round"/>
        <path d="M 70 107 L 73 109 M 67 108 L 68 110.5 M 63 108 L 63.5 110.5 M 58 108 L 58 110.5" stroke={p.stroke} strokeWidth={p.sw * 0.7} strokeLinecap="round" fill="none"/>

        {/* HEAD */}
        <path
          d="M 76 30 Q 78 24 86 22 Q 100 20 110 28 Q 116 34 114 42 Q 113 48 108 52 L 114 56 Q 116 60 112 62 Q 102 64 96 60 Q 90 60 86 56 Q 78 54 76 48 Q 74 38 76 30 Z"
          fill={p.body} stroke={p.stroke} strokeWidth={p.sw} strokeLinejoin="round"
        />

        {/* nostril */}
        <ellipse cx="111" cy="40" rx="1.1" ry="1.5" fill={p.stroke} />

        {/* tooth peek (for neutral / thinking moods) */}
        {(mood === 'idle' || mood === 'thinking' || mood === 'ready') && (
          <path d="M 108 53 L 109 56 L 110 53 Z" fill="#fff" stroke={p.stroke} strokeWidth="0.7"/>
        )}

        {/* head accessory (cap/glasses) */}
        {headProp}

        {/* eye + mouth */}
        {eye}
        {mouth}

        {/* overlays */}
        {overlays}
      </svg>
    </div>
  );
}

// ============================================================
// SOUND FX — tiny soft WebAudio chimes for big moments
// ============================================================
const SfxCtx = { ctx: null };
function getSfxCtx() {
  if (!SfxCtx.ctx) {
    try { SfxCtx.ctx = new (window.AudioContext || window.webkitAudioContext)(); }
    catch { return null; }
  }
  return SfxCtx.ctx;
}
function playTone(freq, duration = 0.15, type = 'sine', vol = 0.08, when = 0) {
  const ctx = getSfxCtx();
  if (!ctx) return;
  const t0 = ctx.currentTime + when;
  const osc = ctx.createOscillator();
  const gain = ctx.createGain();
  osc.type = type;
  osc.frequency.setValueAtTime(freq, t0);
  gain.gain.setValueAtTime(0, t0);
  gain.gain.linearRampToValueAtTime(vol, t0 + 0.02);
  gain.gain.exponentialRampToValueAtTime(0.0001, t0 + duration);
  osc.connect(gain).connect(ctx.destination);
  osc.start(t0);
  osc.stop(t0 + duration + 0.05);
}
const Sfx = {
  enabled: true,
  setEnabled(v) { Sfx.enabled = v; },
  correct() { if (!Sfx.enabled) return; playTone(660, 0.1, 'sine', 0.08); playTone(880, 0.16, 'sine', 0.07, 0.08); },
  wrong()   { if (!Sfx.enabled) return; playTone(220, 0.18, 'triangle', 0.07); playTone(160, 0.22, 'triangle', 0.06, 0.05); },
  streak()  { if (!Sfx.enabled) return; [523, 659, 784, 1047].forEach((f, i) => playTone(f, 0.12, 'sine', 0.07, i * 0.07)); },
  passed()  { if (!Sfx.enabled) return; [523, 659, 784, 1047, 1319].forEach((f, i) => playTone(f, 0.18, 'triangle', 0.07, i * 0.08)); },
  failed()  { if (!Sfx.enabled) return; playTone(330, 0.22, 'triangle', 0.07); playTone(247, 0.3, 'triangle', 0.07, 0.12); playTone(165, 0.36, 'triangle', 0.06, 0.24); },
  hello()   { if (!Sfx.enabled) return; playTone(784, 0.08, 'sine', 0.05); playTone(988, 0.1, 'sine', 0.05, 0.06); },
};

// ============================================================
// LEAF FLURRY — drifting petals & leaves on celebration
// ============================================================
function Confetti({ active, count = 28 }) {
  const pieces = useRef(null);
  if (!pieces.current) {
    pieces.current = Array.from({ length: count }, (_, i) => ({
      id: i,
      left: Math.random() * 100,
      cx: (Math.random() - 0.5) * 280,
      cr: (Math.random() - 0.5) * 720,
      cd: 2400 + Math.random() * 1600,    // slower drift
      delay: Math.random() * 600,         // staggered, not a burst
      size: 14 + Math.random() * 10,
      color: ['var(--primary)', 'var(--secondary)', 'var(--tertiary)', 'var(--accent)'][i % 4],
      shape: i % 3,                       // 0 leaf, 1 petal, 2 seed
    }));
  }
  if (!active) return null;
  return (
    <div style={{ position: 'fixed', inset: 0, pointerEvents: 'none', zIndex: 1000, overflow: 'hidden' }}>
      {pieces.current.map(p => (
        <div
          key={p.id}
          className="leaf-drift"
          style={{
            position: 'absolute',
            left: `${p.left}%`,
            top: '-24px',
            width: p.size, height: p.size,
            color: p.color,
            animationDelay: `${p.delay}ms`,
            '--cx': `${p.cx}px`,
            '--cr': `${p.cr}deg`,
            '--cd': `${p.cd}ms`,
          }}
        >
          {p.shape === 0 ? (
            // teardrop leaf
            <svg viewBox="0 0 24 24" width="100%" height="100%">
              <path d="M12 2 C 6 8, 4 14, 12 22 C 20 14, 18 8, 12 2 Z" fill="currentColor" opacity="0.85"/>
              <path d="M12 4 L12 20" stroke="rgba(0,0,0,0.25)" strokeWidth="0.8" fill="none"/>
            </svg>
          ) : p.shape === 1 ? (
            // round petal
            <svg viewBox="0 0 24 24" width="100%" height="100%">
              <ellipse cx="12" cy="12" rx="9" ry="6" fill="currentColor" opacity="0.8"/>
            </svg>
          ) : (
            // tiny seed/ember
            <svg viewBox="0 0 24 24" width="100%" height="100%">
              <circle cx="12" cy="12" r="4" fill="currentColor" opacity="0.9"/>
            </svg>
          )}
        </div>
      ))}
    </div>
  );
}

// ============================================================
// BUTTON — soft press with footstep step-down
// ============================================================
function Btn({ children, onClick, variant = 'default', size = 'md', disabled, style, className = '', icon, ...rest }) {
  const [pressing, setPressing] = useState(false);
  const cls = [
    'btn',
    variant === 'primary'   && 'btn-primary',
    variant === 'secondary' && 'btn-secondary',
    variant === 'tertiary'  && 'btn-tertiary',
    variant === 'ghost'     && 'btn-ghost',
    size === 'sm' && 'btn-sm',
    size === 'lg' && 'btn-lg',
    size === 'xl' && 'btn-xl',
    pressing && 'squish',
    className,
  ].filter(Boolean).join(' ');
  return (
    <button
      className={cls}
      disabled={disabled}
      onClick={(e) => {
        if (disabled) return;
        setPressing(true);
        setTimeout(() => setPressing(false), 380);
        onClick?.(e);
      }}
      style={style}
      {...rest}
    >
      {icon}
      {children}
    </button>
  );
}

// ============================================================
// PROGRESS BAR — bouncy fill
// ============================================================
function ProgressBar({ value, max = 1, color, height = 18, showLabel = false }) {
  const pct = Math.max(0, Math.min(1, value / max)) * 100;
  return (
    <div className="bar" style={{ height }}>
      <div className="bar-fill" style={{ width: `${pct}%`, background: color || 'var(--primary)' }}/>
      {showLabel && (
        <div style={{ position: 'absolute', inset: 0, display: 'grid', placeItems: 'center', fontSize: 11, fontWeight: 800, color: 'var(--ink)' }}>
          {Math.round(pct)}%
        </div>
      )}
    </div>
  );
}

// ============================================================
// STREAK BADGE — flame icon + day count
// ============================================================
function StreakBadge({ days }) {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      padding: '8px 14px',
      background: 'var(--tertiary)',
      border: 'var(--outline-width) solid var(--line)',
      borderRadius: 'var(--radius-pill)',
      boxShadow: 'var(--shadow-pop-sm)',
      fontWeight: 900,
      color: '#3D1F1A',
    }}>
      <svg width="22" height="22" viewBox="0 0 24 24" className={days > 0 ? 'wiggle' : ''} style={{ animationIterationCount: 'infinite', animationDuration: '2s' }}>
        <path d="M 12 2 C 14 6, 18 8, 18 14 C 18 18, 15 21, 12 21 C 9 21, 6 18, 6 14 C 6 10, 9 8, 10 6 C 11 8, 12 7, 12 2 Z"
              fill="var(--primary)"/>
        <path d="M 12 10 C 13 12, 15 13, 15 16 C 15 18, 13.5 19.5, 12 19.5 C 10.5 19.5, 9 18, 9 16 C 9 14, 10.5 13, 11 12 Z"
              fill="var(--tertiary)"/>
      </svg>
      <span style={{ fontFamily: 'var(--font-display)', color: '#3D1F1A' }}>{days}</span>
      <span style={{ fontSize: 12, fontWeight: 800, color: '#3D1F1A', opacity: 0.7, textTransform: 'uppercase', letterSpacing: '0.04em' }}>day{days === 1 ? '' : 's'}</span>
    </div>
  );
}

// ============================================================
// ICON — minimal stroke icon set
// ============================================================
function Icon({ name, size = 20, color = 'currentColor', strokeWidth = 2 }) {
  const props = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'arrow-left':  return <svg {...props}><path d="M19 12H5M12 19l-7-7 7-7"/></svg>;
    case 'arrow-right': return <svg {...props}><path d="M5 12h14M12 5l7 7-7 7"/></svg>;
    case 'check':       return <svg {...props}><path d="M20 6L9 17l-5-5"/></svg>;
    case 'x':           return <svg {...props}><path d="M18 6L6 18M6 6l12 12"/></svg>;
    case 'plus':        return <svg {...props}><path d="M12 5v14M5 12h14"/></svg>;
    case 'lightning':   return <svg {...props}><path d="M13 2L3 14h7l-1 8 10-12h-7l1-8z" fill={color}/></svg>;
    case 'sparkle':     return <svg {...props}><path d="M12 3l2 6 6 2-6 2-2 6-2-6-6-2 6-2z"/></svg>;
    case 'briefcase':   return <svg {...props}><rect x="3" y="7" width="18" height="13" rx="2"/><path d="M8 7V5a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>;
    case 'database':    return <svg {...props}><ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></svg>;
    case 'book':        return <svg {...props}><path d="M4 4h11a4 4 0 014 4v12H8a4 4 0 01-4-4V4z"/><path d="M4 16a4 4 0 014-4h11"/></svg>;
    case 'clock':       return <svg {...props}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>;
    case 'flame':       return <svg {...props}><path d="M12 2c2 4 6 6 6 12a6 6 0 01-12 0c0-3 2-5 3-7 1 2 2 1 3-5z" fill={color} stroke={color}/></svg>;
    case 'target':      return <svg {...props}><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1.5" fill={color} stroke="none"/></svg>;
    case 'chart':       return <svg {...props}><path d="M3 20h18"/><path d="M6 20V11M11 20V6M16 20v-7M21 20v-4"/></svg>;
    case 'cards':       return <svg {...props}><rect x="3" y="6" width="14" height="14" rx="2"/><path d="M7 6V4a2 2 0 012-2h10a2 2 0 012 2v12a2 2 0 01-2 2h-2"/></svg>;
    case 'pencil':      return <svg {...props}><path d="M16 3l5 5L8 21H3v-5L16 3z"/><path d="M14 5l5 5"/></svg>;
    case 'fire':        return <svg {...props}><path d="M12 2c2 4 6 6 6 12a6 6 0 01-12 0c0-3 2-5 3-7 1 2 2 1 3-5z" fill={color} stroke={color}/><path d="M12 10c1 2 3 3 3 6a3 3 0 01-6 0c0-1.5 1-2.5 1.5-3.5z" fill="var(--surface)" stroke="none"/></svg>;
    default:            return <svg {...props}><circle cx="12" cy="12" r="9"/></svg>;
  }
}

Object.assign(window, { Mascot, Confetti, Btn, ProgressBar, StreakBadge, Icon, Sfx });
