Dave: one Yumina account, one readable scene
Design contract
The player is visiting an unpredictable neighbor during a lawn-defense game. The emotional loop is curiosity → conversation or a concrete gesture → Dave's reaction → return to defending. Connection administration is not part of that loop.
Palette: paper #FFF7DB, ink #303126, leaf #435437, sun #EBC66A, weathered stone #626884, shadow #20281D. Existing native art supplies texture and character; these colors support it.
Type: Dave's conversational handwriting, 20 logical px; Simplified Chinese 18 px in the existing CJK stack. Controls use Trebuchet/YaHei at 16 logical px. Platform controls keep their actual component styles and scale with the scene. Minimum physical target 44 px; readable physical text on phone landscape.
Composition (800 × 600 lawn):
seed bank Back to lawn
[DAVE] CRAZY DAVE
animated / brief speech, 2–4 lines \
native /______________________________\
portrait Your reply… Send
[Yumina model · Mushies] [book]
[sun gift] [bonk] [visits]
native tin when relevant visible lawnThe paper bubble only exists when Dave has words. Pending responses use a restrained animated ellipsis in its place. Errors explain the recoverable problem at the composer, without opening a setup panel. AI provider/model selection belongs to the existing Yumina modal. Notebook contains relationship/memory; a compact visits setting contains only the player preference. No duplicated model or API setup buttons.
Reference critique: Pentiment's character typography and Hades's separation of portrait, speaker and dialogue inform hierarchy, not borrowed artwork. The old design copied a web form into a scaled game: fixed physical iframe text alongside huge logical text was intrinsically inconsistent. Scale the compact iframe and its tools together; expand the model modal at normal viewport scale.
Account contract
Read the signed-in account's saved provider and model. Official requests use the existing official-model access rules, credit pricing and hashed ledger. Private requests use the existing private connection. Include provider intent on each request; reject provider/account changes rather than silently changing the payer. Legacy requests without provider intent remain private-only.
Refresh the pill balance after successful generations. No charge for cached refusals, failed/invalid replies, silent background decisions or cancelled turns. Record upstream usage for diagnosis. Official generations must pass the account's plan and budget checks before contacting a provider.
Verification
Exercise real game + actual React selector using official accounts with Mushies and no private key, private accounts, no-key private mode, provider switch, zero balance, session expiry, API failure, and pending model changes. Inspect desktop, 4K, phone landscape, Chinese and Spanish screenshots. Fixture testing must be explicitly distinguished from real paid provider validation.
