// Cupertino-style AP dashboard — hero number, frosted nav, system fonts.
const { useState, useMemo, useEffect } = React;

const BUCKETS = ["Not due", "0-30", "31-60", "61-90", "90+"];

// Apple system color palette
const BUCKET_COLOR = {
  "Not due": "#8E8E93", // systemGray
  "0-30":    "#34C759", // systemGreen
  "31-60":   "#FFCC00", // systemYellow
  "61-90":   "#FF9500", // systemOrange
  "90+":     "#FF3B30", // systemRed
};

const fmtMoney = (v, ccy) =>
  new Intl.NumberFormat("en-US", {
    style: "currency", currency: ccy,
    minimumFractionDigits: 0, maximumFractionDigits: 0,
  }).format(v);

const fmtDate = (iso) => {
  const d = new Date(iso + "T00:00:00");
  return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
};

const Icon = ({ children, size = 16 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
    stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
    {children}
  </svg>
);
const RefreshIcon = (p) => <Icon {...p}><path d="M3 12a9 9 0 0 1 15.5-6.3L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-15.5 6.3L3 16"/><path d="M3 21v-5h5"/></Icon>;
const SunIcon = (p) => <Icon {...p}><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></Icon>;
const MoonIcon = (p) => <Icon {...p}><path d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79z"/></Icon>;
const SearchIcon = (p) => <Icon {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></Icon>;
const ChevronDownIcon = (p) => <Icon {...p}><path d="m6 9 6 6 6-6"/></Icon>;
const ChevronUpIcon = (p) => <Icon {...p}><path d="m18 15-6-6-6 6"/></Icon>;
const ArrowUpDownIcon = (p) => <Icon {...p}><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></Icon>;
const XIcon = (p) => <Icon {...p}><path d="M18 6 6 18M6 6l12 12"/></Icon>;
const CheckIcon = (p) => <Icon {...p}><path d="M5 12l5 5L20 7"/></Icon>;

// Aging stripe — proportional bar split by bucket value
const AgingStripe = ({ buckets, total, currency }) => {
  if (total === 0) return <div className="h-1.5 w-full rounded-full bg-zinc-200/60 dark:bg-zinc-800"></div>;
  return (
    <div className="flex h-1.5 w-full overflow-hidden rounded-full">
      {BUCKETS.map((b, i) => {
        const pct = (buckets[b] / total) * 100;
        if (pct === 0) return null;
        return (
          <div
            key={b}
            style={{ width: `${pct}%`, background: BUCKET_COLOR[b] }}
            className={`${i === 0 ? "" : "ml-px"}`}
            title={`${b}: ${fmtMoney(buckets[b], currency)}`}
          ></div>
        );
      })}
    </div>
  );
};

const buildMatrix = (bills, entity) => {
  const m = { USD: { total: 0, count: 0 }, GBP: { total: 0, count: 0 }, count: 0 };
  ["USD", "GBP"].forEach((c) => BUCKETS.forEach((b) => (m[c][b] = 0)));
  bills.filter((b) => b.entity === entity).forEach((b) => {
    if (!m[b.currency]) return;
    m[b.currency][b.bucket] += b.balance;
    m[b.currency].total += b.balance;
    m[b.currency].count += 1;
    m.count += 1;
  });
  return m;
};

// Entity panel — Apple Settings group
const EntityPanel = ({ entity, matrix, flag }) => {
  const ccys = ["USD", "GBP"].filter((c) => matrix[c].count > 0 || (entity === "TAD USA" && c === "USD") || (entity === "TAD UK" && c === "GBP"));
  return (
    <div className="rounded-3xl bg-white p-7 ring-1 ring-black/[0.04] shadow-[0_1px_2px_rgba(0,0,0,0.04),0_8px_24px_-12px_rgba(0,0,0,0.08)] dark:bg-zinc-900 dark:ring-white/[0.06] dark:shadow-none">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <div className="text-2xl">{flag}</div>
          <div>
            <div className="text-[15px] font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">{entity}</div>
            <div className="text-[12px] text-zinc-500 dark:text-zinc-400">{matrix.count} open bills</div>
          </div>
        </div>
      </div>

      <div className="mt-6 space-y-5">
        {ccys.map((c) => (
          <div key={c}>
            <div className="flex items-baseline justify-between">
              <div className="flex items-baseline gap-2">
                <span className="text-[10px] font-semibold uppercase tracking-[0.14em] text-zinc-400 dark:text-zinc-500">{c}</span>
                <span className="text-[24px] font-semibold tracking-tight tabular-nums text-zinc-900 dark:text-zinc-100">
                  {matrix[c].count > 0 ? fmtMoney(matrix[c].total, c) : "—"}
                </span>
              </div>
              <span className="text-[11px] tabular-nums text-zinc-500 dark:text-zinc-400">
                {matrix[c].count} {matrix[c].count === 1 ? "bill" : "bills"}
              </span>
            </div>
            <div className="mt-2.5">
              <AgingStripe buckets={matrix[c]} total={matrix[c].total} currency={c} />
            </div>
            <div className="mt-3 grid grid-cols-5 gap-2">
              {BUCKETS.map((b) => {
                const v = matrix[c][b];
                return (
                  <div key={b} className="flex flex-col items-start">
                    <div className="flex items-center gap-1.5">
                      <span className="h-1.5 w-1.5 rounded-full" style={{ background: BUCKET_COLOR[b] }}></span>
                      <span className="text-[10px] uppercase tracking-wide text-zinc-500 dark:text-zinc-400">{b}</span>
                    </div>
                    <div className={`mt-0.5 text-[12px] tabular-nums ${v === 0 ? "text-zinc-300 dark:text-zinc-700" : "text-zinc-800 dark:text-zinc-200"}`}>
                      {v === 0 ? "—" : fmtMoney(v, c)}
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
};

// iOS-style segmented control
const Segmented = ({ value, options, onChange }) => (
  <div className="inline-flex rounded-[10px] bg-black/[0.06] p-0.5 dark:bg-white/[0.08]">
    {options.map((o) => {
      const active = o.value === value;
      return (
        <button
          key={o.value}
          onClick={() => onChange(o.value)}
          className={`flex items-center gap-1.5 rounded-[8px] px-3.5 py-1 text-[13px] font-medium transition-all ${
            active
              ? "bg-white text-zinc-900 shadow-[0_1px_3px_rgba(0,0,0,0.08)] dark:bg-zinc-700 dark:text-white"
              : "text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-200"
          }`}
        >
          {o.icon} {o.label}
        </button>
      );
    })}
  </div>
);

const BucketChips = ({ value, onChange }) => (
  <div className="flex flex-wrap items-center gap-1.5">
    {BUCKETS.map((b) => {
      const active = value.includes(b);
      return (
        <button
          key={b}
          onClick={() => onChange(active ? value.filter((x) => x !== b) : [...value, b])}
          className={`inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-[12px] font-medium transition ${
            active
              ? "bg-zinc-900 text-white dark:bg-white dark:text-zinc-900"
              : "bg-black/[0.04] text-zinc-700 hover:bg-black/[0.08] dark:bg-white/[0.06] dark:text-zinc-300 dark:hover:bg-white/[0.10]"
          }`}
        >
          <span
            className="h-1.5 w-1.5 rounded-full"
            style={{ background: active ? "currentColor" : BUCKET_COLOR[b] }}
          ></span>
          {b}
        </button>
      );
    })}
  </div>
);

const SortHeader = ({ label, sortKey, sort, setSort, align = "left" }) => {
  const active = sort.key === sortKey;
  return (
    <button
      onClick={() => setSort({ key: sortKey, dir: active && sort.dir === "desc" ? "asc" : "desc" })}
      className={`group inline-flex items-center gap-1 text-[11px] font-semibold uppercase tracking-[0.08em] ${
        active ? "text-zinc-900 dark:text-zinc-100" : "text-zinc-500 hover:text-zinc-800 dark:text-zinc-400 dark:hover:text-zinc-200"
      } ${align === "right" ? "flex-row-reverse" : ""}`}
    >
      {label}
      <span className="opacity-70">
        {!active && <ArrowUpDownIcon size={12} />}
        {active && (sort.dir === "desc" ? <ChevronDownIcon size={14} /> : <ChevronUpIcon size={14} />)}
      </span>
    </button>
  );
};

const VendorPicker = ({ vendors, selected, onChange }) => {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const filtered = vendors.filter((v) => v.toLowerCase().includes(q.toLowerCase()));
  return (
    <div className="relative">
      <button
        onClick={() => setOpen((o) => !o)}
        className="inline-flex items-center gap-2 rounded-full bg-black/[0.04] px-3.5 py-1.5 text-[13px] font-medium text-zinc-700 hover:bg-black/[0.08] dark:bg-white/[0.06] dark:text-zinc-300 dark:hover:bg-white/[0.1]"
      >
        <SearchIcon size={13} />
        Vendor
        {selected.length > 0 && (
          <span className="rounded-full bg-zinc-900 px-1.5 py-px text-[10px] font-semibold text-white dark:bg-white dark:text-zinc-900">
            {selected.length}
          </span>
        )}
        <ChevronDownIcon size={13} className="opacity-60" />
      </button>
      {open && (
        <>
          <div className="fixed inset-0 z-10" onClick={() => setOpen(false)}></div>
          <div className="absolute right-0 z-20 mt-2 w-72 overflow-hidden rounded-2xl border border-black/5 bg-white/90 backdrop-blur-2xl shadow-[0_12px_48px_rgba(0,0,0,0.18)] dark:border-white/10 dark:bg-zinc-800/90">
            <div className="flex items-center gap-2 border-b border-black/5 px-3 py-2 dark:border-white/10">
              <SearchIcon size={13} className="text-zinc-400" />
              <input autoFocus value={q} onChange={(e) => setQ(e.target.value)}
                placeholder="Search"
                className="flex-1 bg-transparent text-[13px] focus:outline-none dark:text-zinc-100"
              />
              {selected.length > 0 && (
                <button onClick={() => onChange([])} className="text-[11px] text-[#0071e3]">Clear</button>
              )}
            </div>
            <div className="max-h-72 overflow-y-auto py-1">
              {filtered.map((v) => {
                const checked = selected.includes(v);
                return (
                  <button key={v}
                    onClick={() => onChange(checked ? selected.filter((x) => x !== v) : [...selected, v])}
                    className="flex w-full items-center justify-between px-3 py-1.5 text-left text-[13px] hover:bg-black/[0.04] dark:hover:bg-white/[0.04]"
                  >
                    <span className="truncate text-zinc-800 dark:text-zinc-200">{v}</span>
                    {checked && <CheckIcon size={14} />}
                  </button>
                );
              })}
              {filtered.length === 0 && <div className="px-3 py-6 text-center text-[12px] text-zinc-400">No vendors</div>}
            </div>
          </div>
        </>
      )}
    </div>
  );
};

const App = () => {
  const [entityFilter, setEntityFilter] = useState("Both");
  const [bucketFilter, setBucketFilter] = useState([]);
  const [vendorFilter, setVendorFilter] = useState([]);
  const [sort, setSort] = useState({ key: "daysOverdue", dir: "desc" });
  const [dark, setDark] = useState(false);
  const [refreshing, setRefreshing] = useState(true);
  const [asOf, setAsOf] = useState(null);
  const [bills, setBills] = useState([]);
  const [entitiesMeta, setEntitiesMeta] = useState({});
  const [loadError, setLoadError] = useState(null);

  useEffect(() => {
    document.documentElement.classList.toggle("dark", dark);
  }, [dark]);

  const fetchBills = async () => {
    setRefreshing(true);
    setLoadError(null);
    try {
      const res = await fetch("/api/bills", { cache: "no-store" });
      if (!res.ok) throw new Error(`Server returned ${res.status}`);
      const data = await res.json();
      setBills((data.bills || []).map((b, i) => ({ id: i, ...b })));
      setEntitiesMeta(data.entities || {});
      setAsOf(new Date());
    } catch (err) {
      setLoadError(err.message || String(err));
    } finally {
      setRefreshing(false);
    }
  };

  useEffect(() => { fetchBills(); }, []);

  const vendors = useMemo(() => [...new Set(bills.map((b) => b.vendor))].sort(), [bills]);
  const usaMatrix = useMemo(() => buildMatrix(bills, "TAD USA"), [bills]);
  const ukMatrix  = useMemo(() => buildMatrix(bills, "TAD UK"),  [bills]);

  const grandTotals = useMemo(() => {
    const t = { USD: 0, GBP: 0 };
    bills.forEach((b) => (t[b.currency] += b.balance));
    return t;
  }, [bills]);

  const filtered = useMemo(() => {
    let r = bills.slice();
    if (entityFilter !== "Both") r = r.filter((b) => b.entity === entityFilter);
    if (bucketFilter.length) r = r.filter((b) => bucketFilter.includes(b.bucket));
    if (vendorFilter.length) r = r.filter((b) => vendorFilter.includes(b.vendor));
    const { key, dir } = sort;
    r.sort((a, b) => {
      const va = a[key], vb = b[key];
      if (typeof va === "number" && typeof vb === "number") return dir === "desc" ? vb - va : va - vb;
      return dir === "desc" ? String(vb).localeCompare(String(va)) : String(va).localeCompare(String(vb));
    });
    return r;
  }, [bills, entityFilter, bucketFilter, vendorFilter, sort]);

  const filteredTotals = useMemo(() => {
    const t = { USD: 0, GBP: 0 };
    filtered.forEach((b) => (t[b.currency] += b.balance));
    return t;
  }, [filtered]);

  const hasFilters = entityFilter !== "Both" || bucketFilter.length || vendorFilter.length;
  const entityErrors = Object.entries(entitiesMeta).filter(([, m]) => m && m.error);

  return (
    <div className="min-h-screen bg-[#fbfbfd] text-zinc-900 antialiased dark:bg-black dark:text-zinc-100">
      {/* Frosted nav */}
      <header className="sticky top-0 z-40 border-b border-black/[0.06] bg-white/72 backdrop-blur-2xl dark:border-white/[0.08] dark:bg-black/70">
        <div className="mx-auto flex max-w-[1280px] items-center justify-between px-8 py-3">
          <div className="flex items-center gap-2">
            <div className="text-[14px] font-semibold tracking-tight">Payables</div>
            <div className="text-[13px] text-zinc-400">·</div>
            <div className="text-[13px] text-zinc-500 dark:text-zinc-400">TAD Group</div>
          </div>
          <div className="flex items-center gap-2">
            <div className="hidden text-[12px] text-zinc-500 dark:text-zinc-400 md:block tabular-nums">
              {asOf ? asOf.toLocaleString("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" }) : "—"}
            </div>
            <button onClick={fetchBills} disabled={refreshing}
              className="inline-flex items-center gap-1.5 rounded-full bg-black/[0.04] px-3 py-1.5 text-[12px] font-medium text-zinc-700 hover:bg-black/[0.08] disabled:opacity-50 dark:bg-white/[0.08] dark:text-zinc-200 dark:hover:bg-white/[0.12]">
              <span className={refreshing ? "animate-spin" : ""}><RefreshIcon size={12} /></span>
              {refreshing ? "Refreshing" : "Refresh"}
            </button>
            <button onClick={() => setDark((d) => !d)}
              className="inline-flex h-7 w-7 items-center justify-center rounded-full bg-black/[0.04] text-zinc-600 hover:bg-black/[0.08] dark:bg-white/[0.08] dark:text-zinc-300">
              {dark ? <SunIcon size={13} /> : <MoonIcon size={13} />}
            </button>
          </div>
        </div>
      </header>

      {(loadError || entityErrors.length > 0) && (
        <div className="mx-auto max-w-[1280px] px-8 pt-4">
          <div className="rounded-2xl bg-[#FF3B30]/10 px-4 py-3 text-[13px] ring-1 ring-[#FF3B30]/20 dark:bg-[#FF3B30]/15 dark:ring-[#FF3B30]/30">
            {loadError && (
              <div className="flex items-center justify-between gap-3 text-[#B9261D] dark:text-[#FF6961]">
                <span>Could not load bills: {loadError}</span>
                <button onClick={fetchBills} className="font-semibold underline">Retry</button>
              </div>
            )}
            {entityErrors.map(([ek, m]) => (
              <div key={ek} className="text-[#B9261D] dark:text-[#FF6961]">
                <span className="font-semibold">{m.label}:</span> {m.error}
              </div>
            ))}
          </div>
        </div>
      )}

      <main className="mx-auto max-w-[1280px] px-8">
        {/* Hero */}
        <section className="pt-16 pb-12">
          <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-zinc-500 dark:text-zinc-400">
            Open balance · As of {asOf ? asOf.toLocaleDateString("en-US", { month: "long", day: "numeric" }) : "—"}
          </div>
          <div className="mt-4 flex flex-wrap items-baseline gap-x-8 gap-y-2">
            <div className="text-[80px] font-semibold leading-none tracking-[-0.04em] text-zinc-900 dark:text-zinc-100 tabular-nums">
              {fmtMoney(grandTotals.USD, "USD")}
            </div>
            <div className="text-[36px] font-medium leading-none tracking-tight text-zinc-400 dark:text-zinc-500 tabular-nums">
              + {fmtMoney(grandTotals.GBP, "GBP")}
            </div>
          </div>
          <div className="mt-4 text-[15px] text-zinc-500 dark:text-zinc-400">
            <span className="text-zinc-700 dark:text-zinc-200">{bills.length} open bills</span> across two entities.
            <span className="ml-2 text-[#FF3B30]">
              {bills.filter((b) => b.bucket === "90+").length} over 90 days
            </span>
            <span className="text-zinc-300 dark:text-zinc-700"> · </span>
            <span className="text-[#FF9500]">
              {bills.filter((b) => b.bucket === "61-90").length} between 61 – 90
            </span>
          </div>
        </section>

        {/* Entity panels */}
        <section className="grid grid-cols-1 gap-5 lg:grid-cols-2">
          <EntityPanel entity="TAD USA" matrix={usaMatrix} flag="🇺🇸" />
          <EntityPanel entity="TAD UK"  matrix={ukMatrix}  flag="🇬🇧" />
        </section>

        {/* Filters */}
        <section className="mt-12 mb-5 flex flex-wrap items-center gap-x-5 gap-y-3">
          <Segmented value={entityFilter} onChange={setEntityFilter}
            options={[
              { value: "Both", label: "All" },
              { value: "TAD USA", label: "USA" },
              { value: "TAD UK",  label: "UK"  },
            ]}
          />
          <BucketChips value={bucketFilter} onChange={setBucketFilter} />
          <div className="ml-auto flex items-center gap-2">
            <VendorPicker vendors={vendors} selected={vendorFilter} onChange={setVendorFilter} />
            {hasFilters && (
              <button onClick={() => { setEntityFilter("Both"); setBucketFilter([]); setVendorFilter([]); }}
                className="inline-flex items-center gap-1 rounded-full px-2 py-1 text-[12px] font-medium text-[#0071e3]">
                <XIcon size={12} /> Clear
              </button>
            )}
          </div>
        </section>

        {/* Count */}
        <div className="mb-3 flex items-baseline justify-between">
          <div className="text-[13px] text-zinc-500 dark:text-zinc-400">
            <span className="font-semibold text-zinc-900 dark:text-zinc-100 tabular-nums">{filtered.length}</span>
            <span className="text-zinc-400"> of </span>
            <span className="tabular-nums">{bills.length}</span> bills
          </div>
          <div className="flex items-baseline gap-4 text-[12px] tabular-nums">
            {filteredTotals.USD > 0 && (
              <span className="text-zinc-500 dark:text-zinc-400">
                USD <span className="font-semibold text-zinc-900 dark:text-zinc-100">{fmtMoney(filteredTotals.USD, "USD")}</span>
              </span>
            )}
            {filteredTotals.GBP > 0 && (
              <span className="text-zinc-500 dark:text-zinc-400">
                GBP <span className="font-semibold text-zinc-900 dark:text-zinc-100">{fmtMoney(filteredTotals.GBP, "GBP")}</span>
              </span>
            )}
          </div>
        </div>

        {/* Table */}
        <section className="overflow-hidden rounded-2xl bg-white ring-1 ring-black/[0.04] shadow-[0_1px_2px_rgba(0,0,0,0.03),0_8px_24px_-12px_rgba(0,0,0,0.06)] dark:bg-zinc-900 dark:ring-white/[0.06] dark:shadow-none">
          <div className="overflow-x-auto">
            <table className="w-full text-[13px]">
              <thead>
                <tr className="border-b border-black/[0.06] dark:border-white/[0.08]">
                  <th className="px-5 py-3 text-left"><SortHeader label="Entity" sortKey="entity" sort={sort} setSort={setSort}/></th>
                  <th className="px-5 py-3 text-left"><SortHeader label="Vendor" sortKey="vendor" sort={sort} setSort={setSort}/></th>
                  <th className="px-5 py-3 text-left"><SortHeader label="Bill" sortKey="docNumber" sort={sort} setSort={setSort}/></th>
                  <th className="px-5 py-3 text-left"><SortHeader label="Due" sortKey="dueDate" sort={sort} setSort={setSort}/></th>
                  <th className="px-5 py-3 text-right"><SortHeader label="Days" sortKey="daysOverdue" sort={sort} setSort={setSort} align="right"/></th>
                  <th className="px-5 py-3 text-left"><SortHeader label="Bucket" sortKey="bucket" sort={sort} setSort={setSort}/></th>
                  <th className="px-5 py-3 text-right"><SortHeader label="Amount" sortKey="balance" sort={sort} setSort={setSort} align="right"/></th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((b) => {
                  const overdue = b.daysOverdue > 0;
                  const color = BUCKET_COLOR[b.bucket];
                  return (
                    <tr key={b.id}
                      className={`border-b border-black/[0.04] last:border-b-0 transition-colors hover:bg-black/[0.02] dark:border-white/[0.06] dark:hover:bg-white/[0.03] ${
                        !overdue ? "opacity-70" : ""
                      }`}
                    >
                      <td className="px-5 py-3 text-[12px] text-zinc-500 dark:text-zinc-400">
                        <span className="mr-1.5">{b.entity === "TAD USA" ? "🇺🇸" : "🇬🇧"}</span>
                        {b.entity}
                      </td>
                      <td className="px-5 py-3 font-medium text-zinc-900 dark:text-zinc-100">{b.vendor}</td>
                      <td className="px-5 py-3 font-mono text-[11px] text-zinc-500 dark:text-zinc-400">{b.docNumber}</td>
                      <td className="px-5 py-3 tabular-nums text-zinc-700 dark:text-zinc-300">{fmtDate(b.dueDate)}</td>
                      <td className="px-5 py-3 text-right tabular-nums">
                        {overdue ? (
                          <span style={{ color }} className="font-semibold">+{b.daysOverdue}</span>
                        ) : (
                          <span className="text-zinc-400 dark:text-zinc-500">{b.daysOverdue}</span>
                        )}
                      </td>
                      <td className="px-5 py-3">
                        <span className="inline-flex items-center gap-1.5 text-[12px] text-zinc-700 dark:text-zinc-300">
                          <span className="h-2 w-2 rounded-full" style={{ background: color }}></span>
                          {b.bucket}
                        </span>
                      </td>
                      <td className="px-5 py-3 text-right tabular-nums">
                        <span className="font-semibold text-zinc-900 dark:text-zinc-100">{fmtMoney(b.balance, b.currency)}</span>
                        <span className="ml-1 text-[10px] text-zinc-400">{b.currency}</span>
                      </td>
                    </tr>
                  );
                })}
                {filtered.length === 0 && (
                  <tr><td colSpan={7} className="px-5 py-16 text-center text-[13px] text-zinc-400">No bills match.</td></tr>
                )}
              </tbody>
            </table>
          </div>
        </section>

        <footer className="py-10 text-center text-[11px] text-zinc-400 dark:text-zinc-600">
          QuickBooks Online · A/P aging · TAD Group
        </footer>
      </main>
    </div>
  );
};

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
