26 KiB
Closer — Branding & Artwork Review (Pass H)
Living status document for Closer's brand artwork pass. It records which illustrations/glyphs are live, which surfaces should reuse existing assets, and which brand issues belong in implementation or QA rather than image generation.
Asset ownership: Codex is responsible for making all needed images, dark variants, and custom glyphs. Do not leave image work as user-generated prompt handoff; backlog items here are Codex-owned assets to generate, add to the repo, and verify.
Current state (2026-06-27 audit): the This-or-That redesign (C-DARK-UI-001) + Premium-unlock modal (A13) are done.
But two large brand backlogs are now OPEN (found by the 2026-06-27 asset audit): (1) most illustrations are
light-only — only 12 of ~25 have a dark variant, and all 10 pack_art_* banners + all illustration_couple_*
heroes are light-only, so they show light/pink art on a dark screen; (2) ~60 distinct generic Material icons are
used across ~201 call sites (generic hearts, Person, Lock, Star…) — brand rule: every icon must be a custom Closer
glyph. See Brand standards + the two backlog tables below.
Branding defects (off-brand color, clipped/low-contrast art, a light image on a dark screen, a generic Material icon) →
ClaudeReport.md. Pure "could be warmer / feature" ideas →Future.md## QA. New art/glyphs to create (dark variants, custom glyphs) → logged HERE as Codex-owned assets to make and verify.
Brand standards — MUST hold every QA round (Pass C visual + Pass H branding own these)
Two non-negotiable brand rules. A violation of either is a bug (ClaudeReport.md) and the asset to create is
logged here as Codex-owned image/glyph work:
- Every image has a LIGHT and a DARK variant that matches the IN-APP theme. No light/pink art on a dark screen, no
dark art on a light screen.
drawable-nodpi/= light,drawable-night-nodpi/= dark (auto-selected byBrandIllustrationvia the in-app-theme config override). Transparent/celebration art that genuinely reads on both themes is the only exemption — verify it, don't assume. A surface missing its variant = bug + add the asset below. - Every icon/glyph is a custom Closer glyph — NO generic Material icons, no generic hearts. Material
Icons.*(ArrowBack, Favorite, Person, Lock, Star, PlayArrow, …) are placeholders, not brand. Each in use is replaced by a bespoke glyph in the Closer house style, logged in the icon backlog below for Codex to make + add (glyph_*).
Image style lock: all generated imagery must match the existing shipped flat 2D vector assets, especially
illustration_couple_paywall, illustration_couple_subscription, illustration_couple_onboarding,
illustration_daily_question, and the pack_art_* banners. Keep shapes simple and graphic, with pastel fills, minimal
facial/detail rendering, clean vector-like edges, and gentle gradients only. Reject painterly/storybook rendering,
3D-ish lighting, realistic texture, detailed hair/skin shading, dramatic cinematic glow, hard rectangular backdrops, or
anything that looks materially richer than the existing asset family. For any new batch, generate and review one sample
first against the existing contact sheet before saving more assets.
Image theme-variant coverage (light + dark per surface) — backlog: make the missing DARK variants
Goal: every image row has BOTH a light and a dark asset. Audited 2026-06-27.
| Illustration | Light | Dark | Action |
|---|---|---|---|
| account_deletion_goodbye · answer_history_empty · bucket_list_empty · connection_challenges_header · date_match_empty · date_match_success · memory_lane_capsule · messages_empty · pairing_success · past_games_empty · privacy_recovery · quiet_hours | ✅ | ✅ | none — both exist |
| illustration_couple_paywall (Paywall) | ✅ | ❌ | MAKE DARK (drawable-night-nodpi/) |
| illustration_couple_subscription (Subscription) | ✅ | ❌ | MAKE DARK |
| illustration_couple_onboarding (Onboarding) | ✅ | ❌ | MAKE DARK |
| illustration_couple_invite (Pairing/invite) | ✅ | ❌ | MAKE DARK |
| illustration_couple_history | ✅ | ❌ | MAKE DARK (or confirm unused) |
| illustration_daily_question (Today hero) | ✅ | ❌ | MAKE DARK |
| illustration_partner_activation (Home) | ✅ | ❌ | MAKE DARK |
| illustration_tonight_partner_prompt (Home) | ✅ | ❌ | MAKE DARK |
| illustration_together_empty (Activity) | ✅ | ❌ | MAKE DARK |
| pack_art_* ×10 (communication, deep_reflection, desire, family_commitment, fun_date, future_goals, home_life, intimacy, money_values, trust_repair) | ✅ | ❌ | MAKE DARK for each pack banner (or prove the banner reads correctly on dark) |
| reveal_celebration · streak_milestone · premium_unlock · spin_wheel | ✅ (transparent) | n/a | transparent/celebration — verify reads on both themes; add dark only if it doesn't |
Prompt for the missing dark variants: regenerate each light asset above in the dark/aubergine house palette
(deep aubergine #24122F ground, lavender #B98AF4 / soft-pink #F7C8E4 accents, blush highlights) so it reads on a
dark surface, same composition + flat 2D vector style + transparent/feathered edges as the light version, exported to
drawable-night-nodpi/ with the identical filename. Re-run Pass C's decoupled-theme check after adding each.
⛔ CLAUDE — also run
scripts/theme-scan.shTier 1E every round: any directpainterResource(R.drawable.illustration_*orpainterResource(R.drawable.pack_art_*)not routed throughBrandIllustrationwill fail to follow the decoupled in-app theme and should either be converted toBrandIllustrationor added to this table as a missing-variant candidate. The scanner is allowed to be improved; document any new patterns in its header.
Icon/glyph audit — generic Material icons to replace with custom Closer glyphs (backlog: make these)
Audited 2026-06-27: ~60 distinct Material icons across ~201 call sites. Brand rule #2 — each becomes a bespoke
glyph_*in the house style. Existing custom glyphs (reuse/extend, don't regress): the G/G2 set (glyph_paired_cards,glyph_how_well,glyph_sealed_answer,glyph_connection_challenge,glyph_memory_capsule,glyph_date_card_heart,glyph_question_packs,glyph_bucket_list,glyph_past_games,glyph_spin_wheel,glyph_couple_premium,glyph_privacy_lock,glyph_delete_account,glyph_how_well, + closer_mark/daily_card/ quiet_hours_moon/export_data). To make (high-traffic first):
| Generic icon (≈uses) | Used for | Make custom glyph |
|---|---|---|
ArrowBack (31) |
every top-bar back | glyph_back (brand chevron) |
Favorite / FavoriteBorder (17/5) |
generic hearts — likes, love, daily | glyph_heart (the Closer two-equal-halves heart, filled + outline) |
Lock / LockOpen (18/2) |
premium-locked, security | glyph_lock / glyph_lock_open (keyhole motif from the mark) |
Person / People (16/1) |
avatars/partner fallback | glyph_person / glyph_couple |
Check / Done / CheckCircle (11/1/1) |
confirm/selected/sent | glyph_check |
ArrowForward / ArrowForwardIos (10/4) |
row chevrons, next | glyph_forward |
PlayArrow (8) |
Play tab / start | glyph_play |
Close (7) |
dismiss/close | glyph_close |
Star (6) |
premium/★ ideas | glyph_star (brand sparkle) |
Visibility / VisibilityOff (5/2) |
password reveal | glyph_eye / glyph_eye_off |
ContentCopy (4) |
copy invite code | glyph_copy |
Sync (3) · Image/PhotoLibrary/PhotoCamera/AddAPhoto (3/2/2/2) · Send (3) · Chat (3) · Delete (3) |
retry · media pickers · send · messages · delete | glyph_sync · glyph_photo/glyph_camera · glyph_send · glyph_chat · glyph_trash |
Home (2) · Settings (1) · Notifications/NotificationsNone (2) |
bottom nav + settings | glyph_home · glyph_settings · glyph_bell |
LocalFireDepartment (2) |
streak flame (generic) | glyph_streak (brand flame/spark) |
Mic/Pause · Timeline/TrendingUp/Psychology · Fingerprint/Key/Shield · Edit/Add/Share/Refresh/Warning/CalendarToday/Cake/CardGiftcard/AttachMoney/HourglassEmpty/QuestionAnswer/Palette/OpenInNew (1 each) |
voice · progress · security · misc | one bespoke glyph_* each, in house style |
Replace each Icons.* call site with ImageVector.vectorResource(R.drawable.glyph_*) + Icon(tint=…) (the existing
wiring pattern). Until a glyph exists, the Material icon is a placeholder = a logged brand defect, not acceptable for ship.
R10 brand walk (2026-06-26) — existing art integration clean, 0 defects
R10 visual sweep doubled as the Pass-H existing-art integration check: Today (paired-books daily-question art),
Paywall (couple illustration), Security (padlock), Memory Lane / Date / Bucket-List empties, Home cards — all render
on-brand, in-context, both themes, no clipping/placeholder/off-brand issues (any defect would be a ClaudeReport.md
bug; none found). The new game-alert surfaces (GamePromptBanner, GameWaitingHeroCard) use the brand purple gradient
- PlayArrow glyph and read as intentional action banners, so no illustration is warranted there.
This or That gameplay brand plan (Codex QA, 2026-06-27) — ✅ IMPLEMENTED + verified live R13 (2026-06-27)
Done (R13, working tree).
ThisOrThatScreen.ktChoicePromptBackdropreplaced: the two-circle + diagonal-line "diagram" is gone — now a soft theme-aware glow + two faint paired-card silhouettes low in the frame, never crossing the prompt.OptionCardA/B map tocolorScheme.primary/secondarywith high-contrastonSurfacebody text, visible accent borders, and a rich filled selected state (onPrimary/onSecondary).VersusBadge, progress bar, theN/total+ "This or That" pills, the mood number-circle, andTotLengthChipsare all theme-aware (no fixedCloserPalettedarks). Light/dark previews added. Verified live both themes (5554 dark / 5556 light), 0 FATAL — closes C-DARK-UI-001. Results screen left as-is (verified clean in R12 dark). The plan below is retained for history.
Live review used a dedicated QA launcher/device (CloserCodexQA) with a fresh admin-created test couple
(codex-this-or-that-* / codex-partner-*). Screenshots checked the mood picker and active gameplay in light and dark
mode. The visual issue is real: light-mode option buttons are directionally good, but dark mode makes the current prompt
backdrop feel like an accidental placeholder.
Verdict: The current ChoicePromptBackdrop two-circle + diagonal-line drawing should be treated as a branding defect
for active gameplay. In dark mode the diagonal line cuts through the question, the circles turn muddy, and the whole
motif reads like a technical diagram instead of a warm private ritual for two.
Plan
- Replace the two circles + line with a Closer-native "private choice" motif: two soft sealed answer cards, paired-card silhouettes, or a subtle C-heart/keyhole accent. Keep it decorative and low-contrast behind the prompt; no line should cross the question text.
- Keep the light-mode option card shape, spacing, and button feel. Make the colors theme-aware rather than reusing fixed purple/pink values in both themes.
- Dark-mode option cards need stronger contrast: readable body text, visible borders, and selected states that feel rich instead of dim. Disabled/other-selected states should still be legible.
- Keep
closerBackgroundBrush()as the foundation, but consider one very subtle game-local glow or paired-card vignette in brand colors. The background should support focus, not compete with the question or options. - Re-check the mood picker after gameplay is fixed. The numbered mood circles are acceptable, but paired-card glyphs or warmer step badges would feel more branded than plain numbered bubbles.
- Results can reuse
illustration_reveal_celebrationand existing heart/petal particles for high-match moments; the game surface itself should stay code-native rather than needing a full raster illustration.
Implementation map
- Update
app/src/main/java/app/closer/ui/thisorthat/ThisOrThatScreen.kt, especiallyChoicePromptBackdrop,OptionCard, andVersusBadge. - Add local theme-aware helpers for This-or-That option A/B colors, selected colors, disabled colors, border colors, and
prompt-backdrop alphas. Validate against both
MaterialTheme.colorScheme.backgroundandsurface. - Prefer Compose
Canvas/shape drawing for the prompt motif. Generate raster art only if the code-native motif cannot carry the brand; if generated, use transparent PNG art with no readable text. - Add or update light/dark Compose previews for mood selection, active prompt, selected answer, waiting/disabled, and results.
Acceptance checks
- Light and dark screenshots show no decorative element crossing or competing with the prompt text.
- Long prompts, long options, selected, unselected, and disabled states stay readable.
- The light-mode cards retain the current friendly button feel.
- Dark mode feels intentionally Closer-branded: aubergine/lavender/pink, soft and private, not a placeholder diagram.
- Logs are checked after opening a game from notification/deep link before assuming the route worked.
Generated Art Live
The generated art (source in gitignored docs/brand/generated-art/, copied full-res to
app/src/main/res/drawable-nodpi/) is now wired into the app via the shared EmptyState
(rounded-tile, theme-safe) and a new ui/components/BrandIllustration.kt helper:
| Art | Screen wired | Verified |
|---|---|---|
A1 pairing_success (transparent) |
PairingSuccessScreen hero (replaced the keyhole chip; pulse/spring kept) | gallery (transparent floats) |
A2 answer_history_empty |
AnswerHistoryScreen empty (replaced generic couple_history) | shared EmptyState (Run-2 both-theme) |
A3 connection_challenges_header (banner) |
ConnectionChallengesScreen series-list header | gallery (16:9 banner) |
A4 memory_lane_capsule |
MemoryLaneScreen empty (replaced 📦 emoji) | shared tile |
A5 date_match_empty / date_match_success |
DateMatchesScreen empty / "It is a match!" modal | shared tile / gallery |
A6 bucket_list_empty |
BucketListScreen empty | live dark + light |
A8 messages_empty |
MessagesInboxScreen (new empty state added) | shared EmptyState |
A9 quiet_hours |
NotificationSettings quiet-hours section | live dark |
A10 past_games_empty |
WheelHistoryScreen ("Past Games") empty | shared tile |
A11 privacy_recovery |
SecurityScreen header | live dark |
A12 account_deletion_goodbye |
DeleteAccountScreen header | live dark |
A13 premium_unlock (transparent) |
✅ Wired R13 — one-time Premium unlock modal (PremiumUnlockOverlay) |
live both themes |
All 12 also live in the debug Art preview gallery (Settings → Art preview) for both-theme verification. A7 pack art is
N/A because all 10 question packs already have pack_art_*.
A1-A12 prompts are complete and should not be regenerated. Empty/match/pairing states that need empty-or-new data were not all reachable on the baseline couple, but their render path is proven through the shared tile + gallery.
Premium unlock modal — ✅ IMPLEMENTED + verified live R13 (2026-06-27). ui/components/PremiumUnlockOverlay.kt
(PremiumUnlockViewModel + PremiumUnlockOverlay), hosted at the AppNavigation root next to MessageBubbleOverlay,
so it surfaces over any screen. It's driven off CouplePremiumChecker.isPremium() (which already OR-combines both
partners) — so it fires for both the purchaser (own entitlement active) and the partner (couple-shared Premium
turns on), without depending on the push route. One-time per activation via a new persisted premiumUnlockCelebrated
flag on SettingsRepository/SettingsDataStore (set on dismiss; auto-reset when Premium lapses so a re-activation
celebrates again — mirrors lastCelebratedStreakMilestone). The modal shows illustration_premium_unlock (transparent,
floats via BrandIllustration(tile=false)) + "Premium unlocked ✨" + "Start exploring". Verified live: admin toggle
QA premium ON → modal on BOTH 5554 (dark) and 5556 (light); dismiss → relaunch → no re-show (gate holds); 0 FATAL.
Glyph Status
The original G-set plus G2 set are copied into app/src/main/res/drawable-nodpi/glyph_*.xml. Source SVGs live in
docs/brand/generated-art/glyphs/source-svg/; Android handoff vectors live in
docs/brand/generated-art/glyphs/android-vector/.
Wired + verified live (13 of 17):
- Play hub cards:
paired_cards,how_well,sealed_answer,connection_challenge,memory_capsule,date_card_heart,question_packs,bucket_list,past_games. - WaitingForPartner per-game glyphs:
spin_wheel,paired_cards,how_well,sealed_answer. - Settings rows:
couple_premium,privacy_lock,delete_account.
Generated but intentionally unused for now (4 of 17):
closer_mark— notifications already useic_notification_closer.daily_card— Today uses its hero illustration.quiet_hours_moon— Quiet hours usesillustration_quiet_hours.export_data— no export-data row exists yet.
White monochrome vectors are re-tinted by Icon(tint = ...) and loaded via ImageVector.vectorResource(...).
glyph_paired_cards is also the preferred motif for the This-or-That backdrop redesign tracked as C-DARK-UI-001.
Prompt Style Reference
Use this only when a future pass creates a new prompt. Existing completed art should not be regenerated.
Flat 2D pastel vector illustration in the "Closer" couples-app style: soft rounded shapes, no harsh outlines, gentle smooth gradients, calm and intimate. Palette only: aubergine
#24122F, deep purple#56306F, lavender#B98AF4, soft pink#F7C8E4, soft lavender#D9B8FF, blush white#FFF8FC. Mood: warm, quiet, equal, intentional — a private ritual for two. Recurring motifs available: paired/sealed cards, floating hearts and petals, a small wooden table with mugs + a lit candle + a lavender sprig, moon/window for quiet hours, a calendar/date-card, a sealed capsule/box. If people appear: two balanced, inclusive figures, simple friendly faces, no dominant partner. Soft abstract floral/heart shapes in the background. Do NOT include: any readable text, answer/prompt/message content, invite codes, emails, app UI/buttons, generic dating-app clichés, stock-photo realism, other brands' logos/wordmarks/app-store badges, alarm/urgency/surveillance/fire imagery.
The Closer brand mark (use ONLY where a prompt explicitly calls for it — otherwise keep art mark-free): a pink-to-lavender "C" whose upper arc is soft pink and lower sweep is lavender, curving around a heart-shaped negative space with a small dark aubergine keyhole at its center (the keyhole = trust/privacy; the heart = the couple). Keep it faithful — do not redraw it as a plain
C, turn the keyhole into a heart, add a key/lock shackle, add faces or text. On dark/aubergine surfaces use a white keyhole; on light/blush use the aubergine keyhole.
Aspect/format conventions
- Hero/onboarding/paywall: portrait 4:5 (matches
illustration_couple_*). - Empty states: roughly square 1:1, generous padding, sits centered above text.
- Celebration: 1:1, transparent or blush-white background.
- Glyphs: single-color simple vector, square, legible at 20–32 dp.
- Pack/category art: landscape ~16:9 banner, object-led (no people), like
pack_art_*. - Always readable on both blush-white (light) and aubergine (dark) surfaces — keep a soft self-contained vignette rather than a hard rectangular background; export PNG with transparency where noted.
Existing assets (reuse before generating): the generated A1-A12 illustration set above, illustration_couple_*,
illustration_daily_question, illustration_tonight_partner_prompt, illustration_partner_activation,
illustration_reveal_celebration, illustration_streak_milestone, illustration_together_empty,
illustration_premium_unlock, all 10 pack_art_* assets, particle_heart, and particle_petal. These are Android
assets now; only generate new art when a future QA pass finds a specific missing surface or replacement-worthy defect.
Screen-By-Screen Audit
Legend: ✅ on-brand / no art needed · ➕ reuse/wire existing art · 🔤 brand-copy/color/code touch
| Screen / surface | Current brand state | Opportunity |
|---|---|---|
| Onboarding carousel | ✅ couple art + warm copy | ✅ strong already |
| Welcome (Create / I have account) | heart mark + privacy line | ✅ on-brand; could rotate privacy messages 🔤 |
| Sign up / Login / Forgot password | plain form | 🔤 add small heart mark + one privacy line above the form (no big art — keep forms clean) |
| Create profile — name / sex / photo | plain steps | 🔤 light: small step glyphs; ✅ otherwise (forms stay clean) |
| Pair: invite (create code) | illustration_couple_invite wired |
✅ |
| Pair: accept code / pairing success | illustration_pairing_success wired |
✅ |
| Home (paired) | cards, warm copy | ✅ good |
| Home (unpaired "bring your person in") | couple art present | ✅ on-brand |
| Today / daily question | clean card | ✅; reveal moment is the place for art (below) |
| Answer reveal (mutual) | illustration_reveal_celebration wired |
✅ |
| Answer history | illustration_answer_history_empty wired |
✅ |
| Play hub | game glyphs wired | ✅ |
| This or That (setup/play) | light buttons good; dark prompt backdrop off-brand | 🔤 replace two-circle/line motif + theme option colors |
| This or That / How Well / Desire Sync results | score + rows | ➕ reuse reveal_celebration; particles on high match |
| How Well / Desire Sync intro | icon + copy | ✅ |
| Spin the Wheel | nice wheel art | ✅ wheel is on-brand |
| Wheel complete / results | text reveal | ➕ celebration header (reuse particles) |
| Connection Challenges (series list) | illustration_connection_challenges_header wired |
✅ |
| Connection Challenges (active day) | clean | 🔤 small streak/heart glyph; ✅ otherwise |
| Memory Lane (list) | illustration_memory_lane_capsule empty state wired |
✅ |
| Memory Lane (sealed capsule) | lock + date | ➕ optional: reuse capsule art on sealed-card detail, no new art |
| Date Match (deck) | clean cards | ✅ |
| Date Match (your matches / empty) | empty + success art wired | ✅ |
| Plan Date / Date Builder | form | 🔤 small date-card glyph; ✅ otherwise |
| Bucket List (empty) | illustration_bucket_list_empty wired |
✅ |
| Question Packs (library) | all 10 pack_art_* assets present |
✅ |
| Messages (inbox empty) | illustration_messages_empty wired |
✅ |
| Conversation | chat | ✅ keep clean; quiet-hours art is in settings |
| Past Games (empty/list) | illustration_past_games_empty wired |
✅ |
| Your Progress / Activity | stats | 🔤 brand-colored charts; reuse streak_milestone for milestones |
| Paywall / Subscription | couple art present | ✅ strong (couple illustration + “one subscription for both”) |
| Premium unlock modal | illustration_premium_unlock ready, not wired |
➕ implement one-time modal for purchaser + partner |
| WaitingForPartner | per-game glyphs + copy | ✅ |
| Settings + sub-pages | dense lists | ✅ keep clean — no illustrations; brand via section headers/color only 🔤 |
| Security / Recovery phrase | illustration_privacy_recovery wired |
✅ |
| Privacy & Terms | settings row uses glyph_privacy_lock |
✅; page can stay text-first |
| Delete account | illustration_account_deletion_goodbye wired |
✅ |
| Quiet hours (settings) | illustration_quiet_hours wired |
✅ |
| Notifications (system) | ic_notification_closer used |
✅ no glyph swap needed |
Generation Backlog
Two OPEN backlogs (2026-06-27 audit) — see the tables up top:
- Dark illustration variants — make
drawable-night-nodpi/versions of every light-only image: allillustration_couple_*heroes,daily_question,partner_activation,tonight_partner_prompt,together_empty, and all 10pack_art_*banners (see Image theme-variant coverage). - Custom glyphs to replace ~60 generic Material icons (see Icon/glyph audit) — every icon must be a bespoke
glyph_*, starting with the highest-traffic (back, heart, lock, person, check, forward, play, close, star).
Do not regenerate completed illustration/glyph art unless a QA pass logs a specific defect; the above are net-new.
Generated glyph files: glyph_closer_mark, glyph_paired_cards, glyph_daily_card, glyph_sealed_answer,
glyph_memory_capsule, glyph_date_card_heart, glyph_quiet_hours_moon, glyph_couple_premium,
glyph_export_data, glyph_delete_account, glyph_how_well, glyph_connection_challenge, glyph_question_packs,
glyph_bucket_list, glyph_past_games, glyph_spin_wheel, glyph_privacy_lock.
Notes for the asset hand-off
- Match filenames to the existing scheme:
illustration_<name>.png(nodpi),pack_art_<pack>.png,glyph_<name>.xml,particle_<name>.png. Provide @1x indrawable-nodpi/(illustrations) or density buckets where the existing asset has them. - For the generated G-set, use the source SVGs in
docs/brand/generated-art/glyphs/source-svg/for review and the Android-ready vectors indocs/brand/generated-art/glyphs/android-vector/for app wiring. - After adding art, re-run Pass C (visual, light + dark) on those screens to confirm contrast + no clipping, and
re-export store graphics per
docs/brand/visual-identity.mdif the palette/mark changed.