diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..05e3141
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,34 @@
+# Repository Guidelines
+
+## Project Structure & Module Organization
+
+Application code lives in `src/`. Next.js App Router pages and API route handlers belong in `src/app/`; reusable UI components are in `src/components/`; database access, query functions, hooks, authentication, and domain helpers are in `src/lib/`. Tests are separated into `src/__tests__/unit/` and `src/__tests__/integration/`. PostgreSQL schema and numbered SQL migrations live under `prisma/`, static assets under `public/`, operational scripts under `scripts/`, and design notes under `docs/`.
+
+Keep data flow consistent: API routes call query functions in `src/lib/queries.ts`, which use `queryRaw()` from `src/lib/db.ts`; client components access APIs through TanStack Query hooks in `src/lib/hooks.ts`.
+
+## Build, Test, and Development Commands
+
+- `npm ci` installs the locked dependency set (Node 22 is used in CI).
+- `npm run dev` starts the local Next.js development server.
+- `npm run build` creates a production build; `npm start` serves it.
+- `npm run lint` runs the Next.js ESLint configuration. Existing lint debt makes CI lint advisory, but new code should pass.
+- `npm test` runs fast unit tests.
+- `npm run test:setup` prepares the PostgreSQL test database using `.env.test`.
+- `npm run test:integration` runs database-backed tests.
+- `npm run test:all` runs both test suites.
+
+## Coding Style & Naming Conventions
+
+Use strict TypeScript, two-space indentation, semicolons, and double quotes, matching existing files. Name React components and types in PascalCase, functions and variables in camelCase, and files/routes in kebab-case. Use the `@/` alias for imports from `src/`. Preserve owner scoping and prefer transaction overrides with `COALESCE` in financial queries. Every API route must authenticate before accessing data.
+
+## Testing Guidelines
+
+Vitest is the test framework. Name tests `*.test.ts` and place pure logic tests under `unit/`; put PostgreSQL-dependent behavior under `integration/`. Add regression coverage for query, rule, reconciliation, and category changes. No numeric coverage threshold is configured; focus on meaningful edge cases and run `npm run test:all` before submitting database-related changes.
+
+## Database, Security & Configuration
+
+Add schema changes as the next numbered `prisma/migrations/NNNN_description/migration.sql`. Never commit `.env`, `.env.test`, raw statements in `dump/`, or other financial data. Consult `CLAUDE.md` and relevant `docs/` notes before changing splits, settlements, loans, reconciliation, or statement accounting.
+
+## Commits & Pull Requests
+
+History follows concise Conventional Commit-style subjects such as `feat(rules): preview rule changes`, `fix(trips): ...`, and `docs: ...`. Keep commits focused. Pull requests should explain behavior and data-model impact, link related issues, list validation commands, and include screenshots for UI changes. Ensure unit tests and the production build pass; call out any known lint warnings or migration steps.
diff --git a/docs/ui-information-architecture-review.md b/docs/ui-information-architecture-review.md
new file mode 100644
index 0000000..ca94b95
--- /dev/null
+++ b/docs/ui-information-architecture-review.md
@@ -0,0 +1,661 @@
+# UI and information architecture review
+
+**Date:** 2026-07-26
+**Status:** Review and redesign proposal — nothing implemented
+
+## Executive summary
+
+The July 19 UI refresh gave the app a cohesive and distinctive visual identity.
+The ink-and-copper palette, typography, financial number treatment, month spine,
+and transaction drill-downs are all strong foundations.
+
+The larger remaining issue is not appearance. It is information hierarchy.
+Analytics and Insights contain useful data, but they are reporting-heavy rather
+than decision-oriented. Shared communicates the immediate running balance, but
+the current settlement model prevents it from answering which expenses a payment
+settled, whether a trip is closed, or how the shared loan should be represented.
+
+The product should make four questions easy to answer:
+
+1. Am I financially okay?
+2. What changed and why?
+3. What needs my attention?
+4. Who owes what, and for which expenses?
+
+Today there is no single page that answers the first three. The app opens on
+Transactions and presents ten equally weighted navigation items.
+
+The recommended direction is:
+
+- Add an Overview as the default landing page.
+- Keep Analytics focused on historical exploration: **what happened?**
+- Rebuild Insights around decisions and attention: **what should I know or do?**
+- Rebuild Shared around settlement contexts: **who owes what, and why?**
+- Keep the shared loan as a separate ledger from shared consumption expenses.
+- Fix calculation and coverage inconsistencies before adding more visualisations.
+
+## Context reviewed
+
+This review covered:
+
+- The current Next.js pages and shared components.
+- Analytics SQL and API calculations.
+- Shared-expense balance and transaction queries.
+- `CLAUDE.md`.
+- `docs/shared-expenses-design.md`.
+- `docs/expense-baseline.md`.
+- Recent repository history.
+- Recent finance-app memories retrieved from OpenViking.
+
+The OpenViking history confirmed:
+
+- The July 19 redesign intentionally introduced the ink-and-copper theme,
+ Fraunces display type, month-spine navigation, top movers, category
+ sparklines, and heat-tinted ledger tables.
+- The user prefers a modern, high-fidelity interface and actionable analytics.
+- Later July 25–26 work changed the financial meaning under those screens:
+ split-aware personal spend, AUD-aware settlement, refund netting, loan
+ principal/interest separation, rule previews, and the proposed contextual
+ settlement model.
+- The preferred settlement model links payments to real transactions, separates
+ Household, Trip, and Historical contexts, and keeps the shared loan separate.
+
+## What already works
+
+### Visual system
+
+- The dark ink-and-copper theme is coherent and distinctive.
+- Serif headings and mono financial figures create useful hierarchy.
+- The copper accent is used consistently for selection and emphasis.
+- The design feels like one application rather than a collection of unrelated
+ pages.
+
+### Analytics interactions
+
+- The month spine is an effective year-at-a-glance navigation control.
+- “What changed” is more useful than a generic category chart.
+- Category sparklines make direction visible without creating a large
+ multi-series chart.
+- Category rows can be expanded into their transactions.
+- Inline recategorisation allows users to correct the data while investigating
+ it.
+
+### Shared workflow
+
+- “Owes you,” “you owe,” and “all square” communicate the immediate relationship
+ balance clearly.
+- Payment history is preserved rather than reducing settlement to a boolean.
+- Participant and tag filters support practical investigation.
+- Split transactions can be edited without returning to the main transaction
+ page.
+
+## App-wide information architecture
+
+### Current problem
+
+The app redirects `/` to `/transactions`. This makes the operational ledger the
+default product surface. Transactions are important, but they do not tell the
+user whether anything needs attention or what the current financial position
+means.
+
+The sidebar also gives equal weight to:
+
+- operational screens such as Reconcile;
+- analytical screens such as Analytics;
+- configuration screens such as Rules;
+- organisational screens such as Tags.
+
+This makes the product feel like a database administration interface even when
+the individual pages are well designed.
+
+The `/budget` route is labelled Analytics in navigation. This is a leftover from
+an older product concept and should become `/analytics`.
+
+### Recommended navigation
+
+Group navigation by intent:
+
+**Overview**
+
+- Overview
+
+**Money**
+
+- Transactions
+- Statements
+- Reconcile
+
+**Understand**
+
+- Analytics
+- Insights
+- Merchants
+
+**Shared**
+
+- Shared
+- Trips
+- Loan
+
+**Organise**
+
+- Tags
+- Rules
+
+Lower-frequency configuration items can be visually separated or collapsed.
+
+### Recommended Overview
+
+The default landing page should be a concise status and attention surface, not
+another full analytics dashboard.
+
+Suggested structure:
+
+1. **This month**
+ - Personal spend to date
+ - Expected baseline at this point in the month
+ - Income
+ - Net cash
+
+2. **Financial resilience**
+ - Realistic monthly baseline
+ - Cash coverage in months
+ - Redraw shown separately from cash
+
+3. **Needs attention**
+ - Uncategorised or `other` transactions
+ - Unreconciled transactions
+ - Statements failing balance assertions
+ - New or unusual recurring charges
+ - Shared expenses added since the last settlement
+
+4. **Shared**
+ - Current balances by person and context
+ - Loan contribution shortfall shown separately
+
+5. **Recent change**
+ - The two or three categories that explain the largest movement
+
+The Overview should link into Analytics, Insights, Shared, and Reconcile rather
+than reproduce their complete tables.
+
+## Analytics review
+
+### What the current page does
+
+The current Analytics page includes:
+
+- selected-month spend hero;
+- twelve-month month spine;
+- income, expenses, invested, and net-cash strip;
+- top category movers;
+- eight category sparkline cards;
+- spend-concentration Pareto chart;
+- cumulative spend pace;
+- expandable category table;
+- six-month heat-tinted category ledger.
+
+Each component is defensible in isolation. Together, they create too many
+competing summaries of the same category data.
+
+### What Analytics should answer
+
+Analytics should answer:
+
+> What happened during this period, how does it compare, and what explains the
+> difference?
+
+Recommended primary structure:
+
+1. Period and comparison controls.
+2. Personal spend, income, invested, and net cash.
+3. Explanation of the change versus the selected comparison.
+4. One main category/trend visualisation.
+5. Category breakdown with transaction drill-down.
+6. An optional Explore section for detailed tables.
+
+### Recommended removals and consolidation
+
+- Keep either category sparklines or the six-month ledger as the primary
+ category-trend representation, not both.
+- Move the Pareto chart behind an Explore section. It describes concentration
+ but rarely produces an immediate decision.
+- Retain “What changed,” but make each item clickable and explain which
+ transactions caused the movement.
+- Avoid comparing a partial current month with full prior months unless values
+ are projected or compared through the same day.
+- Add gross-versus-personal-share switching only if it is clearly labelled.
+ Personal share should remain the default.
+
+### Calculation and trust issues
+
+#### Reconciled source rows can be double-counted
+
+`/api/analytics/monthly` does not currently exclude manual source rows where
+`reconciled_with_id IS NOT NULL`. The baseline analysis identified 48
+double-counted rows.
+
+The analytics query should apply the same reconciled-row exclusion used by the
+main transaction queries.
+
+#### Spend pace compares unlike numbers
+
+The Analytics headline uses:
+
+- split-adjusted personal share;
+- fees and interest;
+- refund and credit netting;
+- loan interest rather than principal;
+- non-spend-category exclusions.
+
+The cumulative spend-pace chart uses only `transaction_type === "debit"` and
+adds gross `amount_aud ?? amount`. It does not use personal share and does not
+apply the same refund, fee, interest, or loan semantics.
+
+The chart can therefore disagree with the headline while both appear to
+represent “spend.” The cumulative series should be produced by the same
+server-side spend semantics as the monthly total.
+
+#### Split coverage changes mid-series
+
+Reliable in-app split data begins on 2026-01-09. A trailing twelve-month personal
+series currently combines older gross spending with newer split-adjusted
+spending.
+
+Until historical splits are restored:
+
+- default personal trend analysis to February–June 2026;
+- visibly mark periods with incomplete split coverage; or
+- offer gross-only twelve-month comparison separately.
+
+Do not present the mixed series as one comparable personal-spend trend.
+
+#### Comparison baseline is too naive
+
+The selected month is compared against the average of all other months with
+data. That average can include travel, annual fees, tax payments, incomplete
+current periods, and months with incompatible split coverage.
+
+Better comparison choices:
+
+- previous month;
+- same month last year;
+- median of comparable complete months;
+- recurring baseline;
+- user-selected comparison.
+
+### Data trust indicator
+
+Analytics should include a compact methodology and coverage indicator:
+
+> Personal share · refunds netted · investments excluded · split coverage
+> reliable from Feb 2026 · 12 transactions need classification
+
+This makes the meaning of the numbers inspectable without overwhelming the page.
+
+## Insights review
+
+### Current problem
+
+The current Insights page contains:
+
+- Regular versus occasional spending;
+- another monthly category breakdown;
+- recurring charges;
+- fees and interest.
+
+The monthly breakdown duplicates Analytics. The page does not yet surface the
+most decision-relevant findings already known from the data: sustainable monthly
+cost, liquidity, the loan-overpayment lever, data-quality weaknesses, or unusual
+changes requiring attention.
+
+### “Regular” is not the same as committed or essential
+
+`REGULAR_CATEGORIES` includes:
+
+- groceries;
+- dining;
+- transport;
+- health;
+- personal care;
+- government;
+- charity;
+- pets.
+
+These may recur, but they have very different flexibility and obligation.
+“Regular” describes transaction behaviour, not financial necessity.
+
+The current chart therefore cannot answer:
+
+- What is the minimum monthly cost?
+- What can be cut?
+- What is contractually committed?
+- What is lifestyle spending?
+- What is a one-off?
+
+### Recommended model
+
+Replace Regular versus Occasional with:
+
+1. **Fixed commitments**
+ - Contracted loan repayment
+ - Insurance
+ - Rates and registration
+ - Known annual fees
+ - Contractual subscriptions
+
+2. **Essential variable spending**
+ - Utilities
+ - Groceries
+ - Transport
+ - Health
+
+3. **Lifestyle and discretionary**
+ - Dining
+ - Shopping
+ - Entertainment
+ - Personal care
+
+4. **One-offs and travel**
+
+5. **Investments and transfers**
+ - Shown for cashflow context, excluded from spending
+
+This should support scenario views rather than claiming there is one true
+baseline.
+
+### Recommended Insights structure
+
+#### 1. Financial baseline
+
+Show the scenarios already established by the expense-baseline analysis:
+
+- Survival: contracted loan repayment and essentials only.
+- Realistic: contracted loan repayment plus ordinary dining and charity.
+- Status quo: current loan overpayment and normal life excluding travel.
+
+For each scenario show:
+
+- monthly amount;
+- six-month reserve;
+- twelve-month reserve.
+
+#### 2. Liquidity and resilience
+
+Show:
+
+- cash available;
+- redraw available separately;
+- months covered under each baseline;
+- a warning that redraw is lender-controlled and not equivalent to cash.
+
+#### 3. Biggest flexible levers
+
+Examples:
+
+- voluntary loan overpayment;
+- dining;
+- shopping;
+- subscriptions;
+- travel.
+
+The loan should always show both the contracted floor and actual repayment.
+
+#### 4. Attention and anomalies
+
+Examples:
+
+- a new recurring charge;
+- a charge larger than its prior range;
+- a category materially above baseline;
+- a fee increase;
+- an unexpected incoming credit categorised as spend;
+- a merchant still classified as `other`;
+- an investment incorrectly counted as spending.
+
+Each insight should link directly to the affected transactions.
+
+#### 5. Data-quality work queue
+
+The baseline analysis found that data quality is currently a larger blocker than
+visualisation:
+
+- `other` remains a large unresolved category;
+- Raiz, Vanguard Super, and moomoo need investment classification;
+- incoming `other` credits can make spending negative;
+- `government` conflates tax with rates and registration;
+- annual fees distort short-window monthly averages.
+
+Insights should make these visible as fixable tasks.
+
+### Recurring charges
+
+The current detector identifies merchants with regular transaction intervals.
+That does not necessarily mean a subscription or commitment. Weekly grocery
+shopping can look recurring.
+
+Recommended changes:
+
+- Rename the section **Recurring patterns** unless contractual charges can be
+ distinguished.
+- Show confidence and the basis for classification.
+- Show the next expected charge date.
+- Separate likely subscriptions from recurring merchants.
+- Allow dismissing or confirming a detected pattern.
+- Highlight price changes.
+- Collapse inactive patterns by default.
+
+The current eight-column table is also too wide for a primary page. Put secondary
+fields such as first seen, total paid, and count into an expandable detail row.
+
+### Fees and interest
+
+The current fees query aggregates statement summary values across all available
+statements without a date filter. The UI does not label the period, so the total
+looks like a current-period figure even though it is effectively lifetime to
+date.
+
+Recommended presentation:
+
+- Explicit date range.
+- Avoidable fees.
+- Known annual fees.
+- Credit-card interest.
+- Loan interest.
+- Change versus prior comparable period.
+- Drill-down transactions.
+
+Loan interest should remain spending, but appear under fixed or
+non-discretionary costs rather than being hidden.
+
+## Shared review
+
+### What the current page answers well
+
+The unfiltered balance cards correctly implement a running ledger:
+
+> splits minus payments
+
+This is coherent and should not be changed to exclude splits marked `settled`.
+The `transaction_splits.settled` field is dead data and must not be used for new
+UI claims.
+
+### What the current model cannot answer
+
+- Which split expenses did a payment settle?
+- Is a particular trip settled?
+- Can a trip be closed without closing Household?
+- Is an imported offset-account credit already represented by a manual payment?
+- What remains open inside one settlement context?
+- How should the shared-loan contribution shortfall be shown?
+
+The page should not imply answers that the data model cannot support.
+
+### Tag-filtered balance cards are semantically misleading
+
+When a tag filter is active, participant balance queries intentionally stop
+subtracting payments because payments are not attributable to a tag. The cards
+then show raw split totals for the tag.
+
+This behavior is explained in small text, but the card still says “owes you” or
+“you owe.” That looks like a real payable balance when it is not.
+
+When filtered, relabel the cards:
+
+> Split total in Europe 2026
+
+Do not show payment or settlement actions from that state.
+
+### Recommended settlement-context design
+
+Use explicit settlement contexts:
+
+- Household
+- Individual trips
+- Historical / Pre-2026
+- Closed contexts
+
+Recommended Shared navigation:
+
+- All
+- Household
+- Trips
+- Closed
+
+Within a context show:
+
+1. Net balance and direction.
+2. Expenses added since the last settlement.
+3. Payments attributed to that context.
+4. A chronological activity ledger combining expenses and payments.
+5. Context status: running, ready to settle, or closed.
+6. Settlement action.
+
+### Payments should link to transactions
+
+An offset-account credit and a manual `split_payments` row can represent the same
+money. The page should:
+
+- propose matching an imported credit to a settlement;
+- display the linked transaction;
+- prevent silent duplication;
+- allow a manual payment only when no matching transaction exists.
+
+“Record Payment” should become a context-aware settlement flow:
+
+1. Choose what is being settled.
+2. Match an existing incoming transaction where possible.
+3. Confirm amount and residual balance.
+4. Preserve an auditable history.
+
+### Shared transaction table
+
+The table currently shows raw `tx.amount` with a dollar sign and no currency
+indicator. Participant balances correctly convert to AUD.
+
+For foreign transactions, show:
+
+- the native amount and currency;
+- the AUD equivalent;
+- splits based on the AUD settlement amount.
+
+This prevents a visible mismatch between transaction rows and participant
+balances.
+
+### Shared loan
+
+The loan is not a shared-expense settlement context. It funds an asset rather
+than consumption, and a loan contribution must never settle a dinner or utility
+bill.
+
+Give it a separate page or clearly separated ledger showing:
+
+- expected contribution by period;
+- actual contribution;
+- running shortfall or receivable;
+- principal reduction;
+- interest expense;
+- contracted repayment;
+- actual repayment;
+- voluntary overpayment;
+- redraw movement.
+
+The partner obligation is a fixed 50% of the repayment schedule, not a percentage
+inferred from actual contributions.
+
+## Responsive and interaction improvements
+
+- Replace wide eight-column primary tables with compact rows and expandable
+ details.
+- Keep financial summaries readable at mobile widths without horizontal
+ scrolling.
+- Add explicit loading skeletons rather than only text.
+- Add error states for failed analytics requests.
+- Ensure chart meaning is not conveyed by colour alone.
+- Give interactive chart regions keyboard-accessible equivalents.
+- Confirm material deletions, including payment-history deletion.
+- Make expandable table rows use buttons with appropriate accessibility state.
+- Use consistent labels for personal share, gross amount, native currency, and
+ AUD equivalent.
+
+## Recommended implementation order
+
+### Priority 0 — metric integrity
+
+1. Exclude reconciled source rows from monthly analytics.
+2. Make spend pace use the same spend semantics as the headline.
+3. Add date ranges to fees and interest.
+4. Add split-coverage warnings to historical personal-share analysis.
+5. Fix Shared foreign-currency presentation.
+6. Avoid partial-month versus full-month comparisons.
+
+### Priority 1 — product hierarchy
+
+1. Add Overview and make it the default route.
+2. Group sidebar navigation by user intent.
+3. Rename `/budget` to `/analytics`.
+4. Add consistent methodology and coverage indicators.
+
+### Priority 2 — Analytics and Insights
+
+1. Simplify Analytics around period, comparison, change explanation, trend, and
+ drill-down.
+2. Remove the duplicate monthly breakdown from Insights.
+3. Add baseline scenarios and liquidity coverage.
+4. Add flexible-spending levers, anomalies, and a data-quality work queue.
+5. Rework recurring patterns and fees into decision-oriented summaries.
+
+### Priority 3 — Shared
+
+1. Add settlement contexts.
+2. Link payments to real transactions.
+3. Add context activity ledgers and closeable trip contexts.
+4. Introduce the separate loan contribution ledger.
+5. Backfill historical closed-context splits so long-range personal analytics
+ become comparable.
+
+### Priority 4 — polish
+
+1. Improve mobile layouts.
+2. Add accessibility semantics.
+3. Add richer loading, error, and empty states.
+4. Consolidate repeated card, table, filter, and page-header patterns into shared
+ components.
+
+## Proposed success criteria
+
+The redesign is successful when:
+
+- The first page explains current status and outstanding actions without opening
+ multiple screens.
+- Analytics can explain why one comparable period differs from another.
+- Insights identifies baseline cost, financial resilience, flexible levers, and
+ data-quality problems.
+- Every displayed total states or clearly implies its period and whether it is
+ gross or personal share.
+- Historical charts do not silently combine incompatible split coverage.
+- Shared can distinguish Household, Trip, and Historical balances.
+- A settlement can be traced to both the obligation it reduces and the real
+ transaction representing the payment.
+- Loan contributions cannot affect ordinary shared-expense balances.
+
diff --git a/src/__tests__/fixtures/orders/real/ue-mixed.html b/src/__tests__/fixtures/orders/real/ue-mixed.html
new file mode 100644
index 0000000..7f9885d
--- /dev/null
+++ b/src/__tests__/fixtures/orders/real/ue-mixed.html
@@ -0,0 +1,250 @@
+
+
\ No newline at end of file
diff --git a/src/__tests__/unit/order-ingestion.test.ts b/src/__tests__/unit/order-ingestion.test.ts
index c51c44d..a617d9a 100644
--- a/src/__tests__/unit/order-ingestion.test.ts
+++ b/src/__tests__/unit/order-ingestion.test.ts
@@ -164,3 +164,20 @@ describe("order_reference anchoring", () => {
expect(p.flags).toContain("order_uuid_ambiguous");
});
});
+
+describe("mixed Uber payment (issuer-named card leg)", () => {
+ it("captures both legs when the card is labelled by issuer, not brand", () => {
+ // Real receipt: Uber Cash $1.17 + Westpac ••••8032 $15.33 = $16.50.
+ // A brand allowlist (Visa|MasterCard|Amex) misses "Westpac" and drops the
+ // card half, leaving payments that do not account for the total.
+ const p = parseOrderHTML(
+ readFileSync(resolve(dir, "ue-mixed.html"), "utf-8"),
+ meta({ subject: "Your Friday morning order with Uber Eats", sender: "uber.com", receivedAt: "2026-01-09T09:26:44Z" })
+ );
+ expect(p.totals.total_charged).toBeCloseTo(16.50, 2);
+ expect(p.payment.credits_amount).toBeCloseTo(1.17, 2);
+ expect(p.payment.card_amount).toBeCloseTo(15.33, 2);
+ expect(p.payment.card_last4).toBe("8032");
+ expect(validateOrderTotals(p).ok).toBe(true);
+ });
+});
diff --git a/src/lib/order-parse.ts b/src/lib/order-parse.ts
index 8dec904..dfd9c8d 100644
--- a/src/lib/order-parse.ts
+++ b/src/lib/order-parse.ts
@@ -226,8 +226,14 @@ function parsePayment(platform: string, html: string, text: string): PaymentBrea
const cash = text.match(/Uber Cash\s*(?:[A-Z]{3})?\s*\$?([\d,]+\.\d{2})/i);
if (cash) out.credits_amount = money(cash[1]);
+ // Anchor on the masking, not on a list of card brands. Uber labels the card
+ // leg with whatever the issuer is called — "Westpac ••••8032 $15.33",
+ // "Mastercard ••••3893 (CBA Ultimate) CHF 51.23" — so a brand allowlist
+ // silently drops the card half of a mixed payment. Found in the backfill
+ // dry-run: Uber Cash $1.17 + Westpac ••••8032 $15.33 against a $16.50 total,
+ // which validateOrderTotals correctly refused rather than under-recording.
const card = text.match(
- /(?:Visa|MasterCard|American Express|Amex)[^\d]*(\d{4})[^\d]*(?:[A-Z]{3})?\s*\$?([\d,]+\.\d{2})/i
+ /(?:••••|\*{4}|\u2022{4})\s*(\d{4})[^\d]{0,40}?\$?\s*([\d,]+\.\d{2})/
);
if (card) {
out.card_last4 = card[1];