// fp-performance.jsx — Performance Tracker, ROI, Bet History
const { useState: usePS, useEffect: usePE, useMemo: usePM, useRef: usePR } = React;

// ─── Animated Number ──────────────────────────────────────────
function AnimNum({ value, prefix='', suffix='', color='#22ff88', size=28, decimals=0 }) {
  const [display, setDisplay] = usePS(0);
  const target = parseFloat(value) || 0;
  usePE(() => {
    let start = null, from = 0;
    const dur = 900;
    const step = ts => {
      if (!start) start = ts;
      const p = Math.min((ts - start) / dur, 1);
      const ease = 1 - Math.pow(1 - p, 3);
      setDisplay(from + (target - from) * ease);
      if (p < 1) requestAnimationFrame(step);
    };
    requestAnimationFrame(step);
  }, [target]);
  const formatted = decimals > 0 ? display.toFixed(decimals) : Math.round(display).toString();
  return (
    <span style={{ fontSize: size, fontWeight: 700, fontFamily: 'JetBrains Mono', color, animation: 'numFlip .4s ease' }}>
      {prefix}{formatted}{suffix}
    </span>
  );
}

// ─── Mini Sparkline ───────────────────────────────────────────
function Sparkline({ data, color = '#22ff88', height = 36, width = 120 }) {
  if (!data || data.length < 2) return null;
  const min = Math.min(...data);
  const max = Math.max(...data);
  const range = max - min || 1;
  const pts = data.map((v, i) => {
    const x = (i / (data.length - 1)) * width;
    const y = height - ((v - min) / range) * (height - 4) - 2;
    return `${x},${y}`;
  }).join(' ');
  const lastPt = pts.split(' ').pop().split(',');
  return (
    <svg width={width} height={height} style={{ overflow: 'visible' }}>
      <defs>
        <linearGradient id="sparkGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.3" />
          <stop offset="100%" stopColor={color} stopOpacity="0.02" />
        </linearGradient>
      </defs>
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" opacity="0.9" />
      <circle cx={lastPt[0]} cy={lastPt[1]} r="3" fill={color} style={{ filter: `drop-shadow(0 0 4px ${color})` }} />
    </svg>
  );
}

// ─── ROI Chart (last 30 days cumulative P&L) ─────────────────
function PLChart({ bets }) {
  const settled = bets.filter(b => b.status !== 'pending').slice(0, 30).reverse();
  if (settled.length === 0) return null;
  let cum = 0;
  const points = settled.map(b => { cum += b.profit || 0; return cum; });
  const min = Math.min(0, ...points);
  const max = Math.max(0, ...points);
  const range = max - min || 1;
  const W = 310, H = 80;
  const toX = i => (i / (points.length - 1)) * W;
  const toY = v => H - 8 - ((v - min) / range) * (H - 16);
  const pathD = points.map((v, i) => `${i === 0 ? 'M' : 'L'} ${toX(i).toFixed(1)} ${toY(v).toFixed(1)}`).join(' ');
  const areaD = `${pathD} L ${toX(points.length-1).toFixed(1)} ${H} L ${toX(0).toFixed(1)} ${H} Z`;
  const lastVal = points[points.length - 1];
  const lineColor = lastVal >= 0 ? '#22ff88' : '#ff5470';
  const zeroY = toY(0);

  return (
    <div style={{ padding: '12px 16px', background: 'rgba(255,255,255,0.025)', borderRadius: 16, border: '1px solid rgba(255,255,255,0.07)', marginBottom: 14 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
        <span style={{ fontSize: 9, color: 'rgba(255,255,255,0.35)', fontFamily: 'JetBrains Mono', letterSpacing: '.12em' }}>P&L VERLAUF ({settled.length} WETTEN)</span>
        <span style={{ fontSize: 13, fontWeight: 700, fontFamily: 'JetBrains Mono', color: lineColor }}>
          {lastVal >= 0 ? '+' : ''}€{lastVal.toFixed(2)}
        </span>
      </div>
      <svg width={W} height={H} style={{ overflow: 'visible', display: 'block' }}>
        <defs>
          <linearGradient id="plGrad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor={lineColor} stopOpacity="0.25" />
            <stop offset="100%" stopColor={lineColor} stopOpacity="0.01" />
          </linearGradient>
        </defs>
        {/* Zero line */}
        <line x1="0" y1={zeroY} x2={W} y2={zeroY} stroke="rgba(255,255,255,0.08)" strokeWidth="1" strokeDasharray="4,4" />
        <path d={areaD} fill="url(#plGrad)" />
        <path d={pathD} fill="none" stroke={lineColor} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ filter: `drop-shadow(0 0 4px ${lineColor}80)` }} />
        {/* Last point dot */}
        <circle cx={toX(points.length-1)} cy={toY(lastVal)} r="4" fill={lineColor} style={{ filter: `drop-shadow(0 0 6px ${lineColor})` }} />
      </svg>
    </div>
  );
}

// ─── Stat Card ────────────────────────────────────────────────
function StatCard({ label, value, suffix, prefix, color, sub, icon, sparkData }) {
  return (
    <div style={{
      background: `${color}08`, border: `1px solid ${color}22`, borderRadius: 16,
      padding: '12px 14px', backdropFilter: 'blur(12px)',
      boxShadow: `inset 0 1px 0 rgba(255,255,255,0.04)`,
    }}>
      <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.35)', fontFamily: 'JetBrains Mono', letterSpacing: '.12em', marginBottom: 6 }}>
        {icon} {label}
      </div>
      <AnimNum value={value} prefix={prefix||''} suffix={suffix||''} color={color} size={24} decimals={suffix==='%'||prefix==='€'?1:0} />
      {sub && <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.3)', fontFamily: 'Inter', marginTop: 4 }}>{sub}</div>}
      {sparkData && <div style={{ marginTop: 8 }}><Sparkline data={sparkData} color={color} width={100} height={28} /></div>}
    </div>
  );
}

// ─── Bet Row ──────────────────────────────────────────────────
function BetRow({ bet, onSettle }) {
  const isPending = bet.status === 'pending';
  const isWon = bet.status === 'won';
  const sc = isPending ? 'rgba(255,255,255,0.3)' : isWon ? '#22ff88' : '#ff5470';

  return (
    <div style={{
      padding: '10px 12px',
      background: isPending ? 'rgba(255,255,255,0.025)' : isWon ? 'rgba(34,255,136,0.06)' : 'rgba(255,84,112,0.06)',
      border: `1px solid ${isPending ? 'rgba(255,255,255,0.06)' : sc + '22'}`,
      borderRadius: 12, marginBottom: 6, animation: 'fadeUp .3s ease',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        <div style={{ width: 28, height: 28, borderRadius: 8, background: sc + '15', border: `1px solid ${sc}33`, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, flexShrink: 0 }}>
          {isPending ? '⏳' : isWon ? '✅' : '❌'}
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 11, fontWeight: 600, color: 'rgba(255,255,255,0.85)', fontFamily: 'Space Grotesk', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{bet.bet_label}</div>
          <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.3)', fontFamily: 'JetBrains Mono', marginTop: 1 }}>
            {bet.match} · {bet.date} · {bet.league}
          </div>
        </div>
        <div style={{ textAlign: 'right', flexShrink: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 700, fontFamily: 'JetBrains Mono', color: '#ffb648' }}>{bet.odds?.toFixed(2)}</div>
          {!isPending && (
            <div style={{ fontSize: 10, fontFamily: 'JetBrains Mono', color: sc, fontWeight: 700 }}>
              {isWon ? `+€${((bet.stake||10)*(bet.odds||1)-( bet.stake||10)).toFixed(2)}` : `-€${(bet.stake||10).toFixed(2)}`}
            </div>
          )}
        </div>
        {isPending && (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, flexShrink: 0 }}>
            <button onClick={() => onSettle(bet.id, true)} style={{ padding: '3px 8px', borderRadius: 6, background: 'rgba(34,255,136,0.15)', border: '1px solid rgba(34,255,136,0.3)', color: '#22ff88', cursor: 'pointer', fontSize: 10, fontFamily: 'JetBrains Mono', fontWeight: 700 }}>✓ Treffer</button>
            <button onClick={() => onSettle(bet.id, false)} style={{ padding: '3px 8px', borderRadius: 6, background: 'rgba(255,84,112,0.15)', border: '1px solid rgba(255,84,112,0.3)', color: '#ff5470', cursor: 'pointer', fontSize: 10, fontFamily: 'JetBrains Mono', fontWeight: 700 }}>✗ Daneben</button>
          </div>
        )}
      </div>
    </div>
  );
}

// ─── Performance Screen ───────────────────────────────────────
function PerformanceScreen({ onAddTestBets }) {
  const [bets, setBets] = usePS(() => perfStore.get());
  const [filterStatus, setFilterStatus] = usePS('all');
  const [showClear, setShowClear] = usePS(false);

  const stats = usePM(() => perfStore.stats(bets), [bets]);
  const filtered = bets.filter(b => filterStatus === 'all' ? true : b.status === filterStatus);
  const plHistory = usePM(() => {
    let cum = 0;
    return bets.filter(b => b.status !== 'pending').slice(0, 20).reverse().map(b => { cum += b.profit || 0; return cum; });
  }, [bets]);

  const settle = (id, won) => setBets(perfStore.settle(id, won));

  const riskBreakdown = usePM(() => {
    const settled = bets.filter(b => b.status !== 'pending');
    const byRisk = { SAFE: { total: 0, won: 0 }, GOOD: { total: 0, won: 0 }, RISK: { total: 0, won: 0 } };
    settled.forEach(b => {
      const r = b.risk || 'GOOD';
      if (byRisk[r]) { byRisk[r].total++; if (b.status === 'won') byRisk[r].won++; }
    });
    return byRisk;
  }, [bets]);

  const noData = bets.length === 0;

  return (
    <div style={{ height: '100%', overflowY: 'auto', padding: '14px 16px' }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
        <div>
          <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.35)', fontFamily: 'JetBrains Mono', letterSpacing: '.14em', marginBottom: 3 }}>DEINE STATISTIKEN</div>
          <div style={{ fontSize: 20, fontWeight: 700, fontFamily: 'Space Grotesk', color: 'rgba(255,255,255,0.95)', letterSpacing: '-.02em' }}>Performance</div>
        </div>
        {bets.length > 0 && (
          <button onClick={() => setShowClear(true)} style={{ padding: '6px 12px', borderRadius: 8, background: 'rgba(255,84,112,0.1)', border: '1px solid rgba(255,84,112,0.2)', color: '#ff5470', cursor: 'pointer', fontFamily: 'JetBrains Mono', fontSize: 10 }}>Reset</button>
        )}
      </div>

      {/* Clear Confirm */}
      {showClear && (
        <div style={{ padding: '12px 14px', background: 'rgba(255,84,112,0.1)', border: '1px solid rgba(255,84,112,0.25)', borderRadius: 14, marginBottom: 14 }}>
          <div style={{ fontSize: 12, color: '#ff5470', fontFamily: 'Inter', marginBottom: 10 }}>Alle Wetten löschen?</div>
          <div style={{ display: 'flex', gap: 8 }}>
            <button onClick={() => { perfStore.clear(); setBets([]); setShowClear(false); }} style={{ flex: 1, padding: '8px', borderRadius: 8, background: 'rgba(255,84,112,0.2)', border: '1px solid rgba(255,84,112,0.3)', color: '#ff5470', cursor: 'pointer', fontFamily: 'Space Grotesk', fontWeight: 600, fontSize: 12 }}>Ja, löschen</button>
            <button onClick={() => setShowClear(false)} style={{ flex: 1, padding: '8px', borderRadius: 8, background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', color: 'rgba(255,255,255,0.5)', cursor: 'pointer', fontFamily: 'Space Grotesk', fontWeight: 600, fontSize: 12 }}>Abbrechen</button>
          </div>
        </div>
      )}

      {noData ? (
        <div style={{ textAlign: 'center', padding: '40px 20px' }}>
          <div style={{ fontSize: 44, marginBottom: 12, opacity: 0.4 }}>📈</div>
          <div style={{ fontSize: 14, color: 'rgba(255,255,255,0.4)', fontFamily: 'Space Grotesk', marginBottom: 8 }}>Noch keine Wetten getrackt</div>
          <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.25)', fontFamily: 'Inter', lineHeight: 1.6 }}>
            Wenn du einen KI-Schein überträgst oder<br/>einen Tipp zum Schein hinzufügst, wird er<br/>hier automatisch gespeichert.
          </div>
          <button onClick={onAddTestBets} style={{ marginTop: 20, padding: '10px 20px', borderRadius: 10, background: 'rgba(36,218,255,0.1)', border: '1px solid rgba(36,218,255,0.25)', color: '#24daff', cursor: 'pointer', fontFamily: 'Space Grotesk', fontWeight: 600, fontSize: 12 }}>
            Demo-Daten laden
          </button>
        </div>
      ) : (
        <>
          {/* Stats Grid */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, marginBottom: 14 }}>
            <StatCard label="TREFFERQUOTE" value={stats.hitRate} suffix="%" color="#22ff88" icon="🎯" sub={`${stats.won}W ${stats.lost}L von ${stats.total}`} />
            <StatCard label="ROI" value={parseFloat(stats.roi)} suffix="%" color={parseFloat(stats.roi) >= 0 ? '#22ff88' : '#ff5470'} icon="💹" sub={`Gesamt-Einsatz €${stats.total * 10}`} />
            <StatCard label="PROFIT" value={Math.abs(parseFloat(stats.profit))} prefix={parseFloat(stats.profit) >= 0 ? '+€' : '-€'} color={parseFloat(stats.profit) >= 0 ? '#ffb648' : '#ff5470'} icon="💰" sub="Netto P&L" />
            <StatCard label="STREAK" value={stats.streak} suffix={stats.streak === 1 ? ' ✓' : ' ✓'} color={stats.streak >= 3 ? '#22ff88' : stats.streak >= 1 ? '#ffb648' : '#ff5470'} icon="🔥" sub={stats.streak > 0 ? `${stats.streak} richtig in Folge` : 'Kein aktiver Streak'} />
          </div>

          {/* P&L Chart */}
          <PLChart bets={bets} />

          {/* Kalibrierung + Source-Gewichte */}
          <CalibrationCard />

          {/* Risk Breakdown */}
          {stats.total > 0 && (
            <div style={{ background: 'rgba(255,255,255,0.025)', border: '1px solid rgba(255,255,255,0.07)', borderRadius: 16, padding: '12px 14px', marginBottom: 14 }}>
              <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.35)', fontFamily: 'JetBrains Mono', letterSpacing: '.12em', marginBottom: 10 }}>TREFFERQUOTE NACH RISIKO</div>
              {Object.entries(riskBreakdown).map(([risk, d]) => d.total > 0 && (
                <div key={risk} style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8 }}>
                  <span style={{ fontSize: 9, fontFamily: 'JetBrains Mono', fontWeight: 700, color: getRiskColor(risk), width: 52, flexShrink: 0 }}>{getRiskIcon(risk)} {risk}</span>
                  <div style={{ flex: 1, height: 6, background: 'rgba(255,255,255,0.06)', borderRadius: 99, overflow: 'hidden' }}>
                    <div style={{ height: '100%', width: `${d.total > 0 ? (d.won/d.total*100) : 0}%`, background: `linear-gradient(90deg, ${getRiskColor(risk)}, ${getRiskColor(risk)}88)`, borderRadius: 99, transition: 'width 0.8s ease' }} />
                  </div>
                  <span style={{ fontSize: 9, fontFamily: 'JetBrains Mono', color: getRiskColor(risk), width: 32, textAlign: 'right', flexShrink: 0 }}>{d.total > 0 ? Math.round(d.won/d.total*100) : 0}%</span>
                  <span style={{ fontSize: 9, color: 'rgba(255,255,255,0.25)', fontFamily: 'JetBrains Mono', width: 30, flexShrink: 0 }}>{d.won}/{d.total}</span>
                </div>
              ))}
            </div>
          )}

          {/* Liga Breakdown */}
          {stats.total > 0 && stats.byLeague && Object.keys(stats.byLeague).length > 0 && (
            <div style={{ background: 'rgba(36,218,255,0.03)', border: '1px solid rgba(36,218,255,0.12)', borderRadius: 16, padding: '12px 14px', marginBottom: 14 }}>
              <div style={{ fontSize: 9, color: '#24daff', fontFamily: 'JetBrains Mono', letterSpacing: '.12em', marginBottom: 10 }}>LIGA-BREAKDOWN</div>
              {Object.entries(stats.byLeague)
                .sort((a, b) => b[1].total - a[1].total)
                .map(([league, d]) => {
                  const hr = d.total > 0 ? Math.round(d.won / d.total * 100) : 0;
                  const pc = d.profit >= 0 ? '#22ff88' : '#ff5470';
                  const barColor = hr >= 60 ? '#22ff88' : hr >= 45 ? '#ffb648' : '#ff5470';
                  return (
                    <div key={league} style={{ marginBottom: 10 }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                          <span style={{ fontSize: 10, fontFamily: 'JetBrains Mono', fontWeight: 700, color: 'rgba(255,255,255,0.75)' }}>{league}</span>
                          <span style={{ fontSize: 8, color: 'rgba(255,255,255,0.3)', fontFamily: 'JetBrains Mono' }}>{d.won}W/{d.total-d.won}L</span>
                        </div>
                        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                          <span style={{ fontSize: 9, fontFamily: 'JetBrains Mono', color: pc, fontWeight: 700 }}>{d.profit >= 0 ? '+' : ''}€{d.profit.toFixed(2)}</span>
                          <span style={{ fontSize: 9, fontFamily: 'JetBrains Mono', color: barColor, background: barColor + '18', padding: '1px 6px', borderRadius: 4 }}>{hr}%</span>
                        </div>
                      </div>
                      <div style={{ height: 5, background: 'rgba(255,255,255,0.05)', borderRadius: 99, overflow: 'hidden' }}>
                        <div style={{ height: '100%', width: `${hr}%`, background: `linear-gradient(90deg, ${barColor}, ${barColor}88)`, borderRadius: 99, transition: 'width 0.8s ease' }} />
                      </div>
                    </div>
                  );
                })}
            </div>
          )}

          {/* Filter + History */}
          <div style={{ display: 'flex', gap: 6, marginBottom: 10 }}>
            {['all','pending','won','lost'].map(f => (
              <button key={f} onClick={() => setFilterStatus(f)} style={{
                padding: '5px 10px', borderRadius: 8, cursor: 'pointer',
                background: filterStatus===f ? 'rgba(36,218,255,0.15)' : 'rgba(255,255,255,0.04)',
                border: `1px solid ${filterStatus===f ? 'rgba(36,218,255,0.4)' : 'rgba(255,255,255,0.07)'}`,
                color: filterStatus===f ? '#24daff' : 'rgba(255,255,255,0.4)',
                fontFamily: 'JetBrains Mono', fontSize: 9, fontWeight: 600,
              }}>{f.toUpperCase()}</button>
            ))}
          </div>
          <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.25)', fontFamily: 'JetBrains Mono', letterSpacing: '.12em', marginBottom: 8 }}>
            WETTEN HISTORY · {filtered.length} EINTRÄGE
          </div>
          {filtered.map(b => <BetRow key={b.id} bet={b} onSettle={settle} />)}
        </>
      )}
      <div style={{ height: 20 }} />
    </div>
  );
}

// ─── Reliability-Diagramm + Source-Weights (Self-Calibration) ─
function CalibrationCard() {
  const bins = window.tracker?.reliabilityBins?.() || [];
  const fit  = window.tracker?.isotonicFit?.() || { ready: false, n: 0 };
  const wts  = window.tracker?.sourceWeights?.() || null;
  const totalN = bins.reduce((a, b) => a + b.n, 0);
  if (totalN < 5) {
    return (
      <div style={{ padding: '14px 16px', background: 'rgba(255,255,255,0.025)', border: '1px solid rgba(255,255,255,0.07)', borderRadius: 16, marginBottom: 14 }}>
        <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.35)', fontFamily: 'JetBrains Mono', letterSpacing: '.12em', marginBottom: 6 }}>📐 KALIBRIERUNG</div>
        <div style={{ fontSize: 11, color: 'rgba(255,255,255,0.4)', fontFamily: 'Inter' }}>
          {totalN === 0 ? 'Noch keine aufgelösten Picks getrackt.' : `Sammle weitere Daten (${totalN}/5) um das Reliability-Diagramm anzuzeigen.`}
        </div>
      </div>
    );
  }
  const W = 290, H = 130, pad = 22;
  const tx = (p) => pad + p * (W - 2*pad);
  const ty = (p) => H - pad - p * (H - 2*pad);
  // Erwartung: y = x (perfekt kalibriert)
  const idealPath = `M ${tx(0)} ${ty(0)} L ${tx(1)} ${ty(1)}`;

  return (
    <div style={{ padding: '14px 16px', background: 'rgba(94,231,255,0.04)', border: '1px solid rgba(94,231,255,0.14)', borderRadius: 16, marginBottom: 14 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 10 }}>
        <span style={{ fontSize: 9, color: '#5ee7ff', fontFamily: 'JetBrains Mono', letterSpacing: '.12em' }}>📐 KALIBRIERUNG · {totalN} PICKS</span>
        <span style={{ fontSize: 9, color: fit.ready ? '#22ff88' : 'rgba(255,255,255,0.3)', fontFamily: 'JetBrains Mono' }}>
          {fit.ready ? '🟢 Isotonic aktiv' : `🟡 ${fit.n}/30 für Auto-Fix`}
        </span>
      </div>
      <svg width={W} height={H} style={{ display: 'block', overflow: 'visible' }}>
        {/* Grid */}
        {[0.25, 0.5, 0.75].map(g => (
          <g key={g}>
            <line x1={tx(g)} y1={pad} x2={tx(g)} y2={H-pad} stroke="rgba(255,255,255,0.05)" />
            <line x1={pad} y1={ty(g)} x2={W-pad} y2={ty(g)} stroke="rgba(255,255,255,0.05)" />
          </g>
        ))}
        {/* Achsen */}
        <line x1={pad} y1={H-pad} x2={W-pad} y2={H-pad} stroke="rgba(255,255,255,0.15)" />
        <line x1={pad} y1={pad} x2={pad} y2={H-pad} stroke="rgba(255,255,255,0.15)" />
        {/* Ideal-Linie */}
        <path d={idealPath} stroke="rgba(255,255,255,0.25)" strokeWidth="1" strokeDasharray="3,3" fill="none" />
        {/* Bins als Punkte */}
        {bins.filter(b => b.n > 0).map((b, i) => {
          const dx = tx(b.avgPredicted);
          const dy = ty(b.hitRate);
          const r = Math.min(8, 2 + Math.sqrt(b.n));
          const offColor = b.hitRate > b.avgPredicted ? '#22ff88' : '#ff5470';
          const dist = Math.abs(b.hitRate - b.avgPredicted);
          const color = dist < 0.05 ? '#5ee7ff' : offColor;
          return (
            <g key={i}>
              <line x1={dx} y1={dy} x2={tx(b.avgPredicted)} y2={ty(b.avgPredicted)} stroke={color} strokeWidth="1" opacity="0.4" />
              <circle cx={dx} cy={dy} r={r} fill={color} fillOpacity="0.2" stroke={color} strokeWidth="1.5" style={{ filter: `drop-shadow(0 0 4px ${color})` }} />
            </g>
          );
        })}
        {/* Achsenlabels */}
        <text x={tx(0)} y={H-4} fontSize="8" fill="rgba(255,255,255,0.4)" fontFamily="JetBrains Mono">0</text>
        <text x={tx(1)-6} y={H-4} fontSize="8" fill="rgba(255,255,255,0.4)" fontFamily="JetBrains Mono">1</text>
        <text x={4} y={ty(0)+3} fontSize="8" fill="rgba(255,255,255,0.4)" fontFamily="JetBrains Mono">0</text>
        <text x={4} y={ty(1)+3} fontSize="8" fill="rgba(255,255,255,0.4)" fontFamily="JetBrains Mono">1</text>
        <text x={W/2-30} y={H-4} fontSize="8" fill="rgba(255,255,255,0.3)" fontFamily="JetBrains Mono">prognose →</text>
      </svg>
      <div style={{ fontSize: 10, color: 'rgba(255,255,255,0.45)', fontFamily: 'Inter', marginTop: 6, lineHeight: 1.5 }}>
        Punkte über der Diagonale = Modell unterschätzt · darunter = überschätzt.
        {fit.ready && ' Isotonic-Regression korrigiert seit ' + fit.n + ' Picks live.'}
      </div>
      {/* Source-Weights */}
      {wts && (
        <div style={{ marginTop: 10, paddingTop: 10, borderTop: '1px solid rgba(255,255,255,0.06)' }}>
          <div style={{ fontSize: 9, color: 'rgba(255,255,255,0.35)', fontFamily: 'JetBrains Mono', letterSpacing: '.12em', marginBottom: 6 }}>
            🎚 GEWICHTE {wts.learned ? '(GELERNT)' : '(DEFAULT)'}
          </div>
          {[['poisson','#5ee7ff'],['elo','#ffb648'],['llm','#bb88ff']].map(([k, c]) => (
            <div key={k} style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
              <span style={{ fontSize: 9, fontFamily: 'JetBrains Mono', color: c, width: 60 }}>{k.toUpperCase()}</span>
              <div style={{ flex: 1, height: 5, background: 'rgba(255,255,255,0.05)', borderRadius: 99, overflow: 'hidden' }}>
                <div style={{ height: '100%', width: `${(wts[k]||0)*100}%`, background: c, opacity: 0.7 }} />
              </div>
              <span style={{ fontSize: 9, fontFamily: 'JetBrains Mono', color: c, width: 36, textAlign: 'right' }}>{Math.round((wts[k]||0)*100)}%</span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { PerformanceScreen, AnimNum, Sparkline, CalibrationCard });
