// Main app shell — header, filters, table, row expand
const { useState: useS, useMemo: useM, useEffect: useE, useRef: useR } = React;

const { GAMES: _GAMES, TV_NETWORKS: TVN, CONFERENCES: CONFS, WINDOWS: WINS } = window.FBS_DATA;
const ALL_GAMES = _GAMES;

// Season/week catalog. Only 2025-W11 has real data; others show "no data" placeholder.
const SEASONS = [
  { year: 2026, label: "2026", weeks: Array.from({ length: 15 }, (_, i) => ({ n: i + 1, label: `WK ${i + 1}`, dateLabel: weekDateLabel(2026, i + 1) })) },
  { year: 2025, label: "2025", weeks: Array.from({ length: 15 }, (_, i) => ({ n: i + 1, label: `WK ${i + 1}`, dateLabel: weekDateLabel(2025, i + 1) })) },
  { year: 2024, label: "2024", weeks: Array.from({ length: 15 }, (_, i) => ({ n: i + 1, label: `WK ${i + 1}`, dateLabel: weekDateLabel(2024, i + 1) })) },
  { year: 2023, label: "2023", weeks: Array.from({ length: 15 }, (_, i) => ({ n: i + 1, label: `WK ${i + 1}`, dateLabel: weekDateLabel(2023, i + 1) })) }
];
const CURRENT_YEAR = 2025;
const CURRENT_WEEK = 11;

function weekDateLabel(year, wk) {
  // CFB roughly: week 1 starts late Aug. Saturday = Aug 26 + (wk-1)*7 for 2023, close enough for display.
  const base = new Date(year, 7, 24); // Aug 24
  // Move to first Saturday on/after base
  while (base.getDay() !== 6) base.setDate(base.getDate() + 1);
  base.setDate(base.getDate() + (wk - 1) * 7);
  return base.toLocaleDateString("en-US", { month: "short", day: "numeric" }).toUpperCase();
}

// Dropdown primitive
function Dropdown({ label, value, valueLabel, options, palette, onChange, align = "left", width = 180 }) {
  const [open, setOpen] = useS(false);
  const ref = useR();
  useE(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, []);
  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button onClick={() => setOpen(o => !o)} style={{
        background: open ? palette.panel : "transparent",
        border: `1px solid ${open ? palette.accent : palette.border}`,
        color: palette.text, padding: "3px 10px", fontSize: 11, fontFamily: "inherit",
        letterSpacing: 1, cursor: "pointer", display: "flex", alignItems: "center", gap: 8
      }}>
        {label && <span style={{ color: palette.dim, fontSize: 9, letterSpacing: 1.5 }}>{label}</span>}
        <span style={{ color: palette.accent, fontWeight: 700 }}>{valueLabel}</span>
        <span style={{ color: palette.dim, fontSize: 9, transform: open ? "rotate(180deg)" : "none", transition: "transform 0.15s" }}>▾</span>
      </button>
      {open && (
        <div style={{
          position: "absolute", top: "calc(100% + 4px)", [align]: 0, zIndex: 30,
          background: palette.panel, border: `1px solid ${palette.accent}`,
          minWidth: width, maxHeight: 360, overflowY: "auto",
          boxShadow: `0 4px 20px ${palette.accent}22`
        }}>
          {options.map(opt => {
            const isSelected = opt.value === value;
            const disabled = opt.disabled;
            return (
              <button key={opt.value} disabled={disabled} onClick={() => { if (!disabled) { onChange(opt.value); setOpen(false); } }} style={{
                display: "flex", justifyContent: "space-between", alignItems: "center",
                width: "100%", padding: "6px 10px",
                background: isSelected ? `${palette.accent}22` : "transparent",
                border: "none", borderBottom: `1px solid ${palette.border}`,
                color: disabled ? palette.dimmer : isSelected ? palette.accent : palette.text,
                fontSize: 11, fontFamily: "inherit", letterSpacing: 0.5,
                cursor: disabled ? "not-allowed" : "pointer", textAlign: "left"
              }}>
                <span>{opt.label}</span>
                <span style={{ color: palette.dim, fontSize: 9, marginLeft: 12 }}>{opt.hint || ""}</span>
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

function App() {
  // Tweaks state (EDITMODE block)
  const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
    "palette": "neon",
    "density": "regular",
    "accentTint": "amber"
  }/*EDITMODE-END*/;

  const [tweaks, setTweaks] = useS(TWEAK_DEFAULTS);
  const [tweaksOpen, setTweaksOpen] = useS(false);
  const palette = PALETTES[tweaks.palette] || PALETTES.neon;
  const density = DENSITIES[tweaks.density] || DENSITIES.regular;

  const [season, setSeason] = useS(CURRENT_YEAR);
  const [week, setWeek] = useS(CURRENT_WEEK);
  const isLiveSlate = season === CURRENT_YEAR && week === CURRENT_WEEK;
  const currentSeason = SEASONS.find(s => s.year === season) || SEASONS[1];
  const currentWeekObj = currentSeason.weeks.find(w => w.n === week) || currentSeason.weeks[0];

  // Filters
  const [search, setSearch] = useS("");
  const [confFilter, setConfFilter] = useS(new Set());
  const [windowFilter, setWindowFilter] = useS(new Set());
  const [networkFilter, setNetworkFilter] = useS(new Set());
  const [gradeFilter, setGradeFilter] = useS(new Set());
  const [signalOnly, setSignalOnly] = useS(false);
  const [sortBy, setSortBy] = useS("kickoff");
  const [sortDir, setSortDir] = useS("asc");
  const [expanded, setExpanded] = useS(() => {
    try { return new Set(JSON.parse(localStorage.getItem("fbs-expanded") || "[]")); }
    catch (e) { return new Set(); }
  });
  const [tick, setTick] = useS(0);

  useE(() => {
    localStorage.setItem("fbs-expanded", JSON.stringify([...expanded]));
  }, [expanded]);

  // Ticker pulse
  useE(() => {
    const id = setInterval(() => setTick(t => t + 1), 2000);
    return () => clearInterval(id);
  }, []);

  // Edit mode bridge
  useE(() => {
    const handler = (e) => {
      if (e.data?.type === "__activate_edit_mode") setTweaksOpen(true);
      if (e.data?.type === "__deactivate_edit_mode") setTweaksOpen(false);
    };
    window.addEventListener("message", handler);
    window.parent.postMessage({ type: "__edit_mode_available" }, "*");
    return () => window.removeEventListener("message", handler);
  }, []);

  const updateTweak = (k, v) => {
    setTweaks(prev => ({ ...prev, [k]: v }));
    window.parent.postMessage({ type: "__edit_mode_set_keys", edits: { [k]: v } }, "*");
  };

  const toggleSet = (setState, value) => {
    setState(prev => {
      const n = new Set(prev);
      if (n.has(value)) n.delete(value); else n.add(value);
      return n;
    });
  };

  const toggleExpand = (id) => {
    setExpanded(prev => {
      const n = new Set(prev);
      if (n.has(id)) n.delete(id); else n.add(id);
      return n;
    });
  };

  // Filtering
  const filtered = useM(() => {
    let list = (isLiveSlate ? ALL_GAMES : []).filter(g => {
      if (search) {
        const q = search.toLowerCase();
        const hay = [g.home.team, g.away.team, g.home.abbr, g.away.abbr, g.home.conf, g.away.conf, g.network, g.venue].join(" ").toLowerCase();
        if (!hay.includes(q)) return false;
      }
      if (confFilter.size && !confFilter.has(g.home.conf) && !confFilter.has(g.away.conf)) return false;
      if (windowFilter.size && !windowFilter.has(g.window)) return false;
      if (networkFilter.size && !networkFilter.has(g.network)) return false;
      if (gradeFilter.size && !gradeFilter.has(g.confidence)) return false;
      if (signalOnly) {
        const s = g.signals;
        const hasFlag = !!s.sharp || s.rlm || s.weather === "concern" || s.rest !== 0 || s.edgeGrade === "strong" || s.edgeGrade === "mild-fade";
        if (!hasFlag) return false;
      }
      return true;
    });

    const cmp = (a, b) => {
      let av, bv;
      switch (sortBy) {
        case "kickoff": av = a.kickoff; bv = b.kickoff; break;
        case "edge":    av = a.edge; bv = b.edge; break;
        case "spread":  av = a.spread.current; bv = b.spread.current; break;
        case "total":   av = a.total.current; bv = b.total.current; break;
        case "grade":   av = a.confidence; bv = b.confidence; break;
        default: return 0;
      }
      if (av < bv) return sortDir === "asc" ? -1 : 1;
      if (av > bv) return sortDir === "asc" ? 1 : -1;
      return 0;
    };
    return list.sort(cmp);
  }, [search, confFilter, windowFilter, networkFilter, gradeFilter, signalOnly, sortBy, sortDir, isLiveSlate]);

  // Aggregate stats
  const stats = useM(() => {
    const total = filtered.length;
    const signaled = filtered.filter(g => g.signals.sharp || g.signals.rlm || g.signals.weather === "concern" || g.signals.edgeGrade === "strong").length;
    const avgEdge = total ? (filtered.reduce((a, g) => a + g.edge, 0) / total).toFixed(1) : "0.0";
    const aGrade = filtered.filter(g => g.confidence === "A").length;
    return { total, signaled, avgEdge, aGrade };
  }, [filtered]);

  const setSort = (key) => {
    if (sortBy === key) setSortDir(d => d === "asc" ? "desc" : "asc");
    else { setSortBy(key); setSortDir("asc"); }
  };

  const sortArrow = (key) => sortBy === key ? (sortDir === "asc" ? " ▲" : " ▼") : "";

  // Column template
  const COLS = "56px 56px 56px minmax(280px, 1.4fr) minmax(180px, 1fr) minmax(150px, 0.9fr) 96px 120px 50px 100px";

  // -------- UI --------
  return (
    <div style={{
      minHeight: "100vh", background: palette.bg, color: palette.text,
      fontFamily: "'JetBrains Mono', ui-monospace, Menlo, monospace",
      fontSize: density.font, overflowX: "auto"
    }}>
      {/* ===== Top chrome ===== */}
      <div style={{ position: "sticky", top: 0, zIndex: 10, background: palette.bg, borderBottom: `1px solid ${palette.border}`, minWidth: 1280 }}>
        {/* Brand bar */}
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "6px 14px", borderBottom: `1px solid ${palette.border}`, fontSize: 11 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
              <div style={{ width: 12, height: 12, background: palette.accent, display: "inline-block", transform: "rotate(45deg)" }} />
              <span style={{ color: palette.accent, fontWeight: 700, letterSpacing: 2 }}>FBS ADVISOR</span>
              <span style={{ color: palette.dim }}>v2.0.1</span>
            </div>
            <span style={{ color: palette.dimmer }}>│</span>
            <Dropdown
              label="SEASON"
              value={season}
              valueLabel={String(season)}
              options={SEASONS.map(s => ({ value: s.year, label: s.label, hint: s.year === CURRENT_YEAR ? "LIVE" : s.year > CURRENT_YEAR ? "FUTURE" : "ARCHIVE" }))}
              palette={palette}
              onChange={(v) => { setSeason(v); setWeek(v === CURRENT_YEAR ? CURRENT_WEEK : 1); }}
              width={160}
            />
            <Dropdown
              label="WEEK"
              value={week}
              valueLabel={`WK ${week}`}
              options={currentSeason.weeks.map(w => ({
                value: w.n,
                label: w.label,
                hint: w.dateLabel + (season === CURRENT_YEAR && w.n === CURRENT_WEEK ? " · LIVE" : "")
              }))}
              palette={palette}
              onChange={setWeek}
              width={180}
            />
            <span style={{ color: palette.dimmer }}>│</span>
            <span style={{ color: palette.dim }}>{currentWeekObj.dateLabel}</span>
            {!isLiveSlate && (
              <span style={{
                color: season > CURRENT_YEAR ? palette.accent2 : palette.warn,
                border: `1px solid ${season > CURRENT_YEAR ? palette.accent2 : palette.warn}`,
                padding: "1px 6px", fontSize: 9, letterSpacing: 1.5
              }}>
                {season > CURRENT_YEAR ? "◆ FUTURES" : "◆ ARCHIVE"}
              </span>
            )}
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 14, color: palette.dim }}>
            <span>
              <span style={{ display: "inline-block", width: 6, height: 6, borderRadius: "50%", background: palette.up, marginRight: 6, boxShadow: `0 0 4px ${palette.up}`, animation: "pulse 1.6s infinite" }} />
              LIVE · LINES {tick}s
            </span>
            <span>MKT <span style={{ color: palette.accent2 }}>OPEN</span></span>
            <span>{new Date().toLocaleTimeString([], { hour12: false })}</span>
            <button onClick={() => setTweaksOpen(o => !o)} style={{
              background: "transparent", border: `1px solid ${palette.border}`, color: palette.dim,
              padding: "2px 8px", fontSize: 10, letterSpacing: 1, cursor: "pointer", fontFamily: "inherit"
            }}>◇ TWEAKS</button>
          </div>
        </div>

        {/* Command / filter bar */}
        <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 14px", borderBottom: `1px solid ${palette.border}`, flexWrap: "wrap", minWidth: 1280 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6, background: palette.panel, border: `1px solid ${palette.border}`, padding: "2px 10px", flex: "1 1 280px", minWidth: 240 }}>
            <span style={{ color: palette.accent, fontWeight: 700 }}>&gt;</span>
            <input value={search} onChange={e => setSearch(e.target.value)} placeholder="SEARCH team, conf, network, venue…" style={{
              background: "transparent", border: "none", outline: "none",
              color: palette.text, fontFamily: "inherit", fontSize: density.font,
              flex: 1, padding: "4px 0", letterSpacing: 0.5
            }} />
            {search && <button onClick={() => setSearch("")} style={{ background: "transparent", border: "none", color: palette.dim, cursor: "pointer", fontFamily: "inherit" }}>✕</button>}
          </div>

          <FilterChips label="CONF" items={CONFS} active={confFilter} onToggle={v => toggleSet(setConfFilter, v)} palette={palette} colorFn={conferenceColor} />
          <FilterChips label="WINDOW" items={WINS.map(w => w.id)} labels={Object.fromEntries(WINS.map(w => [w.id, w.label]))} active={windowFilter} onToggle={v => toggleSet(setWindowFilter, v)} palette={palette} />
          <FilterChips label="TV" items={["ABC","CBS","ESPN","FOX","NBC","SECN"]} active={networkFilter} onToggle={v => toggleSet(setNetworkFilter, v)} palette={palette} />
          <FilterChips label="GRADE" items={["A","B","C","D"]} active={gradeFilter} onToggle={v => toggleSet(setGradeFilter, v)} palette={palette} colorFn={g => gradeColor(g, palette)} />

          <button onClick={() => setSignalOnly(s => !s)} style={{
            background: signalOnly ? `${palette.up}20` : "transparent",
            border: `1px solid ${signalOnly ? palette.up : palette.border}`,
            color: signalOnly ? palette.up : palette.dim,
            padding: "4px 10px", fontSize: 10, letterSpacing: 1, cursor: "pointer", fontFamily: "inherit"
          }}>● SIGNALS ONLY</button>
        </div>

        {/* Stats strip */}
        <div style={{ display: "flex", gap: 0, borderBottom: `1px solid ${palette.border}`, background: palette.panel }}>
          <StatCell label="GAMES" value={stats.total} palette={palette} />
          <StatCell label="SIGNALED" value={stats.signaled} valueColor={palette.accent2} palette={palette} />
          <StatCell label="AVG EDGE" value={`${stats.avgEdge > 0 ? "+" : ""}${stats.avgEdge}`} valueColor={stats.avgEdge > 0 ? palette.up : palette.down} palette={palette} />
          <StatCell label="A-GRADE" value={stats.aGrade} valueColor={palette.up} palette={palette} />
          <StatCell label="SPREAD RANGE" value={filtered.length ? `${Math.min(...filtered.map(g => g.spread.current)).toFixed(1)} / ${Math.max(...filtered.map(g => g.spread.current)).toFixed(1)}` : "—"} palette={palette} />
          <StatCell label="OVER %" value="54%" valueColor={palette.up} palette={palette} />
          <StatCell label="FAV ATS" value="47-39" palette={palette} />
          <div style={{ flex: 1 }} />
          <div style={{ display: "flex", alignItems: "center", padding: "0 14px", fontSize: 10, color: palette.dim, borderLeft: `1px solid ${palette.border}` }}>
            ● <span style={{ color: palette.accent2, margin: "0 6px" }}>SHARP</span>
            ● <span style={{ color: palette.warn, margin: "0 6px" }}>RLM</span>
            ● <span style={{ color: palette.down, margin: "0 6px" }}>WX</span>
            ● <span style={{ color: palette.up, margin: "0 6px" }}>EDGE</span>
          </div>
        </div>

        {/* Table header */}
        <div style={{
          display: "grid", gridTemplateColumns: COLS, gap: 8,
          padding: "6px 14px", background: palette.panel2,
          borderBottom: `1px solid ${palette.border}`,
          fontSize: 9, color: palette.dim, letterSpacing: 1.5, fontWeight: 600
        }}>
          <HdrCell onClick={() => setSort("kickoff")}>DAY{sortArrow("kickoff")}</HdrCell>
          <HdrCell>TIME</HdrCell>
          <HdrCell>TV</HdrCell>
          <HdrCell>MATCHUP</HdrCell>
          <HdrCell onClick={() => setSort("spread")}>SPREAD{sortArrow("spread")}</HdrCell>
          <HdrCell>MONEYLINE</HdrCell>
          <HdrCell onClick={() => setSort("total")}>TOTAL{sortArrow("total")}</HdrCell>
          <HdrCell>SIGNALS</HdrCell>
          <HdrCell onClick={() => setSort("grade")}>GRD{sortArrow("grade")}</HdrCell>
          <HdrCell onClick={() => setSort("edge")} style={{ textAlign: "right" }}>EDGE{sortArrow("edge")}</HdrCell>
        </div>
      </div>

      {/* ===== Rows ===== */}
      <div style={{ minWidth: 1280 }}>
        {filtered.length === 0 && (
          <div style={{ padding: "60px 14px", textAlign: "center", color: palette.dim, fontSize: 12 }}>
            {!isLiveSlate ? (
              <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 10 }}>
                <div style={{
                  border: `1px dashed ${palette.border}`, padding: "20px 40px",
                  display: "flex", flexDirection: "column", gap: 8, alignItems: "center"
                }}>
                  <div style={{ color: palette.accent, fontSize: 11, letterSpacing: 2 }}>
                    {season > CURRENT_YEAR ? "◆ FUTURES SLATE" : "◆ ARCHIVE"}
                  </div>
                  <div style={{ color: palette.text, fontSize: 14 }}>
                    {season} · Week {week} · {currentWeekObj.dateLabel}
                  </div>
                  <div style={{ color: palette.dim, fontSize: 11, maxWidth: 420, lineHeight: 1.6 }}>
                    {season > CURRENT_YEAR
                      ? "No opening lines posted yet. Sportsbooks typically release spreads 6 days before kickoff."
                      : "Historical slate. Connect archive data feed to backfill closing lines, ATS results, and model performance."}
                  </div>
                  <button onClick={() => { setSeason(CURRENT_YEAR); setWeek(CURRENT_WEEK); }} style={{
                    background: "transparent", border: `1px solid ${palette.accent}`, color: palette.accent,
                    padding: "6px 14px", fontSize: 10, letterSpacing: 1.5, cursor: "pointer", fontFamily: "inherit", marginTop: 4
                  }}>◂ RETURN TO LIVE SLATE</button>
                </div>
              </div>
            ) : (
              "— NO GAMES MATCH FILTERS —"
            )}
          </div>
        )}
        {filtered.map((g, i) => {
          const isOpen = expanded.has(g.id);
          return (
            <div key={g.id}>
              <div
                onClick={() => toggleExpand(g.id)}
                onMouseEnter={(e) => e.currentTarget.style.background = palette.panel}
                onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}
                style={{
                  display: "grid", gridTemplateColumns: COLS, gap: 8,
                  padding: density.pad, alignItems: "center",
                  borderBottom: `1px solid ${palette.border}`,
                  minHeight: density.row, cursor: "pointer",
                  transition: "background 0.08s",
                  borderLeft: isOpen ? `2px solid ${palette.accent}` : `2px solid transparent`
                }}
              >
                <div style={{ color: palette.accent, fontSize: 10, letterSpacing: 1, fontWeight: 600 }}>
                  <span style={{ color: palette.dim, marginRight: 4 }}>{isOpen ? "▾" : "▸"}</span>{g.day}
                </div>
                <div style={{ color: palette.text, fontVariantNumeric: "tabular-nums" }}>{g.time}</div>
                <div style={{ color: palette.accent2, fontSize: 10, fontWeight: 600, letterSpacing: 0.5 }}>{g.network}</div>
                <MatchupCell game={g} palette={palette} />
                <SpreadCell game={g} palette={palette} />
                <div style={{ fontSize: 11, color: palette.text, fontVariantNumeric: "tabular-nums" }}>
                  <span style={{ color: palette.dim }}>{g.away.abbr}</span> {fmtML(g.moneyline.away)}
                  <span style={{ color: palette.dimmer, margin: "0 4px" }}>/</span>
                  <span style={{ color: palette.dim }}>{g.home.abbr}</span> {fmtML(g.moneyline.home)}
                </div>
                <TotalCell game={g} palette={palette} />
                <SignalDots game={g} palette={palette} />
                <div style={{
                  display: "inline-flex", alignItems: "center", justifyContent: "center",
                  width: 22, height: 22, border: `1px solid ${gradeColor(g.confidence, palette)}`,
                  color: gradeColor(g.confidence, palette), fontWeight: 700, fontSize: 11
                }}>{g.confidence}</div>
                <div style={{
                  textAlign: "right", fontWeight: 700,
                  color: g.edge > 1 ? palette.up : g.edge < -1 ? palette.down : palette.dim,
                  fontVariantNumeric: "tabular-nums"
                }}>
                  {fmtEdge(g.edge)}
                  <span style={{ color: palette.dimmer, fontSize: 9, marginLeft: 4 }}>pts</span>
                </div>
              </div>
              {isOpen && <ExpandedRow game={g} palette={palette} />}
            </div>
          );
        })}
      </div>

      {/* Footer */}
      <div style={{ padding: "10px 14px", borderTop: `1px solid ${palette.border}`, display: "flex", justifyContent: "space-between", fontSize: 10, color: palette.dim }}>
        <div>© FBS ADVISOR · ANGULAR/TS MOCK · DATA FABRICATED FOR DESIGN · NOT BETTING ADVICE</div>
        <div>CLICK ANY ROW TO EXPAND · [↑↓] SORT · [/] SEARCH</div>
      </div>

      {/* Tweaks panel */}
      {tweaksOpen && (
        <div style={{
          position: "fixed", bottom: 16, right: 16, zIndex: 50,
          background: palette.panel, border: `1px solid ${palette.accent}`,
          padding: 14, minWidth: 260, boxShadow: `0 0 40px ${palette.accent}33`
        }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10, paddingBottom: 6, borderBottom: `1px solid ${palette.border}` }}>
            <div style={{ color: palette.accent, fontSize: 11, letterSpacing: 2, fontWeight: 700 }}>◇ TWEAKS</div>
            <button onClick={() => setTweaksOpen(false)} style={{ background: "transparent", border: "none", color: palette.dim, cursor: "pointer", fontFamily: "inherit" }}>✕</button>
          </div>

          <div style={{ marginBottom: 12 }}>
            <div style={{ color: palette.dim, fontSize: 10, letterSpacing: 1, marginBottom: 6 }}>PALETTE</div>
            <div style={{ display: "flex", gap: 6 }}>
              {Object.entries(PALETTES).map(([k, p]) => (
                <button key={k} onClick={() => updateTweak("palette", k)} style={{
                  flex: 1, background: tweaks.palette === k ? p.bg : "transparent",
                  border: `1px solid ${tweaks.palette === k ? p.accent : palette.border}`,
                  color: tweaks.palette === k ? p.accent : palette.dim,
                  padding: "6px 4px", fontSize: 10, letterSpacing: 1, cursor: "pointer", fontFamily: "inherit"
                }}>{p.name}</button>
              ))}
            </div>
          </div>

          <div style={{ marginBottom: 6 }}>
            <div style={{ color: palette.dim, fontSize: 10, letterSpacing: 1, marginBottom: 6 }}>DENSITY</div>
            <div style={{ display: "flex", gap: 6 }}>
              {Object.keys(DENSITIES).map(k => (
                <button key={k} onClick={() => updateTweak("density", k)} style={{
                  flex: 1, background: tweaks.density === k ? `${palette.accent}20` : "transparent",
                  border: `1px solid ${tweaks.density === k ? palette.accent : palette.border}`,
                  color: tweaks.density === k ? palette.accent : palette.dim,
                  padding: "6px 4px", fontSize: 10, letterSpacing: 1, cursor: "pointer", fontFamily: "inherit"
                }}>{k.toUpperCase()}</button>
              ))}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ---------- Small components ----------
function HdrCell({ children, onClick, style }) {
  return (
    <div onClick={onClick} style={{
      cursor: onClick ? "pointer" : "default",
      userSelect: "none",
      ...(style || {})
    }}>{children}</div>
  );
}

function StatCell({ label, value, valueColor, palette }) {
  return (
    <div style={{ padding: "6px 14px", borderRight: `1px solid ${palette.border}`, minWidth: 100 }}>
      <div style={{ fontSize: 9, color: palette.dim, letterSpacing: 1.5 }}>{label}</div>
      <div style={{ fontSize: 13, color: valueColor || palette.text, fontWeight: 600, fontVariantNumeric: "tabular-nums" }}>{value}</div>
    </div>
  );
}

function FilterChips({ label, items, labels, active, onToggle, palette, colorFn }) {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 4 }}>
      <div style={{ color: palette.dim, fontSize: 9, letterSpacing: 1.5, marginRight: 2 }}>{label}</div>
      {items.map(item => {
        const isActive = active.has(item);
        const c = colorFn ? colorFn(item) : palette.accent;
        return (
          <button key={item} onClick={() => onToggle(item)} style={{
            background: isActive ? `${c}22` : "transparent",
            border: `1px solid ${isActive ? c : palette.border}`,
            color: isActive ? c : palette.dim,
            padding: "3px 8px", fontSize: 10, letterSpacing: 0.8, cursor: "pointer", fontFamily: "inherit",
            fontWeight: isActive ? 700 : 400
          }}>{labels?.[item] || item}</button>
        );
      })}
    </div>
  );
}

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