// AccrualsPage — window.AccrualsPage (INTELLIGENCE group, "Accruals & Risk").
//
// A CFO-grade accruals & risk-intelligence surface with four tabs:
//   1. Computed Accruals   — deterministic reserves from real GL / subledger
//                            data (AR aging → bad-debt reserve, payroll accrual,
//                            deferred revenue). Never fabricates: shows "—" when
//                            the underlying feed is absent. Inventory obsolescence
//                            is honestly gated (no on-hand aging feed exists).
//   2. Undisclosed Liab.   — an AI-style guided questionnaire that builds a
//                            liability register from the owner's answers,
//                            persisted to localStorage.
//   3. Macro Intelligence  — archetype-aware tariff scenarios, inflation impact
//                            on the real cost structure, interest-rate sensitivity
//                            on detected variable-rate debt, plus cfo-synthesis
//                            page commentary (hides quietly if unavailable).
//   4. Action Plan         — consolidates every gap above into a prioritized,
//                            exportable list.
//
// House conventions: IIFE + React.createElement, window.PerduraPageKit (K) for
// Shell/Hero/SectionHead/Kpi/Card/CFOCommentaryPanel + formatting, real data
// from props.data (pl/plHistory/txns) and the ar_invoices subledger. Every tab
// carries the "planning purposes only — confirm with your accountant" disclaimer.

(function () {
  const R = window.React;
  if (!R) return;
  const h = R.createElement;
  const { useState, useEffect, useMemo } = R;

  // ── Configurable defaults (admin can override in Platform Config later) ──────
  // Industry-standard aging reserve rates, keyed by days-past-due bucket.
  const AR_RESERVE_RATES = [
    { key: "current",  label: "Current",      rate: 0.005 },
    { key: "days_30",  label: "1–30 days",    rate: 0.02  },
    { key: "days_60",  label: "31–60 days",   rate: 0.05  },
    { key: "days_90",  label: "61–90 days",   rate: 0.10  },
    { key: "days_120", label: "91–120 days",  rate: 0.25  },
    { key: "over_120", label: "Over 120 days", rate: 0.50 },
  ];

  const INVENTORY_RESERVE_RATES = [
    { key: "under_90",   label: "Under 90 days",  rate: 0.00 },
    { key: "days_180",   label: "91–180 days",    rate: 0.10 },
    { key: "days_365",   label: "181–365 days",   rate: 0.25 },
    { key: "over_365",   label: "Over 1 year",    rate: 0.50 },
    { key: "over_2yr",   label: "Over 2 years",   rate: 1.00 },
  ];

  const INFLATION_FACTORS = [
    { key: "labor",     rate: 0.042, label: "Labor cost inflation",     match: /payroll|wages|salar|compensation|benefits|\blabor\b/i },
    { key: "materials", rate: 0.031, label: "Materials cost inflation", match: /materials|supplies|freight|packaging|cost of goods|\bcogs\b/i },
    { key: "occupancy", rate: 0.028, label: "Rent / occupancy",         match: /\brent\b|lease|occupancy|facilit/i },
    { key: "utilities", rate: 0.055, label: "Utilities inflation",      match: /utilit|electric|\bgas\b|water|internet|telecom|\bphone\b/i },
  ];

  const TARIFF_SCENARIOS = [
    { label: "Base case (current rates)",   addl: 0.00 },
    { label: "Moderate increase (+10%)",    addl: 0.10 },
    { label: "Significant increase (+25%)", addl: 0.25 },
    { label: "Severe increase (+50%)",      addl: 0.50 },
  ];

  const RATE_SCENARIOS = [0.25, 0.50, 1.00, 2.00]; // ppt increases

  const LIABILITY_QUESTIONS = [
    { id: "legal_claims",   category: "Legal",               riskLevel: "high",
      question: "Are you aware of any pending or threatened legal claims, disputes, or lawsuits against the business — even informal ones not yet filed?",
      followUp: "Can you estimate the potential exposure? Even a rough range helps." },
    { id: "warranties",     category: "Warranties & Returns", riskLevel: "medium",
      question: "Does your business offer warranties, guarantees, or return policies? Do you have any known warranty claims outstanding?",
      followUp: "What is your historical warranty claim rate as a % of revenue?" },
    { id: "tax_exposure",   category: "Tax",                  riskLevel: "high",
      question: "Have there been any tax audits, notices, or unresolved tax positions in the last 3 years?",
      followUp: "Do you have nexus in any states where you may not have filed sales tax?" },
    { id: "contracts",      category: "Contracts",            riskLevel: "medium",
      question: "Are there any customer or vendor contracts with penalty clauses, minimum commitments, or termination fees you may not meet?",
      followUp: "What is the total potential exposure from these contracts?" },
    { id: "insurance",      category: "Insurance",            riskLevel: "medium",
      question: "Are there any outstanding or anticipated insurance claims? Any known gaps in coverage for your business risks?",
      followUp: "When did you last review your policy limits?" },
    { id: "environmental",  category: "Environmental",        riskLevel: "high",
      question: "For businesses with physical locations or manufacturing: are there any environmental compliance issues or cleanup obligations?",
      followUp: "Have you received any notices from regulatory bodies?" },
    { id: "employee_claims",category: "Employment",           riskLevel: "high",
      question: "Are there any current or potential employment disputes, discrimination claims, or unpaid wage issues?",
      followUp: "Any employees on performance plans that may lead to termination costs?" },
    { id: "related_party",  category: "Related Party",        riskLevel: "medium",
      question: "Are there any loans, guarantees, or financial obligations between the business and its owners, family members, or related entities not fully documented on the books?",
      followUp: "What are the terms and when are they due?" },
  ];

  // ── small utilities ─────────────────────────────────────────────────────────
  const N = (v) => { const n = Number(v); return isFinite(n) ? n : 0; };
  const pctRate = (r) => (r * 100).toFixed(r * 100 % 1 === 0 ? 0 : 1) + "%";
  const bps = (frac) => Math.round(frac * 10000);
  const DAY = 86400000;

  // ── Data derivation from the real GL / subledger ────────────────────────────
  // Every figure here traces to props.data (pl/plHistory/txns) or the ar_invoices
  // subledger. When a feed is absent the value is null → the UI renders "—".
  function useAccrualData(props, arRows) {
    const { data } = props;
    return useMemo(() => {
      const plH = (data && (data.plHistory || data.pl)) || {};
      const rev = plH.revenue || [];
      const cogs = plH.cogs || [];
      const opex = plH.opex || [];
      const txns = (data && data.txns) || [];
      const sumLast12 = (arr) => (arr || []).slice(-12).reduce((s, v) => s + N(v), 0);
      const rev12 = sumLast12(rev);
      const cogs12 = sumLast12(cogs);
      const opex12 = sumLast12(opex);

      // Trailing-12 expense by inflation category, from real GL transactions.
      const now = new Date();
      const cutoff = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate()).getTime();
      const catExpense = {};
      INFLATION_FACTORS.forEach((f) => { catExpense[f.key] = 0; });
      let payroll12 = 0, hasPayrollTx = false;
      txns.forEach((t) => {
        const dt = t.posted_date ? new Date(t.posted_date).getTime() : null;
        if (dt == null || dt < cutoff) return;
        const name = String(t.account_name || t.canonical_category || "");
        const amt = Math.abs(N(t.amount));
        INFLATION_FACTORS.forEach((f) => { if (f.match.test(name)) catExpense[f.key] += amt; });
        if (/payroll|wages|salar|compensation/i.test(name)) { payroll12 += amt; hasPayrollTx = true; }
      });

      // Cumulative GL balance for a matched account set (WC-page approach:
      // running sum of amount over matching accounts). Absolute value shown;
      // returns null when no account matches, so the UI degrades to "—".
      const glBalance = (re) => {
        let bal = 0, matched = 0;
        txns.forEach((t) => {
          const name = String(t.account_name || t.canonical_category || "");
          if (re.test(name)) { bal += N(t.amount); matched += 1; }
        });
        return matched ? { value: Math.abs(bal), accounts: matched } : null;
      };
      const allowance = glBalance(/allowance|doubtful|bad debt/i);
      const deferredRev = glBalance(/deferred revenue|unearned revenue|deferred_revenue|customer deposit/i);
      const accruedWages = glBalance(/accrued (payroll|wages|compensation)/i);
      const variableDebt = glBalance(/line of credit|revolv|term loan|note payable|long.?term debt|\bLOC\b/i);

      // Payroll accrual — indicative estimate. Days since last month-end ×
      // (trailing monthly payroll / 30). Labelled as an estimate in the UI.
      const monthlyPayroll = hasPayrollTx ? payroll12 / 12 : null;
      const lastMonthEnd = new Date(now.getFullYear(), now.getMonth(), 0);
      const daysSince = Math.max(0, Math.floor((now.getTime() - lastMonthEnd.getTime()) / DAY));
      const dailyPayroll = monthlyPayroll != null ? monthlyPayroll / 30 : null;
      const payrollAccrual = dailyPayroll != null ? daysSince * dailyPayroll : null;

      return {
        rev12, cogs12, opex12,
        catExpense, hasCat: INFLATION_FACTORS.reduce((o, f) => (o[f.key] = catExpense[f.key] > 0, o), {}),
        allowance, deferredRev, accruedWages, variableDebt,
        monthlyPayroll, daysSince, dailyPayroll, payrollAccrual,
      };
    }, [data, arRows]);
  }

  // Age the ar_invoices subledger into the six spec buckets by days past due.
  function ageAR(rows) {
    if (!rows) return null;                 // still loading
    if (!rows.length) return { buckets: {}, total: 0, empty: true };
    const now = Date.now();
    const buckets = { current: 0, days_30: 0, days_60: 0, days_90: 0, days_120: 0, over_120: 0 };
    let total = 0;
    rows.forEach((it) => {
      const bal = N(it.balance);
      if (!(bal > 0)) return;
      const due = it.due_date ? new Date(it.due_date).getTime() : now;
      const dpd = Math.floor((now - due) / DAY);
      const k = dpd <= 0 ? "current" : dpd <= 30 ? "days_30" : dpd <= 60 ? "days_60"
              : dpd <= 90 ? "days_90" : dpd <= 120 ? "days_120" : "over_120";
      buckets[k] += bal; total += bal;
    });
    return { buckets, total, empty: false };
  }

  // ── shared render helpers ───────────────────────────────────────────────────
  const K = () => window.PerduraPageKit;
  const money = (v, compact) => {
    const k = K(); return v == null ? "—" : k.moneyStr(v, compact ? { compact: true } : undefined);
  };
  const COL = { ink: "#0F1520", mute: "#4B5563", pos: "#059669", neg: "#DC2626", warn: "#D97706", line: "#E4E8F0" };
  const MONO = "'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace";

  function Disclaimer(text) {
    return h("div", { style: { marginTop: 20, padding: "10px 14px", background: "rgba(217,119,6,.06)", border: "1px solid rgba(217,119,6,.2)", borderRadius: 8, fontSize: 11.5, color: COL.mute, lineHeight: 1.5 } },
      "⚠️ " + (text || "For planning purposes only — confirm with your accountant before booking journal entries."));
  }

  function Th(label, align) {
    return h("th", { style: { padding: "8px 12px", textAlign: align || "left", fontSize: 10, letterSpacing: ".07em", textTransform: "uppercase", color: COL.mute, fontWeight: 700, borderBottom: "2px solid " + COL.line, whiteSpace: "nowrap" } }, label);
  }
  function Td(content, o) {
    o = o || {};
    return h("td", { style: { padding: "8px 12px", textAlign: o.align || "left", color: o.color || COL.ink, fontWeight: o.bold ? 700 : 500, fontFamily: o.mono === false ? "inherit" : MONO, borderBottom: o.last ? "none" : "1px solid " + COL.line, borderTop: o.total ? "2px solid " + COL.line : undefined, whiteSpace: o.wrap ? "normal" : "nowrap", fontSize: o.wrap ? 12 : undefined } }, content);
  }
  function Table(head, rows) {
    return h("div", { style: { overflowX: "auto" } },
      h("table", { style: { width: "100%", borderCollapse: "collapse", fontSize: 12.5 } },
        h("thead", null, h("tr", null, head.map((c, i) => h(R.Fragment, { key: i }, Th(c.label, c.align))))),
        h("tbody", null, rows)));
  }

  // ════════════════════════════════════════════════════════════════════════════
  // TAB 1 — COMPUTED ACCRUALS
  // ════════════════════════════════════════════════════════════════════════════
  function ComputedAccruals({ ad, arAging, isProductBusiness, computed }) {
    const k = K();

    // AR bad-debt reserve rows from the real aging split.
    const arReady = arAging && !arAging.empty;
    const arRows = AR_RESERVE_RATES.map((b, i) => {
      const bal = arReady ? N(arAging.buckets[b.key]) : null;
      const accrual = bal != null ? bal * b.rate : null;
      return h("tr", { key: b.key },
        Td(b.label, { mono: false }),
        Td(money(bal), { align: "right" }),
        Td(pctRate(b.rate), { align: "right", color: COL.mute }),
        Td(money(accrual), { align: "right", color: accrual ? COL.ink : COL.mute }));
    });
    const arTotalBal = arReady ? arAging.total : null;
    const arReserve = computed.arReserve;
    arRows.push(h("tr", { key: "tot" },
      Td("Total AR", { bold: true, total: true, mono: false }),
      Td(money(arTotalBal), { align: "right", bold: true, total: true }),
      Td("", { total: true }),
      Td(money(arReserve), { align: "right", bold: true, total: true, color: COL.warn })));

    // ── Accruals summary ──
    const summary = computed.summary;
    const summaryRows = summary.map((r, i) => h("tr", { key: i },
      Td(r.item, { mono: false, wrap: true }),
      Td(money(r.recommended), { align: "right" }),
      Td(money(r.onBooks), { align: "right", color: COL.mute }),
      Td(r.gap == null ? "—" : money(r.gap), { align: "right", color: r.gap ? COL.neg : COL.mute, bold: !!r.gap }),
      Td(r.action, { align: "left", mono: false, color: r.actionColor, wrap: true })));
    summaryRows.push(h("tr", { key: "gaptot" },
      Td("Total accrual gap", { bold: true, total: true, mono: false }),
      Td("", { total: true }), Td("", { total: true }),
      Td(money(computed.totalGap), { align: "right", bold: true, total: true, color: COL.neg }),
      Td("Review with accountant", { total: true, mono: false, color: COL.mute, wrap: true })));

    return h("div", null,
      // ── KPI strip ──
      h("div", { className: "pa-kpi-row", style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", gap: 14, marginBottom: 22 } },
        h(k.Kpi, { label: "Recommended reserves", value: money(computed.totalRecommended, true), sub: "AR + payroll + deferred", accent: "#1C4ED8" }),
        h(k.Kpi, { label: "Currently on books", value: money(computed.totalOnBooks, true), sub: "from matched GL accounts", accent: "#059669" }),
        h(k.Kpi, { label: "Total accrual gap", value: money(computed.totalGap, true), sub: "under-reserved amount", accent: computed.totalGap > 0 ? "#DC2626" : "#059669", valueColor: computed.totalGap > 0 ? "red" : "green" }),
        h(k.Kpi, { label: "Items to review", value: String(computed.reviewCount), sub: "flagged below", accent: "#D97706" })),

      // ── AR bad-debt reserve ──
      h(k.Card, { title: "AR bad-debt reserve", sub: arReady ? "Aged from the live ar_invoices subledger · standard industry reserve rates" : "Awaiting AR subledger" },
        arReady ? h("div", null,
          Table([{ label: "Aging bucket" }, { label: "Balance", align: "right" }, { label: "Reserve rate", align: "right" }, { label: "Accrual", align: "right" }], arRows),
          h("div", { style: { display: "flex", gap: 28, flexWrap: "wrap", marginTop: 14, fontSize: 12.5 } },
            h("div", null, h("span", { style: { color: COL.mute } }, "Currently on books: "), h("b", { style: { fontFamily: MONO } }, money(ad.allowance ? ad.allowance.value : null)), ad.allowance ? h("span", { style: { color: COL.mute, fontSize: 11 } }, " · " + ad.allowance.accounts + " GL acct(s)") : h("span", { style: { color: COL.mute, fontSize: 11 } }, " · no allowance account found")),
            h("div", null, h("span", { style: { color: COL.mute } }, "Gap to accrue: "), h("b", { style: { fontFamily: MONO, color: computed.arGap > 0 ? COL.neg : COL.pos } }, money(computed.arGap))))
        ) : h("div", { style: { padding: 20, textAlign: "center", color: COL.mute, fontSize: 13 } },
          "No open receivables in the subledger yet. Once invoices are ingested, the reserve is aged and computed automatically.")),

      // ── Inventory obsolescence (honestly gated) ──
      isProductBusiness ? h(k.Card, { title: "Inventory obsolescence reserve", sub: "Standard reserve schedule by on-hand age" },
        h("div", null,
          Table([{ label: "On-hand age" }, { label: "Balance", align: "right" }, { label: "Reserve rate", align: "right" }, { label: "Accrual", align: "right" }],
            INVENTORY_RESERVE_RATES.map((b) => h("tr", { key: b.key },
              Td(b.label, { mono: false }), Td("—", { align: "right", color: COL.mute }),
              Td(pctRate(b.rate), { align: "right", color: COL.mute }), Td("—", { align: "right", color: COL.mute })))),
          h("div", { style: { marginTop: 12, padding: "10px 14px", background: "rgba(75,85,99,.06)", borderRadius: 8, fontSize: 12, color: COL.mute, lineHeight: 1.5 } },
            "No on-hand inventory aging feed is connected, so an obsolescence reserve cannot be computed from real data. Connect an inventory system (on-hand quantity × age by SKU) to populate this table. We won't estimate it from sales data alone."))) : null,

      // ── Payroll accrual ──
      h(k.Card, { title: "Payroll accrual", sub: "Indicative estimate — days since last month-end × daily payroll" },
        ad.payrollAccrual != null ? h("div", { style: { display: "flex", gap: 28, flexWrap: "wrap", fontSize: 12.5 } },
          h("div", null, h("div", { style: { color: COL.mute, fontSize: 11 } }, "Trailing monthly payroll (GL)"), h("b", { style: { fontFamily: MONO } }, money(ad.monthlyPayroll))),
          h("div", null, h("div", { style: { color: COL.mute, fontSize: 11 } }, "Daily payroll ÷ 30"), h("b", { style: { fontFamily: MONO } }, money(ad.dailyPayroll))),
          h("div", null, h("div", { style: { color: COL.mute, fontSize: 11 } }, "Days since last month-end"), h("b", { style: { fontFamily: MONO } }, ad.daysSince)),
          h("div", null, h("div", { style: { color: COL.mute, fontSize: 11 } }, "Estimated accrual"), h("b", { style: { fontFamily: MONO, color: COL.warn } }, money(ad.payrollAccrual)))
        ) : h("div", { style: { padding: 16, color: COL.mute, fontSize: 13 } },
          "No payroll/wages transactions detected in the GL — payroll accrual cannot be estimated.")),

      // ── Deferred revenue ──
      h(k.Card, { title: "Deferred revenue", sub: "Credit balances in deferred / unearned revenue accounts" },
        ad.deferredRev ? h("div", { style: { fontSize: 12.5 } },
          h("span", { style: { color: COL.mute } }, "Recorded deferred revenue (GL): "),
          h("b", { style: { fontFamily: MONO } }, money(ad.deferredRev.value)),
          h("span", { style: { color: COL.mute, fontSize: 11 } }, " · " + ad.deferredRev.accounts + " matched account(s) · already a booked liability")
        ) : h("div", { style: { padding: 16, color: COL.mute, fontSize: 13 } },
          "No deferred / unearned revenue accounts found in the GL. If you collect payment before delivering, book these as a liability.")),

      // ── Summary ──
      h(k.Card, { title: "Accruals summary", sub: "Recommended vs. on books — where you may be under-reserved" },
        Table([{ label: "Accrual item" }, { label: "Recommended", align: "right" }, { label: "On books", align: "right" }, { label: "Gap", align: "right" }, { label: "Action" }], summaryRows)),

      Disclaimer("These are indicative accruals based on aging data and standard industry rates. Confirm with your accountant before booking journal entries."));
  }

  // ════════════════════════════════════════════════════════════════════════════
  // TAB 2 — UNDISCLOSED LIABILITIES (guided questionnaire)
  // ════════════════════════════════════════════════════════════════════════════
  function LiabilityBot({ companyId, onRegister }) {
    const k = K();
    const storageKey = "perdura_liability_assessment_" + (companyId || "anon");
    const [answers, setAnswers] = useState({});
    const [idx, setIdx] = useState(0);
    const [done, setDone] = useState(false);

    useEffect(() => {
      try {
        const raw = window.localStorage.getItem(storageKey);
        if (raw) { const p = JSON.parse(raw); setAnswers(p.answers || {}); if (p.completed) setDone(true); }
      } catch (_e) { /* ignore */ }
    }, [storageKey]);

    const persist = (nextAnswers, completed) => {
      try { window.localStorage.setItem(storageKey, JSON.stringify({ answers: nextAnswers, completed: !!completed, savedAt: new Date().toISOString() })); } catch (_e) { /* ignore */ }
    };

    const q = LIABILITY_QUESTIONS[idx];
    const cur = answers[q.id] || { choice: null, note: "", exposure: "" };
    const setCur = (patch) => {
      const next = Object.assign({}, answers, { [q.id]: Object.assign({}, cur, patch) });
      setAnswers(next); persist(next, done);
    };

    const buildRegister = (ans) => {
      const rows = [];
      LIABILITY_QUESTIONS.forEach((qq) => {
        const a = ans[qq.id];
        if (!a || a.choice === "no" || a.choice == null) return;
        rows.push({
          category: qq.category,
          item: (a.note && a.note.trim()) ? a.note.trim() : qq.question.split("—")[0].slice(0, 60) + "…",
          status: a.choice === "yes" ? "Likely" : "Possible",
          exposure: a.exposure && N(a.exposure) > 0 ? N(a.exposure) : null,
          riskLevel: qq.riskLevel,
        });
      });
      return rows;
    };

    const finish = () => { setDone(true); persist(answers, true); onRegister(buildRegister(answers)); };
    // Keep parent register in sync once completed / on load.
    useEffect(() => { if (done) onRegister(buildRegister(answers)); }, [done, answers]);

    if (done) {
      const register = buildRegister(answers);
      const knownExposure = register.reduce((s, r) => s + (r.exposure || 0), 0);
      const hasUnknown = register.some((r) => r.exposure == null);
      const badge = (rl) => h("span", { style: { fontSize: 10, fontWeight: 700, padding: "1px 6px", borderRadius: 4, textTransform: "uppercase", color: rl === "high" ? COL.neg : COL.warn, background: rl === "high" ? "rgba(220,38,38,.1)" : "rgba(217,119,6,.1)" } }, rl);
      return h(k.Card, { title: "Undisclosed liability register", sub: register.length + " item(s) flagged from your responses" },
        register.length ? h("div", null,
          Table([{ label: "Category" }, { label: "Item" }, { label: "Status" }, { label: "Est. exposure", align: "right" }, { label: "Risk" }],
            register.map((r, i) => h("tr", { key: i },
              Td(r.category, { mono: false }),
              Td(r.item, { mono: false, wrap: true }),
              Td(r.status, { mono: false, color: r.status === "Likely" ? COL.neg : COL.warn }),
              Td(r.exposure != null ? money(r.exposure) : "Unknown", { align: "right", color: r.exposure != null ? COL.ink : COL.mute }),
              Td(badge(r.riskLevel), { mono: false })))
            .concat([h("tr", { key: "tot" },
              Td("Total identified exposure", { bold: true, total: true, mono: false }),
              Td("", { total: true }), Td("", { total: true }),
              Td(money(knownExposure) + (hasUnknown ? "+" : ""), { align: "right", bold: true, total: true, color: COL.neg }),
              Td(hasUnknown ? "excl. unknowns" : "", { total: true, mono: false, color: COL.mute }))])),
          h("div", { style: { marginTop: 14, display: "flex", gap: 10 } },
            h("button", { className: "pc-btn-secondary", style: btnStyle(false), onClick: () => { setDone(false); setIdx(0); } }, "↻ Re-run assessment"))
        ) : h("div", null,
          h("div", { style: { padding: 20, textAlign: "center", color: COL.pos, fontSize: 13 } }, "✅ No undisclosed liabilities flagged. Re-run any time as circumstances change."),
          h("button", { style: btnStyle(false), onClick: () => { setDone(false); setIdx(0); } }, "↻ Re-run assessment")),
        Disclaimer("Discuss all items with your attorney and accountant before disclosure. This register is confidential and for internal planning only."));
    }

    // Question card
    return h(k.Card, { title: null },
      h("div", { style: { display: "flex", alignItems: "center", gap: 10, marginBottom: 6 } },
        h("span", { style: { fontSize: 20 } }, "🤖"),
        h("div", { style: { fontSize: 14, fontWeight: 700, color: COL.ink } }, "CFO liability assessment")),
      h("div", { style: { fontSize: 12, color: COL.mute, marginBottom: 16, lineHeight: 1.5 } },
        "I'll ask a short series of questions to help surface liabilities that may not yet be on your books. This is confidential and for planning purposes."),
      h("div", { style: { height: 1, background: COL.line, margin: "0 0 16px" } }),
      h("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 } },
        h("span", { style: { fontSize: 11, fontWeight: 700, color: COL.mute, fontFamily: MONO } }, "Question " + (idx + 1) + " of " + LIABILITY_QUESTIONS.length),
        h("span", { style: { fontSize: 10, fontWeight: 700, padding: "2px 8px", borderRadius: 5, color: "#1C4ED8", background: "rgba(28,78,216,.08)", textTransform: "uppercase", letterSpacing: ".05em" } }, q.category)),
      h("div", { style: { fontSize: 14, color: COL.ink, lineHeight: 1.55, fontWeight: 600, marginBottom: 16 } }, q.question),
      h("div", { style: { display: "flex", flexDirection: "column", gap: 8, marginBottom: 14 } },
        [["no", "No — nothing pending"], ["yes", "Yes — I'll describe below"], ["possibly", "Possibly — uncertain"]].map(([val, label]) =>
          h("label", { key: val, style: { display: "flex", alignItems: "center", gap: 10, padding: "10px 12px", border: "1px solid " + (cur.choice === val ? "#1C4ED8" : COL.line), background: cur.choice === val ? "rgba(28,78,216,.05)" : "transparent", borderRadius: 8, cursor: "pointer", fontSize: 13, color: COL.ink } },
            h("input", { type: "radio", name: "q_" + q.id, checked: cur.choice === val, onChange: () => setCur({ choice: val }) }), label))),
      (cur.choice === "yes" || cur.choice === "possibly") ? h("div", { style: { marginBottom: 14 } },
        h("div", { style: { fontSize: 12, color: COL.mute, marginBottom: 6 } }, q.followUp),
        h("textarea", { value: cur.note, onChange: (e) => setCur({ note: e.target.value }), placeholder: "Describe the situation…", style: { width: "100%", minHeight: 70, padding: "8px 10px", border: "1px solid " + COL.line, borderRadius: 8, fontSize: 13, fontFamily: "inherit", resize: "vertical", boxSizing: "border-box" } }),
        h("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 10 } },
          h("span", { style: { fontSize: 12, color: COL.mute } }, "Estimated exposure ($, optional):"),
          h("input", { type: "number", value: cur.exposure, onChange: (e) => setCur({ exposure: e.target.value }), placeholder: "0", style: { width: 140, padding: "6px 10px", border: "1px solid " + COL.line, borderRadius: 8, fontSize: 13, fontFamily: MONO } }))) : null,
      h("div", { style: { display: "flex", justifyContent: "space-between", marginTop: 8 } },
        h("button", { style: btnStyle(false, idx === 0), disabled: idx === 0, onClick: () => setIdx(Math.max(0, idx - 1)) }, "← Back"),
        idx < LIABILITY_QUESTIONS.length - 1
          ? h("button", { style: btnStyle(true, !cur.choice), disabled: !cur.choice, onClick: () => setIdx(idx + 1) }, "Next question →")
          : h("button", { style: btnStyle(true, !cur.choice), disabled: !cur.choice, onClick: finish }, "Finish & build register →")),
      Disclaimer("Confidential — for internal planning only. Discuss with your attorney and accountant before any disclosure."));
  }

  function btnStyle(primary, disabled) {
    return {
      padding: "9px 16px", borderRadius: 8, fontSize: 12.5, fontWeight: 600, cursor: disabled ? "not-allowed" : "pointer",
      border: primary ? "none" : "1px solid " + COL.line,
      background: disabled ? "rgba(75,85,99,.15)" : primary ? "#1C4ED8" : "#fff",
      color: disabled ? COL.mute : primary ? "#fff" : COL.ink, opacity: disabled ? 0.7 : 1,
    };
  }

  // ════════════════════════════════════════════════════════════════════════════
  // TAB 3 — MACRO INTELLIGENCE
  // ════════════════════════════════════════════════════════════════════════════
  function MacroIntelligence({ ad, companyId, isProductBusiness, tariff, setTariff, computed }) {
    const k = K();

    // ── Tariff scenarios (only if inputs provided) ──
    const importPct = N(tariff.importPct);
    const tariffReady = isProductBusiness && importPct > 0 && ad.cogs12 > 0 && ad.rev12 > 0;
    const importedCOGS = ad.cogs12 * (importPct / 100);
    const tariffRows = TARIFF_SCENARIOS.map((s) => {
      const addlCost = importedCOGS * s.addl;
      const marginImpact = ad.rev12 > 0 ? addlCost / ad.rev12 : 0;
      const priceInc = ad.rev12 > 0 ? addlCost / (ad.rev12 * 0.8) : 0;
      return h("tr", { key: s.label },
        Td(s.label, { mono: false }),
        Td(s.addl === 0 ? "—" : money(addlCost) + "/yr", { align: "right" }),
        Td(s.addl === 0 ? "—" : "-" + bps(marginImpact) + "bps", { align: "right", color: s.addl === 0 ? COL.mute : COL.neg }),
        Td(s.addl === 0 ? "—" : "+" + (priceInc * 100).toFixed(1) + "%", { align: "right", color: s.addl === 0 ? COL.mute : COL.warn }));
    });

    // ── Inflation impact ──
    const infRows = INFLATION_FACTORS.map((f) => {
      const amt = ad.catExpense[f.key];
      const has = amt > 0;
      const impact = has ? amt * f.rate : null;
      return h("tr", { key: f.key },
        Td(f.label, { mono: false }),
        Td(money(has ? amt : null), { align: "right" }),
        Td(pctRate(f.rate), { align: "right", color: COL.mute }),
        Td(money(impact), { align: "right", color: has ? COL.neg : COL.mute }));
    });
    const infTotal = computed.inflationTotal;
    infRows.push(h("tr", { key: "tot" },
      Td("Total inflation headwind", { bold: true, total: true, mono: false }),
      Td("", { total: true }),
      Td(ad.rev12 > 0 ? (infTotal / ad.rev12 * 100).toFixed(1) + "% of rev" : "—", { align: "right", total: true, color: COL.mute }),
      Td(money(infTotal), { align: "right", bold: true, total: true, color: COL.neg })));

    // ── Interest-rate sensitivity (only if variable debt detected) ──
    const vdebt = ad.variableDebt ? ad.variableDebt.value : 0;
    const rateRows = RATE_SCENARIOS.map((r) => {
      const annualCost = vdebt * (r / 100);
      const ebImpact = ad.rev12 > 0 ? annualCost / ad.rev12 : 0;
      return h("tr", { key: r },
        Td("+" + r.toFixed(2) + " ppt", { mono: false }),
        Td(money(annualCost) + "/yr", { align: "right", color: COL.neg }),
        Td("-" + bps(ebImpact) + "bps", { align: "right", color: COL.mute }));
    });

    const set = (patch) => setTariff(Object.assign({}, tariff, patch));

    return h("div", null,
      // ── Tariff ──
      isProductBusiness ? h(k.Card, { title: "🌍 Import tariff analysis", sub: "We detected a product-based business — tariff exposure drives margin planning" },
        h("div", null,
          h("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(180px,1fr))", gap: 12, marginBottom: 16 } },
            h("label", { style: fieldStyle() }, h("span", { style: fieldLabel() }, "Primary sourcing country"),
              h("select", { value: tariff.country, onChange: (e) => set({ country: e.target.value }), style: inputStyle() },
                ["China", "Mexico", "Vietnam", "Canada", "EU", "Other", "Not sure"].map((c) => h("option", { key: c, value: c }, c)))),
            h("label", { style: fieldStyle() }, h("span", { style: fieldLabel() }, "% of COGS from imports"),
              h("input", { type: "number", value: tariff.importPct, onChange: (e) => set({ importPct: e.target.value }), placeholder: "e.g. 40", style: inputStyle() })),
            h("label", { style: fieldStyle() }, h("span", { style: fieldLabel() }, "Current tariff rate applied (%)"),
              h("input", { type: "number", value: tariff.currentTariffRate, onChange: (e) => set({ currentTariffRate: e.target.value }), placeholder: "Unknown", style: inputStyle() })),
            h("label", { style: fieldStyle() }, h("span", { style: fieldLabel() }, "Accrued for tariff increases?"),
              h("select", { value: tariff.accrued, onChange: (e) => set({ accrued: e.target.value }), style: inputStyle() },
                ["No", "Yes"].map((c) => h("option", { key: c, value: c }, c))))),
          tariffReady ? h("div", null,
            h("div", { style: { fontSize: 11.5, color: COL.mute, marginBottom: 8 } }, "Imported COGS base: " + money(importedCOGS) + "/yr (" + importPct + "% of " + money(ad.cogs12) + " trailing COGS)"),
            Table([{ label: "Scenario" }, { label: "Additional cost", align: "right" }, { label: "Margin impact", align: "right" }, { label: "Price increase needed", align: "right" }], tariffRows),
            h("div", { style: { marginTop: 12, padding: "12px 14px", background: "rgba(28,78,216,.05)", borderRadius: 8, fontSize: 12.5, color: COL.ink, lineHeight: 1.5 } },
              "💡 CFO recommendation: at your current import mix, a 25% tariff increase would add ~" + money(importedCOGS * 0.25) + "/yr (≈" + bps(importedCOGS * 0.25 / ad.rev12) + "bps of margin). Consider (1) supplier diversification, (2) a pricing review, and (3) forward-purchasing key SKUs to hedge."))
          : h("div", { style: { padding: 14, color: COL.mute, fontSize: 13 } }, "Enter your import % of COGS above to run the tariff scenario analysis against your real trailing COGS and revenue."))) : null,

      // ── Inflation ──
      h(k.Card, { title: "Inflation impact on your cost structure", sub: "Applied to real trailing-12-month spend by category" },
        Table([{ label: "Cost category" }, { label: "Current annual", align: "right" }, { label: "Inflation rate", align: "right" }, { label: "Annual impact", align: "right" }], infRows),
        infTotal > 0 ? h("div", { style: { marginTop: 12, fontSize: 12.5, color: COL.mute, lineHeight: 1.5 } },
          "Without pricing action, inflation alone compresses EBITDA margin by approximately " + (ad.rev12 > 0 ? bps(infTotal / ad.rev12) : 0) + "bps over the next 12 months.") : null),

      // ── Interest-rate sensitivity ──
      vdebt > 0 ? h(k.Card, { title: "Interest-rate sensitivity", sub: "On detected variable-rate debt: " + money(vdebt) + " (" + ad.variableDebt.accounts + " account(s))" },
        Table([{ label: "Rate increase" }, { label: "Added annual interest", align: "right" }, { label: "EBITDA impact", align: "right" }], rateRows))
        : h(k.Card, { title: "Interest-rate sensitivity", sub: "No variable-rate debt detected" },
          h("div", { style: { padding: 14, color: COL.mute, fontSize: 13 } }, "No line-of-credit or variable-rate term debt found in the GL. If you carry floating-rate debt, map those accounts to see rate sensitivity here.")),

      // ── Deterministic macro synthesis + AI commentary ──
      h(k.CFOCommentaryPanel, {
        title: "Macro risk",
        insights: computed.macroInsights,
        savings: computed.macroSavings,
      }),
      window.PageCommentary ? h(window.PageCommentary, { tenantId: companyId, pageType: "accruals" }) : null,

      Disclaimer("Macro rates are configurable planning defaults. Confirm assumptions and exposures with your accountant."));
  }

  function fieldStyle() { return { display: "flex", flexDirection: "column", gap: 4 }; }
  function fieldLabel() { return { fontSize: 10.5, fontWeight: 700, letterSpacing: ".04em", textTransform: "uppercase", color: COL.mute }; }
  function inputStyle() { return { padding: "8px 10px", border: "1px solid " + COL.line, borderRadius: 8, fontSize: 13, fontFamily: "inherit", background: "#fff", color: COL.ink }; }

  // ════════════════════════════════════════════════════════════════════════════
  // TAB 4 — ACTION PLAN
  // ════════════════════════════════════════════════════════════════════════════
  function ActionPlan({ computed, register, companyId, fullPayload }) {
    const k = K();
    const items = computed.actionItems.concat(
      (register || []).map((r) => ({
        priority: r.riskLevel === "high" ? "high" : "medium",
        item: r.category + " — " + r.item,
        amount: r.exposure != null ? money(r.exposure) : "Unknown",
        action: r.status === "Likely" ? "Engage advisor" : "Monitor / assess",
      })));
    const rank = { high: 0, medium: 1, low: 2 };
    items.sort((a, b) => rank[a.priority] - rank[b.priority]);
    const pill = (p) => h("span", { style: { fontSize: 11, fontWeight: 700 } }, p === "high" ? "🔴 HIGH" : p === "medium" ? "🟡 MEDIUM" : "🟢 LOW");

    const rows = items.map((it, i) => h("tr", { key: i },
      Td(pill(it.priority), { mono: false }),
      Td(it.item, { mono: false, wrap: true }),
      Td(it.amount, { align: "right", color: COL.ink }),
      Td(it.action, { mono: false, color: COL.mute, wrap: true })));

    const exportPlan = () => {
      try {
        const blob = new Blob([JSON.stringify(fullPayload, null, 2)], { type: "application/json" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url; a.download = "accruals-risk-action-plan-" + (companyId || "export") + ".json";
        document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url);
      } catch (_e) { window.print(); }
    };

    const lo = computed.totalGap, hi = computed.totalGap + computed.exposureHi;
    return h("div", null,
      h(k.Card, { title: "Accruals & risk action plan", sub: items.length + " prioritized item(s) — computed gaps + liability register + macro" },
        rows.length ? Table([{ label: "Priority" }, { label: "Item" }, { label: "Est. amount", align: "right" }, { label: "Action required" }], rows)
          : h("div", { style: { padding: 20, textAlign: "center", color: COL.pos, fontSize: 13 } }, "✅ No open accrual gaps or flagged liabilities. Nothing to action right now."),
        h("div", { style: { marginTop: 16, padding: "12px 14px", background: "rgba(220,38,38,.05)", borderRadius: 8, fontSize: 13, fontWeight: 600, color: COL.ink } },
          "Total identified exposure: " + money(lo) + (computed.exposureHi > 0 ? " – " + money(hi) : "")),
        h("div", { style: { display: "flex", gap: 10, marginTop: 16 } },
          h("button", { style: btnStyle(true), onClick: exportPlan }, "⬇ Export action plan"),
          h("button", { style: btnStyle(false), onClick: () => window.print() }, "🖨 Print / schedule review"))),
      Disclaimer("This analysis is for internal planning purposes only. All accruals and disclosures should be reviewed with your accountant and legal counsel before being recorded or disclosed."));
  }

  // ════════════════════════════════════════════════════════════════════════════
  // PAGE SHELL
  // ════════════════════════════════════════════════════════════════════════════
  function Page(props) {
    const k = window.PerduraPageKit;
    if (!k) return h("div", { className: "pc-page" }, "Loading…");
    const { data } = props;
    const companyProfile = props.companyProfile || (data && data.companyProfile) || {};
    const companyId = props.scopedCompanyId || companyProfile.id || (data && data.companyProfile && data.companyProfile.id) || null;

    const profileT = String(companyProfile.industry || companyProfile.business_type || props.bizType || "").toLowerCase();
    const isProductBusiness = !!companyProfile.holds_inventory ||
      ["retail", "distribution", "manufacturing", "ecommerce", "wholesale", "product"].includes(profileT);

    const [tab, setTab] = useState("computed");
    const [arRows, setArRows] = useState(null);
    const [register, setRegister] = useState([]);
    const [tariff, setTariffState] = useState({ country: "China", importPct: "", currentTariffRate: "", accrued: "No" });

    // Persisted macro/tariff inputs + full analysis snapshot.
    const accKey = "perdura_accruals_" + (companyId || "anon");
    useEffect(() => {
      try { const raw = window.localStorage.getItem(accKey); if (raw) { const p = JSON.parse(raw); if (p.tariff) setTariffState(p.tariff); } } catch (_e) { /* ignore */ }
    }, [accKey]);
    const setTariff = (t) => { setTariffState(t); };

    // Load the live AR subledger for aging.
    useEffect(() => {
      let cancelled = false;
      const db = window.supabaseClient;
      if (!db || !companyId) { setArRows([]); return; }
      setArRows(null);
      db.from("ar_invoices").select("due_date,customer_name,balance").eq("company_id", companyId).gt("balance", 0).limit(5000)
        .then(({ data: d }) => { if (!cancelled) setArRows(d || []); }, () => { if (!cancelled) setArRows([]); });
      return () => { cancelled = true; };
    }, [companyId]);

    const ad = useAccrualData(props, arRows);
    const arAging = useMemo(() => ageAR(arRows), [arRows]);

    // ── Derived computations shared across tabs ──
    const computed = useMemo(() => {
      const arReady = arAging && !arAging.empty;
      const arReserve = arReady ? AR_RESERVE_RATES.reduce((s, b) => s + N(arAging.buckets[b.key]) * b.rate, 0) : null;
      const onBooksAllow = ad.allowance ? ad.allowance.value : null;
      const arGap = (arReserve != null) ? Math.max(0, arReserve - (onBooksAllow || 0)) : null;

      const payrollOnBooks = ad.accruedWages ? ad.accruedWages.value : null;
      const payrollGap = ad.payrollAccrual != null ? Math.max(0, ad.payrollAccrual - (payrollOnBooks || 0)) : null;

      const deferredVal = ad.deferredRev ? ad.deferredRev.value : null;

      // Summary rows
      const summary = [
        { item: "AR bad-debt reserve", recommended: arReserve, onBooks: onBooksAllow, gap: arGap,
          action: arGap > 0 ? "⚠️ Under-reserved" : (arReserve != null ? "✅ OK" : "Awaiting subledger"),
          actionColor: arGap > 0 ? COL.warn : (arReserve != null ? COL.pos : COL.mute) },
        { item: "Inventory obsolescence", recommended: null, onBooks: null, gap: null,
          action: isProductBusiness ? "🔴 No on-hand feed" : "n/a — not product-based", actionColor: COL.mute },
        { item: "Payroll accrual", recommended: ad.payrollAccrual, onBooks: payrollOnBooks, gap: payrollGap,
          action: ad.payrollAccrual != null ? "✅ Confirm with payroll" : "No payroll data", actionColor: ad.payrollAccrual != null ? COL.pos : COL.mute },
        { item: "Deferred revenue", recommended: deferredVal, onBooks: deferredVal, gap: null,
          action: deferredVal != null ? "✅ Recorded" : "None found", actionColor: deferredVal != null ? COL.pos : COL.mute },
      ];
      const totalRecommended = (arReserve || 0) + (ad.payrollAccrual || 0) + (deferredVal || 0);
      const totalOnBooks = (onBooksAllow || 0) + (payrollOnBooks || 0) + (deferredVal || 0);
      const totalGap = (arGap || 0) + (payrollGap || 0);
      const reviewCount = summary.filter((r) => r.gap > 0 || (isProductBusiness && r.item.indexOf("Inventory") === 0)).length;

      // Inflation
      const inflationTotal = INFLATION_FACTORS.reduce((s, f) => s + (ad.catExpense[f.key] > 0 ? ad.catExpense[f.key] * f.rate : 0), 0);

      // Tariff 25% reference
      const importPct = N(tariff.importPct);
      const tariff25 = (isProductBusiness && importPct > 0) ? ad.cogs12 * (importPct / 100) * 0.25 : 0;
      const vdebt = ad.variableDebt ? ad.variableDebt.value : 0;

      // Macro insights (deterministic — always available)
      const macroInsights = [];
      if (tariff25 > 0) macroInsights.push({ type: "warning", text: "A 25% tariff increase would add <b>" + money(tariff25) + "/yr</b> to imported COGS (≈" + (ad.rev12 > 0 ? bps(tariff25 / ad.rev12) : 0) + "bps of margin).", detail: "Based on " + importPct + "% import mix of " + money(ad.cogs12) + " trailing COGS." });
      if (inflationTotal > 0) macroInsights.push({ type: "warning", text: "Cost inflation headwind of <b>" + money(inflationTotal) + "/yr</b> across labor, materials, occupancy and utilities.", detail: ad.rev12 > 0 ? "≈" + bps(inflationTotal / ad.rev12) + "bps of EBITDA margin without pricing action." : null });
      if (vdebt > 0) macroInsights.push({ type: "warning", text: "A +1.00 ppt rate move adds <b>" + money(vdebt * 0.01) + "/yr</b> in interest on " + money(vdebt) + " of variable-rate debt.", detail: null });
      if (!macroInsights.length) macroInsights.push({ type: "neutral", text: "No material macro exposure detected from current inputs and GL data.", detail: "Enter tariff inputs above and map cost accounts to sharpen this." });
      const macroSavings = tariff25 > 0
        ? "Diversifying ~30% of import volume away from the primary source could offset roughly " + money(tariff25 * 0.3) + "/yr of a 25% tariff shock."
        : (inflationTotal > 0 ? "A modest " + (ad.rev12 > 0 ? (inflationTotal / ad.rev12 * 100).toFixed(1) : "1.0") + "% price increase would fully offset the projected inflation headwind." : null);

      // Action items from computed side
      const actionItems = [];
      if (isProductBusiness) actionItems.push({ priority: "high", item: "Inventory obsolescence accrual", amount: "Requires on-hand feed", action: "Connect inventory system, then book reserve" });
      if (arGap > 0) actionItems.push({ priority: "medium", item: "AR bad-debt reserve gap", amount: money(arGap), action: "Increase allowance for doubtful accounts" });
      if (tariff25 > 0) actionItems.push({ priority: "medium", item: "Tariff scenario planning", amount: money(tariff25) + " risk", action: "Review pricing & supplier strategy" });
      if (inflationTotal > 0) actionItems.push({ priority: "low", item: "Inflation cost review", amount: money(inflationTotal) + "/yr", action: "Annual pricing review" });
      if (ad.payrollAccrual > 0) actionItems.push({ priority: "low", item: "Payroll accrual", amount: money(ad.payrollAccrual), action: "Confirm with payroll" });
      if (vdebt > 0) actionItems.push({ priority: "low", item: "Interest-rate exposure", amount: money(vdebt * 0.01) + "/yr per ppt", action: "Consider rate hedge / fixed refinancing" });

      const exposureHi = (register || []).reduce((s, r) => s + (r.exposure || 0), 0) + tariff25;

      return { arReserve, arGap, summary, totalRecommended, totalOnBooks, totalGap, reviewCount,
        inflationTotal, macroInsights, macroSavings, actionItems, exposureHi };
    }, [ad, arAging, isProductBusiness, tariff, register]);

    // Persist full analysis snapshot whenever inputs/derived change.
    useEffect(() => {
      try {
        window.localStorage.setItem(accKey, JSON.stringify({
          tariff, savedAt: new Date().toISOString(),
          computed: { totalRecommended: computed.totalRecommended, totalGap: computed.totalGap, inflationTotal: computed.inflationTotal },
          register,
        }));
      } catch (_e) { /* ignore */ }
    }, [accKey, tariff, computed, register]);

    const fullPayload = { companyId, generatedAt: new Date().toISOString(), tariff,
      accruals: computed.summary, totalGap: computed.totalGap, inflationTotal: computed.inflationTotal,
      liabilityRegister: register, actionItems: computed.actionItems };

    const TABS = [
      { key: "computed", label: "Computed Accruals" },
      { key: "liabilities", label: "Undisclosed Liabilities" },
      { key: "macro", label: "Macro Intelligence" },
      { key: "action", label: "Action Plan" },
    ];
    const tabBar = h("div", { style: { display: "flex", gap: 4, flexWrap: "wrap" } },
      TABS.map((t) => h("button", { key: t.key, onClick: () => setTab(t.key),
        style: { padding: "8px 16px", borderRadius: 8, border: "none", cursor: "pointer", fontSize: 12.5, fontWeight: 600,
          background: tab === t.key ? "#1C4ED8" : "rgba(75,85,99,.08)", color: tab === t.key ? "#fff" : COL.mute } }, t.label)));

    let body = null;
    if (tab === "computed") body = h(ComputedAccruals, { ad, arAging, isProductBusiness, computed });
    else if (tab === "liabilities") body = h(LiabilityBot, { companyId, onRegister: setRegister });
    else if (tab === "macro") body = h(MacroIntelligence, { ad, companyId, isProductBusiness, tariff, setTariff, computed });
    else body = h(ActionPlan, { computed, register, companyId, fullPayload });

    return h(k.Shell, {
      hero: {
        eyebrow: "Intelligence",
        title: "Accruals & Risk",
        subtitle: "Deterministic reserves, undisclosed-liability discovery, and macro exposure — from your real ledger",
        controls: tabBar,
      },
    }, body);
  }

  window.AccrualsPage = Page;
})();
