// peper-breakdance.jsx, ritme-battle in oldskool pixelart. Hete Peper danst
// tegen de Boze Wasknijper op 8-bit muziek. Tik precies op de beat: hoe beter
// je timing, hoe straffer de moves (toprock → footwork → freeze → windmill).
// De computer danst mee met een eigen trefkans per pit. Drie rondes, de
// dansvloer (het publiek) beslist wie wint.
//
// Techniek:
//   - Muziek is een eigen chiptune-sequencer op WebAudio. De beat-tijden komen
//     rechtstreeks van de audio-klok, dus tik-beoordeling is sample-precies.
//   - Graphics: canvas van 192x108 pixels, sprites als tekst-tekeningen, CSS
//     schaalt op met image-rendering: pixelated.
//   - Input: tik/klik op het speelveld, spatie/Enter/pijl omhoog, of gamepad A.

const BD_W = 256, BD_H = 144;
const BD_SCALE = 3; // canvas-pixels per sprite-pixel

const BD_PALET = {
  K: "#1A1A1A", R: "#E63946", r: "#B81F2D", G: "#3FA34D", g: "#2B7A38",
  W: "#FFFFFF", Y: "#FFD23F", O: "#FF8C1A", S: "#C8C8C8", s: "#7A7A7A",
  B: "#2D9CDB", P: "#FF80AF",
};

// Sprites: 14 kolommen x 18 rijen, '.' = transparant.
const BD_SPRITES = {
  top1: [
    "......gGG.....", ".....GGGGGG...", "....GGGGGGGGg.", ".....RRRRRR...",
    "....RWKRRWKR..", "....RRRRRRRR..", "....RRKKKKRR..", "K....RRRRRR..K",
    ".K...RRRRRR.K.", "..K.RRRRRRRK..", "...KRRRRRRK...", ".....rRRRr....",
    "......rRr.....", "......KKK.....", ".....KK.KK....", "....KK...KK...",
    "...KKK...KKK..", "..............",
  ],
  top2: [
    "......gGG.....", ".....GGGGGG...", "....GGGGGGGGg.", ".....RRRRRR...",
    "....RWKRRWKR..", "....RRRRRRRR..", "....RRKKKKRR..", ".....RRRRRR...",
    "KKKK.RRRRRR.KK", "....KRRRRRRK.K", "....RRRRRRRR..", ".....rRRRr....",
    "......rRr.....", "......KKK.....", ".....KK.KKK...", "....KK....KKK.",
    "...KKK......KK", "..............",
  ],
  foot: [
    "..............", "..............", "..............", "..............",
    "......gGG.....", ".....GGGGGG...", "....GGGGGGGGg.", ".....RRRRRR...",
    "....RWKRRWKR..", "....RRRRRRRR..", "....RRKKKKRR..", "...K.RRRRRR.K.",
    "..K.RRRRRRRR.K", ".K...rRRRRr.K.", ".K....rRRr.KKK", "KK....KKKKKK..",
    "K...KKK...KKKK", "KK.KKK........",
  ],
  freeze: [
    "..KK......KK..", "...KK....KK...", "....KK..KK....", ".....KKKK.....",
    "......rRr.....", ".....rRRRr....", "....RRRRRRRR..", "....RRRRRRRR..",
    "....RRRRRRRR..", "K...RRKKKKRR..", "K...RRRRRRRR..", ".K..RWKRRWKR..",
    ".KK..RRRRRR...", "..K.GGGGGGGGg.", "..K..GGGGGG...", "..K...gGG.....",
    "..KK..........", "..KKK.........",
  ],
  spin: [
    "..........KK..", ".........KK...", "..........KKK.", "...........KK.",
    "..gG..RRRRRr..", ".GGGG.RRRRRRr.", "GGGGGGRRRRRRRK", ".GRKWRRRRRRRRK",
    ".GRKWRRRRRRRK.", ".GKKRRRRRRRr..", "..RRRRRRRRr...", "K..K..........",
    ".KK...........", "..............", "..............", "..............",
    "..............", "..............",
  ],
  oops: [
    "..............", "..............", "..............", "..............",
    "..............", "..............", "..............", ".Y.........Y..",
    "..............", "..gG.RRRRRr...", ".GGGGRRRRRRr..", "GGGGGGRRRRRRK.",
    ".GRKWRRRRRRRKK", ".GRWKRRRRRRK..", ".GKKKRRRRRRK.K", "..RRRRRRRRr.KK",
    "...K.K.KKKKK..", "..............",
  ],
  top3: [
    "......gGG.....", ".....GGGGGG...", "....GGGGGGGGg.", ".....RRRRRR...",
    "....RWKRRWKR..", "....RRRRRRRR..", "....RRKKKKRR..", "K....RRRRRR...",
    "KK...RRRRRR.KK", "..K.RRRRRRRK..", "...KRRRRRRK...", ".....rRRRr....",
    "......rRr.....", ".....KKKKK....", "......KKK.....", ".....KK.KK....",
    "....KKK.KKK...", "..............",
  ],
  headspin: [
    "KK..........KK", ".KK........KK.", "..KK......KK..", "...KKK..KKK...",
    ".....KKKK.....", "......rRr.....", ".....rRRRr....", "....RRRRRRRR..",
    "K...RRRRRRRR.K", ".KK.RRRRRRRRKK", "...KRRKKKKRRK.", "....RRRRRRRR..",
    "....RWKRRWKR..", ".....RRRRRR...", "....GGGGGGGGg.", ".....GGGGGG...",
    "......gGG.....", "..............",
  ],
  kn3: [
    ".....SSSS.....", "K...SSSSSS...K", "K...SWKSWK...K", ".K..SSSSSS..K.",
    ".K..SKKKKS..K.", "..K.SSSSSS.K..", "...sSSSSSSs...", "...ssssssss...",
    "...SSSSSSSS...", "...SSSs.sSSS..", "...SSS...SSS..", "...SSS...SSS..",
    "...SSS...SSS..", "...SSS...SSS..", "...SSS...SSS..", "...sss...sss..",
    "..............", "..............",
  ],
  kn1: [
    ".....SSSS.....", "....SSSSSS....", "....SWKSWK....", "....SSSSSS....",
    "....SKKKKS....", "....SSSSSS....", "...sSSSSSSs...", "...ssssssss...",
    "...SSSSSSSS...", "...SSSs.sSSS..", "...SSS...SSS..", "...SSS...SSS..",
    "...SSS...SSS..", "...SSS...SSS..", "...SSS...SSS..", "...sss...sss..",
    "..............", "..............",
  ],
  kn2: [
    ".....SSSS.....", "....SSSSSS....", "....SWKSWK....", "....SSSSSS....",
    "....SKKKKS....", "....SSSSSS....", "...sSSSSSSs...", "KK.ssssssss.KK",
    "..KSSSSSSSSK..", "...SSSs.sSSS..", "..SSS....SSS..", "..SSS.....SSS.",
    ".SSS......SSS.", ".SSS.......SSS", "SSS........SSS", "sss........sss",
    "..............", "..............",
  ],
  knspin: [
    "..............", "..............", "..............", "..............",
    "..SSSSSSSS....", ".SSSSSSSSSSS..", ".SKSSSSSSSSSSS", ".SWSSSSs......",
    ".SKSssssSSSSSS", ".SWSSSSs......", ".SKSSSSSSSSSSS", ".SSSSSSSSSSS..",
    "..SSSSSSSS....", "..............", "..............", "..............",
    "..............", "..............",
  ],
  knoops: [
    "..............", "..............", "..............", "..............",
    "..............", "..............", "..Y........Y..", "..............",
    "..............", "...SSSSSSSSSS.", "..SSSSSSSSSSSS", "..SKSSSSs.....",
    "..SWSsssSSSSSS", "..SKSSSSs.....", "..SSSSSSSSSSSS", "...SSSSSSSSSS.",
    "..............", "..............",
  ],
};

// Tekent een sprite met BD_SCALE canvas-pixels per teken, optioneel gespiegeld.
function bdDrawSprite(g, naam, x, y, flip) {
  const rows = BD_SPRITES[naam];
  if (!rows) return;
  const S = BD_SCALE;
  for (let r = 0; r < rows.length; r++) {
    const row = rows[r];
    for (let c = 0; c < 14; c++) {
      const ch = row[c];
      if (!ch || ch === ".") continue;
      g.fillStyle = BD_PALET[ch] || "#F0F";
      const cx = flip ? (13 - c) : c;
      g.fillRect(x + cx * S, y + r * S, S, S);
    }
  }
}

// ─── 8-bit muziek ──────────────────────────────────────────────────────
// Elk liedje: 16 stappen per maat, loop van 2 maten. Midi-nummers, 0 = rust.
// bass heeft 8 noten per maat (achtsten), lead en arp 16 (zestienden).
const BD_SONGS = [
  {
    id: "funk", titel: "PEPERBOS FUNK", bpm: 108, kleur: "#FF8C1A",
    kick: [0, 4, 8, 12], snare: [4, 12], hat: [0, 2, 4, 6, 8, 10, 12, 14], openHat: [14],
    bass: [[45, 45, 57, 45, 48, 48, 43, 43], [45, 45, 57, 45, 41, 41, 43, 43]],
    lead: [[64, 0, 67, 0, 69, 0, 69, 72, 0, 69, 0, 67, 64, 0, 62, 0], [64, 0, 67, 0, 69, 0, 72, 74, 0, 72, 0, 69, 67, 0, 64, 0]],
    leadGolf: "pulse",
  },
  {
    id: "boogie", titel: "KNIJPER BOOGIE", bpm: 120, kleur: "#2D9CDB",
    kick: [0, 4, 8, 12], snare: [4, 12], hat: [0, 2, 4, 6, 8, 10, 12, 14], openHat: [6, 14],
    bass: [[48, 48, 52, 55, 48, 48, 52, 55], [53, 53, 57, 60, 55, 55, 52, 50]],
    lead: [[72, 0, 76, 79, 0, 76, 72, 0, 74, 0, 77, 0, 79, 77, 74, 0], [72, 0, 76, 79, 0, 81, 79, 0, 77, 0, 76, 0, 74, 0, 72, 0]],
    leadGolf: "square",
  },
  {
    id: "nacht", titel: "NACHT IN PEPPERONI CITY", bpm: 96, kleur: "#8E44D1",
    kick: [0, 4, 8, 12], snare: [4, 12], hat: [2, 6, 10, 14], openHat: [],
    bass: [[40, 40, 47, 40, 43, 43, 45, 45], [40, 40, 47, 40, 38, 38, 43, 43]],
    arp: [[64, 67, 71, 76, 64, 67, 71, 76, 62, 67, 71, 74, 62, 67, 71, 74], [64, 67, 71, 76, 64, 67, 71, 76, 60, 64, 67, 72, 59, 62, 67, 71]],
    lead: [[76, 0, 0, 0, 74, 0, 71, 0, 0, 0, 69, 0, 71, 0, 0, 0], [76, 0, 0, 0, 79, 0, 78, 0, 0, 0, 76, 0, 74, 0, 71, 0]],
    leadGolf: "triangle",
  },
  {
    id: "vuur", titel: "VUURSPUWER", bpm: 132, kleur: "#E63946",
    kick: [0, 4, 8, 12], snare: [4, 12], hat: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], openHat: [10],
    bass: [[40, 40, 40, 52, 40, 40, 43, 46], [40, 40, 40, 52, 38, 38, 43, 43]],
    lead: [[64, 64, 0, 67, 0, 69, 70, 69, 0, 67, 0, 64, 0, 62, 0, 64], [64, 64, 0, 67, 0, 69, 70, 71, 0, 72, 0, 71, 0, 69, 0, 67]],
    leadGolf: "pulse",
  },
];
function bdMidi(n) { return 440 * Math.pow(2, (n - 69) / 12); }

function bdMaakChip(ctx) {
  const master = ctx.createGain();
  master.gain.value = 0.45;
  master.connect(ctx.destination);
  // 25%-pulsgolf, dé NES-klank.
  const N = 48, real = new Float32Array(N), imag = new Float32Array(N);
  for (let k = 1; k < N; k++) imag[k] = (2 / (k * Math.PI)) * (1 - Math.cos(k * Math.PI * 0.5));
  const pulse = ctx.createPeriodicWave(real, imag, { disableNormalization: false });
  const noiseBuf = ctx.createBuffer(1, ctx.sampleRate, ctx.sampleRate);
  const data = noiseBuf.getChannelData(0);
  for (let i = 0; i < data.length; i++) data[i] = Math.random() * 2 - 1;

  function toon(freq, t, dur, vol, golf) {
    const osc = ctx.createOscillator();
    const gain = ctx.createGain();
    if (golf === "pulse") osc.setPeriodicWave(pulse); else osc.type = golf;
    osc.frequency.value = freq;
    gain.gain.setValueAtTime(vol, t);
    gain.gain.setValueAtTime(vol, t + dur * 0.6);
    gain.gain.linearRampToValueAtTime(0.0001, t + dur);
    osc.connect(gain).connect(master);
    osc.start(t); osc.stop(t + dur + 0.02);
  }
  function ruis(t, dur, vol, hp) {
    const src = ctx.createBufferSource();
    src.buffer = noiseBuf;
    const filt = ctx.createBiquadFilter();
    filt.type = "highpass"; filt.frequency.value = hp;
    const gain = ctx.createGain();
    gain.gain.setValueAtTime(vol, t);
    gain.gain.exponentialRampToValueAtTime(0.0001, t + dur);
    src.connect(filt).connect(gain).connect(master);
    src.start(t); src.stop(t + dur + 0.02);
  }
  function kick(t) {
    const osc = ctx.createOscillator();
    const gain = ctx.createGain();
    osc.type = "triangle";
    osc.frequency.setValueAtTime(160, t);
    osc.frequency.exponentialRampToValueAtTime(42, t + 0.11);
    gain.gain.setValueAtTime(0.9, t);
    gain.gain.exponentialRampToValueAtTime(0.0001, t + 0.16);
    osc.connect(gain).connect(master);
    osc.start(t); osc.stop(t + 0.2);
  }
  function snare(t) { ruis(t, 0.13, 0.5, 1800); toon(190, t, 0.07, 0.25, "triangle"); }
  function tik(t, hoog) { toon(hoog ? 1760 : 1175, t, 0.06, 0.3, "square"); }

  return {
    master,
    // Speelt stap `stap` van `song` op tijd t. Tijdens de count-in alleen metronoom.
    stap(song, stap, t, countIn) {
      const s = ((stap % 16) + 16) % 16, maat = Math.floor(stap / 16) % 2;
      if (countIn) {
        if (s % 4 === 0) tik(t, s === 0);
        return;
      }
      if (song.kick.includes(s)) kick(t);
      if (song.snare.includes(s)) snare(t);
      if (song.hat.includes(s)) ruis(t, song.openHat.includes(s) ? 0.1 : 0.035, song.openHat.includes(s) ? 0.14 : 0.18, 7000);
      if (s % 2 === 0) {
        const b = song.bass[maat][s / 2];
        if (b) toon(bdMidi(b), t, 0.16, 0.22, "triangle");
      }
      if (song.arp) {
        const a = song.arp[maat][s];
        if (a) toon(bdMidi(a), t, 0.1, 0.06, "pulse");
      }
      const l = song.lead[maat][s];
      if (l) toon(bdMidi(l), t, 0.12, song.leadGolf === "triangle" ? 0.16 : 0.09, song.leadGolf);
    },
    fx(soort, t) {
      if (soort === "perfect") { toon(1319, t, 0.05, 0.2, "square"); toon(1760, t + 0.05, 0.08, 0.2, "square"); }
      else if (soort === "goed") toon(988, t, 0.06, 0.15, "square");
      else if (soort === "mis") toon(110, t, 0.18, 0.25, "sawtooth");
      else if (soort === "win") [523, 659, 784, 1047].forEach((f, i) => toon(f, t + i * 0.09, 0.14, 0.2, "pulse"));
      else if (soort === "lose") [392, 349, 311, 262].forEach((f, i) => toon(f, t + i * 0.16, 0.2, 0.2, "pulse"));
    },
  };
}

// ─── Spel ──────────────────────────────────────────────────────────────
const BD_DIFF = {
  mild:     { tempo: 0.85, perfect: 0.14, goed: 0.26, ai: [0.25, 0.35], rondes: 3 },
  pittig:   { tempo: 1.0,  perfect: 0.11, goed: 0.21, ai: [0.42, 0.33], rondes: 3 },
  vlammend: { tempo: 1.15, perfect: 0.09, goed: 0.17, ai: [0.58, 0.30], rondes: 3 },
};
const BD_COUNT_IN = 4;   // tellen aftellen
const BD_BEATS = 16;     // getikte tellen per ronde

function bdVonken(s, x, y) {
  for (let i = 0; i < 14; i++) {
    const a = Math.random() * Math.PI * 2, v = 30 + Math.random() * 60;
    s.vonken.push({ x, y, vx: Math.cos(a) * v, vy: Math.sin(a) * v - 40, leven: 0.5 + Math.random() * 0.3, kleur: i % 3 === 0 ? "#FFFFFF" : "#FFD23F" });
  }
  s.ringen.push({ x, y, start: performance.now() / 1000 });
}

function bdNieuweDanser() {
  return { score: 0, combo: 0, maxCombo: 0, perfect: 0, goed: 0, mis: 0, oopsTot: -1, flashTot: 0, feedback: null };
}

function PeperBreakdance({ onClose }) {
  const isMobile = useIsMobile();
  const diff = useDifficulty("peper-breakdance", "pittig");
  const cfg = BD_DIFF[diff.level] || BD_DIFF.pittig;

  const canvasRef = React.useRef(null);
  const bgRef = React.useRef(null);
  const audioRef = React.useRef(null);   // { ctx, chip }
  const schedRef = React.useRef(null);   // sequencer-status
  const st = React.useRef(null);         // spelstatus voor de render-loop
  const [ui, setUi] = React.useState({ fase: "idle", ronde: 0 });
  const [, tick] = React.useState(0);
  const forceUi = React.useCallback(() => tick(n => n + 1), []);

  function beginStatus() {
    return {
      fase: "idle", ronde: 0,
      speler: bdNieuweDanser(), cpu: bdNieuweDanser(),
      t0: 0, beatDur: 60 / BD_SONGS[0].bpm,
      hits: {},               // beat-index → "perfect" | "goed" | "mis"
      volgendeJudge: 0,       // eerste beat die nog beoordeeld moet worden
      rondeScore: [],         // [{speler, cpu}]
      winnaar: null, shake: 0, laatsteTapBeat: -1, laatsteN: -1,
      song: BD_SONGS[0], bpm: BD_SONGS[0].bpm, vonken: [], ringen: [],
      setlist: [],           // één liedje per ronde, geen herhaling
    };
  }
  if (!st.current) st.current = beginStatus();

  function zorgAudio() {
    if (audioRef.current) {
      if (audioRef.current.ctx.state === "suspended") audioRef.current.ctx.resume().catch(() => {});
      return audioRef.current;
    }
    try {
      const AC = window.AudioContext || window.webkitAudioContext;
      const ctx = new AC();
      audioRef.current = { ctx, chip: bdMaakChip(ctx) };
    } catch { audioRef.current = null; }
    return audioRef.current;
  }
  function nu() {
    const a = audioRef.current;
    return a ? a.ctx.currentTime : performance.now() / 1000;
  }

  function stopMuziek() {
    if (schedRef.current) { clearInterval(schedRef.current.timer); schedRef.current = null; }
  }

  function startRonde(rondeNr) {
    const s = st.current;
    const a = zorgAudio();
    stopMuziek();
    s.ronde = rondeNr;
    if (s.setlist.length) s.song = s.setlist[rondeNr % s.setlist.length];
    s.fase = "spelen";
    s.hits = {};
    s.volgendeJudge = BD_COUNT_IN;
    s.laatsteTapBeat = -1;
    s.speler.combo = 0; s.cpu.combo = 0;
    s.speler.oopsTot = -1; s.cpu.oopsTot = -1;
    s.speler.feedback = null; s.cpu.feedback = null;
    s.bpm = Math.round(s.song.bpm * cfg.tempo);
    s.beatDur = 60 / s.bpm;
    s.t0 = nu() + 0.35;
    const stapDur = s.beatDur / 4;
    const totaal = (BD_COUNT_IN + BD_BEATS) * 4;
    const sched = { stap: 0, tijd: s.t0, timer: null };
    sched.timer = setInterval(() => {
      const t = nu();
      while (sched.tijd < t + 0.16 && sched.stap < totaal) {
        if (a) a.chip.stap(s.song, sched.stap - BD_COUNT_IN * 4, sched.tijd, sched.stap < BD_COUNT_IN * 4);
        sched.stap++;
        sched.tijd += stapDur;
      }
      if (sched.stap >= totaal) { clearInterval(sched.timer); }
    }, 25);
    schedRef.current = sched;
    setUi({ fase: "spelen", ronde: rondeNr });
  }

  // Setlist: het gekozen liedje opent, de andere liedjes volgen in
  // willekeurige volgorde zodat elke ronde anders klinkt.
  function maakSetlist(eerste) {
    const rest = BD_SONGS.filter(x => x.id !== eerste.id).sort(() => Math.random() - 0.5);
    const lijst = [eerste, ...rest];
    while (lijst.length < cfg.rondes) lijst.push(...rest);
    return lijst.slice(0, cfg.rondes);
  }
  function startSpel(song) {
    const eerste = song || (st.current.setlist[0]) || BD_SONGS[Math.floor(Math.random() * BD_SONGS.length)];
    st.current = beginStatus();
    st.current.setlist = maakSetlist(eerste);
    st.current.song = eerste;
    startRonde(0);
  }

  function beatTijd(n) { return st.current.t0 + n * st.current.beatDur; }

  function registreer(danser, uitkomst, tijd) {
    const punten = uitkomst === "perfect" ? 100 + Math.min(50, danser.combo * 5)
      : uitkomst === "goed" ? 50 + Math.min(20, danser.combo * 2) : 0;
    danser.score += punten;
    if (uitkomst === "mis") { danser.mis++; danser.combo = 0; }
    else {
      danser[uitkomst]++;
      danser.combo++;
      danser.maxCombo = Math.max(danser.maxCombo, danser.combo);
    }
    danser.feedback = { tekst: uitkomst === "perfect" ? "PERFECT!" : uitkomst === "goed" ? "GOED" : "MIS", tot: tijd + 0.55, soort: uitkomst };
    return punten;
  }

  function tap() {
    const s = st.current;
    if (s.fase !== "spelen") return;
    const t = nu();
    const n = Math.round((t - s.t0) / s.beatDur);
    const laatste = BD_COUNT_IN + BD_BEATS - 1;
    if (n < BD_COUNT_IN || n > laatste) return;       // aftellen: vrij oefenen
    if (s.hits[n] !== undefined) return;              // al getikt op deze beat
    const afst = Math.abs(t - beatTijd(n));
    const uitkomst = afst <= cfg.perfect ? "perfect" : afst <= cfg.goed ? "goed" : "mis";
    s.hits[n] = uitkomst;
    s.laatsteTapBeat = n;
    registreer(s.speler, uitkomst, t);
    if (uitkomst === "mis") s.speler.oopsTot = n + 1;
    if (uitkomst === "perfect") { s.speler.flashTot = t + 0.18; s.shake = t + 0.12; bdVonken(s, 88, 110); }
    const a = audioRef.current;
    if (a) a.chip.fx(uitkomst, a.ctx.currentTime);
    forceUi();
  }

  // Beats die voorbij zijn zonder tik = mis. Hier rolt ook de computer.
  function beoordeelVoorbij(t) {
    const s = st.current;
    const laatste = BD_COUNT_IN + BD_BEATS - 1;
    let veranderd = false;
    while (s.volgendeJudge <= laatste && t > beatTijd(s.volgendeJudge) + cfg.goed) {
      const n = s.volgendeJudge;
      if (s.hits[n] === undefined) {
        s.hits[n] = "mis";
        registreer(s.speler, "mis", t);
        s.speler.oopsTot = n + 1;
        const a = audioRef.current;
        if (a) a.chip.fx("mis", a.ctx.currentTime);
      }
      const r = Math.random();
      const cpuUit = r < cfg.ai[0] ? "perfect" : r < cfg.ai[0] + cfg.ai[1] ? "goed" : "mis";
      registreer(s.cpu, cpuUit, t);
      if (cpuUit === "mis") s.cpu.oopsTot = n + 1;
      if (cpuUit === "perfect") { s.cpu.flashTot = t + 0.18; bdVonken(s, 178, 110); }
      s.volgendeJudge++;
      veranderd = true;
    }
    if (veranderd) forceUi();
    if (s.volgendeJudge > laatste && t > beatTijd(laatste) + s.beatDur * 1.5) eindRonde();
  }

  function eindRonde() {
    const s = st.current;
    stopMuziek();
    const vorige = s.rondeScore.reduce((acc, r) => ({ speler: acc.speler + r.speler, cpu: acc.cpu + r.cpu }), { speler: 0, cpu: 0 });
    s.rondeScore.push({ speler: s.speler.score - vorige.speler, cpu: s.cpu.score - vorige.cpu });
    if (s.ronde + 1 >= cfg.rondes) {
      s.fase = "klaar";
      s.winnaar = s.speler.score >= s.cpu.score ? "speler" : "cpu";
      const a = audioRef.current;
      if (a) a.chip.fx(s.winnaar === "speler" ? "win" : "lose", a.ctx.currentTime + 0.2);
      setUi({ fase: "klaar", ronde: s.ronde });
    } else {
      s.fase = "pauze";
      setUi({ fase: "pauze", ronde: s.ronde });
    }
  }

  // Input: tik op speelveld, toetsenbord, gamepad (bridge stuurt spatie/Enter/ArrowUp).
  React.useEffect(() => {
    if (!diff.chosen) return;
    function onKey(e) {
      if (e.repeat) return;
      if (e.key === " " || e.key === "Enter" || e.key === "ArrowUp") {
        e.preventDefault();
        const f = st.current.fase;
        if (f === "spelen") tap();
        else if (f === "idle") startSpel();
        else if (f === "pauze") startRonde(st.current.ronde + 1);
      }
    }
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  });

  React.useEffect(() => () => {
    stopMuziek();
    const a = audioRef.current;
    if (a) { try { a.ctx.close(); } catch {} }
  }, []);

  // Statische achtergrond (lucht, muur, graffiti, speakerstacks, krat) eenmalig
  // naar een offscreen canvas. Alles wat beweegt wordt per frame getekend.
  function maakAchtergrond() {
    const c = document.createElement("canvas");
    c.width = BD_W; c.height = BD_H;
    const g = c.getContext("2d");
    // nachtlucht met sterren en maan
    g.fillStyle = "#0E1430"; g.fillRect(0, 0, BD_W, 26);
    g.fillStyle = "#FFFFFF";
    [[12, 5], [40, 12], [70, 4], [95, 15], [150, 6], [176, 17], [205, 8], [236, 14], [246, 3], [120, 20]].forEach(([x, y]) => g.fillRect(x, y, 1, 1));
    g.fillStyle = "#FFD23F"; g.fillRect(224, 5, 8, 8); g.fillStyle = "#0E1430"; g.fillRect(227, 4, 7, 7);
    // muur
    g.fillStyle = "#2A1B3D"; g.fillRect(0, 26, BD_W, 74);
    for (let y = 28; y < 100; y += 6) {
      const off = ((y - 28) / 6) % 2 ? 6 : 0;
      for (let x = -6; x < BD_W; x += 12) {
        g.fillStyle = ((x * 7 + y * 3) % 41 < 6) ? "#4A2F63" : "#3B2552";
        g.fillRect(x + off, y, 11, 5);
      }
    }
    // lichtsnoer
    g.fillStyle = "#1A1A1A"; g.fillRect(0, 27, BD_W, 1);
    // graffiti PEPER met schaduw
    const graf = ["RRR.RRR.RRR.RRR.RRR", "R.R.R...R.R.R...R.R", "RRR.RR..RRR.RR..RRR", "R...R...R...R...RR.", "R...RRR.R...RRR.R.R"];
    const gx = 92, gy = 36;
    [[2, 2, "#1A1A1A"], [0, 0, null]].forEach(([dx, dy, kleur]) => {
      graf.forEach((row, r) => [...row].forEach((ch, cI) => {
        if (ch !== "R") return;
        g.fillStyle = kleur || (r < 2 ? "#FFD23F" : r < 4 ? "#FF8C1A" : "#E63946");
        g.fillRect(gx + cI * 4 + dx, gy + r * 4 + dy, 4, 4);
      }));
    });
    // druppels onder de graffiti
    g.fillStyle = "#E63946"; [[100, 56], [124, 56], [156, 56]].forEach(([x, y]) => g.fillRect(x, y, 2, 4));
    // peper-tag links
    g.fillStyle = "#E63946";
    [[16, 40], [22, 40], [13, 44], [25, 44], [13, 48], [25, 48], [16, 52], [22, 52], [19, 55]].forEach(([x, y]) => g.fillRect(x, y, 3, 3));
    g.fillStyle = "#3FA34D"; g.fillRect(19, 34, 3, 5);
    // speakerstacks (behuizing, de conussen komen per frame)
    [[4, 218]].forEach(([l, r]) => [l, r].forEach(x => {
      g.fillStyle = "#1A1A1A"; g.fillRect(x, 50, 34, 50);
      g.fillStyle = "#2E2E2E"; g.fillRect(x + 2, 52, 30, 46);
    }));
    // krat onder de boombox
    g.fillStyle = "#8C5A2B"; g.fillRect(104, 82, 48, 18);
    g.fillStyle = "#5E3A18"; for (let y = 84; y < 100; y += 6) g.fillRect(104, y, 48, 1);
    g.fillRect(104, 82, 1, 18); g.fillRect(151, 82, 1, 18);
    // boombox
    g.fillStyle = "#1A1A1A"; g.fillRect(100, 60, 56, 24);
    g.fillStyle = "#C8C8C8"; g.fillRect(102, 62, 52, 20);
    g.fillStyle = "#1A1A1A"; g.fillRect(120, 64, 16, 7);
    g.fillStyle = "#7A7A7A"; g.fillRect(110, 55, 36, 5);
    g.fillStyle = "#2D9CDB"; g.fillRect(106, 65, 3, 2); g.fillRect(111, 65, 3, 2);
    g.fillStyle = "#E63946"; g.fillRect(141, 65, 3, 2); g.fillStyle = "#FFD23F"; g.fillRect(146, 65, 3, 2);
    return c;
  }

  function tekenConus(g, x, y, r, puls) {
    g.fillStyle = "#7A7A7A"; g.fillRect(x - r, y - r, r * 2, r * 2);
    const k = Math.max(1, Math.round(r * (0.35 + puls * 0.3)));
    g.fillStyle = "#1A1A1A"; g.fillRect(x - k, y - k, k * 2, k * 2);
  }

  // Render-loop
  React.useEffect(() => {
    if (!diff.chosen) return;
    const canvas = canvasRef.current;
    if (!canvas) return;
    const g = canvas.getContext("2d");
    g.imageSmoothingEnabled = false;
    if (!bgRef.current) bgRef.current = maakAchtergrond();
    let raf = 0;
    let vorige = performance.now();

    function poseSpeler(d, n, half) {
      if (n < d.oopsTot) return { naam: "oops", flip: false };
      if (d.combo >= 12) return (n % 8) < 4 ? { naam: "spin", flip: half } : { naam: "headspin", flip: half };
      if (d.combo >= 8) return n % 4 === 3 ? { naam: "freeze", flip: false } : { naam: n % 2 ? "top3" : "top2", flip: n % 4 >= 2 };
      if (d.combo >= 4) return { naam: "foot", flip: n % 2 === 1 };
      return { naam: ["top1", "top2", "top1", "top3"][n % 4], flip: n % 4 >= 2 };
    }
    function poseCpu(d, n, half) {
      if (n < d.oopsTot) return { naam: "knoops", flip: true };
      if (d.combo >= 6) return { naam: "knspin", flip: half };
      if (d.combo >= 3) return { naam: n % 2 ? "kn3" : "kn2", flip: true };
      return { naam: n % 2 ? "kn2" : "kn1", flip: true };
    }

    const PX = 74, CX = 158, VOET = 136;   // x van de dansers, y van de vloer onder hun voeten
    const SPOT = ["#FF80AF", "#2D9CDB", "#FFD23F", "#3FA34D"];

    function frame(nowMs) {
      const dt = Math.min(0.05, (nowMs - vorige) / 1000); vorige = nowMs;
      const s = st.current;
      const t = nu();
      if (s.fase === "spelen") beoordeelVoorbij(t);

      const actief = s.fase === "spelen";
      const beatF = actief ? Math.max(0, (t - s.t0) / s.beatDur) : (t * 1.6);
      const n = Math.floor(beatF);
      const prog = beatF - n;
      const half = prog >= 0.5;
      const puls = 1 - prog;
      const idleN = Math.floor(t * 1.6);
      if (actief && n !== s.laatsteN) { s.laatsteN = n; forceUi(); }

      const shake = s.shake > t ? (Math.random() > 0.5 ? 1 : -1) : 0;
      g.save();
      g.translate(shake, 0);
      g.drawImage(bgRef.current, 0, 0);

      // lichtsnoer knippert mee
      for (let i = 0; i < 22; i++) {
        const aan = ((i + n) % 3) === 0 || !actief && (i + idleN) % 3 === 0;
        g.fillStyle = aan ? ["#FFD23F", "#E63946", "#2D9CDB", "#3FA34D"][i % 4] : "#3B2552";
        g.fillRect(4 + i * 12, 26, 3, 3);
      }

      // spotlights vanuit de bovenhoeken, kleur wisselt per tel
      g.globalAlpha = 0.16;
      const k1 = SPOT[n % 4], k2 = SPOT[(n + 2) % 4];
      const zwaai = Math.round(Math.sin(beatF * Math.PI / 2) * 14);
      g.fillStyle = k1; g.beginPath(); g.moveTo(0, 26); g.lineTo(PX + 40 + zwaai, VOET); g.lineTo(PX - 20 + zwaai, VOET); g.closePath(); g.fill();
      g.fillStyle = k2; g.beginPath(); g.moveTo(BD_W, 26); g.lineTo(CX + 60 - zwaai, VOET); g.lineTo(CX - zwaai, VOET); g.closePath(); g.fill();
      g.globalAlpha = 1;

      // speakerconussen
      [[21, 60], [21, 76], [21, 92], [235, 60], [235, 76], [235, 92]].forEach(([x, y], i) => tekenConus(g, x, y, i % 3 === 2 ? 7 : 6, puls));

      // publiek: twee rijen, wippen om de beurt; armen omhoog bij een hoge combo
      for (let rij = 0; rij < 2; rij++) {
        for (let i = 0; i < 20; i++) {
          const x = -2 + i * 13 + (rij ? 6 : 0);
          if (x > 96 && x < 156 && rij === 0) continue;   // plek voor de boombox
          const bob = ((i + rij + n) % 2 === 0) ? Math.round(puls * 2) : 0;
          const y = (rij ? 92 : 86) - bob;
          const donker = rij ? "#141022" : "#1E1830";
          g.fillStyle = donker; g.fillRect(x, y, 9, 14);
          g.fillStyle = ["#E63946", "#FFD23F", "#2D9CDB", "#3FA34D", "#FF80AF"][(i * 3 + rij) % 5]; g.fillRect(x, y - 2, 9, 2);
          g.fillStyle = "#FFFFFF"; g.fillRect(x + 2, y + 4, 1, 1); g.fillRect(x + 6, y + 4, 1, 1);
          const hype = actief && ((x < 128 && s.speler.combo >= 8) || (x >= 128 && s.cpu.combo >= 6));
          if (hype && (i + n) % 2 === 0) { g.fillStyle = donker; g.fillRect(x - 2, y - 6, 2, 8); g.fillRect(x + 9, y - 6, 2, 8); }
        }
      }

      // vloer: dambord dat oplicht, kartonnen dansmat in het midden
      g.fillStyle = "#1A1A1A"; g.fillRect(0, 100, BD_W, 2);
      for (let ty = 0; ty < 4; ty++) for (let tx = 0; tx < 16; tx++) {
        const licht = (tx + ty) % 2 === 0;
        const glow = actief && puls > 0.6 && ((tx + ty + n) % 4 === 0);
        g.fillStyle = glow ? (licht ? "#FFD23F" : "#FF8C1A") : licht ? "#4A3A6A" : "#2E2246";
        g.fillRect(tx * 16, 102 + ty * 11, 16, 11);
      }
      g.fillStyle = "#B8865B"; g.fillRect(52, 108, 152, 32);
      g.fillStyle = "#D9A76F"; g.fillRect(54, 110, 148, 28);
      g.fillStyle = "#B8865B"; g.fillRect(128, 110, 1, 28); g.fillRect(54, 124, 148, 1);
      g.fillStyle = "#C8C8C8"; [[54, 110], [190, 110], [54, 132], [190, 132]].forEach(([x, y]) => g.fillRect(x, y, 12, 6));

      // dansers + schaduw
      const bobP = actief && s.speler.combo > 0 ? -Math.round(puls * 3) : 0;
      const bobC = actief && s.cpu.combo > 0 ? -Math.round(puls * 3) : 0;
      let pS, pC;
      if (s.fase === "klaar") {
        pS = s.winnaar === "speler" ? ((idleN % 8) < 4 ? { naam: "spin", flip: idleN % 2 === 1 } : { naam: "headspin", flip: idleN % 2 === 1 }) : { naam: "oops", flip: false };
        pC = s.winnaar === "cpu" ? { naam: "knspin", flip: idleN % 2 === 1 } : { naam: "knoops", flip: true };
      } else if (actief) {
        pS = poseSpeler(s.speler, n, half); pC = poseCpu(s.cpu, n, half);
      } else {
        pS = { naam: ["top1", "top2", "top1", "top3"][idleN % 4], flip: false };
        pC = { naam: idleN % 2 ? "kn2" : "kn1", flip: true };
      }
      g.fillStyle = "rgba(0,0,0,0.35)";
      g.fillRect(PX + 6, VOET - 2, 30, 4); g.fillRect(CX + 6, VOET - 2, 30, 4);
      if (s.speler.flashTot > t) { g.fillStyle = "rgba(255,210,63,0.30)"; g.fillRect(PX - 8, VOET - 60, 58, 62); }
      if (s.cpu.flashTot > t) { g.fillStyle = "rgba(200,200,200,0.25)"; g.fillRect(CX - 8, VOET - 60, 58, 62); }
      const SH = 18 * BD_SCALE;
      bdDrawSprite(g, pS.naam, PX, VOET - SH + bobP, pS.flip);
      bdDrawSprite(g, pC.naam, CX, VOET - SH + bobC, pC.flip);

      // vonken en ringen bij perfect
      s.vonken = s.vonken.filter(v => v.leven > 0);
      for (const v of s.vonken) {
        v.x += v.vx * dt; v.y += v.vy * dt; v.vy += 120 * dt; v.leven -= dt;
        g.fillStyle = v.kleur; g.fillRect(Math.round(v.x), Math.round(v.y), 2, 2);
      }
      const nowS = performance.now() / 1000;
      s.ringen = s.ringen.filter(r => nowS - r.start < 0.35);
      for (const r of s.ringen) {
        const rad = 6 + (nowS - r.start) * 90;
        g.strokeStyle = "#FFD23F"; g.lineWidth = 2;
        g.beginPath(); g.rect(r.x - rad, r.y - rad, rad * 2, rad * 2); g.stroke();
      }

      // beat-lampjes in de lucht
      if (actief) {
        for (let i = 0; i < 4; i++) {
          const aan = (n % 4) === i && prog < 0.35;
          const countIn = n < BD_COUNT_IN;
          g.fillStyle = "#1A1A1A"; g.fillRect(110 + i * 10, 6, 8, 8);
          g.fillStyle = aan ? (countIn ? "#2D9CDB" : "#FFD23F") : "#3B2552";
          g.fillRect(111 + i * 10, 7, 6, 6);
        }
      }
      g.restore();
      raf = requestAnimationFrame(frame);
    }
    raf = requestAnimationFrame(frame);
    return () => cancelAnimationFrame(raf);
  });

  if (!diff.chosen) {
    return (
      <div style={gameShellStyle(isMobile, "krijt")}>
        <CloseBtn onClose={onClose} isMobile={isMobile} />
        <GameTitle icon="🕺" kleur="#FFD23F" sub="Tik op de beat en versla de Wasknijper in een dance-battle">
          PEPER BREAKDANCE
        </GameTitle>
        <DifficultyPicker
          onChoose={(id) => diff.choose(id)}
          currentLevel={diff.level}
          sub="Mild = liedjes 15% trager en een rustige tegenstander. Pittig = normaal tempo. Vlammend = 15% sneller en de Knijper danst bijna perfect."
        />
      </div>
    );
  }

  const s = st.current;
  const pix = { fontFamily: "'Press Start 2P', 'Courier New', monospace", letterSpacing: 0 };
  const totaalSpeler = s.speler.score, totaalCpu = s.cpu.score;
  const publiek = totaalSpeler + totaalCpu > 0 ? totaalSpeler / (totaalSpeler + totaalCpu) : 0.5;
  const tNow = nu();
  const fbS = s.speler.feedback && s.speler.feedback.tot > tNow ? s.speler.feedback : null;
  const fbC = s.cpu.feedback && s.cpu.feedback.tot > tNow ? s.cpu.feedback : null;
  const fbKleur = (f) => f.soort === "perfect" ? "#FFD23F" : f.soort === "goed" ? "#5BB85B" : "#E63946";
  const inCountIn = ui.fase === "spelen" && (tNow - s.t0) / s.beatDur < BD_COUNT_IN;
  const countInTel = inCountIn ? Math.max(1, BD_COUNT_IN - Math.floor((tNow - s.t0) / s.beatDur)) : 0;
  const laatsteRonde = s.rondeScore[s.rondeScore.length - 1];

  const pixKnop = (kleur, extra = {}) => ({
    ...pix, fontSize: isMobile ? 11 : 13, background: kleur, color: "#1A1A1A",
    border: "4px solid #1A1A1A", boxShadow: "4px 4px 0 #1A1A1A", padding: "12px 16px",
    cursor: "pointer", minHeight: 48, lineHeight: 1.4, ...extra,
  });

  return (
    <div style={{ ...gameShellStyle(isMobile, "krijt"), width: isMobile ? "100%" : "min(760px, 94vw)" }}>
      <CloseBtn onClose={onClose} isMobile={isMobile} />
      <GameTitle icon="🕺" kleur="#FFD23F" sub={ui.fase === "idle" ? "Kies een liedje, tik op de beat, versla de Wasknijper" : `Ronde ${Math.min(s.ronde + 1, cfg.rondes)} van ${cfg.rondes} · ${s.song.titel} · ${s.bpm} BPM`}>
        PEPER BREAKDANCE
      </GameTitle>

      {/* Scorebord */}
      <div style={{ ...pix, display: "flex", justifyContent: "space-between", alignItems: "center", fontSize: isMobile ? 10 : 12, color: "#F0FAE6", position: "relative", zIndex: 1 }}>
        <span style={{ color: "#E63946" }}>PEPER <span style={{ color: "#FFF" }}>{totaalSpeler}</span></span>
        <DifficultyBadge level={diff.level} />
        <span style={{ color: "#C8C8C8" }}><span style={{ color: "#FFF" }}>{totaalCpu}</span> KNIJPER</span>
      </div>
      {/* Publieksmeter */}
      <div style={{ marginTop: 8, height: 14, border: "3px solid #1A1A1A", background: "#7A7A7A", position: "relative", zIndex: 1, boxShadow: "3px 3px 0 #1A1A1A" }}>
        <div style={{ width: `${Math.round(publiek * 100)}%`, height: "100%", background: "#E63946", transition: "width 0.3s" }} />
        <div style={{ position: "absolute", left: "50%", top: -3, bottom: -3, width: 2, background: "#FFD23F" }} />
      </div>

      {/* Speelveld */}
      <div
        onPointerDown={(e) => { e.preventDefault(); if (s.fase === "spelen") tap(); }}
        style={{
          position: "relative", marginTop: 10, border: "4px solid #1A1A1A", boxShadow: "5px 5px 0 #1A1A1A",
          aspectRatio: `${BD_W} / ${BD_H}`, background: "#2A1B3D", overflow: "hidden",
          cursor: "pointer", touchAction: "manipulation", userSelect: "none", WebkitTapHighlightColor: "transparent",
        }}>
        <canvas ref={canvasRef} width={BD_W} height={BD_H}
          style={{ width: "100%", height: "100%", display: "block", imageRendering: "pixelated" }} />

        {fbS && <div style={{ ...pix, position: "absolute", left: "10%", top: "40%", width: "30%", textAlign: "center", fontSize: isMobile ? 10 : 14, color: fbKleur(fbS), textShadow: "2px 2px 0 #1A1A1A", animation: "bd-pop 0.3s ease-out both" }}>{fbS.tekst}</div>}
        {fbC && <div style={{ ...pix, position: "absolute", left: "60%", top: "40%", width: "30%", textAlign: "center", fontSize: isMobile ? 8 : 10, color: fbKleur(fbC), textShadow: "2px 2px 0 #1A1A1A", opacity: 0.85 }}>{fbC.tekst}</div>}
        {ui.fase === "spelen" && s.speler.combo >= 2 && !inCountIn && (
          <div style={{ ...pix, position: "absolute", left: 8, bottom: 6, fontSize: isMobile ? 9 : 11, color: "#FFD23F", textShadow: "2px 2px 0 #1A1A1A" }}>COMBO x{s.speler.combo}</div>
        )}
        {inCountIn && (
          <div style={{ ...pix, position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", fontSize: isMobile ? 28 : 44, color: "#FFF", textShadow: "4px 4px 0 #1A1A1A" }}>{countInTel}</div>
        )}

        {ui.fase === "idle" && (
          <div style={{ position: "absolute", inset: 0, background: "rgba(14,10,30,0.78)", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: isMobile ? 6 : 10, padding: 10, textAlign: "center" }}>
            <div style={{ ...pix, fontSize: isMobile ? 9 : 12, color: "#FFD23F", textShadow: "2px 2px 0 #1A1A1A" }}>♫ JUKEBOX · KIES JE OPENINGSBEAT</div>
            <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: isMobile ? 6 : 8, width: "100%", maxWidth: 520 }}>
              {BD_SONGS.map(song => (
                <button key={song.id}
                  onClick={(e) => { e.stopPropagation(); startSpel(song); }}
                  onPointerDown={e => e.stopPropagation()}
                  style={pixKnop(song.kleur, { color: song.id === "nacht" || song.id === "vuur" ? "#FFF" : "#1A1A1A", fontSize: isMobile ? 8 : 10, padding: isMobile ? "8px 8px" : "10px 12px", minHeight: 40, textAlign: "left", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 8 })}>
                  <span>▶ {song.titel}</span>
                  <span style={{ opacity: 0.8, fontSize: isMobile ? 7 : 8 }}>{Math.round(song.bpm * cfg.tempo)} BPM</span>
                </button>
              ))}
            </div>
            <button onClick={(e) => { e.stopPropagation(); startSpel(BD_SONGS[Math.floor(Math.random() * BD_SONGS.length)]); }} onPointerDown={e => e.stopPropagation()}
              style={pixKnop("#F0FAE6", { fontSize: isMobile ? 8 : 10, padding: "8px 12px", minHeight: 36 })}>🎲 SHUFFLE</button>
            <div style={{ ...pix, fontSize: isMobile ? 7 : 8, color: "#F0FAE6", lineHeight: 1.8 }}>ELKE RONDE EEN ANDER LIEDJE. TIK OP ELKE TEL!</div>
          </div>
        )}

        {ui.fase === "pauze" && laatsteRonde && (
          <div style={{ position: "absolute", inset: 0, background: "rgba(20,10,30,0.7)", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 12, padding: 12, textAlign: "center" }}>
            <div style={{ ...pix, fontSize: isMobile ? 11 : 14, color: "#FFD23F", textShadow: "3px 3px 0 #1A1A1A" }}>RONDE {s.ronde + 1}</div>
            <div style={{ ...pix, fontSize: isMobile ? 9 : 11, color: "#F0FAE6", lineHeight: 1.8 }}>
              PEPER {laatsteRonde.speler} · KNIJPER {laatsteRonde.cpu}<br />
              {laatsteRonde.speler > laatsteRonde.cpu ? "HET PUBLIEK JUICHT!" : laatsteRonde.speler === laatsteRonde.cpu ? "GELIJKSPEL!" : "DE KNIJPER PAKT DEZE."}
            </div>
            {s.setlist[s.ronde + 1] && (
              <div style={{ ...pix, fontSize: isMobile ? 8 : 10, color: s.setlist[s.ronde + 1].kleur, textShadow: "2px 2px 0 #1A1A1A" }}>
                ♫ VOLGENDE BEAT: {s.setlist[s.ronde + 1].titel} · {Math.round(s.setlist[s.ronde + 1].bpm * cfg.tempo)} BPM
              </div>
            )}
            <button onClick={(e) => { e.stopPropagation(); startRonde(s.ronde + 1); }} onPointerDown={e => e.stopPropagation()} style={pixKnop("#FFD23F")}>▶ RONDE {s.ronde + 2}</button>
          </div>
        )}

        {ui.fase === "klaar" && (
          <div style={{ position: "absolute", inset: 0, background: "rgba(20,10,30,0.72)", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 10, padding: 12, textAlign: "center" }}>
            <Confetti trigger={s.winnaar === "speler" ? 1 : 0} />
            <div style={{ ...pix, fontSize: isMobile ? 13 : 18, color: s.winnaar === "speler" ? "#FFD23F" : "#E63946", textShadow: "3px 3px 0 #1A1A1A", animation: "hp-pop 0.5s ease-out both" }}>
              {s.winnaar === "speler" ? "PEPER WINT!" : "KNIJPER WINT"}
            </div>
            <div style={{ ...pix, fontSize: isMobile ? 8 : 10, color: "#F0FAE6", lineHeight: 1.9 }}>
              {totaalSpeler} · {totaalCpu}<br />
              PERFECT {s.speler.perfect} · GOED {s.speler.goed} · MIS {s.speler.mis}<br />
              BESTE COMBO x{s.speler.maxCombo}
            </div>
          </div>
        )}
      </div>

      {/* Tik-hint en knoppen */}
      {ui.fase === "spelen" && (
        <div style={{ ...pix, marginTop: 10, textAlign: "center", fontSize: isMobile ? 8 : 10, color: "#C8C8C8", position: "relative", zIndex: 1 }}>
          {inCountIn ? "AFTELLEN… VOEL DE BEAT" : "TIK HIER / SPATIE / A-KNOP"}
        </div>
      )}
      {ui.fase === "klaar" && (
        <div style={{ display: "flex", gap: 10, justifyContent: "center", flexWrap: "wrap", marginTop: 14, position: "relative", zIndex: 1 }}>
          <button onClick={() => startSpel(st.current.setlist[0])} style={pixKnop("#3FA34D", { color: "#FFF" })}>↻ NOG EENS</button>
          <button onClick={() => { stopMuziek(); st.current = beginStatus(); setUi({ fase: "idle", ronde: 0 }); }} style={pixKnop("#2D9CDB", { color: "#FFF" })}>♫ ANDER LIEDJE</button>
          <button onClick={() => { stopMuziek(); st.current = beginStatus(); setUi({ fase: "idle", ronde: 0 }); diff.reopen(); }} style={pixKnop("#FFD23F")}>🌶 PIT</button>
          <button onClick={onClose} style={pixKnop("#F0FAE6")}>SLUITEN</button>
        </div>
      )}
      <div style={{ marginTop: 10, fontSize: 14, color: "#C8C8C8", textAlign: "center", position: "relative", zIndex: 1 }}>
        Zet je geluid aan: de muziek is de beat. Perfect = 100 punten, goed = 50, combo's geven bonus.
      </div>
      <style>{`
        @keyframes bd-pop {
          0% { transform: scale(0.5); opacity: 0; }
          100% { transform: scale(1); opacity: 1; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { PeperBreakdance });
