diff --git a/README.md b/README.md
index 3ada8c30..6bf9b6bc 100644
--- a/README.md
+++ b/README.md
@@ -1,269 +1,183 @@
-
+
Closer
A private space for two.
- Private daily questions, intentional reveals, shared games, and calm rituals for couples.
+ Daily questions, mutual reveals, shared games, and calm rituals for couples.
-
-
-
-
-
-
-
-
+ Screenshots
+ ·
+ What makes it different
+ ·
+ Status
+ ·
+ Run locally
+ ·
+ QA
+
+
+
+
+ Android reference app · iOS scaffold in progress · Firebase backend · RevenueCat billing · Private repo
+
---
-> **Private daily questions for couples — end-to-end encrypted, never read, never sold.**
-> *You and your paired partner hold the only key.*
+Closer is a native relationship app for couples who want a quieter way to check in with each other.
+Each partner answers privately, reveals intentionally, and keeps a record of the conversations that
+matter.
-A native couples-relationship app that turns check-ins into small, intentional rituals: one daily question, curated conversation packs, private answers, mutual reveal, gentle reminders, shared games, and date planning — with **real E2EE** and **calmer UX**.
+It is not a social network, therapy replacement, or productivity tracker. There are no public feeds,
+likes, followers, or infinite-scroll loops. The product loop is small on purpose:
-Not a social network. Not therapy. Not a productivity tracker. **No public feeds, no likes, no followers, no infinite scroll.**
-
-The core loop is simple: *answer honestly → choose what to reveal → keep a record of the conversations that mattered.*
-
-## TL;DR
-
-| What | Why it matters |
-| --- | --- |
-| 🔐 **Real E2EE** | Answers **and chat messages** are encrypted on-device. Server only sees ciphertext. Couple-owned keys via Tink (Android). |
-| 💑 **One subscription per couple** | No double-billing partners. Premium unlocks for both — server-verified. |
-| 🚫 **No engagement traps** | No infinite scroll. No likes. No follower counts. One daily question is the loop. |
-| 🌗 **Decoupled theme + art** | In-app light/dark controls art; system theme isn't required to match. |
-| 📱 **Native on both platforms** | Kotlin/Compose on Android, SwiftUI on iOS — same Firebase backend, same data model. |
-| 🧪 **QA you can run** | `scripts/theme-scan.sh` (Pass C) and `scripts/wiring-scan.sh` (Pass N) catch the silent-dead-feature and theme-hardcoding classes before merge. |
-
----
+```text
+answer honestly -> reveal together -> keep the conversation going
+```
## Screenshots
Fresh Android dark-mode captures from the current emulator build.
-Daily question stages on Home:
+
+
+ | Ready |
+ Your turn |
+ Reveal ready |
+
+
+  |
+  |
+  |
+
+
-| Question Ready | Your Turn | Reveal Ready |
-| :---: | :---: | :---: |
-|
|
|
|
+
+
+ | Play |
+ This or That |
+ Today |
+ Challenge |
+
+
+  |
+  |
+  |
+  |
+
+
-Other core screens:
+## What makes it different
-| Play | This or That | Today | Challenge |
-| :---: | :---: | :---: | :---: |
-|
|
|
|
|
+
+
+ Private first Partners answer independently before seeing each other's response. |
+ Mutual reveal The app is built around intentional sharing, not performative posting. |
+ Couple-owned trust Android encrypts answers, chat, history, and media on-device with couple-owned keys. |
+
+
+ One subscription per couple Premium unlocks for both partners through server-verified entitlements. |
+ Curated prompts Question packs are written and reviewed, not generated at answer time. |
+ Calm by design No feeds, likes, followers, public profiles, or pressure mechanics. |
+
+
----
+## Product surface
-## Why Closer exists
-
-Subscription apps for couples have a trust problem — confusing trial wording, hard-to-cancel flows, partners getting double-billed. Couples products have a *different* trust problem: partners are asked to be vulnerable in the same space where everything else (social, productivity, dating) wants their engagement, their data, and their attention.
-
-Closer treats both the same way: **clear, straightforward, and built on honesty.**
-
-- 🪞 **Private first, reveal second.** Each partner answers independently. Both decide what to share.
-- 🧠 **Curated, not generated.** 6,000+ hand-written prompts across 22 categories — no AI confabulation in the core loop.
-- 💸 **One sub, not two.** Subscription unlocks for both partners. Server-verified. No silent trial conversions.
-- 🔒 **Encryption that earns the word.** Tink AEAD with couple-owned keys. Answers, messages, and history — server never sees plaintext. Recover with your phrase *or* your partner.
-- 🌙 **Quiet hours, server-side.** Partner pushes respect the *recipient's* in-app window — not just foreground detection.
-
----
-
-## What Closer does
-
-| Feature | Free | Premium |
+| Area | Free | Premium |
| --- | --- | --- |
-| Daily question (text / scale / multi / this-or-that) | ✅ | ✅ |
-| 6,000+ prompts · 22 question packs | ✅ (free) + 🎟️ (premium tiers) | ✅ (incl. premium-only packs) |
-| Private answers + mutual-reveal flow | ✅ | ✅ |
-| Spin the wheel — category-randomized questions | ✅ | ✅ |
-| Recent answer history (last 30 days) | ✅ | ✅ |
-| Full answer history (search, filter, export) | — | ✅ |
-| Saved spin-wheel sessions | — | ✅ |
-| Memory Lane (locked time capsules) | — | ✅ |
-| Desire Sync (preferences alignment exercise) | — | ✅ |
-| Select Connection Challenges (multi-day programs) | ✅ (free) + 🎟️ (premium tiers) | ✅ |
-| Push reminders with quiet-hour support | ✅ | ✅ |
-| Account deletion + data export | ✅ | ✅ |
+| Daily question | Included | Included |
+| Private answers + mutual reveal | Included | Included |
+| Curated question packs | Free + mixed access | Full access |
+| Spin the Wheel | Included | Included |
+| This or That / How Well Do You Know Me | Included | Included |
+| Recent answer history | Included | Included |
+| Memory Lane capsules | Limited | Full access |
+| Desire Sync | Limited | Full access |
+| Connection Challenges | Free + mixed access | Full access |
+| Date ideas, matches, and bucket list | Included | Premium ideas gated |
+| Push reminders + quiet hours | Included | Included |
+| Account deletion | Included | Included |
-One subscription unlocks premium for **both** partners — `couples/{coupleId}/entitlements` is per-couple, not per-user.
-
----
+Data export is not currently offered. The in-app privacy copy intentionally says so until a real export
+flow exists.
## Platform status
-| Platform | Stack | Status | Notes |
-| --- | --- | --- | --- |
-| **Android** | Kotlin · Jetpack Compose · Material 3 · Hilt · Room · DataStore | 🟢 **Reference implementation** | Feature-complete MVP, light/dark theme polished |
-| **iOS** | SwiftUI · MVVM · async/await · Firebase iOS SDK | 🟡 **Scaffold landed on `dev`** | Full screen parity; pairing from iOS is blocked until E2EE keys are wired (Android-only today) |
-| **Backend** | Firebase Auth · Firestore · Cloud Functions · FCM · App Check | 🟢 **Shared source of truth** | 17 callable/trigger/scheduled/webhook functions |
-| **Billing** | RevenueCat · Google Play Billing · StoreKit | 🟢 **Server-verified** | Webhook → Firestore entitlements → `CouplePremiumChecker` |
+| Platform | Status | Notes |
+| --- | --- | --- |
+| Android | Reference implementation | Kotlin, Jetpack Compose, Material 3, Hilt, Room, DataStore, Firebase, Tink |
+| iOS | Scaffold in progress | SwiftUI screen parity exists; pairing is blocked until E2EE interop is complete |
+| Backend | Shared source of truth | Firebase Auth, Firestore, Cloud Functions, FCM, App Check |
+| Billing | Server verified | RevenueCat webhook writes Firestore entitlements observed by the app |
-> 📐 iOS scaffold has **all 49 screens** mapped to SwiftUI views, Firebase + RevenueCat integration, and full screen parity on the `dev` branch. CryptoKit-based E2EE parity (interop with Android's Tink key material) is the only blocker for end-to-end iOS pairing.
+Android is the product source of truth today. iOS has the app shell, Firebase/RevenueCat integration,
+and SwiftUI screens, but end-to-end pairing waits on CryptoKit/Tink interoperability.
----
-
-## Architecture at a glance
+## Architecture
```text
- ┌──────────────────────────┐ ┌──────────────────────────┐
- │ Android (Kotlin/Compose)│ │ iOS (SwiftUI) │
- │ • Hilt DI · Room · DSK │ │ • MVVM · AppState · SPM │
- │ • Tink AEAD + Argon2id │ │ • CryptoKit (follow-up) │
- └────────────┬─────────────┘ └────────────┬─────────────┘
- │ │
- └──────────────┬─────────────────────┘
- │
- ┌──────────▼──────────┐
- │ Firebase │
- │ • Auth (email / │
- │ Google via │
- │ Credential Mgr) │
- │ • Firestore │
- │ (couple-scoped) │
- │ • Cloud Functions │
- │ • FCM │
- │ • App Check │
- │ (Play Integrity)│
- └──────────┬──────────┘
- │
- ┌──────────▼──────────┐
- │ RevenueCat │
- │ → webhook │
- │ → Firestore │
- │ entitlements │
- └─────────────────────┘
+Android (Kotlin/Compose) iOS (SwiftUI)
+Hilt · Room · DataStore MVVM · AppState · SPM
+Tink AEAD · Argon2id CryptoKit interop in progress
+ \ /
+ \ /
+ v v
+ Firebase + RevenueCat
+ Auth · Firestore · Functions · FCM
+ App Check · server-verified billing
```
-- **Couple-scoped data.** Firestore rules deny cross-couple reads/writes. Users only see their own + their partner's surface.
-- **Server-mediated pairing.** 6-character invite codes are enumerable; invite reads/writes are server-side only.
-- **Server-verified billing.** RevenueCat → Cloud Function webhook → Firestore `users/{uid}/entitlements/premium` → `CouplePremiumChecker` observes both partners' premium state.
-- **Local-first questions.** Prompts ship in the app so daily questions load instantly; only assignment and sync hit the network.
+Core rules:
----
+- Couple-scoped Firestore data. Users only read/write their own couple surface.
+- Server-mediated pairing. Invite lifecycle runs through Cloud Functions.
+- Local-first question content. Prompts ship with the app; assignment/sync uses Firebase.
+- Server-verified premium. Clients observe entitlements; they do not self-grant access.
+- No anonymous auth. Accounts use email/password or Google sign-in.
-## Tech stack
+## Security and privacy
-### Android
+- Android encrypts answer content, chat messages, media, capsules, and backed-up conversation history
+ on-device before sync.
+- The server stores ciphertext for private content and never receives plaintext answers.
+- Recovery phrase wrapping uses Argon2id-derived keys.
+- Partner-assisted restore lets a trusted partner help restore the couple key to a new device.
+- Quiet hours are enforced server-side before push delivery.
+- Account deletion exists; data export does not yet.
-| Layer | Stack |
-| --- | --- |
-| Language | Kotlin 2.x |
-| UI | Jetpack Compose · Material 3 · Navigation Compose |
-| Architecture | Clean architecture — `core/` · `data/` · `domain/` · `ui/` |
-| State | ViewModel · Kotlin Coroutines · Kotlin Flow |
-| DI | Hilt |
-| Local data | Room · DataStore Preferences · bundled SQLite seed |
-| Crypto | Google Tink AEAD + Argon2id (Bouncy Castle KDF) |
-| Auth | Firebase Auth · **Credential Manager** for Google Sign-In |
-| Build | min 26 · target 35 · compile 35 · Java 17 · KSP |
+The canonical technical reference is
+[docs/Engineering_Reference_Manual.md](docs/Engineering_Reference_Manual.md).
-### iOS
+## Local development
-| Layer | Stack |
-| --- | --- |
-| Language | Swift 6.0 |
-| UI | SwiftUI · NavigationStack · TabView |
-| Architecture | MVVM · `AppState` ObservableObject · `EnvironmentObject` |
-| Concurrency | async/await · Swift 6 strict concurrency |
-| Dependency management | Swift Package Manager · XcodeGen (`project.yml`) |
-| Auth | Firebase Auth · Google Sign-In SDK |
-| Crypto | Apple CryptoKit (E2EE parity — follow-up) |
-| SDK | iOS 17.0+ |
+
+Prerequisites
-### Backend (shared)
+- Android Studio, Android SDK, and JDK 17
+- Node 20 for Firebase Functions tooling
+- Firebase project with Auth, Firestore, Cloud Messaging, Crashlytics, Analytics, and App Check
+- `app/google-services.json`
+- RevenueCat project and Android API key
-| Layer | Stack |
-| --- | --- |
-| Auth | Firebase Authentication — **email/password · Google** (Android uses Credential Manager) |
-| Database | Cloud Firestore (couple-scoped rules) |
-| Server logic | Firebase Cloud Functions (TypeScript) |
-| Push | Firebase Cloud Messaging (FCM) |
-| Security | Firebase App Check · Play Integrity (Android) · DeviceCheck (iOS, planned) |
-| Billing | RevenueCat (server-verified entitlements) |
-| Analytics | Firebase Analytics · Crashlytics |
+For iOS work:
-> 🚫 **No anonymous auth.** There is no anonymous sign-in or account-linking flow in either platform. Accounts are email/password or Google.
+- macOS, Xcode 16, XcodeGen, and iOS 17+
+- `iphone/Closer/GoogleService-Info.plist`
+- RevenueCat iOS API key
----
+
-## Repository layout
-
-```text
-.
-├── app/ # Native Android app (Kotlin)
-│ └── src/main/java/app/closer
-│ ├── core/ # Firebase, analytics, billing, nav, notifications, security
-│ ├── data/ # Room, Firestore data sources, repositories, seed parsing
-│ ├── domain/ # Models + repository contracts
-│ └── ui/ # Compose screens + feature ViewModels
-├── iphone/ # Native iOS app (SwiftUI)
-│ ├── ARCHITECTURE_AUDIT.md # iOS port blueprint (49 screens, schema, models)
-│ ├── project.yml # XcodeGen project spec
-│ ├── Package.swift # SPM dependency manifest
-│ └── Closer/
-│ ├── Models/ # Firestore + domain codable types
-│ ├── Core/ # Auth · Billing · Notifications
-│ ├── Services/ # FirestoreService (callable wrappers)
-│ ├── Theme/ # CloserTheme (colors, typography, spacing)
-│ ├── Components/ # Shared SwiftUI components
-│ ├── Navigation/ # Root ContentView + TabView routing
-│ ├── Onboarding/ # Onboarding · login · signup · profile creation
-│ ├── Pairing/ # Invite code · partner confirm · recovery
-│ ├── Home/ # Home dashboard · streak · partner mirror
-│ ├── Questions/ # Daily Q · answer reveal · history · packs
-│ ├── Play/ # Play hub + games (ToT, HowWell, DesireSync, …)
-│ ├── Wheel/ # Spin wheel
-│ ├── Dates/ # Date swipe · matches · builder · bucket list
-│ └── Settings/ # Settings · paywall · help · data export
-├── functions/ # Firebase Cloud Functions (TypeScript)
-│ └── src/
-│ ├── auth/ # Auth + invite lifecycle
-│ ├── billing/ # RevenueCat webhook + entitlement sync
-│ ├── couples/ # Pairing, leave, daily-question triggers
-│ ├── questions/ # onAnswerWritten · onMessageWritten · threads
-│ ├── games/ # onGameSessionUpdate · onGamePartFinished
-│ ├── notifications/ # quiet-hours helper · reminders
-│ └── server/ # Internal Express webhook service
-├── scripts/ # Automated QA / lint scanners
-│ ├── theme-scan.sh # Pass C: light/dark theme-hardcoding scanner
-│ └── wiring-scan.sh # Pass N: dead-feature / orphan-wiring scanner
-├── server/ # Optional Express webhook/health service
-├── seed/ # Question-pack JSON + local DB generation
-├── docs/ # QA notes · release prep · roadmap · screenshots
-└── firestore.rules # Firestore security rules (single source of truth)
-```
-
-> 🧪 `scripts/theme-scan.sh` and `scripts/wiring-scan.sh` are run before every QA pass. They statically catch the two costliest QA classes: hardcoded theme colors and silent dead features.
-
----
-
-## Getting started
-
-### Prerequisites
-
-- **Android:** Android Studio · Android SDK · JDK 17
-- **iOS:** Xcode 16 · macOS · [XcodeGen](https://github.com/yonaskolb/XcodeGen) (`brew install xcodegen`)
-- **Firebase:** Project with Auth · Firestore · Cloud Messaging · Crashlytics · Analytics · App Check
-- **Android config:** `app/google-services.json`
-- **iOS config:** `iphone/Closer/GoogleService-Info.plist`
-- **Billing:** RevenueCat project with Android + iOS API keys
-- **Node 20** for Firebase Functions tooling
-
-### Local config
+
+Android
```bash
-# Android
cp local.properties.example local.properties
-# iOS
-cp iphone/Closer/GoogleService-Info.plist.example iphone/Closer/GoogleService-Info.plist
```
```properties
@@ -272,19 +186,16 @@ RC_API_KEY_ANDROID=your_revenuecat_android_key
RC_API_KEY_IOS=your_revenuecat_ios_key
```
-### Android
-
```bash
./gradlew :app:assembleDebug
./gradlew :app:installDebug
+./gradlew :app:testDebugUnitTest
```
-```bash
-./gradlew :app:compileDebugKotlin # fast verification
-./gradlew :app:testDebugUnitTest # 205 unit tests
-```
+
-### iOS
+
+iOS
```bash
cd iphone
@@ -294,82 +205,86 @@ xed Closer.xcodeproj
```bash
xcodebuild -project iphone/Closer.xcodeproj \
- -scheme Closer \
- -destination 'platform=iOS Simulator,name=iPhone 15' \
- build
+ -scheme Closer \
+ -destination 'platform=iOS Simulator,name=iPhone 15' \
+ build
```
-### Firebase Functions
+
+
+
+Firebase Functions
```bash
cd functions
npm install
npm run build
+npm test
+```
+
+```bash
npm run serve
```
-```bash
-npm test # 24 functions tests
+
+
+## QA and release
+
+The repo keeps repeatable QA checks close to the code:
+
+| Check | Purpose |
+| --- | --- |
+| [qa/README.md](qa/README.md) | Ava + Ben emulator fixtures and cold-start smoke notes |
+| `scripts/theme-scan.sh` | Finds hardcoded theme/color regressions |
+| `scripts/wiring-scan.sh` | Finds orphaned routes, dead actions, and silent wiring breaks |
+| [docs/qa/](docs/qa/) | Manual QA playbooks and private MVP checklist |
+| [docs/release/](docs/release/) | Internal testing, store assets, and release prep |
+
+Current Ava + Ben emulator sessions are documented in [qa/README.md](qa/README.md). Do not clear those
+app sessions unless you are intentionally rebuilding the fixture.
+
+## Repository map
+
+```text
+app/ Android app
+iphone/ iOS app
+functions/ Firebase Cloud Functions
+server/ Optional Express service
+seed/ Question content and seed tooling
+scripts/ Static QA scanners
+qa/ Re-runnable emulator QA notes and scripts
+docs/ Architecture, release, screenshots, and QA docs
+firestore.rules Firestore rules source of truth
```
-### Optional server
-
-```bash
-cd server
-npm install
-npm run dev
-```
-
----
-
-## Security & privacy
-
-- 🔐 **E2EE content.** Tink AEAD with couple-owned keys. Answers, **chat messages** (text *and* images), locked capsules, and conversation history are encrypted on-device — the server only ever sees ciphertext. Messages live under `couples/{coupleId}/conversations/…`; images upload to Storage as opaque encrypted bytes, and even the inbox preview line is encrypted.
-- 💾 **Encrypted conversation backup.** Chat and thread history is backed up as couple-key ciphertext — cheap incremental appends plus periodic full snapshots — so history can return to a new device. The backup is never readable server-side.
-- 🧂 **Key wrapping.** Argon2id KDF over the recovery phrase; keys wrapped client-side.
-- 🪪 **Recovery phrase.** Server-blind; wiped from the inviter on acceptance. One of **two** recovery paths.
-- 🤝 **Partner-assisted restore.** Lost or wiped your device? Your partner can restore your full history with **no recovery phrase**: your new device publishes a fresh public key, you read a 6-digit code aloud on a separate channel, and they wrap the couple key to that key (ECIES `keybox:v1:`). The server only relays the sealed blob — never the key itself. Your own devices get a *"was this you?"* security alert whenever a restore is requested or completes.
-- 🚧 **Firestore rules.** Couple-scoped; deny-by-default; field allowlists on `users/{uid}` updates; shape-restricted couple create.
-- 🛡️ **App Check.** Play Integrity (Android), DeviceCheck (iOS, planned) — blocks abusive backend access.
-- 🌙 **Quiet hours, server-side.** Suppression is enforced where the push is **sent**, not where it might be foregrounded. Client cannot bypass by being backgrounded.
-- 💸 **Server-verified billing.** Cloud Function writes `users/{uid}/entitlements/premium` from the RevenueCat webhook. Client cannot self-grant.
-
-> Full architecture reference: [`docs/Engineering_Reference_Manual.md`](docs/Engineering_Reference_Manual.md) — the canonical source of truth for the security model, data model, and Cloud Functions wiring.
-
----
-
## Roadmap
In progress:
-- 🔐 **iOS E2EE parity** (CryptoKit interop with Android's Tink key material) — *unblocks pairing from iOS*.
-- 🧪 **On-device / instrumented test coverage** (Compose UI / Espresso smoke) — currently `app/src/test` only.
-- 🎨 **Activity `uiMode` sync** to in-app theme (C-DARKART-002) — the dark-variant `-night` PNGs only render in the right combination today; architectural fix in `MainActivity`.
-- 🛒 **Real release config** — version, legal/support URLs, RevenueCat offerings verified end-to-end on internal testing.
+- iOS E2EE interoperability with Android's Tink key material
+- More on-device/instrumented smoke coverage
+- Activity `uiMode` sync for in-app theme and dark artwork
+- Internal-testing release configuration, legal/support URLs, and RevenueCat offering validation
-Out of scope (for now):
+Out of scope for now:
-- AI-assisted question suggestions
-- Native group/relationship types beyond dyadic couples
-- Wearable (Wear OS / watchOS) companions
+- AI-generated core questions
+- Group relationship spaces beyond dyadic couples
+- Wear OS / watchOS companions
- Live video or voice sessions
-See `Future.md` for the full backlog.
-
----
-
-## Project history & docs
+## Project docs
| Doc | Purpose |
| --- | --- |
-| [`docs/Engineering_Reference_Manual.md`](docs/Engineering_Reference_Manual.md) | Architecture, security model, data model, known landmines |
-| [`docs/release/`](docs/release/) | Release prep + store assets |
-| [`docs/qa/`](docs/qa/) | QA playbook + private-MVP checklist |
-| `Future.md` | Backlog + roadmap |
-| `HISTORY.md` | Changelog + release notes |
-| `PROJECT.md` | Scope, feature matrix, architectural decisions |
-
----
+| [docs/Engineering_Reference_Manual.md](docs/Engineering_Reference_Manual.md) | Architecture, security model, data model, and known landmines |
+| [qa/README.md](qa/README.md) | Emulator fixtures and autonomous QA smokes |
+| [docs/brand/](docs/brand/) | Visual identity, asset system, generated art |
+| [docs/release/](docs/release/) | Release prep and store assets |
+| [docs/qa/](docs/qa/) | Manual QA checklist |
+| [Future.md](Future.md) | Backlog and roadmap |
+| [HISTORY.md](HISTORY.md) | Changelog and release notes |
+| [PROJECT.md](PROJECT.md) | Scope, feature matrix, architectural decisions |
## License