Welcome subtitle now caps its font scale so the widest line fits VIRTUAL_WIDTH
instead of a centered 1.18x label spilling off both edges on web/phone portrait.
GWT dist from game main + TutorialScreen fit-to-width fix.
GWT dist from game main 3cde104 — the platform/commerce reconcile with the
platform.* transport excluded from the web compile (Main.gwt.xml). WebBillingManager
now drives premium from window.SUCH_APP.premium; checkout remains fail-closed/inert
until Operations populates app-config.js. Code-only change (permutation swap +
bootstrap); real game assets unchanged, and the 252MB tile_packs DLC that leaked
into a local build was kept out (packs come from the CDN, never the payload).
- app-config.js: public config placeholder (all null/false -> INERT). Operations
populates OIDC client + shop tenant + checkout URL at deploy; no secrets.
- checkout.js: Authorization Code + S256 PKCE (public client, no secret), state CSRF
guard, token in sessionStorage, code/state scrubbed from URL. Resolves premium via
the ledger's per-user /me/entitlements (user's own OIDC token, never the shared
read token) and sets window.SUCH_APP.premium for WebBillingManager. Redemption also
resolves on page reload / next login (crypto is webhook-driven).
- index.html: load config+checkout in <head>; CTA calls SUCH_APP_startCheckout, else
falls through to the store links (fail-closed). Store/itch buttons unchanged.
Patch over v1.3.0. User-facing fix is the HighScores crash on Android
that hit users when MODE_OPTIONS grew to 5 but the screen's local arrays
stayed at length 4. The web build itself wasn't affected by that crash
but rebuilds anyway to pick up: bounds-clamping on stored prefs indexes,
the BackgroundRunner abstraction that restored html:dist after months of
silent breakage (Thread/Runtime/String.format calls had crept into
shared core), and the GwtAdManager dead-method cleanup.