// Project detail screen — deep-dive on a single project

function ProjectDetail({ slug = "contract-ai", setScreen }){
  const project = PROJECTS.find(p => p.slug === slug) || PROJECTS[0];
  const [tab, setTab] = useState("overview");      // overview | requests | comparison | reports
  const [range, setRange] = useState("30d");        // 30d | 90d | all

  // Derive period stats for this project
  const totals = useMemo(() => deriveProjectTotals(project), [project.slug]);
  const provider = MODELS[project.primaryModel].provider;
  const created = "2026-03-04";

  return (
    <div data-screen-label="03 Project Detail" style={{ padding:"20px 28px 40px", maxWidth:1380, margin:"0 auto", display:"flex", flexDirection:"column", gap:18 }}>

      {/* Breadcrumb */}
      <div style={{ display:"flex", alignItems:"center", gap:8, fontSize:12.5, color:"var(--fg-2)" }}>
        <button onClick={()=>setScreen("projects")} style={{ background:"none", border:"none", color:"var(--fg-2)", padding:0, cursor:"pointer", fontSize:12.5, display:"inline-flex", alignItems:"center", gap:5 }}>
          <Icon name="chevLeft" size={12}/> Projects
        </button>
        <span style={{ color:"var(--fg-3)" }}>/</span>
        <span style={{ color:"var(--fg-0)", fontWeight:500 }}>{project.name}</span>
      </div>

      {/* ── Hero header ─────────────────────────────────── */}
      <header className="card" style={{ padding:0, overflow:"hidden", position:"relative" }}>
        <div style={{ position:"absolute", inset:0, background:`linear-gradient(135deg, ${PROVIDERS[provider].color}11 0%, transparent 60%)`, pointerEvents:"none" }}/>
        <div style={{ padding:"22px 26px 18px", display:"flex", justifyContent:"space-between", alignItems:"flex-start", gap:24, position:"relative" }}>
          <div style={{ display:"flex", flexDirection:"column", gap:14 }}>
            <div style={{ display:"flex", alignItems:"center", gap:12 }}>
              <div style={{ width:40, height:40, borderRadius:10, background:`linear-gradient(135deg, ${PROVIDERS[provider].color}, ${PROVIDERS[provider].color}cc)`, color:"#fff", display:"flex", alignItems:"center", justifyContent:"center", fontSize:18, fontWeight:600, boxShadow:"0 1px 2px rgba(20,16,8,0.10)" }}>{project.name.charAt(0).toUpperCase()}</div>
              <div>
                <h1 style={{ margin:0, fontSize:24, fontWeight:600, color:"var(--fg-0)", letterSpacing:-0.4 }}>{project.name}</h1>
                <div style={{ display:"flex", gap:10, alignItems:"center", marginTop:4, fontSize:12, color:"var(--fg-2)" }}>
                  <span className="mono" style={{ background:"var(--bg-3)", padding:"1px 7px", borderRadius:5, color:"var(--fg-1)" }}>/{project.slug}</span>
                  <span>{project.client}</span>
                  <span style={{ color:"var(--fg-3)" }}>·</span>
                  <span>Created <span className="mono">{created}</span></span>
                  <span style={{ color:"var(--fg-3)" }}>·</span>
                  <span style={{ display:"inline-flex", alignItems:"center", gap:5, color:"var(--pos)" }}>
                    <span style={{ width:6, height:6, borderRadius:"50%", background:"var(--pos)" }}/>Active
                  </span>
                </div>
              </div>
            </div>
            <div style={{ display:"flex", alignItems:"baseline", gap:14, marginTop:4 }}>
              <Money value={project.spend} size="hero"/>
              <Delta pct={0.421} size="lg"/>
              <span style={{ fontSize:13, color:"var(--fg-2)" }}>this period · <span className="mono">{fmtUSD(project.spend * GBP_TO_USD, 2)}</span></span>
            </div>
          </div>

          <div style={{ display:"flex", flexDirection:"column", gap:10, alignItems:"flex-end" }}>
            <div style={{ display:"flex", gap:8 }}>
              <button style={btnSecondary()}><Icon name="sparkles" size={13}/> Optimise</button>
              <button style={btnSecondary()}><Icon name="ext" size={13}/> Open in IDE</button>
              <button style={btnPrimary()}><Icon name="download" size={13}/> Generate report</button>
            </div>
            <div style={{ display:"flex", alignItems:"center", gap:8, fontSize:11, color:"var(--fg-3)" }}>
              <span className="mono" style={{ padding:"2px 7px", border:"1px solid var(--line-2)", borderRadius:5, background:"#fff" }}>.haltonrc</span>
              <span>auto-tagging enabled</span>
            </div>
          </div>
        </div>

        {/* Inline KPI strip */}
        <div style={{ display:"grid", gridTemplateColumns:"repeat(5,1fr)", borderTop:"1px solid var(--line-1)", background:"rgba(20,16,8,0.012)" }}>
          <PStat label="Requests"           value={project.requests.toLocaleString()} sub={`${Math.round(project.requests/PERIOD.daysElapsed)}/day`} delta={0.38} icon="activity"/>
          <PStat label="Avg cost / req"     value={fmtGBP(project.spend/project.requests, 6)}  sub="Opus 4.7 baseline" icon="coins" border/>
          <PStat label="Tokens"             value={fmtTokens(totals.tokens)} sub={`${fmtTokens(totals.input)} in · ${fmtTokens(totals.output)} out`} icon="tokens" border/>
          <PStat label="Cache hit rate"     value={`${(totals.cacheRate*100).toFixed(0)}%`} sub={`saved ≈ ${fmtGBP(totals.cacheSaved)}`} icon="chip" delta={0.12} border/>
          <PStat label="Avg latency"        value={<><span className="mono">{totals.latency}</span><span style={{ color:"var(--fg-3)", fontWeight:400, marginLeft:2 }}>ms</span></>} sub="P95 1,840ms" icon="clock" border/>
        </div>
      </header>

      {/* ── Tabs ───────────────────────────────────────── */}
      <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", borderBottom:"1px solid var(--line-1)", marginTop:-4 }}>
        <div style={{ display:"flex", gap:2 }}>
          {[
            { id:"overview",   label:"Overview" },
            { id:"requests",   label:"Requests", count: project.requests },
            { id:"comparison", label:"Cross-provider" },
            { id:"reports",    label:"Reports" },
          ].map(t => {
            const active = tab === t.id;
            return (
              <button key={t.id} onClick={()=>setTab(t.id)} style={{
                appearance:"none", background:"transparent", border:"none",
                padding:"10px 14px",
                fontSize:13, fontWeight: active?500:400,
                color: active?"var(--fg-0)":"var(--fg-2)",
                borderBottom: active?"2px solid var(--accent)":"2px solid transparent",
                marginBottom:-1,
                cursor:"pointer",
                display:"inline-flex", alignItems:"center", gap:8,
              }}>
                {t.label}
                {t.count != null && <span className="mono" style={{ fontSize:10.5, color: active?"var(--fg-3)":"var(--fg-3)" }}>{t.count.toLocaleString()}</span>}
              </button>
            );
          })}
        </div>
        <div style={{ display:"flex", gap:6, paddingBottom:6 }}>
          <RangeToggle value={range} onChange={setRange}/>
        </div>
      </div>

      {tab === "overview" && (
        <div style={{ display:"grid", gridTemplateColumns:"minmax(0, 1fr) 320px", gap:18 }}>
          {/* ── Main column ─────────────────────────────── */}
          <div style={{ display:"flex", flexDirection:"column", gap:18, minWidth:0 }}>
            <ProjectSpendChart project={project} totals={totals}/>
            <ProjectRequestVolume/>
            <RecentRequestsTable project={project}/>
          </div>

          {/* ── Sidebar ────────────────────────────────── */}
          <aside style={{ display:"flex", flexDirection:"column", gap:14 }}>
            <PeriodSummaryCard totals={totals}/>
            <ByProviderCard totals={totals}/>
            <ByModelCard totals={totals}/>
            <EfficiencyCard project={project} totals={totals}/>
            <DangerZoneCard/>
          </aside>
        </div>
      )}

      {tab === "requests" && (
        <div className="card" style={{ padding:0, overflow:"hidden" }}>
          <RequestsFull project={project}/>
        </div>
      )}

      {tab === "comparison" && <ComparisonView project={project} totals={totals}/>}
      {tab === "reports"    && <ReportsStub project={project}/>}

      <div style={{ textAlign:"center", color:"var(--fg-3)", fontSize:11, marginTop:6 }}>{project.requests.toLocaleString()} requests · period: May 2026 (partial)</div>
    </div>
  );
}

// ── Helpers ─────────────────────────────────────────────────
function deriveProjectTotals(project){
  // Synth realistic numbers from spend + requests + primary model
  const m = MODELS[project.primaryModel];
  const isOpus = project.primaryModel.includes("opus");
  const avgInPerReq  = isOpus ? 4200 : 1800;
  const avgOutPerReq = isOpus ? 980  : 380;
  const thinkPerReq  = isOpus ? 1200 : 0;
  const cachedPerReq = isOpus ? 1600 : 600;

  const input   = project.requests * avgInPerReq;
  const output  = project.requests * avgOutPerReq;
  const thinking= project.requests * thinkPerReq;
  const cached  = project.requests * cachedPerReq;
  const tokens  = input + output;

  const cacheRate = cached / (cached + input);
  const cacheSavedUSD = cached * (m.in * 0.9) / 1e6;
  const cacheSaved = cacheSavedUSD * USD_TO_GBP;

  // Per-provider breakdown (in this period — mostly primary, tiny long tail)
  const primaryProvider = m.provider;
  const byProvider = [
    { provider: primaryProvider, cost: project.spend * 0.985, requests: Math.floor(project.requests*0.985) },
  ];
  if (primaryProvider !== "google") byProvider.push({ provider:"google", cost: project.spend*0.015, requests: Math.floor(project.requests*0.015) });

  // Per-model breakdown
  const byModel = [
    { id: project.primaryModel, cost: project.spend * 0.92, requests: Math.floor(project.requests*0.92) },
  ];
  if (project.primaryModel !== "claude-sonnet-4-6") byModel.push({ id:"claude-sonnet-4-6", cost: project.spend*0.05, requests: Math.floor(project.requests*0.05) });
  if (project.primaryModel !== "claude-haiku-4-5")  byModel.push({ id:"claude-haiku-4-5",  cost: project.spend*0.025,requests: Math.floor(project.requests*0.025) });
  byModel.push({ id:"gemini-3-flash", cost: project.spend*0.005, requests: Math.floor(project.requests*0.005) });

  return {
    input, output, thinking, cached, tokens,
    cacheRate, cacheSaved,
    latency: isOpus ? 1620 : 420,
    byProvider, byModel,
  };
}

// Compact stat used in project header strip
function PStat({ label, value, sub, delta, icon, border }){
  return (
    <div style={{ padding:"14px 18px", borderLeft: border ? "1px solid var(--line-1)" : "none", display:"flex", flexDirection:"column", gap:5 }}>
      <span style={{ display:"inline-flex", alignItems:"center", gap:7, fontSize:10.5, letterSpacing:0.08, textTransform:"uppercase", color:"var(--fg-3)", fontWeight:600 }}>
        <Icon name={icon} size={12} stroke="var(--fg-3)"/>{label}
      </span>
      <div style={{ display:"flex", alignItems:"baseline", gap:7 }}>
        <span className="mono" style={{ fontSize:18, fontWeight:600, color:"var(--fg-0)", letterSpacing:-0.2 }}>{value}</span>
        {delta != null && <Delta pct={delta}/>}
      </div>
      <span style={{ fontSize:10.5, color:"var(--fg-2)" }}>{sub}</span>
    </div>
  );
}

// Range toggle
function RangeToggle({ value, onChange }){
  const opts = [
    { id:"30d", label:"30d" },
    { id:"90d", label:"90d" },
    { id:"all", label:"All" },
  ];
  return (
    <div style={{ display:"inline-flex", padding:3, background:"var(--bg-3)", borderRadius:8, border:"1px solid var(--line-1)" }}>
      {opts.map(o => {
        const active = value === o.id;
        return (
          <button key={o.id} onClick={()=>onChange(o.id)} style={{
            appearance:"none", border:"none", padding:"4px 12px", borderRadius:6,
            background: active ? "#fff" : "transparent",
            boxShadow: active ? "0 0 0 1px var(--line-1), 0 1px 1px rgba(20,16,8,0.04)" : "none",
            color: active ? "var(--fg-0)" : "var(--fg-2)",
            fontSize:11.5, fontWeight: active ? 500 : 400, cursor:"pointer",
          }}>{o.label}</button>
        );
      })}
    </div>
  );
}

// ── Spend over time chart (project-scoped, stacked by model) ──────
function ProjectSpendChart({ project, totals }){
  const ref = useRef(null);
  const w = useWidth(ref);
  const [hover, setHover] = useState(null);
  const h = 240;
  const padL = 50, padR = 18, padT = 16, padB = 32;
  const innerW = Math.max(100, w - padL - padR);
  const innerH = h - padT - padB;

  // Build 30-day series shaped by project.shape, decomposed into model layers
  const n = 30;
  const base = makeSeries(project.spend, n, project.shape);
  const data = base.map((v, i) => ({
    d: i + 1,
    primary:  v * 0.92,
    sonnet:   v * 0.05,
    haiku:    v * 0.025,
    gemini:   v * 0.005,
    total:    v,
  }));

  const layers = [
    { id:"primary", color: PROVIDERS[MODELS[project.primaryModel].provider].color, label: MODELS[project.primaryModel].short },
    { id:"sonnet",  color: PROVIDERS.anthropic.color, label:"Sonnet 4.6", opacity:0.55 },
    { id:"haiku",   color: PROVIDERS.anthropic.color, label:"Haiku 4.5",  opacity:0.35 },
    { id:"gemini",  color: PROVIDERS.google.color,    label:"Gemini 3" },
  ];

  const maxCost = Math.max(...data.map(d=>d.total), 1) * 1.18;
  const x = i => (i/(n-1))*innerW;
  const y = v => innerH - (v/maxCost)*innerH;

  // Stacked paths
  function stackPath(layerIdx){
    const upper = data.map((d,i) => {
      const top = layers.slice(0, layerIdx+1).reduce((s,L) => s + (d[L.id] || 0), 0);
      return [x(i), y(top)];
    });
    const lower = data.map((d,i) => {
      const bot = layers.slice(0, layerIdx).reduce((s,L) => s + (d[L.id] || 0), 0);
      return [x(i), y(bot)];
    }).reverse();
    const all = [...upper, ...lower];
    return "M" + all.map(([px,py]) => `${px.toFixed(1)},${py.toFixed(1)}`).join(" L") + " Z";
  }

  const yTicks = [0, 0.25, 0.5, 0.75, 1].map(t => ({ v: t*maxCost, y: y(t*maxCost) }));

  function onMove(e){
    const rect = ref.current.getBoundingClientRect();
    const px = e.clientX - rect.left - padL;
    if (px < 0 || px > innerW) { setHover(null); return; }
    setHover(Math.max(0, Math.min(n-1, Math.round((px/innerW)*(n-1)))));
  }

  return (
    <section className="card" style={{ padding:"20px 22px" }}>
      <SectionHeader
        title="Spend over time"
        subtitle="Stacked by model · 30 days"
        action={
          <div style={{ display:"flex", gap:14 }}>
            {layers.filter(L => data.some(d => d[L.id] > 0.001)).map(L => (
              <span key={L.id} style={{ display:"inline-flex", alignItems:"center", gap:6, fontSize:11, color:"var(--fg-2)" }}>
                <span style={{ width:9, height:9, borderRadius:2, background:L.color, opacity:L.opacity || 1 }}/>{L.label}
              </span>
            ))}
          </div>
        }
      />
      <div ref={ref} style={{ position:"relative", width:"100%", height:h }} onMouseMove={onMove} onMouseLeave={()=>setHover(null)}>
        <svg width={w} height={h} style={{ display:"block", overflow:"visible" }}>
          {yTicks.map((t,i) => (
            <g key={i}>
              <line x1={padL} x2={padL+innerW} y1={padT+t.y} y2={padT+t.y} stroke="var(--line-1)" strokeDasharray={i===0?"":"2 4"}/>
              <text x={padL-10} y={padT+t.y+3} textAnchor="end" fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)">£{t.v.toFixed(t.v<1?2:1)}</text>
            </g>
          ))}
          <g transform={`translate(${padL},${padT})`}>
            {layers.map((L, i) => (
              <path key={L.id} d={stackPath(i)} fill={L.color} fillOpacity={L.opacity || 0.85} stroke={L.color} strokeOpacity="0.6" strokeWidth="0.4"/>
            ))}
            {hover != null && (
              <>
                <line x1={x(hover)} x2={x(hover)} y1={0} y2={innerH} stroke="var(--fg-3)" strokeDasharray="3 3"/>
                <circle cx={x(hover)} cy={y(data[hover].total)} r="3.5" fill="#fff" stroke={PROVIDERS[MODELS[project.primaryModel].provider].color} strokeWidth="2"/>
              </>
            )}
          </g>

          {/* X labels every 5 days */}
          {data.map((d,i) => (i===0 || i===n-1 || i%5===4) && (
            <text key={i} x={padL+x(i)} y={h-10} textAnchor="middle" fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)">{d.d} May</text>
          ))}
        </svg>

        {hover != null && (
          <div className="tt" style={{ left: Math.min(w-220, padL + x(hover) + 14), top: padT + 6, minWidth:200 }}>
            <div style={{ fontSize:11, color:"var(--fg-3)", marginBottom:6 }} className="mono">{data[hover].d} May 2026</div>
            {layers.filter(L => (data[hover][L.id] || 0) > 0.0001).map(L => (
              <div key={L.id} style={{ display:"flex", justifyContent:"space-between", gap:14, fontSize:12, padding:"1px 0" }}>
                <span style={{ display:"inline-flex", alignItems:"center", gap:6, color:"var(--fg-1)" }}>
                  <span style={{ width:7, height:7, borderRadius:2, background:L.color, opacity:L.opacity || 1 }}/>{L.label}
                </span>
                <span className="mono" style={{ color:"var(--fg-0)" }}>£{(data[hover][L.id]).toFixed(4)}</span>
              </div>
            ))}
            <div style={{ display:"flex", justifyContent:"space-between", gap:14, fontSize:12, padding:"4px 0 1px", borderTop:"1px solid var(--line-1)", marginTop:5 }}>
              <span style={{ color:"var(--fg-2)" }}>total</span>
              <span className="mono" style={{ color:"var(--fg-0)", fontWeight:600 }}>£{data[hover].total.toFixed(4)}</span>
            </div>
          </div>
        )}
      </div>
    </section>
  );
}

// ── Request volume bars + latency overlay ───────────────────
function ProjectRequestVolume(){
  const ref = useRef(null);
  const w = useWidth(ref);
  const h = 120;
  const padL = 50, padR = 18, padT = 12, padB = 26;
  const innerW = Math.max(100, w - padL - padR);
  const innerH = h - padT - padB;
  const n = 30;

  // Synth request volume per day
  const data = Array.from({length:n}, (_, i) => ({
    d: i+1,
    reqs: Math.round(60 + Math.sin(i*0.7)*30 + (i>15 ? 30 : 0) + (i===n-1?120:0) + Math.abs(Math.sin(i*1.7)*30)),
  }));
  const max = Math.max(...data.map(d=>d.reqs));
  const barW = (innerW/n) * 0.55;

  return (
    <section className="card" style={{ padding:"18px 22px" }}>
      <SectionHeader
        title="Request volume"
        subtitle="Requests per day · 30 days"
        action={<span className="badge badge--ghost">{data.reduce((s,d)=>s+d.reqs,0).toLocaleString()} requests</span>}
      />
      <div ref={ref} style={{ width:"100%", height:h }}>
        <svg width={w} height={h}>
          <line x1={padL} x2={padL+innerW} y1={padT+innerH} y2={padT+innerH} stroke="var(--line-1)"/>
          <text x={padL-10} y={padT+8} textAnchor="end" fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)">{max}</text>
          <text x={padL-10} y={padT+innerH+3} textAnchor="end" fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)">0</text>
          {data.map((d,i) => {
            const cx = padL + (i/(n-1))*innerW;
            const bh = (d.reqs/max)*innerH;
            return (
              <rect key={i} x={cx-barW/2} y={padT+innerH-bh} width={barW} height={bh} fill="var(--accent)" fillOpacity="0.7" rx="1.5"/>
            );
          })}
          {/* X labels */}
          <text x={padL} y={h-8} fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)">1 May</text>
          <text x={padL+innerW} y={h-8} textAnchor="end" fontSize="10" fontFamily="var(--font-mono)" fill="var(--fg-3)">30 May</text>
        </svg>
      </div>
    </section>
  );
}

// ── Recent requests table ───────────────────────────────────
function RecentRequestsTable({ project }){
  const rows = ACTIVITY.filter(r => r.project === project.slug);
  // pad with synthetic if too few
  const synth = [
    { ts:"14:25:11", project:project.slug, provider:"anthropic", model:project.primaryModel, inT:5200, outT:1240, cost:0.1830, mode:"thinking", status:"success", latency:1840 },
    { ts:"14:22:48", project:project.slug, provider:"anthropic", model:project.primaryModel, inT:3800, outT:920,  cost:0.1290, mode:"standard", status:"success", latency:1240 },
    { ts:"14:19:32", project:project.slug, provider:"anthropic", model:"claude-sonnet-4-6", inT:2200, outT:540, cost:0.0147, mode:"standard", status:"success", latency:680 },
    { ts:"14:14:07", project:project.slug, provider:"anthropic", model:project.primaryModel, inT:7400, outT:1820, cost:0.2475, mode:"thinking", status:"success", latency:2210 },
    { ts:"14:09:55", project:project.slug, provider:"anthropic", model:project.primaryModel, inT:1900, outT:420, cost:0.0600, mode:"standard", status:"error",   latency:8400 },
    { ts:"14:04:22", project:project.slug, provider:"google",    model:"gemini-3-flash",     inT:1200, outT:400, cost:0.000280, mode:"standard", status:"success", latency:320 },
  ];
  const all = [...rows, ...synth].slice(0, 8);

  return (
    <section className="card" style={{ padding:0, overflow:"hidden" }}>
      <div style={{ padding:"16px 22px", display:"flex", alignItems:"center", justifyContent:"space-between", borderBottom:"1px solid var(--line-1)" }}>
        <div>
          <h2 style={{ margin:0, fontSize:14, fontWeight:600, color:"var(--fg-0)" }}>Recent requests</h2>
          <div style={{ fontSize:11.5, color:"var(--fg-2)", marginTop:3 }}>Last 8 of <span className="mono">{project.requests.toLocaleString()}</span> in this period</div>
        </div>
        <button style={btnGhost()}>View all <Icon name="arrow" size={11}/></button>
      </div>
      <table className="tbl">
        <thead>
          <tr>
            <th style={{ paddingLeft:22 }}>Time</th>
            <th>Model</th>
            <th>Mode</th>
            <th className="right">Input</th>
            <th className="right">Output</th>
            <th className="right">Cost</th>
            <th className="right">Latency</th>
            <th style={{ paddingRight:22 }}>Status</th>
          </tr>
        </thead>
        <tbody>
          {all.map((r,i) => (
            <tr key={i} className="clickable">
              <td style={{ paddingLeft:22 }} className="mono">
                <span style={{ color:"var(--fg-0)" }}>{r.ts}</span>
                <span style={{ color:"var(--fg-3)", marginLeft:6, fontSize:11 }}>17 May</span>
              </td>
              <td><ModelBadge model={r.model}/></td>
              <td>
                {r.mode==="thinking"
                  ? <span className="badge badge--accent" style={{ fontSize:10 }}>thinking</span>
                  : <span style={{ color:"var(--fg-3)", fontSize:11 }} className="mono">standard</span>}
              </td>
              <td className="right mono" style={{ color:"var(--fg-1)", fontSize:12 }}>{fmtTokens(r.inT)}</td>
              <td className="right mono" style={{ color:"var(--fg-1)", fontSize:12 }}>{fmtTokens(r.outT)}</td>
              <td className="right"><Money value={r.cost*USD_TO_GBP} size="sm"/></td>
              <td className="right mono" style={{ color: r.latency>3000?"var(--warn)":r.latency>5000?"var(--neg)":"var(--fg-2)", fontSize:12 }}>{r.latency || 1450}ms</td>
              <td style={{ paddingRight:22 }}>
                {r.status==="error"
                  ? <span className="badge badge--neg" style={{ fontSize:10 }}>error</span>
                  : <span style={{ display:"inline-flex", alignItems:"center", gap:5, fontSize:11.5, color:"var(--pos)" }}><span style={{ width:5, height:5, borderRadius:"50%", background:"var(--pos)" }}/>ok</span>}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </section>
  );
}

// ── Sidebar cards ───────────────────────────────────────────
function PeriodSummaryCard({ totals }){
  return (
    <div className="card" style={{ padding:"16px 18px" }}>
      <div style={{ display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom:12 }}>
        <h3 style={{ margin:0, fontSize:12.5, fontWeight:600, color:"var(--fg-0)" }}>This period</h3>
        <span style={{ fontSize:10.5, color:"var(--fg-3)" }}>May 2026</span>
      </div>
      <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
        <SummaryRow label="Input tokens"    value={fmtTokens(totals.input)} hint="≈ 3.2k / req"/>
        <SummaryRow label="Output tokens"   value={fmtTokens(totals.output)} hint="≈ 750 / req"/>
        <SummaryRow label="Thinking tokens" value={fmtTokens(totals.thinking)} hint="visible reasoning"/>
        <SummaryRow label="Cached tokens"   value={fmtTokens(totals.cached)} hint={`${(totals.cacheRate*100).toFixed(0)}% hit rate`}/>
      </div>
      <div style={{ marginTop:14, paddingTop:12, borderTop:"1px solid var(--line-1)", display:"flex", justifyContent:"space-between", alignItems:"baseline" }}>
        <span style={{ fontSize:11.5, color:"var(--fg-2)" }}>Cache savings</span>
        <span className="mono" style={{ fontSize:13, color:"var(--pos)", fontWeight:600 }}>≈ {fmtGBP(totals.cacheSaved)}</span>
      </div>
    </div>
  );
}

function SummaryRow({ label, value, hint }){
  return (
    <div>
      <div style={{ display:"flex", justifyContent:"space-between", alignItems:"baseline" }}>
        <span style={{ fontSize:11.5, color:"var(--fg-2)" }}>{label}</span>
        <span className="mono" style={{ fontSize:13, color:"var(--fg-0)", fontWeight:500 }}>{value}</span>
      </div>
      {hint && <div style={{ fontSize:10.5, color:"var(--fg-3)", marginTop:1 }}>{hint}</div>}
    </div>
  );
}

function ByProviderCard({ totals }){
  const totalCost = totals.byProvider.reduce((s,p)=>s+p.cost, 0);
  return (
    <div className="card" style={{ padding:"16px 18px" }}>
      <h3 style={{ margin:"0 0 12px", fontSize:12.5, fontWeight:600, color:"var(--fg-0)" }}>By provider</h3>
      <div style={{ display:"flex", flexDirection:"column", gap:12 }}>
        {totals.byProvider.map(p => {
          const pct = p.cost/totalCost;
          return (
            <div key={p.provider}>
              <div style={{ display:"flex", justifyContent:"space-between", alignItems:"baseline", marginBottom:5 }}>
                <span style={{ display:"inline-flex", alignItems:"center", gap:7, fontSize:12 }}>
                  <ProviderDot provider={p.provider}/><span style={{ color:"var(--fg-0)", fontWeight:500 }}>{PROVIDERS[p.provider].name}</span>
                </span>
                <span className="mono" style={{ fontSize:12, color:"var(--fg-0)" }}>{fmtGBP(p.cost, p.cost<1?4:2)}</span>
              </div>
              <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                <div style={{ flex:1, height:5, background:"var(--bg-3)", borderRadius:99, position:"relative", overflow:"hidden" }}>
                  <div style={{ position:"absolute", left:0, top:0, bottom:0, width:(pct*100)+"%", background:PROVIDERS[p.provider].color, borderRadius:99 }}/>
                </div>
                <span className="mono" style={{ fontSize:10.5, color:"var(--fg-3)", minWidth:36, textAlign:"right" }}>{(pct*100).toFixed(1)}%</span>
              </div>
              <div className="mono" style={{ fontSize:10.5, color:"var(--fg-3)", marginTop:3 }}>{p.requests.toLocaleString()} requests</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function ByModelCard({ totals }){
  const totalCost = totals.byModel.reduce((s,m)=>s+m.cost, 0);
  const sorted = [...totals.byModel].sort((a,b)=>b.cost-a.cost).slice(0, 5);
  return (
    <div className="card" style={{ padding:"16px 18px" }}>
      <h3 style={{ margin:"0 0 12px", fontSize:12.5, fontWeight:600, color:"var(--fg-0)" }}>By model</h3>
      <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
        {sorted.map(m => {
          const meta = MODELS[m.id] || MODELS.unknown;
          const provider = PROVIDERS[meta.provider];
          const pct = m.cost/totalCost;
          return (
            <div key={m.id} style={{ display:"grid", gridTemplateColumns:"1fr auto", gap:8, alignItems:"baseline" }}>
              <div style={{ display:"flex", flexDirection:"column", gap:2, minWidth:0 }}>
                <span style={{ display:"inline-flex", alignItems:"center", gap:6 }}>
                  <span style={{ width:6, height:6, borderRadius:2, background:provider.color, flexShrink:0 }}/>
                  <span className="mono" style={{ fontSize:11.5, color:"var(--fg-0)" }}>{meta.short}</span>
                </span>
                <span className="mono" style={{ fontSize:10.5, color:"var(--fg-3)" }}>{m.requests.toLocaleString()} reqs</span>
              </div>
              <div style={{ textAlign:"right" }}>
                <div className="mono" style={{ fontSize:12, color:"var(--fg-0)", fontWeight:500 }}>{fmtGBP(m.cost, m.cost<1?4:2)}</div>
                <div className="mono" style={{ fontSize:10.5, color:"var(--fg-3)", marginTop:1 }}>{(pct*100).toFixed(pct<0.01?2:1)}%</div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function EfficiencyCard({ project, totals }){
  const cpr = project.spend / project.requests;
  const altCost = project.requests * (3.5 / 1e3); // theoretical alt
  const savePct = 0.62;
  return (
    <div className="card" style={{ padding:"16px 18px", borderColor:"var(--accent-line)", background:"linear-gradient(180deg, rgba(91,80,238,0.04), transparent 50%)" }}>
      <div style={{ display:"flex", alignItems:"center", gap:7, marginBottom:10 }}>
        <Icon name="sparkles" size={14} stroke="var(--accent)"/>
        <h3 style={{ margin:0, fontSize:12.5, fontWeight:600, color:"var(--fg-0)" }}>Cost efficiency</h3>
      </div>
      <div style={{ display:"flex", flexDirection:"column", gap:10 }}>
        <SummaryRow label="Cost / request"        value={fmtGBP(cpr,6)} hint="92% Opus 4.7"/>
        <SummaryRow label="Cost / 1k tokens"      value={fmtGBP(project.spend/totals.tokens*1000, 4)} hint="blended rate"/>
        <SummaryRow label="Tokens / request"      value={Math.round(totals.tokens/project.requests).toLocaleString()} hint="input + output"/>
      </div>
      <div style={{ marginTop:12, padding:"10px 12px", borderRadius:8, background:"#fff", border:"1px solid var(--accent-line)" }}>
        <div style={{ display:"flex", alignItems:"center", gap:6, fontSize:11.5, color:"var(--fg-0)", fontWeight:500, marginBottom:4 }}>
          <Icon name="bolt" size={12} stroke="var(--accent)"/> Sonnet 4.6 could save ≈ <span className="mono">{fmtGBP(project.spend*savePct)}</span>
        </div>
        <div style={{ fontSize:10.5, color:"var(--fg-2)", lineHeight:1.45 }}>If 70% of Opus calls were routed to Sonnet, estimated savings of {(savePct*100).toFixed(0)}% based on token equivalence.</div>
      </div>
    </div>
  );
}

function DangerZoneCard(){
  return (
    <div style={{ padding:"12px 14px", border:"1px dashed var(--line-2)", borderRadius:10, background:"transparent" }}>
      <div style={{ fontSize:11, color:"var(--fg-3)", marginBottom:6, letterSpacing:0.04, textTransform:"uppercase", fontWeight:600 }}>Project</div>
      <div style={{ display:"flex", gap:8, flexWrap:"wrap" }}>
        <button style={btnSubtle()}><Icon name="archive" size={12}/> Archive</button>
        <button style={btnSubtle()}><Icon name="cog" size={12}/> Settings</button>
      </div>
    </div>
  );
}

// ── Tab stubs ───────────────────────────────────────────────
function RequestsFull({ project }){
  return (
    <div style={{ padding:"40px 24px", textAlign:"center", color:"var(--fg-2)" }}>
      <Icon name="activity" size={28} stroke="var(--fg-3)"/>
      <div style={{ marginTop:10, fontSize:14, color:"var(--fg-1)" }}>Paginated request log for <span className="mono">{project.slug}</span></div>
      <div style={{ fontSize:12, color:"var(--fg-3)", marginTop:4 }}>Coming next iteration</div>
    </div>
  );
}

function ComparisonView({ project, totals }){
  const baseline = project.spend;
  const rows = [
    { provider:"anthropic", model:"claude-opus-4-7",   cost: baseline,         note:"actual",     actual:true },
    { provider:"anthropic", model:"claude-sonnet-4-6", cost: baseline * 0.38, note:"estimate · best for general tasks" },
    { provider:"anthropic", model:"claude-haiku-4-5",  cost: baseline * 0.11, note:"estimate · quality risk on reasoning" },
    { provider:"openai",    model:"gpt-4o",            cost: baseline * 0.78, note:"estimate · similar tier" },
    { provider:"openai",    model:"o1",                cost: baseline * 1.32, note:"estimate · higher reasoning cost" },
    { provider:"google",    model:"gemini-3-flash",    cost: baseline * 0.04, note:"estimate · quality risk on coding" },
  ];
  return (
    <div className="card" style={{ padding:0, overflow:"hidden" }}>
      <div style={{ padding:"16px 22px", borderBottom:"1px solid var(--line-1)" }}>
        <h2 style={{ margin:0, fontSize:14, fontWeight:600 }}>Cross-provider comparison</h2>
        <div style={{ fontSize:11.5, color:"var(--fg-2)", marginTop:3 }}>What would this period's token volume have cost on each model? <span style={{ fontStyle:"italic" }}>Estimates only — based on published rates.</span></div>
      </div>
      <table className="tbl">
        <thead>
          <tr>
            <th style={{ paddingLeft:22 }}>Provider</th>
            <th>Model</th>
            <th className="right">Est. cost</th>
            <th className="right">vs actual</th>
            <th style={{ paddingRight:22 }}>Notes</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((r,i) => {
            const delta = (r.cost - baseline) / baseline;
            return (
              <tr key={i} className="clickable" style={{ background: r.actual ? "rgba(91,80,238,0.04)" : "transparent" }}>
                <td style={{ paddingLeft:22 }}>
                  <span style={{ display:"inline-flex", alignItems:"center", gap:7 }}>
                    <ProviderDot provider={r.provider}/>{PROVIDERS[r.provider].name}
                  </span>
                </td>
                <td><ModelBadge model={r.model}/></td>
                <td className="right">
                  {r.actual
                    ? <Money value={r.cost} size="sm"/>
                    : <span style={{ fontStyle:"italic", color:"var(--fg-1)" }}>≈ <Money value={r.cost} size="sm" strong={false}/></span>}
                </td>
                <td className="right">
                  {r.actual
                    ? <span className="badge badge--accent" style={{ fontSize:10 }}>actual</span>
                    : <Delta pct={delta}/>}
                </td>
                <td style={{ paddingRight:22, color:"var(--fg-2)", fontSize:12 }}>{r.note}</td>
              </tr>
            );
          })}
        </tbody>
      </table>
      <div style={{ padding:"12px 22px", borderTop:"1px solid var(--line-1)", fontSize:11, color:"var(--fg-3)", display:"flex", gap:8, alignItems:"center" }}>
        <Icon name="info" size={12}/>
        Comparative costs are estimates based on published rates and token-equivalence calibration. Actual costs may differ.
      </div>
    </div>
  );
}

function ReportsStub({ project }){
  return (
    <div className="card" style={{ padding:"40px 24px", textAlign:"center", color:"var(--fg-2)" }}>
      <Icon name="print" size={28} stroke="var(--fg-3)"/>
      <div style={{ marginTop:10, fontSize:14, color:"var(--fg-1)" }}>Generated reports for <span className="mono">{project.slug}</span></div>
      <div style={{ fontSize:12, color:"var(--fg-3)", marginTop:4 }}>Past PDFs will appear here</div>
      <button style={{ ...btnPrimary(), marginTop:18 }}><Icon name="download" size={13}/> Generate May 2026 report</button>
    </div>
  );
}

Object.assign(window, { ProjectDetail });
