155 lines
8.9 KiB
Markdown
155 lines
8.9 KiB
Markdown
|
|
# F — Visual system (tokens + components)
|
|||
|
|
|
|||
|
|
## Goal
|
|||
|
|
Establish the design language that every surface (iOS, iPad, macOS, web) inherits. Tokens-first so a renamed brand or palette tweak doesn't ripple through every screen.
|
|||
|
|
|
|||
|
|
## Designer skim
|
|||
|
|
|
|||
|
|
- **Headline UX**: Tokens-first design language. SwiftUI-native primitives where possible (system fonts, SF Symbols, system materials). WCAG AA contrast min. Light + dark from day one.
|
|||
|
|
- **Sections (7)**: F1 color · F2 typography · F3 spacing+radius · F4 motion+haptics · **F5 24-surface iconography** (a–g sub-blocks: N1 content / N2 directories / N3 brand sites / N4 channels / N5 commerce / fallback / geometry-coded distinction) · F6 empty-loading-error · F7 component library.
|
|||
|
|
- **Foundation**: lives in `00-system/` alongside voice. Every brief inherits from here.
|
|||
|
|
- **Blocking Qs**: [OPEN-DECISIONS.md](./OPEN-DECISIONS.md) → VS-Q1 stakes-high-vs-destructive-red collision.
|
|||
|
|
|
|||
|
|
## Constraints
|
|||
|
|
- Inherit `lilith-messenger-ios/LilithMessenger/Design/{Theme,Typography}.swift` as the **starting point**, then specialize for CocotteAI's identity.
|
|||
|
|
- SwiftUI-native primitives where possible (system fonts, SF Symbols, system materials).
|
|||
|
|
- WCAG AA contrast minimum in light AND dark.
|
|||
|
|
|
|||
|
|
## Token layers (ordered from primitive to composite)
|
|||
|
|
|
|||
|
|
### F1 — Color tokens
|
|||
|
|
- **Primitives**: a 12-step neutral ramp (light + dark), a 12-step accent ramp, semantic colors.
|
|||
|
|
- **Accent** proposal: warm rose — Quinn's talent-tier accent. Designer to validate against the **Cocotte** umbrella brand palette before locking. (Cocotte is the customer-facing brand; Demimonde is back-office and has no customer-facing palette.)
|
|||
|
|
- **Semantic stakes colors**: low = neutral-500 (gray), medium = amber-500, high = rose-600. Must work as text + as background + as dot/chip in both modes.
|
|||
|
|
- **Background materials**: app background, sheet background, card surface, elevated card.
|
|||
|
|
|
|||
|
|
### F2 — Typography
|
|||
|
|
- Display, Title, Headline, Body, Body-emphasized, Caption, Footnote.
|
|||
|
|
- All scales use SF Pro Display + SF Pro Text.
|
|||
|
|
- Dynamic Type support (iOS accessibility).
|
|||
|
|
|
|||
|
|
### F3 — Spacing + radius
|
|||
|
|
- 4pt base grid; spacing scale {2, 4, 8, 12, 16, 24, 32, 48}.
|
|||
|
|
- Radius scale {4 (chips), 12 (cards), 20 (sheets), full (avatars)}.
|
|||
|
|
|
|||
|
|
### F4 — Motion + haptics
|
|||
|
|
- Approval swipe: 200ms easeOut animation, light haptic on threshold crossing, success haptic on commit.
|
|||
|
|
- Streaming reply tokens: stagger 16ms, fade-in 100ms.
|
|||
|
|
- Sheet present: native iOS sheet timing; do not override.
|
|||
|
|
- High-stakes notification arrival: notification haptic + display haptic.
|
|||
|
|
|
|||
|
|
### F5 — Surface iconography
|
|||
|
|
|
|||
|
|
Per-surface visual marks for the **canonical 24-surface roster** in [brief O](./O-surfaces-roster.brief.md). Goal: at chip size (16pt) Quinn recognizes the surface in <200ms without reading text. Where a brand mark is unrecognizable at chip size, fall back to a 2-letter monogram on a category-tinted square.
|
|||
|
|
|
|||
|
|
**Geometry rules (all marks):**
|
|||
|
|
- Circular bounding box, 16pt (chip) / 20pt (card) / 24pt (drawer header).
|
|||
|
|
- 1pt stroke on the bounding ring in light mode; 0pt in dark (relies on chip background).
|
|||
|
|
- Always paired with `SurfaceChip` (F7) — never rendered standalone without a display name nearby on first introduction.
|
|||
|
|
|
|||
|
|
#### F5a — N1 content surfaces (brand-mark; recognizable)
|
|||
|
|
|
|||
|
|
| ID | Mark | Light color | Dark color | Notes |
|
|||
|
|
|---|---|---|---|---|
|
|||
|
|
| `onlyfans` | OF wordmark in circle | `#00AFF0` (OF blue) | same | Recognizable. |
|
|||
|
|
| `x` | X glyph | `#000` | `#FFF` | Mono. |
|
|||
|
|
| `instagram` | gradient ring + camera | brand gradient | brand gradient | Don't reduce to mono — recognition collapses. |
|
|||
|
|
| `tiktok` | musical-note glyph | `#000` | `#FFF` w/ cyan/red shadow | Mono with brand accent. |
|
|||
|
|
| `threads` | @ mark | `#000` | `#FFF` | Cheap to render; cross-post sibling of `x`. |
|
|||
|
|
| `bluesky` | butterfly | `#1185FE` | same | New 2026. |
|
|||
|
|
| `reddit` | snoo silhouette | `#FF4500` | same | High recognition. |
|
|||
|
|
| `fansly` | "F" monogram | `#0F8` (fansly green) | same | OF alternative; lower brand recognition — accept word-mark fallback at 16pt. |
|
|||
|
|
| `youtube` | play-triangle | `#FF0000` | same | SFW only. |
|
|||
|
|
| `twitch` | speech-bubble glyph | `#9146FF` | same | SFW only. |
|
|||
|
|
| `facebook` | "f" wordmark | `#1877F2` | mono in dark | Defensive listing; rarely shown. |
|
|||
|
|
|
|||
|
|
#### F5b — N2 escort directories (12 surfaces — most have weak brand recognition)
|
|||
|
|
|
|||
|
|
Default for this category: **2-letter monogram on category-tinted square** (radius 4pt, neutral-700 background in light, neutral-200 in dark; foreground = accent-rose for "live" directories, neutral-400 for "pending/blocked"). Reserve brand-mark rendering for the two anchor directories.
|
|||
|
|
|
|||
|
|
| ID | Mark | Strategy |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `tryst` | "T" in rose square + verified-checkmark glyph | Anchor; gets a distinct mark. |
|
|||
|
|
| `ts4rent` | "T4" monogram | Anchor; distinct. |
|
|||
|
|
| `seeking` | "S" monogram | Sugar-dating context — give it its own neutral-blue tint to separate from N2 escort directories visually (per brief O open question). |
|
|||
|
|
| `privatedelights` | "PD" monogram | Pending verification — render in pending-gray. |
|
|||
|
|
| `tsescorts` | "TS" monogram | |
|
|||
|
|
| `adultsearch` | "AS" monogram | |
|
|||
|
|
| `adultlook` | "AL" monogram | |
|
|||
|
|
| `eros` | "ER" monogram | **Blocked-on-legal-name-change** state — render at reduced opacity 0.5 + lock glyph overlay. |
|
|||
|
|
| `eroticmonkey` | "EM" monogram | |
|
|||
|
|
| `skipthegames` | "SKG" trigraph (exception: 3 chars allowed when "STG" reads worse) | |
|
|||
|
|
| `megapersonals` | "MP" monogram | |
|
|||
|
|
| `ts.live` | "ts" lowercase monogram + `.live` superscript | Distinguish from `tsescorts` and `ts4rent` — three "ts" prefixes in the roster. |
|
|||
|
|
|
|||
|
|
**Status-state overlays (apply on top of any N2 mark):**
|
|||
|
|
- Live → no overlay.
|
|||
|
|
- Pending verification → 0.7 opacity + amber dot top-right.
|
|||
|
|
- Blocked / suspended → 0.5 opacity + lock glyph.
|
|||
|
|
- Not started → 0.4 opacity + dashed bounding ring.
|
|||
|
|
|
|||
|
|
#### F5c — N3 brand sites (Quinn-owned)
|
|||
|
|
|
|||
|
|
Quinn-owned brand sites get a **distinct shape (rounded square, not circle)** to telegraph "this is ours, not external." Foreground = brand-rose; background = neutral-100/900.
|
|||
|
|
|
|||
|
|
| ID | Mark |
|
|||
|
|
|---|---|
|
|||
|
|
| `transquinnftw.com` | tqftw monogram |
|
|||
|
|
| `adult-therapy-tours.com` | "ATT" trigraph |
|
|||
|
|
| `futa-waifu-tour` | "FWT" trigraph |
|
|||
|
|
|
|||
|
|
#### F5d — N4 channels (messaging, not posting)
|
|||
|
|
|
|||
|
|
Channels are NOT `surface_kind` (per brief O); they render with a different component (`ChannelChip`, sibling to `SurfaceChip`) that uses **rounded-square** geometry to visually separate "channel-of-arrival" from "surface-of-origin" — critical for the unified inbox in brief P.
|
|||
|
|
|
|||
|
|
| ID | Mark | Notes |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `imessage` | SMS bubble glyph (iOS) | System SF Symbol `message.fill`. |
|
|||
|
|
| `signal` | Signal logo | Encrypted-channel marker. |
|
|||
|
|
| `telegram` | paper-plane | |
|
|||
|
|
| `discord` | discord-mark | |
|
|||
|
|
| `email` | envelope SF Symbol | Plus per-mailbox tint when from multiple Proton accounts (see brief P). |
|
|||
|
|
| `sniffies` | "Sn" monogram | Light surface. |
|
|||
|
|
|
|||
|
|
#### F5e — N5 commerce (P5+, enumerated only)
|
|||
|
|
|
|||
|
|
Commerce providers render as monogram tiles in green tint when Quinn surfaces them; otherwise hidden. Enumerated for completeness; no P0 design effort.
|
|||
|
|
|
|||
|
|
#### F5f — Fallback for unknown / new surfaces
|
|||
|
|
|
|||
|
|
When a `surface_kind` value arrives that the iconography registry doesn't know (forward-compat with brief O additions), render: **neutral-tinted circle + first 2 alphanumeric chars of the ID** (uppercase). Never break the layout; never throw.
|
|||
|
|
|
|||
|
|
#### F5g — Surface-vs-channel visual distinction (summary)
|
|||
|
|
|
|||
|
|
| Geometry | Used for | Examples |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Circle | N1 content + N2 directories (posting/listing surfaces) | OF, Tryst |
|
|||
|
|
| Rounded-square (Quinn-owned tint) | N3 brand sites | tqftw.com |
|
|||
|
|
| Rounded-square (channel tint) | N4 channels | iMessage, email |
|
|||
|
|
| Monogram tile (green) | N5 commerce | Venmo |
|
|||
|
|
|
|||
|
|
This geometry-coded distinction lets Quinn see at a glance whether a card is **about a place she posts** vs **about a place she receives** vs **about a place she gets paid** — without reading.
|
|||
|
|
|
|||
|
|
### F6 — Empty / loading / error states
|
|||
|
|
- Standard empty illustration set (one icon family, branded).
|
|||
|
|
- Loading: thin determinate progress when measurable, skeleton on lists, spinner only as last resort.
|
|||
|
|
- Error: standard error card with retry affordance; never a system alert.
|
|||
|
|
|
|||
|
|
### F7 — Component library
|
|||
|
|
- `ApprovalCard` (all variants from brief A)
|
|||
|
|
- `StakesBadge`, `ConfidenceBar`
|
|||
|
|
- `SurfaceChip` (uses F5 iconography)
|
|||
|
|
- `SpecialistMention` (inline tappable text)
|
|||
|
|
- `Drawer` (sheet wrapper, brief B)
|
|||
|
|
- `VoiceMicButton` (push-to-talk + long-press hands-free)
|
|||
|
|
- `PersonaFacetEditor` (chip + free-text inputs for facet JSON)
|
|||
|
|
|
|||
|
|
## Out of scope
|
|||
|
|
- 3D / @chobit avatar visuals (P5+).
|
|||
|
|
- Marketing site visuals (cocottetech.com is a different brief).
|
|||
|
|
|
|||
|
|
## Open questions
|
|||
|
|
- Should stakes-high red overlap with destructive-action red (reject swipe color)? Argue against — semantic collision.
|
|||
|
|
- Custom font, or stay system? System wins on Dynamic Type + accessibility for free.
|
|||
|
|
- Iconography for V3 specialists themselves (a per-specialist mark) — needed P0 or P1?
|