e095650944
Address the Copilot review on #26. #1 The game_start / art_style_select payload fields were typed as bare `string`, so free text could still slip through despite the "content-free by construction" claim. Add lib/options.ts as the single source of truth for the selector option sets (`as const` → literal-union types), have the home OPTS render from those arrays, and type the analytics fields from the derived unions (gender/art_style/plot_style/pacing/style) plus a template type for `card`. Free text now fails to compile; no casts at call sites. #2 The /play heartbeat scheduled its 30s interval unconditionally. Gate the effect on the same NEXT_PUBLIC_UMAMI_* env used for script injection, so nothing is scheduled when the tracker is off (visibility check kept — a hidden tab still never emits). #3 choice_select no longer emits a -1 choice_index: skip the event when the index can't be resolved instead of polluting the index distribution. Verified with tsc (exit 0) and a throwaway negative test: free text in any of the six fields raises TS2322, valid enum/template values compile. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>