// TrialBalancePage — window.TrialBalancePage
//
// General-ledger trial balance: every distinct GL account aggregated from the
// transaction feed for a selected month, with debit/credit balances, a section
// grouping (ASSETS · LIABILITIES · EQUITY · REVENUE · EXPENSES), per-section
// subtotals, a grand total, and a debits-vs-credits balance check. Each row's
// category is click-to-edit and writes an account_mappings.category_override to
// Supabase. Honest fallback when no GL data is present — never fabricates
// numbers.
//
// Props: { data, companyProfile, scopedCompanyId, globalPeriod, setPage }
//
// Sign convention assumption: data.txns[].amount is signed in the platform's
// income-statement convention — revenue / credits are NEGATIVE, expenses /
// debits are POSITIVE. We aggregate each account's net signed amount, then
// present Debit = max(net, 0) and Credit = max(-net, 0) so that a positive net
// shows as a debit balance and a negative net as a credit balance. This keeps a
// section subtotal tying to the sum of its rows and the grand total of debits
// equalling credits when the underlying GL is balanced.

(function () {
  const { useState, useMemo } = React;
  const h = React.createElement;

  // ── design tokens (matched to sibling pages) ────────────────────────────────
  const C = {
    bg: "#F7F8FB", card: "#FFFFFF", border: "#E4E8F0", accent: "#1C4ED8", accentSoft: "#EEF2FF",
    text1: "#1A2233", text2: "#475569", muted: "#6B7A99",
    green: "#059669", greenSoft: "#DCFCE7", amber: "#B45309", amberSoft: "#FEF3C7",
    red: "#DC2626", redSoft: "#FEE2E2",
  };
  const CARD = { background: C.card, border: "1px solid " + C.border, boxShadow: "0 1px 4px rgba(0,0,0,0.06)", borderRadius: 10 };

  const money = (v, opts) => {
    if (v == null || !isFinite(v)) return "—";
    if (window.PerduraFormat && window.PerduraFormat.money) return window.PerduraFormat.money(v, opts);
    const n = Math.round(v);
    return (n < 0 ? "-$" : "$") + Math.abs(n).toLocaleString();
  };
  const pct = (v, d) => (v == null || !isFinite(v)) ? "—" : v.toFixed(d == null ? 1 : d) + "%";

  // ── 5-section statement model ───────────────────────────────────────────────
  // taxonomy section keys → one of the five statement sections we display.
  const SECTION_MAP = {
    current_assets: "ASSETS", non_current_assets: "ASSETS",
    current_liab: "LIABILITIES", long_term_liab: "LIABILITIES",
    equity: "EQUITY",
    revenue: "REVENUE", contra_revenue: "REVENUE", other_income: "REVENUE",
    cogs: "EXPENSES", opex: "EXPENSES", da: "EXPENSES", other_op_exp: "EXPENSES",
    interest: "EXPENSES", tax: "EXPENSES", other_expense: "EXPENSES",
  };
  const SECTION_ORDER = ["ASSETS", "LIABILITIES", "EQUITY", "REVENUE", "EXPENSES"];

  // Fallback: infer a statement section from account code ranges / category text
  // when the taxonomy can't resolve a category.
  function inferSection(code, category, name) {
    const c = String(code || "").trim();
    const cat = String(category || "").toLowerCase();
    const n = String(name || "").toLowerCase();
    if (/^1\d/.test(c)) return "ASSETS";
    if (/^2\d/.test(c)) return "LIABILITIES";
    if (/^3\d/.test(c)) return "EQUITY";
    if (/^4\d/.test(c)) return "REVENUE";
    if (/^[5-9]\d/.test(c)) return "EXPENSES";
    if (/revenue|sales|income/.test(cat) || /revenue|sales|income/.test(n)) return "REVENUE";
    if (/asset|cash|receivable|inventory|prepaid/.test(cat) || /asset|cash|receivable|inventory/.test(n)) return "ASSETS";
    if (/liab|payable|accrued|debt|loan|credit card/.test(cat) || /payable|accrued|loan|debt/.test(n)) return "LIABILITIES";
    if (/equity|retained|capital|distribution|net assets/.test(cat) || /equity|retained|capital/.test(n)) return "EQUITY";
    if (/cogs|opex|expense|depreciation|interest|tax|cost/.test(cat) || /expense|cost|payroll|rent/.test(n)) return "EXPENSES";
    return "EXPENSES";
  }

  function sectionFor(t, profile) {
    const tax = window.PerduraTaxonomy;
    let sec = null;
    if (tax && tax.sectionForCategory && t.canonical_category) {
      try { sec = tax.sectionForCategory(t.canonical_category, profile); } catch (e) { sec = null; }
    }
    if (sec && SECTION_MAP[sec]) return SECTION_MAP[sec];
    return inferSection(t.account_code, t.canonical_category, t.account_name);
  }

  // ── month-key helpers ───────────────────────────────────────────────────────
  const MONTH_ABBR = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  const monthKeyOf = (iso) => (iso ? String(iso).slice(0, 7) : null); // "YYYY-MM"
  const labelForKey = (k) => { const [y, m] = k.split("-"); return MONTH_ABBR[(Number(m) || 1) - 1] + " " + y; };
  const prevMonthKey = (k) => {
    const [y, m] = k.split("-").map(Number);
    const d = new Date(Date.UTC(y, m - 2, 1));
    return d.getUTCFullYear() + "-" + String(d.getUTCMonth() + 1).padStart(2, "0");
  };

  // ── small UI atoms ──────────────────────────────────────────────────────────
  function Card({ title, subtitle, right, children, pad }) {
    return h("div", { style: { ...CARD, marginBottom: 16 } },
      (title || right) ? h("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", padding: "14px 16px 0" } },
        h("div", null,
          title ? h("div", { style: { fontSize: 14, fontWeight: 700, color: C.text1 } }, title) : null,
          subtitle ? h("div", { style: { fontSize: 12, color: C.muted, marginTop: 2 } }, subtitle) : null),
        right || null) : null,
      h("div", { style: { padding: pad == null ? 16 : pad } }, children));
  }

  function Placeholder({ label }) {
    return h("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", textAlign: "center", minHeight: 140, padding: "22px 24px", border: "1px dashed " + C.border, borderRadius: 8, color: C.muted, fontSize: 13, lineHeight: 1.6, background: "#FCFDFF" } }, label);
  }

  const ctrlStyle = { padding: "7px 10px", fontSize: 12.5, border: "1px solid " + C.border, borderRadius: 7, outline: "none", background: C.card, color: C.text1 };

  // ── canonical category list (for the edit dropdown) ─────────────────────────
  function canonicalCategories(profile, txns) {
    const tax = window.PerduraTaxonomy;
    if (tax && tax.categoriesForProfile) {
      try {
        const seen = new Set(); const out = [];
        tax.categoriesForProfile(profile).forEach((c) => { if (c.key && !seen.has(c.key)) { seen.add(c.key); out.push(c.key); } });
        if (out.length) return out;
      } catch (e) { /* fall through */ }
    }
    // Fallback: distinct canonical_category values present in the feed.
    const seen = new Set();
    (txns || []).forEach((t) => { if (t.canonical_category) seen.add(t.canonical_category); });
    return Array.from(seen).sort();
  }

  // ── CSV export ──────────────────────────────────────────────────────────────
  function exportCsv(rows, monthLabel) {
    const head = ["Account Code", "Account Name", "Account Type", "Category", "Debit", "Credit", "Net Balance", "% of Revenue", "Prior Month", "Var $"];
    const esc = (v) => { const s = v == null ? "" : String(v); return /[",\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s; };
    const lines = [head.map(esc).join(",")];
    rows.forEach((r) => {
      lines.push([r.code, r.name, r.section, r.category || "", r.debit.toFixed(2), r.credit.toFixed(2), r.net.toFixed(2),
        r.pctRev == null ? "" : r.pctRev.toFixed(1), r.prior.toFixed(2), r.varAmt.toFixed(2)].map(esc).join(","));
    });
    const csv = lines.join("\n");
    if (window.PerduraExport && window.PerduraExport.csv) { try { window.PerduraExport.csv(csv, "trial-balance.csv"); return; } catch (e) { /* fall through */ } }
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url; a.download = "trial-balance-" + monthLabel.replace(/\s+/g, "-") + ".csv";
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  }

  // ── editable category cell ──────────────────────────────────────────────────
  function CategoryCell({ row, options, scopedCompanyId, onSaved }) {
    const [editing, setEditing] = useState(false);
    const [saving, setSaving] = useState(false);
    const [saved, setSaved] = useState(false);
    const [value, setValue] = useState(row.category || "");

    const commit = (newCat) => {
      setEditing(false);
      if (!newCat || newCat === row.category) return;
      setValue(newCat);
      const db = window.supabaseClient;
      if (!db || !scopedCompanyId) { onSaved && onSaved(row.code, newCat); return; }
      setSaving(true); setSaved(false);
      db.from("account_mappings").update({ category_override: newCat })
        .eq("company_id", scopedCompanyId).eq("account_code", row.code)
        .then(() => { setSaving(false); setSaved(true); onSaved && onSaved(row.code, newCat); setTimeout(() => setSaved(false), 2000); },
              () => { setSaving(false); });
    };

    if (editing) {
      return h("td", { style: tdL, onClick: (e) => e.stopPropagation() },
        h("select", { autoFocus: true, value: value, style: { ...ctrlStyle, padding: "4px 6px", maxWidth: 220 },
          onChange: (e) => commit(e.target.value), onBlur: () => setEditing(false) },
          h("option", { value: "" }, "— select —"),
          options.map((o) => h("option", { key: o, value: o }, o))));
    }
    return h("td", { style: { ...tdL, cursor: "pointer" }, title: "Click to re-categorize this account", onClick: (e) => { e.stopPropagation(); setEditing(true); } },
      h("span", { style: { borderBottom: "1px dashed " + C.border } }, value || h("span", { style: { color: C.muted } }, "Unclassified")),
      saving ? h("span", { style: { marginLeft: 6, fontSize: 10.5, color: C.muted } }, "saving…") : null,
      saved ? h("span", { style: { marginLeft: 6, fontSize: 10.5, color: C.green, fontWeight: 700 } }, "✓ saved") : null);
  }

  // ── main component ──────────────────────────────────────────────────────────
  function TrialBalancePage(props) {
    const { data, companyProfile, scopedCompanyId, setPage } = props || {};
    const txns = (data && data.txns) || [];

    // Local overrides applied optimistically after a successful save, so the
    // visible category and its section regrouping update without a refetch.
    const [overrides, setOverrides] = useState({}); // account_code -> category

    // Distinct month keys present in the feed, plus any from data.pl labels/years.
    const monthKeys = useMemo(() => {
      const set = new Set();
      txns.forEach((t) => { const k = monthKeyOf(t.posted_date); if (k) set.add(k); });
      const pl = data && data.pl;
      if (pl && Array.isArray(pl.labels) && Array.isArray(pl.years)) {
        pl.labels.forEach((lbl, i) => {
          const mi = MONTH_ABBR.findIndex((a) => a.toLowerCase() === String(lbl).slice(0, 3).toLowerCase());
          if (mi >= 0 && pl.years[i]) set.add(pl.years[i] + "-" + String(mi + 1).padStart(2, "0"));
        });
      }
      return Array.from(set).sort(); // ascending
    }, [txns, data]);

    const [month, setMonth] = useState(null);
    const selMonth = month || (monthKeys.length ? monthKeys[monthKeys.length - 1] : null);

    const [search, setSearch] = useState("");
    const [typeFilter, setTypeFilter] = useState("ALL");
    const [activeOnly, setActiveOnly] = useState(true);
    const [openSections, setOpenSections] = useState(() => new Set(SECTION_ORDER));

    const categoryOptions = useMemo(() => canonicalCategories(companyProfile, txns), [companyProfile, txns]);

    const withOverride = (t) => overrides[t.account_code] ? { ...t, canonical_category: overrides[t.account_code] } : t;

    // Aggregate net signed amount per (code, name) for a given month key.
    const aggregateMonth = (key) => {
      const map = new Map();
      if (!key) return map;
      for (const raw of txns) {
        if (monthKeyOf(raw.posted_date) !== key) continue;
        const t = withOverride(raw);
        const code = (t.account_code != null && t.account_code !== "") ? String(t.account_code) : "(no code)";
        const name = t.account_name || t.canonical_category || "(unnamed account)";
        const id = code + "||" + name;
        const cur = map.get(id) || { code, name, net: 0, category: t.canonical_category || "", section: sectionFor(t, companyProfile) };
        cur.net += Number(t.amount) || 0;
        if (!cur.category && t.canonical_category) { cur.category = t.canonical_category; cur.section = sectionFor(t, companyProfile); }
        map.set(id, cur);
      }
      return map;
    };

    const priorMap = useMemo(() => selMonth ? aggregateMonth(prevMonthKey(selMonth)) : new Map(), [selMonth, txns, overrides, companyProfile]);

    // Build display rows for the selected month.
    const rows = useMemo(() => {
      const map = aggregateMonth(selMonth);
      // Period revenue total (sum of REVENUE-section credit balances, absolute).
      let revenueTotal = 0;
      map.forEach((r) => { if (r.section === "REVENUE") revenueTotal += Math.max(0, -r.net); });
      const out = [];
      map.forEach((r, id) => {
        const debit = Math.max(0, r.net);
        const credit = Math.max(0, -r.net);
        const pr = priorMap.get(id);
        const prior = pr ? pr.net : 0;
        out.push({
          id, code: r.code, name: r.name, section: r.section, category: r.category,
          debit, credit, net: r.net,
          pctRev: revenueTotal ? (r.net / revenueTotal * 100) : null,
          prior, varAmt: r.net - prior,
        });
      });
      out.sort((a, b) => (a.code === b.code ? a.name.localeCompare(b.name) : String(a.code).localeCompare(String(b.code), undefined, { numeric: true })));
      return { rows: out, revenueTotal };
    }, [selMonth, txns, overrides, companyProfile, priorMap]);

    const allRows = rows.rows;

    // Filtered rows (search + type + activity), used for display & export.
    const filtered = useMemo(() => allRows.filter((r) => {
      if (typeFilter !== "ALL" && r.section !== typeFilter) return false;
      if (activeOnly && Math.abs(r.net) < 0.005 && Math.abs(r.prior) < 0.005) return false;
      if (search) {
        const q = search.toLowerCase();
        if (!(String(r.name).toLowerCase().includes(q) || String(r.code).toLowerCase().includes(q))) return false;
      }
      return true;
    }), [allRows, typeFilter, activeOnly, search]);

    // Section grouping of the filtered rows, in statement order.
    const grouped = useMemo(() => {
      const g = {};
      SECTION_ORDER.forEach((s) => { g[s] = []; });
      filtered.forEach((r) => { (g[r.section] || (g[r.section] = [])).push(r); });
      return g;
    }, [filtered]);

    const totals = useMemo(() => {
      let debit = 0, credit = 0;
      filtered.forEach((r) => { debit += r.debit; credit += r.credit; });
      return { debit, credit, diff: debit - credit };
    }, [filtered]);

    const toggleSection = (s) => setOpenSections((prev) => { const n = new Set(prev); n.has(s) ? n.delete(s) : n.add(s); return n; });
    const onSaved = (code, cat) => setOverrides((prev) => ({ ...prev, [code]: cat }));

    // ── render ────────────────────────────────────────────────────────────────
    const hero = h("div", { className: "pa-hero", style: { borderRadius: 14, marginBottom: 18 } },
      h("div", { className: "pa-hero-eyebrow" }, "GENERAL LEDGER"),
      h("div", { className: "pa-hero-title" }, "Trial Balance"),
      h("div", { className: "pa-hero-subtitle" }, "Every GL account with debit / credit balances and a balance check"));

    if (!txns.length) {
      return h("div", { style: { background: C.bg, minHeight: "100%", padding: "4px 2px" } }, hero,
        h(Card, { title: "Trial Balance" }, h(Placeholder, { label: "Awaiting general-ledger data — connect your accounting system or import a transaction feed to build the trial balance with per-account debit/credit balances and a balance check." })));
    }

    const controls = h("div", { style: { display: "flex", flexWrap: "wrap", gap: 10, alignItems: "center", marginBottom: 16 } },
      h("select", { value: selMonth || "", onChange: (e) => setMonth(e.target.value), style: ctrlStyle },
        monthKeys.length ? monthKeys.slice().reverse().map((k) => h("option", { key: k, value: k }, labelForKey(k)))
          : h("option", { value: "" }, "No months")),
      h("input", { value: search, onChange: (e) => setSearch(e.target.value), placeholder: "Search account name or code…", style: { ...ctrlStyle, minWidth: 220 } }),
      h("select", { value: typeFilter, onChange: (e) => setTypeFilter(e.target.value), style: ctrlStyle },
        h("option", { value: "ALL" }, "All account types"),
        SECTION_ORDER.map((s) => h("option", { key: s, value: s }, s.charAt(0) + s.slice(1).toLowerCase()))),
      h("label", { style: { display: "flex", alignItems: "center", gap: 6, fontSize: 12.5, color: C.text2, cursor: "pointer" } },
        h("input", { type: "checkbox", checked: activeOnly, onChange: (e) => setActiveOnly(e.target.checked) }),
        "Show only accounts with activity"),
      h("div", { style: { flex: 1 } }),
      h("button", { onClick: () => exportCsv(filtered, selMonth ? labelForKey(selMonth) : "all"),
        style: { ...ctrlStyle, cursor: "pointer", fontWeight: 600, color: C.accent, background: C.accentSoft, border: "1px solid " + C.accent } }, "⭳ Export CSV"));

    const balanced = Math.abs(totals.diff) < 1;

    return h("div", { style: { background: C.bg, minHeight: "100%", padding: "4px 2px" } }, hero, controls,
      h("div", { style: { fontSize: 10, color: C.muted, padding: "0 2px 10px", display: "flex", alignItems: "center", gap: 6 } },
        h("span", null, "💡"), "Click any number, chart, or row to see the monthly breakdown and CFO insights"),
      h(Card, { title: "Trial Balance — " + (selMonth ? labelForKey(selMonth) : "—"),
        subtitle: filtered.length + " accounts · " + (activeOnly ? "with activity" : "including zero-balance") + (typeFilter !== "ALL" ? " · " + typeFilter : ""), pad: 0 },
        h("div", { style: { overflowX: "auto" } },
          h("table", { style: tableStyle },
            h("thead", null, h("tr", null,
              ["Account Code", "Account Name", "Account Type", "Category", "Debit", "Credit", "Net Balance", "% of Rev", "Prior Month", "Var $"].map((c, i) =>
                h("th", { key: i, style: i <= 3 ? thL : thR }, c)))),
            h("tbody", null, buildBody())))));

    function buildBody() {
      const body = [];
      SECTION_ORDER.forEach((sec) => {
        const secRows = grouped[sec] || [];
        if (!secRows.length) return;
        const open = openSections.has(sec);
        let sDebit = 0, sCredit = 0;
        secRows.forEach((r) => { sDebit += r.debit; sCredit += r.credit; });

        // Section divider / header row (clickable to expand/collapse).
        body.push(h("tr", { key: "h-" + sec, onClick: () => toggleSection(sec),
          style: { cursor: "pointer", background: C.accentSoft } },
          h("td", { colSpan: 4, style: { ...tdL, fontWeight: 800, color: C.accent, letterSpacing: 0.4, padding: "9px 10px" } },
            (open ? "▾ " : "▸ ") + sec + "  (" + secRows.length + ")"),
          h("td", { style: { ...tdR, fontWeight: 700, color: C.text1 } }, money(sDebit, { compact: true })),
          h("td", { style: { ...tdR, fontWeight: 700, color: C.text1 } }, money(sCredit, { compact: true })),
          h("td", { colSpan: 4, style: tdR }, "")));

        if (open) {
          secRows.forEach((r) => {
            body.push(h("tr", { key: r.id, title: "View account detail",
              onClick: () => window.openAccountDetail && window.openAccountDetail({ name: r.name, category: r.section || r.category, page: "trial-balance" }),
              style: { cursor: "pointer" } },
              h("td", { style: { ...tdL, fontVariantNumeric: "tabular-nums", color: C.muted } }, r.code),
              h("td", { style: { ...tdL, fontWeight: 600, color: C.text1 } }, r.name),
              h("td", { style: { ...tdL, color: C.muted, fontSize: 11.5 } }, r.section.charAt(0) + r.section.slice(1).toLowerCase()),
              h(CategoryCell, { row: r, options: categoryOptions, scopedCompanyId, onSaved }),
              h("td", { style: tdR }, r.debit ? money(r.debit, { compact: true }) : "—"),
              h("td", { style: tdR }, r.credit ? money(r.credit, { compact: true }) : "—"),
              h("td", { style: { ...tdR, fontWeight: 600, color: r.net >= 0 ? C.text1 : C.green } }, money(r.net, { compact: true })),
              h("td", { style: { ...tdR, color: C.muted } }, r.pctRev == null ? "—" : pct(r.pctRev, 0)),
              h("td", { style: { ...tdR, color: C.muted } }, r.prior ? money(r.prior, { compact: true }) : "—"),
              h("td", { style: { ...tdR, color: Math.abs(r.varAmt) < 0.005 ? C.muted : (r.varAmt >= 0 ? C.text2 : C.red) } }, Math.abs(r.varAmt) < 0.005 ? "—" : money(r.varAmt, { compact: true }))));
          });
          // Section subtotal row.
          body.push(h("tr", { key: "s-" + sec, style: { borderTop: "1px solid " + C.border, background: "#FAFBFE" } },
            h("td", { colSpan: 4, style: { ...tdR, fontWeight: 700, color: C.text2 } }, "Subtotal — " + sec.charAt(0) + sec.slice(1).toLowerCase()),
            h("td", { style: { ...tdR, fontWeight: 700 } }, money(sDebit, { compact: true })),
            h("td", { style: { ...tdR, fontWeight: 700 } }, money(sCredit, { compact: true })),
            h("td", { colSpan: 4, style: tdR }, "")));
        }
      });

      // Grand total row.
      body.push(h("tr", { key: "grand", style: { borderTop: "2px solid " + C.border, background: "#F1F5FB" } },
        h("td", { colSpan: 4, style: { ...tdR, fontWeight: 800, color: C.text1 } }, "GRAND TOTAL"),
        h("td", { style: { ...tdR, fontWeight: 800, color: C.text1 } }, money(totals.debit, { compact: true })),
        h("td", { style: { ...tdR, fontWeight: 800, color: C.text1 } }, money(totals.credit, { compact: true })),
        h("td", { colSpan: 4, style: tdR }, "")));

      // Balance-check row.
      body.push(h("tr", { key: "balcheck", style: { background: balanced ? C.greenSoft : C.redSoft } },
        h("td", { colSpan: 4, style: { ...tdL, fontWeight: 800, color: balanced ? C.green : C.red } },
          balanced ? "✓ IN BALANCE" : "⚠ OUT OF BALANCE — Difference: " + money(Math.abs(totals.diff))),
        h("td", { style: { ...tdR, fontWeight: 800, color: balanced ? C.green : C.red } }, money(totals.debit, { compact: true })),
        h("td", { style: { ...tdR, fontWeight: 800, color: balanced ? C.green : C.red } }, money(totals.credit, { compact: true })),
        h("td", { colSpan: 3, style: { ...tdR, fontWeight: 700, color: balanced ? C.green : C.red } },
          balanced ? "TOTAL DEBITS = TOTAL CREDITS" : "Δ " + money(totals.diff, { compact: true })),
        h("td", { style: tdR }, "")));

      return body;
    }
  }

  // shared table styles (matched to sibling pages)
  const tableStyle = { width: "100%", borderCollapse: "collapse", fontSize: 12.5 };
  const thBase = { padding: "10px 10px", borderBottom: "1px solid " + C.border, color: C.muted, fontWeight: 600, fontSize: 11, whiteSpace: "nowrap" };
  const thL = { ...thBase, textAlign: "left" };
  const thR = { ...thBase, textAlign: "right" };
  const tdBase = { padding: "7px 10px", borderBottom: "1px solid #F1F5F9", color: C.text2, whiteSpace: "nowrap" };
  const tdL = { ...tdBase, textAlign: "left" };
  const tdR = { ...tdBase, textAlign: "right", fontVariantNumeric: "tabular-nums" };

  window.TrialBalancePage = TrialBalancePage;
})();
