// Cash Flow Statement (indirect method) — formal monthly statement.
// Separate from the management "Cash Flow & Runway" view at page = "cash".
//
// Layout matches Income Statement / Balance Sheet: one column per month from
// the global period selector + a Total column.

const { useState: useCFS_useState, useEffect: useCFS_useEffect, useMemo: useCFS_useMemo } = React;

function useCFS_companyId(scopedCompanyId) {
  const [cid, setCid] = useCFS_useState(scopedCompanyId || null);
  useCFS_useEffect(() => {
    if (scopedCompanyId) { setCid(scopedCompanyId); return; }
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const { data: { session } } = await db.auth.getSession();
      if (!session) return;
      const { data: m } = await db.from('company_users').select('company_id')
        .eq('user_id', session.user.id).in('status', ['Active','Pending']).maybeSingle();
      if (m?.company_id) setCid(m.company_id);
    })();
  }, [scopedCompanyId]);
  return cid;
}

// ── Fetch every GL txn for the company (paginated, capped) ──────────────
async function fetchAllGL(db, companyId, hardCap = 80000) {
  const PAGE = 1000;
  let from = 0; let out = [];
  for (let i = 0; i < hardCap / PAGE; i++) {
    const { data, error } = await db.from('gl_transactions')
      .select('id, posted_date, account_code, account_name, amount')
      .eq('company_id', companyId)
      .order('posted_date', { ascending: true })
      .range(from, from + PAGE - 1);
    if (error || !data || data.length === 0) break;
    out = out.concat(data);
    if (data.length < PAGE) break;
    from += PAGE;
  }
  return out;
}

async function fetchCFSInputs(db, companyId) {
  const [txns, mappings, accountMaster] = await Promise.all([
    fetchAllGL(db, companyId),
    db.from('account_mappings').select('account_code, canonical_category, subcategory').eq('company_id', companyId).range(0, 1999).then(r => r.data || []),
    db.from('account_master').select('account_no, account_name, account_type, statement, normal_balance').eq('company_id', companyId).range(0, 1999).then(r => r.data || []),
  ]);
  return { txns, mappings, accountMaster };
}

// ── Renderer ────────────────────────────────────────────────────────────
function CFS_MoneyCell({ v, signed, bold }) {
  const F = window.PerduraFmt || { fmtUSD: (n) => '$' + Math.round(n).toLocaleString() };
  if (v === null || v === undefined || (typeof v === 'number' && !isFinite(v))) {
    return <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'ui-monospace, monospace', fontSize: 11.5, color: 'var(--text-4)' }}>—</td>;
  }
  const isZero = Math.abs(v) < 0.5;
  const col = signed ? (v < 0 ? 'var(--danger)' : 'var(--text-1)') : (isZero ? 'var(--text-4)' : 'var(--text-1)');
  return (
    <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'ui-monospace, monospace', fontSize: 11.5,
                  color: col, fontWeight: bold ? 700 : 400, whiteSpace: 'nowrap' }}>
      {isZero ? '—' : (v < 0 ? '(' + F.fmtUSD(Math.abs(v), { compact: true }) + ')' : F.fmtUSD(v, { compact: true }))}
    </td>
  );
}

function CFS_Row({ label, vals, total, bold, indent = 0, accent, cmp, curForVar, showCmp, drill }) {
  // Like-for-like variance: curForVar is the trimmed-current total that
  // pairs index-for-index with `cmp`. When the comparison is fully covered
  // (no trim), curForVar === total and the math is unchanged. When partial,
  // Var $ uses the equal-length pair so the % isn't 13-vs-11 distorted.
  const basis = (typeof curForVar === 'number') ? curForVar : total;
  const delta = (typeof cmp === 'number') ? (basis - cmp) : null;
  const deltaPct = (delta !== null && cmp !== 0 && isFinite(cmp))
    ? (delta / Math.abs(cmp)) * 100
    : null;
  return (
    <tr className={drill ? 'pc-clickable' : undefined}
        title={drill ? `View the GL accounts behind ${label}` : undefined}
        onClick={drill || undefined}
        style={{ background: accent || 'transparent' }}>
      <td style={{ paddingLeft: 14 + indent * 14, paddingRight: 12, fontSize: 12, fontWeight: bold ? 700 : 400,
                    color: bold ? 'var(--text-1)' : 'var(--text-2)' }}>{label}{drill && <span style={{ color: 'var(--accent)', marginLeft: 6, fontSize: 11 }}>↗</span>}</td>
      {vals.map((v, i) => <CFS_MoneyCell key={i} v={v} signed bold={bold} />)}
      <CFS_MoneyCell v={total} signed bold={bold} />
      {showCmp && (
        <>
          <CFS_MoneyCell v={(typeof cmp === 'number') ? cmp : NaN} signed bold={false} />
          <CFS_MoneyCell v={delta} signed bold={false} />
          <td style={{ textAlign: 'right', padding: '6px 12px', fontFamily: 'ui-monospace, monospace', fontSize: 11.5,
                        color: delta == null ? 'var(--text-4)' : (delta < 0 ? 'var(--danger)' : 'var(--text-2)') }}>
            {deltaPct == null ? (cmp === 0 && basis !== 0 ? 'n/m' : '—') : (deltaPct >= 0 ? '+' : '') + deltaPct.toFixed(1) + '%'}
          </td>
        </>
      )}
    </tr>
  );
}

function CFS_SectionHeader({ label, cols }) {
  return (
    <tr><td colSpan={cols} style={{ padding: '10px 14px', fontSize: 10.5, fontWeight: 700, color: 'var(--text-3)',
              textTransform: 'uppercase', letterSpacing: 0.6, background: 'var(--bg-elev-2)' }}>{label}</td></tr>
  );
}

// ── Self-contained presentation primitives (no cross-file const deps) ──────
const CF_INK = "#0F1520", CF_MUTE = "#4B5563", CF_POS = "#059669", CF_NEG = "#DC2626", CF_LINE = "#E4E8F0";
const CF_CARD = { borderRadius: 10, boxShadow: "0 1px 4px rgba(0,0,0,0.06)", background: "#fff", border: "1px solid " + CF_LINE };
const CF_SECT = { operating: "#1C4ED8", investing: "#D97706", financing: "#7C3AED" };
function cfFmt() { return window.PerduraFormat || { money: (v, o) => (o && o.compact && Math.abs(v) >= 1000 ? "$" + (v / 1000).toFixed(0) + "K" : "$" + Math.round(v).toLocaleString()) }; }
function cfMoneyStr(v, opts) { const F = cfFmt(); const n = Number(v || 0); const body = F.money(Math.abs(n), opts); return n < 0 ? "(" + body + ")" : body; }
function cfMoney(v, opts) { const o = opts || {}; const n = Number(v || 0); const F = cfFmt(); const body = F.money(Math.abs(n), o); const txt = n < 0 ? "(" + body + ")" : body; return <span style={{ color: n < 0 ? CF_NEG : (o.color || "inherit"), fontVariantNumeric: "tabular-nums" }}>{txt}</span>; }

function CFKpiTile({ label, value, accent, sub, subColor, subSmall }) {
  return (
    <div
      onClick={() => window.__perduraSetPage && window.__perduraSetPage("trial_balance")}
      title="View underlying GL accounts"
      style={{ ...CF_CARD, borderLeft: "4px solid " + accent, padding: "14px 16px", minWidth: 0, cursor: "pointer" }}>
      <div style={{ fontSize: 11, color: CF_MUTE, textTransform: "uppercase", letterSpacing: 0.5, fontWeight: 700, marginBottom: 6 }}>{label}</div>
      <div style={{ fontSize: 22, fontWeight: 800, color: CF_INK, letterSpacing: -0.5, fontVariantNumeric: "tabular-nums", lineHeight: 1.1 }}>{value}</div>
      {sub != null && <div style={{ fontSize: subSmall ? 11 : 12, fontWeight: subSmall ? 500 : 700, color: subColor || CF_MUTE, marginTop: 5, fontVariantNumeric: "tabular-nums" }}>{sub}</div>}
    </div>
  );
}

// Section with a colored header band and dotted-leader line items.
function CFSummarySection({ title, accent, caption, items, netLabel, netValue }) {
  return (
    <div style={{ ...CF_CARD, padding: 0, overflow: "hidden" }}>
      <div style={{ background: accent, color: "#fff", padding: "10px 16px" }}>
        <div style={{ fontSize: 12.5, fontWeight: 800, textTransform: "uppercase", letterSpacing: 0.5 }}>{title}</div>
        {caption && <div style={{ fontSize: 11, opacity: 0.9, marginTop: 1 }}>{caption}</div>}
      </div>
      <div style={{ padding: "8px 16px 4px" }}>
        {items.map((it, i) => (
          <div key={i} onClick={it.drill || undefined} className={"gl-row" + (it.drill ? " pc-clickable" : "")}
               style={{ display: "flex", alignItems: "baseline", gap: 4, padding: "6px 0", paddingLeft: it.indent ? 20 : 0, cursor: it.drill ? "pointer" : "default" }}>
            <span style={{ fontSize: 12.5, color: CF_INK, fontWeight: it.indent ? 400 : 500 }}>{it.label}{it.drill && <span className="gl-link" onClick={(e) => { e.stopPropagation(); it.drill(); }}>View in Data Room →</span>}</span>
            <span style={{ flex: 1, borderBottom: "1px dotted #CBD5E1", transform: "translateY(-3px)", margin: "0 4px" }} />
            <span style={{ fontSize: 12.5, fontWeight: 600, color: CF_INK, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" }}>{cfMoney(it.value)}</span>
          </div>
        ))}
      </div>
      <div style={{ borderTop: "2px solid " + accent, padding: "11px 16px", display: "flex", justifyContent: "space-between", alignItems: "center", background: "#FBFCFE" }}>
        <span style={{ fontSize: 12.5, fontWeight: 800, color: CF_INK }}>{netLabel}</span>
        <span style={{ fontSize: 18, fontWeight: 800, color: netValue < 0 ? CF_NEG : accent, fontVariantNumeric: "tabular-nums" }}>{cfMoneyStr(netValue, { compact: true })}</span>
      </div>
    </div>
  );
}

// Proportional reconciliation bar: Operating | Investing | Financing → Net.
function CFReconBar({ op, inv, fin, net }) {
  const parts = [
    { label: "Operating", v: op, color: CF_SECT.operating },
    { label: "Investing", v: inv, color: CF_SECT.investing },
    { label: "Financing", v: fin, color: CF_SECT.financing },
  ];
  const denom = parts.reduce((s, p) => s + Math.abs(p.v), 0) || 1;
  return (
    <div style={{ display: "grid", gridTemplateColumns: "1fr auto 1fr", gap: 18, alignItems: "center" }}>
      <div>
        <div style={{ display: "flex", height: 30, borderRadius: 6, overflow: "hidden", background: "#F1F5F9" }}>
          {parts.map((p, i) => {
            const w = Math.max(0, Math.abs(p.v) / denom * 100);
            return <div key={i} title={`${p.label}: ${cfMoneyStr(p.v)}`} style={{ width: w + "%", background: p.color, opacity: p.v < 0 ? 0.55 : 1 }} />;
          })}
        </div>
        <div style={{ display: "flex", gap: 16, marginTop: 8, flexWrap: "wrap" }}>
          {parts.map((p, i) => (
            <div key={i} style={{ display: "flex", alignItems: "center", gap: 6, fontSize: 11.5 }}>
              <span style={{ width: 10, height: 10, borderRadius: 3, background: p.color, display: "inline-block" }} />
              <span style={{ color: CF_MUTE }}>{p.label}</span>
              <b style={{ color: p.v < 0 ? CF_NEG : CF_INK, fontVariantNumeric: "tabular-nums" }}>{cfMoneyStr(p.v, { compact: true })}</b>
            </div>
          ))}
        </div>
      </div>
      <div style={{ fontSize: 26, fontWeight: 700, color: "#94A3B8" }}>=</div>
      <div>
        <div style={{ fontSize: 10.5, fontWeight: 700, color: CF_MUTE, textTransform: "uppercase", letterSpacing: 0.5 }}>Net change in cash</div>
        <div style={{ fontSize: 24, fontWeight: 800, color: net < 0 ? CF_NEG : CF_POS, fontVariantNumeric: "tabular-nums" }}>{(net >= 0 ? "+" : "−") + cfMoneyStr(Math.abs(net), { compact: true })}</div>
        <div style={{ height: 12, borderRadius: 4, marginTop: 6, background: net < 0 ? CF_NEG : CF_POS, opacity: 0.9 }} />
      </div>
    </div>
  );
}

// Trend bars (green positive / red negative).
function CFBarChart({ values, labels }) {
  const vals = (values || []).map(Number);
  if (!vals.length) return null;
  const W = 760, H = 180, padT = 14, padB = 28, padX = 12, plotH = H - padT - padB;
  const maxV = Math.max(0, ...vals), minV = Math.min(0, ...vals), range = (maxV - minV) || 1;
  const y = (v) => padT + ((maxV - v) / range) * plotH;
  const n = vals.length, colW = (W - padX * 2) / n, bw = Math.min(38, colW * 0.6);
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: "block" }} preserveAspectRatio="xMidYMid meet">
      <line x1={padX} x2={W - padX} y1={y(0)} y2={y(0)} stroke="#E4E8F0" />
      {vals.map((v, i) => {
        const cx = padX + colW * i + colW / 2, top = v >= 0 ? y(v) : y(0), h = Math.max(1, Math.abs(y(v) - y(0)));
        return <g key={i}><rect x={cx - bw / 2} y={top} width={bw} height={h} rx={2} fill={v >= 0 ? CF_POS : CF_NEG} opacity={0.9} />{n <= 16 && <text x={cx} y={(v >= 0 ? top : y(0)) - 3} textAnchor="middle" fontSize={8.5} fontWeight={600} fill="#0F1520" fontFamily="Inter, system-ui">{cfMoneyStr(v, { compact: true })}</text>}{labels && i % Math.ceil(n / 12) === 0 && <text x={cx} y={H - 9} textAnchor="middle" fontSize={9} fill="#94A3B8">{labels[i]}</text>}</g>;
      })}
    </svg>
  );
}
// Cumulative cash position area.
function CFAreaChart({ values, labels, color = "#1C4ED8" }) {
  const vals = (values || []).map(Number).filter(Number.isFinite);
  if (vals.length < 2) return <div style={{ padding: 16, fontSize: 11, color: "#94A3B8" }}>Not enough history.</div>;
  const W = 760, H = 180, padT = 14, padB = 28, padL = 46, padR = 12, plotH = H - padT - padB, plotW = W - padL - padR;
  const maxV = Math.max(...vals, 0), minV = Math.min(...vals, 0), range = (maxV - minV) || 1;
  const x = (i) => padL + (vals.length <= 1 ? 0 : (plotW / (vals.length - 1)) * i);
  const y = (v) => padT + (1 - (v - minV) / range) * plotH;
  const path = vals.map((v, i) => (i === 0 ? "M" : "L") + x(i).toFixed(1) + "," + y(v).toFixed(1)).join(" ");
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: "block" }} preserveAspectRatio="xMidYMid meet">
      <line x1={padL} x2={W - padR} y1={y(0)} y2={y(0)} stroke="#F0F0F0" />
      <path d={path + ` L${x(vals.length - 1)},${H - padB} L${x(0)},${H - padB} Z`} fill={color} fillOpacity={0.1} />
      <path d={path} fill="none" stroke={color} strokeWidth={2.2} strokeLinecap="round" strokeLinejoin="round" />
      {vals.map((v, i) => <circle key={i} cx={x(i)} cy={y(v)} r={2} fill={color} />)}
      {labels.map((l, i) => (i % Math.ceil(labels.length / 12) === 0 ? <text key={i} x={x(i)} y={H - 9} textAnchor="middle" fontSize={9} fill="#94A3B8">{l}</text> : null))}
    </svg>
  );
}
// Grouped monthly bars by activity.
function CFGroupedBars({ op, inv, fin, labels }) {
  const n = (op || []).length; if (!n) return null;
  const W = 760, H = 200, padT = 14, padB = 28, padX = 12, plotH = H - padT - padB;
  const all = op.concat(inv, fin);
  const maxV = Math.max(0, ...all), minV = Math.min(0, ...all), range = (maxV - minV) || 1;
  const y = (v) => padT + ((maxV - v) / range) * plotH;
  const colW = (W - padX * 2) / n, bw = Math.max(3, Math.min(9, colW / 4));
  const series = [{ vals: op, c: CF_SECT.operating }, { vals: inv, c: CF_SECT.investing }, { vals: fin, c: CF_SECT.financing }];
  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" style={{ display: "block" }} preserveAspectRatio="xMidYMid meet">
      <line x1={padX} x2={W - padX} y1={y(0)} y2={y(0)} stroke="#E4E8F0" />
      {series.map((s, si) => s.vals.map((v, i) => {
        const cx = padX + colW * i + colW / 2 + (si - 1) * (bw + 1.5), top = v >= 0 ? y(v) : y(0), h = Math.max(1, Math.abs(y(v) - y(0)));
        return <rect key={si + "-" + i} x={cx - bw / 2} y={top} width={bw} height={h} rx={1.5} fill={s.c} opacity={0.9} />;
      }))}
      {labels.map((l, i) => (i % Math.ceil(n / 12) === 0 ? <text key={i} x={padX + colW * i + colW / 2} y={H - 9} textAnchor="middle" fontSize={9} fill="#94A3B8">{l}</text> : null))}
    </svg>
  );
}
function CFLegend({ items }) {
  return (
    <div style={{ display: "flex", gap: 16, flexWrap: "wrap", marginTop: 8 }}>
      {items.map((it, i) => <div key={i} style={{ display: "flex", alignItems: "center", gap: 5, fontSize: 11, color: "#475569" }}><span style={{ width: 10, height: 10, borderRadius: 3, background: it.color, display: "inline-block" }} />{it.label}</div>)}
    </div>
  );
}
// Blue-gradient CFO narrative.
function CFCommentary({ items }) {
  return (
    <div style={{ borderRadius: 10, boxShadow: "0 1px 4px rgba(0,0,0,0.06)", color: "#fff", padding: "18px 20px", background: "linear-gradient(135deg, #1C4ED8 0%, #2563EB 48%, #0891B2 100%)" }}>
      <div style={{ fontSize: 11.5, textTransform: "uppercase", letterSpacing: 0.7, fontWeight: 800, opacity: 0.9, marginBottom: 14 }}>CFO commentary — cash flow</div>
      <div style={{ display: "flex", flexDirection: "column", gap: 11 }}>
        {items.map((it, i) => (
          <div key={i} style={{ display: "flex", gap: 11, alignItems: "flex-start" }}>
            <span style={{ flex: "0 0 auto", width: 22, height: 22, borderRadius: 6, background: "rgba(255,255,255,0.18)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 12 }}>{it.icon || "›"}</span>
            <div style={{ fontSize: 13.5, lineHeight: 1.5 }} dangerouslySetInnerHTML={{ __html: it.text }} />
          </div>
        ))}
      </div>
    </div>
  );
}
function CFPill(active) { return { padding: "6px 14px", borderRadius: 999, fontSize: 12.5, fontWeight: 700, cursor: "pointer", border: "1px solid " + (active ? "#1C4ED8" : "#E4E8F0"), background: active ? "#1C4ED8" : "#F7F8FB", color: active ? "#fff" : "#4B5563" }; }

function CashFlowStatementPage({ scopedCompanyId, periodResolved, companyProfile, setPage }) {
  const companyId = useCFS_companyId(scopedCompanyId);
  const [loading, setLoading] = useCFS_useState(true);
  const [error, setError]     = useCFS_useState(null);
  const [raw, setRaw]         = useCFS_useState(null);
  const [cfView, setCfView]   = useCFS_useState("summary"); // summary | detail | trend
  // Inline period selector above the CF table — windows the visible month
  // columns (trailing N) within the global period. Defaults to 12M per spec.
  const [cfInlinePeriod, setCfInlinePeriod] = useCFS_useState("12M"); // 1M|3M|6M|YTD|12M|13M

  useCFS_useEffect(() => {
    if (!companyId) { setLoading(false); return; }
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    let cancelled = false;
    setLoading(true); setError(null);
    fetchCFSInputs(db, companyId)
      .then(d => { if (!cancelled) { setRaw(d); setLoading(false); } })
      .catch(e => { if (!cancelled) { setError(String(e?.message || e)); setLoading(false); } });
    return () => { cancelled = true; };
  }, [companyId]);

  const engine = window.PerduraCashFlow;
  // Window the global period's months by the inline selector (trailing N).
  const allMonthCols = periodResolved?.months || [];
  const monthCols = (() => {
    if (!allMonthCols.length) return allMonthCols;
    if (cfInlinePeriod === "YTD") { const ly = allMonthCols[allMonthCols.length - 1].year; return allMonthCols.filter(m => m.year === ly); }
    const N = { "1M": 1, "3M": 3, "6M": 6, "12M": 12, "13M": 13 }[cfInlinePeriod] || 12;
    return allMonthCols.slice(-N);
  })();

  const cf = useCFS_useMemo(() => {
    if (!engine || !raw) return null;
    return engine.compute({
      txns: raw.txns, mappings: raw.mappings, accountMaster: raw.accountMaster,
      monthCols, profile: companyProfile,
      fiscalYearStartMonth: companyProfile?.fiscal_year_start_month || 1,
    });
  }, [engine, raw, monthCols.map(m => m.year + '-' + m.month1).join(','), companyProfile?.fiscal_year_start_month]);

  // Account codes per cash-flow bucket — lets each statement line drill into
  // the Data Room scoped to exactly the GL accounts that fed it. Uses the same
  // classifier the engine uses, so the drill matches the line's composition.
  const codesByBucket = useCFS_useMemo(() => {
    const classify = window.PerduraCashFlow && window.PerduraCashFlow.classifyAccount;
    if (!raw || !classify) return {};
    const mapByCode = {}; (raw.mappings || []).forEach(m => { mapByCode[m.account_code] = m; });
    const mstByCode = {}; (raw.accountMaster || []).forEach(a => { mstByCode[a.account_no] = a; });
    const seen = new Set(); const out = {};
    for (const t of raw.txns || []) {
      const code = t.account_code; if (!code || seen.has(code)) continue; seen.add(code);
      const map = mapByCode[code] || {}; const mst = mstByCode[code] || {};
      const bucket = classify({
        accountCode: code, accountName: mst.account_name || t.account_name,
        accountType: mst.account_type, canonicalCategory: map.canonical_category, subcategory: map.subcategory,
      }, companyProfile);
      if (!bucket) continue;
      (out[bucket] || (out[bucket] = new Set())).add(String(code));
    }
    const arr = {}; Object.keys(out).forEach(k => { arr[k] = Array.from(out[k]); });
    return arr;
  }, [raw, companyProfile]);

  // Build a row click handler for a set of buckets — only when it has accounts,
  // so lines with no contributing accounts stay non-clickable.
  const mkDrill = (buckets, label) => {
    const s = new Set();
    buckets.forEach(b => (codesByBucket[b] || []).forEach(c => s.add(c)));
    const codes = Array.from(s);
    if (!codes.length || !window.__perduraDrillDataRoom || !periodResolved) return undefined;
    return () => window.__perduraDrillDataRoom({
      t: 'gl_transactions', codes,
      start: periodResolved.startDate, end: periodResolved.endDate, label,
    });
  };

  // ── Like-for-like comparison ────────────────────────────────────────
  // Pair each current month with its index-aligned prior month. Drop pairs
  // where the prior side has no GL data. Variance is then computed from the
  // equal-length pair — never 13-vs-11 distortion.
  const cmpMonths = periodResolved?.compare?.months || [];
  const lfl = useCFS_useMemo(() => {
    if (!raw || !cmpMonths.length || !monthCols.length)
      return { curLfl: [], cmpLfl: [] };
    const haveYM = new Set();
    for (const t of raw.txns || []) {
      if (!t.posted_date) continue;
      const d = new Date(t.posted_date);
      haveYM.add(d.getFullYear() * 100 + (d.getMonth() + 1));
    }
    const curLfl = [], cmpLfl = [];
    const n = Math.min(monthCols.length, cmpMonths.length);
    for (let i = 0; i < n; i++) {
      const cm = cmpMonths[i];
      const cu = monthCols[i];
      if (cm && haveYM.has(cm.year * 100 + cm.month1)) {
        curLfl.push(cu); cmpLfl.push(cm);
      }
    }
    return { curLfl, cmpLfl };
  }, [raw, monthCols.map(m => m.year + '-' + m.month1).join(','), cmpMonths.map(m => m.year + '-' + m.month1).join(',')]);

  const cmpCf = useCFS_useMemo(() => {
    if (!engine || !raw || lfl.cmpLfl.length === 0) return null;
    return engine.compute({
      txns: raw.txns, mappings: raw.mappings, accountMaster: raw.accountMaster,
      monthCols: lfl.cmpLfl, profile: companyProfile,
      fiscalYearStartMonth: companyProfile?.fiscal_year_start_month || 1,
    });
  }, [engine, raw, lfl]);

  // Like-for-like CURRENT run: same months as `cf` but trimmed to align with
  // cmp. Var $ / Var % use this, not the full `cf`. When prior is fully
  // available, lfl.curLfl === monthCols and curLflCf === cf.
  const curLflCf = useCFS_useMemo(() => {
    if (!engine || !raw || lfl.curLfl.length === 0) return null;
    if (lfl.curLfl.length === monthCols.length) return null;  // signal "use cf"
    return engine.compute({
      txns: raw.txns, mappings: raw.mappings, accountMaster: raw.accountMaster,
      monthCols: lfl.curLfl, profile: companyProfile,
      fiscalYearStartMonth: companyProfile?.fiscal_year_start_month || 1,
    });
  }, [engine, raw, lfl, monthCols.length]);

  const cmpLabel = (() => {
    const raw_ = periodResolved?.compare?.label || '';
    if (!raw_) return '';
    if (cmpMonths.length === 0) return raw_;
    if (lfl.cmpLfl.length === 0) return raw_ + ' · no comparison data';
    if (lfl.cmpLfl.length < cmpMonths.length) return raw_ + ` · like-for-like ${lfl.cmpLfl.length} mo vs ${lfl.cmpLfl.length} mo (${lfl.cmpLfl.length} of ${cmpMonths.length} prior mo available)`;
    return raw_;
  })();

  if (!engine) {
    return (
      <div className="pc-page"><Card><div style={{ padding: 24 }}>Cash-flow engine not loaded.</div></Card></div>
    );
  }
  if (!companyId) {
    return (
      <div className="pc-page"><Card><div style={{ padding: 24, color: 'var(--text-3)' }}>Resolving company…</div></Card></div>
    );
  }
  if (loading) {
    return (
      <div className="pc-page"><Card><div style={{ padding: 24, color: 'var(--text-3)' }}>Loading transactions…</div></Card></div>
    );
  }
  if (error) {
    return (
      <div className="pc-page"><Card><div style={{ padding: 24, color: 'var(--danger)' }}>Error: {error}</div></Card></div>
    );
  }
  if (!cf || !monthCols.length) {
    return (
      <div className="pc-page"><Card><div style={{ padding: 24 }}>No period selected.</div></Card></div>
    );
  }

  const tot = (row) => row.reduce((a, b) => a + b, 0);
  const showCmp = lfl.cmpLfl.length > 0;
  const cmpTot = (row) => row ? row.reduce((a, b) => a + b, 0) : null;
  // `cur` for variance: when comparison is partial, use the trimmed
  // like-for-like current run; otherwise use the full `cf`. The Var $ / Var %
  // basis is therefore always the same count of months on both sides.
  const curForVar = curLflCf || cf;
  const cols = monthCols.length + 2 + (showCmp ? 3 : 0);

  // ── Headline / summary derivations ──────────────────────────────────────
  const MS = (engine.MONTH_SHORT) || ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  const monthLabels = monthCols.map(m => `${MS[m.month1 - 1]} ${String(m.year).slice(-2)}`);
  const opTotal = tot(cf.operating.total), invTotal = tot(cf.investing.total), finTotal = tot(cf.financing.total);
  const netChange = tot(cf.netChange);
  const opening = cf.beginningCash[0] || 0;
  const closing = cf.endingCash[cf.endingCash.length - 1] || 0;
  const pOp = cmpCf ? cmpTot(cmpCf.operating.total) : null;
  const pInv = cmpCf ? cmpTot(cmpCf.investing.total) : null;
  const pFin = cmpCf ? cmpTot(cmpCf.financing.total) : null;
  const pNet = cmpCf ? cmpTot(cmpCf.netChange) : null;
  const nMo = monthCols.length;
  const avgNet = nMo ? netChange / nMo : 0;
  const burning = avgNet < -1;
  const runwayDays = burning && Math.abs(avgNet) > 0 ? Math.round(closing / (Math.abs(avgNet) / 30)) : null;
  const projection90 = closing + avgNet * 3;

  const keep = (it) => Math.abs(it.value) >= 1 || it.always;
  const opItems = [
    { label: "Net income", value: tot(cf.operating.netIncome), always: true, drill: mkDrill(['is_revenue','is_cogs','is_opex','is_da','is_other'], 'Net income') },
    { label: "+ Depreciation & amortization", value: tot(cf.operating.depreciation), indent: true, drill: mkDrill(['is_da'], 'Depreciation & amortization') },
    { label: "(Increase) / decrease in AR", value: tot(cf.operating.deltaAR), indent: true, drill: mkDrill(['wc_ar'], 'Change in AR') },
    { label: "(Increase) / decrease in inventory", value: tot(cf.operating.deltaInventory), indent: true, drill: mkDrill(['wc_inv'], 'Change in inventory') },
    { label: "Increase / (decrease) in AP", value: tot(cf.operating.deltaAP), indent: true, drill: mkDrill(['wc_ap'], 'Change in AP') },
    { label: "Increase / (decrease) in accruals", value: tot(cf.operating.deltaAccrued), indent: true, drill: mkDrill(['wc_accr'], 'Change in accruals') },
    { label: "Other Δ current assets", value: tot(cf.operating.deltaOtherCA), indent: true, drill: mkDrill(['wc_other_a'], 'Other Δ current assets') },
    { label: "Other Δ current liabilities", value: tot(cf.operating.deltaOtherCL), indent: true, drill: mkDrill(['wc_other_l'], 'Other Δ current liabilities') },
  ].filter(keep);
  const invItems = [
    { label: "Capital expenditures (PP&E)", value: tot(cf.investing.capex), drill: mkDrill(['inv_capex'], 'Capital expenditures (PP&E)') },
    { label: "Other investing", value: tot(cf.investing.other), indent: true, drill: mkDrill(['inv_other','inv_acc_dep'], 'Other investing') },
  ].filter(keep);
  const finItems = [
    { label: "Debt — net (draws / repayments)", value: tot(cf.financing.debt), drill: mkDrill(['fin_debt'], 'Debt — net') },
    { label: "Equity contributions", value: tot(cf.financing.equityContrib), indent: true, drill: mkDrill(['fin_equity'], 'Equity contributions') },
    { label: "Distributions / dividends", value: tot(cf.financing.distributions), indent: true, drill: mkDrill(['fin_distrib'], 'Distributions / dividends') },
  ].filter(keep);

  const narrative = [
    { icon: opTotal >= 0 ? "▲" : "▼", text: `Operating activities ${opTotal >= 0 ? "generated" : "consumed"} <b>${cfMoneyStr(Math.abs(opTotal), { compact: true })}</b>${pOp != null ? ` (${opTotal - pOp >= 0 ? "up" : "down"} vs prior)` : ""} — ${opTotal >= 0 ? "the core business is self-funding" : "the core business is burning cash"}.` },
    { icon: "◆", text: `Investing used ${cfMoneyStr(Math.abs(invTotal), { compact: true })} and financing ${finTotal >= 0 ? "contributed" : "returned"} ${cfMoneyStr(Math.abs(finTotal), { compact: true })}; net cash ${netChange >= 0 ? "rose" : "fell"} ${cfMoneyStr(Math.abs(netChange), { compact: true })} to a ${cfMoneyStr(closing, { compact: true })} balance.` },
    { icon: burning ? "▼" : "▲", text: burning ? `At the current burn rate, cash projects to <b>${cfMoneyStr(projection90, { compact: true })}</b> in 90 days (~${runwayDays} days of runway).` : `Cash is self-sustaining; the 90-day projection is <b>${cfMoneyStr(projection90, { compact: true })}</b> on the current trajectory.` },
    { icon: "➜", text: `<b>Recommended action:</b> ${burning ? "Extend runway — tighten working capital (collect AR faster, stage payables) and revisit discretionary capex." : (invTotal < 0 && Math.abs(invTotal) > opTotal) ? "Investing outpaces operating cash — make sure capex is funded by durable cash generation, not balance-sheet drawdown." : "Healthy cash engine — consider deploying surplus into growth, debt paydown, or reserves."}` },
  ];

  const renderDetailTable = () => (
    <Card title="Cash flow detail" subtitle="Indirect method · GL-level monthly breakdown" padding={0}>
      <div style={{ overflowX: 'auto' }}>
        <table className="pc-table" style={{ fontSize: 11.5, minWidth: 320 + monthCols.length * 100 + 100 }}>
          <thead>
            <tr>
              <th style={{ padding: '10px 14px', textAlign: 'left' }}>&nbsp;</th>
              {monthCols.map(m => (
                <th key={m.year + '-' + m.month1} style={{ padding: '10px 12px', textAlign: 'right', fontFamily: 'ui-monospace, monospace', fontSize: 11 }}>{MS[m.month1 - 1]} {m.year}</th>
              ))}
              <th style={{ padding: '10px 12px', textAlign: 'right', fontWeight: 700 }}>Total</th>
              {showCmp && <>
                <th style={{ padding: '10px 12px', textAlign: 'right', borderLeft: '1px solid var(--border-strong)' }}>{cmpLabel || 'Comparison'}</th>
                <th style={{ padding: '10px 12px', textAlign: 'right' }}>Var $</th>
                <th style={{ padding: '10px 12px', textAlign: 'right' }}>Var %</th>
              </>}
            </tr>
          </thead>
          <tbody>
            <CFS_SectionHeader label="Cash from operating activities" cols={cols} />
            <CFS_Row label="Net income"                          vals={cf.operating.netIncome}      total={tot(cf.operating.netIncome)}      cmp={cmpCf && cmpTot(cmpCf.operating.netIncome)}      curForVar={tot(curForVar.operating.netIncome)}      showCmp={showCmp} drill={mkDrill(['is_revenue','is_cogs','is_opex','is_da','is_other'], 'Net income')} />
            <CFS_Row label="+ Depreciation & amortization"       vals={cf.operating.depreciation}   total={tot(cf.operating.depreciation)}   cmp={cmpCf && cmpTot(cmpCf.operating.depreciation)}   curForVar={tot(curForVar.operating.depreciation)}   showCmp={showCmp} indent={1} drill={mkDrill(['is_da'], 'Depreciation & amortization')} />
            <CFS_Row label="(Increase) / decrease in AR"         vals={cf.operating.deltaAR}        total={tot(cf.operating.deltaAR)}        cmp={cmpCf && cmpTot(cmpCf.operating.deltaAR)}        curForVar={tot(curForVar.operating.deltaAR)}        showCmp={showCmp} indent={1} drill={mkDrill(['wc_ar'], 'Change in AR')} />
            <CFS_Row label="(Increase) / decrease in inventory"  vals={cf.operating.deltaInventory} total={tot(cf.operating.deltaInventory)} cmp={cmpCf && cmpTot(cmpCf.operating.deltaInventory)} curForVar={tot(curForVar.operating.deltaInventory)} showCmp={showCmp} indent={1} drill={mkDrill(['wc_inv'], 'Change in inventory')} />
            <CFS_Row label="Increase / (decrease) in AP"         vals={cf.operating.deltaAP}        total={tot(cf.operating.deltaAP)}        cmp={cmpCf && cmpTot(cmpCf.operating.deltaAP)}        curForVar={tot(curForVar.operating.deltaAP)}        showCmp={showCmp} indent={1} drill={mkDrill(['wc_ap'], 'Change in AP')} />
            <CFS_Row label="Increase / (decrease) in accruals"   vals={cf.operating.deltaAccrued}   total={tot(cf.operating.deltaAccrued)}   cmp={cmpCf && cmpTot(cmpCf.operating.deltaAccrued)}   curForVar={tot(curForVar.operating.deltaAccrued)}   showCmp={showCmp} indent={1} drill={mkDrill(['wc_accr'], 'Change in accruals')} />
            <CFS_Row label="Other Δ current assets"              vals={cf.operating.deltaOtherCA}   total={tot(cf.operating.deltaOtherCA)}   cmp={cmpCf && cmpTot(cmpCf.operating.deltaOtherCA)}   curForVar={tot(curForVar.operating.deltaOtherCA)}   showCmp={showCmp} indent={1} drill={mkDrill(['wc_other_a'], 'Other Δ current assets')} />
            <CFS_Row label="Other Δ current liabilities"         vals={cf.operating.deltaOtherCL}   total={tot(cf.operating.deltaOtherCL)}   cmp={cmpCf && cmpTot(cmpCf.operating.deltaOtherCL)}   curForVar={tot(curForVar.operating.deltaOtherCL)}   showCmp={showCmp} indent={1} drill={mkDrill(['wc_other_l'], 'Other Δ current liabilities')} />
            <CFS_Row label="Cash from operating activities"      vals={cf.operating.total}          total={tot(cf.operating.total)}          cmp={cmpCf && cmpTot(cmpCf.operating.total)}          curForVar={tot(curForVar.operating.total)}          showCmp={showCmp} bold accent="rgba(28,78,216,0.06)" />

            <CFS_SectionHeader label="Cash from investing activities" cols={cols} />
            <CFS_Row label="Capital expenditures (PP&E)"         vals={cf.investing.capex} total={tot(cf.investing.capex)} cmp={cmpCf && cmpTot(cmpCf.investing.capex)} curForVar={tot(curForVar.investing.capex)} showCmp={showCmp} drill={mkDrill(['inv_capex'], 'Capital expenditures (PP&E)')} />
            <CFS_Row label="Other investing"                     vals={cf.investing.other} total={tot(cf.investing.other)} cmp={cmpCf && cmpTot(cmpCf.investing.other)} curForVar={tot(curForVar.investing.other)} showCmp={showCmp} indent={1} drill={mkDrill(['inv_other','inv_acc_dep'], 'Other investing')} />
            <CFS_Row label="Cash from investing activities"      vals={cf.investing.total} total={tot(cf.investing.total)} cmp={cmpCf && cmpTot(cmpCf.investing.total)} curForVar={tot(curForVar.investing.total)} showCmp={showCmp} bold accent="rgba(217,119,6,0.06)" />

            <CFS_SectionHeader label="Cash from financing activities" cols={cols} />
            <CFS_Row label="Debt — net (draws / repayments)"     vals={cf.financing.debt}          total={tot(cf.financing.debt)}          cmp={cmpCf && cmpTot(cmpCf.financing.debt)}          curForVar={tot(curForVar.financing.debt)}          showCmp={showCmp} drill={mkDrill(['fin_debt'], 'Debt — net')} />
            <CFS_Row label="Equity contributions"                vals={cf.financing.equityContrib} total={tot(cf.financing.equityContrib)} cmp={cmpCf && cmpTot(cmpCf.financing.equityContrib)} curForVar={tot(curForVar.financing.equityContrib)} showCmp={showCmp} indent={1} drill={mkDrill(['fin_equity'], 'Equity contributions')} />
            <CFS_Row label="Distributions / dividends"           vals={cf.financing.distributions} total={tot(cf.financing.distributions)} cmp={cmpCf && cmpTot(cmpCf.financing.distributions)} curForVar={tot(curForVar.financing.distributions)} showCmp={showCmp} indent={1} drill={mkDrill(['fin_distrib'], 'Distributions / dividends')} />
            <CFS_Row label="Cash from financing activities"      vals={cf.financing.total}         total={tot(cf.financing.total)}         cmp={cmpCf && cmpTot(cmpCf.financing.total)}         curForVar={tot(curForVar.financing.total)}         showCmp={showCmp} bold accent="rgba(124,58,237,0.06)" />

            {cf.unclassifiedCashEffect.some(v => Math.abs(v) >= 1) && (
              <>
                <CFS_SectionHeader label="Unclassified accounts (needs mapping)" cols={cols} />
                <CFS_Row label="Cash effect of unclassified accounts" vals={cf.unclassifiedCashEffect} total={tot(cf.unclassifiedCashEffect)} cmp={cmpCf && cmpTot(cmpCf.unclassifiedCashEffect)} curForVar={tot(curForVar.unclassifiedCashEffect)} showCmp={showCmp} accent="rgba(248,113,113,0.04)" drill={mkDrill(['unclassified'], 'Unclassified accounts')} />
              </>
            )}

            <tr><td colSpan={cols} style={{ borderTop: '1px solid var(--border)', padding: 0 }}/></tr>
            <CFS_Row label="Net change in cash"   vals={cf.netChange}     total={tot(cf.netChange)}     cmp={cmpCf && cmpTot(cmpCf.netChange)} curForVar={tot(curForVar.netChange)} showCmp={showCmp} bold />
            <CFS_Row label="+ Beginning cash"     vals={cf.beginningCash} total={cf.beginningCash[0] || 0} cmp={cmpCf && (cmpCf.beginningCash[0] || 0)} curForVar={curForVar.beginningCash[0] || 0} showCmp={showCmp} />
            <CFS_Row label="= Ending cash"        vals={cf.endingCash}    total={cf.endingCash[cf.endingCash.length - 1] || 0} cmp={cmpCf && (cmpCf.endingCash[cmpCf.endingCash.length - 1] || 0)} curForVar={curForVar.endingCash[curForVar.endingCash.length - 1] || 0} showCmp={showCmp} bold accent="rgba(28,78,216,0.08)" />
            <CFS_Row label="Balance Sheet cash (validator)" vals={cf.bsEndingCash} total={cf.bsEndingCash[cf.bsEndingCash.length - 1] || 0} cmp={cmpCf && (cmpCf.bsEndingCash[cmpCf.bsEndingCash.length - 1] || 0)} curForVar={curForVar.bsEndingCash[curForVar.bsEndingCash.length - 1] || 0} showCmp={showCmp} />
            <CFS_Row label="Check (CF end − BS cash)" vals={cf.endingCash.map((v,i) => v - cf.bsEndingCash[i])} total={(cf.endingCash[cf.endingCash.length-1] || 0) - (cf.bsEndingCash[cf.bsEndingCash.length-1] || 0)} showCmp={false} accent={cf.endingCash.some((v,i) => Math.abs(v - cf.bsEndingCash[i]) > 1) ? 'rgba(248,113,113,0.06)' : 'rgba(110,231,183,0.06)'} />

            {cf.unreconciledLine.some(v => Math.abs(v) >= 1) && (
              <>
                <tr><td colSpan={cols} style={{ padding: '4px 0' }}/></tr>
                <CFS_Row label="Bridge residual (CF buckets − BS cash Δ)" vals={cf.unreconciledLine} total={tot(cf.unreconciledLine)} showCmp={false} accent="rgba(248,113,113,0.06)" />
              </>
            )}
          </tbody>
        </table>
      </div>
    </Card>
  );

  return (
    <div className="pc-page">
      <div className="pa-hero" style={{ borderRadius: 14, marginBottom: 4 }}>
        <div className="pa-hero-eyebrow">LIQUIDITY</div>
        <div className="pa-hero-title">Cash Flow Statement</div>
        <div className="pa-hero-subtitle">Indirect method · operating, investing &amp; financing activities</div>
      </div>
      {/* Period header */}
      <div style={{ ...CF_CARD, padding: "14px 16px", display: "flex", flexWrap: "wrap", gap: 12, alignItems: "center", justifyContent: "space-between" }}>
        <div>
          <div style={{ fontSize: 11, color: CF_MUTE, textTransform: 'uppercase', letterSpacing: 0.5, fontWeight: 700 }}>Finance · Statement of Cash Flows</div>
          <div style={{ fontSize: 13, color: "#475569", marginTop: 3 }}>
            Indirect method · {monthCols.length} month{monthCols.length === 1 ? '' : 's'} · {periodResolved.startDate} → {periodResolved.endDate}{cmpLabel && <> · vs {cmpLabel}</>}
          </div>
          <div style={{ fontSize: 10.5, color: "#4B5563", marginTop: 2 }}>Change the period in the global period bar at the top of the app.</div>
        </div>
        <div style={{ display: "flex", gap: 12, alignItems: "center", flexWrap: "wrap" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
            <span style={{ fontSize: 10, fontWeight: 700, color: "#6475a0", textTransform: "uppercase", letterSpacing: ".06em", marginRight: 2 }}>View:</span>
            {["1M", "3M", "6M", "YTD", "12M", "13M"].map(p => (
              <button key={p} onClick={() => setCfInlinePeriod(p)} style={{ padding: "3px 9px", fontSize: 10.5, fontWeight: 700, cursor: "pointer", borderRadius: 5, border: "1px solid rgba(13,32,64,.15)", background: cfInlinePeriod === p ? "#0d2040" : "rgba(13,32,64,.05)", color: cfInlinePeriod === p ? "#fff" : "#6475a0" }}>{p}</button>
            ))}
          </div>
          <div style={{ display: "flex", gap: 6 }}>
            {[["summary", "Summary"], ["detail", "Detail"], ["trend", "Trend"]].map(([k, lab]) => (
              <button key={k} onClick={() => setCfView(k)} style={CFPill(cfView === k)}>{lab}</button>
            ))}
          </div>
        </div>
      </div>

      {/* Header KPI strip */}
      <div className="pc-kpi-grid pc-kpi-grid-4">
        <CFKpiTile label="Operating Cash Flow" accent={CF_SECT.operating} value={cfMoneyStr(opTotal, { compact: true })}
          sub={pOp == null ? "no prior period" : `${opTotal - pOp >= 0 ? "▲" : "▼"} ${cfMoneyStr(Math.abs(opTotal - pOp), { compact: true })} vs prior`}
          subColor={pOp == null ? CF_MUTE : (opTotal - pOp >= 0 ? CF_POS : CF_NEG)} />
        <CFKpiTile label="Investing Cash Flow" accent={CF_SECT.investing} value={cfMoneyStr(invTotal, { compact: true })}
          sub={invTotal < 0 ? "cash deployed" : "net inflow"} subColor={invTotal < 0 ? CF_NEG : CF_POS} />
        <CFKpiTile label="Financing Cash Flow" accent={CF_SECT.financing} value={cfMoneyStr(finTotal, { compact: true })}
          sub={finTotal >= 0 ? "raised" : "returned to capital"} subColor={finTotal >= 0 ? CF_POS : CF_NEG} />
        <CFKpiTile label="Net Change in Cash" accent={netChange >= 0 ? CF_POS : CF_NEG} value={(netChange >= 0 ? "+" : "−") + cfMoneyStr(Math.abs(netChange), { compact: true })}
          sub={`ending cash ${cfMoneyStr(closing, { compact: true })}`} subColor={CF_MUTE} subSmall />
      </div>

      {cfView === "summary" && (
        <>
          <div className="pc-kpi-grid pc-kpi-grid-3">
            <CFSummarySection title="Operating Activities" accent={CF_SECT.operating} caption="Cash generated from running the business" items={opItems} netLabel="Net operating cash flow" netValue={opTotal} />
            <CFSummarySection title="Investing Activities" accent={CF_SECT.investing} caption="Cash used for long-term investments" items={invItems} netLabel="Net investing cash flow" netValue={invTotal} />
            <CFSummarySection title="Financing Activities" accent={CF_SECT.financing} caption="Cash from debt and equity transactions" items={finItems} netLabel="Net financing cash flow" netValue={finTotal} />
          </div>

          <Card title="Net change reconciliation" subtitle="Contribution of each activity to the period's net cash movement" padding={18}>
            <CFReconBar op={opTotal} inv={invTotal} fin={finTotal} net={netChange} />
          </Card>

          <Card title="Cash position" subtitle="Opening → net change → closing" padding={0}>
            <div style={{ maxWidth: 460 }}>
              {[["Opening cash", opening, false, CF_INK],
                ["+ Net change in cash", netChange, false, netChange < 0 ? CF_NEG : CF_POS],
                ["= Closing cash", closing, true, CF_INK]].map(([l, v, strong, col], i) => (
                <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "11px 16px", borderTop: i === 2 ? "2px solid #E4E8F0" : "1px solid #F1F5F9" }}>
                  <span style={{ fontSize: 13, fontWeight: strong ? 800 : 500, color: CF_INK }}>{l}</span>
                  <span style={{ fontSize: strong ? 17 : 13.5, fontWeight: strong ? 800 : 600, color: col, fontVariantNumeric: "tabular-nums" }}>{(l[0] === "+" && netChange >= 0 ? "+" : "") + cfMoneyStr(v)}</span>
                </div>
              ))}
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "11px 16px", background: "#FBFCFE", borderTop: "1px solid #F1F5F9" }}>
                <span style={{ fontSize: 12.5, fontWeight: 600, color: CF_MUTE }}>Days of runway</span>
                <span style={{ fontSize: 14, fontWeight: 800, color: runwayDays == null ? CF_POS : runwayDays < 90 ? CF_NEG : runwayDays < 180 ? "#D97706" : CF_POS, fontVariantNumeric: "tabular-nums" }}>{runwayDays == null ? "cash-generative" : runwayDays.toLocaleString() + " days"}</span>
              </div>
            </div>
          </Card>

          <CFCommentary items={narrative} />
        </>
      )}

      {cfView === "detail" && renderDetailTable()}

      {cfView === "trend" && (
        <>
          <Card title="Operating cash flow" subtitle="Monthly operating cash — green positive, red negative" padding={14}>
            <CFBarChart values={cf.operating.total} labels={monthLabels} />
          </Card>
          <Card title="Cumulative cash position" subtitle="Ending cash balance across the period" padding={14}>
            <CFAreaChart values={cf.endingCash} labels={monthLabels} color="#1C4ED8" />
          </Card>
          <Card title="Cash flow by activity" subtitle="Operating vs investing vs financing, by month" padding={14}>
            <CFGroupedBars op={cf.operating.total} inv={cf.investing.total} fin={cf.financing.total} labels={monthLabels} />
            <CFLegend items={[{ label: "Operating", color: CF_SECT.operating }, { label: "Investing", color: CF_SECT.investing }, { label: "Financing", color: CF_SECT.financing }]} />
          </Card>
        </>
      )}

      {cfView === "trend" && <CFCommentary items={narrative} />}

      {cf.unclassified.length > 0 && cfView === "detail" && (
        <Card padding={0}>
          <div style={{ padding: '10px 14px', fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: 0.5, borderBottom: '1px solid var(--border)' }}>
            Unclassified accounts &middot; needs mapping
          </div>
          <table className="pc-table compact">
            <thead><tr><th>Account</th><th>Name</th><th>Tx count</th><th style={{ textAlign: 'right' }}>Net amount</th></tr></thead>
            <tbody>
              {cf.unclassified.slice(0, 50).map((u, i) => (
                <tr key={i}>
                  <td style={{ paddingLeft: 14, fontFamily: 'ui-monospace, monospace', fontSize: 11 }}>{u.account_code || '—'}</td>
                  <td>{u.account_name}</td>
                  <td>{u.count}</td>
                  <td style={{ textAlign: 'right', fontFamily: 'ui-monospace, monospace' }}>{cfMoneyStr(u.amount, { compact: true })}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      )}
    </div>
  );
}

Object.assign(window, { CashFlowStatementPage });
