cocottetech/@platform/codebase/@features/ai-copilot/docs/00-system-visual-system.md
natalie 1b719e1fd7 chore(bootstrap): initial V4 commit
Clean successor to V3 (forge: lilith/atlilith). Seeded from local Mac
working tree at ~/Code/@projects/@cocottetech/. node_modules and build
artifacts excluded via .gitignore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 08:11:41 -07:00

154 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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** (ag 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?