// Standings, calendar, bracket, stats, live scoreboard, dashboard, teams, settings.
const { useState: useS, useEffect: useE, useMemo: useM, useRef: useR } = React;

// ============================================================
// Shield system
// ============================================================
const SHIELDS = [
  { id: 'classic',  label: 'Clásico',   vb: '0 0 40 44', path: 'M20,1 L39,8 L39,28 Q39,42 20,44 Q1,42 1,28 L1,8 Z',               cx:20, cy:24 },
  { id: 'badge',    label: 'Badge',     vb: '0 0 40 44', path: 'M7,1 Q1,1 1,7 L1,30 Q1,42 20,44 Q39,42 39,30 L39,7 Q39,1 33,1 Z',  cx:20, cy:23 },
  { id: 'modern',   label: 'Moderno',   vb: '0 0 40 44', path: 'M20,1 L40,9 L37,36 L20,44 L3,36 L0,9 Z',                           cx:20, cy:24 },
  { id: 'angular',  label: 'Angular',   vb: '0 0 40 44', path: 'M1,2 L39,2 L39,28 L20,44 L1,28 Z',                                 cx:20, cy:23 },
  { id: 'octagon',  label: 'Octágono',  vb: '0 0 40 44', path: 'M12,0 L28,0 L40,12 L40,32 L28,44 L12,44 L0,32 L0,12 Z',           cx:20, cy:22 },
  { id: 'circle',   label: 'Circular',  vb: '0 0 40 40', path: 'M20,1 C30.5,1 39,9.5 39,20 C39,30.5 30.5,39 20,39 C9.5,39 1,30.5 1,20 C1,9.5 9.5,1 20,1 Z', cx:20, cy:20 },
  { id: 'diamond',  label: 'Diamante',  vb: '0 0 40 44', path: 'M20,0 L40,22 L20,44 L0,22 Z',                                     cx:20, cy:22 },
  { id: 'curved',   label: 'Curvo',     vb: '0 0 40 44', path: 'M20,1 Q36,4 38,14 Q40,28 20,44 Q0,28 2,14 Q4,4 20,1 Z',           cx:20, cy:24 },
];

const PRESET_COLORS = [
  '#E63946','#FF6B35','#FFBE0B','#06D6A0','#118AB2',
  '#5E60CE','#9D4EDD','#FF2D8A','#F77F00','#2EC4B6',
  '#3A86FF','#FB5607','#38B000','#7209B7','#F72585',
  '#4CC9F0','#AACC00','#EF476F','#FFFFFF','#1A1A2E',
];

function ShieldSvg({ shieldId = 'classic', color = '#3A86FF', size = 40, text = '' }) {
  const s = SHIELDS.find(x => x.id === shieldId) || SHIELDS[0];
  const [vW, vH] = s.vb.split(' ').slice(2).map(Number);
  const h = Math.round(size * vH / vW);
  const fs = Math.round(size * 0.37);
  return (
    <svg viewBox={s.vb} width={size} height={h} xmlns="http://www.w3.org/2000/svg" style={{ display:'block', flexShrink:0, overflow:'visible' }}>
      <defs>
        <linearGradient id="sg-g" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%"   stopColor="rgba(255,255,255,0.22)"/>
          <stop offset="100%" stopColor="rgba(0,0,0,0.32)"/>
        </linearGradient>
      </defs>
      <path d={s.path} fill={color}/>
      <path d={s.path} fill="url(#sg-g)"/>
      <path d={s.path} fill="none" stroke="rgba(255,255,255,0.20)" strokeWidth="1.5"/>
      <path d={s.path} fill="none" stroke="rgba(0,0,0,0.22)" strokeWidth="0.5"/>
      {text && (
        <text x={s.cx} y={s.cy} textAnchor="middle" dominantBaseline="central"
          fontFamily="'Anton','Bebas Neue',Impact,sans-serif"
          fontSize={fs} fill="white" letterSpacing="0.02em"
          stroke="rgba(0,0,0,0.35)" strokeWidth="0.8" paintOrder="stroke">
          {text}
        </text>
      )}
    </svg>
  );
}

function ShieldPickerPanel({ team, dispatch, onClose }) {
  const ref = useR(null);
  useE(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, [onClose]);
  const upd = (patch) => dispatch({ type: 'UPDATE_TEAM', id: team.id, patch });
  const cur = team.shield || 'classic';
  const col = team.color || '#3A86FF';
  return (
    <div ref={ref} style={{
      position:'absolute', top:'calc(100% + 8px)', left:0, zIndex:300,
      background:'var(--surface-2)', border:'1px solid var(--border-2)',
      borderRadius:'var(--r)', padding:'14px 14px 12px', width:264,
      boxShadow:'var(--shadow-md)', animation:'fadeUp .15s ease',
    }}>
      <div style={{ fontSize:9.5, textTransform:'uppercase', letterSpacing:'.20em', color:'var(--muted)', fontFamily:'var(--ui-cond)', fontWeight:700, marginBottom:8 }}>
        Forma del escudo
      </div>
      <div style={{ display:'grid', gridTemplateColumns:'repeat(4,1fr)', gap:6, marginBottom:14 }}>
        {SHIELDS.map(s => (
          <button key={s.id} onClick={() => upd({ shield: s.id })} title={s.label} style={{
            background: cur === s.id ? 'var(--surface-4)' : 'var(--surface-3)',
            border: cur === s.id ? '2px solid var(--gold)' : '1px solid var(--border)',
            borderRadius:'var(--r-sm)', padding:'7px 4px 5px', cursor:'pointer',
            display:'flex', flexDirection:'column', alignItems:'center', gap:4,
            transition:'border .12s, background .12s',
            boxShadow: cur === s.id ? '0 0 8px var(--gold-dim)' : 'none',
          }}>
            <ShieldSvg shieldId={s.id} color={col} size={28} text=""/>
            <span style={{ fontSize:8.5, color: cur===s.id ? 'var(--gold)' : 'var(--muted)', fontFamily:'var(--ui-cond)', letterSpacing:'.08em', fontWeight: cur===s.id ? 700 : 400 }}>
              {s.label.toUpperCase()}
            </span>
          </button>
        ))}
      </div>
      <div style={{ fontSize:9.5, textTransform:'uppercase', letterSpacing:'.20em', color:'var(--muted)', fontFamily:'var(--ui-cond)', fontWeight:700, marginBottom:8 }}>
        Color
      </div>
      <div style={{ display:'grid', gridTemplateColumns:'repeat(5,1fr)', gap:5, marginBottom:10 }}>
        {PRESET_COLORS.map(c => (
          <button key={c} onClick={() => upd({ color: c })} title={c} style={{
            width:'100%', aspectRatio:'1', background:c, cursor:'pointer',
            border: col===c ? '2px solid var(--gold)' : '1px solid rgba(255,255,255,0.12)',
            borderRadius:'var(--r-xs)',
            boxShadow: col===c ? '0 0 0 1px rgba(0,0,0,0.3), 0 0 6px var(--gold-dim)' : '0 1px 3px rgba(0,0,0,0.3)',
            transform: col===c ? 'scale(1.12)' : 'scale(1)',
            transition:'transform .12s, border .12s',
          }}/>
        ))}
      </div>
      <div style={{ display:'flex', alignItems:'center', gap:8, paddingTop:8, borderTop:'1px solid var(--border)' }}>
        <input type="color" value={col} onChange={(e) => upd({ color: e.target.value })}
          style={{ width:36, height:30, border:'none', padding:0, background:'transparent', cursor:'pointer', borderRadius:4 }}
          title="Color personalizado"/>
        <span style={{ fontSize:11, color:'var(--muted)', fontFamily:'monospace', letterSpacing:'.05em' }}>{col}</span>
        <span style={{ marginLeft:'auto', fontSize:10, color:'var(--muted)' }}>Libre</span>
      </div>
    </div>
  );
}

// ============================================================
// Common helpers
// ============================================================
function TeamBadge({ team, size = 36 }) {
  if (!team) return null;
  return (
    <ShieldSvg
      shieldId={team.shield || 'classic'}
      color={team.color || '#3A86FF'}
      size={size}
      text={team.short || abbrev(team.name)}
    />
  );
}

function TeamPickerInline({ team, onClick }) {
  if (!team) return <span className="muted" style={{ fontStyle: "italic" }}>—</span>;
  return (
    <div className="row gap-8 center" onClick={onClick} style={{ cursor: onClick ? "pointer" : "default" }}>
      <ShieldSvg shieldId={team.shield || 'classic'} color={team.color || '#3A86FF'} size={20} text={team.short || abbrev(team.name)}/>
      <span style={{ fontWeight: 500 }}>{team.name}</span>
    </div>
  );
}

function computeStandings(teams, matches, meta) {
  return teams.map((tm) => {
    const played = matches.filter(
      (m) => m.played && (m.homeId === tm.id || m.awayId === tm.id)
    );
    let pj = 0, pg = 0, pe = 0, pp = 0, gf = 0, gc = 0;
    played.forEach((m) => {
      pj++;
      const isHome = m.homeId === tm.id;
      const my = isHome ? +m.homeScore : +m.awayScore;
      const op = isHome ? +m.awayScore : +m.homeScore;
      gf += my; gc += op;
      if (my > op) pg++;
      else if (my === op) pe++;
      else pp++;
    });
    const pts = pg * meta.pointsWin + pe * meta.pointsDraw + pp * meta.pointsLoss;
    return { team: tm, pj, pg, pe, pp, gf, gc, dg: gf - gc, pts };
  }).sort((a, b) => b.pts - a.pts || b.dg - a.dg || b.gf - a.gf || a.team.name.localeCompare(b.team.name));
}

// ============================================================
// Dashboard
// ============================================================
function ResultRow({ match, state }) {
  const home = state.teams.find(tm => tm.id === match.homeId);
  const away = state.teams.find(tm => tm.id === match.awayId);
  const hs = +match.homeScore, as = +match.awayScore;
  const homeWin = hs > as, awayWin = as > hs;
  const venue = (state.venues || []).find(v => v.id === match.venueId);
  const penWinner = match.penaltyWinnerId ? state.teams.find(t => t.id === match.penaltyWinnerId) : null;
  const meta = [match.date, match.time, venue?.name].filter(Boolean).join(' · ');
  const sortedScorers = [...(match.scorers || [])].sort((a, b) => (+a.minute || 999) - (+b.minute || 999));
  const homeScorers = sortedScorers.filter(s => s.teamId === match.homeId);
  const awayScorers = sortedScorers.filter(s => s.teamId === match.awayId);

  return (
    <div style={{ borderBottom: '1px solid var(--border)', transition: 'background .1s' }}
      onMouseEnter={e => e.currentTarget.style.background = 'var(--surface-3)'}
      onMouseLeave={e => e.currentTarget.style.background = ''}
    >
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 80px 1fr', gap: 10, alignItems: 'center', padding: '10px 16px' }}>
        {/* Home */}
        <div style={{ display:'flex', alignItems:'center', gap:8, justifyContent:'flex-end', minWidth:0 }}>
          {homeWin && <span style={{ color:'var(--green)', fontSize:11, fontWeight:800, flexShrink:0 }}>✓</span>}
          <span style={{ fontWeight: homeWin ? 700 : 400, opacity: awayWin ? 0.48 : 1, fontSize:13, textAlign:'right', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
            {home?.name || '?'}
          </span>
          <TeamBadge team={home || { shield:'classic', color:'var(--muted)', short:'?' }} size={26}/>
        </div>

        {/* Score */}
        <div style={{ display:'flex', flexDirection:'column', alignItems:'center', gap:1 }}>
          <div style={{ fontFamily:'var(--display)', fontSize:22, letterSpacing:'.04em', display:'flex', alignItems:'center', gap:5, lineHeight:1 }}>
            <span style={{ color: homeWin ? 'var(--green)' : awayWin ? 'var(--faint)' : 'var(--text)' }}>{match.homeScore}</span>
            <span style={{ color:'var(--muted)', fontSize:12 }}>–</span>
            <span style={{ color: awayWin ? 'var(--green)' : homeWin ? 'var(--faint)' : 'var(--text)' }}>{match.awayScore}</span>
          </div>
          {penWinner && <span style={{ fontSize:9, color:'var(--amber)', fontWeight:700, letterSpacing:'.08em', textTransform:'uppercase' }}>Pen</span>}
          {meta && <span style={{ fontSize:9, color:'var(--muted)', fontFamily:'var(--ui-cond)', letterSpacing:'.06em', textAlign:'center', marginTop:1 }}>{meta}</span>}
        </div>

        {/* Away */}
        <div style={{ display:'flex', alignItems:'center', gap:8, minWidth:0 }}>
          <TeamBadge team={away || { shield:'classic', color:'var(--muted)', short:'?' }} size={26}/>
          <span style={{ fontWeight: awayWin ? 700 : 400, opacity: homeWin ? 0.48 : 1, fontSize:13, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
            {away?.name || '?'}
          </span>
          {awayWin && <span style={{ color:'var(--green)', fontSize:11, fontWeight:800, flexShrink:0 }}>✓</span>}
        </div>
      </div>

      {/* Scorers */}
      {sortedScorers.length > 0 && (
        <div className="result-scorers">
          <div className="result-scorer-home">
            {homeScorers.map((s, i) => (
              <span key={i} className="result-scorer-name">
                {s.minute ? <span className="result-scorer-min">{s.minute}'</span> : null}
                <span>⚽</span>
                <span>{s.name || '?'}</span>
                {s.assistName && <span className="result-scorer-assist">(↗ {s.assistName})</span>}
              </span>
            ))}
          </div>
          <div/>
          <div className="result-scorer-away">
            {awayScorers.map((s, i) => (
              <span key={i} className="result-scorer-name">
                {s.minute ? <span className="result-scorer-min">{s.minute}'</span> : null}
                <span>⚽</span>
                <span>{s.name || '?'}</span>
                {s.assistName && <span className="result-scorer-assist">(↗ {s.assistName})</span>}
              </span>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

function Dashboard({ state, t, goto }) {
  const [histFilter, setHistFilter] = useS('all');

  const players = state.teams.reduce((s, tm) => s + tm.players.length, 0);
  const allMatches = state.matches;
  const playedMatches = allMatches.filter(m => m.played);
  const goals = playedMatches.reduce((s, m) => s + (+m.homeScore || 0) + (+m.awayScore || 0), 0);
  const upcoming = allMatches.filter(m => !m.played).slice(0, 4);

  // Ordered knockout stages for grouping
  const KO_ORDER = ['Dieciseisavos','Octavos de Final','Cuartos de Final','Semifinales','Final'];

  // Build stage order map
  const stageOrder = s => s === 'groups' ? -1 : (KO_ORDER.indexOf(s) >= 0 ? KO_ORDER.indexOf(s) : 99);

  // Group played matches by stage
  const byStage = {};
  playedMatches.forEach(m => {
    const k = m.stage || 'groups';
    byStage[k] = byStage[k] || [];
    byStage[k].push(m);
  });

  const stageKeys = Object.keys(byStage).sort((a, b) => stageOrder(a) - stageOrder(b));

  // Filter tabs: all + each stage
  const filterTabs = [
    { id: 'all', label: 'Todos', count: playedMatches.length },
    ...stageKeys.map(k => ({
      id: k,
      label: k === 'groups' ? 'Grupos' : k,
      count: byStage[k].length,
    })),
  ];

  const filteredByStage = histFilter === 'all'
    ? byStage
    : { [histFilter]: byStage[histFilter] || [] };

  const filteredStageKeys = histFilter === 'all' ? stageKeys : [histFilter].filter(k => byStage[k]);

  // Top scorers
  const scorerCounts = {};
  allMatches.forEach(m => {
    (m.scorers || []).forEach(s => {
      const key = s.playerId || (s.teamId + ":" + (s.name || ""));
      scorerCounts[key] = (scorerCounts[key] || 0) + 1;
    });
  });
  const topScorers = Object.entries(scorerCounts)
    .map(([key, count]) => {
      let player = null, team = null;
      state.teams.forEach(tm => tm.players.forEach(p => {
        if (p.id === key) { player = p; team = tm; }
      }));
      if (!player) {
        const [tid, name] = key.split(":");
        team = state.teams.find(tm => tm.id === tid);
        player = { name: name || "—" };
      }
      return { player, team, count };
    })
    .sort((a, b) => b.count - a.count)
    .slice(0, 5);

  // Detect champion
  const champion = useM(() => {
    const finalRound = state.bracket.rounds.find(r => r.label === 'Final');
    if (finalRound?.matches.length) {
      const m = finalRound.matches[0];
      if (m.played && m.homeScore != null && m.awayScore != null) {
        const h = +m.homeScore, a = +m.awayScore;
        const wId = h > a ? m.homeId : a > h ? m.awayId : (m.penaltyWinnerId || null);
        if (wId) return state.teams.find(tm => tm.id === wId) || null;
      }
    }
    const finalCal = state.matches.filter(m => m.stage === 'Final' && m.played);
    for (const m of finalCal) {
      const h = +m.homeScore, a = +m.awayScore;
      const wId = h > a ? m.homeId : a > h ? m.awayId : (m.penaltyWinnerId || null);
      if (wId) return state.teams.find(tm => tm.id === wId) || null;
    }
    return null;
  }, [state.bracket.rounds, state.matches, state.teams]);

  return (
    <div data-screen-label="01 Dashboard">
      {/* Champion banner */}
      {champion && (
        <div style={{
          background: 'linear-gradient(135deg, #6b3f00 0%, #c98b00 28%, #ffd700 50%, #c98b00 72%, #6b3f00 100%)',
          borderRadius: 'var(--r)', padding: '20px 28px', marginBottom: 20,
          display: 'flex', alignItems: 'center', gap: 20,
          boxShadow: '0 0 50px rgba(255,200,0,.25), 0 4px 20px rgba(0,0,0,.5)',
          position: 'relative', overflow: 'hidden',
        }}>
          <div style={{ position:'absolute', inset:0, background:'repeating-linear-gradient(45deg,transparent,transparent 8px,rgba(255,255,255,.015) 8px,rgba(255,255,255,.015) 9px)', pointerEvents:'none' }}/>
          <div style={{ fontSize:48, lineHeight:1, filter:'drop-shadow(0 3px 8px rgba(0,0,0,.5))', position:'relative' }}>🏆</div>
          <div style={{ position:'relative' }}>
            <div style={{ fontSize:9, fontWeight:800, letterSpacing:'.3em', textTransform:'uppercase', color:'rgba(0,0,0,.52)', marginBottom:6 }}>Campeón del Torneo</div>
            <div style={{ display:'flex', alignItems:'center', gap:14 }}>
              <ShieldSvg shieldId={champion.shield||'classic'} color={champion.color||'#3A86FF'} size={48} text={champion.short||abbrev(champion.name)}/>
              <span style={{ fontFamily:'var(--display)', fontSize:30, letterSpacing:'.04em', color:'#1a0e00' }}>{champion.name.toUpperCase()}</span>
            </div>
          </div>
        </div>
      )}

      <div className="page-head">
        <div>
          <h1 className="page-title">{state.meta.name}</h1>
          <div className="page-sub">{t("dashboard_sub")}</div>
        </div>
        <div className="page-actions">
          <button className="btn-sorteo" onClick={() => goto("draw")}>
            <span className="btn-sorteo-shine"/>
            <svg width="14" height="14" viewBox="0 0 20 20" fill="none"><path d="M10 1L12.39 7.26L19 7.64L14.18 11.97L15.88 18.36L10 14.9L4.12 18.36L5.82 11.97L1 7.64L7.61 7.26L10 1Z" fill="currentColor" stroke="rgba(0,0,0,0.15)" strokeWidth="0.5" strokeLinejoin="round"/></svg>
            <span>{t("run_draw").toUpperCase()}</span>
            <svg width="14" height="14" viewBox="0 0 20 20" fill="none" style={{opacity:0.6}}><path d="M10 1L12.39 7.26L19 7.64L14.18 11.97L15.88 18.36L10 14.9L4.12 18.36L5.82 11.97L1 7.64L7.61 7.26L10 1Z" fill="currentColor" stroke="rgba(0,0,0,0.15)" strokeWidth="0.5" strokeLinejoin="round"/></svg>
          </button>
        </div>
      </div>

      <div className="stat-grid">
        <div className="stat accent">
          <div className="stat-label">{t("teams_count")}</div>
          <div className="stat-value">{state.teams.length}</div>
          <div className="stat-foot">{t("groups_count")}: {state.groups.length}</div>
        </div>
        <div className="stat">
          <div className="stat-label">{t("players_count")}</div>
          <div className="stat-value">{players}</div>
        </div>
        <div className="stat">
          <div className="stat-label">{t("matches_played")}</div>
          <div className="stat-value">{playedMatches.length}<span className="muted" style={{ fontSize: 22 }}>/{allMatches.length}</span></div>
        </div>
        <div className="stat">
          <div className="stat-label">{t("goals_total")}</div>
          <div className="stat-value">{goals}</div>
        </div>
      </div>

      {/* Próximos + goleadores */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 16 }}>
        <div className="card">
          <div className="card-h">
            <h3 className="card-title">{t("next_matches")}</h3>
            <button className="btn btn-ghost" onClick={() => goto("calendar")}>→</button>
          </div>
          {upcoming.length === 0 ? (
            <div className="muted" style={{ fontSize: 12 }}>{t("no_matches_yet")}</div>
          ) : (
            <div className="match-list">
              {upcoming.map(m => <MiniMatch key={m.id} match={m} state={state}/>)}
            </div>
          )}
        </div>
        <div className="card">
          <div className="card-h">
            <h3 className="card-title">{t("top_scorers")}</h3>
            <button className="btn btn-ghost" onClick={() => goto("stats")}>→</button>
          </div>
          {topScorers.length === 0 ? (
            <div className="muted" style={{ fontSize: 12 }}>—</div>
          ) : (
            <table className="table">
              <thead><tr><th>#</th><th>{t("player_name")}</th><th>{t("team")}</th><th className="num">{t("goals")}</th></tr></thead>
              <tbody>
                {topScorers.map((s, i) => (
                  <tr key={i}>
                    <td className="pos">{i + 1}</td>
                    <td>{s.player?.name || "—"}</td>
                    <td>{s.team ? <TeamPickerInline team={s.team}/> : "—"}</td>
                    <td className="num"><b>{s.count}</b></td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>
      </div>

      {/* Historial de resultados */}
      <div className="card">
        <div className="card-h">
          <h3 className="card-title">📋 Historial de Resultados</h3>
          <div style={{ display:'flex', alignItems:'center', gap:10 }}>
            <span className="muted" style={{ fontSize:11, fontFamily:'var(--ui-cond)', letterSpacing:'.04em' }}>
              {playedMatches.length} jugados
            </span>
            <button className="btn btn-ghost" onClick={() => goto("calendar")}>→</button>
          </div>
        </div>

        {playedMatches.length === 0 ? (
          <div className="muted" style={{ fontSize: 12, padding: '8px 0' }}>No hay resultados aún.</div>
        ) : (
          <>
            {/* Filter tabs */}
            <div style={{ display:'flex', gap:6, flexWrap:'wrap', paddingBottom:12, marginBottom:4, borderBottom:'1px solid var(--border)' }}>
              {filterTabs.map(tab => (
                <button
                  key={tab.id}
                  onClick={() => setHistFilter(tab.id)}
                  className={"btn btn-sm" + (histFilter === tab.id ? " btn-primary" : " btn-ghost")}
                  style={{ fontSize:11 }}
                >
                  {tab.label}
                  <span style={{ marginLeft:5, fontFamily:'var(--ui-cond)', opacity: histFilter === tab.id ? 1 : 0.6, fontSize:10 }}>{tab.count}</span>
                </button>
              ))}
            </div>

            {/* Results grouped by stage */}
            {filteredStageKeys.map(stageKey => {
              const matches = filteredByStage[stageKey] || [];
              const isKO = stageKey !== 'groups';
              const isFinal = stageKey === 'Final';
              const stageLabel = stageKey === 'groups' ? 'Fase de Grupos' : stageKey;
              const icon = isFinal ? '🏆' : isKO ? '⚡' : '⚽';

              // Group group-stage matches by group
              const groupedMatches = {};
              if (!isKO) {
                matches.forEach(m => {
                  const g = state.groups.find(gg => gg.id === m.groupId);
                  const k = g ? 'Grupo ' + g.name : 'Grupo';
                  groupedMatches[k] = groupedMatches[k] || [];
                  groupedMatches[k].push(m);
                });
              }

              return (
                <div key={stageKey} style={{ marginTop: 14 }}>
                  <div style={{
                    display:'flex', alignItems:'center', gap:8,
                    padding:'6px 16px', marginBottom:0,
                    background:'var(--surface-3)', borderRadius:'var(--r-sm) var(--r-sm) 0 0',
                    borderBottom:'1px solid var(--border)',
                  }}>
                    <span style={{ fontSize:13 }}>{icon}</span>
                    <span style={{ fontFamily:'var(--ui-cond)', fontSize:11, fontWeight:800, letterSpacing:'.18em', textTransform:'uppercase', color: isFinal ? 'var(--gold)' : isKO ? 'var(--accent)' : 'var(--muted)' }}>
                      {stageLabel}
                    </span>
                    <span style={{ marginLeft:'auto', fontFamily:'var(--ui-cond)', fontSize:10, color:'var(--muted)', letterSpacing:'.04em' }}>
                      {matches.length} {matches.length === 1 ? 'partido' : 'partidos'}
                    </span>
                  </div>

                  <div style={{ background:'var(--surface-2)', borderRadius:'0 0 var(--r-sm) var(--r-sm)', overflow:'hidden', border:'1px solid var(--border)', borderTop:'none' }}>
                    {!isKO ? (
                      Object.entries(groupedMatches).map(([grpName, grpMatches]) => (
                        <React.Fragment key={grpName}>
                          {Object.keys(groupedMatches).length > 1 && (
                            <div style={{ padding:'4px 16px', fontSize:9.5, fontWeight:700, letterSpacing:'.15em', textTransform:'uppercase', color:'var(--muted)', background:'var(--surface-3)', borderBottom:'1px solid var(--border)' }}>
                              {grpName}
                            </div>
                          )}
                          {grpMatches.map(m => <ResultRow key={m.id} match={m} state={state}/>)}
                        </React.Fragment>
                      ))
                    ) : (
                      matches.map(m => <ResultRow key={m.id} match={m} state={state}/>)
                    )}
                  </div>
                </div>
              );
            })}
          </>
        )}
      </div>
    </div>
  );
}

function MiniMatch({ match, state }) {
  const home = state.teams.find((tm) => tm.id === match.homeId);
  const away = state.teams.find((tm) => tm.id === match.awayId);
  const venue = state.venues?.find((v) => v.id === match.venueId);
  const meta = [match.date, match.time, venue?.name, match.court].filter(Boolean).join(" · ");
  return (
    <div className="match-card" style={{ padding: "10px 12px" }}>
      <div className="match-main" style={{ gridTemplateColumns: "1fr 80px 1fr" }}>
        <div className="match-team home">
          <span style={{ fontWeight: 600, fontSize: 13 }}>{home?.name || "?"}</span>
          {home && <TeamBadge team={home} size={26} />}
        </div>
        <div className="match-score" style={{ fontSize: 18 }}>
          {match.played ? (
            <><span>{match.homeScore}</span><span className="vs">·</span><span>{match.awayScore}</span></>
          ) : <span className="vs">VS</span>}
        </div>
        <div className="match-team away">
          {away && <TeamBadge team={away} size={26} />}
          <span style={{ fontWeight: 600, fontSize: 13 }}>{away?.name || "?"}</span>
        </div>
      </div>
      {meta && <div className="match-meta" style={{ fontSize: 10, paddingTop: 4, borderTop: "1px solid var(--border)" }}>{meta}</div>}
    </div>
  );
}

// ============================================================
// Teams
// ============================================================
function TeamsView({ state, dispatch, t }) {
  return (
    <div data-screen-label="02 Teams">
      <div className="page-head">
        <div>
          <h1 className="page-title">{t("teams_title")}</h1>
          <div className="page-sub">{t("teams_sub")}</div>
        </div>
        <div className="page-actions">
          <button className="btn btn-primary" onClick={() => dispatch({ type: "ADD_TEAM" })}>
            + {t("add_team")}
          </button>
        </div>
      </div>

      {state.teams.length === 0 ? (
        <div className="empty">
          <h3>{t("no_teams_yet")}</h3>
          <button className="btn btn-primary btn-lg" onClick={() => dispatch({ type: "ADD_TEAM" })}>
            + {t("add_team")}
          </button>
        </div>
      ) : (
        <div className="team-grid">
          {state.teams.map((tm) => (
            <TeamCard key={tm.id} team={tm} state={state} dispatch={dispatch} t={t} />
          ))}
        </div>
      )}
    </div>
  );
}

function ConfirmBtn({ label, confirmLabel, className = "btn", onConfirm, disabled = false, style = {} }) {
  const [armed, setArmed] = useS(false);
  useE(() => {
    if (!armed) return;
    const id = setTimeout(() => setArmed(false), 2500);
    return () => clearTimeout(id);
  }, [armed]);
  return (
    <button
      className={className + (armed ? " btn-danger" : "")}
      disabled={disabled}
      onClick={() => {
        if (armed) { onConfirm(); setArmed(false); }
        else setArmed(true);
      }}
      style={armed ? { background: "var(--hot)", color: "white", borderColor: "var(--hot)", ...style } : style}
    >
      {armed ? ("✓ " + (confirmLabel || "Confirmar")) : label}
    </button>
  );
}

function ConfirmX({ onConfirm, title = "Eliminar", style = {} }) {
  const [armed, setArmed] = useS(false);
  useE(() => {
    if (!armed) return;
    const id = setTimeout(() => setArmed(false), 2500);
    return () => clearTimeout(id);
  }, [armed]);
  return (
    <button
      className={"btn btn-icon " + (armed ? "btn-danger" : "btn-ghost")}
      onClick={(e) => {
        e.stopPropagation();
        if (armed) { onConfirm(); setArmed(false); }
        else setArmed(true);
      }}
      title={armed ? "Click otra vez para confirmar" : title}
      style={armed ? { background: "var(--hot)", color: "white", borderColor: "var(--hot)", ...style } : style}
    >{armed ? "✓" : "×"}</button>
  );
}

function TeamCard({ team, state, dispatch, t }) {
  const group = state.groups.find((g) => g.id === team.groupId);
  const [pickerOpen, setPickerOpen] = useS(false);
  return (
    <div className="team-card">
      <div className="team-head">
        <div style={{ position:'relative', flexShrink:0 }}>
          <button onClick={() => setPickerOpen(o => !o)}
            style={{ background:'none', border:'none', padding:0, cursor:'pointer', display:'block', borderRadius:'var(--r-sm)', transition:'filter .15s' }}
            title="Cambiar escudo">
            <ShieldSvg shieldId={team.shield||'classic'} color={team.color||'#3A86FF'} size={44} text={team.short||abbrev(team.name)}/>
          </button>
          {pickerOpen && <ShieldPickerPanel team={team} dispatch={dispatch} onClose={() => setPickerOpen(false)}/>}
        </div>
        <input
          className="input editable"
          value={team.name}
          onChange={(e) => dispatch({ type: "UPDATE_TEAM", id: team.id, patch: { name: e.target.value, short: abbrev(e.target.value) } })}
          style={{
            fontFamily: "var(--display)",
            fontSize: 18,
            letterSpacing: ".03em",
            textTransform: "uppercase",
            padding: "4px 8px",
          }}
        />
        <ConfirmX
          title={t("delete_team_confirm")}
          onConfirm={() => dispatch({ type: "DELETE_TEAM", id: team.id })}
        />
      </div>
      <div className="row gap-8" style={{ fontSize: 11 }}>
        <span className="tag">{team.short}</span>
        {group && <span className="tag accent">GRUPO {group.name}</span>}
        <input
          className="input editable"
          placeholder={t("team_coach") + " (" + t("optional") + ")"}
          value={team.coach || ""}
          onChange={(e) => dispatch({ type: "UPDATE_TEAM", id: team.id, patch: { coach: e.target.value } })}
          style={{ flex: 1, fontSize: 11 }}
        />
      </div>
      <div className="divider" style={{ margin: "8px 0" }}></div>
      <div style={{ fontSize: 10, letterSpacing: ".15em", color: "var(--muted)", fontWeight: 700, textTransform: "uppercase" }}>
        {t("players_count")} ({team.players.length})
      </div>
      <div className="player-list">
        {team.players.length === 0 ? (
          <div className="muted" style={{ fontSize: 11, padding: 6, fontStyle: "italic" }}>
            {t("no_players")}
          </div>
        ) : (
          team.players.map((p) => (
            <div className="player-row" key={p.id}>
              <input
                className="player-num input editable"
                value={p.number || ""}
                onChange={(e) => dispatch({
                  type: "UPDATE_PLAYER", teamId: team.id, playerId: p.id,
                  patch: { number: e.target.value },
                })}
                style={{ width: 28, height: 24, padding: 0, textAlign: "center" }}
              />
              <input
                className="input editable player-name"
                value={p.name}
                placeholder={t("player_name")}
                onChange={(e) => dispatch({
                  type: "UPDATE_PLAYER", teamId: team.id, playerId: p.id,
                  patch: { name: e.target.value },
                })}
              />
              <input
                className="input editable"
                value={p.position || ""}
                placeholder="POS"
                onChange={(e) => dispatch({
                  type: "UPDATE_PLAYER", teamId: team.id, playerId: p.id,
                  patch: { position: e.target.value },
                })}
                style={{ width: 50, fontSize: 10, textTransform: "uppercase" }}
              />
              <ConfirmX
                title={t("delete_player_confirm")}
                onConfirm={() => dispatch({ type: "DELETE_PLAYER", teamId: team.id, playerId: p.id })}
              />
            </div>
          ))
        )}
      </div>
      <button
        className="btn"
        onClick={() => dispatch({ type: "ADD_PLAYER", teamId: team.id })}
        style={{ alignSelf: "flex-start" }}
      >+ {t("add_player")}</button>
    </div>
  );
}

// ============================================================
// Calendar / Matches — Full rewrite
// ============================================================
const KNOCKOUT_STAGES = ['Dieciseisavos', 'Octavos de Final', 'Cuartos de Final', 'Semifinales', 'Final'];
const KNOCKOUT_ORDER = { 'Dieciseisavos': 0, 'Octavos de Final': 1, 'Cuartos de Final': 2, 'Semifinales': 3, 'Final': 4 };

function ChampionBanner({ team }) {
  return (
    <div style={{
      background: 'linear-gradient(135deg, #6b3f00 0%, #c98b00 28%, #ffd700 50%, #c98b00 72%, #6b3f00 100%)',
      borderRadius: 'var(--r)', padding: '24px 32px', marginBottom: 24,
      display: 'flex', alignItems: 'center', gap: 24,
      boxShadow: '0 0 60px rgba(255,200,0,.28), 0 6px 24px rgba(0,0,0,.55)',
      position: 'relative', overflow: 'hidden',
    }}>
      <div style={{ position:'absolute', inset:0, background:'repeating-linear-gradient(45deg,transparent,transparent 8px,rgba(255,255,255,.02) 8px,rgba(255,255,255,.02) 9px)', pointerEvents:'none' }}/>
      <div style={{ fontSize: 56, lineHeight: 1, filter: 'drop-shadow(0 4px 10px rgba(0,0,0,.55))', position:'relative' }}>🏆</div>
      <div style={{ position:'relative' }}>
        <div style={{ fontSize: 9.5, fontWeight: 800, letterSpacing: '.32em', textTransform: 'uppercase', color: 'rgba(0,0,0,.52)', fontFamily: 'var(--ui-cond)', marginBottom: 8 }}>
          Campeón del Torneo
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
          <ShieldSvg shieldId={team.shield || 'classic'} color={team.color || '#3A86FF'} size={56} text={team.short || abbrev(team.name)}/>
          <span style={{ fontFamily: 'var(--display)', fontSize: 36, letterSpacing: '.04em', color: '#1a0e00', textShadow: '0 1px 0 rgba(255,255,255,.45)' }}>
            {team.name.toUpperCase()}
          </span>
        </div>
      </div>
    </div>
  );
}

function MatchMeta({ match, state, upd, t }) {
  const venue = (state.venues || []).find(v => v.id === match.venueId);
  const metaParts = [match.date, match.time, venue?.name, match.court].filter(Boolean);
  return (
    <div className="match-details">
      <div className="match-detail-field">
        <label className="match-detail-label">{t("date")}</label>
        <input className="input" type="date" value={match.date || ""} onChange={(e) => upd({ date: e.target.value })}/>
      </div>
      <div className="match-detail-field">
        <label className="match-detail-label">{t("time")}</label>
        <input className="input" type="time" value={match.time || ""} onChange={(e) => upd({ time: e.target.value })}/>
      </div>
      <div className="match-detail-field">
        <label className="match-detail-label">{t("venue")}</label>
        <select className="select" value={match.venueId || ""} onChange={(e) => upd({ venueId: e.target.value || null })}>
          <option value="">— {t("venue")} —</option>
          {(state.venues || []).map(v => <option key={v.id} value={v.id}>{v.name}</option>)}
        </select>
      </div>
      <div className="match-detail-field">
        <label className="match-detail-label">{t("court")}</label>
        <input className="input" type="text" value={match.court || ""} onChange={(e) => upd({ court: e.target.value })} placeholder={t("court")} style={{ width: 80 }}/>
      </div>
    </div>
  );
}

function GoalEventsPanel({ match, state, dispatch }) {
  const [open, setOpen] = useS(false);
  const [fTeam, setFTeam] = useS('');
  const [fPlayer, setFPlayer] = useS('');
  const [fManual, setFManual] = useS('');
  const [fMin, setFMin] = useS('');
  const [fAssist, setFAssist] = useS('');
  const [fAssistManual, setFAssistManual] = useS('');

  useE(() => { if (open && !fTeam) setFTeam(match.homeId || ''); }, [open]);
  useE(() => { setFPlayer(''); setFAssist(''); }, [fTeam]);

  if (!match.played) return null;

  const scorers = match.scorers || [];
  const homeTeam = state.teams.find(t => t.id === match.homeId);
  const awayTeam = state.teams.find(t => t.id === match.awayId);
  const selTeam = state.teams.find(t => t.id === fTeam);
  const teamPlayers = selTeam?.players || [];
  const selPlayer = fPlayer && fPlayer !== '__manual__' ? teamPlayers.find(p => p.id === fPlayer) : null;
  const sorted = [...scorers].map((s, i) => ({ ...s, _idx: i })).sort((a, b) => (+a.minute || 999) - (+b.minute || 999));

  function addGoal() {
    const name = selPlayer?.name || fManual.trim() || '?';
    const assistPl = fAssist && fAssist !== '__manual__' ? teamPlayers.find(p => p.id === fAssist) : null;
    const assistName = assistPl?.name || (fAssist === '__manual__' ? fAssistManual.trim() : '') || '';
    dispatch({ type: 'ADD_SCORER', matchId: match.id, scorer: {
      id: uid(), teamId: fTeam,
      playerId: selPlayer?.id || null,
      name, minute: fMin ? +fMin : '',
      assistPlayerId: assistPl?.id || null, assistName,
    }});
    setFPlayer(''); setFManual(''); setFMin(''); setFAssist(''); setFAssistManual('');
  }

  const canAdd = fTeam && (selPlayer || fManual.trim());

  return (
    <div className="gep">
      <div className="gep-header">
        <span className="gep-title">
          ⚽ Goles
          {scorers.length > 0 && <span className="badge accent">{scorers.length}</span>}
        </span>
        <button className="btn btn-sm btn-ghost" onClick={() => setOpen(o => !o)} style={{ fontSize:11, padding:'3px 9px' }}>
          {open ? '✕ Cerrar' : '+ Agregar gol'}
        </button>
      </div>

      {sorted.length > 0 && (
        <div className="gep-list">
          {sorted.map(s => {
            const team = state.teams.find(t => t.id === s.teamId);
            return (
              <div key={s._idx} className="gep-goal">
                <span className="gep-min">{s.minute ? s.minute + "'" : '–'}</span>
                <span className="gep-dot" style={{ background: team?.color || 'var(--muted)' }}/>
                <div className="gep-names">
                  <span className="gep-name">{s.name || '?'}</span>
                  {s.assistName && <span className="gep-assist">↗ {s.assistName}</span>}
                </div>
                <span className="gep-team-short">{team?.short || ''}</span>
                <button className="gep-remove" onClick={() => dispatch({ type: 'REMOVE_SCORER', matchId: match.id, index: s._idx })}>×</button>
              </div>
            );
          })}
        </div>
      )}

      {open && (
        <div className="gep-form">
          {/* Team */}
          <div className="gep-form-row">
            <span className="gep-label">Equipo</span>
            <div style={{ display:'flex', gap:5, flex:1 }}>
              <button className={"btn btn-sm " + (fTeam === match.homeId ? "btn-primary" : "btn-ghost")}
                onClick={() => setFTeam(match.homeId || '')} style={{ flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis' }}>
                {homeTeam?.short || homeTeam?.name || 'Local'}
              </button>
              <button className={"btn btn-sm " + (fTeam === match.awayId ? "btn-primary" : "btn-ghost")}
                onClick={() => setFTeam(match.awayId || '')} style={{ flex:1, minWidth:0, overflow:'hidden', textOverflow:'ellipsis' }}>
                {awayTeam?.short || awayTeam?.name || 'Visit.'}
              </button>
            </div>
          </div>

          {/* Player + Minute */}
          <div className="gep-form-row">
            <span className="gep-label">Goleador</span>
            <div style={{ display:'flex', gap:5, flex:1 }}>
              {teamPlayers.length > 0 ? (
                <select className="select" value={fPlayer} onChange={e => { setFPlayer(e.target.value); setFManual(''); }} style={{ flex:1 }}>
                  <option value="">— Jugador —</option>
                  {teamPlayers.map(p => <option key={p.id} value={p.id}>#{p.number} {p.name}</option>)}
                  <option value="__manual__">✎ Manual</option>
                </select>
              ) : (
                <input className="input" value={fManual} onChange={e => setFManual(e.target.value)} placeholder="Nombre del goleador" style={{ flex:1 }}/>
              )}
              <input className="input" type="number" min="1" max="120" value={fMin} onChange={e => setFMin(e.target.value)} placeholder="Min" style={{ width:58, flexShrink:0 }}/>
            </div>
          </div>
          {fPlayer === '__manual__' && (
            <div className="gep-form-row">
              <span className="gep-label"/>
              <input className="input" value={fManual} onChange={e => setFManual(e.target.value)} placeholder="Nombre del goleador" style={{ flex:1 }}/>
            </div>
          )}

          {/* Assist */}
          <div className="gep-form-row">
            <span className="gep-label">Asistencia</span>
            <div style={{ flex:1 }}>
              {teamPlayers.length > 0 ? (
                <select className="select" value={fAssist} onChange={e => { setFAssist(e.target.value); setFAssistManual(''); }}>
                  <option value="">— Sin asistencia —</option>
                  {teamPlayers.filter(p => p.id !== fPlayer).map(p => <option key={p.id} value={p.id}>#{p.number} {p.name}</option>)}
                  <option value="__manual__">✎ Manual</option>
                </select>
              ) : (
                <input className="input" value={fAssistManual} onChange={e => setFAssistManual(e.target.value)} placeholder="Asistente (opcional)"/>
              )}
              {fAssist === '__manual__' && (
                <input className="input" value={fAssistManual} onChange={e => setFAssistManual(e.target.value)} placeholder="Nombre del asistente" style={{ marginTop:4 }}/>
              )}
            </div>
          </div>

          <div style={{ display:'flex', justifyContent:'flex-end', gap:6 }}>
            <button className="btn btn-sm btn-ghost" onClick={() => setOpen(false)}>Cancelar</button>
            <button className="btn btn-sm btn-primary" disabled={!canAdd} onClick={addGoal}>⚽ Agregar gol</button>
          </div>
        </div>
      )}
    </div>
  );
}

function GroupMatchCard({ match, state, dispatch, t }) {
  const home = state.teams.find(tm => tm.id === match.homeId);
  const away = state.teams.find(tm => tm.id === match.awayId);
  function upd(patch) { dispatch({ type: "UPDATE_MATCH", id: match.id, patch }); }
  function setHome(v) {
    const n = v === "" ? null : Math.max(0, +v);
    const u = { homeScore: n };
    if (n !== null && match.awayScore !== null) u.played = true;
    dispatch({ type: "UPDATE_MATCH", id: match.id, patch: u });
  }
  function setAway(v) {
    const n = v === "" ? null : Math.max(0, +v);
    const u = { awayScore: n };
    if (n !== null && match.homeScore !== null) u.played = true;
    dispatch({ type: "UPDATE_MATCH", id: match.id, patch: u });
  }

  const homeScore = match.homeScore ?? "";
  const awayScore = match.awayScore ?? "";
  const homeWin = match.played && homeScore !== "" && awayScore !== "" && +homeScore > +awayScore;
  const awayWin = match.played && homeScore !== "" && awayScore !== "" && +awayScore > +homeScore;

  return (
    <div className={"match-card" + (match.played ? " mc-played" : "")}>
      <div className="match-main">
        <div className="match-team home">
          <select className="select" value={match.homeId || ""} onChange={(e) => upd({ homeId: e.target.value || null })} style={{ minWidth: 130, fontWeight: 600 }}>
            <option value="">— {t("home")} —</option>
            {state.teams.map(tm => <option key={tm.id} value={tm.id}>{tm.name}</option>)}
          </select>
          {home && <TeamBadge team={home} size={34}/>}
        </div>
        <div className="match-score">
          <input type="number" value={homeScore} onChange={(e) => setHome(e.target.value)} placeholder="–"
            style={match.played ? { color: homeWin ? 'var(--green)' : awayWin ? 'var(--muted)' : 'inherit' } : {}}/>
          <span className="vs">{match.played ? '–' : 'VS'}</span>
          <input type="number" value={awayScore} onChange={(e) => setAway(e.target.value)} placeholder="–"
            style={match.played ? { color: awayWin ? 'var(--green)' : homeWin ? 'var(--muted)' : 'inherit' } : {}}/>
        </div>
        <div className="match-team away">
          {away && <TeamBadge team={away} size={34}/>}
          <select className="select" value={match.awayId || ""} onChange={(e) => upd({ awayId: e.target.value || null })} style={{ minWidth: 130, fontWeight: 600 }}>
            <option value="">— {t("away")} —</option>
            {state.teams.map(tm => <option key={tm.id} value={tm.id}>{tm.name}</option>)}
          </select>
        </div>
        <div className="row gap-8">
          {match.played && <span className="tag accent" style={{ fontSize:10 }}>FT</span>}
          <ConfirmX title="Eliminar partido" onConfirm={() => dispatch({ type: "DELETE_MATCH", id: match.id })}/>
        </div>
      </div>
      <MatchMeta match={match} state={state} upd={upd} t={t}/>
      <GoalEventsPanel match={match} state={state} dispatch={dispatch}/>
    </div>
  );
}

function KnockoutMatchCard({ match, state, dispatch, t, isFinal }) {
  const [hs, setHs] = React.useState(match.homeScore != null ? String(match.homeScore) : "");
  const [as, setAs] = React.useState(match.awayScore != null ? String(match.awayScore) : "");
  const [editing, setEditing] = React.useState(false);

  React.useEffect(() => {
    if (!editing) {
      setHs(match.homeScore != null ? String(match.homeScore) : "");
      setAs(match.awayScore != null ? String(match.awayScore) : "");
    }
  }, [match.homeScore, match.awayScore, editing]);

  const home = state.teams.find(tm => tm.id === match.homeId);
  const away = state.teams.find(tm => tm.id === match.awayId);
  const hsNum = hs !== "" ? +hs : null;
  const asNum = as !== "" ? +as : null;
  const bothEntered = hsNum !== null && asNum !== null && !isNaN(hsNum) && !isNaN(asNum);
  const localWinner = bothEntered ? (hsNum > asNum ? match.homeId : asNum > hsNum ? match.awayId : null) : null;
  const showConfirm = bothEntered && match.homeId && match.awayId && (!match.played || editing);
  const locked = match.played && !editing;

  const winnerId = React.useMemo(() => {
    if (!match.played || match.homeScore == null || match.awayScore == null) return null;
    const h = +match.homeScore, a = +match.awayScore;
    return h > a ? match.homeId : a > h ? match.awayId : (match.penaltyWinnerId || null);
  }, [match.played, match.homeScore, match.awayScore, match.homeId, match.awayId, match.penaltyWinnerId]);

  const isDraw = match.played && match.homeScore != null && match.awayScore != null && +match.homeScore === +match.awayScore;
  const homeWin = match.played && winnerId === match.homeId;
  const awayWin = match.played && winnerId === match.awayId;
  const winner = winnerId ? state.teams.find(tm => tm.id === winnerId) : null;

  function syncBracket(id, patch) {
    let found = false;
    const newRounds = state.bracket.rounds.map(r => ({
      ...r, matches: r.matches.map(m => { if (m.id === id) { found = true; return { ...m, ...patch }; } return m; }),
    }));
    if (found) dispatch({ type: "SET_BRACKET", bracket: { rounds: newRounds } });
  }

  function advanceInBracket(winId, matchId) {
    const rounds = JSON.parse(JSON.stringify(state.bracket.rounds));
    let ri = -1, mi = -1;
    for (let r = 0; r < rounds.length; r++) {
      const idx = rounds[r].matches.findIndex(m => m.id === matchId);
      if (idx !== -1) { ri = r; mi = idx; break; }
    }
    if (ri === -1) return;
    const m = rounds[ri].matches[mi];
    if (m.homeScore != null && m.awayScore != null && +m.homeScore === +m.awayScore) m.penaltyWinnerId = winId;
    const nextRi = ri + 1;
    if (nextRi < rounds.length) {
      const nextMi = Math.floor(mi / 2);
      const slot = mi % 2 === 0 ? "homeId" : "awayId";
      const nextM = rounds[nextRi].matches[nextMi];
      if (nextM) {
        nextM[slot] = winId;
        dispatch({ type: "UPDATE_MATCH", id: nextM.id, patch: { [slot]: winId } });
      }
    }
    dispatch({ type: "SET_BRACKET", bracket: { rounds } });
  }

  function confirm() {
    if (!bothEntered) return;
    const patch = { homeScore: hsNum, awayScore: asNum, played: true, penaltyWinnerId: null };
    dispatch({ type: "UPDATE_MATCH", id: match.id, patch });
    syncBracket(match.id, patch);
    if (localWinner) advanceInBracket(localWinner, match.id);
    setEditing(false);
  }

  function handlePenalty(winId) {
    const patch = { penaltyWinnerId: winId };
    dispatch({ type: "UPDATE_MATCH", id: match.id, patch });
    syncBracket(match.id, patch);
    advanceInBracket(winId, match.id);
  }

  function upd(patch) {
    dispatch({ type: "UPDATE_MATCH", id: match.id, patch });
    const bf = ['homeId', 'awayId', 'homeScore', 'awayScore', 'played'];
    if (Object.keys(patch).some(k => bf.includes(k))) syncBracket(match.id, patch);
  }

  const cardClass = "match-card" + (isFinal && winner ? " mc-champion" : isFinal ? " mc-final" : " mc-ko") + (locked ? " mc-played" : "");

  return (
    <div className={cardClass}>
      {/* Locked state: clean row layout */}
      {locked ? (
        <div style={{ padding: '0 0 0 0' }}>
          {/* Home row */}
          <div className={"ko-row " + (homeWin ? "ko-win" : awayWin ? "ko-loss" : "ko-neutral")}
            style={homeWin && home?.color ? { borderLeftColor: home.color } : {}}>
            <div className={"ko-team" + (homeWin ? " is-winner" : "")}>
              <TeamBadge team={home || { shield:'classic', color:'var(--muted)', short:'?' }} size={26}/>
              <span className="ko-name">{home?.name || <span style={{ color:'var(--muted)', fontStyle:'italic' }}>Por definir</span>}</span>
              {homeWin && !isFinal && <span style={{ color:'var(--green)', fontSize:11, marginLeft:4, flexShrink:0 }}>✓ Pasa</span>}
              {homeWin && isFinal && <span style={{ fontSize:13, marginLeft:4, flexShrink:0 }}>🏆</span>}
            </div>
            <span className={"ko-score " + (homeWin ? "sc-win" : awayWin ? "sc-loss" : "")}>{match.homeScore ?? '–'}</span>
          </div>
          {/* Away row */}
          <div className={"ko-row " + (awayWin ? "ko-win" : homeWin ? "ko-loss" : "ko-neutral")}
            style={awayWin && away?.color ? { borderLeftColor: away.color } : {}}>
            <div className={"ko-team" + (awayWin ? " is-winner" : "")}>
              <TeamBadge team={away || { shield:'classic', color:'var(--muted)', short:'?' }} size={26}/>
              <span className="ko-name">{away?.name || <span style={{ color:'var(--muted)', fontStyle:'italic' }}>Por definir</span>}</span>
              {awayWin && !isFinal && <span style={{ color:'var(--green)', fontSize:11, marginLeft:4, flexShrink:0 }}>✓ Pasa</span>}
              {awayWin && isFinal && <span style={{ fontSize:13, marginLeft:4, flexShrink:0 }}>🏆</span>}
            </div>
            <span className={"ko-score " + (awayWin ? "sc-win" : homeWin ? "sc-loss" : "")}>{match.awayScore ?? '–'}</span>
          </div>
          {/* Champion row for Final */}
          {isFinal && winner && (
            <div style={{ padding:'10px 16px', borderTop:'1px solid rgba(245,200,66,.30)', background:'linear-gradient(90deg,rgba(245,200,66,.09) 0%,rgba(245,200,66,.03) 100%)', display:'flex', alignItems:'center', gap:12 }}>
              <span style={{ fontSize:22 }}>🏆</span>
              <div>
                <div style={{ fontSize:8.5, fontWeight:800, letterSpacing:'.22em', textTransform:'uppercase', color:'var(--gold)', marginBottom:3, fontFamily:'var(--ui-cond)' }}>Campeón</div>
                <div style={{ display:'flex', alignItems:'center', gap:8 }}>
                  <TeamBadge team={winner} size={22}/>
                  <span style={{ fontFamily:'var(--display)', fontSize:15, color:'var(--gold)', letterSpacing:'.04em' }}>{winner.name}</span>
                </div>
              </div>
            </div>
          )}
          {/* Penalty draw indicator */}
          {isDraw && winnerId && (
            <div style={{ padding:'4px 16px', background:'rgba(245,158,11,.06)', borderTop:'1px solid rgba(245,158,11,.15)', display:'flex', alignItems:'center', gap:8 }}>
              <span style={{ fontSize:10, color:'var(--amber)', fontWeight:700, letterSpacing:'.08em', textTransform:'uppercase' }}>⚡ Penales</span>
              <span style={{ fontSize:12, color:'var(--text-2)' }}>{state.teams.find(tm => tm.id === winnerId)?.name || '?'} gana en penales</span>
            </div>
          )}
        </div>
      ) : (
        /* Editing / unlocked state */
        <div className="match-main">
          <div className="match-team home">
            <select className="select" value={match.homeId || ""} onChange={(e) => upd({ homeId: e.target.value || null })} style={{ minWidth:120, fontWeight:600 }}>
              <option value="">— Local —</option>
              {state.teams.map(tm => <option key={tm.id} value={tm.id}>{tm.name}</option>)}
            </select>
            {home && <TeamBadge team={home} size={32}/>}
          </div>
          <div className="match-score">
            <input type="number" min="0" value={hs} onChange={(e) => setHs(e.target.value)} placeholder="–"/>
            <span className="vs">VS</span>
            <input type="number" min="0" value={as} onChange={(e) => setAs(e.target.value)} placeholder="–"/>
          </div>
          <div className="match-team away">
            {away && <TeamBadge team={away} size={32}/>}
            <select className="select" value={match.awayId || ""} onChange={(e) => upd({ awayId: e.target.value || null })} style={{ minWidth:120, fontWeight:600 }}>
              <option value="">— Visitante —</option>
              {state.teams.map(tm => <option key={tm.id} value={tm.id}>{tm.name}</option>)}
            </select>
          </div>
          <div className="row gap-8">
            <span className="tag" style={{ fontSize:9.5 }}>KO</span>
            <ConfirmX title="Eliminar partido" onConfirm={() => dispatch({ type: "DELETE_MATCH", id: match.id })}/>
          </div>
        </div>
      )}

      {/* Confirm button */}
      {showConfirm && (
        <div style={{ padding:'7px 12px', borderTop:'1px solid var(--border)', display:'flex', gap:8 }}>
          <button className="btn btn-sm btn-primary" style={{ flex:1 }} onClick={confirm}>
            ✓ {localWinner ? "Confirmar — " + (state.teams.find(tm => tm.id === localWinner)?.name || '?') + " pasa →" : "Confirmar empate"}
          </button>
          {editing && <button className="btn btn-sm btn-ghost" onClick={() => setEditing(false)}>Cancelar</button>}
        </div>
      )}

      {/* Penalty selector */}
      {isDraw && !winnerId && home && away && (
        <div style={{ padding:'8px 12px', borderTop:'1px solid var(--border)', background:'rgba(245,158,11,.05)', display:'flex', alignItems:'center', gap:10, flexWrap:'wrap' }}>
          <span style={{ fontSize:11, color:'var(--amber)', fontWeight:800, letterSpacing:'.1em', textTransform:'uppercase', flexShrink:0 }}>⚡ Penales:</span>
          <button className={"btn btn-sm" + (match.penaltyWinnerId === home.id ? " btn-primary" : "")} onClick={() => handlePenalty(home.id)}>
            {home.short || home.name}
          </button>
          <button className={"btn btn-sm" + (match.penaltyWinnerId === away.id ? " btn-primary" : "")} onClick={() => handlePenalty(away.id)}>
            {away.short || away.name}
          </button>
        </div>
      )}

      {/* Correction + delete bar for played matches */}
      {match.played && (
        <div style={{ padding:'3px 12px', borderTop:'1px solid var(--border)', display:'flex', justifyContent:'space-between', alignItems:'center' }}>
          {winnerId && !editing && (
            <button className="btn btn-sm btn-ghost" style={{ fontSize:10 }} onClick={() => advanceInBracket(winnerId, match.id)}>→ Pasar ganador</button>
          )}
          <div style={{ display:'flex', alignItems:'center', gap:6, marginLeft:'auto' }}>
            <ConfirmX title="Eliminar partido" onConfirm={() => dispatch({ type: "DELETE_MATCH", id: match.id })}/>
            <button
              onClick={editing ? confirm : () => { setEditing(true); setHs(match.homeScore != null ? String(match.homeScore) : ""); setAs(match.awayScore != null ? String(match.awayScore) : ""); }}
              style={{ background:'none', border:'none', color: editing ? 'var(--accent)' : 'var(--muted)', fontSize:10, cursor:'pointer', padding:'2px 4px' }}
            >{editing ? '✓ Guardar' : '✎ Corregir'}</button>
          </div>
        </div>
      )}

      {/* Date / Time / Venue */}
      <MatchMeta match={match} state={state} upd={upd} t={t}/>
      <GoalEventsPanel match={match} state={state} dispatch={dispatch}/>
    </div>
  );
}

function CalendarView({ state, dispatch, t }) {
  const [calHistFilter, setCalHistFilter] = useS('all');
  const champion = React.useMemo(() => {
    const finalRound = state.bracket.rounds.find(r => r.label === 'Final');
    if (finalRound?.matches.length) {
      const m = finalRound.matches[0];
      if (m.played && m.homeScore != null && m.awayScore != null) {
        const h = +m.homeScore, a = +m.awayScore;
        const winId = h > a ? m.homeId : a > h ? m.awayId : (m.penaltyWinnerId || null);
        if (winId) return state.teams.find(tm => tm.id === winId) || null;
      }
    }
    const finalCal = state.matches.filter(m => m.stage === 'Final');
    for (const m of finalCal) {
      if (m.played && m.homeScore != null && m.awayScore != null) {
        const h = +m.homeScore, a = +m.awayScore;
        const winId = h > a ? m.homeId : a > h ? m.awayId : (m.penaltyWinnerId || null);
        if (winId) return state.teams.find(tm => tm.id === winId) || null;
      }
    }
    return null;
  }, [state.bracket.rounds, state.matches, state.teams]);

  function generateGroupFixtures() {
    const newMatches = [];
    state.groups.forEach(g => {
      const teams = state.teams.filter(tm => tm.groupId === g.id);
      for (let i = 0; i < teams.length; i++) {
        for (let j = i + 1; j < teams.length; j++) {
          newMatches.push({
            id: uid(), stage: "groups", groupId: g.id, round: 1,
            homeId: teams[i].id, awayId: teams[j].id,
            homeScore: null, awayScore: null, played: false,
            scorers: [], date: "", time: "", venueId: null, court: "",
          });
        }
      }
    });
    dispatch({ type: "SET_MATCHES", matches: [...newMatches, ...state.matches.filter(m => m.stage !== "groups")] });
  }

  const byGroup = {}, byKnockout = {}, otherList = [];
  state.matches.forEach(m => {
    if (m.stage === "groups") {
      const k = m.groupId || "_";
      byGroup[k] = byGroup[k] || [];
      byGroup[k].push(m);
    } else if (KNOCKOUT_ORDER[m.stage] !== undefined) {
      byKnockout[m.stage] = byKnockout[m.stage] || [];
      byKnockout[m.stage].push(m);
    } else {
      otherList.push(m);
    }
  });

  const sortedKnockoutKeys = Object.keys(byKnockout).sort((a, b) =>
    (KNOCKOUT_ORDER[a] ?? 99) - (KNOCKOUT_ORDER[b] ?? 99)
  );

  return (
    <div data-screen-label="04 Calendar">
      {champion && <ChampionBanner team={champion}/>}

      <div className="page-head">
        <div>
          <h1 className="page-title">{t("calendar_title")}</h1>
          <div className="page-sub">{t("calendar_sub")}</div>
        </div>
        <div className="page-actions">
          <ConfirmBtn
            label={"⚙ " + t("generate_fixtures")}
            confirmLabel="Generar"
            className="btn"
            disabled={state.groups.length === 0}
            onConfirm={generateGroupFixtures}
          />
          <button className="btn btn-primary" onClick={() => dispatch({ type: "ADD_MATCH" })}>
            + {t("add_match")}
          </button>
        </div>
      </div>

      {state.matches.length === 0 ? (
        <div className="empty" style={{ paddingTop: 60 }}>
          <div style={{ fontSize: 44, marginBottom: 16 }}>⚽</div>
          <h3 style={{ marginBottom: 8 }}>{t("no_matches_yet")}</h3>
          <p className="muted" style={{ maxWidth: 340, margin: '0 auto 20px' }}>Genera los partidos de grupo o agrega uno manual.</p>
          <ConfirmBtn
            label={"⚙ " + t("generate_fixtures")}
            confirmLabel="Generar"
            className="btn btn-primary"
            disabled={state.groups.length === 0}
            onConfirm={generateGroupFixtures}
          />
        </div>
      ) : (
        <>
          {Object.entries(byGroup).map(([groupId, matches]) => {
            const g = state.groups.find(gg => gg.id === groupId);
            const label = t("stage_groups") + (g ? " — " + t("group") + " " + g.name : "");
            const played = matches.filter(m => m.played).length;
            const total = matches.length;
            const pct = total ? Math.round(played / total * 100) : 0;
            const done = played === total && total > 0;
            return (
              <div key={groupId} style={{ marginBottom: 28 }}>
                <div className="section-row" style={{ marginBottom: 6 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <span className="section-icon">⚽</span>
                    <h2>{label}</h2>
                  </div>
                  <div className="section-stat">
                    <span className={"section-pct" + (done ? " done" : "")}>{pct}%</span>
                    <span>{played}/{total}</span>
                  </div>
                </div>
                <div className="phase-bar" style={{ marginBottom: 12 }}>
                  <div className={"phase-bar-fill" + (done ? " bar-done" : "")} style={{ width: pct + "%" }}/>
                </div>
                <div className="match-list">
                  {matches.map(m => <GroupMatchCard key={m.id} match={m} state={state} dispatch={dispatch} t={t}/>)}
                </div>
              </div>
            );
          })}

          {sortedKnockoutKeys.map(stageKey => {
            const matches = byKnockout[stageKey];
            const isFinal = stageKey === 'Final';
            const played = matches.filter(m => m.played).length;
            const total = matches.length;
            const pct = total ? Math.round(played / total * 100) : 0;
            const done = played === total && total > 0;
            const icon = isFinal ? '🏆' : '⚡';
            return (
              <div key={stageKey} style={{ marginBottom: 28 }}>
                <div className="section-row" style={{ marginBottom: 6 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <span className="section-icon">{icon}</span>
                    <h2>{stageKey}</h2>
                    <span className="tag accent" style={{ fontSize:9.5, padding:'2px 6px' }}>KO</span>
                    {isFinal && champion && <span style={{ fontSize:14 }}>🏆</span>}
                  </div>
                  <div className="section-stat">
                    <span className={"section-pct" + (done ? " done" : "")}>{pct}%</span>
                    <span>{played}/{total}</span>
                  </div>
                </div>
                <div className={"phase-bar"} style={{ marginBottom: 12 }}>
                  <div className={"phase-bar-fill" + (done ? " bar-done" : isFinal ? " bar-final" : " bar-ko")} style={{ width: pct + "%" }}/>
                </div>
                <div className="match-list">
                  {matches.map(m => <KnockoutMatchCard key={m.id} match={m} state={state} dispatch={dispatch} t={t} isFinal={isFinal}/>)}
                </div>
              </div>
            );
          })}

          {otherList.length > 0 && (
            <div style={{ marginBottom: 28 }}>
              <div className="section-row" style={{ marginBottom: 6 }}>
                <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                  <span className="section-icon">📋</span>
                  <h2>Otros partidos</h2>
                </div>
                <div className="section-stat">
                  <span>{otherList.filter(m => m.played).length}/{otherList.length}</span>
                </div>
              </div>
              <div className="match-list">
                {otherList.map(m => <GroupMatchCard key={m.id} match={m} state={state} dispatch={dispatch} t={t}/>)}
              </div>
            </div>
          )}

          {/* ── Calendar History ── */}
          {(() => {
            const playedM = state.matches.filter(m => m.played);
            if (playedM.length === 0) return null;
            const CAL_KO = ['Dieciseisavos','Octavos de Final','Cuartos de Final','Semifinales','Final'];
            const sOrd = s => s === 'groups' ? -1 : (CAL_KO.indexOf(s) >= 0 ? CAL_KO.indexOf(s) : 99);
            const bySt = {};
            playedM.forEach(m => { const k = m.stage || 'groups'; bySt[k] = bySt[k] || []; bySt[k].push(m); });
            const stKeys = Object.keys(bySt).sort((a,b) => sOrd(a) - sOrd(b));
            const tabs = [
              { id: 'all', label: 'Todos', count: playedM.length },
              ...stKeys.map(k => ({ id: k, label: k === 'groups' ? 'Grupos' : k, count: bySt[k].length })),
            ];
            const filtered = calHistFilter === 'all' ? bySt : { [calHistFilter]: bySt[calHistFilter] || [] };
            const filteredKeys = calHistFilter === 'all' ? stKeys : [calHistFilter].filter(k => bySt[k]);
            return (
              <div style={{ marginTop: 36 }}>
                <div className="section-row" style={{ marginBottom: 14 }}>
                  <div style={{ display:'flex', alignItems:'center', gap:10 }}>
                    <span className="section-icon">📋</span>
                    <h2>Historial de Resultados</h2>
                  </div>
                  <span className="muted" style={{ fontSize:11 }}>{playedM.length} jugados</span>
                </div>
                <div className="card" style={{ padding:0, overflow:'hidden' }}>
                  {tabs.length > 2 && (
                    <div style={{ display:'flex', gap:6, padding:'12px 16px', borderBottom:'1px solid var(--border)', flexWrap:'wrap', background:'var(--surface-3)' }}>
                      {tabs.map(tab => (
                        <button key={tab.id} onClick={() => setCalHistFilter(tab.id)}
                          className={"btn btn-sm " + (calHistFilter === tab.id ? "btn-primary" : "btn-ghost")}
                          style={{ fontSize:11 }}>
                          {tab.label}
                          <span style={{ marginLeft:4, opacity:.6, fontSize:10 }}>{tab.count}</span>
                        </button>
                      ))}
                    </div>
                  )}
                  {filteredKeys.map(stageKey => {
                    const ms = filtered[stageKey] || [];
                    const isKO = stageKey !== 'groups';
                    const isFinal = stageKey === 'Final';
                    const stLabel = stageKey === 'groups' ? 'Fase de Grupos' : stageKey;
                    const icon = isFinal ? '🏆' : isKO ? '⚡' : '⚽';
                    const grpMap = {};
                    if (!isKO) ms.forEach(m => { const g = state.groups.find(gg => gg.id === m.groupId); const k = g ? 'Grupo ' + g.name : 'Grupo'; grpMap[k] = grpMap[k] || []; grpMap[k].push(m); });
                    return (
                      <div key={stageKey}>
                        <div style={{ display:'flex', alignItems:'center', gap:8, padding:'7px 18px', background:'var(--surface-3)', borderTop:'1px solid var(--border)', borderBottom:'1px solid var(--border)' }}>
                          <span style={{ fontSize:13 }}>{icon}</span>
                          <span style={{ fontFamily:'var(--ui-cond)', fontSize:11, fontWeight:800, letterSpacing:'.18em', textTransform:'uppercase', color: isFinal ? 'var(--gold)' : isKO ? 'var(--accent)' : 'var(--muted)' }}>{stLabel}</span>
                          <span style={{ marginLeft:'auto', fontSize:10, color:'var(--muted)' }}>{ms.length} {ms.length === 1 ? 'partido' : 'partidos'}</span>
                        </div>
                        {!isKO ? (
                          Object.entries(grpMap).map(([grpName, grpMs]) => (
                            <React.Fragment key={grpName}>
                              {Object.keys(grpMap).length > 1 && (
                                <div style={{ padding:'4px 18px', fontSize:9.5, fontWeight:700, letterSpacing:'.15em', textTransform:'uppercase', color:'var(--muted)', background:'var(--surface-2)', borderBottom:'1px solid var(--border)' }}>{grpName}</div>
                              )}
                              {grpMs.map(m => <ResultRow key={m.id} match={m} state={state}/>)}
                            </React.Fragment>
                          ))
                        ) : (
                          ms.map(m => <ResultRow key={m.id} match={m} state={state}/>)
                        )}
                      </div>
                    );
                  })}
                </div>
              </div>
            );
          })()}
        </>
      )}
    </div>
  );
}

const MatchCard = GroupMatchCard;

// ============================================================
// Standings
// ============================================================
function StandingsView({ state, t }) {
  return (
    <div data-screen-label="05 Standings">
      <div className="page-head">
        <div>
          <h1 className="page-title">{t("standings_title")}</h1>
          <div className="page-sub">{t("standings_sub")}</div>
        </div>
      </div>
      {state.groups.length === 0 ? (
        <StandingsTable rows={computeStandings(state.teams, state.matches, state.meta)} qualifyTop={0} t={t} />
      ) : (
        state.groups.map((g) => {
          const teams = state.teams.filter((tm) => tm.groupId === g.id);
          if (teams.length === 0) return null;
          const matches = state.matches.filter((m) => m.groupId === g.id);
          const rows = computeStandings(teams, matches, state.meta);
          return (
            <div key={g.id} className="card" style={{ marginBottom: 18 }}>
              <div className="card-h">
                <div className="row gap-12 center">
                  <div className="group-letter">{g.name}</div>
                  <h3 className="card-title">{t("group")} {g.name}</h3>
                </div>
                <span className="muted" style={{ fontSize: 11 }}>
                  {matches.filter((m) => m.played).length}/{matches.length} {t("matches")}
                </span>
              </div>
              <StandingsTable rows={rows} qualifyTop={state.meta.qualifyPerGroup || 2} t={t} />
            </div>
          );
        })
      )}
    </div>
  );
}

function StandingsTable({ rows, qualifyTop, t }) {
  return (
    <table className="table">
      <thead>
        <tr>
          <th>{t("pos")}</th>
          <th>{t("team")}</th>
          <th className="num">{t("pj")}</th>
          <th className="num">{t("pg")}</th>
          <th className="num">{t("pe")}</th>
          <th className="num">{t("pp")}</th>
          <th className="num">{t("gf")}</th>
          <th className="num">{t("gc")}</th>
          <th className="num">{t("dg")}</th>
          <th className="num"><b>{t("pts")}</b></th>
        </tr>
      </thead>
      <tbody>
        {rows.map((r, i) => (
          <tr key={r.team.id} className={i < qualifyTop ? "qualify" : ""}>
            <td className="pos">{i + 1}</td>
            <td>
              <div className="team-cell">
                <TeamBadge team={r.team} size={28} />
                <span style={{ fontWeight: 600 }}>{r.team.name}</span>
              </div>
            </td>
            <td className="num">{r.pj}</td>
            <td className="num">{r.pg}</td>
            <td className="num">{r.pe}</td>
            <td className="num">{r.pp}</td>
            <td className="num">{r.gf}</td>
            <td className="num">{r.gc}</td>
            <td className="num">{r.dg > 0 ? "+" + r.dg : r.dg}</td>
            <td className="num"><b style={{ fontFamily: "var(--display)", fontSize: 18 }}>{r.pts}</b></td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

window.Dashboard = Dashboard;
window.TeamsView = TeamsView;
window.CalendarView = CalendarView;
window.StandingsView = StandingsView;
window.TeamBadge = TeamBadge;
window.ShieldSvg = ShieldSvg;
window.SHIELDS = SHIELDS;
window.computeStandings = computeStandings;
window.MiniMatch = MiniMatch;
