Design overview
The mobile app's visual and interaction design is captured in a formal handoff from the design team. This section of the docs is the public surface: design language, tokens, components, and screens. The raw handoff — spec doc, interactive HTML prototype, screenshots, backlog — lives at apps/mobile/design/ in the repo, alongside the mobile code it informs.
Design language
"Tropical Modernist, paper-light." Three signature rules apply everywhere; nothing that ships breaks them.
1. The Shaka cut
Every rounded surface keeps one near-hard corner (bottom-left by default). Buttons, cards, chips, sheets — never uniform radii. This is non-negotiable brand DNA.
--r-btn: 26px 26px 26px 6px
--r-card: 24px 24px 24px 6px
--r-chip: 12px 12px 12px 3px
--r-sheet: 44px 14px 0 0 /* bottom sheet: big cut top-left */
See tokens for the full list.
2. Extreme weight contrast
Bricolage Grotesque 800 display sits directly against Hanken Grotesk 400 body. Nothing in between except functional 600/700 UI weights. No 500-weight anything.
3. Gradient discipline
The Shaka teal gradient (--shaka: linear-gradient(180deg, #00D4AA, #009B7A)) is sacred — it appears only on the logo mark and the payment-success burst. Never on buttons, cards, or decoration.
Other rules worth knowing
- Money values use tabular numerals (
.rd-num/font-variant-numeric: tabular-nums lining-nums) — always. Balances, amounts, FX rates, receipts. - Paper-grain overlay on light screens: SVG fractal noise at 5% opacity, user-disableable via
prefers-reduced-motion. - Dark screens are reserved for camera / scanner / mid-payment moments. Everything else is paper.
- Errors are calm — coral appears on the signal element (a card border, an icon) only, never as a full-screen alarm. Every error names what happened to the money first ("nothing left your balance").
- Fees are always shown, even when
$0.00— the transparency is the product. - All animations respect
prefers-reduced-motion— durations effectively zeroed.
Reconciliation with current architecture
The handoff was originally written against a product model where the app held a USDC balance and did FX at every deposit, payment, and withdraw. That model was replaced by the current Model A — see architecture/custody-model. Under Model A, Infinia holds the user's GBP or EUR balance directly and FX happens only at PIX payment time.
The design language, tokens, components, and screen structure transfer unchanged. What changes is money copy on a handful of screens. Full drift table in apps/mobile/design/README.md; short version:
| Screen | Handoff copy | Current-architecture copy |
|---|---|---|
| Home | USDC BALANCE · $142.50 | BALANCE · £142.50 (or €) |
| Confirm | 1 USDC = R$ 5,51 | £1 = R$ 5,80 · rate locked for 60s |
| Load | "Load USDC" — FX line + no-fee tag | "Add money" — show bank funding instructions, no FX |
| Withdraw | 1 USDC = £0.789 FX line | Same-currency withdraw, no FX line |
| Send | Contacts include on-chain USDC option | PIX-only; defer or drop the Send screen for MVP |
| Markets | Colombia / Mexico / Argentina / Bolivia marked "coming soon" | Brazil only in MVP; roadmap phasing is different — see product/roadmap § Geographic scope |
What transfers unchanged: everything about how it looks and feels — the tokens, the components, the screen layouts and micro-interactions, the slide-to-pay commit gesture, the scanner sequence timings, the success burst, the offline recovery pattern.
Cross-references
- tokens — colours, radii, typography, spacing, motion
- components — shared component patterns (buttons, slide-to-pay, keypad, chip rails, activity rows)
- screens — screen-by-screen with screenshots, cross-linked to backend flows
apps/mobile/design/— raw handoff (spec, prototype, screenshots, backlog)- flows/onboarding, flows/deposit, flows/pix-payment, flows/withdraw — what the backend does behind each screen