diff --git a/app/(consumer)/history/[id].tsx b/app/(consumer)/history/[id].tsx index aeb27cc..15ab7a6 100644 --- a/app/(consumer)/history/[id].tsx +++ b/app/(consumer)/history/[id].tsx @@ -15,6 +15,7 @@ import * as Haptics from 'expo-haptics'; import { Colors, Radius, Spacing, Typography } from '@/constants/theme'; import { ScreenHeader } from '@/components/shared/ScreenHeader'; import { Card } from '@/components/ui/Card'; +import { Money } from '@/components/ui/Money'; import { Button } from '@/components/ui/Button'; import { Icon, type IconName } from '@/components/ui/Icon'; import { BankLogo } from '@/components/ui/BankLogo'; @@ -147,9 +148,13 @@ export default function TransactionDetailScreen() { /> - - {isCredit ? '+' : '−'}₦{transaction.amount.toLocaleString()} - + {transaction.merchantName} @@ -392,10 +397,7 @@ const styles = StyleSheet.create({ justifyContent: 'center', marginTop: Spacing.lg, }, - amount: { - fontFamily: 'SpaceGrotesk_700Bold', - fontSize: Typography.displayMd.fontSize, - letterSpacing: Typography.displayMd.letterSpacing, + amount: { letterSpacing: Typography.displayMd.letterSpacing, marginTop: Spacing.lg, }, merchant: { diff --git a/app/(consumer)/rewards/index.tsx b/app/(consumer)/rewards/index.tsx index abaf279..e7a59a6 100644 --- a/app/(consumer)/rewards/index.tsx +++ b/app/(consumer)/rewards/index.tsx @@ -14,6 +14,7 @@ import { Colors, Radius, Spacing, Typography } from '@/constants/theme'; import { SectionTitle } from '@/components/shared/SectionTitle'; import { Button } from '@/components/ui/Button'; import { Icon } from '@/components/ui/Icon'; +import { Money } from '@/components/ui/Money'; import { EmptyState } from '@/components/shared/EmptyState'; import { useRewardsStore } from '@/store/rewards'; import { CASHBACK_RATES, CATEGORY_ICON, REWARD_POINT_VALUE } from '@/mock/data'; @@ -81,7 +82,7 @@ export default function RewardsScreen() { translate; showing what it is worth is the whole point of a rewards programme. */} Your points are worth - ₦{pointsValueNGN.toLocaleString()} + {points.toLocaleString()} pts · ₦{REWARD_POINT_VALUE.toFixed(2)} each @@ -280,11 +281,7 @@ const styles = StyleSheet.create({ paddingHorizontal: Spacing.xl, }, value: { - fontFamily: 'SpaceGrotesk_700Bold', - fontSize: Typography.displayLg.fontSize, lineHeight: Typography.displayLg.lineHeight, - letterSpacing: Typography.displayLg.letterSpacing, - color: Colors.onSurface, paddingHorizontal: Spacing.xl, marginTop: Spacing.xs, }, diff --git a/app/(consumer)/scan/success.tsx b/app/(consumer)/scan/success.tsx index aa64e9c..024a1a9 100644 --- a/app/(consumer)/scan/success.tsx +++ b/app/(consumer)/scan/success.tsx @@ -13,6 +13,7 @@ import { Colors, Radius, Spacing, Typography } from '@/constants/theme'; import { Card } from '@/components/ui/Card'; import { Button } from '@/components/ui/Button'; import { Icon } from '@/components/ui/Icon'; +import { Money } from '@/components/ui/Money'; import { usePaymentStore } from '@/store/payment'; function formatTime(date: Date) { @@ -75,7 +76,12 @@ export default function SuccessScreen() { Payment Sent! {transaction.merchantName} - ₦{transaction.amount.toLocaleString()} + @@ -175,11 +181,7 @@ const styles = StyleSheet.create({ color: Colors.onSurfaceVariant, marginTop: Spacing.xs, }, - amount: { - fontFamily: 'SpaceGrotesk_700Bold', - fontSize: Typography.displayMd.fontSize, - color: Colors.primary, - marginTop: Spacing.md, + amount: { marginTop: Spacing.md, }, pointsBadge: { flexDirection: 'row', diff --git a/app/(consumer)/sources/[id].tsx b/app/(consumer)/sources/[id].tsx index b90c1b9..6d57a19 100644 --- a/app/(consumer)/sources/[id].tsx +++ b/app/(consumer)/sources/[id].tsx @@ -8,6 +8,7 @@ import { SectionTitle } from '@/components/shared/SectionTitle'; import { Badge, type BadgeKind } from '@/components/ui/Badge'; import { Button } from '@/components/ui/Button'; import { Icon } from '@/components/ui/Icon'; +import { Money } from '@/components/ui/Money'; import { CryptoLogo, hasCryptoLogo } from '@/components/ui/CryptoLogo'; import { BankLogo } from '@/components/ui/BankLogo'; import { TransactionRow } from '@/components/shared/TransactionRow'; @@ -101,7 +102,11 @@ export default function SourceDetailScreen() { Balance - ₦{Math.round(source.balance).toLocaleString()} + {withheld > 0 ? ( ₦{Math.round(spendable).toLocaleString()} available · ₦ @@ -248,11 +253,7 @@ const styles = StyleSheet.create({ textTransform: 'uppercase', marginTop: Spacing.lg, }, - balance: { - fontFamily: 'SpaceGrotesk_700Bold', - fontSize: Typography.displayMd.fontSize, - color: Colors.onSurface, - marginTop: Spacing.xs, + balance: { marginTop: Spacing.xs, }, balanceSpendable: { fontFamily: 'Inter_400Regular', diff --git a/app/(merchant)/index.tsx b/app/(merchant)/index.tsx index 12e116c..c1482b8 100644 --- a/app/(merchant)/index.tsx +++ b/app/(merchant)/index.tsx @@ -9,6 +9,7 @@ import { QuickActions } from '@/components/shared/QuickActions'; import { EmptyState } from '@/components/shared/EmptyState'; import { Badge } from '@/components/ui/Badge'; import { Icon } from '@/components/ui/Icon'; +import { Money } from '@/components/ui/Money'; import { useMerchantStore } from '@/store/merchant'; import { fetchMerchantPayments, fetchSettlements } from '@/services/merchant'; import { REVENUE_LAST_7_DAYS } from '@/mock/merchant'; @@ -51,7 +52,7 @@ export default function MerchantHomeScreen() { TODAY'S REVENUE - ₦{todayRevenue.toLocaleString()} + @@ -134,11 +135,7 @@ const styles = StyleSheet.create({ textTransform: 'uppercase', marginTop: Spacing.xl, }, - revenue: { - fontFamily: 'SpaceGrotesk_700Bold', - fontSize: Typography.displayLg.fontSize, - lineHeight: Typography.displayLg.lineHeight, - color: Colors.onSurface, + revenue: { lineHeight: Typography.displayLg.lineHeight, marginTop: Spacing.xs, }, statsRow: { diff --git a/components/ui/Money.tsx b/components/ui/Money.tsx new file mode 100644 index 0000000..e362c57 --- /dev/null +++ b/components/ui/Money.tsx @@ -0,0 +1,95 @@ +import React from 'react'; +import { Text, StyleSheet, type TextStyle, type StyleProp } from 'react-native'; +import { Colors } from '@/constants/theme'; +import type { CurrencyCode } from '@/types/payment'; + +/** + * A currency amount set for display. + * + * Space Grotesk draws ₦ (U+20A6) with crossbars almost as heavy as its + * counters, and at Bold display weight the glyph both fills in and kerns + * straight into the following digit — "₦10" renders with the symbol and the 1 + * touching. The glyph is present in the font; it is simply not usable at this + * weight and size. Inter's ₦ at the same size is clean. + * + * So the symbol is set in Inter, slightly smaller than the digits and followed + * by a thin space, while the digits stay in Space Grotesk. Mixing a face for + * the currency mark is ordinary typographic practice, and it is the smallest + * change that fixes every large amount in the app at once. + * + * Only worth using at display sizes. In body copy Inter already sets both the + * symbol and the number, and there is nothing to correct. + */ + +const SYMBOL_SCALE = 0.72; +/** U+2009. Narrower than a word space — a gap, not a separation. */ +const THIN_SPACE = ' '; + +const SYMBOL: Partial> = { + NGN: '₦', + USD: '$', + GBP: '£', + EUR: '€', +}; + +export interface MoneyProps { + /** Amount in major units. */ + value: number; + currency?: CurrencyCode; + /** Font size of the digits; the symbol is scaled from this. */ + size: number; + color?: string; + /** Space Grotesk weight for the digits. */ + weight?: '500Medium' | '700Bold'; + /** Prefix shown before the symbol, e.g. a debit/credit sign. */ + sign?: string; + maximumFractionDigits?: number; + style?: StyleProp; + numberOfLines?: number; +} + +export function Money({ + value, + currency = 'NGN', + size, + color = Colors.onSurface, + weight = '700Bold', + sign, + maximumFractionDigits = 0, + style, + numberOfLines, +}: MoneyProps) { + const symbol = SYMBOL[currency] ?? ''; + const digits = value.toLocaleString(undefined, { maximumFractionDigits }); + + return ( + + {sign} + + {symbol} + + {THIN_SPACE} + {digits} + + ); +} + +const styles = StyleSheet.create({ + base: { + // Tightened tracking is what makes the collision visible in the first + // place, so it is not applied here; per-call-site style can still set it. + includeFontPadding: false, + }, + symbol: { + fontFamily: 'Inter_600SemiBold', + }, +}); diff --git a/docs/UI-REDESIGN-PRD.md b/docs/UI-REDESIGN-PRD.md new file mode 100644 index 0000000..b68e9c5 --- /dev/null +++ b/docs/UI-REDESIGN-PRD.md @@ -0,0 +1,516 @@ +# LenzPay UI Redesign — Product Requirements Document + +**Status:** Draft for design kickoff +**Audience:** Product design, UX research, product, engineering, compliance +**Platforms:** iOS and Android mobile apps +**Primary design constraint:** Retain LenzPay mint `#34FEA0` as the primary brand color +**Last updated:** 7 September 2026 + +## 1. Executive summary + +LenzPay is a payment vault that lets a customer pay in Nigerian naira using money held across multiple sources: Nigerian bank accounts, mobile wallets, USD accounts, cards, and crypto wallets. LenzPay can choose the best source automatically or split a payment across sources when one balance is insufficient. The product also includes transaction history, rewards, security controls, and a separate merchant experience for accepting QR payments and managing settlement. + +This project will redesign the mobile UI without changing the underlying product logic. The redesign should make a complex multi-source payment product feel simple, trustworthy, fast, and distinctly LenzPay. It must improve hierarchy, comprehension, consistency, accessibility, and cross-platform behavior while preserving the existing primary mint. + +The most important design outcome is confidence: before confirming a payment, a customer should understand who is being paid, how much will be paid, which source or sources will fund it, what conversion or transaction costs apply, and what happens next. + +## 2. Product context + +### 2.1 Core proposition + +**One payment identity across all of a user's money.** + +LenzPay enables customers to: + +- connect multiple financial sources; +- see their combined NGN-equivalent spending capacity; +- scan a merchant QR or enter bank/Lenz Tag details; +- let LenzPay automatically select a funding source; +- manually choose a source when desired; +- split a payment across eligible sources when necessary; +- review fees, FX, and funding details before authorization; +- authorize securely with PIN or biometrics; +- earn and redeem rewards; +- inspect and control security, limits, devices, and alerts. + +LenzPay enables merchants to: + +- complete business onboarding and verification; +- configure a settlement account; +- generate and share payment QR codes; +- monitor payments, revenue, analytics, and settlements; +- control accepted currencies and business settings. + +### 2.2 Target users + +#### Consumer + +A digitally active Nigerian customer who keeps money across banks, wallets, foreign-currency accounts, or crypto and wants a single, reliable way to pay locally. The customer may have uneven balances, may be sensitive to hidden fees, and needs strong reassurance about security and payment status. + +#### Merchant + +A Nigerian small-business owner or operator who wants to accept QR payments, confirm payment quickly, understand daily revenue, and know when funds will settle. + +### 2.3 User needs + +- “Help me pay without moving money between accounts first.” +- “Show me exactly where the money will come from.” +- “Do not surprise me with fees or exchange rates.” +- “Tell me clearly whether the payment succeeded, failed, or is still processing.” +- “Give me control when automatic selection is not what I want.” +- “Make security visible without making every task feel alarming.” +- “For merchants, make payment confirmation and settlement status unmistakable.” + +## 3. Problem statement + +The current app contains the necessary product capabilities, but its large screen set and dense financial information need a more unified experience. The redesign must address: + +- inconsistent visual hierarchy across onboarding, payment, account, reward, and merchant screens; +- the cognitive load of explaining automatic and split funding; +- insufficient distinction between balance, spendable balance, source currency, and NGN equivalent; +- the risk of users missing fees, FX rates, pending collection, or failure details; +- inconsistent empty, loading, disabled, error, success, and pending states; +- five-item tab structures that may compete with the primary payment action; +- the need for consistent patterns across iOS and Android, including edge-to-edge layouts and safe areas; +- a brand inconsistency between the product’s primary mint and the current app icon lime. + +## 4. Goals and success criteria + +### 4.1 Goals + +1. Make the path from intent to completed payment obvious and fast. +2. Make automatic and split funding understandable at a glance. +3. Increase confidence through transparent fees, FX, source, status, and security information. +4. Create one scalable design system for consumer and merchant experiences. +5. Preserve LenzPay’s recognizable mint while improving the supporting palette and hierarchy. +6. Deliver accessible, implementation-ready designs for both iOS and Android. + +### 4.2 Product metrics + +Baseline values should be captured before release. The redesign should target: + +- increased completion rate from payment initiation to successful payment; +- reduced abandonment on source selection and payment confirmation; +- reduced median time from QR recognition to payment authorization; +- fewer retries caused by unclear validation or failure recovery; +- increased successful source connections; +- increased comprehension of split funding in usability testing; +- no regression in merchant QR creation and settlement-task completion; +- accessibility audit pass for all critical flows. + +### 4.3 Usability targets + +In moderated testing, at least 4 of 5 representative users should be able to: + +- identify the total payment amount and payee without prompting; +- explain which account or accounts will fund the payment; +- identify any fee or FX cost before confirming; +- distinguish completed, pending, and failed payment states; +- recover from an insufficient-balance or declined-source scenario; +- add a new source and understand whether it is ready to use. + +## 5. Non-goals + +This redesign does not authorize changes to: + +- payment orchestration, source-ranking, split-allocation, FX, rewards, fraud, or settlement logic; +- regulatory or KYC requirements; +- backend contracts or provider capabilities; +- supported source types, currencies, or payment rails; +- consumer-to-merchant and merchant settlement business rules; +- the primary brand color. + +Designers may recommend product changes, but those recommendations must be separated from the implementation-ready redesign and reviewed by product and engineering. + +## 6. Brand and visual direction + +### 6.1 Non-negotiable brand color + +The primary color remains: + +- **Primary mint:** `#34FEA0` +- **Primary gradient endpoint:** `#0CEF93` +- **Text/icon on mint:** `#005C36` + +Use mint for primary actions, active navigation, selected states, progress, focus, and moments of positive brand emphasis. It should not fill every surface or compete with semantic status colors. + +The current app icon uses `#B5E61D`, a yellow-lime that does not match the product. The redesign should update the icon and related brand assets to the primary mint rather than change the interface to match the icon. + +### 6.2 Existing foundation + +The current product is dark-first and uses: + +- background: `#0E0E0F`; +- layered surfaces from `#131314` to `#2C2C2D`; +- Space Grotesk for display text and financial figures; +- Inter for body text, labels, and controls; +- purple for crypto/reward accents; +- green, amber, and red for success, pending, and failure; +- blue, orange, teal, and purple-blue as asset identifiers. + +Designers may refine the supporting neutrals, typography scale, spacing, radius, elevation, illustration style, and motion language. Any proposed light theme is an optional exploration and is not required for the initial handoff. + +### 6.3 Desired personality + +- confident, not loud; +- premium, not ornamental; +- modern African fintech, not generic crypto trading; +- transparent, not mysterious; +- calm under failure; +- precise with money and status. + +### 6.4 Color requirements + +- Semantic colors must never rely on color alone; pair them with labels and icons. +- Confirm text and icon contrast in every state, especially text placed on mint. +- Treat crypto/asset colors as identifiers, not primary action colors. +- Specify pressed, focused, disabled, loading, selected, and destructive variants. +- Avoid mint for failed, destructive, or warning actions. + +## 7. Experience principles + +1. **Money first.** Amount, currency, payee, source, and status receive the strongest hierarchy. +2. **Progressive disclosure.** Show the decision users need now; make detailed funding legs, rates, and guarantees available without overwhelming the primary task. +3. **Automation with an explanation.** “Auto” must always show what LenzPay selected and why, with a clear route to manual control. +4. **No financial ambiguity.** Distinguish available/spendable balance from ledger balance, native currency from NGN equivalent, and estimated values from final values. +5. **One obvious primary action.** Each screen should have a single dominant next step. +6. **Status is a system.** Loading, preparing, processing, pending, successful, partially collected, failed, and blocked states must look related but unmistakably different. +7. **Recovery over blame.** Error screens should explain what happened in plain language and offer the most useful next action. +8. **Secure by design.** Make verification and protection visible at decision points without adding unnecessary friction. + +## 8. Information architecture + +### 8.1 Consumer areas + +The existing consumer navigation contains Home, Scan, History, Rewards, and Security, with Sources, Notifications, and Profile as linked destinations. + +Design should test whether all five current tabs deserve equal weight. The payment action must remain the dominant destination. At minimum, provide a recommended navigation model and one rationale-backed alternative. + +Required consumer destinations: + +- Home/dashboard +- Pay: scan QR and enter account/Lenz Tag +- Payment history and transaction detail +- Sources and source detail +- Rewards, tiers, and redemption +- Security center, limits, devices, PIN, and alerts +- Notifications +- Profile, settings, FX rates, and support + +### 8.2 Merchant areas + +The existing merchant navigation contains Home, Payments, Analytics, Settlement, and QR, with Settings and Onboarding as linked destinations. + +Required merchant destinations: + +- Merchant home/dashboard +- Payment list and payment detail +- Analytics +- Settlement status and history +- Create/display/share QR +- Business settings +- Merchant onboarding and KYC + +### 8.3 Role handling + +Consumer and merchant modes must be visually related but clearly distinguishable. Designs must define how a user knows which mode is active and how role switching works if it is exposed in the product. + +## 9. Priority journeys + +### P0 — Must be designed first + +#### A. Consumer onboarding and account setup + +Welcome → create/sign in → OTP → create PIN → KYC → KYC pending → biometrics → consumer home. + +Requirements: + +- communicate the multi-source proposition in plain language; +- keep data-entry progress clear; +- show inline validation and preserve entered data when possible; +- explain why BVN, identity documents, camera access, and biometrics are requested; +- support keyboard, camera, permission-denied, retry, and pending-review states; +- do not imply that optional biometrics are mandatory. + +#### B. Scan-to-pay + +Scan QR → recognize merchant → enter/confirm amount → choose automatic/manual/split funding → review → PIN/biometric authorization → processing → success, pending, or failure. + +Requirements: + +- offer manual payment entry when camera access is unavailable; +- show merchant verification and identity clearly; +- support merchant-provided and customer-entered amounts; +- keep amount and payee visible throughout the flow; +- explain auto-selection and allow source changes; +- show split allocations as exact amounts per source; +- disclose fees, FX rate, total debit, rewards, and settlement expectations before authorization; +- prevent accidental navigation away while payment is being authorized or processed; +- provide specific recovery actions for insufficient funds, source failure, expired quote, limit exceeded, fraud review, and network interruption; +- make the receipt shareable and transaction reference easy to copy. + +#### C. Add and manage funding sources + +Sources → choose source type → connect bank/card/wallet/USD/crypto → verify/link → source detail → set default/priority/reserve/remove. + +Requirements: + +- distinguish source type, institution, account mask, currency, native balance, NGN equivalent, and spendable amount; +- communicate connection method and security before requesting credentials; +- identify source availability, freshness, capability, and sync status; +- make default, priority, and reserve behavior understandable; +- disclose crypto conversion spread before connection and payment; +- require clear confirmation for source removal. + +#### D. Merchant receives a payment + +Merchant onboarding → settlement setup → QR generation/share → payment received → payment detail → settlement tracking. + +Requirements: + +- make QR legible and usable at distance; +- support open-amount and fixed-amount QR states; +- make business identity and payment amount visible near the QR; +- distinguish customer payment success from merchant settlement completion; +- show pending settlement amount and expected timing; +- provide unmistakable real-time confirmation for received payments. + +### P1 — Complete before developer handoff + +- Consumer home/dashboard +- Payment history, filtering, empty state, and transaction detail +- Rewards overview, tiers, progress, earning history, and redemption +- Security overview, transaction limits, trusted devices, PIN change, and fraud alerts +- Notifications +- Profile, settings, live FX rates, and support +- Merchant dashboard, payments, analytics, settlement, and settings + +### P2 — Supporting states and polish + +- skeletons and loading states; +- offline and degraded-connectivity behavior; +- permission education; +- zero-data and first-use states; +- long names, large balances, small screens, and dynamic type; +- reduced-motion variants; +- app icon, splash, notification icon, and shareable receipt presentation. + +## 10. Screen-level requirements + +### 10.1 Consumer home + +Must prioritize: + +1. total available NGN-equivalent balance; +2. primary Pay/Scan action; +3. linked sources and their status; +4. recent transactions; +5. rewards summary; +6. alerts requiring action. + +Balance privacy/hide behavior should be explored. Avoid presenting an aggregate value without clarifying that it is an NGN equivalent and may include converted assets. + +### 10.2 Source selection and Smart Split + +For each source show institution/asset, account mask, spendable amount, currency, status, and relevant fee/FX implication. Automatic selection must have a visible recommendation rationale. Split funding must show a sum that reconciles exactly to the payment total. + +### 10.3 Confirmation + +The confirmation screen must show, above the authorization action: + +- payee and verification state; +- amount the payee receives; +- total amount debited; +- source or source breakdown; +- fee and conversion cost; +- FX rate and quote-expiry treatment when applicable; +- reward estimate; +- authorization method. + +No cost may first appear after authorization. + +### 10.4 Payment status and receipt + +Design distinct variants for: + +- preparing funds; +- processing; +- completed; +- completed with collection pending; +- failed before payee settlement; +- blocked for security review; +- interrupted/unknown status. + +The unknown-status state must tell users not to retry blindly and should direct them to check transaction history. + +### 10.5 History and transaction detail + +Transaction rows must expose direction, merchant/payee, amount, date, and status. Detail must show funding legs for split transactions, total fees, conversion details, pending collection, reference, and support/dispute entry points where applicable. + +### 10.6 Rewards + +Clearly separate points, naira value, cashback, current tier, next-tier progress, earning rates, and redemption methods. Do not present promotional value in a way that can be confused with withdrawable cash. + +### 10.7 Security + +The security center should give users a quick status overview and direct access to limits, devices, PIN, biometrics, and alerts. High-risk actions require explicit confirmation. Fraud alerts must prioritize payee, amount, time, reason, and “Was this you?” actions. + +### 10.8 Merchant dashboard + +Prioritize today’s received revenue, pending settlement, latest payments, and the Show/Create QR action. Analytics should support quick period comparison without resembling a speculative trading interface. + +## 11. Component and design-system requirements + +The Figma library must include documented variants for: + +- color, typography, spacing, radius, elevation, and icon tokens; +- primary, secondary, tertiary, destructive, and icon buttons; +- text inputs, amount inputs, OTP, PIN pad, search, selectors, and validation; +- cards, source cards, transaction rows, balance blocks, and statistic blocks; +- tabs/navigation, headers, sheets, modals, dialogs, and toasts; +- badges, chips, segmented controls, toggles, sliders, and progress; +- QR scanner viewport and QR display; +- chart styles, legends, tooltips, empty charts, and error states; +- skeleton, spinner, success, pending, warning, failure, and offline states; +- receipt and funding-breakdown patterns. + +Every interactive component must define default, pressed, focused, selected, disabled, loading, error, and success states where applicable. + +## 12. Content design + +- Use short, direct Nigerian English suitable for a broad financial-literacy range. +- Use “source” only after introducing it as an account or wallet used to fund payment. +- Prefer “Pay with” over internal orchestration terminology. +- Explain “Smart Split” the first time it appears. +- Never use “successful” if the final outcome is unknown. +- Pair error causes with a recovery action. +- Use consistent money formatting, currency codes, account masking, dates, and transaction references. +- Confirm whether the brand is written **LenzPay** or **Lenz Pay** and apply one convention consistently. The current interface uses both. + +## 13. Accessibility and inclusive design + +Designs must meet WCAG 2.2 AA where applicable and platform accessibility guidance. + +- Minimum touch target: 44 × 44 pt on iOS and 48 × 48 dp on Android. +- Body text should remain readable at supported dynamic font sizes without clipping. +- Primary information must not rely on color, animation, gesture, or sound alone. +- Define logical screen-reader order and accessible names for icons and financial values. +- Provide visible focus states for keyboard/switch navigation. +- Respect reduced motion and avoid essential information in transient animation. +- Support small Android screens, safe areas, display cutouts, and edge-to-edge layouts. +- Avoid low-contrast muted text for disclosures, fees, errors, and disabled controls. +- Camera-based payment must have a non-camera alternative. + +## 14. Motion and feedback + +Motion should explain state changes rather than decorate them. + +- Use subtle transitions when a source is selected or a split is calculated. +- Keep processing animation calm and pair it with text status. +- Use haptics for deliberate milestones such as successful scan, authorization, and payment completion. +- Do not use success motion until the payment state is confirmed. +- Provide reduced-motion alternatives for onboarding, charts, progress, and status animations. + +## 15. Platform requirements + +- Provide iOS and Android layouts or annotated differences where native behavior diverges. +- Account for Android edge-to-edge rendering and system bars. +- Specify keyboard behavior for forms and amount entry. +- Use native-feeling back behavior and prevent back navigation during irreversible payment steps. +- Design camera, biometric, settings, share-sheet, and permission transitions with platform conventions. +- Do not place essential actions inside unsafe or gesture-conflict areas. + +## 16. Required states + +Every applicable screen must include: + +- first use/empty; +- populated; +- loading/skeleton; +- refreshing; +- inline validation; +- disabled; +- permission denied; +- offline; +- recoverable error; +- non-recoverable or blocked state; +- success; +- pending/unknown status; +- long-content and large-text stress case. + +Financial screens additionally require stale balance/rate, expired quote, insufficient spendable balance, source unavailable, limit exceeded, partial/split funding, and pending collection states. + +## 17. Design deliverables + +1. Current-experience audit with usability and consistency findings. +2. Sitemap and revised consumer/merchant navigation recommendation. +3. End-to-end user-flow diagrams for all P0 journeys. +4. Low-fidelity wireframes covering P0 flows and major edge cases. +5. High-fidelity iOS and Android designs. +6. Clickable prototypes for consumer payment and merchant payment receipt. +7. Tokenized Figma design system with component variants. +8. Content/copy sheet covering labels, validation, errors, status, and disclosures. +9. Accessibility annotations and contrast report. +10. Motion specifications, including reduced-motion behavior. +11. Developer handoff with measurements, tokens, component behavior, asset exports, and state logic. +12. Updated app icon and launch assets using the retained primary mint. + +## 18. Handoff acceptance criteria + +The redesign is ready for implementation when: + +- all P0 and P1 screens and required states are represented; +- the primary mint remains `#34FEA0` and its usage is documented; +- all costs and source allocations appear before payment authorization; +- automatic and split payment concepts pass comprehension testing; +- designs cover iOS and Android differences; +- reusable components are linked to a Figma library rather than detached copies; +- text and controls pass agreed contrast and touch-target checks; +- long content, small screens, keyboard-open, loading, empty, and error cases have been validated; +- product, engineering, compliance, and accessibility reviewers approve the handoff; +- proposed product-logic changes are explicitly separated from visual/interaction changes. + +## 19. Suggested project phases + +### Phase 1 — Discovery and audit + +Review the running app, map flows, identify drop-off risks, interview stakeholders, and test the existing payment journey with representative consumers and merchants. + +### Phase 2 — Structure and critical flows + +Resolve navigation and prototype onboarding, source connection, scan-to-pay, Smart Split, confirmation, payment states, merchant QR, and settlement status. + +### Phase 3 — Visual system + +Define the refreshed visual language around the retained mint, create the component library, and validate accessibility. + +### Phase 4 — Full product application + +Apply the system to all P1 screens and supporting states, then complete iOS/Android adaptations. + +### Phase 5 — Validation and handoff + +Run usability testing, incorporate findings, complete annotations, and conduct product/engineering handoff reviews. + +## 20. Open questions for kickoff + +1. Is the redesign dark-only, or should designers explore a light theme? +2. Which audience is the launch priority: consumers, merchants, or both simultaneously? +3. Does one account support both consumer and merchant roles, and how should switching work? +4. Which payment methods and source integrations will be live at launch versus demonstrated only? +5. Are fees and FX spread included in the entered amount or added to the total debit? +6. What exact status language has compliance approved for pending collection and settlement? +7. Should balance privacy be enabled by default or controlled by the user? +8. What support and dispute actions will be available from transaction detail? +9. What analytics events and baseline conversion metrics currently exist? +10. Should the product name be standardized as “LenzPay” or “Lenz Pay”? + +## 21. Reference route inventory + +The current implementation includes approximately 50 screens across: + +- authentication and consumer KYC; +- consumer home, notifications, history, rewards, sources, scan/pay, security, profile, settings, rates, and support; +- merchant onboarding, home, payments, analytics, settlement, QR, and settings. + +Designers should use the running application and current route inventory as a functional reference, not as a constraint on hierarchy or presentation. Product behavior described in this PRD takes precedence over visual details in the current interface.