/* ==========================================================
   Dashboard -- Live Stats · percentage-only, no raw counts
   Sections:
     1. Campaign Pulse  (4 ratio signals)
     2. Match Verdict Grid  (hero stacked bars)
     3. Match Popularity Share  (% of crowd per match)
     4. Momentum Curve  (relative index, peak=100)
     5. Crowd Track Record  (% accuracy on settled)
   ========================================================== */

/* ── Verdict config ── */
const VERDICT_CFG = {
  DECIDED:   { label: 'DECIDED',   bg: 'var(--ink)',      fg: '#fff',          desc: 'Crowd locked in' },
  LEANING:   { label: 'LEANING',   bg: 'var(--orange)',   fg: '#fff',          desc: 'Strong lean' },
  CONTESTED: { label: 'CONTESTED', bg: 'var(--orange-50)', fg: 'var(--orange-dark)', desc: 'Close call' },
  SPLIT:     { label: 'SPLIT',     bg: 'var(--grey-200)', fg: 'var(--ink)',     desc: 'Too close to call' },
};

/* ── Verdict chip ── */
function VerdictChip({ verdict }) {
  const cfg = VERDICT_CFG[verdict] || VERDICT_CFG.SPLIT;
  return (
    <span className="skew-tag" style={{
      display: 'inline-flex',
      background: cfg.bg,
      color: cfg.fg,
      padding: '3px 12px',
      fontSize: 10,
      fontWeight: 800,
      letterSpacing: '0.14em',
      textTransform: 'uppercase',
    }}>
      <span className="skew-tag-inner">{cfg.label}</span>
    </span>
  );
}

/* ── Animated percentage counter ── */
function PctCounter({ value, suffix = '%', duration = 900 }) {
  const [disp, setDisp] = useState(0);
  const start = useRef(null);
  const frame = useRef(null);
  useEffect(() => {
    start.current = null;
    const target = value || 0;
    const step = (ts) => {
      if (!start.current) start.current = ts;
      const prog = Math.min((ts - start.current) / duration, 1);
      const ease = 1 - Math.pow(1 - prog, 4);
      setDisp(Math.round(ease * target));
      if (prog < 1) frame.current = requestAnimationFrame(step);
    };
    frame.current = requestAnimationFrame(step);
    return () => cancelAnimationFrame(frame.current);
  }, [value, duration]);
  return <span aria-live="polite" aria-atomic="true">{disp}{suffix}</span>;
}

/* ── Stacked bar for a match ── */
function MatchBar({ pA, pDraw, pB, labelA, labelB, size = 'lg' }) {
  const h = size === 'lg' ? 44 : 32;
  const fs = size === 'lg' ? 11 : 10;
  return (
    <div style={{ display: 'flex', height: h, borderRadius: 3, overflow: 'hidden', border: '1px solid var(--grey-200)' }}>
      {[
        { pct: pA,    bg: 'var(--ink)',        label: labelA },
        { pct: pDraw, bg: 'var(--grey-400)',   label: 'Draw' },
        { pct: pB,    bg: 'var(--orange)',     label: labelB },
      ].map((seg, i) => (
        <div key={i} className="grow-bar" style={{
          width: `${seg.pct}%`,
          background: seg.bg,
          color: '#fff',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: fs,
          fontWeight: 700,
          letterSpacing: '0.04em',
          overflow: 'hidden',
          whiteSpace: 'nowrap',
          transition: 'width 0.7s cubic-bezier(.2,.7,.2,1)',
          animationDelay: `${i * 80}ms`,
        }}>
          {seg.pct >= 10 ? `${seg.pct}%` : ''}
        </div>
      ))}
    </div>
  );
}

/* ── Pulse signal card ── */
function PulseCard({ label, value, sub, accent, icon, ariaLabel }) {
  const accents = {
    orange: { bar: 'var(--orange)',   ring: 'rgba(241,86,35,0.15)' },
    ink:    { bar: 'var(--ink)',      ring: 'rgba(17,6,24,0.10)' },
    green:  { bar: 'var(--success)',  ring: 'rgba(22,163,74,0.12)' },
    grey:   { bar: 'var(--grey-400)', ring: 'rgba(17,6,24,0.06)' },
  };
  const ac = accents[accent] || accents.orange;
  return (
    <div style={{
      background: '#fff',
      border: '1px solid var(--grey-200)',
      borderTop: `3px solid ${ac.bar}`,
      borderRadius: '0 0 8px 8px',
      padding: '18px 20px 20px',
      position: 'relative',
    }} aria-label={ariaLabel || label}>
      <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.16em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 10 }}>
        {label}
      </div>
      <div style={{ lineHeight: 1 }}>
        {value}
      </div>
      {sub && (
        <div style={{ fontSize: 12, color: 'var(--grey-500)', marginTop: 8, fontWeight: 500 }}>{sub}</div>
      )}
    </div>
  );
}

/* ── Section header ── */
function SectionHead({ title, sub }) {
  return (
    <div style={{ marginBottom: 20 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <div style={{ width: 4, height: 28, background: 'var(--orange)', flexShrink: 0 }} />
        <h2 className="font-display" style={{ fontSize: 22, letterSpacing: '-0.01em', margin: 0 }}>{title}</h2>
      </div>
      {sub && <p style={{ margin: '6px 0 0 16px', fontSize: 13, color: 'var(--grey-500)', fontWeight: 500 }}>{sub}</p>}
    </div>
  );
}

/* ── Momentum curve SVG ── */
function MomentumCurve({ data }) {
  if (!data || data.length < 2) {
    return (
      <div role="status" style={{ textAlign: 'center', color: 'var(--grey-400)', padding: '48px 0', fontSize: 13, letterSpacing: '0.08em', textTransform: 'uppercase', fontWeight: 600 }}>
        Warming up. Check back once predictions roll in.
      </div>
    );
  }
  const W = 680, H = 200;
  const pad = { l: 38, r: 16, t: 20, b: 30 };
  const iW = W - pad.l - pad.r;
  const iH = H - pad.t - pad.b;
  const xStep = iW / (data.length - 1);
  const pts = data.map((d, i) => [pad.l + i * xStep, pad.t + (1 - d.idx / 100) * iH]);
  const line = pts.map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x.toFixed(1)} ${y.toFixed(1)}`).join(' ');
  const area = `${line} L ${pts[pts.length-1][0]} ${pad.t + iH} L ${pts[0][0]} ${pad.t + iH} Z`;

  const ticks = [0, 25, 50, 75, 100];
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} style={{ display: 'block' }}>
      <defs>
        <linearGradient id="momFade" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%"   stopColor="var(--orange)" stopOpacity="0.28" />
          <stop offset="100%" stopColor="var(--orange)" stopOpacity="0" />
        </linearGradient>
      </defs>

      {ticks.map(v => {
        const y = pad.t + (1 - v / 100) * iH;
        return (
          <g key={v}>
            <line x1={pad.l} x2={W - pad.r} y1={y} y2={y} stroke="var(--grey-200)" strokeDasharray="4 3" />
            <text x={pad.l - 6} y={y + 4} fontSize="9.5" fill="var(--grey-400)" textAnchor="end">{v}</text>
          </g>
        );
      })}

      <path d={area} fill="url(#momFade)" />
      <path d={line}  fill="none" stroke="var(--orange)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" />

      {pts.map(([x, y], i) => {
        const isLast = i === pts.length - 1;
        const isPeak = data[i].idx === 100;
        return isLast
          ? <circle key={i} cx={x} cy={y} r={6} fill="var(--ink)" stroke="#fff" strokeWidth={2} />
          : isPeak
            ? <circle key={i} cx={x} cy={y} r={5} fill="var(--orange)" stroke="#fff" strokeWidth={1.5} />
            : <circle key={i} cx={x} cy={y} r={3.5} fill="var(--orange)" opacity="0.7" />;
      })}

      {data.map((d, i) => {
        if (i % 3 !== 0 && i !== data.length - 1) return null;
        const x = pad.l + i * xStep;
        return (
          <text key={i} x={x} y={H - 6} fontSize="9.5" fill="var(--grey-400)" textAnchor="middle">{d.d}</text>
        );
      })}

      <g transform={`translate(${pts[pts.length-1][0] - 44}, ${pts[pts.length-1][1] - 32})`}>
        <rect x={0} y={0} width={82} height={20} fill="var(--ink)" />
        <text x={41} y={14} fontSize="10" fill="#fff" textAnchor="middle" fontWeight="800" letterSpacing="0.08em">
          NOW {data[data.length-1].idx}
        </text>
      </g>

      <g transform={`translate(${pad.l - 2}, ${pad.t - 4})`}>
        <rect x={0} y={0} width={70} height={18} fill="var(--orange-50)" />
        <text x={35} y={12.5} fontSize="9" fill="var(--orange-dark)" textAnchor="middle" fontWeight="700" letterSpacing="0.06em">PEAK = 100</text>
      </g>
    </svg>
  );
}

/* ── Popularity share list ── */
function PopularityList({ matches }) {
  if (!matches || matches.length === 0) {
    return <div role="status" style={{ color: 'var(--grey-400)', fontSize: 13, padding: '24px 0', textAlign: 'center' }}>No data yet.</div>;
  }
  const sorted = [...matches].sort((a, b) => b.share - a.share).slice(0, 5);
  return (
    <div style={{ display: 'grid', gap: 10 }}>
      {sorted.map((m, i) => (
        <div key={m.id} style={{ display: 'grid', gridTemplateColumns: '28px 1fr 52px', gap: 12, alignItems: 'center' }}>
          <div className="font-display" style={{
            fontSize: 14,
            color: i === 0 ? 'var(--orange)' : 'var(--grey-400)',
            textAlign: 'right',
          }}>
            {i + 1}
          </div>
          <div>
            <div style={{ fontSize: 13.5, fontWeight: 700, marginBottom: 4 }}>{m.label}</div>
            <div style={{
              height: 8,
              background: 'var(--grey-100)',
              borderRadius: 2,
              overflow: 'hidden',
              border: '1px solid var(--grey-200)',
            }}>
              <div className="grow-bar" style={{
                width: `${m.share}%`,
                height: '100%',
                background: i === 0 ? 'var(--orange)' : i === 1 ? 'var(--ink)' : 'var(--grey-300)',
                animationDelay: `${i * 50}ms`,
              }} />
            </div>
          </div>
          <div className="font-display" style={{ fontSize: 20, textAlign: 'right', color: i === 0 ? 'var(--orange)' : 'var(--ink)' }}>
            {m.share}%
          </div>
        </div>
      ))}
    </div>
  );
}

/* ── Top Predictors Panel ── */
function TopPredictorsPanel({ predictors }) {
  if (!predictors || predictors.length === 0) {
    return (
      <div style={{
        border: '1px solid var(--grey-200)', borderRadius: 8,
        padding: '32px 20px', textAlign: 'center', background: 'var(--grey-50)',
      }}>
        <div style={{ fontSize: 13, color: 'var(--grey-500)', fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
          No settled results yet
        </div>
        <div style={{ fontSize: 12, color: 'var(--grey-400)', marginTop: 6 }}>
          Leaderboard appears once matches are settled.
        </div>
      </div>
    );
  }

  const MEDALS = ['1st', '2nd', '3rd', '4th', '5th'];
  const maxCorrect = predictors[0]?.correct || 1;

  return (
    <div style={{ display: 'grid', gap: 10 }}>
      {predictors.map((p, i) => (
        <div key={p.name + i} style={{
          display: 'grid', gridTemplateColumns: '36px 1fr 56px',
          gap: 12, alignItems: 'center',
          border: i === 0 ? '1.5px solid var(--orange)' : '1px solid var(--grey-200)',
          borderRadius: 8,
          padding: '10px 14px',
          background: i === 0 ? 'oklch(99% 0.01 50)' : '#fff',
        }}>
          {/* Rank */}
          <div style={{ textAlign: 'center', lineHeight: 1 }}>
            <span aria-label={'Rank ' + (i + 1)} style={{
              display: 'inline-block',
              background: i === 0 ? 'var(--orange)' : i === 1 ? 'var(--ink)' : i === 2 ? 'var(--grey-600)' : 'var(--grey-200)',
              color: i < 3 ? '#fff' : 'var(--grey-600)',
              fontSize: 10, fontWeight: 800, letterSpacing: '0.06em',
              padding: '3px 6px', borderRadius: 4,
            }}>{MEDALS[i] || (i + 1)}</span>
          </div>
          {/* Name + bar */}
          <div>
            <div style={{ fontSize: 13.5, fontWeight: 700, marginBottom: 5, color: 'var(--ink)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
              {p.name}
            </div>
            <div style={{ height: 6, background: 'var(--grey-100)', borderRadius: 2, overflow: 'hidden', border: '1px solid var(--grey-200)' }}>
              <div className="grow-bar" style={{
                width: `${Math.round((p.correct / maxCorrect) * 100)}%`,
                height: '100%',
                background: i === 0 ? 'var(--orange)' : i === 1 ? 'var(--ink)' : 'var(--grey-400)',
                animationDelay: `${i * 60}ms`,
              }} />
            </div>
          </div>
          {/* Score */}
          <div style={{ textAlign: 'right' }}>
            <div className="font-display" style={{ fontSize: 22, lineHeight: 1, color: i === 0 ? 'var(--orange)' : 'var(--ink)' }}>
              {p.correct}
            </div>
            <div style={{ fontSize: 10, color: 'var(--grey-400)', letterSpacing: '0.08em', textTransform: 'uppercase', fontWeight: 600, marginTop: 2 }}>correct</div>
          </div>
        </div>
      ))}
    </div>
  );
}

/* ── Track record ── */
function TrackRecord({ accuracy }) {
  if (!accuracy) {
    return (
      <div style={{
        border: '1px solid var(--grey-200)',
        borderRadius: 10,
        padding: '32px 24px',
        textAlign: 'center',
        background: 'var(--grey-50)',
      }}>
        <div style={{ fontSize: 13, color: 'var(--grey-500)', fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase' }}>
          Results pending
        </div>
        <div style={{ fontSize: 12, color: 'var(--grey-400)', marginTop: 6 }}>
          Track record unlocks once matches are settled.
        </div>
      </div>
    );
  }

  const pct = accuracy.pct;
  const color = pct >= 70 ? 'var(--success)' : pct >= 50 ? 'var(--orange)' : 'var(--grey-500)';
  const rating = pct >= 70 ? 'SHARP' : pct >= 55 ? 'DECENT' : pct >= 40 ? 'MIXED' : 'OFF';

  return (
    <div style={{
      border: '1px solid var(--grey-200)',
      borderRadius: 10,
      padding: '28px 28px',
      display: 'grid',
      gridTemplateColumns: '1fr auto',
      gap: 24,
      alignItems: 'center',
      background: '#fff',
    }}>
      <div>
        <div style={{ fontSize: 11, fontWeight: 800, letterSpacing: '0.18em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 10 }}>
          Crowd accuracy on settled matches
        </div>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12 }}>
          <span className="font-display" style={{ fontSize: 52, lineHeight: 1, color, letterSpacing: '-0.03em' }}>
            <PctCounter value={pct} />
          </span>
          <span className="skew-tag" style={{
            display: 'inline-flex',
            background: color,
            color: '#fff',
            padding: '4px 12px',
            fontSize: 11,
            fontWeight: 800,
            letterSpacing: '0.14em',
          }}>
            <span className="skew-tag-inner">{rating}</span>
          </span>
        </div>
        <div style={{ fontSize: 12.5, color: 'var(--grey-500)', marginTop: 10 }}>
          {accuracy.correct} of {accuracy.settled} settled {accuracy.settled === 1 ? 'match' : 'matches'} -- crowd majority pick matched the actual result.
        </div>
      </div>
      <div style={{ textAlign: 'center' }}>
        <svg width="90" height="90" viewBox="0 0 90 90">
          <circle cx={45} cy={45} r={38} fill="none" stroke="var(--grey-100)" strokeWidth={8} />
          <circle cx={45} cy={45} r={38} fill="none" stroke={color} strokeWidth={8}
            strokeDasharray={`${2 * Math.PI * 38 * pct / 100} ${2 * Math.PI * 38 * (1 - pct / 100)}`}
            strokeDashoffset={2 * Math.PI * 38 * 0.25}
            strokeLinecap="round"
            style={{ transition: 'stroke-dasharray 1.2s cubic-bezier(.2,.7,.2,1)' }}
          />
          <text x={45} y={50} textAnchor="middle" fontSize="11" fontWeight="800" fill={color} fontFamily="Nunito, sans-serif">
            {pct}%
          </text>
        </svg>
      </div>
    </div>
  );
}

/* ── Live pill ── */
function LivePill({ ts }) {
  const t = new Date(ts);
  const label = `${String(t.getHours()).padStart(2,'0')}:${String(t.getMinutes()).padStart(2,'0')}:${String(t.getSeconds()).padStart(2,'0')}`;
  return (
    <div className="skew-tag" style={{
      background: 'var(--success-bg)',
      color: '#0f5f2e',
      border: '2px solid var(--success)',
      padding: '7px 18px',
      display: 'inline-flex',
      alignItems: 'center',
      gap: 8,
      fontSize: 11,
      fontWeight: 800,
      letterSpacing: '0.14em',
      textTransform: 'uppercase',
    }}>
      <span className="skew-tag-inner" style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}>
        <span className="pulse-dot" style={{ width: 7, height: 7, background: 'var(--success)', borderRadius: '50%' }} />
        Live {label}
      </span>
    </div>
  );
}

/* ── Match verdict card ── */
function MatchVerdictCard({ match, delay = 0 }) {
  if (!match) return null;
  // Parse label like "MEX vs SAF" or match_label from DB
  const parts = (match.label || '').split(/\s+vs\.?\s+/i);
  const nameA = parts[0] || 'Team A';
  const nameB = parts[1] || 'Team B';
  const cfg = VERDICT_CFG[match.verdict] || VERDICT_CFG.SPLIT;
  const fixture = MATCHES.find(m => m.id === match.id);

  return (
    <div className="slide-up" style={{
      border: '1px solid var(--grey-200)',
      borderRadius: 8,
      overflow: 'hidden',
      background: '#fff',
      animationDelay: `${delay}ms`,
    }}>
      {/* Top accent strip */}
      <div style={{ height: 3, background: cfg.bg === 'var(--grey-200)' ? 'var(--grey-300)' : cfg.bg }} />

      <div style={{ padding: '14px 16px 16px' }}>
        {/* Header row */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4, gap: 10 }}>
          <div className="font-display" style={{ fontSize: 15, letterSpacing: '-0.01em', flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {match.label}
          </div>
          <VerdictChip verdict={match.verdict} />
        </div>

        {/* Match date / time */}
        {fixture && (
          <div style={{ fontSize: 11, color: 'var(--grey-500)', fontWeight: 600, marginBottom: 12 }}>
            {formatKickoff(fixture.kickoffAt)}
          </div>
        )}

        {/* Stacked bar */}
        <MatchBar pA={match.pA} pDraw={match.pDraw} pB={match.pB} labelA={nameA} labelB={nameB} />

        {/* Footer pct row */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6, marginTop: 10 }}>
          {[
            { label: nameA, pct: match.pA,    color: 'var(--ink)' },
            { label: 'Draw',  pct: match.pDraw, color: 'var(--grey-400)' },
            { label: nameB, pct: match.pB,    color: 'var(--orange)' },
          ].map((seg, i) => (
            <div key={i} style={{ textAlign: 'center' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5 }}>
                <span style={{ width: 8, height: 8, background: seg.color, flexShrink: 0, borderRadius: 1 }} />
                <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--grey-600)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 70 }}>{seg.label}</span>
              </div>
              <div className="font-display" style={{ fontSize: 22, lineHeight: 1.1, color: seg.color, marginTop: 4 }}>
                {seg.pct}%
              </div>
            </div>
          ))}
        </div>

        {/* Odds-style implied odds */}
        <OddsRow pA={match.pA} pDraw={match.pDraw} pB={match.pB} nameA={nameA} nameB={nameB} />

        {/* Actual result vs crowd verdict */}
        {match.actual && <ActualResultRow actual={match.actual} crowdPick={match.crowdPick} nameA={nameA} nameB={nameB} />}
      </div>
    </div>
  );
}

/* ── Actual result vs crowd prediction comparison ── */
function pickName(pick, nameA, nameB) {
  return pick === 'A' ? nameA : pick === 'B' ? nameB : 'Draw';
}
function ActualResultRow({ actual, crowdPick, nameA, nameB }) {
  const correct = actual.correct;
  return (
    <div style={{
      marginTop: 12, paddingTop: 12, borderTop: '1px dashed var(--grey-200)',
      display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 10, flexWrap: 'wrap',
    }}>
      <div>
        <div style={{ fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', fontWeight: 700 }}>
          Final result
        </div>
        <div className="font-display" style={{ fontSize: 16, marginTop: 2 }}>
          {nameA} {actual.scoreA} – {actual.scoreB} {nameB}
          <span style={{ fontSize: 12, color: 'var(--grey-500)', marginLeft: 6 }}>
            ({pickName(actual.winnerPick, nameA, nameB)} won)
          </span>
        </div>
      </div>
      <span className="skew-tag" style={{
        display: 'inline-flex',
        background: correct ? 'var(--success)' : 'var(--grey-200)',
        color: correct ? '#fff' : 'var(--ink)',
        padding: '4px 12px', fontSize: 10.5, fontWeight: 800,
        letterSpacing: '0.1em', textTransform: 'uppercase',
      }}>
        <span className="skew-tag-inner">
          {correct ? `Crowd called it (${pickName(crowdPick, nameA, nameB)})` : `Crowd picked ${pickName(crowdPick, nameA, nameB)}`}
        </span>
      </span>
    </div>
  );
}

/* ── Momentum direction badge ── */
function MomentumBadge({ dir }) {
  const map = {
    up:   { label: 'Trending Up',  color: 'var(--success)', arrow: '↑' },
    down: { label: 'Cooling Off',  color: 'var(--orange)',  arrow: '↓' },
    flat: { label: 'Steady',       color: 'var(--grey-500)', arrow: '→' },
  };
  const m = map[dir] || map.flat;
  return (
    <div style={{ lineHeight: 1 }}>
      <div style={{ fontSize: 44, fontWeight: 800, color: m.color, fontFamily: 'Nunito, sans-serif', letterSpacing: '-0.02em' }}>
        {m.arrow}
      </div>
      <div style={{ fontSize: 13, fontWeight: 700, color: m.color, letterSpacing: '0.04em', marginTop: 4, textTransform: 'uppercase' }}>
        {m.label}
      </div>
    </div>
  );
}

/* ── Loading skeleton ── */
function DashSkeleton() {
  const bar = (w, h = 16) => (
    <div style={{ width: w, height: h, background: 'var(--grey-100)', borderRadius: 4 }} />
  );
  return (
    <div style={{ maxWidth: 1200, margin: '0 auto', padding: '32px 22px' }}>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 16, marginBottom: 32 }}>
        {[0,1,2,3].map(i => (
          <div key={i} style={{ border: '1px solid var(--grey-200)', borderTop: '3px solid var(--grey-200)', borderRadius: '0 0 8px 8px', padding: 20 }}>
            {bar('60%', 10)}
            <div style={{ height: 12 }} />
            {bar('40%', 36)}
          </div>
        ))}
      </div>
      {bar('30%', 28)}
      <div style={{ height: 20 }} />
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 16 }}>
        {[0,1,2,3].map(i => (
          <div key={i} style={{ border: '1px solid var(--grey-200)', borderRadius: 8, padding: 20 }}>
            {bar('70%', 16)}
            <div style={{ height: 10 }} />
            {bar('100%', 44)}
          </div>
        ))}
      </div>
    </div>
  );
}

/* ── My Predictions panel (used in my-predictions.jsx page) ── */
/* ── Social Share Card Modal ── */
function ShareCardModal({ item, userName, onClose }) {
  const canvasRef = React.useRef(null);

  React.useEffect(function() {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const S = 1080;
    canvas.width = S; canvas.height = S;

    var match = (item.matchLabel || 'Match Prediction');
    var parts = match.split(' vs ');
    var teamA = parts[0] || '';
    var teamB = parts[1] || '';
    var winner = item.pick === 'A' ? (teamA || item.pick)
               : item.pick === 'B' ? (teamB || item.pick)
               : 'Draw';

    // Resolve flag URLs from the live match object (codes -> flagcdn ISO)
    var matchObj = (window.MATCHES || []).filter(function(m){ return m.id === item.matchId; })[0];
    function isoOf(code) {
      if (!code) return null;
      var map = window._FIFA_ISO_ADMIN || {};
      return map[code] || String(code).toLowerCase();
    }
    function flagUrl(code) {
      var iso = isoOf(code);
      return iso ? ('https://flagcdn.com/w160/' + iso + '.png') : null;
    }
    var flagUrlA = matchObj && matchObj.teamA ? flagUrl(matchObj.teamA.flag) : null;
    var flagUrlB = matchObj && matchObj.teamB ? flagUrl(matchObj.teamB.flag) : null;

    function loadImg(src, cross) {
      return new Promise(function(resolve) {
        if (!src) { resolve(null); return; }
        var im = new Image();
        if (cross) im.crossOrigin = 'anonymous';
        im.onload = function(){ resolve(im); };
        im.onerror = function(){ resolve(null); };
        im.src = src;
      });
    }

    Promise.all([
      loadImg('/assets/images/share-template.png', false),
      loadImg(flagUrlA, true),
      loadImg(flagUrlB, true),
    ]).then(function(imgs) {
      var tpl = imgs[0], fA = imgs[1], fB = imgs[2];
      if (!tpl) return;

      ctx.drawImage(tpl, 0, 0, S, S);

      // Cover the template's baked sample text
      ctx.fillStyle = '#ffffff';
      ctx.fillRect(S * 0.04, S * 0.510, S * 0.92, S * 0.120); // match + picked band
      ctx.fillRect(S * 0.04, S * 0.636, S * 0.92, S * 0.060); // predicted-by band

      var nameA = teamA.toUpperCase();
      var nameB = teamB.toUpperCase();

      // ── Match row: [flagA] NAME A  vs  NAME B [flagB] ──
      function layout(size) {
        var fH = size;
        var fW = Math.round(fH * 1.45);
        ctx.font = '800 ' + size + 'px Nunito, Arial, sans-serif';
        var wA = ctx.measureText(nameA).width;
        var wB = ctx.measureText(nameB).width;
        var vsSize = Math.round(size * 0.72);
        ctx.font = '600 ' + vsSize + 'px "DM Sans", Arial, sans-serif';
        var wVs = ctx.measureText('vs').width;
        var gap = 14, vsGap = 16;
        var total = (fA ? fW + gap : 0) + wA + vsGap + wVs + vsGap + wB + (fB ? gap + fW : 0);
        return { fH: fH, fW: fW, wA: wA, wB: wB, wVs: wVs, vsSize: vsSize, gap: gap, vsGap: vsGap, total: total };
      }
      var size = 42, L;
      do { L = layout(size); if (L.total <= S * 0.88) break; size -= 2; } while (size > 20);

      var cy = S * 0.555;
      var x = (S - L.total) / 2;
      ctx.textAlign = 'left';
      ctx.textBaseline = 'middle';

      if (fA) {
        ctx.drawImage(fA, x, cy - L.fH / 2, L.fW, L.fH);
        ctx.strokeStyle = 'rgba(0,0,0,0.12)'; ctx.lineWidth = 1;
        ctx.strokeRect(x, cy - L.fH / 2, L.fW, L.fH);
        x += L.fW + L.gap;
      }
      ctx.font = '800 ' + size + 'px Nunito, Arial, sans-serif';
      ctx.fillStyle = '#1c1b29';
      ctx.fillText(nameA, x, cy); x += L.wA + L.vsGap;
      ctx.font = '600 ' + L.vsSize + 'px "DM Sans", Arial, sans-serif';
      ctx.fillStyle = '#9a9ab0';
      ctx.fillText('vs', x, cy); x += L.wVs + L.vsGap;
      ctx.font = '800 ' + size + 'px Nunito, Arial, sans-serif';
      ctx.fillStyle = '#1c1b29';
      ctx.fillText(nameB, x, cy); x += L.wB + L.gap;
      if (fB) {
        ctx.drawImage(fB, x, cy - L.fH / 2, L.fW, L.fH);
        ctx.strokeStyle = 'rgba(0,0,0,0.12)'; ctx.lineWidth = 1;
        ctx.strokeRect(x, cy - L.fH / 2, L.fW, L.fH);
      }
      ctx.textBaseline = 'alphabetic';

      // ── Picked line (single, grey) ──
      ctx.textAlign = 'center';
      ctx.fillStyle = '#8a8a99';
      ctx.font = '700 23px "DM Sans", Arial, sans-serif';
      ctx.fillText(('Picked: ' + winner).toUpperCase(), S / 2, S * 0.604);

      // ── Predicted by (template style: left-aligned, grey label + bold indigo name) ──
      if (userName) {
        var label = 'PREDICTED BY ';
        var name = String(userName).toUpperCase();
        var pbY = S * 0.672;
        var pbSize = 30;
        var startPX = S * 0.115;
        // shrink to fit within right margin
        for (;;) {
          ctx.font = '700 ' + pbSize + 'px "DM Sans", Arial, sans-serif';
          var wL = ctx.measureText(label).width;
          ctx.font = '800 ' + pbSize + 'px Nunito, Arial, sans-serif';
          var wN = ctx.measureText(name).width;
          if (startPX + wL + wN <= S * 0.92 || pbSize <= 18) break;
          pbSize -= 2;
        }
        ctx.textAlign = 'left';
        ctx.font = '700 ' + pbSize + 'px "DM Sans", Arial, sans-serif';
        var wLabel = ctx.measureText(label).width;
        ctx.fillStyle = '#9a9ab0';
        ctx.fillText(label, startPX, pbY);
        ctx.fillStyle = '#2b2a68';
        ctx.font = '800 ' + pbSize + 'px Nunito, Arial, sans-serif';
        ctx.fillText(name, startPX + wLabel, pbY);
        ctx.textAlign = 'center';
      }
    });
  }, [item, userName]);

  function download() {
    const link = document.createElement('a');
    link.download = 'sunfront-correct-pick.png';
    link.href = canvasRef.current.toDataURL('image/png');
    link.click();
  }
  function share() {
    canvasRef.current.toBlob(function(blob) {
      const file = new File([blob], 'sunfront-pick.png', { type: 'image/png' });
      if (navigator.canShare && navigator.canShare({ files: [file] })) {
        navigator.share({ files: [file], title: 'SunFront World Cup Pick', text: 'I nailed it! Correct prediction in SunFront World Cup Foari 2026.' });
      } else { download(); }
    });
  }

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 200, background: 'rgba(17,6,24,0.90)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16,
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: '#fff', borderRadius: 14, padding: 18, width: '100%', maxWidth: 380,
        boxShadow: '0 24px 80px rgba(0,0,0,0.60)',
      }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>
          <span className="font-display" style={{ fontSize: 16, color: 'var(--ink)' }}>Your share card</span>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: 20, color: 'var(--grey-500)', lineHeight: 1 }}>&times;</button>
        </div>
        <canvas ref={canvasRef} style={{ width: '100%', height: 'auto', borderRadius: 8, display: 'block' }} />
        <div style={{ display: 'flex', gap: 10, marginTop: 14 }}>
          <button onClick={share} className="font-display btn-press" style={{
            flex: 1, background: 'var(--orange)', color: '#fff', border: 'none', borderRadius: 6,
            padding: '12px 0', fontSize: 13, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', cursor: 'pointer',
          }}>Share</button>
          <button onClick={download} style={{
            flex: 1, background: 'var(--ink)', color: '#fff', border: 'none', borderRadius: 6,
            padding: '12px 0', fontSize: 13, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', cursor: 'pointer',
          }}>Download</button>
        </div>
        <p style={{ fontSize: 11, color: 'var(--grey-400)', textAlign: 'center', margin: '10px 0 0' }}>
          Tap Share to post on WhatsApp, Instagram, or any social app.
        </p>
      </div>
    </div>
  );
}

function MyPredictions() {
  const [phase, setPhase]         = useState('phone');   // phone | bills | verify | results
  const [phone, setPhone]         = useState('');
  const [bills, setBills]         = useState([]);
  const [selectedBill, setSelected] = useState(null);
  const [amount, setAmount]       = useState('');
  const [data, setData]           = useState(null);
  const [loading, setLoading]     = useState(false);
  const [err, setErr]             = useState('');
  const [shareItem, setShareItem] = useState(null);

  const phoneOk = /^\+960\d{7}$/.test(phone.trim());
  // digits only (last 7) for the input field
  const phoneDigits = phone.startsWith('+960') ? phone.slice(4) : phone.replace(/^\+?960/, '');

  async function lookupPhone() {
    if (!phoneOk) { setErr('Enter a valid Maldivian number: +960 followed by 7 digits.'); return; }
    setLoading(true); setErr('');
    try {
      const r = await fetch('/api/my-predictions?phone=' + encodeURIComponent(phone.trim()));
      const j = await r.json();
      if (!r.ok) { setErr(j.error || 'Not found.'); setLoading(false); return; }
      setBills(j.bills);
      setPhase('bills');
    } catch { setErr('Network error. Try again.'); }
    setLoading(false);
  }

  async function verifyBill() {
    if (!selectedBill || !amount) { setErr('Select a bill and enter the amount.'); return; }
    setLoading(true); setErr('');
    try {
      const r = await fetch('/api/my-predictions', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ phone: phone.trim(), bill: selectedBill, amount }),
      });
      const j = await r.json();
      if (!r.ok) { setErr(j.error || 'Verification failed.'); setLoading(false); return; }
      setData(j);
      setPhase('results');
    } catch { setErr('Network error. Try again.'); }
    setLoading(false);
  }

  function reset() { setPhase('phone'); setPhone(''); setBills([]); setSelected(null); setAmount(''); setData(null); setErr(''); }

  const inputStyle = {
    width: '100%', boxSizing: 'border-box',
    border: '1px solid var(--grey-200)', borderRadius: 7,
    padding: '12px 14px', fontSize: 15, fontFamily: 'Inter, sans-serif',
    outline: 'none', color: 'var(--ink)',
  };
  const btnPrimary = (disabled) => ({
    background: disabled ? 'var(--grey-200)' : 'var(--ink)', color: disabled ? 'var(--grey-400)' : '#fff',
    border: 'none', borderRadius: 7, padding: '12px 28px',
    fontSize: 13, fontWeight: 800, letterSpacing: '0.06em', textTransform: 'uppercase',
    cursor: disabled ? 'not-allowed' : 'pointer', transition: 'background 0.15s',
  });

  const PICK_LABELS = { A: 'Team A', DRAW: 'Draw', B: 'Team B' };
  const OUTCOME_CFG = {
    correct: { bg: 'var(--success)', fg: '#fff',          icon: 'check', label: 'Correct' },
    wrong:   { bg: '#fee2e2',        fg: '#b91c1c',        icon: null,    label: 'Wrong'   },
    pending: { bg: 'var(--grey-100)', fg: 'var(--grey-500)', icon: null,  label: 'Pending' },
  };

  return (
    <div style={{
      border: '2px solid var(--ink)',
      borderRadius: 12, overflow: 'hidden',
      background: '#fff',
    }}>
      {/* Header bar */}
      <div style={{
        background: 'var(--ink)', color: '#fff',
        padding: '14px 22px',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <Icon name="target" size={18} color="var(--orange)" />
          <span className="font-display" style={{ fontSize: 17, letterSpacing: '0.01em' }}>My Predictions</span>
        </div>
        {phase !== 'phone' && (
          <button onClick={reset} style={{
            background: 'rgba(255,255,255,0.12)', border: 'none', borderRadius: 5,
            padding: '5px 14px', fontSize: 11, fontWeight: 700, color: '#fff',
            letterSpacing: '0.08em', cursor: 'pointer', textTransform: 'uppercase',
          }}>Start over</button>
        )}
      </div>

      <div style={{ padding: '24px 22px' }}>

        {/* ── Step 1: enter phone ── */}
        {phase === 'phone' && (
          <div style={{ maxWidth: 400 }}>
            <div role="status" style={{ fontSize: 13, color: 'var(--grey-500)', marginBottom: 16, lineHeight: 1.5 }}>
              Enter your Maldivian mobile number to see your bills and predictions.
            </div>
            <div style={{ display: 'flex', gap: 10 }}>
              <div style={{ display: 'flex', flex: 1, border: '1px solid var(--grey-200)', borderRadius: 7, overflow: 'hidden', background: '#fff' }}>
                <span style={{
                  display: 'flex', alignItems: 'center', padding: '0 12px',
                  background: 'var(--grey-50)', borderRight: '1px solid var(--grey-200)',
                  fontSize: 15, fontWeight: 700, color: 'var(--ink)', fontFamily: 'JetBrains Mono, monospace',
                  whiteSpace: 'nowrap', userSelect: 'none',
                }}>+960</span>
                <input
                  style={{ ...inputStyle, border: 'none', borderRadius: 0, flex: 1 }}
                  placeholder="7654321"
                  value={phoneDigits}
                  onChange={e => {
                    const digits = e.target.value.replace(/\D/g, '').slice(0, 7);
                    setPhone('+960' + digits);
                    setErr('');
                  }}
                  onKeyDown={e => e.key === 'Enter' && lookupPhone()}
                  inputMode="numeric"
                  maxLength={7}
                />
              </div>
              <button onClick={lookupPhone} disabled={loading || !phoneOk} style={{ ...btnPrimary(!phoneOk || loading), whiteSpace: 'nowrap' }}>
                {loading ? '...' : 'Look up'}
              </button>
            </div>
            {err && <div role="alert" style={{ marginTop: 10, fontSize: 12.5, color: '#b91c1c', fontWeight: 600 }}>{err}</div>}
          </div>
        )}

        {/* ── Step 2: select bill ── */}
        {phase === 'bills' && (
          <div>
            <div style={{ fontSize: 13, color: 'var(--grey-500)', marginBottom: 14 }}>
              {bills.length} bill{bills.length !== 1 ? 's' : ''} found for <strong style={{ color: 'var(--ink)' }}>{phone}</strong>. Select one and enter its amount to unlock predictions.
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 18 }}>
              {bills.map(b => (
                <button key={b.bill}
                  onClick={() => { setSelected(b.bill); setErr(''); }}
                  style={{
                    textAlign: 'left', background: selectedBill === b.bill ? 'var(--orange-50)' : 'var(--grey-50)',
                    border: selectedBill === b.bill ? '2px solid var(--orange)' : '1px solid var(--grey-200)',
                    borderRadius: 8, padding: '11px 16px', cursor: 'pointer',
                    display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                  }}>
                  <span className="font-mono" style={{ fontSize: 14, fontWeight: 700, color: 'var(--ink)' }}>{b.bill}</span>
                  <span style={{ fontSize: 11.5, color: 'var(--grey-500)', fontWeight: 600 }}>
                    {b.usedVotes}/{b.maxVotes} votes used
                  </span>
                </button>
              ))}
            </div>
            {selectedBill && (
              <div style={{ display: 'flex', gap: 10, maxWidth: 400 }}>
                <input
                  style={inputStyle}
                  placeholder="Bill amount (MVR)"
                  value={amount}
                  onChange={e => { setAmount(e.target.value); setErr(''); }}
                  onKeyDown={e => e.key === 'Enter' && verifyBill()}
                  inputMode="decimal"
                />
                <button onClick={verifyBill} disabled={loading || !amount} style={{ ...btnPrimary(!amount || loading), whiteSpace: 'nowrap' }}>
                  {loading ? '...' : 'Verify'}
                </button>
              </div>
            )}
            {err && <div role="alert" style={{ marginTop: 10, fontSize: 12.5, color: '#b91c1c', fontWeight: 600 }}>{err}</div>}
          </div>
        )}

        {/* ── Step 3: results ── */}
        {phase === 'results' && data && (() => {
          // Compute streak: consecutive correct picks (all bills, ordered by submittedAt)
          const allPreds = data.bills.flatMap(b => b.predictions)
            .filter(p => p.outcome !== 'pending')
            .sort((a, b) => new Date(a.submittedAt) - new Date(b.submittedAt));
          let streak = 0;
          for (let i = allPreds.length - 1; i >= 0; i--) {
            if (allPreds[i].outcome === 'correct') streak++;
            else break;
          }
          const totalSettled = data.overall.settled || 0;
          const totalCorrect = data.overall.correct || 0;
          const badges = [];
          if (streak >= 5) badges.push({ icon: '🔥', label: streak + ' in a row!', color: '#c2410c' });
          else if (streak >= 3) badges.push({ icon: '⚡', label: streak + ' streak', color: 'var(--orange)' });
          if (totalCorrect >= totalSettled && totalSettled >= 3) badges.push({ icon: '🎯', label: 'Perfect round', color: 'var(--success)' });
          else if (data.overall.accuracyPct >= 80 && totalSettled >= 3) badges.push({ icon: '🏆', label: '80%+ accuracy', color: 'var(--success)' });

          return (
          <div>
            {/* Streak badges */}
            {badges.length > 0 && (
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 16 }}>
                {badges.map((b, i) => (
                  <div key={i} style={{
                    display: 'inline-flex', alignItems: 'center', gap: 6,
                    background: 'var(--grey-50)', border: '1.5px solid ' + b.color,
                    borderRadius: 8, padding: '6px 14px', fontSize: 12.5, fontWeight: 700, color: b.color,
                  }}>
                    <span>{b.icon}</span> {b.label}
                  </div>
                ))}
              </div>
            )}

            {/* Identity row */}
            <div style={{ display: 'flex', alignItems: 'center', gap: 16, marginBottom: 20, flexWrap: 'wrap' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                <Icon name="phone" size={14} color="var(--orange)" />
                <span style={{ fontSize: 13, fontWeight: 700, color: 'var(--ink)' }}>{phone}</span>
              </div>
              {data.customerName && (
                <span style={{ fontSize: 13, color: 'var(--grey-500)' }}>{data.customerName}</span>
              )}
              <span style={{ fontSize: 11, color: 'var(--grey-400)', background: 'var(--grey-100)', padding: '3px 10px', borderRadius: 4, fontWeight: 600 }}>
                {data.bills.length} bill{data.bills.length !== 1 ? 's' : ''}
              </span>
            </div>

            {/* Overall summary */}
            <h3 id="my-summary-heading" style={{ fontSize: 13, fontWeight: 700, color: 'var(--grey-500)', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 10, marginTop: 0 }}>Overall Summary</h3>
            <div style={{
              display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12, marginBottom: 28,
            }} className="my-pred-summary" role="region" aria-labelledby="my-summary-heading">
              {[
                { label: 'Total picks', val: data.overall.total,    color: 'var(--ink)' },
                { label: 'Settled',     val: data.overall.settled,  color: 'var(--grey-500)' },
                { label: 'Correct',     val: data.overall.correct,  color: 'var(--success)' },
                { label: 'Accuracy',    val: data.overall.accuracyPct != null ? data.overall.accuracyPct + '%' : 'N/A', color: 'var(--orange)' },
              ].map(s => (
                <div key={s.label} style={{ border: '1px solid var(--grey-200)', borderRadius: 8, padding: '12px 16px', textAlign: 'center' }}>
                  <div style={{ fontSize: 10, color: 'var(--grey-400)', fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase', marginBottom: 6 }}>{s.label}</div>
                  <div className="font-display" style={{ fontSize: 26, lineHeight: 1, color: s.color }}>{s.val}</div>
                </div>
              ))}
            </div>

            {/* Per-bill sections */}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
              {data.bills.map(b => (
                <div key={b.bill} style={{
                  border: '1px solid var(--grey-200)', borderRadius: 12, overflow: 'hidden',
                  boxShadow: '0 4px 20px rgba(17,6,24,0.08)',
                  borderTop: '3px solid var(--orange)',
                }}>
                  {/* Bill header */}
                  <div style={{
                    background: 'var(--ink)', color: '#fff',
                    padding: '14px 18px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 10,
                  }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                      <div style={{ width: 32, height: 32, background: 'rgba(241,86,35,0.18)', borderRadius: 6, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
                        <Icon name="receipt" size={16} color="var(--orange)" />
                      </div>
                      <div>
                        <h3 className="font-mono" style={{ fontSize: 14, fontWeight: 800, color: '#fff', margin: '0 0 2px', letterSpacing: '0.04em' }}>{b.bill}</h3>
                        <span style={{ fontSize: 11, color: 'rgba(255,255,255,0.55)', fontWeight: 500 }}>MVR {Number(b.amountMyr).toLocaleString('en', { minimumFractionDigits: 2 })}</span>
                      </div>
                    </div>
                    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 6 }}>
                      <div style={{ display: 'flex', gap: 14, fontSize: 12, fontWeight: 700 }}>
                        <span style={{ color: 'rgba(255,255,255,0.70)' }}>
                          <span style={{ color: 'var(--orange)', fontSize: 15 }}>{b.usedVotes}</span>/{b.maxVotes} picks used
                        </span>
                        {b.summary && b.summary.settled > 0 && (
                          <span style={{ color: b.summary.accuracyPct >= 50 ? '#4ade80' : 'var(--orange-light)' }}>
                            {b.summary.accuracyPct}% correct
                          </span>
                        )}
                      </div>
                      {/* Vote usage bar */}
                      <div style={{ width: 140, height: 5, background: 'rgba(255,255,255,0.12)', borderRadius: 999 }}>
                        <div className="grow-bar" style={{
                          width: b.maxVotes > 0 ? Math.round((b.usedVotes / b.maxVotes) * 100) + '%' : '0%',
                          height: '100%', background: 'var(--orange)', borderRadius: 999,
                        }} />
                      </div>
                    </div>
                  </div>

                  {/* Predictions list */}
                  {b.predictions.length === 0 ? (
                    <div role="status" style={{ padding: '16px', fontSize: 12.5, color: 'var(--grey-400)', textAlign: 'center' }}>No predictions yet on this bill.</div>
                  ) : (
                    <ul style={{ padding: '10px 12px', display: 'flex', flexDirection: 'column', gap: 6, listStyle: 'none', margin: 0 }}>
                      {b.predictions.map((p, i) => {
                        const oc = OUTCOME_CFG[p.outcome] || OUTCOME_CFG.pending;
                        const parts = (p.matchLabel || '').split(' vs ');
                        const pickLabel = p.pick === 'A' ? parts[0] : p.pick === 'B' ? parts[1] : 'Draw';
                        const resultLabel = p.winner ? (p.winner === 'A' ? parts[0] : p.winner === 'B' ? parts[1] : 'Draw') : null;
                        return (
                          <li key={i} style={{
                            display: 'grid', gridTemplateColumns: '1fr auto',
                            alignItems: 'center', gap: 10,
                            border: '1px solid var(--grey-100)', borderRadius: 7, padding: '10px 14px',
                            background: p.outcome === 'correct' ? 'oklch(97.5% 0.01 145)' : p.outcome === 'wrong' ? 'oklch(98.5% 0.01 20)' : '#fff',
                          }}>
                            <div>
                              <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--ink)', marginBottom: 2 }}>
                                {p.matchLabel || 'Match ' + p.matchId}
                              </div>
                              <div style={{ fontSize: 11.5, color: 'var(--grey-400)' }}>
                                Picked: <strong style={{ color: 'var(--ink)' }}>{pickLabel || p.pick}</strong>
                                {resultLabel && <span style={{ marginLeft: 10 }}>Result: <strong style={{ color: 'var(--grey-600)' }}>{resultLabel}</strong></span>}
                              </div>
                              <div style={{ fontSize: 10.5, color: 'var(--grey-400)', marginTop: 3, display: 'flex', gap: 12, flexWrap: 'wrap' }}>
                                {p.submittedAt && <span>Locked {new Date(p.submittedAt).toLocaleString('en-MV', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: true })}</span>}
                                {p.changedAt   && <span style={{ color: 'var(--orange)' }}>Changed {new Date(p.changedAt).toLocaleString('en-MV', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: true })}</span>}
                              </div>
                            </div>
                            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 6 }}>
                              <span style={{
                                background: oc.bg, color: oc.fg,
                                fontSize: 10, fontWeight: 800, letterSpacing: '0.1em',
                                padding: '4px 10px', borderRadius: 4, textTransform: 'uppercase', whiteSpace: 'nowrap',
                              }}>{oc.label}</span>
                              {p.outcome === 'correct' && (
                                <button
                                  onClick={() => setShareItem({ ...p })}
                                  style={{
                                    background: 'var(--orange)', color: '#fff',
                                    border: 'none', borderRadius: 5,
                                    padding: '5px 12px', fontSize: 10, fontWeight: 800,
                                    cursor: 'pointer', whiteSpace: 'nowrap',
                                    letterSpacing: '0.06em', textTransform: 'uppercase',
                                    display: 'inline-flex', alignItems: 'center', gap: 5,
                                  }}>
                                  Share <Icon name="arrow" size={10} color="#fff" />
                                </button>
                              )}
                            </div>
                          </li>
                        );
                      })}
                    </ul>
                  )}
                </div>
              ))}
            </div>
          </div>
          );
        })()}

      </div>

      <style>{`
        @media (max-width: 600px) {
          .my-pred-summary { grid-template-columns: repeat(2, 1fr) !important; }
        }
      `}</style>

      {/* Share card modal */}
      {shareItem && (
        <ShareCardModal
          item={shareItem}
          userName={data && data.customerName ? data.customerName : ''}
          onClose={() => setShareItem(null)}
        />
      )}
    </div>
  );
}

/* ── Recent picks live feed strip ── */
function RecentPicksFeed() {
  const [picks, setPicks] = useState([]);
  const PICK_COLORS = { A: 'var(--ink)', DRAW: 'var(--grey-500)', B: 'var(--orange)' };
  const PICK_EMOJI = { A: 'A', DRAW: '=', B: 'B' };

  function load() {
    fetch('/api/recent-picks?limit=14')
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d && d.picks) setPicks(d.picks); })
      .catch(() => {});
  }

  useEffect(() => {
    load();
    const id = setInterval(load, 12000);
    return () => clearInterval(id);
  }, []);

  if (picks.length === 0) return null;

  const doubled = [...picks, ...picks]; // seamless loop
  return (
    <div style={{
      background: 'var(--ink)', overflow: 'hidden',
      borderBottom: '3px solid var(--orange)',
      padding: '10px 0',
    }}>
      <div className="ticker-track" style={{
        display: 'inline-flex', gap: 40, whiteSpace: 'nowrap',
        animation: 'tickerSlide 36s linear infinite',
      }}>
        {doubled.map((p, i) => (
          <span key={i} style={{ display: 'inline-flex', alignItems: 'center', gap: 8, fontSize: 11.5, color: '#fff', fontWeight: 600 }}>
            <span style={{
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
              width: 20, height: 20, borderRadius: 3,
              background: PICK_COLORS[p.pick] || 'var(--grey-400)', color: '#fff',
              fontSize: 10, fontWeight: 800,
            }}>{PICK_EMOJI[p.pick] || p.pick}</span>
            <span style={{ color: 'var(--grey-300)' }}>{p.matchLabel}</span>
            <span style={{ color: 'var(--grey-500)', fontSize: 10 }}>{p.ago}</span>
            <span style={{ color: 'var(--orange)', opacity: 0.5 }}>{'|'}</span>
          </span>
        ))}
      </div>
    </div>
  );
}

/* ── Odds-style row ── */
function OddsRow({ pA, pDraw, pB, nameA, nameB }) {
  const toOdds = (pct) => pct > 0 ? (100 / pct).toFixed(2) : 'N/A';
  const items = [
    { label: nameA || 'Team A', odds: toOdds(pA),    pct: pA },
    { label: 'Draw',            odds: toOdds(pDraw), pct: pDraw },
    { label: nameB || 'Team B', odds: toOdds(pB),    pct: pB },
  ];
  const bestIdx = [pA, pDraw, pB].indexOf(Math.max(pA, pDraw, pB));
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6, marginTop: 10 }}>
      {items.map((it, i) => (
        <div key={i} style={{
          textAlign: 'center',
          background: i === bestIdx ? 'var(--orange-50)' : 'var(--grey-50)',
          border: i === bestIdx ? '1px solid rgba(241,86,35,0.3)' : '1px solid var(--grey-200)',
          borderRadius: 5, padding: '5px 4px',
        }}>
          <div style={{ fontSize: 9.5, color: 'var(--grey-500)', fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 2, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {it.label}
          </div>
          <div className="font-mono" style={{ fontSize: 13, fontWeight: 800, color: i === bestIdx ? 'var(--orange)' : 'var(--ink)' }}>
            {it.odds}
          </div>
        </div>
      ))}
    </div>
  );
}

/* ── Winner card ── */
function WinnerCard({ name, phone }) {
  const initial = name ? name.trim()[0].toUpperCase() : '?';
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12,
      padding: '10px 14px',
      background: 'var(--grey-50, #fafafa)',
      border: '1px solid var(--grey-200)',
      borderRadius: 8,
      marginBottom: 8,
    }}>
      <div style={{
        width: 34, height: 34, borderRadius: '50%',
        background: 'var(--ink)', color: '#fff',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontSize: 14, fontWeight: 800, flexShrink: 0,
      }}>{initial}</div>
      <div>
        <div style={{ fontWeight: 700, fontSize: 14, color: 'var(--ink)', lineHeight: 1.2 }}>{name}</div>
        <div style={{ fontSize: 12, color: 'var(--grey-500)', letterSpacing: '0.06em', marginTop: 2 }}>{phone}</div>
      </div>
    </div>
  );
}

/* ── Draw winners section (public) ── */
function DrawWinnersSection() {
  const [winners, setWinners] = useState([]);
  const [loaded,  setLoaded]  = useState(false);

  useEffect(() => {
    fetch('/api/draw-winners')
      .then(r => r.json())
      .then(d => { setWinners(Array.isArray(d) ? d : []); setLoaded(true); })
      .catch(() => setLoaded(true));
  }, []);

  if (!loaded || winners.length === 0) return null;

  const campaign = winners.filter(w => w.prize_type === 'campaign');
  const weekly   = winners.filter(w => w.prize_type === 'weekly')
    .sort((a, b) => (a.scope_key || '').localeCompare(b.scope_key || ''));
  const matchday = winners.filter(w => w.prize_type === 'matchday');

  // Group matchday by scope_key, ascending order
  const mdMap = {};
  matchday.forEach(w => {
    if (!mdMap[w.scope_key]) mdMap[w.scope_key] = { label: w.scope_label || w.scope_key, ws: [] };
    mdMap[w.scope_key].ws.push(w);
  });
  const mdGroups = Object.entries(mdMap)
    .sort((a, b) => a[0].localeCompare(b[0]))
    .map(([, g]) => g);

  const colStyle = {
    background: '#fff', border: '1px solid var(--grey-200)',
    borderRadius: 10, padding: '18px 20px',
    boxShadow: '0 2px 8px rgba(17,6,24,0.05)',
  };
  const headStyle = { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 16 };
  const subLabel  = { fontSize: 10, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', fontWeight: 700, marginBottom: 6 };

  return (
    <div style={{ marginBottom: 40 }}>
      <SectionHead
        title="Draw winners"
        sub="Official prize draw results — confirmed by SunFront."
      />

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 20 }} className="winners-grid">

        {/* Column 1 — Match Day */}
        <div style={colStyle}>
          <div style={headStyle}>
            <span style={{ fontSize: 16 }}>⚽</span>
            <span className="font-display" style={{ fontSize: 16, letterSpacing: '-0.01em' }}>Match Day Winners</span>
          </div>
          {mdGroups.length === 0
            ? <p style={{ color: 'var(--grey-400)', fontSize: 13, margin: 0 }}>Draw pending</p>
            : mdGroups.map(group => (
              <div key={group.label} style={{ marginBottom: 14 }}>
                <div style={subLabel}>{group.label}</div>
                {group.ws.map(w => <WinnerCard key={w.id} name={w.winner_name} phone={w.winner_phone} />)}
              </div>
            ))
          }
        </div>

        {/* Column 2 — Weekly */}
        <div style={colStyle}>
          <div style={headStyle}>
            <span style={{ fontSize: 16 }}>⭐</span>
            <span className="font-display" style={{ fontSize: 16, letterSpacing: '-0.01em' }}>Weekly Winners</span>
          </div>
          {weekly.length === 0
            ? <p style={{ color: 'var(--grey-400)', fontSize: 13, margin: 0 }}>Draw pending</p>
            : weekly.map(w => (
              <div key={w.id} style={{ marginBottom: 14 }}>
                {w.scope_label && <div style={subLabel}>{w.scope_label}</div>}
                <WinnerCard name={w.winner_name} phone={w.winner_phone} />
              </div>
            ))
          }
        </div>

        {/* Column 3 — Grand Prize */}
        <div style={{
          ...colStyle,
          background: campaign.length > 0
            ? 'linear-gradient(135deg, #78350f 0%, #92400e 100%)'
            : '#fff',
          border: campaign.length > 0 ? '2px solid #f59e0b' : '1px solid var(--grey-200)',
          boxShadow: campaign.length > 0 ? '0 8px 32px rgba(245,158,11,0.15)' : colStyle.boxShadow,
        }}>
          <div style={headStyle}>
            <span style={{ fontSize: 16 }}>🏆</span>
            <span className="font-display" style={{ fontSize: 16, letterSpacing: '-0.01em', color: campaign.length > 0 ? '#fcd34d' : 'inherit' }}>
              Grand Prize
            </span>
          </div>
          {campaign.length === 0
            ? <p style={{ color: 'var(--grey-400)', fontSize: 13, margin: 0 }}>Draw pending</p>
            : campaign.map(w => (
              <div key={w.id} style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 10 }}>
                <div style={{
                  width: 44, height: 44, borderRadius: '50%',
                  background: '#f59e0b', color: '#fff',
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 18, fontWeight: 900, flexShrink: 0,
                }}>{w.winner_name.trim()[0].toUpperCase()}</div>
                <div>
                  <div className="font-display" style={{ fontSize: 18, color: '#fff', letterSpacing: '-0.01em', lineHeight: 1.1 }}>{w.winner_name}</div>
                  <div style={{ fontSize: 12, color: '#fcd34d', letterSpacing: '0.08em', marginTop: 3 }}>{w.winner_phone}</div>
                </div>
              </div>
            ))
          }
        </div>

      </div>
    </div>
  );
}

/* ── Settled match accordion row ── */
function SettledMatchRow({ match }) {
  if (!match) return null;
  const [open, setOpen] = React.useState(false);
  const parts = (match.label || '').split(/\s+vs\.?\s+/i);
  const nameA = parts[0] || 'Team A';
  const nameB = parts[1] || 'Team B';
  const cfg = VERDICT_CFG[match.verdict] || VERDICT_CFG.SPLIT;
  const correct = match.actual && match.actual.correct;

  return (
    <div style={{ border: '1px solid var(--grey-200)', borderRadius: 8, overflow: 'hidden', background: '#fff' }}>
      <div style={{ height: 3, background: cfg.bg === 'var(--grey-200)' ? 'var(--grey-300)' : cfg.bg }} />
      <button
        onClick={() => setOpen(function(o) { return !o; })}
        aria-expanded={open}
        style={{
          width: '100%', display: 'flex', alignItems: 'center', gap: 12,
          padding: '11px 16px', background: 'transparent', border: 'none', cursor: 'pointer', textAlign: 'left',
        }}
      >
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="font-display" style={{ fontSize: 14, letterSpacing: '-0.01em', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
            {match.label}
          </div>
          {match.actual && (
            <div style={{ fontSize: 12, color: 'var(--grey-500)', marginTop: 2, fontWeight: 600 }}>
              {nameA} <span style={{ fontWeight: 800, color: 'var(--ink)' }}>{match.actual.scoreA} – {match.actual.scoreB}</span> {nameB}
            </div>
          )}
        </div>
        <span style={{
          flexShrink: 0, fontSize: 10, fontWeight: 800, letterSpacing: '0.1em', textTransform: 'uppercase',
          padding: '3px 10px', borderRadius: 4,
          background: correct ? 'var(--success)' : 'var(--grey-100)',
          color: correct ? '#fff' : 'var(--grey-500)',
        }}>{correct ? 'Crowd ✓' : 'Crowd ✗'}</span>
        <VerdictChip verdict={match.verdict} />
        <span style={{ color: 'var(--grey-400)', fontSize: 12, lineHeight: 1, flexShrink: 0, marginLeft: 4 }}>
          {open ? '▲' : '▼'}
        </span>
      </button>
      {open && (
        <div style={{ borderTop: '1px solid var(--grey-100)', padding: '12px 16px 16px' }}>
          <MatchBar pA={match.pA} pDraw={match.pDraw} pB={match.pB} labelA={nameA} labelB={nameB} />
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 6, marginTop: 10 }}>
            {[
              { label: nameA, pct: match.pA,    color: 'var(--ink)' },
              { label: 'Draw', pct: match.pDraw, color: 'var(--grey-400)' },
              { label: nameB, pct: match.pB,    color: 'var(--orange)' },
            ].map(function(seg, i) { return (
              <div key={i} style={{ textAlign: 'center' }}>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5 }}>
                  <span style={{ width: 8, height: 8, background: seg.color, flexShrink: 0, borderRadius: 1 }} />
                  <span style={{ fontSize: 11, fontWeight: 600, color: 'var(--grey-600)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 70 }}>{seg.label}</span>
                </div>
                <div className="font-display" style={{ fontSize: 22, lineHeight: 1.1, color: seg.color, marginTop: 4 }}>{seg.pct}%</div>
              </div>
            ); })}
          </div>
          <OddsRow pA={match.pA} pDraw={match.pDraw} pB={match.pB} nameA={nameA} nameB={nameB} />
          {match.actual && <ActualResultRow actual={match.actual} crowdPick={match.crowdPick} nameA={nameA} nameB={nameB} />}
        </div>
      )}
    </div>
  );
}

/* ── Main dashboard page ── */
function DashboardPage() {
  const [data, setData]     = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError]   = useState(null);
  const [tick, setTick]     = useState(0);
  const [teamFilter, setTeamFilter] = useState('all');

  useEffect(() => {
    let cancel = false;
    setLoading(prev => prev || true);
    fetch('/api/dashboard-stats')
      .then(r => r.json())
      .then(d => { if (!cancel) { setData(d); setLoading(false); setError(null); } })
      .catch(e => { if (!cancel) { setError('Could not load stats.'); setLoading(false); } });
    return () => { cancel = true; };
  }, [tick]);

  // Auto-refresh every 45 seconds
  useEffect(() => {
    const id = setInterval(() => setTick(t => t + 1), 45000);
    return () => clearInterval(id);
  }, []);

  if (loading && !data) return <DashSkeleton />;

  if (error && !data) {
    return (
      <div style={{ maxWidth: 480, margin: '80px auto', padding: '0 22px', textAlign: 'center' }}>
        <div className="font-display" style={{ fontSize: 22, marginBottom: 10 }}>Could not load stats</div>
        <p style={{ color: 'var(--grey-500)', fontSize: 14 }}>Check your connection and try again.</p>
        <button onClick={() => setTick(t => t+1)} style={{
          marginTop: 16, background: 'var(--ink)', color: '#fff', border: 'none',
          padding: '10px 28px', fontWeight: 700, fontSize: 13, letterSpacing: '0.06em', cursor: 'pointer',
        }}>Retry</button>
      </div>
    );
  }

  const pulse   = data.pulse   || {};
  const matches = data.matches || [];
  const momentum = data.momentum || [];
  const accuracy = data.accuracy || null;
  const topPredictors = data.topPredictors || [];

  const dirSub = {
    up:   'More predictions this week vs last',
    down: 'Slower week than the previous',
    flat: 'Consistent pace week over week',
  };

  return (
    <main>
      {/* ── Campaign banner ── */}
      <InnerPageBanner />

      {/* ── Page band ── */}
      <PageBand
        eyebrow="Live campaign stats"
        title={<>The crowd<br />has spoken.</>}
        right={<LivePill ts={data._ts || Date.now()} />}
      />

      <div style={{ maxWidth: 1200, margin: '0 auto', padding: '32px 22px 64px' }}>

        {/* ── Section 1: Campaign Pulse ── */}
        <div style={{ marginBottom: 40 }}>
          <SectionHead
            title="Campaign pulse"
            sub="Four crowd signals updated every 45 seconds."
          />
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14 }} className="pulse-grid">
            <PulseCard
              label="Avg crowd consensus"
              value={<div className="font-display" style={{ fontSize: 40, lineHeight: 1, letterSpacing: '-0.02em', color: 'var(--orange)' }}><PctCounter value={pulse.avgConsensus || 0} /></div>}
              sub="Mean winning pick % across all matches"
              accent="orange"
            />
            <PulseCard
              label="Coverage"
              value={<div className="font-display" style={{ fontSize: 40, lineHeight: 1, letterSpacing: '-0.02em', color: 'var(--ink)' }}><PctCounter value={pulse.coverage || 0} /></div>}
              sub="Bills that have cast at least one vote"
              accent="ink"
            />
            <PulseCard
              label="Momentum"
              value={<MomentumBadge dir={pulse.momentumDir || 'flat'} />}
              sub={dirSub[pulse.momentumDir] || dirSub.flat}
              accent="green"
            />
            <PulseCard
              label="Match spread"
              value={<div className="font-display" style={{ fontSize: 40, lineHeight: 1, letterSpacing: '-0.02em', color: 'var(--grey-400)' }}><PctCounter value={pulse.outletSpread || 0} /></div>}
              sub="How evenly predictions spread across matches"
              accent="grey"
            />
          </div>
        </div>

        {/* ── Section 2: Momentum Curve + Top Predictors ── */}
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.4fr) minmax(0, 1fr)', gap: 22, marginBottom: 40 }} className="bottom-grid">
          {/* Momentum curve */}
          <div>
            <SectionHead
              title="Momentum curve"
              sub="Crowd fever, charted daily -- the hottest day takes the trophy at 100."
            />
            <div style={{
              border: '1px solid var(--grey-200)',
              borderRadius: 8,
              padding: '16px 20px 10px',
              background: '#fff',
            }}>
              <MomentumCurve data={momentum} />
            </div>
          </div>

          {/* Top Predictors */}
          <div>
            <SectionHead
              title="Top predictors"
              sub="5 customers with most correct picks."
            />
            <TopPredictorsPanel predictors={topPredictors} />
          </div>
        </div>

        {/* ── Section 3: Match Verdict Grid ── */}
        <div style={{ marginBottom: 40 }}>
          <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 16, marginBottom: 20 }}>
            <div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                <div style={{ width: 4, height: 28, background: 'var(--orange)', flexShrink: 0 }} />
                <h2 className="font-display" style={{ fontSize: 22, letterSpacing: '-0.01em', margin: 0 }}>Match verdict</h2>
              </div>
              <p style={{ margin: '6px 0 0 16px', fontSize: 13, color: 'var(--grey-500)', fontWeight: 500 }}>Where the crowd stands on every tracked match.</p>
            </div>
            {matches.length > 0 && (() => {
              const allTeams = [...new Set(
                matches.flatMap(m =>
                  (m.label || '').split(/\s+vs\.?\s+/i).map(t => t.trim()).filter(Boolean)
                )
              )].sort();
              return (
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
                  <label style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: 'var(--grey-500)', whiteSpace: 'nowrap' }}>
                    Filter
                  </label>
                  <select
                    value={teamFilter}
                    onChange={e => setTeamFilter(e.target.value)}
                    style={{
                      border: '1.5px solid var(--grey-200)',
                      borderRadius: 5,
                      padding: '7px 32px 7px 12px',
                      fontSize: 13,
                      fontWeight: 600,
                      color: 'var(--ink)',
                      background: '#fff',
                      cursor: 'pointer',
                      outline: 'none',
                      appearance: 'none',
                      backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23888' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E")`,
                      backgroundRepeat: 'no-repeat',
                      backgroundPosition: 'right 10px center',
                      minWidth: 160,
                    }}
                  >
                    <option value="all">All Teams</option>
                    {allTeams.map(t => <option key={t} value={t}>{t}</option>)}
                  </select>
                </div>
              );
            })()}
          </div>
          {(() => {
            const filtered = teamFilter === 'all'
              ? matches
              : matches.filter(m => {
                  const parts = (m.label || '').split(/\s+vs\.?\s+/i).map(t => t.trim());
                  return parts.some(t => t.toLowerCase() === teamFilter.toLowerCase());
                });
            if (matches.length === 0) {
              return (
                <div style={{ border: '1px solid var(--grey-200)', borderRadius: 8, padding: '40px 24px', textAlign: 'center', background: 'var(--grey-50)' }}>
                  <div style={{ fontSize: 13, color: 'var(--grey-500)', fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
                    No predictions yet
                  </div>
                  <div style={{ fontSize: 12, color: 'var(--grey-400)', marginTop: 6 }}>
                    Verdicts appear once predictions are submitted.
                  </div>
                </div>
              );
            }
            if (filtered.length === 0) {
              return (
                <div style={{ border: '1px solid var(--grey-200)', borderRadius: 8, padding: '32px 24px', textAlign: 'center', background: 'var(--grey-50)' }}>
                  <div style={{ fontSize: 13, color: 'var(--grey-500)', fontWeight: 600, letterSpacing: '0.08em', textTransform: 'uppercase' }}>
                    No matches for {teamFilter}
                  </div>
                  <div style={{ fontSize: 12, color: 'var(--grey-400)', marginTop: 6 }}>
                    Try a different team filter.
                  </div>
                </div>
              );
            }
            const openMatches = filtered.filter(m => !m.actual).sort((a, b) => {
              const fa = MATCHES.find(x => x.id === a.id);
              const fb = MATCHES.find(x => x.id === b.id);
              return (fa ? fa.kickoffMs : 0) - (fb ? fb.kickoffMs : 0); // ascending
            });
            const settledMatches = filtered.filter(m => !!m.actual).sort((a, b) => {
              const fa = MATCHES.find(x => x.id === a.id);
              const fb = MATCHES.find(x => x.id === b.id);
              return (fb ? fb.kickoffMs : 0) - (fa ? fa.kickoffMs : 0); // most recent settled first
            });
            return (
              <div>
                {openMatches.length > 0 && (
                  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 14, marginBottom: settledMatches.length > 0 ? 20 : 0 }} className="verdict-grid">
                    {openMatches.map((m, i) => (
                      <MatchVerdictCard key={m.id} match={m} delay={i * 60} />
                    ))}
                  </div>
                )}
                {settledMatches.length > 0 && (
                  <div>
                    {openMatches.length > 0 && (
                      <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: 'var(--grey-500)', marginBottom: 10 }}>
                        Results — {settledMatches.length} settled
                      </div>
                    )}
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                      {settledMatches.map((m) => (
                        <SettledMatchRow key={m.id} match={m} />
                      ))}
                    </div>
                  </div>
                )}
              </div>
            );
          })()}
        </div>

        {/* ── Section 4: Crowd Track Record ── */}
        <div style={{ marginBottom: 40 }}>
          <SectionHead
            title="Crowd track record"
            sub="How often the majority pick was the right call."
          />
          <TrackRecord accuracy={accuracy} />
        </div>
      </div>

      {/* ── Draw Winners ── */}
      <div style={{ maxWidth: 1200, margin: '0 auto', padding: '0 22px' }}>
        <DrawWinnersSection />
      </div>

      {/* Sponsor -- JBL (placed where prize banner was) */}
      <SponsorStrip />

      <style>{`
        @media (max-width: 760px) {
          .pulse-grid   { grid-template-columns: repeat(2, 1fr) !important; }
          .verdict-grid { grid-template-columns: 1fr !important; }
          .bottom-grid  { grid-template-columns: 1fr !important; }
          .winners-grid { grid-template-columns: 1fr !important; }
        @media (max-width: 900px) and (min-width: 761px) {
          .winners-grid { grid-template-columns: repeat(2, 1fr) !important; }
        }
        }
        @media (max-width: 460px) {
          .pulse-grid   { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </main>
  );
}

Object.assign(window, { DashboardPage, MyPredictions });
