// app.jsx — jeperweed SPA
// One shell. URL drives state. CSV drives content.
//
// Routes:
//   /                                  welcome
//   /history                           history (past issues)
//   /{slug}                            quiz root (no tiles cleared)
//   /{slug}/q/{tile}                   question from root
//   /{slug}/c/{cleared}                board mid-game (cleared = "200" or "200-400")
//   /{slug}/c/{cleared}/q/{tile}       question from mid-game
//   /{slug}/done                       win
//   /{slug}/over/{tile}                fail (tile they missed, for the reveal)
//
// Robots: indexable on welcome, history, quiz root. Everything else noindex.

const { useState, useEffect, useMemo } = React;

const AGE_KEY = 'jeperweed:age';
const AGE_TTL_DAYS = 30;
const ISSUE_BASE = 83;     // first row in CSV is Issue No. 83
const TODAY_OVERRIDE = null; // set 'YYYY-MM-DD' to test schedule_date filtering

// ─── CSV ────────────────────────────────────────────────────────────────────
function parseCSV(text) {
  const rows = [];
  let row = [], field = '', q = false;
  for (let i = 0; i < text.length; i++) {
    const c = text[i], n = text[i + 1];
    if (q) {
      if (c === '"' && n === '"') { field += '"'; i++; }
      else if (c === '"') q = false;
      else field += c;
    } else if (c === '"') {
      q = true;
    } else if (c === ',') {
      row.push(field); field = '';
    } else if (c === '\n' || c === '\r') {
      if (c === '\r' && n === '\n') i++;
      row.push(field); field = '';
      if (row.some(x => x !== '')) rows.push(row);
      row = [];
    } else {
      field += c;
    }
  }
  if (field !== '' || row.length) {
    row.push(field);
    if (row.some(x => x !== '')) rows.push(row);
  }
  return rows;
}

function csvToObjects(text) {
  const rows = parseCSV(text);
  if (!rows.length) return [];
  const h = rows[0].map(s => s.trim());
  return rows.slice(1).map(r => {
    const o = {};
    h.forEach((k, i) => { o[k] = (r[i] ?? '').trim(); });
    return o;
  });
}

function groupQuizzes(rows) {
  // Group by schedule_date — rows that share a launch date are one quiz.
  // The slug is taken from the first row of that group (assumed consistent across the 3 rows).
  const m = new Map();
  for (const r of rows) {
    const key = r.schedule_date;
    if (!key) continue;
    if (!m.has(key)) {
      m.set(key, {
        slug: r.slug,
        ds: r.ds,
        scheduleDate: r.schedule_date,
        tiles: []
      });
    }
    m.get(key).tiles.push({
      points: parseInt(r.points, 10),
      category: r.category,
      question: r.question,
      choices: [r.a, r.b, r.c],
      correct: 'ABC'.indexOf((r.answer || '').toUpperCase().trim())
    });
  }
  const list = [...m.values()].map(q => ({
    ...q,
    tiles: q.tiles.sort((a, b) => a.points - b.points)
  }));
  list.sort((a, b) => a.scheduleDate.localeCompare(b.scheduleDate));
  list.forEach((q, i) => { q.issueNo = ISSUE_BASE + i; });
  return list;
}

// ─── Routing ────────────────────────────────────────────────────────────────
function parseRoute(pathname) {
  const p = pathname.replace(/\/+$/, '').split('/').filter(Boolean);
  if (p.length === 0) return { name: 'welcome' };
  if (p[0] === 'history' && p.length === 1) return { name: 'history' };

  const slug = p[0];
  if (!/^\d+$/.test(slug)) return { name: '404' };

  if (p.length === 1) return { name: 'board', slug, cleared: [] };

  if (p.length === 2 && p[1] === 'done') return { name: 'win', slug };
  if (p.length === 3 && p[1] === 'over') return { name: 'over', slug, tile: +p[2] };

  if (p.length === 3 && p[1] === 'q') {
    return { name: 'question', slug, cleared: [], tile: +p[2] };
  }
  if (p.length === 3 && p[1] === 'c') {
    return { name: 'board', slug, cleared: parseCleared(p[2]) };
  }
  if (p.length === 5 && p[1] === 'c' && p[3] === 'q') {
    return { name: 'question', slug, cleared: parseCleared(p[2]), tile: +p[4] };
  }
  return { name: '404' };
}

function parseCleared(s) {
  return s.split('-').map(Number).filter(n => !isNaN(n)).sort((a, b) => a - b);
}

function buildUrl(r) {
  if (r.name === 'welcome') return '/';
  if (r.name === 'history') return '/history';
  const cleared = (r.cleared || []).slice().sort((a, b) => a - b);
  const cPath = cleared.length ? `/c/${cleared.join('-')}` : '';
  if (r.name === 'board') return `/${r.slug}${cPath}`;
  if (r.name === 'question') return `/${r.slug}${cPath}/q/${r.tile}`;
  if (r.name === 'win') return `/${r.slug}/done`;
  if (r.name === 'over') return `/${r.slug}/over/${r.tile}`;
  return '/';
}

// ─── Theme ──────────────────────────────────────────────────────────────────
function hexA(hex, a) {
  const h = hex.replace('#', '');
  return `rgba(${parseInt(h.slice(0, 2), 16)},${parseInt(h.slice(2, 4), 16)},${parseInt(h.slice(4, 6), 16)},${a})`;
}
function shade(hex, pct) {
  const h = hex.replace('#', '');
  const r = parseInt(h.slice(0, 2), 16),
        g = parseInt(h.slice(2, 4), 16),
        b = parseInt(h.slice(4, 6), 16);
  const f = c => Math.max(0, Math.min(255, Math.round(c + (pct / 100) * 255)));
  const t = n => n.toString(16).padStart(2, '0');
  return `#${t(f(r))}${t(f(g))}${t(f(b))}`;
}
function applyTheme() {
  const board = '#0e1d3a', paper = '#f4ecdc', gold = '#c79a3c';
  const r = document.documentElement;
  r.style.setProperty('--board', board);
  r.style.setProperty('--board-2', shade(board, -8));
  r.style.setProperty('--paper', paper);
  r.style.setProperty('--ink', '#1a1614');
  r.style.setProperty('--gold', gold);
  r.style.setProperty('--gold-soft', hexA(gold, 0.18));
  r.style.setProperty('--paper-60', hexA(paper, 0.6));
  r.style.setProperty('--ink-60', 'rgba(26,22,20,0.6)');
  r.style.setProperty('--ink-30', 'rgba(26,22,20,0.3)');
  r.style.setProperty('--ink-15', 'rgba(26,22,20,0.15)');
  r.style.setProperty('--ink-08', 'rgba(26,22,20,0.08)');
}

// ─── Robots / canonical per route ───────────────────────────────────────────
function setRobots(route) {
  const indexable =
    route.name === 'welcome' ||
    route.name === 'history' ||
    (route.name === 'board' && (!route.cleared || route.cleared.length === 0));
  let tag = document.querySelector('meta[name="robots"]');
  if (!tag) {
    tag = document.createElement('meta');
    tag.name = 'robots';
    document.head.appendChild(tag);
  }
  tag.content = indexable ? 'index,follow' : 'noindex,follow';
}

// ─── Age gate persistence ───────────────────────────────────────────────────
function readGate() {
  try {
    const raw = localStorage.getItem(AGE_KEY);
    if (!raw) return false;
    const { ts } = JSON.parse(raw);
    return Date.now() - ts < AGE_TTL_DAYS * 86400 * 1000;
  } catch (_) { return false; }
}
function writeGate() {
  try { localStorage.setItem(AGE_KEY, JSON.stringify({ ts: Date.now() })); } catch (_) {}
}

// ─── Helpers ────────────────────────────────────────────────────────────────
function todayISO() {
  if (TODAY_OVERRIDE) return TODAY_OVERRIDE;
  return new Date().toISOString().slice(0, 10);
}
function formatDate(iso) {
  const [y, m, d] = iso.split('-').map(Number);
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
  return `${months[m - 1]} ${d}, ${y}`;
}

// ─── Root ───────────────────────────────────────────────────────────────────
function App() {
  applyTheme();

  const [route, setRoute] = useState(() => parseRoute(location.pathname));
  const [quizzes, setQuizzes] = useState(null);
  const [err, setErr] = useState(null);
  // Age gate currently disabled. Flip GATE_ACTIVE to true to re-enable.
  const GATE_ACTIVE = false;
  const [gated, setGated] = useState(() => GATE_ACTIVE ? readGate() : true);

  useEffect(() => {
    fetch('/quizzes.csv', { cache: 'no-cache' })
      .then(r => { if (!r.ok) throw new Error('Could not load quizzes.csv'); return r.text(); })
      .then(t => setQuizzes(groupQuizzes(csvToObjects(t))))
      .catch(e => setErr(e.message));
  }, []);

  useEffect(() => {
    const onPop = () => setRoute(parseRoute(location.pathname));
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  useEffect(() => { setRobots(route); window.scrollTo(0, 0); }, [route]);

  const navigate = (r, replace = false) => {
    const url = buildUrl(r);
    if (replace) history.replaceState(null, '', url);
    else history.pushState(null, '', url);
    setRoute(r);
  };

  const passGate = () => { writeGate(); setGated(true); };

  if (err) return <Frame><ErrorBody msg={err} /></Frame>;
  if (!quizzes) return <Frame><Splash /></Frame>;

  // Schedule filter disabled — every quiz in the CSV is visible.
  const live = quizzes;

  if (!gated && route.name !== 'welcome') {
    return <Frame><AgeGate onPass={passGate} /></Frame>;
  }

  let body;
  if (route.name === 'welcome') {
    body = <Welcome live={live} navigate={navigate} gated={gated} onPass={passGate} />;
  } else if (route.name === 'history') {
    body = <History live={live} navigate={navigate} />;
  } else if (route.name === '404') {
    body = <NotFound navigate={navigate} />;
  } else {
    const quiz = live.find(q => q.slug === route.slug);
    if (!quiz) body = <NotFound navigate={navigate} />;
    else if (route.name === 'board') body = <Board quiz={quiz} cleared={route.cleared} navigate={navigate} />;
    else if (route.name === 'question') body = <Question quiz={quiz} cleared={route.cleared} tile={route.tile} navigate={navigate} />;
    else if (route.name === 'win') body = <Win quiz={quiz} navigate={navigate} />;
    else if (route.name === 'over') body = <Over quiz={quiz} tile={route.tile} navigate={navigate} />;
    else body = <NotFound navigate={navigate} />;
  }

  return <Frame>{body}</Frame>;
}

function Frame({ children }) {
  return (
    <div className="stage device-mobile">
      <div className="device">
        <div className="device-screen">{children}</div>
      </div>
    </div>
  );
}

// ─── Site header (HudHaus brand + nav) ──────────────────────────────────────
function SiteHeader({ withNav, navigate }) {
  const goHome = (e) => { e.preventDefault(); navigate({ name: 'welcome' }); };
  return (
    <div className="site-header">
      <a className="site-brand" href="/" onClick={goHome}>
        HudHa<span className="site-brand-u">ü</span>s
      </a>
      {withNav && (
        <nav className="site-nav">
          <a className="site-nav-link" href="https://visit.hudhaus.net">Visit</a>
          <a className="site-nav-link is-current" href="/" onClick={goHome}>Quiz</a>
          <a className="site-nav-link" href="https://blog.hudhaus.net">Blog</a>
        </nav>
      )}
    </div>
  );
}

function Splash() {
  return (
    <div className="screen" style={{ display: 'grid', placeItems: 'center' }}>
      <div className="wordmark"><span className="wordmark-set">jeperweed</span></div>
    </div>
  );
}

function ErrorBody({ msg }) {
  return (
    <div className="screen" style={{ display: 'grid', placeItems: 'center', textAlign: 'center' }}>
      <div>
        <p style={{ color: 'var(--gold)', fontStyle: 'italic' }}>Something didn't load.</p>
        <p style={{ fontSize: 13, color: 'var(--ink-60)' }}>{msg}</p>
      </div>
    </div>
  );
}

function NotFound({ navigate }) {
  return (
    <section className="screen over" data-screen-label="404">
      <div className="over-mark">×</div>
      <h2 className="over-title">Not here.</h2>
      <p className="over-copy">That issue is either retired or hasn't dropped yet.</p>
      <button className="btn-primary" onClick={() => navigate({ name: 'welcome' })}>Back to current</button>
    </section>
  );
}

// ─── Welcome ────────────────────────────────────────────────────────────────
function Welcome({ live, navigate, gated, onPass }) {
  const latest = live[live.length - 1];
  const start = () => {
    if (!gated) onPass();
    navigate({ name: 'board', slug: latest.slug, cleared: [] });
  };
  return (
    <section className="screen welcome" data-screen-label="00 Welcome">
      <SiteHeader withNav navigate={navigate} />
      <div className="welcome-body">
      <div className="welcome-inner">
        <div className="wordmark welcome-mark"><span className="wordmark-set">jeperweed</span></div>
        <div className="gate-divider" />
        <p className="welcome-tag">
          A weekly cannabis trivia from <em>HudHaus</em>. Three tiles. One wrong ends it. New issues Tuesdays and Fridays.
        </p>
        {latest ? (
          <>
            <div className="welcome-issue">
              <span className="welcome-issue-no">No. {latest.issueNo}</span>
              <span className="welcome-issue-date">{formatDate(latest.scheduleDate)}</span>
            </div>
            <button className="btn-primary" onClick={start}>Play this issue</button>
          </>
        ) : (
          <p className="welcome-tag" style={{ color: 'var(--ink-60)' }}>No issue is live yet. Check back Tuesday.</p>
        )}
        <button className="welcome-history" onClick={() => navigate({ name: 'history' })}>Past issues →</button>
      </div>
      </div>
    </section>
  );
}

// ─── History ────────────────────────────────────────────────────────────────
function History({ live, navigate }) {
  const items = [...live].reverse();
  return (
    <section className="screen history" data-screen-label="00b History">
      <SiteHeader navigate={navigate} />
      <header className="masthead">
        <div className="masthead-l">
          <button className="node-back" onClick={() => navigate({ name: 'welcome' })} aria-label="Back">←</button>
        </div>
        <div className="masthead-r">
          <div className="masthead-issue">Past issues</div>
          <div className="masthead-date">{items.length} published</div>
        </div>
      </header>
      {items.length === 0 ? (
        <p className="welcome-tag" style={{ color: 'var(--ink-60)' }}>Nothing yet. Tuesday will be the first.</p>
      ) : (
        <ul className="history-list">
          {items.map(q => (
            <li key={q.slug} className="history-item">
              <button onClick={() => navigate({ name: 'board', slug: q.slug, cleared: [] })}>
                <span className="history-no">No. {q.issueNo}</span>
                <span className="history-date">{formatDate(q.scheduleDate)}</span>
                <span className="history-cats">{q.tiles.map(t => t.category).join(' · ')}</span>
              </button>
            </li>
          ))}
        </ul>
      )}
    </section>
  );
}

// ─── Age Gate ───────────────────────────────────────────────────────────────
function AgeGate({ onPass }) {
  const [m, setM] = useState('');
  const [d, setD] = useState('');
  const [y, setY] = useState('');
  const [err, setErr] = useState('');

  const submit = (e) => {
    e?.preventDefault();
    const yy = +y, mm = +m, dd = +d;
    if (!yy || !mm || !dd) return setErr('Enter your date of birth.');
    const dob = new Date(yy, mm - 1, dd);
    const age = (Date.now() - dob) / (1000 * 60 * 60 * 24 * 365.25);
    if (age >= 21) onPass(); else setErr('You must be 21 or older.');
  };

  return (
    <section className="screen gate" data-screen-label="01 Age Gate">
      <div className="gate-inner">
        <div className="wordmark"><span className="wordmark-set">jeperweed</span></div>
        <div className="gate-divider" />
        <p className="gate-copy">
          The state would like to know you are <em>at least</em> twenty-one before we let you in.
        </p>
        <form className="gate-form" onSubmit={submit}>
          <div className="gate-dob">
            <input inputMode="numeric" maxLength="2" placeholder="MM"
                   value={m} onChange={e => { setM(e.target.value.replace(/\D/g, '')); setErr(''); }} />
            <span className="gate-slash">/</span>
            <input inputMode="numeric" maxLength="2" placeholder="DD"
                   value={d} onChange={e => { setD(e.target.value.replace(/\D/g, '')); setErr(''); }} />
            <span className="gate-slash">/</span>
            <input inputMode="numeric" maxLength="4" placeholder="YYYY"
                   value={y} onChange={e => { setY(e.target.value.replace(/\D/g, '')); setErr(''); }} />
          </div>
          {err && <div className="gate-err">{err}</div>}
          <button className="btn-primary" type="submit">Enter</button>
        </form>
        <p className="gate-fine">We remember you on this device for thirty days.</p>
      </div>
    </section>
  );
}

// ─── Board ──────────────────────────────────────────────────────────────────
function Board({ quiz, cleared, navigate }) {
  const remaining = quiz.tiles.filter(t => !cleared.includes(t.points));
  const isRoot = cleared.length === 0;
  return (
    <section className="screen board" data-screen-label="02 Board">
      <SiteHeader navigate={navigate} />
      <header className="masthead">
        <div className="masthead-l">
          {isRoot
            ? <div className="wordmark wordmark-sm"><span className="wordmark-set">jeperweed</span></div>
            : <button className="node-back" onClick={() => navigate({ name: 'welcome' })} aria-label="Home">←</button>}
        </div>
        <div className="masthead-r">
          <div className="masthead-issue">No. {quiz.issueNo}</div>
          <div className="masthead-date">{formatDate(quiz.scheduleDate)}</div>
        </div>
      </header>

      <div className="board-prompt">
        <span className="board-prompt-eyebrow">{isRoot ? 'This issue' : 'Continue'}</span>
        <h1 className="board-prompt-title">
          {isRoot
            ? <>Pick a tile.<br/><em>Three to clear.</em></>
            : <><em>{remaining.length}</em> {remaining.length === 1 ? 'tile' : 'tiles'} to go.</>}
        </h1>
      </div>

      <div className="cells">
        {quiz.tiles.map(tile => {
          const solved = cleared.includes(tile.points);
          return (
            <button
              key={tile.points}
              className={`cell ${solved ? 'is-solved' : ''}`}
              disabled={solved}
              onClick={solved ? undefined : () => navigate({ name: 'question', slug: quiz.slug, cleared, tile: tile.points })}
            >
              <div className="cell-head"><span className="cell-head-text">{tile.category}</span></div>
              <div className="cell-body">
                {solved
                  ? <span className="cell-mark">✓</span>
                  : <><span className="cell-currency">$</span><span className="cell-value">{tile.points}</span></>}
              </div>
            </button>
          );
        })}
      </div>

      <footer className="board-foot">
        <span className="board-foot-l">{remaining.length > 0 ? `${remaining.length} to go` : 'cleared'}</span>
        <span className="board-foot-r">/{quiz.slug}</span>
      </footer>
    </section>
  );
}

// ─── Question ───────────────────────────────────────────────────────────────
function Question({ quiz, cleared, tile, navigate }) {
  const t = quiz.tiles.find(x => x.points === tile);
  const [picked, setPicked] = useState(null);
  const [revealed, setRevealed] = useState(false);

  if (!t) return <NotFound navigate={navigate} />;

  const click = (i) => {
    if (revealed) return;
    setPicked(i);
    setRevealed(true);
    setTimeout(() => {
      if (i === t.correct) {
        const next = [...cleared, tile].sort((a, b) => a - b);
        if (next.length === quiz.tiles.length) navigate({ name: 'win', slug: quiz.slug });
        else navigate({ name: 'board', slug: quiz.slug, cleared: next });
      } else {
        navigate({ name: 'over', slug: quiz.slug, tile });
      }
    }, 1100);
  };

  return (
    <section className="screen node" data-screen-label="03 Question">
      <SiteHeader navigate={navigate} />
      <header className="node-mast">
        <button className="node-back" onClick={() => navigate({ name: 'board', slug: quiz.slug, cleared })} aria-label="Back">←</button>
        <div className="node-cat">{t.category}</div>
        <div className="node-val">${t.points}</div>
      </header>

      <div className="node-card">
        <p className="node-q">{t.question}</p>
      </div>

      <div className="node-choices">
        {t.choices.map((c, i) => {
          const state = !revealed ? '' :
            i === t.correct ? 'is-correct' :
            i === picked ? 'is-wrong' : 'is-faded';
          return (
            <button key={i} className={`choice ${state}`} onClick={() => click(i)} disabled={revealed}>
              <span className="choice-letter">{String.fromCharCode(65 + i)}</span>
              <span className="choice-text">{c}</span>
            </button>
          );
        })}
      </div>
    </section>
  );
}

// ─── Win ────────────────────────────────────────────────────────────────────
function Win({ quiz, navigate }) {
  const [email, setEmail] = useState('');
  const [subbed, setSubbed] = useState(false);
  const [verifyMode, setVerifyMode] = useState(false);
  const [verified, setVerified] = useState(false);
  const [m, setM] = useState('');
  const [d, setD] = useState('');
  const [y, setY] = useState('');
  const [vErr, setVErr] = useState('');

  const verify = (e) => {
    e?.preventDefault();
    const yy = +y, mm = +m, dd = +d;
    if (!yy || !mm || !dd) return setVErr('Fill in your date of birth.');
    const dob = new Date(yy, mm - 1, dd);
    const age = (Date.now() - dob) / (1000 * 60 * 60 * 24 * 365.25);
    if (age >= 21) { setVerified(true); setVerifyMode(false); }
    else setVErr('You must be 21 or older to claim.');
  };

  const code = `HH-${quiz.slug.slice(0, 4)}-${quiz.slug.slice(-4).toUpperCase()}`;

  return (
    <section className="screen win" data-screen-label="04 Win">
      <SiteHeader navigate={navigate} />
      <div className="win-celebrate">
        <div className="win-confetti" aria-hidden="true">
          <span>★</span><span>✦</span><span>✺</span><span>✧</span><span>✱</span>
        </div>
        <div className="win-medal">
          <svg viewBox="0 0 100 100" width="100%" height="100%">
            <circle cx="50" cy="50" r="46" fill="none" stroke="currentColor" strokeWidth="0.6" />
            <circle cx="50" cy="50" r="34" fill="none" stroke="currentColor" strokeWidth="0.4" />
            <text x="50" y="58" textAnchor="middle" fontSize="22"
                  fontFamily="'Old Standard TT', serif" fontStyle="italic" fill="currentColor">finis</text>
          </svg>
        </div>
        <div className="win-lines">
          <div className="win-line-0">You took it.</div>
          <div className="win-line-1">No. {quiz.issueNo}, in the bag.</div>
          <div className="win-line-2">A clean run earns a prize code.</div>
        </div>
      </div>

      <div className="win-prize">
        {!verified && !verifyMode && (
          <button className="btn-primary win-claim" onClick={() => setVerifyMode(true)}>
            Verify your age to collect your prize code
          </button>
        )}
        {verifyMode && (
          <form className="win-verify" onSubmit={verify}>
            <p className="win-verify-copy">Twenty-one or older to claim. Quick check.</p>
            <div className="gate-dob">
              <input inputMode="numeric" maxLength="2" placeholder="MM"
                     value={m} onChange={e => { setM(e.target.value.replace(/\D/g, '')); setVErr(''); }} />
              <span className="gate-slash">/</span>
              <input inputMode="numeric" maxLength="2" placeholder="DD"
                     value={d} onChange={e => { setD(e.target.value.replace(/\D/g, '')); setVErr(''); }} />
              <span className="gate-slash">/</span>
              <input inputMode="numeric" maxLength="4" placeholder="YYYY"
                     value={y} onChange={e => { setY(e.target.value.replace(/\D/g, '')); setVErr(''); }} />
            </div>
            {vErr && <div className="gate-err">{vErr}</div>}
            <button className="btn-primary" type="submit">Verify</button>
            <button type="button" className="win-replay" onClick={() => setVerifyMode(false)}>Maybe later</button>
          </form>
        )}
        {verified && (
          <div className="win-code-block">
            <span className="win-code-eyebrow">Your prize code</span>
            <div className="win-code">{code}</div>
            <p className="win-code-hint">Screenshot it. Bring it in. Or save it for the next drop.</p>
          </div>
        )}
      </div>

      <div className="win-cta">
        {!subbed ? (
          <form className="win-form" onSubmit={e => { e.preventDefault(); if (email.includes('@')) setSubbed(true); }}>
            <p className="win-sub-copy">Subscribe for early drops, more chances at freebies, and the next issue first in your inbox.</p>
            <div className="win-form-row">
              <input className="win-input" type="email" placeholder="your@email"
                     value={email} onChange={e => setEmail(e.target.value)} required />
              <button className="win-btn" type="submit">Subscribe</button>
            </div>
          </form>
        ) : (
          <div className="win-thanks">In. The next freebie lands with the next issue.</div>
        )}
      </div>

      <button className="win-replay" onClick={() => navigate({ name: 'history' })}>↺ Past issues</button>
    </section>
  );
}

// ─── Game Over ──────────────────────────────────────────────────────────────
function Over({ quiz, tile, navigate }) {
  const t = quiz.tiles.find(x => x.points === tile);
  return (
    <section className="screen over" data-screen-label="05 Game Over">
      <SiteHeader navigate={navigate} />
      <div className="over-mark">×</div>
      <h2 className="over-title">That's the issue.</h2>
      <p className="over-copy">One wrong answer ends the week. The correct answer was —</p>
      {t && <div className="over-answer">{t.choices[t.correct]}</div>}
      <p className="over-fine">New tiles drop Tuesdays and Fridays at 7am ET.</p>
      <button className="btn-primary" onClick={() => navigate({ name: 'history' })}>Past issues</button>
    </section>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
