/* ============================================================
   THE QUARTET — main app
   ============================================================ */

const { useState, useEffect, useRef, useCallback } = React;

// ---------------- IMG WITH FALLBACK -----------------
function ImgFill({ src, alt, label }) {
  const [failed, setFailed] = useState(!src);
  if (failed) return <div className="fill-empty">DROP:<br/>{label}</div>;
  return <img className="fill-img" src={src} alt={alt} loading="lazy" onError={() => setFailed(true)} />;
}

// ---------------- TOAST -----------------
function Toast({ msg, onDone }) {
  useEffect(() => {
    if (!msg) return;
    const t = setTimeout(onDone, 3200);
    return () => clearTimeout(t);
  }, [msg, onDone]);
  if (!msg) return null;
  return <div className="toast">{msg}</div>;
}

// ---------------- DICE -----------------
function Dice({ size = 56 }) {
  const [face, setFace] = useState(6);
  const [rolling, setRolling] = useState(false);
  const onClick = () => {
    setRolling(true);
    diceClack();
    setTimeout(() => {
      setFace(1 + Math.floor(Math.random() * 6));
      setRolling(false);
    }, 600);
  };
  const pipPositions = {
    1: [[50, 50]],
    2: [[25, 25], [75, 75]],
    3: [[25, 25], [50, 50], [75, 75]],
    4: [[25, 25], [75, 25], [25, 75], [75, 75]],
    5: [[25, 25], [75, 25], [50, 50], [25, 75], [75, 75]],
    6: [[25, 25], [75, 25], [25, 50], [75, 50], [25, 75], [75, 75]],
  };
  return (
    <div className={"dice" + (rolling ? " rolling" : "")} onClick={onClick} style={{ width: size, height: size }}>
      {pipPositions[face].map((p, i) => (
        <span key={i} className="pip" style={{ left: `calc(${p[0]}% - 5px)`, top: `calc(${p[1]}% - 5px)` }} />
      ))}
    </div>
  );
}

// ---------------- HERO -----------------
function Hero() {
  return (
    <section className="hero">
      <div className="hero-topbar">
        <span>FATHER'S DAY · 2026</span>
        <span>SUN · JUN 21</span>
      </div>
      <p className="section-kicker" style={{ marginBottom: 6, color: "var(--oxblood)" }}>★ FATHER'S DAY 2026 ☆ OFFICIAL DECREE ★</p>
      <h1 className="hero-title">THE<br/>QUARTET</h1>
      <div className="hero-datestrip">
        <span>SUN</span><span>·</span><span>JUN</span><span>21</span><span>·</span><span>2026</span>
      </div>
      <p className="hero-sub">Four men · One garage · Infinite meeples</p>
      <p className="hero-tagline">
        A heartfelt internet-flavored monument to <em>Christian, Abe, Toby &amp; Jeremy</em> — kings of the heavy euro, defenders of the analysis paralysis, drinkers of <em>whatever's cold</em> <span style={{ fontSize: 11, opacity: 0.75 }}>(Jeremy's is a seltzer)</span>.
      </p>
      <div className="hero-orn">
        <Dice />
        <Stein small />
        <Dice />
      </div>
      <p className="f-mono" style={{ fontSize: 11, marginTop: 14, opacity: 0.7 }}>↓ scroll for the plan · roll · cheers · click everything ↓</p>
    </section>
  );
}

// ---------------- STEIN SVG -----------------
function Stein({ small, big, onClick }) {
  const s = small ? 56 : big ? 180 : 100;
  return (
    <svg width={s} height={s * 1.15} viewBox="0 0 100 115" onClick={onClick} style={{ cursor: onClick ? "pointer" : "default" }}>
      {/* handle */}
      <path d="M 78 38 Q 96 42 96 60 Q 96 78 78 82" fill="none" stroke="#221208" strokeWidth="6" />
      {/* mug body */}
      <rect x="14" y="32" width="68" height="76" rx="3" fill="#f4ead4" stroke="#221208" strokeWidth="3.5" />
      {/* beer fill */}
      <rect x="18" y="42" width="60" height="62" fill="#d4a04a" />
      {/* bubbles */}
      <circle cx="30" cy="60" r="2.5" fill="#f8f1d8" opacity="0.7" />
      <circle cx="50" cy="78" r="2" fill="#f8f1d8" opacity="0.7" />
      <circle cx="65" cy="55" r="3" fill="#f8f1d8" opacity="0.7" />
      <circle cx="40" cy="92" r="2.5" fill="#f8f1d8" opacity="0.7" />
      <circle cx="62" cy="84" r="1.8" fill="#f8f1d8" opacity="0.7" />
      {/* foam top */}
      <ellipse cx="48" cy="36" rx="36" ry="9" fill="#f8f1d8" stroke="#221208" strokeWidth="3" />
      <circle cx="22" cy="30" r="8" fill="#f8f1d8" stroke="#221208" strokeWidth="3" />
      <circle cx="40" cy="26" r="9" fill="#f8f1d8" stroke="#221208" strokeWidth="3" />
      <circle cx="58" cy="27" r="8" fill="#f8f1d8" stroke="#221208" strokeWidth="3" />
      <circle cx="72" cy="32" r="7" fill="#f8f1d8" stroke="#221208" strokeWidth="3" />
      {/* base */}
      <ellipse cx="48" cy="108" rx="34" ry="4" fill="#221208" opacity="0.25" />
    </svg>
  );
}

// ---------------- THE PLAN -----------------
const PLAN_TARGET = new Date("2026-06-21T15:00:00").getTime();

function Countdown() {
  const [now, setNow] = useState(Date.now());
  useEffect(() => {
    const t = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(t);
  }, []);
  const diff = Math.max(0, PLAN_TARGET - now);
  const days = Math.floor(diff / 86400000);
  const hours = Math.floor((diff % 86400000) / 3600000);
  const mins = Math.floor((diff % 3600000) / 60000);
  const secs = Math.floor((diff % 60000) / 1000);
  return (
    <div className="countdown">
      <div className="cd-cell"><div className="cd-num">{String(days).padStart(2, "0")}</div><div className="cd-label">DAYS</div></div>
      <div className="cd-sep">:</div>
      <div className="cd-cell"><div className="cd-num">{String(hours).padStart(2, "0")}</div><div className="cd-label">HRS</div></div>
      <div className="cd-sep">:</div>
      <div className="cd-cell"><div className="cd-num">{String(mins).padStart(2, "0")}</div><div className="cd-label">MIN</div></div>
      <div className="cd-sep">:</div>
      <div className="cd-cell"><div className="cd-num">{String(secs).padStart(2, "0")}</div><div className="cd-label">SEC</div></div>
    </div>
  );
}

const TIME_OPTIONS = ["10:00 AM", "11:00 AM", "12:00 PM", "1:00 PM", "2:00 PM"];

// Shorten a quest name for compact display
function shortQuest(name) {
  if (!name) return "—";
  if (name.length <= 22) return name;
  return name.split(" \u00d7 ")[0].split(" & ")[0].slice(0, 22);
}

function StatusBoard({ leadingQuest, leadingTime, inCount, allInCount }) {
  const whenLocked = !!leadingTime;
  const whereLocked = !!leadingQuest;
  const inLocked = inCount >= 4;
  const allLocked = whenLocked && whereLocked && inLocked;
  return (
    <div className={"status-board" + (allLocked ? " all-locked" : "")}>
      <div className="sb-header">★ LOCK-IN STATUS ★</div>
      <div className="sb-grid">
        <div className={"sb-cell" + (whenLocked ? " locked" : "")}>
          <div className="sb-label">WHEN</div>
          <div className="sb-value">{leadingTime || "—"}</div>
          <div className="sb-check">{whenLocked ? "✓" : "○"}</div>
        </div>
        <div className={"sb-cell" + (whereLocked ? " locked" : "")}>
          <div className="sb-label">WHERE</div>
          <div className="sb-value" title={leadingQuest ? leadingQuest.name : ""}>{shortQuest(leadingQuest && leadingQuest.name)}</div>
          <div className="sb-check">{whereLocked ? "✓" : "○"}</div>
        </div>
        <div className={"sb-cell" + (inLocked ? " locked" : "")}>
          <div className="sb-label">IN</div>
          <div className="sb-value">{inCount}<span className="sb-of">/4</span></div>
          <div className="sb-check">{inLocked ? "✓" : "○"}</div>
        </div>
      </div>
      {allLocked && <div className="sb-victory">✓ ALL LOCKED IN · SEE YOU SUNDAY</div>}
      {!allLocked && (
        <div className="sb-hint">
          {!whereLocked && !whenLocked && "Vote below to start locking it in."}
          {whereLocked && !whenLocked && "Where: ✓ · Pick a start time below."}
          {!whereLocked && whenLocked && "When: ✓ · Pick a brewery below."}
          {whereLocked && whenLocked && !inLocked && `So close — ${4 - inCount} more lad${4 - inCount === 1 ? "" : "s"} to confirm IN.`}
        </div>
      )}
    </div>
  );
}

// ---- Meeple icon used in voting chips ----
function MeepleIcon({ size = 14, fill = "currentColor" }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill={fill}>
      <path d="M12 2 C 9.5 2 8.5 4 9 5.5 L 5 7 L 5 12 L 8 12 L 8 22 L 16 22 L 16 12 L 19 12 L 19 7 L 15 5.5 C 15.5 4 14.5 2 12 2 Z" />
    </svg>
  );
}

function MeepleChip({ player, voted, onClick }) {
  return (
    <button
      className={`meeple-chip color-${player.color} ${voted ? "voted" : ""}`}
      onClick={onClick}
      aria-label={`${player.name}'s vote`}
    >
      <span className="mc-icon"><MeepleIcon size={16} /></span>
      <span className="mc-name">{player.name.slice(0, 3)}</span>
    </button>
  );
}

function QuestCard({ quest, votes, onVote, isLeader }) {
  const voterIds = Object.keys(votes).filter(pid => votes[pid] === quest.id);
  const count = voterIds.length;
  const avgDrive = Math.round(
    (quest.drives.christian + quest.drives.toby + quest.drives.abe + quest.drives.jeremy) / 4
  );
  return (
    <div
      className={"quest-card" + (isLeader ? " leader" : "") + (quest.badge ? " editors-pick" : "")}
      style={{ "--quest-color": quest.color }}
    >
      {quest.badge && <span className="quest-pick-badge">★ {quest.badge}</span>}
      <div className="quest-band" />
      <div className="quest-body">
        <h4 className="quest-name">{quest.name}</h4>
        <div className="quest-tag">{quest.tag}</div>
        <div className="quest-area">📍 {quest.area}</div>

        <p className="quest-pitch">{quest.why}</p>

        <div className="quest-meta">
          <div className="qm-row"><span className="qm-label">FOOD</span><span className="qm-val">{quest.food}</span></div>
          <div className="qm-row"><span className="qm-label">TABLES</span><span className="qm-val">{quest.tables}</span></div>
          <div className="qm-row"><span className="qm-label">WALK TO</span><span className="qm-val">{quest.walkable}</span></div>
        </div>

        <div className="quest-section">
          <div className="quest-label">◇ DRIVE TIME (MIN) · AVG {avgDrive}</div>
          <div className="drive-pills">
            {PLAYERS.map(p => (
              <span key={p.id} className={`drive-pill color-${p.color}`}>
                <span className="dp-name">{p.name.slice(0, 3)}</span>
                <span className="dp-min">{quest.drives[p.id]}</span>
              </span>
            ))}
          </div>
        </div>

        <div className="quest-vote">
          <div className="quest-label">◇ WHO'S VOTING</div>
          <div className="vote-chips">
            {PLAYERS.map(p => (
              <MeepleChip
                key={p.id}
                player={p}
                voted={votes[p.id] === quest.id}
                onClick={() => onVote(p.id, quest.id)}
              />
            ))}
          </div>
          <div className="vote-summary">
            {count === 0 && <span className="vs-empty">— NO VOTES YET —</span>}
            {count > 0 && (
              <span className="vs-count">
                {"★".repeat(count)} {count} VOTE{count === 1 ? "" : "S"}
                {isLeader && count >= 2 ? " · LEADING" : ""}
              </span>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

function PlanSection({ onToast }) {
  // QUEST + TIME voting (one vote per lad)
  const [questVotes, setQuestVotes] = useSharedField("quest_votes", {});
  const [timeVotes, setTimeVotes] = useSharedField("time_votes", {});
  // RSVP toggles for the quartet
  const [rsvps, setRsvps] = useSharedField("rsvps", {});
  // Open guestbook for everyone else
  const [guests, setGuests] = useSharedField("guests", []);
  const [guestInput, setGuestInput] = useState("");
  // What people are bringing
  const [bring, setBring] = useSharedField("bring", {
    christian: "SALTY LICORICE",
    abe: "WHATEVER'S COLD x6",
    toby: "THE GAMES + THE TABLE",
    jeremy: "CARROTS AND HUMMUS",
  });

  // Quest vote tally
  const questCounts = QUESTS.reduce((acc, q) => {
    acc[q.id] = Object.values(questVotes).filter(v => v === q.id).length;
    return acc;
  }, {});
  const maxQuestVotes = Math.max(...Object.values(questCounts), 0);
  const leadingQuest = QUESTS.find(q => questCounts[q.id] === maxQuestVotes && maxQuestVotes > 0);

  // Time vote tally
  const timeCounts = TIME_OPTIONS.reduce((acc, t) => {
    acc[t] = Object.values(timeVotes).filter(v => v === t).length;
    return acc;
  }, {});
  const maxTimeVotes = Math.max(...Object.values(timeCounts), 0);
  const leadingTime = TIME_OPTIONS.find(t => timeCounts[t] === maxTimeVotes && maxTimeVotes > 0);

  const voteQuest = (playerId, questId) => {
    pop();
    setQuestVotes(v => {
      if (v[playerId] === questId) {
        const { [playerId]: _, ...rest } = v;
        return rest;
      }
      return { ...v, [playerId]: questId };
    });
  };

  const voteTime = (playerId, time) => {
    pop();
    setTimeVotes(v => {
      if (v[playerId] === time) {
        const { [playerId]: _, ...rest } = v;
        return rest;
      }
      return { ...v, [playerId]: time };
    });
  };

  const toggleRsvp = (id) => {
    pop();
    setRsvps(r => ({ ...r, [id]: !r[id] }));
  };

  const inCount = PLAYERS.filter(p => rsvps[p.id]).length;

  const addGuest = () => {
    const name = guestInput.trim();
    if (!name) return;
    if (guests.some(g => g.name.toLowerCase() === name.toLowerCase())) {
      onToast(`${name.toUpperCase()} IS ALREADY IN. WE GET IT.`);
      return;
    }
    clink();
    setGuests(g => [...g, { name, at: Date.now() }]);
    setGuestInput("");
    onToast(`${name.toUpperCase()} IS IN. 🍻`);
  };
  const removeGuest = (name) => {
    pop();
    setGuests(g => g.filter(x => x.name !== name));
  };

  const rollFate = () => {
    diceClack();
    const random = QUESTS[Math.floor(Math.random() * QUESTS.length)];
    // Cast a random "fate vote" using a phantom player id
    setQuestVotes(v => ({ ...v, "__fate__": random.id }));
    setTimeout(() => onToast(`🎲 THE DICE GODS DECREE: ${random.name}.`), 100);
  };

  return (
    <section className="plan-wrap">
      <div className="plan-poster">
        <div className="poster-nail nail-tl" />
        <div className="poster-nail nail-tr" />
        <div className="poster-nail nail-bl" />
        <div className="poster-nail nail-br" />
        <span className="stamp plan-stamp">PINNED</span>

        <p className="section-kicker" style={{ textAlign: "center", marginBottom: 4 }}>★ TAVERN NOTICE ★</p>
        <h2 className="plan-title">THE PLAN</h2>
        <div className="plan-divider"><span>FATHER'S DAY · 2026</span></div>

        <p className="plan-mission">
          One Sunday. Four lads. Three things to lock in:<br/>
          <span className="mission-thing">WHEN</span> we start · <span className="mission-thing">WHERE</span> we start · <span className="mission-thing">WHO'S IN</span>.
        </p>

        <StatusBoard
          leadingQuest={leadingQuest && maxQuestVotes >= 2 ? leadingQuest : null}
          leadingTime={leadingTime && maxTimeVotes >= 2 ? leadingTime : null}
          inCount={inCount}
        />

        {/* ----- WHEN ----- */}
        <div className="plan-row plan-date">
          <div className="plan-kicker">DATE</div>
          <div className="plan-big">SUNDAY · JUNE 21</div>
          <div className="plan-sub">↓ countdown until the meeples drop ↓</div>
          <Countdown />
        </div>

        {/* ----- WHERE WE START ----- */}
        <div className="plan-row">
          <div className="plan-kicker">WHERE WE START <span style={{ float: "right", fontWeight: "normal" }}>PICK A VISTA BREWERY</span></div>
          <p className="plan-intro">
            Vista has more breweries per capita than any U.S. city. Three of these four spots are walkable to each other — lock one in and we can roam from there. <em>Tap your meeple</em> to cast your vote.
          </p>

          {leadingQuest && maxQuestVotes >= 2 && (
            <div className="quest-leader-banner">
              <span className="qlb-prefix">CURRENT LEADER →</span>
              <span className="qlb-name">{leadingQuest.name}</span>
              <span className="qlb-count">{maxQuestVotes} VOTES</span>
            </div>
          )}

          <div className="quest-list">
            {QUESTS.map(q => (
              <QuestCard
                key={q.id}
                quest={q}
                votes={questVotes}
                onVote={voteQuest}
                isLeader={leadingQuest && leadingQuest.id === q.id && maxQuestVotes >= 2}
              />
            ))}
          </div>

          <button className="btn green roll-fate" onClick={rollFate}>🎲 ROLL FATE</button>
          <div className="plan-hint" style={{ textAlign: "center" }}>can't agree? the dice gods will pick.</div>
        </div>

        {/* ----- START TIME ----- */}
        <div className="plan-row">
          <div className="plan-kicker">
            START TIME
            <span style={{ float: "right", fontWeight: "normal" }}>
              {leadingTime ? `LEADER: ${leadingTime}` : "PICK YOURS"}
            </span>
          </div>
          <p className="plan-intro">
            Goal: <strong>fully consume Sunday</strong>. The earlier we start, the more we get. Tap your meeple under your preferred kickoff.
          </p>
          <div className="time-vote-grid">
            {TIME_OPTIONS.map(t => {
              const voters = PLAYERS.filter(p => timeVotes[p.id] === t);
              const isLead = leadingTime === t && maxTimeVotes > 0;
              return (
                <div key={t} className={"time-vote-cell" + (isLead ? " lead" : "")}>
                  <div className="tv-time">{t}</div>
                  <div className="tv-chips">
                    {PLAYERS.map(p => (
                      <button
                        key={p.id}
                        className={`tv-chip color-${p.color}` + (timeVotes[p.id] === t ? " voted" : "")}
                        onClick={() => voteTime(p.id, t)}
                        aria-label={`${p.name} votes ${t}`}
                      >{p.name[0]}</button>
                    ))}
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        {/* ----- RSVP (quartet) ----- */}
        <div className="plan-row plan-rsvp-row">
          <div className="plan-kicker plan-kicker-xl">ARE YOU IN? <span style={{ float: "right", fontWeight: "normal" }}>{inCount} / 4 · THE QUARTET</span></div>
          <p className="plan-intro">
            The most important question on this site. <strong>Tap your name to confirm.</strong>
          </p>
          <div className="rsvp-grid">
            {PLAYERS.map(p => (
              <button
                key={p.id}
                className={"rsvp-btn" + (rsvps[p.id] ? " in" : "")}
                onClick={() => toggleRsvp(p.id)}
              >
                <span className="rsvp-name">{p.name}</span>
                <span className="rsvp-state">{rsvps[p.id] ? "✓ IN" : "TAP IF IN"}</span>
              </button>
            ))}
          </div>
        </div>

        {/* ----- GUESTBOOK (open signup) ----- */}
        <div className="plan-row">
          <div className="plan-kicker">SIGN IN <span style={{ float: "right", fontWeight: "normal" }}>{guests.length} GUEST{guests.length === 1 ? "" : "S"}</span></div>
          <p className="plan-intro">
            Anyone else dropping by? Type your name, hit <strong>I'M IN</strong>.
          </p>
          <form
            className="guest-form"
            onSubmit={e => { e.preventDefault(); addGuest(); }}
          >
            <input
              className="guest-input"
              type="text"
              placeholder="YOUR NAME"
              value={guestInput}
              onChange={e => setGuestInput(e.target.value)}
              spellCheck="false"
              maxLength={32}
            />
            <button type="submit" className="guest-submit">I'M IN</button>
          </form>
          {guests.length > 0 && (
            <ul className="guest-list">
              {guests.map(g => (
                <li key={g.name} className="guest-item">
                  <span className="gi-check">✓</span>
                  <span className="gi-name">{g.name.toUpperCase()}</span>
                  <button className="gi-x" onClick={() => removeGuest(g.name)} aria-label="remove">×</button>
                </li>
              ))}
            </ul>
          )}
        </div>

        {/* ----- BRINGING ----- */}
        <div className="plan-row">
          <div className="plan-kicker">BRINGING</div>
          <div className="bring-list">
            {PLAYERS.map(p => (
              <div key={p.id} className="bring-row">
                <span className={`bring-name color-${p.color}`}>{p.name}</span>
                <input
                  className="bring-input"
                  value={bring[p.id] || ""}
                  onChange={e => setBring(b => ({ ...b, [p.id]: e.target.value }))}
                  spellCheck="false"
                  placeholder="..."
                />
              </div>
            ))}
          </div>
        </div>

        {/* ----- CTA ----- */}
        <div className="plan-cta-row">
          <button
            className="btn green"
            onClick={() => {
              clink();
              const quest = leadingQuest ? leadingQuest.name : "(undecided)";
              const time = leadingTime || "(undecided)";
              onToast(`LOCKED IN: ${time} · ${quest}.`);
            }}
          >LOCK IT IN</button>
        </div>
        <div className="plan-hint" style={{ textAlign: "center", marginTop: 6 }}>
          changes save automatically — everyone sees the same board.
        </div>
      </div>
    </section>
  );
}

// ---------------- PLAYER CARDS -----------------
function PlayerCard({ p, onToast }) {
  return (
    <div className={`player-card ${p.tilt} ${p.color}`}>
      <div className="pc-head">
        <span>★ PLAYER 0{PLAYERS.findIndex(x => x.id === p.id) + 1}</span>
        <span>{p.klass}</span>
      </div>
      <div className="pc-body">
        <div className="pc-portrait">
          <ImgFill src={p.img} alt={p.name} label={p.name} />
        </div>
        <div>
          <div className="pc-name">{p.name}</div>
          <div className="pc-class">{p.klass}</div>
          <div className="pc-stats">
            {p.stats.map(([k, v]) => (
              <div className="stat" key={k}>
                <span>{k}</span><span>{v}</span>
              </div>
            ))}
          </div>
        </div>
      </div>
      <button className="pc-ability" onClick={() => { pop(); const r = p.ability(); onToast(r.msg); }}>
        {p.abilityLabel}
      </button>
    </div>
  );
}

function PlayersSection({ onToast }) {
  return (
    <section style={{ background: "var(--cream-deep)" }}>
      <p className="section-kicker">⚔ DRAMATIS PERSONAE ⚔</p>
      <h2 className="section-title">THE LADS</h2>
      <p className="f-mono" style={{ fontSize: 12, marginBottom: 16, opacity: 0.8 }}>
        Tap each one's <strong>special ability</strong>. (You will regret only one of them.)
      </p>
      <div className="players">
        {PLAYERS.map(p => <PlayerCard key={p.id} p={p} onToast={onToast} />)}
      </div>
    </section>
  );
}

// ---------------- CHEERS -----------------
function CheersSection({ onToast }) {
  const [count, setCount] = useSharedField("cheers", 0);
  const [foams, setFoams] = useState([]);
  const [freezerOpen, setFreezerOpen] = useState(false);
  const steinRef = useRef(null);

  const doCheers = (e) => {
    clink();
    setCount(c => (c || 0) + 1);
    // foam particles
    const id = Date.now() + Math.random();
    const newFoams = Array.from({ length: 6 }).map((_, i) => ({
      id: id + i,
      dx: (Math.random() * 200 - 100) + "px",
      dy: (-80 - Math.random() * 80) + "px",
      left: 50 + (Math.random() * 30 - 15),
      top: 30 + (Math.random() * 10),
    }));
    setFoams(f => [...f, ...newFoams]);
    setTimeout(() => {
      setFoams(f => f.filter(x => !newFoams.find(n => n.id === x.id)));
    }, 1300);
  };

  return (
    <section className="cheers-wrap">
      <p className="section-kicker">🍺 RAISE 'EM 🍺</p>
      <h2 className="section-title">CHEERS COUNTER</h2>
      <p className="f-mono" style={{ fontSize: 13, opacity: 0.9, margin: "6px 0 18px" }}>
        For every cold one we've cracked at Toby's table.<br/>
        <span style={{ fontSize: 11, opacity: 0.7 }}>(Jeremy is raising his lime seltzer. It still counts.)</span>
      </p>
      <div className="cheers-counter">{count.toString().padStart(4, "0")}</div>
      <div className="cheers-label">TOAST COUNT</div>

      <div className="stein-btn" ref={steinRef} onClick={doCheers}>
        <Stein big />
        {foams.map(f => (
          <span
            key={f.id}
            className="foam-particle"
            style={{
              left: f.left + "%",
              top: f.top + "%",
              "--dx": f.dx,
              "--dy": f.dy,
            }}
          />
        ))}
      </div>

      <p className="f-mono" style={{ fontSize: 12, marginTop: 14, opacity: 0.75 }}>tap the stein → satisfying clink</p>

      <button className="freezer-btn" onClick={() => { pop(); setFreezerOpen(true); }}>
        ❄ BUY THE FREEZER ❄
      </button>

      {freezerOpen && (
        <div className="freezer-modal" onClick={() => setFreezerOpen(false)}>
          <div className="freezer-modal-inner" onClick={e => e.stopPropagation()}>
            <span className="stamp" style={{ position: "absolute", top: -16, right: -14 }}>OFFICIAL</span>
            <h3>BUY THE FREEZER!</h3>
            <p>
              The official garage-game-night decree.
              <br/><br/>
              When the fridge runs out of cold ones, you don't run for more.<br/>
              You <em>buy the freezer.</em><br/><br/>
              No further questions.
            </p>
            <button className="btn green freezer-close" onClick={() => setFreezerOpen(false)}>UNDERSTOOD</button>
          </div>
        </div>
      )}
    </section>
  );
}

// ---------------- GARAGE MAP -----------------
function GarageSection() {
  const [selected, setSelected] = useState("heavy-euros");
  const shelf = SHELVES.find(s => s.id === selected);

  // Shelf hit-zones on the SVG
  const zones = [
    { id: "heavy-euros", x: 30, y: 50, w: 100, h: 70, label: "HEAVY" },
    { id: "trains-cows", x: 140, y: 50, w: 100, h: 70, label: "TRAINS" },
    { id: "medieval",   x: 250, y: 50, w: 100, h: 70, label: "DARK" },
    { id: "fillers",    x: 30, y: 130, w: 100, h: 50, label: "FILLERS" },
    { id: "shame",      x: 140, y: 130, w: 100, h: 50, label: "SHAME" },
    { id: "freezer",    x: 250, y: 130, w: 100, h: 50, label: "FREEZER" },
  ];

  return (
    <section className="garage-wrap">
      <p className="section-kicker">📍 TOBY'S RV GARAGE 📍</p>
      <h2 className="section-title">THE COLLECTION</h2>
      <p className="f-mono" style={{ fontSize: 12, marginBottom: 14, opacity: 0.8 }}>
        Tap a shelf. Read the lore. Despair at the wall of shrink-wrap.
      </p>
      <svg className="garage-svg" viewBox="0 0 380 240" xmlns="http://www.w3.org/2000/svg">
        {/* concrete floor pattern */}
        <defs>
          <pattern id="concrete" width="20" height="20" patternUnits="userSpaceOnUse">
            <rect width="20" height="20" fill="#c5ad7f"/>
            <circle cx="3" cy="5" r="0.6" fill="#9e8559"/>
            <circle cx="14" cy="11" r="0.5" fill="#9e8559"/>
            <circle cx="8" cy="16" r="0.7" fill="#9e8559"/>
          </pattern>
          <pattern id="boards" width="6" height="12" patternUnits="userSpaceOnUse">
            <rect width="6" height="12" fill="#7a5a32"/>
            <rect x="0" y="11" width="6" height="1" fill="#3a2a16"/>
          </pattern>
        </defs>
        {/* back wall */}
        <rect x="0" y="0" width="380" height="190" fill="#a88860"/>
        <rect x="0" y="190" width="380" height="50" fill="url(#concrete)"/>
        {/* RV silhouette top corner */}
        <g opacity="0.35">
          <rect x="282" y="10" width="92" height="28" fill="#5a3818" stroke="#221208" strokeWidth="1.5" rx="4"/>
          <circle cx="298" cy="40" r="5" fill="#221208"/>
          <circle cx="356" cy="40" r="5" fill="#221208"/>
          <rect x="288" y="14" width="14" height="10" fill="#d4a04a"/>
          <rect x="306" y="14" width="14" height="10" fill="#d4a04a"/>
          <text x="328" y="29" fontFamily="Rye, serif" fontSize="8" fill="#f4ead4">TOBY'S</text>
        </g>
        {/* SHELVES — clickable */}
        {zones.map(z => {
          const isActive = z.id === selected;
          return (
            <g
              key={z.id}
              className={"shelf-clickable" + (isActive ? " active" : "")}
              onClick={() => { pop(); setSelected(z.id); }}
            >
              <rect
                x={z.x} y={z.y} width={z.w} height={z.h}
                fill="url(#boards)"
                stroke={isActive ? "#c7991a" : "#221208"}
                strokeWidth={isActive ? 3 : 2}
              />
              {/* shelf rows of game boxes */}
              {Array.from({ length: 3 }).map((_, row) => (
                <g key={row}>
                  {Array.from({ length: Math.floor(z.w / 14) }).map((_, col) => {
                    const colors = ["#6e1f1f", "#1f3a2b", "#d4a04a", "#c7991a", "#4a1212", "#e9dcb6", "#8a5a2b"];
                    const fill = colors[(col + row + z.id.length) % colors.length];
                    const h = z.h / 3 - 4;
                    return (
                      <rect
                        key={col}
                        x={z.x + 3 + col * 13}
                        y={z.y + 3 + row * (h + 2)}
                        width={11}
                        height={h}
                        fill={fill}
                        stroke="#221208"
                        strokeWidth="0.6"
                      />
                    );
                  })}
                </g>
              ))}
              <rect x={z.x} y={z.y + z.h - 4} width={z.w} height={4} fill="#3a2a16"/>
              <text
                x={z.x + z.w / 2}
                y={z.y - 3}
                fontFamily="Rye, serif"
                fontSize="8"
                fill={isActive ? "#c7991a" : "#221208"}
                textAnchor="middle"
              >{z.label}</text>
            </g>
          );
        })}
        {/* TOBY meeple in front */}
        <g transform="translate(180, 195)">
          <ellipse cx="0" cy="38" rx="14" ry="3" fill="#221208" opacity="0.4"/>
          <path d="M 0 -10 Q -6 -10 -6 -3 L -12 0 L -12 14 L -8 14 L -8 36 L 8 36 L 8 14 L 12 14 L 12 0 L 6 -3 Q 6 -10 0 -10 Z"
                fill="#d4a04a" stroke="#221208" strokeWidth="1.5"/>
          <circle cx="0" cy="-5" r="6" fill="#d4a04a" stroke="#221208" strokeWidth="1.5"/>
          <text x="0" y="46" fontFamily="Rye, serif" fontSize="7" fill="#221208" textAnchor="middle">TOBY (curator)</text>
        </g>
      </svg>

      <div className="shelf-info">
        <h4>{shelf.label}</h4>
        <div className="shelf-tag">{shelf.tag}</div>
        <p>{shelf.desc}</p>
        <div className="games">{shelf.games}</div>
      </div>

      {/* The "one wood for one wooooood" easter egg lives here, thematically */}
      <WoodTrade />
    </section>
  );
}

function WoodTrade() {
  const [traded, setTraded] = useState(0);
  const click = () => {
    pop();
    setTraded(t => t + 1);
  };
  const msg = traded === 0 ? "ONE WOOD" : "ONE WOOOOO" + "O".repeat(Math.min(traded, 12)) + "D";
  return (
    <div className="wood-card">
      <h4>↻ THE ETERNAL TRADE ↻</h4>
      <p className="f-mono" style={{ fontSize: 12, marginBottom: 10 }}>I'll give you one wood for...</p>
      <button className="wood-trade-btn" onClick={click}>{msg}</button>
      {traded >= 6 && (
        <p className="f-mono" style={{ fontSize: 11, marginTop: 10, color: "var(--cream)" }}>
          ⚠ DEAL ACCEPTED. NO TAKEBACKSIES.
        </p>
      )}
    </div>
  );
}

// ---------------- POLAROIDS -----------------
function PolaroidsSection() {
  return (
    <section className="polaroid-wall">
      <p className="section-kicker">📷 EVIDENCE 📷</p>
      <h2 className="section-title">THE WALL</h2>
      <p className="f-mono" style={{ fontSize: 13, marginBottom: 10, opacity: 0.85 }}>
        Drag &amp; drop your favorite shots into the polaroids. They stick.
      </p>
      <div className="polaroid-grid">
        {POLAROIDS.map(p => (
          <div key={p.id} className="polaroid">
            <div className="polaroid-img-wrap">
              <ImgFill src={p.img} alt={p.caption} label={p.id.replace("polaroid-", "#")} />
            </div>
            <div className="polaroid-caption">{p.caption}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

// ---------------- HALL OF GAMES -----------------
function HallSection({ onToast }) {
  return (
    <section className="hall">
      <p className="section-kicker">📚 THE GREATEST HITS 📚</p>
      <h2 className="section-title">HALL OF GAMES</h2>
      <p className="f-mono" style={{ fontSize: 12, marginBottom: 14, opacity: 0.8 }}>
        Six titles we cannot stop bringing to the table. Diamonds = weight.
      </p>
      <div className="games-grid">
        {GAMES.map((g, idx) => (
          <div key={g.name} className="game-card" onClick={() => { pop(); onToast(`NOW TABLED: ${g.name}. ${pick(["GO PEE.","CRACK ONE OPEN.","SUMMON CHRISTIAN.","HIDE THE SHRINK-WRAP."])}`); }}>
            <span className="gc-corner">{idx + 1}</span>
            <h5>{g.name}</h5>
            <div className="gc-meta">{g.meta}</div>
            <div className="gc-desc">{g.desc}</div>
            <div className="gc-weight">
              {Array.from({ length: 5 }).map((_, i) => (
                <span key={i} className={i < g.weight ? "" : "off"} />
              ))}
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

// ---------------- FOOTER -----------------
function Footer({ onToast }) {
  return (
    <section className="footer">
      <p className="section-kicker" style={{ color: "var(--amber)" }}>★ ROLL CREDITS ★</p>
      <h2 className="section-title">HAPPY FATHER'S DAY</h2>
      <p style={{ marginTop: 14 }}>
        To <strong>Christian, Abe, Toby &amp; Jeremy</strong>: thanks for the rulebooks, the rivalries, the absurd combos, the questionable jokes, the colder-than-cold cans, and a garage full of <em>mind-bending cardboard.</em>
      </p>
      <p className="signoff">— THE QUARTET · 2026 —</p>
      <div style={{ display: "flex", gap: 8, justifyContent: "center", flexWrap: "wrap", margin: "10px 0 18px" }}>
        <Dice />
        <Dice />
        <Dice />
      </div>
      <p className="credits">
        v0.06 · cardboard-driven design · brewed in HTML<br/>
        you've found the bottom. drink water.
      </p>
      <button className="btn amber" style={{ marginTop: 16 }}
        onClick={() => { clink(); onToast(pick([
          "TO TOBY'S SHELVES! 🍻",
          "TO CHRISTIAN'S ENGINES! 🍻",
          "TO ABE'S TIMING! 🍻",
          "TO JEREMY'S WARDROBE! 🍻",
          "TO JEREMY'S SELTZER GAME! 🍋",
          "TO WHATEVER'S COLD! 🍻",
        ])); }}
      >ONE LAST CHEERS</button>
    </section>
  );
}

// ---------------- APP -----------------
function App() {
  const [toast, setToast] = useState("");
  const onToast = useCallback((m) => setToast(m), []);
  return (
    <>
      <Hero />
      <PlanSection onToast={onToast} />
      <PlayersSection onToast={onToast} />
      <CheersSection onToast={onToast} />
      <GarageSection />
      <PolaroidsSection />
      <HallSection onToast={onToast} />
      <Footer onToast={onToast} />
      <Toast msg={toast} onDone={() => setToast("")} />
    </>
  );
}

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