// grid-games.jsx — mines, towers, keno, plinko

// ═════════════════════════════════════════════════════════════
// MINES — 5×5 grid, reveal safe cells, avoid mines
// ═════════════════════════════════════════════════════════════
const MINES_GRID_SIZE = 25;

// Multiplier after k safe reveals with M mines, 1% edge.
// Formula: 0.99 / P(k consecutive safe), where
// P = product over i=0..k-1 of (N-M-i)/(N-i)
function minesMultiplier(safeCount, mineCount) {
  if (safeCount === 0) return 1.00;
  const N = MINES_GRID_SIZE;
  const M = mineCount;
  let p = 1;
  for (let i = 0; i < safeCount; i++) {
    p *= (N - M - i) / (N - i);
  }
  if (p <= 0) return 1.00;
  return 0.99 / p;
}

function Mines({ onBack, onHistory, onRules, onTip }) {
  const { balance, settle } = useStore();
  const [bet, setBet] = React.useState(50);
  const [mineCount, setMineCount] = React.useState(3);
  const [phase, setPhase] = React.useState('bet'); // bet | playing | done
  const [grid, setGrid] = React.useState(() =>
    Array.from({ length: MINES_GRID_SIZE }, () => ({ revealed: false, mine: false }))
  );
  const [safeRevealed, setSafeRevealed] = React.useState(0);
  const [busted, setBusted] = React.useState(false);
  const [result, setResult] = React.useState(null);

  const multiplier = minesMultiplier(safeRevealed, mineCount);
  const nextMultiplier = minesMultiplier(safeRevealed + 1, mineCount);

  const start = () => {
    if (!bet || bet > balance || mineCount < 1 || mineCount > 24) return;
    // Place mines
    const positions = Array.from({ length: MINES_GRID_SIZE }, (_, i) => i);
    for (let i = positions.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [positions[i], positions[j]] = [positions[j], positions[i]];
    }
    const mineSet = new Set(positions.slice(0, mineCount));
    const newGrid = Array.from({ length: MINES_GRID_SIZE }, (_, i) => ({
      revealed: false,
      mine: mineSet.has(i),
    }));
    setGrid(newGrid);
    setSafeRevealed(0);
    setBusted(false);
    setResult(null);
    setPhase('playing');
  };

  const reveal = (idx) => {
    if (phase !== 'playing') return;
    const cell = grid[idx];
    if (cell.revealed) return;
    const newGrid = grid.map((c, i) => i === idx ? { ...c, revealed: true } : c);
    if (cell.mine) {
      // BUST — reveal all mines
      const finalGrid = newGrid.map((c) => c.mine ? { ...c, revealed: true } : c);
      setGrid(finalGrid);
      setBusted(true);
      try { if (typeof sounds !== 'undefined') sounds.crash(); } catch (e) {}
      const delta = -bet;
      settle('Mines', delta, `bust on ${safeRevealed} safe`);
      setResult({ delta, label: `bust at ${multiplier.toFixed(2)}×` });
      setPhase('done');
    } else {
      setGrid(newGrid);
      setSafeRevealed((s) => s + 1);
      try { if (typeof sounds !== 'undefined') sounds.reveal(); } catch (e) {}
    }
  };

  const cashOut = () => {
    if (phase !== 'playing' || safeRevealed === 0) return;
    const delta = Math.floor(bet * multiplier - bet);
    settle('Mines', delta, `cash · ${multiplier.toFixed(2)}× · ${safeRevealed} safe`);
    setResult({ delta, label: `${multiplier.toFixed(2)}× · ${safeRevealed} safe` });
    // Reveal all for visibility
    setGrid((g) => g.map((c) => ({ ...c, revealed: true })));
    setPhase('done');
  };

  const newRound = () => {
    setPhase('bet');
    setGrid(Array.from({ length: MINES_GRID_SIZE }, () => ({ revealed: false, mine: false })));
    setSafeRevealed(0);
    setBusted(false);
    setResult(null);
  };

  const renderCell = (cell, i) => {
    const isPlayable = phase === 'playing' && !cell.revealed;
    let content = null;
    let cellStyle = {};
    if (cell.revealed) {
      if (cell.mine) {
        // mine
        content = <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
          <path d="M3 3L11 11M3 11L11 3" stroke="#b85450" strokeWidth="1.4" strokeLinecap="round" />
        </svg>;
        cellStyle = { borderColor: 'rgba(184, 84, 80, 0.4)', background: 'rgba(184, 84, 80, 0.04)' };
      } else {
        // safe — diamond dot
        content = <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
          <circle cx="5" cy="5" r="2" fill="var(--text)" />
        </svg>;
        cellStyle = { borderColor: 'var(--line-2)', background: 'rgba(255,255,255,0.02)' };
      }
    }
    return (
      <button
        key={i}
        className={isPlayable ? 'press' : ''}
        onClick={() => reveal(i)}
        disabled={!isPlayable}
        style={{
          border: '1px solid var(--line-2)',
          background: 'rgba(255,255,255,0.015)',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          cursor: isPlayable ? 'pointer' : 'default',
          transition: 'border-color 200ms, background 200ms',
          padding: 0,
          ...cellStyle,
        }}
      >
        {content}
      </button>
    );
  };

  return (
    <>
      <TopBar onBack={onBack} title="MINES" balance={balance} onRules={onRules} onTip={onTip} />
      <div className="stage">
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '20px 24px', gap: 16 }}>
          {/* Multiplier header */}
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
            <div>
              <div className="eyebrow">{phase === 'bet' ? 'Stake' : 'Multiplier'}</div>
              <div className="mono" style={{
                fontSize: 28, color: 'var(--text)', fontVariantNumeric: 'tabular-nums',
                letterSpacing: '0.02em', fontWeight: 300, lineHeight: 1.1, marginTop: 4,
              }}>
                {phase === 'bet' ? (bet ? bet.toLocaleString('en-US') : '—') : `${multiplier.toFixed(2)}×`}
              </div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div className="eyebrow">{phase === 'bet' ? 'Mines' : 'Safe'}</div>
              <div className="mono" style={{
                fontSize: 28, color: 'var(--text-2)', fontVariantNumeric: 'tabular-nums',
                letterSpacing: '0.02em', fontWeight: 300, lineHeight: 1.1, marginTop: 4,
              }}>
                {phase === 'bet' ? mineCount : `${safeRevealed} / ${MINES_GRID_SIZE - mineCount}`}
              </div>
            </div>
          </div>

          {/* Grid */}
          <div style={{
            display: 'grid',
            gridTemplateColumns: 'repeat(5, 60px)',
            gridAutoRows: '60px',
            gap: 6,
            justifyContent: 'center',
            margin: '8px 0',
          }}>
            {grid.map((c, i) => renderCell(c, i))}
          </div>

          <div style={{ minHeight: 22, textAlign: 'center' }}>
            {result ? <ResultLine result={{ delta: result.delta, label: result.label }} />
              : phase === 'playing' && safeRevealed > 0
                ? <div className="eyebrow">next · {nextMultiplier.toFixed(2)}×</div>
              : phase === 'playing'
                ? <div className="eyebrow">Reveal a cell</div>
              : <div className="eyebrow">Set mines and stake</div>}
          </div>
        </div>

        {phase === 'bet' && (
          <>
            <div style={{ padding: '0 24px 14px' }}>
              <div className="eyebrow" style={{ marginBottom: 10 }}>Mines</div>
              <div style={{ display: 'flex', gap: 6, justifyContent: 'space-between' }}>
                {[1, 3, 5, 10, 24].map((m) => (
                  <button key={m}
                    className={'chip press' + (mineCount === m ? ' active' : '')}
                    onClick={() => setMineCount(m)}>{m}</button>
                ))}
              </div>
            </div>
            <div style={{ padding: '0 0 16px' }}>
              <div className="eyebrow" style={{ padding: '0 24px 12px' }}>Stake</div>
              <BetSelector value={bet} onChange={setBet} />
            </div>
            <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
              <button className="btn" onClick={start} disabled={bet > balance}
                style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>Start</button>
            </div>
          </>
        )}

        {phase === 'playing' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn primary" onClick={cashOut} disabled={safeRevealed === 0}
              style={{ width: '100%', height: 56, letterSpacing: '0.3em', opacity: safeRevealed === 0 ? 0.35 : 1 }}>
              {safeRevealed === 0 ? 'Reveal a cell to start' : `Cash ${Math.floor(bet * multiplier).toLocaleString('en-US')}`}
            </button>
          </div>
        )}

        {phase === 'done' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn primary" onClick={newRound}
              style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>New Round</button>
          </div>
        )}
      </div>
    </>
  );
}

// ═════════════════════════════════════════════════════════════
// TOWERS — climb 8 rows, avoid traps each row
// ═════════════════════════════════════════════════════════════
const TOWERS_ROWS = 8;
const TOWERS_COLS = 4;

const TOWERS_DIFFICULTY = {
  easy:   { traps: 1, label: 'Easy' },
  medium: { traps: 2, label: 'Medium' },
  hard:   { traps: 3, label: 'Hard' },
};

function towersMultiplier(level, traps) {
  if (level === 0) return 1.00;
  const safe = TOWERS_COLS - traps;
  const p = Math.pow(safe / TOWERS_COLS, level);
  if (p <= 0) return 1.00;
  return 0.99 / p;
}

function Towers({ onBack, onHistory, onRules, onTip }) {
  const { balance, settle } = useStore();
  const [bet, setBet] = React.useState(50);
  const [diff, setDiff] = React.useState('medium');
  const [phase, setPhase] = React.useState('bet'); // bet | playing | done
  const [layout, setLayout] = React.useState([]); // array of row arrays of {trap: bool}
  const [picks, setPicks] = React.useState([]);   // index per row picked
  const [level, setLevel] = React.useState(0);
  const [busted, setBusted] = React.useState(false);
  const [result, setResult] = React.useState(null);

  const traps = TOWERS_DIFFICULTY[diff].traps;
  const multiplier = towersMultiplier(level, traps);
  const nextMultiplier = towersMultiplier(level + 1, traps);

  const start = () => {
    if (!bet || bet > balance) return;
    const newLayout = Array.from({ length: TOWERS_ROWS }, () => {
      const positions = Array.from({ length: TOWERS_COLS }, (_, i) => i);
      for (let i = positions.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [positions[i], positions[j]] = [positions[j], positions[i]];
      }
      const trapSet = new Set(positions.slice(0, traps));
      return Array.from({ length: TOWERS_COLS }, (_, i) => ({ trap: trapSet.has(i) }));
    });
    setLayout(newLayout);
    setPicks([]);
    setLevel(0);
    setBusted(false);
    setResult(null);
    setPhase('playing');
  };

  const choose = (col) => {
    if (phase !== 'playing') return;
    const cell = layout[level][col];
    const newPicks = [...picks, col];
    setPicks(newPicks);
    if (cell.trap) {
      setBusted(true);
      try { if (typeof sounds !== 'undefined') sounds.crash(); } catch (e) {}
      const delta = -bet;
      settle('Towers', delta, `bust on row ${level + 1}`);
      setResult({ delta, label: `bust at ${multiplier.toFixed(2)}×` });
      setPhase('done');
    } else {
      try { if (typeof sounds !== 'undefined') sounds.reveal(); } catch (e) {}
      const next = level + 1;
      setLevel(next);
      if (next >= TOWERS_ROWS) {
        // Cleared all rows
        const finalMult = towersMultiplier(TOWERS_ROWS, traps);
        const delta = Math.floor(bet * finalMult - bet);
        settle('Towers', delta, `cleared · ${finalMult.toFixed(2)}×`);
        setResult({ delta, label: `cleared · ${finalMult.toFixed(2)}×` });
        setPhase('done');
      }
    }
  };

  const cashOut = () => {
    if (phase !== 'playing' || level === 0) return;
    const delta = Math.floor(bet * multiplier - bet);
    settle('Towers', delta, `cash · ${multiplier.toFixed(2)}× · row ${level}`);
    setResult({ delta, label: `${multiplier.toFixed(2)}× · row ${level}` });
    setPhase('done');
  };

  const newRound = () => {
    setPhase('bet'); setLayout([]); setPicks([]); setLevel(0);
    setBusted(false); setResult(null);
  };

  const renderCell = (rowIdx, colIdx) => {
    const row = layout[rowIdx];
    const isCurrentRow = phase === 'playing' && rowIdx === level;
    const isPastRow = phase !== 'bet' && rowIdx < level;
    const isFutureRow = phase === 'playing' && rowIdx > level;
    const isPicked = picks[rowIdx] === colIdx;
    const isDone = phase === 'done';

    let content = null;
    let style = {
      borderColor: 'var(--line-2)',
      background: 'rgba(255,255,255,0.015)',
    };

    if (!row) {
      // bet phase
      style.borderColor = 'var(--line-2)';
    } else if (isPastRow) {
      // already passed, show pick
      if (isPicked) {
        content = <svg width="10" height="10" viewBox="0 0 10 10"><circle cx="5" cy="5" r="2" fill="var(--text)" /></svg>;
        style.borderColor = 'var(--line-2)';
        style.background = 'rgba(255,255,255,0.02)';
      }
    } else if (isCurrentRow) {
      // active: hover effect via CSS .press
      style.borderColor = 'var(--line-2)';
    } else if (isFutureRow) {
      style.opacity = 0.35;
    } else if (isDone) {
      // reveal traps in current and remaining rows
      if (rowIdx === level && isPicked && row[colIdx].trap) {
        content = <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
          <path d="M3 3L11 11M3 11L11 3" stroke="#b85450" strokeWidth="1.4" strokeLinecap="round" />
        </svg>;
        style.borderColor = 'rgba(184, 84, 80, 0.4)';
        style.background = 'rgba(184, 84, 80, 0.04)';
      } else if (rowIdx === level && row[colIdx].trap) {
        // show other traps on the busted row
        content = <svg width="10" height="10" viewBox="0 0 10 10"><circle cx="5" cy="5" r="1.4" fill="#b85450" /></svg>;
        style.borderColor = 'rgba(184, 84, 80, 0.2)';
      }
    }

    return (
      <button
        key={colIdx}
        className={isCurrentRow ? 'press' : ''}
        onClick={() => isCurrentRow && choose(colIdx)}
        disabled={!isCurrentRow}
        style={{
          width: '100%', height: 36,
          border: '1px solid',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          cursor: isCurrentRow ? 'pointer' : 'default',
          transition: 'all 200ms',
          ...style,
        }}
      >
        {content}
      </button>
    );
  };

  // Visual rows: top of stack = last row to reach (TOWERS_ROWS - 1)
  // Bottom of stack = first row (0)
  const visualRows = Array.from({ length: TOWERS_ROWS }, (_, i) => TOWERS_ROWS - 1 - i);

  return (
    <>
      <TopBar onBack={onBack} title="TOWERS" balance={balance} onRules={onRules} onTip={onTip} />
      <div className="stage">
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '14px 24px', gap: 10 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
            <div>
              <div className="eyebrow">{phase === 'bet' ? 'Stake' : 'Multiplier'}</div>
              <div className="mono" style={{
                fontSize: 24, color: 'var(--text)', fontVariantNumeric: 'tabular-nums',
                letterSpacing: '0.02em', fontWeight: 300, lineHeight: 1.1, marginTop: 4,
              }}>
                {phase === 'bet' ? (bet ? bet.toLocaleString('en-US') : '—') : `${multiplier.toFixed(2)}×`}
              </div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div className="eyebrow">{phase === 'bet' ? 'Difficulty' : 'Row'}</div>
              <div className="mono" style={{
                fontSize: 24, color: 'var(--text-2)', fontVariantNumeric: 'tabular-nums',
                letterSpacing: '0.02em', fontWeight: 300, lineHeight: 1.1, marginTop: 4,
              }}>
                {phase === 'bet' ? TOWERS_DIFFICULTY[diff].label : `${level} / ${TOWERS_ROWS}`}
              </div>
            </div>
          </div>

          {/* Stack of rows */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, padding: '8px 0' }}>
            {visualRows.map((rowIdx) => (
              <div key={rowIdx} style={{
                display: 'grid', gridTemplateColumns: `repeat(${TOWERS_COLS}, 1fr)`, gap: 4,
              }}>
                {Array.from({ length: TOWERS_COLS }, (_, colIdx) => renderCell(rowIdx, colIdx))}
              </div>
            ))}
          </div>

          <div style={{ minHeight: 22, textAlign: 'center' }}>
            {result ? <ResultLine result={{ delta: result.delta, label: result.label }} />
              : phase === 'playing' && level > 0
                ? <div className="eyebrow">next · {nextMultiplier.toFixed(2)}×</div>
              : phase === 'playing'
                ? <div className="eyebrow">Climb the tower</div>
              : <div className="eyebrow">Set difficulty and stake</div>}
          </div>
        </div>

        {phase === 'bet' && (
          <>
            <div style={{ padding: '0 24px 14px' }}>
              <div className="eyebrow" style={{ marginBottom: 10 }}>Difficulty</div>
              <div style={{ display: 'flex', gap: 6 }}>
                {Object.entries(TOWERS_DIFFICULTY).map(([k, v]) => (
                  <button key={k}
                    className={'chip press' + (diff === k ? ' active' : '')}
                    onClick={() => setDiff(k)}
                    style={{ flex: 1 }}>{v.label}</button>
                ))}
              </div>
            </div>
            <div style={{ padding: '0 0 16px' }}>
              <div className="eyebrow" style={{ padding: '0 24px 12px' }}>Stake</div>
              <BetSelector value={bet} onChange={setBet} />
            </div>
            <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
              <button className="btn" onClick={start} disabled={bet > balance}
                style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>Start</button>
            </div>
          </>
        )}

        {phase === 'playing' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn primary" onClick={cashOut} disabled={level === 0}
              style={{ width: '100%', height: 56, letterSpacing: '0.3em', opacity: level === 0 ? 0.35 : 1 }}>
              {level === 0 ? 'Pick a cell to start' : `Cash ${Math.floor(bet * multiplier).toLocaleString('en-US')}`}
            </button>
          </div>
        )}

        {phase === 'done' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn primary" onClick={newRound}
              style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>New Round</button>
          </div>
        )}
      </div>
    </>
  );
}

// ═════════════════════════════════════════════════════════════
// PLINKO — ball drops through pegs into multiplier slot
// ═════════════════════════════════════════════════════════════
const PLINKO_ROWS = 9;
const PLINKO_SLOTS = 10;
// Multipliers calibrated so 50% of rounds yield > stake (edge ~3%)
// Slot probabilities (binomial 9 rows): 0.2 / 1.76 / 7 / 16.4 / 24.6 % each side
const PLINKO_MULTS = [12, 3, 1.5, 1.1, 0.5, 0.5, 1.1, 1.5, 3, 12];

function Plinko({ onBack, onHistory, onRules, onTip }) {
  const { balance, settle } = useStore();
  const [bet, setBet] = React.useState(50);
  const [phase, setPhase] = React.useState('bet'); // bet | dropping | done
  const [ballPos, setBallPos] = React.useState({ row: -1, col: 0 });
  const [path, setPath] = React.useState([]);
  const [finalSlot, setFinalSlot] = React.useState(null);
  const [result, setResult] = React.useState(null);
  const stepTimer = React.useRef(0);

  React.useEffect(() => () => clearInterval(stepTimer.current), []);

  const start = () => {
    if (!bet || bet > balance) return;
    setPhase('dropping');
    setResult(null);
    setFinalSlot(null);
    // Build path: start at center, each row pick left or right
    const newPath = [{ row: -1, col: PLINKO_ROWS / 2 }]; // start above row 0
    let pos = PLINKO_ROWS / 2;
    for (let r = 0; r < PLINKO_ROWS; r++) {
      pos = pos + (Math.random() < 0.5 ? -0.5 : 0.5);
      newPath.push({ row: r, col: pos });
    }
    // Final slot
    const slot = Math.round(pos);
    setPath(newPath);
    setBallPos(newPath[0]);

    let i = 0;
    stepTimer.current = setInterval(() => {
      i++;
      if (i < newPath.length) {
        setBallPos(newPath[i]);
        try { if (typeof sounds !== 'undefined') sounds.pegHit(); } catch (e) {}
      } else {
        clearInterval(stepTimer.current);
        setFinalSlot(slot);
        const mult = PLINKO_MULTS[slot] ?? 0;
        const delta = Math.floor(bet * mult - bet);
        settle('Plinko', delta, `slot ${slot} · ${mult}×`);
        setResult({ delta, label: `${mult}×` });
        setPhase('done');
      }
    }, 180);
  };

  const newRound = () => {
    setPhase('bet'); setBallPos({ row: -1, col: 0 }); setPath([]);
    setFinalSlot(null); setResult(null);
  };

  // SVG dimensions
  const W = 300;
  const H = 300;
  const SPACING_X = 26;
  const SPACING_Y = (H - 60) / PLINKO_ROWS;
  const CENTER_X = W / 2;

  const pegX = (row, col) => CENTER_X + (col - row / 2) * SPACING_X;
  const pegY = (row) => 30 + row * SPACING_Y;

  const ballSvgX = ballPos.row < 0
    ? CENTER_X
    : CENTER_X + (ballPos.col - PLINKO_ROWS / 2) * SPACING_X;
  const ballSvgY = ballPos.row < 0
    ? 10
    : pegY(ballPos.row) + SPACING_Y / 2;

  const slotWidth = W / PLINKO_SLOTS;

  return (
    <>
      <TopBar onBack={onBack} title="PLINKO" balance={balance} onRules={onRules} onTip={onTip} />
      <div className="stage">
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', padding: '8px 0 0', gap: 4 }}>
          <svg viewBox={`0 0 ${W} ${H + 32}`} width="300" height={H + 32}>
            {/* Pegs */}
            {Array.from({ length: PLINKO_ROWS }, (_, r) =>
              Array.from({ length: r + 1 }, (_, c) => (
                <circle key={`${r}-${c}`} cx={pegX(r, c)} cy={pegY(r)} r="1.6" fill="var(--text-3)" />
              ))
            )}
            {/* Ball */}
            <circle
              cx={ballSvgX}
              cy={ballSvgY}
              r="5"
              fill="var(--accent)"
              style={{ transition: phase === 'dropping' ? 'cx 180ms ease-in, cy 180ms ease-in' : 'none' }}
            />
            {/* Slots */}
            {PLINKO_MULTS.map((m, i) => (
              <g key={i}>
                <rect
                  x={i * slotWidth}
                  y={H - 10}
                  width={slotWidth - 1}
                  height={36}
                  fill="none"
                  stroke={finalSlot === i ? 'var(--accent)' : 'var(--line)'}
                  strokeWidth="1"
                />
                <text
                  x={i * slotWidth + slotWidth / 2}
                  y={H + 12}
                  fill={finalSlot === i ? 'var(--accent)' : 'var(--text-3)'}
                  fontSize="9"
                  fontFamily="var(--font-mono)"
                  textAnchor="middle"
                  letterSpacing="0.04em"
                >
                  {m}×
                </text>
              </g>
            ))}
          </svg>

          <div style={{ minHeight: 22, textAlign: 'center', marginTop: 8 }}>
            {result ? <ResultLine result={{ delta: result.delta, label: result.label }} />
              : phase === 'dropping' ? <div className="eyebrow" style={{ color: 'var(--text-3)' }}>·</div>
              : <div className="eyebrow">Drop the ball</div>}
          </div>
        </div>

        {phase === 'bet' && (
          <>
            <div style={{ padding: '0 0 16px' }}>
              <div className="eyebrow" style={{ padding: '0 24px 12px' }}>Stake</div>
              <BetSelector value={bet} onChange={setBet} />
            </div>
            <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
              <button className="btn" onClick={start} disabled={bet > balance}
                style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>Drop</button>
            </div>
          </>
        )}

        {phase === 'dropping' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn" disabled style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>· · ·</button>
          </div>
        )}

        {phase === 'done' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn primary" onClick={newRound}
              style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>New Round</button>
          </div>
        )}
      </div>
    </>
  );
}

// ═════════════════════════════════════════════════════════════
// KENO — pick 5 of 80, draw 20, count hits
// ═════════════════════════════════════════════════════════════
const KENO_PICKS = 6;
const KENO_DRAW = 20;
const KENO_TOTAL = 80;
// payouts for 6 picks: 0..6 hits → multiplier (~10% house edge)
const KENO_PAYS = [0, 0, 0, 2, 8, 70, 1500];

function Keno({ onBack, onHistory, onRules, onTip }) {
  const { balance, settle } = useStore();
  const [bet, setBet] = React.useState(null);
  const [picks, setPicks] = React.useState(new Set());
  const [phase, setPhase] = React.useState('bet'); // bet | drawing | done
  const [drawn, setDrawn] = React.useState(new Set());
  const [drawOrder, setDrawOrder] = React.useState([]);
  const [lastDrawn, setLastDrawn] = React.useState(null);
  const [result, setResult] = React.useState(null);
  const drawTimer = React.useRef(0);

  React.useEffect(() => () => clearInterval(drawTimer.current), []);

  const togglePick = (n) => {
    if (phase !== 'bet') return;
    const next = new Set(picks);
    if (next.has(n)) next.delete(n);
    else if (next.size < KENO_PICKS) next.add(n);
    setPicks(next);
  };

  const quickPick = () => {
    if (phase !== 'bet') return;
    const next = new Set();
    while (next.size < KENO_PICKS) {
      next.add(1 + Math.floor(Math.random() * KENO_TOTAL));
    }
    setPicks(next);
  };

  const start = () => {
    if (!bet || bet > balance || picks.size !== KENO_PICKS) return;
    // generate the draw
    const all = Array.from({ length: KENO_TOTAL }, (_, i) => i + 1);
    for (let i = all.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [all[i], all[j]] = [all[j], all[i]];
    }
    const drawn20 = all.slice(0, KENO_DRAW);
    setDrawOrder(drawn20);
    setDrawn(new Set());
    setLastDrawn(null);
    setPhase('drawing');
    setResult(null);

    let i = 0;
    drawTimer.current = setInterval(() => {
      const drawnNum = drawn20[i];
      setDrawn((prev) => new Set([...prev, drawnNum]));
      setLastDrawn(drawnNum);
      // Only chime on hits — silence on misses keeps it tense
      if (picks.has(drawnNum)) {
        try { if (typeof sounds !== 'undefined') sounds.numberDraw(); } catch (e) {}
      }
      i++;
      if (i >= drawn20.length) {
        clearInterval(drawTimer.current);
        // Calculate hits
        const hits = drawn20.filter((n) => picks.has(n)).length;
        const mult = KENO_PAYS[hits] || 0;
        const delta = mult > 0 ? Math.floor(bet * mult - bet) : -bet;
        settle('Keno', delta, `${hits}/${KENO_PICKS} · ${mult}×`);
        setResult({ delta, label: `${hits} hits · ${mult}×` });
        setPhase('done');
      }
    }, 180);
  };

  const newRound = () => {
    // Keep picks AND bet so user can re-Draw quickly with same numbers
    setPhase('bet');
    setDrawn(new Set());
    setDrawOrder([]);
    setLastDrawn(null);
    setResult(null);
  };

  const renderNumber = (n) => {
    const isPicked = picks.has(n);
    const isDrawn = drawn.has(n);
    const isHit = isPicked && isDrawn;
    const isLast = n === lastDrawn;

    let bg = 'transparent';
    let border = 'var(--line-2)';
    let color = 'var(--text-3)';
    let scale = 1;
    if (phase === 'bet') {
      if (isPicked) {
        border = 'var(--accent)';
        color = 'var(--accent)';
        bg = 'rgba(255,255,255,0.04)';
      }
    } else {
      if (isHit) {
        bg = 'rgba(255,255,255,0.10)';
        border = 'var(--accent)';
        color = 'var(--accent)';
      } else if (isPicked) {
        border = 'var(--line-2)';
        color = 'var(--text-2)';
      } else if (isDrawn) {
        bg = 'rgba(255,255,255,0.03)';
        border = 'rgba(255,255,255,0.20)';
        color = 'var(--text-3)';
      }
      // emphasis on the most recently drawn number
      if (isLast) {
        bg = isPicked ? 'rgba(255,255,255,0.18)' : 'rgba(255,255,255,0.08)';
        border = 'var(--text)';
        scale = 1.08;
      }
    }

    return (
      <button
        key={n}
        className={phase === 'bet' ? 'press' : ''}
        onClick={() => togglePick(n)}
        disabled={phase !== 'bet'}
        style={{
          aspectRatio: '1',
          border: '1px solid ' + border,
          background: bg,
          color: color,
          fontSize: 11,
          fontFamily: 'var(--font-mono)',
          letterSpacing: '0.02em',
          fontVariantNumeric: 'tabular-nums',
          cursor: phase === 'bet' ? 'pointer' : 'default',
          transition: 'all 180ms ease',
          transform: `scale(${scale})`,
          zIndex: isLast ? 1 : 0,
        }}
      >
        {n}
      </button>
    );
  };

  return (
    <>
      <TopBar onBack={onBack} title="KENO" balance={balance} onRules={onRules} onTip={onTip} />
      <div className="stage">
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', padding: '14px 20px', gap: 10, overflowY: 'auto' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', minHeight: 32 }}>
            <div className="eyebrow">{phase === 'bet' ? `Pick · ${picks.size} / ${KENO_PICKS}` : `Drawn · ${drawn.size} / ${KENO_DRAW}`}</div>
            {phase === 'bet' ? (
              <button className="press" onClick={quickPick}
                style={{
                  fontSize: 10, color: 'var(--text-3)', letterSpacing: '0.18em',
                  textTransform: 'uppercase', background: 'transparent', border: 0, cursor: 'pointer',
                }}>quick pick</button>
            ) : lastDrawn !== null ? (
              <div style={{
                fontFamily: 'var(--font-serif)', fontStyle: 'italic',
                fontSize: 26, lineHeight: 1,
                fontVariantNumeric: 'tabular-nums',
                color: picks.has(lastDrawn) ? 'var(--accent)' : 'var(--text)',
                transition: 'color 200ms',
              }}>
                {lastDrawn}
              </div>
            ) : null}
          </div>

          {/* 8x10 grid (1-80) */}
          <div style={{
            display: 'grid', gridTemplateColumns: 'repeat(8, 1fr)', gap: 3,
          }}>
            {Array.from({ length: KENO_TOTAL }, (_, i) => renderNumber(i + 1))}
          </div>

          {/* Pay table */}
          <div style={{
            display: 'flex', justifyContent: 'space-around', padding: '12px 0',
            borderTop: '1px solid var(--line)', borderBottom: '1px solid var(--line)',
            fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text-3)',
            letterSpacing: '0.04em',
          }}>
            {KENO_PAYS.slice(3).map((p, i) => (
              <div key={i} style={{ textAlign: 'center' }}>
                <div>{i + 3} hits</div>
                <div style={{ color: 'var(--text)', marginTop: 2 }}>{p}×</div>
              </div>
            ))}
          </div>

          <div style={{ minHeight: 22, textAlign: 'center' }}>
            {result ? <ResultLine result={{ delta: result.delta, label: result.label }} />
              : phase === 'drawing' ? <div className="eyebrow" style={{ color: 'var(--text-3)' }}>·</div>
              : phase === 'bet' && picks.size === KENO_PICKS
                ? <div className="eyebrow">Ready to draw</div>
              : <div className="eyebrow">Pick {KENO_PICKS} numbers</div>}
          </div>
        </div>

        {phase === 'bet' && (
          <>
            <div style={{ padding: '0 0 16px' }}>
              <div className="eyebrow" style={{ padding: '0 24px 12px' }}>Stake</div>
              <BetSelector value={bet} onChange={setBet} />
            </div>
            <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
              <button className="btn" onClick={start} disabled={bet > balance || picks.size !== KENO_PICKS}
                style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>Draw</button>
            </div>
          </>
        )}

        {phase === 'drawing' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn" disabled style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>· · ·</button>
          </div>
        )}

        {phase === 'done' && (
          <div style={{ padding: '8px 24px 24px', borderTop: '1px solid var(--line)' }}>
            <button className="btn primary" onClick={newRound}
              style={{ width: '100%', height: 56, letterSpacing: '0.3em' }}>New Round</button>
          </div>
        )}
      </div>
    </>
  );
}

Object.assign(window, { Mines, Towers, Plinko, Keno });
