# salon.screen Single-screen breakdown for an **AE4 salon** — a multi-peer ai-mediated group room with stated topic, rotating moderator quorum, and proposal→awaiting-quorum→active→archived lifecycle. Sibling to [chat-home.screen](./chat-home.screen.md) (DM-shaped stream) and [coop-drawer.screen](./coop-drawer.screen.md) (multi-member surface pattern). Inherits AD opacity, K3 PII gate, and §V6 banned-phrase enforcement on every outbound. Voice register: **hearth** on first arrival, **working** on ops, **plain** on moderation (per voice §V2c — moderation cost is too high for hearth). ## Layout (iPhone 17 logical 393×852, active salon — default) ``` ┌─────────────────────────────────────────────────┐ │ ◄ status bar (system) │ 47pt ├─────────────────────────────────────────────────┤ │ ◄ Chat Berlin Tryst peers · 7 · open [⋯] │ 56pt — header (topic + member count + posture) │ moderators: 2 of 3 active │ sub-line: quorum signal ├─────────────────────────────────────────────────┤ │ ┌───────────────────────────────────────────┐ │ ambient receipt (hearth) │ │ Welcome to Berlin Tryst peers. │ │ first-arrival, dismissible │ │ 7 in the room, last active 12 minutes ago.│ │ │ └───────────────────────────────────────────┘ │ │ │ │ rosa · 14:02 · • mediated │ sender handle + mediation dot │ Anyone seeing slower bumps on Tryst tonight? │ │ │ │ mari · 14:03 · • mediated │ │ Yes — two failed retries on my side. │ │ │ │ q-berlin · 14:04 · • mediated │ │ Mine held. EU-west edge maybe. │ │ │ │ ─── Cocotte · 14:05 · ambient ──────────────── │ specialist note (hearth) │ Three of you are watching this. Want a │ │ shared playbook in the drawer? │ │ │ │ ┌───────────────────────────────────────────┐ │ inline mod-action card │ │ ▢ Mute sender mari for 24h? plain │ │ visible to mods only │ │ 2 of 3 mods need to agree. You + 1 more.│ │ │ │ [ Decline ] [ Agree ] │ │ │ └───────────────────────────────────────────┘ │ │ │ ├─────────────────────────────────────────────────┤ │ ╭─────────────────────────────╮ [🎤] [📷] │ 56pt — composer │ │ Say something to the salon… │ │ placeholder rotates per state │ ╰─────────────────────────────╯ long-press = ☎ │ └─────────────────────────────────────────────────┘ │ 34pt — home indicator ``` ### Pre-activation variant (proposal · awaiting-quorum) ``` ┌─────────────────────────────────────────────────┐ │ ◄ Chat Berlin Tryst peers · proposal [⋯] │ ├─────────────────────────────────────────────────┤ │ Proposed by rosa · 2h ago │ │ Topic: "Tryst listing optimization, Berlin" │ │ Flavor: closed · quorum needed: 3 of 3 │ │ │ │ Founders (2 of 3 confirmed): │ │ ✓ rosa (founder, accepted) │ │ ✓ mari (founder, accepted) │ │ … q-berlin (invited, pending) │ │ │ │ [ Invite founder ] [ Withdraw proposal ] │ │ │ │ Stream is closed until quorum reached. │ └─────────────────────────────────────────────────┘ ``` ## Components | Component | Brief ref | Notes | |---|---|---| | Header | AE4, [coop-drawer §header](./coop-drawer.screen.md) | Topic (≤ 40 char truncated), member count, posture chip (`open` / `closed`), quorum status sub-line. Tap = topic+rules sheet (see Interactions). `[⋯]` = overflow (member roster, leave salon, archive, report). | | Mediation dot | AE3, [Brief AD](./AD-multilingual-opaque.brief.md) | Single `•` glyph next to sender handle + timestamp. Tappable → "rendered for you in {your locale} · the AI mediated this · view what {sender} literally wrote" sheet (the only AD opacity break, per AE3, requires both peers' consent at salon-join). | | Stream | AE4 | Vertical message list. Each row: handle · time · mediation dot · body. No avatars (per chat-home parity); sender color is hash-derived for visual distinction without identity disclosure. | | Specialist ambient | [Brief L §L2](./specialist-ai-copilot.contract.md), voice §V2a | `ai-copilot` posts hearth-register observations into salons (e.g. shared-playbook nudge). Always prefixed `── Cocotte · {time} · ambient ──`; never indistinguishable from a peer. | | Member roster drawer | AE4, [coop-drawer §roster](./coop-drawer.screen.md) | Slide-in from right. Lists members, role (`member` / `mod`), join date, per-member muted/blocked state, and (mod-only) per-member sanction affordances. | | Moderator quorum action sheet | AE4, AE10 | Inline card (mods-only) for any moderation action: mute, remove, archive. Each shows `N of M mods needed`, current tally, [Agree] / [Decline]. On quorum reached, the action commits + a plain-register receipt appears in stream. | | Topic + rules sheet | AE4 | Modal opened by tapping header. Shows full topic, flavor (open/closed), rules (anonymous-OK, evidence-req., locale-mix posture), founders, archive policy, and `[Leave salon]` / `[Report to platform-admin]`. | | Composer | A §multimodal, AE4 | Same as chat-home composer; placeholder swaps per state. Outbound passes through K3 + §V6 + AD3 pipeline before any recipient delivery. | ## States 1. **proposal** — pre-activation. Founder draft visible only to invited founders. Composer disabled with "Stream opens at quorum." Right-aligned `[Withdraw proposal]` for the originator. 2. **awaiting-quorum** (n of 3 founders) — same as proposal but with live founder tally; counter advances as each founder accepts. Visible founders see each other's confirm state; invited-but-pending founders see only "Pending your confirm." On quorum, transitions to `active` with a hearth receipt: "Berlin Tryst peers is live. 3 founders. Make the first turn yours." 3. **active (default)** — full layout as drawn. Composer placeholder: "Say something to the salon…" 4. **archived** — manual or 90d-inactivity (per AE4). Stream becomes read-only with grey wash; composer replaced by banner "Archived {date}. Reason: {manual / 90d-inactive}. Read-only." `[⋯]` retains "Report" + "Leave" only. 5. **mod-action-pending** — any state above with at least one open quorum proposal. Mods see the action card inline at the bottom-above-composer; non-mods see no card and no leak that an action is being deliberated. Receipt on commit is plain-register: "{Sender} muted by moderator quorum until {date}." 6. **per-member muted** — viewer-side state. Muted member's messages collapse to a single line "Hidden — muted by you" with `[Show]` affordance. The muted member never learns (per AE10 mute semantics). 7. **K3 leak suppressed broadcast** — outbound message tripped K3 PII gate; the message is blocked before any recipient delivery; one `peer_group_messages` row written once with `delivered_text=NULL` per recipient (per AE edge cases). Sender sees plain-register counter-action receipt: "Held a draft back — contains restricted content. See audit for the row." No recipient sees anything. 8. **empty (no messages yet)** — newly-active salon, no turns yet. Centered hearth prompt: "Welcome to {salon name} peers. 3 in the room. The first turn is yours." Composer placeholder: "Start the salon." 9. **cross-locale mixed** — multiple member locales coexist; every recipient sees stream entirely in their preferred locale per AD opacity (no "translated from…" annotation ever). The mediation dot is the only signal that ingestion happened. 10. **founder leaves before quorum** — `awaiting-quorum` with one or more founders having withdrawn. Banner: "{Founder} left before quorum. {Originator} can invite a replacement or withdraw the proposal." If originator leaves, the proposal auto-withdraws + a plain-register notice to remaining founders: "{Originator} withdrew. The proposal is closed." 11. **coop deletion cascade** — salon is coop-bound (closed, `coop_id` set) and the parent coop was dissolved (per [coop-drawer state 8](./coop-drawer.screen.md)). Banner replaces stream: "The coop this salon belonged to was dissolved on {date}. The salon is archived; transcripts remain in audit." Composer disabled. 12. **VoiceOver / reduced motion / Dynamic Type XXL** — inherits chat-home accessibility patterns (per [Brief X](./X-accessibility.brief.md)). Roster drawer reads members in order; mediation dot announces "mediated by ai-copilot" as a hint; quorum cards read tally first. ## Interactions / gestures - **Long-press a message** → action sheet: "Quote in reply" / "Report to mods" / "Report to platform-admin" / "View what {sender} literally wrote" (the AD verbatim-view, requires both-peers consent at salon-join). On `quote`, composer pre-fills with quoted snippet attribution. - **Swipe-right on a message (mod only)** → "Mute {handle} for 24h?" opens a quorum action card inline. Non-mods get no gesture affordance here. - **Swipe-left on a message** → set-aside / dismiss from your view only (does not affect any other recipient). - **Tap header** → topic + rules sheet (modal). - **Tap mediation dot** → AD opacity break sheet (verbatim sender text). - **Tap `[⋯]`** → overflow menu (member roster · leave salon · archive (mods only) · report). - **Pull-to-refresh** → re-pulls salon state + new messages. - **Swipe-down on header** → dismiss back to chat / drawer. ## In-the-wild copy - (hearth, first-arrival receipt) "Welcome to Berlin Tryst peers. 7 in the room, last active 12 minutes ago." - (working, quorum reached) "Berlin Tryst peers is live. 3 founders. Make the first turn yours." - (working, ambient nudge) "Three of you are watching this. Want a shared playbook in the drawer?" - (plain, mod quorum proposed) "Mute mari for 24h? 2 of 3 mods need to agree." - (plain, quorum committed) "mari is muted by moderator quorum until tomorrow 14:02. Reason: off-topic spam." - (plain, K3 leak suppressed) "Held a draft back — contains restricted content. See audit for the row." - (plain, archived 90d) "Archived March 12. Reason: 90 days no activity. Read-only." - (plain, coop dissolved) "The coop this salon belonged to was dissolved on March 12. The salon is archived; transcripts remain in audit." - (plain, founder withdrew pre-quorum) "rosa withdrew. The proposal is closed." ## Edge cases - **Founder leaves before quorum** — see state 10. Originator gets the invite-replacement / withdraw-proposal affordance; remaining founders get a plain-register notice when the proposal closes. - **90d-inactivity auto-archive** — last-message timestamp ≥ 90d ago triggers a background sweep that flips the salon to `archived` + writes a plain-register receipt audible to all members on their next open. Members can still read the transcript; no new turns accepted. Per AE4 lifecycle. - **Coop deletion cascade** — if `coop_id` is set and the parent coop dissolves (per [Brief N §N6d](./N-provider-coop.brief.md)), the salon auto-archives with state 11's banner. Members are not removed from their personal AE plane; only the salon goes read-only. Open salons not bound to a coop are unaffected. - **Member's posture flips to incognito mid-salon** — past messages remain visible to other members (consent was at salon-join); the incognito member can still read but cannot send. Header shows no leak; only that member sees the composer disabled with "Posture is incognito. Open posture to post." Per AE11. - **Cross-locale founders propose a salon** — proposal-state shows founders' handles only; AD opacity holds even pre-quorum. The proposed topic is itself stored as canonical-EN + per-locale rendered per AD6 triad. - **Right-to-left member in LTR salon** — recipient-view rendering flips per locale; mediation dot stays adjacent to the handle in reading order. Per [Brief AD §AD-Q4](./AD-multilingual-opaque.brief.md). - **Mod proposes a quorum action while another mod is offline** — action card persists until quorum reached or 7d expires (timeout auto-declines). Plain-register receipt on timeout: "Mute proposal on mari expired without quorum." - **Founder is also the only mod** — at salon activation, the founder is auto-`mod`; quorum threshold for mod actions in a 3-founder salon defaults to 2 of 3. Per AE4 + schema `quorum_count` default. - **Salon ai-mediation degraded** — `@model-boss /translate` unreachable; per [Brief M §M2a](./M-error-degraded-modes.brief.md): outbound queues with a degraded chip; recipients see a plain-register banner "ai-copilot is catching up on this salon. Some messages will arrive late." - **Reduced motion / VoiceOver / Dynamic Type XXL** — see state 12. ## Related - [Brief AE §AE4](./AE-provider-social-network.brief.md) — parent design (lifecycle, schema, mediation). - [Brief AE §AE10](./AE-provider-social-network.brief.md) — moderation surfaces (block, mute, report). - [Brief AE §AE11](./AE-provider-social-network.brief.md) — opt-in posture affecting send-eligibility. - [Brief AD](./AD-multilingual-opaque.brief.md) — opacity + storage triad + recipient-view rendering applied per salon message. - [Brief K §K3](./K-safety-blocklist.brief.md) — PII gate that produces state 7's suppressed-broadcast. - [Brief N](./N-provider-coop.brief.md) — parent coop lifecycle for state 11's cascade. - [Brief L §L2](./specialist-ai-copilot.contract.md) — `ai-copilot` ambient nudges inside salons. - [Brief I](./I-audit-trust-replay.brief.md) — every salon turn is an `agent_actions` row linked to `peer_group_messages`. - [Brief X](./X-accessibility.brief.md) — VoiceOver / reduced-motion / Dynamic Type behavior. - [chat-home.screen.md](./chat-home.screen.md) — DM-shaped sibling stream. - [coop-drawer.screen.md](./coop-drawer.screen.md) — multi-member surface pattern this screen extends. - [approval-card.screen.md](./approval-card.screen.md) — quorum action cards reuse the stakes-band + 3-action shape. ## Out of scope - Salon discovery + join flow (lives in `peer-profile.screen.md` + AE5 directory; not authored here). - Cross-platform variants (iPad / web; deferred per [Brief E](./E-cross-platform.brief.md)). - Shared-playbook composer (AE6 `shared_playbook` collab kind; separate screen if surfaced). - Platform-admin moderation queue interior (AE10 escalation target; out-of-brief signpost only). - Founder-replacement dispute resolution (covered in AE4 proposal lifecycle; no dedicated screen at P0). ## Open questions - **SAL-Q1** Mediation-dot affordance — does tapping the dot open the AD verbatim-view sheet by default, or is verbatim-view a long-press only (to keep tap-on-handle = profile)? `[blocking]` (lean: long-press for verbatim, tap-on-handle for profile; the dot itself is a non-interactive signal). - **SAL-Q2** Quorum threshold for mod actions in salons larger than 3 founders — flat `2 of 3` of currently-active mods, proportional `⌈M/2⌉ + 1`, or salon-configurable at creation? `[engineering]` (lean: proportional with floor=2; configurable post-P0). - **SAL-Q3** Specialist-ambient frequency cap — how often can `ai-copilot` post ambient nudges into a salon before it feels intrusive? Per-salon daily cap or per-member dismissibility? `[exploratory]` (lean: per-salon daily cap = 1, plus member-side mute of all ambient).