Phase 2 · States gallery

Apply for studio access.

The public side of the beta studio gate: the entry CTA and every state of the request modal it opens. Studio access is a platform-level flag Toko admins grant to an existing account — no account is ever created from this form, and account creation itself is never gated (R58). The admin side lives in admin-studio-access-states-gallery-2026-06-30.html.

01Entry CTA — by account stateThe button that opens the modal, in each state an account can be in. The label is Apply for studio access — never "become a creator", because Creator now means the per-project role and nothing else. A pending or granted account never sees the apply CTA again, so nobody can file a second request by accident.
CTA states — reference, not a screen
Signed out

Opens the modal straight away. Signing in isn't required to apply — the form collects a Toko User ID only if the person already has one.

Signed in · no access

Same CTA. The modal pre-fills the signed-in account's User ID and hides the "if you don't have an account" hint.

Request pending Not a V1 state

There is no pending state in V1. The intake is a Google Form whose responses land in a Sheet outside the backend, so the platform cannot know an application exists — backend states are NeverGranted, Active and Revoked only. Signed-in-no-access shows the ordinary Apply CTA, and a duplicate application is a cheaper failure than a wrongly hidden one. A real pending state needs native intake or an explicit admin import.

Has studio access Studio access

The gate is passed, so the CTA becomes the destination. This is the only state where the apply modal is unreachable.

02Modal — first open (empty)Canonical Simple Modal Base: Anton title + close ✕ in a bordered header, lede and fields in the body, footer row with ghost Cancel + primary action. Nothing else renders around it — the grey is just the page behind the overlay. Every field is empty; no validation has run yet, so nothing is marked red on open.
03Modal — filled and readyThe same modal completed by a signed-in applicant. The User ID is pre-filled from the session and the "if you don't have one" hint is replaced by confirmation of which account access would land on — the single most common support question, answered before it's asked.
04Modal — validation on sendValidation runs on Send, not while typing, so the form never scolds someone mid-sentence. Errors sit on the field they belong to — never in a banner — and focus jumps to the first one. Required: name, email, and what you plan to launch. The User ID is optional, but a malformed one is caught here rather than failing silently in review.
05Modal — sendingWhile the request is in flight the fields lock and the primary button becomes a spinner, so nobody double-submits into two rows of the review sheet. Cancel stays live — it abandons the send and closes; the ✕ is removed for the duration so a stray click can't leave the person unsure whether it went.
06Modal — application sentThe confirmation replaces the form in the same modal rather than opening a second one. One action only — Done (or ✕) — matching the admin tool's grant-success modal; there is no "apply again". It sets expectations plainly: reviewed in waves, reply by email, and access lands on the existing account rather than arriving as a new login.
07Modal — couldn’t sendThe send failed in transit. Everything typed is kept and re-editable — losing a long answer to a dropped connection is the worst outcome this form has. The primary action becomes Try again, with a plain-text fallback address so a determined applicant is never fully blocked by our own outage.
Implementation note — not part of the page

V1 backing: this form can POST straight to a Google Form (each field maps to a Forms question via its entry.NNN id), so responses land in a Sheet for the team with zero backend work. The same fields translate 1:1 if we later swap to a native endpoint. A cross-origin Forms POST gives no readable response, so frame 06 fires on request completion and frame 07 covers a genuine network failure only.

The has access CTA state in 01 reads the account's entitlement, so it is derivable; until that value is exposed to the client, ship the signed-out CTA everywhere — an extra duplicate application is a cheaper failure than a wrongly hidden one. Pending is not derivable and is not a V1 state at all (see 01). Note also that platform Super Admins and Admins bypass the gate without a grant record, so a staff account lands in has access without ever appearing in the access list.

Review flow: the team checks responses, then grants studio access to the applicant’s existing account via the internal admin tool (account lookup by User ID / principal — see admin-studio-access-states-gallery-2026-06-30.html). No accounts are created from this form.