/* Total Degeneracy – WC2026 Pick'Em Pool  (server-backed) */
const { useState, useEffect, useRef } = React;

/* ═══════════════════════════════════════════════
   PLAYER THEMES
═══════════════════════════════════════════════ */
const PLAYER_THEMES = {
  Martin:  { emoji:"🍀", label:"The Leprechaun",    bg:"linear-gradient(160deg,#1a4a1a,#0d2e0d)", border:"#3daa3d", accent:"#7fe87f", shadow:"rgba(61,170,61,0.5)",    textColor:"#b8ffb8", tagline:"Top o' the mornin'",         pattern:"radial-gradient(circle at 20% 80%,rgba(61,170,61,0.15) 0%,transparent 50%)" },
  Gaston:  { emoji:"🎣", label:"Cuban Fisherman",   bg:"linear-gradient(160deg,#0a2a4a,#1a1a00)", border:"#c8a020", accent:"#f0c850", shadow:"rgba(200,160,32,0.5)",   textColor:"#ffd87a", tagline:"El pescador de La Habana",    pattern:"radial-gradient(circle at 80% 20%,rgba(200,160,32,0.12) 0%,transparent 50%)" },
  Chuck:   { emoji:"☭",  label:"1950s Communist",   bg:"linear-gradient(160deg,#5a0000,#2a0000)", border:"#ff3030", accent:"#ffcc00", shadow:"rgba(255,48,48,0.5)",    textColor:"#ffcc00", tagline:"For the proletariat!",        pattern:"radial-gradient(circle at 50% 50%,rgba(255,48,48,0.1) 0%,transparent 60%)" },
  Jim:     { emoji:"🦌", label:"Upstate NY",         bg:"linear-gradient(160deg,#1a2a3a,#2a1a0a)", border:"#a06020", accent:"#e88030", shadow:"rgba(160,96,32,0.5)",   textColor:"#f0b070", tagline:"Finger Lakes represent",       pattern:"radial-gradient(circle at 30% 70%,rgba(160,96,32,0.15) 0%,transparent 50%)" },
  Josh:    { emoji:"👑", label:"Biggie Smalls",      bg:"linear-gradient(160deg,#1a0a2a,#0a0a1a)", border:"#aa60ff", accent:"#cc88ff", shadow:"rgba(170,96,255,0.5)",  textColor:"#ddaaff", tagline:"It was all a dream",          pattern:"radial-gradient(circle at 60% 30%,rgba(170,96,255,0.15) 0%,transparent 50%)" },
  Richard: { emoji:"🐊", label:"Crocodile Dundee",  bg:"linear-gradient(160deg,#2a1a00,#1a2a0a)", border:"#8aaa20", accent:"#c8e040", shadow:"rgba(138,170,32,0.5)",  textColor:"#d8f060", tagline:"That's not a knife…",         pattern:"radial-gradient(circle at 70% 60%,rgba(138,170,32,0.15) 0%,transparent 50%)" },
};

/* ═══════════════════════════════════════════════
   CONSTANTS
═══════════════════════════════════════════════ */
const PLAYERS = ["Josh","Martin","Gaston","Jim","Chuck","Richard"];
const TOURNAMENT_START = new Date("2026-06-11T16:00:00-04:00");

const SCORING = {
  group: {result:3}, r32:{winner:3,method:2}, r16:{winner:5,method:3},
  qf:{winner:7,method:4}, sf:{winner:10,method:5}, final:{winner:13,method:8}, golden:10,
};
const ROUNDS = [
  {id:"group",label:"Group Stage"},{id:"r32",label:"Round of 32"},
  {id:"r16",label:"Round of 16"},{id:"qf",label:"Quarterfinals"},
  {id:"sf",label:"Semifinals"},{id:"final",label:"Final"},
];

/* ═══════════════════════════════════════════════
   SCHEDULE
═══════════════════════════════════════════════ */
const GROUP_GAMES = [
  {id:"g1", home:"Mexico",      away:"South Africa", group:"A",kickoff:"2026-06-11T15:00:00-04:00"},
  {id:"g2", home:"South Korea", away:"Czechia",      group:"A",kickoff:"2026-06-11T22:00:00-04:00"},
  {id:"g3", home:"Czechia",     away:"South Africa", group:"A",kickoff:"2026-06-18T12:00:00-04:00"},
  {id:"g4", home:"Mexico",      away:"South Korea",  group:"A",kickoff:"2026-06-18T15:00:00-04:00"},
  {id:"g5", home:"Mexico",      away:"Czechia",      group:"A",kickoff:"2026-06-22T16:00:00-04:00"},
  {id:"g6", home:"South Africa",away:"South Korea",  group:"A",kickoff:"2026-06-22T16:00:00-04:00"},
  {id:"g7", home:"Canada",      away:"Bosnia-Herz.", group:"B",kickoff:"2026-06-12T15:00:00-04:00"},
  {id:"g8", home:"Qatar",       away:"Switzerland",  group:"B",kickoff:"2026-06-12T15:00:00-04:00"},
  {id:"g9", home:"Switzerland", away:"Bosnia-Herz.", group:"B",kickoff:"2026-06-19T12:00:00-04:00"},
  {id:"g10",home:"Canada",      away:"Qatar",        group:"B",kickoff:"2026-06-19T18:00:00-04:00"},
  {id:"g11",home:"Canada",      away:"Switzerland",  group:"B",kickoff:"2026-06-23T16:00:00-04:00"},
  {id:"g12",home:"Bosnia-Herz.",away:"Qatar",        group:"B",kickoff:"2026-06-23T16:00:00-04:00"},
  {id:"g13",home:"Brazil",      away:"Morocco",      group:"C",kickoff:"2026-06-13T15:00:00-04:00"},
  {id:"g14",home:"Haiti",       away:"Scotland",     group:"C",kickoff:"2026-06-13T21:00:00-04:00"},
  {id:"g15",home:"Brazil",      away:"Haiti",        group:"C",kickoff:"2026-06-20T12:00:00-04:00"},
  {id:"g16",home:"Scotland",    away:"Morocco",      group:"C",kickoff:"2026-06-20T15:00:00-04:00"},
  {id:"g17",home:"Brazil",      away:"Scotland",     group:"C",kickoff:"2026-06-24T20:00:00-04:00"},
  {id:"g18",home:"Morocco",     away:"Haiti",        group:"C",kickoff:"2026-06-24T20:00:00-04:00"},
  {id:"g19",home:"USA",         away:"Paraguay",     group:"D",kickoff:"2026-06-12T21:00:00-04:00"},
  {id:"g20",home:"Australia",   away:"Turkey",       group:"D",kickoff:"2026-06-13T18:00:00-04:00"},
  {id:"g21",home:"Turkey",      away:"Paraguay",     group:"D",kickoff:"2026-06-19T12:00:00-04:00"},
  {id:"g22",home:"USA",         away:"Australia",    group:"D",kickoff:"2026-06-19T15:00:00-04:00"},
  {id:"g23",home:"Turkey",      away:"USA",          group:"D",kickoff:"2026-06-25T22:00:00-04:00"},
  {id:"g24",home:"Paraguay",    away:"Australia",    group:"D",kickoff:"2026-06-25T15:00:00-04:00"},
  {id:"g25",home:"Germany",     away:"Curacao",      group:"E",kickoff:"2026-06-14T16:00:00-04:00"},
  {id:"g26",home:"Ivory Coast", away:"Ecuador",      group:"E",kickoff:"2026-06-14T19:00:00-04:00"},
  {id:"g27",home:"Germany",     away:"Ivory Coast",  group:"E",kickoff:"2026-06-20T13:00:00-04:00"},
  {id:"g28",home:"Ecuador",     away:"Curacao",      group:"E",kickoff:"2026-06-20T00:00:00-04:00"},
  {id:"g29",home:"Ecuador",     away:"Germany",      group:"E",kickoff:"2026-06-25T19:00:00-04:00"},
  {id:"g30",home:"Curacao",     away:"Ivory Coast",  group:"E",kickoff:"2026-06-25T19:00:00-04:00"},
  {id:"g31",home:"Netherlands", away:"Japan",        group:"F",kickoff:"2026-06-14T16:00:00-04:00"},
  {id:"g32",home:"Sweden",      away:"Tunisia",      group:"F",kickoff:"2026-06-14T22:00:00-04:00"},
  {id:"g33",home:"Netherlands", away:"Sweden",       group:"F",kickoff:"2026-06-20T13:00:00-04:00"},
  {id:"g34",home:"Tunisia",     away:"Japan",        group:"F",kickoff:"2026-06-20T00:00:00-04:00"},
  {id:"g35",home:"Tunisia",     away:"Netherlands",  group:"F",kickoff:"2026-06-25T19:00:00-04:00"},
  {id:"g36",home:"Japan",       away:"Sweden",       group:"F",kickoff:"2026-06-25T19:00:00-04:00"},
  {id:"g37",home:"Belgium",     away:"Egypt",        group:"G",kickoff:"2026-06-15T18:00:00-04:00"},
  {id:"g38",home:"Iran",        away:"New Zealand",  group:"G",kickoff:"2026-06-15T00:00:00-04:00"},
  {id:"g39",home:"Belgium",     away:"Iran",         group:"G",kickoff:"2026-06-21T15:00:00-04:00"},
  {id:"g40",home:"New Zealand", away:"Egypt",        group:"G",kickoff:"2026-06-21T18:00:00-04:00"},
  {id:"g41",home:"New Zealand", away:"Belgium",      group:"G",kickoff:"2026-06-26T16:00:00-04:00"},
  {id:"g42",home:"Egypt",       away:"Iran",         group:"G",kickoff:"2026-06-26T16:00:00-04:00"},
  {id:"g43",home:"Spain",       away:"Cape Verde",   group:"H",kickoff:"2026-06-15T13:00:00-04:00"},
  {id:"g44",home:"Saudi Arabia",away:"Uruguay",      group:"H",kickoff:"2026-06-15T18:00:00-04:00"},
  {id:"g45",home:"Spain",       away:"Saudi Arabia", group:"H",kickoff:"2026-06-21T19:00:00-04:00"},
  {id:"g46",home:"Uruguay",     away:"Cape Verde",   group:"H",kickoff:"2026-06-21T22:00:00-04:00"},
  {id:"g47",home:"Uruguay",     away:"Spain",        group:"H",kickoff:"2026-06-26T20:00:00-04:00"},
  {id:"g48",home:"Cape Verde",  away:"Saudi Arabia", group:"H",kickoff:"2026-06-26T20:00:00-04:00"},
  {id:"g49",home:"France",      away:"Senegal",      group:"I",kickoff:"2026-06-16T15:00:00-04:00"},
  {id:"g50",home:"Iraq",        away:"Norway",       group:"I",kickoff:"2026-06-16T18:00:00-04:00"},
  {id:"g51",home:"France",      away:"Iraq",         group:"I",kickoff:"2026-06-22T15:00:00-04:00"},
  {id:"g52",home:"Norway",      away:"Senegal",      group:"I",kickoff:"2026-06-22T18:00:00-04:00"},
  {id:"g53",home:"Norway",      away:"France",       group:"I",kickoff:"2026-06-26T16:00:00-04:00"},
  {id:"g54",home:"Senegal",     away:"Iraq",         group:"I",kickoff:"2026-06-26T16:00:00-04:00"},
  {id:"g55",home:"Argentina",   away:"Algeria",      group:"J",kickoff:"2026-06-16T21:00:00-04:00"},
  {id:"g56",home:"Austria",     away:"Jordan",       group:"J",kickoff:"2026-06-17T00:00:00-04:00"},
  {id:"g57",home:"Argentina",   away:"Austria",      group:"J",kickoff:"2026-06-22T21:00:00-04:00"},
  {id:"g58",home:"Jordan",      away:"Algeria",      group:"J",kickoff:"2026-06-23T00:00:00-04:00"},
  {id:"g59",home:"Argentina",   away:"Jordan",       group:"J",kickoff:"2026-06-27T16:00:00-04:00"},
  {id:"g60",home:"Algeria",     away:"Austria",      group:"J",kickoff:"2026-06-27T16:00:00-04:00"},
  {id:"g61",home:"Portugal",    away:"DR Congo",     group:"K",kickoff:"2026-06-17T13:00:00-04:00"},
  {id:"g62",home:"Uzbekistan",  away:"Colombia",     group:"K",kickoff:"2026-06-17T22:00:00-04:00"},
  {id:"g63",home:"Portugal",    away:"Uzbekistan",   group:"K",kickoff:"2026-06-23T15:00:00-04:00"},
  {id:"g64",home:"Colombia",    away:"DR Congo",     group:"K",kickoff:"2026-06-23T18:00:00-04:00"},
  {id:"g65",home:"Portugal",    away:"Colombia",     group:"K",kickoff:"2026-06-27T20:00:00-04:00"},
  {id:"g66",home:"DR Congo",    away:"Uzbekistan",   group:"K",kickoff:"2026-06-27T20:00:00-04:00"},
  {id:"g67",home:"England",     away:"Croatia",      group:"L",kickoff:"2026-06-17T16:00:00-04:00"},
  {id:"g68",home:"Ghana",       away:"Panama",       group:"L",kickoff:"2026-06-17T19:00:00-04:00"},
  {id:"g69",home:"England",     away:"Ghana",        group:"L",kickoff:"2026-06-23T21:00:00-04:00"},
  {id:"g70",home:"Panama",      away:"Croatia",      group:"L",kickoff:"2026-06-24T00:00:00-04:00"},
  {id:"g71",home:"England",     away:"Panama",       group:"L",kickoff:"2026-06-27T16:00:00-04:00"},
  {id:"g72",home:"Croatia",     away:"Ghana",        group:"L",kickoff:"2026-06-27T16:00:00-04:00"},
];

const KNOCKOUT_ROUNDS = {
  r32:[
    {id:"r32_1", label:"R32 Match 1",  home:"TBD",away:"TBD",kickoff:"2026-06-28T15:00:00-04:00"},
    {id:"r32_2", label:"R32 Match 2",  home:"TBD",away:"TBD",kickoff:"2026-06-28T19:00:00-04:00"},
    {id:"r32_3", label:"R32 Match 3",  home:"TBD",away:"TBD",kickoff:"2026-06-29T15:00:00-04:00"},
    {id:"r32_4", label:"R32 Match 4",  home:"TBD",away:"TBD",kickoff:"2026-06-29T19:00:00-04:00"},
    {id:"r32_5", label:"R32 Match 5",  home:"TBD",away:"TBD",kickoff:"2026-06-30T15:00:00-04:00"},
    {id:"r32_6", label:"R32 Match 6",  home:"TBD",away:"TBD",kickoff:"2026-06-30T19:00:00-04:00"},
    {id:"r32_7", label:"R32 Match 7",  home:"TBD",away:"TBD",kickoff:"2026-07-01T15:00:00-04:00"},
    {id:"r32_8", label:"R32 Match 8",  home:"TBD",away:"TBD",kickoff:"2026-07-01T19:00:00-04:00"},
    {id:"r32_9", label:"R32 Match 9",  home:"TBD",away:"TBD",kickoff:"2026-07-02T15:00:00-04:00"},
    {id:"r32_10",label:"R32 Match 10", home:"TBD",away:"TBD",kickoff:"2026-07-02T19:00:00-04:00"},
    {id:"r32_11",label:"R32 Match 11", home:"TBD",away:"TBD",kickoff:"2026-07-03T15:00:00-04:00"},
    {id:"r32_12",label:"R32 Match 12", home:"TBD",away:"TBD",kickoff:"2026-07-03T19:00:00-04:00"},
    {id:"r32_13",label:"R32 Match 13", home:"TBD",away:"TBD",kickoff:"2026-07-04T15:00:00-04:00"},
    {id:"r32_14",label:"R32 Match 14", home:"TBD",away:"TBD",kickoff:"2026-07-04T19:00:00-04:00"},
    {id:"r32_15",label:"R32 Match 15", home:"TBD",away:"TBD",kickoff:"2026-07-05T15:00:00-04:00"},
    {id:"r32_16",label:"R32 Match 16", home:"TBD",away:"TBD",kickoff:"2026-07-05T19:00:00-04:00"},
  ],
  r16:[
    {id:"r16_1",label:"R16 Match 1",home:"TBD",away:"TBD",kickoff:"2026-07-06T15:00:00-04:00"},
    {id:"r16_2",label:"R16 Match 2",home:"TBD",away:"TBD",kickoff:"2026-07-06T19:00:00-04:00"},
    {id:"r16_3",label:"R16 Match 3",home:"TBD",away:"TBD",kickoff:"2026-07-07T15:00:00-04:00"},
    {id:"r16_4",label:"R16 Match 4",home:"TBD",away:"TBD",kickoff:"2026-07-07T19:00:00-04:00"},
    {id:"r16_5",label:"R16 Match 5",home:"TBD",away:"TBD",kickoff:"2026-07-08T15:00:00-04:00"},
    {id:"r16_6",label:"R16 Match 6",home:"TBD",away:"TBD",kickoff:"2026-07-08T19:00:00-04:00"},
    {id:"r16_7",label:"R16 Match 7",home:"TBD",away:"TBD",kickoff:"2026-07-09T15:00:00-04:00"},
    {id:"r16_8",label:"R16 Match 8",home:"TBD",away:"TBD",kickoff:"2026-07-09T19:00:00-04:00"},
  ],
  qf:[
    {id:"qf_1",label:"QF Match 1",home:"TBD",away:"TBD",kickoff:"2026-07-11T15:00:00-04:00"},
    {id:"qf_2",label:"QF Match 2",home:"TBD",away:"TBD",kickoff:"2026-07-11T19:00:00-04:00"},
    {id:"qf_3",label:"QF Match 3",home:"TBD",away:"TBD",kickoff:"2026-07-12T15:00:00-04:00"},
    {id:"qf_4",label:"QF Match 4",home:"TBD",away:"TBD",kickoff:"2026-07-12T19:00:00-04:00"},
  ],
  sf:[
    {id:"sf_1",label:"SF Match 1",home:"TBD",away:"TBD",kickoff:"2026-07-14T19:00:00-04:00"},
    {id:"sf_2",label:"SF Match 2",home:"TBD",away:"TBD",kickoff:"2026-07-15T19:00:00-04:00"},
  ],
  final:[
    {id:"final_1",label:"The Final",home:"TBD",away:"TBD",kickoff:"2026-07-19T15:00:00-04:00"},
  ],
};

const GOLDEN_BOOT_CANDIDATES = [
  "Kylian Mbappé","Erling Haaland","Vinicius Jr.","Lionel Messi",
  "Harry Kane","Lamine Yamal","Jude Bellingham","Cristiano Ronaldo",
  "Pedri","Bukayo Saka","Phil Foden","Antoine Griezmann",
  "Darwin Núñez","Richarlison","Cody Gakpo","Lautaro Martínez",
  "Achraf Hakimi","Sadio Mané","Romelu Lukaku","Dušan Vlahović",
  "Rasmus Højlund","Leroy Sané","Memphis Depay","Hirving Lozano",
  "Alexis Vega","Cyle Larin","Andy Robertson","Robert Lewandowski",
];
const METHOD_OPTIONS = [{value:"90",label:"90 min"},{value:"aet",label:"Extra Time"},{value:"pens",label:"Penalties"}];

const FLAGS = {
  "Mexico":"🇲🇽","South Africa":"🇿🇦","South Korea":"🇰🇷","Czechia":"🇨🇿",
  "Canada":"🇨🇦","Bosnia-Herz.":"🇧🇦","Qatar":"🇶🇦","Switzerland":"🇨🇭",
  "Brazil":"🇧🇷","Morocco":"🇲🇦","Haiti":"🇭🇹","Scotland":"🏴󠁧󠁢󠁳󠁣󠁴󠁿",
  "USA":"🇺🇸","Paraguay":"🇵🇾","Australia":"🇦🇺","Turkey":"🇹🇷",
  "Germany":"🇩🇪","Curacao":"🇨🇼","Ivory Coast":"🇨🇮","Ecuador":"🇪🇨",
  "Netherlands":"🇳🇱","Japan":"🇯🇵","Sweden":"🇸🇪","Tunisia":"🇹🇳",
  "Belgium":"🇧🇪","Egypt":"🇪🇬","Iran":"🇮🇷","New Zealand":"🇳🇿",
  "Spain":"🇪🇸","Cape Verde":"🇨🇻","Saudi Arabia":"🇸🇦","Uruguay":"🇺🇾",
  "France":"🇫🇷","Senegal":"🇸🇳","Iraq":"🇮🇶","Norway":"🇳🇴",
  "Argentina":"🇦🇷","Algeria":"🇩🇿","Austria":"🇦🇹","Jordan":"🇯🇴",
  "Portugal":"🇵🇹","DR Congo":"🇨🇩","Uzbekistan":"🇺🇿","Colombia":"🇨🇴",
  "England":"🏴󠁧󠁢󠁥󠁮󠁧󠁿","Croatia":"🇭🇷","Ghana":"🇬🇭","Panama":"🇵🇦","TBD":"⚽",
};
const fl = t => FLAGS[t] || "🏳️";

/* ═══════════════════════════════════════════════
   HELPERS
═══════════════════════════════════════════════ */
function gameDeadline(game) {
  if (!game.kickoff) return null;
  return new Date(new Date(game.kickoff).getTime() - 30*60*1000);
}
function isGameLocked(game) {
  const dl = gameDeadline(game);
  return dl ? new Date() >= dl : false;
}
function goldenBootLocked() { return new Date() >= TOURNAMENT_START; }
function isKoRoundOpen(rid)  { return (KNOCKOUT_ROUNDS[rid]||[]).some(g => !isGameLocked(g)); }
function isLocked(rid) {
  if (rid==="group") return GROUP_GAMES.every(g => isGameLocked(g));
  return !isKoRoundOpen(rid);
}
function fmtDeadline(game) {
  const dl = gameDeadline(game); if (!dl) return null;
  return dl.toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",timeZoneName:"short",hour12:true});
}
function fmtTimestamp(iso) {
  if (!iso) return null;
  return new Date(iso).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit",timeZoneName:"short",hour12:true});
}
function resolveGame(game, liveFixtures) {
  const live = liveFixtures && liveFixtures[game.id];
  if (!live) return game;
  return {...game, home:live.home||game.home, away:live.away||game.away, kickoff:live.kickoff||game.kickoff};
}
function getLocalClaim() {
  try { return JSON.parse(localStorage.getItem("wc26_claim")||"null"); } catch { return null; }
}
function setLocalClaim(name, code) {
  try { localStorage.setItem("wc26_claim", JSON.stringify({name,code})); } catch {}
}
function genCode() { return String(Math.floor(1000+Math.random()*9000)); }

function calcScore(player, picks, results, goldenBoot) {
  let score = 0;
  const pp = picks[player]||{};
  GROUP_GAMES.forEach(g => {
    const pick=pp[g.id], res=results[g.id];
    if (pick&&res&&pick.result===res.result) score+=SCORING.group.result;
  });
  ["r32","r16","qf","sf","final"].forEach(rid => {
    const sc=SCORING[rid];
    (KNOCKOUT_ROUNDS[rid]||[]).forEach(g => {
      const pick=pp[g.id], res=results[g.id];
      if (!pick||!res) return;
      if (pick.winner===res.winner) { score+=sc.winner; if (pick.method===res.method) score+=sc.method; }
    });
  });
  const gb=goldenBoot[player];
  if (gb&&results.goldenBoot&&gb===results.goldenBoot) score+=SCORING.golden;
  return score;
}
function calcBreakdown(player, picks, results, goldenBoot) {
  const pp=picks[player]||{};
  const bd={group:0,r32:0,r16:0,qf:0,sf:0,final:0,golden:0};
  GROUP_GAMES.forEach(g => {
    const pick=pp[g.id], res=results[g.id];
    if (pick&&res&&pick.result===res.result) bd.group+=SCORING.group.result;
  });
  ["r32","r16","qf","sf","final"].forEach(rid => {
    const sc=SCORING[rid];
    (KNOCKOUT_ROUNDS[rid]||[]).forEach(g => {
      const pick=pp[g.id], res=results[g.id];
      if (!pick||!res) return;
      if (pick.winner===res.winner) { bd[rid]+=sc.winner; if (pick.method===res.method) bd[rid]+=sc.method; }
    });
  });
  const gb=goldenBoot[player];
  if (gb&&results.goldenBoot&&gb===results.goldenBoot) bd.golden+=SCORING.golden;
  return bd;
}

/* ═══════════════════════════════════════════════
   SERVER API  (replaces localStorage)
═══════════════════════════════════════════════ */
async function loadAll() {
  const claim = getLocalClaim();
  const qs = claim ? `?player=${encodeURIComponent(claim.name)}&pin=${encodeURIComponent(claim.code)}` : "";
  try {
    const r = await fetch("/api/state"+qs);
    if (!r.ok) throw new Error("api");
    return r.json();
  } catch { return {picks:{},results:{},goldenBoot:{},claims:{},liveFixtures:{}}; }
}

/* ═══════════════════════════════════════════════
   APP ROOT
═══════════════════════════════════════════════ */
function App() {
  const [view,setView]               = useState("home");
  const [activePlayer,setActivePlayer] = useState(null);
  const [activeRound,setActiveRound] = useState("group");
  const [data,setData]               = useState({picks:{},results:{},goldenBoot:{},claims:{},liveFixtures:{}});
  const [saving,setSaving]           = useState(false);
  const [adminMode,setAdminMode]     = useState(false);
  const [adminKey,setAdminKey]       = useState("");
  const [toast,setToast]             = useState(null);
  const [localPicks,setLocalPicks]   = useState({});
  const [localGolden,setLocalGolden] = useState("");
  const [showRules,setShowRules]     = useState(false);
  const [claimModal,setClaimModal]   = useState(null);
  const [claimInput,setClaimInput]   = useState("");
  const [localClaim,setLocalClaimState] = useState(() => getLocalClaim());
  const [confirmSave,setConfirmSave] = useState(false);

  useEffect(() => { loadAll().then(setData); }, []);

  function notify(msg,type="ok") {
    setToast({msg,type}); setTimeout(()=>setToast(null),3000);
  }

  function handlePlayerTap(name) {
    const alreadyClaimed = !!(data.claims&&data.claims[name]);
    if (localClaim&&localClaim.name===name) { doEnterPlayer(name); return; }
    setClaimInput("");
    setClaimModal({mode: alreadyClaimed ? "verify" : "choose", name});
  }

  async function handleClaimNew(name) {
    const code = genCode();
    try {
      const r = await fetch("/api/claim",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({player:name,pin:code})});
      if (!r.ok) { const e=await r.json().catch(()=>{}); notify(e?.error||"Claim failed","err"); return; }
      const nd = await r.json();
      setData(nd);
      setLocalClaim(name,code); setLocalClaimState({name,code});
      setClaimModal({mode:"show",name,code});
    } catch { notify("Network error","err"); }
  }

  async function handleVerifyCode(name) {
    try {
      const r = await fetch("/api/verify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({player:name,pin:claimInput.trim()})});
      if (!r.ok) { notify("Wrong code ✗","err"); return; }
      const nd = await r.json();
      setData(nd);
      setLocalClaim(name,claimInput.trim()); setLocalClaimState({name,code:claimInput.trim()});
      setClaimModal(null); doEnterPlayer(name);
    } catch { notify("Network error","err"); }
  }

  function doEnterPlayer(name) {
    setActivePlayer(name);
    setLocalPicks({...(data.picks[name]||{})});
    setLocalGolden(data.goldenBoot[name]||"");
    setActiveRound("group");
    setClaimModal(null);
    setView("picks");
  }

  function savePicks() {
    if (isLocked(activeRound)) { notify("This round is locked 🔒","err"); return; }
    setConfirmSave(true);
  }

  async function doSavePicks() {
    setConfirmSave(false); setSaving(true);
    const claim = getLocalClaim();
    if (!claim||claim.name!==activePlayer) { notify("Session mismatch — re-select your name","err"); setSaving(false); return; }
    try {
      const r = await fetch("/api/picks",{method:"POST",headers:{"Content-Type":"application/json"},
        body:JSON.stringify({player:activePlayer,pin:claim.code,picks:localPicks,goldenBoot:localGolden,round:activeRound})});
      if (!r.ok) { const e=await r.json().catch(()=>{}); notify(e?.error||"Save failed","err"); setSaving(false); return; }
      const nd = await r.json(); setData(nd); notify("Picks saved ✓");
    } catch { notify("Network error","err"); }
    setSaving(false);
  }

  async function saveResultsBatch(newResults) {
    try {
      const r = await fetch("/api/admin/results",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({adminKey,results:newResults})});
      if (!r.ok) { const e=await r.json().catch(()=>{}); notify(e?.error||"Save failed","err"); return; }
      setData(await r.json());
    } catch { notify("Network error","err"); }
  }

  async function saveResult(id,obj) { await saveResultsBatch({[id]:obj}); }

  async function saveFixturesBatch(newFixtures) {
    try {
      const r = await fetch("/api/admin/fixtures",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({adminKey,fixtures:newFixtures})});
      if (!r.ok) { notify("Save failed","err"); return; }
      setData(await r.json());
    } catch { notify("Network error","err"); }
  }

  const scores = PLAYERS.map(p=>({name:p,score:calcScore(p,data.picks,data.results,data.goldenBoot)})).sort((a,b)=>b.score-a.score);
  const daysLeft = Math.max(0,Math.ceil((TOURNAMENT_START-new Date())/86400000));

  return (
    <div style={S.root}>
      <div style={S.confettiBg}/>
      <div style={S.orb1}/><div style={S.orb2}/><div style={S.orb3}/>

      {toast&&<div style={{...S.toast,background:toast.type==="err"?"#c0392b":"#1a7a3a"}}>{toast.msg}</div>}
      {showRules&&<RulesModal onClose={()=>setShowRules(false)}/>}
      {claimModal&&(
        <ClaimModal modal={claimModal} claimInput={claimInput} setClaimInput={setClaimInput}
          onClose={()=>setClaimModal(null)} onClaimNew={handleClaimNew}
          onVerify={handleVerifyCode} onEnter={doEnterPlayer} localClaim={localClaim}/>
      )}
      {confirmSave&&(
        <ConfirmSaveModal player={activePlayer} round={activeRound} localPicks={localPicks}
          localGolden={localGolden} onConfirm={doSavePicks} onCancel={()=>setConfirmSave(false)}/>
      )}

      <header style={S.header}>
        <div style={S.headerInner}>
          <div style={S.brand} onClick={()=>setView("home")}>
            <div style={S.brandBall}>⚽</div>
            <div>
              <div style={S.brandTitle}>TOTAL DEGENERACY</div>
              <div style={S.brandSub}>World Cup 2026 · Pick'Em Pool</div>
            </div>
          </div>
          <div style={S.headerRight}>
            <button style={S.rulesBtn} onClick={()=>setShowRules(true)}>📋 Rules</button>
            <nav style={S.nav}>
              {[["home","Home"],["leaderboard","Standings"],["reveal","Picks"],["admin","Admin"]].map(([v,l])=>(
                <button key={v} style={{...S.navBtn,...(view===v?S.navActive:{})}} onClick={()=>setView(v)}>{l}</button>
              ))}
            </nav>
          </div>
        </div>
      </header>

      <main style={S.main}>
        {view==="home"&&<HomeView players={PLAYERS} onSelect={handlePlayerTap} scores={scores} daysLeft={daysLeft} localClaim={localClaim}/>}
        {view==="picks"&&activePlayer&&(
          <PicksView player={activePlayer} activeRound={activeRound} setActiveRound={setActiveRound}
            localPicks={localPicks}
            setGroupPick={(id,r)=>setLocalPicks(p=>({...p,[id]:{result:r,_savedAt:new Date().toISOString()}}))}
            setKoPick={(id,fld,val)=>setLocalPicks(p=>({...p,[id]:{...(p[id]||{}),[fld]:val}}))}
            localGolden={localGolden} setLocalGolden={setLocalGolden}
            onSave={savePicks} saving={saving} data={data} onBack={()=>setView("home")}
            savedAt={data.savedAt||{}} liveFixtures={data.liveFixtures||{}}/>
        )}
        {view==="leaderboard"&&<LeaderboardView scores={scores} data={data}/>}
        {view==="reveal"&&<PicksRevealView data={data} liveFixtures={data.liveFixtures||{}}/>}
        {view==="admin"&&(
          <AdminView adminMode={adminMode} adminKey={adminKey} setAdminKey={setAdminKey}
            setAdminMode={setAdminMode} data={data} saveResult={saveResult}
            saveResultsBatch={saveResultsBatch} saveFixturesBatch={saveFixturesBatch}
            notify={notify} setData={setData}/>
        )}
      </main>
    </div>
  );
}

/* ═══════════════════════════════════════════════
   HOME VIEW
═══════════════════════════════════════════════ */
function HomeView({players,onSelect,scores,daysLeft,localClaim}) {
  return (
    <div style={S.homeWrap}>
      <div style={S.heroSection}>
        <div style={S.heroTitle}>🏆 WORLD CUP 2026</div>
        <div style={S.heroSub}>104 games. 6 degenerates. One champion.</div>
        {daysLeft>0
          ? <div style={S.heroCountdown}>Tournament starts in <strong style={{color:"#ffcc44"}}>{daysLeft} day{daysLeft!==1?"s":""}</strong></div>
          : <div style={S.heroCountdown}>🔴 <strong style={{color:"#ff6644"}}>Tournament is LIVE</strong></div>
        }
      </div>
      {scores.some(s=>s.score>0)&&(
        <div style={S.miniLeader}>
          <div style={S.sectionLabel}>CURRENT STANDINGS</div>
          <div style={S.miniLeaderGrid}>
            {scores.map((s,i)=>{
              const theme=PLAYER_THEMES[s.name]||{};
              return (
                <div key={s.name} style={{...S.miniLeaderCard,border:`1px solid ${theme.border}44`}}>
                  <span style={{color:"#ffcc44",minWidth:20,fontWeight:"bold"}}>{i===0?"🥇":i===1?"🥈":i===2?"🥉":`${i+1}.`}</span>
                  <span style={{color:theme.accent}}>{theme.emoji} {s.name}</span>
                  <span style={{color:"#aaa",marginLeft:"auto",fontWeight:"bold"}}>{s.score}pts</span>
                </div>
              );
            })}
          </div>
        </div>
      )}
      <div style={S.sectionLabel}>SELECT YOUR NAME TO ENTER PICKS</div>
      <div style={S.playerGrid}>
        {players.map(name=>(
          <PlayerCard key={name} name={name} score={scores.find(s=>s.name===name)?.score??0}
            onSelect={onSelect} isLocalPlayer={localClaim?.name===name}
            isClaimed={false}/>
        ))}
      </div>
    </div>
  );
}

function PlayerCard({name,score,onSelect,isLocalPlayer}) {
  const theme=PLAYER_THEMES[name]||{};
  return (
    <div onClick={()=>onSelect(name)} style={{...S.playerCard,background:theme.bg,border:`2px solid ${isLocalPlayer?theme.border:theme.border+"55"}`,boxShadow:isLocalPlayer?`0 0 24px ${theme.shadow},0 4px 16px rgba(0,0,0,0.5)`:"0 4px 16px rgba(0,0,0,0.4)"}}>
      <div style={{position:"absolute",inset:0,backgroundImage:theme.pattern,borderRadius:14}}/>
      {isLocalPlayer&&<div style={{...S.playerBadge,background:theme.border,color:"#000"}}>YOUR PICKS</div>}
      <div style={S.playerEmoji}>{theme.emoji}</div>
      <div style={{...S.playerName,color:theme.accent}}>{name}</div>
      <div style={{...S.playerLabel,color:theme.textColor+"88"}}>{theme.label}</div>
      {score>0&&<div style={{...S.playerScore,color:theme.accent}}>{score} pts</div>}
      <div style={{...S.playerTagline,color:theme.textColor+"66"}}>"{theme.tagline}"</div>
    </div>
  );
}

/* ═══════════════════════════════════════════════
   PICKS VIEW
═══════════════════════════════════════════════ */
function PicksView({player,activeRound,setActiveRound,localPicks,setGroupPick,setKoPick,localGolden,setLocalGolden,onSave,saving,data,onBack,savedAt,liveFixtures}) {
  const theme=PLAYER_THEMES[player]||{};
  const gbLocked=goldenBootLocked();
  const locked=isLocked(activeRound);
  const roundSavedAt=savedAt[`${player}__${activeRound}`]||null;
  const allGamesPicked = activeRound==="group"
    ? GROUP_GAMES.every(g=>localPicks[g.id]?.result)
    : (KNOCKOUT_ROUNDS[activeRound]||[]).every(g=>{const rg=resolveGame(g,liveFixtures);return rg.home==="TBD"||localPicks[g.id]?.winner;});

  return (
    <div style={{...S.picksWrap,borderColor:theme.border}}>
      <div style={{position:"absolute",inset:0,backgroundImage:theme.pattern,borderRadius:14,pointerEvents:"none"}}/>
      <div style={S.picksHeader}>
        <button style={S.backBtn} onClick={onBack}>← Back</button>
        <div style={{display:"flex",alignItems:"center",gap:12}}>
          <span style={{fontSize:28}}>{theme.emoji}</span>
          <div>
            <div style={{...S.picksTitle,color:theme.accent}}>{player}'s Picks</div>
            <div style={{fontSize:12,color:theme.textColor+"66"}}>{theme.tagline}</div>
          </div>
        </div>
        <div style={{textAlign:"right"}}>
          <button style={{...S.saveBtn,background:locked?"#1a1a1a":"linear-gradient(135deg,#3daa3d,#2ecc44)",color:locked?"#446":"#000",opacity:saving?0.6:1,fontSize:15,padding:"12px 24px",borderRadius:10,boxShadow:locked?"none":"0 0 16px rgba(44,204,68,0.35)"}} onClick={onSave} disabled={locked||saving}>
            {saving?"Saving…":locked?"🔒 Locked":"Save Picks"}
          </button>
          {roundSavedAt&&<div style={{fontSize:10,color:"#3a6a3a",marginTop:4}}>✅ Saved {fmtTimestamp(roundSavedAt)}</div>}
        </div>
      </div>

      <div style={S.roundTabs}>
        {ROUNDS.map(r=>{
          const hasLocked=(r.id==="group")?GROUP_GAMES.some(g=>isGameLocked(g)):(KNOCKOUT_ROUNDS[r.id]||[]).some(g=>isGameLocked(resolveGame(g,liveFixtures)));
          const isCurrent=r.id===activeRound;
          return (
            <button key={r.id} style={{...S.roundTab,...(isCurrent?{...S.roundTabActive,borderColor:theme.border,color:theme.accent}:{})}}
              onClick={()=>setActiveRound(r.id)}>
              {r.label}{hasLocked&&r.id!==activeRound?<span style={{marginLeft:4,fontSize:9,color:"#664"}}>🔒</span>:null}
            </button>
          );
        })}
      </div>

      <div style={{padding:"0 0 16px",maxWidth:900,margin:"0 auto"}}>
        <div style={{display:"flex",alignItems:"center",gap:10,marginBottom:12,flexWrap:"wrap"}}>
          <div style={{...S.gbWrap,borderColor:theme.border+"44"}}>
            <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:6}}>
              <span style={{fontSize:16}}>🥾</span>
              <div>
                <div style={{...S.gbTitle,color:theme.accent}}>Golden Boot {gbLocked?"🔒 Locked":"(locks at kickoff)"}</div>
                <div style={S.gbSub}>Worth 10 pts if correct</div>
              </div>
            </div>
            <select style={S.gbSelect} value={localGolden} onChange={e=>!gbLocked&&setLocalGolden(e.target.value)} disabled={gbLocked}>
              <option value="">— pick a player —</option>
              {GOLDEN_BOOT_CANDIDATES.map(c=><option key={c} value={c}>{c}</option>)}
            </select>
          </div>
          {!allGamesPicked&&!locked&&<div style={{fontSize:11,color:"#886644",background:"rgba(255,200,100,0.08)",border:"1px solid rgba(255,200,100,0.2)",borderRadius:6,padding:"6px 10px"}}>⚠️ Not all games picked yet</div>}
        </div>

        {activeRound==="group"
          ? <GroupPanel localPicks={localPicks} setGroupPick={setGroupPick} locked={locked} results={data.results} savedAt={savedAt}/>
          : <KnockoutPanel roundId={activeRound} localPicks={localPicks} setKoPick={setKoPick} locked={locked} results={data.results} liveFixtures={liveFixtures}/>
        }
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════
   GROUP PANEL
═══════════════════════════════════════════════ */
function GroupPanel({localPicks,setGroupPick,locked,results,savedAt}) {
  const [viewMode,setViewMode]=useState("date");

  const fmtDateHeader = dateStr =>
    new Date(dateStr + 'T12:00:00Z')
      .toLocaleDateString("en-US",{weekday:"short",month:"short",day:"numeric"})
      .toUpperCase();

  const gamesByDate=()=>{
    const buckets={};
    GROUP_GAMES.forEach(g=>{
      const key = g.kickoff ? g.kickoff.slice(0,10) : 'TBD';
      if(!buckets[key])buckets[key]=[];
      buckets[key].push(g);
    });
    // Return sorted by date key (YYYY-MM-DD sorts correctly)
    return Object.entries(buckets).sort(([a],[b])=>a.localeCompare(b));
  };

  const gamesByGroup=()=>{
    const buckets={};
    GROUP_GAMES.forEach(g=>{
      if(!buckets[g.group])buckets[g.group]=[];
      buckets[g.group].push(g);
    });
    return buckets;
  };

  return (
    <div>
      <div style={{display:"flex",gap:6,marginBottom:14}}>
        {[["date","📅 By Date"],["group","🗂 By Group"]].map(([m,l])=>(
          <button key={m} style={{...S.roundTab,...(viewMode===m?S.roundTabActive:{})}} onClick={()=>setViewMode(m)}>{l}</button>
        ))}
      </div>
      {viewMode==="date"
        ? gamesByDate().map(([dateKey,games])=>(
            <div key={dateKey} style={{marginBottom:16}}>
              <div style={S.dateHeader}>📅 {fmtDateHeader(dateKey)}</div>
              {games.map(game=><GameRow key={game.id} game={game} localPicks={localPicks} setGroupPick={setGroupPick} locked={locked} results={results} savedAt={savedAt} showGroup/>)}
            </div>
          ))
        : Object.entries(gamesByGroup()).sort(([a],[b])=>a.localeCompare(b)).map(([grp,games])=>(
            <div key={grp} style={{marginBottom:16}}>
              <div style={S.dateHeader}>GROUP {grp}</div>
              {games.map(game=><GameRow key={game.id} game={game} localPicks={localPicks} setGroupPick={setGroupPick} locked={locked} results={results} savedAt={savedAt}/>)}
            </div>
          ))
      }
    </div>
  );
}

function GameRow({game,localPicks,setGroupPick,locked,results,savedAt,showGroup}) {
  const now=new Date();
  const pick=localPicks[game.id]?.result;
  const res=results[game.id]?.result;
  const dl=gameDeadline(game);
  const gameLocked=isGameLocked(game);
  const pickTs=localPicks[game.id]?._savedAt||null;
  const urgentSoon=dl&&!gameLocked&&(dl-now)<6*60*60*1000;
  return (
    <div style={{borderBottom:"1px solid rgba(255,255,255,0.05)",padding:"10px 0"}}>
      <div style={{display:"flex",alignItems:"center",gap:8}}>
        {showGroup&&<span style={S.grpBadge}>Grp {game.group}</span>}
        <span style={{...S.teamName,flex:1,textAlign:"left"}}>{fl(game.home)} {game.home}</span>
        <div style={S.btnGroup}>
          {[["home","W"],["draw","D"],["away","W"]].map(([opt,label])=>{
            const active=pick===opt;
            const correct=res&&res===opt;
            const wrong=res&&active&&!correct;
            return (
              <button key={opt} disabled={locked||gameLocked}
                style={{...S.pickBtn,
                  background:active?(correct?"#1a5a1a":wrong?"#5a1a1a":"#1a2a4a"):"rgba(255,255,255,0.04)",
                  border:`1px solid ${active?(correct?"#2ecc66":wrong?"#cc3333":"#4488cc"):"rgba(255,255,255,0.12)"}`,
                  color:active?(correct?"#2ecc66":wrong?"#ff6666":"#88aaff"):"#99aabb",
                  opacity:(locked||gameLocked)&&!active?0.35:1,
                  fontWeight:active?"bold":"normal",
                  width:36,textAlign:"center"}}
                onClick={()=>!(locked||gameLocked)&&setGroupPick(game.id,opt)}>
                {label}
              </button>
            );
          })}
        </div>
        <span style={{...S.teamName,flex:1,textAlign:"right"}}>{game.away} {fl(game.away)}</span>
      </div>
      <div style={{display:"flex",justifyContent:"space-between",marginTop:5,fontSize:10}}>
        <span style={{color:gameLocked?"#664":"#446"}}>
          {gameLocked?"🔒 Locked":(dl?<Countdown deadline={dl} urgentSoon={urgentSoon}/>:null)}
        </span>
        <span style={{color:pickTs?"#3a6a3a":"#334"}}>
          {pickTs?`✅ ${gameLocked?"Submitted":"Picked"} ${fmtTimestamp(pickTs)}`:""}
        </span>
      </div>
    </div>
  );
}

function Countdown({deadline,urgentSoon}) {
  const [now,setNow]=useState(new Date());
  useEffect(()=>{ const t=setInterval(()=>setNow(new Date()),1000); return ()=>clearInterval(t); },[]);
  const ms=deadline-now;
  if (ms<=0) return <span style={{fontSize:10,color:"#664444"}}>🔒 Locked</span>;
  const totalSecs=Math.floor(ms/1000);
  const d=Math.floor(totalSecs/86400), h=Math.floor((totalSecs%86400)/3600),
        m=Math.floor((totalSecs%3600)/60), s=totalSecs%60;
  const parts=[]; if(d>0)parts.push(`${d}d`); if(d>0||h>0)parts.push(`${h}h`); parts.push(`${m}m`);
  if(d===0&&h===0)parts.push(`${String(s).padStart(2,"0")}s`);
  const color=urgentSoon?"#ffaa44":d>1?"#446655":"#88ccaa";
  return <span style={{fontSize:10,color,letterSpacing:0.5,fontVariantNumeric:"tabular-nums"}}>⏳ {parts.join(" ")} to lock</span>;
}

/* ═══════════════════════════════════════════════
   KNOCKOUT PANEL
═══════════════════════════════════════════════ */
function KnockoutPanel({roundId,localPicks,setKoPick,locked,results,liveFixtures}) {
  const games=KNOCKOUT_ROUNDS[roundId]||[];
  return (
    <div>
      {games.map(rawGame=>{
        const game=resolveGame(rawGame,liveFixtures);
        const pick=localPicks[game.id]||{};
        const res=results[game.id]||{};
        const gameLocked=isGameLocked(game);
        const isTbd=game.home==="TBD"||game.away==="TBD";
        return (
          <div key={game.id} style={{...S.koGameRow,opacity:isTbd?0.5:1}}>
            <div style={{display:"flex",alignItems:"center",gap:8,marginBottom:8,flexWrap:"wrap"}}>
              <span style={{fontSize:11,color:"#99aabb",letterSpacing:1}}>{game.label}</span>
              {gameLocked&&<span style={{fontSize:10,color:"#664"}}>🔒</span>}
              {game.kickoff&&<span style={{fontSize:10,color:"#446"}}>{fmtDeadline(game)}</span>}
            </div>
            <div style={{display:"flex",gap:10,alignItems:"center",flexWrap:"wrap"}}>
              <span style={S.koTeam}>{fl(game.home)} {game.home}</span>
              <span style={{color:"#334",fontSize:12}}>vs</span>
              <span style={S.koTeam}>{fl(game.away)} {game.away}</span>
            </div>
            {!isTbd&&(
              <div style={{display:"flex",gap:10,marginTop:10,flexWrap:"wrap"}}>
                <div style={{flex:1,minWidth:140}}>
                  <div style={{fontSize:11,color:"#99aabb",marginBottom:4}}>Winner</div>
                  {[game.home,game.away].map(team=>{
                    const active=pick.winner===team;
                    const correct=res.winner===team;
                    return (
                      <button key={team} disabled={locked||gameLocked}
                        style={{...S.koPickBtn,background:active?(correct?"#1a6a1a":"#1a3a6a"):"rgba(255,255,255,0.03)",border:`1px solid ${active?(correct?"#3daa3d":"#4488cc"):"rgba(255,255,255,0.08)"}`,color:active?"#fff":"#667"}}
                        onClick={()=>!(locked||gameLocked)&&setKoPick(game.id,"winner",team)}>
                        {fl(team)} {team} {correct&&"✓"}
                      </button>
                    );
                  })}
                </div>
                <div style={{flex:1,minWidth:140}}>
                  <div style={{fontSize:11,color:"#99aabb",marginBottom:4}}>Method (+{SCORING[roundId]?.method||0} pts)</div>
                  {METHOD_OPTIONS.map(opt=>{
                    const active=pick.method===opt.value;
                    const correct=res.method===opt.value&&!!res.winner;
                    return (
                      <button key={opt.value} disabled={locked||gameLocked||!pick.winner}
                        style={{...S.koPickBtn,background:active?(correct?"#1a6a1a":"#1a3a6a"):"rgba(255,255,255,0.03)",border:`1px solid ${active?(correct?"#3daa3d":"#4488cc"):"rgba(255,255,255,0.08)"}`,color:active?"#fff":"#667",opacity:!pick.winner?0.4:1}}
                        onClick={()=>!(locked||gameLocked)&&pick.winner&&setKoPick(game.id,"method",opt.value)}>
                        {opt.label} {correct&&"✓"}
                      </button>
                    );
                  })}
                </div>
              </div>
            )}
            {res.winner&&<div style={{fontSize:11,color:"#4a8a4a",marginTop:6}}>Result: {res.winner} ({METHOD_OPTIONS.find(m=>m.value===res.method)?.label||res.method})</div>}
          </div>
        );
      })}
    </div>
  );
}

/* ═══════════════════════════════════════════════
   LEADERBOARD
═══════════════════════════════════════════════ */
function LeaderboardView({scores,data}) {
  const [expanded,setExpanded]=useState(null);
  return (
    <div style={S.lbWrap}>
      <div style={S.pageTitle}>🏆 Standings</div>
      {scores.map((s,i)=>{
        const theme=PLAYER_THEMES[s.name]||{};
        const bd=calcBreakdown(s.name,data.picks,data.results,data.goldenBoot);
        const isExp=expanded===s.name;
        return (
          <div key={s.name} style={{...S.lbCard,background:theme.bg,border:`1px solid ${theme.border}66`}} onClick={()=>setExpanded(isExp?null:s.name)}>
            <div style={{display:"flex",alignItems:"center",gap:12}}>
              <span style={{fontSize:22,minWidth:32,textAlign:"center"}}>{i===0?"🥇":i===1?"🥈":i===2?"🥉":`${i+1}.`}</span>
              <span style={{fontSize:20}}>{theme.emoji}</span>
              <div style={{flex:1}}>
                <div style={{...S.lbName,color:theme.accent}}>{s.name}</div>
                <div style={{fontSize:11,color:theme.textColor+"66"}}>{theme.label}</div>
              </div>
              <div style={{...S.lbScore,color:theme.accent}}>{s.score}<span style={{fontSize:12,color:theme.textColor+"66"}}> pts</span></div>
              <span style={{fontSize:10,color:"#445"}}>{isExp?"▲":"▼"}</span>
            </div>
            {isExp&&(
              <div style={{marginTop:12,paddingTop:12,borderTop:`1px solid ${theme.border}22`,display:"flex",flexWrap:"wrap",gap:8}}>
                {Object.entries(bd).map(([k,v])=>(
                  <div key={k} style={{background:"rgba(0,0,0,0.3)",borderRadius:6,padding:"6px 10px",minWidth:90,textAlign:"center"}}>
                    <div style={{fontSize:10,color:"#446",textTransform:"capitalize"}}>{k==="golden"?"Golden Boot":k}</div>
                    <div style={{fontSize:16,color:v>0?theme.accent:"#334",fontWeight:"bold"}}>{v}</div>
                  </div>
                ))}
              </div>
            )}
          </div>
        );
      })}
    </div>
  );
}

/* ═══════════════════════════════════════════════
   PICKS REVEAL
═══════════════════════════════════════════════ */
function PicksRevealView({data,liveFixtures}) {
  const [roundId,setRoundId]=useState("group");
  return (
    <div style={S.revealWrap}>
      <div style={S.pageTitle}>👁 All Picks</div>
      <div style={S.roundTabs}>
        {ROUNDS.map(r=>(
          <button key={r.id} style={{...S.roundTab,...(roundId===r.id?S.roundTabActive:{})}} onClick={()=>setRoundId(r.id)}>{r.label}</button>
        ))}
      </div>
      <RevealRound roundId={roundId} data={data} liveFixtures={liveFixtures}/>
    </div>
  );
}

function RevealRound({roundId,data,liveFixtures}) {
  const games = roundId==="group" ? GROUP_GAMES : (KNOCKOUT_ROUNDS[roundId]||[]).map(g=>resolveGame(g,liveFixtures));
  return (
    <div style={{overflowX:"auto"}}>
      <table style={{width:"100%",borderCollapse:"collapse",fontSize:12}}>
        <thead>
          <tr style={{borderBottom:"1px solid #1a2a1a"}}>
            <th style={{...S.th,textAlign:"left"}}>Match</th>
            {PLAYERS.map(p=><th key={p} style={S.th}>{PLAYER_THEMES[p]?.emoji} {p}</th>)}
            <th style={S.th}>Result</th>
          </tr>
        </thead>
        <tbody>
          {games.map(game=>{
            const res=data.results[game.id];
            const locked=isGameLocked(game);
            return (
              <tr key={game.id} style={{borderBottom:"1px solid #0a1a0a"}}>
                <td style={{...S.td,color:"#99aabb",minWidth:160}}>
                  {game.home==="TBD"?game.label:`${fl(game.home)}${game.home} v ${fl(game.away)}${game.away}`}
                </td>
                {PLAYERS.map(p=>{
                  const pick=data.picks[p]?.[game.id];
                  const correct=res&&(roundId==="group"?pick?.result===res.result:pick?.winner===res.winner);
                  const txt=roundId==="group"?(pick?.result?{home:"H",draw:"D",away:"A"}[pick.result]:"–"):(pick?.winner?`${fl(pick.winner)}${pick.winner}${pick.method?` (${pick.method})`:""}` :"–");
                  return (
                    <td key={p} style={{...S.td,textAlign:"center",color:locked?(correct?"#4a8a4a":res?"#8a4a4a":"#334"):"#334",background:locked&&correct?"rgba(44,204,102,0.07)":locked&&res&&pick?"rgba(180,44,44,0.07)":"transparent"}}>
                      {locked?txt:"🔒"}
                    </td>
                  );
                })}
                <td style={{...S.td,textAlign:"center",color:"#4a6a4a",fontSize:11}}>
                  {res?(roundId==="group"?({home:`${game.home} win`,draw:"Draw",away:`${game.away} win`}[res.result]||"?"):`${res.winner} (${res.method||"?"})`):"–"}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

/* ═══════════════════════════════════════════════
   ADMIN VIEW
═══════════════════════════════════════════════ */
function AdminView({adminMode,adminKey,setAdminKey,setAdminMode,data,saveResult,saveResultsBatch,saveFixturesBatch,notify,setData}) {
  const [adminTab,setAdminTab]=useState("sync");
  const [adminRound,setAdminRound]=useState("group");
  const [localResults,setLocalResults]=useState({});
  const [syncing,setSyncing]=useState(false);
  const [syncLog,setSyncLog]=useState([]);
  const [goldenInput,setGoldenInput]=useState("");

  function log(msg){setSyncLog(l=>[...l.slice(-19),msg]);}

  async function syncResults() {
    setSyncing(true); setSyncLog([]);
    try {
      log("Sending sync request to server…");
      const r=await fetch("/api/admin/sync-results",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({adminKey})});
      const res=await r.json();
      if(!r.ok) throw new Error(res.error||"Sync failed");
      (res.log||[]).forEach(log);
      if(res.data) setData(res.data);
    } catch(e){log(`❌ ${e.message}`);} setSyncing(false);
  }

  async function syncFixtures() {
    setSyncing(true); setSyncLog([]);
    try {
      log("Syncing fixtures from server…");
      const r=await fetch("/api/admin/sync-fixtures",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({adminKey})});
      const res=await r.json();
      if(!r.ok) throw new Error(res.error||"Sync failed");
      (res.log||[]).forEach(log);
      if(res.data) setData(res.data);
    } catch(e){log(`❌ ${e.message}`);} setSyncing(false);
  }

  async function saveGoldenBoot() {
    if(!goldenInput){notify("Pick a player","err");return;}
    try {
      const r=await fetch("/api/admin/results",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({adminKey,results:{goldenBoot:goldenInput}})});
      if(!r.ok) throw new Error("Failed");
      setData(await r.json()); notify("Golden Boot set ✓"); setGoldenInput("");
    } catch{notify("Failed","err");}
  }

  if (!adminMode) return (
    <div style={S.adminGate}>
      <div style={S.adminCard}>
        <div style={{fontSize:28,marginBottom:4}}>🔐</div>
        <div style={{fontSize:20,fontWeight:"bold",color:"#f0c040",letterSpacing:2,marginBottom:16}}>Admin Access</div>
        <input style={S.adminInput} type="password" placeholder="Password"
          value={adminKey} onChange={e=>setAdminKey(e.target.value)}
          onKeyDown={e=>e.key==="Enter"&&setAdminMode(true)}/>
        <button style={{...S.saveBtn,background:"linear-gradient(135deg,#3daa3d,#2a8a2a)",color:"#fff"}}
          onClick={()=>setAdminMode(true)}>Enter</button>
      </div>
    </div>
  );

  return (
    <div style={S.adminWrap}>
      <div style={{display:"flex",gap:8,marginBottom:20,flexWrap:"wrap"}}>
        {[["sync","🔄 Sync"],["results","📝 Results"],["recover","🚨 Recovery"]].map(([t,l])=>(
          <button key={t} style={{...S.roundTab,...(adminTab===t?S.roundTabActive:{})}} onClick={()=>setAdminTab(t)}>{l}</button>
        ))}
      </div>

      {adminTab==="sync"&&(
        <div>
          <div style={S.adminSectionTitle}>Sync from football-data.org</div>
          <div style={{display:"flex",gap:10,marginBottom:16,flexWrap:"wrap"}}>
            <button style={{...S.saveBtn,background:"linear-gradient(135deg,#1a5a8a,#2288cc)",color:"#fff",opacity:syncing?0.5:1}} onClick={syncResults} disabled={syncing}>
              {syncing?"Syncing…":"⚽ Sync Results"}
            </button>
            <button style={{...S.saveBtn,background:"linear-gradient(135deg,#5a1a8a,#8822cc)",color:"#fff",opacity:syncing?0.5:1}} onClick={syncFixtures} disabled={syncing}>
              {syncing?"Syncing…":"🗓 Sync Fixtures"}
            </button>
          </div>
          {syncLog.length>0&&(
            <pre style={{fontSize:11,color:"#4a7a4a",background:"#050810",border:"1px solid #0d1a0d",borderRadius:6,padding:10,maxHeight:200,overflowY:"auto",fontFamily:"monospace",whiteSpace:"pre-wrap"}}>
              {syncLog.join("\n")}
            </pre>
          )}
          <div style={{marginTop:20}}>
            <div style={S.adminSectionTitle}>Set Golden Boot Winner</div>
            <div style={{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"}}>
              <select style={{...S.adminInput,width:"auto"}} value={goldenInput} onChange={e=>setGoldenInput(e.target.value)}>
                <option value="">— select player —</option>
                {GOLDEN_BOOT_CANDIDATES.map(c=><option key={c} value={c}>{c}</option>)}
              </select>
              <button style={{...S.saveBtn,background:"linear-gradient(135deg,#8a7a00,#ccbb00)",color:"#000"}} onClick={saveGoldenBoot}>Set</button>
            </div>
            {data.results?.goldenBoot&&<div style={{fontSize:12,color:"#aacc44",marginTop:8}}>Current: {data.results.goldenBoot}</div>}
          </div>
        </div>
      )}

      {adminTab==="results"&&(
        <div>
          <div style={S.adminSectionTitle}>Manual Result Entry</div>
          <div style={{display:"flex",gap:8,marginBottom:12,flexWrap:"wrap"}}>
            {ROUNDS.filter(r=>r.id!=="group").map(r=>(
              <button key={r.id} style={{...S.roundTab,...(adminRound===r.id?S.roundTabActive:{})}} onClick={()=>setAdminRound(r.id)}>{r.label}</button>
            ))}
            <button style={{...S.roundTab,...(adminRound==="group"?S.roundTabActive:{})}} onClick={()=>setAdminRound("group")}>Group Stage</button>
          </div>
          {adminRound==="group"?(
            GROUP_GAMES.map(game=>(
              <div key={game.id} style={{...S.gameRow,flexDirection:"column",marginBottom:8}}>
                <div style={{fontSize:12,color:"#99aabb",marginBottom:6}}>{fl(game.home)} {game.home} vs {fl(game.away)} {game.away}</div>
                <div style={{display:"flex",gap:6,flexWrap:"wrap"}}>
                  {["home","draw","away"].map(opt=>(
                    <button key={opt} style={{...S.pickBtn,background:(localResults[game.id]?.result===opt||(data.results[game.id]?.result===opt&&!localResults[game.id]))?"#1a3a6a":"rgba(255,255,255,0.04)",color:"#aac",border:"1px solid #223"}}
                      onClick={()=>setLocalResults(r=>({...r,[game.id]:{result:opt}}))}>
                      {opt==="home"?game.home:opt==="draw"?"Draw":game.away}
                    </button>
                  ))}
                  {(localResults[game.id]||data.results[game.id])&&(
                    <button style={{...S.pickBtn,background:"#1a6a1a",color:"#4f4"}} onClick={()=>{saveResult(game.id,localResults[game.id]||data.results[game.id]);setLocalResults(r=>{const n={...r};delete n[game.id];return n;});}}>💾</button>
                  )}
                </div>
              </div>
            ))
          ):(
            (KNOCKOUT_ROUNDS[adminRound]||[]).map(rawGame=>{
              const game=resolveGame(rawGame,data.liveFixtures||{});
              const cur=localResults[game.id]||data.results[game.id]||{};
              return (
                <div key={game.id} style={{...S.koGameRow,marginBottom:8}}>
                  <div style={{fontSize:12,color:"#99aabb",marginBottom:8}}>{game.label}: {fl(game.home)}{game.home} vs {fl(game.away)}{game.away}</div>
                  <div style={{display:"flex",gap:10,flexWrap:"wrap"}}>
                    <div>
                      <div style={{fontSize:10,color:"#446",marginBottom:4}}>Winner</div>
                      {[game.home,game.away].map(t=>(
                        <button key={t} style={{...S.koPickBtn,background:cur.winner===t?"#1a3a6a":"rgba(255,255,255,0.03)",color:"#aac",border:"1px solid #223"}}
                          onClick={()=>setLocalResults(r=>({...r,[game.id]:{...(r[game.id]||{}),winner:t}}))}>
                          {fl(t)} {t}
                        </button>
                      ))}
                    </div>
                    <div>
                      <div style={{fontSize:10,color:"#446",marginBottom:4}}>Method</div>
                      {METHOD_OPTIONS.map(m=>(
                        <button key={m.value} style={{...S.koPickBtn,background:cur.method===m.value?"#1a3a6a":"rgba(255,255,255,0.03)",color:"#aac",border:"1px solid #223"}}
                          onClick={()=>setLocalResults(r=>({...r,[game.id]:{...(r[game.id]||{}),method:m.value}}))}>
                          {m.label}
                        </button>
                      ))}
                    </div>
                    {(localResults[game.id]?.winner)&&(
                      <button style={{...S.saveBtn,background:"#1a6a1a",color:"#4f4",alignSelf:"flex-end"}}
                        onClick={()=>{saveResult(game.id,localResults[game.id]);setLocalResults(r=>{const n={...r};delete n[game.id];return n;});}}>💾 Save</button>
                    )}
                  </div>
                </div>
              );
            })
          )}
        </div>
      )}

      {adminTab==="recover"&&(
        <RecoveryTab adminKey={adminKey} notify={notify} setData={setData}/>
      )}
    </div>
  );
}

/* ═══════════════════════════════════════════════
   RECOVERY TAB
═══════════════════════════════════════════════ */
function RecoveryTab({adminKey,notify,setData}) {
  const [backups,setBackups]=useState([]);
  const [scanning,setScanning]=useState(false);

  async function listBackups() {
    setScanning(true);
    try {
      const r=await fetch(`/api/admin/backups?adminKey=${encodeURIComponent(adminKey)}`);
      if(!r.ok) throw new Error("Failed — check admin key");
      const {backups:list}=await r.json();
      setBackups(list); notify(`Found ${list.length} backup${list.length!==1?"s":""}`);
    } catch(e){notify(e.message,"err");}
    setScanning(false);
  }

  async function exportData() {
    try {
      const r=await fetch(`/api/admin/export?adminKey=${encodeURIComponent(adminKey)}`);
      if(!r.ok) throw new Error("Export failed");
      const blob=await r.blob();
      const url=URL.createObjectURL(blob);
      const a=document.createElement("a"); a.href=url; a.download=`pool-export-${Date.now()}.json`; a.click();
      URL.revokeObjectURL(url);
    } catch(e){notify(e.message,"err");}
  }

  return (
    <div>
      <div style={{background:"rgba(255,60,60,0.07)",border:"1px solid rgba(255,60,60,0.3)",borderRadius:10,padding:"14px 18px",marginBottom:20}}>
        <div style={{fontSize:13,color:"#ff8888",fontWeight:"bold",marginBottom:6}}>🚨 Data Recovery</div>
        <div style={{fontSize:12,color:"#aa7777",lineHeight:1.7}}>Server backups are taken hourly. Use Export to download current data as JSON.</div>
      </div>
      <div style={{display:"flex",gap:10,flexWrap:"wrap",marginBottom:16}}>
        <button style={{...S.saveBtn,background:"linear-gradient(135deg,#1a4a7a,#2266aa)",color:"#fff",opacity:scanning?0.5:1}} onClick={listBackups} disabled={scanning}>
          {scanning?"Loading…":"🔍 List Backups"}
        </button>
        <button style={{...S.saveBtn,background:"linear-gradient(135deg,#4a4a1a,#8a8a22)",color:"#fff"}} onClick={exportData}>
          📥 Export JSON
        </button>
      </div>
      {backups.length>0&&(
        <div style={{fontSize:12,color:"#99aabb",fontFamily:"monospace"}}>
          {backups.map(b=><div key={b} style={{padding:"3px 0",borderBottom:"1px solid #0a1a0a"}}>{b}</div>)}
        </div>
      )}
    </div>
  );
}

/* ═══════════════════════════════════════════════
   CLAIM MODAL
═══════════════════════════════════════════════ */
function ClaimModal({modal,claimInput,setClaimInput,onClose,onClaimNew,onVerify,onEnter,localClaim}) {
  const theme=PLAYER_THEMES[modal.name]||{};
  return (
    <div style={S.modalOverlay} onClick={onClose}>
      <div style={{...S.modalBox,border:`1px solid ${theme.border}88`}} onClick={e=>e.stopPropagation()}>
        <div style={{fontSize:28,marginBottom:8}}>{theme.emoji}</div>
        <div style={{fontSize:18,fontWeight:"bold",color:theme.accent,marginBottom:4}}>{modal.name}</div>
        {modal.mode==="choose"&&(
          <>
            <div style={{fontSize:13,color:"#778",marginBottom:16}}>Claim this name to save your picks. You'll get a 4-digit code — write it down!</div>
            <button style={{...S.saveBtn,background:`linear-gradient(135deg,${theme.border},${theme.accent})`,color:"#000",width:"100%"}} onClick={()=>onClaimNew(modal.name)}>🔑 Claim &amp; Get Code</button>
            {localClaim?.name===modal.name&&<button style={{...S.saveBtn,background:"#1a3a1a",color:"#4f4",width:"100%",marginTop:8}} onClick={()=>{onClose();onEnter(modal.name);}}>▶ Enter (already claimed)</button>}
          </>
        )}
        {modal.mode==="show"&&(
          <>
            <div style={{fontSize:13,color:"#778",marginBottom:12}}>Your code — write this down!</div>
            <div style={{fontSize:36,fontWeight:"bold",color:theme.accent,letterSpacing:8,marginBottom:16,fontFamily:"monospace"}}>{modal.code}</div>
            <div style={{fontSize:11,color:"#99aabb",marginBottom:16}}>You'll need this to access your picks from other devices.</div>
            <button style={{...S.saveBtn,background:`linear-gradient(135deg,${theme.border},${theme.accent})`,color:"#000",width:"100%"}} onClick={()=>{onClose();onEnter(modal.name);}}>✓ Got it — Enter Picks</button>
          </>
        )}
        {modal.mode==="verify"&&(
          <>
            <div style={{fontSize:13,color:"#778",marginBottom:12}}>Enter your 4-digit code to access picks.</div>
            <input style={{...S.adminInput,textAlign:"center",letterSpacing:8,fontSize:20,marginBottom:12}}
              type="text" maxLength={4} placeholder="0000" value={claimInput} onChange={e=>setClaimInput(e.target.value.replace(/\D/g,""))}
              onKeyDown={e=>e.key==="Enter"&&onVerify(modal.name)}/>
            <button style={{...S.saveBtn,background:`linear-gradient(135deg,${theme.border},${theme.accent})`,color:"#000",width:"100%"}} onClick={()=>onVerify(modal.name)}>Verify →</button>
          </>
        )}
        <button style={{...S.saveBtn,background:"rgba(255,255,255,0.05)",color:"#99aabb",marginTop:8,width:"100%"}} onClick={onClose}>Cancel</button>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════
   CONFIRM SAVE MODAL
═══════════════════════════════════════════════ */
function ConfirmSaveModal({player,round,localPicks,localGolden,onConfirm,onCancel}) {
  const theme=PLAYER_THEMES[player]||{};
  const roundGames=round==="group"?GROUP_GAMES:(KNOCKOUT_ROUNDS[round]||[]);
  const pickedCount=round==="group"?roundGames.filter(g=>localPicks[g.id]?.result).length:roundGames.filter(g=>localPicks[g.id]?.winner).length;
  return (
    <div style={S.modalOverlay} onClick={onCancel}>
      <div style={{...S.modalBox,border:`1px solid ${theme.border}88`}} onClick={e=>e.stopPropagation()}>
        <div style={{fontSize:22,marginBottom:8}}>💾</div>
        <div style={{fontSize:16,fontWeight:"bold",color:theme.accent,marginBottom:8}}>Save {player}'s Picks?</div>
        <div style={{fontSize:12,color:"#778",marginBottom:4}}>{ROUNDS.find(r=>r.id===round)?.label}</div>
        <div style={{fontSize:13,color:"#aaa",marginBottom:4}}>{pickedCount} of {roundGames.length} games picked</div>
        {localGolden&&<div style={{fontSize:12,color:"#ffcc44",marginBottom:12}}>🥾 Golden Boot: {localGolden}</div>}
        <div style={{fontSize:11,color:"#99aabb",marginBottom:16}}>Picks for locked games will be ignored.</div>
        <div style={{display:"flex",gap:8}}>
          <button style={{...S.saveBtn,background:`linear-gradient(135deg,${theme.border},${theme.accent})`,color:"#000",flex:1}} onClick={onConfirm}>Confirm</button>
          <button style={{...S.saveBtn,background:"rgba(255,255,255,0.05)",color:"#99aabb",flex:1}} onClick={onCancel}>Cancel</button>
        </div>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════
   RULES MODAL
═══════════════════════════════════════════════ */
function RulesModal({onClose}) {
  return (
    <div style={S.modalOverlay} onClick={onClose}>
      <div style={{...S.modalBox,maxWidth:500,textAlign:"left"}} onClick={e=>e.stopPropagation()}>
        <div style={{fontSize:18,fontWeight:"bold",color:"#ffcc44",marginBottom:12}}>📋 Rules &amp; Scoring</div>
        <div style={{fontSize:13,color:"#aac",lineHeight:1.8}}>
          <strong style={{color:"#ffcc44"}}>Group Stage</strong><br/>
          Pick Home Win / Draw / Away Win<br/>
          <strong style={{color:"#7fe87f"}}>3 pts</strong> for correct result<br/><br/>
          <strong style={{color:"#ffcc44"}}>Knockout Rounds</strong><br/>
          Pick the winner (no draws)<br/>
          <table style={{width:"100%",fontSize:12,marginBottom:8,borderCollapse:"collapse"}}>
            <thead><tr style={{color:"#99aabb"}}><th style={S.th}>Round</th><th style={S.th}>Winner</th><th style={S.th}>Method bonus</th></tr></thead>
            <tbody>
              {[["R32",3,2],["R16",5,3],["QF",7,4],["SF",10,5],["Final",13,8]].map(([r,w,m])=>(
                <tr key={r} style={{borderBottom:"1px solid #0a1a0a"}}>
                  <td style={S.td}>{r}</td><td style={{...S.td,color:"#7fe87f",textAlign:"center"}}>{w}</td><td style={{...S.td,color:"#88aaff",textAlign:"center"}}>{m}</td>
                </tr>
              ))}
            </tbody>
          </table>
          Method = 90 min / Extra Time / Penalties<br/><br/>
          <strong style={{color:"#ffcc44"}}>Golden Boot</strong><br/>
          Pick the tournament top scorer — <strong style={{color:"#ffcc44"}}>10 pts</strong> if correct<br/>
          Locks at tournament kickoff<br/><br/>
          <strong style={{color:"#ff8888"}}>Picks lock 1 hour before each game.</strong>
        </div>
        <button style={{...S.saveBtn,background:"rgba(255,255,255,0.07)",color:"#99aabb",marginTop:16,width:"100%"}} onClick={onClose}>Close</button>
      </div>
    </div>
  );
}

/* ═══════════════════════════════════════════════
   STYLES
═══════════════════════════════════════════════ */
const S = {
  root:         {minHeight:"100vh",background:"#050810",position:"relative",overflow:"hidden"},
  confettiBg:   {position:"fixed",inset:0,backgroundImage:"radial-gradient(ellipse at 20% 50%,rgba(44,204,102,0.04) 0%,transparent 60%),radial-gradient(ellipse at 80% 20%,rgba(44,102,204,0.04) 0%,transparent 60%)",pointerEvents:"none"},
  orb1:         {position:"fixed",top:-100,left:-100,width:400,height:400,background:"radial-gradient(circle,rgba(44,204,102,0.06) 0%,transparent 70%)",pointerEvents:"none"},
  orb2:         {position:"fixed",bottom:-150,right:-100,width:500,height:500,background:"radial-gradient(circle,rgba(44,102,204,0.06) 0%,transparent 70%)",pointerEvents:"none"},
  orb3:         {position:"fixed",top:"40%",left:"60%",width:300,height:300,background:"radial-gradient(circle,rgba(200,160,32,0.04) 0%,transparent 70%)",pointerEvents:"none"},
  toast:        {position:"fixed",top:20,left:"50%",transform:"translateX(-50%)",zIndex:9999,padding:"10px 20px",borderRadius:8,fontSize:14,color:"#fff",fontWeight:"bold",boxShadow:"0 4px 16px rgba(0,0,0,0.5)"},
  header:       {background:"rgba(5,8,16,0.95)",backdropFilter:"blur(10px)",borderBottom:"1px solid rgba(44,204,102,0.1)",position:"sticky",top:0,zIndex:100},
  headerInner:  {maxWidth:1100,margin:"0 auto",padding:"12px 20px",display:"flex",alignItems:"center",justifyContent:"space-between",gap:12,flexWrap:"wrap"},
  brand:        {display:"flex",alignItems:"center",gap:10,cursor:"pointer"},
  brandBall:    {fontSize:24},
  brandTitle:   {fontSize:16,fontWeight:"bold",color:"#2ecc66",letterSpacing:2},
  brandSub:     {fontSize:10,color:"#446",letterSpacing:1},
  headerRight:  {display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},
  rulesBtn:     {background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.1)",color:"#889",borderRadius:6,padding:"6px 12px",fontSize:12,cursor:"pointer"},
  nav:          {display:"flex",gap:4},
  navBtn:       {background:"transparent",border:"1px solid transparent",color:"#446",borderRadius:6,padding:"6px 12px",fontSize:12,cursor:"pointer",transition:"all 0.15s"},
  navActive:    {background:"rgba(44,204,102,0.1)",border:"1px solid rgba(44,204,102,0.3)",color:"#2ecc66"},
  main:         {maxWidth:1100,margin:"0 auto",padding:"24px 16px"},
  homeWrap:     {display:"flex",flexDirection:"column",gap:24},
  heroSection:  {textAlign:"center",padding:"32px 0 16px"},
  heroTitle:    {fontSize:28,fontWeight:"bold",color:"#2ecc66",letterSpacing:3,marginBottom:8},
  heroSub:      {fontSize:14,color:"#446",marginBottom:8},
  heroCountdown:{fontSize:13,color:"#667"},
  miniLeader:   {background:"rgba(255,255,255,0.02)",border:"1px solid rgba(44,204,102,0.1)",borderRadius:10,padding:"14px 18px"},
  miniLeaderGrid:{display:"flex",flexDirection:"column",gap:6,marginTop:8},
  miniLeaderCard:{display:"flex",alignItems:"center",gap:10,background:"rgba(0,0,0,0.3)",borderRadius:6,padding:"6px 10px",fontSize:13},
  sectionLabel: {fontSize:10,letterSpacing:3,color:"#334",textTransform:"uppercase",marginBottom:8},
  playerGrid:   {display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(160px,1fr))",gap:16},
  playerCard:   {position:"relative",borderRadius:14,padding:"20px 14px",cursor:"pointer",transition:"transform 0.15s,box-shadow 0.15s",display:"flex",flexDirection:"column",alignItems:"center",gap:6,overflow:"hidden"},
  playerBadge:  {position:"absolute",top:8,right:8,fontSize:8,letterSpacing:1,padding:"2px 6px",borderRadius:3,fontWeight:"bold"},
  playerEmoji:  {fontSize:28},
  playerName:   {fontSize:16,fontWeight:"bold",letterSpacing:1},
  playerLabel:  {fontSize:10,letterSpacing:1},
  playerScore:  {fontSize:18,fontWeight:"bold"},
  playerTagline:{fontSize:10,fontStyle:"italic",textAlign:"center"},
  picksWrap:    {position:"relative",borderRadius:14,padding:"20px",border:"2px solid",overflow:"hidden",background:"linear-gradient(160deg, rgba(42, 26, 0, 0.26), rgba(26, 42, 10, 0.4))"},
  picksHeader:  {display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:16,gap:12,flexWrap:"wrap"},
  backBtn:      {background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.1)",color:"#667",borderRadius:6,padding:"6px 12px",fontSize:12,cursor:"pointer"},
  picksTitle:   {fontSize:18,fontWeight:"bold"},
  saveBtn:      {border:"none",borderRadius:8,padding:"10px 18px",fontSize:13,fontWeight:"bold",cursor:"pointer",transition:"opacity 0.15s"},
  roundTabs:    {display:"flex",gap:6,marginBottom:16,flexWrap:"wrap"},
  roundTab:     {background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,255,255,0.08)",color:"#446",borderRadius:6,padding:"6px 12px",fontSize:11,cursor:"pointer"},
  roundTabActive:{background:"rgba(44,204,102,0.1)",border:"1px solid rgba(44,204,102,0.3)",color:"#2ecc66"},
  gbWrap:       {background:"rgba(0,0,0,0.3)",borderRadius:8,border:"1px solid",padding:"10px 14px",flex:1,minWidth:200,maxWidth:360},
  gbTitle:      {fontSize:12,fontWeight:"bold"},
  gbSub:        {fontSize:10,color:"#446"},
  gbSelect:     {width:"100%",background:"#0a0a14",border:"1px solid #1a3a1a",color:"#aac",borderRadius:6,padding:"6px 8px",fontSize:12,marginTop:4},
  groupBlock:   {marginBottom:20,background:"rgba(255,255,255,0.02)",borderRadius:10,padding:"12px 14px"},
  groupLabel:   {fontSize:10,letterSpacing:3,color:"#334",marginBottom:8},
  dateHeader:   {fontSize:11,letterSpacing:2,color:"#99aabb",background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,255,255,0.06)",borderRadius:6,padding:"5px 10px",marginBottom:6,display:"inline-block"},
  grpBadge:     {fontSize:9,letterSpacing:1,color:"#aacc44",background:"rgba(170,204,68,0.12)",border:"1px solid rgba(170,204,68,0.25)",borderRadius:4,padding:"2px 6px",whiteSpace:"nowrap",flexShrink:0},
  gameRow:      {display:"flex",alignItems:"center",gap:8,padding:"8px 0",borderBottom:"1px solid rgba(255,255,255,0.04)"},
  teamName:     {fontSize:12,color:"#aac",minWidth:80,flex:1},
  btnGroup:     {display:"flex",gap:4},
  pickBtn:      {borderRadius:5,padding:"5px 10px",fontSize:11,fontWeight:"bold",cursor:"pointer",transition:"all 0.1s",minWidth:36},
  koGameRow:    {background:"rgba(255,255,255,0.02)",borderRadius:10,padding:"14px",marginBottom:10,border:"1px solid rgba(255,255,255,0.06)"},
  koTeam:       {fontSize:13,color:"#aac"},
  koPickBtn:    {display:"block",width:"100%",borderRadius:6,padding:"7px 10px",fontSize:11,cursor:"pointer",marginBottom:4,textAlign:"left"},
  lbWrap:       {display:"flex",flexDirection:"column",gap:10},
  lbCard:       {borderRadius:12,padding:"14px 18px",cursor:"pointer",transition:"transform 0.1s"},
  lbName:       {fontSize:16,fontWeight:"bold"},
  lbScore:      {fontSize:24,fontWeight:"bold"},
  revealWrap:   {display:"flex",flexDirection:"column",gap:16},
  pageTitle:    {fontSize:20,fontWeight:"bold",color:"#2ecc66",letterSpacing:2,marginBottom:8},
  th:           {padding:"6px 10px",color:"#334",fontSize:11,letterSpacing:1,textAlign:"center",fontWeight:"normal"},
  td:           {padding:"6px 10px",fontSize:12},
  adminGate:    {display:"flex",alignItems:"center",justifyContent:"center",minHeight:300},
  adminCard:    {background:"rgba(255,255,255,0.03)",border:"1px solid rgba(255,200,68,0.2)",borderRadius:12,padding:"30px 40px",textAlign:"center",display:"flex",flexDirection:"column",gap:12,minWidth:260},
  adminInput:   {background:"#0a0a14",border:"1px solid #1a3a1a",color:"#aac",borderRadius:6,padding:"8px 12px",fontSize:14,outline:"none",width:"100%"},
  adminWrap:    {maxWidth:800},
  adminSectionTitle:{fontSize:13,color:"#99aabb",letterSpacing:2,marginBottom:12,textTransform:"uppercase"},
  modalOverlay: {position:"fixed",inset:0,background:"rgba(0,0,0,0.8)",zIndex:200,display:"flex",alignItems:"center",justifyContent:"center",padding:16},
  modalBox:     {background:"#0a0a14",borderRadius:14,padding:"28px 24px",textAlign:"center",maxWidth:360,width:"100%",display:"flex",flexDirection:"column",gap:8,boxShadow:"0 20px 60px rgba(0,0,0,0.8)"},
};

// Mount
ReactDOM.createRoot(document.getElementById('root')).render(React.createElement(App));
