// Draft Command — the in-app draft room.
// Layout is dense on purpose; goal is single-viewport above the fold on a 1440px screen.

function DraftView({ onSelectPlayer, activeLeague, onRequestLeague, onLeagueChange, onFinishDraft, onResetPicks, onSavePick, manualLive = false }) {
  const nflStatus = window.useNflDataStatus();
  const [mode, setMode] = React.useState(manualLive ? "league" : "simulator");
  const [scoring, setScoring] = React.useState("ppr");
  const basePlayers = React.useMemo(
    () => window.buildDraftPool(window.PLAYERS || [], scoring),
    [nflStatus.projections, nflStatus.projectionsLoaded, scoring],
  );
  const [pos, setPos] = React.useState("ALL");
  const [search, setSearch] = React.useState("");
  const [queue, setQueue] = React.useState([]);
  const [draftedByPlayerId, setDraftedByPlayerId] = React.useState({});
  const [pickIndex, setPickIndex] = React.useState(0);
  const [question, setQuestion] = React.useState("");
  const [submittedQuestion, setSubmittedQuestion] = React.useState("");
  const [teamCount, setTeamCount] = React.useState(12);
  const [userSlot, setUserSlot] = React.useState(1);
  const [simStarted, setSimStarted] = React.useState(false);
  const [turnSeconds, setTurnSeconds] = React.useState(90);
  const [rosterConfig, setRosterConfig] = React.useState(window.DEFAULT_ROSTER_CONFIG);
  const [showSettings, setShowSettings] = React.useState(false);
  const [showDraftFinishedAsk, setShowDraftFinishedAsk] = React.useState(false);
  const [showDraftComplete, setShowDraftComplete] = React.useState(false);
  const [draftPersisted, setDraftPersisted] = React.useState(false);
  const [draftTeams, setDraftTeams] = React.useState([]);
  const boardScrollRef = React.useRef(null);
  const skipFinishPrompt = React.useRef(false);
  const hydratedLeagueId = React.useRef(null);
  const draftedRef = React.useRef({});
  draftedRef.current = draftedByPlayerId;

  React.useEffect(() => {
    if (typeof window.setDraftScoringContext === "function") {
      window.setDraftScoringContext(scoring);
    }
  }, [scoring]);

  React.useEffect(() => {
    if (!manualLive) return;
    if (!activeLeague) {
      setDraftTeams([]);
      setMode("league");
      return;
    }
    const nextTeamCount = activeLeague.teamCount || 12;
    const storedUser = activeLeague.teams?.find(team => team.isUserTeam);
    const nextUserSlot = storedUser?.slot || activeLeague.draftPosition || 1;
    setTeamCount(nextTeamCount);
    setUserSlot(nextUserSlot);
    setScoring(activeLeague.scoring === "standard" ? "std" : (activeLeague.scoring || "ppr"));
    setRosterConfig(
      activeLeague.rosterConfig
      || (window.resolveRosterConfig ? window.resolveRosterConfig(activeLeague) : window.DEFAULT_ROSTER_CONFIG)
    );
    setDraftTeams(Array.from({ length: nextTeamCount }, (_, index) => {
      const slot = index + 1;
      const stored = activeLeague.teams?.find(team => team.slot === slot);
      const isUserTeam = slot === nextUserSlot;
      return {
        slot,
        name: isUserTeam ? (activeLeague.teamName || stored?.name || "My Team") : (stored?.name || `Team ${slot}`),
        isUserTeam,
      };
    }));
    setMode("league");
  }, [manualLive, activeLeague?.id]);

  const rosterSlots = React.useMemo(() => window.buildRosterSlots(rosterConfig), [rosterConfig]);
  const rounds = rosterSlots.length;
  const leagueSettings = React.useMemo(() => ({
    teamCount,
    rosterConfig,
    includeFreeAgents: true,
  }), [teamCount, rosterConfig]);

  const teams = React.useMemo(() => Array.from({ length: teamCount }, (_, i) => {
    const slot = i + 1;
    const configured = draftTeams.find(team => team.slot === slot);
    return {
      id: `t${slot}`,
      slot,
      name: configured?.name || activeLeague?.teams?.find(team => team.slot === slot)?.name || `Team ${slot}`,
      isUser: slot === userSlot,
    };
  }), [activeLeague, draftTeams, teamCount, userSlot]);

  const draftOrder = React.useMemo(() => window.buildDraftOrder(teamCount, rounds), [teamCount, rounds]);
  const currentTeamNumber = draftOrder[pickIndex] || null;
  const currentTeam = teams[currentTeamNumber - 1];
  const isUserTurn = currentTeam?.isUser;
  const pickNumber = pickIndex + 1;
  const nextUserPick = window.findNextUserPick(draftOrder, pickIndex, userSlot);

  const scoredBoard = React.useMemo(() => {
    if (manualLive && (mode === "live" || mode === "picks")) return basePlayers;
    return window.buildOverallDraftBoardFromSettings(basePlayers, scoring, {}, 1, null, leagueSettings);
  }, [basePlayers, scoring, leagueSettings, manualLive, mode]);

  const board = React.useMemo(() => {
    if (manualLive && (mode === "live" || mode === "picks")) {
      return scoredBoard.map((player) => {
        const drafted = draftedByPlayerId[player.id];
        return drafted ? { ...player, drafted } : player;
      });
    }
    return typeof window.applyDraftLiveState === "function"
      ? window.applyDraftLiveState(scoredBoard, draftedByPlayerId, pickNumber, teamCount)
      : window.applyLiveBoardBands(
        scoredBoard.map((player) => ({ ...player, drafted: draftedByPlayerId[player.id] || null })),
        pickNumber,
        teamCount,
      );
  }, [scoredBoard, draftedByPlayerId, pickNumber, teamCount, manualLive, mode]);

  const rankedBoard = React.useMemo(() => {
    const positionCounts = {};
    return board.map(player => {
      positionCounts[player.pos] = (positionCounts[player.pos] || 0) + 1;
      return {
        ...player,
        positionRankLabel: `${player.pos}${positionCounts[player.pos]}`,
      };
    });
  }, [board]);

  const availablePlayers = React.useMemo(() => rankedBoard.filter(p => !p.drafted), [rankedBoard]);
  const filtered = rankedBoard
    .filter(p => {
      if (pos === "ALL") return true;
      return p.pos === pos || (pos === "FLEX" && ["RB", "WR", "TE"].includes(p.pos));
    })
    .filter(p => !search || `${p.name} ${p.team} ${p.pos}`.toLowerCase().includes(search.toLowerCase()))
    .slice()
    .sort((a, b) => {
      if (pos === "ALL") return 0;
      return typeof window.compareByFormatPoints === "function"
        ? window.compareByFormatPoints(a, b, scoring)
        : (b.adjusted || b.proj || 0) - (a.adjusted || a.proj || 0);
    });

  const rosters = React.useMemo(() => window.buildRosters(rankedBoard, teams, draftedByPlayerId), [rankedBoard, teams, draftedByPlayerId]);
  const userRoster = rosters[`t${userSlot}`] || [];
  const pickLog = React.useMemo(() => window.buildPickLog(rankedBoard, teams, draftedByPlayerId), [rankedBoard, teams, draftedByPlayerId]);
  const boardSettings = rankedBoard[0]?.boardSettings || null;
  const grade = React.useMemo(() => window.gradeUserDraft(userRoster, rosterSlots), [userRoster, rosterSlots]);
  const gm = React.useMemo(() => {
    if (mode === "live" || mode === "picks") {
      return { best: null, valuePick: null, ranked: [], board: [], ctx: {} };
    }
    return window.buildGmReadoutForUser(availablePlayers.slice(0, 80), {
      pickNumber,
      nextUserPick,
      teamCount,
      userRoster,
      rosterSlots,
      draftOrder,
      rosters,
      teams,
      scoring,
      grade,
      userSlot,
      includeFreeAgents: true,
    });
  }, [mode, availablePlayers, pickNumber, nextUserPick, teamCount, userRoster, rosterSlots, draftOrder, rosters, teams, scoring, grade, userSlot]);
  const gmBands = React.useMemo(() => {
    if (mode === "live" || mode === "picks") return [];
    return window.buildBandGroups(availablePlayers.slice(0, 80), pickNumber);
  }, [mode, availablePlayers, pickNumber]);

  React.useEffect(() => {
    if (!simStarted || !isUserTurn || mode !== "simulator" || pickIndex >= draftOrder.length) return;
    setTurnSeconds(90);
  }, [simStarted, isUserTurn, pickIndex, mode, draftOrder.length]);

  React.useEffect(() => {
    if (!simStarted || !isUserTurn || mode !== "simulator" || pickIndex >= draftOrder.length) return;
    const id = setInterval(() => setTurnSeconds(prev => Math.max(0, prev - 1)), 1000);
    return () => clearInterval(id);
  }, [simStarted, isUserTurn, mode, pickIndex, draftOrder.length]);

  React.useEffect(() => {
    if (!simStarted || isUserTurn || mode !== "simulator" || pickIndex >= draftOrder.length) return;
    const id = setTimeout(() => autoPickOne(), 650);
    return () => clearTimeout(id);
  }, [simStarted, isUserTurn, mode, pickIndex, draftOrder.length, draftedByPlayerId]);

  React.useEffect(() => {
    if (!simStarted || !isUserTurn || mode !== "simulator" || pickIndex >= draftOrder.length || turnSeconds > 0 || !gm.best) return;
    draftPlayer(gm.best.id);
  }, [simStarted, isUserTurn, mode, pickIndex, draftOrder.length, turnSeconds, gm.best?.id]);

  React.useEffect(() => {
    // Auto-scroll the board back to the top after a pick so the next available
    // row is in view.
    if (boardScrollRef.current && pickIndex > 0) {
      boardScrollRef.current.scrollTop = 0;
    }
  }, [pickIndex]);

  React.useEffect(() => {
    if (!manualLive) return;
    if (skipFinishPrompt.current) return;
    if (activeLeague?.draftStatus === "complete") return;
    if (simStarted && pickIndex >= draftOrder.length && pickIndex > 0) {
      setShowDraftFinishedAsk(true);
    }
  }, [manualLive, simStarted, pickIndex, draftOrder.length, activeLeague?.draftStatus]);

  React.useEffect(() => {
    if (!manualLive) return;
    if (!activeLeague) {
      hydratedLeagueId.current = null;
      skipFinishPrompt.current = false;
      setDraftedByPlayerId({});
      setPickIndex(0);
      setSimStarted(false);
      setDraftPersisted(false);
      setShowDraftFinishedAsk(false);
      return;
    }
    const leagueChanged = hydratedLeagueId.current !== activeLeague.id;
    const savedPicks = [...(activeLeague.picks || [])].sort((a, b) => a.pick - b.pick);
    if (!savedPicks.length) {
      if (!leagueChanged && simStarted && pickIndex > 0) return;
      hydratedLeagueId.current = activeLeague.id;
      skipFinishPrompt.current = false;
      setDraftedByPlayerId({});
      setPickIndex(0);
      setSimStarted(false);
      setDraftPersisted(false);
      setShowDraftFinishedAsk(false);
      return;
    }
    if (!basePlayers.length) return;
    const localDrafted = draftedRef.current || {};
    const localByPick = {};
    Object.values(localDrafted).forEach((record) => {
      const pick = Number(record?.pick);
      if (pick) localByPick[pick] = true;
    });
    const alreadyCurrent = !leagueChanged
      && Object.keys(localDrafted).length >= savedPicks.length
      && savedPicks.every((savedPick) => localByPick[Number(savedPick.pick)]);
    if (alreadyCurrent) {
      hydratedLeagueId.current = activeLeague.id;
      setDraftPersisted(true);
      return;
    }
    hydratedLeagueId.current = activeLeague.id;
    const restored = {};
    savedPicks.forEach(savedPick => {
      const savedPickIndex = Math.max(0, Number(savedPick.pick) - 1);
      const player = (window.findDraftPoolPlayer && window.findDraftPoolPlayer(basePlayers, savedPick))
        || basePlayers.find(item => item.id === savedPick.playerId)
        || basePlayers.find(item => item.name === savedPick.playerName && item.pos === savedPick.playerPosition);
      if (!player) return;
      const teamNumber = savedPick.teamSlot || draftOrder[savedPickIndex];
      const pick = Number(savedPick.pick) || savedPickIndex + 1;
      const adp = Number(player.adp) || pick;
      const band = window.marketBandForPick ? window.marketBandForPick(pick, adp, teamCount).label : "Expected";
      const grade = window.draftStockGradeForPick
        ? window.draftStockGradeForPick(player, pick, teamCount)
        : null;
      restored[player.id] = {
        teamId: `t${teamNumber}`,
        pick,
        roundPick: window.formatRoundPick(savedPickIndex, teamCount),
        adpDelta: Math.round((pick - adp) * 10) / 10,
        liveExpectedPick: player.adp || null,
        liveAvailableRank: null,
        selectedBand: band,
        boardBand: band,
        draftScore: grade?.score ?? null,
        draftGrade: grade?.letter ?? null,
        draftGradeColor: grade?.color ?? null,
        teamCount,
        valueScore: window.seasonValueScore ? window.seasonValueScore(player) : null,
        modelScore: window.cfModelScore ? window.cfModelScore(player) : null,
        sosScore: window.sosScore ? window.sosScore(player) : null,
        bestAvailable: null,
        stealAvailable: null,
      };
    });
    const nextPickIndex = savedPicks.length
      ? Math.min(Math.max(...savedPicks.map(pick => Number(pick.pick) || 0)), draftOrder.length)
      : 0;
    const alreadyDone = activeLeague.draftStatus === "complete" || nextPickIndex >= draftOrder.length;
    skipFinishPrompt.current = alreadyDone;
    const restoredSlot = window.inferUserSlot
      ? window.inferUserSlot({ ...activeLeague, picks: savedPicks })
      : (activeLeague.draftPosition || userSlot);
    if (restoredSlot) setUserSlot(restoredSlot);
    setDraftedByPlayerId(restored);
    setPickIndex(nextPickIndex);
    setSimStarted(true);
    setDraftPersisted(true);
    if (alreadyDone) setShowDraftFinishedAsk(false);
  }, [manualLive, activeLeague?.id, activeLeague?.picks?.length, activeLeague?.draftStatus, basePlayers.length]);

  function reviewDraft() {
    setMode("score");
    setShowDraftComplete(false);
    setShowDraftFinishedAsk(false);
  }

  function resetDraft() {
    setShowDraftFinishedAsk(false);
    setShowDraftComplete(false);
    setDraftedByPlayerId({});
    setPickIndex(0);
    setQueue([]);
    setQuestion("");
    setSubmittedQuestion("");
    setSimStarted(false);
    setTurnSeconds(90);
    skipFinishPrompt.current = false;
    const shouldClearRemote = draftPersisted || (activeLeague?.picks || []).length > 0;
    setDraftPersisted(false);
    if (manualLive && shouldClearRemote && activeLeague?.id && typeof onResetPicks === "function") {
      onResetPicks(activeLeague.id);
    }
  }

  function startSimulator() { setSimStarted(true); setTurnSeconds(90); }

  function startLeagueDraft() {
    if (!activeLeague) return;
    setSimStarted(true);
    setTurnSeconds(90);
  }

  function normalizedScoring(value) {
    if (value === "std") return "standard";
    return value;
  }

  function persistLeagueSetup(nextTeams, overrides = {}) {
    if (!activeLeague || typeof onLeagueChange !== "function") return Promise.resolve();
    const nextTeamCount = overrides.teamCount || teamCount;
    const nextUserSlot = overrides.userSlot || userSlot;
    const normalizedTeams = Array.from({ length: nextTeamCount }, (_, index) => {
      const slot = index + 1;
      const team = nextTeams.find(item => item.slot === slot);
      return {
        slot,
        name: (team?.name || `Team ${slot}`).trim() || `Team ${slot}`,
        isUserTeam: slot === nextUserSlot,
      };
    });
    const userTeam = normalizedTeams.find(team => team.slot === nextUserSlot);
    return onLeagueChange({
      ...activeLeague,
      teamCount: nextTeamCount,
      draftPosition: nextUserSlot,
      scoring: normalizedScoring(overrides.scoring || scoring),
      rosterConfig: overrides.rosterConfig || rosterConfig,
      teamName: userTeam?.name || activeLeague.teamName || "My Team",
      teams: normalizedTeams,
    });
  }

  function changeTeamCount(nextCount) {
    setTeamCount(nextCount);
    const nextUserSlot = Math.min(userSlot, nextCount);
    setUserSlot(nextUserSlot);
    const nextTeams = Array.from({ length: nextCount }, (_, index) => {
      const slot = index + 1;
      const current = draftTeams.find(team => team.slot === slot);
      return {
        slot,
        name: slot === nextUserSlot
          ? (activeLeague?.teamName || current?.name || "My Team")
          : (current?.name || `Team ${slot}`),
        isUserTeam: slot === nextUserSlot,
      };
    });
    setDraftTeams(nextTeams);
    persistLeagueSetup(nextTeams, { teamCount: nextCount, userSlot: nextUserSlot });
  }

  function changeUserSlot(nextUserSlot) {
    setUserSlot(nextUserSlot);
    const nextTeams = Array.from({ length: teamCount }, (_, index) => {
      const slot = index + 1;
      const current = draftTeams.find(team => team.slot === slot);
      const wasUserTeam = current?.isUserTeam || slot === userSlot;
      return {
        slot,
        name: slot === nextUserSlot
          ? (activeLeague?.teamName || "My Team")
          : (wasUserTeam ? `Team ${slot}` : (current?.name || `Team ${slot}`)),
        isUserTeam: slot === nextUserSlot,
      };
    });
    setDraftTeams(nextTeams);
    persistLeagueSetup(nextTeams, { userSlot: nextUserSlot });
  }

  function changeScoring(nextScoring) {
    setScoring(nextScoring);
    persistLeagueSetup(draftTeams, { scoring: nextScoring });
  }

  function changeTeamName(slot, name) {
    setDraftTeams(current => current.map(team => team.slot === slot ? { ...team, name } : team));
  }

  function commitTeamNames() {
    persistLeagueSetup(draftTeams);
  }

  function createDraftRecord(player, teamNumber, draftPickIndex, availableAtPick = []) {
    const pick = draftPickIndex + 1;
    const enriched = player.adjusted ? player : window.enrichDraftPlayer(player, scoring, null, pick, window.findNextUserPick(draftOrder, draftPickIndex, userSlot));
    const boardBand = window.marketBandForPick(pick, enriched.adp, teamCount).label;
    const grade = window.draftStockGradeForPick({ ...enriched, valueLabel: boardBand }, pick, teamCount);
    const ranked = (availableAtPick || []).slice(0, 36).map((p, i) => {
      const gmBand = window.gmBandForPlayer(p, pick, i + 1);
      return { ...p, valueLabel: window.marketBandForPick(pick, p.adp, teamCount).label, gmBandScore: gmBand.score };
    }).sort((a, b) => (b.gmBandScore || -999) - (a.gmBandScore || -999) || a.adp - b.adp);
    const selected = ranked.find(p => p.id === player.id) || enriched;
    const bestAvailable = ranked[0];
    const stealAvailable = ranked.find(p => p.valueLabel && p.valueLabel.includes("Steal"));

    return {
      teamId: `t${teamNumber}`,
      pick,
      roundPick: window.formatRoundPick(draftPickIndex, teamCount),
      adpDelta: Math.round((pick - (Number(enriched.adp) || pick)) * 10) / 10,
      liveExpectedPick: selected.liveExpectedPick || null,
      liveAvailableRank: selected.liveAvailableRank || null,
      selectedBand: boardBand,
      boardBand,
      draftScore: grade.score,
      draftGrade: grade.letter,
      draftGradeColor: grade.color,
      teamCount,
      valueScore: window.seasonValueScore(enriched),
      modelScore: window.cfModelScore(enriched),
      sosScore: window.sosScore(enriched),
      bestAvailable: bestAvailable ? { id: bestAvailable.id, name: bestAvailable.name, label: bestAvailable.valueLabel, adp: bestAvailable.adp } : null,
      stealAvailable: stealAvailable ? { id: stealAvailable.id, name: stealAvailable.name, label: stealAvailable.valueLabel, adp: stealAvailable.adp } : null,
    };
  }

  function draftPlayer(playerId, forcedTeamNumber = currentTeamNumber) {
    if (!forcedTeamNumber || draftedByPlayerId[playerId]) return;
    const player = availablePlayers.find(p => p.id === playerId) || board.find(p => p.id === playerId) || basePlayers.find(p => p.id === playerId);
    if (!player) return;

    const localDrafted = { ...draftedByPlayerId, [playerId]: createDraftRecord(player, forcedTeamNumber, pickIndex, availablePlayers) };
    let localPickIndex = Math.min(pickIndex + 1, draftOrder.length);

    if (forcedTeamNumber === userSlot) {
      while (localPickIndex < draftOrder.length && draftOrder[localPickIndex] !== userSlot) {
        const teamNumber = draftOrder[localPickIndex];
        const localBoardWithBands = window.applyDraftLiveState
          ? window.applyDraftLiveState(scoredBoard, localDrafted, localPickIndex + 1, teamCount)
          : window.applyLiveBoardBands(
            scoredBoard.map((item) => ({ ...item, drafted: localDrafted[item.id] || null })),
            localPickIndex + 1,
            teamCount,
          );
        const localRosters = window.buildRosters(localBoardWithBands, teams, localDrafted);
        const localAvailable = localBoardWithBands.filter(p => !p.drafted);
        const pick = window.chooseComputerPick(localAvailable, localRosters[`t${teamNumber}`] || [], localPickIndex + 1, { scoring, teamCount, rosterSlots });
        if (!pick) break;
        localDrafted[pick.id] = createDraftRecord(pick, teamNumber, localPickIndex, localAvailable);
        localPickIndex += 1;
      }
    }

    setDraftedByPlayerId(localDrafted);
    setQueue(prev => prev.filter(id => !localDrafted[id]));
    setPickIndex(localPickIndex);
  }

  function draftLeaguePlayer(playerId) {
    if (!currentTeamNumber || draftedByPlayerId[playerId] || pickIndex >= draftOrder.length) return;
    const player = availablePlayers.find(p => p.id === playerId) || board.find(p => p.id === playerId) || basePlayers.find(p => p.id === playerId);
    if (!player) return;
    const record = createDraftRecord(player, currentTeamNumber, pickIndex, availablePlayers);
    const localDrafted = { ...draftedByPlayerId, [playerId]: record };
    setDraftedByPlayerId(localDrafted);
    setQueue(prev => prev.filter(id => !localDrafted[id]));
    setPickIndex(prev => Math.min(prev + 1, draftOrder.length));
    if (manualLive && activeLeague?.id && typeof onSavePick === "function") {
      onSavePick(activeLeague.id, {
        pick: record.pick,
        roundNumber: Math.floor((record.pick - 1) / teamCount) + 1,
        roundPick: record.roundPick,
        teamSlot: currentTeamNumber,
        teamName: teams[currentTeamNumber - 1]?.name || `Team ${currentTeamNumber}`,
        playerId,
        playerName: player.name,
        playerPosition: player.pos || null,
        playerTeam: player.team || null,
      });
    }
  }

  function undoDraftPick(playerId) {
    const record = draftedByPlayerId[playerId];
    if (!record) return;
    const rewindTo = Math.max(1, Number(record.pick) || 1);
    const nextDrafted = {};
    Object.entries(draftedByPlayerId).forEach(([id, pick]) => {
      if ((Number(pick.pick) || 0) < rewindTo) nextDrafted[id] = pick;
    });
    setDraftedByPlayerId(nextDrafted);
    setPickIndex(rewindTo - 1);
    setShowDraftFinishedAsk(false);
    setShowDraftComplete(false);
    setDraftPersisted(false);
  }

  function picksForPersist() {
    return Object.entries(draftedByPlayerId).map(([playerId, record]) => {
      const player = basePlayers.find(item => item.id === playerId)
        || board.find(item => item.id === playerId);
      const teamSlot = Number(String(record.teamId || "").replace("t", "")) || 1;
      return {
        pick: record.pick,
        roundNumber: Math.floor((record.pick - 1) / teamCount) + 1,
        roundPick: record.roundPick,
        teamSlot,
        teamName: teams[teamSlot - 1]?.name || `Team ${teamSlot}`,
        playerId,
        playerName: player?.name || "",
        playerPosition: player?.pos || null,
        playerTeam: player?.team || null,
      };
    }).sort((a, b) => a.pick - b.pick);
  }

  async function confirmDraftFinished() {
    skipFinishPrompt.current = true;
    if (manualLive && activeLeague?.id) {
      const userTeam = draftTeams.find((team) => team.slot === userSlot);
      await persistLeagueSetup(draftTeams, { userSlot });
      if (typeof onFinishDraft === "function") {
        await onFinishDraft(activeLeague.id, picksForPersist(), {
          draftPosition: userSlot,
          teamName: userTeam?.name || activeLeague.teamName,
          teams: draftTeams,
        });
        setDraftPersisted(true);
      }
    }
    setShowDraftFinishedAsk(false);
    setShowDraftComplete(true);
  }

  function autoPickOne() {
    if (!currentTeamNumber || pickIndex >= draftOrder.length) return;
    const teamRoster = rosters[`t${currentTeamNumber}`] || [];
    const pick = window.chooseComputerPick(availablePlayers, teamRoster, pickNumber, { scoring, teamCount, rosterSlots });
    if (pick) draftPlayer(pick.id, currentTeamNumber);
  }

  function simToUserPick() {
    let localPickIndex = pickIndex;
    const localDrafted = { ...draftedByPlayerId };
    while (localPickIndex < draftOrder.length && draftOrder[localPickIndex] !== userSlot) {
      const teamNumber = draftOrder[localPickIndex];
      const localBoardWithBands = window.applyDraftLiveState
        ? window.applyDraftLiveState(scoredBoard, localDrafted, localPickIndex + 1, teamCount)
        : window.applyLiveBoardBands(
          scoredBoard.map((item) => ({ ...item, drafted: localDrafted[item.id] || null })),
          localPickIndex + 1,
          teamCount,
        );
      const localRosters = window.buildRosters(localBoardWithBands, teams, localDrafted);
      const localAvailable = localBoardWithBands.filter(p => !p.drafted);
      const pick = window.chooseComputerPick(localAvailable, localRosters[`t${teamNumber}`] || [], localPickIndex + 1, { scoring, teamCount, rosterSlots });
      if (!pick) break;
      localDrafted[pick.id] = createDraftRecord(pick, teamNumber, localPickIndex, localAvailable);
      localPickIndex += 1;
    }
    setDraftedByPlayerId(localDrafted);
    setPickIndex(localPickIndex);
    setQueue(prev => prev.filter(id => !localDrafted[id]));
  }

  function toggleQueue(playerId) {
    if (draftedByPlayerId[playerId]) return;
    setQueue(prev => prev.includes(playerId) ? prev.filter(id => id !== playerId) : [...prev, playerId]);
  }

  function addToQueue(playerId) {
    if (draftedByPlayerId[playerId]) return;
    setQueue(prev => prev.includes(playerId) ? prev : [...prev, playerId]);
  }

  const answer = window.buildGmAnswer(submittedQuestion, gm, userRoster, {
    scoring,
    grade,
    pickNumber,
    nextUserPick,
    teamCount,
    rosterSlots,
    userSlot,
  });
  const showClock = simStarted && isUserTurn && mode === "simulator";
  const clockLabel = mode === "league"
    ? (simStarted ? "Live entry" : "Not started")
    : simStarted ? (isUserTurn ? "Your clock" : "CPU pick") : "Not started";

  if (window.DRAFT_BOARD_PAUSED && !(activeLeague?.picks || []).length) {
    return (
      <div className="view-enter" style={{ maxWidth: 900, margin: "0 auto", padding: "48px 24px" }}>
        <div className="card" style={{ padding: 28 }}>
          <div className="mono" style={{ color: "var(--gold)", fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase" }}>Draft board paused</div>
          <h1 className="display" style={{ margin: "10px 0 8px", color: "var(--mint-soft)" }}>Draft board paused</h1>
          <p style={{ margin: 0, color: "var(--slate)", lineHeight: 1.6 }}>
            The draft board is intentionally disabled in this environment.
          </p>
        </div>
      </div>
    );
  }

  const projectionsLoading = window.REQUIRE_RAPIDAPI_DATA
    && (!nflStatus.projections || nflStatus.projections === "loading")
    && !basePlayers.length;
  const projectionsFailed = window.REQUIRE_RAPIDAPI_DATA
    && nflStatus.projections === "unavailable"
    && !basePlayers.length
    && !(activeLeague?.picks || []).length;
  const projectionsReady = window.REQUIRE_RAPIDAPI_DATA
    && nflStatus.projections === "live"
    && window.PROJECTIONS_OK;

  if (projectionsLoading) {
    return (
      <div className="view-enter" style={{ maxWidth: 900, margin: "0 auto", padding: "48px 24px" }}>
        <div className="card" style={{ padding: 28 }}>
          <div className="mono" style={{ color: "var(--mint)", fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase" }}>Loading projections</div>
          <h1 className="display" style={{ margin: "10px 0 8px", color: "var(--mint-soft)" }}>Building draft board</h1>
          <p style={{ margin: 0, color: "var(--slate)", lineHeight: 1.6 }}>
            Waiting for <code>/api/nfl/projections</code>. First load may take up to a minute.
          </p>
        </div>
      </div>
    );
  }
  if (projectionsFailed) {
    return (
      <div className="view-enter" style={{ maxWidth: 900, margin: "0 auto", padding: "48px 24px" }}>
        <div className="card" style={{ padding: 28 }}>
          <div className="mono" style={{ color: "var(--red)", fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase" }}>Projection load failed</div>
          <h1 className="display" style={{ margin: "10px 0 8px", color: "var(--mint-soft)" }}>Could not load projections</h1>
          <p style={{ margin: 0, color: "var(--slate)", lineHeight: 1.6 }}>
            {nflStatus.message || "The live projection request failed. Retry when the API is available."}
          </p>
          <button className="btn" onClick={() => window.hydrateProjectionsFromApi?.()} style={{ marginTop: 18 }}>
            Retry
          </button>
        </div>
      </div>
    );
  }
  if (projectionsReady && !basePlayers.length) {
    return (
      <div className="view-enter" style={{ maxWidth: 900, margin: "0 auto", padding: "48px 24px" }}>
        <div className="card" style={{ padding: 28 }}>
          <div className="mono" style={{ color: "var(--gold)", fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase" }}>Empty player pool</div>
          <h1 className="display" style={{ margin: "10px 0 8px", color: "var(--mint-soft)" }}>No draft players available</h1>
          <p style={{ margin: 0, color: "var(--slate)", lineHeight: 1.6 }}>
            Projections loaded successfully but returned no draftable players for this scoring format.
          </p>
        </div>
      </div>
    );
  }

  return (
    <div className="view-enter" style={{ maxWidth: 1440, margin: "0 auto", padding: "20px 24px 28px" }}>

      {/* ───── Compact hero ───── */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 16, marginBottom: 14 }}>
        <div>
          <div className="mono" style={{ fontSize: 10, color: "var(--mint)", textTransform: "uppercase", letterSpacing: "0.18em", marginBottom: 4 }}>
            {manualLive
              ? `Draft Live · ${teamCount}-team snake · ${scoring.toUpperCase()} · writes to your league`
              : `Mock Draft · ${teamCount}-team snake · ${scoring.toUpperCase()} · practice only`}
          </div>
          <h1 className="display" style={{ margin: 0, fontSize: 30, color: "var(--mint-soft)", lineHeight: 1 }}>{manualLive ? "Draft Live" : "Draft Board"}</h1>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
          {!manualLive && !simStarted && <button className="btn" onClick={startSimulator}>Start Mock Draft</button>}
          {manualLive && !simStarted && (
            <button className="btn" onClick={activeLeague ? startLeagueDraft : onRequestLeague}>
              {activeLeague ? "Start Live Draft" : "Add a League First"}
            </button>
          )}
          {!manualLive && (
            <>
              <button className="btn ghost" onClick={simToUserPick} disabled={!simStarted || isUserTurn || pickIndex >= draftOrder.length} style={{ opacity: !simStarted || isUserTurn ? 0.45 : 1 }}>Sim to My Pick</button>
              <button className="btn" onClick={() => isUserTurn ? draftPlayer(gm.best?.id) : autoPickOne()} disabled={!gm.best || !simStarted}>
                <window.IconBolt size={14} stroke="var(--black)" />
                {isUserTurn ? "Take GM Pick" : "Auto Pick"}
              </button>
            </>
          )}
          <button className="btn ghost" onClick={resetDraft} style={{ padding: "8px 12px", fontSize: 12 }}>Reset</button>
        </div>
      </div>

      {/* ───── Sticky top: settings bar + active roster band ───── */}
      <div style={{
        position: "sticky", top: 64, zIndex: 30,
        marginLeft: -24, marginRight: -24, padding: "10px 24px 4px",
        background: "rgba(5,8,7,0.92)", backdropFilter: "blur(10px)",
        borderBottom: "1px solid var(--green-600)",
      }}>
        <SettingsBar
          showSettings={showSettings}
          setShowSettings={setShowSettings}
          currentTeam={currentTeam}
          simStarted={simStarted}
          isUserTurn={isUserTurn}
          pickNumber={pickNumber}
          nextUserPick={nextUserPick}
          teamCount={teamCount}
          setTeamCount={manualLive ? changeTeamCount : setTeamCount}
          userSlot={userSlot}
          setUserSlot={manualLive ? changeUserSlot : setUserSlot}
          scoring={scoring}
          setScoring={manualLive ? changeScoring : setScoring}
          rosterConfig={rosterConfig}
          setRosterConfig={setRosterConfig}
          rosterSlots={rosterSlots}
          turnSeconds={turnSeconds}
          clockLabel={clockLabel}
          showClock={showClock}
          hideClock={manualLive}
          grade={grade}
          boardSettings={boardSettings}
        />

        <RosterBand userRoster={userRoster} rosterSlots={rosterSlots} />
        {manualLive && (
          <TeamBand
            teams={teams}
            currentTeam={currentTeam}
            locked={pickIndex > 0}
            onTeamNameChange={changeTeamName}
            onTeamNamesCommit={commitTeamNames}
          />
        )}
      </div>

      {/* ───── Main 2-column grid: GM column (bands + Ask GM) | Board ───── */}
      <div style={{ display: "grid", gridTemplateColumns: "272px minmax(0, 1fr)", gap: 14, alignItems: "stretch" }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 12, minWidth: 0 }}>
          <GmPanel gm={gm} bands={gmBands} onQueue={toggleQueue} />
          <GmInteractionBox
            question={question} setQuestion={setQuestion}
            onSubmit={() => setSubmittedQuestion(question)}
            answer={answer}
            gm={gm}
            userRoster={userRoster}
            pickNumber={pickNumber}
            onQueueDrop={addToQueue}
            rosterSlots={rosterSlots}
          />
        </div>

        <BoardCard
          boardScrollRef={boardScrollRef}
          mode={mode} setMode={setMode}
          liveRoom={manualLive}
          pos={pos} setPos={setPos}
          search={search} setSearch={setSearch}
          players={filtered}
          availablePlayers={availablePlayers}
          teams={teams}
          rosters={rosters}
          pickLog={pickLog}
          userRoster={userRoster}
          grade={grade}
          gm={gm}
          draftOrder={draftOrder}
          pickNumber={pickNumber}
          teamCount={teamCount}
          rounds={rounds}
          queue={queue}
          isUserTurn={isUserTurn}
          simStarted={simStarted}
          onDraft={manualLive ? draftLeaguePlayer : draftPlayer}
          onQueue={toggleQueue}
          onQueueDrop={addToQueue}
          onUndoPick={undoDraftPick}
          onSelectPlayer={onSelectPlayer}
          rosterSlots={rosterSlots}
        />
      </div>

      {showDraftFinishedAsk && (
        <DraftFinishedAskModal
          onYes={confirmDraftFinished}
          onNo={() => setShowDraftFinishedAsk(false)}
        />
      )}
      {showDraftComplete && (
        <DraftCompleteModal
          grade={grade}
          onReview={reviewDraft}
          onClose={() => setShowDraftComplete(false)}
          onReset={resetDraft}
        />
      )}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// Settings bar — always-on info strip + collapsible draft-settings card.
// Always visible: status · clock · pick context (info during the draft)
// Collapsed: chevron + summary chip line
// Expanded: 4 selects + 8 roster steppers + ranking source caption
// ────────────────────────────────────────────────────────────────────────────
function SettingsBar({
  showSettings, setShowSettings,
  currentTeam, simStarted, isUserTurn, pickNumber, nextUserPick,
  teamCount, setTeamCount, userSlot, setUserSlot, scoring, setScoring,
  rosterConfig, setRosterConfig, rosterSlots,
  turnSeconds, clockLabel, showClock, hideClock = false, grade, boardSettings,
}) {
  const statusValue = !simStarted ? "Not Started"
    : !currentTeam ? "Complete"
    : currentTeam.isUser ? "You're on the clock"
    : `${currentTeam.name} picking`;
  const shapeLabel = window.rosterShapeLabel({ teamCount, rosterConfig }, scoring);
  const replacementLabel = window.replacementSummaryLabel(boardSettings?.replacementRanks || {});

  return (
    <div className="card" style={{ padding: 10, marginBottom: 10 }}>
      {/* Always-on info strip: status · draft grade · clock · pick context · settings toggle */}
      <div style={{ display: "grid", gridTemplateColumns: hideClock
        ? "minmax(160px, 1.1fr) minmax(160px, 1.1fr) auto minmax(0, 1fr) auto"
        : "minmax(160px, 1.1fr) minmax(160px, 1.1fr) auto auto minmax(0, 1fr) auto", gap: 8, alignItems: "stretch" }}>
        <StatusPill label={simStarted ? "On clock" : "Status"} value={statusValue} active={showClock} foot={
          !simStarted ? (hideClock ? "Click Start Live Draft when ready" : "Click Start Mock Draft when ready")
          : currentTeam ? `Pick ${pickNumber} · next yours ${nextUserPick || "done"}`
          : "Draft complete"
        } />
        <DraftGradePill grade={grade} />
        {!hideClock && <ClockChip seconds={showClock ? turnSeconds : 90} active={showClock} label={clockLabel} />}
        <PickContextChip pickNumber={pickNumber} teamCount={teamCount} />

        {!showSettings && (
          <div className="mono" style={{ display: "flex", alignItems: "center", gap: 14, color: "var(--mint-soft)", fontSize: 11, letterSpacing: "0.04em", paddingLeft: 4, flexWrap: "wrap" }}>
            <span style={{ color: "var(--slate)" }}>Teams<span style={{ color: "var(--mint)", marginLeft: 4 }}>{teamCount}</span></span>
            <span style={{ color: "var(--slate)" }}>Pos<span style={{ color: "var(--mint)", marginLeft: 4 }}>{userSlot}</span></span>
            <span style={{ color: "var(--slate)" }}>{scoring.toUpperCase()}</span>
            <span style={{ color: "var(--slate)" }}>949 Overall</span>
            <span style={{ color: "var(--slate-dim)", padding: "0 6px" }}>·</span>
            {["QB", "RB", "WR", "TE", "FLEX", "SUPERFLEX", "DST", "K", "BENCH"].map(slot => rosterConfig[slot] > 0 && (
              <span key={slot} style={{ color: "var(--slate)" }}>
                {slot}<span style={{ color: "var(--mint)", marginLeft: 4 }}>{rosterConfig[slot]}</span>
              </span>
            ))}
          </div>
        )}
        {showSettings && <div />}

        <button
          onClick={() => setShowSettings(o => !o)}
          style={{
            display: "inline-flex", alignItems: "center", gap: 8,
            padding: "6px 12px", borderRadius: 8,
            background: "var(--green-900)", border: "1px solid var(--green-600)",
            color: "var(--mint-soft)", cursor: "pointer",
            fontFamily: "Sora", fontSize: 11,
            alignSelf: "center"
          }}>
          <span className="mono" style={{ color: "var(--mint)", letterSpacing: "0.1em", textTransform: "uppercase", fontSize: 9 }}>Settings</span>
          <span style={{ transform: showSettings ? "rotate(90deg)" : "rotate(0deg)", display: "inline-flex", transition: "transform 0.15s" }}>
            <window.IconChevron size={10} />
          </span>
        </button>
      </div>

      {/* Expanded settings panel */}
      {showSettings && (
        <div style={{ marginTop: 10, paddingTop: 10, borderTop: "1px solid var(--green-600)" }}>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(3, minmax(0, 1fr))", gap: 8 }}>
            <CompactSelect label="Teams" value={teamCount} onChange={v => setTeamCount(Number(v))} options={[8, 10, 12, 14].map(n => ({ value: n, label: `${n}` }))} />
            <CompactSelect label="Your Pos" value={userSlot} onChange={v => setUserSlot(Number(v))} options={Array.from({ length: teamCount }, (_, i) => ({ value: i + 1, label: `${i + 1}` }))} />
            <CompactSelect label="Scoring" value={scoring} onChange={setScoring} options={[{ value: "ppr", label: "PPR" }, { value: "half", label: "Half" }, { value: "std", label: "Std" }]} />
          </div>

          <div className="mono" style={{ marginTop: 10, color: "var(--mint)", fontSize: 9, letterSpacing: "0.12em", textTransform: "uppercase" }}>Roster Layout</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(72px, 1fr))", gap: 6, marginTop: 6 }}>
            {["QB", "RB", "WR", "TE", "FLEX", "SUPERFLEX", "DST", "K", "BENCH"].map(slot => (
              <RosterStepper
                key={slot}
                label={slot}
                value={rosterConfig[slot] || 0}
                min={0}
                max={slot === "BENCH" ? 12 : slot === "FLEX" ? 3 : slot === "SUPERFLEX" ? 1 : slot === "DST" || slot === "K" ? 2 : 4}
                onChange={value => {
                  const next = { ...rosterConfig, [slot]: value };
                  setRosterConfig(next);
                  persistLeagueSetup(draftTeams, { rosterConfig: next });
                }}
              />
            ))}
          </div>

          <div className="mono" style={{ marginTop: 10, color: "var(--slate-dim)", fontSize: 10, letterSpacing: "0.06em", textTransform: "uppercase" }}>
            Ranking source · 949 Overall rankings · {shapeLabel} · {scoring.toUpperCase()} · Replacement {replacementLabel || "pending"}
          </div>
        </div>
      )}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// Roster band — horizontal active-roster strip above the board.
// One pill per slot; "Open" until a player is drafted into it.
// ────────────────────────────────────────────────────────────────────────────
function RosterBand({ userRoster, rosterSlots }) {
  const slots = Array.isArray(rosterSlots) ? rosterSlots : (window.buildRosterSlots ? window.buildRosterSlots(rosterSlots || window.DEFAULT_ROSTER_CONFIG) : []);
  const assigned = window.assignRosterSlots(userRoster, slots);
  return (
    <div className="card" style={{ padding: 10, marginBottom: 12 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 6 }}>
        <span className="mono" style={{ fontSize: 9, color: "var(--mint)", letterSpacing: "0.16em", textTransform: "uppercase" }}>Active Roster</span>
        <span className="mono" style={{ fontSize: 10, color: "var(--slate-dim)" }}>{userRoster.length}/{slots.length}</span>
        <span style={{ flex: 1, height: 1, background: "linear-gradient(to right, var(--green-600), transparent)" }} />
        <span className="mono" style={{ fontSize: 9, color: "var(--slate-dim)", letterSpacing: "0.06em", textTransform: "uppercase" }}>Other teams: open Live tab</span>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: `repeat(${Math.max(1, slots.length)}, minmax(0, 1fr))`, gap: 5 }}>
        {slots.map((slot, i) => {
          const player = assigned[i];
          const posColor = player ? window.positionColor(player.pos) : "var(--slate-dim)";
          const tier = player ? window.playerTier(player) : null;
          return (
            <div key={`${slot}-${i}`} style={{
              padding: "6px 8px", borderRadius: 6,
              background: player ? "var(--green-900)" : "rgba(12,26,19,0.55)",
              border: `1px solid ${player ? `${posColor}55` : "var(--green-600)"}`,
              minWidth: 0,
            }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 6 }}>
                <span className="mono" style={{ fontSize: 9, color: posColor, letterSpacing: "0.08em", textTransform: "uppercase", fontWeight: 700 }}>{slot}</span>
                {tier && <span className="mono" style={{ fontSize: 8, color: tier.color, fontWeight: 900, letterSpacing: "0.06em", textTransform: "uppercase" }}>{tier.label}</span>}
              </div>
              <div style={{ marginTop: 3, fontSize: 11, lineHeight: 1.15, color: player ? "var(--mint-soft)" : "var(--slate-dim)", fontWeight: player ? 700 : 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                {player ? player.name : "Open"}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function TeamBand({ teams, currentTeam, locked, onTeamNameChange, onTeamNamesCommit }) {
  return (
    <div className="card" style={{ padding: 10, marginBottom: 12, overflow: "hidden" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 6 }}>
        <span className="mono" style={{ fontSize: 9, color: "var(--mint)", letterSpacing: "0.16em", textTransform: "uppercase" }}>League Teams</span>
        <span className="mono" style={{ fontSize: 10, color: "var(--slate-dim)" }}>{teams.length} slots</span>
        <span style={{ flex: 1, height: 1, background: "linear-gradient(to right, var(--green-600), transparent)" }} />
        <span className="mono" style={{ fontSize: 9, color: locked ? "var(--gold)" : "var(--slate-dim)", letterSpacing: "0.06em", textTransform: "uppercase" }}>
          {locked ? "Names locked after first pick" : "Enter every team before the draft"}
        </span>
      </div>
      <div style={{ overflowX: "auto", paddingBottom: 2 }}>
        <div style={{ display: "grid", gridTemplateColumns: `repeat(${teams.length}, minmax(108px, 1fr))`, gap: 5, minWidth: teams.length * 113 }}>
          {teams.map(team => {
            const onClock = currentTeam?.id === team.id;
            return (
              <label key={team.id} style={{
                display: "grid", gap: 4, minWidth: 0,
                padding: "6px 8px", borderRadius: 6,
                background: team.isUser ? "rgba(149,249,174,0.09)" : "rgba(12,26,19,0.55)",
                border: `1px solid ${onClock || team.isUser ? "var(--mint)" : "var(--green-600)"}`,
              }}>
                <span className="mono" style={{ display: "flex", justifyContent: "space-between", gap: 5, color: team.isUser ? "var(--mint)" : "var(--slate)", fontSize: 8, letterSpacing: "0.08em", textTransform: "uppercase" }}>
                  <span>Slot {team.slot}</span>
                  <span>{team.isUser ? "You" : onClock ? "On clock" : ""}</span>
                </span>
                <input
                  aria-label={`Team name for draft slot ${team.slot}`}
                  value={team.name}
                  disabled={locked}
                  onChange={event => onTeamNameChange(team.slot, event.target.value)}
                  onBlur={onTeamNamesCommit}
                  style={{
                    width: "100%", minWidth: 0, padding: 0,
                    color: team.isUser ? "var(--mint-soft)" : "var(--slate)",
                    background: "transparent", border: "none", outline: "none",
                    fontFamily: "Sora", fontSize: 11, fontWeight: 700,
                    textOverflow: "ellipsis",
                  }}
                />
              </label>
            );
          })}
        </div>
      </div>
    </div>
  );
}

function DraftGradePill({ grade }) {
  const hasPicks = grade && grade.letter !== "—";
  const color = hasPicks ? grade.color : "var(--slate-dim)";
  return (
    <div style={{
      padding: "8px 12px", borderRadius: 9,
      background: "var(--green-900)",
      border: `1px solid ${hasPicks ? color + "55" : "var(--green-600)"}`,
      display: "flex", flexDirection: "column", justifyContent: "center", minWidth: 0
    }}>
      <div className="mono" style={{ fontSize: 9, color: "var(--slate)", textTransform: "uppercase", letterSpacing: "0.1em" }}>Draft Grade</div>
      <div style={{ display: "flex", alignItems: "center", gap: 10, marginTop: 4 }}>
        <span className="num" style={{ color, fontSize: 26, fontWeight: 900, lineHeight: 1, letterSpacing: "-0.04em" }}>{hasPicks ? grade.letter : "—"}</span>
        <span className="mono" style={{ color: "var(--slate)", fontSize: 10, lineHeight: 1.3, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", minWidth: 0 }}>
          {hasPicks ? grade.note : "Awaiting first pick"}
        </span>
      </div>
    </div>
  );
}

function StatusPill({ label, value, foot, active }) {
  return (
    <div style={{
      padding: "8px 12px", borderRadius: 9,
      background: "var(--green-900)",
      border: `1px solid ${active ? "var(--mint)" : "var(--green-600)"}`,
      display: "flex", flexDirection: "column", justifyContent: "center", minWidth: 0
    }}>
      <div className="mono" style={{ fontSize: 9, color: "var(--slate)", textTransform: "uppercase", letterSpacing: "0.1em" }}>{label}</div>
      <div className="num" style={{ marginTop: 4, fontSize: 16, color: active ? "var(--mint)" : "var(--mint-soft)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", lineHeight: 1.1 }}>{value}</div>
      {foot && <div className="mono" style={{ marginTop: 3, fontSize: 9, color: "var(--slate-dim)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{foot}</div>}
    </div>
  );
}

function CompactSelect({ label, value, onChange, options }) {
  return (
    <label style={{ display: "flex", flexDirection: "column", padding: "8px 10px", borderRadius: 9, background: "var(--green-900)", border: "1px solid var(--green-600)", minWidth: 0, cursor: "pointer" }}>
      <span className="mono" style={{ fontSize: 9, color: "var(--slate)", textTransform: "uppercase", letterSpacing: "0.1em" }}>{label}</span>
      <select value={value} onChange={e => onChange(e.target.value)} style={{
        marginTop: 2, width: "100%", background: "transparent", border: "none",
        color: "var(--mint-soft)", fontFamily: "Space Grotesk", fontWeight: 700,
        fontSize: 18, outline: "none", appearance: "none", padding: 0, lineHeight: 1.1
      }}>
        {options.map(o => <option key={o.value} value={o.value} style={{ background: "var(--green-900)" }}>{o.label}</option>)}
      </select>
    </label>
  );
}

function ClockChip({ seconds, active, label }) {
  return (
    <div style={{
      display: "flex", flexDirection: "column", justifyContent: "center",
      padding: "6px 12px", borderRadius: 9,
      background: "var(--green-900)",
      border: `1px solid ${active ? "var(--mint)" : "var(--green-600)"}`,
      boxShadow: active ? "0 0 18px rgba(149,249,174,0.12)" : "none",
      minWidth: 96
    }}>
      <span className="mono" style={{ color: active ? "var(--mint)" : "var(--slate)", fontSize: 9, letterSpacing: "0.1em", textTransform: "uppercase", whiteSpace: "nowrap" }}>{label}</span>
      <span className="num" style={{ color: active ? "var(--mint)" : "var(--mint-soft)", fontSize: 20, lineHeight: 1, marginTop: 3 }}>{window.formatClock(seconds)}</span>
    </div>
  );
}

function PickContextChip({ pickNumber, teamCount }) {
  const round = Math.floor((pickNumber - 1) / teamCount) + 1;
  const pick = ((pickNumber - 1) % teamCount) + 1;
  return (
    <div style={{
      display: "flex", flexDirection: "column", justifyContent: "center", gap: 3,
      padding: "6px 12px", borderRadius: 9,
      background: "var(--green-900)", border: "1px solid var(--green-600)",
    }}>
      <span className="mono" style={{ color: "var(--slate)", fontSize: 9, letterSpacing: "0.1em", textTransform: "uppercase" }}>Pick context</span>
      <span style={{ display: "flex", gap: 10 }}>
        <span className="mono" style={{ color: "var(--slate)", fontSize: 10, letterSpacing: "0.06em", textTransform: "uppercase" }}>R<strong style={{ color: "var(--mint-soft)", fontSize: 12 }}> {round}</strong></span>
        <span className="mono" style={{ color: "var(--slate)", fontSize: 10, letterSpacing: "0.06em", textTransform: "uppercase" }}>P<strong style={{ color: "var(--mint-soft)", fontSize: 12 }}> {pick}</strong></span>
        <span className="mono" style={{ color: "var(--slate)", fontSize: 10, letterSpacing: "0.06em", textTransform: "uppercase" }}>OA<strong style={{ color: "var(--mint-soft)", fontSize: 12 }}> {pickNumber}</strong></span>
      </span>
    </div>
  );
}

function RosterStepper({ label, value, min, max, onChange }) {
  return (
    <div style={{ padding: 7, borderRadius: 8, background: "var(--green-900)", border: "1px solid var(--green-600)" }}>
      <div className="mono" style={{ color: "var(--slate)", fontSize: 9, textTransform: "uppercase", letterSpacing: "0.08em" }}>{label}</div>
      <div style={{ display: "grid", gridTemplateColumns: "22px 1fr 22px", alignItems: "center", gap: 4, marginTop: 5 }}>
        <button onClick={() => onChange(Math.max(min, value - 1))} style={stepBtn}>−</button>
        <span className="num" style={{ color: "var(--mint-soft)", fontSize: 18, textAlign: "center" }}>{value}</span>
        <button onClick={() => onChange(Math.min(max, value + 1))} style={stepBtn}>+</button>
      </div>
    </div>
  );
}

const stepBtn = {
  width: 22, height: 22, borderRadius: 6, border: "1px solid var(--green-600)",
  background: "rgba(149,249,174,0.08)", color: "var(--mint)", cursor: "pointer",
  fontFamily: "Space Grotesk", fontWeight: 800, lineHeight: 1,
};

// ────────────────────────────────────────────────────────────────────────────
// GM Pick Bands — vertical sidebar with all 7 bands.
// ────────────────────────────────────────────────────────────────────────────
function GmPanel({ gm, bands, onQueue }) {
  return (
    <div className="card" style={{ padding: 12, display: "flex", flexDirection: "column", minHeight: 0 }}>
      <div style={{ marginBottom: 8, flex: "0 0 auto" }}>
        <div className="mono" style={{ fontSize: 9, color: "var(--mint)", textTransform: "uppercase", letterSpacing: "0.16em" }}>GM</div>
        <div className="display" style={{ fontSize: 15, color: "var(--mint-soft)", marginTop: 2 }}>Pick Bands</div>
      </div>
      <div style={{ display: "grid", gap: 6, overflow: "auto", maxHeight: 520, paddingRight: 4 }}>
        {bands.map(band => (
          <div key={band.label} style={{ padding: 7, borderRadius: 7, background: "var(--green-900)", border: "1px solid var(--green-600)" }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 5 }}>
              <span className="mono" style={{ fontSize: 9, color: "var(--mint)", letterSpacing: "0.1em", textTransform: "uppercase" }}>{band.label}</span>
            </div>
            <div style={{ display: "grid", gap: 4 }}>
              {band.players.length ? band.players.map((p, index) => (
                <button key={p.id} draggable onDragStart={e => e.dataTransfer.setData("text/plain", p.id)} onClick={() => onQueue(p.id)} style={{
                  display: "grid", gridTemplateColumns: "20px minmax(0, 1fr) 28px", gap: 6, alignItems: "center",
                  padding: "4px 6px", borderRadius: 5, border: `1px solid ${window.positionColor(p.pos)}55`,
                  background: window.positionBg(p.pos), color: "inherit", cursor: "pointer", textAlign: "left",
                }}>
                  <span className="mono" style={{ color: window.positionColor(p.pos), fontSize: 9, fontWeight: 700 }}>{index + 1}</span>
                  <span style={{ color: "var(--mint-soft)", fontSize: 11, fontWeight: 700, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{p.name}</span>
                  <span className="mono" style={{ color: "var(--slate)", fontSize: 9, textAlign: "right" }}>{Number.isFinite(p.adp) && p.adp > 0 ? p.adp.toFixed(1) : "—"}</span>
                </button>
              )) : (
                <span style={{ color: "var(--slate-dim)", fontSize: 10, padding: "2px 0" }}>No players in range</span>
              )}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// Board card — search + mode/pos tabs + the board itself.
// ────────────────────────────────────────────────────────────────────────────
function BoardCard({
  boardScrollRef,
  mode, setMode, liveRoom, pos, setPos, search, setSearch,
  players, availablePlayers, teams, rosters, pickLog, userRoster, grade, gm,
  draftOrder, pickNumber, teamCount, rounds, queue, isUserTurn, simStarted,
  onDraft, onQueue, onQueueDrop, onUndoPick, onSelectPlayer, rosterSlots,
}) {
  return (
    <div className="card" style={{ overflow: "hidden" }}>
      <div style={{ padding: "12px 14px", borderBottom: "1px solid var(--green-600)", display: "grid", gap: 10 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
          <div className="mono" style={{ fontSize: 9, color: "var(--mint)", textTransform: "uppercase", letterSpacing: "0.16em" }}>
            {liveRoom ? (mode === "league" ? "League Draft" : mode === "live" ? "Live League" : mode === "score" ? "Draft Grade" : mode === "picks" ? "Round Grid" : "Board") : (mode === "live" ? "Mock Teams" : mode === "score" ? "Mock Grade" : mode === "picks" ? "Mock Picks" : "Mock Draft")}
          </div>
        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
          <TabBar
            tabs={liveRoom
              ? [{ id: "league", label: "Board" }, { id: "live", label: "Teams" }, { id: "picks", label: "Picks" }, { id: "score", label: "Score" }]
              : [{ id: "simulator", label: "Mock Board" }, { id: "live", label: "Teams" }, { id: "picks", label: "Picks" }, { id: "score", label: "Score" }]}
            value={mode}
            onChange={setMode}
          />
          <TabBar tabs={[{ id: "ALL", label: "All" }, { id: "QB", label: "QB" }, { id: "RB", label: "RB" }, { id: "WR", label: "WR" }, { id: "TE", label: "TE" }, { id: "FLEX", label: "Flex" }, { id: "K", label: "K" }, { id: "DST", label: "DST" }]} value={pos} onChange={setPos} />
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "6px 10px", borderRadius: 8, background: "var(--green-900)", border: "1px solid var(--green-600)" }}>
          <window.IconSearch size={13} stroke="var(--slate)" />
          <input value={search} onChange={e => setSearch(e.target.value)} placeholder="Search draft board" style={{ flex: 1, background: "transparent", border: "none", outline: "none", color: "var(--mint-soft)", fontFamily: "Sora", fontSize: 12 }} />
        </div>
      </div>
      <DraftBoardMode
        boardScrollRef={boardScrollRef}
        mode={mode}
        players={players}
        availablePlayers={availablePlayers}
        teams={teams}
        rosters={rosters}
        pickLog={pickLog}
        userRoster={userRoster}
        grade={grade}
        gm={gm}
        draftOrder={draftOrder}
        pickNumber={pickNumber}
        teamCount={teamCount}
        rounds={rounds}
        queue={queue}
        isUserTurn={isUserTurn}
        simStarted={simStarted}
        onDraft={onDraft}
        onQueue={onQueue}
        onQueueDrop={onQueueDrop}
        onUndoPick={onUndoPick}
        onSelectPlayer={onSelectPlayer}
        rosterSlots={rosterSlots}
      />
    </div>
  );
}

const DRAFT_TILE_MIN_WIDTH = 132;
const DRAFT_TILE_GAP = 6;

function DraftBoardMode({ boardScrollRef, mode, players, availablePlayers, teams, rosters, pickLog, userRoster, grade, gm, draftOrder, pickNumber, teamCount, rounds, queue, isUserTurn, simStarted, onDraft, onQueue, onQueueDrop, onUndoPick, onSelectPlayer, rosterSlots }) {
  const boardGridRef = React.useRef(null);
  const [boardColumnCount, setBoardColumnCount] = React.useState(1);

  React.useEffect(() => {
    const grid = boardGridRef.current;
    if (!grid) return;

    function syncColumnCount() {
      const width = grid.clientWidth || DRAFT_TILE_MIN_WIDTH;
      const nextCount = Math.max(1, Math.floor((width + DRAFT_TILE_GAP) / (DRAFT_TILE_MIN_WIDTH + DRAFT_TILE_GAP)));
      setBoardColumnCount(prev => prev === nextCount ? prev : nextCount);
    }

    syncColumnCount();
    const observer = new ResizeObserver(syncColumnCount);
    observer.observe(grid);
    return () => observer.disconnect();
  }, [mode]);

  const visiblePlayers = players;
  const clearedCount = players.length - visiblePlayers.length;
  const isLeagueMode = mode === "league";

  if (mode === "live") return <LiveLeagueBoard teams={teams} rosters={rosters} />;
  if (mode === "picks") return <PicksRoundBoard pickLog={pickLog} draftOrder={draftOrder} teams={teams} teamCount={teamCount} rounds={rounds} />;
  if (mode === "score") return <ScoreCardBoard userRoster={userRoster} grade={grade} gm={gm} pickLog={pickLog} rosterSlots={rosterSlots} teamCount={teamCount} />;

  return (
    <div
      ref={boardScrollRef}
      onDragOver={e => e.preventDefault()}
      onDrop={e => { e.preventDefault(); const id = e.dataTransfer.getData("text/plain"); if (id) onQueueDrop(id); }}
      style={{ padding: 12, maxHeight: 780, overflow: "auto", overscrollBehavior: "contain" }}
    >
      {clearedCount > 0 && (
        <div className="mono" style={{ marginBottom: 8, fontSize: 9, color: "var(--slate-dim)", letterSpacing: "0.08em", textTransform: "uppercase" }}>
          Cleared {clearedCount} taken player{clearedCount === 1 ? "" : "s"} from completed board row{clearedCount === boardColumnCount ? "" : "s"}
        </div>
      )}
      <div ref={boardGridRef} style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(132px, 1fr))", gap: 6 }}>
        {visiblePlayers.map(player => (
          <DraftPlayerTile
            key={player.id}
            player={player}
            queued={queue.includes(player.id)}
            canDraft={isLeagueMode ? simStarted : simStarted && isUserTurn}
            onDraft={() => onDraft(player.id)}
            onUndo={() => onUndoPick && onUndoPick(player.id)}
            onQueue={(event) => { event.stopPropagation(); onQueue(player.id); }}
            onSelect={() => onSelectPlayer && !player.synthetic && onSelectPlayer(player)}
            pickNumber={pickNumber}
            teamCount={teamCount}
          />
        ))}
      </div>
    </div>
  );
}

function collapseFullyDraftedRows(players, columnCount) {
  if (!players.length || columnCount <= 1) return players;
  let visible = players;
  let changed = true;

  while (changed) {
    changed = false;
    const next = [];

    for (let i = 0; i < visible.length; i += columnCount) {
      const row = visible.slice(i, i + columnCount);
      const isFullRow = row.length === columnCount;
      const allTaken = isFullRow && row.every(player => !!player.drafted);
      if (allTaken) {
        changed = true;
      } else {
        next.push(...row);
      }
    }

    visible = next;
  }

  return visible;
}

function DraftPlayerTile({ player, queued, canDraft = true, onDraft, onUndo, onQueue, onSelect, pickNumber = 1, teamCount = 12 }) {
  const team = window.TEAMS[player.team] || { color: "#2A4A37", name: player.team };
  const isGone = !!player.drafted;
  const posColor = window.positionColor(player.pos);
  const posBg = window.positionBg(player.pos);
  const valueGrade = window.seasonValueGrade(player);
  const liveGrade = queued && !isGone
    ? window.liveDraftGrade(player, { pickNumber, teamCount })
    : null;
  const positionRankLabel = player.positionRank
    ? `${player.pos}${player.positionRank}`
    : player.positionRankLabel || player.pos;
  const playerBadge = player.pos;
  const riskColor = player.risk === "high" ? "var(--red)" : player.risk === "med" ? "var(--gold)" : "var(--mint)";
  const seasonProjection = Number.isFinite(player.nine49Model?.s)
    ? Number(player.nine49Model.s)
    : Number.isFinite(player.projected_total)
    ? Number(player.projected_total)
    : Number.isFinite(player.ros)
    ? player.ros
    : Number.isFinite(player.adjusted)
      ? player.adjusted * 17
      : Number.isFinite(player.proj)
        ? player.proj * 17
        : 0;
  const adpPick = Number(player.liveDraftAdp) > 0
    ? Number(player.liveDraftAdp)
    : (player.adpSource && Number(player.adp) > 0 ? Number(player.adp) : null);
  const overallRank = player.overallRank || player.displayRank || null;

  return (
    <div style={{ position: "relative" }}>
    <button
      draggable={!isGone}
      onDragStart={e => e.dataTransfer.setData("text/plain", player.id)}
      onClick={isGone || !canDraft ? undefined : onDraft}
      onDoubleClick={onSelect}
      style={{
        position: "relative", overflow: "hidden", width: "100%",
        minHeight: 96, padding: "8px 9px",
        borderRadius: 8,
        border: `1px solid ${queued && !isGone ? posColor : `${posColor}40`}`,
        background: queued && !isGone
          ? `linear-gradient(135deg, ${posBg}, var(--green-900) 70%)`
          : "var(--green-900)",
        color: "var(--mint-soft)", textAlign: "left",
        cursor: isGone ? "default" : canDraft ? "pointer" : "grab",
        opacity: isGone ? 0.38 : 1,
        boxShadow: queued && !isGone ? `inset 0 0 0 2px ${posColor}88, 0 0 16px ${posColor}22` : "none",
        transition: "transform 0.12s, box-shadow 0.12s",
      }}
    >
      {/* Position-colored top accent line */}
      <div style={{ position: "absolute", top: 0, left: 0, right: 0, height: 2, background: posColor }} />

      {/* Top row: pos pill · team chip · position rank */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 4 }}>
        <span className="mono" style={{
          color: posColor, fontSize: 8, fontWeight: 700, letterSpacing: "0.08em",
          padding: "2px 5px", borderRadius: 3, border: `1px solid ${posColor}66`,
          background: `${posColor}14`,
        }}>{player.pos}</span>
        <span style={{ display: "flex", alignItems: "baseline", gap: 6, minWidth: 0 }}>
          <span className="mono" title="949 Value" style={{ color: valueGrade.color, fontSize: 16, fontWeight: 900, letterSpacing: "0.02em", lineHeight: 1 }}>{valueGrade.letter}</span>
          <span className="mono" title="Position rank" style={{ color: posColor, fontSize: 9, fontWeight: 700, letterSpacing: "0.04em" }}>{positionRankLabel}</span>
        </span>
      </div>

      {/* Middle: jersey badge + name + meta */}
      <div style={{ display: "grid", gridTemplateColumns: "32px 1fr", gap: 7, marginTop: 6 }}>
        <div style={{
          width: 32, height: 32, borderRadius: 6,
          background: `linear-gradient(135deg, ${team.color}, #050807)`,
          border: "1px solid rgba(255,255,255,0.08)",
          display: "flex", alignItems: "center", justifyContent: "center",
          fontFamily: "Space Grotesk", fontWeight: 800,
          fontSize: 10,
          color: "white", lineHeight: 1,
        }}>{playerBadge}</div>

        <div style={{ minWidth: 0, display: "flex", flexDirection: "column", justifyContent: "center" }}>
          <div style={{
            fontSize: 11, lineHeight: 1.15, fontWeight: 800, color: "var(--mint-soft)",
            overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
          }}>{player.name}</div>
          <div className="mono" style={{ display: "flex", alignItems: "center", gap: 5, marginTop: 3, fontSize: 8, color: "var(--slate)" }}>
            <span style={{ width: 5, height: 5, borderRadius: "50%", background: team.color, boxShadow: "0 0 0 1px rgba(255,255,255,0.08)" }} />
            <span style={{ color: "var(--mint-soft)", fontWeight: 600, letterSpacing: "0.04em" }}>{player.team}</span>
            <span style={{ width: 4, height: 4, borderRadius: "50%", background: riskColor, marginLeft: 2 }} />
            <span style={{ color: riskColor, letterSpacing: "0.06em", textTransform: "uppercase" }}>{player.risk}</span>
          </div>
        </div>
      </div>

      {/* Bottom row: ADP / Proj blocks + queue */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 7 }}>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(2, auto)", gap: 10, alignItems: "start" }}>
          <div style={{ display: "grid", gap: 2 }}>
            <span className="mono" style={{ color: "var(--slate)", fontSize: 9, letterSpacing: "0.04em" }}>ADP</span>
            <span className="mono" style={{ color: "var(--mint-soft)", fontSize: 9 }}>{adpPick ? window.formatAdpPick(adpPick, teamCount) : "—"}</span>
            <span
              className="mono"
              title={adpPick ? `ESPN AVG PICK ${adpPick.toFixed(1)} · 949 overall #${overallRank || "—"}` : `949 overall #${overallRank || "—"}`}
              style={{ color: "var(--slate-dim)", fontSize: 9 }}
            >
              {adpPick ? `${adpPick.toFixed(1)} · ` : ""}#{overallRank || "—"}
            </span>
          </div>
          <div style={{ display: "grid", gap: 2 }}>
            <span className="mono" style={{ color: "var(--slate)", fontSize: 9, letterSpacing: "0.04em" }}>Proj</span>
            <span className="mono" style={{ color: "var(--mint)", fontSize: 9 }}>{seasonProjection.toFixed(1)}</span>
          </div>
        </div>
        {!isGone && (
          <span style={{ display: "flex", alignItems: "center", gap: 6 }}>
            {liveGrade && (
              <span
                className="mono"
                title={liveGrade.note}
                style={{ display: "grid", justifyItems: "center", lineHeight: 1 }}
              >
                <span style={{ color: "var(--slate-dim)", fontSize: 7, letterSpacing: "0.08em", fontWeight: 700 }}>PICK</span>
                <span style={{ color: liveGrade.color, fontSize: 16, fontWeight: 900 }}>{liveGrade.letter}</span>
                <span style={{ color: valueGrade.color, fontSize: 7, letterSpacing: "0.04em", marginTop: 2 }}>VAL {valueGrade.letter}</span>
              </span>
            )}
            <span
              onClick={onQueue}
              className="mono"
              title={liveGrade ? liveGrade.note : "Queue to see pick grade at the current slot vs ADP. 949 Value stays a separate player grade."}
              style={{
                color: queued ? "var(--mint-soft)" : "var(--slate)", fontSize: 8,
                padding: "2px 6px", borderRadius: 4,
                border: `1px solid ${queued ? posColor : "var(--green-600)"}`,
                background: queued ? `${posColor}1F` : "transparent",
                letterSpacing: "0.08em", fontWeight: 700,
                whiteSpace: "nowrap", minWidth: 58, textAlign: "center",
              }}>
              {queued ? "QUEUED" : "QUEUE"}
            </span>
          </span>
        )}
      </div>

      {isGone && (
        <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", background: "rgba(5,8,7,0.55)" }}>
          <span className="chip">Taken {player.drafted.roundPick}</span>
        </div>
      )}
    </button>
    {isGone && (
      <button
        type="button"
        title="Undo this pick and every pick after it"
        onClick={(event) => { event.preventDefault(); event.stopPropagation(); onUndo && onUndo(); }}
        style={{
          position: "absolute", top: 6, right: 6, zIndex: 3,
          width: 16, height: 16, padding: 0, borderRadius: 3,
          border: "2px solid #95F9AE",
          background: "rgba(5,8,7,0.55)",
          cursor: "pointer", boxShadow: "0 1px 4px rgba(0,0,0,0.35)",
        }}
      />
    )}
    </div>
  );
}

function LiveLeagueBoard({ teams, rosters }) {
  return (
    <div style={{ padding: 14, maxHeight: 560, overflow: "auto" }}>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(150px, 1fr))", gap: 10 }}>
        {teams.map(team => (
          <div key={team.id} style={{ minHeight: 160, padding: 10, borderRadius: 8, background: "var(--green-900)", border: team.isUser ? "1px solid var(--mint)" : "1px solid var(--green-600)" }}>
            <div style={{ display: "flex", justifyContent: "space-between", gap: 8, marginBottom: 8 }}>
              <span style={{ fontSize: 12, color: "var(--mint-soft)", fontWeight: 800, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{team.name}</span>
              <span className="mono" style={{ color: team.isUser ? "var(--mint)" : "var(--slate)", fontSize: 10 }}>{(rosters[team.id] || []).length}</span>
            </div>
            <div style={{ display: "grid", gap: 5 }}>
              {(rosters[team.id] || []).map(p => (
                <div key={p.id} style={{ display: "grid", gridTemplateColumns: "24px minmax(0,1fr) 22px", gap: 6, alignItems: "center" }}>
                  <span className="mono" style={{ color: window.positionColor(p.pos), fontSize: 9 }}>{p.pos}</span>
                  <span style={{ color: "var(--slate)", fontSize: 11, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{p.name}</span>
                  <span
                    className="mono"
                    title={`Pick grade vs ADP. 949 Value ${window.seasonValueGrade(p).letter} is player quality.`}
                    style={{ color: window.draftStockGrade(p).color, fontSize: 9, fontWeight: 800, textAlign: "right" }}
                  >
                    {window.draftStockGrade(p).letter}
                  </span>
                </div>
              ))}
              {!(rosters[team.id] || []).length && <span style={{ color: "var(--slate-dim)", fontSize: 11 }}>No picks yet</span>}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function ScoreCardBoard({ userRoster, grade, gm, pickLog, rosterSlots, teamCount }) {
  const [hoveredId, setHoveredId] = React.useState(null);
  const lineup = window.buildScoredLineup(userRoster, rosterSlots);
  const starters = lineup.filter(i => i.slot !== "BENCH").map(i => i.player);
  const bench = lineup.filter(i => i.slot === "BENCH").map(i => i.player);
  const starterGrade = window.gradeLineupDraft(starters);
  const starterCounts = window.countPositions(starters);
  const strongestPos = Object.keys(starterCounts).sort((a, b) => starterCounts[b] - starterCounts[a] || window.bestPositionScore(starters, b) - window.bestPositionScore(starters, a))[0] || "skill";
  const bestStarter = starters.filter(p => p.pos === strongestPos).sort((a, b) => (b.draft?.draftScore || 0) - (a.draft?.draftScore || 0))[0]
    || starters.slice().sort((a, b) => (b.draft?.draftScore || 0) - (a.draft?.draftScore || 0))[0];
  const weakestStarter = starters.slice().sort((a, b) => (a.draft?.draftScore || 100) - (b.draft?.draftScore || 100))[0];
  const starterBuckets = window.countDraftBuckets(starters);
  const benchBuckets = window.countDraftBuckets(bench);
  const missed = starters.find(p => p.draft?.stealAvailable && (p.draft?.boardBand || "").includes("Reach"));
  const benchSummary = bench.length
    ? `Bench: ${benchBuckets.steals} steals, ${benchBuckets.expected} expected, ${benchBuckets.reaches} reaches.`
    : "Bench: no bench picks yet.";
  const summary = userRoster.length
    ? `Starter strength grades as a ${starterGrade.letter} from 949 value and spend. The strongest starter group is ${strongestPos}${bestStarter ? `, led by ${bestStarter.name}` : ""}. ${missed ? `At ${missed.draft.roundPick}, you took ${missed.name} while ${missed.draft.stealAvailable.name} was still flagged as ${missed.draft.stealAvailable.label}.` : weakestStarter && (weakestStarter.draft?.boardBand || "").includes("Reach") ? `${weakestStarter.name} is the main starting-lineup board reach to monitor.` : "No major live-board reach is controlling the build."} ${benchSummary}`
    : "Start the simulator or enter live picks to generate a draft score.";

  return (
    <div style={{ padding: 14, maxHeight: 780, overflow: "auto", position: "relative" }}>
      <div style={{ display: "grid", gridTemplateColumns: "0.55fr 1.45fr", gap: 14 }}>
        <div style={{ padding: 18, borderRadius: 10, background: "var(--green-900)", border: "1px solid var(--green-600)", minHeight: 200 }}>
          <div className="mono" style={{ color: "var(--slate)", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.12em" }}>Starter Strength</div>
          <div className="num" style={{ color: starterGrade.color, fontSize: 68, marginTop: 10, lineHeight: 0.9 }}>{starterGrade.letter}</div>
          <div style={{ color: "var(--mint-soft)", fontSize: 15, fontWeight: 800, marginTop: 14 }}>{starterGrade.note}</div>
          <div className="mono" style={{ color: "var(--slate)", fontSize: 10, marginTop: 6 }}>{starters.length} starters · {(starterGrade.score || 0).toFixed(0)} composite</div>
        </div>
        <div style={{ padding: 14, borderRadius: 10, background: "var(--green-900)", border: "1px solid var(--green-600)" }}>
          <div className="mono" style={{ color: "var(--mint)", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.14em" }}>Draft Summary</div>
          <p style={{ color: "var(--mint-soft)", fontSize: 13, lineHeight: 1.55, marginTop: 10 }}>{summary}</p>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(5, 1fr)", gap: 8, marginTop: 14 }}>
            <EvidenceChip label="Starter Steals" value={starterBuckets.steals} />
            <EvidenceChip label="Expected" value={starterBuckets.expected} />
            <EvidenceChip label="Starter Reaches" value={starterBuckets.reaches} />
            <EvidenceChip label="Bench Reaches" value={benchBuckets.reaches} />
            <EvidenceChip label="Picks" value={userRoster.length} />
          </div>
        </div>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(150px, 1fr))", gap: 10, marginTop: 12 }}>
        {userRoster.map(p => (
          <div key={p.id}
            onMouseEnter={() => setHoveredId(p.id)}
            onMouseLeave={() => setHoveredId(null)}
            style={{ position: "relative", padding: 11, borderRadius: 8, background: window.positionBg(p.pos), border: `1px solid ${window.positionColor(p.pos)}66`, cursor: "help" }}>
            <div style={{ display: "flex", justifyContent: "space-between", gap: 8 }}>
              <span style={{ color: "var(--mint-soft)", fontSize: 12, fontWeight: 800 }}>{p.name}</span>
              <span className="mono" title="Pick grade vs ADP" style={{ color: window.draftStockGrade(p).color, fontSize: 11, fontWeight: 900 }}>{window.draftStockGrade(p).letter}</span>
            </div>
            <div className="mono" style={{ color: "var(--slate)", fontSize: 9, marginTop: 4 }}>{window.formatRoundPick((p.draft?.pick || 1) - 1, teamCount)} · {pickBandForPlayer(p, teamCount)}</div>
            <div className="mono" style={{ color: "var(--slate-dim)", fontSize: 9, marginTop: 3 }}>
              Stock {Math.round(p.draft?.draftScore || window.draftStockGrade(p).score)} · Market {formatPickPrice(p.draft?.adpDelta || 0, pickBandForPlayer(p, teamCount))} · {window.roleProjectionLabel(p)}{Number.isFinite(window.scheduleEaseRank(p)) ? ` · SOS ${window.scheduleEaseRank(p)}` : ""}
            </div>
            {hoveredId === p.id && <ScorePlayerTooltip player={p} teamCount={teamCount} />}
          </div>
        ))}
      </div>
    </div>
  );
}

function pickBandForPlayer(player, teamCount = 12) {
  if (player.draft?.selectedBand) return player.draft.selectedBand;
  if (player.draft?.boardBand) return player.draft.boardBand;
  const pick = Number(player.draft?.pick);
  if (pick && typeof window.marketBandForPick === "function") {
    return window.marketBandForPick(pick, player.adp, teamCount).label;
  }
  return player.valueLabel || "Expected";
}

function ScorePlayerTooltip({ player, teamCount = player.draft?.teamCount || 12 }) {
  const draftGrade = window.draftStockGrade(player);
  const rawDelta = Number(player.draft?.adpDelta || 0);
  const adpDelta = Math.round(rawDelta * 10) / 10;
  const deltaLabel = adpDelta > 0
    ? `${adpDelta} after ADP (discount)`
    : adpDelta < 0
      ? `${Math.abs(adpDelta)} before ADP (overpay)`
      : "at ADP";
  const role = window.roleProjectionLabel(player);
  const stock = Math.round(player.draft?.draftScore || draftGrade.score);
  const sos = window.scheduleEaseRank(player);
  const sosNote = window.scheduleStrengthNote(player);
  const marketBand = pickBandForPlayer(player, teamCount);
  const boardBand = marketBand;
  const pickPrice = formatPickPrice(adpDelta, marketBand);
  const valueGrade = window.seasonValueGrade(player);
  const valueIndex = player.valueIndex ? player.valueIndex.toFixed(2) : null;
  const actualPick = player.draft?.pick || null;
  const actualPickLabel = actualPick ? `#${actualPick} (${window.formatRoundPick(actualPick - 1, teamCount)})` : "—";
  const adpLabel = `#${Math.round(player.adp)} (${window.formatAdpPick(player.adp, teamCount)})`;
  return (
    <div style={{
      position: "absolute", bottom: "calc(100% + 6px)", left: 0, zIndex: 8,
      padding: "9px 11px", borderRadius: 8,
      background: "rgba(5,8,7,0.97)", border: "1px solid var(--green-600)",
      backdropFilter: "blur(6px)",
      width: 260, maxWidth: 260,
      boxShadow: "0 12px 28px rgba(0,0,0,0.4)",
      pointerEvents: "none",
    }}>
      <div style={{ display: "flex", justifyContent: "space-between", gap: 10, alignItems: "start" }}>
        <div style={{ minWidth: 0 }}>
          <div style={{ color: "var(--mint-soft)", fontSize: 12, fontWeight: 800, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{player.name}</div>
          <div className="mono" style={{ marginTop: 2, color: window.positionColor(player.pos), fontSize: 9 }}>{player.pos} · ADP {window.formatAdpPick(player.adp, teamCount)}</div>
        </div>
        <span className="num" title="Pick grade vs ADP" style={{ color: draftGrade.color, fontSize: 18, lineHeight: 1 }}>{draftGrade.letter}</span>
      </div>
      <div className="mono" style={{ marginTop: 8, display: "grid", gridTemplateColumns: "1fr auto", gap: "3px 10px", fontSize: 10 }}>
        <span style={{ color: "var(--slate)" }}>Board Signal</span><span style={{ color: window.valueToneForChip(boardBand) }}>{boardBand}</span>
        <span style={{ color: "var(--slate)" }}>Market Price</span><span style={{ color: window.valueToneForChip(marketBand) }}>{marketBand}</span>
        <span style={{ color: "var(--slate)" }}>Pick</span><span style={{ color: "var(--mint-soft)" }}>{actualPickLabel}</span>
        <span style={{ color: "var(--slate)" }}>ADP</span><span style={{ color: "var(--mint-soft)" }}>{adpLabel}</span>
        <span style={{ color: "var(--slate)" }}>Pick grade</span><span style={{ color: draftGrade.color }}>{draftGrade.letter}</span>
        <span style={{ color: "var(--slate)" }}>949 Value</span><span style={{ color: valueGrade.color }}>{valueGrade.letter}{valueIndex ? ` · ${valueIndex}` : ""}</span>
        <span style={{ color: "var(--slate)" }}>Draft Stock</span><span style={{ color: "var(--mint-soft)" }}>{stock}</span>
        <span style={{ color: "var(--slate)" }}>ADP Delta</span><span style={{ color: adpDelta >= 0 ? "var(--mint)" : "var(--gold)" }}>{pickPrice}</span>
        <span style={{ color: "var(--slate)" }}>EOS Role</span><span style={{ color: "var(--mint-soft)" }}>{role}</span>
        <span style={{ color: "var(--slate)" }}>SOS</span><span style={{ color: "var(--mint-soft)" }}>{Number.isFinite(sos) ? `${sos}/32` : "Pending"}</span>
      </div>
      <div style={{ marginTop: 8, paddingTop: 7, borderTop: "1px solid rgba(149,249,174,0.16)", color: "var(--slate)", fontSize: 9, lineHeight: 1.4 }}>
        {deltaLabel} · {sosNote}
      </div>
    </div>
  );
}

function formatPickPrice(adpDelta, band = "Expected") {
  if (band === "Expected") return "Expected";
  const rounded = Math.round(Number(adpDelta || 0) * 10) / 10;
  if (rounded > 0) return `${band} +${rounded}`;
  if (rounded < 0) return `${band} ${rounded}`;
  return band;
}

function pickPriceBand(adpDelta, teamCount = 12) {
  return window.marketBandForPick(1 + (adpDelta || 0), 1, teamCount).label;
}

function PicksRoundBoard({ pickLog, draftOrder, teams, teamCount, rounds }) {
  const byPick = Object.fromEntries(pickLog.map(item => [item.draft.pick, item]));
  return (
    <div style={{ padding: 14, maxHeight: 560, overflow: "auto" }}>
      <div style={{ display: "grid", gap: 8 }}>
        {Array.from({ length: rounds }, (_, r) => (
          <div key={r} style={{ display: "grid", gridTemplateColumns: `48px repeat(${teamCount}, minmax(74px, 1fr))`, gap: 5, alignItems: "stretch" }}>
            <div className="mono" style={{ color: "var(--mint)", fontSize: 11, display: "flex", alignItems: "center" }}>R{r + 1}</div>
            {Array.from({ length: teamCount }, (_, p) => {
              const roundPickIndex = r % 2 === 1 ? teamCount - 1 - p : p;
              const pick = r * teamCount + roundPickIndex + 1;
              const item = byPick[pick];
              const teamNumber = draftOrder[pick - 1];
              const team = teams[teamNumber - 1];
              return (
                <div key={pick} style={{ minHeight: 50, padding: 6, borderRadius: 6, border: "1px solid var(--green-600)", background: item ? window.positionBg(item.player.pos) : "var(--green-900)" }}>
                  <div className="mono" style={{ color: team?.isUser ? "var(--mint)" : "var(--slate)", fontSize: 9 }}>{window.formatRoundPick(pick - 1, teamCount)}</div>
                  <div style={{ marginTop: 4, color: item ? "var(--mint-soft)" : "var(--slate-dim)", fontSize: 10, lineHeight: 1.15, fontWeight: item ? 700 : 500, overflow: "hidden" }}>{item ? item.player.name : team?.name}</div>
                </div>
              );
            })}
          </div>
        ))}
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────────
// GM Q&A box
// ────────────────────────────────────────────────────────────────────────────
function GmInteractionBox({ question, setQuestion, onSubmit, answer, gm, userRoster, pickNumber, onQueueDrop, rosterSlots }) {
  return (
    <div className="card"
      onDragOver={e => e.preventDefault()}
      onDrop={e => { e.preventDefault(); const id = e.dataTransfer.getData("text/plain"); if (id) onQueueDrop(id); }}
      style={{ padding: 12 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: 8 }}>
        <div>
          <div className="mono" style={{ fontSize: 9, color: "var(--mint)", textTransform: "uppercase", letterSpacing: "0.16em" }}>GM Interaction</div>
          <div className="display" style={{ fontSize: 14, color: "var(--mint-soft)", marginTop: 2 }}>Ask the GM</div>
        </div>
        <span className="mono" style={{ color: "var(--slate-dim)", fontSize: 9, letterSpacing: "0.06em", textTransform: "uppercase" }}>Pick {pickNumber} · {gm.biggestNeed || "—"}</span>
      </div>
      <textarea
        value={question}
        onChange={e => setQuestion(e.target.value)}
        onKeyDown={e => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); onSubmit(); } }}
        placeholder="Henry or Bijan? Will this WR make it back? Best value? Last WR in this tier?"
        style={{ width: "100%", minHeight: 56, resize: "vertical", background: "var(--green-900)", border: "1px solid var(--green-600)", borderRadius: 7, color: "var(--mint-soft)", padding: 8, fontFamily: "Sora", fontSize: 12, outline: "none" }}
      />
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 7, gap: 8 }}>
        <button className="btn" onClick={onSubmit} style={{ padding: "6px 12px", fontSize: 11 }}>Ask GM</button>
        <span className="mono" style={{ color: "var(--slate-dim)", fontSize: 9, letterSpacing: "0.06em", textTransform: "uppercase" }}>Roster {userRoster.length}/{rosterSlots.length}</span>
      </div>
      <div style={{ marginTop: 8, padding: 9, borderRadius: 7, background: "var(--green-900)", border: "1px solid var(--green-600)" }}>
        <div className="mono" style={{ color: "var(--mint)", fontSize: 9, letterSpacing: "0.14em", textTransform: "uppercase" }}>Answer</div>
        <div style={{ marginTop: 5, color: "var(--mint-soft)", fontSize: 12, lineHeight: 1.45 }}>{answer}</div>
      </div>
    </div>
  );
}

function EvidenceChip({ label, value }) {
  return (
    <div style={{ padding: 8, borderRadius: 7, background: "rgba(149,249,174,0.06)", border: "1px solid var(--green-600)" }}>
      <div className="mono" style={{ color: "var(--slate)", fontSize: 8, textTransform: "uppercase", letterSpacing: "0.08em" }}>{label}</div>
      <div className="num" style={{ color: "var(--mint-soft)", fontSize: 15, lineHeight: 1, marginTop: 4 }}>{value}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────────────────────
// Draft Complete — surfaces once the simulator/league fills every pick.
function DraftFinishedAskModal({ onYes, onNo }) {
  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 72, display: "flex", alignItems: "center", justifyContent: "center",
      padding: 24, background: "rgba(5,8,7,0.78)", backdropFilter: "blur(8px)"
    }}>
      <div className="card" style={{ width: "min(420px, 100%)", padding: 24, boxShadow: "0 30px 80px rgba(0,0,0,0.55)" }}>
        <h2 className="display" style={{ margin: "0 0 20px", color: "var(--mint-soft)", fontSize: 26, lineHeight: 1.1 }}>Is your draft complete?</h2>
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10 }}>
          <button className="btn ghost" onClick={onNo}>No</button>
          <button className="btn" onClick={onYes}>Yes</button>
        </div>
      </div>
    </div>
  );
}

function DraftCompleteModal({ grade, onReview, onClose, onReset }) {
  const hasPicks = grade && grade.letter !== "—";
  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 70, display: "flex", alignItems: "center", justifyContent: "center",
      padding: 24, background: "rgba(5,8,7,0.78)", backdropFilter: "blur(8px)"
    }}>
      <div className="card" style={{ width: "min(480px, 100%)", padding: 24, boxShadow: "0 30px 80px rgba(0,0,0,0.55)" }}>
        <div className="mono" style={{ color: "var(--mint)", fontSize: 10, letterSpacing: "0.16em", textTransform: "uppercase" }}>Draft Complete</div>
        <h2 className="display" style={{ margin: "8px 0 12px", color: "var(--mint-soft)", fontSize: 26, lineHeight: 1.1 }}>Your draft has concluded</h2>
        <p style={{ color: "var(--slate)", fontSize: 13, lineHeight: 1.55 }}>
          Every pick is in. Open Review to see the starting-lineup grade, pick-by-pick band, and missed value calls.
        </p>
        {hasPicks && (
          <div style={{ marginTop: 14, padding: 12, borderRadius: 10, background: "var(--green-900)", border: `1px solid ${grade.color}55`, display: "flex", alignItems: "center", gap: 14 }}>
            <span className="num" style={{ color: grade.color, fontSize: 44, lineHeight: 1, fontWeight: 900 }}>{grade.letter}</span>
            <div>
              <div className="mono" style={{ color: "var(--slate)", fontSize: 10, letterSpacing: "0.1em", textTransform: "uppercase" }}>Current Grade</div>
              <div style={{ color: "var(--mint-soft)", fontSize: 13, marginTop: 4 }}>{grade.note}</div>
            </div>
          </div>
        )}
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 20, flexWrap: "wrap" }}>
          <button className="btn ghost" onClick={onReset}>Reset Draft</button>
          <button className="btn ghost" onClick={onClose}>Stay on Board</button>
          <button className="btn" onClick={onReview}>Review Draft</button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { DraftView });
