What changed, and why
The opening objective screen is the first thing a new, signed-out visitor sees. It was quietly telling them the wrong thing: that they had to sign in to play.
The culprit was a block titled "Sign in for the full archive" — a bold heading over two full-width Google/Discord buttons — sitting between the list of objectives and the Begin button. Visually it looked like a step you had to clear. It isn't. Anonymous players get three starter objectives (listStarterObjectives) and can play them with no account at all; signing in only widens the slate and unlocks AI compose. The one real gate is server-side, in server/api/objective.get.ts — never this screen.
Three small moves fix it, plus one shared CSS cap that had been making every sign-in button in the app stretch edge-to-edge. Nothing about the signed-in briefing (full slate, steer dials, compose) changes.
The gate that wasn't
Two edits to the anonymous briefing. First, the subtitle now says the quiet part out loud — you can start right now, no account. Second, the sign-in nudge moves out from between the list and Begin down to below Begin, so the choose → Begin flow is unbroken and sign-in reads as an optional footer.
The nudge itself is reframed to match. The bold ew-fg heading becomes a quiet ew-label eyebrow (the same 11px uppercase used by the steer fieldset's legend), and the copy leads with reassurance — "The three above are yours to play right now" — before the upsell. It now sits exactly where the steer dials sit for a signed-in player: a secondary, optional row, not a barrier.
The anonymous subtitle, and the relocated + reframed nudge (now after the Begin action).
components/MissionSelect.vue · 507 lines
⋯ 81 lines hidden (lines 1–81)
⋯ 172 lines hidden (lines 91–262)
⋯ 226 lines hidden (lines 282–507)
Sign-in buttons at a real width
SignInForm is shared across four surfaces: the objective briefing, the run-packs modal, the balance popover, and settings. Its buttons were width: 100%, so in any wide host they stretched the full container width — off-brand for provider buttons, and part of what made the nudge feel like a mandatory banner.
The fix is one rule: cap the form column at 22rem. The buttons keep width: 100% and simply fill that capped column, so they render at a standard sign-in width everywhere. Because it's a max, a narrow host like the balance popover still fills naturally.
The class hook on the root, and the single capping rule that the width:100% buttons fill.
components/SignInForm.vue · 280 lines
⋯ 179 lines hidden (lines 4–182)
⋯ 81 lines hidden (lines 200–280)
Pinning the intent
The corrected order is the whole point, so a test pins it. It mounts the anonymous briefing and asserts the sign-in nudge appears after the Begin button in document order, and that the "no account needed" reassurance is present. This fails on the pre-fix layout, where the nudge rendered before the actions row — so a future refactor can't silently slide it back into a gate.
Document-order + reassurance assertions — a regression guard, not coverage padding.
tests/unit/components/MissionSelect.spec.ts · 489 lines
⋯ 71 lines hidden (lines 1–71)
⋯ 401 lines hidden (lines 89–489)
Result
Driven in the real app across 375–1280, light and dark. The three starters are plainly playable now; Begin follows the list directly and lights terracotta once an objective is chosen; the sign-in footer is quiet and its buttons are a normal width.