// peper-schieter.jsx, Angry-Birds-achtige variant. Een boze peper wordt
// met een katapult weggeschoten richting wasknijpers, ijsheksen en slijmpjes
// die op houten torens staan. Schiet alle vijanden om om het level uit te
// spelen. Sleep met je vinger of muis om te mikken, laat los om te schieten.

function Peperschieter({ onClose }) {
  const FIELD_W = 960;
  const FIELD_H = 560;
  const GROUND_Y = 490;
  const SLING_X = 140;
  const SLING_Y = GROUND_Y - 120;
  const PROJ_R = 28;
  const MAX_PULL = 130;
  const POWER = 9;
  const GRAVITY = 1500;
  const MAX_FLIGHT = 5; // seconden, vlucht stopt sowieso na deze tijd

  // levels: vijanden + houten/stenen blokken
  const LEVELS = React.useMemo(() => [
    {
      shots: 3,
      enemies: [
        { type: "wasknijper", x: 660, y: GROUND_Y - 38, r: 32 },
        { type: "wasknijper", x: 800, y: GROUND_Y - 38, r: 32 },
      ],
      blocks: [
        { x: 700, y: GROUND_Y - 14, w: 80, h: 14, hp: 1, mat: "wood" },
      ],
    },
    {
      shots: 4,
      enemies: [
        { type: "ijsheks", x: 680, y: GROUND_Y - 40, r: 34 },
        { type: "wasknijper", x: 820, y: GROUND_Y - 220, r: 32 },
      ],
      blocks: [
        { x: 600, y: GROUND_Y - 160, w: 32, h: 160, hp: 2, mat: "wood" },
        { x: 790, y: GROUND_Y - 160, w: 32, h: 160, hp: 2, mat: "wood" },
        { x: 600, y: GROUND_Y - 192, w: 222, h: 32, hp: 2, mat: "wood" },
        { x: 800, y: GROUND_Y - 220, w: 60, h: 28, hp: 1, mat: "wood" },
      ],
    },
    {
      shots: 5,
      enemies: [
        { type: "slijm", x: 580, y: GROUND_Y - 40, r: 32 },
        { type: "wasknijper", x: 730, y: GROUND_Y - 270, r: 32 },
        { type: "ijsheks", x: 870, y: GROUND_Y - 40, r: 34 },
      ],
      blocks: [
        { x: 670, y: GROUND_Y - 230, w: 30, h: 230, hp: 2, mat: "wood" },
        { x: 770, y: GROUND_Y - 230, w: 30, h: 230, hp: 2, mat: "wood" },
        { x: 670, y: GROUND_Y - 260, w: 130, h: 30, hp: 3, mat: "stone" },
        { x: 820, y: GROUND_Y - 100, w: 30, h: 100, hp: 2, mat: "wood" },
        { x: 900, y: GROUND_Y - 100, w: 30, h: 100, hp: 2, mat: "wood" },
        { x: 820, y: GROUND_Y - 128, w: 110, h: 28, hp: 2, mat: "wood" },
      ],
    },
  ], []);

  const [scale, setScale] = React.useState(1);
  const [narrow, setNarrow] = React.useState(typeof window !== "undefined" && window.innerWidth <= 480);
  const [levelIdx, setLevelIdx] = React.useState(0);
  const [shotsLeft, setShotsLeft] = React.useState(LEVELS[0].shots);
  const [score, setScore] = React.useState(0);
  const [best, setBest] = React.useState(() => {
    try { return parseInt(localStorage.getItem("peper-schieter-best") || "0", 10) || 0; }
    catch { return 0; }
  });
  const [phase, setPhase] = React.useState("intro");
  const [, forceRender] = React.useReducer(x => x + 1, 0);

  const wrapRef = React.useRef(null);
  const fieldRef = React.useRef(null);
  const projRef = React.useRef({ x: SLING_X, y: SLING_Y, vx: 0, vy: 0, rot: 0 });
  const enemiesRef = React.useRef([]);
  const blocksRef = React.useRef([]);
  const particlesRef = React.useRef([]);
  const floatersRef = React.useRef([]); // drijvende score-tekst
  const cloudsRef = React.useRef([]);
  const birdsRef = React.useRef([]);
  const aimRef = React.useRef(null);
  const flightTimeRef = React.useRef(0);
  const shakeRef = React.useRef(0);
  const animTimeRef = React.useRef(0);
  const idRef = React.useRef(0);

  // schaling, mee met viewport
  React.useEffect(() => {
    function measure() {
      setNarrow(window.innerWidth <= 480);
      if (!wrapRef.current) return;
      const r = wrapRef.current.getBoundingClientRect();
      if (r.width > 0 && r.height > 0) {
        setScale(Math.max(0.3, Math.min(r.width / FIELD_W, r.height / FIELD_H)));
      }
    }
    measure();
    let ro;
    if (typeof ResizeObserver !== "undefined" && wrapRef.current) {
      ro = new ResizeObserver(measure);
      ro.observe(wrapRef.current);
    }
    window.addEventListener("resize", measure);
    window.addEventListener("orientationchange", measure);
    return () => {
      if (ro) ro.disconnect();
      window.removeEventListener("resize", measure);
      window.removeEventListener("orientationchange", measure);
    };
  }, []);

  // body-scroll lock
  React.useEffect(() => {
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => { document.body.style.overflow = prev; };
  }, []);

  React.useEffect(() => {
    function onKey(e) { if (e.key === "Escape") onClose && onClose(); }
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  // wolken en vogels in de lucht, drijven traag voorbij
  React.useEffect(() => {
    cloudsRef.current = [
      { id: ++idRef.current, x: 100, y: 80, s: 1.2, vx: 8 },
      { id: ++idRef.current, x: 380, y: 120, s: 0.9, vx: 6 },
      { id: ++idRef.current, x: 640, y: 70, s: 1.4, vx: 10 },
      { id: ++idRef.current, x: 850, y: 150, s: 0.8, vx: 7 },
      { id: ++idRef.current, x: 250, y: 200, s: 0.7, vx: 5 },
    ];
    birdsRef.current = [
      { id: ++idRef.current, x: 200, y: 160, vx: 35, phase: 0 },
      { id: ++idRef.current, x: 520, y: 130, vx: 28, phase: 1.2 },
      { id: ++idRef.current, x: 720, y: 200, vx: 32, phase: 2.4 },
    ];
  }, []);

  // achtergrond animatie loop, draait altijd zodat wolken en vogels bewegen
  React.useEffect(() => {
    let raf = 0;
    let last = performance.now();
    function tick(ts) {
      const dt = Math.min(0.05, (ts - last) / 1000);
      last = ts;
      animTimeRef.current += dt;

      cloudsRef.current.forEach(c => {
        c.x += c.vx * dt;
        if (c.x > FIELD_W + 80) c.x = -80;
      });
      birdsRef.current.forEach(b => {
        b.x += b.vx * dt;
        b.phase += dt * 4;
        if (b.x > FIELD_W + 30) {
          b.x = -30;
          b.y = 80 + Math.random() * 150;
        }
      });

      if (shakeRef.current > 0) shakeRef.current = Math.max(0, shakeRef.current - dt);

      forceRender();
      raf = requestAnimationFrame(tick);
    }
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  function loadLevel(i) {
    const L = LEVELS[i];
    enemiesRef.current = L.enemies.map((e, idx) => ({
      ...e, id: 'e' + i + '-' + idx, alive: true,
      wob: Math.random() * Math.PI * 2,
    }));
    blocksRef.current = L.blocks.map((b, idx) => ({
      ...b, id: 'b' + i + '-' + idx, hp: b.hp, broken: false,
      maxHp: b.hp,
    }));
    particlesRef.current = [];
    floatersRef.current = [];
    setShotsLeft(L.shots);
    projRef.current = { x: SLING_X, y: SLING_Y, vx: 0, vy: 0, rot: 0 };
    flightTimeRef.current = 0;
    setPhase("ready");
  }

  function startGame() {
    setScore(0);
    setLevelIdx(0);
    loadLevel(0);
  }

  function nextLevel() {
    if (levelIdx + 1 < LEVELS.length) {
      const next = levelIdx + 1;
      setLevelIdx(next);
      loadLevel(next);
    } else {
      setPhase("complete");
      setBest(prev => {
        if (score > prev) {
          try { localStorage.setItem("peper-schieter-best", String(score)); } catch {}
          return score;
        }
        return prev;
      });
    }
  }

  function retryLevel() {
    loadLevel(levelIdx);
  }

  function spawnParticles(x, y, color = "#FFD23F", count = 14, kind = "spark") {
    for (let i = 0; i < count; i++) {
      const a = Math.random() * Math.PI * 2;
      const v = 200 + Math.random() * 320;
      particlesRef.current.push({
        id: ++idRef.current,
        x, y,
        vx: Math.cos(a) * v,
        vy: Math.sin(a) * v - 80,
        life: 0.5 + Math.random() * 0.5,
        maxLife: 1,
        color, kind,
        r: 3 + Math.random() * 5,
        rot: Math.random() * Math.PI * 2,
        spin: (Math.random() - 0.5) * 8,
      });
    }
  }

  function spawnFloater(x, y, text, color = "#FFD23F") {
    floatersRef.current.push({
      id: ++idRef.current,
      x, y, text, color,
      life: 1.0,
    });
  }

  function stepProjectile(p, dt) {
    p.x += p.vx * dt;
    p.y += p.vy * dt;
    p.vy += GRAVITY * dt;
    p.rot += dt * (p.vx > 0 ? 8 : -8);
  }

  // game loop tijdens vliegen
  React.useEffect(() => {
    if (phase !== "flying") return;
    let raf = 0;
    let last = performance.now();
    flightTimeRef.current = 0;

    function frame(ts) {
      const dt = Math.min(0.04, (ts - last) / 1000);
      last = ts;
      flightTimeRef.current += dt;

      const p = projRef.current;
      stepProjectile(p, dt);

      let scoreDelta = 0;
      let landed = false;

      // botsing met vijanden
      for (const e of enemiesRef.current) {
        if (!e.alive) continue;
        const dx = p.x - e.x, dy = p.y - e.y;
        if (Math.hypot(dx, dy) < PROJ_R + e.r) {
          e.alive = false;
          scoreDelta += 100;
          spawnParticles(e.x, e.y, "#FFD23F", 22, "spark");
          spawnParticles(e.x, e.y, "#E63946", 12, "puff");
          spawnFloater(e.x, e.y - 20, "+100", "#FFD23F");
          shakeRef.current = 0.25;
          p.vx *= 0.55; p.vy *= 0.55;
        }
      }

      // botsing met blokken (AABB-cirkel met reflectie)
      for (const b of blocksRef.current) {
        if (b.broken) continue;
        const cx = Math.max(b.x, Math.min(p.x, b.x + b.w));
        const cy = Math.max(b.y, Math.min(p.y, b.y + b.h));
        const dx = p.x - cx, dy = p.y - cy;
        const d2 = dx * dx + dy * dy;
        if (d2 < PROJ_R * PROJ_R) {
          const d = Math.sqrt(d2) || 1;
          const nx = dx / d, ny = dy / d;
          const dot = p.vx * nx + p.vy * ny;
          if (dot < 0) {
            const bounce = b.mat === "stone" ? 0.7 : 0.45;
            p.vx = (p.vx - 2 * dot * nx) * bounce;
            p.vy = (p.vy - 2 * dot * ny) * bounce;
          }
          p.x = cx + nx * (PROJ_R + 0.5);
          p.y = cy + ny * (PROJ_R + 0.5);
          b.hp -= 1;
          if (b.hp <= 0) {
            b.broken = true;
            scoreDelta += 30;
            const col = b.mat === "stone" ? "#888880" : "#A06B3F";
            spawnParticles(b.x + b.w / 2, b.y + b.h / 2, col, 18, "chip");
            spawnFloater(b.x + b.w / 2, b.y, "+30", "#FFF8EC");
          } else {
            // kleine splinters bij elke hit
            const col = b.mat === "stone" ? "#AAAAA0" : "#C18E59";
            spawnParticles(p.x, p.y, col, 6, "chip");
          }
          shakeRef.current = Math.max(shakeRef.current, 0.18);
        }
      }

      // grond
      if (p.y + PROJ_R >= GROUND_Y) {
        p.y = GROUND_Y - PROJ_R;
        if (Math.abs(p.vy) > 90) {
          p.vy = -p.vy * 0.4;
          p.vx *= 0.7;
          spawnParticles(p.x, GROUND_Y, "#C8B07A", 8, "puff");
        } else {
          p.vy = 0;
          p.vx *= 0.8;
        }
      }

      // deeltjes-update
      particlesRef.current = particlesRef.current
        .map(d => ({
          ...d,
          x: d.x + d.vx * dt,
          y: d.y + d.vy * dt,
          vy: d.vy + 1100 * dt,
          life: d.life - dt,
          rot: d.rot + d.spin * dt,
        }))
        .filter(d => d.life > 0);

      // floaters-update
      floatersRef.current = floatersRef.current
        .map(f => ({ ...f, y: f.y - 60 * dt, life: f.life - dt }))
        .filter(f => f.life > 0);

      if (scoreDelta) setScore(s => s + scoreDelta);

      // einde-vlucht-checks
      const allDead = enemiesRef.current.filter(e => e.alive).length === 0;
      const slow = Math.abs(p.vx) < 25 && Math.abs(p.vy) < 25 && p.y >= GROUND_Y - PROJ_R - 1;
      const offscreen = p.x > FIELD_W + 60 || p.x < -60 || p.y > FIELD_H + 80;
      const tooLong = flightTimeRef.current > MAX_FLIGHT;

      if (allDead || slow || offscreen || tooLong) landed = true;

      if (landed) {
        setPhase("landed");
        return;
      }

      forceRender();
      raf = requestAnimationFrame(frame);
    }
    raf = requestAnimationFrame(frame);
    return () => cancelAnimationFrame(raf);
  }, [phase]);

  React.useEffect(() => {
    if (phase !== "landed") return;
    const t = setTimeout(() => {
      const aliveEnemies = enemiesRef.current.filter(e => e.alive).length;
      if (aliveEnemies === 0) {
        const bonus = shotsLeft * 50;
        if (bonus) setScore(s => s + bonus);
        setPhase("won");
        return;
      }
      const remaining = shotsLeft - 1;
      if (remaining <= 0) {
        setPhase("lost");
        return;
      }
      setShotsLeft(remaining);
      projRef.current = { x: SLING_X, y: SLING_Y, vx: 0, vy: 0, rot: 0 };
      flightTimeRef.current = 0;
      setPhase("ready");
    }, 600);
    return () => clearTimeout(t);
  }, [phase, shotsLeft]);

  // pointer-aim
  function pointerToField(e) {
    const r = fieldRef.current.getBoundingClientRect();
    return {
      x: ((e.clientX - r.left) / Math.max(1, r.width)) * FIELD_W,
      y: ((e.clientY - r.top) / Math.max(1, r.height)) * FIELD_H,
    };
  }

  function onPointerDown(e) {
    if (phase !== "ready") return;
    aimRef.current = pointerToField(e);
    if (e.currentTarget.setPointerCapture) {
      try { e.currentTarget.setPointerCapture(e.pointerId); } catch {}
    }
    setPhase("aiming");
  }

  function onPointerMove(e) {
    if (phase !== "aiming") return;
    aimRef.current = pointerToField(e);
    forceRender();
  }

  function onPointerUp(e) {
    if (phase !== "aiming") { aimRef.current = null; return; }
    const aim = aimRef.current;
    if (!aim) { setPhase("ready"); return; }
    const dx = aim.x - SLING_X;
    const dy = aim.y - SLING_Y;
    const d = Math.hypot(dx, dy);
    if (d < 18) { aimRef.current = null; setPhase("ready"); return; }
    const pulled = Math.min(d, MAX_PULL);
    const speed = pulled * POWER;
    const vx = -(dx / d) * speed;
    const vy = -(dy / d) * speed;
    projRef.current = { x: SLING_X, y: SLING_Y, vx, vy, rot: 0 };
    aimRef.current = null;
    flightTimeRef.current = 0;
    setPhase("flying");
  }

  function pulledPos() {
    const a = aimRef.current;
    if (!a) return { x: SLING_X, y: SLING_Y };
    const dx = a.x - SLING_X;
    const dy = a.y - SLING_Y;
    const d = Math.hypot(dx, dy);
    if (d <= MAX_PULL) return { x: a.x, y: a.y };
    return { x: SLING_X + (dx / d) * MAX_PULL, y: SLING_Y + (dy / d) * MAX_PULL };
  }

  function trajectoryPoints() {
    if (phase !== "aiming" || !aimRef.current) return [];
    const a = pulledPos();
    const dx = a.x - SLING_X;
    const dy = a.y - SLING_Y;
    const d = Math.hypot(dx, dy);
    if (d < 18) return [];
    const speed = d * POWER;
    const vx = -(dx / d) * speed;
    const vy = -(dy / d) * speed;
    const sim = { x: SLING_X, y: SLING_Y, vx, vy, rot: 0 };
    const pts = [];
    const dt = 1 / 60;
    for (let i = 0; i < 90; i++) {
      stepProjectile(sim, dt);
      if (i % 3 === 0) pts.push({ x: sim.x, y: sim.y });
      if (sim.y > GROUND_Y || sim.x > FIELD_W) break;
    }
    return pts;
  }

  function projectilePos() {
    if (phase === "ready") return { x: SLING_X, y: SLING_Y };
    if (phase === "aiming") return pulledPos();
    return { x: projRef.current.x, y: projRef.current.y };
  }

  const projPos = projectilePos();
  const projRot = phase === "flying" ? projRef.current.rot : 0;
  const traj = trajectoryPoints();
  const aliveCount = enemiesRef.current.filter(e => e.alive).length;
  const totalEnemies = enemiesRef.current.length;
  const power = aimRef.current ? Math.min(MAX_PULL, Math.hypot(
    aimRef.current.x - SLING_X, aimRef.current.y - SLING_Y
  )) / MAX_PULL : 0;

  // screen-shake offset
  const shakeAmt = shakeRef.current * 8;
  const shakeX = shakeAmt > 0 ? (Math.random() - 0.5) * shakeAmt : 0;
  const shakeY = shakeAmt > 0 ? (Math.random() - 0.5) * shakeAmt : 0;

  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 200,
      background: "#0E1747",
      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",
        color: "#1A1A1A",
      }}>
        <div style={{
          fontFamily: "'Bangers', sans-serif",
          fontSize: narrow ? 22 : 28, letterSpacing: "0.04em",
          color: "#FF8C1A",
          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 ? "SCHIETER" : "PEPERSCHIETER"}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: narrow ? 6 : 10 }}>
          {!narrow && phase !== "intro" && (
            <Pill bg="#FFF8EC" color="#1A1A1A">LEVEL {levelIdx + 1}/{LEVELS.length}</Pill>
          )}
          <Pill bg="#E63946" color="#FFF" narrow={narrow}>🌶️ {shotsLeft}</Pill>
          <Pill bg="#FFD23F" color="#1A1A1A" narrow={narrow}>⚡ {score}</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: FIELD_W * scale, height: FIELD_H * scale,
          position: "relative",
        }}>
          <svg
            ref={fieldRef}
            viewBox={`0 0 ${FIELD_W} ${FIELD_H}`}
            preserveAspectRatio="none"
            width={FIELD_W * scale}
            height={FIELD_H * scale}
            onPointerDown={onPointerDown}
            onPointerMove={onPointerMove}
            onPointerUp={onPointerUp}
            onPointerCancel={onPointerUp}
            style={{
              display: "block",
              border: "4px solid #1A1A1A",
              boxShadow: "5px 5px 0 #1A1A1A",
              touchAction: "none", userSelect: "none",
              cursor: phase === "ready" ? "grab" : phase === "aiming" ? "grabbing" : "default",
            }}>
            <defs>
              <linearGradient id="ps-sky" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#5AB6F0" />
                <stop offset="55%" stopColor="#B4DEF0" />
                <stop offset="100%" stopColor="#FBE9B0" />
              </linearGradient>
              <linearGradient id="ps-grass" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#6FC76F" />
                <stop offset="40%" stopColor="#3EA84A" />
                <stop offset="100%" stopColor="#1F6826" />
              </linearGradient>
              <linearGradient id="ps-wood" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#D29762" />
                <stop offset="50%" stopColor="#8E5E2A" />
                <stop offset="100%" stopColor="#5A3A18" />
              </linearGradient>
              <linearGradient id="ps-stone" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#C5C0B4" />
                <stop offset="100%" stopColor="#7A7670" />
              </linearGradient>
              <linearGradient id="ps-mountainBack" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#7C9DC1" />
                <stop offset="100%" stopColor="#A8C2DD" />
              </linearGradient>
              <linearGradient id="ps-mountainFront" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#5E8AB0" />
                <stop offset="100%" stopColor="#88AECF" />
              </linearGradient>
              <radialGradient id="ps-sun" cx="0.5" cy="0.5" r="0.6">
                <stop offset="0%" stopColor="#FFEB78" />
                <stop offset="80%" stopColor="rgba(255,235,120,0.0)" />
              </radialGradient>
              <radialGradient id="ps-aimGlow" cx="0.5" cy="0.5" r="0.5">
                <stop offset="0%" stopColor="rgba(255,210,63,0.85)" />
                <stop offset="100%" stopColor="rgba(255,210,63,0)" />
              </radialGradient>
              <pattern id="ps-grass-pattern" x="0" y="0" width="32" height="14" patternUnits="userSpaceOnUse">
                <path d="M 4 14 l 3 -10 l 3 10 M 18 14 l 2 -7 l 4 7" stroke="#1F6826" strokeWidth="1.6" fill="none" />
              </pattern>
            </defs>

            <g transform={`translate(${shakeX} ${shakeY})`}>
              {/* lucht */}
              <rect x="0" y="0" width={FIELD_W} height={FIELD_H} fill="url(#ps-sky)" />

              {/* zon met stralen */}
              <g transform={`translate(${FIELD_W - 130} 100)`}>
                <g transform={`rotate(${(animTimeRef.current * 8).toFixed(1)})`}>
                  {Array.from({ length: 12 }).map((_, i) => (
                    <rect key={i} x={-2} y={-90}
                      width={4} height={36}
                      fill="#FFD23F" opacity="0.55"
                      transform={`rotate(${i * 30})`} />
                  ))}
                </g>
                <circle cx="0" cy="0" r={140} fill="url(#ps-sun)" />
                <circle cx="0" cy="0" r={48} fill="#FFE56F" stroke="#1A1A1A" strokeWidth="3" />
                <circle cx="-12" cy="-10" r={14} fill="rgba(255,255,255,0.6)" />
              </g>

              {/* parallax bergen achter */}
              <path d={`M -10 ${GROUND_Y - 80} L 90 ${GROUND_Y - 200} L 200 ${GROUND_Y - 130} L 320 ${GROUND_Y - 220} L 460 ${GROUND_Y - 150} L 600 ${GROUND_Y - 240} L 740 ${GROUND_Y - 160} L 880 ${GROUND_Y - 220} L ${FIELD_W + 20} ${GROUND_Y - 90} L ${FIELD_W + 20} ${GROUND_Y} L -10 ${GROUND_Y} Z`}
                fill="url(#ps-mountainBack)" stroke="#1A1A1A" strokeWidth="2" strokeLinejoin="round" opacity="0.85" />
              {/* sneeuw-toppen achterste bergen */}
              <path d="M 70 312 L 90 290 L 110 312 Z M 290 290 L 320 270 L 350 290 Z M 580 290 L 600 270 L 620 290 Z M 860 280 L 880 270 L 900 280 Z"
                fill="#FFFAF0" stroke="#1A1A1A" strokeWidth="1.5" opacity="0.85" />

              {/* parallax bergen voor */}
              <path d={`M -10 ${GROUND_Y - 40} L 100 ${GROUND_Y - 130} L 220 ${GROUND_Y - 80} L 360 ${GROUND_Y - 160} L 500 ${GROUND_Y - 90} L 660 ${GROUND_Y - 170} L 820 ${GROUND_Y - 100} L ${FIELD_W + 20} ${GROUND_Y - 60} L ${FIELD_W + 20} ${GROUND_Y} L -10 ${GROUND_Y} Z`}
                fill="url(#ps-mountainFront)" stroke="#1A1A1A" strokeWidth="2.5" strokeLinejoin="round" />

              {/* heuvels op de voorgrond */}
              <path d={`M -10 ${GROUND_Y - 30} Q 200 ${GROUND_Y - 110} 420 ${GROUND_Y - 50} T ${FIELD_W + 20} ${GROUND_Y - 30} L ${FIELD_W + 20} ${GROUND_Y} L -10 ${GROUND_Y} Z`}
                fill="#7BC57B" stroke="#1A1A1A" strokeWidth="3" strokeLinejoin="round" />

              {/* bomen op de horizon */}
              {[
                { x: 290, h: 80 },
                { x: 460, h: 100 },
                { x: 540, h: 70 },
                { x: 880, h: 90 },
              ].map((t, i) => (
                <g key={i} transform={`translate(${t.x} ${GROUND_Y - 22})`}>
                  <rect x="-4" y={-t.h * 0.45} width="8" height={t.h * 0.45} fill="#5A3A18" stroke="#1A1A1A" strokeWidth="1.5" />
                  <ellipse cx="0" cy={-t.h * 0.55} rx={t.h * 0.32} ry={t.h * 0.45}
                    fill="#3EA84A" stroke="#1A1A1A" strokeWidth="2" />
                  <ellipse cx={-t.h * 0.16} cy={-t.h * 0.7} rx={t.h * 0.22} ry={t.h * 0.28}
                    fill="#5BB85B" stroke="#1A1A1A" strokeWidth="1.5" opacity="0.9" />
                </g>
              ))}

              {/* wolken */}
              {cloudsRef.current.map(c => (
                <g key={c.id} transform={`translate(${c.x} ${c.y}) scale(${c.s})`}>
                  <ellipse cx="0" cy="0" rx="46" ry="22" fill="#FFF" stroke="#1A1A1A" strokeWidth="2.5" />
                  <ellipse cx="-26" cy="6" rx="22" ry="14" fill="#FFF" stroke="#1A1A1A" strokeWidth="2.5" />
                  <ellipse cx="28" cy="6" rx="24" ry="16" fill="#FFF" stroke="#1A1A1A" strokeWidth="2.5" />
                  <ellipse cx="6" cy="-8" rx="18" ry="11" fill="#FFF" stroke="#1A1A1A" strokeWidth="2" />
                </g>
              ))}

              {/* vogels op de achtergrond */}
              {birdsRef.current.map(b => {
                const flap = Math.sin(b.phase) * 8;
                return (
                  <g key={b.id} transform={`translate(${b.x} ${b.y})`}>
                    <path d={`M -14 0 Q -7 ${-6 - flap} 0 0 Q 7 ${-6 - flap} 14 0`}
                      stroke="#1A1A1A" strokeWidth="2.5" fill="none" strokeLinecap="round" />
                  </g>
                );
              })}

              {/* gras-grond en streep */}
              <rect x="0" y={GROUND_Y} width={FIELD_W} height={FIELD_H - GROUND_Y} fill="url(#ps-grass)" stroke="#1A1A1A" strokeWidth="3" />
              <rect x="0" y={GROUND_Y} width={FIELD_W} height="14" fill="url(#ps-grass-pattern)" opacity="0.6" />
              {/* gras-pollen */}
              {Array.from({ length: 26 }).map((_, i) => {
                const x = i * 38 + 10 + (i % 3) * 4;
                const h = 8 + (i % 4) * 3;
                return (
                  <path key={i}
                    d={`M ${x} ${GROUND_Y + 2} l ${h * 0.3} ${-h} l ${h * 0.3} ${h} M ${x + 6} ${GROUND_Y + 2} l ${h * 0.25} ${-h * 0.8} l ${h * 0.25} ${h * 0.8}`}
                    stroke="#1F6826" strokeWidth="2" fill="none" strokeLinecap="round" />
                );
              })}

              {/* houten/stenen blokken met houtnerf en knopen */}
              {blocksRef.current.map(b => b.broken ? null : (
                <BlockShape key={b.id} block={b} />
              ))}

              {/* katapult, basis met steen */}
              <g>
                <ellipse cx={SLING_X} cy={GROUND_Y + 4} rx={42} ry={6} fill="rgba(0,0,0,0.28)" />
                {/* stenen sokkel */}
                <ellipse cx={SLING_X} cy={GROUND_Y - 4} rx={28} ry={10}
                  fill="#A8A0A0" stroke="#1A1A1A" strokeWidth="2.5" />
                {/* houten Y, getekend met meerdere lijnen voor diepte */}
                <g>
                  <rect x={SLING_X - 8} y={SLING_Y + 8} width={16} height={GROUND_Y - SLING_Y - 6}
                    fill="url(#ps-wood)" stroke="#1A1A1A" strokeWidth="3" rx="3" />
                  {/* knot in stam */}
                  <ellipse cx={SLING_X - 1} cy={SLING_Y + (GROUND_Y - SLING_Y) * 0.5} rx="3" ry="6"
                    fill="rgba(0,0,0,0.35)" />
                  {/* takken */}
                  <g transform={`translate(${SLING_X} ${SLING_Y + 12})`}>
                    <path d="M 0 0 Q -10 -8 -28 -16 L -34 -10 Q -16 -2 -4 6 Z"
                      fill="url(#ps-wood)" stroke="#1A1A1A" strokeWidth="2.5" strokeLinejoin="round" />
                    <path d="M 0 0 Q 10 -8 28 -16 L 34 -10 Q 16 -2 4 6 Z"
                      fill="url(#ps-wood)" stroke="#1A1A1A" strokeWidth="2.5" strokeLinejoin="round" />
                  </g>
                  {/* tape om de takken */}
                  <rect x={SLING_X - 28} y={SLING_Y - 12} width={10} height={16}
                    fill="#3A2415" stroke="#1A1A1A" strokeWidth="1.5" rx="2"
                    transform={`rotate(-22 ${SLING_X - 23} ${SLING_Y - 4})`} />
                  <rect x={SLING_X + 18} y={SLING_Y - 12} width={10} height={16}
                    fill="#3A2415" stroke="#1A1A1A" strokeWidth="1.5" rx="2"
                    transform={`rotate(22 ${SLING_X + 23} ${SLING_Y - 4})`} />
                </g>
                {/* elastiek achterzijde */}
                {(phase === "ready" || phase === "aiming") && (
                  <line x1={SLING_X - 22} y1={SLING_Y - 4}
                    x2={projPos.x - 8} y2={projPos.y}
                    stroke="#3A2415" strokeWidth="5" strokeLinecap="round" />
                )}
              </g>

              {/* trajectory dots, animeren langs de baan */}
              {traj.map((t, i) => {
                const phaseOff = (animTimeRef.current * 6 + i) % traj.length;
                const fade = 0.85 - i * 0.011;
                return (
                  <circle key={i} cx={t.x} cy={t.y}
                    r={3 + (1 - i / traj.length) * 2}
                    fill="#FFF8EC" stroke="#1A1A1A" strokeWidth="1"
                    opacity={Math.max(0.15, fade - (phaseOff / traj.length) * 0.4)} />
                );
              })}

              {/* power glow rondom de peper bij mikken */}
              {phase === "aiming" && power > 0.05 && (
                <circle cx={projPos.x} cy={projPos.y} r={42 + power * 18}
                  fill="url(#ps-aimGlow)"
                  opacity={0.4 + power * 0.6} />
              )}

              {/* vijanden */}
              {enemiesRef.current.map(e => e.alive && (
                <EnemyShape key={e.id} type={e.type} x={e.x} y={e.y} r={e.r}
                  wob={e.wob + animTimeRef.current * 2} />
              ))}

              {/* leren pouch achter de peper */}
              {(phase === "ready" || phase === "aiming") && (
                <ellipse cx={projPos.x} cy={projPos.y + PROJ_R * 0.3}
                  rx={PROJ_R + 4} ry={PROJ_R * 0.6}
                  fill="#5A3A18" stroke="#1A1A1A" strokeWidth="2" />
              )}

              {/* projectiel (peper) met spark-trail */}
              {phase === "flying" && (
                <g>
                  {Array.from({ length: 5 }).map((_, i) => {
                    const t = (i + 1) * 0.04;
                    const tx = projRef.current.x - projRef.current.vx * t;
                    const ty = projRef.current.y - projRef.current.vy * t;
                    return (
                      <circle key={i} cx={tx} cy={ty} r={PROJ_R - i * 4}
                        fill="#FFD23F" opacity={0.18 - i * 0.03} />
                    );
                  })}
                </g>
              )}
              <g transform={`translate(${projPos.x} ${projPos.y}) rotate(${(projRot * 180 / Math.PI).toFixed(2)})`}>
                <image href="/assets/peper-schieter.png"
                  x={-PROJ_R - 6} y={-PROJ_R - 6}
                  width={(PROJ_R + 6) * 2} height={(PROJ_R + 6) * 2}
                  style={{ pointerEvents: "none", filter: "drop-shadow(2px 4px 0 rgba(0,0,0,0.4))" }}
                  preserveAspectRatio="xMidYMid meet" />
              </g>

              {/* elastiek voorzijde */}
              {(phase === "ready" || phase === "aiming") && (
                <line x1={SLING_X + 22} y1={SLING_Y - 4}
                  x2={projPos.x + 8} y2={projPos.y}
                  stroke="#3A2415" strokeWidth="5" strokeLinecap="round" />
              )}

              {/* deeltjes */}
              {particlesRef.current.map(d => {
                if (d.kind === "chip") {
                  return (
                    <rect key={d.id} x={d.x - d.r / 2} y={d.y - d.r / 2}
                      width={d.r} height={d.r * 0.6}
                      transform={`rotate(${(d.rot * 180 / Math.PI).toFixed(1)} ${d.x} ${d.y})`}
                      fill={d.color} stroke="#1A1A1A" strokeWidth="1"
                      opacity={Math.max(0, d.life)} />
                  );
                }
                if (d.kind === "puff") {
                  return (
                    <circle key={d.id} cx={d.x} cy={d.y} r={d.r * 1.4}
                      fill={d.color} opacity={Math.max(0, d.life * 0.55)} />
                  );
                }
                return (
                  <circle key={d.id} cx={d.x} cy={d.y} r={d.r}
                    fill={d.color} opacity={Math.max(0, d.life)} />
                );
              })}

              {/* drijvende score-tekst */}
              {floatersRef.current.map(f => (
                <g key={f.id} transform={`translate(${f.x} ${f.y})`}>
                  <text textAnchor="middle"
                    fontFamily="Bangers, sans-serif" fontSize="28"
                    fill={f.color} stroke="#1A1A1A" strokeWidth="2"
                    paintOrder="stroke fill"
                    opacity={Math.min(1, f.life * 1.4)}>{f.text}</text>
                </g>
              ))}

              {/* HUD met vijanden-teller */}
              {phase !== "intro" && (
                <g transform={`translate(${FIELD_W / 2} 32)`}>
                  <rect x={-100} y={-22} width={200} height={36}
                    fill="rgba(255,255,255,0.92)"
                    stroke="#1A1A1A" strokeWidth="3" rx="6" />
                  <text x="0" y="6" textAnchor="middle"
                    fontFamily="Bangers, sans-serif" fontSize="20"
                    fill="#1A1A1A" letterSpacing="2">
                    VIJANDEN: {totalEnemies - aliveCount} / {totalEnemies}
                  </text>
                </g>
              )}

              {/* power-meter onder de katapult */}
              {phase === "aiming" && (
                <g transform={`translate(${SLING_X - 40} ${GROUND_Y + 16})`}>
                  <rect x="0" y="0" width="80" height="10"
                    fill="rgba(0,0,0,0.4)" stroke="#1A1A1A" strokeWidth="1.5" rx="2" />
                  <rect x="0" y="0" width={80 * power} height="10"
                    fill={power > 0.7 ? "#E63946" : power > 0.4 ? "#FF8C1A" : "#FFD23F"}
                    stroke="#1A1A1A" strokeWidth="1.5" rx="2" />
                </g>
              )}
            </g>
          </svg>

          {phase === "intro" && (
            <Overlay>
              <Title color="#FF8C1A">PEPERSCHIETER</Title>
              <p style={overlayText}>
                Sleep de boze peper achterwaarts uit de katapult, mik op je doelen
                en laat los om te schieten! Sloop alle wasknijpers, ijsheksen en
                slijmpjes voor je pepers op zijn.
              </p>
              <BigButton onClick={startGame} color="#5BB85B" style={{ color: "#FFF" }}>
                ▶ START
              </BigButton>
            </Overlay>
          )}
          {phase === "won" && (
            <Overlay>
              <Title color="#3FA34D">{levelIdx + 1 < LEVELS.length ? "GOED GEMIKT!" : "ALLES GESLOOPT!"}</Title>
              <p style={overlayText}>
                Score: <strong>{score}</strong>
                {shotsLeft > 0 && <> · Bonus: {shotsLeft} pepers over!</>}
              </p>
              <div style={{ display: "flex", gap: 10, justifyContent: "center", flexWrap: "wrap" }}>
                {levelIdx + 1 < LEVELS.length ? (
                  <BigButton onClick={nextLevel} color="#5BB85B" style={{ color: "#FFF" }}>
                    VOLGEND LEVEL →
                  </BigButton>
                ) : (
                  <BigButton onClick={startGame} color="#5BB85B" style={{ color: "#FFF" }}>
                    ↻ NOG EENS
                  </BigButton>
                )}
              </div>
            </Overlay>
          )}
          {phase === "lost" && (
            <Overlay>
              <Title color="#E63946">PEPERS OP!</Title>
              <p style={overlayText}>
                Score: <strong>{score}</strong>. Geen pepers meer! Probeer het opnieuw.
              </p>
              <div style={{ display: "flex", gap: 10, justifyContent: "center", flexWrap: "wrap" }}>
                <BigButton onClick={retryLevel} color="#FFD23F">↻ OPNIEUW</BigButton>
                <BigButton onClick={startGame} color="#5BB85B" style={{ color: "#FFF" }}>NIEUW POTJE</BigButton>
              </div>
            </Overlay>
          )}
          {phase === "complete" && (
            <Overlay>
              <Title color="#FFD23F">CHAMPION!</Title>
              <p style={overlayText}>
                Eindscore: <strong>{score}</strong> · 🏆 Beste: {best}
              </p>
              <BigButton onClick={startGame} color="#5BB85B" style={{ color: "#FFF" }}>
                ↻ NOG EENS
              </BigButton>
            </Overlay>
          )}
        </div>
      </div>
    </div>
  );
}

const overlayText = { fontSize: 18, lineHeight: 1.4, maxWidth: 420, margin: "0 0 16px" };

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

function Title({ children, color }) {
  return (
    <div style={{
      fontFamily: "'Bangers', sans-serif", fontSize: 44,
      color, letterSpacing: "0.04em", lineHeight: 1,
      WebkitTextStroke: "1.5px #1A1A1A",
      textShadow: "4px 4px 0 #1A1A1A",
      marginBottom: 12,
    }}>{children}</div>
  );
}

function Overlay({ children }) {
  return (
    <div style={{
      position: "absolute", inset: 0,
      display: "flex", alignItems: "center", justifyContent: "center",
      background: "rgba(0,0,0,0.55)",
      padding: 16, textAlign: "center", color: "#FFF",
    }}>
      <div style={{
        background: "#FFF8EC",
        border: "5px solid #1A1A1A",
        boxShadow: "6px 6px 0 #1A1A1A",
        padding: "22px 26px",
        maxWidth: 480, color: "#1A1A1A",
        transform: "rotate(-0.5deg)",
      }}>
        {children}
      </div>
    </div>
  );
}

function BlockShape({ block: b }) {
  const fill = b.mat === "stone" ? "url(#ps-stone)" : "url(#ps-wood)";
  const isWood = b.mat !== "stone";
  const damaged = b.hp < b.maxHp;
  return (
    <g>
      {/* schaduw onder blok */}
      <ellipse cx={b.x + b.w / 2} cy={b.y + b.h + 3}
        rx={b.w * 0.45} ry={3} fill="rgba(0,0,0,0.25)" />
      <rect x={b.x} y={b.y} width={b.w} height={b.h}
        fill={fill} stroke="#1A1A1A" strokeWidth="3" rx={isWood ? 3 : 4} />
      {isWood ? (
        <>
          <line x1={b.x + 4} y1={b.y + b.h * 0.3} x2={b.x + b.w - 4} y2={b.y + b.h * 0.3}
            stroke="rgba(0,0,0,0.3)" strokeWidth="1.5" />
          <line x1={b.x + 4} y1={b.y + b.h * 0.65} x2={b.x + b.w - 4} y2={b.y + b.h * 0.65}
            stroke="rgba(0,0,0,0.3)" strokeWidth="1.5" />
          {/* knot */}
          <ellipse cx={b.x + b.w * 0.35} cy={b.y + b.h * 0.5}
            rx={Math.min(b.w, b.h) * 0.06} ry={Math.min(b.w, b.h) * 0.1}
            fill="rgba(0,0,0,0.45)" />
        </>
      ) : (
        <>
          {/* stenen blokjes-patroon */}
          <line x1={b.x + b.w * 0.5} y1={b.y + 2} x2={b.x + b.w * 0.5} y2={b.y + b.h * 0.5}
            stroke="rgba(0,0,0,0.3)" strokeWidth="1.5" />
          <line x1={b.x + 2} y1={b.y + b.h * 0.5} x2={b.x + b.w - 2} y2={b.y + b.h * 0.5}
            stroke="rgba(0,0,0,0.3)" strokeWidth="1.5" />
          <line x1={b.x + b.w * 0.25} y1={b.y + b.h * 0.5} x2={b.x + b.w * 0.25} y2={b.y + b.h - 2}
            stroke="rgba(0,0,0,0.3)" strokeWidth="1.5" />
          <line x1={b.x + b.w * 0.75} y1={b.y + b.h * 0.5} x2={b.x + b.w * 0.75} y2={b.y + b.h - 2}
            stroke="rgba(0,0,0,0.3)" strokeWidth="1.5" />
        </>
      )}
      {damaged && (
        <g>
          <line x1={b.x + 6} y1={b.y + 6} x2={b.x + b.w - 6} y2={b.y + b.h - 6}
            stroke="rgba(0,0,0,0.55)" strokeWidth="2" strokeDasharray="4 3" />
          {b.hp === 1 && b.maxHp >= 2 && (
            <line x1={b.x + b.w - 6} y1={b.y + 6} x2={b.x + 6} y2={b.y + b.h - 6}
              stroke="rgba(0,0,0,0.55)" strokeWidth="2" strokeDasharray="4 3" />
          )}
        </g>
      )}
    </g>
  );
}

function EnemyShape({ type, x, y, r, wob = 0 }) {
  const bob = Math.sin(wob) * 1.6;
  const tilt = Math.sin(wob * 0.8) * 3;
  if (type === "wasknijper") {
    const w = r * 1.7, h = r * 2.6;
    return (
      <g transform={`translate(${x - w / 2} ${y - h / 2 - r * 0.2 + bob}) rotate(${tilt} ${w / 2} ${h / 2})`}>
        <ellipse cx={w / 2} cy={h + 6} rx={w * 0.42} ry={4} fill="rgba(0,0,0,0.25)" />
        <path d={`M ${w * 0.32} ${h * 0.45} L ${w * 0.18} ${h} L ${w * 0.36} ${h} L ${w * 0.46} ${h * 0.55} Z`}
          fill="#C8C2B4" stroke="#1A1A1A" strokeWidth="2.8" strokeLinejoin="round" />
        <path d={`M ${w * 0.68} ${h * 0.45} L ${w * 0.82} ${h} L ${w * 0.64} ${h} L ${w * 0.54} ${h * 0.55} Z`}
          fill="#B5AD9C" stroke="#1A1A1A" strokeWidth="2.8" strokeLinejoin="round" />
        {/* metalen veer */}
        <ellipse cx={w / 2} cy={h * 0.42} rx={w * 0.16} ry={w * 0.1}
          fill="#8B8273" stroke="#1A1A1A" strokeWidth="2" />
        <path d={`M ${w * 0.36} ${h * 0.42} Q ${w / 2} ${h * 0.36} ${w * 0.64} ${h * 0.42} M ${w * 0.36} ${h * 0.46} Q ${w / 2} ${h * 0.4} ${w * 0.64} ${h * 0.46}`}
          stroke="#1A1A1A" strokeWidth="1.8" fill="none" />
        <path d={`M ${w * 0.18} ${h * 0.45} Q ${w * 0.18} ${h * 0.16} ${w * 0.5} ${h * 0.1} Q ${w * 0.82} ${h * 0.16} ${w * 0.82} ${h * 0.45} L ${w * 0.74} ${h * 0.5} L ${w * 0.26} ${h * 0.5} Z`}
          fill="#C8C2B4" stroke="#1A1A1A" strokeWidth="2.8" strokeLinejoin="round" />
        {/* hooglicht */}
        <path d={`M ${w * 0.26} ${h * 0.18} Q ${w * 0.26} ${h * 0.36} ${w * 0.32} ${h * 0.42}`}
          stroke="rgba(255,255,255,0.5)" strokeWidth="3" fill="none" />
        {/* wenkbrauwen + ogen */}
        <path d={`M ${w * 0.32} ${h * 0.22} L ${w * 0.46} ${h * 0.3}`} stroke="#1A1A1A" strokeWidth="3" strokeLinecap="round" />
        <path d={`M ${w * 0.68} ${h * 0.22} L ${w * 0.54} ${h * 0.3}`} stroke="#1A1A1A" strokeWidth="3" strokeLinecap="round" />
        <circle cx={w * 0.42} cy={h * 0.34} r={3} fill="#1A1A1A" />
        <circle cx={w * 0.58} cy={h * 0.34} r={3} fill="#1A1A1A" />
        <path d={`M ${w * 0.36} ${h * 0.44} Q ${w * 0.5} ${h * 0.36} ${w * 0.64} ${h * 0.44}`}
          stroke="#1A1A1A" strokeWidth="2.5" fill="none" strokeLinecap="round" />
      </g>
    );
  }
  if (type === "ijsheks") {
    const s = r * 2;
    return (
      <g transform={`translate(${x - s / 2} ${y - s / 2 + bob}) rotate(${tilt} ${s / 2} ${s / 2})`}>
        <ellipse cx={s / 2} cy={s + 4} rx={s * 0.4} ry={4} fill="rgba(0,0,0,0.25)" />
        {/* gloed */}
        <circle cx={s / 2} cy={s / 2} r={s * 0.62} fill="rgba(170,220,250,0.45)" />
        <path d={`M ${s * 0.5} ${s * 0.06} Q ${s * 0.16} ${s * 0.16} ${s * 0.14} ${s * 0.5} Q ${s * 0.16} ${s * 0.94} ${s * 0.5} ${s * 0.96} Q ${s * 0.84} ${s * 0.94} ${s * 0.86} ${s * 0.5} Q ${s * 0.84} ${s * 0.16} ${s * 0.5} ${s * 0.06} Z`}
          fill="#9EDAF5" stroke="#1A1A1A" strokeWidth="3" strokeLinejoin="round" />
        {/* hooglicht */}
        <ellipse cx={s * 0.35} cy={s * 0.3} rx={s * 0.1} ry={s * 0.18} fill="rgba(255,255,255,0.65)" />
        {/* sneeuwvlok */}
        <g transform={`translate(${s * 0.5} ${s * 0.34}) scale(${s / 90})`}>
          <path d="M 0 -22 L 4 -10 L 14 -14 L 8 -4 L 22 -2 L 10 4 L 22 12 L 8 12 L 14 22 L 4 16 L 0 26 L -4 16 L -14 22 L -8 12 L -22 12 L -10 4 L -22 -2 L -8 -4 L -14 -14 L -4 -10 Z"
            fill="#FFFAF0" stroke="#1A1A1A" strokeWidth="2.2" strokeLinejoin="round" />
        </g>
        {/* ogen */}
        <circle cx={s * 0.4} cy={s * 0.62} r={s * 0.06} fill="#FFF" stroke="#1A1A1A" strokeWidth="2" />
        <circle cx={s * 0.6} cy={s * 0.62} r={s * 0.06} fill="#FFF" stroke="#1A1A1A" strokeWidth="2" />
        <circle cx={s * 0.41} cy={s * 0.63} r={s * 0.025} fill="#1A1A1A" />
        <circle cx={s * 0.61} cy={s * 0.63} r={s * 0.025} fill="#1A1A1A" />
        {/* mond */}
        <path d={`M ${s * 0.4} ${s * 0.78} Q ${s * 0.5} ${s * 0.74} ${s * 0.6} ${s * 0.78}`}
          stroke="#1A1A1A" strokeWidth="2.5" fill="none" strokeLinecap="round" />
        {/* sparkles */}
        <circle cx={s * 0.18} cy={s * 0.2} r={s * 0.025} fill="#FFF" opacity="0.9" />
        <circle cx={s * 0.86} cy={s * 0.4} r={s * 0.02} fill="#FFF" opacity="0.7" />
      </g>
    );
  }
  // slijm
  const s = r * 2;
  const drip = Math.sin(wob * 1.5) * 2;
  return (
    <g transform={`translate(${x - s / 2} ${y - s / 2 + bob}) rotate(${tilt} ${s / 2} ${s / 2})`}>
      <ellipse cx={s / 2} cy={s + 4} rx={s * 0.4} ry={4} fill="rgba(0,0,0,0.25)" />
      <path d={`M ${s * 0.14} ${s * 0.5} Q ${s * 0.08} ${s * 0.16} ${s * 0.5} ${s * 0.14} Q ${s * 0.92} ${s * 0.16} ${s * 0.86} ${s * 0.5} Q ${s * 0.92} ${s * 0.74} ${s * 0.78} ${s * 0.84} L ${s * 0.7} ${s * 0.96 + drip} L ${s * 0.6} ${s * 0.84} L ${s * 0.5} ${s * 0.96 + drip} L ${s * 0.4} ${s * 0.84} L ${s * 0.3} ${s * 0.96 + drip} L ${s * 0.22} ${s * 0.84} Q ${s * 0.08} ${s * 0.74} ${s * 0.14} ${s * 0.5} Z`}
        fill="#7FDBA3" stroke="#1A1A1A" strokeWidth="3" strokeLinejoin="round" />
      <ellipse cx={s * 0.34} cy={s * 0.32} rx={s * 0.12} ry={s * 0.06} fill="rgba(255,255,255,0.55)" />
      <circle cx={s * 0.4} cy={s * 0.5} r={s * 0.08} fill="#FFF" stroke="#1A1A1A" strokeWidth="2.5" />
      <circle cx={s * 0.62} cy={s * 0.5} r={s * 0.08} fill="#FFF" stroke="#1A1A1A" strokeWidth="2.5" />
      <circle cx={s * 0.42} cy={s * 0.52} r={s * 0.03} fill="#1A1A1A" />
      <circle cx={s * 0.64} cy={s * 0.52} r={s * 0.03} fill="#1A1A1A" />
      <path d={`M ${s * 0.42} ${s * 0.68} Q ${s * 0.52} ${s * 0.62} ${s * 0.62} ${s * 0.68}`}
        stroke="#1A1A1A" strokeWidth="2.5" fill="none" strokeLinecap="round" />
      {/* tanden */}
      <path d={`M ${s * 0.46} ${s * 0.66} L ${s * 0.48} ${s * 0.7} L ${s * 0.5} ${s * 0.66} M ${s * 0.54} ${s * 0.66} L ${s * 0.56} ${s * 0.7} L ${s * 0.58} ${s * 0.66}`}
        stroke="#1A1A1A" strokeWidth="1.8" fill="#FFF" />
    </g>
  );
}

Object.assign(window, { Peperschieter });
