// Hub home page — featured games + leaderboard
const { useState, useEffect, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "arcade",
  "showLeaderboard": true,
  "showStats": true,
  "showRecent": true
}/*EDITMODE-END*/;

const GAMES_BASE = [
  {
    id: "danish-500",
    title: "500 (Danish)",
    subtitle: "The classic trick-taking card game",
    players: "3–4 players",
    deck: "52-card",
    difficulty: 4,
    accent: "var(--pink)",
    href: "danish-500.html",
    available: true,
    icon: "cards",
  },
  {
    id: "backgammon",
    title: "Backgammon",
    subtitle: "Race your pieces around the board",
    players: "2 players",
    deck: "Dice + board",
    difficulty: 3,
    accent: "var(--teal)",
    href: "backgammon.html",
    available: true,
    icon: "dice",
  },
  {
    id: "shithead",
    title: "Shithead",
    subtitle: "Don't be the last with cards",
    players: "2–6 players",
    deck: "52-card",
    difficulty: 2,
    accent: "var(--lime)",
    href: "shithead.html",
    available: true,
    icon: "trophy",
  },
  {
    id: "new-game",
    title: "Add a Game",
    subtitle: "Got a family classic? Bring it in.",
    players: "Any",
    deck: "—",
    difficulty: 0,
    accent: "var(--yellow)",
    href: "#",
    available: false,
    icon: "plus",
    lastPlayed: "Make it yours",
  },
];

// Re-read history when the window regains focus, so finishing a game
// in another tab/page reflects when you come back to the hub.
function useHistory() {
  const [history, setHistoryState] = useState(() => getHistory());
  useEffect(() => {
    let alive = true;
    const refresh = async () => {
      const next = await fetchHistory();
      if (alive) setHistoryState(next);
    };
    refresh();
    const unsubAuth = window.svendeAuth ? window.svendeAuth.onChange(refresh) : null;
    const cacheOnly = () => setHistoryState(getHistory());
    window.addEventListener("focus", refresh);
    document.addEventListener("visibilitychange", refresh);
    window.addEventListener("storage", cacheOnly);
    window.addEventListener("online", refresh);
    return () => {
      alive = false;
      if (unsubAuth) unsubAuth();
      window.removeEventListener("focus", refresh);
      document.removeEventListener("visibilitychange", refresh);
      window.removeEventListener("storage", cacheOnly);
      window.removeEventListener("online", refresh);
    };
  }, []);
  return [history, setHistoryState];
}

// Decorative game icons drawn with simple shapes only
function GameIcon({ kind, color, size = 110 }) {
  if (kind === "cards") {
    return (
      <div style={{ position: "relative", width: size, height: size }}>
        <div style={{
          position: "absolute", left: "20%", top: "15%", width: "55%", height: "75%",
          background: "var(--ink)", borderRadius: 10, border: "3px solid var(--border)",
          transform: "rotate(-12deg)", boxShadow: "3px 3px 0 var(--border)",
        }} />
        <div style={{
          position: "absolute", left: "30%", top: "10%", width: "55%", height: "75%",
          background: color, borderRadius: 10, border: "3px solid var(--border)",
          transform: "rotate(8deg)", boxShadow: "3px 3px 0 var(--border)",
          display: "flex", alignItems: "center", justifyContent: "center",
          fontFamily: "'Space Grotesk', sans-serif", fontWeight: 800,
          fontSize: size * 0.36, color: "#0a0a0a",
        }}>♦</div>
      </div>
    );
  }
  if (kind === "dice") {
    return (
      <div style={{ position: "relative", width: size, height: size }}>
        <div style={{
          position: "absolute", left: "15%", top: "20%", width: "45%", height: "45%",
          background: color, borderRadius: 12, border: "3px solid var(--border)",
          boxShadow: "4px 4px 0 var(--border)", transform: "rotate(-8deg)",
        }}>
          <div style={{ position: "absolute", left: "25%", top: "25%", width: 8, height: 8, background: "#0a0a0a", borderRadius: "50%" }} />
          <div style={{ position: "absolute", right: "25%", bottom: "25%", width: 8, height: 8, background: "#0a0a0a", borderRadius: "50%" }} />
        </div>
        <div style={{
          position: "absolute", right: "10%", bottom: "15%", width: "42%", height: "42%",
          background: "var(--ink)", borderRadius: 12, border: "3px solid var(--border)",
          boxShadow: "4px 4px 0 var(--border)", transform: "rotate(12deg)",
        }}>
          <div style={{ position: "absolute", left: "40%", top: "40%", width: 8, height: 8, background: "#0a0a0a", borderRadius: "50%" }} />
        </div>
      </div>
    );
  }
  if (kind === "trophy") {
    return (
      <div style={{ position: "relative", width: size, height: size, display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div style={{
          width: "60%", height: "70%", background: color,
          borderRadius: "50% 50% 20% 20%", border: "3px solid var(--border)",
          boxShadow: "4px 4px 0 var(--border)", display: "flex",
          alignItems: "center", justifyContent: "center",
          fontFamily: "'Space Grotesk', sans-serif", fontSize: size * 0.4,
          fontWeight: 800, color: "#0a0a0a",
        }}>★</div>
      </div>
    );
  }
  if (kind === "plus") {
    return (
      <div style={{
        width: size, height: size, display: "flex",
        alignItems: "center", justifyContent: "center",
        fontFamily: "'Space Grotesk', sans-serif",
        fontSize: size * 0.7, fontWeight: 800, color: "var(--ink)",
        opacity: 0.4,
      }}>+</div>
    );
  }
  return null;
}

function lastPlayedLabel(game, lastByGame) {
  if (!game.available) return game.lastPlayed || "Coming soon";
  const ts = lastByGame[game.id];
  if (!ts) return "Never played";
  return `Last played ${formatRelativeTime(ts)}`;
}

function GameCard({ game }) {
  const [hover, setHover] = useState(false);
  return (
    <a
      href={game.href}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        background: game.accent,
        borderRadius: "var(--radius)",
        border: "3px solid var(--border)",
        padding: 24,
        display: "flex",
        flexDirection: "column",
        gap: 16,
        textDecoration: "none",
        color: "#0a0a0a",
        boxShadow: hover ? "12px 12px 0 var(--border)" : "var(--card-shadow)",
        transform: hover ? "translate(-2px, -2px)" : "none",
        transition: "all 0.15s ease",
        opacity: game.available ? 1 : 0.92,
        position: "relative",
        overflow: "hidden",
        minHeight: 320,
      }}
    >
      {!game.available && (
        <div style={{
          position: "absolute", top: 16, right: 16,
          background: "#0a0a0a", color: "var(--yellow)",
          fontFamily: "'Space Grotesk', sans-serif", fontWeight: 700,
          fontSize: 10, textTransform: "uppercase", letterSpacing: "0.1em",
          padding: "4px 10px", borderRadius: 999,
        }}>Coming soon</div>
      )}
      <div style={{ display: "flex", justifyContent: "center", padding: "16px 0" }}>
        <GameIcon kind={game.icon} color="var(--ink)" />
      </div>
      <div style={{ flex: 1 }}>
        <h3 style={{
          fontFamily: "'Space Grotesk', sans-serif",
          fontSize: 26, fontWeight: 700, margin: "0 0 6px",
          letterSpacing: "-0.02em", lineHeight: 1.05,
        }}>{game.title}</h3>
        <p style={{
          fontFamily: "'DM Sans', sans-serif",
          fontSize: 14, margin: "0 0 16px", opacity: 0.75,
        }}>{game.subtitle}</p>
        <div style={{
          display: "flex", flexDirection: "column", gap: 6,
          fontFamily: "'DM Sans', sans-serif", fontSize: 13,
        }}>
          <Row label="Players" value={game.players} />
          <Row label="Deck" value={game.deck} />
          <Row label="Difficulty" value={"●".repeat(game.difficulty) + "○".repeat(5 - game.difficulty)} />
        </div>
      </div>
      <div style={{
        marginTop: 8, display: "flex", justifyContent: "space-between",
        alignItems: "center", paddingTop: 14,
        borderTop: "2px solid rgba(0,0,0,0.15)",
      }}>
        <span style={{ fontFamily: "'DM Sans', sans-serif", fontSize: 12, opacity: 0.7 }}>
          {game.lastPlayed}
        </span>
        <div style={{
          width: 36, height: 36, borderRadius: "50%",
          background: "#0a0a0a", color: game.accent,
          display: "flex", alignItems: "center", justifyContent: "center",
          fontWeight: 700, fontSize: 18,
        }}>→</div>
      </div>
    </a>
  );
}

function Row({ label, value }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
      <span style={{ opacity: 0.65 }}>{label}</span>
      <span style={{ fontWeight: 600 }}>{value}</span>
    </div>
  );
}

function Hero({ history, playerStats, family }) {
  const latest = history[history.length - 1];
  const playableGames = GAMES_BASE.filter(g => g.available).length;
  const knownPlayers = Object.keys(playerStats).length;
  const familyLabel = family?.name || "SvendeBanan";

  let banner = null;
  if (latest) {
    const sortedScores = latest.players
      .map((p, i) => ({ name: p.name, score: latest.finalScores[i] || 0 }))
      .sort((a, b) => b.score - a.score);
    const margin = sortedScores.length >= 2
      ? sortedScores[0].score - sortedScores[1].score : 0;
    const title = GAME_TITLES[latest.game] || latest.game;
    let bannerText = `Last ${title}: ${latest.winner.name} won`;
    if (latest.game === "shithead") {
      const losses = (latest.meta && latest.meta.losses) || [];
      const winLosses = losses[latest.players.findIndex(p => p.name === latest.winner.name)];
      bannerText = `Last ${title}: ${latest.winner.name} ${winLosses === 0 ? "stayed clean" : `(${winLosses} shithead${winLosses === 1 ? "" : "s"})`}`;
    } else if (margin > 0) {
      const runnerUp = sortedScores[1].name;
      bannerText = `Last ${title}: ${latest.winner.name} beat ${runnerUp} by ${margin} point${margin === 1 ? "" : "s"}`;
    }
    banner = (
      <div style={{
        display: "inline-flex", alignItems: "center", gap: 8,
        background: "rgba(255,210,63,0.15)", border: "2px solid var(--yellow)",
        borderRadius: 999, padding: "6px 14px", marginBottom: 24,
        fontFamily: "'DM Sans', sans-serif", fontSize: 13,
        color: "var(--yellow)", fontWeight: 600,
      }}>
        <span style={{ width: 8, height: 8, background: "var(--lime)", borderRadius: "50%" }} />
        {bannerText} · {formatRelativeTime(latest.finishedAt)}
      </div>
    );
  } else {
    banner = (
      <div style={{
        display: "inline-flex", alignItems: "center", gap: 8,
        background: "rgba(255,255,255,0.06)", border: "2px solid rgba(255,255,255,0.15)",
        borderRadius: 999, padding: "6px 14px", marginBottom: 24,
        fontFamily: "'DM Sans', sans-serif", fontSize: 13,
        color: "var(--ink-dim)", fontWeight: 600,
      }}>
        <span style={{ width: 8, height: 8, background: "var(--ink-dim)", borderRadius: "50%" }} />
        No games played yet — pick one below to get started
      </div>
    );
  }

  const tracked = knownPlayers;
  return (
    <section style={{
      position: "relative", zIndex: 1,
      maxWidth: 1280, margin: "0 auto", padding: "40px 32px 24px",
      textAlign: "center",
    }}>
      {banner}
      <h1 style={{
        fontFamily: "'Space Grotesk', sans-serif",
        fontSize: "clamp(40px, 7vw, 84px)",
        fontWeight: 700,
        letterSpacing: "-0.03em",
        lineHeight: 0.95,
        margin: "0 0 20px",
        color: "var(--ink)",
        textWrap: "balance",
      }}>
        Welcome to the
        <br />
        <span style={{
          display: "inline-block",
          background: "var(--yellow)", color: "#0a0a0a",
          padding: "0 18px", borderRadius: 14,
          border: "3px solid var(--border)",
          boxShadow: "6px 6px 0 var(--border)",
          transform: "rotate(-2deg)",
          marginTop: 8,
        }}>family arena</span>
      </h1>
      <p style={{
        fontFamily: "'DM Sans', sans-serif",
        fontSize: 18, color: "var(--ink-dim)",
        maxWidth: 540, margin: "20px auto 0",
        textWrap: "pretty",
      }}>
        Score keeping, stats, and bragging rights for the {familyLabel} dynasty.
        Currently tracking <strong style={{ color: "var(--ink)" }}>{playableGames} game{playableGames === 1 ? "" : "s"}</strong> across <strong style={{ color: "var(--ink)" }}>{tracked} family member{tracked === 1 ? "" : "s"}</strong>.
      </p>
    </section>
  );
}

function GamesGrid({ lastByGame }) {
  const games = GAMES_BASE.map(g => ({ ...g, lastPlayed: lastPlayedLabel(g, lastByGame) }));
  return (
    <section id="games" style={{ position: "relative", zIndex: 1, maxWidth: 1280, margin: "0 auto", padding: "40px 32px" }}>
      <SectionTitle eyebrow="Pick your poison" title="Family Games" accent="var(--pink)" />
      <div style={{
        display: "grid",
        gridTemplateColumns: "repeat(auto-fit, minmax(260px, 1fr))",
        gap: 24,
        marginTop: 32,
      }}>
        {games.map((g) => <GameCard key={g.id} game={g} />)}
      </div>
    </section>
  );
}

function SectionTitle({ eyebrow, title, accent }) {
  return (
    <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", flexWrap: "wrap", gap: 12 }}>
      <div>
        <div style={{
          fontFamily: "'DM Sans', sans-serif", fontSize: 12,
          textTransform: "uppercase", letterSpacing: "0.2em",
          color: accent, fontWeight: 700, marginBottom: 8,
        }}>— {eyebrow}</div>
        <h2 style={{
          fontFamily: "'Space Grotesk', sans-serif",
          fontSize: "clamp(32px, 4vw, 48px)",
          fontWeight: 700, margin: 0,
          letterSpacing: "-0.02em", color: "var(--ink)",
        }}>{title}</h2>
      </div>
    </div>
  );
}

function Leaderboard({ playerStats }) {
  const sorted = useMemo(() => {
    return Object.values(playerStats)
      .map(s => ({ ...s, winRate: s.played ? Math.round((s.wins / s.played) * 100) : 0 }))
      .sort((a, b) => {
        if (b.wins !== a.wins) return b.wins - a.wins;
        if (b.winRate !== a.winRate) return b.winRate - a.winRate;
        return b.points - a.points;
      });
  }, [playerStats]);

  if (sorted.length === 0) {
    return (
      <section id="leaderboard" style={{ position: "relative", zIndex: 1, maxWidth: 1280, margin: "0 auto", padding: "40px 32px" }}>
        <SectionTitle eyebrow="The reckoning" title="Hall of Fame" accent="var(--yellow)" />
        <div style={{
          marginTop: 32,
          background: "rgba(255,255,255,0.04)",
          border: "2px dashed rgba(255,255,255,0.2)",
          borderRadius: "var(--radius)",
          padding: 48, textAlign: "center",
        }}>
          <div style={{ fontFamily: "'Space Grotesk', sans-serif", fontSize: 22, fontWeight: 700, marginBottom: 8 }}>
            The hall is empty
          </div>
          <p style={{ fontFamily: "'DM Sans', sans-serif", color: "var(--ink-dim)", margin: 0 }}>
            Finish your first game and you'll show up on the leaderboard.
          </p>
        </div>
      </section>
    );
  }

  return (
    <section id="leaderboard" style={{ position: "relative", zIndex: 1, maxWidth: 1280, margin: "0 auto", padding: "40px 32px" }}>
      <SectionTitle eyebrow="The reckoning" title="Hall of Fame" accent="var(--yellow)" />

      {/* Top 3 podium — only shown when there are at least 3 players ranked */}
      {sorted.length >= 3 && (
        <div style={{
          display: "grid",
          gridTemplateColumns: "repeat(3, 1fr)",
          gap: 16,
          marginTop: 32,
          marginBottom: 32,
          alignItems: "end",
        }}>
          <PodiumCard player={sorted[1]} place={2} height={180} bg="var(--teal)" />
          <PodiumCard player={sorted[0]} place={1} height={220} bg="var(--yellow)" />
          <PodiumCard player={sorted[2]} place={3} height={150} bg="var(--coral)" />
        </div>
      )}

      <div style={{
        background: "rgba(255,255,255,0.04)",
        borderRadius: "var(--radius)",
        border: "2px solid var(--border)",
        overflow: "hidden",
        marginTop: sorted.length >= 3 ? 0 : 32,
      }}>
        <div style={{
          display: "grid",
          gridTemplateColumns: "60px 1fr 90px 90px 90px 100px",
          gap: 12, padding: "14px 24px",
          borderBottom: "2px solid var(--border)",
          background: "rgba(255,255,255,0.04)",
          fontFamily: "'DM Sans', sans-serif",
          fontSize: 11, textTransform: "uppercase",
          letterSpacing: "0.15em", color: "var(--ink-dim)",
          fontWeight: 700,
        }}>
          <div>#</div><div>Player</div>
          <div style={{ textAlign: "right" }}>Wins</div>
          <div style={{ textAlign: "right" }}>Played</div>
          <div style={{ textAlign: "right" }}>Win %</div>
          <div style={{ textAlign: "right" }}>Points</div>
        </div>
        {sorted.map((p, i) => (
          <div key={p.name} style={{
            display: "grid",
            gridTemplateColumns: "60px 1fr 90px 90px 90px 100px",
            gap: 12, padding: "14px 24px",
            borderBottom: i < sorted.length - 1 ? "1px solid rgba(255,255,255,0.06)" : "none",
            alignItems: "center",
            fontFamily: "'DM Sans', sans-serif",
            color: "var(--ink)", fontSize: 15,
          }}>
            <div style={{
              fontFamily: "'Space Grotesk', sans-serif",
              fontWeight: 700, fontSize: 18,
              color: i < 3 ? "var(--yellow)" : "var(--ink-dim)",
            }}>{String(i + 1).padStart(2, "0")}</div>
            <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <Avatar name={p.name} color={p.color} size={36} />
              <span style={{ fontWeight: 600 }}>{p.name}</span>
            </div>
            <div style={{ textAlign: "right" }}>{p.wins}</div>
            <div style={{ textAlign: "right", color: "var(--ink-dim)" }}>{p.played}</div>
            <div style={{ textAlign: "right", color: "var(--ink-dim)", fontVariantNumeric: "tabular-nums" }}>{p.winRate}%</div>
            <div style={{ textAlign: "right", fontWeight: 700, color: "var(--yellow)", fontVariantNumeric: "tabular-nums" }}>
              {p.points.toLocaleString()}
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

function PodiumCard({ player, place, height, bg }) {
  if (!player) return null;
  return (
    <div style={{
      background: bg, color: "#0a0a0a",
      borderRadius: "var(--radius)",
      border: "3px solid var(--border)",
      boxShadow: "var(--card-shadow)",
      padding: 20, height,
      display: "flex", flexDirection: "column",
      justifyContent: "space-between",
      transform: place === 1 ? "translateY(-12px)" : "none",
    }}>
      <div style={{
        display: "flex", justifyContent: "space-between",
        alignItems: "flex-start",
      }}>
        <span style={{
          fontFamily: "'Space Grotesk', sans-serif",
          fontSize: 38, fontWeight: 800,
          letterSpacing: "-0.02em",
        }}>#{place}</span>
        <div style={{
          width: 44, height: 44, borderRadius: "50%",
          background: "#0a0a0a", color: player.color,
          display: "flex", alignItems: "center", justifyContent: "center",
          fontFamily: "'Space Grotesk', sans-serif",
          fontWeight: 800, fontSize: 18,
          border: "2px solid #0a0a0a",
        }}>{player.name[0].toUpperCase()}</div>
      </div>
      <div>
        <div style={{
          fontFamily: "'Space Grotesk', sans-serif",
          fontSize: 22, fontWeight: 700,
          marginBottom: 2,
        }}>{player.name}</div>
        <div style={{
          fontFamily: "'DM Sans', sans-serif", fontSize: 13,
          opacity: 0.75,
        }}>{player.wins} win{player.wins === 1 ? "" : "s"} · {player.played} game{player.played === 1 ? "" : "s"}</div>
      </div>
    </div>
  );
}

function StatStrip({ history, playerStats }) {
  const totalPoints = Object.values(playerStats).reduce((a, s) => a + s.points, 0);
  const activePlayers = Object.keys(playerStats).length;
  const latest = history[history.length - 1];
  const reigning = latest ? latest.winner.name : "—";
  const stats = [
    { label: "Games played", value: history.length, color: "var(--pink)" },
    { label: "Total points scored", value: totalPoints.toLocaleString(), color: "var(--yellow)" },
    { label: "Active players", value: activePlayers, color: "var(--teal)" },
    { label: "Reigning champion", value: reigning, color: "var(--lime)" },
  ];
  return (
    <section style={{ position: "relative", zIndex: 1, maxWidth: 1280, margin: "0 auto", padding: "0 32px" }}>
      <div style={{
        display: "grid",
        gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
        gap: 16,
      }}>
        {stats.map((s) => (
          <div key={s.label} style={{
            background: "rgba(255,255,255,0.04)",
            border: "2px solid var(--border)",
            borderRadius: "var(--radius)",
            padding: "20px 22px",
            position: "relative",
            overflow: "hidden",
          }}>
            <div style={{
              position: "absolute", top: 0, left: 0, right: 0, height: 4,
              background: s.color,
            }} />
            <div style={{
              fontFamily: "'DM Sans', sans-serif",
              fontSize: 12, textTransform: "uppercase",
              letterSpacing: "0.15em", color: "var(--ink-dim)",
              marginBottom: 8,
            }}>{s.label}</div>
            <div style={{
              fontFamily: "'Space Grotesk', sans-serif",
              fontSize: 32, fontWeight: 700, color: "var(--ink)",
              letterSpacing: "-0.02em",
            }}>{s.value}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

const GAME_BADGE = {
  "danish-500": { label: "500", color: "var(--pink)" },
  "backgammon": { label: "BG", color: "var(--teal)" },
  "shithead":   { label: "💩",  color: "var(--lime)" },
};

function recentScoreText(g) {
  if (g.game === "shithead") {
    const losses = (g.meta && g.meta.losses) || [];
    if (losses.length === 0) return `${g.meta?.rounds || 0} rounds`;
    return losses.map(l => l).join("–") + " losses";
  }
  if (g.game === "backgammon") {
    const [a, b] = g.finalScores || [0, 0];
    return `${a}–${b} (race to ${g.meta?.target || "?"})`;
  }
  // danish-500: show scores in finishing order (already sorted desc by score)
  const ordered = g.players
    .map((p, i) => ({ name: p.name, score: (g.finalScores || [])[i] || 0 }))
    .sort((a, b) => b.score - a.score);
  return ordered.map(o => o.score).join("–");
}

function recentPlayersText(g) {
  if (g.game === "danish-500") {
    return g.players
      .map((p, i) => ({ name: p.name, score: (g.finalScores || [])[i] || 0 }))
      .sort((a, b) => b.score - a.score)
      .map(o => o.name)
      .join(" · ");
  }
  return g.players.map(p => p.name).join(" · ");
}

function RecentGames({ history }) {
  const games = useMemo(() => [...history].reverse().slice(0, 8), [history]);

  return (
    <section id="players" style={{ position: "relative", zIndex: 1, maxWidth: 1280, margin: "0 auto", padding: "40px 32px" }}>
      <SectionTitle eyebrow="The chronicles" title="Recent Games" accent="var(--teal)" />
      {games.length === 0 ? (
        <div style={{
          marginTop: 32,
          background: "rgba(255,255,255,0.04)",
          border: "2px dashed rgba(255,255,255,0.2)",
          borderRadius: "var(--radius)",
          padding: 40, textAlign: "center",
        }}>
          <div style={{ fontFamily: "'Space Grotesk', sans-serif", fontSize: 20, fontWeight: 700, marginBottom: 6 }}>
            No games on record
          </div>
          <p style={{ fontFamily: "'DM Sans', sans-serif", color: "var(--ink-dim)", margin: 0 }}>
            Finish a game and it'll show up here.
          </p>
        </div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 12, marginTop: 32 }}>
          {games.map((g) => {
            const badge = GAME_BADGE[g.game] || { label: "?", color: "var(--ink-dim)" };
            return (
              <div key={g.id} style={{
                display: "grid",
                gridTemplateColumns: "auto 1fr auto auto",
                gap: 24,
                alignItems: "center",
                background: "rgba(255,255,255,0.04)",
                border: "2px solid var(--border)",
                borderRadius: "var(--radius)",
                padding: "16px 24px",
              }}>
                <div style={{
                  width: 56, height: 56, borderRadius: 16,
                  background: badge.color, color: "#0a0a0a",
                  border: "2px solid var(--border)",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  fontFamily: "'Space Grotesk', sans-serif",
                  fontWeight: 800, fontSize: 18,
                }}>{badge.label}</div>
                <div>
                  <div style={{
                    fontFamily: "'Space Grotesk', sans-serif",
                    fontSize: 18, fontWeight: 700, color: "var(--ink)",
                  }}>
                    {g.winner.name} won <span style={{ color: "var(--yellow)" }}>·</span> {g.players.length} player{g.players.length === 1 ? "" : "s"}
                  </div>
                  <div style={{
                    fontFamily: "'DM Sans', sans-serif",
                    fontSize: 13, color: "var(--ink-dim)", marginTop: 2,
                  }}>
                    {recentPlayersText(g)}
                  </div>
                </div>
                <div style={{
                  fontFamily: "'Space Grotesk', sans-serif",
                  fontSize: 16, fontWeight: 600, color: "var(--ink)",
                  fontVariantNumeric: "tabular-nums",
                }}>{recentScoreText(g)}</div>
                <div style={{
                  fontFamily: "'DM Sans', sans-serif",
                  fontSize: 13, color: "var(--ink-dim)",
                }}>{formatRelativeTime(g.finishedAt)}</div>
              </div>
            );
          })}
        </div>
      )}
    </section>
  );
}

function Footer() {
  return (
    <footer style={{
      position: "relative", zIndex: 1,
      maxWidth: 1280, margin: "0 auto",
      padding: "60px 32px 40px",
      borderTop: "2px solid rgba(255,255,255,0.08)",
      marginTop: 40,
      display: "flex", justifyContent: "space-between",
      alignItems: "center", flexWrap: "wrap", gap: 16,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
        <Mascot size={40} />
        <span style={{
          fontFamily: "'DM Sans', sans-serif",
          fontSize: 14, color: "var(--ink-dim)",
        }}>
          SvendeBanan · made with ♥ for the family
        </span>
      </div>
      <span style={{
        fontFamily: "'DM Sans', sans-serif", fontSize: 13,
        color: "var(--ink-dim)",
      }}>
        © 2026 · v1.0
      </span>
    </footer>
  );
}

function App() {
  // ALL hooks must be called unconditionally on every render — no early
  // returns above this block. The onboarding gate is rendered conditionally
  // *after* all the useState/useMemo/useEffect calls.
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [history, setHistoryState] = useHistory();
  const { user, currentFamily, refresh: refreshFamily } = useFamily();

  useEffect(() => {
    applyTheme(tweaks.theme);
  }, [tweaks.theme]);

  const playerStats = useMemo(() => getPlayerStats(history), [history]);
  const lastByGame = useMemo(() => lastPlayedByGame(history), [history]);

  const resetHistory = () => {
    if (confirm("Erase all recorded game history? In-progress games on each scorekeeper page are kept.")) {
      setHistory([]);
      setHistoryState([]);
    }
  };

  // Signed-in but no family yet → show onboarding gate.
  if (user && !currentFamily) {
    return <FamilyOnboarding onJoined={refreshFamily} />;
  }

  return (
    <div style={{
      minHeight: "100vh",
      background: "var(--bg)",
      color: "var(--ink)",
      position: "relative",
    }}>
      <ConfettiBg count={50} seed={7} />
      <Header active="home" family={currentFamily} />
      <Hero history={history} playerStats={playerStats} family={currentFamily} />
      <GamesGrid lastByGame={lastByGame} />
      {tweaks.showStats && <StatStrip history={history} playerStats={playerStats} />}
      {tweaks.showLeaderboard && <Leaderboard playerStats={playerStats} />}
      {tweaks.showRecent && <RecentGames history={history} />}
      <Footer />

      <TweaksPanel title="Tweaks">
        <TweakSection title="Visual direction">
          <TweakSelect
            label="Theme"
            value={tweaks.theme}
            options={[
              { value: "arcade", label: "Arcade Pop (default)" },
              { value: "neobrutal", label: "Neo Brutal (light)" },
              { value: "candy", label: "Soft Candy" },
            ]}
            onChange={(v) => setTweak("theme", v)}
          />
        </TweakSection>
        <TweakSection title="Sections">
          <TweakToggle
            label="Show stats strip"
            value={tweaks.showStats}
            onChange={(v) => setTweak("showStats", v)}
          />
          <TweakToggle
            label="Show leaderboard"
            value={tweaks.showLeaderboard}
            onChange={(v) => setTweak("showLeaderboard", v)}
          />
          <TweakToggle
            label="Show recent games"
            value={tweaks.showRecent}
            onChange={(v) => setTweak("showRecent", v)}
          />
        </TweakSection>
        <TweakSection title="Data">
          <TweakButton label={`Reset history (${history.length})`} secondary onClick={resetHistory} />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

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