function PeperTouwtrekken({ onClose }) {
  const FIELD_W = 480;
  const FIELD_H = 600;
  const ROPE_Y = 280;
  const CENTER = FIELD_W / 2;
  const WIN_THRESHOLD = 160;
  const ROUND_DURATION = 35;

  const DIFFICULTIES = {
    mild:     { label: "MILD",     icon: "🌶️",       baseBpm: 55, bpmPerRound: 5,  aiBase: 0.25, aiPerRound: 0.04, perfectWindow: 0.20, goodWindow: 0.38, rounds: 3 },
    pittig:   { label: "PITTIG",   icon: "🌶️🌶️",    baseBpm: 72, bpmPerRound: 8,  aiBase: 0.35, aiPerRound: 0.06, perfectWindow: 0.16, goodWindow: 0.32, rounds: 4 },
    vlammend: { label: "VLAMMEND", icon: "🌶️🌶️🌶️", baseBpm: 90, bpmPerRound: 12, aiBase: 0.45, aiPerRound: 0.09, perfectWindow: 0.12, goodWindow: 0.26, rounds: 5 },
  };

  const [phase, setPhase] = React.useState("intro");
  const [difficulty, setDifficulty] = React.useState(() => {
    try { return localStorage.getItem("hp_diff_peper-touwtrekken") || "mild"; }
    catch { return "mild"; }
  });
  const [score, setScore] = React.useState(0);
  const [round, setRound] = React.useState(1);
  const [best, setBest] = React.useState(() => {
    try { return parseInt(localStorage.getItem("peper-touwtrekken-best") || "0", 10) || 0; }
    catch { return 0; }
  });
  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 ropeRef = React.useRef(0);
  const beatRef = React.useRef({
    bpm: 60, phase: 0, combo: 0, maxCombo: 0,
    perfectHits: 0, goodHits: 0, misses: 0, totalBeats: 0,
    flash: 0, pullStrength: 0, lastBeatIdx: -1,
  });
  const aiRef = React.useRef({ pullPower: 0.5, timer: 0 });
  const lastFrameRef = React.useRef(0);
  const timeRef = React.useRef(ROUND_DURATION);
  const idRef = React.useRef(0);
  const particlesRef = React.useRef([]);
  const ringRef = React.useRef([]);
  const tapFlashRef = React.useRef(0);
  const resultRef = React.useRef("");
  const diffRef = React.useRef(difficulty);

  function getDiff() { return DIFFICULTIES[diffRef.current] || DIFFICULTIES.mild; }

  function pickDifficulty(d) {
    setDifficulty(d);
    diffRef.current = d;
    try { localStorage.setItem("hp_diff_peper-touwtrekken", d); } catch {}
  }

  React.useEffect(() => {
    function measure() {
      setNarrow(window.innerWidth <= 600);
      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);
    return () => { if (ro) ro.disconnect(); window.removeEventListener("resize", measure); };
  }, []);

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

  function reset(r) {
    const d = getDiff();
    ropeRef.current = 0;
    const bpm = d.baseBpm + (r || round) * d.bpmPerRound;
    beatRef.current = {
      bpm, phase: 0, combo: 0, maxCombo: 0,
      perfectHits: 0, goodHits: 0, misses: 0, totalBeats: 0,
      flash: 0, pullStrength: 0, lastBeatIdx: -1,
    };
    aiRef.current = { pullPower: d.aiBase + (r || round) * d.aiPerRound, timer: 0 };
    timeRef.current = ROUND_DURATION;
    particlesRef.current = [];
    ringRef.current = [];
    tapFlashRef.current = 0;
    resultRef.current = "";
  }

  function startGame() {
    setRound(1);
    setScore(0);
    reset(1);
    setPhase("playing");
  }

  function startRound(r) {
    setRound(r);
    reset(r);
    setPhase("playing");
  }

  function handleTap(e) {
    if (phase === "intro") return;
    if (phase === "result") { startGame(); return; }
    if (phase === "roundWin" || phase === "roundLose") return;
    if (phase !== "playing") return;

    const d = getDiff();
    const beat = beatRef.current;
    const beatProgress = beat.phase % 1;
    const distFromBeat = Math.min(beatProgress, 1 - beatProgress);

    tapFlashRef.current = 1;

    if (distFromBeat < d.perfectWindow) {
      beat.pullStrength = 1.0;
      beat.combo++;
      beat.perfectHits++;
      beat.flash = 1;
      beat.maxCombo = Math.max(beat.maxCombo, beat.combo);
      ringRef.current.push({ id: ++idRef.current, t: 0, color: "#FFD23F", label: "PERFECT!" });
      for (let i = 0; i < 8; i++) {
        const ang = Math.random() * Math.PI * 2;
        const v = 80 + Math.random() * 120;
        particlesRef.current.push({
          id: ++idRef.current,
          x: CENTER, y: FIELD_H - 100,
          vx: Math.cos(ang) * v, vy: Math.sin(ang) * v - 50,
          life: 0.6 + Math.random() * 0.3,
          r: 3 + Math.random() * 4,
          c: ["#FFD23F", "#FF8C1A", "#FFF"][Math.floor(Math.random() * 3)],
        });
      }
    } else if (distFromBeat < d.goodWindow) {
      beat.pullStrength = 0.55;
      beat.combo++;
      beat.goodHits++;
      beat.flash = 0.4;
      beat.maxCombo = Math.max(beat.maxCombo, beat.combo);
      ringRef.current.push({ id: ++idRef.current, t: 0, color: "#3FA34D", label: "GOED!" });
    } else {
      beat.pullStrength = 0.08;
      beat.combo = 0;
      beat.misses++;
      ringRef.current.push({ id: ++idRef.current, t: 0, color: "#E63946", label: "MIS!" });
    }
  }

  React.useEffect(() => {
    function onKey(e) {
      if (e.key === "Escape") { onClose && onClose(); return; }
      if (phase === "intro") return;
      if (e.key === " " || e.key === "Enter") {
        e.preventDefault();
        handleTap();
      }
    }
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [phase, round, difficulty]);

  React.useEffect(() => {
    if (phase !== "playing") return;
    let raf = 0;
    lastFrameRef.current = performance.now();
    function frame(ts) {
      const dt = Math.min(0.04, (ts - lastFrameRef.current) / 1000);
      lastFrameRef.current = ts;

      const beat = beatRef.current;
      const ai = aiRef.current;

      timeRef.current -= dt;

      const beatInterval = 60 / beat.bpm;
      beat.phase += dt / beatInterval;

      const curBeatIdx = Math.floor(beat.phase);
      if (curBeatIdx > beat.lastBeatIdx) {
        beat.lastBeatIdx = curBeatIdx;
        beat.totalBeats = curBeatIdx;
      }

      const comboMulti = 1 + Math.min(beat.combo, 10) * 0.15;
      const playerPull = beat.pullStrength * comboMulti * 1.2;
      beat.pullStrength *= Math.pow(0.02, dt);

      ai.timer += dt;
      const aiPull = ai.pullPower * (0.7 + Math.sin(ai.timer * 1.5) * 0.3);

      ropeRef.current += (playerPull - aiPull) * dt * 80;
      ropeRef.current *= 0.995;

      beat.flash = Math.max(0, beat.flash - dt * 3);
      tapFlashRef.current = Math.max(0, tapFlashRef.current - dt * 4);

      ringRef.current = ringRef.current
        .map(r => ({ ...r, t: r.t + dt }))
        .filter(r => r.t < 0.8);

      particlesRef.current = particlesRef.current
        .map(d => ({ ...d, x: d.x + d.vx * dt, y: d.y + d.vy * dt, vy: d.vy + 300 * dt, life: d.life - dt }))
        .filter(d => d.life > 0);

      const d = getDiff();
      if (ropeRef.current > WIN_THRESHOLD) {
        const roundScore = Math.floor(beat.perfectHits * 10 + beat.goodHits * 5 + beat.maxCombo * 3);
        setScore(s => s + roundScore);
        resultRef.current = "win";
        setPhase("roundWin");
        setTimeout(() => {
          if (round < d.rounds) {
            startRound(round + 1);
          } else {
            setBest(prev => {
              const total = score + roundScore;
              if (total > prev) {
                try { localStorage.setItem("peper-touwtrekken-best", String(total)); } catch {}
                return total;
              }
              return prev;
            });
            setPhase("result");
          }
        }, 2000);
        forceRender();
        return;
      }

      if (ropeRef.current < -WIN_THRESHOLD || timeRef.current <= 0) {
        resultRef.current = "lose";
        setBest(prev => {
          if (score > prev) {
            try { localStorage.setItem("peper-touwtrekken-best", String(score)); } catch {}
            return score;
          }
          return prev;
        });
        setPhase("result");
        forceRender();
        return;
      }

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

  const rope = ropeRef.current;
  const beat = beatRef.current;
  const beatProgress = beat.phase % 1;
  const d = getDiff();

  const TARGET_R = 54;
  const approachRadius = TARGET_R + (1 - beatProgress) * 60;
  const approachOpacity = 0.4 + beatProgress * 0.6;
  const onBeat = Math.min(beatProgress, 1 - beatProgress) < d.perfectWindow;
  const nearBeat = Math.min(beatProgress, 1 - beatProgress) < d.goodWindow;
  const beatBounce = Math.max(0, 1 - beatProgress * 4);

  function Pill({ bg, color, narrow: n, children }) {
    return (
      <span style={{
        background: bg, 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: 40,
        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,20,42,0.88)",
        display: "flex", flexDirection: "column",
        alignItems: "center", justifyContent: "center",
        padding: 20, gap: 12, color: "#FFF8EC",
      }}>{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>
    );
  }

  function DiffBtn({ id, selected, onClick }) {
    const cfg = DIFFICULTIES[id];
    return (
      <button onClick={onClick} style={{
        background: selected ? "#FF8C1A" : "#2A2A3A",
        color: selected ? "#FFF" : "#AAA",
        border: selected ? "3px solid #FFD23F" : "3px solid #555",
        boxShadow: selected ? "3px 3px 0 #1A1A1A" : "none",
        fontFamily: "'Bangers', sans-serif", fontSize: 18,
        padding: "8px 16px", cursor: "pointer", letterSpacing: "0.04em",
        display: "flex", flexDirection: "column", alignItems: "center", gap: 2,
        minWidth: 100,
        transform: selected ? "scale(1.08)" : "scale(1)",
        transition: "all 0.15s",
      }}>
        <span style={{ fontSize: 14 }}>{cfg.icon}</span>
        <span>{cfg.label}</span>
        <span style={{ fontSize: 12, opacity: 0.7 }}>{cfg.rounds} rondes</span>
      </button>
    );
  }

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

  const ropeNorm = Math.max(-1, Math.min(1, rope / WIN_THRESHOLD));
  const markerX = CENTER + ropeNorm * (FIELD_W / 2 - 40);

  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 200,
      background: "#2A1B0E",
      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 ? 20 : 26, 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 ? 18 : 22, WebkitTextStroke: 0, textShadow: "none" }}>🪢</span>
          {narrow ? "TOUWTREK" : "TOUWTREKKEN"}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: narrow ? 4 : 8, flexWrap: "wrap" }}>
          <Pill bg="#8E44D1" color="#FFF" narrow={narrow}>Ronde {round}/{d.rounds}</Pill>
          <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} onPointerDown={handleTap} style={{
        flex: 1, position: "relative",
        display: "flex", alignItems: "center", justifyContent: "center",
        padding: 6, overflow: "hidden", cursor: "pointer",
      }}>
        <div style={{
          width: FIELD_W * scale, height: FIELD_H * scale,
          position: "relative",
        }}>
          <svg viewBox={`0 0 ${FIELD_W} ${FIELD_H}`}
            preserveAspectRatio="none"
            width={FIELD_W * scale} height={FIELD_H * scale}
            style={{
              display: "block",
              border: "4px solid #1A1A1A",
              boxShadow: "5px 5px 0 #1A1A1A",
              touchAction: "none", userSelect: "none",
            }}>
            <defs>
              <linearGradient id="pt-sky" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#87CEEB" />
                <stop offset="100%" stopColor="#E0F0FF" />
              </linearGradient>
              <linearGradient id="pt-grass" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="#4CAF50" />
                <stop offset="100%" stopColor="#2E7D32" />
              </linearGradient>
              <radialGradient id="pt-glow" cx="0.5" cy="0.5" r="0.5">
                <stop offset="0%" stopColor="#FFD23F" stopOpacity="0.6" />
                <stop offset="100%" stopColor="#FFD23F" stopOpacity="0" />
              </radialGradient>
            </defs>

            {/* lucht */}
            <rect x="0" y="0" width={FIELD_W} height={FIELD_H} fill="url(#pt-sky)" />

            {/* wolken */}
            <g opacity="0.6">
              <ellipse cx="80" cy="50" rx="50" ry="20" fill="#FFF" />
              <ellipse cx="350" cy="80" rx="40" ry="16" fill="#FFF" />
              <ellipse cx="220" cy="35" rx="35" ry="14" fill="#FFF" />
            </g>

            {/* grond */}
            <rect x="0" y={ROPE_Y + 80} width={FIELD_W} height={FIELD_H - ROPE_Y - 80} fill="url(#pt-grass)" stroke="#1A1A1A" strokeWidth="2" />

            {/* modder-lijn in het midden */}
            <rect x={CENTER - 4} y={ROPE_Y + 60} width="8" height={FIELD_H - ROPE_Y - 60} fill="#8B6914" stroke="#1A1A1A" strokeWidth="1.5" />

            {/* touw */}
            <line x1={40 + ropeNorm * 40} y1={ROPE_Y} x2={FIELD_W - 40 + ropeNorm * 40} y2={ROPE_Y}
              stroke="#8B6914" strokeWidth="8" strokeLinecap="round" />
            <line x1={40 + ropeNorm * 40} y1={ROPE_Y} x2={FIELD_W - 40 + ropeNorm * 40} y2={ROPE_Y}
              stroke="#A0822A" strokeWidth="4" strokeLinecap="round" strokeDasharray="6 8" />

            {/* touw-lint in het midden */}
            <rect x={markerX - 5} y={ROPE_Y - 14} width="10" height="28" rx="2"
              fill="#E63946" stroke="#1A1A1A" strokeWidth="2" />

            {/* Hete Peper (rechts, speler) */}
            <g transform={`translate(${FIELD_W - 60 + ropeNorm * 30} ${ROPE_Y - 20})`}>
              <ellipse cx="0" cy="30" rx="22" ry="30" fill="#E63946" stroke="#1A1A1A" strokeWidth="2.5" />
              <ellipse cx="0" cy="-4" rx="10" ry="5" fill="#3FA34D" stroke="#1A1A1A" strokeWidth="1.5" transform="rotate(-10)" />
              <circle cx="-7" cy="18" r="4" fill="#FFF" />
              <circle cx="7" cy="18" r="4" fill="#FFF" />
              <circle cx="-7" cy="18" r="2" fill="#1A1A1A" />
              <circle cx="7" cy="18" r="2" fill="#1A1A1A" />
              <path d="M -5 28 Q 0 34 5 28" stroke="#1A1A1A" strokeWidth="2" fill="none" />
              <line x1="-18" y1="22" x2="-35" y2={20} stroke="#E63946" strokeWidth="4" strokeLinecap="round" />
              <line x1="-18" y1="22" x2="-35" y2={20} stroke="#1A1A1A" strokeWidth="1.5" strokeLinecap="round" />
              {beat.combo >= 3 && (
                <g transform="translate(0 -14)">
                  <ellipse cx="0" cy="-8" rx={6 + beat.combo} ry={8 + beat.combo * 0.5}
                    fill="#FF8C1A" opacity="0.7" />
                  <ellipse cx="0" cy="-10" rx="4" ry="6" fill="#FFD23F" opacity="0.8" />
                </g>
              )}
            </g>

            {/* Wasknijper (links, AI) */}
            <g transform={`translate(${60 + ropeNorm * 30} ${ROPE_Y - 15})`}>
              <rect x="-15" y="0" width="30" height="40" rx="6" fill="#888" stroke="#1A1A1A" strokeWidth="2.5" />
              <circle cx="0" cy="20" r="6" fill="#666" stroke="#1A1A1A" strokeWidth="1.5" />
              <circle cx="-6" cy="12" r="3" fill="#FFF" />
              <circle cx="6" cy="12" r="3" fill="#FFF" />
              <circle cx="-6" cy="13" r="1.5" fill="#1A1A1A" />
              <circle cx="6" cy="13" r="1.5" fill="#1A1A1A" />
              <path d="M -5 30 L 0 27 L 5 30" stroke="#1A1A1A" strokeWidth="2" fill="none" />
              <line x1="18" y1="18" x2="35" y2={15} stroke="#888" strokeWidth="4" strokeLinecap="round" />
              <line x1="18" y1="18" x2="35" y2={15} stroke="#1A1A1A" strokeWidth="1.5" strokeLinecap="round" />
            </g>

            {/* deeltjes */}
            {particlesRef.current.map(dd => (
              <circle key={dd.id} cx={dd.x} cy={dd.y} r={dd.r}
                fill={dd.c} opacity={Math.max(0, dd.life * 2)} />
            ))}

            {/* ===== BEAT INDICATOR (groot, duidelijk) ===== */}
            {phase === "playing" && (
              <g transform={`translate(${CENTER} ${FIELD_H - 110})`}>
                {/* glow op de beat */}
                {onBeat && (
                  <circle cx="0" cy="0" r="90" fill="url(#pt-glow)" opacity="0.8" />
                )}

                {/* vaste doelring */}
                <circle cx="0" cy="0" r={TARGET_R}
                  fill="none" stroke="#FFF" strokeWidth="5" opacity="0.3" />
                <circle cx="0" cy="0" r={TARGET_R}
                  fill="none"
                  stroke={onBeat ? "#FFD23F" : nearBeat ? "#3FA34D" : "#FFF"}
                  strokeWidth={onBeat ? "8" : "5"}
                  opacity={onBeat ? 1 : 0.5}
                  strokeDasharray={onBeat ? "none" : "12 6"} />

                {/* krimpende approach-cirkel */}
                <circle cx="0" cy="0" r={approachRadius}
                  fill="none"
                  stroke="#FFD23F"
                  strokeWidth="4"
                  opacity={approachOpacity} />

                {/* beat-puls flash op moment van beat */}
                {beatBounce > 0 && (
                  <circle cx="0" cy="0" r={TARGET_R + beatBounce * 20}
                    fill="none" stroke="#FFD23F" strokeWidth={4 * beatBounce}
                    opacity={beatBounce * 0.9} />
                )}

                {/* grote achtergrond cirkel */}
                <circle cx="0" cy="0" r={TARGET_R - 6}
                  fill={onBeat ? "rgba(255,210,63,0.25)" : "rgba(0,0,0,0.3)"} />

                {/* centraal icoon */}
                <text x="0" y="8" textAnchor="middle" fill="#FFF8EC"
                  fontFamily="'Bangers', sans-serif" fontSize="32">
                  {tapFlashRef.current > 0 ? "👊" : onBeat ? "🔥" : "👆"}
                </text>

                {/* "TIK NU!" tekst wanneer op de beat */}
                {onBeat && (
                  <text x="0" y={-TARGET_R - 14} textAnchor="middle" fill="#FFD23F"
                    fontFamily="'Bangers', sans-serif" fontSize="20"
                    stroke="#1A1A1A" strokeWidth="2" paintOrder="stroke"
                    opacity={0.6 + beatBounce * 0.4}>
                    TIK NU!
                  </text>
                )}

                {/* combo */}
                {beat.combo >= 2 && (
                  <text x="0" y={TARGET_R + 24} textAnchor="middle" fill="#FFD23F"
                    fontFamily="'Bangers', sans-serif" fontSize="18"
                    stroke="#1A1A1A" strokeWidth="1.5" paintOrder="stroke">
                    🔥 {beat.combo}× COMBO
                  </text>
                )}
              </g>
            )}

            {/* hit feedback ringen */}
            {ringRef.current.map(r => (
              <g key={r.id} transform={`translate(${CENTER} ${FIELD_H - 110})`}>
                <circle cx="0" cy="0" r={TARGET_R + r.t * 50}
                  fill="none" stroke={r.color} strokeWidth={Math.max(0, 4 - r.t * 4)}
                  opacity={Math.max(0, 1 - r.t * 1.3)} />
                <text x="0" y={-TARGET_R - 30 - r.t * 40} textAnchor="middle" fill={r.color}
                  fontFamily="'Bangers', sans-serif" fontSize={22 + r.t * 10}
                  opacity={Math.max(0, 1 - r.t * 1.3)}
                  stroke="#1A1A1A" strokeWidth="1.5" paintOrder="stroke">
                  {r.label}
                </text>
              </g>
            ))}

            {/* touwmeter (bovenaan) */}
            {phase === "playing" && (
              <g>
                <rect x="40" y="16" width={FIELD_W - 80} height="30" rx="6"
                  fill="#2A2A3A" stroke="#1A1A1A" strokeWidth="2" />
                <line x1={CENTER} y1="14" x2={CENTER} y2="48"
                  stroke="#FFD23F" strokeWidth="2" />
                <rect x={CENTER} y="18" width={ropeNorm * (FIELD_W / 2 - 44)}
                  height="26" rx="4"
                  fill={ropeNorm > 0 ? "#3FA34D" : "#E63946"} opacity="0.8" />
                <text x="50" y="36" fill="#888" fontFamily="'Bangers', sans-serif" fontSize="14">👔</text>
                <text x={FIELD_W - 56} y="36" fill="#E63946" fontFamily="'Bangers', sans-serif" fontSize="14">🌶️</text>
              </g>
            )}

            {/* timer */}
            {phase === "playing" && (
              <text x={CENTER} y="75" textAnchor="middle" fill="#FFF"
                fontFamily="'Bangers', sans-serif" fontSize="26"
                stroke="#1A1A1A" strokeWidth="2" paintOrder="stroke">
                ⏱ {Math.ceil(timeRef.current)}s
              </text>
            )}

            {/* BPM */}
            {phase === "playing" && (
              <text x={CENTER} y="98" textAnchor="middle" fill="#FFD23F"
                fontFamily="'Bangers', sans-serif" fontSize="15"
                stroke="#1A1A1A" strokeWidth="1" paintOrder="stroke" opacity="0.6">
                ♪ {beat.bpm} BPM
              </text>
            )}
          </svg>

          {/* tap flash overlay */}
          {tapFlashRef.current > 0.5 && (
            <div style={{
              position: "absolute", inset: 0,
              background: "rgba(255,210,63,0.18)",
              pointerEvents: "none",
              borderRadius: 4,
            }} />
          )}

          {phase === "roundWin" && (
            <Overlay>
              <Title color="#3FA34D">RONDE GEWONNEN!</Title>
              <p style={oText}>
                Hete Peper trekt de wasknijper over de lijn! 🔥<br />
                Perfect: {beat.perfectHits} | Goed: {beat.goodHits} | Mis: {beat.misses}<br />
                Max combo: {beat.maxCombo}×
              </p>
            </Overlay>
          )}

          {phase === "intro" && (
            <Overlay>
              <Title color="#FF8C1A">TOUWTREKKEN</Title>
              <p style={oText}>
                Help Hete Peper het touwtrekken te winnen!<br />
                Tik wanneer de <strong>gele cirkel</strong> de witte ring raakt.<br />
                Hoe preciezer, hoe harder Peper trekt. Combo's geven extra kracht! 🔥
              </p>
              <div style={{ display: "flex", gap: 10, marginTop: 8 }}>
                <DiffBtn id="mild" selected={difficulty === "mild"} onClick={() => pickDifficulty("mild")} />
                <DiffBtn id="pittig" selected={difficulty === "pittig"} onClick={() => pickDifficulty("pittig")} />
                <DiffBtn id="vlammend" selected={difficulty === "vlammend"} onClick={() => pickDifficulty("vlammend")} />
              </div>
              <BigBtn onClick={startGame} color="#E63946">▶ TREK!</BigBtn>
            </Overlay>
          )}

          {phase === "result" && (
            <Overlay>
              <Title color={resultRef.current === "lose" ? "#E63946" : "#FFD23F"}>
                {resultRef.current === "lose" ? "VERLOREN!" : "GEWONNEN!"}
              </Title>
              <p style={oText}>
                {resultRef.current === "lose"
                  ? "De wasknijper was te sterk..."
                  : `Je hebt alle ${d.rounds} rondes gewonnen!`}
                <br />
                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={() => setPhase("intro")} color="#3FA34D">↻ NOG EENS</BigBtn>
            </Overlay>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { PeperTouwtrekken });
