Add Positive Pay, statement guide v1.0, onboarding, and switch every feature on

- Positive Pay on the 12 Oct /pps contract (account number, not account ID):
  OTP enrollment, cheque submit, saved cheques, detail and stop payment.
  Full flow passed on the phone against mobile-banking-backend.lincpay.
- Statement & Mini Statement guide v1.0 (14 Oct): mini statement JSON on
  Home and the Statement screen; dated PDF export with the password rule.
- Onboarding slides and splash screen, Inter font, shared Icon and
  TypewriterText components, nearby branches via OpenStreetMap.
- Every feature switched on; the 14 Oct switch set is kept in
  featureConfig.stage-2026-10-14.ts. Loans run on demo data until the
  backend has /loans routes.
- npm run android wraps run-android for shells spawned from VS Code.
- OpenProject work packages updated to 14-10-2026 status, with screenshots
  of Positive Pay, statement, loans and cards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Abin Toppo
2026-10-14 18:18:40 +05:30
co-authored by Claude Opus 5.5
parent 5fbd13ba12
commit f960a119e8
510 changed files with 20268 additions and 6483 deletions
+16 -12
View File
@@ -220,18 +220,22 @@ const checkRamp = (ramp, rampName) => {
add(sep >= TINT_SEPARATION, `category.${hue} tint distinct from surface`, sep, TINT_SEPARATION);
}
// The on-brand tiers, against the LIGHTEST stop of the wash — the worst case.
const wash = ramp.brandGradient[0];
for (const tier of ['onBrandPrimary', 'onBrandSecondary', 'onBrandMuted']) {
const r = ratio(ramp[tier], wash);
add(r >= AA, `${tier} on the brand wash`, r, AA);
}
// And solid white on each translucent fill — the tiers do not stack, so a
// fill always carries the solid tone.
for (const fill of ['onBrandSurface', 'onBrandSurfaceStrong']) {
const composited = composite(ramp[fill], wash);
const r = ratio(ramp.onBrandPrimary, composited);
add(r >= AA, `onBrandPrimary on ${fill}`, r, AA);
// The on-brand tiers, against the LIGHTEST stop of each wash — the worst
// case. `heroGradient` carries the same tiers (the account card, a promo
// banner), so it is held to the same bar.
for (const gradient of ['brandGradient', 'heroGradient']) {
const wash = ramp[gradient][0];
for (const tier of ['onBrandPrimary', 'onBrandSecondary', 'onBrandMuted']) {
const r = ratio(ramp[tier], wash);
add(r >= AA, `${tier} on ${gradient}`, r, AA);
}
// And solid white on each translucent fill — the tiers do not stack, so a
// fill always carries the solid tone.
for (const fill of ['onBrandSurface', 'onBrandSurfaceStrong']) {
const composited = composite(ramp[fill], wash);
const r = ratio(ramp.onBrandPrimary, composited);
add(r >= AA, `onBrandPrimary on ${fill} over ${gradient}`, r, AA);
}
}
return results;