UI readability pass and Bazaar in-app purchase bridge

- muted text #9e9ec0 -> #727299 (contrast 2.6 -> 4.5 on white); tab labels 11px
- map: chapter titles wrap to two lines instead of being cut off
- reduced-motion respected (MotionConfig + CSS), focus-visible ring,
  no pull-to-refresh, short vibration on correct/wrong answers
- src/lib/bazaar.ts: bridge to the Android WebView wrapper; checkout uses
  Bazaar IAP only inside that app, Zarinpal everywhere else (unchanged)
- android/: WebView wrapper with Poolakey; written but never built

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 19:13:12 +03:30
parent adecf25486
commit f8cf86e4e8
19 changed files with 619 additions and 68 deletions

View File

@@ -21,7 +21,10 @@
--color-ink: #1a1a2e; /* متنِ اصلی */
--color-body: #3a3a5c; /* متنِ بدنه */
--color-muted: #9e9ec0; /* متنِ کم‌رنگ */
/* متنِ کم‌رنگ. تا ۲۰۲۶-۱۰-۰۳ ‎#9e9ec0 بود: کنتراست ۲٫۶ روی سفید، زیرِ حدِ ۴٫۵ِ WCAG، و
همین رنگ زیرنویسِ ۱۰–۱۲ پیکسلیِ همه‌ی صفحه‌ها و آیکونِ تب‌های غیرفعال است. این یکی
روی سفید ۴٫۵ و روی پس‌زمینه‌ی صفحه ۴٫۲ است. */
--color-muted: #727299;
--color-faint: #b0b0c8;
--color-line: #e9e6f7; /* حاشیه‌ی کارت */
--color-soft: #f0eeff; /* پس‌زمینه‌ی ملایم */
@@ -47,6 +50,30 @@
button:disabled {
cursor: not-allowed;
}
/* کشیدنِ صفحه به پایین در کروم اندروید کلِ اپ را رفرش می‌کرد (pull-to-refresh)
و وسطِ آزمون جوابِ جاری را می‌پراند؛ صفحه‌های داخلی خودشان اسکرول دارند. */
html, body {
overscroll-behavior: none;
}
/* حلقه‌ی فوکوس فقط برای صفحه‌کلید (focus-visible)، نه برای لمس. */
:focus-visible {
outline: 2px solid var(--color-indigo);
outline-offset: 2px;
}
}
/* کاربری که در تنظیماتِ گوشی «کاهشِ حرکت» را زده: انیمیشن‌ها و transitionهای CSS
تقریباً آنی می‌شوند. انیمیشن‌های motion را MotionConfig در App خاموش می‌کند. */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
@layer base {
input, textarea {
font: inherit;
}