/* Crypto Soccer — arcade edition
   - Click START (referee whistle) to begin
   - Drag tokens to push the ball
   - Keepers patrol entire goal area (can come out)
   - Kick sound on every collision · arcade SFX throughout
   - Wallets start at 0 · winner gets prize coins falling from sky */

const TOKENS = [
  { id: 'btc',  name: 'BTC',  c: '#f7931a', team: 'A', emoji: '₿' },
  { id: 'eth',  name: 'ETH',  c: '#627eea', team: 'A', emoji: 'Ξ' },
  { id: 'doge', name: 'DOGE', c: '#c2a633', team: 'B', emoji: 'Ð' },
  { id: 'ltc',  name: 'LTC',  c: '#345d9d', team: 'B', emoji: 'Ł' },
];

const CS_W = 600, CS_H = 400, CS_R = 18, CS_BR = 14;
const CS_GOAL_TOP = 140, CS_GOAL_BOT = 260;
const CS_TARGET = 3;
const CS_PRIZE = 500;

/* Players start near the ball facing it from their side */
const startChars = () => ([
  { id: 'btc',  x: 38,  y: 200, role: 'keeper' }, // Team A keeper en zona chica izq
  { id: 'eth',  x: 230, y: 200, role: 'roam'   }, // Team A roamer cerca del balón
  { id: 'doge', x: 562, y: 200, role: 'keeper' }, // Team B keeper en zona chica der
  { id: 'ltc',  x: 370, y: 200, role: 'roam'   }, // Team B roamer cerca del balón
]);
const startBall = () => ({ x: CS_W/2, y: CS_H/2, vx: 0, vy: 0 });

/* ===== Arcade sound engine ===== */
const useSounds = () => {
  const ctxRef = React.useRef(null);
  const mutedRef = React.useRef(false);
  const crowdRef = React.useRef(null);
  const ensureCtx = () => {
    if (!ctxRef.current) {
      try {
        const Ctx = window.AudioContext || window.webkitAudioContext;
        ctxRef.current = new Ctx();
      } catch (_) { return null; }
    }
    if (ctxRef.current.state === 'suspended') ctxRef.current.resume();
    return ctxRef.current;
  };
  const beep = (freq, dur, type = 'square', vol = 0.12, slide = 0) => {
    if (mutedRef.current) return;
    const ctx = ensureCtx();
    if (!ctx) return;
    const osc = ctx.createOscillator();
    const g = ctx.createGain();
    osc.type = type;
    osc.frequency.setValueAtTime(freq, ctx.currentTime);
    if (slide) osc.frequency.linearRampToValueAtTime(freq + slide, ctx.currentTime + dur);
    osc.connect(g); g.connect(ctx.destination);
    g.gain.setValueAtTime(vol, ctx.currentTime);
    g.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + dur);
    osc.start(); osc.stop(ctx.currentTime + dur + 0.02);
  };
  const sounds = React.useRef({
    whistle: () => {
      beep(2400, 0.18, 'square', 0.18);
      setTimeout(() => beep(2800, 0.12, 'square', 0.16), 80);
      setTimeout(() => beep(2200, 0.2,  'square', 0.18), 220);
    },
    kick: () => beep(180, 0.06, 'square', 0.16, -60),
    wallHit: () => beep(420, 0.03, 'square', 0.08, -120),
    goal: () => {
      const notes = [523, 659, 784, 1047];
      notes.forEach((f, i) => setTimeout(() => beep(f, 0.14, 'square', 0.18), i * 90));
    },
    win: () => {
      const seq = [523, 659, 784, 1047, 784, 1047, 1319];
      seq.forEach((f, i) => setTimeout(() => beep(f, 0.18, 'triangle', 0.18), i * 120));
    },
    coin: () => beep(1200, 0.06, 'square', 0.1, 600),
    coinFall: () => {
      // cascade of coin clicks
      for (let i = 0; i < 14; i++) {
        setTimeout(() => beep(900 + Math.random() * 600, 0.05, 'square', 0.08, 200), i * 80);
      }
    },
    confetti: () => {
      beep(800, 0.08, 'square', 0.14, 400);
      setTimeout(() => beep(1100, 0.08, 'square', 0.14, 600), 60);
      setTimeout(() => beep(1400, 0.1,  'square', 0.14, 800), 120);
    },
    click: () => beep(880, 0.04, 'square', 0.08),
    crowdStart: () => {
      if (mutedRef.current || crowdRef.current) return;
      const ctx = ensureCtx();
      if (!ctx) return;
      // Crowd = filtered pink noise + modulated LFO peaks (cheering rolls)
      const bufSize = ctx.sampleRate * 4;
      const buf = ctx.createBuffer(1, bufSize, ctx.sampleRate);
      const data = buf.getChannelData(0);
      // Pink noise approximation
      let b0=0,b1=0,b2=0,b3=0,b4=0,b5=0,b6=0;
      for (let i=0; i<bufSize; i++) {
        const w = Math.random()*2 - 1;
        b0 = 0.99886*b0 + w*0.0555179;
        b1 = 0.99332*b1 + w*0.0750759;
        b2 = 0.96900*b2 + w*0.1538520;
        b3 = 0.86650*b3 + w*0.3104856;
        b4 = 0.55000*b4 + w*0.5329522;
        b5 = -0.7616*b5 - w*0.0168980;
        data[i] = (b0+b1+b2+b3+b4+b5+b6+w*0.5362) * 0.11;
        b6 = w*0.115926;
      }
      const noise = ctx.createBufferSource();
      noise.buffer = buf;
      noise.loop = true;
      // Band-pass para sonido tipo murmullo/voces lejanas
      const filter = ctx.createBiquadFilter();
      filter.type = 'bandpass';
      filter.frequency.value = 850;
      filter.Q.value = 0.6;
      // LFO de gain para "olas" de porra
      const g = ctx.createGain();
      g.gain.value = 0.07;
      const lfo = ctx.createOscillator();
      lfo.frequency.value = 0.18;
      const lfoGain = ctx.createGain();
      lfoGain.gain.value = 0.035;
      lfo.connect(lfoGain); lfoGain.connect(g.gain);
      noise.connect(filter); filter.connect(g); g.connect(ctx.destination);
      noise.start(); lfo.start();
      crowdRef.current = { source: noise, lfo, gain: g };
    },
    crowdCheer: () => {
      // Burst de "GOOOL!" — sube el crowd 2-3 segundos
      if (mutedRef.current || !crowdRef.current) return;
      const ctx = ensureCtx();
      if (!ctx) return;
      const g = crowdRef.current.gain.gain;
      const now = ctx.currentTime;
      g.cancelScheduledValues(now);
      g.setValueAtTime(g.value, now);
      g.linearRampToValueAtTime(0.22, now + 0.15);
      g.linearRampToValueAtTime(0.07, now + 2.4);
    },
    crowdStop: () => {
      if (crowdRef.current) {
        try { crowdRef.current.source.stop(); crowdRef.current.lfo.stop(); } catch(_) {}
        crowdRef.current = null;
      }
    },
  });
  return { sounds: sounds.current, mutedRef };
};

const CryptoSoccer = () => {
  const [ball, setBall] = React.useState(startBall);
  const [chars, setChars] = React.useState(startChars);
  const [scoreA, setScoreA] = React.useState(0);
  const [scoreB, setScoreB] = React.useState(0);
  const [hint, setHint] = React.useState('press START to kick off');
  const [started, setStarted] = React.useState(false);
  const [muted, setMuted] = React.useState(false);
  const [goalFlash, setGoalFlash] = React.useState(null);
  const [showHelp, setShowHelp] = React.useState(false);
  const [winner, setWinner] = React.useState(null);
  const [walletA, setWalletA] = React.useState(0);
  const [walletB, setWalletB] = React.useState(0);
  const [claimed, setClaimed] = React.useState(false);
  const [confetti, setConfetti] = React.useState([]);
  const [fallingCoins, setFallingCoins] = React.useState([]);
  // Match clock + halves (1T / 2T)
  const HALF_SECONDS = 60;
  const [period, setPeriod] = React.useState(1); // 1 = primer tiempo, 2 = segundo tiempo, 0 = pre-kickoff / fin
  const [clock, setClock] = React.useState(HALF_SECONDS); // segundos restantes del medio tiempo
  const [halftime, setHalftime] = React.useState(false);
  // Hat-trick + per-team goal counter for celebration
  const [streakBanner, setStreakBanner] = React.useState(null); // {team, text}
  const lastGoalScorerRef = React.useRef(null);
  const consecutiveRef = React.useRef({ A: 0, B: 0 });
  // NFT trophy mint
  const [minting, setMinting] = React.useState(false);
  const [mintedTx, setMintedTx] = React.useState(null);

  const { sounds, mutedRef } = useSounds();
  mutedRef.current = muted;

  const dragRef = React.useRef(null);
  const stageRef = React.useRef(null);
  const ballRef = React.useRef(ball);
  ballRef.current = ball;
  const charsRef = React.useRef(chars);
  charsRef.current = chars;
  const pausedRef = React.useRef(true);   // start paused until whistle
  const winnerRef = React.useRef(null);
  winnerRef.current = winner;
  const startedRef = React.useRef(false);
  startedRef.current = started;
  const scoreARef = React.useRef(0);
  scoreARef.current = scoreA;
  const scoreBRef = React.useRef(0);
  scoreBRef.current = scoreB;
  const lastKickRef = React.useRef(0);
  const lastWallRef = React.useRef(0);
  const stuckFramesRef = React.useRef(0);
  const rafRef = React.useRef(null);

  // ---- Throw-in (saque tras balón fuera/atorado) ----
  const throwIn = () => {
    pausedRef.current = true;
    sounds.whistle();
    vibe(50);
    setHint('FUERA · saque desde el centro');
    setTimeout(() => {
      setBall({ x: CS_W/2, y: CS_H/2, vx: 0, vy: 0 });
      setChars(startChars());
      sounds.whistle();
      setHint(`${period === 2 ? '2T' : '1T'} · drag a token onto the ball · first to 3 goals wins`);
      if (!userPausedRef.current && inViewRef.current) pausedRef.current = false;
    }, 1100);
  };

  // ---- Vibration helper (mobile only) ----
  const vibe = (ms) => {
    if (typeof navigator !== 'undefined' && navigator.vibrate) {
      try { navigator.vibrate(ms); } catch (_) {}
    }
  };

  // ---- START ----
  const kickOff = () => {
    sounds.whistle();
    sounds.crowdStart();
    vibe(60);
    setStarted(true);
    setPeriod(1);
    setClock(HALF_SECONDS);
    setHalftime(false);
    setHint('1T · drag a token onto the ball · first to 3 goals wins');
    setBall({
      x: CS_W/2, y: CS_H/2,
      vx: 2.4 * (Math.random() < 0.5 ? -1 : 1),
      vy: 1.4 * (Math.random() < 0.5 ? -1 : 1),
    });
    pausedRef.current = false;
  };

  // ---- Match clock tick (interval que respeta pausedRef en cada tick) ----
  React.useEffect(() => {
    if (!started || winner || period === 0) return;
    const intv = setInterval(() => {
      if (pausedRef.current || winnerRef.current) return;
      setClock(c => Math.max(0, c - 1));
    }, 1000);
    return () => clearInterval(intv);
  }, [started, winner, period]);

  // ---- Reacciona cuando clock llega a 0 (half-time o final whistle) ----
  React.useEffect(() => {
    if (!started || winner || halftime || period === 0) return;
    if (clock > 0) return;
    if (period === 1) {
      // Half time
      pausedRef.current = true;
      setHalftime(true);
      setHint('HALF TIME · 2T starting…');
      sounds.whistle();
      setTimeout(() => sounds.whistle(), 200);
      vibe([80, 80, 80]);
      setTimeout(() => {
        setPeriod(2);
        setClock(HALF_SECONDS);
        setHalftime(false);
        setBall({ x: CS_W/2, y: CS_H/2, vx: 2.4 * (Math.random() < 0.5 ? -1 : 1), vy: 1.4 * (Math.random() < 0.5 ? -1 : 1) });
        setChars(startChars());
        setHint('2T · drag a token onto the ball · first to 3 goals wins');
        sounds.whistle();
        if (!userPausedRef.current && inViewRef.current) pausedRef.current = false;
      }, 2600);
    } else {
      // Final whistle
      pausedRef.current = true;
      sounds.whistle();
      setTimeout(() => sounds.whistle(), 180);
      setTimeout(() => sounds.whistle(), 360);
      sounds.crowdCheer();
      setTimeout(() => sounds.crowdStop(), 4500);
      vibe([100, 80, 100, 80, 200]);
      const a = scoreARef.current, bb = scoreBRef.current;
      if (a === bb) {
        setHint(`FULL TIME · DRAW ${a}-${bb} · tap Reset for rematch`);
        setPeriod(0);
      } else {
        const tw = a > bb ? 'A' : 'B';
        setWinner(tw);
        sounds.win();
        setHint(`Team ${tw} wins ${a}-${bb} · tap CLAIM to receive ${CS_PRIZE} BBC`);
      }
    }
  }, [clock, started, winner, period, halftime]);

  // ---- Goal ----
  const scoreGoal = (team) => {
    pausedRef.current = true;
    sounds.goal();
    sounds.crowdCheer();
    vibe([60, 40, 120]);
    const next = team === 'A' ? scoreARef.current + 1 : scoreBRef.current + 1;
    if (team === 'A') setScoreA(next);
    else setScoreB(next);
    setGoalFlash(team);

    // Streak / hat-trick tracking
    if (lastGoalScorerRef.current === team) {
      consecutiveRef.current[team]++;
    } else {
      consecutiveRef.current = { A: 0, B: 0 };
      consecutiveRef.current[team] = 1;
    }
    lastGoalScorerRef.current = team;
    const streak = consecutiveRef.current[team];
    let banner = null;
    if (streak === 2) banner = { team, text: '🔥 DOUBLE!' };
    else if (streak === 3) banner = { team, text: '🔥🔥 HAT-TRICK!' };
    else if (streak >= 4) banner = { team, text: '⚡ UNSTOPPABLE!' };
    if (banner) { setStreakBanner(banner); setTimeout(() => setStreakBanner(null), 2200); }

    setHint(banner ? banner.text : 'GOAL!');
    setTimeout(() => {
      if (next >= CS_TARGET) {
        setWinner(team);
        setGoalFlash(null);
        sounds.win();
        setHint(`Team ${team} wins · tap CLAIM to receive ${CS_PRIZE} BBC`);
        return;
      }
      setGoalFlash(null);
      const periodLabel = (period === 2 ? '2T' : '1T');
      setHint(`${periodLabel} · drag a token onto the ball · first to 3 goals wins`);
      const dir = team === 'A' ? -1 : 1;
      setBall({ x: CS_W/2, y: CS_H/2, vx: 2.6 * dir, vy: (Math.random() - 0.5) * 3 });
      setChars(startChars());
      pausedRef.current = false;
      sounds.whistle();
    }, 1400);
  };

  // ---- Pause manual + Auto-pause cuando no se ve (scroll/slide change) ----
  const [userPaused, setUserPaused] = React.useState(false);
  const userPausedRef = React.useRef(false);
  const inViewRef = React.useRef(true);

  const togglePause = () => {
    const next = !userPaused;
    setUserPaused(next);
    userPausedRef.current = next;
    if (next) {
      pausedRef.current = true;
    } else if (started && !winner && !halftime && inViewRef.current) {
      pausedRef.current = false;
    }
    sounds.click();
  };

  React.useEffect(() => {
    if (!stageRef.current) return;
    const checkVis = () => {
      if (!stageRef.current) return;
      const rect = stageRef.current.getBoundingClientRect();
      const inView =
        rect.bottom > 40 && rect.top < (window.innerHeight - 40) &&
        rect.right > 40 && rect.left < (window.innerWidth - 40) &&
        rect.width > 40;
      if (inView !== inViewRef.current) {
        inViewRef.current = inView;
        // Auto mute: silencia cuando no está visible
        mutedRef.current = !inView || muted;
        // Auto pause: pausa cuando no está visible, reanuda solo si user no pausó
        if (!inView) {
          pausedRef.current = true;
        } else if (!userPausedRef.current && started && !winner && !halftime) {
          pausedRef.current = false;
        }
      }
    };
    checkVis();
    window.addEventListener('scroll', checkVis, { passive: true });
    window.addEventListener('resize', checkVis);
    const intv = setInterval(checkVis, 500); // detecta cambio de slide del carrusel
    return () => {
      window.removeEventListener('scroll', checkVis);
      window.removeEventListener('resize', checkVis);
      clearInterval(intv);
    };
  }, [muted, started, winner, halftime]);

  // ---- NFT Trophy mint (fake but realistic for demo) ----
  const mintTrophy = () => {
    if (minting || mintedTx) return;
    setMinting(true);
    sounds.click();
    setTimeout(() => {
      const hex = '0x' + Array.from({length: 64}, () =>
        '0123456789abcdef'[Math.floor(Math.random()*16)]
      ).join('');
      setMintedTx(hex);
      setMinting(false);
      sounds.win();
      vibe([40, 40, 40, 40, 200]);
    }, 1800);
  };

  const resetMatch = () => {
    sounds.click();
    sounds.crowdStop();
    setScoreA(0);
    setScoreB(0);
    setWinner(null);
    setGoalFlash(null);
    setClaimed(false);
    setConfetti([]);
    setFallingCoins([]);
    setStarted(false);
    setPeriod(1);
    setClock(HALF_SECONDS);
    setHalftime(false);
    setMintedTx(null);
    setMinting(false);
    consecutiveRef.current = { A: 0, B: 0 };
    lastGoalScorerRef.current = null;
    setHint('press START to kick off');
    setBall(startBall());
    setChars(startChars());
    pausedRef.current = true;
  };

  // ---- Claim ----
  const claimPrize = () => {
    if (!winner || claimed) return;
    sounds.confetti();
    setTimeout(() => sounds.coinFall(), 250);
    setClaimed(true);
    const colors = ['#22d3ee', '#5eead4', '#fb7185', '#fbbf24', '#a78bfa', '#f7931a'];
    const newConfetti = Array.from({ length: 50 }, (_, i) => ({
      id: 'cf-' + Date.now() + '-' + i,
      x: 50 + (Math.random() - 0.5) * 40,
      vx: (Math.random() - 0.5) * 80,
      vy: -40 - Math.random() * 50,
      rot: Math.random() * 720,
      color: colors[i % colors.length],
    }));
    setConfetti(newConfetti);
    setTimeout(() => setConfetti([]), 2400);

    // Money falls from the sky on the WINNER'S side only
    const target = winner === 'A' ? 'left' : 'right';
    const newCoins = Array.from({ length: 30 }, (_, i) => ({
      id: 'fc-' + Date.now() + '-' + i,
      target,
      // Constrain X to the winner's half so coins really fall on that side
      startX: target === 'left'
        ? 5 + Math.random() * 38
        : 57 + Math.random() * 38,
      delay: i * 70,
    }));
    setFallingCoins(newCoins);
    setTimeout(() => setFallingCoins([]), 3000);

    setTimeout(() => {
      if (winner === 'A') setWalletA(w => w + CS_PRIZE);
      else setWalletB(w => w + CS_PRIZE);
      sounds.coin();
      setHint(`+${CS_PRIZE} BBC added to Team ${winner} wallet · tap Reset for rematch`);
    }, 1800);
  };

  // ---- Game loop (always running, paused via flag) ----
  React.useEffect(() => {
    let last = performance.now();
    const tick = (now) => {
      const dt = Math.min(40, now - last) / 1000;
      last = now;
      rafRef.current = requestAnimationFrame(tick);
      if (pausedRef.current || winnerRef.current || !startedRef.current) return;

      let b = { ...ballRef.current };
      b.vx *= 0.97;
      b.vy *= 0.97;
      // Cap max speed so ball never teleports through keepers
      const MAX_SPEED = 14;
      const sp = Math.sqrt(b.vx*b.vx + b.vy*b.vy);
      if (sp > MAX_SPEED) { b.vx = b.vx / sp * MAX_SPEED; b.vy = b.vy / sp * MAX_SPEED; }
      b.x += b.vx * dt * 60;
      b.y += b.vy * dt * 60;

      const MIN_BOUNCE = 1.4;
      const CORNER_R = 38; // radio del cuarto-círculo en cada esquina (estilo cancha pro)
      const wallHit = (now - lastWallRef.current > 80);

      // ===== Esquinas redondeadas — física circular en los 4 vértices =====
      // En lugar de que las paredes hagan un ángulo de 90°, en cada esquina
      // hay un cuarto-círculo. La pelota rebota como contra un arco → nunca
      // se queda atorada en el vértice.
      const corners = [
        { cx: CS_BR + CORNER_R,        cy: CS_BR + CORNER_R,        zx: CS_BR + CORNER_R, zy: CS_BR + CORNER_R, dir: 'tl' },
        { cx: CS_W - CS_BR - CORNER_R, cy: CS_BR + CORNER_R,        zx: CS_W - CS_BR - CORNER_R, zy: CS_BR + CORNER_R, dir: 'tr' },
        { cx: CS_BR + CORNER_R,        cy: CS_H - CS_BR - CORNER_R, zx: CS_BR + CORNER_R, zy: CS_H - CS_BR - CORNER_R, dir: 'bl' },
        { cx: CS_W - CS_BR - CORNER_R, cy: CS_H - CS_BR - CORNER_R, zx: CS_W - CS_BR - CORNER_R, zy: CS_H - CS_BR - CORNER_R, dir: 'br' },
      ];
      for (const cr of corners) {
        // ¿La pelota está en el cuadrante de esa esquina?
        const inQuadrant =
          (cr.dir === 'tl' && b.x < cr.zx && b.y < cr.zy) ||
          (cr.dir === 'tr' && b.x > cr.zx && b.y < cr.zy) ||
          (cr.dir === 'bl' && b.x < cr.zx && b.y > cr.zy) ||
          (cr.dir === 'br' && b.x > cr.zx && b.y > cr.zy);
        if (!inQuadrant) continue;
        const dx = b.x - cr.cx, dy = b.y - cr.cy;
        const d = Math.sqrt(dx * dx + dy * dy);
        const limit = CORNER_R - CS_BR;
        if (d > limit && d > 0.01) {
          // Está fuera del arco — empujar hacia adentro y reflejar
          const nx = dx / d, ny = dy / d;
          b.x = cr.cx + nx * limit;
          b.y = cr.cy + ny * limit;
          const dot = b.vx * nx + b.vy * ny;
          if (dot > 0) {
            b.vx = (b.vx - 2 * dot * nx) * 0.55;
            b.vy = (b.vy - 2 * dot * ny) * 0.55;
            // Asegurar velocidad mínima de rebote en dirección normal
            const reboundSpeed = Math.sqrt(b.vx * b.vx + b.vy * b.vy);
            if (reboundSpeed < MIN_BOUNCE * 1.5) {
              b.vx = -nx * MIN_BOUNCE * 2;
              b.vy = -ny * MIN_BOUNCE * 2;
            }
            if (wallHit) { sounds.wallHit(); lastWallRef.current = now; }
          }
        }
      }
      if (b.y < CS_BR) {
        b.y = CS_BR;
        b.vy = Math.max(MIN_BOUNCE, Math.abs(b.vy) * 0.55);
        if (wallHit && Math.abs(b.vy) > 2) { sounds.wallHit(); lastWallRef.current = now; }
      }
      if (b.y > CS_H - CS_BR) {
        b.y = CS_H - CS_BR;
        b.vy = -Math.max(MIN_BOUNCE, Math.abs(b.vy) * 0.55);
        if (wallHit && Math.abs(b.vy) > 2) { sounds.wallHit(); lastWallRef.current = now; }
      }
      if (b.x < CS_BR) {
        if (b.y > CS_GOAL_TOP && b.y < CS_GOAL_BOT) { scoreGoal('B'); return; }
        b.x = CS_BR;
        b.vx = Math.max(MIN_BOUNCE, Math.abs(b.vx) * 0.55);
        if (wallHit && Math.abs(b.vx) > 2) { sounds.wallHit(); lastWallRef.current = now; }
      }
      if (b.x > CS_W - CS_BR) {
        if (b.y > CS_GOAL_TOP && b.y < CS_GOAL_BOT) { scoreGoal('A'); return; }
        b.x = CS_W - CS_BR;
        b.vx = -Math.max(MIN_BOUNCE, Math.abs(b.vx) * 0.55);
        if (wallHit && Math.abs(b.vx) > 2) { sounds.wallHit(); lastWallRef.current = now; }
      }

      // Stuck → "FUERA" — declarado out of bounds, balón al centro + jugadores reset
      const speedReal = Math.sqrt(b.vx * b.vx + b.vy * b.vy);
      const EDGE = 36;
      const nearEdge =
        b.x < CS_BR + EDGE || b.x > CS_W - CS_BR - EDGE ||
        b.y < CS_BR + EDGE || b.y > CS_H - CS_BR - EDGE;
      if (nearEdge && speedReal < 2.5) {
        stuckFramesRef.current++;
        if (stuckFramesRef.current > 25) {
          stuckFramesRef.current = 0;
          throwIn();
          return;
        }
      } else {
        stuckFramesRef.current = 0;
      }

      // Char collisions → kick sound (rate limited)
      // Keepers: hitbox more solid + can't be crossed (CCD-lite via prev position)
      const canKick = (now - lastKickRef.current > 90);
      charsRef.current.forEach(c => {
        const isKeeper = c.role === 'keeper';
        const dx = b.x - c.x, dy = b.y - c.y;
        const d = Math.sqrt(dx*dx + dy*dy);
        const minD = CS_R + CS_BR + (isKeeper ? 4 : 0);
        if (d < minD && d > 0) {
          const nx = dx / d, ny = dy / d;
          b.x = c.x + nx * minD;
          b.y = c.y + ny * minD;
          const power = (isKeeper ? 10 : 8) + (minD - d) * 0.8;
          b.vx = nx * power;
          b.vy = ny * power;
          if (canKick) { sounds.kick(); lastKickRef.current = now; }
        } else if (isKeeper) {
          // Solid keeper wall: si la pelota cruzó el plano X del keeper
          // (entró por un lado y salió por el otro) dentro de su radio Y,
          // empujarla de vuelta — evita que pase por detrás.
          const prevX = b.x - b.vx * dt * 60;
          const crossed = (prevX - c.x) * (b.x - c.x) < 0; // signo cambió
          if (crossed && Math.abs(b.y - c.y) < CS_R + CS_BR + 6) {
            const sideSign = prevX < c.x ? -1 : 1; // empujar al lado donde venía
            b.x = c.x + sideSign * (CS_R + CS_BR + 6);
            b.vx = sideSign * Math.max(7, Math.abs(b.vx) * 0.8);
            if (canKick) { sounds.kick(); lastKickRef.current = now; }
          }
        }
      });
      setBall(b);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, []);

  // ---- AI: keepers come out to block angles, roamers chase ----
  React.useEffect(() => {
    const id = setInterval(() => {
      if (pausedRef.current || winnerRef.current || !startedRef.current) return;
      setChars(prev => prev.map(c => {
        if (dragRef.current && dragRef.current.id === c.id) return c;
        const b = ballRef.current;
        if (c.role === 'keeper') {
          // El portero vive en la zona chica, pero PUEDE salir a despejar
          // cuando la pelota se mete en su mitad / cerca de su área.
          // Cuando la pelota se aleja → regresa RÁPIDO al área chica.
          const isLeft = (c.id === 'btc');
          const xHomeMin = isLeft ? 26 : 556;
          const xHomeMax = isLeft ? 48 : 574;
          const xHomeCenter = isLeft ? 38 : 562;
          // Hasta dónde puede salir a buscar la pelota
          const xMaxOut = isLeft ? 130 : (CS_W - 130);
          // ¿La pelota está cerca de su área? → autoriza salida
          const ballNearArea = isLeft ? b.x < 180 : b.x > CS_W - 180;
          let homeX;
          if (ballNearArea) {
            // Sale a despejar — sigue la X de la pelota hasta xMaxOut
            const want = isLeft ? Math.min(xMaxOut, b.x - 12) : Math.max(xMaxOut, b.x + 12);
            homeX = want;
          } else {
            // Pelota lejos → regresa al centro de su área chica
            homeX = xHomeCenter;
          }
          // ¿Está fuera del área chica? → paso de regreso más rápido
          const outsideArea = isLeft ? c.x > xHomeMax + 6 : c.x < xHomeMin - 6;
          const wantsToReturn = !ballNearArea && outsideArea;
          const xStep = wantsToReturn ? 26 : 16; // sprint de regreso
          // Track Y — predice trayectoria
          const predictedY = b.y + b.vy * 6;
          const yMin = CS_GOAL_TOP - 12;
          const yMax = CS_GOAL_BOT + 12;
          const targetY = Math.max(yMin, Math.min(yMax, predictedY));
          const dy = targetY - c.y;
          const ny = c.y + Math.sign(dy) * Math.min(Math.abs(dy), 26);
          const dx = homeX - c.x;
          const nx = c.x + Math.sign(dx) * Math.min(Math.abs(dx), xStep);
          // Clamp X: dentro del rango permitido (zona chica + salida)
          const xAbsMin = isLeft ? xHomeMin - 4 : xMaxOut;
          const xAbsMax = isLeft ? xMaxOut : xHomeMax + 4;
          const clampedX = Math.max(xAbsMin, Math.min(xAbsMax, nx));
          const clampedY = Math.max(yMin, Math.min(yMax, ny));
          return { ...c, x: clampedX, y: clampedY };
        }
        const dx = b.x - c.x, dy = b.y - c.y;
        const d = Math.sqrt(dx*dx + dy*dy);
        const step = 8 + Math.random() * 4;
        let nx = c.x, ny = c.y;
        if (d > 22) { nx = c.x + (dx/d)*step; ny = c.y + (dy/d)*step; }
        else { nx = c.x + (Math.random() - 0.5) * 8; ny = c.y + (Math.random() - 0.5) * 8; }
        return {
          ...c,
          x: Math.max(CS_R + 4, Math.min(CS_W - CS_R - 4, nx)),
          y: Math.max(CS_R + 4, Math.min(CS_H - CS_R - 4, ny)),
        };
      }));
      // Resolver overlaps player-vs-player (no se montan unos sobre otros)
      setChars(curr => {
        const next = curr.map(c => ({ ...c }));
        const minDist = CS_R * 2 + 2;
        for (let iter = 0; iter < 2; iter++) {
          for (let i = 0; i < next.length; i++) {
            // No empujar al char que se está draggeando
            if (dragRef.current && dragRef.current.id === next[i].id) continue;
            for (let j = i + 1; j < next.length; j++) {
              const a = next[i], b2 = next[j];
              const dx2 = b2.x - a.x, dy2 = b2.y - a.y;
              const d2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
              if (d2 < minDist && d2 > 0.1) {
                const push = (minDist - d2) / 2;
                const nx2 = dx2 / d2, ny2 = dy2 / d2;
                a.x -= nx2 * push;
                a.y -= ny2 * push;
                if (!dragRef.current || dragRef.current.id !== b2.id) {
                  b2.x += nx2 * push;
                  b2.y += ny2 * push;
                }
              }
            }
          }
        }
        // Clamp final
        return next.map(c => ({
          ...c,
          x: Math.max(CS_R + 4, Math.min(CS_W - CS_R - 4, c.x)),
          y: Math.max(CS_R + 4, Math.min(CS_H - CS_R - 4, c.y)),
        }));
      });
    }, 100);
    return () => clearInterval(id);
  }, []);

  // ---- Drag handlers ----
  const stagePos = (e) => {
    const rect = stageRef.current.getBoundingClientRect();
    const pt = e.touches ? e.touches[0] : e;
    return {
      x: ((pt.clientX - rect.left) / rect.width) * CS_W,
      y: ((pt.clientY - rect.top) / rect.height) * CS_H,
    };
  };
  const onDown = (id, e) => {
    if (winnerRef.current || !startedRef.current) return;
    e.preventDefault();
    const pos = stagePos(e);
    const c = charsRef.current.find(c => c.id === id);
    dragRef.current = { id, offsetX: pos.x - c.x, offsetY: pos.y - c.y, prevX: c.x, prevY: c.y };
    setHint('release to let go');
  };
  React.useEffect(() => {
    const onMove = (e) => {
      const dr = dragRef.current;
      if (!dr) return;
      e.preventDefault();
      const pos = stagePos(e);
      const target = {
        x: Math.max(CS_R, Math.min(CS_W - CS_R, pos.x - dr.offsetX)),
        y: Math.max(CS_R, Math.min(CS_H - CS_R, pos.y - dr.offsetY)),
      };
      const vx = (target.x - dr.prevX) * 1.2;
      const vy = (target.y - dr.prevY) * 1.2;
      const b = ballRef.current;
      const dx = b.x - target.x, dy = b.y - target.y;
      const d = Math.sqrt(dx*dx + dy*dy);
      if (d < CS_R + CS_BR + 8) {
        setBall(bb => ({
          ...bb,
          vx: bb.vx * 0.2 + vx + (Math.sign(vx || 1) * 2),
          vy: bb.vy * 0.2 + vy + (Math.sign(vy || 1) * 2),
        }));
      }
      dr.prevX = target.x;
      dr.prevY = target.y;
      const dragId = dr.id;
      setChars(prev => prev.map(c => c.id === dragId ? { ...c, ...target } : c));
    };
    const onUp = () => {
      if (dragRef.current) {
        dragRef.current = null;
        if (!winnerRef.current && startedRef.current) {
          setHint('drag a token onto the ball · first to 3 goals wins');
        }
      }
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    window.addEventListener('touchmove', onMove, { passive: false });
    window.addEventListener('touchend', onUp);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
      window.removeEventListener('touchmove', onMove);
      window.removeEventListener('touchend', onUp);
    };
  }, []);

  const fmt2 = (n) => Number(n).toLocaleString('en-US');

  return (
    <div className="ipad-wrap">
      <div className="ipad">
        <div className="ipad-cam"/>
        <div className="ipad-screen">
          <div className="cs-app">
            {/* Status bar */}
            <div className="sims-status">
              <span className="sims-time">9:41</span>
              <span className="sims-app-name">CryptoSoccer · Web4 League</span>
              <span className="sims-status-r">
                <button
                  className="cs-mute"
                  onClick={() => { setMuted(m => !m); sounds.click(); }}
                  aria-label={muted ? "Unmute" : "Mute"}
                  title={muted ? "Unmute" : "Mute"}
                >
                  {muted ? '🔇' : '🔊'}
                </button>
                <span className="sims-bat">100%</span>
              </span>
            </div>

            {/* Scoreboard */}
            <div className="cs-score">
              <div className="cs-team cs-team-a">
                <span className="cs-team-tokens">
                  <span className="cs-mini-tok" style={{background:'#f7931a'}}>₿</span>
                  <span className="cs-mini-tok" style={{background:'#627eea'}}>Ξ</span>
                </span>
                <div className="cs-team-id">
                  <strong>TEAM A</strong>
                  <span className="cs-team-wallet">BBC {fmt2(walletA)}</span>
                </div>
                <span className="cs-team-score">{scoreA}<span className="cs-team-target">/{CS_TARGET}</span></span>
              </div>
              <div className="cs-clock">
                {started && !winner ? (
                  <>
                    <span className="cs-clock-time">{period === 2 ? '2T' : '1T'} · {String(Math.max(0, Math.floor(clock / 60))).padStart(1, '0')}:{String(Math.max(0, clock % 60)).padStart(2, '0')}</span>
                    <span className="cs-clock-label">{CS_PRIZE} BBC PRIZE</span>
                  </>
                ) : (
                  <>
                    <span className="cs-clock-time">PRIZE</span>
                    <span className="cs-clock-label">{CS_PRIZE} BBC</span>
                  </>
                )}
              </div>
              <div className="cs-team cs-team-b">
                <span className="cs-team-score">{scoreB}<span className="cs-team-target">/{CS_TARGET}</span></span>
                <div className="cs-team-id">
                  <strong>TEAM B</strong>
                  <span className="cs-team-wallet">BBC {fmt2(walletB)}</span>
                </div>
                <span className="cs-team-tokens">
                  <span className="cs-mini-tok" style={{background:'#c2a633'}}>Ð</span>
                  <span className="cs-mini-tok" style={{background:'#345d9d'}}>Ł</span>
                </span>
              </div>
              <button
                className="cs-help-btn"
                onClick={() => { setShowHelp(s => !s); sounds.click(); }}
                aria-label="How to play"
              >?</button>
            </div>

            {showHelp && (
              <div className="cs-help-panel">
                <div className="cs-help-head">
                  <strong>How to play</strong>
                  <button onClick={() => setShowHelp(false)} aria-label="Close">✕</button>
                </div>
                <ul className="cs-help-list">
                  <li><span className="cs-help-step">1</span> Tap <strong>START</strong> for the referee whistle.</li>
                  <li><span className="cs-help-step">2</span> <strong>Drag</strong> a token to push the ball.</li>
                  <li><span className="cs-help-step">3</span> First to <strong>{CS_TARGET} goals wins {CS_PRIZE} BBC</strong>.</li>
                  <li><span className="cs-help-step">4</span> Hit <strong>Claim</strong> — coins fall on your side.</li>
                </ul>
              </div>
            )}

            {/* Field */}
            <div className="cs-field-wrap">
              <svg
                ref={stageRef}
                className="cs-field"
                viewBox={`0 0 ${CS_W} ${CS_H}`}
                preserveAspectRatio="xMidYMid meet"
              >
                <defs>
                  <linearGradient id="cs-grass" x1="0" y1="0" x2="0" y2="1">
                    <stop offset="0" stopColor="#0c2818"/>
                    <stop offset="1" stopColor="#06180e"/>
                  </linearGradient>
                  <pattern id="cs-stripes" width="60" height={CS_H} patternUnits="userSpaceOnUse">
                    <rect width="30" height={CS_H} fill="rgba(255,255,255,0.025)"/>
                  </pattern>
                </defs>
                <rect x="0" y="0" width={CS_W} height={CS_H} fill="url(#cs-grass)"/>
                <rect x="0" y="0" width={CS_W} height={CS_H} fill="url(#cs-stripes)"/>
                {/* Línea perimetral con esquinas redondeadas (coincide con física circular) */}
                <rect x="8" y="8" width={CS_W-16} height={CS_H-16} rx="38" ry="38" fill="none" stroke="rgba(255,255,255,0.28)" strokeWidth="1.5"/>
                <line x1={CS_W/2} y1="8" x2={CS_W/2} y2={CS_H-8} stroke="rgba(255,255,255,0.25)" strokeWidth="1.5"/>
                <circle cx={CS_W/2} cy={CS_H/2} r="40" fill="none" stroke="rgba(255,255,255,0.25)" strokeWidth="1.5"/>
                <circle cx={CS_W/2} cy={CS_H/2} r="3" fill="rgba(255,255,255,0.6)"/>
                <rect x="8" y={CS_GOAL_TOP - 18} width="44" height={CS_GOAL_BOT - CS_GOAL_TOP + 36} fill="none" stroke="rgba(255,255,255,0.2)" strokeWidth="1"/>
                <rect x={CS_W - 52} y={CS_GOAL_TOP - 18} width="44" height={CS_GOAL_BOT - CS_GOAL_TOP + 36} fill="none" stroke="rgba(255,255,255,0.2)" strokeWidth="1"/>
                {/* Goal A (left) — postes + crossbar + red de gol */}
                <rect x="-12" y={CS_GOAL_TOP - 6} width="20" height={CS_GOAL_BOT - CS_GOAL_TOP + 12} fill="rgba(34, 211, 238, 0.10)"/>
                <pattern id="cs-net-a" width="6" height="6" patternUnits="userSpaceOnUse">
                  <path d="M0 0 L6 6 M6 0 L0 6" stroke="rgba(255,255,255,0.35)" strokeWidth="0.6"/>
                </pattern>
                <rect x="-12" y={CS_GOAL_TOP - 6} width="20" height={CS_GOAL_BOT - CS_GOAL_TOP + 12} fill="url(#cs-net-a)"/>
                <rect x="-2" y={CS_GOAL_TOP - 6} width="4" height="4" fill="#fff"/>
                <rect x="-2" y={CS_GOAL_BOT + 2} width="4" height="4" fill="#fff"/>
                <line x1="-2" y1={CS_GOAL_TOP - 4} x2="-2" y2={CS_GOAL_BOT + 4} stroke="#22d3ee" strokeWidth="3"/>
                <line x1="-2" y1={CS_GOAL_TOP - 4} x2="8" y2={CS_GOAL_TOP - 4} stroke="#22d3ee" strokeWidth="2"/>
                <line x1="-2" y1={CS_GOAL_BOT + 4} x2="8" y2={CS_GOAL_BOT + 4} stroke="#22d3ee" strokeWidth="2"/>

                {/* Goal B (right) — postes + crossbar + red */}
                <rect x={CS_W - 8} y={CS_GOAL_TOP - 6} width="20" height={CS_GOAL_BOT - CS_GOAL_TOP + 12} fill="rgba(251, 113, 133, 0.10)"/>
                <pattern id="cs-net-b" width="6" height="6" patternUnits="userSpaceOnUse">
                  <path d="M0 0 L6 6 M6 0 L0 6" stroke="rgba(255,255,255,0.35)" strokeWidth="0.6"/>
                </pattern>
                <rect x={CS_W - 8} y={CS_GOAL_TOP - 6} width="20" height={CS_GOAL_BOT - CS_GOAL_TOP + 12} fill="url(#cs-net-b)"/>
                <rect x={CS_W - 2} y={CS_GOAL_TOP - 6} width="4" height="4" fill="#fff"/>
                <rect x={CS_W - 2} y={CS_GOAL_BOT + 2} width="4" height="4" fill="#fff"/>
                <line x1={CS_W + 2} y1={CS_GOAL_TOP - 4} x2={CS_W + 2} y2={CS_GOAL_BOT + 4} stroke="#fb7185" strokeWidth="3"/>
                <line x1={CS_W + 2} y1={CS_GOAL_TOP - 4} x2={CS_W - 8} y2={CS_GOAL_TOP - 4} stroke="#fb7185" strokeWidth="2"/>
                <line x1={CS_W + 2} y1={CS_GOAL_BOT + 4} x2={CS_W - 8} y2={CS_GOAL_BOT + 4} stroke="#fb7185" strokeWidth="2"/>

                {goalFlash && (
                  <rect x="0" y="0" width={CS_W} height={CS_H} fill={goalFlash === 'A' ? '#5eead4' : '#fb7185'} opacity="0.18">
                    <animate attributeName="opacity" values="0.4;0;0.4;0" dur="1.2s" repeatCount="1"/>
                  </rect>
                )}

                {/* Ball */}
                <g transform={`translate(${ball.x} ${ball.y})`}>
                  <circle r={CS_BR + 2} fill="rgba(0,0,0,0.4)" opacity="0.5" cy="3"/>
                  <circle r={CS_BR} fill="#fff" stroke="#04141a" strokeWidth="1.4"/>
                  <path d={`M${-CS_BR*0.5} ${-CS_BR*0.2} L0 ${-CS_BR*0.6} L${CS_BR*0.5} ${-CS_BR*0.2} L${CS_BR*0.6} ${CS_BR*0.5} L${-CS_BR*0.6} ${CS_BR*0.5} Z`} fill="#04141a"/>
                </g>

                {/* Tokens */}
                {chars.map(c => {
                  const meta = TOKENS.find(t => t.id === c.id);
                  const isKeeper = c.role === 'keeper';
                  return (
                    <g
                      key={c.id}
                      transform={`translate(${c.x} ${c.y})`}
                      className="cs-token"
                      onMouseDown={(e) => onDown(c.id, e)}
                      onTouchStart={(e) => onDown(c.id, e)}
                      style={{ cursor: started ? 'grab' : 'default' }}
                    >
                      <circle r={CS_R + 2} fill="rgba(0,0,0,0.5)" cy="3"/>
                      <circle r={CS_R} fill={meta.c} stroke="#fff" strokeWidth="2"/>
                      {isKeeper && (
                        <circle r={CS_R + 4} fill="none" stroke="#fff" strokeOpacity="0.45" strokeWidth="1" strokeDasharray="2 3"/>
                      )}
                      <text textAnchor="middle" y="6" fill="#fff"
                        fontSize={CS_R} fontFamily="Space Grotesk" fontWeight="700"
                        style={{ pointerEvents: 'none' }}>{meta.emoji}</text>
                    </g>
                  );
                })}

                {goalFlash && (
                  <text x={CS_W/2} y={CS_H/2 + 10} textAnchor="middle"
                    fontSize="64" fontFamily="Space Grotesk" fontWeight="700"
                    fill={goalFlash === 'A' ? '#5eead4' : '#fb7185'}>GOAL!</text>
                )}

                {streakBanner && (
                  <g>
                    <rect x={CS_W/2 - 180} y={CS_H/2 - 40} width="360" height="60" rx="14"
                      fill={streakBanner.team === 'A' ? 'rgba(94,234,212,0.92)' : 'rgba(251,113,133,0.92)'}/>
                    <text x={CS_W/2} y={CS_H/2 + 2} textAnchor="middle"
                      fontSize="28" fontFamily="Space Grotesk" fontWeight="700"
                      fill="#04141a">{streakBanner.text}</text>
                  </g>
                )}

                {halftime && (
                  <g>
                    <rect x="0" y="0" width={CS_W} height={CS_H} fill="rgba(0,0,0,0.55)"/>
                    <text x={CS_W/2} y={CS_H/2 - 6} textAnchor="middle"
                      fontSize="42" fontFamily="Space Grotesk" fontWeight="700" fill="#22d3ee">
                      HALF TIME
                    </text>
                    <text x={CS_W/2} y={CS_H/2 + 28} textAnchor="middle"
                      fontSize="14" fontFamily="JetBrains Mono" letterSpacing="0.2em"
                      fill="rgba(255,255,255,0.7)">2T STARTING…</text>
                  </g>
                )}

                {userPaused && started && !winner && !halftime && (
                  <g style={{ cursor: 'pointer' }} onClick={togglePause}>
                    <rect x="0" y="0" width={CS_W} height={CS_H} fill="rgba(0,0,0,0.6)"/>
                    <circle cx={CS_W/2} cy={CS_H/2} r="48" fill="rgba(34,211,238,0.18)" stroke="#22d3ee" strokeWidth="2"/>
                    <path d={`M${CS_W/2 - 12} ${CS_H/2 - 18} L${CS_W/2 - 12} ${CS_H/2 + 18} M${CS_W/2 + 12} ${CS_H/2 - 18} L${CS_W/2 + 12} ${CS_H/2 + 18}`}
                      stroke="#22d3ee" strokeWidth="6" strokeLinecap="round"/>
                    <text x={CS_W/2} y={CS_H/2 + 80} textAnchor="middle"
                      fontSize="11" fontFamily="JetBrains Mono" letterSpacing="0.2em"
                      fill="rgba(255,255,255,0.7)">PAUSED · TAP TO RESUME</text>
                  </g>
                )}

                {/* START overlay */}
                {!started && !winner && (
                  <g
                    style={{ cursor: 'pointer' }}
                    onClick={kickOff}
                    onTouchStart={(e) => { e.preventDefault(); kickOff(); }}
                  >
                    <rect x="0" y="0" width={CS_W} height={CS_H} fill="rgba(0, 0, 0, 0.55)"/>
                    <circle cx={CS_W/2} cy={CS_H/2} r="56" fill="#22d3ee" stroke="#04141a" strokeWidth="3">
                      <animate attributeName="r" values="54;60;54" dur="1.4s" repeatCount="indefinite"/>
                    </circle>
                    <text x={CS_W/2} y={CS_H/2 + 10} textAnchor="middle"
                      fontSize="26" fontFamily="Space Grotesk" fontWeight="700" fill="#04141a"
                      style={{ pointerEvents: 'none' }}>
                      START
                    </text>
                    <text x={CS_W/2} y={CS_H/2 + 90} textAnchor="middle"
                      fontSize="13" fontFamily="JetBrains Mono" fill="rgba(255,255,255,0.6)"
                      letterSpacing="0.18em"
                      style={{ pointerEvents: 'none' }}>
                      TAP TO KICK OFF
                    </text>
                  </g>
                )}

                {/* Winner overlay con NFT trophy mint */}
                {winner && (
                  <g>
                    <rect x="0" y="0" width={CS_W} height={CS_H} fill="rgba(0, 0, 0, 0.78)"/>
                    <text x={CS_W/2} y={CS_H/2 - 50} textAnchor="middle"
                      fontSize="38" fontFamily="Space Grotesk" fontWeight="700"
                      fill={winner === 'A' ? '#5eead4' : '#fb7185'}>
                      TEAM {winner} WINS · {scoreA} – {scoreB}
                    </text>
                    {!mintedTx ? (
                      <g
                        style={{ cursor: minting ? 'wait' : 'pointer' }}
                        onClick={mintTrophy}
                        onTouchStart={(e) => { e.preventDefault(); mintTrophy(); }}
                      >
                        <rect x={CS_W/2 - 130} y={CS_H/2 - 14} width="260" height="48" rx="24"
                          fill={minting ? 'rgba(34,211,238,0.35)' : 'rgba(34,211,238,0.9)'}
                          stroke="#22d3ee" strokeWidth="2"/>
                        <text x={CS_W/2} y={CS_H/2 + 16} textAnchor="middle"
                          fontSize="15" fontFamily="Space Grotesk" fontWeight="700"
                          fill="#04141a" style={{ pointerEvents: 'none' }}>
                          {minting ? '⏳ Minting on Polygon…' : '🏆 MINT TROPHY NFT'}
                        </text>
                      </g>
                    ) : (
                      <g>
                        <rect x={CS_W/2 - 200} y={CS_H/2 - 14} width="400" height="58" rx="14"
                          fill="rgba(94,234,212,0.12)" stroke="#5eead4" strokeWidth="1.5"/>
                        <text x={CS_W/2} y={CS_H/2 + 4} textAnchor="middle"
                          fontSize="11" fontFamily="JetBrains Mono" letterSpacing="0.12em"
                          fill="#5eead4">✓ TROPHY NFT MINTED</text>
                        <text x={CS_W/2} y={CS_H/2 + 28} textAnchor="middle"
                          fontSize="10" fontFamily="JetBrains Mono"
                          fill="rgba(255,255,255,0.85)">{mintedTx.slice(0, 14)}…{mintedTx.slice(-10)}</text>
                      </g>
                    )}
                    <text x={CS_W/2} y={CS_H/2 + 70} textAnchor="middle"
                      fontSize="11" fontFamily="JetBrains Mono"
                      fill="rgba(255,255,255,0.55)" letterSpacing="0.18em">
                      TAP CLAIM TO COLLECT {CS_PRIZE} BBC
                    </text>
                  </g>
                )}
              </svg>
            </div>

            <div className="cs-bottom">
              <div className="cs-hint">{hint}</div>
              <div className="cs-controls">
                <button className="sims-btn" onClick={resetMatch}>↻ Reset</button>
                <button
                  className="sims-btn"
                  onClick={togglePause}
                  disabled={!started || !!winner}
                  title={userPaused ? 'Resume' : 'Pause'}
                >
                  {userPaused ? '▶ Play' : '⏸ Pause'}
                </button>
                <button
                  className={"sims-btn " + (winner && !claimed ? 'sims-btn-primary cs-claim-glow' : '')}
                  disabled={!winner || claimed}
                  onClick={claimPrize}
                >
                  🎁 {claimed ? 'Claimed!' : winner ? `Claim ${CS_PRIZE} BBC` : 'Claim Prize'}
                </button>
                <button className="sims-btn" onClick={() => { setShowHelp(true); sounds.click(); }}>❓ How</button>
                <a className="sims-btn cs-fs-btn" href="games/crypto-soccer.html" target="_blank" rel="noopener" title="Play full-screen">
                  ⛶ Ver en grande
                </a>
              </div>
            </div>
          </div>

          {confetti.length > 0 && (
            <div className="cs-confetti">
              {confetti.map(p => (
                <span
                  key={p.id}
                  className="cs-confetto"
                  style={{
                    left: p.x + '%',
                    background: p.color,
                    '--vx': p.vx + 'vw',
                    '--vy': p.vy + 'vh',
                    '--rot': p.rot + 'deg',
                  }}
                />
              ))}
            </div>
          )}
          {fallingCoins.length > 0 && (
            <div className="cs-fall">
              {fallingCoins.map(c => (
                <span
                  key={c.id}
                  className={"cs-fall-coin cs-fall-" + c.target}
                  style={{ left: c.startX + '%', animationDelay: c.delay + 'ms' }}
                >BBC</span>
              ))}
            </div>
          )}
        </div>
        <div className="ipad-home-indicator"/>
      </div>
    </div>
  );
};

Object.assign(window, { CryptoSoccer });
