// §3.11 Total Cost of Ownership (TCO) Analysis

function TCOAnalysis({ user, perms }) {
  const [tab, setTab] = useState("league");
  const [openTerminal, setOpenTerminal] = useState(null);

  const tabs = [
    { id: "league", label: "Cost League Table" },
    { id: "waterfall", label: "Cost Waterfall" },
    { id: "benchmark", label: "Benchmarking" },
    { id: "trend", label: "Cost Trend" },
    { id: "whatif", label: "What-if Simulation" },
  ];

  return (
    <div>
      <PageHeader
        title="TCO Analysis"
        sub="Total Cost of Ownership · synthesises rates + volume + rebates · per-terminal benchmark"
        right={
          <>
            <button className="btn"><Icon name="refresh" size={14} /> Recalculate</button>
            <button className="btn primary"><Icon name="download" size={14} /> Monthly TCO report</button>
          </>
        }
      />
      <TCOKpis />
      <Tabs tabs={tabs} current={tab} onChange={setTab} />
      {tab === "league" && <CostLeague onOpen={setOpenTerminal} />}
      {tab === "waterfall" && <CostWaterfall />}
      {tab === "benchmark" && <Benchmarking />}
      {tab === "trend" && <CostTrend />}
      {tab === "whatif" && <WhatIfSimulation />}

      {openTerminal && <TerminalCostDetail terminal={openTerminal} onClose={() => setOpenTerminal(null)} />}
    </div>
  );
}

function TCOKpis() {
  const totalGross = TCO.reduce((s, t) => s + t.gross, 0);
  const totalRebate = TCO.reduce((s, t) => s + t.rebate, 0);
  const totalNet = totalGross - totalRebate;
  const totalTEU = TCO.reduce((s, t) => s + t.monthlyTEU, 0);
  const blendedNet = totalNet / totalTEU;
  const yield_ = (totalRebate / totalGross) * 100;
  return (
    <div className="grid-4" style={{ marginBottom: 18 }}>
      <KPI label="Gross Terminal Cost (May)" value={fmt.usd(totalGross / 1000) + "k"} sub="across APA" />
      <KPI label="Rebate Offset" value={"-" + fmt.usd(totalRebate / 1000) + "k"} sub={`Rebate yield ${yield_.toFixed(1)}%`} deltaDir="up" />
      <KPI label="Net Cost / TEU" value={fmt.usd(blendedNet)} sub={`${fmt.num(totalTEU / 1000, 0)}k TEU base`} delta="↓ −1.8% MoM" deltaDir="up" />
      <KPI label="Best vs Worst" value={`${(((TCO[TCO.length-1].netPerTEU - TCO[0].netPerTEU) / TCO[0].netPerTEU) * 100).toFixed(0)}%`} sub="cost spread" />
    </div>
  );
}

// ============== LEAGUE TABLE ==============
function CostLeague({ onOpen }) {
  const apaAvg = TCO.reduce((s, t) => s + t.netPerTEU, 0) / TCO.length;

  return (
    <div>
      <div className="filterbar">
        <FilterChip keyLabel="Period" value="May 2025" set />
        <FilterChip keyLabel="Region" value="" />
        <FilterChip keyLabel="Cost Type" value="All" set />
        <div className="grow" />
        <div className="row gap-12 tiny muted">
          <span><span style={{ display: "inline-block", width: 8, height: 8, background: "var(--green)", borderRadius: 50, marginRight: 4 }} />Below avg</span>
          <span><span style={{ display: "inline-block", width: 8, height: 8, background: "var(--amber)", borderRadius: 50, marginRight: 4 }} />Near avg ±10%</span>
          <span><span style={{ display: "inline-block", width: 8, height: 8, background: "var(--red)", borderRadius: 50, marginRight: 4 }} />Above avg</span>
        </div>
      </div>

      <Card title="Terminal Cost League · sorted by Net Cost/TEU"
        sub={`APA blended average: ${fmt.usd(apaAvg)} / TEU · May 2025`}>
        <div className="table-wrap">
          <table className="table">
            <thead>
              <tr>
                <th>Rank</th>
                <th>Terminal</th>
                <th>Region</th>
                <th className="num">Monthly TEU</th>
                <th className="num">Gross / TEU</th>
                <th className="num">Rebate Yield</th>
                <th className="num">Net / TEU</th>
                <th>vs APA avg</th>
                <th className="num">MoM</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {TCO.slice(0, 16).map((t, i) => {
                const delta = ((t.netPerTEU - apaAvg) / apaAvg) * 100;
                const status = delta < -5 ? "green" : delta < 10 ? "amber" : "red";
                const color = status === "green" ? "var(--green)" : status === "amber" ? "var(--amber)" : "var(--red)";
                return (
                  <tr key={t.terminal} onClick={() => onOpen(t)} style={{ cursor: "pointer" }}>
                    <td className="mono tiny" style={{ color: i < 3 ? "var(--ink)" : "var(--ink-mute)", fontWeight: i < 3 ? 600 : 400 }}>
                      #{i + 1}
                    </td>
                    <td>
                      <div className="bold tiny">{t.terminalName}</div>
                      <div className="tiny muted mono">{t.terminal}</div>
                    </td>
                    <td className="tiny muted">{t.region}</td>
                    <td className="num mono">{fmt.num(t.monthlyTEU, 0)}</td>
                    <td className="num mono">{fmt.usd(t.grossPerTEU)}</td>
                    <td className="num mono" style={{ color: t.rebateYield > 0 ? "var(--green)" : "var(--ink-mute)" }}>
                      {t.rebateYield > 0 ? "-" + t.rebateYield.toFixed(2) + "%" : "—"}
                    </td>
                    <td className="num mono bold">{fmt.usd(t.netPerTEU)}</td>
                    <td>
                      <div className="row gap-6">
                        <span style={{ width: 8, height: 8, background: color, borderRadius: 50 }} />
                        <span className="tiny mono" style={{ color }}>
                          {delta > 0 ? "+" : ""}{delta.toFixed(1)}%
                        </span>
                      </div>
                    </td>
                    <td className="num mono tiny" style={{ color: t.momChange < 0 ? "var(--green)" : "var(--red)" }}>
                      {t.momChange > 0 ? "↑" : "↓"} {Math.abs(t.momChange).toFixed(1)}%
                    </td>
                    <td><button className="btn ghost tiny" style={{ height: 24 }} onClick={e=>e.stopPropagation()}><Icon name="arrowRight" size={12} /></button></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </Card>
    </div>
  );
}

// ============== WATERFALL CHART ==============
function CostWaterfall() {
  const [terminal, setTerminal] = useState("CNSHA");
  const t = TCO.find(x => x.terminal === terminal);

  const steps = [
    { label: "CY Handling", value: t.breakdown["CY Handling"], type: "in" },
    { label: "Storage", value: t.breakdown["Storage"], type: "in" },
    { label: "Reefer", value: t.breakdown["Reefer"], type: "in" },
    { label: "Other Behavior", value: t.breakdown["Other Behavior"], type: "in" },
    { label: "Gross Total", value: t.gross, type: "total" },
    { label: "Rebate Offset", value: -t.rebate, type: "out" },
    { label: "Net Total", value: t.net, type: "total" },
  ];
  const maxVal = t.gross;
  const W = 880, H = 320, padL = 60, padR = 40, padT = 30, padB = 50;
  const chartW = W - padL - padR;
  const chartH = H - padT - padB;
  let runningY = 0;

  return (
    <div>
      <div className="filterbar">
        <span className="tiny mono muted">Terminal:</span>
        <select className="select" style={{ width: 240, height: 28, fontSize: 12 }} value={terminal} onChange={e => setTerminal(e.target.value)}>
          {TCO.map(x => <option key={x.terminal} value={x.terminal}>{x.terminalName}</option>)}
        </select>
        <FilterChip keyLabel="Period" value="May 2025" set />
        <div className="grow" />
        <button className="btn"><Icon name="download" size={14} /> Export</button>
      </div>

      <Card title="Cost build-up" sub={`${t.terminalName} · ${fmt.num(t.monthlyTEU, 0)} TEU · May 2025`}>
        <div style={{ padding: 20 }}>
          <svg width="100%" height={H} viewBox={`0 0 ${W} ${H}`}>
            {/* gridlines */}
            {[0, 0.25, 0.5, 0.75, 1].map(p => (
              <g key={p}>
                <line x1={padL} y1={padT + chartH - p * chartH} x2={W - padR} y2={padT + chartH - p * chartH} stroke="#e7ebef" strokeWidth="1" />
                <text x={padL - 6} y={padT + chartH - p * chartH + 3} textAnchor="end" fontSize="10" fill="#5a6a7c" fontFamily="IBM Plex Mono">{fmt.usd((maxVal * p) / 1000)}k</text>
              </g>
            ))}
            {steps.map((s, i) => {
              const x = padL + (i * chartW) / steps.length + 12;
              const bw = chartW / steps.length - 24;
              let h, y, color, runningTop;
              if (s.type === "total") {
                h = (s.value / maxVal) * chartH;
                y = padT + chartH - h;
                color = "var(--ink)";
                runningTop = y;
              } else if (s.type === "in") {
                h = (s.value / maxVal) * chartH;
                y = padT + chartH - runningY - h;
                color = "var(--teal)";
                runningY += h;
                runningTop = y;
              } else {
                // out — rebate
                h = (Math.abs(s.value) / maxVal) * chartH;
                y = padT + chartH - runningY;
                color = "var(--green)";
                runningY -= h;
                runningTop = y;
              }
              return (
                <g key={i}>
                  <rect x={x} y={y} width={bw} height={h} fill={color} opacity={s.type === "total" ? 1 : 0.85} />
                  {/* dashed connector to next */}
                  {i < steps.length - 1 && s.type !== "total" && (
                    <line x1={x + bw} y1={runningTop} x2={x + bw + 24} y2={runningTop} stroke="var(--ink-mute)" strokeWidth="1" strokeDasharray="2 2" />
                  )}
                  <text x={x + bw / 2} y={padT + chartH + 16} textAnchor="middle" fontSize="10" fill="var(--ink)" fontFamily="IBM Plex Sans" fontWeight={s.type === "total" ? 600 : 400}>{s.label}</text>
                  <text x={x + bw / 2} y={y - 6} textAnchor="middle" fontSize="10" fill="var(--ink)" fontFamily="IBM Plex Mono" fontWeight={500}>
                    {s.value < 0 ? "−" : ""}{fmt.usd(Math.abs(s.value) / 1000)}k
                  </text>
                </g>
              );
            })}
          </svg>

          <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginTop: 20 }}>
            <div style={{ padding: 12, background: "var(--paper)", borderRadius: 6 }}>
              <div className="tiny mono muted" style={{ textTransform: "uppercase" }}>Gross / TEU</div>
              <div className="serif" style={{ fontSize: 22, fontWeight: 500 }}>{fmt.usd(t.grossPerTEU)}</div>
            </div>
            <div style={{ padding: 12, background: "var(--green-soft)", borderRadius: 6 }}>
              <div className="tiny mono muted" style={{ textTransform: "uppercase" }}>Rebate Yield</div>
              <div className="serif" style={{ fontSize: 22, fontWeight: 500, color: "var(--green)" }}>{t.rebateYield.toFixed(2)}%</div>
            </div>
            <div style={{ padding: 12, background: "var(--paper)", borderRadius: 6 }}>
              <div className="tiny mono muted" style={{ textTransform: "uppercase" }}>Net / TEU</div>
              <div className="serif" style={{ fontSize: 22, fontWeight: 500 }}>{fmt.usd(t.netPerTEU)}</div>
            </div>
            <div style={{ padding: 12, background: "var(--paper)", borderRadius: 6 }}>
              <div className="tiny mono muted" style={{ textTransform: "uppercase" }}>Cost per Move</div>
              <div className="serif" style={{ fontSize: 22, fontWeight: 500 }}>{fmt.usd(t.gross / (t.monthlyTEU * 0.62))}</div>
            </div>
          </div>
        </div>
      </Card>
    </div>
  );
}

// ============== BENCHMARKING ==============
function Benchmarking() {
  const [costType, setCostType] = useState("");
  const sample = TCO.slice(0, 8);

  return (
    <div>
      <div className="filterbar">
        <span className="tiny muted">Benchmark on:</span>
        <select className="select" style={{ width: 180, height: 28, fontSize: 12 }} value={costType} onChange={e => setCostType(e.target.value)}>
          <option value="">Total Net Cost / TEU</option>
          {COST_TYPES.map(c => <option key={c.code} value={c.code}>{c.name} only</option>)}
        </select>
        <FilterChip keyLabel="Period" value="May 2025" set />
        <FilterChip keyLabel="Region" value="" />
        <div className="grow" />
        <button className="btn"><Icon name="bolt" size={14} stroke="var(--teal)" /> Open What-if</button>
        <button className="btn"><Icon name="download" size={14} /> Export</button>
      </div>

      <Card title="Terminal Benchmarking" sub="Direct cost comparison · sortable on any column">
        <div className="table-wrap">
          <table className="table">
            <thead>
              <tr>
                <th>Terminal</th>
                <th className="num">Gross / TEU</th>
                <th className="num">Rebate Yield</th>
                <th className="num">Net / TEU</th>
                <th>Rank (Region)</th>
                <th>MoM Change</th>
                <th>Trend (90d)</th>
              </tr>
            </thead>
            <tbody>
              {sample.map((t, i) => {
                const trendData = [t.netPerTEU * 1.04, t.netPerTEU * 1.02, t.netPerTEU * 1.05, t.netPerTEU * 1.01, t.netPerTEU * 1.03, t.netPerTEU * 0.99, t.netPerTEU];
                return (
                  <tr key={t.terminal}>
                    <td>
                      <div className="bold tiny">{t.terminalName}</div>
                      <div className="tiny muted mono">{t.region}</div>
                    </td>
                    <td className="num mono">{fmt.usd(t.grossPerTEU)}</td>
                    <td className="num mono" style={{ color: t.rebateYield > 0 ? "var(--green)" : "var(--ink-mute)" }}>{t.rebateYield > 0 ? `-${t.rebateYield.toFixed(1)}%` : "—"}</td>
                    <td className="num mono bold">{fmt.usd(t.netPerTEU)}</td>
                    <td>
                      <span className="pill plain" style={{ fontSize: 10 }}>#{i + 1} of {sample.length}</span>
                    </td>
                    <td>
                      <span className="mono tiny" style={{ color: t.momChange < 0 ? "var(--green)" : "var(--red)" }}>
                        {t.momChange > 0 ? "↑" : "↓"} {Math.abs(t.momChange).toFixed(1)}%
                      </span>
                    </td>
                    <td><Sparkline data={trendData} w={80} h={20} color={t.momChange < 0 ? "var(--green)" : "var(--red)"} /></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </Card>

      <div className="card" style={{ marginTop: 14, padding: 14, display: "flex", gap: 12 }}>
        <Icon name="sparkle" size={20} stroke="var(--teal)" />
        <div style={{ flex: 1 }}>
          <b className="tiny">Negotiation insight:</b>
          <span className="tiny muted"> Qingdao Qianwan operates {fmt.usd(sample[sample.length-1].netPerTEU - sample[0].netPerTEU)} / TEU above Shanghai (Yangshan). Closing the gap to APA Top-3 average would save approximately {fmt.usd((sample[sample.length-1].netPerTEU - sample[0].netPerTEU) * sample[sample.length-1].monthlyTEU * 12)} per year at current volume pace.</span>
        </div>
      </div>
    </div>
  );
}

// ============== TREND ==============
function CostTrend() {
  // 12 months of Net Cost/TEU for top terminals + benchmark
  const months = VOLUME.months;
  const terminals = TCO.slice(0, 5);
  const series = terminals.map((t, ti) => ({
    name: t.terminalName,
    color: ["#0e7f95", "#14a3bd", "#8a4d2e", "#1f6f5c", "#6b3f8a"][ti],
    data: months.map((m, mi) => t.netPerTEU * (1 + 0.04 * Math.sin((mi / 12) * Math.PI * 2 + ti) - 0.005 * mi)),
  }));
  // CCFI overlay (normalized)
  const ccfi = months.map((m, i) => 95 + 8 * Math.sin((i / 12) * Math.PI * 2 - 1) - 0.3 * i);

  const W = 880, H = 280, padL = 50, padR = 50, padT = 20, padB = 40;
  const chartW = W - padL - padR;
  const chartH = H - padT - padB;
  const allValues = series.flatMap(s => s.data);
  const min = Math.min(...allValues) * 0.95;
  const max = Math.max(...allValues) * 1.05;

  return (
    <div>
      <div className="filterbar">
        <FilterChip keyLabel="Period" value="Last 12 months" set />
        <FilterChip keyLabel="Region" value="" />
        <label className="check"><input type="checkbox" defaultChecked /> Overlay CCFI index</label>
        <div className="grow" />
        <button className="btn"><Icon name="bolt" size={14} stroke="var(--amber)" /> View rate change impacts</button>
      </div>

      <Card title="Net Cost / TEU · Rolling 12 months" sub="Overlaid with CCFI reference index">
        <div style={{ padding: 18 }}>
          <svg width="100%" height={H} viewBox={`0 0 ${W} ${H}`}>
            {/* gridlines */}
            {[0, 0.25, 0.5, 0.75, 1].map(p => (
              <g key={p}>
                <line x1={padL} y1={padT + chartH - p * chartH} x2={W - padR} y2={padT + chartH - p * chartH} stroke="#e7ebef" strokeWidth="1" />
                <text x={padL - 6} y={padT + chartH - p * chartH + 3} textAnchor="end" fontSize="10" fill="#5a6a7c" fontFamily="IBM Plex Mono">
                  {fmt.usd(min + (max - min) * p)}
                </text>
              </g>
            ))}
            {/* x-axis labels */}
            {months.map((m, i) => (
              <text key={m} x={padL + (i * chartW) / (months.length - 1)} y={padT + chartH + 16} textAnchor="middle" fontSize="9" fill="#5a6a7c" fontFamily="IBM Plex Mono">{m.slice(5)}</text>
            ))}
            {/* CCFI dashed line */}
            <polyline
              points={ccfi.map((v, i) => {
                const norm = (v - 80) / (110 - 80); // 0-1
                return `${padL + (i * chartW) / (ccfi.length - 1)},${padT + chartH - norm * chartH}`;
              }).join(" ")}
              fill="none" stroke="var(--ink-mute)" strokeWidth="1.5" strokeDasharray="4 3"
            />
            <text x={W - padR + 4} y={padT + chartH * 0.3} fontSize="9" fill="var(--ink-mute)" fontFamily="IBM Plex Mono">CCFI</text>
            {/* terminal lines */}
            {series.map((s, si) => (
              <g key={si}>
                <polyline
                  points={s.data.map((v, i) => `${padL + (i * chartW) / (s.data.length - 1)},${padT + chartH - ((v - min) / (max - min)) * chartH}`).join(" ")}
                  fill="none" stroke={s.color} strokeWidth="2" strokeLinejoin="round" strokeLinecap="round"
                />
                {s.data.map((v, i) => (
                  <circle key={i} cx={padL + (i * chartW) / (s.data.length - 1)} cy={padT + chartH - ((v - min) / (max - min)) * chartH} r="2" fill={s.color} />
                ))}
              </g>
            ))}
          </svg>

          <div className="row gap-16" style={{ flexWrap: "wrap", marginTop: 12, justifyContent: "center" }}>
            {series.map((s, i) => (
              <div key={i} className="row gap-6 tiny"><span style={{ width: 14, height: 2, background: s.color }} /> {s.name}</div>
            ))}
            <div className="row gap-6 tiny muted"><span style={{ width: 14, height: 0, borderTop: "1.5px dashed var(--ink-mute)" }} /> CCFI Index</div>
          </div>
        </div>
      </Card>

      {/* Variance Decomposition */}
      <div style={{ marginTop: 16 }}>
        <Card title="YoY Cost Variance Decomposition" sub="Decomposes change vs prior year into volume / rate / rebate effects">
          <div style={{ padding: 18 }}>
            <VarianceWaterfall />
          </div>
        </Card>
      </div>
    </div>
  );
}

function VarianceWaterfall() {
  const steps = [
    { l: "FY24 Baseline", v: 2840000, type: "base" },
    { l: "Volume Effect", v: 152000, type: "in" },
    { l: "Rate Effect", v: 84000, type: "in" },
    { l: "Rebate Effect", v: -210000, type: "out" },
    { l: "FY25 YTD", v: 2866000, type: "total" },
  ];
  const maxVal = 3100000;
  const W = 840, H = 200, padL = 60, padR = 30, padT = 20, padB = 40;
  const chartW = W - padL - padR, chartH = H - padT - padB;
  let running = 0;
  return (
    <svg width="100%" height={H} viewBox={`0 0 ${W} ${H}`}>
      {[0, 0.5, 1].map(p => (
        <g key={p}>
          <line x1={padL} y1={padT + chartH - p * chartH} x2={W - padR} y2={padT + chartH - p * chartH} stroke="#e7ebef" />
          <text x={padL - 6} y={padT + chartH - p * chartH + 3} textAnchor="end" fontSize="10" fill="#5a6a7c" fontFamily="IBM Plex Mono">{fmt.usd((maxVal * p) / 1000000, 1)}M</text>
        </g>
      ))}
      {steps.map((s, i) => {
        const x = padL + (i * chartW) / steps.length + 16;
        const bw = chartW / steps.length - 32;
        let h, y, color;
        if (s.type === "base" || s.type === "total") {
          h = (s.v / maxVal) * chartH;
          y = padT + chartH - h;
          color = "var(--ink)";
          running = s.v;
        } else if (s.type === "in") {
          h = (s.v / maxVal) * chartH;
          y = padT + chartH - (running / maxVal) * chartH - h;
          color = "var(--amber)";
          running += s.v;
        } else {
          h = (Math.abs(s.v) / maxVal) * chartH;
          y = padT + chartH - (running / maxVal) * chartH;
          color = "var(--green)";
          running += s.v;
        }
        return (
          <g key={i}>
            <rect x={x} y={y} width={bw} height={h} fill={color} opacity={(s.type === "in" || s.type === "out") ? 0.85 : 1} />
            <text x={x + bw / 2} y={padT + chartH + 16} textAnchor="middle" fontSize="10" fill="var(--ink)" fontFamily="IBM Plex Sans" fontWeight={s.type === "base" || s.type === "total" ? 600 : 400}>{s.l}</text>
            <text x={x + bw / 2} y={y - 6} textAnchor="middle" fontSize="10" fill="var(--ink)" fontFamily="IBM Plex Mono">
              {s.v > 0 && s.type !== "base" && s.type !== "total" ? "+" : ""}{fmt.usd(s.v / 1000, 0)}k
            </text>
          </g>
        );
      })}
    </svg>
  );
}

// ============== WHAT-IF SIMULATION ==============
function WhatIfSimulation() {
  const [overrides, setOverrides] = useState({ rate: 0, volume: 0 });
  const baseline = TCO[0];
  const newGross = baseline.gross * (1 + overrides.rate / 100) * (1 + overrides.volume / 100);
  const newNet = newGross - baseline.rebate;
  const newPerTeu = newNet / (baseline.monthlyTEU * (1 + overrides.volume / 100));
  const pnlImpact = (newNet - baseline.net) * 12;

  return (
    <div style={{ display: "grid", gridTemplateColumns: "360px 1fr", gap: 18 }}>
      <Card title="Scenario inputs" sub="Override rate or volume · doesn't affect stored data">
        <div style={{ padding: 18, display: "grid", gap: 18 }}>
          <Field label="Terminal">
            <select className="select"><option>{baseline.terminalName}</option></select>
          </Field>
          <Field label="Cost Type">
            <select className="select"><option>All cost types</option>{COST_TYPES.map(c => <option key={c.code}>{c.name}</option>)}</select>
          </Field>
          <div>
            <div className="row" style={{ justifyContent: "space-between", marginBottom: 4 }}>
              <label className="tiny mono muted" style={{ textTransform: "uppercase", letterSpacing: 0.06 }}>Rate change</label>
              <span className="mono bold" style={{ color: overrides.rate > 0 ? "var(--red)" : overrides.rate < 0 ? "var(--green)" : null }}>
                {overrides.rate > 0 ? "+" : ""}{overrides.rate}%
              </span>
            </div>
            <input type="range" min="-30" max="30" step="0.5" value={overrides.rate} onChange={e => setOverrides({ ...overrides, rate: parseFloat(e.target.value) })} style={{ width: "100%" }} />
            <div className="row tiny muted" style={{ justifyContent: "space-between" }}>
              <span className="mono">−30%</span><span className="mono">+30%</span>
            </div>
          </div>
          <div>
            <div className="row" style={{ justifyContent: "space-between", marginBottom: 4 }}>
              <label className="tiny mono muted" style={{ textTransform: "uppercase", letterSpacing: 0.06 }}>Volume change</label>
              <span className="mono bold" style={{ color: overrides.volume > 0 ? "var(--green)" : overrides.volume < 0 ? "var(--red)" : null }}>
                {overrides.volume > 0 ? "+" : ""}{overrides.volume}%
              </span>
            </div>
            <input type="range" min="-30" max="30" step="0.5" value={overrides.volume} onChange={e => setOverrides({ ...overrides, volume: parseFloat(e.target.value) })} style={{ width: "100%" }} />
          </div>
          <div className="divider" />
          <button className="btn teal" style={{ height: 36 }}>
            <Icon name="bolt" size={14} />
            Save scenario
          </button>
          <button className="btn ghost" onClick={() => setOverrides({ rate: 0, volume: 0 })}>Reset to baseline</button>
        </div>
      </Card>

      <div>
        <Card title="Impact preview" sub="Recalculated instantly · no stored data affected">
          <div style={{ padding: 22 }}>
            <div className="grid-3" style={{ marginBottom: 18 }}>
              <div>
                <div className="tiny mono muted" style={{ textTransform: "uppercase" }}>Baseline Net/TEU</div>
                <div className="serif" style={{ fontSize: 28, fontWeight: 500 }}>{fmt.usd(baseline.netPerTEU)}</div>
              </div>
              <div>
                <div className="tiny mono muted" style={{ textTransform: "uppercase" }}>Scenario Net/TEU</div>
                <div className="serif" style={{ fontSize: 28, fontWeight: 500, color: newPerTeu > baseline.netPerTEU ? "var(--amber)" : "var(--green)" }}>{fmt.usd(newPerTeu)}</div>
                <div className="tiny mono" style={{ color: newPerTeu > baseline.netPerTEU ? "var(--red)" : "var(--green)" }}>
                  {newPerTeu > baseline.netPerTEU ? "↑" : "↓"} {fmt.usd(Math.abs(newPerTeu - baseline.netPerTEU))}
                </div>
              </div>
              <div>
                <div className="tiny mono muted" style={{ textTransform: "uppercase" }}>Annual P&L impact</div>
                <div className="serif" style={{ fontSize: 28, fontWeight: 500, color: pnlImpact > 0 ? "var(--red)" : "var(--green)" }}>
                  {pnlImpact > 0 ? "+" : ""}{fmt.usd(pnlImpact)}
                </div>
              </div>
            </div>

            <div className="divider" />

            <div className="tiny mono muted" style={{ textTransform: "uppercase", marginBottom: 10 }}>Cost composition</div>
            <table style={{ width: "100%", fontSize: 13 }}>
              <thead>
                <tr style={{ color: "var(--ink-mute)" }}>
                  <th style={{ textAlign: "left", padding: 6, fontWeight: 500 }}>Component</th>
                  <th style={{ textAlign: "right", padding: 6, fontWeight: 500 }}>Baseline</th>
                  <th style={{ textAlign: "right", padding: 6, fontWeight: 500 }}>Scenario</th>
                  <th style={{ textAlign: "right", padding: 6, fontWeight: 500 }}>Δ</th>
                </tr>
              </thead>
              <tbody>
                {Object.entries(baseline.breakdown).map(([k, v]) => {
                  const newV = v * (1 + overrides.rate / 100) * (1 + overrides.volume / 100);
                  return (
                    <tr key={k} style={{ borderTop: "1px solid var(--line)" }}>
                      <td style={{ padding: 8 }}>{k}</td>
                      <td className="num mono" style={{ padding: 8 }}>{fmt.usd(v / 1000, 0)}k</td>
                      <td className="num mono" style={{ padding: 8 }}>{fmt.usd(newV / 1000, 0)}k</td>
                      <td className="num mono" style={{ padding: 8, color: newV > v ? "var(--red)" : newV < v ? "var(--green)" : "var(--ink-mute)" }}>
                        {newV !== v ? (newV > v ? "+" : "") + fmt.usd((newV - v) / 1000, 0) + "k" : "—"}
                      </td>
                    </tr>
                  );
                })}
                <tr style={{ borderTop: "2px solid var(--ink)" }}>
                  <td style={{ padding: 8, fontWeight: 600 }}>Gross</td>
                  <td className="num mono bold" style={{ padding: 8 }}>{fmt.usd(baseline.gross / 1000, 0)}k</td>
                  <td className="num mono bold" style={{ padding: 8 }}>{fmt.usd(newGross / 1000, 0)}k</td>
                  <td className="num mono bold" style={{ padding: 8, color: newGross > baseline.gross ? "var(--red)" : "var(--green)" }}>
                    {newGross !== baseline.gross ? (newGross > baseline.gross ? "+" : "") + fmt.usd((newGross - baseline.gross) / 1000, 0) + "k" : "—"}
                  </td>
                </tr>
                <tr>
                  <td style={{ padding: 8 }}>Rebate offset</td>
                  <td className="num mono" style={{ padding: 8, color: "var(--green)" }}>-{fmt.usd(baseline.rebate / 1000, 0)}k</td>
                  <td className="num mono" style={{ padding: 8, color: "var(--green)" }}>-{fmt.usd(baseline.rebate / 1000, 0)}k</td>
                  <td className="num mono muted" style={{ padding: 8 }}>—</td>
                </tr>
                <tr style={{ borderTop: "1px solid var(--ink)" }}>
                  <td style={{ padding: 8, fontWeight: 600 }}>Net</td>
                  <td className="num mono bold" style={{ padding: 8 }}>{fmt.usd(baseline.net / 1000, 0)}k</td>
                  <td className="num mono bold" style={{ padding: 8 }}>{fmt.usd(newNet / 1000, 0)}k</td>
                  <td className="num mono bold" style={{ padding: 8, color: newNet > baseline.net ? "var(--red)" : "var(--green)" }}>
                    {newNet !== baseline.net ? (newNet > baseline.net ? "+" : "") + fmt.usd((newNet - baseline.net) / 1000, 0) + "k" : "—"}
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </Card>
      </div>
    </div>
  );
}

// ============== TERMINAL COST DETAIL ==============
function TerminalCostDetail({ terminal, onClose }) {
  const months = VOLUME.months.slice(-6);
  return (
    <SlideOver
      open={true}
      onClose={onClose}
      wide
      title={`Cost detail · ${terminal.terminalName}`}
      sub={`${terminal.terminal} · ${terminal.region}`}
      foot={
        <>
          <button className="btn"><Icon name="bolt" size={14} /> What-if</button>
          <button className="btn"><Icon name="download" size={14} /> Export</button>
          <div className="grow" />
          <button className="btn" onClick={onClose}>Close</button>
        </>
      }
    >
      <div className="grid-3" style={{ marginBottom: 16 }}>
        <KPI label="Net / TEU" value={fmt.usd(terminal.netPerTEU)} sub={`MoM ${terminal.momChange > 0 ? "↑" : "↓"} ${Math.abs(terminal.momChange).toFixed(1)}%`} />
        <KPI label="Rebate Yield" value={terminal.rebateYield.toFixed(2) + "%"} sub={fmt.usd(terminal.rebate / 1000, 0) + "k / month"} />
        <KPI label="Monthly TEU" value={fmt.num(terminal.monthlyTEU / 1000, 1) + "k"} />
      </div>

      <Card title="6-month breakdown · USD" style={{ marginBottom: 14 }}>
        <div className="table-wrap">
          <table className="table">
            <thead>
              <tr>
                <th>Cost Type</th>
                {months.map(m => <th key={m} className="num">{m.slice(5)}</th>)}
              </tr>
            </thead>
            <tbody>
              {Object.entries(terminal.breakdown).map(([k, v]) => (
                <tr key={k}>
                  <td className="bold tiny">{k}</td>
                  {months.map((m, i) => (
                    <td key={m} className="num mono tiny">{fmt.usd(v / 1000 * (0.92 + i * 0.025), 0)}k</td>
                  ))}
                </tr>
              ))}
              <tr style={{ borderTop: "2px solid var(--ink)" }}>
                <td className="bold tiny">Gross</td>
                {months.map((m, i) => (
                  <td key={m} className="num mono tiny bold">{fmt.usd(terminal.gross / 1000 * (0.92 + i * 0.025), 0)}k</td>
                ))}
              </tr>
              <tr>
                <td className="tiny" style={{ color: "var(--green)" }}>Rebate</td>
                {months.map((m, i) => (
                  <td key={m} className="num mono tiny" style={{ color: "var(--green)" }}>-{fmt.usd(terminal.rebate / 1000 * (0.85 + i * 0.04), 0)}k</td>
                ))}
              </tr>
              <tr style={{ borderTop: "1px solid var(--ink)" }}>
                <td className="bold tiny">Net</td>
                {months.map((m, i) => (
                  <td key={m} className="num mono tiny bold">{fmt.usd((terminal.gross * (0.92 + i * 0.025) - terminal.rebate * (0.85 + i * 0.04)) / 1000, 0)}k</td>
                ))}
              </tr>
            </tbody>
          </table>
        </div>
      </Card>

      <div style={{ padding: 12, background: "var(--amber-soft)", border: "1px solid #f0d8a8", borderRadius: 6, display: "flex", gap: 10 }}>
        <Icon name="bell" size={16} stroke="var(--amber)" />
        <div className="tiny">
          <b style={{ color: "var(--amber)" }}>Rate change impact alert:</b> CY Handling for {terminal.terminal} was updated 2025-05-10.
          At current volume pace, full-year P&L impact is estimated at <b>{fmt.usd(terminal.gross * 0.04 * 12)}</b>. FBP notified via in-app + email.
        </div>
      </div>
    </SlideOver>
  );
}

Object.assign(window, { TCOAnalysis });
