/* organizer-pages.jsx — All page-section components for the Arena Organizer
 * React 18 · in-browser Babel · no build step
 * Data comes from props, NOT from window.ORG_* globals
 * Exports all components on window.*
 */

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function openPicker(e) {
  try { if (e.currentTarget && typeof e.currentTarget.showPicker === 'function') e.currentTarget.showPicker(); } catch (_) {}
}
function formatTs(ts) {
  if (!ts) return '—';
  return new Date(ts * 1000).toLocaleDateString();
}

function PhaseBadge(props) {
  var phase = props.phase || '';
  var colorMap = { registration: 'brand', draft: 'wn', playing: 'ok' };
  var cls = 'pill ' + (colorMap[phase] || '');
  return React.createElement('span', { className: cls }, phase || '—');
}

// ---------------------------------------------------------------------------
// OrgSessionsDashboard
// ---------------------------------------------------------------------------
window.OrgSessionsDashboard = function OrgSessionsDashboard(props) {
  var games = props.games || [];
  var metrics = props.metrics || null;
  var onCreateGame = props.onCreateGame || function() {};
  var onNavigate = props.onNavigate || function() {};
  var onEditGame = props.onEditGame || function() {};
  var onDeleteGame = props.onDeleteGame || function() {};
  var onOpenMonitor = props.onOpenMonitor || function() {};
  var onRefresh = props.onRefresh || function() {};
  var loading = props.loading || false;

  var totalGames   = metrics ? metrics.total_games              : '—';
  var totalPlayers = metrics ? metrics.total_players            : '—';
  var avgPerGame   = metrics ? metrics.avg_players_per_game     : '—';
  var scoreAvg     = metrics && metrics.score_stats ? metrics.score_stats.avg : '—';

  return (
    <div className="page-sessions">
      {/* Page header */}
      <div className="pghd">
        <div>
          <div className="title">
            Sessions
            <span style={{ marginLeft: '10px', fontSize: '14px', color: 'var(--i3)', fontWeight: 400 }}>
              {games.length} game{games.length !== 1 ? 's' : ''}
            </span>
          </div>
        </div>
        <div className="right" style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
          <button className="btn ghost" onClick={onRefresh} disabled={loading}>
            {loading ? '…' : '↻'} Refresh
          </button>
        </div>
      </div>

      {/* KPI strip */}
      <div className="kpis">
        <div className="kpi">
          <span className="lbl">Total games</span>
          <span className="v">{totalGames}</span>
        </div>
        <div className="kpi">
          <span className="lbl">Total players</span>
          <span className="v">{totalPlayers}</span>
        </div>
        <div className="kpi">
          <span className="lbl">Avg per game</span>
          <span className="v">{avgPerGame}</span>
        </div>
        <div className="kpi">
          <span className="lbl">Score avg</span>
          <span className="v">{scoreAvg}</span>
        </div>
      </div>

      {/* Games table */}
      <div className="card" style={{ marginTop: '18px' }}>
        <div className="card-hd">
          <h3>All games</h3>
        </div>
        <div className="card-bd">
          {games.length === 0 ? (
            <div className="empty-state">
              <div style={{ textAlign: 'center', padding: '48px 24px', color: 'var(--i3)' }}>
                <div style={{ fontSize: '32px', marginBottom: '12px' }}>🎮</div>
                <div style={{ fontWeight: 600, marginBottom: '6px' }}>No sessions yet</div>
                <div style={{ fontSize: '13px' }}>Click '+ New session' to create one.</div>
              </div>
            </div>
          ) : (
            <div className="games-table">
              {games.map(function(game) {
                return (
                  <div className="game-row" key={game.game_id}
                    style={{
                      display: 'grid',
                      gridTemplateColumns: '140px 1fr 110px 120px auto',
                      gap: '12px',
                      alignItems: 'center',
                      padding: '10px 16px',
                      borderBottom: '1px solid var(--line-soft)',
                      cursor: game.is_event_draft ? 'pointer' : 'default',
                      transition: 'background .12s',
                    }}
                    onMouseEnter={function(e) { if (game.is_event_draft) e.currentTarget.style.background = 'var(--s2)'; }}
                    onMouseLeave={function(e) { if (game.is_event_draft) e.currentTarget.style.background = ''; }}
                    onClick={function() {
                      if (game.is_event_draft) {
                        window.location.href = '/v2/tech-day-speakers?event_id=' + game.event_id;
                      }
                    }}
                  >
                    <code className="join-code" style={{
                      fontFamily: 'var(--f-m)',
                      fontSize: '16px',
                      fontWeight: 700,
                      background: 'var(--brand)',
                      color: '#fff',
                      padding: '4px 10px',
                      borderRadius: '6px',
                      letterSpacing: '2px',
                      cursor: 'pointer',
                      display: 'inline-flex',
                      alignItems: 'center',
                      gap: '6px',
                      transition: 'transform .1s, box-shadow .1s',
                      userSelect: 'all',
                    }} title="Click to copy join code"
                      onMouseEnter={function(e) { e.currentTarget.style.transform = 'scale(1.04)'; e.currentTarget.style.boxShadow = '0 2px 8px rgba(0,0,0,.25)'; }}
                      onMouseLeave={function(e) { e.currentTarget.style.transform = ''; e.currentTarget.style.boxShadow = ''; }}
                      onClick={function(e) {
                        e.stopPropagation();
                        var code = game.join_code || game.game_id;
                        // Fallback for HTTP (navigator.clipboard requires HTTPS)
                        var ta = document.createElement('textarea');
                        ta.value = code;
                        ta.style.position = 'fixed';
                        ta.style.left = '-9999px';
                        document.body.appendChild(ta);
                        ta.select();
                        try { document.execCommand('copy'); } catch(_) {}
                        document.body.removeChild(ta);
                        if (props.showToast) props.showToast('Copied: ' + code, 'ok');
                      }}>
                      {game.join_code || game.game_id}
                      <span style={{ fontSize: '12px', opacity: 0.7 }}>📋</span>
                    </code>
                    <div>
                      <div style={{ fontWeight: 600 }}>{game.name || '—'}</div>
                      {game.location && (
                        <div style={{ fontSize: '12px', color: 'var(--i3)' }}>{game.location}</div>
                      )}
                    </div>
                    <PhaseBadge phase={game.current_phase} />
                    <div style={{ fontSize: '12px', color: 'var(--i3)' }}>
                      {formatTs(game.created_at)}
                    </div>
                    <div style={{ display: 'flex', gap: '6px' }}>
                      {game.is_event_draft && (
                        <button className="btn primary" style={{ fontSize: '12px', padding: '4px 10px' }}
                          onClick={function(e) { e.stopPropagation(); window.location.href = '/v2/tech-day-speakers?event_id=' + game.event_id; }}>
                          🎤 Open
                        </button>
                      )}
                      {game.event_id && !game.is_event_draft && (
                        <button className="btn ghost" style={{ fontSize: '12px', padding: '4px 10px' }}
                          onClick={function(e) { e.stopPropagation(); onEditGame(game); }}>
                          ✎ Edit
                        </button>
                      )}
                      {!game.is_event_draft && (
                        <button className="btn ghost" style={{ fontSize: '12px', padding: '4px 10px' }}
                          onClick={function(e) { e.stopPropagation(); onOpenMonitor(game.game_id); }}>
                          Monitor
                        </button>
                      )}
                      <button className="btn ghost" style={{ fontSize: '12px', padding: '4px 10px', color: 'var(--dn)' }}
                        onClick={function(e) { e.stopPropagation(); onDeleteGame(game.game_id); }}>
                        Delete
                      </button>
                    </div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgOverviewPage
// ---------------------------------------------------------------------------
window.OrgOverviewPage = function OrgOverviewPage(props) {
  var metrics = props.metrics || null;
  var onRefresh = props.onRefresh || function() {};

  return (
    <div className="page-overview">
      {/* Page header */}
      <div className="pghd">
        <div>
          <div className="title">Overview</div>
        </div>
        <div className="right">
          <button className="btn ghost" onClick={onRefresh}>↻ Refresh</button>
        </div>
      </div>

      {metrics === null ? (
        <div className="card" style={{ marginTop: '18px' }}>
          <div className="card-bd" style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>
            <div style={{ fontSize: '20px', marginBottom: '8px' }}>Loading metrics…</div>
          </div>
        </div>
      ) : (
        <>
          {/* Primary KPIs */}
          <div className="kpis" style={{ marginTop: '18px' }}>
            <div className="kpi">
              <span className="lbl">Total games</span>
              <span className="v">{metrics.total_games != null ? metrics.total_games : '—'}</span>
            </div>
            <div className="kpi">
              <span className="lbl">Total players</span>
              <span className="v">{metrics.total_players != null ? metrics.total_players : '—'}</span>
            </div>
            <div className="kpi">
              <span className="lbl">Avg players/game</span>
              <span className="v">{metrics.avg_players_per_game != null ? metrics.avg_players_per_game : '—'}</span>
            </div>
            <div className="kpi">
              <span className="lbl">Events count</span>
              <span className="v">{metrics.events_count != null ? metrics.events_count : '—'}</span>
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginTop: '16px' }}>
            {/* Score stats card */}
            {metrics.score_stats && (
              <div className="card">
                <div className="card-hd"><h3>Score stats</h3></div>
                <div className="card-bd" style={{ padding: '16px 18px' }}>
                  <div className="kpis" style={{ gridTemplateColumns: 'repeat(3,1fr)', gap: '10px' }}>
                    <div className="kpi">
                      <span className="lbl">Min</span>
                      <span className="v">{metrics.score_stats.min != null ? metrics.score_stats.min : '—'}</span>
                    </div>
                    <div className="kpi">
                      <span className="lbl">Max</span>
                      <span className="v">{metrics.score_stats.max != null ? metrics.score_stats.max : '—'}</span>
                    </div>
                    <div className="kpi">
                      <span className="lbl">Avg</span>
                      <span className="v">{metrics.score_stats.avg != null ? metrics.score_stats.avg : '—'}</span>
                    </div>
                  </div>
                </div>
              </div>
            )}

            {/* Module popularity */}
            {metrics.module_popularity && metrics.module_popularity.length > 0 && (
              <div className="card">
                <div className="card-hd"><h3>Module popularity</h3></div>
                <div className="card-bd" style={{ padding: '16px 18px' }}>
                  {metrics.module_popularity.map(function(mod, i) {
                    return (
                      <div key={i} style={{
                        display: 'flex',
                        justifyContent: 'space-between',
                        padding: '5px 0',
                        borderBottom: '1px solid var(--line-soft)',
                        fontSize: '13px',
                      }}>
                        <span>{mod.name || mod.module || mod}</span>
                        <span style={{ color: 'var(--brand)', fontFamily: 'var(--f-m)' }}>
                          {mod.count || mod.plays || ''}
                        </span>
                      </div>
                    );
                  })}
                </div>
              </div>
            )}
          </div>

          {/* Recent games */}
          {metrics.recent_games && metrics.recent_games.length > 0 && (
            <div className="card" style={{ marginTop: '16px' }}>
              <div className="card-hd"><h3>Recent games</h3></div>
              <div className="card-bd" style={{ padding: '0' }}>
                {metrics.recent_games.slice(0, 5).map(function(game, i) {
                  return (
                    <div key={i} style={{
                      display: 'flex',
                      justifyContent: 'space-between',
                      alignItems: 'center',
                      padding: '10px 18px',
                      borderBottom: '1px solid var(--line-soft)',
                    }}>
                      <code style={{ fontFamily: 'var(--f-m)', fontSize: '12px', color: 'var(--brand)' }}>
                        {game.game_id}
                      </code>
                      <span style={{ flex: 1, margin: '0 12px' }}>{game.name || '—'}</span>
                      <PhaseBadge phase={game.current_phase} />
                    </div>
                  );
                })}
              </div>
            </div>
          )}
        </>
      )}
    </div>
  );
};

// ---------------------------------------------------------------------------
// MonitorOpsTabs — tab strip for OrgMonitorPage
// ---------------------------------------------------------------------------
window.MonitorOpsTabs = function MonitorOpsTabs(props) {
  var activeTab = props.activeTab || 'control';
  var onChange = props.onChange || function() {};
  var badges = props.badges || {};

  var TABS = [
    { id: 'control',    label: 'Control',         icon: '🎛️' },
    { id: 'breach',     label: 'Breach VAR',       icon: '🔓' },
    { id: 'gameplan',   label: 'GamePlan',         icon: '📐' },
    { id: 'zonamixta',  label: 'Zona Mixta',       icon: '⚡' },
    { id: 'triage',     label: 'Triage Review',    icon: '🎫' },
  ];

  return (
    <div style={{
      display: 'flex',
      gap: '4px',
      borderBottom: '2px solid var(--line-soft)',
      marginBottom: '18px',
      marginTop: '12px',
    }}>
      {TABS.map(function(tab) {
        var isActive = activeTab === tab.id;
        var badge = badges[tab.id];
        return (
          <button
            key={tab.id}
            onClick={function() { onChange(tab.id); }}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: '6px',
              padding: '8px 16px',
              border: 'none',
              background: 'none',
              cursor: 'pointer',
              fontSize: '13px',
              fontWeight: isActive ? 700 : 500,
              color: isActive ? '#00BCEB' : 'var(--i2)',
              borderBottom: isActive ? '2px solid #00BCEB' : '2px solid transparent',
              marginBottom: '-2px',
              borderRadius: '0',
              transition: 'color .15s',
              whiteSpace: 'nowrap',
            }}
          >
            <span>{tab.icon}</span>
            <span>{tab.label}</span>
            {badge > 0 && (
              <span style={{
                background: '#00BCEB',
                color: '#fff',
                borderRadius: '10px',
                fontSize: '10px',
                fontWeight: 700,
                padding: '1px 6px',
                minWidth: '18px',
                textAlign: 'center',
                lineHeight: '16px',
              }}>{badge}</span>
            )}
          </button>
        );
      })}
    </div>
  );
};

// ---------------------------------------------------------------------------
// GamePlanScoringTab
// ---------------------------------------------------------------------------
window.GamePlanScoringTab = function GamePlanScoringTab(props) {
  var gameId = props.gameId;

  var _s1 = React.useState([]), submissions = _s1[0], setSubmissions = _s1[1];
  var _s2 = React.useState(null), selectedTeamId = _s2[0], setSelectedTeamId = _s2[1];
  var _s3 = React.useState(false), loading = _s3[0], setLoading = _s3[1];
  var _s4 = React.useState(null), saveError = _s4[0], setSaveError = _s4[1];
  var _s5 = React.useState(false), saving = _s5[0], setSaving = _s5[1];
  var _s6 = React.useState(''), saveMsg = _s6[0], setSaveMsg = _s6[1];

  // Rubric scores
  var _r1 = React.useState(0), technical = _r1[0], setTechnical = _r1[1];
  var _r2 = React.useState(0), bom = _r2[0], setBom = _r2[1];
  var _r3 = React.useState(0), clarity = _r3[0], setClarity = _r3[1];
  var _r4 = React.useState(0), presentation = _r4[0], setPresentation = _r4[1];
  var _rn = React.useState(''), notes = _rn[0], setNotes = _rn[1];

  var total = technical + bom + clarity + presentation;

  var RUBRIC = [
    { key: 'technical',    label: 'Technical correctness / fit',      max: 200, bands: [60, 120, 170, 200], val: technical,    set: setTechnical },
    { key: 'bom',          label: 'BOM accuracy / completeness',       max: 125, bands: [40, 80, 110, 125], val: bom,          set: setBom },
    { key: 'clarity',      label: 'Architecture clarity',              max: 125, bands: [40, 80, 110, 125], val: clarity,      set: setClarity },
    { key: 'presentation', label: 'Presentation / executive delivery', max: 50,  bands: [10, 25, 40, 50],  val: presentation, set: setPresentation },
  ];

  function _authHeaders() {
    var t = (window.AdminSession && window.AdminSession.getToken) ? window.AdminSession.getToken() : null;
    return t ? { 'Authorization': 'Bearer ' + t } : {};
  }

  function fetchSubmissions() {
    if (!gameId) return;
    setLoading(true);
    fetch('/api/g/' + encodeURIComponent(gameId) + '/proctor/gameplan-submissions', { headers: _authHeaders() })
      .then(function(r) { return r.ok ? r.json() : Promise.reject(r); })
      .then(function(data) {
        var teams = data.teams || [];
        setSubmissions(teams);
        // Use functional setter to read CURRENT selectedTeamId (avoid stale closure from 10s interval)
        setSelectedTeamId(function(prev) {
          if (prev) return prev;
          return teams.length > 0 ? teams[0].team_id : null;
        });
      })
      .catch(function(err) { console.error('[GamePlanScoring] fetch failed:', err); })
      .finally(function() { setLoading(false); });
  }

  React.useEffect(function() {
    fetchSubmissions();
    var interval = setInterval(fetchSubmissions, 10000);
    return function() { clearInterval(interval); };
  }, [gameId]);

  // Load existing score when team changes
  React.useEffect(function() {
    if (!selectedTeamId) return;
    var team = submissions.find(function(t) { return t.team_id === selectedTeamId; });
    if (team && team.score) {
      setTechnical(team.score.technical || 0);
      setBom(team.score.bom || 0);
      setClarity(team.score.clarity || 0);
      setPresentation(team.score.presentation || 0);
      setNotes(team.notes || '');
    } else {
      setTechnical(0); setBom(0); setClarity(0); setPresentation(0); setNotes('');
    }
  }, [selectedTeamId]);

  // Keyboard shortcuts
  React.useEffect(function() {
    function onKey(e) {
      if (e.target.tagName === 'TEXTAREA' || e.target.tagName === 'INPUT') return;
      var idx = submissions.findIndex(function(t) { return t.team_id === selectedTeamId; });
      if (e.key === 'j' || e.key === 'J') {
        var next = submissions[idx + 1];
        if (next) { setSelectedTeamId(next.team_id); }
      } else if (e.key === 'k' || e.key === 'K') {
        var prev = submissions[idx - 1];
        if (prev) { setSelectedTeamId(prev.team_id); }
      } else if (e.key === 'Enter') {
        handleSave();
      }
    }
    window.addEventListener('keydown', onKey);
    return function() { window.removeEventListener('keydown', onKey); };
  }, [selectedTeamId, submissions, technical, bom, clarity, presentation, notes]);

  function handleSave() {
    if (!selectedTeamId) return;
    setSaving(true);
    setSaveError(null);
    fetch('/api/g/' + encodeURIComponent(gameId) + '/proctor/gameplan-score', {
      method: 'POST',
      headers: Object.assign({ 'Content-Type': 'application/json' }, _authHeaders()),
      body: JSON.stringify({
        team_id: selectedTeamId,
        total: total,
        breakdown: { technical: technical, bom: bom, clarity: clarity, presentation: presentation },
        notes: notes,
      }),
    })
      .then(function(r) { return r.ok ? r.json() : Promise.reject(r); })
      .then(function() {
        setSaveMsg('✅ Saved!');
        setTimeout(function() { setSaveMsg(''); }, 3500);
        fetchSubmissions();
        // Advance to next team
        var idx = submissions.findIndex(function(t) { return t.team_id === selectedTeamId; });
        var next = submissions[idx + 1];
        if (next) setSelectedTeamId(next.team_id);
      })
      .catch(function(err) {
        console.error('[GamePlanScoring] save failed:', err);
        if (err && err.json) {
          err.json().then(function(j) { setSaveError('Save failed: ' + (j.detail || JSON.stringify(j))); }).catch(function(){ setSaveError('Save failed (HTTP ' + (err.status || '?') + ')'); });
        } else {
          setSaveError('Save failed');
        }
      })
      .finally(function() { setSaving(false); });
  }

  var selectedTeam = submissions.find(function(t) { return t.team_id === selectedTeamId; });

  // Pull scenario brief from window.GAME_MODULES['ise'].data.briefs (client-side reference)
  function _getBrief(idx) {
    if (idx == null) return null;
    try {
      var mods = (typeof window !== 'undefined' && window.GAME_MODULES) ? window.GAME_MODULES : null;
      if (!mods) return null;
      // Try ise first (live game), then fall back to any module that has briefs
      var mod = mods['ise'];
      if (!mod) {
        for (var k in mods) { if (mods[k] && mods[k].data && mods[k].data.briefs) { mod = mods[k]; break; } }
      }
      var briefs = (mod && mod.data && mod.data.briefs) || null;
      if (briefs && briefs[idx]) return briefs[idx];
    } catch(e) {}
    return null;
  }
  var brief = selectedTeam ? _getBrief(selectedTeam.scenario_index) : null;

  // Local helpers for compact styled blocks
  var _LBL = { fontSize: '11px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: '4px', fontWeight: 600 };
  var _PILL = { display: 'inline-block', padding: '2px 8px', borderRadius: '10px', fontSize: '11px', fontWeight: 600, marginRight: '6px', marginBottom: '4px' };

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '200px 1fr 320px', gap: '14px', alignItems: 'start' }}>
      {/* Left rail — team list */}
      <div className="card" style={{ overflow: 'hidden' }}>
        <div className="card-hd"><h3 style={{ fontSize: '13px' }}>Teams</h3></div>
        <div style={{ padding: '0' }}>
          {loading && submissions.length === 0 && (
            <div style={{ padding: '20px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }}>Loading…</div>
          )}
          {submissions.map(function(team) {
            var isActive = team.team_id === selectedTeamId;
            var hasSubmission = !!team.submission;
            var isScored = team.score && (team.score.total > 0 || (team.score.breakdown && (team.score.breakdown.technical > 0 || team.score.breakdown.bom > 0)));
            var statusIcon = !hasSubmission ? '❌' : (isScored ? '✅' : '⏳');
            return (
              <div
                key={team.team_id}
                onClick={function() { setSelectedTeamId(team.team_id); }}
                style={{
                  padding: '10px 14px',
                  borderBottom: '1px solid var(--line-soft)',
                  cursor: 'pointer',
                  background: isActive ? 'color-mix(in srgb, #00BCEB 12%, transparent)' : 'transparent',
                  borderLeft: isActive ? '3px solid #00BCEB' : '3px solid transparent',
                  display: 'flex',
                  alignItems: 'center',
                  gap: '8px',
                }}
              >
                <span style={{ fontSize: '14px' }}>{statusIcon}</span>
                <span style={{ fontSize: '13px', fontWeight: isActive ? 700 : 500, flex: 1 }}>{team.team_name || team.team_id}</span>
              </div>
            );
          })}
          {submissions.length === 0 && !loading && (
            <div style={{ padding: '20px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }}>No submissions yet</div>
          )}
        </div>
      </div>

      {/* Center — submission */}
      <div className="card">
        <div className="card-hd">
          <h3 style={{ fontSize: '13px' }}>
            {selectedTeam ? (selectedTeam.team_name || selectedTeam.team_id) : 'Select a team'}
          </h3>
        </div>
        <div className="card-bd" style={{ padding: '16px' }}>
          {!selectedTeam ? (
            <div style={{ color: 'var(--i3)', fontSize: '13px' }}>Select a team from the left rail.</div>
          ) : !selectedTeam.submission ? (
            <div style={{ color: 'var(--i3)', fontSize: '13px', padding: '32px', textAlign: 'center' }}>❌ No submission received yet.</div>
          ) : (
            <div style={{ display: 'flex', flexDirection: 'column', gap: '14px' }}>
              {/* Scenario brief reference (proctor-only) */}
              {selectedTeam.scenario_index != null && (
                <div style={{ border: '1px solid var(--line-soft)', borderRadius: '8px', overflow: 'hidden' }}>
                  {/* Header */}
                  <div style={{ padding: '10px 14px', background: 'linear-gradient(135deg, color-mix(in srgb, #00BCEB 14%, transparent), color-mix(in srgb, #049FD9 8%, transparent))', borderBottom: '1px solid var(--line-soft)' }}>
                    <div style={{ fontSize: '10px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 700, marginBottom: '3px' }}>
                      Escenario #{selectedTeam.scenario_index + 1}{brief && brief.phase ? ' · ' + brief.phase : ''}
                    </div>
                    <div style={{ fontSize: '15px', fontWeight: 800, color: 'var(--i1)' }}>
                      {brief && brief.logo ? brief.logo + ' ' : '🏢 '}
                      {brief ? (brief.client || 'Cliente') : 'Brief no disponible — recarga la página'}
                    </div>
                    {brief && (
                      <div style={{ fontSize: '12px', color: 'var(--i2)', marginTop: '4px' }}>
                        {brief.industry && <span>{brief.industry}</span>}
                        {brief.employees && <span> · {brief.employees.toLocaleString ? brief.employees.toLocaleString() : brief.employees} empleados</span>}
                        {brief.endpoints && <span> · {brief.endpoints.toLocaleString ? brief.endpoints.toLocaleString() : brief.endpoints} endpoints</span>}
                        {brief.sites && <span> · {brief.sites} sitios</span>}
                        {brief.budget && <span> · {brief.budget}</span>}
                      </div>
                    )}
                  </div>

                  {brief && (
                    <div style={{ padding: '12px 14px', display: 'flex', flexDirection: 'column', gap: '12px' }}>
                      {/* TRICK REQUIREMENT — most important for scoring */}
                      {brief.trickRequirement && (
                        <div style={{ background: 'color-mix(in srgb, #FBAB18 18%, transparent)', border: '1px solid #FBAB18', borderRadius: '6px', padding: '10px 12px' }}>
                          <div style={{ fontSize: '11px', fontWeight: 800, color: '#B07A00', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: '4px' }}>⚠️ Requerimiento trampa (deduce si lo ignoraron)</div>
                          <div style={{ fontSize: '12px', color: 'var(--i1)', lineHeight: 1.45 }}>{brief.trickRequirement}</div>
                        </div>
                      )}

                      {/* Context */}
                      {brief.context && (
                        <details>
                          <summary style={Object.assign({}, _LBL, { cursor: 'pointer', marginBottom: '6px' })}>📋 Contexto del cliente</summary>
                          <div style={{ fontSize: '12px', color: 'var(--i2)', lineHeight: 1.5, padding: '4px 0 0 4px' }}>{brief.context}</div>
                        </details>
                      )}

                      {/* Pain points + constraints */}
                      {(brief.painPoints || brief.constraints) && (
                        <details>
                          <summary style={Object.assign({}, _LBL, { cursor: 'pointer', marginBottom: '6px' })}>🎯 Pain points & restricciones</summary>
                          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '10px', padding: '4px 0 0 4px', fontSize: '12px' }}>
                            {brief.painPoints && (
                              <div>
                                <div style={{ fontWeight: 700, color: '#E74C3C', marginBottom: '4px' }}>Pain points</div>
                                <ul style={{ margin: 0, paddingLeft: '16px', color: 'var(--i2)' }}>
                                  {brief.painPoints.map(function(p, i) { return <li key={i} style={{ marginBottom: '3px' }}>{p}</li>; })}
                                </ul>
                              </div>
                            )}
                            {brief.constraints && (
                              <div>
                                <div style={{ fontWeight: 700, color: '#9B59B6', marginBottom: '4px' }}>Restricciones</div>
                                <ul style={{ margin: 0, paddingLeft: '16px', color: 'var(--i2)' }}>
                                  {brief.constraints.map(function(p, i) { return <li key={i} style={{ marginBottom: '3px' }}>{p}</li>; })}
                                </ul>
                              </div>
                            )}
                          </div>
                        </details>
                      )}

                      {/* Licensing */}
                      {brief.licensingRequirements && (
                        <div>
                          <div style={_LBL}>🎟️ Licenciamiento esperado</div>
                          <div>
                            {brief.licensingRequirements.tier && <span style={Object.assign({}, _PILL, { background: '#00BCEB', color: '#fff' })}>{brief.licensingRequirements.tier}</span>}
                            {brief.licensingRequirements.endpointCount && <span style={Object.assign({}, _PILL, { background: 'var(--s2)', color: 'var(--i1)', border: '1px solid var(--line-soft)' })}>{brief.licensingRequirements.endpointCount.toLocaleString ? brief.licensingRequirements.endpointCount.toLocaleString() : brief.licensingRequirements.endpointCount} endpoints</span>}
                            {brief.licensingRequirements.subscriptionTerm && <span style={Object.assign({}, _PILL, { background: 'var(--s2)', color: 'var(--i1)', border: '1px solid var(--line-soft)' })}>{brief.licensingRequirements.subscriptionTerm}</span>}
                            {brief.licensingRequirements.deviceAdmin && <span style={Object.assign({}, _PILL, { background: '#6CC04A', color: '#fff' })}>Device Admin</span>}
                          </div>
                          {brief.licensingRequirements.features && brief.licensingRequirements.features.length > 0 && (
                            <div style={{ fontSize: '11px', color: 'var(--i2)', marginTop: '4px' }}>
                              <strong>Features:</strong> {brief.licensingRequirements.features.join(', ')}
                            </div>
                          )}
                        </div>
                      )}

                      {/* Gold-standard BOM */}
                      {brief.goldStandardBom && (
                        <details open>
                          <summary style={Object.assign({}, _LBL, { cursor: 'pointer', marginBottom: '6px', color: '#6CC04A' })}>🏆 BOM gold standard (referencia)</summary>
                          <div style={{ padding: '4px 0 0 4px', fontSize: '12px', display: 'flex', flexDirection: 'column', gap: '8px' }}>
                            {brief.goldStandardBom.iseNodes && brief.goldStandardBom.iseNodes.length > 0 && (
                              <div>
                                <div style={{ fontWeight: 700, color: 'var(--i1)', marginBottom: '3px' }}>Nodos ISE</div>
                                <ul style={{ margin: 0, paddingLeft: '16px', color: 'var(--i2)' }}>
                                  {brief.goldStandardBom.iseNodes.map(function(n, i) {
                                    var txt = (typeof n === 'string') ? n : (n.qty ? n.qty + '× ' : '') + (n.model || '') + (n.role ? ' (' + n.role + ')' : '') + (n.notes ? ' — ' + n.notes : '');
                                    return <li key={i} style={{ marginBottom: '2px' }}>{txt}</li>;
                                  })}
                                </ul>
                              </div>
                            )}
                            {brief.goldStandardBom.licensing && brief.goldStandardBom.licensing.length > 0 && (
                              <div>
                                <div style={{ fontWeight: 700, color: 'var(--i1)', marginBottom: '3px' }}>Licencias</div>
                                <ul style={{ margin: 0, paddingLeft: '16px', color: 'var(--i2)' }}>
                                  {brief.goldStandardBom.licensing.map(function(l, i) {
                                    var txt = (typeof l === 'string') ? l : (l.sku ? l.sku + ' ' : '') + (l.qty ? '×' + l.qty + ' ' : '') + (l.description || l.notes || '');
                                    return <li key={i} style={{ marginBottom: '2px' }}>{txt}</li>;
                                  })}
                                </ul>
                              </div>
                            )}
                            {brief.goldStandardBom.integration && brief.goldStandardBom.integration.length > 0 && (
                              <div>
                                <div style={{ fontWeight: 700, color: 'var(--i1)', marginBottom: '3px' }}>Integraciones esperadas</div>
                                <ul style={{ margin: 0, paddingLeft: '16px', color: 'var(--i2)' }}>
                                  {brief.goldStandardBom.integration.map(function(it, i) {
                                    return <li key={i} style={{ marginBottom: '2px' }}>{typeof it === 'string' ? it : (it.name || JSON.stringify(it))}</li>;
                                  })}
                                </ul>
                              </div>
                            )}
                            {brief.goldStandardBom.commonMistakes && brief.goldStandardBom.commonMistakes.length > 0 && (
                              <div style={{ background: 'color-mix(in srgb, #E74C3C 10%, transparent)', border: '1px solid color-mix(in srgb, #E74C3C 30%, transparent)', borderRadius: '6px', padding: '8px 10px', marginTop: '4px' }}>
                                <div style={{ fontWeight: 700, color: '#C0392B', marginBottom: '4px', fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.04em' }}>❌ Errores comunes — buscar en la entrega</div>
                                <ul style={{ margin: 0, paddingLeft: '16px', color: 'var(--i2)' }}>
                                  {brief.goldStandardBom.commonMistakes.map(function(m, i) { return <li key={i} style={{ marginBottom: '3px' }}>{m}</li>; })}
                                </ul>
                              </div>
                            )}
                          </div>
                        </details>
                      )}

                      {/* BOM focus hint */}
                      {brief.bomFocus && (
                        <div style={{ fontSize: '11px', color: 'var(--i3)', fontStyle: 'italic', borderTop: '1px dashed var(--line-soft)', paddingTop: '8px' }}>
                          <strong>Foco BOM:</strong> {brief.bomFocus}
                        </div>
                      )}
                    </div>
                  )}
                </div>
              )}
              {/* BOM file */}
              {selectedTeam.submission.bom_file && (
                <div>
                  <div style={{ fontSize: '11px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: '4px' }}>BOM File</div>
                  <a
                    href={'/uploads/' + encodeURIComponent(gameId) + '/' + encodeURIComponent(selectedTeam.team_id) + '/' + selectedTeam.submission.bom_file}
                    target="_blank"
                    rel="noreferrer"
                    style={{ color: '#00BCEB', fontSize: '13px' }}
                  >
                    📄 {selectedTeam.submission.bom_file}
                  </a>
                </div>
              )}
              {/* Architecture image */}
              {selectedTeam.submission.arch_file && /\.(png|jpg|jpeg|gif|webp|svg)$/i.test(selectedTeam.submission.arch_file) && (
                <div>
                  <div style={{ fontSize: '11px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: '6px' }}>Architecture Diagram</div>
                  <img
                    src={'/uploads/' + encodeURIComponent(gameId) + '/' + encodeURIComponent(selectedTeam.team_id) + '/' + selectedTeam.submission.arch_file}
                    alt="Architecture diagram"
                    style={{ maxWidth: '100%', border: '1px solid var(--line-soft)', borderRadius: '8px' }}
                  />
                </div>
              )}
              {/* Non-image arch file */}
              {selectedTeam.submission.arch_file && !/\.(png|jpg|jpeg|gif|webp|svg)$/i.test(selectedTeam.submission.arch_file) && (
                <div>
                  <div style={{ fontSize: '11px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: '4px' }}>Architecture File</div>
                  <a
                    href={'/uploads/' + encodeURIComponent(gameId) + '/' + encodeURIComponent(selectedTeam.team_id) + '/' + selectedTeam.submission.arch_file}
                    target="_blank"
                    rel="noreferrer"
                    style={{ color: '#00BCEB', fontSize: '13px' }}
                  >
                    📎 {selectedTeam.submission.arch_file}
                  </a>
                </div>
              )}
              {/* Free-text / notes from team */}
              {selectedTeam.submission.notes && (
                <div>
                  <div style={{ fontSize: '11px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.05em', marginBottom: '4px' }}>Team Notes</div>
                  <blockquote style={{ margin: '0', padding: '10px 14px', borderLeft: '3px solid #00BCEB', background: 'var(--s2)', borderRadius: '0 6px 6px 0', fontSize: '13px', color: 'var(--i2)' }}>
                    {selectedTeam.submission.notes}
                  </blockquote>
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {/* Right rail — rubric */}
      <div className="card">
        <div className="card-hd"><h3 style={{ fontSize: '13px' }}>Rubric</h3></div>
        <div className="card-bd" style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: '14px' }}>
          {RUBRIC.map(function(dim) {
            return (
              <div key={dim.key}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '6px' }}>
                  <span style={{ fontSize: '12px', fontWeight: 600, color: 'var(--i1)' }}>{dim.label}</span>
                  <span style={{ fontSize: '12px', fontFamily: 'var(--f-m)', color: dim.val > 0 ? '#00BCEB' : 'var(--i3)' }}>
                    {dim.val}/{dim.max}
                  </span>
                </div>
                <div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}>
                  {dim.bands.map(function(band) {
                    var isSelected = dim.val === band;
                    return (
                      <button
                        key={band}
                        onClick={function() { dim.set(band); }}
                        style={{
                          padding: '4px 10px',
                          fontSize: '12px',
                          border: '1px solid ' + (isSelected ? '#00BCEB' : 'var(--line-soft)'),
                          background: isSelected ? '#00BCEB' : 'var(--s2)',
                          color: isSelected ? '#fff' : 'var(--i2)',
                          borderRadius: '4px',
                          cursor: 'pointer',
                          fontWeight: isSelected ? 700 : 400,
                          transition: 'all .1s',
                        }}
                      >{band}</button>
                    );
                  })}
                </div>
              </div>
            );
          })}

          {/* Total */}
          <div style={{ borderTop: '1px solid var(--line-soft)', paddingTop: '12px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span style={{ fontSize: '14px', fontWeight: 700 }}>Total</span>
            <span style={{ fontSize: '22px', fontWeight: 800, color: '#00BCEB', fontFamily: 'var(--f-m)' }}>{total} / 500</span>
          </div>

          {/* Notes */}
          <div>
            <div style={{ fontSize: '11px', color: 'var(--i3)', marginBottom: '4px', textTransform: 'uppercase', letterSpacing: '.05em' }}>Notes</div>
            <textarea
              value={notes}
              onChange={function(e) { setNotes(e.target.value); }}
              rows={3}
              placeholder="Optional feedback for the team…"
              style={{ width: '100%', padding: '8px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '12px', resize: 'vertical', boxSizing: 'border-box' }}
            />
          </div>

          {/* Save */}
          <button
            className="btn primary"
            disabled={saving || total === 0}
            onClick={handleSave}
            style={{ background: '#00BCEB', borderColor: '#00BCEB', fontWeight: 700 }}
          >
            {saving ? 'Saving…' : saveMsg || '💾 Save & next team'}
          </button>
          {saveError && <div style={{ color: 'var(--dn)', fontSize: '12px' }}>{saveError}</div>}
          <div style={{ fontSize: '11px', color: 'var(--i3)' }}>Shortcuts: J/K = next/prev team · Enter = save</div>
        </div>
      </div>
    </div>
  );
};

// ---------------------------------------------------------------------------
// ZonaMixtaScoringTab — LIVE verbal scoring (no text submission from teams)
// ---------------------------------------------------------------------------
window.ZonaMixtaScoringTab = function ZonaMixtaScoringTab(props) {
  var gameId = props.gameId;

  var _c1 = React.useState(0), curveball = _c1[0], setCurveball = _c1[1];
  var _c2 = React.useState([]), teams = _c2[0], setTeams = _c2[1];
  var _c3 = React.useState(false), loading = _c3[0], setLoading = _c3[1];
  var _c4 = React.useState({}), scores = _c4[0], setScores = _c4[1];
  var _c5 = React.useState({}), notesMap = _c5[0], setNotesMap = _c5[1];
  var _c6 = React.useState({}), savedMap = _c6[0], setSavedMap = _c6[1];
  var _c7 = React.useState({}), adjustMap = _c7[0], setAdjustMap = _c7[1];
  var _c8 = React.useState(''), curveballQuestion = _c8[0], setCurveballQuestion = _c8[1];
  var _c9 = React.useState(''), curveballSolution = _c9[0], setCurveballSolution = _c9[1];
  var _c10 = React.useState(''), curveballContext = _c10[0], setCurveballContext = _c10[1];
  var _c11 = React.useState(''), curveballHints = _c11[0], setCurveballHints = _c11[1];

  // Helper: read curveball reference data from window.CURVEBALLS JS global (fallback)
  function _getCBLocal(idx) {
    try {
      var cbs = (typeof window !== 'undefined' && window.CURVEBALLS) ? window.CURVEBALLS : null;
      if (cbs && cbs[idx]) return cbs[idx];
    } catch(e) {}
    return null;
  }

  function _zmAuthHeaders() {
    var t = (window.AdminSession && window.AdminSession.getToken) ? window.AdminSession.getToken() : null;
    return t ? { 'Authorization': 'Bearer ' + t } : {};
  }

  React.useEffect(function() {
    if (!gameId) return;
    setLoading(true);
    fetch('/api/g/' + encodeURIComponent(gameId) + '/proctor/zonamixta-teams?curveball_index=' + curveball, { headers: _zmAuthHeaders() })
      .then(function(r) { return r.ok ? r.json() : Promise.reject(r); })
      .then(function(data) {
        setTeams(data.teams || []);
        // Use API fields first, fall back to window.CURVEBALLS for reference data
        var localCB = _getCBLocal(curveball);
        setCurveballQuestion(data.curveball_question || (localCB && localCB.text) || '');
        setCurveballSolution(data.curveball_solution || (localCB && localCB.strongResponse) || '');
        setCurveballContext(data.curveball_context || (localCB && localCB.context) || '');
        setCurveballHints(data.curveball_hints || (localCB && localCB.weakResponse) || '');
        // Preload existing scores
        var sc = {};
        var adj = {};
        (data.teams || []).forEach(function(t) {
          if (t.score) { sc[t.team_id] = t.score.score; adj[t.team_id] = 0; }
        });
        setScores(sc);
        setAdjustMap(adj);
      })
      .catch(function() {
        // If API fails entirely, still try to load local curveball data
        var localCB = _getCBLocal(curveball);
        if (localCB) {
          setCurveballQuestion(localCB.text || '');
          setCurveballSolution(localCB.strongResponse || '');
          setCurveballContext(localCB.context || '');
          setCurveballHints(localCB.weakResponse || '');
        }
      })
      .finally(function() { setLoading(false); });
  }, [gameId, curveball]);

  function setScore(teamId, base) {
    setScores(function(prev) { return Object.assign({}, prev, { [teamId]: base }); });
    setAdjustMap(function(prev) { return Object.assign({}, prev, { [teamId]: 0 }); });
  }

  function adjustScore(teamId, delta) {
    setAdjustMap(function(prev) { return Object.assign({}, prev, { [teamId]: (prev[teamId] || 0) + delta }); });
  }

  function finalScore(teamId) {
    return (scores[teamId] || 0) + (adjustMap[teamId] || 0);
  }

  function handleSave(teamId) {
    var fs = finalScore(teamId);
    fetch('/api/g/' + encodeURIComponent(gameId) + '/proctor/zonamixta-score', {
      method: 'POST',
      headers: Object.assign({ 'Content-Type': 'application/json' }, _zmAuthHeaders()),
      body: JSON.stringify({
        curveball_index: curveball,
        team_id: teamId,
        score: fs,
        notes: notesMap[teamId] || '',
      }),
    })
      .then(function(r) { return r.ok ? r.json() : Promise.reject(r); })
      .then(function() {
        setSavedMap(function(prev) { return Object.assign({}, prev, { [teamId]: true }); });
        setTimeout(function() {
          setSavedMap(function(prev) { var n = Object.assign({}, prev); delete n[teamId]; return n; });
        }, 2000);
      })
      .catch(function() {});
  }

  var BANDS = [
    { score: 25, label: '25 — Weak' },
    { score: 60, label: '60 — Partial' },
    { score: 85, label: '85 — Strong' },
  ];

  return (
    <div>
      {/* Curveball selector — full width above both columns */}
      <div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '16px' }}>
        <span style={{ fontSize: '13px', fontWeight: 600, color: 'var(--i2)' }}>Curveball:</span>
        {[0,1,2,3,4].map(function(n) {
          var isActive = curveball === n;
          return (
            <button
              key={n}
              onClick={function() { setCurveball(n); }}
              style={{
                padding: '6px 14px',
                border: '1px solid ' + (isActive ? '#00BCEB' : 'var(--line-soft)'),
                background: isActive ? '#00BCEB' : 'var(--s2)',
                color: isActive ? '#fff' : 'var(--i2)',
                borderRadius: '6px',
                cursor: 'pointer',
                fontWeight: isActive ? 700 : 500,
                fontSize: '13px',
              }}
            >#{n + 1}</button>
          );
        })}
      </div>

      {/* 2-column layout */}
      <div style={{ display: 'flex', gap: '16px', alignItems: 'flex-start' }}>

        {/* LEFT COLUMN — Reference panel (40%, sticky) */}
        <div style={{ flex: '0 0 40%', maxWidth: '40%', position: 'sticky', top: '16px', display: 'flex', flexDirection: 'column', gap: '12px' }}>

          {/* 📋 La pregunta */}
          <div style={{ padding: '14px 16px', background: 'var(--s2)', border: '1px solid #FF6600', borderRadius: '8px' }}>
            <div style={{ fontSize: '11px', fontWeight: 700, color: '#FF6600', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '8px' }}>📋 La pregunta</div>
            {curveballQuestion
              ? <p style={{ margin: 0, fontSize: '13px', color: 'var(--i1)', lineHeight: '1.7', fontWeight: 500 }}>{curveballQuestion}</p>
              : <p style={{ margin: 0, fontSize: '12px', color: 'var(--i3)', fontStyle: 'italic' }}>Selecciona un curveball arriba</p>
            }
          </div>

          {/* 💡 Respuesta de referencia */}
          {curveballSolution ? (
            <div style={{ padding: '14px 16px', background: 'rgba(22,101,52,0.12)', border: '1px solid rgba(22,101,52,0.4)', borderRadius: '8px' }}>
              <div style={{ fontSize: '11px', fontWeight: 700, color: '#22c55e', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '4px' }}>💡 Respuesta de referencia</div>
              <div style={{ fontSize: '10px', color: '#86efac', fontStyle: 'italic', marginBottom: '8px' }}>Para referencia del proctor — no compartir con jugadores</div>
              <p style={{ margin: 0, fontSize: '12px', color: 'var(--i1)', lineHeight: '1.7', whiteSpace: 'pre-wrap' }}>{curveballSolution}</p>
            </div>
          ) : null}

          {/* 📌 Respuestas débiles a evitar */}
          {curveballHints ? (
            <div style={{ padding: '12px 14px', background: 'rgba(234,179,8,0.08)', border: '1px solid rgba(234,179,8,0.3)', borderRadius: '8px' }}>
              <div style={{ fontSize: '11px', fontWeight: 700, color: '#eab308', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '6px' }}>📌 Señales de alerta</div>
              <p style={{ margin: 0, fontSize: '12px', color: 'var(--i2)', lineHeight: '1.6', whiteSpace: 'pre-wrap' }}>{curveballHints}</p>
            </div>
          ) : null}

          {/* Context/scenario if available */}
          {curveballContext ? (
            <div style={{ padding: '10px 14px', background: 'var(--s2)', border: '1px solid var(--line-soft)', borderRadius: '8px' }}>
              <div style={{ fontSize: '11px', fontWeight: 700, color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: '6px' }}>🎯 Contexto</div>
              <p style={{ margin: 0, fontSize: '12px', color: 'var(--i3)', lineHeight: '1.6', fontStyle: 'italic' }}>{curveballContext}</p>
            </div>
          ) : null}
        </div>

        {/* RIGHT COLUMN — LIVE scoring (60%) */}
        <div style={{ flex: '1 1 60%', display: 'flex', flexDirection: 'column', gap: '12px' }}>

          {/* LIVE badge */}
          <div style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '10px 14px', background: 'rgba(255,102,0,0.1)', border: '1px solid #FF6600', borderRadius: '8px' }}>
            <span style={{ fontSize: '18px' }}>🎤</span>
            <span style={{ fontSize: '13px', fontWeight: 600, color: '#FF6600' }}>LIVE — proctor listens to verbal answers and scores each team</span>
          </div>

          {loading && (
            <div style={{ padding: '32px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }}>Loading teams…</div>
          )}

          <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
            {teams.map(function(team, idx) {
              var teamColor = team.team_color || '#049FD9';
              var base = scores[team.team_id];
              var adj = adjustMap[team.team_id] || 0;
              var fs = finalScore(team.team_id);
              return (
                <div key={team.team_id} className="card" style={{ borderLeft: '4px solid ' + teamColor }}>
                  <div className="card-hd" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                      <span style={{ display: 'inline-block', width: '12px', height: '12px', borderRadius: '50%', background: teamColor, flexShrink: 0 }}></span>
                      <h3 style={{ fontSize: '14px', color: teamColor, margin: 0 }}>{team.team_name || team.team_id}</h3>
                    </div>
                    {base != null && (
                      <span style={{ fontSize: '18px', fontWeight: 800, fontFamily: 'var(--f-m)', color: '#00BCEB' }}>
                        {fs} pts
                      </span>
                    )}
                  </div>
                  <div className="card-bd" style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: '10px' }}>
                    {/* Quick notes textarea */}
                    <textarea
                      rows={2}
                      placeholder="¿Qué dijo este equipo? (notas rápidas)"
                      value={notesMap[team.team_id] || ''}
                      onChange={function(e) {
                        var v = e.target.value;
                        setNotesMap(function(prev) { return Object.assign({}, prev, { [team.team_id]: v }); });
                      }}
                      style={{ padding: '6px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '12px', resize: 'vertical', lineHeight: '1.5', fontFamily: 'inherit' }}
                    />
                    {/* Band buttons */}
                    <div style={{ display: 'flex', gap: '8px', alignItems: 'center', flexWrap: 'wrap' }}>
                      {BANDS.map(function(band) {
                        var isSel = base === band.score;
                        return (
                          <button
                            key={band.score}
                            onClick={function() { setScore(team.team_id, band.score); }}
                            style={{
                              padding: '8px 16px',
                              border: '1px solid ' + (isSel ? '#00BCEB' : 'var(--line-soft)'),
                              background: isSel ? '#00BCEB' : 'var(--s2)',
                              color: isSel ? '#fff' : 'var(--i2)',
                              borderRadius: '6px',
                              cursor: 'pointer',
                              fontWeight: isSel ? 700 : 400,
                              fontSize: '13px',
                            }}
                          >{band.label}</button>
                        );
                      })}
                      {/* ±10 adjustment */}
                      {base != null && (
                        <div style={{ display: 'flex', gap: '4px', alignItems: 'center', marginLeft: '8px' }}>
                          <button onClick={function() { adjustScore(team.team_id, -10); }}
                            style={{ padding: '4px 8px', border: '1px solid var(--line-soft)', background: 'var(--s2)', borderRadius: '4px', cursor: 'pointer', fontSize: '12px' }}>−10</button>
                          <span style={{ fontSize: '12px', color: adj !== 0 ? '#00BCEB' : 'var(--i3)', minWidth: '30px', textAlign: 'center' }}>
                            {adj > 0 ? '+' + adj : (adj < 0 ? adj : '±0')}
                          </span>
                          <button onClick={function() { adjustScore(team.team_id, 10); }}
                            style={{ padding: '4px 8px', border: '1px solid var(--line-soft)', background: 'var(--s2)', borderRadius: '4px', cursor: 'pointer', fontSize: '12px' }}>+10</button>
                        </div>
                      )}
                    </div>
                    <button
                      className="btn primary"
                      disabled={base == null}
                      onClick={function() { handleSave(team.team_id); }}
                      style={{ alignSelf: 'flex-start', background: '#00BCEB', borderColor: '#00BCEB' }}
                    >
                      {savedMap[team.team_id] ? '✅ Guardado' : '💾 Guardar'}
                    </button>
                  </div>
                </div>
              );
            })}
            {!loading && teams.length === 0 && (
              <div style={{ padding: '32px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }}>No teams found for this game yet.</div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

// ---------------------------------------------------------------------------
// TriageReviewTab
// ---------------------------------------------------------------------------
window.TriageReviewTab = function TriageReviewTab(props) {
  var gameId = props.gameId;
  var initialAnswers = props.initialAnswers || [];

  var _t1 = React.useState(initialAnswers), answers = _t1[0], setAnswers = _t1[1];
  var _t2 = React.useState(''), filterPlayer = _t2[0], setFilterPlayer = _t2[1];
  var _t3 = React.useState(''), filterTicket = _t3[0], setFilterTicket = _t3[1];
  var _t4 = React.useState(null), expandedRow = _t4[0], setExpandedRow = _t4[1];
  var _t5 = React.useState(null), overrideRow = _t5[0], setOverrideRow = _t5[1];
  var _t6 = React.useState(''), overrideScore = _t6[0], setOverrideScore = _t6[1];
  var _t7 = React.useState(''), overrideReason = _t7[0], setOverrideReason = _t7[1];
  var _t8 = React.useState(false), overrideSaving = _t8[0], setOverrideSaving = _t8[1];
  var _t9 = React.useState(''), overrideMsg = _t9[0], setOverrideMsg = _t9[1];

  React.useEffect(function() {
    setAnswers(initialAnswers);
  }, [initialAnswers.length]);

  // Unique players / tickets for filters
  var playerSet = {};
  answers.forEach(function(a) { if (a.email) playerSet[a.email] = a.player_name || a.email; });
  var ticketSet = {};
  answers.forEach(function(a) { if (a.ticket_number != null) ticketSet[a.ticket_number] = true; });

  var filtered = answers.filter(function(a) {
    if (filterPlayer && a.email !== filterPlayer) return false;
    if (filterTicket && String(a.ticket_number) !== filterTicket) return false;
    return true;
  });

  function handleOverrideSave() {
    if (!overrideRow) return;
    var score = parseFloat(overrideScore);
    if (isNaN(score)) { setOverrideMsg('Enter a valid score'); return; }
    setOverrideSaving(true);
    fetch('/api/g/' + encodeURIComponent(gameId) + '/ticket-answer/proctor-score', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        answer_id: overrideRow.id,
        score: score,
        reason: overrideReason,
      }),
    })
      .then(function(r) { return r.ok ? r.json() : Promise.reject(r); })
      .then(function() {
        setOverrideMsg('Saved!');
        setTimeout(function() { setOverrideRow(null); setOverrideMsg(''); }, 1200);
        // Update local state
        setAnswers(function(prev) {
          return prev.map(function(a) {
            if (a.id === overrideRow.id) return Object.assign({}, a, { proctor_score: score, proctor_scored: 1 });
            return a;
          });
        });
      })
      .catch(function() { setOverrideMsg('Save failed'); })
      .finally(function() { setOverrideSaving(false); });
  }

  return (
    <div>
      {/* Filters */}
      <div style={{ display: 'flex', gap: '12px', marginBottom: '16px', flexWrap: 'wrap', alignItems: 'center' }}>
        <select
          value={filterPlayer}
          onChange={function(e) { setFilterPlayer(e.target.value); }}
          style={{ padding: '6px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}
        >
          <option value="">All players</option>
          {Object.entries(playerSet).map(function(kv) {
            return <option key={kv[0]} value={kv[0]}>{kv[1]}</option>;
          })}
        </select>
        <select
          value={filterTicket}
          onChange={function(e) { setFilterTicket(e.target.value); }}
          style={{ padding: '6px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}
        >
          <option value="">All tickets</option>
          {Object.keys(ticketSet).sort(function(a,b){return a-b;}).map(function(tn) {
            return <option key={tn} value={tn}>Ticket #{tn}</option>;
          })}
        </select>
        <span style={{ fontSize: '12px', color: 'var(--i3)' }}>{filtered.length} row{filtered.length !== 1 ? 's' : ''}</span>
        {(filterPlayer || filterTicket) && (
          <button className="btn ghost" style={{ fontSize: '12px' }} onClick={function() { setFilterPlayer(''); setFilterTicket(''); }}>✕ Clear filters</button>
        )}
      </div>

      {/* Table */}
      <div style={{ overflowX: 'auto' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '13px' }}>
          <thead>
            <tr style={{ borderBottom: '2px solid var(--line-soft)', textAlign: 'left' }}>
              <th style={{ padding: '8px 10px', color: 'var(--i3)', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em' }}>Jugador</th>
              <th style={{ padding: '8px 10px', color: 'var(--i3)', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em' }}>Ticket</th>
              <th style={{ padding: '8px 10px', color: 'var(--i3)', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em' }}>Pregunta (preview)</th>
              <th style={{ padding: '8px 10px', color: 'var(--i3)', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em' }}>Score</th>
              <th style={{ padding: '8px 10px', color: 'var(--i3)', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em' }}>Estado</th>
              <th style={{ padding: '8px 10px', color: 'var(--i3)', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em' }}></th>
            </tr>
          </thead>
          <tbody>
            {filtered.length === 0 && (
              <tr><td colSpan={6} style={{ padding: '32px', textAlign: 'center', color: 'var(--i3)' }}>No responses found.</td></tr>
            )}
            {filtered.map(function(row, idx) {
              var rowKey = row.id || idx;
              var isExpanded = expandedRow === rowKey;
              var questionPreview = (row.ticket_question || row.question || '—').slice(0, 80) + ((row.ticket_question || row.question || '').length > 80 ? '…' : '');
              var statusBadge = row.proctor_scored
                ? <span style={{ fontSize: '11px', background: 'rgba(108,192,74,0.15)', color: '#6CC04A', padding: '2px 6px', borderRadius: '10px', fontWeight: 600 }}>⚠️ Override</span>
                : (row.ai_available
                  ? <span style={{ fontSize: '11px', background: 'rgba(4,159,217,0.12)', color: '#049FD9', padding: '2px 6px', borderRadius: '10px', fontWeight: 600 }}>✅ AI scored</span>
                  : <span style={{ fontSize: '11px', background: 'rgba(255,180,0,0.12)', color: '#FFAA00', padding: '2px 6px', borderRadius: '10px', fontWeight: 600 }}>⏳ Pendiente</span>
                );
              var finalScore = row.proctor_scored ? row.proctor_score : (row.ai_score != null ? row.ai_score : null);

              return [
                /* Collapsed row */
                <tr key={'row-' + rowKey} style={{ borderBottom: isExpanded ? 'none' : '1px solid var(--line-soft)', verticalAlign: 'middle', background: idx % 2 === 0 ? 'transparent' : 'var(--s2)' }}>
                  <td style={{ padding: '10px 10px', whiteSpace: 'nowrap' }}>
                    <div style={{ fontWeight: 600, fontSize: '13px' }}>{row.player_name || row.email || '—'}</div>
                    {row.player_team && <div style={{ fontSize: '11px', color: 'var(--i3)' }}>{row.player_team}</div>}
                  </td>
                  <td style={{ padding: '10px 10px', whiteSpace: 'nowrap', fontFamily: 'var(--f-m)', fontSize: '12px' }}>
                    #{row.ticket_number || row.ticket_id?.slice(-4) || '—'}
                  </td>
                  <td style={{ padding: '10px 10px', maxWidth: '280px', color: 'var(--i2)', fontSize: '12px' }}>
                    {questionPreview}
                  </td>
                  <td style={{ padding: '10px 10px', whiteSpace: 'nowrap' }}>
                    <span style={{ fontWeight: 700, color: row.proctor_scored ? '#6CC04A' : '#049FD9' }}>
                      {finalScore != null ? finalScore : '—'}
                    </span>
                    <span style={{ color: 'var(--i3)', fontSize: '11px' }}>/100</span>
                  </td>
                  <td style={{ padding: '10px 10px' }}>{statusBadge}</td>
                  <td style={{ padding: '10px 10px', whiteSpace: 'nowrap', display: 'flex', gap: '6px', alignItems: 'center' }}>
                    <button
                      className="btn ghost"
                      style={{ fontSize: '11px', padding: '4px 8px' }}
                      onClick={function() { setExpandedRow(isExpanded ? null : rowKey); }}
                    >{isExpanded ? 'Colapsar ▲' : 'Expandir ▼'}</button>
                  </td>
                </tr>,

                /* Expanded detail row */
                isExpanded && (
                  <tr key={'exp-' + rowKey} style={{ borderBottom: '2px solid #049FD9', background: idx % 2 === 0 ? 'transparent' : 'var(--s2)' }}>
                    <td colSpan={6} style={{ padding: '0 12px 16px 12px' }}>
                      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginTop: '8px' }}>

                        {/* Panel 1: Ticket question */}
                        <div style={{ background: 'var(--s2)', border: '1px solid var(--line-soft)', borderRadius: '8px', padding: '12px', borderTop: '3px solid #049FD9' }}>
                          <div style={{ fontSize: '11px', fontWeight: 700, color: '#049FD9', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: '8px' }}>📋 Pregunta del ticket</div>
                          <div style={{ fontSize: '13px', color: 'var(--i1)', lineHeight: 1.55, whiteSpace: 'pre-wrap' }}>
                            {row.ticket_question || row.question || '—'}
                          </div>
                          {row.ticket_scenario && (
                            <div style={{ marginTop: '8px', paddingTop: '8px', borderTop: '1px solid var(--line-soft)' }}>
                              <div style={{ fontSize: '11px', color: 'var(--i3)', marginBottom: '4px', fontWeight: 600 }}>Escenario</div>
                              <div style={{ fontSize: '12px', color: 'var(--i2)', whiteSpace: 'pre-wrap', fontFamily: 'var(--f-m)' }}>{row.ticket_scenario}</div>
                            </div>
                          )}
                        </div>

                        {/* Panel 2: Expected/canonical answer */}
                        <div style={{ background: 'rgba(108,192,74,0.06)', border: '1px solid rgba(108,192,74,0.3)', borderRadius: '8px', padding: '12px', borderTop: '3px solid #6CC04A' }}>
                          <div style={{ fontSize: '11px', fontWeight: 700, color: '#6CC04A', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: '4px' }}>💡 Respuesta esperada (referencia)</div>
                          <div style={{ fontSize: '10px', color: 'var(--i3)', marginBottom: '8px', fontStyle: 'italic' }}>Para referencia del proctor — no compartir con jugadores</div>
                          <div style={{ fontSize: '12px', color: 'var(--i1)', whiteSpace: 'pre-wrap', fontFamily: 'var(--f-m)', lineHeight: 1.55 }}>
                            {row.ticket_solution || '—'}
                          </div>
                          {row.ticket_hint && (
                            <div style={{ marginTop: '8px', paddingTop: '8px', borderTop: '1px solid rgba(108,192,74,0.2)' }}>
                              <div style={{ fontSize: '11px', color: 'var(--i3)', marginBottom: '4px', fontWeight: 600 }}>💬 Pista</div>
                              <div style={{ fontSize: '12px', color: 'var(--i2)', fontStyle: 'italic' }}>{row.ticket_hint}</div>
                            </div>
                          )}
                        </div>

                        {/* Panel 3: Player answer */}
                        <div style={{ background: 'var(--s2)', border: '1px solid var(--line-soft)', borderRadius: '8px', padding: '12px', borderTop: '3px solid #FFAA00' }}>
                          <div style={{ fontSize: '11px', fontWeight: 700, color: '#FFAA00', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: '8px' }}>✍️ Respuesta del jugador</div>
                          <div style={{ fontSize: '13px', color: 'var(--i1)', whiteSpace: 'pre-wrap', lineHeight: 1.55, fontFamily: 'var(--f-m)' }}>
                            {row.answer || '—'}
                          </div>
                        </div>

                        {/* Panel 4: LLM evaluation + override */}
                        <div style={{ background: 'var(--s2)', border: '1px solid var(--line-soft)', borderRadius: '8px', padding: '12px', borderTop: '3px solid #9B59B6', display: 'flex', flexDirection: 'column', gap: '10px' }}>
                          <div>
                            <div style={{ fontSize: '11px', fontWeight: 700, color: '#9B59B6', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: '8px' }}>🤖 Evaluación del LLM</div>
                            {row.ai_available ? (
                              <div>
                                <span style={{ fontSize: '20px', fontWeight: 700, color: '#049FD9' }}>{row.ai_score != null ? row.ai_score : '—'}</span>
                                <span style={{ fontSize: '13px', color: 'var(--i3)' }}> / 100</span>
                                {row.ai_feedback && <div style={{ fontSize: '12px', color: 'var(--i2)', marginTop: '6px', lineHeight: 1.5 }}>{row.ai_feedback}</div>}
                              </div>
                            ) : (
                              <div style={{ fontSize: '12px', color: 'var(--i3)', fontStyle: 'italic' }}>IA no disponible — revisión manual requerida</div>
                            )}
                          </div>
                          <div style={{ borderTop: '1px solid var(--line-soft)', paddingTop: '10px' }}>
                            <div style={{ fontSize: '11px', fontWeight: 700, color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: '6px' }}>⚖️ Override del proctor</div>
                            {row.proctor_scored ? (
                              <div style={{ marginBottom: '8px', fontSize: '12px', color: '#6CC04A' }}>
                                Score actual: <strong>{row.proctor_score}/100</strong> (override aplicado)
                              </div>
                            ) : null}
                            <button
                              className="btn primary"
                              style={{ fontSize: '12px', padding: '6px 14px', background: '#00BCEB', borderColor: '#00BCEB' }}
                              onClick={function() {
                                setOverrideRow(row);
                                setOverrideScore(row.proctor_scored && row.proctor_score != null ? String(row.proctor_score) : (row.ai_score != null ? String(row.ai_score) : ''));
                                setOverrideReason('');
                                setOverrideMsg('');
                              }}
                            >{row.proctor_scored ? 'Cambiar override' : 'Override score'}</button>
                          </div>
                        </div>

                      </div>
                    </td>
                  </tr>
                ),
              ];
            })}
          </tbody>
        </table>
      </div>

      {/* Override modal */}
      {overrideRow && (
        <div style={{
          position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.55)', zIndex: 1000,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}
          onClick={function(e) { if (e.target === e.currentTarget) setOverrideRow(null); }}
        >
          <div className="card" style={{ width: '420px', maxWidth: '95vw' }}>
            <div className="card-hd">
              <h3>Override Score</h3>
            </div>
            <div className="card-bd" style={{ padding: '16px 18px', display: 'flex', flexDirection: 'column', gap: '12px' }}>
              <div style={{ fontSize: '13px', color: 'var(--i2)' }}>
                <strong>{overrideRow.player_name || overrideRow.email}</strong> — Ticket #{overrideRow.ticket_number}
              </div>
              <blockquote style={{ margin: '0', padding: '8px 12px', borderLeft: '3px solid #00BCEB', background: 'var(--s2)', fontSize: '12px', color: 'var(--i2)', borderRadius: '0 4px 4px 0' }}>
                {overrideRow.answer || '—'}
              </blockquote>
              <label style={{ display: 'flex', flexDirection: 'column', gap: '4px', fontSize: '13px' }}>
                New Score
                <input
                  type="number"
                  value={overrideScore}
                  onChange={function(e) { setOverrideScore(e.target.value); }}
                  style={{ padding: '8px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '14px', width: '100px' }}
                />
              </label>
              <label style={{ display: 'flex', flexDirection: 'column', gap: '4px', fontSize: '13px' }}>
                Reason (optional)
                <input
                  type="text"
                  value={overrideReason}
                  onChange={function(e) { setOverrideReason(e.target.value); }}
                  placeholder="Why are you overriding?"
                  style={{ padding: '8px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}
                />
              </label>
              {overrideMsg && <div style={{ fontSize: '13px', color: overrideMsg === 'Saved!' ? '#6CC04A' : 'var(--dn)' }}>{overrideMsg}</div>}
              <div style={{ display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
                <button className="btn ghost" onClick={function() { setOverrideRow(null); }}>Cancel</button>
                <button className="btn primary" disabled={overrideSaving} onClick={handleOverrideSave}
                  style={{ background: '#00BCEB', borderColor: '#00BCEB' }}>
                  {overrideSaving ? 'Saving…' : 'Save Override'}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgMonitorPage
// ---------------------------------------------------------------------------
window.OrgMonitorPage = function OrgMonitorPage(props) {
  var gameId = props.gameId || null;
  var detail = props.detail || null;
  var games = props.games || [];
  var onSelectGame = props.onSelectGame || function() {};
  var onSetPhase = props.onSetPhase || function() {};
  var onTimerAction = props.onTimerAction || function() {};
  var onResetGame = props.onResetGame || function() {};
  var showToast = props.showToast || function() {};

  // Resolve join code for display
  var _matchedGame = games.filter(function(g) { return g.game_id === gameId; })[0];
  var displayCode = _matchedGame && _matchedGame.join_code ? _matchedGame.join_code : gameId;

  // No game selected — show picker
  if (!gameId) {
    return (
      <div className="page-monitor">
        <div className="pghd">
          <div className="title">Monitor</div>
        </div>
        <div className="card" style={{ marginTop: '18px' }}>
          <div className="card-hd"><h3>Select a game to monitor</h3></div>
          <div className="card-bd" style={{ padding: '0' }}>
            {games.length === 0 ? (
              <div className="empty-state" style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>
                No games available.
              </div>
            ) : (
              <div className="game-picker">
                {games.map(function(game) {
                  return (
                    <div key={game.game_id}
                      style={{
                        display: 'flex',
                        alignItems: 'center',
                        gap: '14px',
                        padding: '12px 18px',
                        borderBottom: '1px solid var(--line-soft)',
                        cursor: 'pointer',
                        transition: 'background .15s',
                      }}
                      onClick={function() { onSelectGame(game.game_id); }}
                      onMouseEnter={function(e) { e.currentTarget.style.background = 'var(--s2)'; }}
                      onMouseLeave={function(e) { e.currentTarget.style.background = ''; }}
                    >
                       <code style={{ fontFamily: 'var(--f-m)', fontSize: '13px', fontWeight: 700, color: 'var(--brand)', background: 'var(--brand-soft)', padding: '3px 8px', borderRadius: '4px', letterSpacing: '1px' }}>
                        {game.join_code || game.game_id}
                      </code>
                       <span style={{ flex: 1, fontWeight: 600 }}>{game.name || '—'}</span>
                      <PhaseBadge phase={game.current_phase} />
                      <span style={{ fontSize: '12px', color: 'var(--i3)' }}>→</span>
                    </div>
                  );
                })}
              </div>
            )}
          </div>
        </div>
      </div>
    );
  }

  // Game selected but detail not loaded yet
  if (!detail) {
    return (
      <div className="page-monitor">
        <div className="pghd">
          <div className="title">Monitor · <code style={{ fontFamily: 'var(--f-m)' }}>{displayCode}</code></div>
        </div>
        <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>Loading game detail…</div>
      </div>
    );
  }

  var game = detail.game || {};
  var leaderboard = detail.leaderboard || [];
  var players = detail.players || [];
  var phase = detail.phase || game.current_phase || 'registration';
  var timer = detail.timer || null;

  var phaseOptions = ['registration', 'playing'];

  var _tp1 = React.useState(10), testPlayerCount = _tp1[0], setTestPlayerCount = _tp1[1];
  var _tp2 = React.useState(false), generatingPlayers = _tp2[0], setGeneratingPlayers = _tp2[1];

  // Quiz sampling config
  var _qc1 = React.useState(game.quiz_count || 10), quizCount = _qc1[0], setQuizCount = _qc1[1];
  var _qc2 = React.useState(game.fun_count != null ? game.fun_count : 3), funCount = _qc2[0], setFunCount = _qc2[1];
  var _qc3 = React.useState(false), savingQuizConfig = _qc3[0], setSavingQuizConfig = _qc3[1];
  var _tc1 = React.useState(game.ticket_count || 1), ticketCount = _tc1[0], setTicketCount = _tc1[1];
  var _gp1 = React.useState(game.gameplan_count || 0), gameplanCount = _gp1[0], setGameplanCount = _gp1[1];
  var _zm1 = React.useState(game.zonamixta_count || 0), zonamixtaCount = _zm1[0], setZonamixtaCount = _zm1[1];

  // Active proctor tab
  var _at1 = React.useState('control'), activeTab = _at1[0], setActiveTab = _at1[1];

  // Duration input for set-duration control (stored in seconds internally)
  // Synced from server timer[currentSubPhase].duration on first load.
  // userEditedDuration ref prevents server polls from clobbering the proctor's typed value.
  var _di1 = React.useState(1500), durationInput = _di1[0], setDurationInput = _di1[1];
  var userEditedDuration = React.useRef(false);
  React.useEffect(function() {
    var activePhaseDur = timer && currentSubPhase && timer[currentSubPhase] && timer[currentSubPhase].duration;
    if (!activePhaseDur) activePhaseDur = timer && timer.quiz && timer.quiz.duration;
    if (activePhaseDur && !userEditedDuration.current) { setDurationInput(activePhaseDur); }
  }, [timer && currentSubPhase && timer[currentSubPhase] && timer[currentSubPhase].duration,
      timer && timer.quiz && timer.quiz.duration]);

  // Triage state
  var _tria = React.useState([]), ticketAnswers = _tria[0], setTicketAnswers = _tria[1];

  // Current sub-phase (for state-machine guards on advance buttons)
  var _sp1 = React.useState(null), currentSubPhase = _sp1[0], setCurrentSubPhase = _sp1[1];

  // Observer mode toast
  var _obs1 = React.useState(null), observerToast = _obs1[0], setObserverToast = _obs1[1];

  // Sync when server data updates
  React.useEffect(function() { if (game.quiz_count != null) setQuizCount(game.quiz_count); }, [game.quiz_count]);
  React.useEffect(function() { if (game.fun_count != null) setFunCount(game.fun_count); }, [game.fun_count]);
  React.useEffect(function() { if (game.ticket_count != null) setTicketCount(game.ticket_count); }, [game.ticket_count]);
  React.useEffect(function() { if (game.gameplan_count != null) setGameplanCount(game.gameplan_count); }, [game.gameplan_count]);
  React.useEffect(function() { if (game.zonamixta_count != null) setZonamixtaCount(game.zonamixta_count); }, [game.zonamixta_count]);

  // Triage fetch — runs when game enters playing phase, refreshes every 15s
  React.useEffect(function() {
    if (phase !== 'playing' || !gameId) return;
    function fetchTicketAnswers() {
      AdminApi.getTicketAnswers(gameId)
        .then(function(data) { setTicketAnswers(Array.isArray(data) ? data : data.answers || []); })
        .catch(function() {});
    }
    fetchTicketAnswers();
    var triageTimer = setInterval(fetchTicketAnswers, 15000);
    return function() { clearInterval(triageTimer); };
  }, [phase, gameId]);

  // Sub-phase polling — refresh every 4s while in playing
  React.useEffect(function() {
    if (phase !== 'playing' || !gameId) { setCurrentSubPhase(null); return; }
    function fetchSubPhase() {
      AdminApi.getSubPhase(gameId)
        .then(function(data) { setCurrentSubPhase(data && data.sub_phase ? data.sub_phase : null); })
        .catch(function() {});
    }
    fetchSubPhase();
    var spTimer = setInterval(fetchSubPhase, 4000);
    return function() { clearInterval(spTimer); };
  }, [phase, gameId]);

    var _actRef = React.useState([]);
    var activity = _actRef[0];
    var setActivity = _actRef[1];

    React.useEffect(function() {
      if (!gameId) return;
      function fetchActivity() {
        AdminApi.getActivity(gameId).then(function(data) {
          setActivity(data || []);
        }).catch(function() {});
      }
      fetchActivity();
      var interval = setInterval(fetchActivity, 10000);
      return function() { clearInterval(interval); };
    }, [gameId]);

  function handleSaveQuizConfig() {
    setSavingQuizConfig(true);
    fetch('/api/g/' + encodeURIComponent(gameId) + '/quiz-config', {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ quiz_count: quizCount, fun_count: funCount, ticket_count: ticketCount, gameplan_count: gameplanCount, zonamixta_count: zonamixtaCount })
    })
      .then(function(r) { return r.ok ? r.json() : Promise.reject(r); })
      .then(function(res) {
        var gpMsg = res.gameplan_count ? res.gameplan_count : 'all';
        var zmMsg = res.zonamixta_count ? res.zonamixta_count : 'all';
        showToast('Saved: ' + res.quiz_count + ' tech + ' + res.fun_count + ' fun + ' + res.ticket_count + ' tix · GP:' + gpMsg + ' · ZM:' + zmMsg, 'ok');
      })
      .catch(function(err) { showToast('Failed to save quiz config', 'error'); })
      .finally(function() { setSavingQuizConfig(false); });
  }

  function handleGenerateTestPlayers() {
    setGeneratingPlayers(true);
    AdminApi.generateTestPlayers(gameId, testPlayerCount)
      .then(function(res) {
        var cnt = res.count || testPlayerCount;
        if (props.showToast) props.showToast(cnt + ' test players created', 'ok');
        setGeneratingPlayers(false);
        if (props.onForceRefresh) props.onForceRefresh();
      })
      .catch(function(err) {
        if (props.showToast) props.showToast('Failed: ' + err.message, 'dn');
        setGeneratingPlayers(false);
      });
  }

  function handleResetPlayers() {
    if (!window.confirm('Delete ALL players from this game? This cannot be undone.')) return;
    AdminApi.resetPlayers(gameId)
      .then(function() { showToast('All players deleted', 'ok'); })
      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
  }

  // --- Captain assignment state ---
  var _ca1 = React.useState(false), startingDraft = _ca1[0], setStartingDraft = _ca1[1];
  var _aa1 = React.useState(false), autoAssigning = _aa1[0], setAutoAssigning = _aa1[1];

  function handleAutoAssignAndPlay() {
    if (!window.confirm('Auto-assign all players to teams and start playing immediately?')) return;
    setAutoAssigning(true);
    AdminApi.assignUnassigned(gameId)
      .then(function(res) {
        showToast('Assigned ' + (res.count || 0) + ' players to teams', 'ok');
        return new Promise(function(resolve) { setTimeout(resolve, 300); });
      })
      .then(function() {
        return onSetPhase('playing');
      })
      .then(function() {
        showToast('Playing phase started!', 'ok');
      })
      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); })
      .finally(function() { setAutoAssigning(false); });
  }

  // Get teams for this game's theme
  // THEME_API_MAP in wizard maps gp→f1, wc→world-cup, rz→nfl, it→realm
  // Reverse it so DB values resolve to data.js theme IDs
  var THEME_REVERSE_MAP = { 'f1': 'gp', 'world-cup': 'cup', 'nfl': 'nfl', 'realm': 'realm' };
  var rawThemeId = (game.theme_id || game.theme || 'cisco');
  var gameThemeId = THEME_REVERSE_MAP[rawThemeId] || rawThemeId;
  var themeObj = (window.THEMES || []).find(function(t) { return t.id === gameThemeId; }) || (window.THEMES || [])[0] || { teams: [] };
  var themeTeams = themeObj.teams || [];

  // Derive captain state from players
  var captains = players.filter(function(p) { return p.isCaptain; });
  var captainByTeam = {};
  captains.forEach(function(p) { if (p.team) captainByTeam[p.team] = p; });
  var nonCaptainPlayers = players.filter(function(p) { return !p.isCaptain && !p.isProctor; });

  // Draft progress tracking
  var undraftedForProgress = players.filter(function(p) { return !p.team && !p.isProctor; }).length;
  var draftedForProgress = players.filter(function(p) { return !!p.team; }).length;
  var allPlayersAssigned = undraftedForProgress === 0 && draftedForProgress > 0;
  var draftIsComplete = phase === 'draft' && allPlayersAssigned;
  var isPlayingWithTeams = phase === 'playing' && allPlayersAssigned;

  function handleSetCaptain(email, teamId) {
    AdminApi.setCaptain(gameId, email, teamId)
      .then(function() { showToast('Captain set for ' + teamId, 'ok'); })
      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
  }

  function handleRemoveCaptain(email, teamId) {
    AdminApi.removeCaptain(gameId, email, teamId)
      .then(function() { showToast('Captain removed', 'ok'); })
      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
  }

  function handleStartDraft() {
    if (captains.length < 2) {
      showToast('Assign at least 2 captains first (' + captains.length + '/' + themeTeams.length + ')', 'error');
      return;
    }
    setStartingDraft(true);
    AdminApi.startDraft(gameId)
      .then(function() { showToast('Draft started!', 'ok'); })
      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); })
      .finally(function() { setStartingDraft(false); });
  }

  function handleResetDraft() {
    if (!window.confirm('Reset draft? This clears all teams, captains, and returns to registration.')) return;
    AdminApi.resetDraft(gameId)
      .then(function() { showToast('Draft reset', 'ok'); })
      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
  }

  // Triage derived values
  var triageAiGraded = ticketAnswers.filter(function(a) { return a.ai_available === 1; }).length;
  var triageProctorGraded = ticketAnswers.filter(function(a) { return a.proctor_scored === 1; }).length;
  var triageEmailSet = {};
  ticketAnswers.forEach(function(a) { if (a.email) triageEmailSet[a.email] = true; });
  var triageUniqueSubmitters = Object.keys(triageEmailSet).length;
  var triageTotalPlayers = players.length;
  var triagePct = triageTotalPlayers > 0 ? Math.round(triageUniqueSubmitters / triageTotalPlayers * 100) : 0;
  var triageUnreviewed = Math.max(0, triageAiGraded - triageProctorGraded);
  var submissions_badge = 0; // GamePlanScoringTab fetches its own data

  // Live event monitor redesign — this event intentionally runs only these
  // three phases. TODO: infer this from event/module configuration once the
  // backend exposes an explicit per-event phase itinerary.
  var LIVE_PHASES = [
    { id: 'quiz',     label: 'Fase de Grupos',      short: 'Quiz',         icon: '🏆', accent: '#00BCEB', hint: 'knowledge round · points table' },
    { id: 'breach',   routeId: 'triage',            label: 'VAR',                 short: 'Breach',       icon: '📺', accent: '#E74C3C', hint: 'incident review · partner under attack' },
    { id: 'gameplan', label: 'Pizarra Táctica',     short: 'Architecture', icon: '📐', accent: '#FBAB18', hint: 'chalkboard · draw the plan' },
  ];
  var ADVANCED_PHASES = [
    { id: 'triage',    label: 'Triage Review', icon: '🎫' },
    { id: 'zonamixta', label: 'Zona Mixta',    icon: '⚡' },
    { id: 'wrap',      label: 'Wrap-up',       icon: '🏁' },
  ];
  var phaseOrder = LIVE_PHASES.map(function(p) { return p.id; });
  var rawSub = typeof currentSubPhase === 'string' ? currentSubPhase : null;
  // Breach currently rides the legacy `triage` player route for clinic events;
  // keep the organizer language clean while preserving the proven endpoint flow.
  var safeSub = rawSub === 'triage' ? 'breach' : rawSub;
  var currentLiveIdx = phaseOrder.indexOf(safeSub);
  var _selLive = React.useState(null), selectedLivePhase = _selLive[0], setSelectedLivePhase = _selLive[1];
  var panelPhase = selectedLivePhase || (phaseOrder.indexOf(safeSub) >= 0 ? safeSub : 'quiz');
  React.useEffect(function() {
    // Initial sync only — don't clobber proctor's manual phase preview.
    if (safeSub && phaseOrder.indexOf(safeSub) >= 0 && selectedLivePhase == null) setSelectedLivePhase(safeSub);
  }, [safeSub]);

  // ── Header live-timer smooth tick (Bug 1 fix for organizer view).
  // activeTimerFor / phaseMeta are function-hoisted so safe to call here.
  var _hdTimerObj = activeTimerFor(panelPhase);
  var _hdServerRem = _hdTimerObj && _hdTimerObj.remaining != null ? _hdTimerObj.remaining : null;
  var _hdLR = React.useState(_hdServerRem); var hdLocalRem = _hdLR[0], setHdLocalRem = _hdLR[1];
  var hdLastSync = React.useRef({ at: Date.now(), val: _hdServerRem });
  React.useEffect(function() {
    hdLastSync.current = { at: Date.now(), val: _hdServerRem };
    setHdLocalRem(_hdServerRem);
  }, [_hdServerRem]);
  React.useEffect(function() {
    if (!_hdTimerObj || !_hdTimerObj.running) return;
    var iv = setInterval(function() {
      var driftSec = (Date.now() - hdLastSync.current.at) / 1000;
      setHdLocalRem(Math.max(0, Math.floor(hdLastSync.current.val - driftSec)));
    }, 1000);
    return function() { clearInterval(iv); };
  }, [_hdTimerObj && _hdTimerObj.running, _hdServerRem]);
  var hdDisplayRem = (_hdTimerObj && _hdTimerObj.running) ? hdLocalRem : _hdServerRem;

  // Re-seed durationInput when proctor switches panel phase or server advances the phase.
  // Clears the user-edited flag so the new phase's timer duration is shown in the input.
  // activeTimerFor is function-hoisted; panelPhase and currentSubPhase are in scope here.
  React.useEffect(function() {
    userEditedDuration.current = false;
    var panelTimer = activeTimerFor(panelPhase);
    var dur = (panelTimer && panelTimer.duration) ||
              (timer && timer.quiz && timer.quiz.duration);
    if (dur) setDurationInput(dur);
  }, [panelPhase, currentSubPhase]);

  var _breach1 = React.useState([]), breachDecisions = _breach1[0], setBreachDecisions = _breach1[1];
  var _gpLive1 = React.useState([]), gpTeams = _gpLive1[0], setGpTeams = _gpLive1[1];
  var _beat1 = React.useState(function() {
    var n = parseInt(window.localStorage.getItem('breach_beat_' + gameId), 10);
    return isNaN(n) ? 0 : Math.max(0, n);
  }), breachBeatIndex = _beat1[0], setBreachBeatIndex = _beat1[1];

  React.useEffect(function() {
    if (!gameId) return;
    function fetchBreachDecisions() {
      AdminApi.getBreachDecisions(gameId)
        .then(function(data) { setBreachDecisions((data && data.decisions) || []); })
        .catch(function() {});
    }
    fetchBreachDecisions();
    var t = setInterval(fetchBreachDecisions, 6000);
    return function() { clearInterval(t); };
  }, [gameId]);

  React.useEffect(function() {
    if (!gameId) return;
    function fetchGamePlanTeams() {
      AdminApi.getGamePlanSubmissions(gameId)
        .then(function(data) { setGpTeams((data && data.teams) || []); })
        .catch(function() {});
    }
    fetchGamePlanTeams();
    var t = setInterval(fetchGamePlanTeams, 7000);
    return function() { clearInterval(t); };
  }, [gameId]);

  React.useEffect(function() {
    function onBreachKey(e) {
      if (panelPhase !== 'breach') return;
      if (e.target && (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA')) return;
      if (e.key === '[') setBreachBeat(-1);
      if (e.key === ']') setBreachBeat(1);
    }
    window.addEventListener('keydown', onBreachKey);
    return function() { window.removeEventListener('keydown', onBreachKey); };
  }, [panelPhase, breachBeatIndex, gameId]);

  function fmtLiveMmSs(s) {
    if (s == null) return '--:--';
    var n = Math.max(0, Math.round(s || 0));
    var m = Math.floor(n / 60);
    var r = n % 60;
    return (m < 10 ? '0' : '') + m + ':' + (r < 10 ? '0' : '') + r;
  }
  function phaseMeta(id) {
    return LIVE_PHASES.concat(ADVANCED_PHASES).filter(function(p) { return p.id === id; })[0] || { id: id, label: id || '—', short: id || '—', icon: '•', accent: 'var(--brand)' };
  }
  function activeTimerFor(id) {
    var meta = phaseMeta(id);
    var routeId = meta.routeId || id;
    return (timer && timer[id]) ? timer[id] : ((timer && timer[routeId]) ? timer[routeId] : ((timer && timer.quiz) ? timer.quiz : null));
  }
  function requestSubPhase(target) {
    var meta = phaseMeta(target);
    if (target === safeSub) { setSelectedLivePhase(target); return; }
    if (!window.confirm('Advance players to ' + meta.label + ' (' + target + ')?')) return;
    var routeId = meta.routeId || target;
    AdminApi.setSubPhase(gameId, routeId)
      .then(function() { setSelectedLivePhase(target); setCurrentSubPhase(routeId); showToast('Players advancing to ' + meta.label, 'ok'); })
      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
  }
  function setBreachBeat(delta) {
    var total = (window.BREACH_SCENARIO && window.BREACH_SCENARIO.beats && window.BREACH_SCENARIO.beats.length) || 6;
    var next = Math.max(0, Math.min(total - 1, breachBeatIndex + delta));
    setBreachBeatIndex(next);
    try { window.localStorage.setItem('breach_beat_' + gameId, String(next)); } catch(_) {}
  }
  function renderTimerCard(phaseId) {
    var meta = phaseMeta(phaseId);
    var effectivePhaseId = meta.routeId || phaseId;
    var tmr = activeTimerFor(phaseId);
    var remaining = tmr ? tmr.remaining : null;
    var isExpired = tmr && tmr.expired;
    var isPaused = tmr && tmr.paused;
    var countColor = isExpired ? 'var(--dn, #E10600)' : (remaining != null && remaining < 120 ? '#F0A000' : 'var(--up, #6CC04A)');
    var phaseDur = durationInput;
    var durationMins = Math.max(0.5, Math.round((phaseDur / 60) * 10) / 10);
    return (
      <div style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', padding: '16px', background: 'var(--s1)', boxShadow: '0 10px 24px rgba(0,0,0,.08)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px', alignItems: 'flex-start', marginBottom: '12px' }}>
          <div>
            <div style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--i3)', fontWeight: 800 }}>⏱ {tc('Phase timer')}</div>
            <div style={{ fontSize: '16px', fontWeight: 800, color: 'var(--i1)', marginTop: '3px' }}>{meta.icon} {tc(meta.label)}</div>
            <div style={{ fontSize: '12px', color: 'var(--i3)', marginTop: '2px' }}>{tc(meta.hint || meta.short || phaseId)}</div>
          </div>
          <div style={{ fontFamily: 'var(--f-m, monospace)', fontSize: '38px', fontWeight: 900, color: countColor, letterSpacing: '.04em', lineHeight: 1, fontVariantNumeric: 'tabular-nums' }}>{fmtLiveMmSs(remaining)}</div>
        </div>
        {(isPaused || isExpired) && <div style={{ fontSize: '12px', color: isExpired ? 'var(--dn)' : '#F0A000', fontWeight: 700, marginBottom: '10px' }}>{isExpired ? 'Expired' : 'Paused'}</div>}
        <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', alignItems: 'center' }}>
          <button className="btn ghost" onClick={function() { onTimerAction('start', effectivePhaseId); }}>▶ {tc('Start')}</button>
          <button className="btn ghost" onClick={function() { onTimerAction('pause', effectivePhaseId); }}>⏸ {tc('Pause')}</button>
          <button className="btn ghost" onClick={function() { onTimerAction('restart', effectivePhaseId); }}>↩ {tc('Restart')}</button>
          <span style={{ width: '1px', height: '28px', background: 'var(--line-soft)' }} />
          <input type="number" min="1" max="1440" value={durationMins} onChange={function(e) { userEditedDuration.current = true; setDurationInput(Math.round((parseFloat(e.target.value) || 1) * 60)); }} style={{ width: '64px', padding: '7px 8px', border: '1px solid var(--line-soft)', borderRadius: '8px', background: 'var(--s2)', color: 'var(--i1)', textAlign: 'center' }} />
          <span style={{ fontSize: '12px', color: 'var(--i3)' }}>min</span>
          <button className="btn ghost" onClick={function() { onTimerAction('set-duration', effectivePhaseId, durationInput); }}>{tc('Set')}</button>
          <button className="btn ghost" onClick={function() { onTimerAction('extend', effectivePhaseId, 60); }}>+1</button>
          <button className="btn ghost" onClick={function() { onTimerAction('extend', effectivePhaseId, 300); }}>+5</button>
        </div>
      </div>
    );
  }
  function renderObserverCard() {
    return (
      <div style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', padding: '16px', background: 'var(--s1)' }}>
        <div style={{ fontSize: '11px', fontWeight: 800, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--i3)', marginBottom: '8px' }}>👁 {tc('Observer')}</div>
        {observerToast && <div style={{ fontSize: '12px', color: '#1BA0D7', marginBottom: '8px', padding: '7px 10px', background: 'rgba(27,160,215,0.10)', borderRadius: '8px', wordBreak: 'break-all' }}>Observer tab opened: <code>{observerToast}</code></div>}
        <button className="btn ghost" onClick={function() { var ts = Date.now(); var email = 'observer+' + ts + '@cisco.com'; var url = window.location.origin + '/v2/?game=' + encodeURIComponent(gameId) + '&email=' + encodeURIComponent(email) + '&name=Observer&observer=1'; window.open(url, '_blank'); setObserverToast(email); setTimeout(function() { setObserverToast(null); }, 8000); }}>👁 {tc('Join as observer')}</button>
        <div style={{ fontSize: '11px', color: 'var(--i3)', marginTop: '8px' }}>{tc('Opens player UI — no team, no scoring')}</div>
      </div>
    );
  }
  function teamDisplayName(teamId) {
    var tt = themeTeams.find(function(t) { return t.id === teamId || t.name === teamId || t.short === teamId; });
    return (tt && tt.name) || (teamId ? String(teamId).charAt(0).toUpperCase() + String(teamId).slice(1) : '—');
  }
  function teamColor(teamId) {
    var tt = themeTeams.find(function(t) { return t.id === teamId || t.name === teamId || t.short === teamId; });
    return (tt && tt.color) || 'var(--brand)';
  }
  var topTeams = (function() {
    var teamMap = {};
    leaderboard.forEach(function(entry) { if (entry.team) teamMap[entry.team] = (teamMap[entry.team] || 0) + (entry.score || 0); });
    return Object.keys(teamMap).map(function(team) { return { team: team, total: teamMap[team] }; }).sort(function(a,b) { return b.total - a.total; }).slice(0, 5);
  })();
  var teamAvgById = (function() {
    var map = {};
    (leaderboard.length ? leaderboard : players).forEach(function(entry) {
      var tid = entry.team || entry.tid;
      if (!tid) return;
      if (!map[tid]) map[tid] = { total: 0, count: 0 };
      map[tid].total += Number(entry.score || 0);
      map[tid].count += 1;
    });
    return map;
  })();
  function teamAvgLabel(teamId) {
    var bucket = teamAvgById[teamId];
    return bucket && bucket.count ? Math.round(bucket.total / bucket.count).toLocaleString() : '—';
  }
  var breachBeats = (window.BREACH_SCENARIO && window.BREACH_SCENARIO.beats) || [];
  var currentBeat = breachBeats[Math.max(0, Math.min(breachBeatIndex, Math.max(0, breachBeats.length - 1)))] || null;
  var breachTeams = themeTeams.length ? themeTeams : [{ id: 'team1', name: 'Team 1' }, { id: 'team2', name: 'Team 2' }, { id: 'team3', name: 'Team 3' }, { id: 'team4', name: 'Team 4' }, { id: 'team5', name: 'Team 5' }];
  var decisionsThisBeat = breachDecisions.filter(function(d) { return currentBeat && d.beat === currentBeat.id; });
  var gpByTeam = {};
  gpTeams.forEach(function(t) { gpByTeam[t.team_id] = t; });

  return (
    <div className="page-monitor">
      <div className="pghd" style={{ alignItems: 'stretch' }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: '10px', flexWrap: 'wrap' }}>
            <div className="title">{tc('Monitor & Game Controls')}</div>
            <code style={{ fontFamily: 'var(--f-m)', fontSize: '13px', background: 'var(--s2)', padding: '4px 10px', borderRadius: '8px', color: 'var(--brand)', letterSpacing: '.08em' }}>{game.join_code || displayCode}</code>
            <PhaseBadge phase={phase} />
            <span style={{ fontSize: '13px', color: 'var(--i3)' }}>{players.length} player{players.length !== 1 ? 's' : ''}</span>
          </div>
          <div style={{ marginTop: '8px', fontSize: '14px', color: 'var(--i2)' }}>{tc('Current phase')}: <strong style={{ color: phaseMeta(safeSub).accent }}>{phaseMeta(safeSub).icon} {tc(phaseMeta(safeSub).label)}</strong></div>
        </div>
        <div className="right" style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
          <div style={{ textAlign: 'right', padding: '8px 14px', border: '1px solid var(--line-soft)', borderRadius: '14px', background: 'var(--s1)' }}>
            <div style={{ fontSize: '10px', textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--i3)', fontWeight: 800 }}>{tc('Live timer')}</div>
            {(function() {
              var t = activeTimerFor(panelPhase);
              var running = t && t.running && t.remaining > 0;
              if (running) {
                return <div style={{ fontFamily: 'var(--f-m)', fontSize: '34px', fontWeight: 900, lineHeight: 1.05, color: 'var(--up)', fontVariantNumeric: 'tabular-nums' }}>{fmtLiveMmSs(hdDisplayRem)}</div>;
              }
              var meta = phaseMeta(panelPhase);
              var routeId = meta.routeId || panelPhase;
              var defaultDur = (t && t.duration) || 1500;
              return (
                <button className="btn primary" style={{ marginTop: '2px', fontSize: '13px', padding: '6px 12px', background: 'var(--warn)', borderColor: 'var(--warn)', color: '#1a1a1a', fontWeight: 900 }}
                  title={tc('No timer running — players have no countdown')}
                  onClick={function() {
                    AdminApi.startTimer(gameId, routeId)
                      .then(function() { showToast(tc('Timer started'), 'ok'); })
                      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
                  }}>
                  ▶ {tc('Start Timer')} ({fmtLiveMmSs(defaultDur)})
                </button>
              );
            })()}
          </div>
          <button className="btn" onClick={function() { var url = '/v2/projector.html?game=' + encodeURIComponent(gameId); window.open(url, 'arena-projector-' + gameId, 'width=1920,height=1080,menubar=no,toolbar=no,location=no,status=no'); }} style={{ background: 'linear-gradient(135deg, #00BCEB 0%, #1E4D8C 100%)', borderColor: '#00BCEB', color: '#fff', fontWeight: 800 }}>📺 {tc('Projector')} ↗</button>
          <button className="btn ghost" onClick={function() { onSelectGame(null); }}>← {tc('Back')}</button>
        </div>
      </div>

      {(phase === 'registration' || phase === 'draft') && (
        <div className="card" style={{ borderColor: 'var(--brand)', borderWidth: '2px', margin: '18px 0', background: 'linear-gradient(135deg, color-mix(in srgb, var(--brand) 10%, var(--s1)), var(--s1))' }}>
          <div className="card-bd" style={{ padding: '18px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: '16px', flexWrap: 'wrap', justifyContent: 'space-between', marginBottom: '14px' }}>
              <div>
                <div style={{ fontSize: '11px', color: 'var(--brand)', fontWeight: 900, letterSpacing: '.1em', textTransform: 'uppercase' }}>⚡ {tc('Pre-game setup')}</div>
                <div style={{ fontSize: '17px', fontWeight: 900, marginTop: '4px' }}>{tc('Assign captains and start the draft')}</div>
                <div style={{ fontSize: '13px', color: 'var(--i2)', marginTop: '4px' }}>
                  {captains.length}/{themeTeams.length} {tc('captains')} · {players.length} {tc('players')}
                  {phase === 'draft' && allPlayersAssigned ? ' · ✓ ' + tc('Draft complete') : ''}
                </div>
              </div>
              {phase === 'registration' && (
                <button className="btn primary" disabled={startingDraft || captains.length < 2} onClick={handleStartDraft} style={{ fontSize: '15px', padding: '10px 18px' }}>
                  {startingDraft ? '…' : '▶ ' + tc('Start Draft') + ' (' + captains.length + '/' + themeTeams.length + ')'}
                </button>
              )}
              {phase === 'draft' && allPlayersAssigned && (
                <button className="btn primary" onClick={function() {
                  AdminApi.setGamePhase(gameId, 'playing')
                    .then(function() { return AdminApi.setSubPhase(gameId, 'quiz'); })
                    .then(function() { showToast(tc('Quiz phase started!'), 'ok'); })
                    .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
                }} style={{ background: 'var(--up)', borderColor: 'var(--up)', fontSize: '15px', padding: '10px 18px' }}>
                  {'▶ ' + tc('Start Quiz Phase')}
                </button>
              )}
            </div>
            {themeTeams.length === 0 ? (
              <div style={{ padding: '14px', color: 'var(--i3)', fontSize: '13px', textAlign: 'center', border: '1px dashed var(--line-soft)', borderRadius: '10px' }}>
                {tc('No teams found for theme')} "{gameThemeId}"
              </div>
            ) : (
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: '10px' }}>
                {themeTeams.map(function(team) {
                  var captain = captainByTeam[team.id];
                  return (
                    <div key={team.id} style={{
                      display: 'flex', alignItems: 'center', gap: '10px',
                      padding: '10px 12px', borderRadius: '10px', background: 'var(--s2)',
                      borderLeft: '3px solid ' + (team.color || 'var(--i3)'),
                    }}>
                      <div style={{ width: '90px', fontWeight: 700, fontSize: '13px', flexShrink: 0 }}>{team.name}</div>
                      {captain ? (
                        <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: '8px', justifyContent: 'space-between' }}>
                          <span style={{ fontSize: '13px' }}>⭐ {captain.name || captain.email}</span>
                          <button className="btn ghost" style={{ fontSize: '11px', padding: '2px 8px' }}
                            onClick={function() { handleRemoveCaptain(captain.email, team.id); }}>✕</button>
                        </div>
                      ) : (
                        <select style={{ flex: 1, padding: '6px 8px', borderRadius: '6px', border: '1px solid var(--line-soft)', background: 'var(--s1)', color: 'var(--i1)', fontSize: '13px' }}
                          value=""
                          onChange={function(e) { if (e.target.value) handleSetCaptain(e.target.value, team.id); }}>
                          <option value="">{tc('Select captain…')}</option>
                          {nonCaptainPlayers.map(function(p) {
                            return <option key={p.email} value={p.email}>{p.name || p.email}</option>;
                          })}
                        </select>
                      )}
                    </div>
                  );
                })}
              </div>
            )}
          </div>
        </div>
      )}

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: '12px', margin: '18px 0' }}>
        {LIVE_PHASES.map(function(p, idx) {
          var isCurrent = p.id === safeSub;
          var isPast = currentLiveIdx >= 0 && idx < currentLiveIdx;
          var isSelected = p.id === panelPhase;
          return (
            <button key={p.id} onClick={function() { setSelectedLivePhase(p.id); }} title={isCurrent ? tc('Currently live') : tc('Preview only — does NOT advance players')} style={{ position: 'relative', textAlign: 'left', padding: '16px 18px', borderRadius: '16px', border: '1px solid ' + (isCurrent || isSelected ? p.accent : 'var(--line-soft)'), background: isCurrent ? 'linear-gradient(135deg, color-mix(in srgb, ' + p.accent + ' 18%, var(--s1)), var(--s1))' : (isSelected ? 'color-mix(in srgb, ' + p.accent + ' 8%, var(--s1))' : 'var(--s1)'), color: 'var(--i1)', cursor: 'pointer', opacity: currentLiveIdx >= 0 && idx > currentLiveIdx ? .62 : 1, boxShadow: isCurrent ? '0 0 0 3px color-mix(in srgb, ' + p.accent + ' 18%, transparent)' : (isSelected ? '0 0 0 2px color-mix(in srgb, ' + p.accent + ' 30%, transparent)' : 'none') }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '10px' }}>
                <span style={{ fontSize: '22px' }}>{isPast ? '✅' : p.icon}</span>
                <span style={{ fontSize: '11px', color: isCurrent ? p.accent : 'var(--i3)', fontWeight: 900, letterSpacing: '.08em', textTransform: 'uppercase' }}>{isCurrent ? tc('Live now') : (isPast ? tc('Completed') : tc('Upcoming'))}</span>
              </div>
              <div style={{ fontSize: '17px', fontWeight: 900, marginTop: '8px' }}>{tc(p.label)}</div>
              <div style={{ fontSize: '12px', color: 'var(--i3)', marginTop: '3px' }}>{p.short} · {tc(p.hint)}</div>
              {isSelected && !isCurrent ? <div style={{ position: 'absolute', top: '8px', right: '10px', fontSize: '10px', fontWeight: 900, color: p.accent, letterSpacing: '.08em', textTransform: 'uppercase', background: 'rgba(0,0,0,.06)', padding: '2px 6px', borderRadius: '6px' }}>👁 {tc('Previewing')}</div> : null}
              {!isCurrent ? (
                <div style={{ marginTop: '10px', display: 'flex', gap: '6px', alignItems: 'center' }}>
                  <button className="btn ghost" style={{ fontSize: '11px', padding: '4px 8px', borderColor: p.accent, color: p.accent }} onClick={function(e) { e.stopPropagation(); if (window.confirm(tc('Advance ALL players to ') + tc(p.label) + '? ' + tc('Use Preview to inspect this phase without disrupting players.'))) requestSubPhase(p.id); }}>⚠ {tc('Send players here')}</button>
                </div>
              ) : null}
            </button>
          );
        })}
      </div>

      <div className="card" style={{ borderColor: phaseMeta(panelPhase).accent, overflow: 'hidden' }}>
        <div className="card-hd" style={{ background: 'linear-gradient(90deg, color-mix(in srgb, ' + phaseMeta(panelPhase).accent + ' 14%, transparent), transparent)' }}>
          <h3>{phaseMeta(panelPhase).icon} {tc(phaseMeta(panelPhase).label)} <span style={{ color: 'var(--i3)', fontWeight: 500 }}>· {tc(phaseMeta(panelPhase).short || panelPhase)}</span></h3>
        </div>
        <div className="card-bd" style={{ padding: '18px', display: 'grid', gridTemplateColumns: 'minmax(0, 1.5fr) minmax(320px, .9fr)', gap: '18px', alignItems: 'start' }}>
          {panelPhase === 'quiz' && (
            <>
              <div style={{ display: 'grid', gap: '14px' }}>
                {renderTimerCard('quiz')}
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: '12px' }}>
                  <div className="kpi"><span className="v">{quizCount + funCount}</span><span className="lbl">{tc('Questions')}</span></div>
                  <div className="kpi"><span className="v">{players.length}</span><span className="lbl">{tc('Players')}</span></div>
                  <div className="kpi"><span className="v">{topTeams.length ? topTeams[0].total : 0}</span><span className="lbl">{tc('Top score')}</span></div>
                </div>
                <div style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', padding: '14px', background: 'var(--s1)' }}>
                  <div style={{ fontSize: '11px', color: 'var(--i3)', fontWeight: 800, textTransform: 'uppercase', letterSpacing: '.08em', marginBottom: '10px' }}>{tc('Question count per player')}</div>
                  <div style={{ display: 'flex', gap: '14px', alignItems: 'center', flexWrap: 'wrap' }}>
                    <label style={{ display: 'flex', alignItems: 'center', gap: '8px', fontSize: '13px', fontWeight: 700 }}>
                      🏆 {tc('Tech')}
                      <input type="number" min="1" max="50" value={quizCount}
                        onChange={function(e) { setQuizCount(Math.max(1, Math.min(50, Number(e.target.value) || 1))); }}
                        style={{ width: '64px', padding: '6px 8px', border: '1px solid var(--line-soft)', borderRadius: '8px', fontSize: '14px', textAlign: 'center', fontFamily: 'var(--f-m)', fontWeight: 800 }}
                      />
                    </label>
                    <label style={{ display: 'flex', alignItems: 'center', gap: '8px', fontSize: '13px', fontWeight: 700 }}>
                      🎉 {tc('Fun')}
                      <input type="number" min="0" max="20" value={funCount}
                        onChange={function(e) { setFunCount(Math.max(0, Math.min(20, Number(e.target.value) || 0))); }}
                        style={{ width: '64px', padding: '6px 8px', border: '1px solid var(--line-soft)', borderRadius: '8px', fontSize: '14px', textAlign: 'center', fontFamily: 'var(--f-m)', fontWeight: 800 }}
                      />
                    </label>
                    <span style={{ fontSize: '12px', color: 'var(--i3)' }}>= <strong style={{ color: 'var(--i1)' }}>{quizCount + funCount}</strong> {tc('per player')}</span>
                  </div>
                </div>
                <div style={{ display: 'flex', gap: '10px', alignItems: 'center', flexWrap: 'wrap' }}>
                  <button className="btn primary" onClick={handleSaveQuizConfig} disabled={savingQuizConfig}>{savingQuizConfig ? '…' : '💾 ' + tc('Save question count')}</button>
                  <button className="btn ghost" style={{ color: 'var(--dn)', borderColor: 'var(--dn)' }} onClick={function() { if (window.confirm('Reset quiz/game scores for ' + gameId + '?')) onResetGame(); }}>{tc('Reset quiz')}</button>
                </div>
              </div>
              <div style={{ display: 'grid', gap: '14px' }}>
                {renderObserverCard()}
                <div style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', overflow: 'hidden' }}>
                  <div style={{ padding: '12px 14px', fontSize: '12px', fontWeight: 800, color: 'var(--i2)', borderBottom: '1px solid var(--line-soft)' }}>{tc('Leaderboard preview')}</div>
                  {topTeams.length ? topTeams.map(function(t, i) { return <div key={t.team} style={{ display: 'grid', gridTemplateColumns: '24px 1fr auto', gap: '10px', padding: '10px 14px', borderBottom: '1px solid var(--line-soft)', alignItems: 'center' }}><span style={{ color: teamColor(t.team), fontWeight: 900 }}>#{i+1}</span><span>{teamDisplayName(t.team)}</span><strong style={{ fontFamily: 'var(--f-m)' }}>{t.total}</strong></div>; }) : <div style={{ padding: '18px', color: 'var(--i3)', fontSize: '13px' }}>{tc('No scores yet.')}</div>}
                </div>
              </div>
            </>
          )}

          {panelPhase === 'breach' && (
            <>
              <div style={{ display: 'grid', gap: '14px' }}>
                {renderTimerCard('breach')}
                <div style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', padding: '16px', background: 'var(--s1)' }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', gap: '12px', alignItems: 'center' }}>
                    <div><div style={{ fontSize: '11px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.08em', fontWeight: 800 }}>{tc('Current beat')}</div><div style={{ fontSize: '18px', fontWeight: 900, marginTop: '4px' }}>{currentBeat ? currentBeat.kicker + ' · ' + currentBeat.headline : 'Beat ' + (breachBeatIndex + 1)}</div></div>
                    <div style={{ display: 'flex', gap: '8px' }}><button className="btn ghost" onClick={function() { setBreachBeat(-1); }} disabled={breachBeatIndex <= 0}>[ Prev</button><button className="btn ghost" onClick={function() { setBreachBeat(1); }} disabled={breachBeats.length && breachBeatIndex >= breachBeats.length - 1}>Next ]</button></div>
                  </div>
                  <div style={{ fontSize: '12px', color: 'var(--i3)', marginTop: '10px' }}>{tc('Keyboard')}: <strong>[</strong> / <strong>]</strong> · {tc('local beat indicator for the proctor/projector flow')}</div>
                </div>
                <a className="btn primary" href={('/v2/organizer-breach-review.html?game=' + encodeURIComponent(gameId) + ((window.AdminSession && window.AdminSession.getToken && window.AdminSession.getToken()) ? '#t=' + encodeURIComponent(window.AdminSession.getToken()) : ''))} target="_blank" rel="noreferrer" style={{ justifySelf: 'start', textDecoration: 'none' }}>🔓 {tc('Open Breach review')} ↗</a>
              </div>
              <div style={{ display: 'grid', gap: '14px' }}>
                {renderObserverCard()}
                <div style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', overflow: 'hidden' }}>
                  <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--line-soft)', fontSize: '12px', fontWeight: 800 }}>{tc('Team decisions')} · {decisionsThisBeat.length}/{breachTeams.length}</div>
                  {breachTeams.map(function(t) { var d = decisionsThisBeat.filter(function(x) { return x.team === t.id || x.team === t.name; })[0]; return <div key={t.id || t.name} style={{ display: 'grid', gridTemplateColumns: '12px 1fr auto', gap: '10px', alignItems: 'center', padding: '10px 14px', borderBottom: '1px solid var(--line-soft)' }}><span style={{ width: 10, height: 10, borderRadius: '50%', background: teamColor(t.id || t.name) }}></span><span style={{ fontWeight: 700 }}>{t.name || t.id}</span><span style={{ fontSize: '12px', color: d ? 'var(--up)' : 'var(--i3)', fontWeight: 800 }}>{d ? '✓ submitted' : 'waiting'}</span></div>; })}
                </div>
              </div>
            </>
          )}

          {panelPhase === 'gameplan' && (
            <>
              <div style={{ display: 'grid', gap: '14px' }}>
                {renderTimerCard('gameplan')}
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: '12px' }}>
                  {(gpTeams.length ? gpTeams : themeTeams.slice(0,5).map(function(t) { return { team_id: t.id, team_name: t.name }; })).slice(0,5).map(function(t) { var hasSub = !!t.submission; return <div key={t.team_id} style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', padding: '14px', background: 'var(--s1)', borderLeft: '4px solid ' + teamColor(t.team_id) }}><div style={{ fontWeight: 900 }}>{teamDisplayName(t.team_id)}</div><div style={{ fontSize: '12px', color: 'var(--i3)', marginTop: '6px' }}>{tc('Scenario')}: <strong>{t.scenario_index != null ? '#' + (t.scenario_index + 1) : '—'}</strong></div><div style={{ fontSize: '12px', color: hasSub ? 'var(--up)' : 'var(--i3)', marginTop: '6px', fontWeight: 800 }}>{hasSub ? '✅ ' + tc('Uploaded') : '⏳ ' + tc('No upload yet')}</div></div>; })}
                </div>
                <div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap' }}>
                  <button className="btn ghost" disabled title="Selections are turn-ordered by the game engine">🔒 {tc('Lock selections')} ({tc('auto')})</button>
                  <button className="btn primary" onClick={function() { setActiveTab('gameplan'); }}>📐 {tc('Open scoring workspace')}</button>
                </div>
              </div>
              <div style={{ display: 'grid', gap: '14px' }}>
                {renderObserverCard()}
                <div style={{ border: '1px solid var(--line-soft)', borderRadius: '14px', padding: '16px', background: 'var(--s1)' }}><div style={{ fontSize: '12px', fontWeight: 800, color: 'var(--i2)' }}>{tc('Upload status')}</div><div style={{ fontSize: '34px', fontWeight: 900, color: 'var(--brand)', marginTop: '8px' }}>{gpTeams.filter(function(t) { return !!t.submission; }).length}/{Math.max(gpTeams.length, 5)}</div><div style={{ color: 'var(--i3)', fontSize: '12px' }}>{tc('teams submitted architecture/BOM')}</div></div>
              </div>
            </>
          )}
        </div>
      </div>

      <div style={{ display: 'flex', gap: '10px', justifyContent: 'space-between', alignItems: 'center', marginTop: '16px', flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
          <a className="btn ghost" href={'/api/g/' + encodeURIComponent(gameId) + '/report/post-game'} target="_blank" rel="noreferrer" style={{ textDecoration: 'none' }}>⬇ {tc('Export data')}</a>
          <button className="btn ghost" style={{ color: 'var(--dn)', borderColor: 'var(--dn)' }} onClick={function() { if (window.confirm('End game and send players to wrap-up?')) requestSubPhase('wrap'); }}>{tc('End game')}</button>
        </div>
        <details style={{ position: 'relative' }}>
          <summary className="btn ghost" style={{ listStyle: 'none', cursor: 'pointer' }}>{tc('Advanced phases')} ▾</summary>
          <div style={{ position: 'absolute', right: 0, bottom: '44px', minWidth: '220px', background: 'var(--s1)', border: '1px solid var(--line-soft)', borderRadius: '12px', padding: '8px', boxShadow: '0 18px 40px rgba(0,0,0,.20)', zIndex: 5 }}>
            {ADVANCED_PHASES.map(function(p) { return <button key={p.id} className="btn ghost" onClick={function() { requestSubPhase(p.id); }} style={{ width: '100%', justifyContent: 'flex-start', marginBottom: '6px' }}>{p.icon} {tc(p.label)}</button>; })}
          </div>
        </details>
      </div>

      {activeTab === 'gameplan' && <div style={{ marginTop: '16px' }}>{React.createElement(window.GamePlanScoringTab, { gameId: gameId })}</div>}

      {activeTab === 'breach' && (
        <div style={{ marginTop: '16px' }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '10px', gap: '12px', flexWrap: 'wrap' }}>
            <div>
              <div style={{ fontSize: '16px', fontWeight: 800 }}>🔓 Breach VAR · Read-only review</div>
              <div style={{ fontSize: '12px', color: 'var(--i3)', marginTop: '2px' }}>{tc('Captain decisions per beat + player notes. Scoring is manual — adjust team totals after review.')}</div>
            </div>
            <a className="btn primary" href={('/v2/organizer-breach-review.html?game=' + encodeURIComponent(gameId) + ((window.AdminSession && window.AdminSession.getToken && window.AdminSession.getToken()) ? '#t=' + encodeURIComponent(window.AdminSession.getToken()) : ''))} target="_blank" rel="noreferrer" style={{ textDecoration: 'none' }}>↗ {tc('Open in new tab')}</a>
          </div>
          <iframe
            src={('/v2/organizer-breach-review.html?game=' + encodeURIComponent(gameId) + ((window.AdminSession && window.AdminSession.getToken && window.AdminSession.getToken()) ? '#t=' + encodeURIComponent(window.AdminSession.getToken()) : ''))}
            style={{ width: '100%', height: 'calc(100vh - 320px)', minHeight: '600px', border: '1px solid var(--line-soft)', borderRadius: '12px', background: '#02050b' }}
            title="Breach VAR Review"
          />
        </div>
      )}

      {/* Players by team — full-width card with per-player team override */}
      {(function() {
        var teamMeta = {};
        (themeTeams || []).forEach(function(t) { teamMeta[t.id] = { name: t.name, color: t.color }; });
        var hasTeams = players.filter(function(p) { return p.team; }).length > 0;
        var groups = [];
        if (hasTeams) {
          var seen = {};
          players.forEach(function(p) {
            var tid = p.team || '';
            if (!seen[tid]) {
              seen[tid] = true;
              var m = teamMeta[tid] || {};
              groups.push({ teamId: tid, teamName: tid ? (m.name || tid) : 'Unassigned', teamColor: tid ? (m.color || 'var(--i3)') : 'var(--i3)', players: [] });
            }
          });
          groups.sort(function(a, b) { if (!a.teamId && b.teamId) return 1; if (a.teamId && !b.teamId) return -1; return a.teamName.localeCompare(b.teamName); });
          var gm = {}; groups.forEach(function(g) { gm[g.teamId] = g; });
          players.forEach(function(p) { var tid = p.team || ''; if (gm[tid]) gm[tid].players.push(p); });
        }
        function moveTo(player, newTeam) {
          if (newTeam === (player.team || '')) return;
          var dest = newTeam ? ((teamMeta[newTeam] && teamMeta[newTeam].name) || newTeam) : 'unassigned';
          if (!window.confirm('Move ' + (player.name || player.email) + ' to ' + dest + '?')) return;
          AdminApi.assignTeam(gameId, player.email, newTeam)
            .then(function() { showToast('Team updated', 'ok'); })
            .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
        }
        function delPlayer(player) {
          if (!window.confirm('Remove ' + (player.name || player.email) + ' from the game?')) return;
          AdminApi.deletePlayer(gameId, player.email)
            .then(function() { showToast('Player removed', 'ok'); })
            .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
        }
        function row(p, key) {
          var dot = (p.team && teamMeta[p.team] && teamMeta[p.team].color) || 'var(--i3)';
          return (
            <div key={key} style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '8px 12px', borderBottom: '1px solid var(--line-soft)', fontSize: '13px' }}>
              <span style={{ width: '8px', height: '8px', borderRadius: '50%', background: dot, flexShrink: 0 }} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  {p.isCaptain ? <span style={{ color: dot, marginRight: '3px' }}>★</span> : null}
                  {p.name || '—'}
                  {p.isProctor ? <span style={{ marginLeft: '6px', fontSize: '9px', fontWeight: 700, color: 'var(--i3)', background: 'var(--s2)', border: '1px solid var(--line-soft)', borderRadius: '3px', padding: '1px 4px' }}>PROCTOR</span> : null}
                </div>
                <div style={{ fontSize: '11px', color: 'var(--i3)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.email || ''}</div>
              </div>
              <span style={{ fontFamily: 'var(--f-m)', fontSize: '12px', color: 'var(--i3)', textAlign: 'right' }}>
                <span>{p.score != null ? Number(p.score).toLocaleString() : '—'}</span>
                {p.team ? <span style={{ display: 'block', fontSize: '11px', color: 'var(--i3)', fontWeight: 500 }}>team avg: {teamAvgLabel(p.team)}</span> : null}
              </span>
              {!p.isProctor && (
                <select value={p.team || ''} onChange={function(e) { moveTo(p, e.target.value); }} title="Override team"
                  style={{ fontSize: '11px', padding: '2px 4px', borderRadius: '4px', border: '1px solid var(--line-soft)', background: 'var(--s1)', color: 'var(--i1)', maxWidth: '110px', flexShrink: 0 }}>
                  <option value="">— unassigned</option>
                  {(themeTeams || []).map(function(t) { return <option key={t.id} value={t.id}>{t.name}</option>; })}
                </select>
              )}
              <button onClick={function() { delPlayer(p); }}
                style={{ color: 'var(--dn)', fontSize: '11px', padding: '2px 6px', cursor: 'pointer', opacity: 0.5, background: 'none', border: '1px solid transparent', borderRadius: '4px', flexShrink: 0 }}
                onMouseEnter={function(e) { e.currentTarget.style.opacity = '1'; }}
                onMouseLeave={function(e) { e.currentTarget.style.opacity = '0.5'; }}>✕</button>
            </div>
          );
        }
        var assigned = players.filter(function(p) { return p.team; }).length;
        return (
          <div className="card" style={{ marginTop: '16px' }}>
            <div className="card-hd">
              <h3>{tc('Players')} · {players.length}
                {hasTeams ? <span style={{ fontSize: '11px', fontWeight: 400, color: 'var(--i3)', marginLeft: '8px' }}>
                  {assigned} {tc('on teams')}{players.length - assigned > 0 ? ', ' + (players.length - assigned) + ' ' + tc('unassigned') : ''}
                </span> : null}
              </h3>
            </div>
            <div className="card-bd" style={{ padding: hasTeams ? '0' : '0', maxHeight: hasTeams ? 'none' : '600px', overflowY: hasTeams ? 'visible' : 'auto' }}>
              {players.length === 0 ? (
                <div style={{ padding: '24px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }}>{tc('No players joined yet.')}</div>
              ) : hasTeams ? (
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))', gap: '16px', padding: '16px', alignItems: 'start' }}>
                  {groups.map(function(g) {
                    return (
                      <div key={g.teamId || 'unassigned'} style={{ border: '1px solid var(--line-soft)', borderRadius: '12px', overflow: 'hidden', maxHeight: '520px', overflowY: 'auto' }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: '8px', padding: '10px 14px', background: 'var(--s2)', borderBottom: '1px solid var(--line-soft)', position: 'sticky', top: 0, zIndex: 1 }}>
                          <span style={{ width: '10px', height: '10px', borderRadius: '50%', background: g.teamColor, flexShrink: 0 }} />
                          <span style={{ fontWeight: 700, fontSize: '12px', textTransform: 'uppercase', letterSpacing: '.04em' }}>{g.teamName}</span>
                          <span style={{ fontSize: '11px', color: 'var(--i3)', marginLeft: 'auto' }}>{g.players.length} {g.players.length === 1 ? tc('member') : tc('members')}</span>
                        </div>
                        {g.players.map(function(p, i) { return row(p, g.teamId + '-' + i); })}
                      </div>
                    );
                  })}
                </div>
              ) : (
                <div>{players.map(function(p, i) { return row(p, i); })}</div>
              )}
            </div>
          </div>
        );
      })()}
    </div>
  );

  return (
    <div className="page-monitor">
      {/* Game header */}
      <div className="pghd">
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: '10px', flexWrap: 'wrap' }}>
            <div className="title">{game.name || gameId}</div>
            <code style={{
              fontFamily: 'var(--f-m)',
              fontSize: '12px',
              background: 'var(--s2)',
              padding: '2px 8px',
              borderRadius: '4px',
              color: 'var(--brand)',
            }}>{game.join_code || displayCode}</code>
            <PhaseBadge phase={phase} />
            <span style={{ fontSize: '13px', color: 'var(--i3)' }}>
              {players.length} player{players.length !== 1 ? 's' : ''}
            </span>
          </div>
        </div>
        <div className="right" style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
          <button
            className="btn"
            onClick={function() {
              var url = '/v2/projector.html?game=' + encodeURIComponent(gameId);
              window.open(url, 'arena-projector-' + gameId,
                'width=1920,height=1080,menubar=no,toolbar=no,location=no,status=no');
            }}
            title="Opens the big-screen view in a new window — cast this to your projector or TV"
            style={{
              background: 'linear-gradient(135deg, #00BCEB 0%, #1E4D8C 100%)',
              borderColor: '#00BCEB',
              color: '#fff',
              fontWeight: 700,
              boxShadow: '0 0 0 1px rgba(0,188,235,0.35), 0 4px 14px rgba(0,188,235,0.25)',
              letterSpacing: '.02em',
            }}>
            📺 Open Projector View ↗
          </button>
          <a
            href={('/v2/organizer-breach-review.html?game=' + encodeURIComponent(gameId) + ((window.AdminSession && window.AdminSession.getToken && window.AdminSession.getToken()) ? '#t=' + encodeURIComponent(window.AdminSession.getToken()) : ''))}
            target="_blank"
            rel="noreferrer"
            className="btn"
            title="Review and score breach (VAR) submissions in a read-only window. Does NOT affect what players see."
            style={{
              background: 'linear-gradient(135deg, #ff6b35 0%, #c2185b 100%)',
              borderColor: '#ff6b35',
              color: '#fff',
              fontWeight: 700,
              textDecoration: 'none',
              boxShadow: '0 0 0 1px rgba(255,107,53,0.35), 0 4px 14px rgba(255,107,53,0.25)',
              letterSpacing: '.02em',
              display: 'inline-flex',
              alignItems: 'center',
              gap: '6px',
            }}>
            📋 Review Breach ↗
          </a>
          <button className="btn ghost" onClick={function() { onSelectGame(null); }}>← Back</button>
        </div>
      </div>

      {/* Tab strip */}
      {React.createElement(window.MonitorOpsTabs, {
        activeTab: activeTab,
        onChange: setActiveTab,
        badges: {
          gameplan: submissions_badge,
          triage: triageUnreviewed,
        },
      })}

      {activeTab === 'control' && (
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 420px', gap: '16px', marginTop: '0' }}>
        {/* Left column */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>

          {/* Phase + Timer controls */}
          <div className="card">
            <div className="card-hd"><h3>Game controls</h3></div>
            <div className="card-bd" style={{ padding: '16px 18px', display: 'flex', flexDirection: 'column', gap: '14px' }}>

              {/* Phase controls */}
              <div>
                <div style={{ fontSize: '11px', color: 'var(--i3)', marginBottom: '8px', textTransform: 'uppercase', letterSpacing: '.05em' }}>Phase</div>
                <div className="phase-controls" style={{ display: 'flex', gap: '6px' }}>
                  {phaseOptions.map(function(p) {
                    var isActive = phase === p;
                    return (
                      <button key={p}
                        className={'btn' + (isActive ? ' primary' : ' ghost')}
                        style={{ textTransform: 'capitalize' }}
                        onClick={function() { onSetPhase(p); }}
                      >
                        {p}
                      </button>
                    );
                  })}
                </div>
              </div>

              {/* Start Quiz — prominent CTA after draft completes */}
              {phase !== 'playing' && allPlayersAssigned && (
                <div style={{ padding: '14px 18px', background: 'color-mix(in srgb, var(--up) 10%, transparent)', borderRadius: '10px', textAlign: 'center' }}>
                  <div style={{ fontSize: '13px', color: 'var(--up)', fontWeight: 600, marginBottom: '8px' }}>✓ Draft complete — all players assigned to teams</div>
                  <button className="btn primary" onClick={function() {
                    AdminApi.setGamePhase(gameId, 'playing')
                      .then(function() { return AdminApi.setSubPhase(gameId, 'quiz'); })
                      .then(function() { showToast(tc('Quiz phase started!'), 'ok'); })
                      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
                  }}
                    style={{ background: 'var(--up)', borderColor: 'var(--up)', fontSize: '15px', padding: '12px 32px' }}>
                    ▶ Start Quiz Phase
                  </button>
                </div>
              )}

              {/* ⏱ Phase timer — redesigned with minutes, mm:ss display, grouped layout */}
              {(function() {
                var activePhaseId = currentSubPhase || 'quiz';
                var activeTimer = (timer && timer[activePhaseId]) ? timer[activePhaseId]
                  : (timer && timer.quiz) ? timer.quiz : null;
                var totalSecs = activeTimer
                  ? (activeTimer.paused ? activeTimer.remaining : activeTimer.remaining)
                  : null;
                function fmtMmSs(s) {
                  var n = Math.max(0, Math.round(s || 0));
                  var m = Math.floor(n / 60);
                  var r = n % 60;
                  return (m < 10 ? '0' : '') + m + ':' + (r < 10 ? '0' : '') + r;
                }
                var isRunning = activeTimer && !activeTimer.paused && !activeTimer.expired && activeTimer.remaining > 0;
                var isExpired = activeTimer && activeTimer.expired;
                var isPaused  = activeTimer && activeTimer.paused;
                var countColor = isExpired ? 'var(--dn, #E10600)'
                  : (totalSecs != null && totalSecs < 120) ? '#F0A000'
                  : 'var(--up, #6CC04A)';
                var durationMins = Math.max(0.5, Math.round((durationInput / 60) * 10) / 10);
                return (
                  <div style={{
                    border: '1px solid var(--line-soft)',
                    borderRadius: '10px',
                    padding: '12px 14px',
                    background: 'var(--s1)',
                    display: 'flex',
                    flexDirection: 'column',
                    gap: '10px',
                  }}>
                    {/* Header row: heading + big mm:ss */}
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                      <div style={{ fontSize: '11px', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.06em', color: 'var(--i2)' }}>
                        ⏱ {tc('Phase timer')} · <span style={{ textTransform: 'none', fontWeight: 500, color: 'var(--i3)' }}>{activePhaseId}</span>
                        {isPaused && <span style={{ marginLeft: 6, color: '#F0A000', fontWeight: 600 }}>⏸ paused</span>}
                        {isExpired && <span style={{ marginLeft: 6, color: 'var(--dn, #E10600)', fontWeight: 600 }}>expired</span>}
                      </div>
                      <div style={{
                        fontFamily: 'var(--f-m, monospace)',
                        fontSize: '28px',
                        fontWeight: 800,
                        color: countColor,
                        letterSpacing: '.04em',
                        fontVariantNumeric: 'tabular-nums',
                        lineHeight: 1,
                      }}>
                        {totalSecs != null ? fmtMmSs(totalSecs) : '--:--'}
                      </div>
                    </div>

                    {/* Start / Pause / Restart */}
                    <div style={{ display: 'flex', gap: '6px' }}>
                      <button className="btn ghost" onClick={function() { onTimerAction('start', activePhaseId); }}>▶ Start</button>
                      <button className="btn ghost" onClick={function() { onTimerAction('pause', activePhaseId); }}>⏸ Pause</button>
                      <button className="btn ghost" onClick={function() { onTimerAction('restart', activePhaseId); }}>↩ Restart</button>
                    </div>

                    {/* Set duration row */}
                    <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
                      <span style={{ fontSize: '12px', color: 'var(--i3)', minWidth: '60px' }}>Set:</span>
                      <input
                        type="number" min="1" max="1440" step="1"
                        value={durationMins}
                        onChange={function(e) {
                          userEditedDuration.current = true;
                          var m = Math.max(0.5, parseFloat(e.target.value) || 1);
                          setDurationInput(Math.round(m * 60));
                        }}
                        style={{ width: '60px', padding: '4px 6px', border: '1px solid var(--line-soft)', borderRadius: '4px', fontSize: '13px', textAlign: 'center' }}
                        title="Duration in minutes"
                      />
                      <span style={{ fontSize: '12px', color: 'var(--i3)' }}>min</span>
                      <button className="btn ghost"
                        onClick={function() { onTimerAction('set-duration', activePhaseId, durationInput); }}
                        style={{ fontSize: '12px' }}>
                        Set
                      </button>
                    </div>

                    {/* Extend row */}
                    <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
                      <span style={{ fontSize: '12px', color: 'var(--i3)', minWidth: '60px' }}>Extend:</span>
                      <button className="btn ghost"
                        onClick={function() { onTimerAction('extend', activePhaseId, 60); }}
                        style={{ fontSize: '12px' }}>+1 min</button>
                      <button className="btn ghost"
                        onClick={function() { onTimerAction('extend', activePhaseId, 300); }}
                        style={{ fontSize: '12px' }}>+5 min</button>
                    </div>
                  </div>
                );
              })()}

              {/* 👁 Observer mode */}
              <div style={{
                border: '1px solid var(--line-soft)',
                borderRadius: '10px',
                padding: '12px 14px',
                background: 'var(--s1)',
              }}>
                <div style={{ fontSize: '11px', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.06em', color: 'var(--i2)', marginBottom: '8px' }}>
                  👁 {tc('Observer')}
                </div>
                {observerToast && (
                  <div style={{ fontSize: '12px', color: '#1BA0D7', marginBottom: '8px', padding: '6px 10px', background: 'rgba(27,160,215,0.10)', borderRadius: '6px', wordBreak: 'break-all' }}>
                    👁 Observer tab opened: <code style={{ fontSize: '11px', userSelect: 'all' }}>{observerToast}</code>
                  </div>
                )}
                <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                  <button className="btn ghost" onClick={function() {
                    var ts = Date.now();
                    var email = 'observer+' + ts + '@cisco.com';
                    var url = window.location.origin + '/v2/?game=' + encodeURIComponent(gameId) + '&email=' + encodeURIComponent(email) + '&name=Observer&observer=1';
                    window.open(url, '_blank');
                    setObserverToast(email);
                    setTimeout(function() { setObserverToast(null); }, 8000);
                  }}>👁 Join as observer</button>
                  <span style={{ fontSize: '11px', color: 'var(--i3)' }}>Opens player UI — no team, no scoring</span>
                </div>
              </div>

              {/* Quiz Settings */}
              <div>
                <div style={{ fontSize: '11px', color: 'var(--i3)', marginBottom: '8px', textTransform: 'uppercase', letterSpacing: '.05em' }}>
                  Phase content limits ({quizCount + funCount} quiz · {gameplanCount || 'all'} GP · {zonamixtaCount || 'all'} ZM)
                </div>
                <div style={{ display: 'flex', gap: '10px', alignItems: 'center', flexWrap: 'wrap' }}>
                  <label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '13px' }}>
                    Tech
                    <input type="number" min="1" max="50" value={quizCount}
                      onChange={function(e) { setQuizCount(Math.max(1, Math.min(50, Number(e.target.value) || 1))); }}
                      style={{ width: '52px', padding: '4px 6px', border: '1px solid var(--line-soft)', borderRadius: '4px', fontSize: '13px', textAlign: 'center' }}
                    />
                  </label>
                  <label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '13px' }}>
                    Fun
                    <input type="number" min="0" max="20" value={funCount}
                      onChange={function(e) { setFunCount(Math.max(0, Math.min(20, Number(e.target.value) || 0))); }}
                      style={{ width: '52px', padding: '4px 6px', border: '1px solid var(--line-soft)', borderRadius: '4px', fontSize: '13px', textAlign: 'center' }}
                    />
                  </label>
                  <label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '13px' }}>
                    Tickets
                    <input type="number" min="1" max="10" value={ticketCount}
                      onChange={function(e) { setTicketCount(Math.max(1, Math.min(10, Number(e.target.value) || 1))); }}
                      style={{ width: '52px', padding: '4px 6px', border: '1px solid var(--line-soft)', borderRadius: '4px', fontSize: '13px', textAlign: 'center' }}
                    />
                  </label>
                  <label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '13px' }} title="Number of GamePlan scenarios available. 0 = all available briefs.">
                    GamePlan
                    <input type="number" min="0" max="50" value={gameplanCount}
                      onChange={function(e) { setGameplanCount(Math.max(0, Math.min(50, Number(e.target.value) || 0))); }}
                      style={{ width: '52px', padding: '4px 6px', border: '1px solid var(--line-soft)', borderRadius: '4px', fontSize: '13px', textAlign: 'center' }}
                    />
                  </label>
                  <label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '13px' }} title="Number of Zona Mixta curveballs. 0 = all available.">
                    Zona Mixta
                    <input type="number" min="0" max="50" value={zonamixtaCount}
                      onChange={function(e) { setZonamixtaCount(Math.max(0, Math.min(50, Number(e.target.value) || 0))); }}
                      style={{ width: '52px', padding: '4px 6px', border: '1px solid var(--line-soft)', borderRadius: '4px', fontSize: '13px', textAlign: 'center' }}
                    />
                  </label>
                  <button className="btn ghost" onClick={handleSaveQuizConfig} disabled={savingQuizConfig}
                    style={{ fontSize: '12px' }}>
                    {savingQuizConfig ? '…' : '💾 Save'}
                  </button>
                   <span style={{ fontSize: '11px', color: 'var(--i3)' }}>Players must refresh to see changes</span>
                </div>
              </div>

              {/* ─── Game phase advance (state-machine guarded) ─── */}
              {phase === 'playing' && (() => {
                var SUB_ORDER = ['quiz', 'triage', 'gameplan', 'zonamixta', 'wrap'];
                var SUB_LABELS = { quiz: 'Quiz', triage: 'Triage', gameplan: 'Game Plan', zonamixta: 'Zona Mixta', wrap: 'Wrap-up' };
                var SUB_COLORS = { quiz: '#1BA0D7', triage: '#6CC04A', gameplan: '#FFA500', zonamixta: '#FF6600', wrap: '#9B59B6' };
                var safeSub = typeof currentSubPhase === 'string' ? currentSubPhase : null;
                var curIdx = safeSub ? SUB_ORDER.indexOf(safeSub) : -1;
                function advanceTo(target) {
                  AdminApi.setSubPhase(gameId, target)
                    .then(function() { showToast('Players advancing to ' + SUB_LABELS[target], 'ok'); })
                    .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
                }
                return (
                  <div style={{ borderTop: '1px solid var(--line-soft)', margin: '16px 0', paddingTop: '16px' }}>
                    <h4 style={{ fontSize: '13px', fontWeight: 600, marginBottom: '10px', color: 'var(--i1)', display: 'flex', alignItems: 'center', gap: '8px' }}>
                      🏁 Game phase
                      <span style={{ fontSize: '11px', color: 'var(--i3)', textTransform: 'uppercase', letterSpacing: '.05em' }}>
                        Current: {safeSub ? (SUB_LABELS[safeSub] || safeSub) : '— (not started)'}
                      </span>
                    </h4>
                    <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
                      {SUB_ORDER.map(function(target, idx) {
                        var isCurrent = target === safeSub;
                        var isPast = curIdx >= 0 && idx < curIdx;
                        var isNext = idx === curIdx + 1 || (curIdx === -1 && idx === 0);
                        var disabled = isCurrent || isPast;
                        var bg = disabled ? 'var(--s2)' : SUB_COLORS[target];
                        var border = disabled ? 'var(--line-soft)' : SUB_COLORS[target];
                        var color = disabled ? 'var(--i3)' : '#fff';
                        var ring = isNext ? '0 0 0 2px ' + SUB_COLORS[target] + '55' : 'none';
                        return (
                          <button key={target} className="btn"
                            disabled={disabled}
                            onClick={function() { advanceTo(target); }}
                            title={disabled ? (isCurrent ? 'Players are here now' : 'Already past this phase') : 'Advance players to ' + SUB_LABELS[target]}
                            style={{
                              background: bg, borderColor: border, color: color,
                              cursor: disabled ? 'not-allowed' : 'pointer',
                              opacity: disabled ? 0.55 : 1,
                              boxShadow: ring,
                              fontWeight: isNext ? 700 : 500
                            }}>
                            {isCurrent ? '● ' : (isPast ? '✓ ' : '▶ ')}
                            {SUB_LABELS[target]}
                          </button>
                        );
                      })}
                    </div>
                    <div style={{ fontSize: '11px', color: 'var(--i3)', marginTop: '8px' }}>
                      Phases advance left → right. Past phases are locked to prevent sending players backward.
                    </div>
                  </div>
                );
              })()}

              {/* ─── Triage settings ─── */}
              <div style={{ borderTop: '1px solid var(--line-soft)', margin: '16px 0', paddingTop: '16px' }}>
                <h4 style={{ fontSize: '13px', fontWeight: 600, marginBottom: '10px', color: 'var(--i1)' }}>🎫 Triage phase</h4>
                <div style={{ display: 'flex', gap: '12px', marginBottom: '12px' }}>
                  <div className="kpi">
                    <span className="kpi-val">{ticketAnswers.length}</span>
                    <span className="kpi-lbl">Submissions</span>
                  </div>
                  <div className="kpi">
                    <span className="kpi-val">{triageAiGraded}</span>
                    <span className="kpi-lbl">AI graded</span>
                  </div>
                  <div className="kpi">
                    <span className="kpi-val">{triageProctorGraded}</span>
                    <span className="kpi-lbl">Proctor reviewed</span>
                  </div>
                </div>
                <div style={{ height: '6px', background: 'var(--s2)', borderRadius: '3px', marginBottom: '12px' }}>
                  <div style={{ height: '100%', width: triagePct + '%', background: 'var(--ok)', borderRadius: '3px', transition: 'width .4s' }}></div>
                </div>
                <button className="btn primary" onClick={function() { setActiveTab('triage'); }}>
                  Open proctor queue →
                </button>
              </div>
            </div>
          </div>

          {/* Activity Feed */}
          <div className="card">
            <div className="card-hd" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <h3 style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
                <span style={{ fontSize: '16px' }}>📡</span> Activity Feed
              </h3>
              <div style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em', color: 'var(--i3)' }}>
                {activity.length} events
              </div>
            </div>
            <div className="card-bd" style={{ padding: '0', maxHeight: '360px', overflowY: 'auto' }}>
              {activity.length === 0 && (
                <div style={{ padding: '32px 16px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }}>
                  No activity yet — events will appear as players interact
                </div>
              )}
              {activity.map(function(evt, idx) {
                var icon = '📋';
                var evtColor = 'var(--i2)';
                if (evt.event_type === 'ticket_graded') { icon = '🤖'; evtColor = '#049FD9'; }
                if (evt.event_type === 'answer_submitted') { icon = '📝'; evtColor = '#6CC04A'; }
                if (evt.event_type === 'proctor_scored') { icon = '⭐'; evtColor = '#FFCC00'; }
                if (evt.event_type === 'phase_advanced') { icon = '🏁'; evtColor = '#FF6600'; }
                if (evt.event_type === 'powerup_used') { icon = '⚡'; evtColor = '#9B59B6'; }
                if (evt.event_type === 'player_joined') { icon = '👤'; evtColor = '#1BA0D7'; }

                var timeAgo = '';
                if (evt.created_at) {
                  var diff = Math.floor((Date.now() - new Date(evt.created_at + 'Z').getTime()) / 1000);
                  if (diff < 60) { timeAgo = diff + 's ago'; }
                  else if (diff < 3600) { timeAgo = Math.floor(diff / 60) + 'm ago'; }
                  else { timeAgo = Math.floor(diff / 3600) + 'h ago'; }
                }

                return (
                  <div key={evt.id || idx} style={{
                    display: 'flex', alignItems: 'center', gap: '10px',
                    padding: '10px 16px', borderBottom: '1px solid var(--line-soft)',
                    fontSize: '13px', lineHeight: '1.4'
                  }}>
                    <span style={{ fontSize: '16px', flexShrink: 0 }}>{icon}</span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <span style={{ fontWeight: 600, color: evtColor }}>{evt.player_name || 'System'}</span>
                      <span style={{ color: 'var(--i2)', marginLeft: '6px' }}>{evt.detail}</span>
                    </div>
                    <span style={{
                      fontSize: '11px', color: 'var(--i3)', whiteSpace: 'nowrap',
                      fontFamily: 'var(--f-m)', flexShrink: 0
                    }}>{timeAgo}</span>
                  </div>
                );
              })}
            </div>
          </div>

          {/* Test Players — development tool */}
          <div className="card">
              <div className="card-hd" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '12px' }}>
                <h3>Test Players</h3>
                <div style={{ fontSize: '11px', textTransform: 'uppercase', letterSpacing: '.05em', color: 'var(--i3)' }}>Dev tool</div>
              </div>
              <div className="card-bd" style={{ padding: '16px 18px' }}>
                <div style={{ display: 'flex', gap: '8px', alignItems: 'center', flexWrap: 'wrap' }}>
                  <label style={{ fontSize: '13px', color: 'var(--i2)' }}>Generate</label>
                  <input type="number" min="1" max="100" value={testPlayerCount}
                    onChange={function(e) { setTestPlayerCount(Math.max(1, Math.min(100, parseInt(e.target.value) || 1))); }}
                    style={{ width: '64px', padding: '8px 10px', borderRadius: '8px', border: '1px solid var(--line-soft)', background: 'var(--s2)', color: 'var(--i1)', fontFamily: 'var(--f-m)', fontSize: '13px', textAlign: 'center' }}
                  />
                  <label style={{ fontSize: '13px', color: 'var(--i2)' }}>fake players</label>
                  <button className="btn primary" disabled={generatingPlayers} onClick={handleGenerateTestPlayers}>
                    {generatingPlayers ? 'Creating…' : '＋ Generate'}
                  </button>
                </div>
                <div style={{ display: 'flex', gap: '8px', alignItems: 'center', marginTop: '12px', paddingTop: '12px', borderTop: '1px solid var(--line-soft)' }}>
                  <button className="btn ghost" style={{ color: 'var(--dn)', borderColor: 'var(--dn)', fontSize: '12px' }} onClick={handleResetPlayers}>
                    ✕ Delete all players
                  </button>
                  <span style={{ fontSize: '11px', color: 'var(--i3)' }}>Keeps game config &amp; modules</span>
                </div>
              </div>
            </div>

          {/* Captain Assignment + Draft */}
          <div className="card" data-anchor="captain-assignment" style={{ transition: 'box-shadow .3s' }}>
              <div className="card-hd" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                <h3>Captain Assignment</h3>
                <span style={{ fontSize: '12px', color: captains.length >= 2 ? 'var(--up)' : 'var(--i3)' }}>
                  {captains.length}/{themeTeams.length} assigned
                </span>
              </div>
              <div className="card-bd" style={{ padding: '0' }}>
                {themeTeams.length === 0 ? (
                  <div style={{ padding: '24px', color: 'var(--i3)', fontSize: '13px', textAlign: 'center' }}>
                    No teams found for theme "{gameThemeId}". Check window.THEMES.
                  </div>
                ) : (
                  <div>
                    {themeTeams.map(function(team) {
                      var captain = captainByTeam[team.id];
                      return (
                        <div key={team.id} style={{
                          display: 'flex', alignItems: 'center', gap: '10px',
                          padding: '10px 16px', borderBottom: '1px solid var(--line-soft)',
                        }}>
                          <div style={{
                            width: '10px', height: '10px', borderRadius: '50%',
                            background: team.color || 'var(--i3)', flexShrink: 0,
                          }} />
                          <div style={{ width: '90px', fontWeight: 600, fontSize: '13px' }}>
                            {team.name}
                          </div>
                          {captain ? (
                            <div style={{ flex: 1, display: 'flex', alignItems: 'center', gap: '8px' }}>
                              <span style={{ fontSize: '13px' }}>{captain.name || captain.email}</span>
                              <button className="btn ghost" style={{ fontSize: '11px', padding: '2px 6px', color: 'var(--dn)' }}
                                onClick={function() { handleRemoveCaptain(captain.email, team.id); }}>
                                ✕
                              </button>
                            </div>
                          ) : (
                            <select
                              style={{
                                flex: 1, padding: '6px 8px', borderRadius: '6px',
                                border: '1px solid var(--line-soft)', background: 'var(--s2)',
                                color: 'var(--i1)', fontSize: '12px', fontFamily: 'var(--f-m)',
                              }}
                              value=""
                              onChange={function(e) {
                                if (e.target.value) handleSetCaptain(e.target.value, team.id);
                              }}
                            >
                              <option value="">Select captain…</option>
                              {nonCaptainPlayers.map(function(p) {
                                return (
                                  <option key={p.email} value={p.email}>
                                    {p.name || p.email}
                                  </option>
                                );
                              })}
                            </select>
                          )}
                        </div>
                      );
                    })}
                  </div>
                )}

                {/* Draft progress bar */}
                {(phase === 'draft' || isPlayingWithTeams) && players.length > 0 && (
                  <div style={{ padding: '10px 16px', borderTop: '1px solid var(--line-soft)' }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '11px', color: 'var(--i3)', marginBottom: '6px' }}>
                      <span>Draft progress</span>
                      <span style={{ color: (allPlayersAssigned) ? 'var(--up)' : 'var(--brand)', fontFamily: 'var(--f-m)' }}>
                        {draftedForProgress}/{draftedForProgress + undraftedForProgress} assigned
                      </span>
                    </div>
                    <div style={{ height: '6px', borderRadius: '999px', background: 'var(--s2)', overflow: 'hidden' }}>
                      <div style={{
                        height: '100%',
                        width: (draftedForProgress + undraftedForProgress > 0) ? ((draftedForProgress / (draftedForProgress + undraftedForProgress)) * 100) + '%' : '0%',
                        background: (allPlayersAssigned) ? 'var(--up)' : 'var(--brand)',
                        borderRadius: '999px',
                        transition: 'width .4s ease',
                      }} />
                    </div>
                  </div>
                )}

                {/* Action buttons */}
                <div style={{ padding: '12px 16px', display: 'flex', gap: '8px', flexWrap: 'wrap', borderTop: '1px solid var(--line-soft)' }}>
                  {(phase === 'registration' || phase === 'draft') && !allPlayersAssigned && (
                  <button className="btn primary" disabled={startingDraft || captains.length < 2}
                    onClick={handleStartDraft}
                    title={captains.length < 2 ? 'Need at least 2 captains' : ('Start draft with ' + captains.length + ' captain' + (captains.length === 1 ? '' : 's'))}
                    style={{ opacity: captains.length < 2 ? 0.5 : 1 }}>
                    {startingDraft ? 'Starting…' : '▶ Start Draft (' + captains.length + '/' + themeTeams.length + ')'}
                  </button>
                  )}
                  {isPlayingWithTeams && (
                    <span style={{ display: 'inline-flex', alignItems: 'center', gap: '6px', fontSize: '13px', fontWeight: 700, color: 'var(--up)', padding: '6px 14px', background: 'color-mix(in srgb, var(--up) 12%, transparent)', borderRadius: '8px' }}>
                      ✓ Draft complete — Playing phase active
                    </span>
                  )}
                  {draftIsComplete && (
                    <button className="btn primary" onClick={function() { onSetPhase('playing'); }}
                      style={{ background: 'var(--up)', borderColor: 'var(--up)' }}>
                      ▶ Start Playing Phase
                    </button>
                  )}
                  {phase === 'registration' && players.length > 0 && (
                    <button className="btn ghost" disabled={autoAssigning}
                      onClick={handleAutoAssignAndPlay}
                      style={{ borderColor: 'var(--brand)' }}>
                      {autoAssigning ? 'Assigning…' : '⚡ Auto-assign & Play'}
                    </button>
                  )}
                  {(phase === 'draft' || phase === 'playing') && (
                    <button className="btn ghost" style={{ color: 'var(--dn)' }} onClick={handleResetDraft}>
                      ↩ Reset Draft
                    </button>
                  )}
                  <span style={{ fontSize: '11px', color: isPlayingWithTeams ? 'var(--up)' : 'var(--i3)', alignSelf: 'center', fontWeight: isPlayingWithTeams ? 600 : 400 }}>
                    {isPlayingWithTeams
                      ? 'All ' + draftedForProgress + ' players on teams. Ready to play!'
                      : draftIsComplete
                        ? '✓ All players assigned! Click ▶ to start playing.'
                        : phase === 'registration' 
                          ? 'Assign 1 captain per team, then start the draft' 
                          : phase === 'draft'
                            ? 'Draft in progress — players are being assigned to teams'
                            : 'Draft complete · ↩ Reset to redo'}
                  </span>
                </div>
              </div>
            </div>

          {/* Leaderboard */}
          <div className="card">
            <div className="card-hd"><h3>Leaderboard</h3></div>
            <div className="card-bd" style={{ padding: '0' }}>
              {leaderboard.length === 0 ? (
                <div style={{ padding: '24px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }}>
                  No scores yet.
                </div>
              ) : (function() {
                  // Group players by team
                  var teamMap = {};
                  var unassigned = [];
                  leaderboard.forEach(function(entry) {
                    if (!entry.team) {
                      unassigned.push(entry);
                    } else {
                      if (!teamMap[entry.team]) teamMap[entry.team] = [];
                      teamMap[entry.team].push(entry);
                    }
                  });

                  // Build sorted team list
                  var teamGroups = Object.keys(teamMap).map(function(teamName) {
                    var members = teamMap[teamName].slice().sort(function(a, b) { return (b.score || 0) - (a.score || 0); });
                    var total = members.reduce(function(sum, p) { return sum + (p.score || 0); }, 0);
                    var themeTeam = themeTeams && themeTeams.find(function(t) { return t.id === teamName || t.name === teamName || t.short === teamName; });
                    var teamColor = (themeTeam && themeTeam.color) || (members[0] && (members[0].team_color || members[0].color)) || 'var(--brand)';
                    var displayName = (themeTeam && themeTeam.name) || teamName;
                    return { name: teamName, displayName: displayName, members: members, total: total, color: teamColor };
                  });
                  teamGroups.sort(function(a, b) { return b.total - a.total; });

                  var sortedUnassigned = unassigned.slice().sort(function(a, b) { return (b.score || 0) - (a.score || 0); });
                  var unassignedTotal = sortedUnassigned.reduce(function(s, p) { return s + (p.score || 0); }, 0);

                  return (
                    <React.Fragment>
                      {teamGroups.map(function(tg) {
                        return (
                          <React.Fragment key={'tg-' + tg.name}>
                            <div style={{
                              display: 'grid', gridTemplateColumns: '14px 1fr auto auto',
                              gap: '10px', alignItems: 'center',
                              padding: '10px 16px 8px 16px',
                              borderBottom: '1px solid var(--line-soft)',
                              borderLeft: '3px solid ' + tg.color,
                              background: 'var(--s2)',
                            }}>
                              <span style={{ width: 10, height: 10, borderRadius: '50%', background: tg.color, display: 'inline-block' }}></span>
                              <span style={{ fontWeight: 700, fontSize: 14 }}>{tg.displayName}</span>
                              <span style={{ fontFamily: 'var(--f-m)', fontSize: 14, fontWeight: 700, color: 'var(--brand)' }}>{tg.total} pts</span>
                              <span style={{ fontSize: 11, color: 'var(--i3)' }}>{tg.members.length} player{tg.members.length !== 1 ? 's' : ''}</span>
                            </div>
                            {tg.members.map(function(entry, pi) {
                              return (
                                <div key={'p-' + (entry.email || tg.name + pi)} style={{
                                  display: 'grid', gridTemplateColumns: '1fr auto', gap: '10px',
                                  alignItems: 'center', padding: '7px 16px 7px 28px',
                                  borderBottom: '1px solid var(--line-soft)',
                                }}>
                                  <div>
                                    <span style={{ fontSize: 13, fontWeight: 500 }}>{entry.name || '—'}</span>
                                    {entry.email ? <span style={{ fontSize: 11, color: 'var(--i3)', marginLeft: 8 }}>{entry.email}</span> : null}
                                  </div>
                                  <span style={{ fontFamily: 'var(--f-m)', fontSize: 13, color: 'var(--i1)' }}>{entry.score != null ? entry.score : '—'}</span>
                                </div>
                              );
                            })}
                          </React.Fragment>
                        );
                      })}
                      {sortedUnassigned.length > 0 ? (
                        <React.Fragment>
                          <div style={{
                            display: 'grid', gridTemplateColumns: '14px 1fr auto auto',
                            gap: '10px', alignItems: 'center',
                            padding: '10px 16px 8px 16px',
                            borderBottom: '1px solid var(--line-soft)',
                            borderLeft: '3px solid var(--i3)',
                            background: 'var(--s2)',
                          }}>
                            <span style={{ width: 10, height: 10, borderRadius: '50%', background: 'var(--i3)', display: 'inline-block' }}></span>
                            <span style={{ fontWeight: 700, fontSize: 14, color: 'var(--i3)' }}>Unassigned</span>
                            <span style={{ fontFamily: 'var(--f-m)', fontSize: 14, fontWeight: 700, color: 'var(--i3)' }}>{unassignedTotal} pts</span>
                            <span style={{ fontSize: 11, color: 'var(--i3)' }}>{sortedUnassigned.length} player{sortedUnassigned.length !== 1 ? 's' : ''}</span>
                          </div>
                          {sortedUnassigned.map(function(entry, pi) {
                            return (
                              <div key={'u-' + (entry.email || pi)} style={{
                                display: 'grid', gridTemplateColumns: '1fr auto', gap: '10px',
                                alignItems: 'center', padding: '7px 16px 7px 28px',
                                borderBottom: '1px solid var(--line-soft)',
                              }}>
                                <div>
                                  <span style={{ fontSize: 13, fontWeight: 500 }}>{entry.name || '—'}</span>
                                  {entry.email ? <span style={{ fontSize: 11, color: 'var(--i3)', marginLeft: 8 }}>{entry.email}</span> : null}
                                </div>
                                <span style={{ fontFamily: 'var(--f-m)', fontSize: 13, color: 'var(--i1)' }}>{entry.score != null ? entry.score : '—'}</span>
                              </div>
                            );
                          })}
                        </React.Fragment>
                      ) : null}
                    </React.Fragment>
                  );
                })()
              }
            </div>
          </div>

          {/* Danger zone */}
          <div className="card danger-zone" style={{ borderColor: 'var(--dn)' }}>
            <div className="card-hd" style={{ borderBottomColor: 'var(--dn)' }}>
              <h3 style={{ color: 'var(--dn)' }}>Danger zone</h3>
            </div>
            <div className="card-bd" style={{ padding: '16px 18px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <div>
                <div style={{ fontWeight: 600, marginBottom: '4px' }}>Reset game</div>
                <div style={{ fontSize: '12px', color: 'var(--i3)' }}>Clears all scores and events. This cannot be undone.</div>
              </div>
              <button className="btn ghost" style={{ color: 'var(--dn)', borderColor: 'var(--dn)' }}
                onClick={function() {
                  if (window.confirm('Reset game ' + gameId + '? This cannot be undone.')) {
                    onResetGame();
                  }
                }}>
                Reset game
              </button>
            </div>
          </div>
        </div>

        {/* Right column wrapper */}
        <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', alignSelf: 'start' }}>

        {/* Available players card — draft phase only */}
        {phase === 'draft' && (function() {
          var undrafted = players.filter(function(p) { return p.team === '' && !p.isCaptain && !p.isProctor; });
          return (
            <div className="card">
              <div className="card-hd">
                <h3>Jugadores disponibles · {undrafted.length}</h3>
              </div>
              <div className="card-bd" style={{ padding: '0', maxHeight: '300px', overflowY: 'auto' }}>
                {undrafted.length === 0 ? (
                  <div style={{ padding: '16px 18px', fontSize: '13px', color: 'var(--up)', display: 'flex', alignItems: 'center', gap: '6px' }}>
                    <span>✓</span>
                    <span>Todos los jugadores han sido asignados</span>
                  </div>
                ) : (
                  <div>
                    {undrafted.map(function(p, i) {
                      return (
                        <div key={p.email || i} style={{
                          display: 'flex',
                          alignItems: 'center',
                          gap: '10px',
                          padding: '7px 14px',
                          borderBottom: '1px solid var(--line-soft)',
                          fontSize: '13px',
                        }}>
                          <div style={{ flex: 1, minWidth: 0 }}>
                            <div style={{ fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                              {p.name || p.email || '—'}
                            </div>
                          </div>
                          {p.score > 0 && (
                            <span style={{
                              fontSize: '11px',
                              fontFamily: 'var(--f-m)',
                              background: 'var(--s2)',
                              color: 'var(--brand)',
                              borderRadius: '4px',
                              padding: '2px 6px',
                              flexShrink: 0,
                            }}>
                              {p.score}
                            </span>
                          )}
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
            </div>
          );
        })()}

        </div>{/* end right column wrapper */}
      </div>
      )} {/* end activeTab === 'control' grid */}

      {activeTab === 'control' && (
      <div>
      {/* Full-width players card — teams displayed horizontally */}
      {(function() {
        var assignedCount = players.filter(function(p) { return p.team; }).length;
        var hasTeams = assignedCount > 0;

        var teamMeta = {};
        (themeTeams || []).forEach(function(t) {
          teamMeta[t.id] = { name: t.name, color: t.color };
        });

        var groups = [];
        if (hasTeams) {
          var seen = {};
          players.forEach(function(p) {
            var tid = p.team || '';
            if (!seen[tid]) {
              seen[tid] = true;
              var meta = teamMeta[tid] || {};
              groups.push({
                teamId: tid,
                teamName: tid ? (meta.name || tid) : 'Unassigned',
                teamColor: tid ? (meta.color || p.team_color || 'var(--i3)') : 'var(--i3)',
                players: [],
              });
            }
          });
          groups.sort(function(a, b) {
            if (!a.teamId && b.teamId) return 1;
            if (a.teamId && !b.teamId) return -1;
            return a.teamName.localeCompare(b.teamName);
          });
          var groupMap = {};
          groups.forEach(function(g) { groupMap[g.teamId] = g; });
          players.forEach(function(p) {
            var tid = p.team || '';
            if (groupMap[tid]) groupMap[tid].players.push(p);
          });
        }

        function renderPlayerRow(player, i) {
          var dotColor = (player.team && teamMeta[player.team] && teamMeta[player.team].color)
            ? teamMeta[player.team].color
            : (player.team_color || 'var(--i3)');
          return (
            React.createElement('div', {
              key: player.email || i,
              style: {
                display: 'flex',
                alignItems: 'center',
                gap: '10px',
                padding: '8px 14px',
                borderBottom: '1px solid var(--line-soft)',
                fontSize: '13px',
              }
            },
              React.createElement('span', {
                style: {
                  width: '8px',
                  height: '8px',
                  borderRadius: '50%',
                  background: dotColor,
                  flexShrink: 0,
                }
              }),
              React.createElement('div', { style: { flex: 1, minWidth: 0 } },
                React.createElement('div', {
                  style: { fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }
                },
                  player.isCaptain ? React.createElement('span', { style: { color: dotColor, marginRight: '3px' } }, '★') : null,
                  player.name || '—',
                  player.isProctor ? React.createElement('span', {
                    style: {
                      marginLeft: '6px',
                      fontSize: '9px',
                      fontWeight: 700,
                      letterSpacing: '.05em',
                      color: 'var(--i3)',
                      background: 'var(--s2)',
                      border: '1px solid var(--line-soft)',
                      borderRadius: '3px',
                      padding: '1px 4px',
                      verticalAlign: 'middle',
                    }
                  }, 'PROCTOR') : null
                ),
                React.createElement('div', {
                  style: { fontSize: '11px', color: 'var(--i3)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }
                }, player.email || '')
              ),
              React.createElement('span', {
                style: { fontFamily: 'var(--f-m)', fontSize: '12px', color: 'var(--i3)' }
              }, player.score != null ? player.score : '—'),
              player.isProctor ? null : React.createElement('select', {
                value: player.team || '',
                title: 'Override team for ' + (player.name || player.email),
                onChange: function(e) {
                  var newTeam = e.target.value;
                  if (newTeam === (player.team || '')) return;
                  if (!window.confirm('Move ' + (player.name || player.email) + ' to ' + (newTeam ? (teamMeta[newTeam] && teamMeta[newTeam].name) || newTeam : 'unassigned') + '?')) return;
                  AdminApi.assignTeam(gameId, player.email, newTeam)
                    .then(function() { showToast('Team updated', 'ok'); })
                    .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
                },
                style: {
                  fontSize: '11px',
                  padding: '2px 4px',
                  borderRadius: '4px',
                  border: '1px solid var(--line-soft)',
                  background: 'var(--s1)',
                  color: 'var(--i1)',
                  maxWidth: '110px',
                  flexShrink: 0,
                }
              },
                React.createElement('option', { value: '' }, '— unassigned'),
                (themeTeams || []).map(function(t) {
                  return React.createElement('option', { key: t.id, value: t.id }, t.name);
                })
              ),
              React.createElement('button', {
                style: {
                  color: 'var(--dn)',
                  fontSize: '11px',
                  padding: '2px 6px',
                  cursor: 'pointer',
                  opacity: 0.5,
                  background: 'none',
                  border: '1px solid transparent',
                  borderRadius: '4px',
                  flexShrink: 0,
                },
                onMouseEnter: function(e) { e.currentTarget.style.opacity = '1'; },
                onMouseLeave: function(e) { e.currentTarget.style.opacity = '0.5'; },
                onClick: function() {
                  if (window.confirm('Remove ' + (player.name || player.email) + ' from the game?')) {
                    AdminApi.deletePlayer(gameId, player.email)
                      .then(function() { showToast('Player removed', 'ok'); })
                      .catch(function(err) { showToast('Failed: ' + (err.message || err), 'error'); });
                  }
                },
              }, '✕')
            )
          );
        }

        return (
          React.createElement('div', { className: 'card', style: { marginTop: '16px' } },
            React.createElement('div', { className: 'card-hd' },
              React.createElement('h3', null,
                'Players · ' + players.length,
                hasTeams ? React.createElement('span', {
                  style: { fontSize: '11px', fontWeight: 400, color: 'var(--i3)', marginLeft: '8px' }
                }, assignedCount + ' on teams' + (players.length - assignedCount > 0 ? ', ' + (players.length - assignedCount) + ' unassigned' : '')) : null
              )
            ),
            React.createElement('div', {
              className: 'card-bd',
              style: hasTeams ? { padding: '0' } : { padding: '0', maxHeight: '600px', overflowY: 'auto' }
            },
              players.length === 0 ? (
                React.createElement('div', {
                  style: { padding: '24px', textAlign: 'center', color: 'var(--i3)', fontSize: '13px' }
                }, 'No players joined yet.')
              ) : hasTeams ? (
                React.createElement('div', {
                  className: 'player-list',
                  style: {
                    display: 'grid',
                    gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
                    gap: '16px',
                    padding: '16px',
                    alignItems: 'start',
                  }
                },
                  groups.map(function(group) {
                    return React.createElement('div', {
                      key: group.teamId || 'unassigned',
                      style: {
                        border: '1px solid var(--line-soft)',
                        borderRadius: '12px',
                        overflow: 'hidden',
                        maxHeight: '520px',
                        overflowY: 'auto',
                        minWidth: 0,
                      }
                    },
                      React.createElement('div', {
                        style: {
                          display: 'flex',
                          alignItems: 'center',
                          gap: '8px',
                          padding: '10px 14px',
                          background: 'var(--s2)',
                          borderBottom: '1px solid var(--line-soft)',
                          position: 'sticky',
                          top: 0,
                          zIndex: 1,
                        }
                      },
                        React.createElement('span', {
                          style: {
                            width: '10px',
                            height: '10px',
                            borderRadius: '50%',
                            background: group.teamColor,
                            flexShrink: 0,
                          }
                        }),
                        React.createElement('span', {
                          style: { fontWeight: 700, fontSize: '12px', textTransform: 'uppercase', letterSpacing: '.04em' }
                        }, group.teamName),
                        React.createElement('span', {
                          style: { fontSize: '11px', color: 'var(--i3)', marginLeft: 'auto' }
                        }, group.players.length + ' member' + (group.players.length !== 1 ? 's' : ''))
                      ),
                      group.players.map(function(player, i) { return renderPlayerRow(player, group.teamId + '-' + i); })
                    );
                  })
                )
              ) : (
                React.createElement('div', { className: 'player-list' },
                  players.map(function(player, i) { return renderPlayerRow(player, i); })
                )
              )
            )
          )
        );
      })()}
      </div>
      )} {/* end activeTab === 'control' players */}

      {/* ─── Proctor scoring tabs ─── */}
      {activeTab === 'gameplan' && (
        <div style={{ marginTop: '4px' }}>
          {React.createElement(window.GamePlanScoringTab, { gameId: gameId })}
        </div>
      )}

      {activeTab === 'zonamixta' && (
        <div style={{ marginTop: '4px' }}>
          {React.createElement(window.ZonaMixtaScoringTab, { gameId: gameId })}
        </div>
      )}

      {activeTab === 'triage' && (
        <div style={{ marginTop: '4px' }}>
          {React.createElement(window.TriageReviewTab, { gameId: gameId, initialAnswers: ticketAnswers })}
        </div>
      )}

    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgQuestionBankPage
// ---------------------------------------------------------------------------
window.OrgQuestionBankPage = function OrgQuestionBankPage(props) {
  var showToast = props.showToast || function() {};

  var ref1 = React.useState([]), modules = ref1[0], setModules = ref1[1];
  var ref2 = React.useState([]), content = ref2[0], setContent = ref2[1];
  var ref3 = React.useState(''), moduleFilter = ref3[0], setModuleFilter = ref3[1];
  var ref4 = React.useState(''), typeFilter = ref4[0], setTypeFilter = ref4[1];
  var ref5 = React.useState(''), search = ref5[0], setSearch = ref5[1];
  var ref6 = React.useState(false), loading = ref6[0], setLoading = ref6[1];

  function fetchData() {
    setLoading(true);
    Promise.all([
      AdminApi.listModules().catch(function() { return []; }),
      AdminApi.listContent().catch(function() { return []; }),
    ]).then(function(results) {
      setModules(Array.isArray(results[0]) ? results[0] : results[0].modules || []);
      setContent(Array.isArray(results[1]) ? results[1] : results[1].content || []);
    }).catch(function(err) {
      showToast('Failed to load content: ' + err.message, 'error');
    }).finally(function() { setLoading(false); });
  }

  React.useEffect(function() { fetchData(); }, []);

  var filtered = content.filter(function(item) {
    if (moduleFilter && (item.module_id || item.module) !== moduleFilter) return false;
    if (typeFilter && item.type !== typeFilter) return false;
    if (search) {
      var q = search.toLowerCase();
      var haystack = ((item.title || '') + ' ' + (item.question || '') + ' ' + (item.text || '')).toLowerCase();
      if (!haystack.includes(q)) return false;
    }
    return true;
  });

  var TYPE_COLORS = { quiz: 'brand', scenario: 'ok', truefalse: 'wn', ticket: '' };

  return (
    <div className="page-question-bank">
      <div className="pghd">
        <div>
          <div className="title">
            Question Bank
            <span style={{ marginLeft: '10px', fontSize: '14px', color: 'var(--i3)', fontWeight: 400 }}>
              {filtered.length} item{filtered.length !== 1 ? 's' : ''}
            </span>
          </div>
        </div>
        <div className="right" style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
          <button className="btn ghost" onClick={fetchData} disabled={loading}>
            {loading ? '…' : '↻'} Refresh
          </button>
        </div>
      </div>

      {/* Filters */}
      <div className="card" style={{ marginTop: '18px' }}>
        <div className="card-bd" style={{ padding: '14px 18px', display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
          <input
            type="text"
            placeholder="Search title / question…"
            value={search}
            onChange={function(e) { setSearch(e.target.value); }}
            style={{
              flex: '1 1 220px',
              padding: '7px 12px',
              border: '1px solid var(--line-soft)',
              borderRadius: '6px',
              background: 'var(--s2)',
              color: 'var(--i1)',
              fontSize: '13px',
            }}
          />
          <select value={moduleFilter} onChange={function(e) { setModuleFilter(e.target.value); }}
            style={{ padding: '7px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}>
            <option value="">All modules</option>
            {modules.map(function(m) {
              var id = m.module_id || m.id || m;
              var name = m.name || m.title || id;
              return <option key={id} value={id}>{name}</option>;
            })}
          </select>
          <select value={typeFilter} onChange={function(e) { setTypeFilter(e.target.value); }}
            style={{ padding: '7px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}>
            <option value="">All types</option>
            <option value="quiz">quiz</option>
            <option value="scenario">scenario</option>
            <option value="truefalse">truefalse</option>
            <option value="ticket">ticket</option>
          </select>
        </div>
      </div>

      {/* Content list */}
      <div className="card" style={{ marginTop: '14px' }}>
        <div className="card-hd">
          <h3>Content</h3>
        </div>
        <div className="card-bd" style={{ padding: '0' }}>
          {loading && content.length === 0 ? (
            <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>Loading…</div>
          ) : filtered.length === 0 ? (
            <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>No items match your filters.</div>
          ) : (
            <div>
              {/* Header row */}
              <div style={{
                display: 'grid',
                gridTemplateColumns: '100px 1fr 160px 80px',
                gap: '12px',
                padding: '8px 16px',
                borderBottom: '2px solid var(--line-soft)',
                fontSize: '11px',
                color: 'var(--i3)',
                textTransform: 'uppercase',
                letterSpacing: '.05em',
                fontWeight: 600,
              }}>
                <span>Type</span>
                <span>Title / Question</span>
                <span>Module</span>
                <span>Lang</span>
              </div>
              {filtered.map(function(item, i) {
                var typeColor = TYPE_COLORS[item.type] || '';
                return (
                  <div key={item.id || item.content_id || i} style={{
                    display: 'grid',
                    gridTemplateColumns: '100px 1fr 160px 80px',
                    gap: '12px',
                    alignItems: 'center',
                    padding: '10px 16px',
                    borderBottom: '1px solid var(--line-soft)',
                  }}>
                    <span className={'pill ' + typeColor} style={{ fontSize: '11px' }}>{item.type || '—'}</span>
                    <div>
                      <div style={{ fontWeight: 600, fontSize: '13px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {item.title || item.question || item.text || '—'}
                      </div>
                    </div>
                    <div style={{ fontSize: '12px', color: 'var(--i3)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                      {item.module_name || item.module || item.module_id || '—'}
                    </div>
                    <div style={{ fontSize: '12px', color: 'var(--i3)' }}>{item.language || item.lang || '—'}</div>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgResultsPage
// ---------------------------------------------------------------------------
window.OrgResultsPage = function OrgResultsPage(props) {
  var games = props.games || [];
  var showToast = props.showToast || function() {};

  var ref1 = React.useState(''), selectedGameId = ref1[0], setSelectedGameId = ref1[1];
  var ref2 = React.useState(null), report = ref2[0], setReport = ref2[1];
  var ref3 = React.useState(null), feedback = ref3[0], setFeedback = ref3[1];
  var ref4 = React.useState(false), loading = ref4[0], setLoading = ref4[1];

  function loadGame(gameId) {
    setSelectedGameId(gameId);
    if (!gameId) { setReport(null); setFeedback(null); return; }
    setLoading(true);
    Promise.all([
      AdminApi.getPostGameReport(gameId).catch(function() { return null; }),
      AdminApi.getFeedback(gameId).catch(function() { return null; }),
    ]).then(function(results) {
      setReport(results[0]);
      setFeedback(results[1]);
    }).catch(function(err) {
      showToast('Failed to load report: ' + err.message, 'error');
    }).finally(function() { setLoading(false); });
  }

  var standings = report && (report.standings || report.leaderboard || []);
  var topScorers = report && (report.top_scorers || []);
  var teamScores = report && (report.team_scores || report.teams || []);

  return (
    <div className="page-results">
      <div className="pghd">
        <div>
          <div className="title">Results &amp; Reports</div>
        </div>
      </div>

      {/* Game picker */}
      <div className="card" style={{ marginTop: '18px' }}>
        <div className="card-bd" style={{ padding: '14px 18px', display: 'flex', alignItems: 'center', gap: '12px' }}>
          <label style={{ fontSize: '13px', color: 'var(--i3)', flexShrink: 0 }}>Select game:</label>
          <select value={selectedGameId} onChange={function(e) { loadGame(e.target.value); }}
            style={{ flex: 1, maxWidth: '360px', padding: '7px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}>
            <option value="">— pick a game —</option>
            {games.map(function(g) {
              return <option key={g.game_id} value={g.game_id}>{g.name || g.game_id} ({g.game_id})</option>;
            })}
          </select>
        </div>
      </div>

      {/* Empty state */}
      {!selectedGameId && (
        <div style={{ padding: '64px', textAlign: 'center', color: 'var(--i3)' }}>
          <div style={{ fontSize: '32px', marginBottom: '12px' }}>📊</div>
          <div style={{ fontWeight: 600 }}>No game selected</div>
          <div style={{ fontSize: '13px', marginTop: '6px' }}>Pick a game above to view its report.</div>
        </div>
      )}

      {selectedGameId && loading && (
        <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>Loading report…</div>
      )}

      {selectedGameId && !loading && report && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginTop: '16px' }}>
          {/* Standings */}
          {standings && standings.length > 0 && (
            <div className="card">
              <div className="card-hd"><h3>Standings</h3></div>
              <div className="card-bd" style={{ padding: '0' }}>
                {standings.map(function(entry, i) {
                  return (
                    <div key={entry.email || i} style={{
                      display: 'grid',
                      gridTemplateColumns: '32px 1fr 80px',
                      gap: '10px',
                      alignItems: 'center',
                      padding: '9px 16px',
                      borderBottom: '1px solid var(--line-soft)',
                      background: i === 0 ? 'var(--s2)' : '',
                    }}>
                      <span style={{ fontFamily: 'var(--f-m)', fontSize: '13px', color: i === 0 ? 'var(--brand)' : 'var(--i3)', fontWeight: i === 0 ? 700 : 400 }}>#{i + 1}</span>
                      <div>
                        <div style={{ fontWeight: 600, fontSize: '13px' }}>{entry.name || entry.display_name || '—'}</div>
                        <div style={{ fontSize: '11px', color: 'var(--i3)' }}>{entry.email || ''}</div>
                      </div>
                      <span style={{ fontFamily: 'var(--f-m)', fontSize: '13px', color: 'var(--i1)', textAlign: 'right' }}>{entry.score != null ? entry.score : '—'}</span>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* Top scorers */}
          {topScorers && topScorers.length > 0 && (
            <div className="card">
              <div className="card-hd"><h3>Top scorers</h3></div>
              <div className="card-bd" style={{ padding: '0' }}>
                {topScorers.map(function(entry, i) {
                  return (
                    <div key={entry.email || i} style={{
                      display: 'flex',
                      alignItems: 'center',
                      gap: '12px',
                      padding: '9px 16px',
                      borderBottom: '1px solid var(--line-soft)',
                    }}>
                      <span style={{ fontFamily: 'var(--f-m)', fontSize: '13px', color: 'var(--brand)', fontWeight: 700, width: '28px' }}>#{i + 1}</span>
                      <div style={{ flex: 1 }}>
                        <div style={{ fontWeight: 600, fontSize: '13px' }}>{entry.name || entry.display_name || '—'}</div>
                        <div style={{ fontSize: '11px', color: 'var(--i3)' }}>{entry.team || ''}</div>
                      </div>
                      <span style={{ fontFamily: 'var(--f-m)', fontSize: '13px' }}>{entry.score != null ? entry.score : '—'}</span>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* Team scores */}
          {teamScores && teamScores.length > 0 && (
            <div className="card">
              <div className="card-hd"><h3>Team scores</h3></div>
              <div className="card-bd" style={{ padding: '0' }}>
                {teamScores.map(function(team, i) {
                  var color = team.color || team.team_color || 'var(--brand)';
                  return (
                    <div key={team.name || i} style={{
                      display: 'flex',
                      alignItems: 'center',
                      gap: '12px',
                      padding: '10px 16px',
                      borderBottom: '1px solid var(--line-soft)',
                    }}>
                      <span style={{ width: '12px', height: '12px', borderRadius: '50%', background: color, flexShrink: 0 }}></span>
                      <span style={{ flex: 1, fontWeight: 600 }}>{team.name || '—'}</span>
                      <span style={{ fontFamily: 'var(--f-m)', fontSize: '13px' }}>{team.score != null ? team.score : (team.total_score != null ? team.total_score : '—')}</span>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* Feedback */}
          {feedback && (
            <div className="card">
              <div className="card-hd"><h3>Feedback summary</h3></div>
              <div className="card-bd" style={{ padding: '16px 18px' }}>
                {Array.isArray(feedback) ? (
                  feedback.length === 0 ? (
                    <div style={{ color: 'var(--i3)', fontSize: '13px' }}>No feedback submitted.</div>
                  ) : (
                    feedback.map(function(fb, i) {
                      return (
                        <div key={i} style={{ borderBottom: '1px solid var(--line-soft)', padding: '8px 0', fontSize: '13px' }}>
                          <div style={{ color: 'var(--i3)', fontSize: '11px', marginBottom: '4px' }}>{fb.email || ''} · {fb.rating != null ? '★'.repeat(fb.rating) : ''}</div>
                          <div>{fb.comment || fb.text || '—'}</div>
                        </div>
                      );
                    })
                  )
                ) : (
                  <pre style={{ fontSize: '12px', color: 'var(--i3)', whiteSpace: 'pre-wrap', margin: 0 }}>{JSON.stringify(feedback, null, 2)}</pre>
                )}
              </div>
            </div>
          )}
        </div>
      )}

      {selectedGameId && !loading && !report && (
        <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>No report data available for this game.</div>
      )}
    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgSettingsPage
// ---------------------------------------------------------------------------
window.OrgSettingsPage = function OrgSettingsPage(props) {
  var admin = props.admin || null;
  var showToast = props.showToast || function() {};

  // Change password state
  var ref1 = React.useState(''), currentPw = ref1[0], setCurrentPw = ref1[1];
  var ref2 = React.useState(''), newPw = ref2[0], setNewPw = ref2[1];
  var ref3 = React.useState(false), pwLoading = ref3[0], setPwLoading = ref3[1];

  // Admins state
  var ref4 = React.useState([]), admins = ref4[0], setAdmins = ref4[1];
  var ref5 = React.useState(false), adminsLoading = ref5[0], setAdminsLoading = ref5[1];

  // Add admin form state
  var ref6 = React.useState(''), newEmail = ref6[0], setNewEmail = ref6[1];
  var ref7 = React.useState(''), newName = ref7[0], setNewName = ref7[1];
  var ref8 = React.useState(''), newAdminPw = ref8[0], setNewAdminPw = ref8[1];
  var ref9 = React.useState(false), addLoading = ref9[0], setAddLoading = ref9[1];

  function fetchAdmins() {
    setAdminsLoading(true);
    AdminApi.listAdmins()
      .then(function(data) { setAdmins(Array.isArray(data) ? data : data.admins || []); })
      .catch(function(err) { showToast('Failed to load admins: ' + err.message, 'error'); })
      .finally(function() { setAdminsLoading(false); });
  }

  React.useEffect(function() { fetchAdmins(); }, []);

  function handleChangePassword(e) {
    e.preventDefault();
    if (!currentPw || !newPw) { showToast('Fill in both fields', 'error'); return; }
    setPwLoading(true);
    AdminApi.changePassword(currentPw, newPw)
      .then(function() {
        showToast('Password changed', 'ok');
        setCurrentPw('');
        setNewPw('');
      })
      .catch(function(err) { showToast('Password change failed: ' + err.message, 'error'); })
      .finally(function() { setPwLoading(false); });
  }

  function handleAddAdmin(e) {
    e.preventDefault();
    if (!newEmail || !newName || !newAdminPw) { showToast('Fill in all fields', 'error'); return; }
    setAddLoading(true);
    AdminApi.createAdmin({ email: newEmail, display_name: newName, password: newAdminPw })
      .then(function() {
        showToast('Admin created', 'ok');
        setNewEmail(''); setNewName(''); setNewAdminPw('');
        fetchAdmins();
      })
      .catch(function(err) { showToast('Create admin failed: ' + err.message, 'error'); })
      .finally(function() { setAddLoading(false); });
  }

  var inputStyle = {
    width: '100%',
    padding: '8px 12px',
    border: '1px solid var(--line-soft)',
    borderRadius: '6px',
    background: 'var(--s2)',
    color: 'var(--i1)',
    fontSize: '13px',
    boxSizing: 'border-box',
  };

  return (
    <div className="page-settings">
      <div className="pghd">
        <div>
          <div className="title">Settings</div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginTop: '18px' }}>
        {/* Change password card */}
        <div className="card" style={{ alignSelf: 'start' }}>
          <div className="card-hd"><h3>Change password</h3></div>
          <div className="card-bd" style={{ padding: '18px' }}>
            <form onSubmit={handleChangePassword} style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
              <div>
                <label style={{ fontSize: '12px', color: 'var(--i3)', display: 'block', marginBottom: '5px' }}>Current password</label>
                <input type="password" value={currentPw} onChange={function(e) { setCurrentPw(e.target.value); }}
                  style={inputStyle} placeholder="Current password" />
              </div>
              <div>
                <label style={{ fontSize: '12px', color: 'var(--i3)', display: 'block', marginBottom: '5px' }}>New password</label>
                <input type="password" value={newPw} onChange={function(e) { setNewPw(e.target.value); }}
                  style={inputStyle} placeholder="New password" />
              </div>
              <button type="submit" className="btn primary" disabled={pwLoading} style={{ alignSelf: 'flex-start' }}>
                {pwLoading ? 'Saving…' : 'Change password'}
              </button>
            </form>
          </div>
        </div>

        {/* Admins card */}
        <div className="card" style={{ alignSelf: 'start' }}>
          <div className="card-hd" style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <h3>Admins</h3>
            <button className="btn ghost" style={{ fontSize: '12px', padding: '4px 10px' }} onClick={fetchAdmins} disabled={adminsLoading}>
              {adminsLoading ? '…' : '↻'}
            </button>
          </div>
          <div className="card-bd" style={{ padding: '0' }}>
            {adminsLoading && admins.length === 0 ? (
              <div style={{ padding: '24px', textAlign: 'center', color: 'var(--i3)' }}>Loading…</div>
            ) : admins.length === 0 ? (
              <div style={{ padding: '24px', textAlign: 'center', color: 'var(--i3)' }}>No admins found.</div>
            ) : (
              admins.map(function(a, i) {
                var isMe = admin && (a.email === admin.email);
                return (
                  <div key={a.email || i} style={{
                    display: 'flex',
                    alignItems: 'center',
                    gap: '12px',
                    padding: '10px 16px',
                    borderBottom: '1px solid var(--line-soft)',
                  }}>
                    <div style={{ flex: 1 }}>
                      <div style={{ fontWeight: 600, fontSize: '13px' }}>{a.display_name || a.name || '—'}</div>
                      <div style={{ fontSize: '11px', color: 'var(--i3)' }}>{a.email}</div>
                    </div>
                    {isMe && <span className="pill brand" style={{ fontSize: '11px' }}>you</span>}
                  </div>
                );
              })
            )}
          </div>

          {/* Add admin form */}
          <div style={{ borderTop: '2px solid var(--line-soft)', padding: '16px 18px' }}>
            <div style={{ fontSize: '12px', color: 'var(--i3)', marginBottom: '10px', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.05em' }}>Add admin</div>
            <form onSubmit={handleAddAdmin} style={{ display: 'flex', flexDirection: 'column', gap: '9px' }}>
              <input type="email" value={newEmail} onChange={function(e) { setNewEmail(e.target.value); }}
                style={inputStyle} placeholder="Email" />
              <input type="text" value={newName} onChange={function(e) { setNewName(e.target.value); }}
                style={inputStyle} placeholder="Display name" />
              <input type="password" value={newAdminPw} onChange={function(e) { setNewAdminPw(e.target.value); }}
                style={inputStyle} placeholder="Password" />
              <button type="submit" className="btn primary" disabled={addLoading} style={{ alignSelf: 'flex-start' }}>
                {addLoading ? 'Adding…' : '+ Add admin'}
              </button>
            </form>
          </div>
        </div>
      </div>
    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgProctorPage
// ---------------------------------------------------------------------------
window.OrgProctorPage = function OrgProctorPage(props) {
  var games = props.games || [];
  var showToast = props.showToast || function() {};

  var ref1 = React.useState(props.gameId || ''), selectedGame = ref1[0], setSelectedGame = ref1[1];
  var _ta = React.useState([]), ticketAnswers = _ta[0], setTicketAnswers = _ta[1];
  var _fl = React.useState('all'), statusFilter = _fl[0], setStatusFilter = _fl[1];
  var _tm = React.useState('all'), teamFilter = _tm[0], setTeamFilter = _tm[1];
  var _ex = React.useState(null), expanded = _ex[0], setExpanded = _ex[1];
  var _sc = React.useState({}), editScores = _sc[0], setEditScores = _sc[1];
  var _sv = React.useState({}), saving = _sv[0], setSaving = _sv[1];
  var _ld = React.useState(false), loading = _ld[0], setLoading = _ld[1];

  function refreshAnswers() {
    if (!selectedGame) return;
    AdminApi.getTicketAnswers(selectedGame)
      .then(function(data) { setTicketAnswers(Array.isArray(data) ? data : data.answers || []); })
      .catch(function(err) { showToast('Failed to load answers: ' + (err.message || err), 'error'); });
  }

  React.useEffect(function() {
    if (!selectedGame) { setTicketAnswers([]); return; }
    setLoading(true);
    AdminApi.getTicketAnswers(selectedGame)
      .then(function(data) { setTicketAnswers(Array.isArray(data) ? data : data.answers || []); })
      .catch(function(err) { showToast('Failed to load answers: ' + (err.message || err), 'error'); })
      .finally(function() { setLoading(false); });
  }, [selectedGame]);

  // Auto-refresh every 20s
  React.useEffect(function() {
    if (!selectedGame) return;
    var timer = setInterval(refreshAnswers, 20000);
    return function() { clearInterval(timer); };
  }, [selectedGame]);

  // Derived stats
  var proctorGraded = ticketAnswers.filter(function(a) { return a.proctor_scored === 1; }).length;
  var aiOnly = ticketAnswers.filter(function(a) { return a.ai_available === 1 && a.proctor_scored !== 1; }).length;
  var pending = ticketAnswers.filter(function(a) { return a.ai_available !== 1 && a.proctor_scored !== 1; }).length;

  // Unique teams
  var teamSet = {};
  ticketAnswers.forEach(function(a) { if (a.player_team) teamSet[a.player_team] = true; });
  var uniqueTeams = Object.keys(teamSet).sort();

  // Filtering
  var filtered = ticketAnswers.filter(function(a) {
    if (statusFilter === 'pending' && a.proctor_scored === 1) return false;
    if (statusFilter === 'graded' && a.proctor_scored !== 1) return false;
    if (statusFilter === 'ai-only' && (a.ai_available !== 1 || a.proctor_scored === 1)) return false;
    if (teamFilter !== 'all' && a.player_team !== teamFilter) return false;
    return true;
  });

  return (
    <div className="page-proctor">
      <div className="pghd">
        <div>
          <div className="title">Proctor Queue</div>
        </div>
        {selectedGame && (
          <div className="right">
            <button className="btn ghost" onClick={refreshAnswers} disabled={loading} style={{ fontSize: '12px', padding: '6px 12px' }}>
              {loading ? '…' : '↻'} Refresh
            </button>
          </div>
        )}
      </div>

      {/* Game picker */}
      <div className="card" style={{ marginTop: '18px' }}>
        <div className="card-bd" style={{ padding: '14px 18px', display: 'flex', alignItems: 'center', gap: '12px' }}>
          <label style={{ fontSize: '13px', color: 'var(--i3)', flexShrink: 0 }}>Select game:</label>
          <select value={selectedGame} onChange={function(e) { setSelectedGame(e.target.value); }}
            style={{ flex: 1, maxWidth: '360px', padding: '7px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}>
            <option value="">— pick a game —</option>
            {games.map(function(g) {
              return <option key={g.game_id} value={g.game_id}>{g.name || g.game_id} ({g.game_id})</option>;
            })}
          </select>
        </div>
      </div>

      {/* Empty state — no game */}
      {!selectedGame && (
        <div style={{ padding: '64px', textAlign: 'center', color: 'var(--i3)' }}>
          <div style={{ fontSize: '32px', marginBottom: '12px' }}>🎫</div>
          <div style={{ fontWeight: 600 }}>No game selected</div>
          <div style={{ fontSize: '13px', marginTop: '6px' }}>Select a game above to view ticket answers.</div>
        </div>
      )}

      {/* Loading */}
      {selectedGame && loading && ticketAnswers.length === 0 && (
        <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>Loading ticket answers…</div>
      )}

      {selectedGame && !loading && ticketAnswers.length === 0 && (
        <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>No ticket answers submitted yet.</div>
      )}

      {selectedGame && ticketAnswers.length > 0 && (
        <div style={{ marginTop: '16px' }}>

          {/* Stats bar */}
          <div className="kpi-strip" style={{ display: 'flex', gap: '12px', marginBottom: '16px' }}>
            <div className="kpi">
              <span className="kpi-val">{ticketAnswers.length}</span>
              <span className="kpi-lbl">Total</span>
            </div>
            <div className="kpi">
              <span className="kpi-val" style={{ color: 'var(--ok)' }}>{proctorGraded}</span>
              <span className="kpi-lbl">Proctor graded</span>
            </div>
            <div className="kpi">
              <span className="kpi-val" style={{ color: 'var(--brand)' }}>{aiOnly}</span>
              <span className="kpi-lbl">AI only</span>
            </div>
            <div className="kpi">
              <span className="kpi-val" style={{ color: 'var(--wn)' }}>{pending}</span>
              <span className="kpi-lbl">Pending</span>
            </div>
          </div>

          {/* Filter bar */}
          <div style={{ display: 'flex', gap: '10px', marginBottom: '16px', flexWrap: 'wrap', alignItems: 'center' }}>
            <select value={statusFilter} onChange={function(e) { setStatusFilter(e.target.value); }}
              style={{ padding: '7px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}>
              <option value="all">All status</option>
              <option value="pending">Pending proctor review</option>
              <option value="graded">Proctor graded</option>
              <option value="ai-only">AI graded only</option>
            </select>
            <select value={teamFilter} onChange={function(e) { setTeamFilter(e.target.value); }}
              style={{ padding: '7px 10px', border: '1px solid var(--line-soft)', borderRadius: '6px', background: 'var(--s2)', color: 'var(--i1)', fontSize: '13px' }}>
              <option value="all">All teams</option>
              {uniqueTeams.map(function(team) {
                return <option key={team} value={team}>{team}</option>;
              })}
            </select>
            <span style={{ marginLeft: 'auto', color: 'var(--i3)', fontSize: '12px' }}>
              {filtered.length + ' of ' + ticketAnswers.length + ' answers'}
            </span>
          </div>

          {/* Answer cards */}
          {filtered.length === 0 ? (
            <div style={{ padding: '48px', textAlign: 'center', color: 'var(--i3)' }}>No answers match your filters.</div>
          ) : (
            filtered.map(function(a) {
              var isExpanded = expanded === a.id;
              return (
                <div className="card" key={a.id} style={{ marginBottom: '8px', cursor: 'pointer' }}
                  onClick={function() { setExpanded(isExpanded ? null : a.id); }}>
                  {/* Header row */}
                  <div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '4px', flexWrap: 'wrap' }}>
                    <span style={{ fontWeight: 600 }}>{a.player_name || a.email}</span>
                    {a.player_team && (
                      <span className="badge" style={{ background: 'var(--brand-soft)', color: 'var(--brand)', fontSize: '10px' }}>{a.player_team}</span>
                    )}
                    <span style={{ color: 'var(--i3)', fontSize: '11px', fontFamily: 'var(--f-m)' }}>{'Ticket: ' + a.ticket_id}</span>
                    <span style={{ marginLeft: 'auto' }}>
                      {a.proctor_scored === 1
                        ? <span className="badge" style={{ background: 'var(--ok-soft)', color: 'var(--ok)' }}>{'✓ Proctor: ' + a.proctor_score}</span>
                        : a.ai_available === 1
                          ? <span className="badge" style={{ background: 'var(--brand-soft)', color: 'var(--brand)' }}>{'AI: ' + a.ai_score}</span>
                          : <span className="badge" style={{ background: 'var(--wn-soft)', color: 'var(--wn)' }}>Pending</span>
                      }
                    </span>
                  </div>

                  {/* Answer preview */}
                  <p style={{ color: 'var(--i2)', fontSize: '12px', margin: 0 }}>
                    {isExpanded ? a.answer : (a.answer || '').substring(0, 120) + (a.answer && a.answer.length > 120 ? '…' : '')}
                  </p>

                  {/* Expanded section */}
                  {isExpanded && (
                    <div style={{ marginTop: '12px', paddingTop: '12px', borderTop: '1px solid var(--line-soft)' }}>
                      {/* AI feedback */}
                      {a.ai_feedback && (
                        <div style={{ background: 'var(--s1)', padding: '10px', borderRadius: 'var(--r-s)', marginBottom: '10px', fontSize: '12px' }}>
                          <strong style={{ color: 'var(--brand)' }}>AI Feedback:</strong>
                          <p style={{ margin: '4px 0 0', color: 'var(--i2)' }}>{a.ai_feedback}</p>
                        </div>
                      )}
                      {/* Proctor scoring */}
                      <div style={{ display: 'flex', alignItems: 'center', gap: '10px', flexWrap: 'wrap' }}>
                        <label style={{ fontSize: '12px', color: 'var(--i3)' }}>Proctor score (0-100):</label>
                        <input type="number" min="0" max="100"
                          style={{ width: '70px', padding: '4px 8px', background: 'var(--s2)', border: '1px solid var(--line)', borderRadius: 'var(--r-s)', color: 'var(--i1)', fontSize: '13px' }}
                          value={editScores[a.id] != null ? editScores[a.id] : (a.proctor_scored === 1 ? a.proctor_score : a.ai_score)}
                          onClick={function(e) { e.stopPropagation(); }}
                          onChange={function(e) {
                            var copy = Object.assign({}, editScores);
                            copy[a.id] = parseInt(e.target.value) || 0;
                            setEditScores(copy);
                          }}
                        />
                        <button className="btn primary" disabled={saving[a.id]}
                          onClick={function(e) {
                            e.stopPropagation();
                            var answerId = a.id;
                            var answerEmail = a.email;
                            var answerTicketId = a.ticket_id;
                            var answerAiScore = a.ai_score;
                            var answerProctorScore = a.proctor_score;
                            var answerProctorScored = a.proctor_scored;
                            var score = editScores[answerId] != null ? editScores[answerId] : (answerProctorScored === 1 ? answerProctorScore : answerAiScore);
                            var sv = Object.assign({}, saving); sv[answerId] = true; setSaving(sv);
                            AdminApi.proctorScoreTicket(selectedGame, answerEmail, answerTicketId, score)
                              .then(function() {
                                var sv2 = Object.assign({}, saving); delete sv2[answerId]; setSaving(sv2);
                                var sc2 = Object.assign({}, editScores); delete sc2[answerId]; setEditScores(sc2);
                                refreshAnswers();
                              })
                              .catch(function() {
                                var sv2 = Object.assign({}, saving); delete sv2[answerId]; setSaving(sv2);
                              });
                          }}>
                          {saving[a.id] ? 'Saving…' : '💾 Save score'}
                        </button>
                        {a.proctor_scored === 1 && (
                          <span style={{ fontSize: '11px', color: 'var(--ok)' }}>{'✓ Previously scored: ' + a.proctor_score}</span>
                        )}
                      </div>
                    </div>
                  )}
                </div>
              );
            })
          )}
        </div>
      )}
    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgPlaceholderPage
// ---------------------------------------------------------------------------
window.OrgPlaceholderPage = function OrgPlaceholderPage(props) {
  var pageId = props.pageId || 'unknown';

  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '400px' }}>
      <div className="card" style={{ maxWidth: '400px', width: '100%', textAlign: 'center' }}>
        <div className="card-bd" style={{ padding: '48px 32px' }}>
          <div style={{ fontSize: '36px', marginBottom: '16px' }}>🚧</div>
          <div style={{
            fontFamily: 'var(--f-m)',
            fontSize: '13px',
            color: 'var(--brand)',
            background: 'var(--s2)',
            display: 'inline-block',
            padding: '3px 10px',
            borderRadius: '4px',
            marginBottom: '16px',
          }}>
            {pageId}
          </div>
          <div style={{ fontWeight: 700, fontSize: '18px', marginBottom: '8px' }}>Coming soon</div>
          <div style={{ color: 'var(--i3)', fontSize: '13px', marginBottom: '24px' }}>
            This page is under construction.
          </div>
          <a href="#sessions" style={{ color: 'var(--brand)', fontSize: '13px', textDecoration: 'none' }}>
            ← Back to Sessions
          </a>
        </div>
      </div>
    </div>
  );
};

// ---------------------------------------------------------------------------
// OrgCreateWizard — Event Setup Wizard (scrollable two-column form + sidebar)
// ---------------------------------------------------------------------------

var EVENT_TYPES = [
  { id: 'clinic', tag: 'clinic', name: 'Design Clinic', desc: 'Deep-dive architecture session. Smaller group, heavier labs. For internal Cisco SEs or partner SEs.', size: '40\u201380', length: '\xbd day', cls: '' },
  { id: 'tech-day', tag: 'tech day', name: 'Tech Day', desc: 'Outcome-shaped, multi-speaker, account-tagged. Works for internal SEs, partners or customers. Auto-wires the existing Tech Day build.', size: '80\u2013180', length: '\xbd\u20131d', cls: '', flow: true },
  { id: 'connect', tag: 'conference', name: 'Cisco Connect', desc: 'The annual Cisco Connect conference. Multi-track, main stage, broadcast-scale. 400\u20131\u202f200 attendees.', size: '400+', length: '1\u20132 days', cls: 'conn' },
  { id: 'custom', tag: 'custom', name: 'Custom', nameEm: 'off-book', desc: 'Something else \u2014 SKO, partner summit, bootcamp. Unlocks every field manually.', size: '\u2014', length: '\u2014', cls: '' },
];

var WIZARD_AUDIENCES = [
  { id: 'internal', label: 'Internal SEs' },
  { id: 'partner', label: 'Partner SEs' },
  { id: 'customer', label: 'Customers' },
];

var WIZARD_THEMES = [
  { id: 'gp', key: 'gp', name: 'Grand Prix', nameEm: 'GRAND', nameRest: 'PRIX', sport: 'F1', tagline: '"Lights out. Engines on. Customer outcomes."', meta: 'pole \xb7 podium',
    phases: [
      { base: 'Prep', name: 'Track Walk', em: 'Track', rest: ' Walk', sub: 'warm-up laps \xb7 learn the circuit' },
      { base: 'Knowledge', name: 'Qualifying', em: 'Qualifying', rest: '', sub: 'set a lap time \xb7 earn grid slot' },
      { base: 'Diagnosis', name: 'Telemetry Review', em: 'Telemetry', rest: ' Review', sub: 'read the data \xb7 spot the fault' },
      { base: 'Design', name: 'Pit Wall Strategy', em: 'Pit Wall', rest: ' Strategy', sub: 'call the stops \xb7 pick the compound' },
      { base: 'Defense', name: 'Press Conference', em: 'Press', rest: ' Conference', sub: 'face the media \xb7 defend the call' },
    ]
  },
  { id: 'cup', key: 'cup', name: 'World Cup', nameEm: 'WORLD', nameRest: 'CUP', sport: 'Futebol', tagline: '"Gol. Pase. Resultado. Customer outcomes."', meta: 'grupos \xb7 final',
    phases: [
      { base: 'Prep', name: 'Reconocimiento de Cancha', em: 'Reconocimiento', rest: '', sub: 'de cancha \xb7 scouting report' },
      { base: 'Knowledge', name: 'Fase de Grupos', em: 'Fase de Grupos', rest: '', sub: 'group stage \xb7 points table' },
      { base: 'Diagnosis', name: 'VAR', em: 'VAR', rest: '', sub: 'video review \xb7 find the incident' },
      { base: 'Design', name: 'Pizarra T\xe1ctica', em: 'Pizarra T\xe1ctica', rest: '', sub: 'chalkboard \xb7 draw the plan' },
      { base: 'Defense', name: 'Zona Mixta', em: 'Zona Mixta', rest: '', sub: 'mixed zone \xb7 defend the result' },
    ]
  },
  { id: 'rz', key: 'rz', name: 'Red Zone', nameEm: 'RED', nameRest: 'ZONE', sport: 'NFL', tagline: '"Film. Playbook. Execution. Customer outcomes."', meta: 'combine \xb7 drill',
    phases: [
      { base: 'Prep', name: 'Film Study', em: 'Film Study', rest: '', sub: 'review tape \xb7 scout tendencies' },
      { base: 'Knowledge', name: 'Combine', em: 'Combine', rest: '', sub: 'measurables \xb7 prove fundamentals' },
      { base: 'Diagnosis', name: 'Booth Review', em: 'Booth Review', rest: '', sub: 'replay \xb7 confirm the call' },
      { base: 'Design', name: 'Playbook Design', em: 'Playbook Design', rest: '', sub: 'draw up the play \xb7 read defense' },
      { base: 'Defense', name: 'Two-Minute Drill', em: 'Two-Minute Drill', rest: '', sub: 'stand the drive \xb7 seal the game' },
    ]
  },
  { id: 'it', key: 'it', name: 'Iron Throne', nameEm: 'IRON', nameRest: 'THRONE', sport: 'GoT / HOTD', tagline: '"Ravens. Counsel. The realm endures."', meta: 'council \xb7 court',
    phases: [
      { base: 'Prep', name: 'Raven Briefing', em: 'Raven Briefing', rest: '', sub: "maester\u2019s scroll \xb7 lay of the land" },
      { base: 'Knowledge', name: 'Council Trials', em: 'Council Trials', rest: '', sub: 'prove your claim to the small council' },
      { base: 'Diagnosis', name: 'Raven Reports', em: 'Raven Reports', rest: '', sub: 'scrolls from the field \xb7 read the signs' },
      { base: 'Design', name: 'War Council', em: 'War Council', rest: '', sub: 'map the realm \xb7 plan the march' },
      { base: 'Defense', name: 'Court of the Realm', em: 'Court of the Realm', rest: '', sub: 'stand before the throne \xb7 hold your claim' },
    ]
  },
];

var WIZARD_LANGUAGES = [
  { id: 'en', code: 'EN', name: 'English', sub: 'default \xb7 always available', isDefault: true },
  { id: 'es', code: 'ES', name: 'Espa\xf1ol', sub: 'full translation', isDefault: false },
  { id: 'pt', code: 'PT', name: 'Portugu\xeas \xb7 BR', sub: 'full translation', isDefault: false },
];

var WIZARD_STEPS = [
  { num: '01', label: 'Event type', short: 'type' },
  { num: '02', label: 'Theme & phases', short: 'theme' },
  { num: '03', label: 'Tech modules', short: 'tech' },
  { num: '04', label: 'Language \xb7 date \xb7 venue', short: 'details' },
  { num: '05', label: 'Review & launch', short: 'review' },
];

var WIZARD_FALLBACK_MODULES = [
  { id: 'ise', name: 'ISE', description: 'Identity Services Engine', question_count: 142, ready: true },
  { id: 'firewall', name: 'Firewall', description: 'Cisco Secure Firewall', question_count: 98, ready: true },
  { id: 'sdwan', name: 'SD-WAN', description: 'Software-Defined WAN', question_count: 116, ready: true },
  { id: 'secure-access', name: 'Secure Access', description: 'Cisco Secure Access (SSE)', question_count: 72, ready: true },
];

var THEME_API_MAP = { gp: 'f1', wc: 'world-cup', rz: 'nfl', it: 'realm' };
var THEME_API_MAP_REV = { f1: 'gp', 'world-cup': 'wc', nfl: 'rz', realm: 'it' };

var STEPPER_TTLS = [
  ['Event ', 'type', ''],
  ['Theme & ', 'phases', ''],
  ['', 'Tech', ' modules'],
  ['Language \xb7 date \xb7 ', 'venue', ''],
  ['Review & ', 'launch', ''],
];

window.OrgCreateWizard = function OrgCreateWizard(props) {
  var admin      = props.admin;
  var showToast = props.showToast || function() {};
  var onForceRefresh = props.onForceRefresh || function() {};
  var onComplete = props.onComplete || function() {};
  var onCancel   = props.onCancel   || function() {};
  var editEvent  = props.editEvent  || null;

  /* ── state ── */
  var _et = React.useState('tech-day');    var eventType = _et[0]; var setEventType = _et[1];
  var _th = React.useState('gp');          var themeId   = _th[0]; var setThemeId   = _th[1];
  var _au = React.useState('customer');    var audience  = _au[0]; var setAudience  = _au[1];
  var _mo = React.useState([]);            var modules   = _mo[0]; var setModules   = _mo[1];
  var _la = React.useState('en');          var language  = _la[0]; var setLanguage  = _la[1];
  var _nm = React.useState('');            var evtName   = _nm[0]; var setEvtName   = _nm[1];
  var _lo = React.useState('');            var loc       = _lo[0]; var setLoc       = _lo[1];
  var _sd = React.useState('');            var startDate = _sd[0]; var setStartDate = _sd[1];
  var _st = React.useState('');            var startTime = _st[0]; var setStartTime = _st[1];
  var _en = React.useState('');            var endTime   = _en[0]; var setEndTime   = _en[1];
  var _fm = React.useState('In person');   var format    = _fm[0]; var setFormat    = _fm[1];
  var _fs = React.useState(1);             var focusStep = _fs[0]; var setFocusStep = _fs[1];
  var _bu = React.useState(false);         var busy      = _bu[0]; var setBusy      = _bu[1];
  var _am = React.useState(WIZARD_FALLBACK_MODULES);
  var availModules    = _am[0];
  var setAvailModules = _am[1];

  /* ── fetch modules on mount ── */
  React.useEffect(function() {
    AdminApi.listModules()
      .then(function(data) {
        var list = Array.isArray(data) ? data : data.modules || [];
        if (list.length > 0) {
          // Normalize: API returns module_id, wizard expects id
          setAvailModules(list.map(function(m) {
            return Object.assign({}, m, {
              id: m.id || m.module_id,
              question_count: m.question_count || 0,
              ready: m.status === 'active'
            });
          }));
        }
      })
      .catch(function() { /* keep fallback */ });
  }, []);

  /* ── pre-populate when editing ── */
  React.useEffect(function() {
    if (!editEvent) return;
    var cfg = {};
    try { cfg = typeof editEvent.config === 'string' ? JSON.parse(editEvent.config) : (editEvent.config || {}); } catch(e) { cfg = {}; }
    if (editEvent.name) setEvtName(editEvent.name);
    if (editEvent.location) setLoc(editEvent.location);
    if (editEvent.start_date) setStartDate(editEvent.start_date);
    if (editEvent.theme_id) setThemeId(THEME_API_MAP_REV[editEvent.theme_id] || editEvent.theme_id);
    if (editEvent.audience_mode) setAudience(editEvent.audience_mode);
    if (cfg.modules && cfg.modules.length) setModules(cfg.modules);
    if (cfg.language) setLanguage(cfg.language);
  }, []);

  /* ── helpers ── */
  function toggleModule(id) {
    setModules(function(prev) {
      var idx = prev.indexOf(id);
      if (idx >= 0) { var n = prev.slice(); n.splice(idx, 1); return n; }
      return prev.concat([id]);
    });
  }

  var selTheme = WIZARD_THEMES.filter(function(t) { return t.id === themeId; })[0] || WIZARD_THEMES[0];
  var selType  = EVENT_TYPES.filter(function(t) { return t.id === eventType; })[0] || EVENT_TYPES[1];
  var selLang  = WIZARD_LANGUAGES.filter(function(l) { return l.id === language; })[0] || WIZARD_LANGUAGES[0];
  var readyMods  = availModules.filter(function(m) { return m.ready !== false; });
  var lockedMods = availModules.filter(function(m) { return m.ready === false; });
  var selectedMods = availModules.filter(function(m) { return modules.indexOf(m.id) >= 0; });
  var totalQ = selectedMods.reduce(function(s, m) { return s + (m.question_count || 0); }, 0);

  /* ── step completion ── */
  var step1Done = !!eventType;
  var step2Done = !!themeId;
  var step3Done = eventType === 'tech-day' ? true : modules.length > 0;
  var step4Done = evtName.trim().length > 0;
  var dones = [step1Done, step2Done, step3Done, step4Done, false];
  var doneCount = (step1Done ? 1 : 0) + (step2Done ? 1 : 0) + (step3Done ? 1 : 0) + (step4Done ? 1 : 0);

  /* ── audience helpers ── */
  var audMatch = WIZARD_AUDIENCES.filter(function(a) { return a.id === audience; })[0];
  var audLabel = selType.name + ' \xb7 ' + (audMatch ? audMatch.label : audience);

  /* ── submit ── */
  function handleSubmit(andStart) {
    if (busy) return;
    if (!evtName.trim()) { showToast('Event name is required', 'error'); return; }
    if (modules.length === 0 && eventType !== 'tech-day') { showToast('Select at least one module', 'error'); return; }
    setBusy(true);
    var payload = {
      name: evtName.trim(),
      description: selType.name + ' \xb7 ' + selTheme.name + ' theme',
      location: loc.trim() || 'Online',
      start_date: startDate || null,
      end_date: startDate || null,
      theme_id: THEME_API_MAP[themeId] || themeId,
      audience_mode: audience,
      modules: modules,
      module_configs: {},
      language: language,
      event_type: eventType,
    };
    var apiCall = editEvent
      ? AdminApi.updateEvent(editEvent.event_id, payload)
      : AdminApi.createEvent(payload);
    apiCall
      .then(function(eventData) {
        if (andStart && eventType !== 'tech-day' && eventData && (eventData.id || eventData.event_id)) {
          var eid = eventData.id || eventData.event_id;
          return AdminApi.startEvent(eid).then(function(r) { return r || eventData; });
        }
        return eventData;
      })
      .then(function(result) { setBusy(false); onComplete(result, { eventType: eventType, andStart: andStart }); })
      .catch(function(err) {
        setBusy(false);
        var action = editEvent ? 'Update' : 'Creation';
        showToast(action + ' failed: ' + (err && err.message ? err.message : 'Unknown error'), 'error');
      });
  }

  /* ── stepper label helper ── */
  function stpLbl(i) {
    var done = dones[i] && (i + 1) !== focusStep;
    var now = (i + 1) === focusStep;
    if (done) return '\u25c6 step ' + WIZARD_STEPS[i].num + ' \xb7 done';
    if (now)  return '\u25c6 step ' + WIZARD_STEPS[i].num + ' \xb7 now';
    return 'step ' + WIZARD_STEPS[i].num;
  }

  /* ── form section label helper ── */
  function secLbl(i) {
    var done = dones[i] && (i + 1) !== focusStep;
    var now = (i + 1) === focusStep;
    if (done) return 'step ' + WIZARD_STEPS[i].num + ' \xb7 \u2713 pre-filled';
    if (now)  return '\u25c6 step ' + WIZARD_STEPS[i].num + ' \xb7 active';
    return '\u25c6 step ' + WIZARD_STEPS[i].num;
  }

  var PHASE_BASES = ['Prep', 'Knowledge', 'Diagnosis', 'Design', 'Defense'];

  /* ── render ── */
  return (
    <div className="wiz">

      {/* ── CHROME BAR ── */}
      <div className="chrome">
        <span>{'\u25c6'} {editEvent ? 'Edit event' : 'New event'}</span>
        <span>Draft {'\xb7'} <b>{evtName || 'Untitled event'}</b></span>
        <span>Editing {'\xb7'} <em>now</em></span>
        <span className="sp"></span>
        <span>Owner {'\xb7'} {(admin && (admin.name || admin.email)) || 'Organizer'}</span>
        <button className="btn pr" onClick={onCancel}>Exit</button>
      </div>

      {/* ── HORIZONTAL STEPPER ── */}
      <div className="stepper">
        {WIZARD_STEPS.map(function(s, i) {
          var done = dones[i] && (i + 1) !== focusStep;
          var now  = (i + 1) === focusStep;
          var cls  = 'stp' + (done ? ' done' : '') + (now ? ' now' : '');
          return (
            <div key={i} className={cls} onClick={function() { setFocusStep(i + 1); }} style={{cursor:'pointer'}}>
              <div className="nn">{done ? '\u2713' : s.num}</div>
              <div>
                <div className="lbl">{stpLbl(i)}</div>
                <span className="ttl">{STEPPER_TTLS[i][0]}<em>{STEPPER_TTLS[i][1]}</em>{STEPPER_TTLS[i][2]}</span>
              </div>
            </div>
          );
        })}
      </div>

      {/* ── BODY: form + sidebar ── */}
      <div className="body">

        {/* ── LEFT: all 4 steps visible ── */}
        <div className="form">

          {/* STEP 1 — Event type */}
          <div className="step" onClick={function() { setFocusStep(1); }}>
            <div className="sn">
              <span className="k">{secLbl(0)}</span>
              <span className="t">What <em>kind</em> of event is this?</span>
            </div>
            <div className="sd">Audience surface {'\xb7'} content gates {'\xb7'} NDA posture {'\xb7'} invite copy — all cascade from this</div>

            <div className="etype">
              {EVENT_TYPES.map(function(et) {
                var sel = eventType === et.id;
                var cls = 'et' + (sel ? ' on' : '') + (et.cls ? ' ' + et.cls : '');
                return (
                  <div key={et.id} className={cls} onClick={function(e) { e.stopPropagation(); setEventType(et.id); }}>
                    <div className="top">
                      <span className="tag">{'\u25c6'} {et.tag}</span>
                      <div className="ck">{sel ? '\u2713' : ''}</div>
                    </div>
                    {et.flow && <span className="flow">{'\u25c6'} uses tech day flow</span>}
                    <h4>{et.name}{et.nameEm ? <span> {'\xb7'} <em>{et.nameEm}</em></span> : null}</h4>
                    <p>{et.desc}</p>
                    <div className="footer">
                      <div>Size<b>{et.size}</b></div>
                      <div>Length<b>{et.length}</b></div>
                    </div>
                  </div>
                );
              })}
            </div>

            <div className="sub">
              <span>{'\u25c6'} Audience</span>
              <b>{audLabel}</b>
              <div className="sgr">
                {WIZARD_AUDIENCES.map(function(a) {
                  return (
                    <span key={a.id} className={'sgc' + (audience === a.id ? ' on' : '')} onClick={function(e) { e.stopPropagation(); setAudience(a.id); }}>
                      {a.label}
                    </span>
                  );
                })}
              </div>
            </div>
          </div>

          {/* STEP 2 — Theme & phases */}
          <div className="step" onClick={function() { setFocusStep(2); }}>
            <div className="sn">
              <span className="k">{secLbl(1)}</span>
              <span className="t">Pick a <em>theme</em> — it renames the five phases</span>
            </div>
            <div className="sd">Same game structure {'\xb7'} different skin + vocabulary. Five phases always: prep {'\u2192'} knowledge {'\u2192'} diagnosis {'\u2192'} design {'\u2192'} defense</div>

            <div className="thm">
              {WIZARD_THEMES.map(function(th) {
                var sel = themeId === th.id;
                return (
                  <div key={th.id} className={'thc' + (sel ? ' on' : '')} data-th={th.id} onClick={function(e) { e.stopPropagation(); setThemeId(th.id); }}>
                    <div className="hero">
                      <span className="k">{sel ? '\u25c6 on' : 'switch'}</span>
                      <span className="n"><em>{th.nameEm}</em> {th.nameRest}</span>
                    </div>
                    <div className="meta"><b>{th.sport}</b><span>{th.meta}</span></div>
                  </div>
                );
              })}
            </div>

            <div className="phmap">
              <div className="ph">
                <span>{'\u25c6'} base phase</span>
                {WIZARD_THEMES.map(function(th) {
                  var sel = themeId === th.id;
                  return (
                    <span key={th.id}>
                      {sel ? <b>{th.name}</b> : th.name}
                      {sel ? <span style={{color:'var(--i3)',fontFamily:'var(--f-m)',fontSize:'9px',letterSpacing:'.1em'}}> {'\xb7'} on</span> : null}
                    </span>
                  );
                })}
              </div>
              {PHASE_BASES.map(function(base, pi) {
                return (
                  <div key={pi} className="pr">
                    <span className="k">{'0' + (pi + 1) + ' \xb7 ' + base}</span>
                    {WIZARD_THEMES.map(function(th) {
                      var p = th.phases[pi];
                      var sel = themeId === th.id;
                      return (
                        <span key={th.id} className={'c' + (sel ? ' on' : '')}>
                          {sel ? <span><em>{p.em}</em>{p.rest}</span> : p.name}
                          <span className="tr">{p.sub}</span>
                        </span>
                      );
                    })}
                  </div>
                );
              })}
            </div>
          </div>

          {/* STEP 3 — Tech modules */}
          <div className="step" onClick={function() { setFocusStep(3); }}>
            <div className="sn">
              <span className="k">{secLbl(2)}</span>
              <span className="t"><em>Technology</em> modules</span>
            </div>
            {eventType === 'tech-day' ? (
              <div className="sd" style={{color:'var(--brand)',fontWeight:500}}>Optional for Tech Day — speakers will upload content in the next step. Skip or pre-select modules below.</div>
            ) : (
              <div className="sd">Only modules with a live question bank are selectable {'\xb7'} counts are live {'\xb7'} coming-soon greyed out</div>
            )}

            <div className="techbox">
              <div className="thead">
                <span>{'\u25c6'} <b>ready modules</b> {'\xb7'} have question bank</span>
                <em>{readyMods.length + ' live \xb7 ' + selectedMods.length + ' selected \xb7 ' + totalQ + ' questions total'}</em>
              </div>
              <div className="tlist">
                {readyMods.map(function(m) {
                  var sel = modules.indexOf(m.id) >= 0;
                  return (
                    <div key={m.id} className={'tl' + (sel ? ' on' : '')} onClick={function(e) { e.stopPropagation(); toggleModule(m.id); }}>
                      <div className="ck"></div>
                      <span className="tn">{m.name}</span>
                      <span className="qc">{(m.question_count || 0) + ' q'}</span>
                    </div>
                  );
                })}
              </div>
              {lockedMods.length > 0 && (
                <React.Fragment>
                  <div className="thead" style={{marginTop:'16px',paddingBottom:'8px'}}>
                    <span>{'\u25c6'} coming soon</span><em>not yet selectable</em>
                  </div>
                  <div className="tlist">
                    {lockedMods.map(function(m) {
                      return (
                        <div key={m.id} className="tl locked">
                          <div className="ck"></div>
                          <span className="tn">{m.name}</span>
                          <span className="qc">q pending</span>
                        </div>
                      );
                    })}
                  </div>
                </React.Fragment>
              )}
              <div className="tfoot">
                <span>{'\u25c6'} pool size derived from selection</span>
                <em>{selectedMods.length + ' modules \xb7 ' + totalQ + ' question pool'}</em>
              </div>
            </div>
          </div>

          {/* STEP 4 — Language + date + venue */}
          <div className="step" onClick={function() { setFocusStep(4); }}>
            <div className="sn">
              <span className="k">{secLbl(3)}</span>
              <span className="t">Language {'\xb7'} <em>date</em> {'\xb7'} venue</span>
            </div>
            <div className="sd">All player-facing copy, speaker-brief docs, pre-work packs and invites render in the chosen language</div>

            <div className="fld" style={{marginBottom:'14px'}}>
              <label>Game language<em>applies to UI, questions, speaker docs</em></label>
              <div className="langrow">
                {WIZARD_LANGUAGES.map(function(lg) {
                  var sel = language === lg.id;
                  return (
                    <div key={lg.id} className={'lg' + (sel ? ' on' : '')} data-l={lg.id} onClick={function(e) { e.stopPropagation(); setLanguage(lg.id); }}>
                      <div className="flag"><div className="t">{lg.code}</div></div>
                      <div className="t2">
                        <b>{lg.name}</b>
                        <em>{lg.sub}</em>
                      </div>
                      {lg.isDefault && <span className="df">Default</span>}
                    </div>
                  );
                })}
              </div>
            </div>

            <div className="fldgrid" style={{marginBottom:'12px'}}>
              <div className="fld">
                <label>Event name<em>required</em></label>
                <input type="text" placeholder="e.g. Bengaluru Tech Day '26" value={evtName} onChange={function(e) { setEvtName(e.target.value); }} autoFocus />
              </div>
              <div className="fld">
                <label>Date</label>
                <input type="date" value={startDate} onChange={function(e) { setStartDate(e.target.value); }} onClick={openPicker} />
              </div>
            </div>

            <div className="fldgrid" style={{marginBottom:'12px'}}>
              <div className="fld">
                <label>Start time</label>
                <input type="time" value={startTime} onChange={function(e) { setStartTime(e.target.value); }} onClick={openPicker} />
              </div>
              <div className="fld">
                <label>End time</label>
                <input type="time" value={endTime} onChange={function(e) { setEndTime(e.target.value); }} onClick={openPicker} />
              </div>
            </div>

            <div className="fldgrid">
              <div className="fld">
                <label>Venue</label>
                <input type="text" placeholder="City, venue name" value={loc} onChange={function(e) { setLoc(e.target.value); }} />
              </div>
              <div className="fld">
                <label>Format</label>
                <select value={format} onChange={function(e) { setFormat(e.target.value); }}>
                  <option>In person</option>
                  <option>Virtual</option>
                  <option>Hybrid</option>
                </select>
              </div>
            </div>
          </div>

        </div>

        {/* ── RIGHT: live preview sidebar ── */}
        <aside className="wside">

          <h3>Live preview <em>{'\xb7'} invite card</em></h3>
          <div className="invite">
            <div className="band">
              <div className="c">{'\u2b22'} Cisco {selType.name}{loc ? ' \xb7 ' + loc : ''}</div>
              <h4>THE <em>{selTheme.nameEm}</em><br />{selTheme.nameRest}</h4>
              <div className="tg">{selTheme.tagline}</div>
              <span className="tag">{'\u25c6'} {selType.tag} {'\xb7'} {(audMatch ? audMatch.label.toLowerCase() : audience)} {'\xb7'} {selLang.code}</span>
            </div>
            <div className="facts">
              <div>Date<b>{startDate || '\u2014'}</b><small>{format}</small></div>
              <div>Venue<b>{loc || 'TBD'}</b></div>
              <div>Language<b>{selLang.name}</b></div>
              <div>Modules<b>{selectedMods.length > 0 ? selectedMods.length + ' selected' : '\u2014'}</b></div>
            </div>
            <div className="phases">
              <div className="mh">{'\u25c6'} the five phases {'\xb7'} {selTheme.name}</div>
              <ol>
                {selTheme.phases.map(function(p, i) {
                  return (
                    <li key={i}>
                      <span className="n">{'0' + (i + 1)}</span>
                      <span className="l"><em>{p.em}</em>{p.rest}</span>
                      <span className="o">{p.base.toLowerCase()}</span>
                    </li>
                  );
                })}
              </ol>
            </div>
            {selectedMods.length > 0 && (
              <div className="mods">
                <div className="mh">{'\u25c6'} on the circuit {'\xb7'} technology</div>
                <div className="mr">
                  {selectedMods.map(function(m) {
                    return <span key={m.id}>{m.name}</span>;
                  })}
                </div>
              </div>
            )}
          </div>

          <h3 style={{marginTop:'6px'}}>Auto-checks <em>{'\xb7'} dry run</em></h3>
          <div className="dryrun">
            <div className="drh"><span>{'\u25c6'} validation</span><em>{doneCount >= 4 ? 'all green' : doneCount + ' of 4'}</em></div>
            <div className="r"><span className="k">Type</span><span className="v">{selType.name} {'\xb7'} <em>{audMatch ? audMatch.label.toLowerCase() : audience}</em></span><span className="s">{step1Done ? '\u2713 set' : '\u2014'}</span></div>
            <div className="r"><span className="k">Theme</span><span className="v">{selTheme.name} {'\xb7'} <em>{selTheme.sport}</em></span><span className="s">{step2Done ? '\u2713 5 phases' : '\u2014'}</span></div>
            <div className="r"><span className="k">Language</span><span className="v">{selLang.name}</span><span className="s">{'\u2713'}</span></div>
            <div className="r"><span className="k">Tech pool</span><span className="v">{selectedMods.length + ' modules \xb7 '}<em>{totalQ + ' q'}</em></span><span className="s">{step3Done ? '\u2713 ready' : '\u2014'}</span></div>
            <div className="r"><span className="k">Event name</span><span className="v">{evtName || '\u2014 not set'}</span><span className="s">{step4Done ? '\u2713' : '\u2014'}</span></div>
          </div>

        </aside>

      </div>

      {/* ── FOOTER BAR ── */}
      <div className="foot">
        <span>{'\u25c6'} current draft</span>
        <span>{doneCount + ' of 5 steps complete \xb7 '}{doneCount >= 4 ? <em>ready to launch</em> : <em>{(5 - doneCount) + ' remaining'}</em>}</span>
        <span className="sp"></span>
        <button className="btn" onClick={onCancel} disabled={busy}>{'\u25c2'} Back</button>
        <button className="btn" onClick={function() { handleSubmit(false); }} disabled={busy}>{busy ? 'Saving\u2026' : 'Save draft'}</button>
        <button className="btn pr" onClick={function() { handleSubmit(true); }} disabled={busy}>{busy ? 'Launching\u2026' : 'Review & launch \u25b8'}</button>
      </div>

    </div>
  );
};

// Legacy components (OrgPageHeader, OrgKPIStrip, OrgCalendar, OrgSessionCard,
// OrgIngestCard, OrgAssignCard, OrgQueueCard) removed — they referenced deleted
// window.ORG_* mock globals. The new prop-driven pages replace them.
