feat: expansion coming-soon preview with save-safe display data

Add an expansion preview system so the Goddess and Vampire panels render
their full content (zones, bosses, thralls, achievements, etc.) even when the
expansion has not been unlocked, with all interactive elements visually
disabled.

- API /load now returns expansionPreview alongside game state, populated from
  initialGoddessState() and initialVampireState() — never part of the saved blob
- LoadResponse type updated with expansionPreview field
- gameContext exposes goddessPreview and vampirePreview, stored in separate
  state vars that never touch stateReference so saves are never polluted
- gameLayout applies expansion-preview CSS class when viewing a locked expansion
  with preview data available, and shows the coming-soon banner
- All 22 expansion panels updated to use state.vampire ?? vampirePreview and
  state.goddess ?? goddessPreview for display
- CSS disables all buttons/inputs/selects inside .expansion-preview
- apotheosis service patched to never auto-initialise goddess state — expansion
  remains locked until explicitly released
This commit is contained in:
2026-05-06 18:00:38 -07:00
committed by Naomi Carrigan
parent c6f4e27843
commit 397169e3dc
28 changed files with 204 additions and 90 deletions
+10
View File
@@ -11,9 +11,11 @@ import type {
EquipmentType,
} from "./equipment.js";
import type { GameState } from "./gameState.js";
import type { GoddessState } from "./goddessState.js";
import type { Player } from "./player.js";
import type { ProfileSettings } from "./profileSettings.js";
import type { CompletedChapter } from "./story.js";
import type { VampireState } from "./vampireState.js";
interface AuthResponse {
token: string;
@@ -114,6 +116,14 @@ interface LoadResponse {
* The current expected schema version from the server.
*/
currentSchemaVersion: number;
/**
* Initial expansion states for preview display — never saved to game state.
*/
expansionPreview: {
goddess: GoddessState;
vampire: VampireState;
};
}
interface BossChallengeRequest {