/* Arcade SPA — boot menu, game, cheat-sheet, history, results, settings. */

const HISTORY_KEY = 'cuttle.arcade.history.v1';
const NAME_KEY = 'cuttle.arcade.lastName.v1';
const SETTINGS_KEY = 'cuttle.arcade.settings.v1';
const NAME_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_ ';
const DEFAULT_SETTINGS = { cardHints: true, aiDifficulty: 'HARD' };

function loadHistory() {
  try { return JSON.parse(localStorage.getItem(HISTORY_KEY) || '[]'); } catch { return []; }
}
function saveHistory(h) { localStorage.setItem(HISTORY_KEY, JSON.stringify(h.slice(-200))); }
function loadLastName() {
  const v = localStorage.getItem(NAME_KEY);
  return (v && v.length === 3 && [...v].every(c => NAME_CHARS.includes(c))) ? v : 'AAA';
}
function loadSettings() {
  try {
    const raw = JSON.parse(localStorage.getItem(SETTINGS_KEY) || 'null');
    return { ...DEFAULT_SETTINGS, ...(raw || {}) };
  } catch { return { ...DEFAULT_SETTINGS }; }
}
function saveSettings(s) { localStorage.setItem(SETTINGS_KEY, JSON.stringify(s)); }

// ─── MENU / ATTRACT SCREEN ───────────────────────────────────────────────────
function MenuScreen({ onNav, history }) {
  const wins = history.filter(h => h.winner === 'player').length;
  const total = history.length;
  const wr = total ? Math.round(100 * wins / total) : 0;
  const [show, setShow] = React.useState(true);
  React.useEffect(() => {
    const i = setInterval(() => setShow(s => !s), 600);
    return () => clearInterval(i);
  }, []);

  return (
    <div style={{
      width: '100%', height: '100%', position: 'relative', overflow: 'hidden',
      background: 'radial-gradient(ellipse at center, #1a2347 0%, #0a0e1a 70%)',
    }}>
      <div className="stars" />
      <div className="grid-floor" />

      {/* Wordmark */}
      <div style={{
        position: 'absolute', top: '20%', left: 0, right: 0,
        textAlign: 'center', zIndex: 3,
      }}>
        <div className="wordmark">CUTTLE</div>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 28, color: 'var(--ink)', marginTop: 8, letterSpacing: '0.3em' }}>
          ⟨ A COMBAT CARD GAME ⟩
        </div>
      </div>

      {/* Center: cuttlefish + score */}
      <div style={{
        position: 'absolute', top: '52%', left: '50%', transform: 'translate(-50%, 0)',
        display: 'flex', alignItems: 'center', gap: 60,
      }}>
        <div style={{ textAlign: 'right' }}>
          <div style={{ fontFamily: 'VT323, monospace', fontSize: 18, color: 'var(--ink-dim)', letterSpacing: '0.2em' }}>1P SCORE</div>
          <div style={{ fontFamily: 'VT323, monospace', fontSize: 64, color: 'var(--accent-3)', textShadow: '0 0 14px var(--accent-3)', lineHeight: 1 }}>
            {String(wins).padStart(6, '0')}
          </div>
          <div style={{ fontFamily: 'VT323, monospace', fontSize: 16, color: 'var(--ink-dim)', marginTop: 4, letterSpacing: '0.16em' }}>
            {total} GAMES · {wr}% WR
          </div>
        </div>
        <div style={{
          padding: 14, background: 'var(--bg-panel)',
          boxShadow: '0 0 0 3px var(--bg-deep), 0 0 0 6px var(--accent-2), 8px 8px 0 6px rgba(0,0,0,0.6), 0 0 30px rgba(0,240,200,0.3)',
        }}>
          <PixelCuttlefish mood="smug" size={160} />
        </div>
        <div style={{ textAlign: 'left' }}>
          <div style={{ fontFamily: 'VT323, monospace', fontSize: 18, color: 'var(--ink-dim)', letterSpacing: '0.2em' }}>BOSS LV</div>
          <div style={{ fontFamily: 'VT323, monospace', fontSize: 64, color: 'var(--accent)', textShadow: '0 0 14px var(--accent)', lineHeight: 1 }}>
            ★★★
          </div>
          <div style={{ fontFamily: 'VT323, monospace', fontSize: 16, color: 'var(--ink-dim)', marginTop: 4, letterSpacing: '0.16em' }}>
            CUTTLEBOT
          </div>
        </div>
      </div>

      {/* Buttons */}
      <div style={{
        position: 'absolute', bottom: '14%', left: 0, right: 0,
        display: 'flex', justifyContent: 'center', gap: 24, flexWrap: 'wrap',
      }}>
        <button className="pix-btn primary" onClick={() => onNav('GAME')}>▶ Press Start</button>
        <button className="pix-btn" onClick={() => onNav('RULES')}>How To Play</button>
        <button className="pix-btn" onClick={() => onNav('HISTORY')}>High Scores</button>
        <button className="pix-btn" onClick={() => onNav('SETTINGS')}>Settings</button>
      </div>

      {/* Credits */}
      <div style={{
        position: 'absolute', bottom: 56, left: 0, right: 0, textAlign: 'center',
        fontFamily: 'VT323, monospace', fontSize: 18, color: 'var(--ink-dim)',
        letterSpacing: '0.16em',
      }}>
        CREDITS : BY REMO DIVITO   ·   ART · DRAWSGOOD.ITCH.IO   ·   RULES · RICHARD SIPIE
      </div>

      {/* Bottom blink */}
      <div style={{
        position: 'absolute', bottom: 24, left: 0, right: 0, textAlign: 'center',
        fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--accent-2)',
        opacity: show ? 1 : 0, transition: 'opacity 60ms',
      }}>
        © 2026 CUTTLEBOT INDUSTRIES · ALL RIGHTS RESERVED · PUSH BUTTON TO BEGIN
      </div>
    </div>
  );
}

// ─── RULES / CHEAT SHEET ─────────────────────────────────────────────────────
function RulesScreen({ onBack }) {
  const Row = ({ rank, label, body, color }) => (
    <div style={{ display: 'grid', gridTemplateColumns: '70px 1fr', gap: 18, padding: '14px 0', borderBottom: '1px dashed var(--line)' }}>
      <div style={{
        width: 56, height: 76,
        background: 'var(--bg-panel-2)',
        boxShadow: `inset 0 0 0 2px ${color}, 0 0 12px ${color}66`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: 'VT323, monospace', fontSize: 38, color,
        textShadow: `0 0 8px ${color}`,
      }}>{rank}</div>
      <div>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 26, color: 'var(--ink)', letterSpacing: '0.06em' }}>
          <span style={{ color }}>▸</span> {label}
        </div>
        <div style={{ fontSize: 13, color: 'var(--ink-dim)', lineHeight: 1.6, marginTop: 4 }}>{body}</div>
      </div>
    </div>
  );
  // Strict semantic palette: cyan = utility, magenta = attack, yellow = permanent,
  // grey = inert (rank with no effect). Every chip color carries one job.
  const cyan = '#00f0c8', mag = '#ff3b8b', yel = '#ffd23f', grey = 'var(--ink-dim)';
  return (
    <div style={{ width: '100%', height: '100%', overflow: 'auto', background: 'var(--bg-deep)' }}>
      <div style={{ maxWidth: 880, margin: '0 auto', padding: '28px 32px 80px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <button className="pix-btn small" onClick={onBack}>◀ Back</button>
          <div style={{ flex: 1 }} />
        </div>
        <div className="pixel-text" style={{ fontSize: 96, color: 'var(--accent)', marginTop: 24, lineHeight: 1 }}>
          HOW 2 PLAY
        </div>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--ink-dim)', marginTop: 8 }}>
          ─── OBJECTIVE ───────────────────────────────────────
        </div>
        <div style={{ fontSize: 14, color: 'var(--ink)', lineHeight: 1.7, marginTop: 8, fontFamily: 'JetBrains Mono, monospace' }}>
          Score <b style={{color: yel}}>21 POINTS</b> on your field before Cuttlebot does. Each turn: <b>DRAW</b> or <b>PLAY</b> one card. Most cards have a special effect. You can also <b style={{color: yel}}>SCUTTLE</b> — lay a higher-rank point card onto an opponent point card to send both to the scrap pile.
        </div>

        <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--ink-dim)', marginTop: 28 }}>
          ─── POINT CARDS · A through 10 ──────────────────────
        </div>
        <div style={{ fontSize: 12, color: 'var(--ink-dim)', marginTop: 4, fontFamily: 'JetBrains Mono, monospace' }}>
          Worth face value when laid to your field. OR — used as a one-off effect (then scrapped).
        </div>

        <div style={{ marginTop: 16 }}>
          <Row rank="A" color={mag} label="ACE — WIPE" body="One-off: scrap ALL point cards from both fields." />
          <Row rank="2" color={mag} label="TWO — COUNTER / KILL" body="As a reaction: counter an opponent's one-off or Jack (your 2 and their card both go to scrap). As a one-off: scrap any permanent effect — a Queen, King, Glasses (8), or a Jack on a point card." />
          <Row rank="3" color={cyan} label="THREE — SALVAGE" body="One-off: take any one card from the scrap pile into your hand." />
          <Row rank="4" color={mag} label="FOUR — FORCE DISCARD" body="One-off: opponent must scrap 2 cards from their hand." />
          <Row rank="5" color={cyan} label="FIVE — DRAW 2" body="One-off: draw 2 cards from the deck." />
          <Row rank="6" color={mag} label="SIX — ROYALTY WIPE" body="One-off: scrap all Queens, Kings and Glasses on both fields." />
          <Row rank="7" color={cyan} label="SEVEN — FLIP" body="One-off: flip the top card of the deck and play it immediately, or scrap it." />
          <Row rank="8" color={yel} label="EIGHT — GLASSES" body="Permanent: lay on your field face-up; you see your opponent's hand." />
          <Row rank="9" color={mag} label="NINE — BOUNCE" body="One-off: return any permanent effect card (Queen, King, Glasses or Jack) — on either field — to its controller's hand." />
          <Row rank="10" color={grey} label="TEN — POINT ONLY" body="No one-off effect. Worth 10 points when played to your field, or used to scuttle a lower-rank point card." />
        </div>

        <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--ink-dim)', marginTop: 28 }}>
          ─── FACE CARDS · J Q K ──────────────────────────────
        </div>
        <Row rank="J" color={yel} label="JACK — STEAL" body="Play onto an opponent's unprotected point card. It joins your field, worth its original value." />
        <Row rank="Q" color={yel} label="QUEEN — PROTECT" body="Permanent: while a Queen is on your field, your other cards can't be targeted (Queens don't protect themselves)." />
        <Row rank="K" color={yel} label="KING — LOWER TARGET" body="Permanent: each King on your field lowers your win threshold. 0=21, 1=14, 2=10, 3=7, 4=5." />

      </div>
    </div>
  );
}

// ─── HISTORY / HIGH SCORES ───────────────────────────────────────────────────
function HistoryScreen({ onBack, history, onClear }) {
  const wins = history.filter(h => h.winner === 'player').length;
  const losses = history.length - wins;
  const wr = history.length ? Math.round(100 * wins / history.length) : 0;
  const sortedByScore = history.slice().sort((a, b) => {
    // wins first, by player score, then by fewer turns
    if ((b.winner === 'player') !== (a.winner === 'player')) return (b.winner === 'player') - (a.winner === 'player');
    if (b.playerScore !== a.playerScore) return b.playerScore - a.playerScore;
    return a.turns - b.turns;
  });
  return (
    <div style={{ width: '100%', height: '100%', overflow: 'auto', background: 'var(--bg-deep)' }}>
      <div className="stars" style={{ position: 'fixed', opacity: 0.3 }} />
      <div style={{ maxWidth: 920, margin: '0 auto', padding: '28px 32px 80px', position: 'relative' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <button className="pix-btn small" onClick={onBack}>◀ Back</button>
          <div style={{ flex: 1 }} />
        </div>
        <div className="pixel-text" style={{ fontSize: 96, color: 'var(--accent-3)', marginTop: 24, lineHeight: 1 }}>
          HIGH SCORES
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginTop: 32 }}>
          <Stat label="GAMES" value={history.length} color="var(--ink)" />
          <Stat label="WINS" value={wins} color="var(--accent-2)" />
          <Stat label="WIN RATE" value={wr + '%'} color="var(--accent-3)" />
        </div>

        <div style={{ marginTop: 36, display: 'flex', alignItems: 'center', gap: 12 }}>
          <span className="pix-tag">top runs</span>
          <div style={{ flex: 1 }} />
          {history.length > 0 && <button className="pix-btn small" onClick={onClear}>Clear</button>}
        </div>

        <div style={{ marginTop: 12 }} className="pix-panel">
          {history.length === 0 ? (
            <div style={{ padding: 22, textAlign: 'center', color: 'var(--ink-dim)', fontFamily: 'VT323, monospace', fontSize: 26 }}>
              ─── NO RECORDS YET. INSERT COIN. ───
            </div>
          ) : (
            <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 13 }}>
              <div style={{
                display: 'grid', gridTemplateColumns: '40px 80px 90px 1fr 80px 80px 80px',
                gap: 12, padding: '8px 6px', borderBottom: '1px solid var(--line-bright)',
                color: 'var(--accent-2)', letterSpacing: '0.1em', textTransform: 'uppercase', fontSize: 11,
              }}>
                <div>RNK</div><div>RESULT</div><div>DATE</div><div>NAME</div><div>YOU</div><div>BOT</div><div>TURNS</div>
              </div>
              {sortedByScore.slice(0, 20).map((g, i) => (
                <div key={i} style={{
                  display: 'grid', gridTemplateColumns: '40px 80px 90px 1fr 80px 80px 80px',
                  gap: 12, padding: '8px 6px', alignItems: 'center',
                  borderBottom: '1px dashed var(--line)',
                  color: g.winner === 'player' ? 'var(--ink)' : 'var(--ink-dim)',
                }}>
                  <div style={{ color: i < 3 ? 'var(--accent-3)' : 'var(--ink-dim)', fontFamily: 'VT323, monospace', fontSize: 22 }}>
                    {String(i + 1).padStart(2, '0')}
                  </div>
                  <div style={{ color: g.winner === 'player' ? 'var(--accent-2)' : 'var(--accent)', fontWeight: 700 }}>
                    {g.winner === 'player' ? 'WIN' : 'LOSS'}
                  </div>
                  <div style={{ color: 'var(--ink-dim)' }}>{formatDate(g.endedAt)}</div>
                  <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, letterSpacing: '0.1em' }}>
                    {g.winner === 'player' ? (g.name || 'PLAYER1') : 'CUTTLEBOT'}
                  </div>
                  <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--accent-2)' }}>{String(g.playerScore).padStart(2, '0')}</div>
                  <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--accent)' }}>{String(g.aiScore).padStart(2, '0')}</div>
                  <div style={{ fontFamily: 'VT323, monospace', fontSize: 22 }}>{g.turns}</div>
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

function Stat({ label, value, color }) {
  return (
    <div className="pix-panel" style={{ padding: 18 }}>
      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, letterSpacing: '0.18em', color: 'var(--ink-dim)' }}>{label}</div>
      <div style={{ fontFamily: 'VT323, monospace', fontSize: 64, color, textShadow: `0 0 14px ${color}`, lineHeight: 1, marginTop: 4 }}>
        {value}
      </div>
    </div>
  );
}

function formatDate(ts) {
  const d = new Date(ts);
  const now = new Date();
  const sameDay = d.toDateString() === now.toDateString();
  if (sameDay) return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: false });
  return (d.getMonth()+1) + '/' + d.getDate();
}

// ─── SETTINGS ────────────────────────────────────────────────────────────────
function SettingsScreen({ onBack, settings, onChange }) {
  return (
    <div style={{ width: '100%', height: '100%', overflow: 'auto', background: 'var(--bg-deep)' }}>
      <div className="stars" style={{ position: 'fixed', opacity: 0.3 }} />
      <div style={{ maxWidth: 720, margin: '0 auto', padding: '28px 32px 80px', position: 'relative' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <button className="pix-btn small" onClick={onBack}>◀ Back</button>
          <div style={{ flex: 1 }} />
        </div>
        <div className="pixel-text" style={{ fontSize: 96, color: 'var(--accent-2)', marginTop: 24, lineHeight: 1 }}>
          SETTINGS
        </div>
        <div style={{ marginTop: 28 }} className="pix-panel">
          <SettingRow
            label="CARD HINTS"
            desc="Show a short description when you hover a card in your hand or a permanent on the field."
            value={settings.cardHints}
            onChange={(v) => onChange({ ...settings, cardHints: v })}
          />
          <ChoiceRow
            label="DIFFICULTY"
            desc="EASY: original AI (uniform-rollout MCTS). HARD: heuristic Cuttle-aware MCTS with late-game tactical solver."
            value={settings.aiDifficulty ?? 'HARD'}
            options={['EASY', 'HARD']}
            onChange={(v) => onChange({ ...settings, aiDifficulty: v })}
          />
        </div>
      </div>
    </div>
  );
}

function SettingRow({ label, desc, value, onChange }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 18, padding: '20px 22px', alignItems: 'center', borderBottom: '1px dashed var(--line)' }}>
      <div>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 26, color: 'var(--ink)', letterSpacing: '0.08em' }}>
          <span style={{ color: 'var(--accent-2)' }}>▸</span> {label}
        </div>
        <div style={{ fontSize: 13, color: 'var(--ink-dim)', lineHeight: 1.6, marginTop: 4 }}>{desc}</div>
      </div>
      <button
        onClick={() => onChange(!value)}
        className="pix-btn small"
        style={{ minWidth: 84 }}
      >
        {value ? 'ON' : 'OFF'}
      </button>
    </div>
  );
}

function ChoiceRow({ label, desc, value, options, onChange }) {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: 18, padding: '20px 22px', alignItems: 'center', borderBottom: '1px dashed var(--line)' }}>
      <div>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 26, color: 'var(--ink)', letterSpacing: '0.08em' }}>
          <span style={{ color: 'var(--accent-2)' }}>▸</span> {label}
        </div>
        <div style={{ fontSize: 13, color: 'var(--ink-dim)', lineHeight: 1.6, marginTop: 4 }}>{desc}</div>
      </div>
      <div style={{ display: 'flex', gap: 6 }}>
        {options.map((opt) => (
          <button
            key={opt}
            onClick={() => onChange(opt)}
            className="pix-btn small"
            style={{
              minWidth: 84,
              opacity: opt === value ? 1.0 : 0.45,
              borderColor: opt === value ? 'var(--accent-2)' : undefined,
            }}
          >
            {opt}
          </button>
        ))}
      </div>
    </div>
  );
}

// ─── RESULTS ─────────────────────────────────────────────────────────────────
function ResultsScreen({ result, onRematch, onMenu }) {
  const win = result?.winner === 'player';
  const color = win ? 'var(--accent-2)' : 'var(--accent)';
  // Pick once per result so the face doesn't flip between renders.
  const endMood = React.useMemo(() => pickAIMood(
    { winner: win ? 'player' : 'ai', turn: (result?.playerScore ?? 0) * 31 + (result?.aiScore ?? 0) },
  ), [win, result?.playerScore, result?.aiScore]);
  return (
    <div style={{
      width: '100%', height: '100%', position: 'relative', overflow: 'hidden',
      background: 'radial-gradient(ellipse at center, #1a2347 0%, #0a0e1a 80%)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <div className="stars" />
      <div style={{ textAlign: 'center', position: 'relative', zIndex: 2 }}>
        <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 24 }}>
          <PixelCuttlefish mood={endMood} size={160} />
        </div>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, letterSpacing: '0.4em', color: 'var(--ink-dim)' }}>
          {win ? '── ROUND CLEAR ──' : '── GAME OVER ──'}
        </div>
        <div className="pixel-text" style={{ fontSize: 168, color, lineHeight: 1, marginTop: 12 }}>
          {win ? 'YOU WIN' : 'YOU LOSE'}
        </div>
        <div style={{ display: 'flex', gap: 40, justifyContent: 'center', marginTop: 36 }}>
          <ResultStat label="P1" value={result?.playerScore ?? 0} color="var(--accent-2)" />
          <ResultStat label="CPU" value={result?.aiScore ?? 0} color="var(--accent)" />
          <ResultStat label="TURNS" value={result?.turns ?? 0} color="var(--accent-3)" />
        </div>
        <div style={{ display: 'flex', gap: 18, justifyContent: 'center', marginTop: 44 }}>
          <button className="pix-btn primary" onClick={onRematch}>▶ Continue</button>
          <button className="pix-btn" onClick={onMenu}>Menu</button>
        </div>
      </div>
    </div>
  );
}
function ResultStat({ label, value, color }) {
  return (
    <div>
      <div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 11, letterSpacing: '0.18em', color: 'var(--ink-dim)' }}>{label}</div>
      <div style={{ fontFamily: 'VT323, monospace', fontSize: 84, color, textShadow: `0 0 16px ${color}`, lineHeight: 1, marginTop: 4 }}>
        {String(value).padStart(2, '0')}
      </div>
    </div>
  );
}

// ─── NAME ENTRY ──────────────────────────────────────────────────────────────
function NameEntryScreen({ result, onSubmit }) {
  const [initials, setInitials] = React.useState(() => loadLastName().split(''));
  const [pos, setPos] = React.useState(0);
  const [submitted, setSubmitted] = React.useState(false);
  const [blink, setBlink] = React.useState(true);

  React.useEffect(() => {
    const i = setInterval(() => setBlink(b => !b), 350);
    return () => clearInterval(i);
  }, []);

  function setCharAt(i, ch) {
    setInitials(prev => { const a = [...prev]; a[i] = ch; return a; });
  }
  function cycleChar(delta) {
    const cur = initials[pos];
    const idx = NAME_CHARS.indexOf(cur);
    const j = ((idx < 0 ? 0 : idx) + delta + NAME_CHARS.length) % NAME_CHARS.length;
    setCharAt(pos, NAME_CHARS[j]);
  }
  function movePos(delta) { setPos(p => Math.max(0, Math.min(2, p + delta))); }
  function submit() {
    if (submitted) return;
    setSubmitted(true);
    const name = initials.join('');
    localStorage.setItem(NAME_KEY, name);
    onSubmit(name);
  }

  React.useEffect(() => {
    const onKey = (e) => {
      if (submitted) return;
      if (e.key === 'ArrowUp') { e.preventDefault(); cycleChar(1); }
      else if (e.key === 'ArrowDown') { e.preventDefault(); cycleChar(-1); }
      else if (e.key === 'ArrowLeft') { e.preventDefault(); movePos(-1); }
      else if (e.key === 'ArrowRight') { e.preventDefault(); movePos(1); }
      else if (e.key === 'Enter') {
        e.preventDefault();
        if (pos < 2) movePos(1); else submit();
      }
      else if (e.key === 'Backspace') {
        e.preventDefault();
        setCharAt(pos, ' ');
        if (pos > 0) movePos(-1);
      }
      else if (e.key && e.key.length === 1) {
        const ch = e.key.toUpperCase();
        if (NAME_CHARS.includes(ch)) {
          e.preventDefault();
          setCharAt(pos, ch);
          if (pos < 2) setPos(p => p + 1);
        }
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [pos, initials, submitted]);

  return (
    <div style={{
      width: '100%', height: '100%', position: 'relative', overflow: 'hidden',
      background: 'radial-gradient(ellipse at center, #1a2347 0%, #0a0e1a 80%)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }}>
      <div className="stars" />
      <div style={{ textAlign: 'center', position: 'relative', zIndex: 2, padding: 24 }}>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, letterSpacing: '0.4em', color: 'var(--ink-dim)' }}>
          ── NEW HIGH SCORE ──
        </div>
        <div className="pixel-text" style={{ fontSize: 96, color: 'var(--accent-2)', lineHeight: 1, marginTop: 8 }}>
          ENTER YOUR NAME
        </div>
        <div style={{ fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--ink-dim)', marginTop: 12, letterSpacing: '0.18em' }}>
          {String(result?.playerScore ?? 0).padStart(2, '0')} PTS · {result?.turns ?? 0} TURNS
        </div>

        <div style={{ display: 'flex', gap: 24, justifyContent: 'center', marginTop: 44 }}>
          {initials.map((ch, i) => {
            const active = i === pos;
            return (
              <div key={i} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8 }}>
                <div style={{
                  fontFamily: 'VT323, monospace', fontSize: 36, lineHeight: 1,
                  color: active ? 'var(--accent-2)' : 'transparent',
                  textShadow: active ? '0 0 14px var(--accent-2)' : 'none',
                  opacity: active ? (blink ? 1 : 0.3) : 0,
                  transition: 'opacity 80ms',
                }}>▲</div>
                <div onClick={() => setPos(i)} style={{
                  width: 96, height: 128, cursor: 'pointer',
                  background: 'var(--bg-panel)',
                  boxShadow: active
                    ? '0 0 0 3px var(--bg-deep), 0 0 0 6px var(--accent-2), 0 0 36px rgba(255,210,63,0.55)'
                    : '0 0 0 3px var(--bg-deep), 0 0 0 6px var(--ink-dim), 6px 6px 0 6px rgba(0,0,0,0.5)',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontFamily: 'VT323, monospace', fontSize: 96,
                  color: active ? 'var(--accent-2)' : 'var(--ink)',
                  textShadow: active ? '0 0 14px var(--accent-2)' : 'none',
                  lineHeight: 1, transition: 'box-shadow 120ms, color 120ms',
                  userSelect: 'none',
                }}>
                  {ch === ' ' ? '_' : ch}
                </div>
                <div style={{
                  fontFamily: 'VT323, monospace', fontSize: 36, lineHeight: 1,
                  color: active ? 'var(--accent-2)' : 'transparent',
                  textShadow: active ? '0 0 14px var(--accent-2)' : 'none',
                  opacity: active ? (blink ? 1 : 0.3) : 0,
                  transition: 'opacity 80ms',
                }}>▼</div>
              </div>
            );
          })}
        </div>

        <div style={{ display: 'flex', gap: 12, justifyContent: 'center', marginTop: 36, flexWrap: 'wrap' }}>
          <button className="pix-btn small" onClick={() => movePos(-1)}>◀</button>
          <button className="pix-btn small" onClick={() => cycleChar(-1)}>▼</button>
          <button className="pix-btn small" onClick={() => cycleChar(1)}>▲</button>
          <button className="pix-btn small" onClick={() => movePos(1)}>▶</button>
          <button className="pix-btn primary" onClick={submit}>✓ Enter</button>
        </div>

        <div style={{ fontFamily: 'VT323, monospace', fontSize: 18, color: 'var(--ink-dim)', marginTop: 28, letterSpacing: '0.16em' }}>
          ◆ ARROWS TO CHOOSE · TYPE TO SET · ENTER TO CONFIRM ◆
        </div>
      </div>
    </div>
  );
}

// ─── GAME WRAPPER (CRT cabinet chrome around the table) ──────────────────────
function GameScreen({ seed, settings, onSettingsChange, onGameOver, onMenu }) {
  const [showRules, setShowRules] = React.useState(false);
  // Push the AI difficulty into the (singleton) wasm engine adapter whenever
  // settings change. The adapter holds a process-global default that all
  // aiChooseAction calls fall back to when no per-call override is supplied.
  React.useEffect(() => {
    const d = settings?.aiDifficulty ?? 'HARD';
    window.CuttleEngine?.setDifficulty?.(d);
  }, [settings?.aiDifficulty]);
  return (
    <div style={{ width: '100%', height: '100%', position: 'relative', background: 'var(--bg-deep)' }}>
      {/* Top arcade HUD bar */}
      <div style={{
        position: 'absolute', top: 0, left: 0, right: 0, height: 56,
        background: 'var(--bg-panel)', borderBottom: '2px solid var(--accent)',
        display: 'flex', alignItems: 'center', padding: '0 22px', gap: 10,
        fontFamily: 'VT323, monospace', fontSize: 22, color: 'var(--ink)',
        zIndex: 40,
      }}>
        <span style={{ color: 'var(--accent-2)' }}>▸</span>
        <span style={{ marginLeft: 8, letterSpacing: '0.16em' }}>STAGE 01 · CUTTLEBOT</span>
        <div style={{ flex: 1 }} />
        <button className="pix-btn small" onClick={() => setShowSettings(true)}>⚙ Setup</button>
        <button className="pix-btn small" onClick={() => setShowRules(true)}>? Rules</button>
        <button className="pix-btn small" onClick={onMenu}>◀ Quit</button>
      </div>

      <div style={{ position: 'absolute', top: 56, left: 0, right: 0, bottom: 0 }}>
        <CuttleTable
          theme="arcade"
          layout="stacked"
          cardStyle="realistic"
          showHints
          cardHints={settings?.cardHints !== false}
          animSpeed={1}
          seed={seed}
          onGameOver={onGameOver}
        />
      </div>

      {showRules && (
        <div style={{
          position: 'absolute', inset: 0, zIndex: 60,
          background: 'rgba(0,0,0,0.78)',
        }}>
          <RulesScreen onBack={() => setShowRules(false)} />
        </div>
      )}

      {showSettings && (
        <div style={{
          position: 'absolute', inset: 0, zIndex: 60,
          background: 'rgba(0,0,0,0.78)',
        }}>
          <SettingsScreen onBack={() => setShowSettings(false)} settings={settings} onChange={onSettingsChange} />
        </div>
      )}
    </div>
  );
}

// ─── App ─────────────────────────────────────────────────────────────────────
function App() {
  const [screen, setScreen] = React.useState('MENU');
  const [history, setHistory] = React.useState(loadHistory);
  const [settings, setSettings] = React.useState(loadSettings);
  const [result, setResult] = React.useState(null);
  // ?seed=N in the URL forces a deterministic starting deck — useful for tests
  // and bug repro. Honoured for both the initial mount and subsequent rematches.
  const urlSeed = (() => {
    try {
      const v = new URL(location.href).searchParams.get('seed');
      const n = v == null ? null : Number(v);
      return Number.isFinite(n) ? n : null;
    } catch { return null; }
  })();
  const [seed, setSeed] = React.useState(() => urlSeed ?? Math.floor(Math.random() * 1e9));

  function nav(s) { setScreen(s); }
  function startGame() {
    setSeed(urlSeed ?? Math.floor(Math.random() * 1e9));
    setResult(null); setScreen('GAME');
  }
  function onGameOver(r) {
    setResult(r);
    if (r.winner === 'player') {
      setTimeout(() => setScreen('NAME_ENTRY'), 1300);
    } else {
      const next = [...history, r];
      setHistory(next); saveHistory(next);
      setTimeout(() => setScreen('RESULTS'), 1300);
    }
  }
  function submitName(name) {
    const entry = { ...result, name };
    const next = [...history, entry];
    setHistory(next); saveHistory(next);
    setResult(entry);
    setScreen('RESULTS');
  }

  return (
    <div style={{ width: '100vw', height: '100vh', position: 'relative' }}>
      <div className="pix-fade-in" key={screen} style={{ width: '100%', height: '100%' }}>
        {screen === 'MENU' && <MenuScreen onNav={(s) => s === 'GAME' ? startGame() : nav(s)} history={history} />}
        {screen === 'GAME' && <GameScreen seed={seed} settings={settings} onSettingsChange={(s) => { setSettings(s); saveSettings(s); }} onGameOver={onGameOver} onMenu={() => nav('MENU')} />}
        {screen === 'RULES' && <RulesScreen onBack={() => nav('MENU')} />}
        {screen === 'HISTORY' && <HistoryScreen onBack={() => nav('MENU')} history={history} onClear={() => { setHistory([]); saveHistory([]); }} />}
        {screen === 'SETTINGS' && <SettingsScreen onBack={() => nav('MENU')} settings={settings} onChange={(s) => { setSettings(s); saveSettings(s); }} />}
        {screen === 'NAME_ENTRY' && <NameEntryScreen result={result} onSubmit={submitName} />}
        {screen === 'RESULTS' && <ResultsScreen result={result} onRematch={startGame} onMenu={() => nav('MENU')} />}
      </div>
    </div>
  );
}

function mount() {
  ReactDOM.createRoot(document.getElementById('root')).render(<App />);
}
if (window.CuttleEngine) mount();
else window.addEventListener('cuttle-ready', mount, { once: true });
