// Views: Overview, Transactions, Miles, Accounts, Insights

// ============ MONTH PICKER ============
function MonthPicker({ monthsAvailable, monthFilter, setMonthFilter, allTransactions }) {
  // Group available months by year, oldest year first
  const byYear = React.useMemo(() => {
    const m = {};
    monthsAvailable.forEach(ym => {
      const [y, mo] = ym.split("-");
      (m[y] = m[y] || []).push(parseInt(mo));
    });
    Object.keys(m).forEach(y => m[y].sort((a, b) => a - b));
    return m;
  }, [monthsAvailable]);

  const years = Object.keys(byYear).sort();
  const monthAbbr = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
  const scrollRef = React.useRef(null);
  const activeRef = React.useRef(null);

  // Auto-scroll active chip into view on mount / change
  React.useEffect(() => {
    if (activeRef.current && scrollRef.current) {
      const el = activeRef.current;
      const container = scrollRef.current;
      const elLeft = el.offsetLeft;
      const elRight = elLeft + el.offsetWidth;
      const cLeft = container.scrollLeft;
      const cRight = cLeft + container.clientWidth;
      if (elLeft < cLeft || elRight > cRight) {
        container.scrollTo({ left: elLeft - 80, behavior: "smooth" });
      }
    }
  }, [monthFilter]);

  // Count helper
  const monthCount = (ym) => allTransactions.filter(t => t.date.startsWith(ym)).length;

  return (
    <div style={{
      display: "flex", alignItems: "stretch",
      borderBottom: "1px solid var(--border-subtle)",
      background: "var(--bg-canvas)",
    }}>
      {/* All-time pill (sticky left) */}
      <button
        onClick={() => setMonthFilter("all")}
        ref={monthFilter === "all" ? activeRef : null}
        style={{
          flexShrink: 0,
          padding: "12px 16px",
          background: monthFilter === "all" ? "var(--bg-muted)" : "transparent",
          border: "none", borderRight: "1px solid var(--border-subtle)",
          fontFamily: "inherit", fontSize: 12, fontWeight: 600,
          color: monthFilter === "all" ? "var(--text-1)" : "var(--text-muted)",
          cursor: "pointer", letterSpacing: "-0.005em",
          display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 2,
          minWidth: 88,
        }}>
        <span>All time</span>
        <span style={{ fontSize: 10.5, fontWeight: 500, color: "var(--text-muted)", fontVariantNumeric: "tabular-nums" }}>
          {allTransactions.length} entries
        </span>
      </button>

      {/* Scrollable year-grouped strip */}
      <div ref={scrollRef} style={{
        flex: 1, overflowX: "auto", display: "flex",
        scrollbarWidth: "thin",
      }}>
        {years.map((yr, yIdx) => (
          <div key={yr} style={{
            display: "flex", alignItems: "stretch", flexShrink: 0,
            borderRight: yIdx < years.length - 1 ? "1px solid var(--border-subtle)" : "none",
          }}>
            {/* Year label */}
            <div style={{
              padding: "12px 10px 12px 14px",
              fontSize: 10, fontWeight: 700, letterSpacing: "0.08em",
              color: "var(--text-muted)", textTransform: "uppercase",
              writingMode: "horizontal-tb",
              display: "flex", alignItems: "center",
              borderRight: "1px solid var(--border-subtle)",
              background: "var(--bg-muted)",
            }}>
              {yr}
            </div>
            {/* Month cells */}
            {byYear[yr].map(mo => {
              const ym = `${yr}-${String(mo).padStart(2, "0")}`;
              const isActive = monthFilter === ym;
              const count = monthCount(ym);
              return (
                <button
                  key={ym}
                  onClick={() => setMonthFilter(ym)}
                  ref={isActive ? activeRef : null}
                  style={{
                    flexShrink: 0,
                    padding: "10px 14px",
                    background: isActive ? "var(--text-1)" : "transparent",
                    border: "none",
                    borderRight: "1px solid var(--border-subtle)",
                    fontFamily: "inherit", cursor: "pointer",
                    color: isActive ? "var(--bg)" : "var(--text-2)",
                    display: "flex", flexDirection: "column", alignItems: "center", gap: 3,
                    minWidth: 56,
                    transition: "background 0.12s, color 0.12s",
                  }}
                  onMouseEnter={e => { if (!isActive) e.currentTarget.style.background = "var(--bg-muted)"; }}
                  onMouseLeave={e => { if (!isActive) e.currentTarget.style.background = "transparent"; }}>
                  <span style={{ fontSize: 12, fontWeight: 600, letterSpacing: "-0.005em" }}>{monthAbbr[mo - 1]}</span>
                  <span style={{
                    fontSize: 10, fontWeight: 500,
                    color: isActive ? "var(--bg)" : "var(--text-muted)",
                    opacity: isActive ? 0.7 : 1,
                    fontVariantNumeric: "tabular-nums",
                  }}>
                    {count}
                  </span>
                </button>
              );
            })}
          </div>
        ))}
      </div>
    </div>
  );
}

// ============ OVERVIEW ============
function OverviewView({ onNav, layout = "balanced" }) {
  const { CARDS, ACCOUNTS, CATEGORIES, TRANSACTIONS, MONTHLY_HISTORY } = window.FIN_DATA;
  const creditCards = CARDS.filter(c => c.type === "credit");
  const totalSpent = sumExpensesThisMonth();
  const totalIncome = sumIncomeThisMonth();
  const netWorth = ACCOUNTS.reduce((s, a) => s + a.balance, 0);
  const lastMonth = MONTHLY_HISTORY[MONTHLY_HISTORY.length - 2];
  const spentDelta = ((totalSpent - lastMonth.expenses) / lastMonth.expenses) * 100;

  const byCat = sumByCategory();
  const catData = CATEGORIES
    .map(c => ({ ...c, value: byCat[c.id] || 0 }))
    .filter(c => c.value > 0)
    .sort((a, b) => b.value - a.value);

  const byCard = sumByCard();
  const cardSpending = creditCards
    .map(c => ({ ...c, total: byCard[c.id] || 0 }))
    .filter(c => c.total > 0)
    .sort((a, b) => b.total - a.total);
  const maxCardSpend = Math.max(...cardSpending.map(c => c.total), 1);

  const recent = TRANSACTIONS.slice(0, layout === "list" ? 10 : 6);

  // Cards with bonus that need attention (credit only) — include uncapped (PRVI/KrisFlyer) too
  const milesAttention = creditCards
    .filter(c => c.bonus)
    .map(c => {
      const cap = c.bonus.capSgd;
      const pct = cap ? (c.spent / cap) * 100 : 50; // sort uncapped to middle
      return { ...c, pct };
    })
    .sort((a, b) => b.pct - a.pct);

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
      {/* Greeting */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 12 }}>
        <div>
          <div style={{ fontSize: 13, color: "var(--text-muted)", fontWeight: 500 }}>Wednesday, 29 April 2026</div>
          <h1 style={{ fontSize: 28, fontWeight: 600, margin: "4px 0 0", letterSpacing: "-0.02em", color: "var(--text-1)" }}>Good afternoon</h1>
        </div>
        <button className="btn-primary" onClick={() => onNav("add")}>
          <Icon name="plus" size={14}/> Add transaction
        </button>
      </div>

      {/* Top stats */}
      <div className="grid-4" style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14 }}>
        <Stat label="Spent this month" value={fmt.sgd(totalSpent, { decimals: 0 })}
          icon="arrow-up-right"
          delta={{ label: `${spentDelta > 0 ? "+" : ""}${spentDelta.toFixed(0)}% vs Mar`, negative: spentDelta > 10, positive: spentDelta < 0 }}/>
        <Stat label="Income this month" value={fmt.sgd(totalIncome, { decimals: 0 })}
          icon="arrow-down-left"
          delta={{ label: "+S$242 vs Mar", positive: true }}/>
        <Stat label="Net worth" value={fmt.sgdShort(netWorth)}
          icon="trending-up"
          delta={{ label: "+S$3.2k this month", positive: true }}/>
        <Stat label="Miles earned (Apr)" value={fmt.miles(creditCards.reduce((s, c) => s + (c.bonus ? computeMiles(c).miles : 0), 0))}
          icon="plane"
          delta={{ label: "On track for 12.4k" }}/>
      </div>

      {/* HERO: Miles tracker */}
      <div className="card" style={{ padding: 0, overflow: "hidden" }}>
        <div style={{ padding: "18px 22px", display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: "1px solid var(--border-subtle)" }}>
          <div>
            <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
              <Icon name="plane" size={16}/>
              <h3 style={{ fontSize: 15, fontWeight: 600, margin: 0, color: "var(--text-1)" }}>Miles bonus tracker</h3>
              <span className="pill">April</span>
            </div>
            <div style={{ fontSize: 12, color: "var(--text-muted)", marginTop: 4 }}>
              How close you are to maxing each card's bonus tier this month
            </div>
          </div>
          <button className="btn-ghost" onClick={() => onNav("cards")}>View all <Icon name="arrow-right" size={12}/></button>
        </div>
        <div className="grid-2" style={{ padding: 22, display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 26, rowGap: 22 }}>
          {milesAttention.map(card => (
            <div key={card.id} style={{ display: "flex", gap: 14, alignItems: "flex-start" }}>
              <div style={{
                width: 44, height: 30, borderRadius: 5,
                background: `linear-gradient(135deg, ${card.color}, ${card.color}dd)`,
                flexShrink: 0,
                position: "relative",
                boxShadow: "0 1px 2px rgba(0,0,0,0.1)",
              }}>
                <div style={{ position: "absolute", left: 4, top: 4, width: 8, height: 6, background: card.accent, borderRadius: 1, opacity: 0.8 }}/>
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 6 }}>
                  <div style={{ fontSize: 13, fontWeight: 600, color: "var(--text-1)" }}>{card.name}</div>
                  <div style={{ fontSize: 11, color: "var(--text-muted)" }}>•••• {card.last4}</div>
                </div>
                <MilesProgressBar card={card}/>
              </div>
            </div>
          ))}
        </div>
      </div>

      {layout === "chart" ? <ChartHeavyOverview catData={catData} cardSpending={cardSpending} maxCardSpend={maxCardSpend} totalSpent={totalSpent} recent={recent} onNav={onNav}/>
        : layout === "list" ? <ListHeavyOverview recent={recent} catData={catData} totalSpent={totalSpent} onNav={onNav}/>
        : <BalancedOverview catData={catData} cardSpending={cardSpending} maxCardSpend={maxCardSpend} totalSpent={totalSpent} recent={recent} onNav={onNav}/>}

      {/* Account balances strip */}
      <div className="card" style={{ padding: 22 }}>
        <SectionHeader title="Accounts" subtitle="Bank balances and brokerage holdings"
          action={<button className="btn-ghost" onClick={() => onNav("accounts")}>Manage <Icon name="arrow-right" size={12}/></button>}/>
        <AccountStrip onClick={() => onNav("accounts")}/>
      </div>
    </div>
  );
}

// Layout variant: Balanced (default)
function BalancedOverview({ catData, cardSpending, maxCardSpend, totalSpent, recent, onNav }) {
  const { MONTHLY_HISTORY } = window.FIN_DATA;
  return (
    <>
      <div className="grid-2" style={{ display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 22 }}>
          <SectionHeader title="Spending vs income" subtitle="Last 12 months"
            action={<div style={{ display: "flex", gap: 12, fontSize: 11, color: "var(--text-muted)" }}>
              <span style={{ display: "flex", alignItems: "center", gap: 5 }}><span style={{ width: 12, height: 2, background: "var(--text-1)" }}/> Expenses</span>
              <span style={{ display: "flex", alignItems: "center", gap: 5 }}><span style={{ width: 12, height: 0, borderTop: "1.5px dashed var(--text-muted)" }}/> Income</span>
            </div>}/>
          <MonthlyChart data={MONTHLY_HISTORY}/>
        </div>

        <div className="card" style={{ padding: 22 }}>
          <SectionHeader title="By category" subtitle="April 2026"/>
          <CategoryDonut catData={catData} totalSpent={totalSpent}/>
        </div>
      </div>

      <div className="grid-2" style={{ display: "grid", gridTemplateColumns: "1fr 1.3fr", gap: 14 }}>
        <div className="card" style={{ padding: 22 }}>
          <SectionHeader title="Spending by card" subtitle="Credit cards · April"/>
          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            {cardSpending.map(c => (
              <div key={c.id}>
                <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6, fontSize: 12 }}>
                  <span style={{ color: "var(--text-2)", fontWeight: 500 }}>{c.name}</span>
                  <span style={{ fontVariantNumeric: "tabular-nums", color: "var(--text-1)", fontWeight: 600 }}>{fmt.sgd(c.total, { decimals: 0 })}</span>
                </div>
                <HBar value={c.total} max={maxCardSpend} color={c.color}/>
              </div>
            ))}
          </div>
        </div>

        <div className="card" style={{ padding: 0, overflow: "hidden" }}>
          <div style={{ padding: "18px 22px 12px", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
            <div>
              <h3 style={{ fontSize: 15, fontWeight: 600, margin: 0, color: "var(--text-1)" }}>Recent activity</h3>
              <div style={{ fontSize: 12, color: "var(--text-muted)", marginTop: 2 }}>Latest 6 transactions</div>
            </div>
            <button className="btn-ghost" onClick={() => onNav("transactions")}>See all <Icon name="arrow-right" size={12}/></button>
          </div>
          <div>
            {recent.map(tx => <TxRow key={tx.id} tx={tx} dense/>)}
          </div>
        </div>
      </div>
    </>
  );
}

// Layout variant: Chart-heavy (more visual)
function ChartHeavyOverview({ catData, cardSpending, maxCardSpend, totalSpent, recent, onNav }) {
  const { MONTHLY_HISTORY } = window.FIN_DATA;
  return (
    <>
      <div className="card" style={{ padding: 22 }}>
        <SectionHeader title="Spending vs income" subtitle="Last 12 months"/>
        <MonthlyChart data={MONTHLY_HISTORY} height={260}/>
      </div>
      <div className="grid-2" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 22 }}>
          <SectionHeader title="By category" subtitle="April 2026"/>
          <CategoryDonut catData={catData} totalSpent={totalSpent}/>
        </div>
        <div className="card" style={{ padding: 22 }}>
          <SectionHeader title="By card" subtitle="Credit · April"/>
          <div style={{ display: "flex", flexDirection: "column", gap: 14, marginTop: 8 }}>
            {cardSpending.map(c => (
              <div key={c.id}>
                <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6, fontSize: 12 }}>
                  <span style={{ color: "var(--text-2)", fontWeight: 500 }}>{c.name}</span>
                  <span style={{ fontVariantNumeric: "tabular-nums", color: "var(--text-1)", fontWeight: 600 }}>{fmt.sgd(c.total, { decimals: 0 })}</span>
                </div>
                <HBar value={c.total} max={maxCardSpend} color={c.color}/>
              </div>
            ))}
          </div>
        </div>
      </div>
    </>
  );
}

// Layout variant: List-heavy (transactions front and center)
function ListHeavyOverview({ recent, catData, totalSpent, onNav }) {
  return (
    <div className="grid-2" style={{ display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 14 }}>
      <div className="card" style={{ padding: 0, overflow: "hidden" }}>
        <div style={{ padding: "18px 22px 12px", display: "flex", justifyContent: "space-between" }}>
          <div>
            <h3 style={{ fontSize: 15, fontWeight: 600, margin: 0, color: "var(--text-1)" }}>Recent activity</h3>
            <div style={{ fontSize: 12, color: "var(--text-muted)", marginTop: 2 }}>Latest 10 transactions</div>
          </div>
          <button className="btn-ghost" onClick={() => onNav("transactions")}>See all <Icon name="arrow-right" size={12}/></button>
        </div>
        <div>{recent.map(tx => <TxRow key={tx.id} tx={tx} dense/>)}</div>
      </div>
      <div className="card" style={{ padding: 22 }}>
        <SectionHeader title="By category" subtitle="April 2026"/>
        <CategoryDonut catData={catData} totalSpent={totalSpent}/>
      </div>
    </div>
  );
}

function CategoryDonut({ catData, totalSpent }) {
  return (
    <div style={{ display: "flex", gap: 18, alignItems: "center" }}>
      <div style={{ position: "relative", flexShrink: 0 }}>
        <Donut data={catData} size={140} thickness={18}/>
        <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", textAlign: "center" }}>
          <div>
            <div style={{ fontSize: 10, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em" }}>Total</div>
            <div style={{ fontSize: 16, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.sgdShort(totalSpent)}</div>
          </div>
        </div>
      </div>
      <div style={{ flex: 1, display: "flex", flexDirection: "column", gap: 7 }}>
        {catData.slice(0, 7).map(c => (
          <div key={c.id} style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12 }}>
            <span style={{ width: 8, height: 8, borderRadius: 2, background: c.color, flexShrink: 0 }}/>
            <span style={{ flex: 1, color: "var(--text-2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{c.name}</span>
            <span style={{ fontVariantNumeric: "tabular-nums", color: "var(--text-1)", fontWeight: 500 }}>{fmt.sgd(c.value, { decimals: 0 })}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function AccountStrip({ onClick }) {
  const { ACCOUNTS } = window.FIN_DATA;
  return (
    <div className="grid-6" style={{ display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: 10 }}>
      {ACCOUNTS.slice(0, 7).map(a => (
        <div key={a.id} className="acct-mini" onClick={onClick} style={{
          padding: 14, borderRadius: 10,
          border: "1px solid var(--border-subtle)",
          cursor: "pointer",
          background: "var(--bg)",
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 6, marginBottom: 8 }}>
            <span style={{ width: 6, height: 6, borderRadius: "50%", background: a.color }}/>
            <span style={{ fontSize: 9.5, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em", fontWeight: 600 }}>
              {a.type === "investment" ? "Brokerage" : "Bank"}
            </span>
          </div>
          <div style={{ fontSize: 12.5, fontWeight: 500, color: "var(--text-1)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{a.name}</div>
          <div style={{ fontSize: 15, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)", marginTop: 4, letterSpacing: "-0.01em" }}>
            {fmt.sgd(a.balance, { decimals: 0 })}
          </div>
        </div>
      ))}
    </div>
  );
}

// ============ TRANSACTIONS ============
function TransactionsView() {
  const { TRANSACTIONS } = window.FIN_DATA;
  const [filter, setFilter] = React.useState("all");
  const [search, setSearch] = React.useState("");
  // Month filter: "all" = no filter, otherwise "YYYY-MM"
  const [monthFilter, setMonthFilter] = React.useState("all");
  // Group mode: "day" (current day-by-day view) or "month" (collapsed month sections)
  const [groupMode, setGroupMode] = React.useState("day");
  // Track expanded months in month-group mode
  const [expanded, setExpanded] = React.useState({});

  // Compute all months present in the data, newest first
  const monthsAvailable = React.useMemo(() => {
    const set = new Set();
    TRANSACTIONS.forEach(t => set.add(t.date.slice(0, 7)));
    return [...set].sort().reverse();
  }, [TRANSACTIONS]);

  // Default-expand the most recent month in month-group view
  React.useEffect(() => {
    if (groupMode === "month" && monthsAvailable.length && Object.keys(expanded).length === 0) {
      setExpanded({ [monthsAvailable[0]]: true });
    }
  }, [groupMode, monthsAvailable]);

  const filtered = TRANSACTIONS.filter(t => {
    if (filter !== "all" && t.type !== filter) return false;
    if (search && !t.merchant.toLowerCase().includes(search.toLowerCase())) return false;
    if (monthFilter !== "all" && !t.date.startsWith(monthFilter)) return false;
    return true;
  });

  // Day grouping (existing flat view)
  const groupedByDay = filtered.reduce((acc, tx) => {
    (acc[tx.date] = acc[tx.date] || []).push(tx);
    return acc;
  }, {});

  // Month grouping (new collapsible view)
  const groupedByMonth = filtered.reduce((acc, tx) => {
    const m = tx.date.slice(0, 7);
    (acc[m] = acc[m] || []).push(tx);
    return acc;
  }, {});

  const filters = [
    { id: "all", label: "All", count: TRANSACTIONS.length },
    { id: "expense", label: "Expenses", count: TRANSACTIONS.filter(t => t.type === "expense").length },
    { id: "income", label: "Income", count: TRANSACTIONS.filter(t => t.type === "income").length },
    { id: "transfer", label: "Transfers", count: TRANSACTIONS.filter(t => t.type === "transfer").length },
  ];

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 12 }}>
        <div>
          <h1 style={{ fontSize: 24, fontWeight: 600, margin: 0, letterSpacing: "-0.02em", color: "var(--text-1)" }}>Transactions</h1>
          <div style={{ fontSize: 13, color: "var(--text-muted)", marginTop: 4 }}>
            {filtered.length} {filtered.length === 1 ? "entry" : "entries"} · {fmt.sgd(filtered.filter(t => t.type === "expense").reduce((s, t) => s + t.amount, 0), { decimals: 0 })} spent
          </div>
        </div>
        <button className="btn-primary"><Icon name="plus" size={14}/> Add transaction</button>
      </div>

      <div className="card" style={{ padding: 0, overflow: "hidden" }}>
        <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--border-subtle)", display: "flex", gap: 12, alignItems: "center", flexWrap: "wrap" }}>
          <div style={{ display: "flex", gap: 4, padding: 3, background: "var(--bg-muted)", borderRadius: 8 }}>
            {filters.map(f => (
              <button key={f.id} onClick={() => setFilter(f.id)} className={"seg " + (filter === f.id ? "seg-active" : "")}>
                {f.label} <span style={{ opacity: 0.6, marginLeft: 4 }}>{f.count}</span>
              </button>
            ))}
          </div>
          <div style={{ flex: 1, minWidth: 200, position: "relative" }}>
            <Icon name="search" size={14} style={{ position: "absolute", left: 10, top: "50%", transform: "translateY(-50%)", color: "var(--text-muted)" }}/>
            <input value={search} onChange={e => setSearch(e.target.value)} placeholder="Search merchant…"
              style={{ width: "100%", padding: "7px 10px 7px 30px", background: "var(--bg-muted)", border: "1px solid transparent", borderRadius: 7, fontSize: 13, color: "var(--text-1)", outline: "none", fontFamily: "inherit" }}/>
          </div>
          <div style={{ display: "flex", gap: 4, padding: 3, background: "var(--bg-muted)", borderRadius: 8 }}>
            <button onClick={() => setGroupMode("day")} className={"seg " + (groupMode === "day" ? "seg-active" : "")} title="Day-by-day">
              <Icon name="list" size={11}/> Day
            </button>
            <button onClick={() => setGroupMode("month")} className={"seg " + (groupMode === "month" ? "seg-active" : "")} title="Group by month">
              <Icon name="calendar" size={11}/> Month
            </button>
          </div>
        </div>

        {/* Month picker — year-grouped horizontal navigator */}
        <MonthPicker
          monthsAvailable={monthsAvailable}
          monthFilter={monthFilter}
          setMonthFilter={setMonthFilter}
          allTransactions={TRANSACTIONS}
        />

        <div>
          {filtered.length === 0 && (
            <div style={{ padding: "40px 20px", textAlign: "center", color: "var(--text-muted)", fontSize: 13 }}>
              No transactions match your filters.
            </div>
          )}

          {/* DAY-GROUPED VIEW */}
          {groupMode === "day" && Object.entries(groupedByDay).map(([date, txs]) => {
            const dayTotal = txs.filter(t => t.type === "expense").reduce((s, t) => s + t.amount, 0);
            return (
              <div key={date}>
                <div style={{
                  padding: "10px 16px", background: "var(--bg-muted)",
                  display: "flex", justifyContent: "space-between",
                  fontSize: 11, fontWeight: 600, color: "var(--text-muted)",
                  textTransform: "uppercase", letterSpacing: "0.04em",
                  borderBottom: "1px solid var(--border-subtle)",
                  borderTop: "1px solid var(--border-subtle)",
                }}>
                  <span>{fmt.date(date)}</span>
                  {dayTotal > 0 && <span style={{ fontVariantNumeric: "tabular-nums" }}>−{fmt.sgd(dayTotal)}</span>}
                </div>
                {txs.map(tx => <TxRow key={tx.id} tx={tx}/>)}
              </div>
            );
          })}

          {/* MONTH-GROUPED VIEW (collapsible) */}
          {groupMode === "month" && Object.keys(groupedByMonth).sort().reverse().map(monthKey => {
            const txs = groupedByMonth[monthKey];
            const isOpen = !!expanded[monthKey];
            const expenseTotal = txs.filter(t => t.type === "expense").reduce((s, t) => s + t.amount, 0);
            const incomeTotal = txs.filter(t => t.type === "income").reduce((s, t) => s + t.amount, 0);
            return (
              <div key={monthKey}>
                <button
                  onClick={() => setExpanded(e => ({ ...e, [monthKey]: !e[monthKey] }))}
                  style={{
                    width: "100%", padding: "14px 16px",
                    background: isOpen ? "var(--bg-muted)" : "var(--bg-canvas)",
                    border: "none",
                    borderTop: "1px solid var(--border-subtle)",
                    borderBottom: "1px solid var(--border-subtle)",
                    display: "flex", alignItems: "center", gap: 10,
                    cursor: "pointer", fontFamily: "inherit",
                    color: "var(--text-1)", textAlign: "left",
                  }}>
                  <Icon name="arrow-right" size={12} style={{
                    color: "var(--text-muted)",
                    transform: isOpen ? "rotate(90deg)" : "none",
                    transition: "transform 0.15s",
                  }}/>
                  <div style={{ flex: 1, fontSize: 13.5, fontWeight: 600, letterSpacing: "-0.01em" }}>
                    {fmt.monthLabel(monthKey + "-01")}
                  </div>
                  <div style={{ display: "flex", gap: 14, alignItems: "center", fontSize: 12, fontVariantNumeric: "tabular-nums" }}>
                    <span style={{ color: "var(--text-muted)" }}>{txs.length} {txs.length === 1 ? "entry" : "entries"}</span>
                    {incomeTotal > 0 && <span style={{ color: "var(--success, #16a34a)" }}>+{fmt.sgd(incomeTotal, { decimals: 0 })}</span>}
                    {expenseTotal > 0 && <span style={{ color: "var(--text-1)", fontWeight: 600 }}>−{fmt.sgd(expenseTotal, { decimals: 0 })}</span>}
                  </div>
                </button>
                {isOpen && (
                  <div>
                    {Object.entries(txs.reduce((acc, t) => { (acc[t.date] = acc[t.date] || []).push(t); return acc; }, {})).map(([date, dayTxs]) => {
                      const dayTotal = dayTxs.filter(t => t.type === "expense").reduce((s, t) => s + t.amount, 0);
                      return (
                        <div key={date}>
                          <div style={{
                            padding: "8px 16px 8px 38px", background: "var(--bg-canvas)",
                            display: "flex", justifyContent: "space-between",
                            fontSize: 11, fontWeight: 500, color: "var(--text-muted)",
                            borderBottom: "1px solid var(--border-subtle)",
                          }}>
                            <span>{fmt.date(date)}</span>
                            {dayTotal > 0 && <span style={{ fontVariantNumeric: "tabular-nums" }}>−{fmt.sgd(dayTotal)}</span>}
                          </div>
                          {dayTxs.map(tx => <TxRow key={tx.id} tx={tx}/>)}
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

// ============ MILES / CARDS VIEW ============
function CardsView() {
  const { CARDS } = window.FIN_DATA;
  const credit = CARDS.filter(c => c.type === "credit");
  const debit = CARDS.filter(c => c.type === "debit");
  const totalMiles = credit.reduce((s, c) => s + (c.bonus ? computeMiles(c).miles : 0), 0);
  const totalSpend = credit.reduce((s, c) => s + c.spent, 0);
  const blendedRate = totalSpend > 0 ? totalMiles / totalSpend : 0;

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
      <div>
        <h1 style={{ fontSize: 24, fontWeight: 600, margin: 0, letterSpacing: "-0.02em", color: "var(--text-1)" }}>Cards & Miles</h1>
        <div style={{ fontSize: 13, color: "var(--text-muted)", marginTop: 4 }}>Track bonus tiers, statements and miles earned across all cards</div>
      </div>

      <div className="grid-4" style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14 }}>
        <Stat label="Total miles (Apr)" value={fmt.miles(totalMiles)} icon="plane"/>
        <Stat label="Card spend" value={fmt.sgd(totalSpend, { decimals: 0 })} icon="card"/>
        <Stat label="Blended rate" value={blendedRate.toFixed(2) + " mpd"} icon="zap"/>
        <Stat label="Statements due" value={fmt.sgd(credit.reduce((s, c) => s + c.statementBalance, 0), { decimals: 0 })} icon="alert"/>
      </div>

      <div style={{ fontSize: 11, color: "var(--text-muted)", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em", marginTop: 4 }}>Credit cards</div>
      <div className="grid-2" style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 14 }}>
        {credit.map(card => {
          const m = card.bonus ? computeMiles(card) : { miles: 0, bonusMiles: 0, baseMiles: 0 };
          return (
            <div key={card.id} className="card" style={{ padding: 22, display: "flex", flexDirection: "column", gap: 16 }}>
              <div style={{ display: "flex", gap: 16, alignItems: "flex-start" }}>
                <CreditCard card={card} size="md"/>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 11, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em", fontWeight: 600 }}>Bonus category</div>
                  <div style={{ fontSize: 13.5, fontWeight: 500, color: "var(--text-1)", marginTop: 2 }}>{card.bonus.category}</div>
                  {card.bonus.kind === "ladys" && <LadysCategoryEditor card={card}/>}

                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginTop: 14 }}>
                    <div>
                      <div style={{ fontSize: 10, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em" }}>Bonus rate</div>
                      <div style={{ fontSize: 16, fontWeight: 600, color: "var(--text-1)", marginTop: 2, fontVariantNumeric: "tabular-nums" }}>{card.bonus.rate}<span style={{ fontSize: 11, color: "var(--text-muted)", fontWeight: 500 }}> mpd</span></div>
                    </div>
                    <div>
                      <div style={{ fontSize: 10, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em" }}>Statement</div>
                      <div style={{ fontSize: 16, fontWeight: 600, color: "var(--text-1)", marginTop: 2, fontVariantNumeric: "tabular-nums" }}>{fmt.sgd(card.statementBalance, { decimals: 0 })}</div>
                      <div style={{ fontSize: 10, color: "var(--text-muted)", marginTop: 2 }}>Due {card.dueDate}</div>
                    </div>
                  </div>
                </div>
              </div>

              <div style={{ height: 1, background: "var(--border-subtle)" }}/>

              <MilesProgressBar card={card} expanded/>

              <div style={{ display: "flex", justifyContent: "space-between", paddingTop: 4 }}>
                <div style={{ display: "flex", gap: 16 }}>
                  <div>
                    <div style={{ fontSize: 10, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em" }}>Bonus miles</div>
                    <div style={{ fontSize: 14, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--success)" }}>{fmt.miles(m.bonusMiles)}</div>
                  </div>
                  <div>
                    <div style={{ fontSize: 10, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em" }}>Base miles</div>
                    <div style={{ fontSize: 14, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-2)" }}>{fmt.miles(m.baseMiles)}</div>
                  </div>
                  <div>
                    <div style={{ fontSize: 10, color: "var(--text-muted)", textTransform: "uppercase", letterSpacing: "0.04em" }}>Total</div>
                    <div style={{ fontSize: 14, fontWeight: 700, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.miles(m.miles)}</div>
                  </div>
                </div>
                <button className="btn-ghost"><Icon name="external" size={12}/> Details</button>
              </div>
            </div>
          );
        })}
      </div>

      <div style={{ fontSize: 11, color: "var(--text-muted)", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em", marginTop: 4 }}>Debit cards</div>
      <div className="grid-4" style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14 }}>
        {debit.map(card => (
          <div key={card.id} className="card" style={{ padding: 16, display: "flex", flexDirection: "column", gap: 12 }}>
            <CreditCard card={card} size="md"/>
            <div>
              <div style={{ fontSize: 13, fontWeight: 500, color: "var(--text-1)" }}>{card.name}</div>
              <div style={{ fontSize: 11, color: "var(--text-muted)", marginTop: 2 }}>•••• {card.last4} · Debit</div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ============ ACCOUNTS / TRANSFERS ============
function AccountsView({ transferStyle = "linked", reimbStyle = "tagged" }) {
  const { ACCOUNTS, TRANSACTIONS } = window.FIN_DATA;
  const transfers = TRANSACTIONS.filter(t => t.type === "transfer");
  const reimbursables = TRANSACTIONS.filter(t => t.reimbursable);
  const totalNW = ACCOUNTS.reduce((s, a) => s + a.balance, 0);

  const banks = ACCOUNTS.filter(a => a.type === "bank");
  const investments = ACCOUNTS.filter(a => a.type === "investment");

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 12 }}>
        <div>
          <h1 style={{ fontSize: 24, fontWeight: 600, margin: 0, letterSpacing: "-0.02em", color: "var(--text-1)" }}>Accounts</h1>
          <div style={{ fontSize: 13, color: "var(--text-muted)", marginTop: 4 }}>Net worth: <strong style={{ color: "var(--text-1)", fontVariantNumeric: "tabular-nums" }}>{fmt.sgd(totalNW, { decimals: 0 })}</strong> across {ACCOUNTS.length} accounts</div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <button className="btn-ghost"><Icon name="swap" size={14}/> New transfer</button>
          <button className="btn-primary"><Icon name="plus" size={14}/> Add account</button>
        </div>
      </div>

      <div className="grid-2" style={{ display: "grid", gridTemplateColumns: "1.4fr 1fr", gap: 14, alignItems: "flex-start" }}>
        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <AccountGroup title="Bank accounts" accounts={banks}/>
          <AccountGroup title="Brokerages" accounts={investments}/>
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <TransferPanel transfers={transfers} style={transferStyle}/>
          <ReimbursementsPanel items={reimbursables} style={reimbStyle}/>
        </div>
      </div>
    </div>
  );
}

function TransferPanel({ transfers, style }) {
  const showTwoEntries = style === "split";

  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      <div style={{ padding: "16px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
          <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0, color: "var(--text-1)" }}>Recent transfers</h3>
          <span className="pill">{style === "split" ? "Split entries" : "Linked"}</span>
        </div>
        <div style={{ fontSize: 12, color: "var(--text-muted)", marginTop: 2 }}>
          {style === "split" ? "Two paired entries — outflow and inflow" : "Single transaction linking both accounts"}
        </div>
      </div>
      <div>
        {transfers.map(tx => {
          const from = getAccount(tx.fromAccount);
          const to = getAccount(tx.toAccount);
          if (showTwoEntries) {
            return (
              <div key={tx.id} style={{ borderBottom: "1px solid var(--border-subtle)", padding: "10px 20px", display: "flex", flexDirection: "column", gap: 8 }}>
                <div style={{ fontSize: 11, color: "var(--text-muted)" }}>{fmt.date(tx.date)}{tx.note && ` · ${tx.note}`}</div>
                <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  <Icon name="arrow-up" size={12} style={{ color: "var(--danger)" }}/>
                  <div style={{ flex: 1, fontSize: 12, color: "var(--text-2)" }}>Out — {from?.name}</div>
                  <div style={{ fontSize: 13, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>−{fmt.sgd(tx.amount, { decimals: 0 })}</div>
                </div>
                <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  <Icon name="arrow-down" size={12} style={{ color: "var(--success)" }}/>
                  <div style={{ flex: 1, fontSize: 12, color: "var(--text-2)" }}>In — {to?.name}</div>
                  <div style={{ fontSize: 13, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>+{fmt.sgd(tx.amount, { decimals: 0 })}</div>
                </div>
              </div>
            );
          }
          return (
            <div key={tx.id} style={{ padding: "12px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
                <div style={{ fontSize: 12, color: "var(--text-muted)" }}>{fmt.date(tx.date)}</div>
                <div style={{ fontSize: 13, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.sgd(tx.amount, { decimals: 0 })}</div>
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 5, padding: "3px 8px", borderRadius: 5, background: `${from?.color}15`, color: from?.color, fontWeight: 500 }}>
                  <span style={{ width: 5, height: 5, borderRadius: "50%", background: from?.color }}/>
                  {from?.name}
                </div>
                <Icon name="arrow-right" size={12} style={{ color: "var(--text-muted)" }}/>
                <div style={{ display: "flex", alignItems: "center", gap: 5, padding: "3px 8px", borderRadius: 5, background: `${to?.color}15`, color: to?.color, fontWeight: 500 }}>
                  <span style={{ width: 5, height: 5, borderRadius: "50%", background: to?.color }}/>
                  {to?.name}
                </div>
              </div>
              {tx.note && <div style={{ fontSize: 11, color: "var(--text-muted)", marginTop: 6 }}>↳ {tx.note}</div>}
            </div>
          );
        })}
      </div>
    </div>
  );
}

function ReimbursementsPanel({ items, style }) {
  const totalPending = items.filter(t => t.reimbursableStatus === "pending").reduce((s, t) => s + (t.reimbursableAmount || 0), 0);

  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      <div style={{ padding: "16px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
          <h3 style={{ fontSize: 14, fontWeight: 600, margin: 0, color: "var(--text-1)" }}>Reimbursements</h3>
          <span className="pill">{style === "tagged" ? "Status tag" : "Auto-net"}</span>
        </div>
        <div style={{ fontSize: 12, color: "var(--text-muted)", marginTop: 2 }}>
          <strong style={{ color: "var(--warning)", fontVariantNumeric: "tabular-nums" }}>{fmt.sgd(totalPending, { decimals: 0 })}</strong> pending payback
        </div>
      </div>
      <div>
        {items.map(tx => (
          <div key={tx.id} style={{ padding: "12px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
            <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 6 }}>
              <div style={{ fontSize: 13, fontWeight: 500, color: "var(--text-1)" }}>{tx.merchant}</div>
              <div style={{ fontSize: 13, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.sgd(tx.amount, { decimals: 0 })}</div>
            </div>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", fontSize: 11.5, color: "var(--text-muted)" }}>
              <span>{fmt.dateShort(tx.date)} · {tx.reimbursableFrom} owes {fmt.sgd(tx.reimbursableAmount, { decimals: 0 })}</span>
              {tx.reimbursableStatus === "pending" ? (
                <span style={{ display: "inline-flex", alignItems: "center", gap: 4, padding: "2px 8px", borderRadius: 5, background: "var(--warning-soft)", color: "var(--warning)", fontSize: 10.5, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em" }}>
                  <span style={{ width: 5, height: 5, borderRadius: "50%", background: "var(--warning)" }}/> Pending
                </span>
              ) : (
                <span style={{ display: "inline-flex", alignItems: "center", gap: 4, padding: "2px 8px", borderRadius: 5, background: "var(--success-soft)", color: "var(--success)", fontSize: 10.5, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.04em" }}>
                  <Icon name="check" size={10}/> Settled
                </span>
              )}
            </div>
            {style === "auto" && tx.reimbursableStatus === "settled" && (
              <div style={{ marginTop: 6, fontSize: 11, color: "var(--success)" }}>
                ↳ Net spend: {fmt.sgd(tx.amount - tx.reimbursableAmount, { decimals: 0 })}
              </div>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

function AccountGroup({ title, accounts }) {
  const total = accounts.reduce((s, a) => s + a.balance, 0);
  return (
    <div className="card" style={{ padding: 0, overflow: "hidden" }}>
      <div style={{ padding: "14px 20px", display: "flex", justifyContent: "space-between", alignItems: "center", borderBottom: "1px solid var(--border-subtle)" }}>
        <h3 style={{ fontSize: 12, fontWeight: 600, margin: 0, color: "var(--text-2)", textTransform: "uppercase", letterSpacing: "0.04em" }}>{title} <span style={{ color: "var(--text-muted)", fontWeight: 500 }}>· {accounts.length}</span></h3>
        <div style={{ fontSize: 14, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.sgd(total, { decimals: 0 })}</div>
      </div>
      {accounts.map(a => (
        <div key={a.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "12px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
          <div style={{ width: 32, height: 32, borderRadius: 8, background: `${a.color}1a`, color: a.color, display: "grid", placeItems: "center", flexShrink: 0 }}>
            <Icon name={a.type === "investment" ? "trending-up" : "card"} size={14}/>
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 13.5, fontWeight: 500, color: "var(--text-1)" }}>{a.name}</div>
            <div style={{ fontSize: 11, color: "var(--text-muted)", marginTop: 2 }}>
              {a.primary && "Primary · "}{a.type === "investment" ? "Brokerage" : "Bank"}
            </div>
          </div>
          <div style={{ textAlign: "right" }}>
            <div style={{ fontSize: 14.5, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.sgd(a.balance)}</div>
          </div>
        </div>
      ))}
    </div>
  );
}

// ============ INSIGHTS ============
function InsightsView() {
  const { CATEGORIES, TRANSACTIONS, MONTHLY_HISTORY } = window.FIN_DATA;
  const byCat = sumByCategory();
  const catData = CATEGORIES
    .map(c => ({ ...c, value: byCat[c.id] || 0 }))
    .filter(c => c.value > 0)
    .sort((a, b) => b.value - a.value);
  const total = catData.reduce((s, c) => s + c.value, 0);

  const byMerchant = {};
  TRANSACTIONS.filter(t => t.type === "expense" && t.date.startsWith("2026-04")).forEach(t => {
    byMerchant[t.merchant] = (byMerchant[t.merchant] || 0) + t.amount;
  });
  const topMerchants = Object.entries(byMerchant).map(([k, v]) => ({ merchant: k, amount: v })).sort((a, b) => b.amount - a.amount).slice(0, 8);

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: 20 }}>
      <div>
        <h1 style={{ fontSize: 24, fontWeight: 600, margin: 0, letterSpacing: "-0.02em", color: "var(--text-1)" }}>Insights</h1>
        <div style={{ fontSize: 13, color: "var(--text-muted)", marginTop: 4 }}>Patterns and trends in your spending</div>
      </div>

      <div className="card" style={{ padding: 22 }}>
        <SectionHeader title="12-month trend" subtitle="Expense vs income"/>
        <MonthlyChart data={MONTHLY_HISTORY} height={260}/>
      </div>

      <div className="grid-2" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }}>
        <div className="card" style={{ padding: 22 }}>
          <SectionHeader title="Category breakdown" subtitle="April 2026"/>
          <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
            {catData.map(c => (
              <div key={c.id}>
                <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 5 }}>
                  <span style={{ fontSize: 13, color: "var(--text-2)" }}>{c.name}</span>
                  <span style={{ fontSize: 13, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.sgd(c.value, { decimals: 0 })} <span style={{ color: "var(--text-muted)", fontWeight: 400 }}>({((c.value/total)*100).toFixed(0)}%)</span></span>
                </div>
                <HBar value={c.value} max={total} color={c.color}/>
              </div>
            ))}
          </div>
        </div>

        <div className="card" style={{ padding: 22 }}>
          <SectionHeader title="Top merchants" subtitle="Where your money went this month"/>
          <div style={{ display: "flex", flexDirection: "column" }}>
            {topMerchants.map((m, i) => (
              <div key={m.merchant} style={{ display: "flex", alignItems: "center", gap: 12, padding: "10px 0", borderBottom: i < topMerchants.length - 1 ? "1px solid var(--border-subtle)" : "none" }}>
                <div style={{ width: 22, height: 22, borderRadius: "50%", background: "var(--bg-muted)", color: "var(--text-muted)", display: "grid", placeItems: "center", fontSize: 11, fontWeight: 600 }}>{i + 1}</div>
                <div style={{ flex: 1, fontSize: 13, color: "var(--text-1)", fontWeight: 500 }}>{m.merchant}</div>
                <div style={{ fontSize: 13, fontWeight: 600, fontVariantNumeric: "tabular-nums", color: "var(--text-1)" }}>{fmt.sgd(m.amount, { decimals: 0 })}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// Lady's quarterly category editor — user mostly uses travel/food
function LadysCategoryEditor({ card }) {
  const { CATEGORIES } = window.FIN_DATA;
  const [editing, setEditing] = React.useState(false);
  const current = CATEGORIES.find(c => c.id === card.bonus.chosenCategoryId);
  const popular = ["food", "travel"];

  return (
    <div style={{ marginTop: 8 }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: editing ? 8 : 0 }}>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 6, padding: "3px 10px", borderRadius: 6, background: `${current?.color}1a`, color: current?.color, fontSize: 11.5, fontWeight: 600 }}>
          <span style={{ width: 6, height: 6, borderRadius: 1, background: current?.color }}/>
          Q2 2026 · {current?.name}
        </div>
        <button onClick={() => setEditing(!editing)} className="btn-ghost" style={{ fontSize: 11, padding: "3px 8px" }}>
          <Icon name="edit" size={11}/> {editing ? "Done" : "Change"}
        </button>
      </div>
      {editing && (
        <div style={{ display: "flex", flexWrap: "wrap", gap: 5, padding: 10, background: "var(--bg-muted)", borderRadius: 7 }}>
          {CATEGORIES.map(c => {
            const isPopular = popular.includes(c.id);
            const isCurrent = c.id === card.bonus.chosenCategoryId;
            return (
              <button key={c.id} onClick={() => { card.bonus.chosenCategoryId = c.id; card.bonus.category = c.name + " (chosen quarterly)"; setEditing(false); }}
                style={{
                  display: "inline-flex", alignItems: "center", gap: 5,
                  padding: "5px 9px", borderRadius: 6,
                  border: isCurrent ? `1.5px solid ${c.color}` : "1px solid var(--border-subtle)",
                  background: isCurrent ? `${c.color}15` : "var(--bg)",
                  color: isCurrent ? c.color : "var(--text-2)",
                  fontSize: 11, fontWeight: isCurrent ? 600 : 500, cursor: "pointer",
                  fontFamily: "inherit",
                }}>
                <span style={{ width: 5, height: 5, borderRadius: 1, background: c.color }}/>
                {c.name}
                {isPopular && <span style={{ fontSize: 9, opacity: 0.6, marginLeft: 2 }}>★</span>}
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { OverviewView, TransactionsView, CardsView, AccountsView, InsightsView });