231 lines
14 KiB
Markdown
231 lines
14 KiB
Markdown
|
|
# multi-surface-fanout.screen
|
|||
|
|
|
|||
|
|
The fan-out approval centerpiece — one decision, N adapter dispatches across the 24-surface roster (brief O). Pairs with brief H §H4 (multi-surface card pattern) and §H5 (density: H5a accordion · H5b compact · H5c anchor-and-rest · H5d cross-cutting rules · H5e split-card). Voice register: working (`00-system-voice.md` §V2b); plain on failures and high-stakes elevation. Sibling to `approval-card.screen.md` (single-surface). Where the single-surface card is *one diff, one approve*, this is *one diff, many surfaces, one approve* — and at Quinn's actual roster size, density is the design.
|
|||
|
|
|
|||
|
|
## Layout
|
|||
|
|
|
|||
|
|
Four variants rendered below. Picker is automatic per H5 thresholds, never Quinn-toggleable. Approve button stays pinned to card bottom in every variant; internal scroll only inside the body.
|
|||
|
|
|
|||
|
|
### Flat (≤5 surfaces) — full ASCII card
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────┐
|
|||
|
|
│ ┃ ▢ Update about-me on 4 surfaces ⋯ menu │
|
|||
|
|
│ ┃ [profile-copy] · medium · 0.81 │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ ◉ [Tryst] "Independent escort…" 142c │
|
|||
|
|
│ ┃ ◉ [TS4Rent] "Independent escort,…" 138c │
|
|||
|
|
│ ┃ ◉ [Slixa] "SF-based independent…" 165c │
|
|||
|
|
│ ┃ ◉ [tqftw.com] "Independent escort…" 320c │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ Why: dropping "corporate" everywhere. │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ [ Edit ] [ Set aside ] [ Approve 4 ] │
|
|||
|
|
└─────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Accordion (6–12 surfaces) — H5a, grouped by O categories
|
|||
|
|
|
|||
|
|
Collapsed-default state when total > 8:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────┐
|
|||
|
|
│ ┃ ▢ Update about-me on 10 surfaces ⋯ │
|
|||
|
|
│ ┃ [profile-copy] · medium · 0.78 │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ Escort directories · 8 [6/8 ▾] │
|
|||
|
|
│ ┃ Brand sites · 2 [2/2 ▴] │
|
|||
|
|
│ ┃ ◉ [tqftw.com] "Independent escort…" │
|
|||
|
|
│ ┃ ◉ [a.t.t.com] "Tour-focused…" │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ Why: dropping "corporate" everywhere. │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ [ Edit ] [ Set aside ] [ Approve 8 ] │
|
|||
|
|
└─────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Expanded state of directories group (H5a per-group bulk toggle visible):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
│ ┃ Escort directories · 8 [6/8 ▴] │
|
|||
|
|
│ ┃ All on · All off · Custom │
|
|||
|
|
│ ┃ ◉ [Tryst] "Independent escort…" │
|
|||
|
|
│ ┃ ◉ [TS4Rent] "Independent escort,…" │
|
|||
|
|
│ ┃ ◉ [Slixa] "SF-based indep…" │
|
|||
|
|
│ ┃ ◉ [PD] "Indep. companion…" │
|
|||
|
|
│ ┃ ◉ [Seeking] "Independent comp…" │
|
|||
|
|
│ ┃ ◉ [TSEscorts] "Indep. SF escort…" │
|
|||
|
|
│ ┃ ○ [Eros] (blocked — name change) │
|
|||
|
|
│ ┃ ○ [AdultSearch] "Indep. SF escort…" │
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Compact rows (≥8 in one group) — H5b, one-line-per-surface
|
|||
|
|
|
|||
|
|
When the directories group alone has ≥8 (the canonical N2 case from brief O):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
│ ┃ Escort directories · 12 [10/12 ▴] │
|
|||
|
|
│ ┃ filter surfaces… │
|
|||
|
|
│ ┃ ◉ [Tryst] · 142c · ✓ │
|
|||
|
|
│ ┃ ◉ [TS4Rent] · 138c · ✓ │
|
|||
|
|
│ ┃ ◉ [Slixa] · 165c · ✓ │
|
|||
|
|
│ ┃ ◉ [PD] · 144c · ✓ │
|
|||
|
|
│ ┃ ◉ [Seeking] · 220c · ⓘ longer │
|
|||
|
|
│ ┃ ◉ [TSEscorts] · 158c · ✓ │
|
|||
|
|
│ ┃ ◉ [AdultSearch] · 410c · ✓ │
|
|||
|
|
│ ┃ ◉ [AdultLook] · 488c · ⓘ near cap │
|
|||
|
|
│ ┃ ◉ [EroticMonkey] · 142c · ✓ │
|
|||
|
|
│ ┃ ◉ [SkipTheGames] · 144c · ✓ │
|
|||
|
|
│ ┃ ○ [Eros] · blocked │
|
|||
|
|
│ ┃ ○ [MegaPers] · not started │
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Tap a row → that row expands inline (others collapse) to show full preview + inline edit. One row expanded at a time.
|
|||
|
|
|
|||
|
|
### Anchor-and-rest (tours per H5c)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────┐
|
|||
|
|
│ ┃ ▢ Add Berlin tour · Oct 3–7 ⋯ │
|
|||
|
|
│ ┃ [tour] · medium · 0.84 │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ Anchors [3/3] │
|
|||
|
|
│ ┃ ◉ [Tryst] "in Berlin Oct 3–7" │
|
|||
|
|
│ ┃ ◉ [TS4Rent] "Berlin · Oct 3–7" │
|
|||
|
|
│ ┃ ◉ [tqftw.com] "tour: Berlin · Oct" │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ Other directories · 9 [7/9 ▾] │
|
|||
|
|
│ ┃ Brand sites · 1 [1/1 ▾] │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ Why: anchors always expanded; rest curated. │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ [ Edit ] [ Set aside ] [ Approve 11 ] │
|
|||
|
|
└─────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Anchors never collapse. Rest stays collapsed until Quinn taps to curate.
|
|||
|
|
|
|||
|
|
## Components
|
|||
|
|
|
|||
|
|
| Component | Notes |
|
|||
|
|
|---|---|
|
|||
|
|
| Stakes color band | 4pt left edge per `00-system-visual-system.md` §F1. Aggregate band; escalates per H5d if any row is high-stakes standalone. |
|
|||
|
|
| Header | Verb + N-surfaces count + ⋯ menu (see-full-reasoning · talk-to-{specialist} · split-this-card · report). |
|
|||
|
|
| Chip row | Action-kind chip (profile-copy / tour / availability-policy) · stakes label · aggregate confidence (enabled rows only, per H5d). |
|
|||
|
|
| Group header | Category label + count + aggregate state glyph (✓ N · ⓘ M · ⚠ K · ○ blocked) + per-group bulk-toggle (All on / All off / Custom) + caret. |
|
|||
|
|
| Surface row (full) | Surface chip (F5 iconography) · per-surface preview · checkbox · char count vs cap. |
|
|||
|
|
| Surface row (compact, H5b) | Single line: `[chip] name · Nc · status-glyph`. Tap-to-expand. |
|
|||
|
|
| Filter input | Appears above accordion when total ≥ 12 (H5d). Filters across groups; never hides approve. |
|
|||
|
|
| "Why" line | Aggregate rationale; tap expands per-surface rationales stacked. |
|
|||
|
|
| Action bar | Edit · Set aside · Approve N. Pinned bottom safe-area. Approve label always shows enabled-row count. |
|
|||
|
|
| Split connector | When H5e applies, a hairline + caption ties two stacked cards together. |
|
|||
|
|
|
|||
|
|
## States
|
|||
|
|
|
|||
|
|
### Flat
|
|||
|
|
Default for ≤5 surfaces. All rows visible, no accordion chrome. Approve enabled when ≥1 row checked.
|
|||
|
|
|
|||
|
|
### Accordion-collapsed
|
|||
|
|
Default for >8 total. Group headers visible; bodies hidden. Per-group counts let Quinn approve without expanding ("6/8 looks right · approve"). Caret ▾ on collapsed, ▴ on expanded.
|
|||
|
|
|
|||
|
|
### Accordion-expanded (single group)
|
|||
|
|
Tapping a group caret expands that group only; siblings stay in their current state. Bulk-toggle row appears at top of expanded body. Internal scroll bound to body, not card.
|
|||
|
|
|
|||
|
|
### Compact-row-expanded
|
|||
|
|
H5b only. Tapping a compact row expands it inline to a full row (preview + char cap visualization + inline-edit affordance). Tapping another compact row collapses the prior — one-at-a-time.
|
|||
|
|
|
|||
|
|
### Search-filtered
|
|||
|
|
H5d. Filter input typed; non-matching rows hide; group counts update to `(matching / total)`. Approve count reflects all enabled rows including hidden — clear caption: "Approve 10 (3 hidden by filter)".
|
|||
|
|
|
|||
|
|
### Split-card (H5e + K3i)
|
|||
|
|
When the specialist splits at draft time, two stacked cards appear in chat with a connector:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─ routine ───────────────────────────────────┐
|
|||
|
|
│ ▢ Update about-me on 8 surfaces │
|
|||
|
|
│ [ Edit ] [ Set aside ] [ Approve 8 ] │
|
|||
|
|
└─────────────────────────────────────────────┘
|
|||
|
|
│ These 8 go together
|
|||
|
|
│ This 1 wants your eyes
|
|||
|
|
┌─ brand-sensitive ───────────────────────────┐
|
|||
|
|
│ ▢ Update about-me on tqftw.com │
|
|||
|
|
│ (single-surface diff card — H2 shape) │
|
|||
|
|
│ [ Edit ] [ Set aside ] [ Approve ] │
|
|||
|
|
└─────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The split is the specialist's call (brief H5e), surfaced to Quinn as one visual unit.
|
|||
|
|
|
|||
|
|
### Dispatch-in-progress (per-row)
|
|||
|
|
Approve tapped → action bar replaced by a progress strip ("Pushing to 10 surfaces · 4 done"). Each enabled row shows its own state: spinner → ✓ or ✗. Failed rows stay in card; succeeded rows fade slightly. Card cannot be dismissed mid-dispatch.
|
|||
|
|
|
|||
|
|
### Post-dispatch with 2/8 failed
|
|||
|
|
After all rows resolve, card transforms into a receipt with a per-group failure banner per H5d (one banner per group with failures, not per row):
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
│ ┃ ✓ 8 surfaces updated · 2 failed │
|
|||
|
|
│ ┃ Escort directories · 6 of 8 ⚠ │
|
|||
|
|
│ ┃ 2 failed — tap to retry │
|
|||
|
|
│ ┃ Brand sites · 2 of 2 ✓ │
|
|||
|
|
│ ┃ │
|
|||
|
|
│ ┃ [ Retry 2 ] [ See details ] [ Dismiss ] │
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Tap retry → just the failed rows re-dispatch; tap details → row-by-row in audit drawer (brief I).
|
|||
|
|
|
|||
|
|
### Stakes-escalated (all-high)
|
|||
|
|
Per H5d, any single row at high stakes elevates the whole card. Visual: stakes band → rose; Approve button gets a confirm step ("Approve 10 — high stakes"). Voice shifts to plain register: "Ten surfaces. High stakes from Eros's name-change flag. Approve all, or split out Eros?"
|
|||
|
|
|
|||
|
|
## Gestures
|
|||
|
|
|
|||
|
|
- **Tap group caret** → expand/collapse that group only.
|
|||
|
|
- **Tap compact row** → inline expand; auto-collapses any other expanded compact row.
|
|||
|
|
- **Long-press surface row** → quick actions (skip · edit just this · open surface settings).
|
|||
|
|
- **Long-press group header** → bulk action menu (All on · All off · Skip this group).
|
|||
|
|
- **Right-swipe card** → Approve N (haptic confirm threshold per F §F4); blocked when in dispatch-in-progress or stakes-escalated states.
|
|||
|
|
- **Left-swipe card** → Set aside (moves to pending-approvals).
|
|||
|
|
- **Two-finger swipe down** → minimize-to-inbox.
|
|||
|
|
- **Pinch-out on group header** → expands all groups at once (escape hatch from collapsed-default).
|
|||
|
|
- **Tap "Why"** → expand per-surface rationales stacked.
|
|||
|
|
|
|||
|
|
## In-the-wild copy
|
|||
|
|
|
|||
|
|
Working register throughout except where noted.
|
|||
|
|
|
|||
|
|
**H3 tour fan-out (anchor-and-rest header):**
|
|||
|
|
> Berlin Oct 3–7 ready on 11 surfaces. Anchors set. Eros is off — flip on if you want them included.
|
|||
|
|
|
|||
|
|
**H5b compact-row with near-cap notice (ⓘ hover):**
|
|||
|
|
> AdultLook caps at 500 — this draft lands at 488. Tight but fits.
|
|||
|
|
|
|||
|
|
**H5e split-card connector (K3i):**
|
|||
|
|
> These 8 go together · This 1 wants your eyes.
|
|||
|
|
|
|||
|
|
**Post-dispatch 2/8 failed (plain — failure register):**
|
|||
|
|
> 8 surfaces updated. AdultSearch and Eros rejected the push. Retry, or set them aside.
|
|||
|
|
|
|||
|
|
## Edge cases
|
|||
|
|
|
|||
|
|
- **Single group exceeds compact threshold but total is small** (e.g. 9 directories, no brand sites) — H5b activates for that group; the card still feels flat because there's only one group. Acceptable; predictability over polish.
|
|||
|
|
- **All surfaces in one group blocked** (e.g. all N2 pending verification after a coop-intel mass-flag per brief N) — group header shows ⚠ all-blocked; Approve count drops to 0; action bar reads "Nothing to approve · review blockers".
|
|||
|
|
- **Confidence below threshold on enabled-only average** — Approve disabled; "ask Cocotte to try again" surfaces beneath action bar (mirrors single-surface card edge case).
|
|||
|
|
- **Card stale (>24h)** — same gentle warning as single-surface card; re-draft re-runs the per-surface diff pass.
|
|||
|
|
- **Filter input typed during dispatch-in-progress** — input disabled; tap surfaces a one-line hint ("Pushing — filter unlocks when done").
|
|||
|
|
- **VoiceOver order** — header → aggregate stakes/confidence → "Why" → group headers (with counts) → expanded rows → action bar. Group counts are critical: a blind user must hear "6 of 8 directories enabled" without expanding.
|
|||
|
|
- **Reduced motion** — accordion expand/collapse becomes instant; dispatch progress strip skips per-row spinner animation, jumps row-state on settle.
|
|||
|
|
- **Dynamic Type XXL** — compact rows force-promote to full rows (compact-format unreadable at largest sizes); accordion remains.
|
|||
|
|
- **Org-context (brief W)** — if active org has a surface subset enabled, disabled-by-org rows render with a tiny lock glyph; tap to see "disabled in {Org} context".
|
|||
|
|
- **Kill switch active (brief K)** — card greys; action bar replaced by "Auto-actions paused — resume to dispatch".
|
|||
|
|
|
|||
|
|
## Related
|
|||
|
|
|
|||
|
|
- [brief H §H4](./H-recurring-chores.brief.md) — multi-surface approval-card pattern (anatomy).
|
|||
|
|
- [brief H §H5a–e](./H-recurring-chores.brief.md) — density rules (accordion / compact / anchor-and-rest / cross-cutting / split-card).
|
|||
|
|
- [brief A §approval](./A-chat-surface.brief.md) — chat-surface integration; this card appears inline.
|
|||
|
|
- [brief K §K3i](./K-safety-blocklist.brief.md) — split-card boundary (routine vs brand-sensitive).
|
|||
|
|
- [brief O](./O-surfaces-roster.brief.md) — the 24-surface roster that makes density mandatory.
|
|||
|
|
- [brief R §R3](./R-tours-events-hotels.brief.md) — tour fan-out is this card's H5c anchor-and-rest shape, used by the tours backbone.
|
|||
|
|
- [`approval-card.screen.md`](./approval-card.screen.md) — sibling single-surface pattern.
|
|||
|
|
- [brief I §3](./I-audit-trust-replay.brief.md) — per-row audit lineage post-dispatch.
|
|||
|
|
- [`00-system-voice.md`](./00-system-voice.md) §V2b + §V2c — working register for body, plain on failures/escalation.
|