function PeperNinja({ onClose }) {
  const W = 480;
  const H = 720;
  const GAME_TIME = 60;
  const FRUITS = ["🌶️", "🫑", "🍅", "🥕", "🌽", "🍆"];
  const BADS = ["🧊", "💣"];

  const [phase, setPhase] = React.useState("intro");
  const [score, setScore] = React.useState(0);
  const [best, setBest] = React.useState(() => {
    try { return parseInt(localStorage.getItem("peper-ninja-best") || "0", 10) || 0; }
    catch { return 0; }
  });
  const [combo, setCombo] = React.useState(0);
  const [lives, setLives] = React.useState(3);
  const [scale, setScale] = React.useState(1);
  const [narrow, setNarrow] = React.useState(typeof window !== "undefined" && window.innerWidth <= 600);
  const [, forceRender] = React.useReducer(x => x + 1, 0);

  const wrapRef = React.useRef(null);
  const canvasRef = React.useRef(null);
  const gRef = React.useRef(null);
  const rafRef = React.useRef(0);
  const phaseRef = React.useRef("intro");
  const scoreRef = React.useRef(0);
  const livesRef = React.useRef(3);
  const comboRef = React.useRef(0);

  React.useEffect(() => { phaseRef.current = phase; }, [phase]);

  React.useEffect(() => {
    function measure() {
      setNarrow(window.innerWidth <= 600);
      if (!wrapRef.current) return;
      var r = wrapRef.current.getBoundingClientRect();
      if (r.width > 0 && r.height > 0)
        setScale(Math.max(0.3, Math.min(r.width / W, r.height / H)));
    }
    measure();
    var ro;
    if (typeof ResizeObserver !== "undefined" && wrapRef.current) {
      ro = new ResizeObserver(measure);
      ro.observe(wrapRef.current);
    }
    window.addEventListener("resize", measure);
    return function() { if (ro) ro.disconnect(); window.removeEventListener("resize", measure); };
  }, []);

  React.useEffect(() => {
    var prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return function() { document.body.style.overflow = prev; };
  }, []);

  function makeGame() {
    return {
      items: [],
      slashes: [],
      particles: [],
      splats: [],
      t: 0,
      timeLeft: GAME_TIME,
      spawnTimer: 0,
      nextId: 0,
      missed: 0,
      trail: [],
      pointerDown: false,
      pointerX: 0,
      pointerY: 0,
      flash: 0,
      comboTimer: 0,
      hurtTimer: 0,
    };
  }

  var cryImg = React.useRef(null);
  React.useEffect(function() {
    var img = new Image();
    img.src = "/assets/ninja-cry.png";
    cryImg.current = img;
  }, []);

  function startGame() {
    gRef.current = makeGame();
    scoreRef.current = 0;
    livesRef.current = 3;
    comboRef.current = 0;
    setScore(0);
    setLives(3);
    setCombo(0);
    setPhase("playing");
  }

  React.useEffect(() => {
    function onKey(e) {
      if (e.key === "Escape") { onClose && onClose(); return; }
      if ((phaseRef.current === "intro" || phaseRef.current === "dead") && (e.key === " " || e.key === "Enter")) {
        e.preventDefault(); startGame();
      }
    }
    window.addEventListener("keydown", onKey);
    return function() { window.removeEventListener("keydown", onKey); };
  }, []);

  function toCanvasCoords(e, canvas) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: (e.clientX - rect.left) / rect.width * W,
      y: (e.clientY - rect.top) / rect.height * H,
    };
  }

  React.useEffect(() => {
    if (phase !== "playing" && phase !== "dead") {
      cancelAnimationFrame(rafRef.current);
      return;
    }
    var canvas = canvasRef.current;
    if (!canvas) return;
    var ctx = canvas.getContext("2d");
    var lastT = performance.now();

    function onPD(e) {
      e.preventDefault();
      var g = gRef.current; if (!g) return;
      var t = e.touches ? e.touches[0] : e;
      var p = toCanvasCoords(t, canvas);
      g.pointerDown = true;
      g.pointerX = p.x;
      g.pointerY = p.y;
      g.trail = [{ x: p.x, y: p.y, t: performance.now() }];
    }
    function onPM(e) {
      e.preventDefault();
      var g = gRef.current; if (!g || !g.pointerDown) return;
      var t = e.touches ? e.touches[0] : e;
      var p = toCanvasCoords(t, canvas);
      var prevX = g.pointerX, prevY = g.pointerY;
      g.pointerX = p.x;
      g.pointerY = p.y;
      g.trail.push({ x: p.x, y: p.y, t: performance.now() });
      if (g.trail.length > 20) g.trail.shift();

      if (phaseRef.current !== "playing") return;
      var speed = Math.sqrt((p.x - prevX) * (p.x - prevX) + (p.y - prevY) * (p.y - prevY));
      if (speed < 3) return;

      for (var i = g.items.length - 1; i >= 0; i--) {
        var it = g.items[i];
        if (it.sliced) continue;
        var dx = p.x - it.x, dy = p.y - it.y;
        var dist = Math.sqrt(dx * dx + dy * dy);
        if (dist < it.r + 10) {
          it.sliced = true;
          var ang = Math.atan2(p.y - prevY, p.x - prevX);

          if (it.bad) {
            livesRef.current--;
            setLives(livesRef.current);
            g.flash = 1;
            g.hurtTimer = 1.0;
            comboRef.current = 0;
            setCombo(0);
            for (var j = 0; j < 12; j++) {
              var pa = Math.random() * Math.PI * 2;
              var pv = 100 + Math.random() * 200;
              g.particles.push({
                id: g.nextId++, x: it.x, y: it.y,
                vx: Math.cos(pa) * pv, vy: Math.sin(pa) * pv,
                life: 0.6, r: 3 + Math.random() * 3,
                c: it.emoji === "🧊" ? "#88DDFF" : "#FF4444",
              });
            }
            if (livesRef.current <= 0) {
              setBest(function(prev) {
                if (scoreRef.current > prev) {
                  try { localStorage.setItem("peper-ninja-best", String(scoreRef.current)); } catch(ex) {}
                  return scoreRef.current;
                }
                return prev;
              });
              setPhase("dead");
            }
          } else {
            comboRef.current++;
            setCombo(comboRef.current);
            g.comboTimer = 1.5;
            var pts = comboRef.current >= 5 ? 5 : comboRef.current >= 3 ? 3 : 1;
            scoreRef.current += pts;
            setScore(scoreRef.current);

            var halfL = { emoji: it.emoji, x: it.x - 8, y: it.y, vx: it.vx - 60, vy: it.vy - 30, rot: -3, life: 1.2, r: it.r };
            var halfR = { emoji: it.emoji, x: it.x + 8, y: it.y, vx: it.vx + 60, vy: it.vy - 30, rot: 3, life: 1.2, r: it.r };
            g.splats.push(halfL, halfR);

            var colors = ["#E63946", "#FF8C1A", "#FFD23F", "#3FA34D"];
            for (var k = 0; k < 8; k++) {
              var pa2 = ang + (Math.random() - 0.5) * 1.5;
              var pv2 = 80 + Math.random() * 150;
              g.particles.push({
                id: g.nextId++, x: it.x, y: it.y,
                vx: Math.cos(pa2) * pv2, vy: Math.sin(pa2) * pv2,
                life: 0.5 + Math.random() * 0.3,
                r: 2 + Math.random() * 4,
                c: colors[Math.floor(Math.random() * colors.length)],
              });
            }

            g.slashes.push({
              x1: prevX, y1: prevY, x2: p.x, y2: p.y,
              life: 0.4, id: g.nextId++,
            });
          }
        }
      }
    }
    function onPU() {
      var g = gRef.current; if (!g) return;
      g.pointerDown = false;
    }

    canvas.addEventListener("mousedown", onPD);
    canvas.addEventListener("mousemove", onPM);
    canvas.addEventListener("mouseup", onPU);
    canvas.addEventListener("mouseleave", onPU);
    canvas.addEventListener("touchstart", onPD, { passive: false });
    canvas.addEventListener("touchmove", onPM, { passive: false });
    canvas.addEventListener("touchend", onPU);

    function spawnItem(g) {
      var side = Math.random();
      var x, vx;
      if (side < 0.4) { x = 30 + Math.random() * 100; vx = 40 + Math.random() * 80; }
      else if (side < 0.8) { x = W - 30 - Math.random() * 100; vx = -40 - Math.random() * 80; }
      else { x = 100 + Math.random() * (W - 200); vx = (Math.random() - 0.5) * 100; }

      var isBad = Math.random() < 0.15 + g.t * 0.001;
      var emoji, r;
      if (isBad) {
        emoji = BADS[Math.floor(Math.random() * BADS.length)];
        r = 40;
      } else {
        emoji = FRUITS[Math.floor(Math.random() * FRUITS.length)];
        r = 38 + Math.random() * 8;
      }

      g.items.push({
        id: g.nextId++,
        x: x,
        y: H + 40,
        vx: vx,
        vy: -580 - Math.random() * 200 - Math.min(80, g.t * 1),
        emoji: emoji,
        r: r,
        rot: 0,
        rotV: (Math.random() - 0.5) * 8,
        sliced: false,
        bad: isBad,
        counted: false,
      });
    }

    function loop(ts) {
      var dt = Math.min(0.035, (ts - lastT) / 1000);
      lastT = ts;
      var g = gRef.current;
      if (!g) { rafRef.current = requestAnimationFrame(loop); return; }

      if (phaseRef.current === "playing") {
        g.t += dt;
        g.timeLeft -= dt;
        if (g.timeLeft <= 0) {
          g.timeLeft = 0;
          setBest(function(prev) {
            if (scoreRef.current > prev) {
              try { localStorage.setItem("peper-ninja-best", String(scoreRef.current)); } catch(ex) {}
              return scoreRef.current;
            }
            return prev;
          });
          setPhase("dead");
        }

        g.spawnTimer -= dt;
        if (g.spawnTimer <= 0) {
          var count = 1 + Math.floor(g.t / 15);
          count = Math.min(count, 4);
          for (var s = 0; s < count; s++) {
            setTimeout(function() { if (gRef.current) spawnItem(gRef.current); }, s * 120);
          }
          g.spawnTimer = Math.max(0.5, 1.8 - g.t * 0.015);
        }

        g.comboTimer -= dt;
        if (g.comboTimer <= 0 && comboRef.current > 0) {
          comboRef.current = 0;
          setCombo(0);
        }

        for (var i = g.items.length - 1; i >= 0; i--) {
          var it = g.items[i];
          it.x += it.vx * dt;
          it.y += it.vy * dt;
          it.vy += 700 * dt;
          it.rot += it.rotV * dt;

          if (it.y > H + 60 && !it.sliced && !it.bad && !it.counted) {
            it.counted = true;
            g.missed++;
            if (g.missed % 3 === 0) {
              livesRef.current--;
              setLives(livesRef.current);
              if (livesRef.current <= 0) {
                setBest(function(prev) {
                  if (scoreRef.current > prev) {
                    try { localStorage.setItem("peper-ninja-best", String(scoreRef.current)); } catch(ex) {}
                    return scoreRef.current;
                  }
                  return prev;
                });
                setPhase("dead");
              }
            }
          }
        }
        g.items = g.items.filter(function(it) { return it.y < H + 100; });
      }

      g.splats = g.splats.filter(function(s) {
        s.x += s.vx * dt;
        s.y += s.vy * dt;
        s.vy += 600 * dt;
        s.rot += (s.rot > 0 ? 4 : -4) * dt;
        s.life -= dt;
        return s.life > 0;
      });

      g.particles = g.particles.filter(function(p) {
        p.x += p.vx * dt;
        p.y += p.vy * dt;
        p.vy += 500 * dt;
        p.life -= dt;
        return p.life > 0;
      });

      g.slashes = g.slashes.filter(function(s) {
        s.life -= dt;
        return s.life > 0;
      });

      g.flash = Math.max(0, g.flash - dt * 3);
      g.hurtTimer = Math.max(0, g.hurtTimer - dt);

      var now = performance.now();
      g.trail = g.trail.filter(function(t) { return now - t.t < 150; });

      // === RENDER ===
      ctx.clearRect(0, 0, W, H);

      // achtergrond - kleurrijke lucht met gradient
      var bgGrad = ctx.createLinearGradient(0, 0, 0, H);
      bgGrad.addColorStop(0, "#1A2744");
      bgGrad.addColorStop(0.3, "#2D4A7A");
      bgGrad.addColorStop(0.6, "#4A7AB5");
      bgGrad.addColorStop(0.85, "#7BC8E8");
      bgGrad.addColorStop(1, "#A8E6CF");
      ctx.fillStyle = bgGrad;
      ctx.fillRect(0, 0, W, H);

      // sterretjes/lichtpuntjes in de lucht
      ctx.fillStyle = "#FFF";
      for (var si2 = 0; si2 < 20; si2++) {
        var sx = (si2 * 97 + 13) % W;
        var sy = (si2 * 53 + 7) % (H * 0.5);
        var sAlpha = 0.2 + Math.sin(g.t * 2 + si2) * 0.15;
        ctx.globalAlpha = sAlpha;
        ctx.beginPath();
        ctx.arc(sx, sy, 1.5, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.globalAlpha = 1;

      // zachte wolken onderaan
      ctx.fillStyle = "rgba(255,255,255,0.08)";
      for (var ci = 0; ci < 4; ci++) {
        var cx2 = ((ci * 150 + g.t * 8) % (W + 200)) - 100;
        var cy2 = H - 80 - ci * 40;
        ctx.beginPath();
        ctx.ellipse(cx2, cy2, 80, 25, 0, 0, Math.PI * 2);
        ctx.fill();
      }

      // slash trails - gloeiend wit/geel
      for (var si = 0; si < g.slashes.length; si++) {
        var sl = g.slashes[si];
        ctx.save();
        ctx.globalAlpha = sl.life * 2.5;
        // brede glow
        ctx.strokeStyle = "#FFD23F";
        ctx.lineWidth = 10;
        ctx.shadowColor = "#FFD23F";
        ctx.shadowBlur = 20;
        ctx.lineCap = "round";
        ctx.beginPath();
        ctx.moveTo(sl.x1, sl.y1);
        ctx.lineTo(sl.x2, sl.y2);
        ctx.stroke();
        // scherpe witte kern
        ctx.strokeStyle = "#FFF";
        ctx.lineWidth = 3;
        ctx.shadowBlur = 8;
        ctx.beginPath();
        ctx.moveTo(sl.x1, sl.y1);
        ctx.lineTo(sl.x2, sl.y2);
        ctx.stroke();
        ctx.restore();
      }

      // finger trail - dikkere, kleurrijkere trail
      if (g.pointerDown && g.trail.length > 1) {
        ctx.save();
        ctx.lineCap = "round";
        ctx.lineJoin = "round";
        for (var ti = 1; ti < g.trail.length; ti++) {
          var age = (now - g.trail[ti].t) / 150;
          ctx.globalAlpha = Math.max(0, (1 - age) * 0.85);
          // buitenste glow
          ctx.strokeStyle = "#FF8C1A";
          ctx.lineWidth = Math.max(2, (1 - age) * 12);
          ctx.shadowColor = "#FFD23F";
          ctx.shadowBlur = 12;
          ctx.beginPath();
          ctx.moveTo(g.trail[ti - 1].x, g.trail[ti - 1].y);
          ctx.lineTo(g.trail[ti].x, g.trail[ti].y);
          ctx.stroke();
          // witte kern
          ctx.strokeStyle = "#FFF";
          ctx.lineWidth = Math.max(1, (1 - age) * 4);
          ctx.shadowBlur = 0;
          ctx.beginPath();
          ctx.moveTo(g.trail[ti - 1].x, g.trail[ti - 1].y);
          ctx.lineTo(g.trail[ti].x, g.trail[ti].y);
          ctx.stroke();
        }
        ctx.restore();
      }

      // items (niet gesneden) - groter en met gekleurde cirkel erachter
      for (var ii = 0; ii < g.items.length; ii++) {
        var item = g.items[ii];
        if (item.sliced) continue;
        ctx.save();
        ctx.translate(item.x, item.y);
        ctx.rotate(item.rot);

        // gekleurde cirkel achter het item
        if (!item.bad) {
          var itemColors = { "🌶️": "#E63946", "🫑": "#3FA34D", "🍅": "#E63946", "🥕": "#FF8C1A", "🌽": "#FFD23F", "🍆": "#8E44D1" };
          ctx.fillStyle = itemColors[item.emoji] || "#FF8C1A";
          ctx.globalAlpha = 0.3;
          ctx.beginPath();
          ctx.arc(0, 0, item.r * 0.9, 0, Math.PI * 2);
          ctx.fill();
          ctx.globalAlpha = 1;
        }

        // schaduw
        ctx.shadowColor = "rgba(0,0,0,0.4)";
        ctx.shadowBlur = 8;
        ctx.shadowOffsetY = 4;

        if (item.bad) {
          // Teken bad items handmatig (geen emoji, die zijn onzichtbaar)
          var pulse = 0.6 + Math.sin(g.t * 10) * 0.4;
          var sz = item.r;

          if (item.emoji === "🧊") {
            // IJsblok: lichtblauw vierkant met glans
            ctx.shadowColor = "#44CCFF";
            ctx.shadowBlur = 20;
            ctx.fillStyle = "#88DDFF";
            ctx.beginPath();
            ctx.roundRect(-sz * 0.7, -sz * 0.7, sz * 1.4, sz * 1.4, 8);
            ctx.fill();
            ctx.fillStyle = "#BBEEFF";
            ctx.beginPath();
            ctx.roundRect(-sz * 0.5, -sz * 0.5, sz * 0.5, sz * 0.7, 4);
            ctx.fill();
            ctx.strokeStyle = "#FFF";
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.roundRect(-sz * 0.7, -sz * 0.7, sz * 1.4, sz * 1.4, 8);
            ctx.stroke();
            ctx.shadowBlur = 0;
            // sneeuwvlok-symbool
            ctx.font = "bold " + (sz * 0.9) + "px sans-serif";
            ctx.fillStyle = "#FFF";
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            ctx.fillText("❄", 0, 0);
          } else {
            // Bom: zwarte cirkel met lont
            ctx.shadowColor = "#FF4444";
            ctx.shadowBlur = 20;
            ctx.fillStyle = "#222";
            ctx.beginPath();
            ctx.arc(0, 4, sz * 0.75, 0, Math.PI * 2);
            ctx.fill();
            ctx.strokeStyle = "#444";
            ctx.lineWidth = 2;
            ctx.stroke();
            // glans
            ctx.fillStyle = "#555";
            ctx.beginPath();
            ctx.arc(-sz * 0.2, -sz * 0.1, sz * 0.25, 0, Math.PI * 2);
            ctx.fill();
            // lont
            ctx.strokeStyle = "#AA8844";
            ctx.lineWidth = 3;
            ctx.beginPath();
            ctx.moveTo(0, -sz * 0.7);
            ctx.quadraticCurveTo(sz * 0.4, -sz * 1.1, sz * 0.2, -sz * 1.2);
            ctx.stroke();
            // vonk op lont
            ctx.fillStyle = "#FFD23F";
            ctx.shadowColor = "#FF8C1A";
            ctx.shadowBlur = 12 + pulse * 8;
            ctx.beginPath();
            ctx.arc(sz * 0.2, -sz * 1.2, 5 + pulse * 3, 0, Math.PI * 2);
            ctx.fill();
            ctx.fillStyle = "#FFF";
            ctx.beginPath();
            ctx.arc(sz * 0.2, -sz * 1.2, 2, 0, Math.PI * 2);
            ctx.fill();
            ctx.shadowBlur = 0;
          }

          // pulsende waarschuwingsring
          ctx.strokeStyle = item.emoji === "🧊" ? "#44CCFF" : "#FF4444";
          ctx.lineWidth = 3;
          ctx.globalAlpha = pulse * 0.6;
          ctx.beginPath();
          ctx.arc(0, 0, sz + 12 + pulse * 8, 0, Math.PI * 2);
          ctx.stroke();
          ctx.globalAlpha = 1;

          ctx.restore();
          continue;
        }

        ctx.font = item.r * 2 + "px serif";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText(item.emoji, 0, 0);
        ctx.restore();
      }

      // gesneden helften - groter
      for (var spi = 0; spi < g.splats.length; spi++) {
        var sp = g.splats[spi];
        ctx.save();
        ctx.globalAlpha = Math.max(0, sp.life / 1.2);
        ctx.translate(sp.x, sp.y);
        ctx.rotate(sp.rot);
        ctx.font = sp.r * 1.6 + "px serif";
        ctx.textAlign = "center";
        ctx.textBaseline = "middle";
        ctx.fillText(sp.emoji, 0, 0);
        ctx.restore();
      }

      // deeltjes - groter en met glow
      for (var pi = 0; pi < g.particles.length; pi++) {
        var pp = g.particles[pi];
        ctx.globalAlpha = Math.max(0, pp.life * 2);
        ctx.fillStyle = pp.c;
        ctx.shadowColor = pp.c;
        ctx.shadowBlur = 6;
        ctx.beginPath();
        ctx.arc(pp.x, pp.y, pp.r * 1.3, 0, Math.PI * 2);
        ctx.fill();
      }
      ctx.globalAlpha = 1;
      ctx.shadowBlur = 0;
      ctx.shadowColor = "transparent";

      // timer balk bovenaan - breder en duidelijker
      if (phaseRef.current === "playing") {
        var barW = W - 20;
        var barFrac = Math.max(0, g.timeLeft / GAME_TIME);
        ctx.fillStyle = "rgba(0,0,0,0.5)";
        ctx.beginPath(); ctx.roundRect(10, 10, barW, 18, 9); ctx.fill();
        ctx.fillStyle = barFrac > 0.3 ? "#3FA34D" : barFrac > 0.1 ? "#FF8C1A" : "#E63946";
        ctx.shadowColor = barFrac > 0.3 ? "#3FA34D" : barFrac > 0.1 ? "#FF8C1A" : "#E63946";
        ctx.shadowBlur = 6;
        ctx.beginPath(); ctx.roundRect(10, 10, barW * barFrac, 18, 9); ctx.fill();
        ctx.shadowBlur = 0;
        ctx.fillStyle = "#FFF";
        ctx.font = "bold 12px 'Bangers', sans-serif";
        ctx.textAlign = "center";
        ctx.fillText(Math.ceil(g.timeLeft) + "s", W / 2, 23);
      }

      // score groot in beeld
      if (phaseRef.current === "playing") {
        ctx.save();
        ctx.font = "bold 56px 'Bangers', sans-serif";
        ctx.textAlign = "center";
        ctx.fillStyle = "#FFF";
        ctx.strokeStyle = "#1A1A1A";
        ctx.lineWidth = 5;
        ctx.shadowColor = "rgba(0,0,0,0.5)";
        ctx.shadowBlur = 8;
        ctx.shadowOffsetY = 3;
        ctx.strokeText(scoreRef.current, W / 2, 68);
        ctx.shadowBlur = 0;
        ctx.fillText(scoreRef.current, W / 2, 68);

        if (comboRef.current >= 3) {
          ctx.font = "bold 32px 'Bangers', sans-serif";
          ctx.fillStyle = comboRef.current >= 5 ? "#FF4444" : "#FFD23F";
          ctx.strokeStyle = "#1A1A1A";
          ctx.lineWidth = 3;
          var comboText = "🔥 " + comboRef.current + "x COMBO!";
          ctx.strokeText(comboText, W / 2, 102);
          ctx.fillText(comboText, W / 2, 102);
        }
        ctx.restore();
      }

      // levens - groter
      if (phaseRef.current === "playing") {
        ctx.font = "28px serif";
        ctx.textAlign = "left";
        for (var hi = 0; hi < 3; hi++) {
          ctx.globalAlpha = hi < livesRef.current ? 1 : 0.2;
          ctx.fillText("🌶️", 14 + hi * 34, H - 16);
        }
        ctx.globalAlpha = 1;
      }

      // hurt overlay: rood scherm + huilende ninja
      if (g.hurtTimer > 0) {
        var hAlpha = Math.min(1, g.hurtTimer * 2);
        // rood scherm
        ctx.fillStyle = "rgba(180,10,10," + (hAlpha * 0.55) + ")";
        ctx.fillRect(0, 0, W, H);
        // vignet (donkere randen)
        var vig = ctx.createRadialGradient(W / 2, H / 2, H * 0.2, W / 2, H / 2, H * 0.7);
        vig.addColorStop(0, "rgba(0,0,0,0)");
        vig.addColorStop(1, "rgba(0,0,0," + (hAlpha * 0.5) + ")");
        ctx.fillStyle = vig;
        ctx.fillRect(0, 0, W, H);
        // huilende ninja afbeelding
        if (cryImg.current && cryImg.current.complete) {
          ctx.globalAlpha = hAlpha;
          var imgS = 280;
          var imgY = H / 2 - imgS / 2 - 20;
          ctx.drawImage(cryImg.current, W / 2 - imgS / 2, imgY, imgS, imgS);
          // "AU!" tekst
          ctx.font = "bold 48px 'Bangers', sans-serif";
          ctx.textAlign = "center";
          ctx.fillStyle = "#FFF";
          ctx.strokeStyle = "#8B0000";
          ctx.lineWidth = 4;
          ctx.strokeText("AU!", W / 2, imgY + imgS + 45);
          ctx.fillText("AU!", W / 2, imgY + imgS + 45);
          ctx.globalAlpha = 1;
        }
      } else if (g.flash > 0) {
        ctx.fillStyle = "rgba(255,30,30," + (g.flash * 0.3) + ")";
        ctx.fillRect(0, 0, W, H);
      }

      rafRef.current = requestAnimationFrame(loop);
    }
    rafRef.current = requestAnimationFrame(loop);
    return function() {
      cancelAnimationFrame(rafRef.current);
      canvas.removeEventListener("mousedown", onPD);
      canvas.removeEventListener("mousemove", onPM);
      canvas.removeEventListener("mouseup", onPU);
      canvas.removeEventListener("mouseleave", onPU);
      canvas.removeEventListener("touchstart", onPD);
      canvas.removeEventListener("touchmove", onPM);
      canvas.removeEventListener("touchend", onPU);
    };
  }, [phase]);

  function Pill({ bg, color, narrow: n, children }) {
    return (
      <span style={{
        background: bg, color: color, border: "3px solid #1A1A1A",
        boxShadow: "2px 2px 0 #1A1A1A",
        padding: n ? "4px 8px" : "6px 12px",
        fontFamily: "'Bangers', sans-serif",
        fontSize: n ? 16 : 20, letterSpacing: "0.04em",
      }}>{children}</span>
    );
  }

  function Title({ color, children }) {
    return (
      <div style={{
        fontFamily: "'Bangers', sans-serif", fontSize: 44,
        color: color, WebkitTextStroke: "1.5px #1A1A1A",
        textShadow: "3px 3px 0 #1A1A1A", letterSpacing: "0.05em",
        textAlign: "center", margin: 0,
      }}>{children}</div>
    );
  }

  function Overlay({ children }) {
    return (
      <div style={{
        position: "absolute", inset: 0,
        background: "rgba(15,10,5,0.88)",
        display: "flex", flexDirection: "column",
        alignItems: "center", justifyContent: "center",
        padding: 20, gap: 12, color: "#FFF8EC", zIndex: 5,
      }}>{children}</div>
    );
  }

  function BigBtn({ onClick, color, children }) {
    return (
      <button onClick={onClick} style={{
        background: color, color: "#FFF",
        border: "4px solid #1A1A1A", boxShadow: "4px 4px 0 #1A1A1A",
        fontFamily: "'Bangers', sans-serif", fontSize: 28,
        padding: "10px 28px", cursor: "pointer", letterSpacing: "0.04em",
        marginTop: 8,
      }}>{children}</button>
    );
  }

  var oText = { fontSize: 18, lineHeight: 1.5, maxWidth: 420, textAlign: "center", color: "#FFF8EC", margin: 0 };

  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 200,
      background: "#1A2744",
      fontFamily: "'Patrick Hand', cursive", color: "#1A1A1A",
      display: "flex", flexDirection: "column",
      overscrollBehavior: "contain", touchAction: "none",
    }}>
      <div style={{
        flexShrink: 0,
        display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: narrow ? "8px 10px" : "10px 16px", gap: 8,
        background: "rgba(255,245,220,0.96)", borderBottom: "3px solid #1A1A1A",
      }}>
        <div style={{
          fontFamily: "'Bangers', sans-serif", fontSize: narrow ? 22 : 28,
          letterSpacing: "0.04em", color: "#E63946",
          WebkitTextStroke: "1.2px #1A1A1A", textShadow: "2px 2px 0 #1A1A1A",
          display: "flex", alignItems: "center", gap: 6, whiteSpace: "nowrap",
        }}>
          <span style={{ fontSize: narrow ? 20 : 24, WebkitTextStroke: 0, textShadow: "none" }}>🥷</span>
          {narrow ? "NINJA" : "PEPER NINJA"}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: narrow ? 6 : 10 }}>
          <Pill bg="#FFD23F" color="#1A1A1A" narrow={narrow}>⚡ {score}</Pill>
          <Pill bg="#FF8C1A" color="#FFF" narrow={narrow}>🏆 {best}</Pill>
          <button onClick={onClose} aria-label="Sluiten" style={{
            width: 44, height: 44, borderRadius: "50%",
            background: "#1A1A1A", color: "#F0FAE6",
            border: "3px solid #F0FAE6", boxShadow: "2px 2px 0 #1A1A1A",
            fontFamily: "'Bangers', sans-serif", fontSize: 22,
            cursor: "pointer", flexShrink: 0,
          }}>✕</button>
        </div>
      </div>

      <div ref={wrapRef} style={{
        flex: 1, position: "relative",
        display: "flex", alignItems: "center", justifyContent: "center",
        padding: 6, overflow: "hidden",
      }}>
        <div style={{ width: W * scale, height: H * scale, position: "relative" }}>
          <canvas ref={canvasRef} width={W} height={H}
            style={{
              display: "block", width: W * scale, height: H * scale,
              border: "4px solid #1A1A1A", boxShadow: "5px 5px 0 #1A1A1A",
              touchAction: "none", cursor: "crosshair",
            }} />

          {phase === "intro" && (
            <Overlay>
              <img src="/assets/hete-ninja.png" alt="Hete Peper Ninja"
                style={{ width: 160, height: 160, objectFit: "contain", marginBottom: -4, filter: "drop-shadow(3px 4px 0 #1A1A1A)" }} />
              <Title color="#E63946">PEPER NINJA</Title>
              <p style={oText}>
                Veeg over het scherm om pepers en groenten doormidden te snijden! 🌶️<br />
                <strong>Raak geen ijsblokken 🧊 of bommen 💣 aan!</strong><br />
                Combo's geven extra punten. Laat niet te veel pepers vallen.<br />
                60 seconden, 3 levens!
              </p>
              <BigBtn onClick={startGame} color="#E63946">▶ SNIJ!</BigBtn>
            </Overlay>
          )}

          {phase === "dead" && (
            <Overlay>
              <Title color="#FFD23F">KLAAR!</Title>
              <p style={oText}>
                Score: <strong>{score}</strong>
                {score >= best && score > 0 && <><br /><span style={{ color: "#FF8C1A", fontWeight: "bold" }}>🏆 NIEUW RECORD!</span></>}
                {score < best && <><br />Beste: <strong>{best}</strong></>}
              </p>
              <BigBtn onClick={startGame} color="#3FA34D">↻ NOG EENS</BigBtn>
            </Overlay>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { PeperNinja });
