Replace the WebView SPA handoff with the app's own native screens that call the
same JSON API — hitting the on-device server in local mode or the remote server
in server mode (same code, base URL switches). Uses the api.ts client built earlier.
- api.ts: typed getTracker/toggleBillPaid/createBill/logout + a shared authed
mutate() helper (fetches + echoes the CSRF token); SessionUser type.
- TrackerScreen.tsx: native monthly Tracker — month header, Paid/Needs-action/Bills/
Remaining stat tiles, prev/next month nav, and bill rows with a one-tap mark-paid
toggle that re-fetches. Loading/error/empty states. Currency + dates via Intl in
the WebView (Chromium — full ICU, unlike the embedded server).
- MainApp.tsx + app.css: native app shell (top bar + avatar) and a bottom tab bar
(Tracker built; Calendar/Insights/Account are placeholders/account for now).
- App.tsx: renders MainApp instead of window.location.replace to the SPA; native
auth for both modes (local login shows 'this device'); 401 bounces to login.
Verified on the x86_64 emulator: two-doors setup -> native login -> native Tracker
with live bills -> tap to mark paid -> tiles + row update. No WebView.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>