// SprintReview.jsx — Strategy review.
// intro → (pick a trading goal) → automated scan of that goal's strategies →
// per-strategy mini-proposal with evidence → keep / investigate / cut →
// debrief. Multiple goals are reviewed one lane at a time.

const { useState: useStateSR, useMemo: useMemoSR, useEffect: useEffectSR } = React;

const SR_DISP = {
  keep:        { label: "Keep",        color: "var(--color-success)" },
  investigate: { label: "Investigate", color: "var(--color-focus-ring)" },
  cut:         { label: "Cut",         color: "var(--color-danger)" },
};

function srGlyph(id, size) {
  size = size || 13;
  if (id === "keep") return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.4" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12" /></svg>;
  if (id === "investigate") return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7" /><line x1="21" y1="21" x2="16.5" y2="16.5" /></svg>;
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.4" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>;
}

// Build an evidence-backed proposal for one strategy — works whether it's
// been closed out (realized P&L) or is still paper-trading (paper P&L).
function srProposal(s) {
  const isPaper = s.column === "doing";
  const pnl = isPaper
    ? (s.paperPnl != null ? s.paperPnl : (window.fbPaperPnl ? window.fbPaperPnl(s) : 0))
    : (s.pnl || 0);
  const rec = pnl >= 150 ? "keep" : pnl >= 0 ? "investigate" : "cut";
  const notes = (window.srSampleFeedback ? window.srSampleFeedback(s) : []).slice(0, 1);
  const p = s.params || {};
  const evidence = [
    { label: isPaper ? "Paper P&L" : "Realized P&L", value: (pnl >= 0 ? "+" : "−") + "$" + Math.abs(pnl), good: pnl >= 0 },
    { label: isPaper ? "Paper edge" : "Edge holding", value: pnl >= 150 ? "Strong" : pnl >= 0 ? "Marginal" : "Broke down", good: pnl >= 0 },
    { label: "Risk run", value: (p.riskR ? p.riskR + "R · " + p.stopPct + "% kill · " + p.leverage + "× lev" : "—"), good: true },
  ];
  const rationale = isPaper
    ? (rec === "keep"
        ? "Paper run shows a clean edge at controlled risk. Promote it to a live run."
        : rec === "investigate"
          ? "Paper result is thin or mixed — let it run longer before risking capital."
          : "Paper run lost money with no edge. Drop it before it goes live.")
    : (rec === "keep"
        ? "Booked a clear edge at controlled risk. Keep it on the plan."
        : rec === "investigate"
          ? "Thin or mixed result — not enough signal to commit. Dig in before deciding."
          : "Lost money with no edge to show. Cut it from the plan.");
  return { rec, evidence, rationale, note: notes[0] && notes[0].text, pnl, isPaper };
}

// ─────────────────────────────────────────────────────────────
// Intro
// ─────────────────────────────────────────────────────────────
function SRIntro({ shippedCount, goalCount, onStart, onBack }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", padding: "0 20px 24px", gap: 14, boxSizing: "border-box", overflowY: "auto" }}>
      <button onClick={onBack} style={{ alignSelf: "flex-start", background: "none", border: "none", padding: 0, color: "var(--color-text-link)", fontFamily: "var(--font-family-sans)", fontSize: 14, fontWeight: 500, cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 4, marginTop: 6 }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6" /></svg>
        Back
      </button>
      <div className="ds-overline" style={{ color: "var(--color-brand-primary)" }}>Strategy review</div>
      <h1 style={{ margin: 0, fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 24, lineHeight: "30px", letterSpacing: "-0.01em", color: "var(--color-text-primary)", textWrap: "balance" }}>
        Review each trading goal's strategies.
      </h1>
      <p className="ds-body-sm" style={{ margin: 0, color: "var(--color-text-secondary)" }}>
        Pick a trading goal and the desk runs an automated scan across its strategies —
        closed out or still paper-trading — then proposes a call backed by evidence. For
        each one you decide: <strong>keep</strong> it on the plan,
        <strong>investigate</strong> first, or <strong>cut</strong> it.
      </p>
      <div style={{ background: "var(--color-surface-subtle)", borderRadius: "var(--radius-md)", padding: "12px 14px", display: "flex", flexDirection: "column", gap: 10 }}>
        {Object.keys(SR_DISP).map((id) => (
          <div key={id} style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <span style={{ width: 26, height: 26, borderRadius: "50%", flexShrink: 0, background: SR_DISP[id].color + "14", color: SR_DISP[id].color, display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{srGlyph(id)}</span>
            <span style={{ fontFamily: "var(--font-family-sans)", fontWeight: 700, fontSize: 13.5, color: "var(--color-text-primary)" }}>{SR_DISP[id].label}</span>
            <span style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>
              {id === "keep" ? "Hold it on the plan." : id === "investigate" ? "Dig in before committing." : "Take it off the plan."}
            </span>
          </div>
        ))}
      </div>
      <button onClick={onStart} style={{ marginTop: "auto", height: 52, background: "var(--color-brand-primary)", color: "var(--color-text-on-brand)", border: "none", borderRadius: "var(--radius-sm)", fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 16, cursor: "pointer" }}>
        {goalCount > 1 ? "Choose a goal to review →" : "Open the review →"}
      </button>
    </div>
  );
}

function SREmpty({ onPlanAnother, onBack }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", padding: "0 20px 24px", gap: 16, boxSizing: "border-box" }}>
      <button onClick={onBack} style={{ alignSelf: "flex-start", background: "none", border: "none", padding: 0, color: "var(--color-text-link)", fontFamily: "var(--font-family-sans)", fontSize: 14, fontWeight: 500, cursor: "pointer", marginTop: 6, display: "inline-flex", alignItems: "center", gap: 4 }}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6" /></svg>
        Back
      </button>
      <div className="ds-overline" style={{ color: "var(--color-brand-primary)" }}>Strategy review</div>
      <h1 style={{ margin: 0, fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 22, lineHeight: "28px", color: "var(--color-text-primary)", letterSpacing: "-0.005em", textWrap: "balance" }}>
        Nothing ran — nothing to review.
      </h1>
      <p className="ds-body-sm" style={{ margin: 0, color: "var(--color-text-secondary)" }}>
        Move a strategy into paper trade — or take it live — before running the review.
      </p>
      <button onClick={onPlanAnother} style={{ marginTop: "auto", height: 48, background: "var(--color-brand-primary)", color: "var(--color-text-on-brand)", border: "none", borderRadius: "var(--radius-sm)", fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 15, cursor: "pointer" }}>
        Pick another regime
      </button>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Goal select
// ─────────────────────────────────────────────────────────────
function SRGoalSelect({ goals, reviewed, onPick, onFinish }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", padding: "0 20px 24px", gap: 12, boxSizing: "border-box", overflowY: "auto" }}>
      <div className="ds-overline" style={{ color: "var(--color-brand-primary)", marginTop: 8 }}>Strategy review</div>
      <h2 style={{ margin: 0, fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 22, lineHeight: "28px", color: "var(--color-text-primary)", letterSpacing: "-0.005em", textWrap: "balance" }}>
        Which trading goal do you want to review?
      </h2>
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {goals.map((g) => {
          const done = reviewed.has(g.label);
          return (
            <button key={g.label} onClick={() => onPick(g)} style={{ textAlign: "left", background: "var(--color-surface-default)", border: "1px solid var(--color-border-subtle)", borderRadius: "var(--radius-md)", padding: "12px 14px", cursor: "pointer", font: "inherit", color: "inherit", display: "flex", alignItems: "center", gap: 12 }}>
              <span style={{ width: 30, height: 30, borderRadius: "50%", flexShrink: 0, background: done ? "rgba(11,107,58,0.12)" : "var(--color-surface-promo)", color: done ? "var(--color-success)" : "var(--color-brand-primary)", display: "inline-flex", alignItems: "center", justifyContent: "center" }}>
                {done ? srGlyph("keep", 15) : <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="5" height="16" rx="1" /><rect x="10" y="4" width="5" height="11" rx="1" /><rect x="17" y="4" width="4" height="7" rx="1" /></svg>}
              </span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontWeight: 600, fontSize: 13.5, color: "var(--color-text-primary)", letterSpacing: "-0.003em", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{g.label}</div>
                <div style={{ fontSize: 11, color: "var(--color-text-muted)" }}>{g.stories.length} {g.stories.length === 1 ? "strategy" : "strategies"}{done ? " · reviewed" : ""}</div>
              </div>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" style={{ opacity: 0.6 }}><polyline points="9 18 15 12 9 6" /></svg>
            </button>
          );
        })}
      </div>
      {reviewed.size > 0 && (
        <button onClick={onFinish} style={{ marginTop: "auto", height: 48, background: "var(--color-brand-primary)", color: "var(--color-text-on-brand)", border: "none", borderRadius: "var(--radius-sm)", fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 15, cursor: "pointer" }}>
          Finish review
        </button>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Automated scan
// ─────────────────────────────────────────────────────────────
function SRScan({ goal, onComplete }) {
  const total = goal.stories.length;
  const [done, setDone] = useStateSR(0);
  useEffectSR(() => {
    if (done >= total) { const t = setTimeout(onComplete, 700); return () => clearTimeout(t); }
    const t = setTimeout(() => setDone((d) => d + 1), done === 0 ? 450 : 560);
    return () => clearTimeout(t);
  }, [done, total, onComplete]);
  const pct = total ? Math.round((Math.min(done, total) / total) * 100) : 100;
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", boxSizing: "border-box" }}>
      <style>{`@keyframes srSpin{to{transform:rotate(360deg)}}`}</style>
      <div style={{ padding: "12px 20px", borderBottom: "1px solid var(--color-border-subtle)", background: "var(--color-surface-default)" }}>
        <div className="ds-overline" style={{ color: "var(--color-brand-primary)", marginBottom: 6 }}>Scanning · {goal.label}</div>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <div style={{ flex: 1, height: 6, background: "var(--color-border-subtle)", borderRadius: 3, overflow: "hidden" }}>
            <div style={{ height: "100%", width: pct + "%", background: "var(--color-brand-primary)", transition: "width 360ms var(--ease-standard)" }} />
          </div>
          <span style={{ fontWeight: 700, fontSize: 12, color: "var(--color-text-secondary)", fontVariantNumeric: "tabular-nums" }}>{Math.min(done, total)}/{total}</span>
        </div>
      </div>
      <div style={{ flex: 1, minHeight: 0, overflowY: "auto", padding: "12px 20px", background: "var(--color-surface-subtle)", display: "flex", flexDirection: "column", gap: 8 }}>
        {goal.stories.map((s, i) => {
          const state = done > i ? "done" : done === i ? "scan" : "wait";
          return (
            <div key={s.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 12px", background: "var(--color-surface-default)", border: "1px solid var(--color-border-subtle)", borderRadius: "var(--radius-sm)", opacity: state === "wait" ? 0.5 : 1, transition: "opacity 240ms var(--ease-standard)" }}>
              <span style={{ width: 16, height: 16, flexShrink: 0, display: "inline-flex", alignItems: "center", justifyContent: "center" }}>
                {state === "scan" ? <span style={{ width: 14, height: 14, borderRadius: "50%", border: "2px solid var(--color-border-subtle)", borderTopColor: "var(--color-brand-primary)", display: "inline-block", animation: "srSpin 0.7s linear infinite" }} />
                  : state === "done" ? <span style={{ color: "var(--color-success)" }}>{srGlyph("keep", 14)}</span>
                  : <span style={{ width: 9, height: 9, borderRadius: "50%", border: "1.5px solid var(--color-border-subtle)" }} />}
              </span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--color-text-primary)" }}>{s.want}</div>
                <div style={{ fontSize: 10.5, color: "var(--color-text-muted)" }}>{state === "done" ? "Analysis ready" : "Pulling trades, fills, drawdown…"}</div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Decide — proposal card per strategy
// ─────────────────────────────────────────────────────────────
function SRProposalCard({ s, decision, onDecide }) {
  const pr = useMemoSR(() => srProposal(s), [s]);
  const recDef = SR_DISP[pr.rec];
  return (
    <div style={{ background: "var(--color-surface-default)", border: "1px solid var(--color-border-subtle)", borderRadius: "var(--radius-md)", padding: "12px 14px", display: "flex", flexDirection: "column", gap: 8 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
        <div style={{ minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 1 }}>
            <span className="ds-overline" style={{ fontSize: 10, color: "var(--color-text-muted)" }}>{s.ref} · {s.tag}</span>
            <span style={{
              fontSize: 8.5, fontWeight: 700, letterSpacing: "0.08em", textTransform: "uppercase",
              padding: "1px 6px", borderRadius: "var(--radius-pill)", flexShrink: 0,
              color: pr.isPaper ? "var(--color-focus-ring)" : "var(--color-text-muted)",
              background: pr.isPaper ? "rgba(0,95,204,0.10)" : "var(--color-surface-subtle)",
              border: "1px solid " + (pr.isPaper ? "rgba(0,95,204,0.25)" : "var(--color-border-subtle)"),
            }}>{pr.isPaper ? "Paper trade" : "Closed"}</span>
          </div>
          <div style={{ fontWeight: 600, fontSize: 14, color: "var(--color-text-primary)", letterSpacing: "-0.003em" }}>{s.want}</div>
        </div>
        <span style={{ fontWeight: 700, fontSize: 14, fontVariantNumeric: "tabular-nums", color: pr.pnl >= 0 ? "var(--color-success)" : "var(--color-danger)", flexShrink: 0 }}>{pr.pnl >= 0 ? "+" : "−"}${Math.abs(pr.pnl)}</span>
      </div>

      {/* Evidence */}
      <div style={{ display: "flex", flexDirection: "column", gap: 4, background: "var(--color-surface-subtle)", borderRadius: "var(--radius-sm)", padding: "8px 10px" }}>
        {pr.evidence.map((e, i) => (
          <div key={i} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
            <span style={{ fontSize: 10.5, letterSpacing: "0.06em", textTransform: "uppercase", fontWeight: 700, color: "var(--color-text-muted)" }}>{e.label}</span>
            <span style={{ fontSize: 12, fontWeight: 600, color: e.good ? "var(--color-text-primary)" : "var(--color-danger)", fontVariantNumeric: "tabular-nums" }}>{e.value}</span>
          </div>
        ))}
        {pr.note && <div style={{ fontSize: 11, lineHeight: "15px", color: "var(--color-text-secondary)", marginTop: 2, borderTop: "1px solid var(--color-border-subtle)", paddingTop: 5 }}>“{pr.note}”</div>}
      </div>

      {/* Proposal */}
      <div style={{ display: "flex", alignItems: "flex-start", gap: 8, background: recDef.color + "10", borderLeft: "3px solid " + recDef.color, borderRadius: "var(--radius-sm)", padding: "8px 10px" }}>
        <span style={{ fontSize: 10, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase", color: recDef.color, flexShrink: 0, paddingTop: 1 }}>Proposal · {recDef.label}</span>
      </div>
      <div style={{ fontSize: 12, lineHeight: "16px", color: "var(--color-text-secondary)" }}>{pr.rationale}</div>

      {/* Decision */}
      <div style={{ display: "flex", gap: 6 }}>
        {["keep", "investigate", "cut"].map((id) => {
          const on = decision === id;
          return (
            <button key={id} onClick={() => onDecide(s.id, id)} style={{ flex: 1, height: 40, display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 5, background: on ? SR_DISP[id].color : "var(--color-surface-default)", color: on ? "#fff" : "var(--color-text-primary)", border: "1.5px solid " + (on ? SR_DISP[id].color : "var(--color-border-subtle)"), borderRadius: "var(--radius-sm)", fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 12.5, cursor: "pointer" }}>
              {srGlyph(id, 12)} {SR_DISP[id].label}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function SRDecide({ goal, decisions, onDecide, onDone }) {
  const allDecided = goal.stories.every((s) => decisions[s.id]);
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", boxSizing: "border-box" }}>
      <div style={{ padding: "10px 20px 12px", borderBottom: "1px solid var(--color-border-subtle)", background: "var(--color-surface-default)" }}>
        <div className="ds-overline" style={{ color: "var(--color-brand-primary)", marginBottom: 2 }}>Scan complete · {goal.label}</div>
        <div style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>Decide each strategy's place on the plan.</div>
      </div>
      <div style={{ flex: 1, minHeight: 0, overflowY: "auto", padding: "12px 20px", background: "var(--color-surface-subtle)", display: "flex", flexDirection: "column", gap: 10 }}>
        {goal.stories.map((s) => (
          <SRProposalCard key={s.id} s={s} decision={decisions[s.id]} onDecide={onDecide} />
        ))}
      </div>
      <div style={{ borderTop: "1px solid var(--color-border-subtle)", background: "var(--color-surface-default)", padding: "10px 20px 14px" }}>
        <button onClick={onDone} disabled={!allDecided} style={{ width: "100%", height: 46, background: allDecided ? "var(--color-brand-primary)" : "var(--color-surface-subtle)", color: allDecided ? "var(--color-text-on-brand)" : "var(--color-text-muted)", border: "none", borderRadius: "var(--radius-sm)", fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 15, cursor: allDecided ? "pointer" : "not-allowed" }}>
          {allDecided ? "Lock these calls" : "Decide every strategy"}
        </button>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Debrief
// ─────────────────────────────────────────────────────────────
function SRDebrief({ stories, decisions, canRetro, onRetro, onExit }) {
  const counts = { keep: 0, investigate: 0, cut: 0 };
  stories.forEach((s) => { if (decisions[s.id]) counts[decisions[s.id]]++; });
  const hasPaper = stories.some((s) => s.column === "doing");
  const hasRealized = stories.some((s) => s.column !== "doing");
  const booked = stories.filter((s) => s.column !== "doing").reduce((a, s) => a + (s.pnl || 0), 0);
  const paperTotal = stories.filter((s) => s.column === "doing").reduce((a, s) => a + srProposal(s).pnl, 0);
  const good = stories.filter((s) => decisions[s.id] === srProposal(s).rec).length;

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", padding: "0 20px 20px", gap: 12, boxSizing: "border-box", overflowY: "auto" }}>
      <div className="ds-overline" style={{ color: "var(--color-brand-primary)", marginTop: 6 }}>Review complete</div>
      {hasRealized ? (
        <h2 style={{ margin: 0, fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 23, lineHeight: "29px", letterSpacing: "-0.005em", color: "var(--color-text-primary)", textWrap: "balance" }}>
          {booked >= 0 ? "+" : "−"}${Math.abs(booked).toLocaleString()} booked on the day.
        </h2>
      ) : (
        <h2 style={{ margin: 0, fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 23, lineHeight: "29px", letterSpacing: "-0.005em", color: "var(--color-text-primary)", textWrap: "balance" }}>
          {paperTotal >= 0 ? "+" : "−"}${Math.abs(paperTotal).toLocaleString()} in paper — simulated, nothing booked.
        </h2>
      )}
      {hasRealized && hasPaper && (
        <div style={{ fontSize: 12, lineHeight: "16px", color: "var(--color-text-muted)", marginTop: -4 }}>
          Plus {paperTotal >= 0 ? "+" : "−"}${Math.abs(paperTotal).toLocaleString()} still running in paper (simulated, not booked).
        </div>
      )}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 8 }}>
        {["keep", "investigate", "cut"].map((id) => (
          <div key={id} style={{ background: "var(--color-surface-subtle)", border: "1px solid var(--color-border-subtle)", borderRadius: "var(--radius-md)", padding: "10px", display: "flex", flexDirection: "column", gap: 2 }}>
            <div style={{ fontSize: 9, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase", color: SR_DISP[id].color }}>{SR_DISP[id].label}</div>
            <div style={{ fontFamily: "var(--font-family-sans)", fontWeight: 700, fontSize: 20, color: "var(--color-text-primary)", fontVariantNumeric: "tabular-nums", lineHeight: 1 }}>{counts[id]}</div>
          </div>
        ))}
      </div>
      <div style={{ background: "var(--color-surface-promo)", borderRadius: "var(--radius-md)", padding: "12px 14px", display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div>
          <div className="ds-overline" style={{ fontSize: 10, color: "var(--color-brand-mark)" }}>Calls matching the desk</div>
          <div style={{ fontSize: 12, color: "var(--color-text-secondary)" }}>Keep winners, cut losers, investigate the rest.</div>
        </div>
        <div style={{ fontFamily: "var(--font-family-sans)", fontWeight: 700, fontSize: 22, color: "var(--color-brand-mark)", fontVariantNumeric: "tabular-nums" }}>{good}/{stories.length}</div>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 1, background: "var(--color-border-subtle)", border: "1px solid var(--color-border-subtle)", borderRadius: "var(--radius-md)", overflow: "hidden", maxHeight: 260, overflowY: "auto" }}>
        {stories.map((s) => {
          const rp = srProposal(s);
          return (
          <div key={s.id} style={{ background: "var(--color-surface-default)", padding: "10px 12px", display: "flex", alignItems: "center", gap: 10 }}>
            <span style={{ width: 22, height: 22, borderRadius: "50%", flexShrink: 0, background: SR_DISP[decisions[s.id]].color + "18", color: SR_DISP[decisions[s.id]].color, display: "inline-flex", alignItems: "center", justifyContent: "center" }}>{srGlyph(decisions[s.id], 12)}</span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--color-text-primary)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{s.want}</div>
              <div style={{ fontSize: 10, color: "var(--color-text-muted)" }}>{s.goalLabel}{rp.isPaper ? " · paper" : ""}</div>
            </div>
            <span style={{ fontSize: 12, fontWeight: 700, fontVariantNumeric: "tabular-nums", color: rp.pnl >= 0 ? "var(--color-success)" : "var(--color-danger)" }}>{rp.pnl >= 0 ? "+" : "−"}${Math.abs(rp.pnl)}</span>
          </div>
          );
        })}
      </div>

      {canRetro ? (
        <button onClick={() => onRetro({ bv: Math.max(0, booked), maxBV: stories.reduce((a, s) => a + Math.max(0, s.pnl || 0), 0) })} style={{ marginTop: "auto", height: 50, background: "var(--color-brand-primary)", color: "var(--color-text-on-brand)", border: "none", borderRadius: "var(--radius-sm)", fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 15, cursor: "pointer", display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8 }}>
          Retrospective
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6" /></svg>
        </button>
      ) : (
        <div style={{ marginTop: "auto", display: "flex", flexDirection: "column", gap: 8 }}>
          <div style={{ fontSize: 11.5, lineHeight: "16px", color: "var(--color-text-muted)", textAlign: "center" }}>
            The deep process retrospective unlocks once a trading goal is completed in full — every strategy closed out.
          </div>
          <button onClick={onExit} style={{ height: 50, background: "var(--color-brand-primary)", color: "var(--color-text-on-brand)", border: "none", borderRadius: "var(--radius-sm)", fontFamily: "var(--font-family-sans)", fontWeight: 600, fontSize: 15, cursor: "pointer" }}>
            Back to the desk
          </button>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Container
// ─────────────────────────────────────────────────────────────
function SprintReview({ sg, shippedStories, reviewStories, canRetro, onExit, onPlanAnother, onRetro }) {
  const stories = ((reviewStories && reviewStories.length ? reviewStories : shippedStories) || []).filter(Boolean);
  const goals = useMemoSR(() => {
    const order = [], map = {};
    stories.forEach((s) => { const k = s.goalLabel || (sg && sg.goal) || "Trading goal"; if (!map[k]) { map[k] = []; order.push(k); } map[k].push(s); });
    return order.map((k) => ({ label: k, stories: map[k] }));
  }, [stories]);

  const [phase, setPhase] = useStateSR(stories.length === 0 ? "empty" : "intro");
  const [activeGoal, setActiveGoal] = useStateSR(null);
  const [decisions, setDecisions] = useStateSR({});
  const [reviewed, setReviewed] = useStateSR(() => new Set());

  if (phase === "empty") return <SREmpty onPlanAnother={onPlanAnother} onBack={onExit} />;
  if (phase === "intro") {
    return <SRIntro shippedCount={stories.length} goalCount={goals.length}
      onBack={onExit}
      onStart={() => { if (goals.length === 1) { setActiveGoal(goals[0]); setPhase("scan"); } else setPhase("goal"); }} />;
  }
  if (phase === "goal") {
    return <SRGoalSelect goals={goals} reviewed={reviewed}
      onPick={(g) => { setActiveGoal(g); setPhase("scan"); }}
      onFinish={() => setPhase("done")} />;
  }
  if (phase === "scan" && activeGoal) {
    return <SRScan goal={activeGoal} onComplete={() => setPhase("decide")} />;
  }
  if (phase === "decide" && activeGoal) {
    return <SRDecide goal={activeGoal} decisions={decisions}
      onDecide={(id, d) => setDecisions((p) => ({ ...p, [id]: d }))}
      onDone={() => {
        const nextReviewed = new Set(reviewed); nextReviewed.add(activeGoal.label);
        setReviewed(nextReviewed);
        const remaining = goals.filter((g) => !nextReviewed.has(g.label));
        if (remaining.length === 0) setPhase("done");
        else setPhase("goal");
      }} />;
  }
  // done — only the strategies the trader actually decided on
  const reviewedStories = stories.filter((s) => decisions[s.id]);
  return <SRDebrief stories={reviewedStories.length ? reviewedStories : stories} decisions={decisions} canRetro={canRetro} onRetro={onRetro} onExit={onExit} />;
}

Object.assign(window, { SprintReview });
