Five Across—tri-brand wireframes (Daily Cards)

One platform, three identities, every surface labeled. Five Across (fiveacross.app, general register, minimal camp, share mark ✳️) is the platform; Gay Cruise Bingo (gaycruisebingo.com, cruise register, full camp, 🚢) and Vacay Bingo (vacaybingo.com, trip register, moderate camp, 🧳) are Editions of it. Every frame opens with a brand chip naming the identity it renders and carries a stable anchor of the form #fx-<surface>-<brand>; pre-rename ids from earlier revisions of this doc still resolve as aliases. Wording follows the signed-off Edition lexicon (#608)—registers, wordmarks, share marks and per-surface tables are binding. Five Across ships its own theme trio—✨ Marquee / 🎊 Confetti Hour / 🌙 Afterglow (#617), Marquee the Edition default—and fiveacross-slate is a proposed alternative.

Canvas: iPhone 15 Pro—393×852 pt (19.5:9), Safari baseline, with Dynamic Island and home indicator. Installed-PWA frames run standalone (no browser chrome); the install-nudge frame shows Safari’s bottom bar, since that’s the only moment players see it. Every frame is painted with the actual theme tokens from src/theme/themes.css (fiveacross-slate alone uses a palette proposed in the specs; the tutorial themes and the Bodega day themes all ship). Marked squares use the app’s real linear-gradient(--primary, --secondary) fill with --on-gradient text. The header always shows today’s port and theme on two lines; the board area retints to the viewed Day.

Authoring rule, learned the hard way. When a caption cites a shipped component, the frame's copy must be lifted from that component in the same edit—never add the citation on its own. A frame carrying no reference is read skeptically; a frame captioned TomorrowsCardInvite.tsx is read as settled and gets implemented. So a half-applied citation does not half-fix the frame, it converts a guess a reviewer would have questioned into one they will not. Three findings on #867 were exactly this, all introduced in rounds that were adding rigor. Two corollaries: cite the derivation rule alongside any quoted string (ceremonialDayIndexSet outlives the wording “except the wrap-up”, and the rule stays true when the copy is rewritten), and re-check quoted strings against source immediately before pushing—main moves fast enough that a verbatim quote can go stale inside one branch. A frame that depends on seeded or provisioned state says so on the frame, never in the caption alone.

Known deltas—where this document is deliberately ahead of the app. Every one is tracked, so a reviewer can tell a decision from a mistake without re-deriving it. If you find a divergence that is not on this list, it is a bug in the document, not a proposal.
· #882 — fiveacross-slate, the platform palette these frames wear on Edition-less surfaces. Not a registered ThemeId; the shipped wardrobe is ✨ Marquee / 🎊 Confetti Hour / 🌙 Afterglow (#617).
· #883 — DECIDED (won't-adopt, signed off): the Admin console stays Edition-branded, mounted in the Edition shell at /more/admin and scoped to one Event. sec-fa-admin keeps drawing the declined Five Across platform-surface alternative for the record, not as a live proposal; lexicon.placePlural stays unconsumed either way.
· #884 — resolved: src/recon-share-og.test.ts pins the OG artboards' board pattern/bars, on-mark palette tokens, and eyebrow/stamp copy against scripts/og/render-og-editions.mjs's OG_EDITION_ART manifest; the generated PNGs remain pixel truth, and the artboards' base palette, gradient geometry, font sizes and offsets are illustrative only.
· #885 — DECIDED (won't-adopt, signed off): "— no theme" does not become a first-class Day option. DayDef.theme stays a required registered ThemeId; an occasion-neutral Event picks from its Edition's registered Themes instead.
· #785 / #786 / #545 — the organizer-setup wizard, exploratory in full and marked so in its own section header.
· sec-setup-assist — Drafting with Claude: the credit-backed assists that reach into the wizard's Steps 3 and 4. Exploratory; ticketed as #1958 under #786, with the proposed contract in specs/event-setup-assist.md; proposed against #786 Decision 2's pack problem and the PRD's "AI-assisted prompt drafting with organizer approval" later opportunity.

The three identities—one platform

Five Across is the Brand—the platform—and doubles as its occasion-neutral Edition. Gay Cruise Bingo and Vacay Bingo are the other two Editions (#532 / #608). The platform is confident and neutral; the Editions carry the camp. Everything below the chrome—the grid, marking, tally, Doubts, the tab set, the admin console—is one product; what an Edition owns is its lockup, its palette, its imagery, its prompt language and its register. These three cards are the legend the rest of the doc leans on: every frame carries the brand chip of the identity it renders, and every anchor ends in -gcb, -vacay or -fa—or -tri for cross-brand comparison boards (plus the brand-neutral fx-email-anatomy). Wording is governed by the signed-off Edition lexicon (#608); themes.css ships the Five Across trio—✨ Marquee / 🎊 Confetti Hour / 🌙 Afterglow (#617)—with Marquee the Edition default the shipped gate wears, and fiveacross-slate is a proposed alternative.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
Sign in, get your card, mark it if you see it.
Domain
gaycruisebingo.com
Register
Cruise · Days are Ports · the crowd is "the whole boat" · offline holds up at sea
Share mark
🚢 · file slug gay-cruise-bingo-*
Voice
Full camp. Decorative lead-ins in budget — “A fresh build just docked”
Palette
The 15-theme wardrobe is the identity; reference neon-playground.
18+
Dynamic — the shipped Event derives adultContent: true, so the gate draws.
🧳 Vacay Bingo
VACAY BINGO
by Five Across
Take the detour. For the story.
Domain
vacaybingo.com
Register
Trip · Days are Stops · the crowd is "the whole group" · offline holds up wherever you land
Share mark
🧳 · file slug vacay-bingo-*
Voice
Moderate camp — the spontaneous friend who suggests the detour. No decorative lead-ins.
Palette
Sonoma Coast, deliberately non-tropical; reference side-quests.
18+
Dynamic — Bodega derives adultContent: false, so no gate is drawn.
✳ Five Across
FIVE ACROSS
Bring everyone into the game.
Domain
fiveacross.app
Register
General · Days are Days, Places are Places · the crowd is "everyone here" · offline holds up in a packed venue
Share mark
✳️ (U+2733) · file slug five-across-*
Voice
Minimal camp — the charismatic host. Functional emoji only; update toast leads ⬆️.
Palette
Ships ✨ marquee / 🎊 confetti-hour / 🌙 afterglow (#617), Marquee the default; this card is drawn in proposed fiveacross-slate—slate + signal cobalt.
18+
Dynamic — the gate follows the Event’s pool (OR’d with an Admin override), never the Edition.

Join & event entry—one gate, three identities

The signed-out gate is the only surface a player sees before the app knows anything about them, so it is where the Edition has to carry the whole brand by itself (publicHostnames/{host}.edition → editionBrand(), ADR 0009). Identical mechanics on all three: wordmark, one tagline, the event in a box, Google sign-in, offline reassurance. What changes is the register (cruise / trip / general), the lockup treatment (glow / postcard / set type), and whether the 18+ attestation is drawn at all—that last one follows publicHostnames/{host}.adultContent, derived from the Event's pool OR'd with an Admin forceAdult override, not from the Edition (#608 § Dynamic 18+).

🚢 Gay Cruise Bingo🌱 seeded-preview state
GAY CRUISE BINGOBY FIVE ACROSS
What happens at sea. Goes on the card.
Sign in, get your card, mark it if you see it.
☐
I'm 18 or older and I know exactly what I'm getting into. Keep it legal, no minors, and don't post people who didn't consent.
Continue with Google
Lost signal at sea? Your card keeps working offline—marks sync when you reconnect.

Join—the 18+ gate, drawnFull camp: the wordmark keeps its soft glow, the tagline is the shipped gcb string (the itinerary lives in metaDescription, never on the gate) under a new cruise-register chip, and the sailing sits in a plain panel rather than Vacay's postcard. The panel is conditional chrome, though: EventPostcard renders only from a seeded publicHostnames/{host}.preview slice, and gaycruisebingo.com has none provisioned—today's shipped GCB gate draws no box. New in #688—the BY FIVE ACROSS endorsement line. GCB predates the platform but is now an Edition of it, so it wears the platform's signature exactly as Vacay does, in the same slot: a sibling of the h1, never inside it. An endorsement, not a rename. The wordmark, the cruise register, the adult posture, gaycruisebingo.com and the legacy Firebase project are all untouched—and the Join voice is now harmonised across all three gates: every Edition gets a tagline chip in the same slot and an Event panel wearing the same postage stamp, because a treatment that only one brand receives reads as an accident rather than a system. What stays Vacay-only is the invite note under the CTA. The chips and the gcb stamp are shipped brand-table values (#881). signinTaglineChip stays vacay's own—it REPLACES the plain tagline there; gcb and fiveacross instead carry a separate, ADDITIVE signinVoiceChip, drawn above their own plain tagline rather than instead of it. Postage is signinStampGlyph: 🏳️‍🌈 on gcb, and fiveacross's own ✳️ share mark—not a glyph tied to any one sample Event, since that Edition stays occasion-neutral. At iPhone widths the 16-character wordmark stacks to two lines and the byline centres under it—design intent for this gate stack, not yet measured; what scripts/verify-wordmark-one-line.mjs proves is the post-auth header wordmark staying one-line at 390×844 and 375×667. The offline line drops the old printed-cards-and-PDF claim from THIS slot: all three Editions now promise the same routine mechanic here and vary only the opener. The printed cards and PDF are still real (a launch-accepted total-failure fallback, not a routine one)—they moved to the crash panel's own crashFallbackNote (Codex round 2), not out of the app. The attestation is shown because this Event's pool holds active spicy Prompts, so adultContent derives true; sign-in stays disabled (40% here) until the box is ticked, and ticking it persists the attestation through signIn → attest. Splash before this frame reads "Checking your cruise pass…"; the advisory row in More reads "18+ advisory & acceptable use", and the sheet behind it opens "This is an 18+ space for one sailing's friend group."

🧳 Vacay Bingo
VACAY BINGO
by Five Across
Take the detour. For the story.
Weekend in Bodega Bay
Aug 7–9 · hosted by Kim · Day 1: The Birds Have Entered the Chat
bodega-bay.fiveacross.app
Continue with Google
Prompts are invitations, not chores. Take the fun detour, share the story if you want—five across earns a BINGO.
Patchy signal? Your card keeps working offline—marks sync when you reconnect.

Join—the postcard, not the casinoArrival through any serving hostname draws this same identity in place—publicHostnames/{host}.edition selects the brand, no redirect (#599; the canonical host is analytics-only, #607): one identity, the Vacay lockup with the BY FIVE ACROSS endorsement line, the trip as a postcard whose stamp corner carries the current Day's emoji as its postage (slightly rotated, like it was pressed on; the box is content-sized so the postage can never overflow it, and the postcard reserves its corner so text never runs beneath the stamp; an empty stamp box reads as a rendering bug—if no Day emoji exists, render no stamp and no reserved corner; and the glyph is drawn once—the stamp takes it, so the Day line below drops its leading emoji and names the Day in words instead), the same Google sign-in. No 18+ attestation—Bodega's pool holds no active spicy Prompts (and no Admin override forces it), so adultContent derives false and the button is enabled on load; the same Edition would draw the gate for a spicier trip. Moderate camp: no decorative lead-in emoji, offline stated plainly. The offline line is the shipped vacay offlineNote (src/editions.ts, the #647 follow-through to #608): All three now promise the same mechanic in the same words—your card keeps working offline, marks sync when you reconnect—and only the opener changes register: Lost signal at sea? / Patchy signal? / Packed room, no bars? The old gcb string conflated that routine promise with the total-failure fallback—the printed cards and PDF are real (a launch-accepted contract, specs/x-launch-checklist.md § "Printed 12-card PDF fallback"), just not what this Join-gate line is about; that fallback now lives in the crash panel's own crashFallbackNote instead (#881, Codex round 2). Splash reads "Checking your trip pass…"; installed-PWA name Vacay Bingo.

✳ Five Across🌱 seeded-preview state
FIVE ACROSS
Bring everyone. Into the game.
Sign in, get your card, mark it if you see it.
Continue with Google
Packed room, no bars? Your card keeps working offline—marks sync when you reconnect.

Join—the platform, set in typeThe restraint is the differentiation: no glow on the wordmark (.fa-title), one confident hue, sentence case, functional emoji only. The Event is occasion-neutral—name, place, date window—where GCB shows a sailing and Vacay shows a postcard, and all three now wear a tagline chip and a postage stamp so the gates read as one system. The sample is Kim & Jo's wedding weekend, a Custom-occasion daily-cards Event (three Days, Aug 21–23); the Wedding occasion proper deals one_card—"One card, one celebration" (src/data/occasions.ts)—so a Days-bearing wedding sample has to be the Custom path. The offline note stays the same muted footnote SignIn renders on every Edition, but the fiveacross string is the strongest offline story of the three: a few hundred phones on one cell, behind concrete and structural steel, drops signal harder than a ship does (#608 § offlineWhy—congestion and barriers named together; jammers never mentioned). No 18+ gate on this Event's tame pool—the gate carries no advisory footer; the More advisory row reads "Community guidelines" on a tame pool—and see fx-join-gcb for the gate drawn on an Event whose pool derives it. Drawn in the proposed fiveacross-slate; the shipped gate wears ✨ Marquee, the Edition default. Splash reads "Checking your pass…".

First open—the coach overlay on three Editions

One scrim, once per Event, over the player's first dealt card (src/components/CoachOverlay.tsx): a badge legend, not a tutorial. The mechanics it decodes—tally, Doubt, add-proof, free space—are platform mechanics and read identically on every Edition, which is the honest finding: the overlay itself barely changes. What changes around it is the chrome (wordmark, endorsement line, theme tokens), the Day identity underneath (port / stop / place), and—on a tutorial Day only—the warm-up banner behind the scrim, whose caption is a per-Edition override rather than a token swap ("all on the ship" / "close to home" / "to warm up"). Of these three frames only GCB sits on one: Bodega ships Friday tutorial: false (a competitive easy card), and the wedding weekend opens straight into a competitive card, so TutorialBanner renders nothing there. Replayable from More → How to play; a launch-beat overlay (Reshuffle) queues behind it rather than stacking.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
⚓ Sails Jul 15
🛳️ Welcome Aboard
Day 1 · Welcome AboardWarm-up
🇮🇹 Trieste

How to read your card

4
Tally count. The number on a marked square is how many players got it too—tap it to see who.
👀 2
Doubt badge. Means someone wants proof. Attach a photo to clear it—a Doubt never unmarks your square, it's never a gate.
+
Add proof. Tap the plus on any marked square to attach a pic and back it up.
FREE
Free space. The center square is free—already marked for everyone.
Got it—deal me in.
Card
Feed
Ranks
More

First-open coach overlayShows once per Event, over the player's first dealt card (naturally the embark card for day-one joiners). A badge legend, not a tutorial—the "How this works" banner behind the scrim carries the narrative (three EMBARK_BEATS, then the per-Edition warm-up caption plus the chaosLine derived from the first main Day's unlockAt); the overlay decodes the numbers, verbatim CoachOverlay.tsx on every Edition. Replayable from More → How to play. Cruise register in the chrome: "all on the ship" in the banner caption, 🛳️ in the header.

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
🐚 Bodega Bay
🐦 The Birds Have Entered the Chat
Day 1 · The Birds
🐚 Bodega Bay
Take a windblown group selfie
Get a bird into the background of a photo
Find the best boat name in the harbor
Make a toast about friendship
Capture a colorful buoy or crab pot
Take a picture of a fire
Find a hand-painted sign
Win a game of something
Photograph the drink of the day
Take a picture of something red
Give a friend a compliment
Get a group photo where nobody is ready
FREEThe flock has landed
Photograph the fog rolling in, or refusing to leave
Catch somebody talking about their partner
Take a photo of somebody arriving at the house
Get everyone in one frame using a timer
Find the house's weirdest decorative object
Suggest something for the group to do tomorrow
Post a candid that makes the group laugh
Catch someone talking to a bird
Take a picture of yourself in the hot tub
Photograph the group's shoes in a pile by the door
Find a flower growing somewhere it shouldn't
Capture a cheers/toast in action

How to read your card

4
Tally count. The number on a marked square is how many players got it too—tap it to see who.
👀 2
Doubt badge. Means someone wants proof. Attach a photo to clear it—a Doubt never unmarks your square, it's never a gate.
+
Add proof. Tap the plus on any marked square to attach a pic and back it up.
FREE
Free space. The center square is free—already marked for everyone.
Got it—deal me in.
Card
Feed
Ranks
More

First open on a trip—same legend, trip registerIdentical overlay mechanics; the Edition shows up in the chrome and the Day underneath. Header names a stop, not a port—headerDayIdentity draws {placeEmoji} {place} over {themeEmoji} {label}, with no weekday. The place glyph here is shipped (#881): Friday's placeEmoji moved from 🐦—the same glyph its Theme carries, which duplicated the bird in the header—to 🐚. The Theme glyph is untouched—while the sea-glass/weathered-red day theme retints the whole frame. The grid is Friday's shipped easy pool verbatim (scripts/seed-data/bodega-bay-2026.mjs, free space "The flock has landed"). No warm-up banner and no Warm-up tag: Bodega ships Friday tutorial: false—a competitive easy card—so TutorialBanner renders nothing here and the banner is GCB-only across these three frames. The coach copy is verbatim CoachOverlay.tsx—it contains no cruise noun, so it needs no per-Edition override, which is exactly the kind of string the #608 sweep should leave alone. Replay entry in More reads "Replay the welcome walkthrough" (GCB keeps "Replay the Welcome Aboard walkthrough").

✳ Five Across
FIVE ACROSS
🥂 The Barn at Green Valley
✨ Marquee
Day 1 · Marquee
🥂 The Barn at Green Valley
Meet someone from the other side
Find your seating card
First toast
Someone's shoes already off
Group photo with the hosts
Hear the how-they-met story
Dance floor opens
Program read aloud
Ask a stranger how they know them
Cake spotted
Hand your phone over for a photo
Bar-line conversation
FREEYou made it
A tie loosened
Kids running the room
Someone requests a song
Photo-booth prop misused
Slow song, everyone stands
Sunglasses left behind
A toast goes long
Sparkler handoff
Someone finds the good couch
Late-night snack appears
Everyone in one photo
Last call announced

How to read your card

4
Tally count. The number on a marked square is how many players got it too—tap it to see who.
👀 2
Doubt badge. Means someone wants proof. Attach a photo to clear it—a Doubt never unmarks your square, it's never a gate.
+
Add proof. Tap the plus on any marked square to attach a pic and back it up.
FREE
Free space. The center square is free—already marked for everyone.
Got it—deal me in.
Card
Feed
Ranks
More

First open on the platform—the chrome the Editions inheritSame four legend rows, same CTA, same tab set (Card · Feed · Ranks · More, Lucide throughout, avatar on More)—this is the canonical chrome, and GCB and Vacay are it plus a wardrobe. The Day is just a Day ("Day 1 · Marquee"—Friday's rehearsal on Kim & Jo's wedding weekend, a Custom-occasion daily-cards Event; the Wedding occasion proper deals one_card, "One card, one celebration", so a Days-bearing sample is the Custom path), the header shows a place where GCB shows a port, and the header wordmark drops the glow. Functional emoji only: 👀 and FREE survive because they name badges the player must recognise; nothing decorative gets in. Drawn in the proposed fiveacross-slate; the shipped Five Across wardrobe is ✨ Marquee / 🎊 Confetti Hour / 🌙 Afterglow (#617), with Marquee the Edition default.

The card—active, locked, claiming, proving, notified

The board and everything a player does on it, drawn three times per surface. These are the mechanics the platform owns outright: the grid, the marked-cell gradient, the tally badge, the Doubt eye, the claim sheet and its segments are byte-identical on every Edition (Board.tsx, ProofSheet.tsx). What changes is the lockup, the palette, and the day framing—Port on Gay Cruise Bingo, Stop on Vacay Bingo, plain Place on Five Across. Where a surface already existed in this doc for Gay Cruise Bingo it is kept verbatim and merely chipped and re-anchored: gcb is the fallback Edition and its rendered chrome must not drift.

Active card—the Day as it looks on its own morning

Gay Cruise Bingo is drawn ten times over in the Day-by-day gallery (fx-day-1-gcb … fx-day-10-gcb); Vacay Bingo’s Saturday card is fx-card-vacay. Only the platform variant is new here.

✳ Five Across
FIVE ACROSS
🥂 The Barn at Green Valley
✨ Marquee
Fri 🥂
🔒 Sat 💍
🔒 Sun 🥞
›
Day 1 · Marquee
🥂 The Barn at Green Valley
Lights up, doors open. Bulb-gold warmth and ticket red on deep black—big-night energy for any occasion.
Tonight: 🥂 Run-through at five · 🍽️ Dinner on the lawn
Someone cries during a toast7
Ask the DJ for a song
Find your name on the seating chart
Photo with someone you just met
Grandparents on the dance floor
A speech runs past five minutes
Someone's phone rings mid-vow3
Kids own the aisle
Two guests in the same color
Get a drink for a stranger
Group photo, wide angle
Someone loses a shoe
FREEKim & Jo said yes
Best man forgets a name
Cake before dinner
Photograph the flowers
Sparkler photo attempt11
Someone asks for the wifi
First dance, phones down
A table of empty glasses
Ask a barn staffer their favorite wedding
Bouquet lands nowhere near you2
Late-night snack run
Selfie with the couple
Toast with someone new
Everyone deals from tonight's shared pool—your 24 may differ.
Card
Feed
Ranks
More

Active card — Five AcrossThe platform in its own chrome: FIVE ACROSS set type, no glow, slate + signal cobalt, marked squares filled with the tonal linear-gradient(--primary,--secondary) so they read as one decisive color rather than a party gradient. Occasion-neutral framing throughout — the header shows the place where GCB shows the port, and Days wear registered Themes (“Day 1 · Marquee”; the rehearsal itself lives in the Tonight entries, never the theme slot). The pool note under the grid is doc annotation, not shipped UI—the board renders no such line, and independently dealt cards may differ. Functional emoji only: ✓ and 🔒 plus each Day's one placeEmoji in the day strip (#646), nothing decorative. Tame pool, so this Event derives adultContent: false and never shows the 18+ gate. Brand variants: gcb = #fx-day-2-gcb (gallery, cruise register, per-Day theme retint); vacay = #fx-card-vacay (trip register, Bodega palette). Grid, marking, tally and navigation are identical across all three — only chrome, palette and register move.

Locked future card

Mechanics are brand-invariant: the lock badge, the live free space and the caption “24 fresh squares land at 8 a.m. Come back after coffee.” are platform copy (Board.tsx day-lock-caption), identical on every Edition. The hour and its meridiem are DERIVED from that Day’s own unlockAt (src/unlockCopy.ts) — the 8 a.m. drawn here is this cruise’s schedule, not a fixed string; an Event opening at 06:00 reads “land at 6 a.m.” The tail derives too: a morning unlock ends “Come back after coffee.”, a non-morning one “Come back then.”

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🌊 Sea Day
💖 Neon Pink Playground
✓ Wed 🇮🇹
✓ Thu 🇭🇷
Fri 🌊
🔒 Sat 🇲🇹
›
Day 4 · Sporty Splash
🇲🇹 Valletta
Leave your phone in the cabin—water everywhere, then locker-room fantasy and varsity realness.
Tonight: 💦 Splash T-Dance · 🏋️ Get Sporty
Unlocks 8:00 a.m. · Sat, Jul 18
24 fresh squares land at 8 a.m. Come back after coffee.
Card
Feed
Ranks
⋯More

Locked Day previewViewed from Day 3: full Sporty Splash chrome with the two-party "Tonight" tease, hatched blank squares, live free space, lock badge with the unlock time. The header still shows today (Sea Day · Neon Pink Playground).

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
🦪 Bodega Bay
🌊 Bodega Bay Side Quests
✓ Fri 🐚
Sat 🦪
🔒 Sun 🌅
🔒 Sun 👋
Day 3 · Fog, Froth & Farewells
🌅 Bodega Bay
The last slow morning. Fog silver, chowder cream, coffee brown, and dusk coral through the window.
Tonight: ☕ Last coffee · 🧳 The slow pack
FREEOne last coastal morning
Unlocks 6:00 a.m. · Sun, Aug 9
24 fresh squares land at 6 a.m. Come back after coffee.
Card
Feed
Ranks
More

Locked Day preview — Vacay BingoSunday morning viewed from Saturday. Same locked-preview mechanics as #fx-locked-gcb—hatched blank squares, the live free space (“One last coastal morning” is this Day's own freeText), the lock badge with the unlock time, and the header still showing today—in trip register. Bodega runs FOUR Days, so the strip carries the wrap-up chip too: Sunday twice—the 06:00 morning Day (🌅) and the 11:00 check-out Day wearing the operator's 👋—one emoji per chip (#646). The tease under the day bar is the same two-line pairing every Edition renders, the Theme's registry description then Tonight; register differs, format doesn't. Drawn in the light fog-froth-farewells theme so the locked state is proved against a light palette as well as a dark one. Register diffs only: stop for port, the group for the boat; the lock caption is platform copy whose hour and tail derive from this Day's own unlockAt.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour
✓ Fri 🥂
Sat 💍
🔒 Sun 🥞
Day 3 · Afterglow
🥞 The Barn at Green Valley
The slow, happy wind-down. Dusk violet, ember orange, and one warm last light.
Tonight: 🥞 Send-off brunch · 👋 Safe travels
FREEKim & Jo said yes
Unlocks 8:00 a.m. · Sun, Aug 23
24 fresh squares land at 8 a.m. Come back after coffee.
Card
Feed
Ranks
More

Locked Day preview — Five AcrossThe same surface with the platform imposing no theme of its own: structural, typographic, generous slate space. The day strip keeps to the one-emoji chip rule (#646): ✓ and 🔒 are state, and each chip wears its Day's placeEmoji (🥂 rehearsal, 💍 the wedding, 🥞 the send-off brunch)—identity, not camp. Proof that the locked preview is mechanics, not costume: three Editions, one badge, one caption, one free-space rule.

Claim sheet—the square tap

Every string in the sheet is shipped platform copy from ProofSheet.tsx: the title and its icon-only ✕, the 🔥 heat line, 🎖️ Cross My Heart, the three segments, the #190 Library note, Cancel / Mark it. Nothing here is Edition-scoped—which is the point.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🇭🇷 Split
🌍 Uniforms Without Borders
Day 2 · Uniforms Without Borders
🇭🇷 Split
Card
Feed
Ranks
More
Proof for “Lost passport”
✕
🔥 Marked by 4 others so far
🎖️ Cross My Heart
Photo Sound Callout
Take photo Library
Library picks wear a 🖼️ badge on the Feed
CancelMark it

Tile tap—the Claim sheetThe #181 flow as it ships: the sheet opens on every claim, Cross My Heart is the one-tap honor path, and + on an already-marked square opens the same sheet minus the pledge. The photo body splits into Take photo (live camera, one tap) and Library (native picker, #190)—the 🖼️ badge that marks a library pick renders on the resulting Feed card—and the 🔥 heat line adds social heat under the title. The sheet header carries the icon-only ✕ alongside Cancel; either dismisses. In admin-confirmed mode the primary reads "Submit claim".

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
🦪 Bodega Bay
🌊 Bodega Bay Side Quests
Day 2 · Bodega Bay Side Quests
🦪 Bodega Bay
Walk to a Bodega Head viewpoint
Find the best boat name in the harbor
Stage an original suspense-movie still
Get a bird into the background of a photo
Karaoke your best song
Take a windblown group selfie
Photograph the fog
Capture a colorful buoy or crab pot
Find a seashell on the beach
Spot a gull, pelican, or heron doing something undignified
Walk part of the Bodega Dunes
Photograph someone's hair losing a fight with the wind
FREEMain character on the coast
Spot a whale spout, or convincingly claim you did
Photograph the drink of the day
Get a group photo with the whole Pacific behind you
Take a picture of something red
Take a photo of your feet in the sand
Find a hand-painted sign
Take a picture of a wildflower
Photograph something the exact color of the sea today
Find the best bench on this coast and sit in it a while
Get a group photo where nobody is ready
Find a bakery, farm stand, or roadside sign worth coming back for
Take a picture of yourself in the hot tub
Card
Feed
Ranks
More
Proof for “Find the best boat name in the harbor”
✕
🔥 Marked by 3 others so far
🎖️ Cross My Heart
Photo Sound Callout
Take photo Library
Library picks wear a 🖼️ badge on the Feed
CancelMark it

Claim sheet — Vacay BingoTap a square, get this sheet—identical to #fx-claim-gcb line for line, because the claim flow is platform mechanics, not Edition voice. Sheet title, heat line, 🎖️ Cross My Heart, the Photo·Sound·Callout segments, Take photo vs Library (#190) and Mark it are all shipped ProofSheet.tsx strings with no cruise noun in them, so nothing needed translating. What changes is everything around it: Pacific blue and sea-glass, the Vacay lockup with its BY FIVE ACROSS endorsement line, and a trip Prompt behind the glass. In admin-confirmed mode the primary reads Submit claim and the sheet gains “Goes pending until an admin confirms.”—on every Edition alike.

✳ Five Across
FIVE ACROSS
🥂 The Barn at Green Valley
✨ Marquee
Day 1 · Marquee
🥂 The Barn at Green Valley
Someone cries during a toast
Ask the DJ for a song
Find your name on the seating chart
Photo with someone you just met
Grandparents on the dance floor
A speech runs past five minutes
Someone's phone rings mid-vow
Kids own the aisle
Two guests in the same color
Get a drink for a stranger
Group photo, wide angle
Someone loses a shoe
FREEKim & Jo said yes
Best man forgets a name
Cake before dinner
Photograph the flowers
Sparkler photo attempt
Someone asks for the wifi
First dance, phones down
A table of empty glasses
Ask a barn staffer their favorite wedding
Bouquet lands nowhere near you
Late-night snack run
Selfie with the couple
Toast with someone new
Card
Feed
Ranks
More
Proof for “Someone cries during a toast”
✕
🔥 Marked by 6 others so far
🎖️ Cross My Heart
Photo Sound Callout
Take photo Library
Library picks wear a 🖼️ badge on the Feed
CancelMark it

Claim sheet — Five AcrossThe same sheet on the platform's own chrome. The honor pledge row renders here because this sample Event runs honor mode; in stricter Claim Modes it renders disabled with the “Available when the event runs honor mode” hint, unchanged across Editions. Worth stating plainly in the doc: three near-identical frames is the finding—the claim sheet carries no Edition vocabulary at all, so the lexicon sweep (#608) touches nothing inside it.

Add proof—the + on a square you already marked

The same sheet minus the pledge row: the mark already exists, so there is nothing left to pledge. The primary stays “Mark it” on this path; the heat line subtracts the viewer’s own marker, so the count is genuinely others.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🇭🇷 Split
🌍 Uniforms Without Borders
Day 2 · Uniforms Without Borders
🇭🇷 Split
Lost passport
Matching Speedos
Eat carbs
Cruise boyfriend
Sunset selfie
Late-night pizza
Karaoke “Fergalicious”
Lost bracelet
Mirror-hall selfie
Breakfast in sunglasses
Emergency fan deployment
Overpacked toiletries
FREEComplain about circuit music
Pool-chair territory dispute
Selfie with HAYLA
Poolside caftan moment
Too many group chats
Get lost on the ship
Matching tank tops
Dramatic outfit change before dinner
New best friend from another city
Elevator outfit compliment
Nap through the main event
Drink three dirty martinis
Become ship-famous
Card
Feed
Ranks
More
Proof for “Lost passport”
✕
🔥 Marked by 7 others so far
Photo Sound Callout
Take photo Library
📷
CancelMark it

Add proof — Gay Cruise BingoThe + path: the same sheet as #fx-claim-gcb with the 🎖️ Cross My Heart row gone—the square is already marked, so there is nothing left to pledge. The heat line subtracts your own marker (Codex P3, #211), so “7 others” really is seven other people. A captured photo previews inline; the live/library stamp badges the resulting Feed card (#190). Submitting posts the proof to the Feed and flips your row in the who-list (#fx-wholist-gcb) to ✓ Answered—attaching a proof is what answers a 👀 doubt on your mark, and doubts never unmark you. The primary still reads Mark it on this path—ProofSheet.tsx only swaps the label in admin-confirmed mode, where it becomes Submit claim.

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
🦪 Bodega Bay
🌊 Bodega Bay Side Quests
Day 2 · Bodega Bay Side Quests
🦪 Bodega Bay
Walk to a Bodega Head viewpoint
Find the best boat name in the harbor
Stage an original suspense-movie still
Get a bird into the background of a photo
Karaoke your best song
Take a windblown group selfie
Photograph the fog
Capture a colorful buoy or crab pot
Find a seashell on the beach
Spot a gull, pelican, or heron doing something undignified
Walk part of the Bodega Dunes
Photograph someone's hair losing a fight with the wind
FREEMain character on the coast
Spot a whale spout, or convincingly claim you did
Photograph the drink of the day
Get a group photo with the whole Pacific behind you
Take a picture of something red
Take a photo of your feet in the sand
Find a hand-painted sign
Take a picture of a wildflower
Photograph something the exact color of the sea today
Find the best bench on this coast and sit in it a while
Get a group photo where nobody is ready
Find a bakery, farm stand, or roadside sign worth coming back for
Take a picture of yourself in the hot tub
Card
Feed
Ranks
More
Proof for “Find the best boat name in the harbor”
✕
🔥 Marked by 5 others so far
Photo Sound Callout
Take photo Library
📷
CancelMark it

Add proof — Vacay BingoSame sheet, trip palette. The proof body is where Vacay's “invitations, not chores” posture actually shows up—the Prompt is a detour worth photographing rather than a dare to survive—but not one control or label differs from the GCB frame beside it. 👀 doubts and the Feed post are platform behaviour; the live/library stamp badges the resulting Feed card, not the in-sheet preview.

✳ Five Across
FIVE ACROSS
🥂 The Barn at Green Valley
✨ Marquee
Day 1 · Marquee
🥂 The Barn at Green Valley
Someone cries during a toast
Ask the DJ for a song
Find your name on the seating chart
Photo with someone you just met
Grandparents on the dance floor
A speech runs past five minutes
Someone's phone rings mid-vow
Kids own the aisle
Two guests in the same color
Get a drink for a stranger
Group photo, wide angle
Someone loses a shoe
FREEKim & Jo said yes
Best man forgets a name
Cake before dinner
Photograph the flowers
Sparkler photo attempt
Someone asks for the wifi
First dance, phones down
A table of empty glasses
Ask a barn staffer their favorite wedding
Bouquet lands nowhere near you
Late-night snack run
Selfie with the couple
Toast with someone new
Card
Feed
Ranks
More
Proof for “Someone cries during a toast”
✕
🔥 Marked by 4 others so far
Photo Sound Callout
Take photo Library
📷
CancelMark it

Add proof — Five AcrossThe platform state. Every emoji on this sheet is functional—the 📷 preview and the 🔥 heat line carry state, not tone—so the minimal-camp budget costs the surface nothing. 🎖️ Cross My Heart is absent here only because the square is already marked; on a first claim it appears on all three Editions identically (see #fx-claim-fa).

Admin Notice on the Card screen

The Card-tab banner (NoticeBanner.tsx), not the Feed card. Authoring lives in fx-admin-messages-fa—admin is a Five Across surface on every Edition—but the Notice a player reads renders in that player’s own Edition chrome, which is what these three frames prove.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🌊 Sea Day
💖 Neon Pink Playground
✕🚢 Splash T-Dance moved to 4Pool deck opens an hour earlier than the printed schedule—tell the boat before someone naps through it.
✓ Wed 🇮🇹
✓ Thu 🇭🇷
Fri 🌊
🔒 Sat 🇲🇹
›
Day 3 · Neon Pink Playground
🌊 Sea Day
Sunset selfie
“I need electrolytes”
Matching Speedos9
Ship-photographer ambush
Karaoke “Fergalicious”
Accidental matching outfits
Become ship-famous
Feathers, mesh, or sequins before noon
Late-night pizza
Mirror-hall selfie4
Suspiciously perfect tan
Pool-chair territory dispute
FREEComplain about circuit music
Unexpected Broadway sing-along
Cruise boyfriend
Themed-party costume escalation
Breakfast in sunglasses
“I'm just having one drink”
Matching tank tops2
Nap through the main event
Too many group chats
Eat carbs
Elevator outfit compliment
Poolside caftan moment
Selfie with HAYLA
Card
Feed
Ranks
More

Admin Notice on the Card screen — Gay Cruise BingoThe pinned Notice, seen from the Card tab: accent-bordered, above the day strip and Board (App.tsx mounts NoticeBanner ahead of Board), shown once. The banner is ✕ + title + body only—the 📌 who-line belongs to the Feed's NoticeCard copy of the same Notice. ✕ is a per-device dismissal (gcb.notice.<id>.dismissedAt) that hides only this banner—the Notice stays in the Feed for latecomers (#fx-notice-gcb), and dismissing reveals the next still-undismissed pinned Notice if there is one. Full camp: a 🚢 lead-in on the title and the boat as the crowd noun. Composed in #fx-admin-messages-fa—the console is a Five Across surface, but what the player reads renders in their own Edition's chrome.

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
🦪 Bodega Bay
🌊 Bodega Bay Side Quests
✕Sunday: oysters at 11Meet at The Tides at 11—Kim’s driving the second car. Sunday’s card still unlocks at 6, so mark before you eat.
✓ Fri 🐚
Sat 🦪
🔒 Sun 🌅
🔒 Sun 👋
Day 2 · Bodega Bay Side Quests
🦪 Bodega Bay
Walk to a Bodega Head viewpoint
Find the best boat name in the harbor
Stage an original suspense-movie still
Get a bird into the background of a photo6
Karaoke your best song
Take a windblown group selfie
Photograph the fog
Capture a colorful buoy or crab pot
Find a seashell on the beach
Spot a gull, pelican, or heron doing something undignified
Walk part of the Bodega Dunes
Photograph someone's hair losing a fight with the wind3
FREEMain character on the coast
Spot a whale spout, or convincingly claim you did
Photograph the drink of the day
Get a group photo with the whole Pacific behind you
Take a picture of something red
Take a photo of your feet in the sand
Find a hand-painted sign
Take a picture of a wildflower
Photograph something the exact color of the sea today2
Find the best bench on this coast and sit in it a while
Get a group photo where nobody is ready
Find a bakery, farm stand, or roadside sign worth coming back for
Take a picture of yourself in the hot tub
Card
Feed
Ranks
More

Admin Notice on the Card screen — Vacay BingoSame banner, moderate camp: the decorative lead-in goes, and the banner stays ✕ + title + body—attribution (the 📌 who-line) lives on the Feed's NoticeCard, not the Card-tab banner. The host writes in trip register—the group, a stop, a plan—and the mechanics underneath are untouched: one banner, per-device ✕, the Notice persisting in the Feed. Bodega derives adultContent: false, so nothing on this screen carries an 18+ mark.

✳ Five Across
FIVE ACROSS
🥂 The Barn at Green Valley
✨ Marquee
✕Rehearsal moved to 5:30The Barn asked us to start half an hour early. Same place—everyone meet on the ceremony lawn.
Fri 🥂
🔒 Sat 💍
🔒 Sun 🥞
Day 1 · Marquee
🥂 The Barn at Green Valley
Someone cries during a toast7
Ask the DJ for a song
Find your name on the seating chart
Photo with someone you just met
Grandparents on the dance floor
A speech runs past five minutes
Someone's phone rings mid-vow3
Kids own the aisle
Two guests in the same color
Get a drink for a stranger
Group photo, wide angle
Someone loses a shoe
FREEKim & Jo said yes
Best man forgets a name
Cake before dinner
Photograph the flowers
Sparkler photo attempt11
Someone asks for the wifi
First dance, phones down
A table of empty glasses
Ask a barn staffer their favorite wedding
Bouquet lands nowhere near you
Late-night snack run
Selfie with the couple
Toast with someone new
Card
Feed
Ranks
More

Admin Notice on the Card screen — Five AcrossThe platform register: warm, competent, brief, no lead-in emoji, everyone as the crowd noun. This is the frame that makes the ownership point clearest—the Notice is authored in one Five Across console (#fx-admin-messages-fa) and lands in three different chromes; only the words the organizer types are theirs.

Brand-invariant mechanics—drawn once

Three surfaces whose every visible string is platform copy—save one word: LaunchIntro's second beat interpolates the Edition's occasion noun (“Three for the whole cruise” here; trip/event on the other Editions)—so a tri-brand rendering would differ only by palette and that noun. They are drawn once, in Gay Cruise Bingo chrome (the shipped rendering), with the register deltas stated in the captions rather than re-drawn. Anchors keep the -gcb suffix because that is the chrome shown, not because the surface is Edition-scoped.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🇭🇷 Split
🌍 Uniforms Without Borders
Day 2 · Uniforms Without Borders
🇭🇷 Split
Card
Feed
Ranks
More
Who got “Lost passport”
5 players · 3 open doubts 👀 on this square
A doubt never blocks or unmarks—it's social pressure with a scoreboard.

Asking for proof—the Tally who-listTap any marked square's tally count to open this sheet: every player who marked the prompt, newest state on the right. "Pics or it didn't happen" raises a Doubt against that player's mark (one slot per pair per prompt, so no pile-ons from the same person); their square grows the 👀 badge, and attaching a proof flips their row to ✓ Answered with the proof thumbnail inline. Your own row gets no button—no self-doubt.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🇲🇹 Valletta
💦 Sporty Splash
Day 4 · Sporty Splash
×2
▦Card
◉Feed
♛Ranks
More
Reshuffle this card?
A fresh 24 squares for Day 4—same day, new luck.
This can't be undone. You'll never see this card again—and reshuffles don't come back.
2 of 3 reshuffles left · available only before you've marked a square
Keep my card Reshuffle it

Reshuffle—control + confirmThe shuffle chip lives in the day bar with the remaining cruise-wide count (×3 → ×1; a spent-out player gets no chip at all). It renders only on a pristine card: the moment you mark a square, the card is yours and the chip disappears (want out anyway? unmark everything first—your call, in the open). No cascade to warn about, so the confirm is simple: the card is gone forever and the counter is spent. Keep my card is the primary; Reshuffle is the danger action.

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🇮🇹 Trieste
🛳️ Welcome Aboard
Day 1 · Welcome AboardWarm-up
🇮🇹 Trieste

🆕 New today: reshuffles

Dealt a dud? Tap the shuffle chip on your card to trade it for a fresh one before you start marking.
!
Three for the whole cruise—spend them wisely. A reshuffle never comes back.
✓
Only before you mark: the moment you tap a square, the card's yours for the day.
Nice—let's play
▦Card
◉Feed
♛Ranks
More

Launch-day intro overlayOne-time announcement pop-up on first open after the feature deploys (localStorage-keyed, per feature); replayable nowhere—it's a launch beat, not a tutorial. Uses the coach-overlay pattern already in the app. “Three for the whole cruise” carries this surface's one Edition-scoped word—the interpolated occasion noun (trip/event on the other Editions).

The social surfaces—Feed, Notice, Ranks, More

Where the group sees itself. The mechanics are platform-owned end to end—tally cards, proof cards with their live/library source badge (#190), Moments, hearts (specs/feed-hearts.md), the overall leaderboard and its standings exception (derived from each Day’s resolved Scoring Policy, never from its pool), the daily First-to-BINGO strip, and the More menu’s ordering. The Edition-visible strings are few and they are exactly what these twelve frames isolate: the occasion qualifier on the champion line, the schedule row’s noun, the offline promise under Install, and the register of the Notice a player reads.

Feed—tally cards, proofs, Moments, hearts

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🌊 Sea Day
💖 Neon Pink Playground
Nathan Payne, Sterling Tadlock +12 got “Balcony or porthole photo”Day 1 · 🛳️ Welcome Aboard · bumped just now · tap for who
+ Proof
🎉 Javi got a BINGO! · Day 3 · 14m ago
3
Theo· Day 3 · 💖 Neon Pink Playground · 3:47p
“Feathers, mesh, or sequins before noon”
🏞️📷 live
5
👀 cleared 2 doubtstally 7
Big Denver Chris· Day 3 · 2:15p
“Unexpected Broadway sing-along”
0:19
tally 4
Javi got “Matching Speedos”Day 3 · 1:12p
🙋 Got it too
Jess· Day 3 · 12:31p
“Cause an international incident”
✍️ “Customs in Valletta would like a word with the man in the mesh caftan. Names withheld. It was Dan.”
2
👀 cleared 1 doubttally 2
Card
Feed
Ranks
More

Feed—Tally cards, proofs, and MomentsCruise register, full camp. Tally cards put bare marks in the stream—one live card per prompt per day (never duplicates), first two names then +N, avatar stack, bumped to the top when someone new gets it (debounced to one bump per ~10 min so hot squares don't bury photo proofs). Tap opens the who-list sheet; the button is + Proof if you've marked it, 🙋 Got it too if the square sits unmarked on one of your cards. Proof cards: avatar + name, day chip, the square quoted, then media—photo with live/library source badge (#190), audio with play + waveform + duration, or a callout. Moments stay gradient banners. Hearts (specs/feed-hearts.md): every proof and Moment wears an Instagram-style heart—outline until you tap it, filled with the theme primary once you have, count beside it (hidden at zero), once per player per post, tap again to take it back. Liking pops the heart and ticks the count; tally cards are aggregates, not posts—no heart. Two shipped affordances these frames elide for space: every proof card carries a ⚑ report control (its owner, a 🗑 delete; reports past settings.reportHideThreshold hide the card behind a flagged-for-review badge unless an Admin already restored or cleared reports for this incarnation), and as the finale freeze approaches the Feed shows the pre-freeze cue—Hearts are what the Most-Loved Photo award counts. Every mechanic on this frame is brand-invariant; only the vocabulary and the emoji budget move.

🧳 Vacay Bingo
VACAY BINGOBY FIVE ACROSS
🦪 Bodega Bay
🌊 Bodega Bay Side Quests
Kim, Jo +6 got “Spot the Potter Schoolhouse from the public road—it's someone's home, so admire and keep moving”Day 2 · 🌊 Bodega Bay Side Quests · bumped just now · tap for who
+ Proof
🎉 Jo got a BINGO! · Day 2 · 14m ago
4
Rae· Day 2 · 🌊 Bodega Bay Side Quests · 3:41p
“Photograph the fog”
🏞️📷 live
7
👀 cleared 1 doubttally 5
Dev· Day 2 · 2:26p
“Photograph something you had to pull over on Highway 1 for”
✍️ “Two dozen oysters at the roadside stand. For four people. Kim said ‘we'll manage' in the voice she uses when she has already paid.”
3
tally 2
Sam got “Find a bakery, farm stand, or roadside sign worth coming back for”Day 2 · 1:12p
🙋 Got it too
Kim· Day 1 · 6:04p
“Get a bird into the background of a photo”
0:12
tally 3
Card
Feed
Ranks
More

Feed—trip registerSame three entry kinds, same hearts, same debounce. What moves: the header carries a stop (🦪 Bodega Bay) where GCB carries a port, the day is a named vignette rather than a themed party night, and the lockup runs the VACAY BINGO wordmark over the BY FIVE ACROSS endorsement micro-line—the one-identity rule, never two competing brands in one chrome. Moderate camp: functional and Theme emoji survive, decorative lead-ins do not. Palette is the shipped side-quests reference (deep Pacific blue ground, seafoam primary, buoy-orange secondary, sand accent—the marked-cell gradient stays a coastal tonal pair; tokens synced from themes.css). Prompt voice is invitation, not chore.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour
Priya, Sam +9 got “A toast runs long”Day 2 · 🎊 Confetti Hour · bumped just now · tap for who
+ Proof
🎉 Sam got a BINGO! · Day 2 · 9m ago
6
Alex· Day 2 · 5:47p
“An unplanned group photo”
🏞️📷 live
9
👀 cleared 1 doubttally 6
Priya· Day 2 · 5:02p
“Someone requests a song the band refuses”
0:14
tally 4
Jordan got “Someone loses a shoe on the dance floor”Day 2 · 4:31p
🙋 Got it too
Sam· Day 1 · 8:58p
“A speech mentions the wrong ex”
✍️ “Uncle Ray got two names in before the microphone was, and I quote, ‘having trouble.'”
2
tally 3
Card
Feed
Ranks
More

Feed—general register, platform chromeThe same Feed with the camp turned off: FIVE ACROSS set in the platform grotesk with no glow, header carrying a place and the Day's registered Theme—Five Across registers its own occasion-neutral set (✨ Marquee, 🎊 Confetti Hour, 🌙 Afterglow, #617), because every Day requires a registered Theme and there is no themeless rendering path—and functional emoji only: 📷 🖼 🎙 ✍ 👀 🎉 carry state, nothing leads a sentence for flavour. Sample Event is occasion-neutral (Kim & Jo's Wedding · The Barn at Green Valley · Aug 22) and its pool is tame, so no 18+ furniture appears anywhere in the surface. Proposed fiveacross-slate palette: one signal-cobalt hue, tonally gradiented, so a marked cell and a Moment banner read as one decisive colour rather than a party gradient.

The pinned Notice, as players see it

Accent-bordered card at the very top of the Feed while pinned, above every Proof and Moment. The Feed copy is deliberately not dismissible—it is the durable record latecomers scroll to; the ✕ lives on the Card-tab banner alone (per-device, and the Notice stays here regardless).

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🇫🇷 Marseille
🪩 Revival: Classic Disco
Final stretch 🏁Last days at sea, and every card you've unlocked is still in play. Once a thing has happened, it's happened — if it's on three of your cards, that's three squares. Scroll back through your days, light up everything you've earned, and stack those bingos before we dock in Barcelona. 🚢📌 Nathan · Day 8
📷 Theo got "Poppers spill"Day 9 · 2m ago · 👀 cleared 3 doubts
🎉 Jess got a BINGO!Day 9 · 14m ago
✍️ Marco got "Cabaret hands during karaoke"Day 9 · 22m ago
▦Card
◉Feed
♛Ranks
⋯More

Feed—the pinned Notice players seeAccent-bordered card at the very top of the Feed while pinned, above every Proof and Moment. No ✕ here: the Feed copy is deliberately not dismissible—the durable record latecomers scroll to—while the Card-tab banner carries the per-device ✕. Attribution + day chip match Moment conventions. Unpinned Notices drop into the stream at their timestamp. Full camp: decorative lead-ins (🏁) and the cruise mark (🚢) both sit inside GCB's emoji budget.

🧳 Vacay Bingo
VACAY BINGOBY FIVE ACROSS
🌅 Bodega Bay
🌫️ Fog, Froth & Farewells
Last morningEvery card you've unlocked is still in play. Once a thing has happened, it's happened — if it's on two of your cards, that's two squares. Scroll back through the weekend, light up everything you've earned, and stack those bingos before we drive home. 🧳📌 Kim · Day 3
📷 Rae got "One last sunrise or foggy-morning photo"Day 3 · 4m ago · 👀 cleared 1 doubt
🎉 Dev got a BINGO!Day 3 · 18m ago
✍️ Sam got "Find something someone almost left behind"Day 3 · 25m ago
▦Card
◉Feed
♛Ranks
⋯More

Pinned Notice—trip registerSame accent-bordered card, same pin/attribution convention, same non-dismissible Feed copy. Every cruise noun is gone: at sea → the weekend, before we dock in Barcelona → before we drive home, and the sign-off mark is 🧳. The decorative headline lead-in (GCB's 🏁) drops out—moderate camp keeps functional and Theme emoji, not flourishes. Palette is the Vacay reference theme—registered id side-quests, label “Bodega Bay Side Quests” (Pacific blue, seafoam, buoy orange); tokens synced from themes.css.

✳ Five Across
FIVE ACROSS
🥞 The Barn at Green Valley
🌙 Afterglow
Last callEvery card you've unlocked is still in play. Once a thing has happened, it's happened — if it's on two of your cards, that's two squares. Scroll back through the weekend, light up everything you've earned, and stack those bingos before the last card closes.📌 Jo · Day 3
📷 Alex got "An unplanned group photo"Day 3 · 3m ago · 👀 cleared 1 doubt
🎉 Priya got a BINGO!Day 3 · 16m ago
✍️ Jordan got "Someone asks the band for one more"Day 3 · 24m ago
▦Card
◉Feed
♛Ranks
⋯More

Pinned Notice—general registerMinimal camp: no lead-in emoji in the headline and no sign-off mark in the body—the ✳️ share mark belongs on share cards and footers, not inside a Notice. 📌 📷 🏆 ✍️ stay because they carry state, not tone. Notices are organizer-authored, so this is the surface where the platform voice is most audible: warm, competent, brief. Composed in the Admin console, which mounts inside the Edition-branded shell with Edition-register copy—§sec-fa-admin draws the FA-chrome console as the platform-surface proposal #883 declined, not current or future behavior.

Ranks—overall leaderboard + daily honors

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🇮🇹 Naples
🏛️ Glamiators
AllWith BINGOBlackout
Daily first to bingo
🛳️ D1Marco
🌍 D2Jess
💖 D3Dan
💦 D4Theo
🌌 D5—
›
1
Jess ⭐ First BINGO📷✍️
7 bingos
84 squares
2
Marco📷🖼️🎙
6 bingos
91 squares
3
Dan
6 bingos
77 squares
4
Theo📷
5 bingos
80 squares
5
Big Denver Chris🎙
4 bingos
62 squares
Every Day Card counts here—except the wrap-up, which is pure ceremony. ⭐ marks the cruise-wide First to BINGO—tutorial Days excluded. Proof chips show every kind of proof a player has used. Tap a proof chip for the receipts in the Feed.
Share leaderboard
Shares as “Check out the Gay Cruise Bingo leaderboard 🏆” · gay-cruise-bingo-leaderboard.png
Card
Feed
Ranks
More

Ranks—overall + daily honorsOne cruise-long leaderboard summing every card except the ceremonial wrap-up—an exception derived from the resolved Scoring Policy (ADR 0011), not from pool identity: a closing Day that declares itself competitive still counts, a ceremonial Day on another pool does not, and an Event with no ceremonial Day gets no caveat sentence at all; per-day First to BINGO strip above it, one chip per theme night. The list itself has no section head—the surface runs filter row → honors strip → rows → footnote, and the Edition shows first in the footnote's occasion-wide credit, then in the share copy/filename. Shipped rows also carry each player's first-BINGO time (the final tiebreak) and a BLACKOUT badge when earned—elided here for width. Feed Moments carry the same day chip. Two shipped affordances the earlier wireframe omitted are drawn so the tri-brand comparison is honest: the filter row (All / With BINGO / Blackout, brand-invariant) and Share leaderboard. The ⭐ First-to-BINGO clause follows its own independent policy: it renders only when tutorialDayIndexSet is non-empty and names warm-up Days rather than a pool. Per-day First-to-BINGO chips still include every Day, tutorial Days included.

🧳 Vacay Bingo
VACAY BINGOBY FIVE ACROSS
🌅 Bodega Bay
🌫️ Fog, Froth & Farewells
AllWith BINGOBlackout
Daily first to bingo
🐦 D1Sam
🌊 D2Jo
🌫️ D3Dev
🌫️ D4—
›
1
Jo ⭐ First BINGO📷✍️
3 bingos
41 squares
2
Rae📷🎙
2 bingos
44 squares
3
Dev✍️
2 bingos
38 squares
4
Kim🎙
1 bingo
35 squares
5
Sam
1 bingo
29 squares
Every Day Card counts here—except the wrap-up, which is pure ceremony. ⭐ marks the trip-wide First to BINGO—tutorial Days excluded. Proof chips show every kind of proof a player has used. Tap a proof chip for the receipts in the Feed.
Share leaderboard
Shares as “Check out the Vacay Bingo leaderboard 🏆” · vacay-bingo-leaderboard.png
Card
Feed
Ranks
More

Ranks—trip registerTwo tokens move and nothing else does: the footnote credits the trip-wide First to BINGO, and the share copy/filename carry Vacay Bingo / vacay-bingo-*. Honors chips run on the trip's named vignettes rather than party themes, and the strip is short because Bodega's weekend is four Days (two share the Sunday)—the surface has to look right at 4 chips as well as at 10, and the ceremonial wrap-up still gets its daily honor. The 🏆 in the share text is functional, so it survives the camp reduction. Bodega demonstrates why the ⭐ clause names tutorial policy rather than pool identity: Friday deals from the easy pool but is tutorial: false and therefore remains eligible, while the tutorial wrap-up alone is excluded.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour
AllWith BINGOBlackout
Daily first to bingo
✨ D1Priya
🎊 D2Sam
🌙 D3—
›
1
Priya ⭐ First BINGO📷🎙
4 bingos
52 squares
2
Sam📷✍️
3 bingos
57 squares
3
Alex📷
3 bingos
44 squares
4
Jordan
2 bingos
40 squares
5
Nour🖼️
1 bingo
31 squares
Every Day Card counts here—except the wrap-up, which is pure ceremony. ⭐ marks the event-wide First to BINGO—tutorial Days excluded. Proof chips show every kind of proof a player has used. Tap a proof chip for the receipts in the Feed.
Share leaderboard
Shares as “Check out the Five Across leaderboard 🏆” · five-across-leaderboard.png
Card
Feed
Ranks
More

Ranks—general registerTwo tokens move and nothing else does: the footnote credits the event-wide First to BINGO, and the champion is titled 🏆 Champion with no qualifier when the podium lands (see fx-share-final-fa)—the general register's whole job is to drop the occasion noun without leaving a hole in the sentence. Honors chips carry the Day Themes' emoji exactly as GCB's do: every Day requires a registered Theme, and Five Across registers its own quiet trio (✨ 🎊 🌙, #617). Share copy and filename resolve to Five Across / five-across-* with the ✳️ mark on the card footer.

More / profile

🚢 Gay Cruise Bingo
GAY CRUISE BINGOBY FIVE ACROSS
🌊 Sea Day
💖 Neon Pink Playground
Play
Support
v2.0 · Trieste → Barcelona · Jul 15–24
Card
Feed
Ranks
More

⋯ More menuProfile relocates here from the top bar and the More tab wears your avatar (identity stays glanceable; the header keeps only brand + today's port/theme). Order: profile, theme (with a new “auto: match the day” default), text size (S/M/L—squares auto-fit, so Large never overflows), Play (schedule, suggest-a-square, tutorial replay, install), Support (bug report, 18+ advisory & acceptable use, blocked players), Admin (admins only, with pending-approvals badge), sign out last. Prompts and Admin leave the tab bar and mount here—bottom bar becomes Card · Feed · Ranks · More. This is the densest lexicon surface in the app: four rows carry Edition vocabulary (schedule title, schedule sub, walkthrough name, offline reason) and a fifth follows the dynamic 18+ flag. Three shipped details the drawing compresses: the install row's offline sub is the Chromium branch (iOS renders the Add-to-Home-Screen walkthrough line instead, and the row hides entirely once installed), the version footer runs first place → last place with no trailing mark, and Support ends with a Blocked players row (#689), the one place a Player undoes their own blocks, which the drawing leaves out.

🧳 Vacay Bingo
VACAY BINGOBY FIVE ACROSS
🐚 Bodega Bay
🐦 The Birds Have Entered the Chat
Play
Support
v2.0 · Bodega Bay → The drive home · Aug 7–9
Card
Feed
Ranks
More

More—trip registerRow by row against GCB: Trip schedule / Stops, parties, unlock times, Replay the welcome walkthrough (the Welcome Aboard proper noun is GCB-scoped), works offline wherever you land. The Support advisory reads Community guidelines because Bodega's pool holds no spicy Prompts—the label follows publicHostnames/{host}.adultContent, not the Edition, so a Vacay Event with a spicy pool would read “18+ advisory & acceptable use” here instead. No Admin row: this is a guest's view. Version footer swaps the route for the trip's (first → last place, so the wrap-up's "The drive home" is the terminus)—and carries no trailing mark, matching the shipped footer.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour
Play
Support
v2.0 · The Barn at Green Valley → The Barn at Green Valley · Aug 21–23
Card
Feed
Ranks
More

More—general register, admin entryThe platform's own vocabulary: Schedule / Places, events, unlock times, works offline in a packed venue—offline is a headline capability here, not a footnote, because a few hundred phones on one cell behind concrete and structural steel drop signal more reliably than a ship does. Community guidelines rather than an age gate, since this Event's pool is tame; the two axes are independent, so a Five Across Event with spicy Prompts would show “18+ advisory & acceptable use” in the same slot. Admin is shown here deliberately—the row is title + pending badge only, like GCB's. (§sec-fa-admin draws FA chrome for the console it opens as the platform-surface proposal #883 declined; what opens today, and going forward, is the Edition shell.) The Theme row shows today's Theme emoji exactly as the other Editions do: whenever a Day is live the sub reads its registered Theme, because every Day carries one—there is no themeless state for platform chrome to preserve.

Five Across · System surfaces—install, update, utility states

The surfaces that belong to the platform rather than to any one Event: the PWA install nudge, the app-update banner, and the utility states every Edition inherits unchanged. Install and update get three labelled variants each, because they are the two places the Edition lexicon is most visible in the smallest amount of copy—the offlineWhy clause and the toast lead-in emoji. Everything below them is drawn once, in Five Across chrome, with an annotation table naming what actually changes per brand; three near-identical renderings of a spinner would only make the doc longer, not truer. Frames are bottom crops of the same 393pt canvas as the full frames—a toast is a bottom-anchored component, so the crop shows exactly what it sits over.

Install nudge—three Editions, three offline promises

🚢 Gay Cruise Bingo
Muster-drill flirt
Sail-away cocktail
Matching Speedos
Lost the room key
Sunset selfie
Deck-chair territory war
Poppers spill
Complain about circuit music
Late-night pizza
Nap through the port talk
📲
Add me to your Home ScreenFull screen, works offline at sea.
Show me
Card
Feed
Ranks
More
gaycruisebingo.com

Install · Gay Cruise Bingo (iOS Safari, collapsed)The shipped InstallPrompt in its entry state. Safari never fires beforeinstallprompt, so there is no one-tap install to offer—the primary reads Show me and expands the Share walkthrough in place (next frame but one). Gating is unchanged and deliberate: the nudge waits for the Player's FIRST marked square (useHasMarkedSquare), never appears on load, never appears standalone, and the ✕ dismisses it forever—it can afford to be shy because More → Install the app keeps the affordance. Cruise register: works offline at sea.

🧳 Vacay Bingo
Find the best boat name in the harbor
Capture a colorful buoy or crab pot
Photograph the fog
Walk to a Bodega Head viewpoint
Find a seashell on the beach
Stage an original suspense-movie still
Take a windblown group selfie
Walk part of the Bodega Dunes
Spot a whale spout, or convincingly claim you did
Find the best bench on this coast and sit in it a while
📲
Add me to your Home ScreenFull screen, works offline wherever you land.
Install
Card
Feed
Ranks
More

Install · Vacay Bingo (Chromium, captured prompt)The other platform branch: Chromium fired beforeinstallprompt, the hook captured it, and the primary becomes a one-tap Install that replays the deferred event. Same toast, same gating, same ✕—only the button label and the platform path differ, which is why this is one component and not two. No browser chrome drawn: the Android address bar sits at the TOP of the viewport, outside this crop, and faking it here would be a wireframe lie. Trip register: works offline wherever you land. Decorative lead-ins are dropped on Vacay, but 📲 is functional, not camp—it survives on all three.

✳ Five Across
Someone cries during a toast
Rogue conga line
Cake-cutting photo scrum
Uncle finds the open bar
Playlist skips a track
Group photo takes four tries
Lost seating card
First dance false start
Someone asks for the wifi
Bouquet lands on a chair
📲
Add me to your Home ScreenFull screen, works offline in a packed venue.Tap Share , then “Add to Home Screen.”
Card
Feed
Ranks
More
fiveacross.app

Install · Five Across (iOS Safari, walkthrough expanded)The third component state: Show me has been tapped, the Share → Add to Home Screen steps have taken the button's place, and the toast has grown to three lines. The expansion is conditional on being ALONE in the stack (visibleCount === 1)—the slot offset is a fixed height, so a three-line toast under the urgent one would overlap. On the platform this line is not a footnote: a few hundred phones on one cell behind concrete and structural steel drop signal more reliably than a ship does, so offline is a headline capability and in a packed venue is the strongest of the three offline promises, not the weakest.

Update banner—three lead-ins, one mechanism

🚢 Gay Cruise Bingo
Muster-drill flirt
Sail-away cocktail
Matching Speedos
Lost the room key
Sunset selfie
Deck-chair territory war
Poppers spill
Complain about circuit music
Late-night pizza
Nap through the port talk
🚢
A fresh build just dockedYour marks are safe—reload takes two seconds
ReloadNot now
Card
Feed
Ranks
More

Update · Gay Cruise BingoUpdatePrompt (#178) unchanged: registerType: 'prompt' means the new service worker installs and WAITS instead of activating under the running page; needRefresh flips, this banner offers Reload (updateServiceWorker(true)) and Not now (session-only—the next cold launch updates anyway, and the 60s poll keeps a long-lived sea-day tab current). Held back while a claim sheet is open, so a proof capture in progress is never interrupted. Full camp: 🚢 lead-in, docked.

🧳 Vacay Bingo
Find the best boat name in the harbor
Capture a colorful buoy or crab pot
Photograph the fog
Walk to a Bodega Head viewpoint
Find a seashell on the beach
Stage an original suspense-movie still
Take a windblown group selfie
Walk part of the Bodega Dunes
Spot a whale spout, or convincingly claim you did
Find the best bench on this coast and sit in it a while
🧳
A fresh build just landedYour marks are safe—reload takes two seconds
ReloadNot now
Card
Feed
Ranks
More

Update · Vacay BingoThe same banner with the Edition's lead-in and verb: 🧳 and landed. Vacay drops decorative lead-ins as a rule, but a toast lead-in is the one place the rule holds an exception—the icon slot exists whether or not it carries camp, so the choice is which mark, not whether to have one. The second line stays byte-identical on all three Editions: it carries no occasion noun, so the lexicon sweep leaves it alone.

✳ Five Across
Someone cries during a toast
Rogue conga line
Cake-cutting photo scrum
Uncle finds the open bar
Playlist skips a track
Group photo takes four tries
Lost seating card
First dance false start
Someone asks for the wifi
Bouquet lands on a chair
⬆️
A new version is readyYour marks are safe—reload takes two seconds
ReloadNot now
Card
Feed
Ranks
More

Update · Five AcrossMinimal camp, and the restraint is the point: ⬆️ is functional rather than decorative, and A new version is ready says the thing instead of performing it. Note what did NOT get neutralised—Your marks are safe is warm, brief and competent, which is the platform voice; “general register” is not “no voice.” One invisible fourth state belongs to every Edition and has no banner at all: when the running build is below the remote /build-floor.json (#342) the client skips the offer entirely and activates + reloads as soon as a waiting worker exists.

Device recovery—the attended clear and its warned way forward

The ?device-cache-recovery=1 document (#1411, #1886; contract in specs/private-cache-isolation.md). It loads instead of the app graph, so it is the one platform surface with no Theme engine: it carries the fiveacross-slate tokens and the app’s --danger in its own stylesheet, dark only, identical on every Edition. A failed attempt must never be a dead end: it names the reason, offers a fresh-document retry and, behind a collapsed disclosure, a clearly warned clear that waives the Mark-preservation checks under explicit consent.

✳ Five Across

Finish device recovery

Private and admin views are held closed until this device’s old cache is cleared.

Before you clear

  1. Return to the app and sign in to every account used on this device.
  2. Reconnect, and verify that each account’s queued Marks reached the server.
  3. Stay online, and close the app in every other tab or window.

Clearing early can lose another account’s unsynced Marks.

Confirm to continue

Device recovery · Initial—nothing confirmedThe page’s one job reads as a procedure: three numbered steps the operator performs back in the app, then two confirmations as full-width checklist rows (the row is the hit target). The filled primary stays disabled until both are ticked; Return to the app is always live.

✳ Five Across

Finish device recovery

Private and admin views are held closed until this device’s old cache is cleared.

Before you clear

  1. Return to the app and sign in to every account used on this device.
  2. Reconnect, and verify that each account’s queued Marks reached the server.
  3. Stay online, and close the app in every other tab or window.

Clearing early can lose another account’s unsynced Marks.

Confirm to continue

Finishing recovery…

Device recovery · In progressFinishing recovery… in the role="status" slot with the app’s pulse dots. Every control is disabled but stays legible: disabled is a fill change, not a fade.

✳ Five Across

Finish device recovery

Private and admin views are held closed until this device’s old cache is cleared.

Before you clear

  1. Return to the app and sign in to every account used on this device.
  2. Reconnect, and verify that each account’s queued Marks reached the server.
  3. Stay online, and close the app in every other tab or window.

Clearing early can lose another account’s unsynced Marks.

Confirm to continue

Recovery keeps failing?

Continue without verification

If recovery keeps failing, you can clear this device’s old cache without checking that queued Marks reached the server. Any Mark not yet synced, for any account used on this device, will be permanently lost. Marks already on the server are kept. Boards need a connection to load again afterwards. Private and admin views open once clearing finishes.

Device recovery · Failed—the reason, then the way forwardA role="alert" callout names the failed stage (here: signed out). Clear recovered cache is hidden and Try again takes its place, reloading a fresh recovery document. The escape hatch is a collapsed <details>, so retrying stays the obvious path.

✳ Five Across

Finish device recovery

Private and admin views are held closed until this device’s old cache is cleared.

Before you clear

  1. Return to the app and sign in to every account used on this device.
  2. Reconnect, and verify that each account’s queued Marks reached the server.
  3. Stay online, and close the app in every other tab or window.

Clearing early can lose another account’s unsynced Marks.

Confirm to continue

Recovery keeps failing?

Continue without verification

If recovery keeps failing, you can clear this device’s old cache without checking that queued Marks reached the server. Any Mark not yet synced, for any account used on this device, will be permanently lost. Marks already on the server are kept. Boards need a connection to load again afterwards. Private and admin views open once clearing finishes.

Device recovery · Failed—escape hatch openExpanded: a dashed danger warning spells out the consequence before the button can be pressed, then two danger-register acknowledgements and the filled destructive Clear cache without verification (disabled until both are ticked). It clears without the sign-in, online, server-proof and drain prerequisites.

✳ Five Across

Finish device recovery

Private and admin views are held closed until this device’s old cache is cleared.

Before you clear

  1. Return to the app and sign in to every account used on this device.
  2. Reconnect, and verify that each account’s queued Marks reached the server.
  3. Stay online, and close the app in every other tab or window.

Clearing early can lose another account’s unsynced Marks.

Confirm to continue

Still waiting for cache clearing. Keep this recovery document open; returning or retrying stays unavailable until clearing settles. If it never settles, close the browser rather than reopening the app while this clear is running.

Device recovery · Clearing still pendingA clear that outlives its bound reports waiting in an accent-toned status (a wait, not an error) and keeps every control disabled until the SDK actually settles; a late success still refuses completion.

✳ Five Across

Finish device recovery

Private and admin views are held closed until this device’s old cache is cleared.

Before you clear

  1. Return to the app and sign in to every account used on this device.
  2. Reconnect, and verify that each account’s queued Marks reached the server.
  3. Stay online, and close the app in every other tab or window.

Clearing early can lose another account’s unsynced Marks.

Confirm to continue

Recovery keeps failing?

Continue without verification

If recovery keeps failing, you can clear this device’s old cache without checking that queued Marks reached the server. Any Mark not yet synced, for any account used on this device, will be permanently lost. Marks already on the server are kept. Boards need a connection to load again afterwards. Private and admin views open once clearing finishes.

Device recovery · Escape hatch failedThe status and alert nodes move under the button that was pressed and the hatch is held open. The hatch controls stay disabled (a further attempt reloads the document); Try again and Return to the app re-enable.

The flagship Edition, in cruise register at full camp: Days are Ports, the crowd is the boat, and the party wardrobe—15 real Themes from src/theme/themes.css—is the identity. Each frame shows that Day as it looks on its own morning; the header carries today's port and theme on two lines while the board retints to the viewed Day. Days 1 and 10 are the curated tutorial cards; Days 2–9 deal from the shared main pool. Share mark 🚢, file slug gay-cruise-bingo-*, domain gaycruisebingo.com. Frames are generated—each carries the Gay Cruise Bingo chip and the anchor #fx-day-1-gcb … #fx-day-10-gcb.

Vacay Bingo · Weekend in Bodega Bay—the trip Edition

Same Five Across system, new emotional layer. Trip register at moderate camp: Days are Stops, the crowd is the group, offline holds up wherever you land. One-identity rule—every frame shows VACAY BINGO over the small-caps BY FIVE ACROSS endorsement, never two competing brands, regardless of which hostname the player entered through. Vacay owns colors, imagery, prompt language and recap treatment; the grid, marking, tally and navigation are untouched platform mechanics. Bodega is deliberately non-tropical—fog silver, sea-glass green, Pacific blue, weathered red, postcard cream: a Sonoma Coast weekend preserved in a scrapbook. Share mark 🧳, file slug vacay-bingo-*, domain vacaybingo.com. Voice: the spontaneous friend who suggests the detour. The sign-in gate for this trip is fx-join-vacay, drawn beside its two siblings in §3.

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
🐚 Bodega Bay
🐦 The Birds Have Entered the Chat
Fri 🐚
🔒 Sat 🦪
🔒 Sun 🌅
🔒 Sun 👋
Day 1 · The Birds Have Entered the Chat
Coastal suspense with the volume just slightly too high. Eggshell, ink black, sea green, and one restrained streak of warning red.
Tonight: 🍷 Arrival pours · 🌊 First look at the water
Take a windblown group selfie
Photograph the fog rolling in, or refusing to leave6
Find the best boat name in the harbor
Spot bird-themed art, a sign, or a souvenir
Get a group photo where nobody is ready8
Capture a colorful buoy or crab pot
Get a bird into the background of a photo
Make a toast about friendship
Post a candid that makes the group laugh
Suggest something for the group to do tomorrow
Find the house's weirdest decorative object
Photograph someone in full coastal-main-character mode11
FREEThe flock has landed
Photograph something the exact color of the sea today
Take a picture of a fire
Take a photo of somebody arriving at the house
Catch the moment someone says "I could live here"
Find a hand-painted sign3
Get everyone in one frame using a timer
Spot a gull, pelican, or heron doing something undignified
Photograph someone's hair losing a fight with the wind
Find something in the house older than everyone here
Capture a sunset, or the sky pretending it's going to be one
Photograph the group's shoes in a pile by the door5
Photograph the drink of the day
Card
Feed
Ranks
More

Day 1—🐦 The Birds Have Entered the ChatFri Aug 7 · Bodega Bay · curated easy pool · a competitive easy card, drawn with real seeded prompt text and the seeded free space ("The flock has landed"). Bodega's Friday is pool: 'embark' with tutorial: false—so no Warm-up tag, no "How this works" banner, no warm-up note: that chrome is raised by the tutorial flag, and this Edition's Friday doesn't raise it. Friday also carries the unlockAt: 0 open sentinel (live from event open) with a pre-stamped snapshot. Sea-glass green against weathered red. The strip carries all four chips—Four Days for a three-day trip—each with the Day's one vignette placeEmoji instead of a flag, because a trip Day is a Stop, not a port of call.

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
🦪 Bodega Bay
🌊 Bodega Bay Side Quests
Sat 8 · 🌊 Bodega Bay Side Quests 12 easy · 12 exploratoryFree: Main character on the coast
Sample squares: Walk to a Bodega Head viewpoint · Find the best boat name in the harbor · Stage an original suspense-movie still · Spot a whale spout, or convincingly claim you did · Find a seashell on the beach · Take a windblown group selfie.
Got a moment worth sharing?
🙋 Put it on tomorrow's card
Card
Feed
Ranks
More

Day 2—🌊 Saturday, Bodega Bay Side Quests + co-creationSat Aug 8 · Bodega Bay · main trip pool · the canonical card surface for this Edition. Pacific blue and sea-glass with a buoy-orange accent; grid, marking, tally and navigation are untouched Five Across mechanics (board drawn abstractly here—the real card uses the standard prompt-text cells). The 50/50 easy/exploratory mix reads in the day chip. The dashed "Put it on tomorrow's card" invitation sits under the grid on Friday and Saturday—shipped as TomorrowsCardInvite (#559), rendered only while a targetable future main Day exists (hidden after Sunday's 06:00 cutoff—the wrap-up card never takes suggestions, its pool is closing). Submissions go to the organizer's overnight approval queue: Friday's target is Saturday's main-card snapshot, and Saturday's is Sunday morning's; each target receives its own 2–4 approved ideas.

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
👋 The drive home
🌫️ Fog, Froth & Farewells
✓ Fri 🐚
✓ Sat 🦪
✓ Sun 🌅
Sun 👋
Day 4 · Fog, Froth & FarewellsGoodbye
×2
The last slow morning. Fog silver, chowder cream, coffee brown, and dusk coral through the window.
Tonight: 📸 The photo dump · 📅 Next one
Pick the spot for the last coffee/breakfast moment7
Photograph the fog one last time—it'll be there
Group photo where everyone is genuinely ready to go
Share your favorite photo of the weekend
Share your favorite quote of the weekend
Suggest a location for the next girls' weekend
Photograph the view one last time4
Photograph the last of the snacks
Photograph the house before anyone tidies it
Take one last photo in the hot tub
Photograph the most chipper person this morning
Find something someone almost left behind2
FREEWe did it for the story
Photograph the very last bird
Take a photo of somebody still sleeping
Take the last group photo9
Find something you'd swear wasn't there on Friday
Give this trip a #hashtag
Photograph someone doing the final sweep
Photograph the friend who brought the most stuff
Photograph the road out
Photograph a car, packed and ready to go6
Take a picture of your soundtrack home
Name the weekend's MVP moment
Photograph the last shoes by the door
This card's 11:00 a.m. unlock IS the standings freeze (check-out)—standings froze at unlock; this card is pure ceremony. 2 of 3 reshuffles left, available only before you've marked a square.
Card
Feed
Ranks
More

Day 4—👋 The wrap-up (closing Day)Sun Aug 9 · The drive home · curated closing pool, drawn with real seeded prompt text · Four Days for a three-day trip: Sunday morning's MAIN card (Day 3, 🌅, 06:00, "One last coastal morning") plays competitively until the 11:00 a.m. check-out, which the Event carries as a configured standingsFreezeAt—and this wrap-up Day states scoring: 'ceremonial' and unlocks at that same instant, so it is pure ceremony exactly like GCB's Day 10 (tutorial: true additionally raises the Goodbye tag and keeps a ceremonial bingo out of the Event-wide First to BINGO). Both halves are stated data, not inferred from the closing pool. The chip wears 👋—the operator-set legacy portEmoji wins the coercion the chip reads; the Theme table keeps 🌫️. The light postcard-cream Theme proves the token contract handles a light mode with the same marked-cell gradient; the reshuffle chip reads a bare ×2—the occasion qualifier is dropped on every Edition (signed off), so no "trip reshuffles" appears.

🧳 Vacay Bingo
VACAY BINGO
BY FIVE ACROSS
👋 The drive home
🏆 Final standings
Most-loved photo of the trip
❤ 9
Priya · "Stage an original suspense-movie still" · Frozen at trip end
Podium
1
Maya 🏆 Trip champion
5 bingos
52 squares
2
Priya ⭐ First to BINGO
4 bingos
55 squares
3
Jess
4 bingos
48 squares
Daily honors
🐚 D1Jess
🦪 D2Maya
🌅 D3Priya
👋 D4Maya
Standings froze at the 11:00 a.m. check-out—the wrap-up card is pure ceremony, exactly like GCB's Day 10. We did it for the story.
Card
Feed
Ranks
More

Finale—scrapbook, not scoreboardThe trip's closing surface, in trip register: 🏆 Trip champion and the ⭐ trip-wide First to BINGO. Most-Loved Photo leads (frozen at the standings freeze; ties share the honor; if no photo earned a heart, this block becomes plain photo highlights), then the podium and Daily Honors. Hearts never touch bingo scoring. Sharing this podium produces a vacay-bingo-*.png footed Vacay Bingo 🧳. If the finale is descoped for launch (PRD descope ladder), this frame ships with the Most-Loved block degraded to plain Photo highlights.

The parent platform, shown on the kind of Event that has no theme wardrobe and wants none (whether a Day may go without a Theme was a contract question; #885 decided no—DayDef.theme stays required, and an occasion-neutral Event picks from the Edition's registered Themes instead): Meridian's autumn offsite, two Days at Cedar Hall. General register at minimal camp: Days are Places, the crowd is everyone, the champion is just 🏆 Champion. The wordmark is set type—.fa-title is the same weight-300/800 split as the Editions with the glow removed; the restraint is the differentiation. An Event can't be Theme-less—DayDef.theme is required, and the fallback chain ends at the Edition default, ✨ Marquee—so the shipped render dresses these Days in the registered Five Across Themes: ✨ Marquee for the kickoff, 🌙 Afterglow for the wind-down. The frames below are drawn instead in fiveacross-slate, this document's PROPOSED alternative platform palette (no shipped equivalent in themes.css): near-black slate with one signal-cobalt hue, gradiented tonally so a marked cell reads as one decisive color rather than a party. Offline is a headline capability here, not a footnote: a few hundred phones on one cell behind concrete and structural steel drop signal harder than a ship does. Share mark ✳️, file slug five-across-*, domain fiveacross.app. Voice: the charismatic host—Bring everyone into the game.

✳ Five Across
FIVE ACROSS
🎤 Cedar Hall
✨ Marquee
Thu ✨
🔒 Fri 🌙
Day 1 · MarqueeWarm-up
Cedar Hall
Lights up, doors open. Bulb-gold warmth and ticket red on deep black—big-night energy for any occasion.
Tonight: 🍽️ Long-table dinner · 🎲 Trivia in the lounge
Name tag spelled wrong
Coffee gone before 1014
Icebreaker nobody wanted
Slide with forty bullets
Mic feedback squeal
"Can everyone hear me?"9
Whiteboard runs out of room
Someone joins from the hallway
Adapter hunt begins
Agenda runs twenty long
T-shirt sizing crisis
"Let's take this offline"12
FREEYou found the room
Room too cold to think
Snack table ambush
A question that is a comment
Laptop battery panic
Two people say it at once5
Sticky notes everywhere
Parking-lot idea returns
First inside joke
Meet someone from another team7
Lunch-line photo
Group photo, everyone blinks
Badge left in the room
Card
Feed
Ranks
More

Day 1—KickoffThu Oct 8 · Cedar Hall · curated opening pool · drawn in fiveacross-slate (PROPOSED—no shipped equivalent in themes.css; the shipped render wears ✨ Marquee, the Edition default the fallback chain ends at). Read the header: the place sits exactly where GCB shows its port and Vacay its stop, and the theme line carries the registered Theme—a neutral Event still supplies a placeEmoji or its chips inherit the Theme's emoji, so a Day chip is always weekday + one emoji ("Thu ✨"), Days not Ports. Prompt text stays observational and non-explicit—the Event is configured un-gated (adultContent: false on its hostname record); with no spicy Prompts the monotone derivation never raises it: no 18+ attestation on join, no 🔞 toggle on submit. Other emoji in chrome are functional only (✓, 🔒).

✳ Five Across
FIVE ACROSS
🌳 Riverside Park
🌙 Afterglow
✓ Thu ✨
Fri 🌙
Day 2 · AfterglowGoodbye
×3
The slow, happy wind-down. Dusk violet, ember orange, and one warm last light.
Tonight: 🏆 Paper-plate awards · 🚌 The ride home
Sunscreen passed around
Team name nobody agreed to
Rules invented mid-game8
Tug-of-war rematch demanded
Someone's shoes give up
Cooler runs out of ice
Frisbee in the tree3
A ringer from another team
Photo where everyone blinked
Blister diplomacy
Trophy is a paper plate
Speech nobody prepared6
FREEYou made it outside
Grass stain of honor
A bee interrupts play
Bracket drawn on a napkin
Playlist finally agreed10
Sunset over the field
Leftover swag redistributed
Numbers exchanged for real
Someone sleeps on the bus
"Let's do this quarterly"4
Slow clap starts early
Final scoreboard photo
Last one out turns the lights off
This card's unlock IS the standings freeze—standings froze at unlock; everything marked here is ceremony. 3 of 3 reshuffles left, available only before you've marked a square.
Card
Feed
Ranks
More

Day 2—Field Day (closing Day)Fri Oct 9 · Riverside Park · curated closing pool · a second Place under the same Event, same platform palette (shipped render: 🌙 Afterglow). This Day states scoring: 'ceremonial', so standingsFreezeAtFor resolves the Event's freeze to its unlockAt—the freeze IS this card's unlock and everything marked on it is ceremony, the GCB Day-10 shape on a two-Day Event. The closing pool is not what decides that. Pool identity, tutorial framing and Scoring Policy are three independent facts (ADR 0011): an explicit scoring wins, a configured standingsFreezeAt outranks the schedule derivation entirely, and the old closing-pool rule survives only as the read-time fallback for legacy Days that state no policy. A closing Day declaring itself competitive would play for the standings and freeze nothing. tutorial: true raises the "Goodbye" tag and keeps this ceremonial wrap-up's bingo out of the Event-wide First to BINGO. The reshuffle chip reads a bare ×3 and the note says "3 of 3 reshuffles left"—no occasion qualifier on any Edition. Everything below the header is the chrome the Editions inherit unchanged: same grid, same tally badges, same tab set. What the platform does not do is add camp on top.

Five Across · Admin console—the declined platform-surface proposal

Declined (#883, signed off): this section drew a console that would wear Five Across on gaycruisebingo.com, vacaybingo.com and fiveacross.app alike—an organizer-surface reading of the fiveacross PRD's one-identity rule. The ruling went the other way: the console stays inside the Edition-branded shell, per-Edition copy and all, which is what carries that same one-identity rule on the operator side too. The frames below are kept as the record of what was proposed, not a description of what ships or will ship. Drawn once, in the proposed fiveacross-slate theme: slate ground, one signal-cobalt hue, no glow on the wordmark—the restraint is the differentiation. Labels and subtitles are the shipped strings from src/components/admin/* (captions name the few places a frame compresses a long sub); the sample Event is the real July 2026 sailing, which is the point—Gay Cruise Bingo data inside Five Across chrome is what the declined direction would have looked like. Four doors are drawn; Prompt pool and Players follow the same detail pattern (list + curated add form, banned roster) and are not redrawn. Below the frames, five compact strips isolate the only places the selected Event would have changed what the organizer sees.

✳ Five Across
Admin
Done
✳ Five Across
Atlantis Med—Trieste to Barcelona · July 2026gaycruisebingo.com · cruise register
Switch ▾
Done (sticky, always visible), backdrop tap, or swipe down—dismiss from anywhere. No more scrolling to find Close.
▦Card
◉Feed
♛Ranks
More

Admin hub—one screen, six doors, one platform (declined)Platform-surface framing decided against in #883—the shipped hub keeps its Edition chrome. Row order and subtitles below are still AdminHub.tsx verbatim (Players before Messages); what this frame changed—and what the ruling rejected—is the chrome: slate + cobalt, no theme glow, one surface for an organizer who runs a cruise and a wedding. Also declined: the Event-context bar above the doors—the FA mark, the Event you are administering, its Edition tag and a Switch affordance. Single-Event admin has no such state today (#545 multi-Event), and the ruling gives it no reason to grow one; it was drawn only because every strip below turns on the answer to "which Event is selected?". Routes unchanged either way: /more/admin/<section>.

✳ Five Across
Admin
Review queue
Done
Reports (2)
Proof on "Poppers spill"4 reports · auto-hidden · @jj's photo
Clear reportsHideBan author🗑
"Meet your Grindr wallpaper IRL"4 reports · prompt · hidden
RestoreClear reports🗑
Approvals (3)
"Fall asleep in full harness"@marco · 2h
☑ 🔞 SpicyApprove✕
"Miss the ship in Valletta"@dan_atl · 5h
☐ 🔞 SpicyApprove✕
Pending claims (2) admin-confirmed mode only
Theo · "Dance-floor k-hole"Day 3 · 40m ago
ConfirmReject
One inbox, oldest first, every triage action in thumb reach. Empty state follows the Event's register: "All clear. Go enjoy the boat."
▦Card
◉Feed
♛Ranks
More

Review queue—the merged inbox, plus the 18+ flip confirmReports, pending approvals and pending claims (admin-confirmed mode only) stay ONE triage surface; the hub badge is this queue's total. Report rows carry the shipped verb set—Clear reports lifts the auto-hide, Restore/Hide toggles the status hard-hide, Ban author, 🗑 Delete—and the 🔞 Spicy tag on an approval row is an editable pre-approve checkbox, not a static label, so an admin can correct a submitter's tagging before it becomes authoritative. The flip is never silent (shipped AdultContentConfirm, #610): an approve, bulk approve or admin-add that would derive adultContent: true is confirmed first, in these words (the occasion noun Title-cases per Edition—Cruise / Trip / Event), because the posture is monotone—once on, on for the Event's life. The 🔞 tag stays visible on every Edition (it is an admin category behind auth, not a player-facing age claim). Empty state is one of three strings, chosen by the Event's Edition, not by the console.

✳ Five Across
Admin
Game settings
Done
Easy mix
Claims & proof
Appearance
▦Card
◉Feed
♛Ranks
More

Game settings—every dial in one place, plus the audience switchEasy mix keeps the slider that replaced the 0/25/50 step buttons: full 0–100% with detents, a bubble carrying the square math, commit on release. Claim mode, photo proof source, EXIF strip and AI screen are the shipped rows in the shipped order (the AI-screen sub is compressed here to its first sentence). Adults only lives inside Claims & proof, not a separate block: settings.forceAdult is the escape hatch for mature content the 🔞 tag does not catch, and its sub is posture-aware—on an Event already 18+ from its pool (this one) it reads the shipped "removes the reason, not the posture" line; the derived state itself stays server-derived from active spicy Prompts in dealable pools, fail-closed when unknown. Auto-hide is a −/+ stepper (#222), not a dropdown, and Default theme is a chip list scoped to the Edition's themes (#555)—Five Across chrome, Edition-scoped options.

✳ Five Across
Admin
Schedule
Done
Wed 15 · Trieste tutorial🛳️ Welcome Aboard⛵ Sail-Away Party · 🎉 Welcome Party
Thu 16 · Split 2 parties🌍 Uniforms w/o Borders ✓🪖 Dog Tag T-Dance · ✈️ Duty Free
Fri 17 · Sea Day 2 parties💖 Neon Pink Playground ✓💖 Seriously Pink T-Dance · 🌈 Neon Playground
Sat 18 · Valletta 2 parties💦 Sporty Splash ▾Snapshot predates the easy-mix deployRe-snapshot💦 Splash T-Dance · 🏋️ Get Sporty
Sun 19 · Palermo🌌 Under the Stars ▾🎭 AirOtic · 🌌 Under the Stars
Mon 20 · Naples🏛️ Glamiators ▾🎤 Solea Pfeiffer · 🏛️ Glamiators
Every Day keeps the same row shape—info growing, theme dropdown trailing, never shifting; the Tonight line is an inline field inside every row—ScheduleRow always renders it and merely disables it once that Day has unlocked, so the first three sit dimmed and read-only while Valletta, Palermo and Naples stay editable. A day that needs a rare admin fallback grows a repair line inside its own row: the anomaly in plain words plus the quiet fix. One pending state is drawn on Valletta before its next unlock.
▦Card
◉Feed
♛Ranks
More

Schedule—repair line inside the day that needs itThe shipped editor (theme dropdown, inline Tonight field, both locked once unlocked) under platform chrome. The first three Days are past and their selects are disabled; Valletta is the hub's next unlock, so it and the later Days stay editable. A day needing a rare fallback grows a second line in its own row: the anomaly stated plainly, the quiet button at the line's end. Repair-line controls are deliberately understated—compact, sentence case, hairline border, no glow—and the result ("Unlocked.", "Denied—cards already dealt.") sits beside the button as plain text, not a pill; the button retires only on success. One Edition-scoped thing lives on this screen: the theme dropdown offers only that Edition's themes (#555). There is no section header—lexicon.placePlural (Ports / Stops / Places) exists but nothing consumes it yet. Everything else—unlock times, snapshot mechanics, the Tonight grammar, the repair grammar—is platform.

✳ Five Across
Admin
Messages
Done
New message
Final stretch 🏁
Last days at sea, and every card you've unlocked is still in play. Once a thing has happened, it's happened — if it's on three of your cards, that's three squares. Scroll back through your days, light up everything you've earned, and stack those bingos before we dock in Barcelona. 🚢
Post to everyone
Sent
Final stretch 🏁Day 8 · Nathan · UID admin-uid · 📌 pinned
EditUnpinDelete
Welcome aboard 🛳️Day 1 · Nathan · UID admin-uid · edited
EditPinDelete
One list, newest first. A pinned Notice sits at the top of every Player's Feed and shows once as a Card-tab banner; unpinning demotes it to a normal Feed entry in place. Deleting removes it everywhere. Reusable—any update, any day.
▦Card
◉Feed
♛Ranks
More

Messages—compose once, reach everyoneTitle + body, a pin toggle, one Post button; sent history with quiet Edit / Unpin (or Pin, on unpinned rows) / Delete controls—tapping Edit swaps the row for the #455 inline copy editor, and a corrected Notice carries an "edited" provenance marker in its attribution line. No player picker, no threading, no read receipts—a broadcast Notice, not a chat. Placeholders are the shipped ones ("Title", "What does everyone need to know?"). The composer is platform furniture and does not change per Edition; the writing does, which is the one comparison below where the difference is entirely voice. The player-facing result of this screen is drawn under Gay Cruise Bingo as the pinned Notice in the Feed.

Where the selected Event would have changed the console (declined)

Also declined, with the rest of this section (#883): five compact strips, not five more full screens—because the honest answer would have been that almost nothing changed. The chrome, the doors, the controls, the mechanics and the platform furniture would have been identical on every Edition; what the Event would have supplied is its identity line, its place noun, its theme list, its audience posture, its register and its share mark. Each strip below draws only the differing slice, one column per identity, in that Edition's real tokens — part of the declined proposal's record, not a description of what ships.

✳ Five Across
🚢 Gay Cruise Bingo
Atlantis Med—Trieste to Barcelona · July 2026gaycruisebingo.com · Cruise register
gcb
🧳 Vacay Bingo
Bodega Bay · Aug 7–9bodega-bay.fiveacross.app · Trip register
vacay
✳ Five Across
Kim & Jo's Wedding · Aug 21–23kim-and-jo.fiveacross.app · General register
fiveacross

Admin home—three Events, one console (declined)Every column drawn here is the same slate chrome, the same six doors, the same badge grammar—the shipped console instead runs three separate Edition-branded chromes (#883). Two things would have varied: the Event-context line (name, window, hostname, Edition tag) and the queue's empty state, which is a whole-string override rather than a token swap because "Go enjoy the {crowd}" does not survive interpolation. The Schedule subtitle is deliberately Edition-invariant—${days.length} days; lexicon.placePlural (Ports / Stops / Places) exists in the lexicon but nothing consumes it yet. The 18+ pill reads the derived publicHostnames/{host}.adultContent—it tracks the Event's Prompts, not its Edition, which is why the cruise is on and the wedding is off.

✳ Five Across
🚢 Gay Cruise Bingo
Claims & proof
Appearance
🧳 Vacay Bingo
Claims & proof
Appearance
✳ Five Across
Claims & proof
Appearance

Event settings—the audience block and the theme listEasy mix, claim mode, photo source, EXIF, AI screen and auto-hide are byte-identical on all three and are not redrawn. Two rows earn a column each. Adults only: one shipped row inside Claims & proof (settings.forceAdult), whose sub is posture-aware—the posture itself is derived per Event, not per Edition, so a cruise with a tame pool would read the plain "Turn on for mature content…" sub, and a wedding with one active spicy Prompt would read the "removes the reason, not the posture" one; once on, the posture is monotone. Default theme: options come from themesForEdition, so the wardrobe is the Edition's—fifteen for Gay Cruise Bingo, three Sonoma Coast themes for Vacay, three for Five Across with ✨ Marquee the Edition default (#617). The restrained fiveacross-slate these frames wear stays this doc's PROPOSED addition to that wardrobe—no shipped equivalent.

✳ Five Across
🚢 Gay Cruise Bingo
10 days
Wed 15 · Trieste tutorial🛳️ Welcome Aboard
Thu 16 · Split🌍 Uniforms w/o Borders ▾
Fri 17 · Sea Day💖 Neon Pink Playground ▾
Tonight: 🪖 Dog Tag T-Dance · ✈️ Duty Free
🧳 Vacay Bingo
4 days
Fri 7 · Bodega Bay🐦 The Birds Have Entered the Chat
Sat 8 · Bodega Bay🌊 Bodega Bay Side Quests ▾
Sun 9 · Bodega Bay🌫️ Fog, Froth & Farewells ▾
Sun 9 · The drive home tutorial🌫️ Fog, Froth & Farewells ▾
Tonight: 🦀 Harbor dinner · 🌅 Sunset
✳ Five Across
3 days
Fri 21 · Rehearsal✨ Marquee ▾
Sat 22 · The wedding🎊 Confetti Hour ▾
Sun 23 · Send-off brunch🌙 Afterglow ▾
Tonight: 🥂 Run-through · 💍 Wedding · 🥞 Send-off brunch

Schedule and theme editing—same row shape, different nounsOne uniform row: label, optional pill, theme dropdown trailing, repair line only when a day needs one. The head here is just the Day count—SchedulePanel ships no place-noun header (lexicon.placePlural is unconsumed); the day label takes whatever the Event calls that day (a port, a stay, a moment in a wedding weekend). The dropdown is the sharpest divergence: Gay Cruise Bingo's fifteen-theme wardrobe is its identity, Vacay ships three Sonoma Coast themes, Five Across ships its own three (#617, ✨ Marquee the default)——and the Five Across column draws the shipped model: three registered Themes in the dropdown, because DayDef.theme is required and SchedulePanel enumerates only registered ids. Whether a general Event should be able to want no Theme at all was a real question; #885 settled it against—DayDef.theme stays required, so these rows depict the only shape a Schedule row takes, on every Edition. Themes stay Edition-scoped data (themesForEdition); the console never imposes one.

✳ Five Across
🚢 Gay Cruise Bingo
New message
Final stretch 🏁
Last days at sea, and every card you've unlocked is still in play. Scroll back through your days, light up everything you've earned, and stack those bingos before we dock in Barcelona. 🚢
Full camp · decorative lead-ins allowed
🧳 Vacay Bingo
New message
Last morning
Fog until ten, then coffee at the harbour. Every card you've unlocked is still live—scroll back, mark what you actually did, and take the long way home. 🧳
Moderate camp · one mark, no lead-in
✳ Five Across
New message
Wedding cards are live
Day 2 unlocked at nine. Packed room, no bars? Your card keeps working offline—marks sync when you reconnect. Everything you unlocked earlier still counts.
Minimal camp · functional emoji only

Message composition—identical composer, three registersThe only strip where nothing in the interface differs at all: same two fields, same placeholders ("Title", "What does everyone need to know?"), same pin toggle, same Post button, same broadcast semantics. What differs is the emoji budget and the voice, and it is worth drawing because it is the difference an organizer will actually feel. Gay Cruise Bingo spends decorative emoji freely; Vacay keeps the functional set plus its 🧳 and drops the lead-ins; Five Across writes in sentence case with functional emoji only, and treats offline as a headline capability rather than a footnote—a packed venue drops signal more reliably than a ship does.

✳ Five Across
🚢 Gay Cruise Bingo
Atlantis Med—Trieste to Barcelona · Day 1 · Trieste
BINGO!
Theo
Befriend a bartender
Spot matching Speedos
Stateroom mirror selfie
Hear the ship's horn
Locate the late-night pizza
FREEYou made it aboard
Find your muster station
Balcony or porthole photo
Wave goodbye to land
Find the theater
Bingo #1 · 9 squares · ⛵ Sail-Away Party night
Gay Cruise Bingo 🚢

gay-cruise-bingo-bingo.png
"I got BINGO on the high seas 🚢"

🧳 Vacay Bingo
Bodega Bay · Day 2 · Bodega Bay
BINGO!
Maya
Find the best boat name in the harbor
Take a picture of a wildflower
Take a windblown group selfie
Capture a colorful buoy or crab pot
FREEMain character on the coast
Stage an original suspense-movie still
Photograph the fog
Walk to a Bodega Head viewpoint
Find a seashell on the beach
Bingo #1 · 8 squares · 🦀 Harbor dinner night
Vacay Bingo 🧳

vacay-bingo-bingo.png
"I got BINGO on this trip 🧳"

✳ Five Across
Kim & Jo's Wedding · Day 2 · The Barn at Green Valley
BINGO!
Priya
Someone cries during a toast
Dad finds the good whisky
Unrehearsed speech
Shoes come off
FREEEveryone in one photo
Wrong table place card
Cousin runs the playlist
First dance rehearsal
Last one on the floor
Bingo #1 · 8 squares · 💍 Wedding night
Five Across ✳️

five-across-bingo.png
"I got BINGO. ✳️"

Share-asset previews—the console's proof that the mark follows the EventSame 600×750 canvas, same on-device html-to-image render, same composition (the word, the name, the line); drawn here at 86% of the doc's half-scale artboard so three fit the strip. Three things are Edition-resolved and all three are visible: the theme tokens the card renders in, the footer mark (🚢 / 🧳 / ✳️ from lexicon.shareMark) and the download slug (lexicon.fileSlug). The context line is per-Event, not per-Edition—${event.name} · Day N · ${place}, which is why the cruise card reads "Atlantis Med—Trieste to Barcelona" rather than an app name; the stat line's trailing segment is · ${tonight[0]} night. The celebration text beneath each is a whole-string override, not a token swap—"I got BINGO on the high {occasion}" is exactly the sentence that breaks under interpolation. The unfurl-mismatch bug this strip once documented is resolved: all three share surfaces pass shareOrigin()—the entry-point origin—since #607, so a Bodega guest's link lands (and unfurls) on the surface they shared from. The residual is the baked og:* block, which stays the default Edition's on a hostname-resolved multi-Event bundle served DIRECTLY by Hosting; the #1118 edge HTML rewrite emits it per hostname once the Worker fronts the host. (The PWA manifest left the same residual in #546, which moved it to the edge Worker.)

Not drawn, because nothing would have changed even under the declined proposal: the review queue's triage rows and actions, easy mix, claim mode, photo source, EXIF, AI image screen, auto-hide, the unlock/re-snapshot repair grammar, the prompt-pool editor, the banned roster, the Messages pin/unpin/delete semantics, and the sticky Done contract. That list was the section's best argument for one console, one product—and it still lost: #883 keeps the console Edition-branded.

Utility states & the per-brand annotation table

These are platform mechanics: the same component, the same states, the same copy on every Edition apart from the deltas in the table below. They are rendered once, in the proposed fiveacross-slate theme, because drawing them three times would produce three identical frames in three palettes—the annotation table is the honest form of that comparison.

✳ Five Across
Someone cries during a toast
Rogue conga line
Cake-cutting photo scrum
Uncle finds the open bar
Playlist skips a track
Group photo takes four tries
Lost seating card
First dance false start
Someone asks for the wifi
Bouquet lands on a chair
⬆️
A new version is readyYour marks are safe—reload takes two seconds
ReloadNot now
📲
Add me to your Home ScreenFull screen, works offline in a packed venue.
Show me
Card
Feed
Ranks
More

Toast stack arbitration—the rare both-at-once caseEach toast decides for itself whether it WANTS to show; useToastSlot decides who gets a slot. Ordering rule: urgent (update) outranks invitational (install); newest registration wins within a priority; MAX_VISIBLE_TOASTS = 2, and a third comer simply waits its turn rather than pushing the board off screen. Both reserve bottom clearance through the existing install-prompt-visible / update-prompt-visible body classes, so the tab bar and the board never jump when one appears. Brand-invariant mechanics—only the two strings inside change.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour

Checking your pass…

Auth-resolution state (LoadingState)The one state a Player sees before anything else: role="status", aria-live="polite", a label and three dots. The label is the whole per-Edition delta—Checking your cruise pass… / trip pass… / your pass…—which is why it is an override and not a token: “Checking your event pass…” is the template smell the lexicon explicitly rejects. Rendered with the platform wordmark: no glow, .12em tracking, set type rather than party type.

✳ Five Across
FIVE ACROSS

Something went wrong on this device. Your marks are safe—they live on the server, not in this tab.

Reset & reload

Packed room, no bars? Your card keeps working offline—marks sync when you reconnect.

Crash panel (ErrorBoundary) — and its DealError siblingThe app's only error boundary, and deliberately the most brand-exposed surface in the app: it touches NOTHING from the running app's state, so it renders the Edition wordmark, one reassurance, one recovery action, and (#881) the Edition's crashFallbackNote—the total-failure fallback, falling back to the routine offlineNote for an Edition with no printed-card tradition of its own. Two per-brand strings, both overrides: the wordmark (GAY CRUISE BINGO / VACAY BINGO / FIVE ACROSS—per-Edition via editionBrand(); #602, shipped) and the crash-fallback line. The DealError panel (“we couldn't deal your card” + Retry, reserved for a genuine first-timer with nothing cached) shares the wordmark override but carries NO offline footnote at all (#881, Codex round 4): no card was dealt yet on that screen, so a promise about a card working offline has nothing to refer to.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour
Showing your saved card—reconnecting to sync the latest.
Retry
Day 2 · Confetti Hour
💍 The Barn at Green Valley
Someone cries during a toast
Rogue conga line
Cake-cutting photo scrum
Uncle finds the open bar
Playlist skips a track
Group photo takes four tries
Lost seating card
First dance false start
Someone asks for the wifi
Bouquet lands on a chair
Toast runs long
Sparkler exit rehearsal
FREE
Nobody knows the caterer
Dog in a bow tie
Ring bearer bolts
Speech references a group chat
Photographer climbs a chair
Someone changes shoes
Table finds the dessert early
Grandparents out-dance you
Rain plan invoked
Guest books the wrong hotel
Late arrival, big entrance
Last song, everyone stays
Marked 9 · Bingos 1
Card
Feed
Ranks
More

Offline / durable-card fallback (CachedCardFallback)When the deal fails but this device holds a snapshot, the Card tab renders the saved card read-only rather than a dead-end reload screen—the concrete payoff of the offline promise the install toast makes three frames up. Read-only on purpose: marking, Tally and Doubts all need the live board and its writers, which the interactive Board takes back the instant the deal recovers. One cell here is marked-but-pending (faded, dashed): an admin-confirmed claim that has not landed yet, mirrored from the live Board so the cached view never overstates confirmed progress. Brand-invariant copy—no occasion noun in any of it.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour
Refreshing
Someone cries during a toast
Rogue conga line
Cake-cutting photo scrum
Uncle finds the open bar
Playlist skips a track
Group photo takes four tries
Lost seating card
First dance false start
Someone asks for the wifi
Bouquet lands on a chair
Toast runs long
Sparkler exit rehearsal
FREE
Nobody knows the caterer
Dog in a bow tie
Card
Feed
Ranks
More

Pull-to-refresh (PullToRefresh)The gesture a standalone PWA has no browser reload button for. Only arms at scrollY ≤ 0, only on a mostly-vertical drag past the slop threshold, and commits past the pull threshold—so a horizontal swipe across the day strip never triggers it. The ring is Lucide life-buoy, the one place the icon set carries a nautical shape; it is chrome, not camp, so it stays identical on all three Editions per the “Lucide for chrome, emoji for camp” rule. The only announced string is a visually-hidden role="status" “Refreshing”.

✳ Five Across
FIVE ACROSS
💍 The Barn at Green Valley
🎊 Confetti Hour
Feed · nothing posted yet
Nothing in the feed yet. Somebody do something.
Ranks · filter matches nobody
No one matches this filter yet.
Tally who-list · square unmarked
No one has marked this yet.
Loading, mid-list
Loading…
Card
Feed
Ranks
More

Empty & in-between states (Feed, Ranks, Tally)Four strings that carry no occasion noun, so the lexicon sweep passes straight over them—and one of them should not have. “Nothing in the feed yet. Somebody do something.” is cruise-free but full camp: it reads as personality on Gay Cruise Bingo and as unserious on a wedding. It is a register mismatch the #608 acceptance criterion (“no cruise noun remains”) cannot catch, because the leak here is tone, not vocabulary. Flagged as an override candidate the lexicon does not yet list; the other three are genuinely brand-invariant. Also drawn in one place: the Ranks empty state keeps the share action reachable even when the filter matches nobody.

Per-brand annotation table

What actually changes when a utility state renders on a different Edition. token = interpolated from EditionLexicon; override = a whole per-Edition string on EditionBrand, because the sentence skeleton does not survive a swap. Anything marked invariant is one component, one string, three Editions—do not brand it.

SurfaceAnchorWhat changesGay Cruise BingoVacay BingoFive AcrossKind
Install nudgefx-install-* Benefit line offlineWhy Full screen, works offline at sea. …offline wherever you land. …offline in a packed venue. token
Install nudgefx-install-* Title, 📲 lead-in, ✕, gating, More → Install row Invariant. Platform branch (Show me / Install) is device-derived, not brand-derived. —
Install nudge— Installed PWA name + icon Gay Cruise BingoVacay BingoFive Across asset (#554/#587)
Update bannerfx-update-* Toast lead-in emoji 🚢🧳⬆️ override (updateToastMark)
Update bannerfx-update-* Title line A fresh build just docked A fresh build just landed A new version is ready override
Update bannerfx-update-* Sub-line, Reload / Not now, 60s poll, claim-sheet hold, build-floor force Invariant. “Your marks are safe—reload takes two seconds” carries no occasion noun. —
Toast stackfx-util-toaststack-fa Priority order, cap of 2, body-class clearance Invariant mechanics. Only the strings inside the two toasts differ. —
Loadingfx-util-loading-fa Label Checking your cruise pass… Checking your trip pass… Checking your pass… override
Crash panelfx-util-crash-fa Wordmark GAY CRUISE BINGO
glow, 15px, 300/800
VACAY BINGO
weathered red, no glow
FIVE ACROSS
no glow, .12em
override (#602) — wordmark only: no endorsement byline on ANY Edition here. The byline belongs to the two full-lockup surfaces (gate + in-app header); the two minimal recovery panels go without it, and (#881) no longer share one offline message either — see the two rows below. This row carried a + BY FIVE ACROSS note on Vacay from #647 that the code never matched; corrected in #688 rather than propagated.
Crash panelfx-util-crash-fa Total-failure fallback crashFallbackNote If the app won't recover, the printed cards and PDF still work. Falls back to the routine offlineNote below — Vacay and Five Across have no printed-card tradition of their own to point to (#881). override (gcb), fallback (vacay/fa)
Crash panel
(fallback only)
fx-util-crash-fa Routine dead-zone note offlineNote Lost signal at sea? Your card keeps working offline—marks sync when you reconnect. gcb sets crashFallbackNote, so the crash panel never falls back to this — shown for completeness. Patchy signal? Your card keeps working offline—marks sync when you reconnect. (shipped, #647—the override this doc once flagged to #608 landed in src/editions.ts) Packed room, no bars? Your card keeps working offline—marks sync when you reconnect. fallback
DealErrorfx-util-crash-fa Offline footnote None (#881, Codex round 4). No card was dealt yet on this screen, so a promise about a card working offline has nothing to refer to — the panel carries only the wordmark, the failure message, and Retry. removed
Crash panel
+ DealError
fx-util-crash-fa Reassurance line, Reset & reload, Retry, shell-reset behaviour Invariant. —
Durable cardfx-util-offline-card-fa Banner copy, Retry, pending-cell treatment, count line Invariant. Theme tokens retint it; no string changes. —
Pull-to-refreshfx-util-refresh-fa Lucide life-buoy ring, thresholds, “Refreshing” Invariant — chrome, not camp. The buoy is not a cruise reference to retire. —
Analytics noticefx-util-consent-fa “This is an 18+ app.” opener Follows publicHostnames/{host}.adultContent, NOT the Edition. Present on a Five Across Event whose pool holds spicy Prompts; absent on Bodega. dynamic
Analytics noticefx-util-consent-fa Disclosure body, Got it, versioned key Invariant. —
Empty statesfx-util-empty-fa “Nothing in the feed yet. Somebody do something.” ⚠ Cruise-free but full camp — a register leak the “no cruise noun” guard cannot catch. Needs a Vacay/Five Across override the lexicon does not yet list. override (gap)
Empty statesfx-util-empty-fa “No one matches this filter yet.” · “No one has marked this yet.” · “Loading…” Invariant. —
All of the above— Theme tokens 15-theme wardrobe
Bodega day themes
fiveacross-slate (proposed)
tokens

Share surfaces—one renderer, three identities

The five outbound surfaces, drawn three times each: Gay Cruise Bingo (cruise register, full camp, share mark 🚢, gaycruisebingo.com), Vacay Bingo (trip register, moderate camp, 🧳, vacaybingo.com), and Five Across (general register, minimal camp, ✳️, fiveacross.app). Everything structural is the same shared renderer—ShareCard.tsx's 600×750 canvas, the same podium and honoree blocks, the same on-device html-to-image raster (ADR 0005)—so what differs frame to frame is exactly what the Edition lexicon (#608) owns: the theme tokens, the occasion nouns, the footer share mark, the celebration text, and the download slug. The GCB frames carry the shipped renderer's copy verbatim—every quoted line is what the live Event draws today; that is the point, since gcb is the fallback Edition and any drift there is a bug. Share cards are drawn at half scale; the OG artboards at 1/4. Footer marks and celebration strings below are quoted verbatim from the signed-off lexicon.

1 · BINGO card—the word, the name, the line. Marked squares carry their prompt text (issue #444) so the card doubles as receipts on pinch-to-zoom; unmarked squares stay blank so the board reads as shape at iMessage-bubble size. The free centre matches the on-page free square: the same accent wash in a double ring, with a display FREE over the Day's caption. A caption too long for the tile even at the smallest size takes the whole tile instead: FREE yields first, then the caption's tail goes behind an ellipsis (the accent ring still marks the square). Only the footer mark and celebration text move between Editions; the context line (event name · Day N · place) and the stat line's night suffix (· ⟨tonight[0]⟩ night) carry Event data through an Edition-invariant shape (Board.tsx).

🚢 Gay Cruise Bingo
Atlantis Med—Trieste to Barcelona · Day 1 · Trieste
BINGO!
Theo
Befriend a bartender
Spot matching Speedos
Stateroom mirror selfie
Hear the ship's horn
Locate the late-night pizza
FREEYou made it aboard
Find your muster station
Balcony or porthole photo
Wave goodbye to land
Find the theater
Bingo #1 · 9 squares · ⛵ Sail-Away Party night
Gay Cruise Bingo 🚢

Cruise register—port, sailing, full campDiagonal blazes (lit + outlined + glow); other marked squares glow dimmer; the free centre is the on-page free square at share scale, a display FREE over its caption in an accent ring (an over-long caption takes the whole tile instead, behind an ellipsis if it must). Context line leads with the Event's name, then the Day and its Port; the stat line carries bingo count + squares (the free centre never counts) + the Day's first tonight entry as the party night. Share text "I got BINGO on the high seas 🚢"; file gay-cruise-bingo-bingo.png. Decorative emoji are in budget here and nowhere else.

🧳 Vacay Bingo
Bodega Bay · Day 2 · Bodega Bay
BINGO!
Maya
Walk part of the Bodega Dunes
Find a seashell on the beach
Find the best boat name in the harbor
Photograph a boat name that is pun-y
Capture a colorful buoy or crab pot
FREEMain character on the coast
Take a picture of a wildflower
Photograph the fog
Photograph something you had to pull over on Highway 1 for
Take a windblown group selfie
Bingo #1 · 9 squares · 🦀 Harbor dinner night
Vacay Bingo 🧳

Trip register—stop, group, moderate campSame composition, Pacific blue over sea-glass with the buoy-orange free centre. Context line leads with the Event's name (the trip is literally called "Bodega Bay", so name and Stop repeat—real data, not a typo); the night suffix carries Saturday's seeded tonight[0], whose emoji is Event data and so survives every register. Share text "I got BINGO on this trip 🧳"; file vacay-bingo-bingo.png. Prompts read as invitations, not chores.

✳ Five Across
Kim & Jo's Wedding · Day 1 · The Barn at Green Valley
BINGO!
Sam
Someone cries during a toast
Wrong table number
Group photo redo
Speech runs long
Playlist hijacked
FREESay hi to a stranger
Kid steals the show
Dance floor opens early
Lost the seating chart
Last song singalong
Bingo #1 · 9 squares · 🥂 Rehearsal dinner night
Five Across ✳️

General register—event, place, minimal campSlate and signal cobalt (proposed fiveacross-slate); the tonal gradient makes marked cells read as one decisive color rather than a party fill. Context line names the Day and its Place—the venue, never the occasion word, which lives in the Day's tonight entries ("🥂 Rehearsal dinner" is Day 1's tonight[0]); the night suffix is the same Edition-invariant mechanism as the other two frames. Share text "I got BINGO. ✳️"; file five-across-bingo.png. The BINGO! glow stays—it belongs to the shared renderer, not the wordmark, and the no-glow rule applies only to the lockup.

2 · Blackout / board recap—the progress card at its ceiling. Same layout as the BINGO card with all 24 squares on and the free centre accented; a blackout is all receipts, so every square carries its prompt. The solid wall of gradient is what reads in a chat thread, and it is the one frame where each Edition's palette is visible edge to edge.

🚢 Gay Cruise Bingo
Atlantis Med—Trieste to Barcelona · Day 1 · Trieste
BLACKOUT
Jess
Get your favorite dessert
Find your muster station
Get lost finding your cabin
Ride an elevator the wrong way
Locate the late-night pizza
First soft-serve of the cruise
Toast at the sailaway party
Wave goodbye to land
Hear the ship's horn
Meet someone from another country
Learn a crew member's name
Befriend a bartender
FREEYou made it aboard
Compliment a stranger's outfit
Exchange Instagrams with a new friend
Spot matching Speedos
Unpack a truly unhinged outfit
Plan tomorrow's party look
Test the bed (nap counts)
Stateroom mirror selfie
Balcony or porthole photo
Order a frozen drink with zero shame
Scope out the gym you'll never use
Find the theater
Overhear someone already complaining
All 24 squares · ⛵ Sail-Away Party night
Gay Cruise Bingo 🚢

The full grid lit is the flexTitle swaps to BLACKOUT; the stat line says all 24. Celebration text "BLACKOUT. I win the boat. 🚢"; file gay-cruise-bingo-blackout.png. The example is dealt from the tame warm-up pool (Day 1's boarding-day prompts), so the frame can be shown anywhere. The Event still derives adultContent: true from its main pool, so a main-day card reads differently—the posture follows the content, not the Edition.

🧳 Vacay Bingo
Bodega Bay · Day 1 · Bodega Bay
BLACKOUT
Jess
Take a windblown group selfie
Find the best boat name in the harbor
Get a bird into the background of a photo
Spot bird-themed art, a sign, or a souvenir
Capture a colorful buoy or crab pot
Make a toast about friendship
Photograph the fog rolling in, or refusing to leave
Find the house's weirdest decorative object
Get a group photo where nobody is ready
Photograph something the exact color of the sea today
Take a picture of a fire
Find a hand-painted sign
FREEThe flock has landed
Spot a gull, pelican, or heron doing something undignified
Photograph someone's hair losing a fight with the wind
Find something in the house older than everyone here
Capture a sunset, or the sky pretending it's going to be one
Win a game of something
Catch someone asleep in a chair they meant to sit in briefly
Photograph the group's shoes in a pile by the door
Find a flower growing somewhere it shouldn't
Post a candid that makes the group laugh
Suggest something for the group to do tomorrow
Get everyone in one frame using a timer
Take a photo of your favorite view from inside the house
All 24 squares · 🍷 Arrival pours night
Vacay Bingo 🧳

Sonoma Coast, not tropicalWeathered red over sea-glass green—the same wall of gradient, a completely different weekend. Celebration text "BLACKOUT. I win the trip. 🧳"; file vacay-bingo-blackout.png. Bodega's pool holds nothing spicy, so this Event derives adultContent: false—no gate, no 🔞, same card.

✳ Five Across
Kim & Jo's Wedding · Day 3 · The Barn at Green Valley
BLACKOUT
Sam
Someone cries during a toast
Wrong table number
Group photo redo
Playlist hijacked
Dance floor opens early
Speech runs long
A phone rings mid-vows
Two people in the same suit
Cake cut twice for the camera
Lost the seating chart
Kid steals the show
Uncle finds the mic
FREESay hi to a stranger
Bar-line photo
Grandparents on the floor
Someone changes shoes
Bouquet lands badly
Group selfie with the couple
Sparkler exit rehearsal
First to the buffet
Cufflink emergency
Table of strangers becomes friends
Someone loses a jacket
Late-night second course
Last song singalong
All 24 squares · 🥞 Send-off brunch night
Five Across ✳️

One hue, tonally gradientedCobalt into deep cobalt rather than a two-hue party fill—the blackout still lands as a wall, but reads as the platform rather than a skin. Celebration text "BLACKOUT. I win. ✳️"; file five-across-blackout.png. The night suffix carries the wind-down Day's first tonight entry (“🥞 Send-off brunch”)—Event data, not an Edition-register cut; the suffix mechanism is identical on all three frames.

3 · Leaderboard / standings snapshot—podium first, rows second. Top three as a podium with rank baked into the bars and the ★ First-BINGO pin above its holder; the rest as compact rows, capped at ten (eleven only when the pin holder sits outside the top ten and is appended so the honor never drops off the card). "Through Day N of M" dates the snapshot so a stale screenshot reads as stale. Ranking is ADR 0001 across the full ban-filtered roster, never the currently selected filter.

🚢 Gay Cruise Bingo
Atlantis Med—Trieste to Barcelona · Day 5 · Palermo (Sicily)
LEADERBOARD
Marco6 bingos
2
★ First BINGOJess7 bingos
1
Dan6 bingos
3
4 Theo 5 bingos · 80 sq
5 Big Denver Chris 4 bingos · 62 sq
6 Sam 4 bingos · 58 sq
7 Luca 3 bingos · 61 sq
8 Miguel 3 bingos · 49 sq
9 Andy P 2 bingos · 44 sq
10 Ray 2 bingos · 37 sq
Through Day 5 of 10
Gay Cruise Bingo 🚢

Ten deep on a ten-Day sailing★ pins the cruise-wide First to BINGO—a pin, not a rank. Share text "Check out the Gay Cruise Bingo leaderboard 🏆"; file gay-cruise-bingo-leaderboard.png. 🏆 is functional and unchanged on every Edition; only the qualifier in front of it moves.

🧳 Vacay Bingo
Bodega Bay · Day 2 · Bodega Bay
LEADERBOARD
Priya4 bingos
2
★ First BINGOMaya5 bingos
1
Jess4 bingos
3
4 Kim 3 bingos · 44 sq
5 Dev 2 bingos · 38 sq
6 Ana 1 bingo · 29 sq
Through Day 2 of 4
Vacay Bingo 🧳

Six players, four Days—the cap never bindsThe top-ten cap is a ceiling, not a target: a weekend group renders six rows and the frame still reads. ★ pins the trip-wide First to BINGO. Share text "Check out the Vacay Bingo leaderboard 🏆"; file vacay-bingo-leaderboard.png.

✳ Five Across
Kim & Jo's Wedding · Day 2 · The Barn at Green Valley
LEADERBOARD
Rosa5 bingos
2
★ First BINGOSam6 bingos
1
Dev5 bingos
3
4 Amara 4 bingos · 61 sq
5 Jonah 4 bingos · 58 sq
6 Kim 3 bingos · 55 sq
7 Jo 3 bingos · 52 sq
8 Priya 3 bingos · 47 sq
9 Marcus 2 bingos · 41 sq
10 Elena 2 bingos · 36 sq
Through Day 2 of 3
Five Across ✳️

Occasion-neutral standingsSame podium mechanics with the qualifier gone: the on-page note reads "⭐ marks the event-wide First to BINGO", and the Day line names a Place ("The Barn at Green Valley"), not a port—the occasion word never rides a place slot. Share text "Check out the Five Across leaderboard 🏆"; file five-across-leaderboard.png.

4 · Final standings—the frozen podium, portable (issue #449). Champion and the Event-wide First to BINGO as labeled honoree blocks, then the daily honors as day-vs-name rows, then a line dating it as the last word. Shared from a full-width button at the bottom of the podium itself, and only once the day-meta honors have settled—an early tap would bake an incomplete honors list into the image.

🚢 Gay Cruise Bingo
Atlantis Med—Trieste to Barcelona · Day 10 · Barcelona
FINAL STANDINGS
🏆 Cruise champion
Zacaria Arab
16 bingos · 124 squares
👑 First to BINGO
Logan Murdock
Daily honors
Day 1 · Trieste 🇮🇹Andrew Levad
Day 2 · Split 🇭🇷Logan Murdock
Day 3 · Sea Day 🌊Ido Marcus
Day 4 · Valletta 🇲🇹Turntilla
Day 5 · Palermo (Sicily) 🇮🇹Nathan Payne
Day 6 · Naples (Pompeii) 🇮🇹Logan Murdock
Day 7 · Rome (Civitavecchia) 🇮🇹Nathan Payne
Day 8 · Villefranche (Nice) 🇫🇷Turntilla
Day 9 · Marseille 🇫🇷Zacaria Arab
Day 10 · Barcelona 🇪🇸Nathan Payne
Final standings · 10 days
Gay Cruise Bingo 🚢

"🏆 Cruise champion" · podium aria "Cruise podium"Day labels are Ports (seeded verbatim, parentheticals included) with their flag emoji—per-Event placeEmoji data, not code, so they need no Edition scoping. The 👑 holder is Day 2’s honoree, not Day 4’s: Day 1 (Trieste) is tutorial: true in the Med seed and the Event-wide honor excludes Tutorial Days, so the earliest eligible honor in this example is Day 2 · Split, which the list below gives Logan Murdock. Day order is the example’s shape, not the rule: the selector compares firstBingoAt timestamps, and past Days stay markable all Event (plans/daily-cards-spec.md § Unlock mechanics), so a backfilled Day 2 bingo can be stamped later than someone’s Day 4 one. This roster is drawn the straightforward way—each Day’s honor earned on its own Day—which is what makes Day 2 the holder and keeps the frame teaching the Tutorial-exclusion rule rather than an unstated backfill timeline. Share text "Final standings from Gay Cruise Bingo 🏆"; file gay-cruise-bingo-final-standings.png. Names clamp to one line; honor names ellipsize before day labels give way.

🧳 Vacay Bingo
Bodega Bay · Day 4 · The drive home
FINAL STANDINGS
🏆 Trip champion
Maya
5 bingos · 52 squares
👑 First to BINGO
Maya
Daily honors
Day 1 · Bodega Bay 🐚Jess
Day 2 · Bodega Bay 🦪Maya
Day 3 · Bodega Bay 🌅Priya
Day 4 · The drive home 👋Maya
Final standings · 4 days
Vacay Bingo 🧳

"🏆 Trip champion" · podium aria "Trip podium"Drawn in the light postcard-cream theme to prove the token contract survives a light palette—the one card in the set that is not dark-first. Day labels are Day N · place placeEmoji (makeDayLabel, FarewellPodium.tsx)—Bodega's four Days share one place, so the per-Day emoji is what tells them apart, and the wrap-up Day's "The drive home" is a real place value, not a vignette title (the vignette Theme names live on the cards and the email header, never the honors strip). Share text "Final standings from Vacay Bingo 🏆"; file vacay-bingo-final-standings.png. On a weekend of four Days the champion and the First to BINGO can be the same person; both blocks still render.

✳ Five Across
Kim & Jo's Wedding · Day 3 · The Barn at Green Valley
FINAL STANDINGS
🏆 Champion
Sam
6 bingos · 71 squares
👑 First to BINGO
Rosa
Daily honors
Day 1 · The Barn at Green Valley 🥂Amara
Day 2 · The Barn at Green Valley 💍Sam
Day 3 · The Barn at Green Valley 🥞Rosa
Final standings · 3 days
Five Across ✳️

"🏆 Champion"—no qualifier · podium aria "Final podium"The general register drops the occasion word rather than translating it, which is the tell that the platform is not a third skin. Day labels are the same Day N · place placeEmoji shape as every Edition—a single-venue weekend repeats the Place and lets the per-Day emoji (🥂/💍/🥞) carry the difference; the emoji is the Event's own placeEmoji data, and a Day that sets none renders the bare label. Share text "Final standings from Five Across 🏆"; file five-across-final-standings.png.

4b · Final standings, photo hero (issue #534)—the same frozen podium with the Event's Most-Loved Photo as the centerpiece. This is the image people actually share: the photo carries the memory, and the standings compose around it. The award band and heart count sit on the photo itself; the credit line names the poster, the Prompt and the Day it was shot; the champion keeps the Bebas treatment while ranks 2–3 and the 👑 First to BINGO compress to rows. The one block that yields its space to the photo is the daily-honors list—it stays on the photo-less card above, which remains the documented fallback. Same 600×750 renderer, same share button on the podium, same per-Edition slug: one surface, two compositions. The photo in these frames is a token-tinted placeholder scene; in production it is the frozen winner's actual image, letterboxed to the hero box.

Selection rule (server-frozen at the Standings Freeze, #534): if the Event holds a Most-Loved Photo—at least one photo Proof posted and at least one eligible Heart on it (self-Hearts and Hearts from banned Players never count)—the finale share renders this photo-hero card. Otherwise—no photos, or photos but zero eligible Hearts—it renders the photo-less final-standings card above. Ties share the honor: the hero shows the earliest-posted of the tied photos and the credit line names the tie ("shared with Jess"). The frozen award never recomputes; if the winning photo is later hidden by moderation, the award stays recorded but the share falls back to the photo-less composition rather than rendering a hidden image.

🚢 Gay Cruise Bingo
Atlantis Med—Trieste to Barcelona · Day 10 · Barcelona
FINAL STANDINGS
📷 Most-loved photo❤ 31
Ido Marcus · “Mirror-hall selfie” · Day 7 · Rome (Civitavecchia) 🇮🇹
1Zacaria Arab🏆 Cruise champion16 bingos
2Logan Murdock14 bingos · 117 sq
3Nathan Payne13 bingos · 110 sq
👑Logan MurdockFirst to BINGO
Final standings · 10 days
Gay Cruise Bingo 🚢

The photo is the flex nowSunset-warm so-long-farewell tokens tint the placeholder scene; the ❤ count is the frozen eligible-Heart total, not a live number. "🏆 Cruise champion" keeps its qualifier; the honors list stays on the fallback card. The 👑 row renders name + role only—an earlier draft gave it a stat, dropped as a recorded deviation (specs/most-loved-photo.md § Deviations, item 6: the card system renders no timezone-formatted times). The 👑 row names Logan Murdock for the reason the fallback card above states—Day 1 (Trieste) is tutorial: true, so the Event-wide honor starts at Day 2 · Split—and a Player may hold a rank row and the 👑 row at once, exactly as Maya does on fx-share-final-photo-vacay. Share text "Final standings from Gay Cruise Bingo 🏆"; file gay-cruise-bingo-final-standings.png—the slug does not fork, because this is the same surface in its photo-hero composition.

Gay Cruise Bingo final standings share card with the Most-Loved Photo as centerpiece

file plans/og-images/share-final-photo-gcb.png · 600×750
source this artboard, captured at 2× by scripts/og/render-share-rasters.mjs --edition gcb (#887). The picture directly above and the artboard at the top of this unit are one composition rendered twice, so the 👑 row cannot drift apart from it again the way it did when the refresh was a hand-driven screen capture.

🧳 Vacay Bingo
Bodega Bay · Day 4 · The drive home
FINAL STANDINGS
📷 Most-loved photo❤ 9
Priya · “Stage an original suspense-movie still” · Day 2 · Bodega Bay 🦪
1Maya🏆 Trip champion5 bingos
2Priya4 bingos · 55 sq
3Jess4 bingos · 48 sq
👑MayaFirst to BINGO
Final standings · 4 days
Vacay Bingo 🧳

Scrapbook first—the finale that leads with the photoThe trip Edition is where this card is the point: the Vacay finale is a scrapbook, not a scoreboard, and nine Hearts on a weekend of six players is a landslide. Postcard-cream fog-froth-farewells proves the hero box, badge and heart chip survive the light palette. The winner here matches fx-podium-vacay's Most-Loved block—one frozen award, two surfaces. Share text "Final standings from Vacay Bingo 🏆"; file vacay-bingo-final-standings.png.

Vacay Bingo final standings share card with the Most-Loved Photo as centerpiece

file plans/og-images/share-final-photo-vacay.png · 600×750
source this artboard, via scripts/og/render-share-rasters.mjs --edition vacay. The committed picture predates that renderer and is left as captured, and it has drifted from this artboard's current styling—it draws the two .mlrole chips as bare text rather than accented pills, wraps the credit line onto a second line, and carries black rather than page-ground corners. So the first re-render restyles the card as well as changing whatever copy prompted it; that is this artboard asserting itself, not a regression, but it is not a one-word diff.

✳ Five Across
Kim & Jo's Wedding · Day 3 · The Barn at Green Valley
FINAL STANDINGS
📷 Most-loved photo❤ 14
Amara · “Group selfie with the couple” · Day 3 · The Barn at Green Valley 🥞
1Sam🏆 Champion6 bingos
2Rosa5 bingos · 63 sq
3Dev5 bingos · 58 sq
👑RosaFirst to BINGO
Final standings · 3 days
Five Across ✳️

"🏆 Champion"—no qualifier, one decisive hueThe tonal cobalt scene reads as a platform card, not a party skin; the tempered-gold award chrome is the one accent, which is exactly the hierarchy the general register wants: the photo, then the names. Share text "Final standings from Five Across 🏆"; file five-across-final-standings.png.

Five Across final standings share card with the Most-Loved Photo as centerpiece

file plans/og-images/share-final-photo-fa.png · 600×750
source this artboard, via scripts/og/render-share-rasters.mjs --edition fiveacross. The committed picture predates that renderer and is left as captured; the next content change to it re-renders.

Link unfurls—the rendered OG assets

The surface nobody taps and everybody sees. Crawlers do not run JS, so an unfurl cannot be resolved by browser JavaScript from publicHostnames/{host} at request time—and the fix this section once documented as a live bug has since shipped in three pieces: #587 bakes each Edition's meta block into index.html at build time, #607 moved all three share surfaces from canonicalOrigin() to shareOrigin() so a copied link carries the Edition's own host, and the per-Edition artwork landed as the #609 composition (via #642) with #697 adding its generator (scripts/og/render-og-editions.mjs). Below are the rendered 1200×630 PNGs committed at plans/og-images/—byte-identical mirrors of the shipped public/og-*.png, both written by one generator run—embedded at doc scale, followed by annotated vector artboards of the same generated composition. Residual gap: a hostname-resolved multi-Event bundle keeps the default Edition's baked block wherever Hosting serves it directly; the #1118 edge HTML rewrite emits it per hostname once the Worker fronts the host.

🚢 Gay Cruise Bingo Gay Cruise Bingo—a marked-up live multiplayer bingo card for the high seas

file plans/og-images/gay-cruise-bingo-og.png · 1200×630
og:site_name Gay Cruise Bingo
og:title Gay Cruise Bingo
meta description Live multiplayer bingo for the high seas. Trieste to Barcelona, July 2026.

🧳 Vacay Bingo Vacay Bingo—a marked-up live multiplayer bingo card for the trip

file plans/og-images/vacay-bingo-og.png · 1200×630
og:site_name Vacay Bingo
og:title Vacay Bingo
meta description Live multiplayer bingo for the trip.

✳ Five Across Five Across—a marked-up live multiplayer bingo card

file plans/og-images/five-across-og.png · 1200×630
og:site_name Five Across
og:title Five Across
meta description Live multiplayer bingo for your group.

The artboards

5 · OG / link-unfurl image—the surface nobody taps and everybody sees. 1200×630, drawn here at 1/4. Crawlers do not run JS, so this cannot be resolved by browser JavaScript from publicHostnames/{host} at runtime: single-Event builds bake it via VITE_EDITION (#587—the meta wording below is what its build-time tokens inject, quoted from the lexicon), multi-Event bundles get it from the #1118 edge HTML rewrite, once the Worker fronts the host. These annotated vector artboards follow the shipped #609 composition as rebuilt in scripts/og/render-og-editions.mjs. src/recon-share-og.test.ts's wireframe suite (#884) pins the eyebrow and share-mark copy, wordmark/byline text, appDescription (including its wrap point), the BINGO caption, Edition-specific stamp copy, the board pattern/bars and their bar/cell geometry, the on-mark palette tokens (freeink, on-glow, on-gradient, board shadow), and the checked display faces against the generator's shared og-edition-art.mjs manifest. The committed PNGs above remain pixel truth; the base palette hex values, background gradient geometry, font sizes, and mark/board offsets drawn here are illustrative approximations at 1/4 scale and are not checked against the renderer.

🚢 Gay Cruise Bingo
🚢 ONE SAILING AT A TIME
GAY CRUISE
BINGO
BY FIVE ACROSS
Live multiplayer bingo
for the high seas.
gaycruisebingo.com
FREE
BINGO

og:site_name Gay Cruise Bingo
og:title Gay Cruise Bingo
og:description Sign in, get your card, mark it if you see it. (Edition-invariant—the one untokenised tag, identical on all three; #587)
meta description Live multiplayer bingo for the high seas. Trieste to Barcelona, July 2026.
og:image:alt Gay Cruise Bingo—a marked-up live multiplayer bingo card for the July 2026 sailing, Trieste to Barcelona

The flagship unfurl—endorsedAnton wordmark stacked over the description line, the marked board as the picture, the default neon-playground palette. The drawn line is appDescription ("Live multiplayer bingo for the high seas.")—the artwork's own copy—while the og:description META tag stays the Edition-invariant tagline; the two are different strings on purpose. #688 gives GCB the BY FIVE ACROSS line here too, in exactly the slot fx-og-vacay uses—eyebrow, wordmark, endorsement, rule, description—so the two Editions unfurl as one family. public/og-gcb.png (mirrored byte-identical at plans/og-images/gay-cruise-bingo-og.png) is rendered from scripts/og/og-edition.html by scripts/og/render-og-editions.mjs, which reads its wordmark, endorsement line, description and share mark straight from src/editions.ts—so a copy change is a brand-table edit plus a re-render, not a pixel edit. The runbook is docs/app/og-artwork.md. All three Editions' artwork ships: this one from the legacy project's always-healthy gaycruisebingo.web.app host (the apex TLS-resets for link crawlers—#340), Vacay's and Five Across's from fiveacross.web.app (ADR 0008).

🧳 Vacay Bingo
🧳 ONE TRIP AT A TIME
VACAY
BINGO
BY FIVE ACROSS
Live multiplayer bingo for the trip.
vacaybingo.com
FREE
BINGO
🧳TAKE THE
DETOUR

og:site_name Vacay Bingo
og:title Vacay Bingo
og:description Sign in, get your card, mark it if you see it. (Edition-invariant—the one untokenised tag, identical on all three; #587)
meta description Live multiplayer bingo for the trip.
og:image:alt Vacay Bingo—a marked-up live multiplayer bingo card for the trip

The endorsed unfurl—one identity, plus its parentThe BY FIVE ACROSS small-caps line, in the slot fx-og-gcb now mirrors since #688: the one-identity rule says a Vacay player never sees two competing brands, and the endorsement is a signature, not a second lockup. Only fx-og-fa goes without, being the platform itself. Both Editions' rasters carry it, and both come off the same generator (scripts/og/render-og-editions.mjs). Pacific blue and sea-glass; deliberately non-tropical. The og:url is the one tag whose baked value stays Event-scoped (bodega-bay.fiveacross.app), because a build can bake only one origin; the #1118 edge HTML rewrite owns the served tag per hostname—the artwork itself names the brand's apex, vacaybingo.com.

✳ Five Across
✳ THE PLATFORM
FIVE ACROSS
Live multiplayer bingo for your group.
fiveacross.app
✳
BINGO

og:site_name Five Across
og:title Five Across
og:description Sign in, get your card, mark it if you see it. (Edition-invariant—the one untokenised tag, identical on all three; #587)
meta description Live multiplayer bingo for your group.
og:image:alt Five Across—a marked-up live multiplayer bingo card

Set type, not a party skinThe platform wordmark is one line, with glow removed and tracking opened to .14em—GCB glows, Vacay is a postcard, Five Across is set type, and the restraint is the differentiation. The text-presentation share mark ✳ (U+2733, no variation selector) appears in the eyebrow and free square; the domain line uses only the brand's address. The description is appDescription alone ("Live multiplayer bingo for your group."), while the offline story lives in the app's offlineNote.

Daily engagement email—the Day's Theme in the inbox (issue #616)

One email per participant per Event-local calendar date that has a Day, up to the Event's Standings Freeze, sent that morning in the Event's timezone, carrying the same identity the app shows that morning: the Day's Theme name, its palette, its context line. Revised by #723: the original rule here was one email per DAY at that Day's unlock, but an Event's days array does not map one-to-one onto its calendar dates—Bodega Bay puts two Days on Sunday—so a later Day sharing a date gets no email of its own. Revised by #1121: the mail also stops at the Event's Standings Freeze—the instant scoring permanently ends and the ⭐ is settled—so no morning at or after it produces a daily email, and the finale is the mail that speaks for what is left. The full cadence contract lives in specs/daily-engagement-email.md § Scheduling. Job order is fixed—nudge participation, show standings, make the photo expected, point at the Feed—and the photos message is load-bearing: every BINGO claim is a photo opportunity, and the email is where that becomes a norm rather than a feature. Delivery is the existing transactional stack (Resend via functions/src/email.ts); the sender identity is the Edition's (EMAIL_FROM resolved per Edition, #671/#810); the Feed CTA deep-links the Event's canonical host (#599). Recipients are signed-in participants only, every send carries a working unsubscribe, and the whole family is a default-off opt-in (settings.dailyEmailEnabled)—there is no console control for it yet (#785); the setup wizard's Basics step is where it gets collected.

✳ Five Across
1 Preheader: "Day 2: ⟨Theme label⟩—standings through Day 1 inside."—hidden in the body, shown beside the subject.
Five Across
Theme emoji + name
2 Day 2 of 3 · Saturday, Aug 22 · 💍 The Barn at Green Valley
3 Standings · through Day 1
1Leader name2 bingos · 21 sq
2Second name2 bingos · 18 sq
3Third name1 bingo · 16 sq
You're #5—14 squares marked—your first BINGO is still out there.
4 Participation nudge
Morning, ⟨first name⟩. Today at The Barn at Green Valley starts now—your Day 2 card is live at 8:00 a.m.: 24 fresh squares. The Day's tonight entries ride below, joined with " · ".
5 Photos + the award
Post a photo with every BINGO. That's what the Feed is for. 📷 The most-loved photo of the event takes an award at the finale—Hearts on photo Proofs decide it, frozen at the Standings Freeze.
6 Primary CTA
Open the Feed
7 Five Across—You're getting this because you're part of Kim & Jo's Wedding. Unsubscribe · Email preferences
  1. Preheader. ~85 chars of hidden body text; clients show it beside the subject. Carries the Day + one hook (standings movement or tonight's Theme). Subject and preheader are the Edition's register at its quietest—no decorative lead-ins on any Edition.
  2. Theme header. The Day's Theme name in display type over a two-token gradient band, with the Day context line (Day N of M · weekday · Place, per the Edition's lexicon noun) and the Theme's five-swatch palette strip. This is the module that makes the email "resemble the day": tokens come from the same DayDef/Theme record the app renders. Wordmark stays small—the Theme is the headline, the brand is the sender.
  3. Standings snapshot. Top three through yesterday, plus one personalized line—"You're #N—X bingos and Y squares so far." once you have a BINGO, "You're #N—Y squares marked—your first BINGO is still out there." before it (dailyEmailContent.ts; a drafted distance-to-BINGO tail deliberately did not ship)—which is the only per-recipient variance in the send. Assembled server-side (Admin SDK, #593). On Day 1 this module renders its empty state: no ranks yet, first-BINGO honor still open—see the Vacay render.
  4. Participation nudge. Today's card exists and is live—unlock time, square count, tonight's events. Never guilt; the register is an invitation.
  5. Photos + award. The two content requirements ride together: post a photo with every BINGO (make it expected, celebrated), and the Most-Loved Photo award (#534) is the standing reason. Same module every Day—norms are built by repetition.
  6. Primary CTA. One button, "Open the Feed", deep-linking the Event's canonical host (#599)—the Feed is the destination, not the Card, because the email's job is the social loop. Bulletproof-button construction (padded table cell + border, VML for Outlook), never an image.
  7. Footer. The Edition's brand line bolded, an em dash, the why-you-got-this line with the Event's name interpolated (<strong>{brandLine}</strong>—{whyLine}, emailShell.ts), then visible unsubscribe + preferences links, with List-Unsubscribe/List-Unsubscribe-Post headers so mail clients surface their native control. The sender address lives only in the From: header (per-Edition EMAIL_FROM resolution, #671/#810)—the visible footer never repeats it. Per-user opt-out is persisted and suppressed before send.

Template anatomy—one skeleton, skinned by the DayRendered in the proposed fiveacross-slate because the anatomy is a platform artifact: the Editions change the words and the Day changes the palette, but the module order never moves. Drawn at half scale; 300px here is the 600px email canvas.

🧳 Vacay Bingo
Day 1 is here—your card is live now.
Vacay Bingo · by Five Across
🐦 The Birds Have Entered the Chat
Day 1 of 4 · Friday, Aug 7 · 🐚 Bodega Bay
Standings · Day 1
No standings yet—the trip starts today. First BINGO takes the ⭐ trip-wide honor, and the first photo sets the bar.
Today
Morning, Maya. The group lands in Bodega Bay today—your Day 1 card is live now: 24 fresh squares.
Tonight: 🍷 Arrival pours · 🌊 First look at the water
Photos
Got BINGO? Post a photo with it. Every claim is a photo op, and the group chat wants receipts. 📷 The most-loved photo of the trip takes an award at the finale—Hearts on photo Proofs decide it, frozen at the Standings Freeze.
Open the Feed
Vacay Bingo · by Five Across—You're getting this because you're on the Bodega Bay trip. Unsubscribe · Email preferences

Bodega Day 1—the fully-rendered exampleTrip register at moderate camp: sea-glass and weathered red from the-birds (the five-swatch strip is the email token table's literal hex, dailyEmailTheme.ts), the vignette Theme as the headline, and the endorsement riding the footer brand line (one-identity rule). The host renders only on the pre-auth sign-in card ("hosted by Kim"), never in the email's context line; the sender address lives in the From: header, not the visible footer. Day 1 is the unlockAt: 0 sentinel, so the copy says live now—no clock time is quoted anywhere (#723)—and it shows the standings module's empty state: no ranks to report yet, so the module sells the two open honors instead of apologizing. Theme emoji stays (Theme identity survives the register cut); no decorative lead-ins anywhere.

🚢 Gay Cruise Bingo
Day 4: Sporty Splash—standings through Day 3 inside.
Gay Cruise Bingo · by Five Across
💦 Sporty Splash
Day 4 of 10 · Saturday, Jul 18 · 🇲🇹 Valletta
Standings · through Day 3
1Jess ⭐4 bingos · 41 sq
2Marco3 bingos · 38 sq
3Dan3 bingos · 33 sq
You're #6—1 bingo and 24 squares so far.
Today
Morning, Theo. The boat docks in Valletta today—your Day 4 card is live at 8:00 a.m.: 24 fresh squares.
Tonight: 💦 Splash T-Dance · 🏋️ Get Sporty
Photos
BINGO without a photo is a rumor. Post a pic with every claim—the boat wants receipts. 📷 The most-loved photo of the cruise takes an award at the finale—Hearts on photo Proofs decide it, frozen at the Standings Freeze.
Open the Feed
Gay Cruise Bingo · by Five Across—You're getting this because you're sailing Atlantis Med—Trieste to Barcelona. Unsubscribe · Email preferences

Mid-cruise Day 4—the cruise-Edition exampleCruise register at full camp: sporty-splash tokens skin the band, the port flag rides the context line, the ⭐ cruise-wide First-BINGO pin travels with Jess's row, and the photos module gets to be funny ("BINGO without a photo is a rumor")—the same module Vacay says gently and Five Across says plainly. The standings snapshot is the full state: top three through yesterday plus the personalized "You're #N" line, which is the only per-recipient variance in the send. The brand line Gay Cruise Bingo · by Five Across (#698) rides both the header band and the footer sign-off: the cruise Edition carries the platform endorsement exactly as it does under its in-app wordmark (#688), on one inline line rather than the lockup's stacked micro-line, because this is a sign-off and not display type.

The winner announcement—the last mail of the Event (issue #1192)

One email per participant at the finale's podium beat, and the only mail an Event sends at or after its Standings Freeze. #1121 stops the daily card at the freeze because nothing it says is still true; this is what speaks in its place, so the last thing in the inbox is the final standings rather than a card nobody can play. It is due off the in-app podium Moment and reads that Moment's own stored payload (buildPodiumPayload, functions/src/finaleContent.ts), so the email cannot name a champion the Feed and the Leaderboard do not. Its own quarter-hourly sweep (podiumAnnouncementEmail), shaped like the daily card's rather than run inside the finale beat: a paced per-recipient fan-out in that serial, secret-less, 60-second scheduler would have starved every later Event's Day snapshot and rebuilt the podium from live Player documents on each retry. Reading the Moment is what makes the email quote the frozen record by construction. The honours are ban-filtered for the email even though the Moment's payload is not—the Moment is the record and a ban is reversible, so it keeps the unfiltered truth; this is a rendered view and hides the row. The subject names the champion—it is the strongest true thing the mail has to say, and the register supplies the verb (takes the cruise / takes the trip / takes it); an Event whose board is empty falls back to the occasion close (the cruise is done), because there is no name to print. Exactly one send per Event per recipient, on its own marker rather than the daily card's lastSentDayIndex; a failed send never blocks the freeze or the Moment.

🚢 Gay Cruise Bingo
1 The podium is in—see who took the ⭐ and the Most-Loved Photo.
Gay Cruise Bingo · by Five Across
👋 So Long, Farewell
2 Final standings · Day 10 of 10 · Friday, Jul 24 · 🇪🇸 Barcelona
3 Final standings · frozen
1Zacaria Arab16 bingos · 124 sq
2Logan Murdock ⭐14 bingos · 117 sq
3Nathan Payne13 bingos · 110 sq
4 The ⭐
Logan Murdock took the cruise-wide First to BINGO—Day 2 in 🇭🇷 Split.
5 Most-loved photo
📷 Ido Marcus—"Mirror-hall selfie," Day 7 · 🇮🇹 Rome (Civitavecchia). ❤ 31, frozen at the Standings Freeze.
6 Where you finished
You finished #6—1 bingo and 24 squares.
7 Sign-off + CTA
That's the cruise. Every photo is still in the Feed—go back through the whole thing.
Open the Feed
8 Gay Cruise Bingo · by Five Across—You're getting this because you're sailing Atlantis Med—Trieste to Barcelona. Unsubscribe · Email preferences
  1. Preheader. Names the two honors without naming their holders—the subject already spent the champion, and two unspoiled reveals are what the open is for. Same ~85-char budget and the same no-decorative-lead-ins rule as the daily card.
  2. Theme header. The farewell Day's own Theme (so-long-farewell), unchanged machinery: the band is the Day's palette and the context line is the Day context with Final standings in the slot the daily card gives "Day N". The email wears the day it was sent on, which is the day the Event ended.
  3. Final standings. Top three with bingos and squares, ranked by compareFinalePlayers. Row 1 is the podium's champion field byte for byte—the parity test pins it, because that is the one row the in-app Moment actually carries. Rows 2 and 3 come from the same roster through the same sort; the Moment has no second or third place to disagree with (#1192 decision). Ceremonial Days are excluded from the totals exactly as the podium excludes them, so the farewell Day's own marks never move these numbers.
  4. The ⭐. Its own module rather than a pin, because the Event-wide First to BINGO frequently is not in the top three—Tutorial Days are excluded from the honor, so it belongs to the earliest qualifying bingo on a main Day, whoever that was. Equal to the podium's firstBingo field byte for byte, tie-break included. It rides row 2 here only because Logan happens to hold both.
  5. Most-loved photo. The Most-Loved Photo award (#534/#560) as the podium froze it: winners[0]—the share hero—with its prompt text, Day and eligible-Heart count. The count is the frozen total, never a live re-read. A tie prints the hero and says how many shared it; a no-award Event omits the module rather than printing a zero.
  6. Where you finished. The only per-recipient variance in the send, exactly as "You're #N" is in the daily card—past tense, because nothing moves after this. Omitted entirely for an address that is not on the roster, which is the daily card's rule unchanged.
  7. Sign-off + CTA. One closing line in the Edition's register, then the same "Open the Feed" button the daily card uses, deep-linking the Event's canonical host (#599). The Feed is still the destination: the Event is over, and the archive of it is the thing worth opening.
  8. Footer. Identical to the daily card's—brand line, why-you-got-this, visible unsubscribe + preferences, List-Unsubscribe headers. This is a daily-email send under the existing opt-in (settings.dailyEmailEnabled), not a new category, so the same unsubscribe governs it.

The farewell mail—cruise register at full campSubject "Final standings 🏆—Zacaria Arab takes the cruise"; the empty-board fallback is "Final standings 🏆—the cruise is done". The example is the same Event, roster and honors as the final-standings share card (#fx-share-final-gcb) on purpose—these two surfaces state one frozen result, and a frame that quietly disagreed with the other would hide exactly the drift the parity test exists to catch. The ⭐ holder is Logan Murdock, and the rule is why: Day 1 (Trieste) is tutorial: true in the Med seed and the Event-wide honor excludes Tutorial Days, so it belongs to the earliest main-Day bingo—Day 2 · Split, whose own daily honor this Event's honors list already gives to Logan. Turntilla's earliest honor is Day 4, which cannot precede it. The final-standings share card (#fx-share-final-gcb) named Turntilla when this frame was written; #1208 corrected it, so the two surfaces now agree.

✳ Five Across
The podium is in—see who took the ⭐ and the Most-Loved Photo.
Five Across
✳ Final standings
Final standings · Day 3 of 3 · Sunday, Aug 23 · 💍 The Barn at Green Valley
Final standings · frozen
1Sam ⭐6 bingos · 68 sq
2Rosa5 bingos · 64 sq
3Dev5 bingos · 61 sq
The ⭐
Sam took the event-wide First to BINGO—Day 1 in 💍 The Barn at Green Valley.
Most-loved photo
📷 Amara—"First dance, from the balcony," Day 2 · 💍 The Barn at Green Valley. ❤ 14, frozen at the Standings Freeze.
You finished #7—3 bingos and 52 squares.
That's the event. Every photo is still in the Feed.
Open the Feed
Five Across—You're getting this because you're part of Kim & Jo's Wedding. Unsubscribe · Email preferences

The platform register—plain, and the occasion word goneSubject "Final standings 🏆—Sam takes it"; empty-board fallback "Final standings 🏆—the event is done". Five Across gets a full render here rather than the register strip's annotations (the rule for the daily card) because this email's register carries three new fields—the subject verb, the honor qualifier in module 4, and the sign-off—and a table row cannot show how a three-Day wedding reads when the same skeleton loses the camp. fiveacross-slate tokens, and the header wears ✳ Final standings where a themed Edition wears the Day's Theme: a wedding's closing Day carries no vignette Theme, so the platform band states the occasion instead of inventing one. ⭐ rides row 1 here—the small-Event common case, where the first BINGO and the eventual champion are the same person—which is exactly why module 4 still exists as its own line: the honor is a different question from the ranking, and the answer only coincides sometimes.

Per-brand register strip—the fa variant as annotations

Five Across gets no third full render: the platform email is the anatomy frame above, and drawing it again in slate would document nothing the table below does not say more honestly. Every row is the #608 lexicon applied to one email module; rows marked brand-invariant never change.

Module🚢 Gay Cruise Bingo🧳 Vacay Bingo✳ Five Across
Sender (EMAIL_FROM per-Edition resolution, #671/#810)Gay Cruise Bingo <hello@fiveacross.app>Vacay Bingo <hello@fiveacross.app>Five Across <hello@fiveacross.app>
Subject shape (Day N · label emoji—tail)Day 4 · Sporty Splash 💦—standings + tonightDay 1 · The Birds Have Entered the Chat 🐦—your card is liveDay 2 · Confetti Hour 🎊—standings + today's card
Context-line nounthe port, with flag (🇲🇹 Valletta)the Stop (🐚 Bodega Bay)the Place (💍 The Barn at Green Valley)
Morning line"The boat docks in Valletta today""The group lands in Bodega Bay today" on the opening Day and whenever the Stop changes; "The group is still in Bodega Bay today" on a Day that stays in the previous Day's Stop (#1344)"Today at The Barn at Green Valley starts now"
Photos nudge"BINGO without a photo is a rumor. Post a pic with every claim—the boat wants receipts.""Got BINGO? Post a photo with it. Every claim is a photo op, and the group chat wants receipts.""Post a photo with every BINGO. That's what the Feed is for."
Award linemost-loved photo of the cruisemost-loved photo of the tripmost-loved photo of the event
Why-you-got-this"…because you're sailing Atlantis Med—Trieste to Barcelona.""…because you're on the Bodega Bay trip.""…because you're part of Kim & Jo's Wedding."
Theme headerbrand-invariant mechanism—the Day's Theme name, emoji and palette strip, whatever the Edition
Standings modulebrand-invariant structure—top 3 through yesterday + "You're #N" line; only the ⭐/👑 qualifier word follows the lexicon (cruise-wide / trip-wide / event-wide)
CTAbrand-invariant—"Open the Feed", Theme-gradient bulletproof button, deep link to the Event's canonical host (#599)
Unsubscribebrand-invariant—visible link + List-Unsubscribe headers; per-user opt-out persisted, suppressed before send; the family itself is a default-off Event opt-in (settings.dailyEmailEnabled—no console control yet, #785)

Five Across · New event setup—the organizer wizard 🧪 Exploratory

Status: exploratory, not a parity target. Except for the explicitly proposed admin-console comparison frames, the rest of this document describes surfaces that ship, and downstream tickets implement against those frames. This one does not. Self-service Event creation is blocked on four pieces of platform work that do not exist (below), so these five frames are a design sketch of a flow nobody can build yet—read them for shape and intent, not as a specification to match pixel-for-pixel. They will drift as the platform moves, and that is expected. The durable output of designing this is #785, which extracts the hard contract facts any implementation must satisfy—the 24-minimum being per pool rather than per Event, spicy being main-pool only, a Day not being a calendar date, and the rest. Since these frames were drawn, that list has started becoming code: #786's first ticket landed specs/event-setup-wizard.md (accepted) plus the draft model (EventDraft, src/data/eventDraft.ts), the occasion matrix (src/data/occasions.ts—which mirrors Step 1's six rows verbatim, so their copy is now load-bearing), and the launch-gate predicates (src/data/draftValidation.ts). Where these frames and that spec disagree, the spec wins—it records each deviation instead of leaving it for a reader to spot. If you are about to build this, start with #785 and the spec; this section is the picture, they are the contract.

Everything required to create an event from scratch: occasion, name, dates, URL, squares, look, and invite—in five guided steps with a live preview, targeting the PRD's under-15-minutes goal. The wizard wears the Five Across host brand (ink, cream, grids, crisp type); the event under construction previews in its own edition skin, so the one-identity rule holds for organizers too: you build with Five Across, your players see Vacay Bingo (or the occasion's edition). Occasion selection picks the edition, starter pack, and defaults; the slug claim itself needs no DNS record, riding the wildcard namespaces with <slug>.fiveacross.app as the canonical address and—only when the occasion's Edition owns a distinct namespace—that Edition namespace (e.g. vacaybingo.com) as an alternate serving host. An Edition may own a second namespace; it does not have to, and for a Five Across-Edition occasion (wedding, conference, custom) fiveacross.app is already canonical and there is no alternate to claim. Self-service is blocked on platform work that does not exist yet. The list below is what is known, not a closed set—each round of review against the code has turned up another, so treat it as open and re-check before scheduling this. (1) Sign-in is not wildcard-capable. A hostname must be registered individually in Firebase Auth's authorized domains and as https://<host>/__/auth/handler on the Google OAuth web client—neither accepts a pattern—so a freshly claimed slug lands on an origin where isSignInReachableOnHost is false and the app renders auth-unconfigured. Writing routing documents in a transaction does not change that; only ADR 0010's centralised auth origin makes it wildcard-safe (today's handoff covers exactly one host). Until then, provisioning includes exact-host registration plus a redeploy, which is developer work. (2) There is no admission boundary. Current rules give path scoping, not membership isolation, so any signed-in account reaching the hostname can enter. A wizard whose final step hands out a QR would create ostensibly group-scoped Events that are not scoped at all. (3) Share and install identity are baked per bundle, not per host. index.html stamps og:title / og:image from the build-time Edition and the PWA manifest takes brand.appName the same way, so until the per-host edge work covers them a new Event's link unfurls with another Event's name and artwork, and a cross-Edition install inherits the wrong app name. Crawlers run no JavaScript, so runtime repair cannot reach the unfurl—this one outlives fixing auth and admission. (4) Nothing serves a new hostname yet. Today's Five Across deployment is a set of exact Firebase Hosting custom domains, one Event each; the shared multi-Event wildcard-router build is still future work (#545, see docs/app/deploy-targets.md). Writing the two Firestore hostname documents maps an address to an Event—it does not make that address route, terminate TLS, or serve the bundle. So "no DNS, no certificates, no waiting" is the end state the router buys, not today's. These are prerequisites, not caveats; Step 5 states them on the frame. Two model rules the frames hold to throughout: the creator is granted Admin (Host stays display metadata), and a Prompt's pool (main / easy / closing) is independent of its spicy flag, which is what the server-derived 18+ posture reads. A later section, Drafting with Claude, adds the credit-backed assists that reach into Steps 3 and 4; the dashed ✦ rows on those two frames are its entry points, and nothing else here changes for it.

✳ Five Across
✕ Cancel
New event
Save draft (local)
1Occasion2Basics3Squares4Look5Launch
What's the occasion?
The occasion sets the edition your players see, the starter square pack, and sensible defaults—every one of them changeable before launch.
Continue

Step 1 · Occasion—one choice sets smart defaultsInk-and-cream Five Across chrome: setup is a platform surface, run by an Admin. That word is load-bearing—Host is not the privileged actor. In this model a Host is player-facing social metadata with no permissions at all, so "the organizer" who creates an Event is authorized by an Admin grant, not by being named the Host; a Host who runs their own Event holds both. Gating setup by social identity would authorize the wrong thing. Selecting "Weekend away" quietly commits the player-facing edition (Vacay), the starter pack, and daily-card defaults—shown, not hidden, via the edition pill. Custom starts bare for tinkerers. "Save draft (local)" is labelled that way deliberately: there is no server-side draft today—EventDoc.status admits only active or archived, there is no draft collection, and a client cannot bootstrap its own Admin grant—so persisting a half-built Event server-side would either fail rules or publish a malformed one. Until a separately authorized draft model exists, the draft is device-local and the frames say so rather than implying a resumable server draft.

✳ Five Across
‹ Occasion
New event
Save draft (local)
✓Occasion2Basics3Squares4Look5Launch
Name & dates
Weekend in Point Reyes
Fri Aug 7 → Sun Aug 9 · America/Los_Angeles ▾ suggested
Your event's address
point-reyes✓ availablepoint-reyes.fiveacross.app · canonicalpoint-reyes.vacaybingo.com · Edition alternate
Marking
HonorProofAdmin OK
Audience
All ages18+ (sets forceAdult)
Daily email
OffEach morning
The address is generated from the name—edit it once, live-checked against reserved and taken slugs. Claiming it at launch registers the canonical address—plus the Edition alternate when the Edition owns one (Vacay does)—in one transaction; no DNS, no certificates, no waiting.
Live preview · updates as you buildOpen ›
Continue

Step 2 · Basics—the URL is a text field, not a ticketName auto-generates the slug; availability is checked live with reserved names blocked (format and the reserved list are #790's shared contract—the draft holds only a candidate, and the claim happens once, transactionally, at launch); both hostnames preview inline—canonical first, Edition alternate second—so the organizer sees exactly what the group will type and which address the platform will treat as primary. The alternate row is conditional: an Edition may own a second namespace, so it renders only when the Edition actually has one—Vacay does; a Five Across-Edition occasion shows the canonical alone (#785). The timezone is a control, not a caption: EventDoc.timezone is the zone the whole schedule is interpreted in and unlock and email times are formatted in, so the device zone is only ever a suggestion—committing it unasked provisions a destination Event hours off, the common case for a trip planned from home (#785). Region zones only: the read-side contract rewrites UTC, Etc/* and bare offsets (normalizeTimezone substitutes another zone), so the draft gate refuses those rather than launching a schedule that silently runs elsewhere. Daily email is asked here because setup is the only chance: settings.dailyEmailEnabled reads false unless explicitly true and no shipped Admin surface sets it (#785), so a flow that never asks creates an Event that can never send the daily engagement email without a direct Firestore write. Off is the stated default—the draft's settings block is Required, every value decided rather than left to a call-site fallback. Marking mode is here because EventDoc.claimMode is required and has three real values—honor, proof_required, admin_confirmed—so a wizard that never asks silently hard-codes Honor for every Event. Audience is a first-class basic because it picks which packs are offered, and it is half the verdict, not none of it: the derivation is settings.forceAdult || any active spicy main-pool Prompt, so selecting 18+ must persist forceAdult: true—otherwise an Event that is mature but not sexually explicit publishes adultContent: false and shows no gate at all. The other half runs the opposite way: choosing "All ages" and then adding an explicit Prompt in Step 3 raises the acknowledgement regardless. Step 5 shows the resolved posture with the reason, so neither half can be silently lost. The live-preview strip appears from here on, wearing the event's edition skin. The slug shown is deliberately an unclaimed one: bodega-bay already serves bodega-bay-2026 on both namespaces, so a creation frame using it could never show ✓ available—an illustrative example has to be a name the availability check would actually pass.

✳ Five Across
‹ Basics
New event
Save draft (local)
✓Occasion✓Basics3Squares4Look5Launch
Card format
One cardDaily cards · 4 Days
Maximum 10 Days in the wizard—the Firestore schedule lock checks indexes 0–9 one by one; a longer schedule is set up by script (#1357).
Squares
easyWindblown group selfie✎ ✕
mainWalk to a Chimney Rock viewpoint✎ ✕
mainOriginal suspense-movie still✎ ✕
closingSay the thing you'll actually miss✎ ✕
Add your own… ask a local for a favorite detourAdd
mainNew square · poolmain ▾🔞 spicyoff · main only
Days & pools
Fri · arrivaleasy counts ✓
Sat · main daymain counts ✓
Sun 06:00 · last full daymain counts ✓
Sun 11:00 · wrap-upclosing warm-up
Minimum 24 per assigned pool, checked separately—main 32 ✓, easy 28 ✓, closing 26 ✓. A total is not enough: a Day deals from its own pool alone. counts ✓ / warm-up is DayDef.tutorial, set per Day and independent of pool—it governs exclusion from Event-wide First-to-BINGO only. Whether a Day is ceremonial for standings is a separate set (ceremonialDayIndexSet, resolved from each Day's stated scoring under ADR 0011, with the closing-pool rule kept only as the read-time fallback for Days that state none), so the two must not be collapsed into one control. Every Prompt belongs to one pool (main, easy, closing) and main-pool Prompts carry a separate spicy flag; the final Day must be assigned the closing pool or the finale never runs—and only the final Day may carry it, because the finale resolves to the first closing Day it finds. The daily mix slider lives in Look. Players can suggest more during the event through your approval queue.
86 squares · deals 24 per dayOpen ›
Continue

Step 3 · Squares—pack first, personality secondThe pack seeds a working pool in one tap (min-24 check runs live against the deal guard); rows edit or delete inline; the add bar invites the organizer's own inside jokes. Daily-vs-one-card sits here because it decides how many squares you realistically need, and the wizard's 10-Day ceiling follows the rules: daysThemeLockOk in firestore.rules checks indexes 0–9 one by one, and a longer schedule must state its standings freeze at birth and change through the two-Day edit window (scheduleEditWindowOk, #1357), so it is seeded by script rather than built here. Fixed seed data has never exceeded ten; an arbitrary self-service date range easily would. Two model facts the wizard must not paper over. Pool is a three-way choice, not two: main, easy, and closing, and the closing pool belongs to a final Day. finaleTimes returns null when no Day carries that pool, so a wizard offering only easy/exploratory leaves the farewell Day either undealable or quietly assigned a main pool—no finale beats, no podium, no Most-Loved, and no standings freeze either. That last one runs through a second mechanism worth keeping straight: the finale beats are pool-anchored (finaleTimes finds the first closing Day), while the freeze is Scoring-Policy-anchored (standingsFreezeAtFor). The draft deliberately authors no scoring yet (ADR 0011's fields are deferred to #531), so a wizard-built Event resolves its policy through the legacy pool fallback—which is precisely why the closing-pool assignment still carries both today, and why it stops being sufficient the moment the draft learns to state scoring. Hence the explicit Days & pools assignment and the seeded closing Prompts. And a Day is not a calendar date: Bodega's Sunday is two Days—a competitive main-pool Day at 06:00 and a closing wrap-up at 11:00—so collapsing the last date into one closing Day would delete Sunday's competitive card and freeze standings at the wrong boundary. The rows are per Day, and two may share a date. And tutorial is its own required field, not a consequence of pool—the "counts ✓ / warm-up" chip. Bodega's easy-pool Friday is tutorial: false and only the closing wrap-up is true, so a provisioner that inferred tutorial status from easy/closing membership would wrongly exclude Friday's wins from Event-wide First-to-BINGO. Pool decides what a Day deals; tutorial decides whether its wins count. spicy is independent of pool, not a synonym for exploratory: it tracks sexual explicitness specifically, and the Event's 18+ posture is derived server-side from whether any active Prompt carries it. A custom Prompt added here therefore needs its own spicy control—defaulted off, as addItem does—because an organizer who picked "All ages" in Basics and then adds an explicit inside joke must still raise the public acknowledgement. But the control is main-pool only, and the row says so: adminAddItem forces spicy: false outside the main pool and the posture derivation ignores non-main pools, so a spicy toggle offered on an easy or closing Prompt would let an explicit square reach a card with no 18+ gate raised—the toggle would look honoured and be silently dropped. And the minimum is per pool, not per Event: a closing Day snapshots only its closing pool, and dealBoard rejects an unstratified pool below MIN_POOL (24), so a pack with 62 total but 4 closing yields a farewell card that cannot deal while every total-based check reports success. Each assigned pool is counted and gated on its own. Three more facts the built contract has since pinned down (specs/event-setup-wizard.md). Closing is exclusive to the finale: every finale consumer—client and server—resolves the farewell as the first closing Day, so a closing Day mid-schedule would freeze standings and post the podium days before the intended finale while a final-Day-only check still passed; the gate reports both Days by name. Prompt text is bounded 1–80 characters as persisted: firestore.rules applies text.size() to the stored value and the count gates never read text, so a pack padded with blank or over-long Prompts satisfies the 24-minimum and then fails at provisioning—text gets its own launch gate rather than riding the count. And the pack is a worked example, not a shipped asset: content ownership is open (#786 Decision 2), so every starterPackId in the occasion matrix is null until a pack is authored—the Coastal weekend pack here is a reference for shape and counts, not a promise that those 86 squares exist. The dashed ✦ row is the one addition since: it opens the brief sheet in Drafting with Claude (#frame-setup-assist-brief), which writes into a review list and never straight into a pool, so every count on this step keeps meaning what it means.

✳ Five Across
‹ Squares
New event
Save draft (local)
✓Occasion✓Basics✓Squares4Look5Launch
When each day opens
Fri · arrival06:00 ▾
Sat · main day06:00 ▾
Sun · last full day06:00 ▾
Sun · wrap-up (closing)11:00 ▾
All times in the Event timezone set in Basics (America/Los_Angeles), and each unlock must land on its Day's own calendar date in that zone—the scheduler reads the instant while schedule copy and the daily email read the date, so a mismatch opens a card on one day and labels it as another. Last call is derived, never typed: finaleTimes prefers adding 12h to the unlock of the Day immediately preceding the closing Day, but falls back to subtracting 12h from the closing Day's own unlock whenever that forward offset would land at-or-after the close (#784). Here the preceding Day is Sun 06:00, so the forward candidate (Sun 18:00) lands after the 11:00 closing unlock—so it derives backward instead: Sat 23:00, 12 hours before the close. Shown as the scheduler computes it. Defaults to 06:00 local—change any Day and this line recomputes.
Theme per day
Place & tonight, per day
Fri🌊 Point Reyes
Tonight: 🦀 Crab shack · 🔥 Fire pit
Sat🌅 Point Reyes
Tonight: 🎣 Dock walk · 🍷 Porch wine
Sun · last full day🌅 Point Reyes
Tonight: ☕ Last coffee · 🧳 The slow pack
Sun · wrap-up🌫️ The drive home
Tonight: 👋 Goodbyes · 🚗 The long way back
Place, its emoji, and exactly two Tonight entries are required per Day—they render on the card, the locked tease, the schedule and share copy, and only Tonight is editable in Admin afterwards.
Event default theme
Free space, per day
Fri: The flock has landed
Sat: Main character on the coast
Sun (last full day): We did it for the story
Sun (wrap-up): Take the long way home
Daily mix
Themes are picked from the Edition's registered Theme list—every one is contrast-audited, so any choice is safe. There is no custom-palette option. The free space is each day's motto—make it yours.
Sunday preview · light theme ✓Open ›
Continue

Step 4 · Look—emotion per day, contract underneathSwatch pairs make each day's palette legible at a glance; picking only ever swaps token sets, so contrast checks and mechanics are untouched. Only registered Themes are offered—there is deliberately no "Custom". Every `DayDef.theme` must be a `ThemeId` backed by `THEMES` metadata and a `themes.css` token block; there is no custom-theme value and no persisted custom-token shape, so a Custom option would give an implementation nothing valid to save and no contrast-audited palette to render. Free-space text per day is the cheapest personality lever an organizer has, so it gets first-class placement. The Daily mix slider is the same control as Admin · Game settings (identical .slwrap anatomy)—set here as a starting value, adjustable mid-event there. The unlock times are not a look choice; they are here because nothing else in the wizard sets them. Each Day's unlockAt is an absolute instant that drives snapshot publication, card availability, daily email timing and the finale beats—and a date range plus an auto-detected timezone does not determine it. The wizard's reviewed default is 06:00, not the old 08:00 default, which is exactly the kind of cadence an Event would otherwise launch wrong while the intro promises every default is changeable before launch. Bodega's seeded Friday is the deliberate exception: its unlockAt: 0 open sentinel is paired with a pre-stamped snapshot; Saturday and Sunday open at 06:00. Per-Day controls with a reviewed summary, rather than an invisible default. EventDoc.defaultTheme is collected separately because it is a required field independent of every DayDef.theme: it dresses Auto when no Day is current, so it is what a new player sees first and no amount of per-Day theming supplies it. Last call is shown but not editable, because it is derived: finaleTimes prefers taking the Day immediately before the closing Day and adding LAST_CALL_LEAD_MS (12h) — an offset after that unlock, not before it — but falls back to subtracting the same lead from the closing Day's own unlock whenever the forward offset would land at-or-after the close (#784). Bodega's tail is exactly that shape: two Days on one date (main 06:00, closing 11:00), so the forward candidate is Sunday's 06:00 + 12h = 18:00, after the 11:00 close—so it falls back to Sat 23:00, 12 hours before the closing Day's unlock (finaleTimes is pool-anchored and reads that unlock, not the configured freeze—here Bodega sets them to the same 11:00 instant). The 12h offset assumes a closing Day on its own calendar date; the fallback is what keeps a same-day wrap-up like this one from silently losing the beat. The frame prints what the scheduler actually computes, because a wireframe that quietly displayed a plausible-but-wrong time would hide a future regression from whoever implements this. Note also that the Daily mix applies to main-Day cards only: dealBoard stratifies just the main-pool path, so the arrival and closing Days deal from their own pools untouched by this slider. Place, its emoji and the Tonight pair are collected here because DayDef requires them—they render on the Day Card, the locked tease, the schedule, the leaderboard and share copy, and tonight takes exactly two entries. Only tonight has an Admin editor after creation and place has none, so a wizard that skipped them would force a provisioner to invent or blank player-facing data with no way to correct it—which the "every default is changeable before launch" promise cannot survive. Free space is per-Day because that is the only home it has: the deal reads day.freeText ?? FREE_TEXT, and FREE_TEXT is a build-time constant in Gay Cruise Bingo's own voice ("Complain about circuit music")—EventDoc has no per-Event field—so a one-card Event has no Day to override and would ship that voice verbatim. Giving self-served Events an Event-wide Free Space needs a new EventDoc field, recorded in the spec as outside the wizard's scope. The dashed ✦ row is the one addition since: it asks Claude for the Place, Tonight pair and Free Space of every Day as proposals with their own keep (Drafting with Claude, #frame-setup-assist-look); unlock times and Themes are deliberately not its business.

✳ Five Across
‹ Look
New event
✓Occasion✓Basics✓Squares✓Look5Launch
Ready when you are
✓ Weekend in Point Reyes · Aug 7–9 · America/Los_AngelesEdit
✓ point-reyes.fiveacross.app · canonical, claimed at launchEdit
✓ 86 squares · every pool ≥ 24 ✓Edit
✓ 4 Days scheduled · closing pool set ✓Edit
✓ Last call derives to Sat 23:00 — before the 11:00 closeEdit
✓ First unlock is still ahead (Fri 06:00) — requiredEdit
✓ 4 Days themed · places · tonight · free spaces ✓Edit
✓ Honor · camera or library · EXIF stripped · vision gate on · daily email off · you are AdminEdit
⚠︎ 18+ acknowledgement: on — forceAdult off, 4 spicy main PromptsReview
⚠︎ Create runs server-side (Admin SDK) — clients cannot claim hostnamesWhy
Launch is gated on platform work that does not exist yet. No wildcard router serves a new hostname (#545), so this address routes nowhere. Sign-in must be registered for this exact host (Firebase Auth + the Google OAuth client take no wildcard) or the page renders auth-unconfigured. Anyone signed in who reaches the address can join—the link is an address, not an invitation. And the share unfurl and installed app name still come from the bundle's Edition, not this Event.
Create event — blocked
Invite link and QR appear once creation is unblocked.
point-reyes.fiveacross.app
Copy linkShare invite

Step 5 · Launch—checklist, then the QR is the confettiEvery row is a verified gate (mirroring the POC launch-gate discipline) with an Edit escape hatch; Create is a trusted server-side provisioner, not a client transaction, and that is a rules fact rather than a preference: firestore.rules gates Event creation on isAdmin(eventId), which reads the Event document that does not exist yet, so a client cannot bootstrap its own first Admin grant; and hostnames/{host} denies create/update to every client including admins, because routing is global state no per-Event admin has authority over. A callable with platform-level authorization claims the canonical slug—and the Edition alternate, when the Edition owns one—atomically via the Admin SDK, seeds the Event, grants the creator Admin, and returns the invite QR + link + share. The checklist itself is now a real vocabulary, not a drawing: validateEventDraft (src/data/draftValidation.ts) returns issues rather than a boolean precisely so this screen can render each failure as its own row with its own Edit link—one organizer mistake, one row—and the settings the wizard draws no dedicated step control for—the photo-proof source, EXIF strip and vision gate behind this row's Edit, plus the spicy ratio and report-hide threshold—arrive committed from the occasion defaults, because the draft's settings block is Required: every value stated, nothing left to a call-site fallback. The creator is granted Admin on the new Event—that grant, not the Host field, is what authorizes every setup write; hostedBy stays player-facing display metadata (CONTEXT: “a Host is a social identity, not a permission”). The organizer lands in the familiar Admin hub afterward—setup ends where operations begin. Two rows are deliberately not what they were: there is no photo-enabled boolean in the Event contract—capture is always available, and the real knobs are photoProofSource, stripPhotoExif and visionGate—so the row names those rather than inviting a parallel setting no proof consumer reads. And the last-call row is the point even though it now passes (#784 gave `finaleTimes` a same-date fallback and a non-empty-window guard): it exists so "valid" is backed by an actual computed instant, not a rubber stamp—a schedule shape where the fallback still failed to land before the close would show up here, not slip through as an Event whose last call can never fire. Two rows are honesty, not decoration. The first-unlock row is a hard gate, not a nicety: every Prompt seeded at creation gets a createdAt, and activeSnapshotIds excludes Prompts created after a Day's cutoff—so launching after Friday's 06:00 has already passed permanently stamps an empty arrival snapshot. (The Bodega seed dodges exactly this with an unlockAt: 0 sentinel and a pre-stamped snapshot—but that pairing is Admin-SDK seed territory: no client can write the snapshot, so from the wizard the sentinel is refused under its own issue code as a provisioner capability request, not offered as an organizer choice. firstUnlockIssues says exactly that.) Launch from this flow therefore requires a first unlock still in the future, full stop. The 18+ row is derived server-side from the pool's spicy Prompts and is authoritative over the Step 2 audience choice, so it can contradict what the organizer picked—shown here rather than silently overriding. And the dashed warning carries the two real blockers, because a QR is worth nothing if either holds. Sign-in is per-exact-host, not wildcard: a hostname must be registered in Firebase Auth's authorized domains and as /__/auth/handler on the Google OAuth client, so a freshly claimed slug fails isSignInReachableOnHost and the app renders auth-unconfigured—an Event nobody can sign in to. Claiming the routing documents in a transaction does not help; ADR 0010's centralised origin is what makes this wildcard-safe, and today's handoff covers exactly one host. And there is no admission boundary: current rules give path scoping, not membership isolation, so any signed-in account that reaches the hostname is in whether invited or not. This flow stays blocked until both land—the frame draws the dependencies instead of pretending them away.

Five Across · Drafting with Claude—credit-backed assists inside the wizard 🧪 Exploratory

Status: exploratory, and a proposal rather than a plan—ticketed as #1958 under #786, with the proposed contract in specs/event-setup-assist.md (status: proposed). The wizard above is blocked on the platform work its own Step 5 lists; these four frames add nothing to that list and remove nothing from it. They exist because two facts changed at once. The occasion matrix still binds no starter pack—every starterPackId is null—and #786 Decision 2 (2026-10-02) made the owner the editorial gate for any pack that gets authored, with exactly one pack (Weekend away) plus Custom promised at launch. And the platform now holds a $200 Claude developer-credit grant that nothing spends. Put together: the squares an organizer needs can be written per Event, on request, in the Edition's own register, with the organizer approving every one—which is the PRD's own later opportunity, "AI-assisted prompt drafting with organizer approval" (PRD § Later opportunities), pulled forward because the pack problem it solves is the one standing between Step 3 and the under-15-minutes goal. The durable output is that ticket and that spec, which wins wherever it and these frames disagree; the frames stay the reference for shape and intent, exactly as the section above asks.

Three rules hold throughout, and each is a place the obvious build goes wrong. The organizer is the author; Claude is a very fast first draft. Nothing a model writes enters the draft until the organizer keeps it—row by row, or by an explicit "keep all remaining"—so the launch gate, the 18+ derivation and the per-pool counts all run over Prompts an organizer chose, exactly as they do over typed ones, and the Launch checklist needs no new row. The assist obeys the same contract as the hand. Every row Claude offers is checked by the predicates the wizard already uses before it is shown—promptTextIssues' 1–80 bound on the raw text, spicy representable only on main-pool entries, the duplicate advisory—so a draft that keeps all 88 rows is exactly as launchable as one typed in by hand, and no "AI pool" exists for the gate to miss. Five steps stay the ceiling. The brief lives in a sheet opened from Step 3, not a sixth step; the Day-copy assist lives inside Step 4's own rows. Adding a step for a thing the occasion can default is the regression the PRD names, and asking an organizer to describe their trip before they have picked an occasion would be exactly that. What Claude is not asked to do is as deliberate as what it is: not the slug (deterministic from the name), not the schedule shape (the matrix proposes it), not unlock times (a clock decision), not Themes (applyProposedDayThemes fills them from the matrix, and a model choosing among three registered palettes is theatre), not the marking mode or the audience (settings an organizer must state). The assists write words—squares, Place names, Tonight pairs, Free Space mottos—and only words.

The plumbing, stated once. The key never reaches a client: draftWithClaude is an onCall in functions/src/index.ts beside submitPrompt and approvePrompts, with ANTHROPIC_API_KEY a defineSecret in functions/src/params.ts exactly as RESEND_API_KEY is—which puts the whole thing under the Phase 4 protected path on day one. It requires a signed-in caller (the allowances are per account, and the organizer must be signed in to be granted Admin at launch anyway), takes the draft's occasion, Edition, name, dates, audience, card format, the Days with their pools, the per-pool targets, the brief and the Prompts already in each pool, and returns rows—it writes no Event document, because the draft is device-local and stays so (#786 Decision 1). The model is Claude Opus 5.5 (claude-opus-5-5, adaptive thinking at effort: 'low'—squares are not a hard reasoning task), answering against a JSON schema through output_config.format so a row is { pool, text, spicy } with spicy permitted only when pool is main: the schema says what the type says, within the API's schema subset—structured outputs reject string-length constraints and array bounds, so the 80-character bound is stated in the prompt and enforced by the server and client validators, and the Tonight pair is two required fields the handler maps to the pair. The fixed system block (the register rules, the pool definitions, the format) carries cache_control so repeat drafts pay for it once; the volatile part (the brief, the existing Prompts) comes after it. The response streams: the callable parses rows out of the array as they complete and forwards each with sendChunk, which is what lets the review sheet fill in rather than spin, and a Stop from the sheet aborts the upstream stream so tokens stop being billed. fallbacks: 'default' is on, so a classifier decline is re-run on a fallback model inside the same call and only a whole-chain refusal reaches the organizer. The voice rules are a prompt file under functions/src/prompts/, which REVIEW_POLICY.md's detection for prompt-design changes (**/prompts/**) already routes to full review—so the editorial gate Decision 2 gave the owner over packs lands on the system prompt, once, rather than on every Event's squares. The budget, in numbers. A full 88-square draft is roughly 3k input and 4k output tokens—about $0.09 at Opus 5.5's $4 / $20 per million; a top-up for one pool about $0.04; the four-Day copy pass about $0.03; a spicy read on one typed square well under a cent. An Event that drafts once, tops up twice and fills its Days costs about $0.25–0.40, so the grant covers on the order of five hundred Events before caching helps—orders of magnitude beyond what the wizard will see. The constraint is therefore abuse, not price, and three caps sit in front of the key: a per-account daily allowance (12 drafts, returned on every response as remaining so the sheet can print it), a platform monthly ceiling kept as a server-only ledger (aiUsage/{yyyy-mm}, summed from every usage.iterations entry priced by the model that ran it—primary and fallback attempts alike, an unknown model over-counting at the highest rate—against the price table, with firestore.rules denying every client read and write), and a dedicated Console workspace for the Five Across key with its own spend limit, so a bug in the ledger cannot drain the grant. Every call records ai_draft_requested / ai_draft_kept through the one track seam (src/analytics.ts, #96) with counts only—never the brief, never a square.

✳ Five Across
‹ Squares
Draft squares with Claude
What Claude already knows
🏝 Weekend awayVacay voice · trip registerWeekend in Point ReyesAug 7–9All agesHonor marking4 Days · easy → main → main → closing4 squares already yours
Tell it about the group
Eight of us, college friends, second summer doing this. Two dogs. Someone always forgets the firewood. Dana will swim no matter the weather.
Inside jokes make the best squares. First names are fine—the brief and your squares go to Claude through Five Across's own server, which keeps a count and not a copy; Anthropic handles them under its API terms and may keep them for a limited time.
Keep it
GentlePlayfulUnhinged
How many
main32 to write2 there · 24 needed
easy28 to write1 there · 24 needed
closing28 to write1 there · 24 needed
🔞 spicySpicy squaresoff · All ages, set in Basics
Each pool lands above 24 with room to cut. Counted per pool—a total is not enough, because a Day deals from its own pool alone.
9 of 12 drafts left today · needs a connection
Write 88 squaresNot now

The brief—one sheet, not a sixth stepOpened from the ✦ row on #frame-setup-squares; a sheet in the AdminSheet lineage rather than a wizard step, so the five-step ceiling holds. The top band is the point: by Step 3 the draft already carries almost everything a good draft needs—the occasion and the Edition it bound (EventDraft.occasion / edition, which select the register: Vacay's EditionLexicon says trip, stop, the whole group), the name, the dates, the audience, the card format and the Day list with each Day's pool—so the sheet shows what is already known and asks only for the one thing no field holds: who these people are. The brief is optional; an empty one still writes a competent coastal weekend, a full one writes this coastal weekend. Tone is a register knob, not a content knob: Gentle / Playful / Unhinged shape voice and dare level, and none of them means sexual—that is spicy, and it is governed by the audience the organizer set in Basics. With "All ages" the request forbids sexual content outright and the row says so in Basics' own words; with 18+ the row becomes a control offering a share of spicy main-pool squares, and the sheet never claims the gate stays off either way, because the posture is derived server-side from the flags (ADR 0012) and Step 5 shows the resolved result. "How many" is per pool because the gate is per pool (#785): targets default to a few above MIN_POOL so the organizer can drop rows without dipping under, are capped at 40 per pool per draft, and read the current count from the same countPrompts the launch gate uses—2 there, 24 needed—so the sheet cannot promise a pool is fine that the gate will fail. A pool no Day deals from is not offered (closing on a one-card Event, for instance), the same idle state Step 3's counter shows. The allowance line is the server's number, not the device's: a device-local draft id is a trivial thing to reset, so the cap is per signed-in account per day and comes back first thing on every streamed run (an admission chunk, before any row) and again on every response; the sheet prints it rather than counting for itself, so a stopped run still updated it. Offline, Write is disabled with the reason—every other part of the wizard works without signal, and this one honest exception says so. The privacy sentence is on the sheet rather than in a policy page because a first name in a brief is personal data leaving the device: it travels to Five Across's callable and on to Anthropic's API under Five Across's key and that API's commercial data terms, and the callable keeps no copy—what it keeps is a count. Whether the brief itself persists in the draft across a reload is an open choice: EventDraft has no field for it, so keeping it means a DRAFT_SCHEMA_VERSION bump (#787's lever); v1 can lose it on reload at the cost of retyping a sentence.

✳ Five Across
‹ Brief
Draft squares with Claude
Done · 41 kept
Writing… 54 of 88 · rows land as they're written
main · 26 kept · 24 needed ✓
mainDana swims anyway✓ kept
mainFirewood run, round two✓ kept
mainGroup selfie in the windnear your "Windblown group selfie"✕ dropped
mainDana "just checks" the tide app✎ edited from "Someone 'just checks' the tide app"✓ kept
mainDog steals a sandwich✓   ✕
mainRealize nobody packed a corkscrew✓   ✕
mainElk sighting, allegedly✓   ✕
easy · 15 kept · 24 needed · still writing
easyTouch the Pacific✓ kept
easyWalk both dogs on the beach✓   ✕
easyBuy the firewood this time✓   ✕
easy…
closing · waiting
closing…
1 skipped · over 80 characters. Nothing lands in your draft until you keep it.
Keep all remainingStop writing

Review—the keep is the authorship actRows arrive as Claude writes them and sit undecided until the organizer taps ✓ or ✕. A ✓ commits that one row through addPrompt the moment it is tapped—so a reload mid-review loses nothing kept—and every row therefore passes the same trim, the same 80-character refusal and the same main-only spicy drop a typed square does; there is no bulk path that could skip them. Done closes the sheet with the running count. The per-pool heading is the gate's own number. "main · 26 kept · 24 needed ✓" is countPrompts over the pool as it stands, the organizer's own earlier squares included, so the moment a pool clears its minimum the heading says so and the organizer can stop reading that pool; "still writing" and "waiting" are honest about what has not arrived rather than drawing empty rows as if they were content. Three rows are drawn in states the build has to handle. A dropped row stays visible, struck through, because the organizer may change their mind and because a vanished row is indistinguishable from one Claude never wrote. The near-duplicate sub-line comes from the client comparing against the existing pool and the kept rows (the exact-match form is duplicatePromptTexts, case- and space-insensitive; the request also carries the existing texts so Claude is told to steer clear), and it is advisory exactly as the spec makes duplicates advisory—a repeat breaks no contract, so keeping one is allowed. The edited row shows the organizer's rewrite with Claude's original beneath it: editing before keeping is the common case for a square that is almost right, and the kept text—re-checked against the same 80-character bound before it does—is what enters the draft, not the suggestion. "Keep all remaining" exists because reading 88 rows one by one is the fifteen-minute goal's enemy, and it is explicit rather than the default—the organizer still presses it. "Stop writing" closes the stream and keeps what is there; partial results are fine because each pool's count stands on its own, and the sheet does not fill the gap with rows it did not get. The skipped line counts rows the client refused before showing them (over 80 characters as persisted, blank after trim, a spicy on a curated pool), which the schema makes rare but the client checks anyway, because a response is data. Kept rows become ordinary { text, spicy } entries, indistinguishable afterwards from typed ones: the draft carries no per-Prompt provenance, and the spec records that adding it is a DraftMainPrompt change behind a DRAFT_SCHEMA_VERSION bump owned by #787. v1 deliberately keeps none—the organizer's keep is the authorship, so there is nothing a provenance flag would entitle anyone to do differently, and the Launch checklist needs no "written by Claude" row for the same reason the 18+ row needs none: it derives from the flags, whoever set them.

✳ Five Across
‹ Basics
New event
Save draft (local)
✓Occasion✓Basics3Squares4Look5Launch
Card format
One cardDaily cards · 4 Days
Squares
easyWindblown group selfie✎ ✕
mainDana swims anyway✎ ✕
mainWalk to a Chimney Rock viewpoint✎ ✕
closingLeave with sand in the car✎ ✕
Skinny-dip at Drakes BeachAdd
mainNew square · poolmain ▾🔞 spicyoff
✦ Reads as 18+. Flag it spicy? That turns on the 18+ acknowledgement for everyone who joins.Flag it Keep it off
Days & pools
Fri · arrivaleasy counts ✓
Sat · main daymain counts ✓
Sun 06:00 · last full daymain counts ✓
Sun 11:00 · wrap-upclosing warm-up
83 squares · deals 24 per dayOpen ›
Continue

Step 3 after the keep—the pack row is now the organizer's own79 rows kept, 4 typed, every pool above 24, and the row that used to name a starter pack names the organizer's squares with the same three independent verdicts as before—nothing about Step 3's counting changed, which is the point. Drafting appends; seeding replaces. seedPack swaps every pool for the pack and says so before the tap, because a pack is a whole; a draft is a set of rows the organizer chose one by one, so kept rows join the pools that exist and a second draft never deletes a first. That is also why the ✦ row survives. "More like these" sends the kept rows back as examples (newest first, up to 120—the most one full draft can keep), so the second batch is written to the organizer's demonstrated taste rather than the brief alone; "Top up one pool" names a pool, because the shortfall the gate reports is per pool and a draft that wrote 88 across three pools to fix a shortage of six closing squares would spend the allowance badly; "A different angle" asks for the opposite register—quiet where the first was loud—for an organizer who kept too little to know what they want yet. All three share one allowance. The spicy read is the smallest assist and the most careful. The organizer typed a square the audience setting says should not exist; the callable's spicy-check task reads one main-pool text and answers a boolean with a one-line reason—or no verdict at all when it stops short or is declined, in which case the bar stays silent and the square stands as added—and the row turns a verdict into a question, never a change. It never runs before a notice the organizer has seen: the first main-pool add on a draft shows a one-time note on the add bar naming Five Across and Anthropic, with OK and "Not for this draft", and the square is added either way. It runs only for a main-pool add, because spicy is unrepresentable on the curated pools (DraftCuratedPrompt.spicy?: never) and a verdict there would be a toggle that looks honoured and is silently dropped (#785). "Flag it" sets the flag through setMainPromptSpicy, exactly as the organizer's own tap would; "Keep it off" adds the square unflagged, which is the organizer's right and the derivation's problem—the acknowledgement is theirs to under-state, as it already is by hand. The question says what the flag costs in the derivation's own terms, because an organizer who picked All ages in Basics is about to learn that the choice was half the verdict (ADR 0012). It costs well under a cent and runs on the same model at the same low effort for now; measured against a few hundred typed squares it is the one task here a cheaper model could carry without anyone noticing, and that is a measurement to make, not a default to assume.

✳ Five Across
‹ Squares
New event
Save draft (local)
✓Occasion✓Basics✓Squares4Look5Launch
Place & tonight, per day
Fri · arrival🌊 Point Reyes ✓ keep
Tonight: 🔥 Firewood run (someone forgot) · 🍲 First-night chili
Free space: The flock has landed
Sat · main day🌅 Point Reyes ✓ keep
Tonight: 🐕 Dog beach at dusk · 🎲 Board-game grudge match
Free space: Main character on the coast
Sun · last full day🌅 Point Reyes ✎ change
Tonight: ☕ Last porch coffee · 🏊 Dana's farewell swim|
Free space: We did it for the story
Sun · wrap-up🌫️ The drive home ✓ keep
Tonight: 👋 Goodbyes · 🚗 The long way back
Free space: Take the long way home
Place, its emoji and exactly two Tonight entries per Day—written in the trip register from your kept squares; the schema cannot return one or three. Unlock times and Themes are not suggested.
Theme per day
Sunday preview · light theme ✓Open ›
Continue

Step 4—Day copy with a keep, instead of four blank fieldsDayDef requires place, placeEmoji and exactly two tonight entries per Day, and after creation only tonight has an Admin editor—place has none (#785)—so a wizard that lets an organizer skip them is one that invents or blanks player-facing text with no way back. The ✦ row asks for them instead: one call per schedule, carrying the kept squares, the brief (held in wizard-session state, so it is still there in Step 4 and gone after a reload), the Days with their pools and dates, and the Edition register, answering against a schema that models the Tonight pair as two required fields (the API's structured-output schema subset has no array bounds)—so the "exactly two" rule is a schema fact the client re-checks, not a hope. Each Day renders Claude's Place, emoji, Tonight pair and Free Space as a proposal with its own keep, because the organizer is still the author; "change" opens the field with the suggestion as the starting text (Sunday's second Tonight is being retyped to the swim the brief promised), and every keep commits through the Look transforms the step already has—setDayPlace, setDayPlaceEmoji, setDayTonight, setDayFreeText—so a kept value is stored as typed and judged trimmed exactly as a hand-entered one. What is deliberately not suggested. Unlock times: a clock decision with a reviewed 06:00 default and a zone the organizer chose in Basics, and nothing a model knows improves it. Themes: applyProposedDayThemes already fills every unthemed Day from the occasion's dayThemes, the list is three registered palettes long per Edition, and a model picking among three contrast-audited token sets would be theatre dressed as help—the rows below show the matrix's own proposal, unchanged. The Free Space is the exception that proves it: it is copy, each Day's motto, and the cheapest personality lever the organizer has, so it is written with the rest. Because it forwards the typed squares, an organizer who never opened the brief sheet sees the same one-time note here first, and nothing is sent until OK. The call is small—four Days of short strings, about $0.03—and shares the day's allowance with the squares; a one-card Event has no Days, so the row does not render, and a Custom draft that reaches Look with no Days gets dayCountIssues' "Add a Day" first, as it does today.

States, refusals and caps—the annotation table

Every state the four frames imply but do not draw, in one table—the same honest form the utility section uses for its per-brand deltas. A row is a contract: what the organizer sees, what the system did, and why that is the behaviour rather than its obvious alternative.

StateThe organizer seesWhat happenedWhy this, not the obvious thing
Signed outThe ✦ row reads "Sign in to draft with Claude"; the add bar works as beforeThe callable requires request.auth; allowances are per accountA device-local draft id is free to mint; an account is the only thing worth metering, and the organizer must be signed in before Launch anyway
OfflineWrite / Draft disabled, "needs a connection"No call is madeEverything else in the wizard is device-local and works in a dead zone; this one honest exception says so instead of spinning
WritingRows land as written; per-pool "kept · needed" ticks; Stop is availableStreamed chunks, one validated row each; Stop—and Done, Escape or closing the sheet while writing—aborts the upstream streamA twenty-second spinner for 88 rows reads as broken; rows arriving reads as working, and lets the organizer start keeping at row one
Partial"Claude wrote 21 of 28 closing squares" · Top up offeredstop_reason was max_tokens, or the stream ended shortEach pool's count stands on its own; the sheet never pads a pool with rows it did not receive
Declined"Claude didn't write these. Try a different brief, or add your own."; if rows had arrived, undecided rows are withdrawn and the copy adds "The rows you kept are in your squares."stop_reason: 'refusal' after fallbacks: 'default' also declinedA classifier decline is retried server-side inside the same call; only a whole-chain refusal is shown, once, with no automatic retry loop spending the allowance; a kept row is the organizer's, a withdrawn one never was, and the API's own guidance for a declined partial is to discard it, since the classifier may have fired on exactly those rows
Unreachable"Couldn't reach Claude. Nothing changed—try again. That one didn't count."Callable unavailable / deadline-exceeded, or the 90 s first-row timer, before any row arrived (the admission chunk may have)Fail closed and say so: no row was shown, so none was kept and there is nothing to undo; the draft unit is refunded because nothing was delivered
Request refused"Claude couldn't take this one. Nothing changed—try again later, or add squares by hand."; for a spicy check, nothing at allunauthenticated on a session the client thought was signed in, failed-precondition, invalid-argument, or internal before any row arrived (after one, it is Interrupted); the code is logged, never shownNone of these is something an organizer can act on beyond trying later, so one honest generic row beats four technical ones; the first three charged nothing, internal refunds by the nothing-delivered rule
Interrupted"Claude stopped partway. What you kept is in your draft." · per-pool counts stand · Top up offeredThe connection dropped, the handler ran out of time or failed, or the client timed out, after rows had arrivedKeeps commit through addPrompt the moment they are tapped, so the sheet must not claim nothing changed; a retry is a top-up that appends, never a replay of what was kept; the unit is not refunded
Allowance spent"12 of 12 drafts used today—back tomorrow"; the ✦ row stays, disabled until the next UTC midnight, when it re-enables and the next server answer is authoritativePer-account daily cap, enforced server-side, resource-exhaustedThe number on the sheet is always the server's remaining, never a client count; the cap is generous for an organizer and useless to a scraper
First sendA one-time note naming Five Across and Anthropic on whichever surface first sends typed text—the add bar before a spicy check, or the Step 4 ✦ row before Day copy—with "OK" and "Not for this draft"; a square being added is added either wayNothing has been sent for this draft from outside the brief sheet yet; the call runs only after OK, and "Not for this draft" switches that assist off for the draftThe brief sheet's disclosure is inside a sheet the organizer may never open, and typed text must not leave the device before a notice the organizer has actually seen
Checks spentThe add bar adds the square as usual and the spicy question stops for the day; one quiet note the first time, "Claude's spicy check is resting until tomorrow—flag squares by hand"; the ✦ drafting rows are unaffectedresource-exhausted with reason: 'spicy-checks' after the day's 120 checksA spent check cap says nothing about the draft allowance, so it must not disable drafting or print "12 of 12"; and a silent stop would hide that the assist is gone, so it says so once
Platform ceiling"Drafting is resting until next month—add squares by hand"; the ✦ row stays, disabled until the next UTC month boundary, when it re-enables and the next server answer is authoritativeThe monthly ledger aiUsage/{yyyy-mm} crossed its dollar ceilingThe grant is finite and shared; a ceiling in the ledger plus a spend limit on the Console workspace means one bug cannot drain it
All ages, spicy returnedThe row carries 🔞; keeping it says "turns on the 18+ acknowledgement"The request forbade it; the schema still allows the flag; the client shows what came backThe posture is derived from the flags, whoever set them (ADR 0012); hiding the flag would be the one way to get an explicit square onto an All-ages card
Near-duplicateSub-line "near your '…'"; keep still allowedClient compare against existing + kept rows; the exact form is duplicatePromptTextsAdvisory, as the spec makes duplicates advisory: a repeat breaks no contract and can be deliberate on a long schedule
Skipped"1 skipped · over 80 characters", "3 skipped · 2 over 80 characters, 1 blank"The server reports the rows it dropped by reason and the client adds the rows it refused before showing them under the same reasons: over 80 as persisted, blank after trim, spicy on a curated pool, an unassigned pool, a tonight not of length two, a bad emojiA response is data; the schema makes these rare and the client checks anyway, with the same predicates the launch gate uses; the line names a cause only because the counts carry one
Brief privacyOne sentence on the sheet, where the text is typedThe brief and the draft's existing square texts are sent to the callable and forwarded to the API; Five Across stores nothing, Anthropic retains them under its API terms for a limited time; analytics carry counts onlyA first name in a brief is personal data leaving the device; the sentence sits beside the field, not behind a link
Reload mid-draftKept rows are in the draft; undecided rows are gone; the brief is gone with the sessionKeeps commit through addPrompt immediately; the stream is not resumablePersisting undecided suggestions would need draft fields that do not exist; losing a half-read list costs one re-draft, losing kept rows would cost trust