import { useState, useEffect, useRef } from 'react';
import { useParams, useNavigate, useSearchParams, useLocation } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
  ScanLine, CheckCircle, XCircle, Clock, Loader, Ban,
  ArrowLeft, ChevronRight, ExternalLink, Play, Plus, X as XIcon,
  Trash2, Filter, Copy,
} from 'lucide-react';
import {
  LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip,
  ResponsiveContainer,
} from 'recharts';
import { backtestApi, runsApi, experimentsApi, type BacktestTask } from '../api/client';
import { Loading, ErrorState } from '../components/common/Loading';
import { classifyTradeSleeve, tradeSleeveLabel, type TradeSleeve } from '../lib/tradeSleeves';
import { fmtDate, ansiToHtml } from '../lib/utils';

// ── Shared helpers ───────────────────────────────────────────────────────────

function elapsed(start: string | null, end: string | null): string {
  if (!start) return '—';
  const s = new Date(start).getTime();
  const e = end ? new Date(end).getTime() : Date.now();
  const sec = Math.floor((e - s) / 1000);
  if (sec < 60) return `${sec}s`;
  return `${Math.floor(sec / 60)}m ${sec % 60}s`;
}

function StatusDot({ status }: { status: BacktestTask['status'] }) {
  const map: Record<BacktestTask['status'], { color: string; icon: React.ReactNode; label: string }> = {
    queued:    { color: 'var(--text3)',  icon: <Clock size={13} />,    label: 'queued' },
    running:   { color: 'var(--cyan)',   icon: <Loader size={13} />,   label: 'running' },
    completed: { color: 'var(--green)',  icon: <CheckCircle size={13} />, label: 'completed' },
    failed:    { color: 'var(--red)',    icon: <XCircle size={13} />,  label: 'failed' },
    cancelled: { color: 'var(--text3)', icon: <Ban size={13} />,       label: 'cancelled' },
  };
  const { color, icon, label } = map[status] ?? map.queued;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      fontFamily: 'var(--font-mono)', fontSize: 12,
      color,
      animation: status === 'running' ? 'pulse 1.5s ease-in-out infinite' : 'none',
    }}>
      {icon} {label}
    </span>
  );
}

interface DupState {
  exp: string;
  capital: number;
  year: string | null;
  start: string | null;
  end: string | null;
  no_trades: boolean;
  fixed_capital: boolean;
  parking: string | null;
  idle_alpha: string | null;
  form4_sleeve: string | null;
  ownership_sleeve: string | null;
  risk_off_sleeve: string | null;
  snapshot_id: string | null;
}

function makeDupState(task: BacktestTask): DupState {
  const isYear = !!task.year;
  return {
    exp: task.experiment_name,
    capital: task.capital ?? 10000,
    year: isYear ? task.year! : null,
    start: !isYear ? task.start_date : null,
    end: !isYear ? task.end_date ?? null : null,
    no_trades: task.no_trades ?? false,
    fixed_capital: task.fixed_capital ?? false,
    parking: task.parking ?? null,
    idle_alpha: task.idle_alpha ?? null,
    form4_sleeve: task.form4_sleeve ?? null,
    ownership_sleeve: task.ownership_sleeve ?? null,
    risk_off_sleeve: task.risk_off_sleeve ?? null,
    snapshot_id: task.snapshot_id ?? null,
  };
}

// ── Backtest Task List Page ──────────────────────────────────────────────────

const inputStyle: React.CSSProperties = {
  width: '100%',
  padding: '7px 10px',
  fontSize: 14,
  fontFamily: 'var(--font-mono)',
  background: 'var(--bg2)',
  border: '1px solid var(--border-md)',
  borderRadius: 7,
  color: 'var(--text1)',
  outline: 'none',
  boxSizing: 'border-box',
};

function TerminalLog({ text, large = false }: { text: string; large?: boolean }) {
  return (
    <pre
      style={{
        fontFamily: 'var(--font-mono)',
        fontSize: large ? 13 : 12,
        color: large ? 'rgba(230,237,243,0.85)' : 'var(--text2)',
        lineHeight: large ? 1.7 : 1.6,
        margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-all',
        ...(large ? {} : { maxHeight: 320, overflow: 'auto' }),
      }}
      dangerouslySetInnerHTML={{ __html: ansiToHtml(text) }}
    />
  );
}

function SleeveBadge({ sleeve }: { sleeve: TradeSleeve }) {
  const tone = sleeve === 'parking'
    ? { color: 'var(--gold)', bg: 'var(--gold-dim)' }
    : sleeve === 'ownership'
      ? { color: 'var(--violet, var(--cyan))', bg: 'color-mix(in srgb, var(--violet, var(--cyan)) 12%, transparent)' }
    : sleeve === 'risk_off_alpha'
      ? { color: 'var(--orange)', bg: 'color-mix(in srgb, var(--orange) 12%, transparent)' }
    : sleeve === 'idle_alpha'
      ? { color: 'var(--cyan)', bg: 'var(--cyan-dim)' }
      : { color: 'var(--text2)', bg: 'var(--bg2)' };
  return (
    <span style={{
      display: 'inline-flex',
      alignItems: 'center',
      padding: '2px 8px',
      borderRadius: 999,
      fontFamily: 'var(--font-mono)',
      fontSize: 11,
      fontWeight: 600,
      letterSpacing: '0.04em',
      color: tone.color,
      background: tone.bg,
      whiteSpace: 'nowrap',
    }}>
      {tradeSleeveLabel(sleeve)}
    </span>
  );
}

// ── Backtest Task List Page ───────────────────────────────────────────────────

export function BacktestPage() {
  const navigate = useNavigate();
  const location = useLocation();
  const qc = useQueryClient();
  const [searchParams, setSearchParams] = useSearchParams();
  // Run form visibility: auto-open when ?exp= param present
  const expParam = searchParams.get('exp') ?? '';
  const [showForm, setShowForm] = useState(!!expParam);
  const [selectedExps, setSelectedExps] = useState<string[]>(() =>
    expParam ? expParam.split(',').filter(Boolean) : []
  );
  const [expInput, setExpInput] = useState('');
  const [showExpDrop, setShowExpDrop] = useState(false);
  const expInputRef = useRef<HTMLInputElement>(null);
  const dropRef = useRef<HTMLDivElement>(null);

  // Date mode: 'year' (single YYYY) or 'range' (start + optional end)
  const [dateMode, setDateMode] = useState<'year' | 'range'>('range');
  const [year, setYear] = useState('2022');
  const [startDate, setStartDate] = useState('2022');
  const [endDate, setEndDate] = useState('');
  const [capital, setCapital] = useState('10000');
  const [noTrades, setNoTrades] = useState(false);
  const [fixedCapital, setFixedCapital] = useState(false);
  const [directMode, setDirectMode] = useState(true);
  const [parking, setParking] = useState('');
  const [idleAlpha, setIdleAlpha] = useState('');
  const [form4Sleeve, setForm4Sleeve] = useState('');
  const [ownershipSleeve, setOwnershipSleeve] = useState('');
  const [riskOffSleeve, setRiskOffSleeve] = useState('');
  const [snapshotId, setSnapshotId] = useState('');

  // Directly apply dup state to form — used both inline and on mount
  const applyDup = (s: DupState) => {
    setSelectedExps(s.exp.split(', ').map(n => n.trim()).filter(Boolean));
    setShowForm(true);
    setCapital(String(s.capital ?? 10000));
    if (s.year) {
      setDateMode('year');
      setYear(s.year);
      setStartDate('');
      setEndDate('');
    } else if (s.start) {
      setDateMode('range');
      setStartDate(s.start);
      setYear('');
      setEndDate(s.end ?? '');
    } else {
      setDateMode('range');
      setYear('');
      setStartDate('');
      setEndDate('');
    }
    setNoTrades(s.no_trades ?? false);
    setFixedCapital(s.fixed_capital ?? false);
    setParking(s.parking ?? '');
    setIdleAlpha(s.idle_alpha ?? '');
    setForm4Sleeve(s.form4_sleeve ?? '');
    setOwnershipSleeve(s.ownership_sleeve ?? '');
    setRiskOffSleeve(s.risk_off_sleeve ?? '');
    setSnapshotId(s.snapshot_id ?? '');
  };

  // On mount: apply location.state if it came from a Duplicate button on another page
  useEffect(() => {
    const state = location.state as DupState | null;
    if (state?.exp) applyDup(state);
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  // Open form when ?exp= URL param present (from ExperimentDetail / Experiments pages)
  useEffect(() => {
    if (expParam) {
      const names = expParam.split(',').filter(Boolean);
      setSelectedExps(names);
      setShowForm(true);
      setSearchParams({}, { replace: true });
    }
  }, [expParam]);

  // Parking presets
  const { data: parkingPresetsData } = useQuery({
    queryKey: ['parking-presets'],
    queryFn: () => backtestApi.parkingPresets(),
    staleTime: 60_000,
  });
  const { data: idleAlphaPresetsData } = useQuery({
    queryKey: ['idle-alpha-presets'],
    queryFn: () => backtestApi.idleAlphaPresets(),
    staleTime: 60_000,
  });
  const { data: form4PresetsData } = useQuery({
    queryKey: ['form4-capture-presets'],
    queryFn: () => backtestApi.form4CapturePresets(),
    staleTime: 60_000,
  });
  const { data: ownershipPresetsData } = useQuery({
    queryKey: ['ownership-capture-presets'],
    queryFn: () => backtestApi.ownershipCapturePresets(),
    staleTime: 60_000,
  });
  const { data: riskOffPresetsData } = useQuery({
    queryKey: ['risk-off-alpha-presets'],
    queryFn: () => backtestApi.riskOffAlphaPresets(),
    staleTime: 60_000,
  });

  // Available snapshots
  const { data: snapshotsData } = useQuery({
    queryKey: ['backtest-snapshots'],
    queryFn: () => backtestApi.snapshots(),
    staleTime: 60_000,
  });

  // Experiment search
  const { data: expSearchData } = useQuery({
    queryKey: ['exp-search-bt', expInput],
    queryFn: () => experimentsApi.list({ pattern: expInput, limit: 8 }),
    enabled: expInput.length >= 1,
    staleTime: 3000,
  });

  // Fetch config for single selected experiment (to show baked sleeves)
  const singleExp = selectedExps.length === 1 ? selectedExps[0] : null;
  const { data: singleExpConfig } = useQuery({
    queryKey: ['experiment', singleExp],
    queryFn: () => experimentsApi.get(singleExp!),
    enabled: !!singleExp,
    staleTime: 30_000,
  });
  const bakedSleeves = (() => {
    if (!singleExpConfig) return [];
    const ov = (singleExpConfig as any)?.overrides ?? {};
    const out: { label: string; value: string; color: string }[] = [];
    const pk = ov?.risk?.cash_parking_preset;
    if (pk) out.push({ label: '🅿', value: pk, color: 'var(--orange)' });
    const ia = ov?.idle_alpha_sleeve_preset;
    if (ia) out.push({ label: 'IA', value: ia, color: 'var(--green)' });
    const f4 = ov?.form4_capture_sleeve_preset;
    if (f4) out.push({ label: 'F4', value: f4, color: 'var(--cyan)' });
    const ow = ov?.ownership_capture_sleeve_preset;
    if (ow) out.push({ label: '13D', value: ow, color: 'var(--violet, var(--cyan))' });
    const ro = ov?.risk_off_alpha_sleeve_preset;
    if (ro) out.push({ label: 'RO', value: ro, color: 'var(--red)' });
    return out;
  })();
  const expSuggestions = (expSearchData?.experiments ?? [])
    .filter(e => !selectedExps.includes(e.name))
    .slice(0, 8);

  // Close dropdown on outside click
  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (
        expInputRef.current && !expInputRef.current.contains(e.target as Node) &&
        dropRef.current && !dropRef.current.contains(e.target as Node)
      ) setShowExpDrop(false);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const addExp = (name: string) => {
    if (!selectedExps.includes(name)) setSelectedExps(p => [...p, name]);
    setExpInput('');
    setShowExpDrop(false);
  };

  const removeExp = (name: string) => setSelectedExps(p => p.filter(n => n !== name));

  const submitMutation = useMutation({
    mutationFn: async () => {
      const params = {
        capital: parseFloat(capital) || 10000,
        year: null,
        start: dateMode === 'year'
          ? (year ? `${year}-01-01` : null)
          : (startDate || null),
        end: dateMode === 'year'
          ? (year ? `${year}-12-31` : null)
          : (endDate || null),
        no_trades: noTrades,
        fixed_capital: fixedCapital,
        parking: parking || null,
        idle_alpha: idleAlpha || null,
        form4_sleeve: form4Sleeve || null,
        ownership_sleeve: ownershipSleeve || null,
        risk_off_sleeve: riskOffSleeve || null,
        snapshot_id: snapshotId || null,
      };
      if (selectedExps.length === 1) {
        await backtestApi.submit({ experiment_name: selectedExps[0], ...params, mode: directMode ? 'direct' : 'cli' });
      } else {
        await backtestApi.submitBatch(selectedExps, params);
      }
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['backtest-tasks'] });
    },
  });

  const canSubmit = selectedExps.length > 0 && !submitMutation.isPending &&
    (dateMode === 'year' ? !!year : !!startDate);

  const { data, isLoading, error } = useQuery({
    queryKey: ['backtest-tasks'],
    queryFn: backtestApi.tasks,
    refetchInterval: 5000,
  });

  const cancelMutation = useMutation({
    mutationFn: (id: string) => backtestApi.cancel(id),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['backtest-tasks'] }),
  });

  const [taskSearch, setTaskSearch] = useState('');
  const [taskStatusFilter, setTaskStatusFilter] = useState('');
  const [selectedTasks, setSelectedTasks] = useState<Set<string>>(new Set());
  const [taskSort, setTaskSort] = useState<{ col: string; dir: 'asc' | 'desc' }>({ col: 'created_at', dir: 'desc' });

  const toggleTaskSort = (col: string) => {
    setTaskSort(prev => prev.col === col ? { col, dir: prev.dir === 'asc' ? 'desc' : 'asc' } : { col, dir: 'desc' });
  };

  const isSelectable = (task: BacktestTask) =>
    task.status === 'completed' && (!!task.has_direct_result || !!task.run_id);

  const toggleTaskSelect = (taskId: string, selectable: boolean, e: React.MouseEvent) => {
    e.stopPropagation();
    if (!selectable) return;
    setSelectedTasks(prev => {
      const next = new Set(prev);
      if (next.has(taskId)) {
        next.delete(taskId);
      } else if (next.size < 3) {
        next.add(taskId);
      }
      return next;
    });
  };

  const deleteMutation = useMutation({
    mutationFn: (id: string) => backtestApi.cancel(id),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['backtest-tasks'] }),
  });

  const tasks = data?.tasks ?? [];
  const runningCount = tasks.filter(t => t.status === 'running').length;
  const filteredTasks = (() => {
    const filtered = tasks.filter(t => {
      if (taskSearch && !t.experiment_name.toLowerCase().includes(taskSearch.toLowerCase())) return false;
      if (taskStatusFilter && t.status !== taskStatusFilter) return false;
      return true;
    });
    const { col, dir } = taskSort;
    const d = dir === 'asc' ? 1 : -1;
    return [...filtered].sort((a, b) => {
      let av: unknown, bv: unknown;
      if (col === 'experiment_name') { av = a.experiment_name; bv = b.experiment_name; }
      else if (col === 'status') { av = a.status; bv = b.status; }
      else if (col === 'capital') { av = a.capital ?? 0; bv = b.capital ?? 0; }
      else if (col === 'period') { av = a.start_date ?? ''; bv = b.start_date ?? ''; }
      else if (col === 'return_pct') { av = a.result_summary?.return_pct ?? -Infinity; bv = b.result_summary?.return_pct ?? -Infinity; }
      else if (col === 'max_dd_pct') { av = a.result_summary?.max_dd_pct ?? -Infinity; bv = b.result_summary?.max_dd_pct ?? -Infinity; }
      else if (col === 'sharpe') { av = a.result_summary?.sharpe ?? -Infinity; bv = b.result_summary?.sharpe ?? -Infinity; }
      else if (col === 'win_rate') { av = a.result_summary?.win_rate ?? -Infinity; bv = b.result_summary?.win_rate ?? -Infinity; }
      else if (col === 'created_at') { av = a.created_at ?? ''; bv = b.created_at ?? ''; }
      else { av = a.created_at ?? ''; bv = b.created_at ?? ''; }
      if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * d;
      return String(av).localeCompare(String(bv)) * d;
    });
  })();

  return (
    <div style={{ padding: '36px 40px' }} className="fade-up">
      <style>{`
        @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
        @keyframes spin { to { transform: rotate(360deg); } }
      `}</style>

      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 28 }}>
        <div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.10em', color: 'var(--text3)', textTransform: 'uppercase', marginBottom: 6 }}>
            <span style={{ animation: runningCount > 0 ? 'pulse 1.5s ease-in-out infinite' : 'none', color: runningCount > 0 ? 'var(--cyan)' : 'var(--text3)' }}>
              {runningCount > 0 ? `${runningCount} running` : 'tasks'}
            </span>
            {' · '}{tasks.length} total
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <ScanLine size={17} style={{ color: 'var(--orange)' }} />
            <h1 style={{ fontSize: 28, fontWeight: 700, color: 'var(--text1)', letterSpacing: '-0.02em' }}>Backtest</h1>
          </div>
        </div>
        {showForm ? (
          <button
            onClick={() => { setShowForm(false); setSelectedExps([]); }}
            style={{
              display: 'flex', alignItems: 'center', gap: 6,
              padding: '8px 16px',
              background: 'transparent',
              border: '1px solid var(--border-md)',
              borderRadius: 8, color: 'var(--text3)',
              fontSize: 14, fontWeight: 500, cursor: 'pointer', transition: 'all 0.12s',
            }}
          >
            <XIcon size={14} /> Close
          </button>
        ) : (
          <button
            onClick={() => { setShowForm(true); setSelectedExps([]); }}
            style={{
              display: 'flex', alignItems: 'center', gap: 6,
              padding: '8px 16px',
              background: 'rgba(37,99,235,0.12)',
              border: '1px solid rgba(37,99,235,0.3)',
              borderRadius: 8, color: '#4a9eff',
              fontSize: 14, fontWeight: 500, cursor: 'pointer', transition: 'all 0.12s',
            }}
          >
            <Plus size={14} /> New Backtest
          </button>
        )}
      </div>

      {/* Run form — collapsible */}
      {showForm && (
        <div style={{
          background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 14,
          padding: '20px 24px', marginBottom: 28,
          boxShadow: '0 1px 4px rgba(0,0,0,0.06)',
        }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.09em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 14 }}>
            Run Paper Backtest
          </div>

          {/* Strategy selector */}
          <div style={{ marginBottom: 14 }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 6 }}>
              Strategies
            </div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5, marginBottom: selectedExps.length > 0 ? 8 : 0 }}>
              {selectedExps.map(n => (
                <span key={n} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  fontFamily: 'var(--font-mono)', fontSize: 12,
                  background: 'var(--cyan-dim)', color: 'var(--cyan)',
                  border: '1px solid rgba(0,119,182,0.2)',
                  padding: '3px 8px', borderRadius: 5,
                }}>
                  {n}
                  <button onClick={() => removeExp(n)} style={{ display: 'flex', alignItems: 'center', background: 'none', border: 'none', cursor: 'pointer', color: 'var(--cyan)', padding: 0, opacity: 0.7 }}>
                    <XIcon size={11} />
                  </button>
                </span>
              ))}
            </div>
            <div style={{ position: 'relative' }}>
              <input
                ref={expInputRef}
                type="text"
                placeholder="Search and add strategy..."
                value={expInput}
                onChange={e => { setExpInput(e.target.value); setShowExpDrop(true); }}
                onFocus={() => setShowExpDrop(true)}
                style={{ ...inputStyle, maxWidth: 360 }}
              />
              {showExpDrop && expSuggestions.length > 0 && (
                <div ref={dropRef} style={{
                  position: 'absolute', top: '100%', left: 0, marginTop: 3,
                  background: 'var(--bg1)', border: '1px solid var(--border-md)',
                  borderRadius: 9, minWidth: 320, maxWidth: 480,
                  boxShadow: '0 8px 24px rgba(0,0,0,0.14)', zIndex: 50, overflow: 'hidden',
                }}>
                  {expSuggestions.map(e => (
                    <button
                      key={e.name}
                      onMouseDown={() => addExp(e.name)}
                      style={{
                        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                        width: '100%', padding: '8px 14px',
                        background: 'none', border: 'none', cursor: 'pointer',
                        borderBottom: '1px solid var(--border)',
                        textAlign: 'left', gap: 12,
                      }}
                      onMouseEnter={ev => (ev.currentTarget.style.background = 'var(--cyan-dim)')}
                      onMouseLeave={ev => (ev.currentTarget.style.background = 'none')}
                    >
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text1)' }}>{e.name}</span>
                      {e.sqs_score != null && (
                        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--gold)', flexShrink: 0 }}>
                          SQS {e.sqs_score.toFixed(1)}
                        </span>
                      )}
                    </button>
                  ))}
                </div>
              )}
            </div>
          </div>

          {/* Baked sleeves notice */}
          {bakedSleeves.length > 0 && (
            <div style={{
              display: 'flex', flexWrap: 'wrap', alignItems: 'center', gap: 6,
              marginBottom: 10, padding: '7px 12px',
              background: 'color-mix(in srgb, var(--cyan) 6%, transparent)',
              border: '1px solid color-mix(in srgb, var(--cyan) 20%, transparent)',
              borderRadius: 7,
            }}>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)', marginRight: 2 }}>baked:</span>
              {bakedSleeves.map(s => (
                <span key={s.label} style={{
                  fontFamily: 'var(--font-mono)', fontSize: 12,
                  background: `color-mix(in srgb, ${s.color} 10%, transparent)`,
                  color: s.color,
                  border: `1px solid color-mix(in srgb, ${s.color} 25%, transparent)`,
                  padding: '1px 8px', borderRadius: 4,
                }}>
                  {s.label} {s.value}
                </span>
              ))}
            </div>
          )}

          {/* Date mode toggle + inputs */}
          <div style={{ display: 'grid', gridTemplateColumns: 'auto 160px 1fr 1fr auto', gap: 10, alignItems: 'flex-end', marginBottom: 10 }}>
            {/* Mode toggle */}
            <div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 5 }}>
                Period
              </div>
              <div style={{ display: 'flex', border: '1px solid var(--border-md)', borderRadius: 7, overflow: 'hidden' }}>
                {(['year', 'range'] as const).map(m => (
                  <button key={m} onClick={() => setDateMode(m)} style={{
                    padding: '7px 12px', fontSize: 12, fontFamily: 'var(--font-mono)',
                    background: dateMode === m ? 'var(--cyan-dim)' : 'var(--bg2)',
                    border: 'none', color: dateMode === m ? 'var(--cyan)' : 'var(--text3)',
                    cursor: 'pointer', fontWeight: dateMode === m ? 600 : 400,
                    transition: 'all 0.1s',
                  }}>
                    {m}
                  </button>
                ))}
              </div>
            </div>

            {/* Capital */}
            <div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 5 }}>
                Capital ($)
              </div>
              <input type="number" value={capital} onChange={e => setCapital(e.target.value)} style={inputStyle} min="100" step="1000" />
            </div>

            {/* Date input(s) */}
            {dateMode === 'year' ? (
              <div style={{ gridColumn: 'span 2' }}>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 5 }}>
                  Year (full year only)
                </div>
                <input type="text" placeholder="e.g. 2022" value={year} onChange={e => setYear(e.target.value)} style={inputStyle} />
              </div>
            ) : (
              <>
                <div>
                  <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 5 }}>
                    Start (YYYY-MM or YYYY-MM-DD)
                  </div>
                  <input type="text" placeholder="e.g. 2022-01 or 2022-01-01" value={startDate} onChange={e => setStartDate(e.target.value)} style={inputStyle} />
                </div>
                <div>
                  <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.07em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 5 }}>
                    End (optional)
                  </div>
                  <input type="text" placeholder="e.g. 2021 or 2024-12 or 2024-12-31" value={endDate} onChange={e => setEndDate(e.target.value)} style={inputStyle} />
                </div>
              </>
            )}

            {/* Submit */}
            <button
              onClick={() => submitMutation.mutate()}
              disabled={!canSubmit}
              style={{
                display: 'flex', alignItems: 'center', gap: 6,
                padding: '8px 20px', fontSize: 14, fontWeight: 600, borderRadius: 8, cursor: canSubmit ? 'pointer' : 'not-allowed',
                background: canSubmit ? 'color-mix(in srgb, var(--orange) 12%, transparent)' : 'var(--bg2)',
                border: `1px solid ${canSubmit ? 'color-mix(in srgb, var(--orange) 28%, transparent)' : 'var(--border)'}`,
                color: canSubmit ? 'var(--orange)' : 'var(--text3)',
                transition: 'all 0.12s', whiteSpace: 'nowrap',
              }}
            >
              <Play size={13} />
              {submitMutation.isPending
                ? 'Submitting...'
                : selectedExps.length > 1
                  ? `Run ${selectedExps.length}`
                  : 'Run'}
            </button>
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', whiteSpace: 'nowrap' }}>Dataset</span>
            <select
              value={snapshotId}
              onChange={e => setSnapshotId(e.target.value)}
              style={{ ...inputStyle, width: 'auto', minWidth: 160, fontSize: 12, padding: '5px 8px', color: snapshotId ? 'var(--cyan)' : 'var(--text3)' }}
            >
              <option value="">— default —</option>
              {snapshotsData?.snapshots.map(s => (
                <option key={s.id} value={s.id}>
                  {s.id}{s.start ? ` (${s.start?.slice(0, 7)} ~ ${s.end?.slice(0, 7)})` : ''}
                </option>
              ))}
            </select>
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', whiteSpace: 'nowrap' }}>Cash Parking</span>
            <select
              value={parking}
              onChange={e => setParking(e.target.value)}
              style={{ ...inputStyle, width: 'auto', minWidth: 180, fontSize: 12, padding: '5px 8px', color: parking ? 'var(--orange)' : 'var(--text3)' }}
            >
              <option value="">— none —</option>
              {parkingPresetsData
                ? Object.entries(parkingPresetsData.groups).map(([group, names]) => (
                    <optgroup key={group} label={group}>
                      {names.map(name => (
                        <option key={name} value={name}>{name}</option>
                      ))}
                    </optgroup>
                  ))
                : null}
            </select>
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', whiteSpace: 'nowrap' }}>Idle Alpha</span>
            <select
              value={idleAlpha}
              onChange={e => setIdleAlpha(e.target.value)}
              style={{ ...inputStyle, width: 'auto', minWidth: 180, fontSize: 12, padding: '5px 8px', color: idleAlpha ? 'var(--green)' : 'var(--text3)' }}
            >
              <option value="">— none —</option>
              {idleAlphaPresetsData
                ? Object.entries(idleAlphaPresetsData.groups).map(([group, names]) => (
                    <optgroup key={group} label={group}>
                      {names.map(name => (
                        <option key={name} value={name}>{name}</option>
                      ))}
                    </optgroup>
                  ))
                : null}
            </select>
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', whiteSpace: 'nowrap' }}>Form 4 Sleeve</span>
            <select
              value={form4Sleeve}
              onChange={e => setForm4Sleeve(e.target.value)}
              style={{ ...inputStyle, width: 'auto', minWidth: 180, fontSize: 12, padding: '5px 8px', color: form4Sleeve ? 'var(--cyan)' : 'var(--text3)' }}
            >
              <option value="">— none —</option>
              {form4PresetsData
                ? Object.entries(form4PresetsData.groups).map(([group, names]) => (
                    <optgroup key={group} label={group}>
                      {names.map(name => (
                        <option key={name} value={name}>{name}</option>
                      ))}
                    </optgroup>
                  ))
                : null}
            </select>
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', whiteSpace: 'nowrap' }}>Ownership Sleeve</span>
            <select
              value={ownershipSleeve}
              onChange={e => setOwnershipSleeve(e.target.value)}
              style={{ ...inputStyle, width: 'auto', minWidth: 200, fontSize: 12, padding: '5px 8px', color: ownershipSleeve ? 'var(--violet, var(--cyan))' : 'var(--text3)' }}
            >
              <option value="">— none —</option>
              {ownershipPresetsData
                ? Object.entries(ownershipPresetsData.groups).map(([group, names]) => (
                    <optgroup key={group} label={group}>
                      {names.map(name => (
                        <option key={name} value={name}>{name}</option>
                      ))}
                    </optgroup>
                  ))
                : null}
            </select>

            <select
              value={riskOffSleeve}
              onChange={e => setRiskOffSleeve(e.target.value)}
              style={{ ...inputStyle, width: 'auto', minWidth: 220, fontSize: 12, padding: '5px 8px', color: riskOffSleeve ? 'var(--orange)' : 'var(--text3)' }}
            >
              <option value="">Risk-Off Alpha Sleeve</option>
              {riskOffPresetsData
                ? Object.entries(riskOffPresetsData.groups).map(([group, names]) => (
                    <optgroup key={group} label={group}>
                      {(names as string[]).map(preset => (
                        <option key={preset} value={preset}>{preset}</option>
                      ))}
                    </optgroup>
                  ))
                : null}
            </select>

          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
            <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer' }}>
              <input type="checkbox" checked={noTrades} onChange={e => setNoTrades(e.target.checked)} style={{ width: 13, height: 13 }} />
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>--no-trades</span>
            </label>
            <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer' }}>
              <input type="checkbox" checked={fixedCapital} onChange={e => setFixedCapital(e.target.checked)} style={{ width: 13, height: 13 }} />
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: fixedCapital ? 'var(--orange)' : 'var(--text3)' }}>Fixed Capital (Simple Return)</span>
            </label>
            <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: selectedExps.length === 1 ? 'pointer' : 'not-allowed', opacity: selectedExps.length === 1 ? 1 : 0.4 }}>
              <input
                type="checkbox"
                checked={!directMode}
                onChange={e => setDirectMode(!e.target.checked)}
                disabled={selectedExps.length !== 1}
                style={{ width: 13, height: 13 }}
              />
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: !directMode ? 'var(--cyan)' : 'var(--text3)' }}>
                CLI Mode
              </span>
            </label>
          </div>

          {submitMutation.error && (
            <div style={{ marginTop: 10, fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--red)' }}>
              {(submitMutation.error as Error).message}
            </div>
          )}
        </div>
      )}

      {isLoading && <Loading />}
      {error && <ErrorState error={error as Error} />}

      {!isLoading && tasks.length === 0 && (
        <div style={{
          background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12,
          padding: '56px 24px', textAlign: 'center',
          boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
        }}>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)', marginBottom: 10 }}>
            NO TASKS
          </div>
          <p style={{ color: 'var(--text2)', fontSize: 15 }}>
            전략 페이지에서 백테스트를 실행하세요
          </p>
          <button
            onClick={() => navigate('/experiments')}
            style={{
              marginTop: 16, padding: '8px 20px', fontSize: 14, borderRadius: 8, cursor: 'pointer',
              background: 'var(--cyan-dim)', border: '1px solid rgba(0,119,182,0.25)',
              color: 'var(--cyan)', fontFamily: 'var(--font-mono)',
            }}
          >
            Strategies →
          </button>
        </div>
      )}

      {tasks.length > 0 && (
        <>
          {/* Compare button bar */}
          {selectedTasks.size >= 2 && (
            <div style={{
              display: 'flex', gap: 8, alignItems: 'center', marginBottom: 12,
              background: 'color-mix(in srgb, var(--orange) 10%, transparent)',
              border: '1px solid color-mix(in srgb, var(--orange) 25%, transparent)',
              borderRadius: 10, padding: '10px 16px',
            }}>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--orange)' }}>
                {selectedTasks.size} selected
              </span>
              <button
                onClick={() => navigate(`/backtest/compare?tasks=${Array.from(selectedTasks).join(',')}`)}
                style={{
                  padding: '6px 16px', fontSize: 13, borderRadius: 7, cursor: 'pointer',
                  fontFamily: 'var(--font-mono)', fontWeight: 600,
                  background: 'var(--orange)', border: 'none', color: '#fff',
                }}
              >
                Compare →
              </button>
              <button
                onClick={() => setSelectedTasks(new Set())}
                style={{
                  padding: '5px 12px', fontSize: 12, borderRadius: 7, cursor: 'pointer',
                  fontFamily: 'var(--font-mono)',
                  background: 'none', border: '1px solid color-mix(in srgb, var(--orange) 30%, transparent)',
                  color: 'var(--orange)',
                }}
              >
                Clear
              </button>
            </div>
          )}

          {/* Filter bar */}
          <div style={{ display: 'flex', gap: 8, marginBottom: 10, alignItems: 'center' }}>
            <div style={{ position: 'relative', flex: 1, maxWidth: 320 }}>
              <input
                type="text"
                placeholder="Search experiments..."
                value={taskSearch}
                onChange={e => setTaskSearch(e.target.value)}
                style={{ ...inputStyle, paddingRight: taskSearch ? 28 : 10 }}
              />
              {taskSearch && (
                <button onClick={() => setTaskSearch('')} style={{ position: 'absolute', right: 8, top: '50%', transform: 'translateY(-50%)', background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', display: 'flex', alignItems: 'center', padding: 0 }}>
                  <XIcon size={12} />
                </button>
              )}
            </div>
            <div style={{ position: 'relative', display: 'flex', alignItems: 'center' }}>
              <Filter size={13} style={{ position: 'absolute', left: 9, color: 'var(--text3)', pointerEvents: 'none' }} />
              <select
                value={taskStatusFilter}
                onChange={e => setTaskStatusFilter(e.target.value)}
                style={{ ...inputStyle, width: 'auto', paddingLeft: 28, cursor: 'pointer', appearance: 'none' as const }}
              >
                <option value="">All statuses</option>
                <option value="running">Running</option>
                <option value="queued">Queued</option>
                <option value="completed">Completed</option>
                <option value="failed">Failed</option>
                <option value="cancelled">Cancelled</option>
              </select>
            </div>
            {(taskSearch || taskStatusFilter) && (
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>
                {filteredTasks.length} / {tasks.length}
              </span>
            )}
          </div>

          <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
            <div style={{ overflowX: 'auto' }}>
              <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                <thead>
                  <tr style={{ borderBottom: '1px solid var(--border-md)', background: 'var(--bg2)' }}>
                    <th style={{ padding: '11px 8px 11px 14px', width: 28 }}></th>
                    {([
                      { label: 'Status',     col: 'status' },
                      { label: 'Experiment', col: 'experiment_name' },
                      { label: 'Capital',    col: 'capital' },
                      { label: 'Period',     col: 'period' },
                      { label: 'Return',     col: 'return_pct' },
                      { label: 'DD',         col: 'max_dd_pct' },
                      { label: 'Sharpe',     col: 'sharpe' },
                      { label: 'WR',         col: 'win_rate' },
                      { label: 'Duration',   col: null },
                      { label: 'Created',    col: 'created_at' },
                      { label: 'Actions',    col: null },
                    ] as { label: string; col: string | null }[]).map(({ label, col }, i) => (
                      <th
                        key={label}
                        onClick={col ? () => toggleTaskSort(col) : undefined}
                        style={{
                          padding: '11px 14px', textAlign: 'left',
                          fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 500,
                          letterSpacing: '0.07em', textTransform: 'uppercase',
                          color: col && taskSort.col === col ? 'var(--orange)' : 'var(--text3)',
                          whiteSpace: 'nowrap',
                          cursor: col ? 'pointer' : 'default',
                          userSelect: 'none',
                          ...(i === 10 ? { textAlign: 'right' as const } : {}),
                        }}
                      >
                        {label}
                        {col && (
                          <span style={{ marginLeft: 4, fontSize: 10, opacity: taskSort.col === col ? 1 : 0.25 }}>
                            {taskSort.col === col ? (taskSort.dir === 'asc' ? '▲' : '▼') : '⇅'}
                          </span>
                        )}
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {filteredTasks.map((task, i) => {
                    const isActive = task.status === 'running' || task.status === 'queued';
                    const isDone = !isActive;
                    const modeColor = task.mode === 'direct' ? 'var(--orange)' : 'var(--cyan)';
                    const selectable = isSelectable(task);
                    const isSelected = selectedTasks.has(task.task_id);
                    return (
                      <tr
                        key={task.task_id}
                        onClick={() => navigate(`/backtest/tasks/${task.task_id}`)}
                        style={{
                          borderBottom: i < filteredTasks.length - 1 ? '1px solid var(--border)' : 'none',
                          cursor: 'pointer', transition: 'background 0.1s',
                          background: isSelected ? 'color-mix(in srgb, var(--orange) 6%, transparent)' : 'transparent',
                        }}
                        onMouseEnter={e => (e.currentTarget.style.background = isSelected ? 'color-mix(in srgb, var(--orange) 9%, transparent)' : 'var(--cyan-dim)')}
                        onMouseLeave={e => (e.currentTarget.style.background = isSelected ? 'color-mix(in srgb, var(--orange) 6%, transparent)' : 'transparent')}
                      >
                        <td
                          style={{ padding: '11px 8px 11px 14px', width: 28 }}
                          onClick={e => toggleTaskSelect(task.task_id, selectable, e)}
                        >
                          {selectable && (
                            <input
                              type="checkbox"
                              checked={isSelected}
                              onChange={() => {}}
                              onClick={e => toggleTaskSelect(task.task_id, selectable, e)}
                              style={{ width: 13, height: 13, cursor: 'pointer', accentColor: 'var(--orange)' }}
                            />
                          )}
                        </td>
                        <td style={{ padding: '11px 14px', width: 120 }}>
                          <div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
                            <StatusDot status={task.status} />
                            {task.mode && (
                              <span style={{
                                fontFamily: 'var(--font-mono)', fontSize: 10,
                                color: modeColor,
                                background: `color-mix(in srgb, ${modeColor} 12%, transparent)`,
                                border: `1px solid color-mix(in srgb, ${modeColor} 25%, transparent)`,
                                borderRadius: 3, padding: '1px 5px', width: 'fit-content',
                              }}>
                                {task.mode === 'direct' ? 'DIRECT' : 'CLI'}
                              </span>
                            )}
                          </div>
                        </td>
                        <td style={{ padding: '11px 14px', maxWidth: 260 }}>
                          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text1)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                            {task.experiment_name}
                          </div>
                          <div style={{ display: 'flex', gap: 4, marginTop: 3, flexWrap: 'wrap' }}>
                            {task.run_id && (
                              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>
                                {task.run_id}
                              </span>
                            )}
                            {task.parking && (
                              <span style={{
                                fontFamily: 'var(--font-mono)', fontSize: 10,
                                color: 'var(--orange)',
                                background: 'color-mix(in srgb, var(--orange) 12%, transparent)',
                                border: '1px solid color-mix(in srgb, var(--orange) 25%, transparent)',
                                borderRadius: 3, padding: '1px 5px',
                              }}>
                                🅿 {task.parking}
                              </span>
                            )}
                            {task.idle_alpha && (
                              <span style={{
                                fontFamily: 'var(--font-mono)', fontSize: 10,
                                color: 'var(--green)',
                                background: 'color-mix(in srgb, var(--green) 12%, transparent)',
                                border: '1px solid color-mix(in srgb, var(--green) 25%, transparent)',
                                borderRadius: 3, padding: '1px 5px',
                              }}>
                                IA {task.idle_alpha}
                              </span>
                            )}
                            {task.form4_sleeve && (
                              <span style={{
                                fontFamily: 'var(--font-mono)', fontSize: 10,
                                color: 'var(--cyan)',
                                background: 'color-mix(in srgb, var(--cyan) 12%, transparent)',
                                border: '1px solid color-mix(in srgb, var(--cyan) 25%, transparent)',
                                borderRadius: 3, padding: '1px 5px',
                              }}>
                                F4 {task.form4_sleeve}
                              </span>
                            )}
                            {task.ownership_sleeve && (
                              <span style={{
                                fontFamily: 'var(--font-mono)', fontSize: 10,
                                color: 'var(--violet, var(--cyan))',
                                background: 'color-mix(in srgb, var(--violet, var(--cyan)) 12%, transparent)',
                                border: '1px solid color-mix(in srgb, var(--violet, var(--cyan)) 25%, transparent)',
                                borderRadius: 3, padding: '1px 5px',
                              }}>
                                13D {task.ownership_sleeve}
                              </span>
                            )}
                            {task.risk_off_sleeve && (
                              <span style={{
                                fontFamily: 'var(--font-mono)', fontSize: 10,
                                color: 'var(--orange)',
                                background: 'color-mix(in srgb, var(--orange) 12%, transparent)',
                                border: '1px solid color-mix(in srgb, var(--orange) 25%, transparent)',
                                borderRadius: 3, padding: '1px 5px',
                              }}>
                                RO {task.risk_off_sleeve}
                              </span>
                            )}
                          </div>
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--cyan)', whiteSpace: 'nowrap' }}>
                          ${task.capital?.toLocaleString() ?? '—'}
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)', whiteSpace: 'nowrap' }}>
                          {task.start_date
                            ? task.end_date ? `${task.start_date} → ${task.end_date}` : task.start_date
                            : '—'}
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, whiteSpace: 'nowrap' }}>
                          {task.result_summary?.return_pct != null ? (
                            <span style={{ color: task.result_summary.return_pct >= 0 ? 'var(--green)' : 'var(--red)', fontWeight: 600 }}>
                              {task.result_summary.return_pct >= 0 ? '+' : ''}{task.result_summary.return_pct.toFixed(1)}%
                            </span>
                          ) : <span style={{ color: 'var(--text3)' }}>—</span>}
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, whiteSpace: 'nowrap' }}>
                          {task.result_summary?.max_dd_pct != null ? (
                            <span style={{ color: task.result_summary.max_dd_pct < -10 ? 'var(--red)' : 'var(--text3)' }}>
                              {task.result_summary.max_dd_pct.toFixed(1)}%
                            </span>
                          ) : <span style={{ color: 'var(--text3)' }}>—</span>}
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, whiteSpace: 'nowrap', color: 'var(--text3)' }}>
                          {task.result_summary?.sharpe != null ? task.result_summary.sharpe.toFixed(2) : '—'}
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, whiteSpace: 'nowrap', color: 'var(--text3)' }}>
                          {task.result_summary?.win_rate != null ? `${task.result_summary.win_rate.toFixed(1)}%` : '—'}
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)', whiteSpace: 'nowrap' }}>
                          {elapsed(task.started_at, task.finished_at)}
                        </td>
                        <td style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', whiteSpace: 'nowrap' }}>
                          {fmtDate(task.created_at)}
                        </td>
                        <td style={{ padding: '11px 14px', textAlign: 'right' }} onClick={e => e.stopPropagation()}>
                          <div style={{ display: 'flex', gap: 5, justifyContent: 'flex-end', alignItems: 'center' }}>
                            <button
                              onClick={() => applyDup(makeDupState(task))}
                              title="Duplicate with same settings"
                              style={{ display: 'flex', alignItems: 'center', gap: 3, padding: '3px 8px', fontSize: 12, borderRadius: 5, cursor: 'pointer', background: 'var(--bg2)', border: '1px solid var(--border-md)', color: 'var(--text3)', fontFamily: 'var(--font-mono)' }}
                            >
                              <Copy size={11} />
                            </button>
                            {isActive && (
                              <button
                                onClick={() => cancelMutation.mutate(task.task_id)}
                                style={{ padding: '3px 8px', fontSize: 12, borderRadius: 5, cursor: 'pointer', background: 'var(--red-dim)', border: '1px solid rgba(220,38,38,0.22)', color: 'var(--red)', fontFamily: 'var(--font-mono)' }}
                              >
                                Cancel
                              </button>
                            )}
                            {isDone && (
                              <button
                                onClick={() => deleteMutation.mutate(task.task_id)}
                                title="Remove task"
                                style={{ display: 'flex', alignItems: 'center', padding: '3px 6px', fontSize: 12, borderRadius: 5, cursor: 'pointer', background: 'none', border: '1px solid var(--border)', color: 'var(--text3)', opacity: 0.7 }}
                              >
                                <Trash2 size={11} />
                              </button>
                            )}
                          </div>
                        </td>
                      </tr>
                    );
                  })}
                  {filteredTasks.length === 0 && (
                    <tr>
                      <td colSpan={12} style={{ padding: '28px 14px', textAlign: 'center', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)' }}>
                        No tasks match the filter
                      </td>
                    </tr>
                  )}
                </tbody>
              </table>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

// ── Backtest Task Detail Page ────────────────────────────────────────────────

export function BacktestTaskDetailPage() {
  const { taskId } = useParams<{ taskId: string }>();
  const navigate = useNavigate();
  const qc = useQueryClient();

  const { data: task, isLoading } = useQuery({
    queryKey: ['backtest-task', taskId],
    queryFn: () => backtestApi.task(taskId!),
    enabled: !!taskId,
    staleTime: 0,
    refetchInterval: (query) => {
      const status = query.state.data?.status;
      return status === 'running' || status === 'queued' ? 2000 : false;
    },
  });

  const { data: logData } = useQuery({
    queryKey: ['backtest-log', taskId],
    queryFn: () => backtestApi.taskLog(taskId!),
    enabled: !!taskId,
    staleTime: 0,
    refetchInterval: (query) => {
      const d = query.state.data as { log?: string } | undefined;
      // Keep polling while the task is active — derive status from sibling query cache
      const status = task?.status;
      return (status === 'running' || status === 'queued') ? 2000 : (d?.log ? false : 1000);
    },
  });

  const cancelMutation = useMutation({
    mutationFn: () => backtestApi.cancel(taskId!),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['backtest-task', taskId] }),
  });

  // Don't flash stale data from a different task while the new one loads
  if (isLoading || !task || task.task_id !== taskId) return <div style={{ padding: 32 }}><Loading /></div>;

  const isActive = task.status === 'running' || task.status === 'queued';

  return (
    <div style={{ padding: '36px 40px' }} className="fade-up">
      <style>{`
        @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
        .terminal-scroll { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.2) transparent; }
        .terminal-scroll::-webkit-scrollbar { width: 7px; }
        .terminal-scroll::-webkit-scrollbar-track { background: transparent; }
        .terminal-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.18); border-radius: 4px; }
        .terminal-scroll::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.32); }
      `}</style>

      {/* Breadcrumb */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 20, fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)' }}>
        <button onClick={() => navigate('/backtest')} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13, padding: 0, display: 'flex', alignItems: 'center', gap: 4 }}>
          <ArrowLeft size={12} /> backtest
        </button>
        <ChevronRight size={13} />
        <span style={{ color: 'var(--text2)' }}>{task.task_id}</span>
      </div>

      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 24, gap: 16 }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 6 }}>
            <StatusDot status={task.status} />
            <h1 style={{ fontFamily: 'var(--font-mono)', fontSize: 22, fontWeight: 700, color: 'var(--text1)' }}>
              {task.experiment_name}
            </h1>
          </div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)', display: 'flex', gap: 16, flexWrap: 'wrap' }}>
            <span>capital: <span style={{ color: 'var(--cyan)' }}>${task.capital?.toLocaleString() ?? '—'}</span></span>
            {task.start_date && (
              <span>period: <span style={{ color: 'var(--text2)' }}>{task.start_date}{task.end_date ? ` → ${task.end_date}` : ''}</span></span>
            )}
            <span>duration: <span style={{ color: 'var(--text2)' }}>{elapsed(task.started_at, task.finished_at)}</span></span>
            <span>created: <span style={{ color: 'var(--text2)' }}>{fmtDate(task.created_at)}</span></span>
            {task.run_id && <span>run: <span style={{ color: 'var(--text2)' }}>{task.run_id}</span></span>}
            {task.parking && (
              <span style={{
                fontFamily: 'var(--font-mono)', fontSize: 11,
                color: 'var(--orange)',
                background: 'color-mix(in srgb, var(--orange) 12%, transparent)',
                border: '1px solid color-mix(in srgb, var(--orange) 25%, transparent)',
                borderRadius: 3, padding: '1px 6px',
              }}>
                🅿 {task.parking}
              </span>
            )}
            {task.idle_alpha && (
              <span style={{
                fontFamily: 'var(--font-mono)', fontSize: 11,
                color: 'var(--green)',
                background: 'color-mix(in srgb, var(--green) 12%, transparent)',
                border: '1px solid color-mix(in srgb, var(--green) 25%, transparent)',
                borderRadius: 3, padding: '1px 6px',
              }}>
                IA {task.idle_alpha}
              </span>
            )}
            {task.form4_sleeve && (
              <span style={{
                fontFamily: 'var(--font-mono)', fontSize: 11,
                color: 'var(--cyan)',
                background: 'color-mix(in srgb, var(--cyan) 12%, transparent)',
                border: '1px solid color-mix(in srgb, var(--cyan) 25%, transparent)',
                borderRadius: 3, padding: '1px 6px',
              }}>
                F4 {task.form4_sleeve}
              </span>
            )}
            {task.ownership_sleeve && (
              <span style={{
                fontFamily: 'var(--font-mono)', fontSize: 11,
                color: 'var(--violet, var(--cyan))',
                background: 'color-mix(in srgb, var(--violet, var(--cyan)) 12%, transparent)',
                border: '1px solid color-mix(in srgb, var(--violet, var(--cyan)) 25%, transparent)',
                borderRadius: 3, padding: '1px 6px',
              }}>
                13D {task.ownership_sleeve}
              </span>
            )}
            {task.risk_off_sleeve && (
              <span style={{
                fontFamily: 'var(--font-mono)', fontSize: 11,
                color: 'var(--orange)',
                background: 'color-mix(in srgb, var(--orange) 12%, transparent)',
                border: '1px solid color-mix(in srgb, var(--orange) 25%, transparent)',
                borderRadius: 3, padding: '1px 6px',
              }}>
                RO {task.risk_off_sleeve}
              </span>
            )}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, flexShrink: 0 }}>
          <button
            onClick={() => navigate('/backtest', { state: makeDupState(task) })}
            title="Duplicate with same settings"
            style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '7px 14px', fontSize: 13, borderRadius: 7, cursor: 'pointer', background: 'var(--bg2)', border: '1px solid var(--border-md)', color: 'var(--text2)', fontFamily: 'var(--font-mono)' }}
          >
            <Copy size={13} /> Duplicate
          </button>
          {isActive && (
            <button
              onClick={() => cancelMutation.mutate()}
              disabled={cancelMutation.isPending}
              style={{ padding: '7px 16px', fontSize: 13, borderRadius: 7, cursor: 'pointer', background: 'var(--red-dim)', border: '1px solid rgba(220,38,38,0.25)', color: 'var(--red)', fontFamily: 'var(--font-mono)' }}
            >
              Cancel
            </button>
          )}
          {task.status === 'completed' && task.run_id && (
            <button
              onClick={() => navigate(`/backtest/results/${task.run_id}`)}
              style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '7px 16px', fontSize: 13, borderRadius: 7, cursor: 'pointer', background: 'var(--green-dim)', border: '1px solid rgba(5,150,105,0.25)', color: 'var(--green)', fontFamily: 'var(--font-mono)', fontWeight: 500 }}
            >
              <ExternalLink size={13} /> View Results
            </button>
          )}
        </div>
      </div>

      {/* Error banner (CLI mode only — direct mode shows error inline) */}
      {task.mode !== 'direct' && task.status === 'failed' && task.error && (
        <div style={{ marginBottom: 20, padding: '12px 16px', background: 'var(--red-dim)', border: '1px solid rgba(220,38,38,0.2)', borderRadius: 9, fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--red)', whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}>
          {task.error}
        </div>
      )}

      {task.mode === 'direct' ? (
        <DirectModeTaskView task={task} logData={logData} />
      ) : (
        /* Terminal log (CLI mode) */
        <div style={{ background: '#0d1117', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 12, overflow: 'hidden', boxShadow: '0 4px 20px rgba(0,0,0,0.3)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 16px', background: '#161b22', borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
            <div style={{ display: 'flex', gap: 6 }}>
              <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#ff5f57' }} />
              <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#febc2e' }} />
              <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#28c840' }} />
            </div>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'rgba(255,255,255,0.4)', marginLeft: 8 }}>
              {task.task_id}.log
            </span>
            {isActive && (
              <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--cyan)', animation: 'pulse 1.5s ease-in-out infinite' }}>
                ● live
              </span>
            )}
            {logData?.total_lines != null && (
              <span style={{ marginLeft: isActive ? 8 : 'auto', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'rgba(255,255,255,0.3)' }}>
                {logData.total_lines} lines
              </span>
            )}
          </div>
          <div className="terminal-scroll" style={{ padding: '16px 20px', minHeight: 320, maxHeight: 'calc(100vh - 320px)', overflowY: 'auto' }}>
            {logData?.log
              ? <TerminalLog text={logData.log} large />
              : <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'rgba(255,255,255,0.25)', fontStyle: 'italic' }}>(waiting for output...)</span>
            }
          </div>
        </div>
      )}
    </div>
  );
}

// ── Pagination ────────────────────────────────────────────────────────────────

function Pagination({ page, totalPages, onChange }: {
  page: number;
  totalPages: number;
  onChange: (p: number) => void;
}) {
  if (totalPages <= 1) return null;

  const btnStyle = (disabled: boolean, active = false): React.CSSProperties => ({
    padding: '5px 10px', borderRadius: 6, border: '1px solid var(--border-md)',
    background: active ? 'var(--orange)' : 'none',
    cursor: disabled ? 'default' : 'pointer',
    color: active ? '#fff' : disabled ? 'var(--text3)' : 'var(--text2)',
    fontFamily: 'var(--font-mono)', fontSize: 13,
    minWidth: 34, textAlign: 'center' as const,
    opacity: disabled ? 0.4 : 1,
  });

  // Build page number window: always show first, last, current ±2, with ellipsis
  const pages: (number | '...')[] = [];
  const window = 2;
  for (let i = 0; i < totalPages; i++) {
    if (i === 0 || i === totalPages - 1 || (i >= page - window && i <= page + window)) {
      pages.push(i);
    } else if (pages[pages.length - 1] !== '...') {
      pages.push('...');
    }
  }

  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4, marginTop: 14, fontFamily: 'var(--font-mono)', fontSize: 13 }}>
      <button onClick={() => onChange(0)} disabled={page === 0} style={btnStyle(page === 0)} title="First">|←</button>
      <button onClick={() => onChange(page - 1)} disabled={page === 0} style={btnStyle(page === 0)}>← Prev</button>
      {pages.map((p, i) =>
        p === '...'
          ? <span key={`e${i}`} style={{ padding: '5px 4px', color: 'var(--text3)' }}>…</span>
          : <button key={p} onClick={() => onChange(p)} style={btnStyle(false, p === page)}>{p + 1}</button>
      )}
      <button onClick={() => onChange(page + 1)} disabled={page >= totalPages - 1} style={btnStyle(page >= totalPages - 1)}>Next →</button>
      <button onClick={() => onChange(totalPages - 1)} disabled={page >= totalPages - 1} style={btnStyle(page >= totalPages - 1)} title="Last">→|</button>
    </div>
  );
}

// ── Direct Mode Task View ────────────────────────────────────────────────────

function DirectModeTaskView({
  task,
  logData,
}: {
  task: BacktestTask;
  logData: { log: string; total_lines?: number } | undefined;
}) {
  const [showLog, setShowLog] = useState(false);
  const [tab, setTab] = useState<'summary' | 'equity' | 'trades'>('summary');
  const [tradePage, setTradePage] = useState(0);
  const TRADE_PAGE_SIZE = 50;
  const [tradeSort, setTradeSort] = useState<{ col: string; dir: 'asc' | 'desc' }>({ col: '_no', dir: 'asc' });
  const [tradeFilter, setTradeFilter] = useState({
    symbol: '',
    sleeve: '' as '' | TradeSleeve,
    engine: '',
    reason: '',
    outcome: 'all' as 'all' | 'win' | 'loss',
  });

  const { data: result, isLoading } = useQuery({
    queryKey: ['direct-result', task.task_id],
    queryFn: () => backtestApi.directResult(task.task_id),
    enabled: task.status === 'completed' && !!task.has_direct_result,
  });

  const logSection = (
    <div style={{ marginTop: 16 }}>
      <button
        onClick={() => setShowLog(v => !v)}
        style={{
          display: 'flex', alignItems: 'center', gap: 6,
          background: 'none', border: 'none', cursor: 'pointer',
          fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', padding: '4px 0',
        }}
      >
        <ChevronRight size={12} style={{ transform: showLog ? 'rotate(90deg)' : 'none', transition: 'transform 0.15s' }} />
        {showLog ? 'Hide log' : 'Show log'}
        {logData?.total_lines != null && ` (${logData.total_lines} lines)`}
      </button>
      {showLog && (
        <div style={{ marginTop: 8, background: '#0d1117', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 10, overflow: 'hidden' }}>
          <div className="terminal-scroll" style={{ padding: '14px 18px', maxHeight: 320, overflowY: 'auto' }}>
            {logData?.log
              ? <TerminalLog text={logData.log} large />
              : <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'rgba(255,255,255,0.25)', fontStyle: 'italic' }}>(no log)</span>
            }
          </div>
        </div>
      )}
    </div>
  );

  // Auto-scroll ref for live log
  const liveLogRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if ((task.status === 'queued' || task.status === 'running') && liveLogRef.current) {
      liveLogRef.current.scrollTop = liveLogRef.current.scrollHeight;
    }
  }, [logData?.log, task.status]);

  if (task.status === 'queued' || task.status === 'running') {
    return (
      <div>
        {/* Status bar */}
        <div style={{
          display: 'flex', alignItems: 'center', gap: 10, marginBottom: 10,
          padding: '10px 16px', background: 'var(--bg1)', border: '1px solid var(--border)',
          borderRadius: 10,
        }}>
          <Loader size={14} style={{ color: 'var(--orange)', animation: 'spin 1s linear infinite', flexShrink: 0 }} />
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: 600, color: 'var(--orange)' }}>
            {task.status === 'queued' ? 'Queued...' : 'Running backtest...'}
          </span>
          <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--orange)', animation: 'pulse 1.5s ease-in-out infinite' }}>● live</span>
        </div>

        {/* Live terminal */}
        <div style={{ background: '#0d1117', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 12, overflow: 'hidden', boxShadow: '0 4px 20px rgba(0,0,0,0.3)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 16px', background: '#161b22', borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
            <div style={{ display: 'flex', gap: 6 }}>
              <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#ff5f57' }} />
              <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#febc2e' }} />
              <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#28c840' }} />
            </div>
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'rgba(255,255,255,0.4)', marginLeft: 8 }}>
              {task.task_id}.direct.log
            </span>
            {logData?.total_lines != null && (
              <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'rgba(255,255,255,0.3)' }}>
                {logData.total_lines} lines
              </span>
            )}
          </div>
          <div
            ref={liveLogRef}
            className="terminal-scroll"
            style={{ padding: '16px 20px', minHeight: 200, maxHeight: 420, overflowY: 'auto' }}
          >
            {logData?.log ? (
              <div>
                <TerminalLog text={logData.log} large />
                <span style={{
                  display: 'inline-block', width: 8, height: 15,
                  background: 'var(--orange)', opacity: 0.85,
                  animation: 'pulse 1s ease-in-out infinite',
                  marginLeft: 4, verticalAlign: 'text-bottom', borderRadius: 1,
                }} />
              </div>
            ) : (
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'rgba(255,255,255,0.3)', fontStyle: 'italic' }}>
                Initializing...
              </span>
            )}
          </div>
        </div>
      </div>
    );
  }

  if (task.status === 'completed' && isLoading) {
    return <div style={{ padding: 32, textAlign: 'center' }}><Loading /></div>;
  }

  if (task.status !== 'completed' || !result) {
    // Failed/cancelled: show error + collapsible log
    return (
      <div>
        {task.error && (
          <div style={{ marginBottom: 12, padding: '12px 16px', background: 'var(--red-dim)', border: '1px solid rgba(220,38,38,0.2)', borderRadius: 9, fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--red)', whiteSpace: 'pre-wrap', wordBreak: 'break-all' }}>
            {task.error}
          </div>
        )}
        {logSection}
      </div>
    );
  }

  // Completed with result: full inline display
  const s = result.summary;
  const mb = result.metrics_bundle as Record<string, unknown>;
  const returnPct = s.return_pct ?? 0;

  const chartData = (result.equity_curve ?? []).map(row => ({ date: row.date, equity: row.equity }));

  const allTrades = ((result.trades ?? []) as Record<string, unknown>[]).map((t, i) => ({
    ...t,
    _no: i + 1,
    _sleeve: classifyTradeSleeve(t),
  })) as (Record<string, unknown> & { _no: number; _sleeve: TradeSleeve })[];
  const totalTrades = allTrades.length;

  // unique filter options
  const sleeveOptions: TradeSleeve[] = ['core', 'idle_alpha', 'risk_off_alpha', 'ownership', 'parking'];
  const engineOptions = Array.from(new Set(allTrades.map(t => String(t.engine_id ?? '')))).filter(Boolean).sort();
  const reasonOptions = Array.from(new Set(allTrades.map(t => String(t.reason ?? t.exit_reason ?? '')))).filter(v => v !== '—' && v !== '').sort();

  // apply filters
  const filteredTrades = allTrades.filter(t => {
    if (tradeFilter.symbol && !String(t.symbol ?? '').toLowerCase().includes(tradeFilter.symbol.toLowerCase())) return false;
    if (tradeFilter.sleeve && t._sleeve !== tradeFilter.sleeve) return false;
    if (tradeFilter.engine && String(t.engine_id ?? '') !== tradeFilter.engine) return false;
    if (tradeFilter.reason && String(t.reason ?? t.exit_reason ?? '') !== tradeFilter.reason) return false;
    if (tradeFilter.outcome === 'win' && Number(t.pnl ?? 0) <= 0) return false;
    if (tradeFilter.outcome === 'loss' && Number(t.pnl ?? 0) >= 0) return false;
    return true;
  });

  // apply sort
  const sortedTrades = [...filteredTrades].sort((a, b) => {
    const dir = tradeSort.dir === 'asc' ? 1 : -1;
    const col = tradeSort.col;
    if (col === '_no' || col === 'pnl' || col === 'entry_price' || col === 'exit_price') {
      return (Number(a[col] ?? 0) - Number(b[col] ?? 0)) * dir;
    }
    return String(a[col] ?? '').localeCompare(String(b[col] ?? '')) * dir;
  });

  const filteredTotal = sortedTrades.length;
  const totalPages = Math.ceil(filteredTotal / TRADE_PAGE_SIZE);
  const pageTrades = sortedTrades.slice(tradePage * TRADE_PAGE_SIZE, (tradePage + 1) * TRADE_PAGE_SIZE);
  const filteredPnl = filteredTrades.reduce((sum, t) => sum + Number(t.pnl ?? 0), 0);

  const toggleSort = (col: string) => {
    setTradeSort(s => s.col === col ? { col, dir: s.dir === 'asc' ? 'desc' : 'asc' } : { col, dir: 'asc' });
    setTradePage(0);
  };

  const sortIcon = (col: string) => {
    if (tradeSort.col !== col) return <span style={{ opacity: 0.2, fontSize: 10 }}>⇅</span>;
    return <span style={{ color: 'var(--orange)', fontSize: 10 }}>{tradeSort.dir === 'asc' ? '▲' : '▼'}</span>;
  };

  const TABS = [
    { id: 'summary' as const, label: 'Summary' },
    { id: 'equity' as const, label: 'Equity Curve' },
    { id: 'trades' as const, label: `Trades (${filteredTotal}/${totalTrades})` },
  ];

  return (
    <div>
      {/* Metric cards */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))', gap: 10, marginBottom: 20 }}>
        <MetricCard label="Total Return" value={fmtPct(returnPct)} color={returnPct >= 0 ? 'var(--green)' : 'var(--red)'} />
        {mb?.annualized_return_pct != null && (
          <MetricCard label="Ann. Return" value={fmtPct(mb.annualized_return_pct)} color={Number(mb.annualized_return_pct) >= 0 ? 'var(--green)' : 'var(--red)'} />
        )}
        <MetricCard label="Max Drawdown" value={`-${(s.max_dd_pct ?? 0).toFixed(2)}%`} color="var(--red)" />
        <MetricCard label="Sharpe" value={(s.sharpe ?? 0).toFixed(2)} color="var(--cyan)" />
        {mb?.profit_factor != null && <MetricCard label="Profit Factor" value={fmt(mb.profit_factor, 2)} color="var(--gold)" />}
        <MetricCard label="Win Rate" value={`${(s.win_rate ?? 0).toFixed(1)}%`} />
        <MetricCard label="Trades" value={String(s.trade_count ?? 0)} />
        <MetricCard label="Final Equity" value={`$${(s.final_equity ?? 0).toLocaleString(undefined, { maximumFractionDigits: 0 })}`} />
      </div>

      {/* Tabs */}
      <div style={{ display: 'flex', gap: 2, marginBottom: 20, borderBottom: '1px solid var(--border)' }}>
        {TABS.map(t => (
          <button key={t.id} onClick={() => { setTab(t.id); setTradePage(0); }} style={{
            padding: '9px 18px', fontSize: 15, fontWeight: 500, border: 'none', background: 'none', cursor: 'pointer',
            color: tab === t.id ? 'var(--text1)' : 'var(--text3)',
            borderBottom: tab === t.id ? '2px solid var(--orange)' : '2px solid transparent',
          }}>{t.label}</button>
        ))}
      </div>

      {/* Summary tab */}
      {tab === 'summary' && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
          {[
            { title: 'Trade Stats', rows: [
              ['Total trades', s.trade_count ?? '—'],
              ['Win rate', fmtPct(s.win_rate)],
              ['Avg win', mb?.avg_win_pct != null ? fmtPct(mb.avg_win_pct) : '—'],
              ['Avg loss', mb?.avg_loss_pct != null ? fmtPct(mb.avg_loss_pct) : '—'],
              ['Profit factor', mb?.profit_factor != null ? fmt(mb.profit_factor, 2) : '—'],
              ['Expectancy R', mb?.expectancy_r != null ? fmt(mb.expectancy_r, 3) : '—'],
              ['Avg hold days', mb?.avg_holding_days != null ? fmt(mb.avg_holding_days) : '—'],
              ['Stop exit rate', mb?.stop_exit_rate != null ? fmtPct(mb.stop_exit_rate) : '—'],
            ]},
            { title: 'Portfolio Stats', rows: [
              ['Total return', fmtPct(returnPct)],
              ['Ann. return', mb?.annualized_return_pct != null ? fmtPct(mb.annualized_return_pct) : '—'],
              ['Max drawdown', `-${(s.max_dd_pct ?? 0).toFixed(2)}%`],
              ['Sharpe ratio', (s.sharpe ?? 0).toFixed(2)],
              ['Sortino ratio', mb?.sortino_ratio != null ? fmt(mb.sortino_ratio, 2) : '—'],
              ['Calmar ratio', mb?.calmar_ratio != null ? fmt(mb.calmar_ratio, 2) : '—'],
              ['Avg exposure', mb?.avg_gross_exposure_pct != null ? fmtPct(mb.avg_gross_exposure_pct) : '—'],
              ['Days in market', mb?.days_in_market_pct != null ? fmtPct(mb.days_in_market_pct) : '—'],
            ]},
          ].map(({ title, rows }) => (
            <div key={title} style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 12 }}>{title}</div>
              {rows.map(([k, v]) => (
                <div key={String(k)} style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', borderBottom: '1px solid var(--border)' }}>
                  <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(k)}</span>
                  <span style={{ color: 'var(--text1)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(v)}</span>
                </div>
              ))}
            </div>
          ))}
        </div>
      )}

      {/* Equity Curve tab */}
      {tab === 'equity' && (
        <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
          {chartData.length === 0
            ? <div style={{ textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 14, padding: '40px 0' }}>No equity curve data</div>
            : <>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 16 }}>Equity Curve</div>
                <ResponsiveContainer width="100%" height={280}>
                  <LineChart data={chartData} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
                    <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
                    <XAxis dataKey="date" tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} minTickGap={40} />
                    <YAxis tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} axisLine={false} tickFormatter={v => `$${(v / 1000).toFixed(0)}k`} />
                    <Tooltip contentStyle={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 8, fontFamily: 'var(--font-mono)', fontSize: 12 }} formatter={(v) => [`$${Number(v).toLocaleString()}`, 'Equity']} />
                    <Line type="monotone" dataKey="equity" stroke="var(--orange)" strokeWidth={1.5} dot={false} />
                  </LineChart>
                </ResponsiveContainer>
              </>
          }
        </div>
      )}

      {/* Trades tab */}
      {tab === 'trades' && (
        <div>
          {/* Filter bar */}
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 10, padding: '10px 14px', background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 10 }}>
            <input
              type="text"
              placeholder="Symbol..."
              value={tradeFilter.symbol}
              onChange={e => { setTradeFilter(f => ({ ...f, symbol: e.target.value })); setTradePage(0); }}
              style={{ fontFamily: 'var(--font-mono)', fontSize: 12, background: 'var(--bg2)', border: '1px solid var(--border-md)', borderRadius: 6, padding: '5px 10px', color: 'var(--text1)', outline: 'none', width: 120 }}
            />
            <select
              value={tradeFilter.sleeve}
              onChange={e => { setTradeFilter(f => ({ ...f, sleeve: e.target.value as '' | TradeSleeve })); setTradePage(0); }}
              style={{ fontFamily: 'var(--font-mono)', fontSize: 12, background: 'var(--bg2)', border: '1px solid var(--border-md)', borderRadius: 6, padding: '5px 10px', color: 'var(--text2)', outline: 'none', cursor: 'pointer' }}
            >
              <option value="">All Sleeves</option>
              {sleeveOptions.map(s => <option key={s} value={s}>{tradeSleeveLabel(s)}</option>)}
            </select>
            <select
              value={tradeFilter.engine}
              onChange={e => { setTradeFilter(f => ({ ...f, engine: e.target.value })); setTradePage(0); }}
              style={{ fontFamily: 'var(--font-mono)', fontSize: 12, background: 'var(--bg2)', border: '1px solid var(--border-md)', borderRadius: 6, padding: '5px 10px', color: 'var(--text2)', outline: 'none', cursor: 'pointer' }}
            >
              <option value="">All Engines</option>
              {engineOptions.map(e => <option key={e} value={e}>{e}</option>)}
            </select>
            <select
              value={tradeFilter.reason}
              onChange={e => { setTradeFilter(f => ({ ...f, reason: e.target.value })); setTradePage(0); }}
              style={{ fontFamily: 'var(--font-mono)', fontSize: 12, background: 'var(--bg2)', border: '1px solid var(--border-md)', borderRadius: 6, padding: '5px 10px', color: 'var(--text2)', outline: 'none', cursor: 'pointer' }}
            >
              <option value="">All Exit Reasons</option>
              {reasonOptions.map(r => <option key={r} value={r}>{r}</option>)}
            </select>
            <div style={{ display: 'flex', border: '1px solid var(--border-md)', borderRadius: 6, overflow: 'hidden' }}>
              {(['all', 'win', 'loss'] as const).map(o => (
                <button key={o} onClick={() => { setTradeFilter(f => ({ ...f, outcome: o })); setTradePage(0); }} style={{
                  padding: '5px 12px', fontFamily: 'var(--font-mono)', fontSize: 12, border: 'none', cursor: 'pointer',
                  background: tradeFilter.outcome === o ? (o === 'win' ? 'color-mix(in srgb, var(--green) 18%, transparent)' : o === 'loss' ? 'color-mix(in srgb, var(--red) 18%, transparent)' : 'var(--bg2)') : 'var(--bg1)',
                  color: tradeFilter.outcome === o ? (o === 'win' ? 'var(--green)' : o === 'loss' ? 'var(--red)' : 'var(--text1)') : 'var(--text3)',
                  fontWeight: tradeFilter.outcome === o ? 600 : 400,
                }}>
                  {o === 'all' ? 'All' : o === 'win' ? 'Win' : 'Loss'}
                </button>
              ))}
            </div>
            {(tradeFilter.symbol || tradeFilter.sleeve || tradeFilter.engine || tradeFilter.reason || tradeFilter.outcome !== 'all') && (
              <button onClick={() => { setTradeFilter({ symbol: '', sleeve: '', engine: '', reason: '', outcome: 'all' }); setTradePage(0); }} style={{ fontFamily: 'var(--font-mono)', fontSize: 12, background: 'none', border: '1px solid var(--border-md)', borderRadius: 6, padding: '5px 10px', color: 'var(--text3)', cursor: 'pointer' }}>
                ✕ Clear
              </button>
            )}
            <div style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', display: 'flex', alignItems: 'center', gap: 12 }}>
              <span>{filteredTotal} of {totalTrades} trades</span>
              <span style={{ color: filteredPnl >= 0 ? 'var(--green)' : 'var(--red)', fontWeight: 600 }}>
                PnL {filteredPnl >= 0 ? '+' : ''}${filteredPnl.toFixed(0)}
              </span>
            </div>
          </div>

          {sortedTrades.length === 0
            ? <div style={{ textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 14, padding: '40px 0' }}>
                {totalTrades === 0 ? 'No trades' : 'No trades match filters'}
              </div>
            : <>
                <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden' }}>
                  <div style={{ overflowX: 'auto' }}>
                    <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                      <thead>
                        <tr style={{ borderBottom: '1px solid var(--border-md)', background: 'var(--bg2)' }}>
                          {[
                            { label: 'No.', col: '_no' },
                            { label: 'Symbol', col: 'symbol' },
                            { label: 'Sleeve', col: '_sleeve' },
                            { label: 'Engine', col: 'engine_id' },
                            { label: 'Entry Date', col: 'entry_date' },
                            { label: 'Exit Date', col: 'exit_date' },
                            { label: 'Shares', col: 'shares' },
                            { label: 'Entry $', col: 'entry_price' },
                            { label: 'Exit $', col: 'exit_price' },
                            { label: 'PnL', col: 'pnl' },
                            { label: 'Exit Reason', col: 'reason' },
                          ].map(({ label, col }) => (
                            <th key={col} onClick={() => toggleSort(col)} style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase', color: tradeSort.col === col ? 'var(--orange)' : 'var(--text3)', textAlign: 'left', whiteSpace: 'nowrap', cursor: 'pointer', userSelect: 'none' }}>
                              {label} {sortIcon(col)}
                            </th>
                          ))}
                        </tr>
                      </thead>
                      <tbody>
                        {pageTrades.map((t, i) => {
                          const pnl = Number(t.pnl ?? 0);
                          return (
                            <tr key={i} style={{ borderBottom: i < pageTrades.length - 1 ? '1px solid var(--border)' : 'none', background: i % 2 === 1 ? 'rgba(0,0,0,0.018)' : 'transparent' }}>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)', textAlign: 'right', width: 40 }}>{String(t._no ?? '')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text1)', fontWeight: 500 }}>{String(t.symbol ?? '—')}</td>
                              <td style={{ padding: '9px 14px' }}><SleeveBadge sleeve={t._sleeve} /></td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>{String(t.engine_id ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.entry_date ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.exit_date ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text2)', textAlign: 'right' }}>{t.shares != null ? Math.round(Number(t.shares)) : '—'}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>{t.entry_price != null ? `$${Number(t.entry_price).toFixed(2)}` : '—'}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>{t.exit_price != null ? `$${Number(t.exit_price).toFixed(2)}` : '—'}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: 600, color: pnl >= 0 ? 'var(--green)' : 'var(--red)' }}>{pnl >= 0 ? '+' : ''}${pnl.toFixed(0)}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.reason ?? t.exit_reason ?? '—')}</td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
                <Pagination page={tradePage} totalPages={totalPages} onChange={p => setTradePage(p)} />
              </>
          }
        </div>
      )}

      {/* Collapsible log */}
      {logSection}
    </div>
  );
}

// ── Backtest Results Page ────────────────────────────────────────────────────

type ResultTab = 'summary' | 'equity' | 'trades' | 'engines';

function MetricCard({ label, value, color = 'var(--text1)', sub }: { label: string; value: string; color?: string; sub?: string }) {
  return (
    <div style={{ background: 'var(--bg2)', border: '1px solid var(--border)', borderRadius: 10, padding: '14px 16px' }}>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 8 }}>
        {label}
      </div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 26, fontWeight: 700, color }}>
        {value}
      </div>
      {sub && <div style={{ fontSize: 12, color: 'var(--text3)', marginTop: 3 }}>{sub}</div>}
    </div>
  );
}

function fmt(v: unknown, decimals = 1): string {
  if (v == null) return '—';
  const n = Number(v);
  if (isNaN(n)) return String(v);
  return n.toFixed(decimals);
}

function fmtPct(v: unknown): string {
  if (v == null) return '—';
  const n = Number(v);
  if (isNaN(n)) return '—';
  return `${n >= 0 ? '+' : ''}${n.toFixed(1)}%`;
}

export function BacktestResultsPage() {
  const { runId } = useParams<{ runId: string }>();
  const navigate = useNavigate();
  const [tab, setTab] = useState<ResultTab>('summary');
  const [tradePage, setTradePage] = useState(0);
  const TRADE_PAGE_SIZE = 50;

  const { data: meta, isLoading: metaLoading } = useQuery({
    queryKey: ['run-meta', runId],
    queryFn: () => runsApi.metadata(runId!),
    enabled: !!runId,
  });

  const { data: metrics, isLoading: metricsLoading } = useQuery({
    queryKey: ['run-metrics', runId],
    queryFn: () => runsApi.metrics(runId!),
    enabled: !!runId,
  });

  const { data: equityCurveData } = useQuery({
    queryKey: ['run-equity', runId],
    queryFn: () => runsApi.equityCurve(runId!),
    enabled: tab === 'equity' && !!runId,
  });

  const { data: tradesData } = useQuery({
    queryKey: ['run-trades', runId, tradePage],
    queryFn: () => runsApi.tradeBlotter(runId!, { limit: TRADE_PAGE_SIZE, offset: tradePage * TRADE_PAGE_SIZE }),
    enabled: tab === 'trades' && !!runId,
  });

  const { data: enginesData } = useQuery({
    queryKey: ['run-engines', runId],
    queryFn: () => runsApi.perEngineMetrics(runId!),
    enabled: tab === 'engines' && !!runId,
  });

  if (metaLoading || metricsLoading) return <div style={{ padding: 32 }}><Loading /></div>;

  const m = metrics as Record<string, unknown> | null;
  const expName = (meta as Record<string, unknown>)?.experiment_name as string | undefined;
  const splitName = (meta as Record<string, unknown>)?.split_name as string | undefined;

  const TABS: { id: ResultTab; label: string }[] = [
    { id: 'summary', label: 'Summary' },
    { id: 'equity', label: 'Equity Curve' },
    { id: 'trades', label: 'Trade Blotter' },
    { id: 'engines', label: 'Per-Engine' },
  ];

  const equityPoints = (equityCurveData?.data ?? []) as Record<string, unknown>[];
  const chartData = equityPoints.map(row => ({
    date: String(row.date ?? row.Date ?? ''),
    equity: Number(row.equity ?? row.portfolio_value ?? 0),
    drawdown: Number(row.drawdown_pct ?? row.drawdown ?? 0),
  }));

  const trades = ((tradesData?.trades ?? []) as Record<string, unknown>[]).map(t => ({
    ...t,
    _sleeve: classifyTradeSleeve(t),
  })) as (Record<string, unknown> & { _sleeve: TradeSleeve })[];
  const totalTrades = (tradesData?.total as number) ?? 0;
  const totalPages = Math.ceil(totalTrades / TRADE_PAGE_SIZE);

  return (
    <div style={{ padding: '36px 40px' }} className="fade-up">
      {/* Breadcrumb */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 18, fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)' }}>
        <button
          onClick={() => navigate('/backtest')}
          style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13, padding: 0, display: 'flex', alignItems: 'center', gap: 4 }}
        >
          <ArrowLeft size={12} /> backtest
        </button>
        <ChevronRight size={13} />
        {expName && (
          <>
            <button
              onClick={() => navigate(`/experiments/${encodeURIComponent(expName)}`)}
              style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13, padding: 0 }}
            >
              {expName}
            </button>
            <ChevronRight size={13} />
          </>
        )}
        <span style={{ color: 'var(--text2)' }}>{runId}</span>
      </div>

      {/* Header */}
      <div style={{ marginBottom: 24 }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 4 }}>
          {splitName} split
        </div>
        <h1 style={{ fontSize: 24, fontWeight: 700, color: 'var(--text1)', letterSpacing: '-0.02em' }}>
          {runId}
        </h1>
      </div>

      {/* Metric cards */}
      {m && (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))', gap: 10, marginBottom: 24 }}>
          <MetricCard label="Total Return" value={fmtPct(m.total_return_pct)} color={(Number(m.total_return_pct) ?? 0) >= 0 ? 'var(--green)' : 'var(--red)'} />
          <MetricCard label="Ann. Return" value={fmtPct(m.annualized_return_pct)} color={(Number(m.annualized_return_pct) ?? 0) >= 0 ? 'var(--green)' : 'var(--red)'} />
          <MetricCard label="Max Drawdown" value={fmtPct(m.max_drawdown_pct)} color="var(--red)" />
          <MetricCard label="Sharpe" value={fmt(m.sharpe_ratio, 2)} color="var(--cyan)" />
          <MetricCard label="Profit Factor" value={fmt(m.profit_factor, 2)} color="var(--gold)" />
          <MetricCard label="Win Rate" value={fmtPct(m.win_rate)} />
          <MetricCard label="Trades" value={String(m.trade_count ?? '—')} />
          <MetricCard label="Avg Hold" value={m.avg_holding_days != null ? `${fmt(m.avg_holding_days)}d` : '—'} />
        </div>
      )}

      {/* Tabs */}
      <div style={{ display: 'flex', gap: 2, marginBottom: 20, borderBottom: '1px solid var(--border)' }}>
        {TABS.map(t => (
          <button
            key={t.id}
            onClick={() => setTab(t.id)}
            style={{
              padding: '9px 18px', fontSize: 15, fontWeight: 500, border: 'none',
              background: 'none', cursor: 'pointer', transition: 'all 0.12s',
              color: tab === t.id ? 'var(--text1)' : 'var(--text3)',
              borderBottom: tab === t.id ? '2px solid var(--cyan)' : '2px solid transparent',
            }}
          >
            {t.label}
          </button>
        ))}
      </div>

      {/* Summary tab */}
      {tab === 'summary' && m && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
          <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 12 }}>Trade Stats</div>
            {[
              ['Total trades', m.trade_count],
              ['Win rate', fmtPct(m.win_rate)],
              ['Avg win', fmtPct(m.avg_win_pct)],
              ['Avg loss', fmtPct(m.avg_loss_pct)],
              ['Profit factor', fmt(m.profit_factor, 2)],
              ['Expectancy R', fmt(m.expectancy_r, 3)],
              ['Avg hold days', fmt(m.avg_holding_days)],
              ['Stop exit rate', fmtPct(m.stop_exit_rate)],
              ['Target exit rate', fmtPct(m.target_exit_rate)],
            ].map(([k, v]) => (
              <div key={String(k)} style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', borderBottom: '1px solid var(--border)', fontSize: 14 }}>
                <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(k)}</span>
                <span style={{ color: 'var(--text1)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(v)}</span>
              </div>
            ))}
          </div>
          <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 12 }}>Portfolio Stats</div>
            {[
              ['Total return', fmtPct(m.total_return_pct)],
              ['Ann. return', fmtPct(m.annualized_return_pct)],
              ['Max drawdown', fmtPct(m.max_drawdown_pct)],
              ['Sharpe ratio', fmt(m.sharpe_ratio, 2)],
              ['Sortino ratio', fmt(m.sortino_ratio, 2)],
              ['Calmar ratio', fmt(m.calmar_ratio, 2)],
              ['Avg exposure', fmtPct(m.avg_gross_exposure_pct)],
              ['Days in market', fmtPct(m.days_in_market_pct)],
              ['vs QQQ', fmtPct(m.excess_vs_qqq_pct)],
            ].map(([k, v]) => (
              <div key={String(k)} style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', borderBottom: '1px solid var(--border)', fontSize: 14 }}>
                <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(k)}</span>
                <span style={{ color: 'var(--text1)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(v)}</span>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Equity curve tab */}
      {tab === 'equity' && (
        <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
          {chartData.length === 0
            ? <div style={{ textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 14, padding: '40px 0' }}>No equity curve data</div>
            : (
              <>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 16 }}>Equity Curve</div>
                <ResponsiveContainer width="100%" height={320}>
                  <LineChart data={chartData} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
                    <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
                    <XAxis dataKey="date" tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} minTickGap={40} />
                    <YAxis tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} axisLine={false} tickFormatter={v => `$${(v / 1000).toFixed(0)}k`} />
                    <Tooltip
                      contentStyle={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 8, fontFamily: 'var(--font-mono)', fontSize: 12 }}
                      formatter={(v) => [`$${Number(v).toLocaleString()}`, 'Equity']}
                    />
                    <Line type="monotone" dataKey="equity" stroke="var(--cyan)" strokeWidth={1.5} dot={false} />
                  </LineChart>
                </ResponsiveContainer>

                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 16, marginTop: 24 }}>Drawdown %</div>
                <ResponsiveContainer width="100%" height={160}>
                  <LineChart data={chartData} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
                    <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
                    <XAxis dataKey="date" tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} minTickGap={40} />
                    <YAxis tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} axisLine={false} tickFormatter={v => `${v.toFixed(0)}%`} />
                    <Tooltip
                      contentStyle={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 8, fontFamily: 'var(--font-mono)', fontSize: 12 }}
                      formatter={(v) => [`${Number(v).toFixed(2)}%`, 'Drawdown']}
                    />
                    <Line type="monotone" dataKey="drawdown" stroke="var(--red)" strokeWidth={1.5} dot={false} />
                  </LineChart>
                </ResponsiveContainer>
              </>
            )
          }
        </div>
      )}

      {/* Trade blotter tab */}
      {tab === 'trades' && (
        <div>
          {trades.length === 0
            ? <div style={{ textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 14, padding: '40px 0' }}>No trades</div>
            : (
              <>
                <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden' }}>
                  <div style={{ overflowX: 'auto' }}>
                    <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                      <thead>
                        <tr style={{ borderBottom: '1px solid var(--border-md)', background: 'var(--bg2)' }}>
                          {['Symbol', 'Sleeve', 'Engine', 'Side', 'Entry Date', 'Exit Date', 'Entry $', 'Exit $', 'Return %', 'PnL', 'Exit Reason'].map(h => (
                            <th key={h} style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--text3)', textAlign: 'left', whiteSpace: 'nowrap' }}>
                              {h}
                            </th>
                          ))}
                        </tr>
                      </thead>
                      <tbody>
                        {trades.map((t, i) => {
                          const ret = Number(t.return_pct ?? t.pct_return ?? 0);
                          const netPnl = Number(t.net_pnl ?? t.pnl ?? 0);
                          return (
                            <tr key={i} style={{ borderBottom: i < trades.length - 1 ? '1px solid var(--border)' : 'none', background: i % 2 === 1 ? 'rgba(0,0,0,0.018)' : 'transparent' }}>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text1)' }}>{String(t.symbol ?? '—')}</td>
                              <td style={{ padding: '9px 14px' }}><SleeveBadge sleeve={t._sleeve} /></td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>{String(t.engine_id ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: String(t.side ?? t.direction) === 'long' ? 'var(--green)' : 'var(--red)' }}>{String(t.side ?? t.direction ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.entry_date ?? t.open_date ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.exit_date ?? t.close_date ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>{t.entry_price != null ? `$${Number(t.entry_price).toFixed(2)}` : '—'}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>{t.exit_price != null ? `$${Number(t.exit_price).toFixed(2)}` : '—'}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: ret >= 0 ? 'var(--green)' : 'var(--red)' }}>
                                {ret >= 0 ? '+' : ''}{ret.toFixed(2)}%
                              </td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: netPnl >= 0 ? 'var(--green)' : 'var(--red)' }}>
                                {t.net_pnl != null ? `$${netPnl.toFixed(0)}` : t.pnl != null ? `$${netPnl.toFixed(0)}` : '—'}
                              </td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.exit_reason ?? '—')}</td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
                <Pagination page={tradePage} totalPages={totalPages} onChange={p => setTradePage(p)} />
              </>
            )
          }
        </div>
      )}

      {/* Per-engine tab */}
      {tab === 'engines' && (
        <div>
          {!enginesData || Object.keys(enginesData).length === 0
            ? <div style={{ textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 14, padding: '40px 0' }}>No per-engine data</div>
            : (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                {Object.entries(enginesData).map(([engineId, eData]) => (
                  <div key={engineId} style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
                    <div style={{ fontFamily: 'var(--font-mono)', fontSize: 15, fontWeight: 600, color: 'var(--cyan)', marginBottom: 12 }}>
                      {engineId}
                    </div>
                    <pre style={{ fontSize: 12, color: 'var(--text2)', background: 'var(--bg2)', borderRadius: 7, padding: 14, overflow: 'auto', maxHeight: 300, fontFamily: 'var(--font-mono)', lineHeight: 1.65 }}>
                      {JSON.stringify(eData, null, 2)}
                    </pre>
                  </div>
                ))}
              </div>
            )
          }
        </div>
      )}
    </div>
  );
}

// ── Direct Backtest Results Page ─────────────────────────────────────────────

type DirectResultTab = 'summary' | 'equity' | 'trades';

export function BacktestDirectResultsPage() {
  const { taskId } = useParams<{ taskId: string }>();
  const navigate = useNavigate();
  const [tab, setTab] = useState<DirectResultTab>('summary');
  const [tradePage, setTradePage] = useState(0);
  const TRADE_PAGE_SIZE = 50;

  const { data: task } = useQuery({
    queryKey: ['backtest-task', taskId],
    queryFn: () => backtestApi.task(taskId!),
    enabled: !!taskId,
    staleTime: 60_000,
  });

  const { data: result, isLoading } = useQuery({
    queryKey: ['direct-result', taskId],
    queryFn: () => backtestApi.directResult(taskId!),
    enabled: !!taskId,
  });

  if (isLoading || !result) return <div style={{ padding: 32 }}><Loading /></div>;

  const s = result.summary;
  const mb = result.metrics_bundle as Record<string, unknown>;
  const returnPct = s.return_pct ?? 0;

  const chartData = (result.equity_curve ?? []).map(row => ({
    date: row.date,
    equity: row.equity,
  }));

  const allTrades = ((result.trades ?? []) as Record<string, unknown>[]).map(t => ({
    ...t,
    _sleeve: classifyTradeSleeve(t),
  })) as (Record<string, unknown> & { _sleeve: TradeSleeve })[];
  const totalTrades = allTrades.length;
  const totalPages = Math.ceil(totalTrades / TRADE_PAGE_SIZE);
  const pageTrades = allTrades.slice(tradePage * TRADE_PAGE_SIZE, (tradePage + 1) * TRADE_PAGE_SIZE);

  const TABS: { id: DirectResultTab; label: string }[] = [
    { id: 'summary', label: 'Summary' },
    { id: 'equity', label: 'Equity Curve' },
    { id: 'trades', label: `Trade Blotter (${totalTrades})` },
  ];

  return (
    <div style={{ padding: '36px 40px' }} className="fade-up">
      {/* Breadcrumb */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 18, fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)' }}>
        <button
          onClick={() => navigate('/backtest')}
          style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13, padding: 0, display: 'flex', alignItems: 'center', gap: 4 }}
        >
          <ArrowLeft size={12} /> backtest
        </button>
        <ChevronRight size={13} />
        {task && (
          <>
            <button
              onClick={() => navigate(`/backtest/tasks/${taskId}`)}
              style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13, padding: 0 }}
            >
              {task.experiment_name}
            </button>
            <ChevronRight size={13} />
          </>
        )}
        <span style={{ color: 'var(--text2)' }}>{taskId}</span>
      </div>

      {/* Header */}
      <div style={{ marginBottom: 24 }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--orange)', textTransform: 'uppercase', letterSpacing: '0.08em', marginBottom: 4 }}>
          direct mode result
        </div>
        <h1 style={{ fontSize: 24, fontWeight: 700, color: 'var(--text1)', letterSpacing: '-0.02em' }}>
          {result.session_name}
        </h1>
      </div>

      {/* Metric cards */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))', gap: 10, marginBottom: 24 }}>
        <MetricCard label="Total Return" value={fmtPct(returnPct)} color={returnPct >= 0 ? 'var(--green)' : 'var(--red)'} />
        {mb?.annualized_return_pct != null && (
          <MetricCard label="Ann. Return" value={fmtPct(mb.annualized_return_pct)} color={Number(mb.annualized_return_pct) >= 0 ? 'var(--green)' : 'var(--red)'} />
        )}
        <MetricCard label="Max Drawdown" value={`-${(s.max_dd_pct ?? 0).toFixed(2)}%`} color="var(--red)" />
        <MetricCard label="Sharpe" value={(s.sharpe ?? 0).toFixed(2)} color="var(--cyan)" />
        {mb?.profit_factor != null && (
          <MetricCard label="Profit Factor" value={fmt(mb.profit_factor, 2)} color="var(--gold)" />
        )}
        <MetricCard label="Win Rate" value={`${(s.win_rate ?? 0).toFixed(1)}%`} />
        <MetricCard label="Trades" value={String(s.trade_count ?? 0)} />
        <MetricCard label="Final Equity" value={`$${(s.final_equity ?? 0).toLocaleString(undefined, { maximumFractionDigits: 0 })}`} />
      </div>

      {/* Tabs */}
      <div style={{ display: 'flex', gap: 2, marginBottom: 20, borderBottom: '1px solid var(--border)' }}>
        {TABS.map(t => (
          <button
            key={t.id}
            onClick={() => setTab(t.id)}
            style={{
              padding: '9px 18px', fontSize: 15, fontWeight: 500, border: 'none',
              background: 'none', cursor: 'pointer', transition: 'all 0.12s',
              color: tab === t.id ? 'var(--text1)' : 'var(--text3)',
              borderBottom: tab === t.id ? '2px solid var(--orange)' : '2px solid transparent',
            }}
          >
            {t.label}
          </button>
        ))}
      </div>

      {/* Summary tab */}
      {tab === 'summary' && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
          <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 12 }}>Trade Stats</div>
            {[
              ['Total trades', s.trade_count ?? '—'],
              ['Win rate', fmtPct(s.win_rate)],
              ['Avg win', mb?.avg_win_pct != null ? fmtPct(mb.avg_win_pct) : '—'],
              ['Avg loss', mb?.avg_loss_pct != null ? fmtPct(mb.avg_loss_pct) : '—'],
              ['Profit factor', mb?.profit_factor != null ? fmt(mb.profit_factor, 2) : '—'],
              ['Expectancy R', mb?.expectancy_r != null ? fmt(mb.expectancy_r, 3) : '—'],
              ['Avg hold days', mb?.avg_holding_days != null ? fmt(mb.avg_holding_days) : '—'],
              ['Stop exit rate', mb?.stop_exit_rate != null ? fmtPct(mb.stop_exit_rate) : '—'],
              ['Target exit rate', mb?.target_exit_rate != null ? fmtPct(mb.target_exit_rate) : '—'],
            ].map(([k, v]) => (
              <div key={String(k)} style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', borderBottom: '1px solid var(--border)', fontSize: 14 }}>
                <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(k)}</span>
                <span style={{ color: 'var(--text1)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(v)}</span>
              </div>
            ))}
          </div>
          <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 12 }}>Portfolio Stats</div>
            {[
              ['Total return', fmtPct(returnPct)],
              ['Ann. return', mb?.annualized_return_pct != null ? fmtPct(mb.annualized_return_pct) : '—'],
              ['Max drawdown', fmtPct(-(s.max_dd_pct ?? 0))],
              ['Sharpe ratio', (s.sharpe ?? 0).toFixed(2)],
              ['Sortino ratio', mb?.sortino_ratio != null ? fmt(mb.sortino_ratio, 2) : '—'],
              ['Calmar ratio', mb?.calmar_ratio != null ? fmt(mb.calmar_ratio, 2) : '—'],
              ['Avg exposure', mb?.avg_gross_exposure_pct != null ? fmtPct(mb.avg_gross_exposure_pct) : '—'],
              ['Days in market', mb?.days_in_market_pct != null ? fmtPct(mb.days_in_market_pct) : '—'],
              ['vs QQQ', mb?.excess_vs_qqq_pct != null ? fmtPct(mb.excess_vs_qqq_pct) : '—'],
            ].map(([k, v]) => (
              <div key={String(k)} style={{ display: 'flex', justifyContent: 'space-between', padding: '5px 0', borderBottom: '1px solid var(--border)', fontSize: 14 }}>
                <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(k)}</span>
                <span style={{ color: 'var(--text1)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>{String(v)}</span>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Equity Curve tab */}
      {tab === 'equity' && (
        <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px' }}>
          {chartData.length === 0
            ? <div style={{ textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 14, padding: '40px 0' }}>No equity curve data</div>
            : (
              <>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', textTransform: 'uppercase', letterSpacing: '0.07em', marginBottom: 16 }}>Equity Curve</div>
                <ResponsiveContainer width="100%" height={320}>
                  <LineChart data={chartData} margin={{ top: 5, right: 20, left: 10, bottom: 5 }}>
                    <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" />
                    <XAxis dataKey="date" tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} minTickGap={40} />
                    <YAxis tick={{ fontFamily: 'var(--font-mono)', fontSize: 11, fill: 'var(--text3)' }} tickLine={false} axisLine={false} tickFormatter={v => `$${(v / 1000).toFixed(0)}k`} />
                    <Tooltip
                      contentStyle={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 8, fontFamily: 'var(--font-mono)', fontSize: 12 }}
                      formatter={(v) => [`$${Number(v).toLocaleString()}`, 'Equity']}
                    />
                    <Line type="monotone" dataKey="equity" stroke="var(--orange)" strokeWidth={1.5} dot={false} />
                  </LineChart>
                </ResponsiveContainer>
              </>
            )
          }
        </div>
      )}

      {/* Trade Blotter tab */}
      {tab === 'trades' && (
        <div>
          {pageTrades.length === 0
            ? <div style={{ textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 14, padding: '40px 0' }}>No trades</div>
            : (
              <>
                <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden' }}>
                  <div style={{ overflowX: 'auto' }}>
                    <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                      <thead>
                        <tr style={{ borderBottom: '1px solid var(--border-md)', background: 'var(--bg2)' }}>
                          {['Symbol', 'Sleeve', 'Engine', 'Entry Date', 'Exit Date', 'Entry $', 'Exit $', 'PnL', 'Exit Reason'].map(h => (
                            <th key={h} style={{ padding: '11px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 500, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--text3)', textAlign: 'left', whiteSpace: 'nowrap' }}>
                              {h}
                            </th>
                          ))}
                        </tr>
                      </thead>
                      <tbody>
                        {pageTrades.map((t, i) => {
                          const pnl = Number(t.pnl ?? 0);
                          return (
                            <tr key={i} style={{ borderBottom: i < pageTrades.length - 1 ? '1px solid var(--border)' : 'none', background: i % 2 === 1 ? 'rgba(0,0,0,0.018)' : 'transparent' }}>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text1)' }}>{String(t.symbol ?? '—')}</td>
                              <td style={{ padding: '9px 14px' }}><SleeveBadge sleeve={t._sleeve} /></td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>{String(t.engine_id ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.entry_date ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.exit_date ?? '—')}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>{t.entry_price != null ? `$${Number(t.entry_price).toFixed(2)}` : '—'}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>{t.exit_price != null ? `$${Number(t.exit_price).toFixed(2)}` : '—'}</td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 13, color: pnl >= 0 ? 'var(--green)' : 'var(--red)' }}>
                                {pnl >= 0 ? '+' : ''}${pnl.toFixed(0)}
                              </td>
                              <td style={{ padding: '9px 14px', fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)' }}>{String(t.reason ?? t.exit_reason ?? '—')}</td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
                <Pagination page={tradePage} totalPages={totalPages} onChange={p => setTradePage(p)} />
              </>
            )
          }
        </div>
      )}
    </div>
  );
}
