current_context - xopherdeep/do-it-for-the-xp GitHub Wiki

Current Context

Last Updated: 2026-10-29
Focus Area: CI/CD Autobump Workflow Orchestration on Push to Main

Session 2026-10-29: CI/CD Autobump Workflow Orchestration on Push to Main

What was done:

  • Autobump Workflow Restored (.github/workflows/autobump.yml):
    • Created dedicated Autobump workflow triggering on push to main and master branches, plus manual workflow_dispatch.
    • Computes the YY.M.D-MINS version via HalloftheGods/.github/.github/workflows/calculate-version.yml@main.
    • Bumps package.json, commits chore: auto-bump version to ${VERSION} [skip ci], creates tag v${VERSION}, and pushes commit and tag via HalloftheGods/.github/.github/workflows/wp-plugin-update.yml@main.
  • Downstream Workflow Trigger Synchronization:
    • Updated deploy-pages.yml to trigger via workflow_run after Autobump completes successfully.
    • Updated build-mobile.yml to trigger via workflow_run after Autobump completes successfully.
    • Both build workflows now check out the bumped ref (ref: ${{ github.event.workflow_run.head_branch || github.ref }}) and read version directly from package.json.
    • Removed desynchronized ad-hoc version calculation and redundant tag pushes from build workflows.
    • Preserved manual workflow_dispatch triggers for all workflows.
  • Test Triggers (.github/workflows/tests.yml):
    • Added main branch to push trigger list alongside master.

Session 2026-10-29: Voxel Hero Figurine Widget & Companion 3D Avatar Enhancement

What was done:

  • Native Voxel Figurine Widget (VoxelHeroWidget.java, Slot 12):
    • Created dedicated 2x2 / 2x3 home screen diorama widget showcasing the player's custom 3D voxel character.
    • Designed widget_voxel_hero.xml with RPG window styling, floating level badge, class title, streak status, and widget_pedestal_base.xml diorama stage.
    • Created widget_voxel_hero_preview.xml for launcher preview selector on Android 12+.
    • Bound one-tap deep link (com.forthexp.doit://my-portal).
  • 3D Voxel Avatar Integration for Companion Widget (HeroCompanionWidget.java, Slot 9):
    • Updated widget_hero_companion.xml to two-column horizontal layout pairing the hero's 3D voxel character (@+id/widget_companion_voxel) beside the speech bubble quote.
    • Bound cached voxel bitmap with fallback to hero icon.
  • Native Snapshot Decoding & Caching Pipeline (WidgetImageHelper.java, XpWidgetPlugin.java):
    • Created WidgetImageHelper.java to decode base64 PNG data URLs into internal storage (voxel_<heroId>.png).
    • Implemented safe downsampling during decodeFile to prevent Binder IPC TransactionTooLargeException.
    • Updated XpWidgetPlugin.syncWidgetData to automatically cache incoming avatarImage snapshots across all family heroes and registered VoxelHeroWidget.class in provider broadcasts.
  • Frontend Data Extraction & In-App Preview Customizer (widgetCatalog.ts, widgetDataExtractor.ts, XpWidgetConfigModal.vue):
    • Added avatarImage?: string to WidgetHeroPayload and extracted from user?.avatarImage.
    • Added Voxel Figurine segment button, diorama mockup, and updated companion mockup in XpWidgetConfigModal.vue adhering to Hex Color Ratchet rules (RGB tokens only).
  • RemoteViews Whitelist Compliance Fix (widget_voxel_hero.xml, widget_voxel_hero_preview.xml):
    • Replaced <View> pedestal tags with <FrameLayout>, resolving the Android launcher InflateException: Class not allowed to be inflated android.view.View and eliminating the "Couldn't load widget" homescreen crash.
  • Testing & Deployment:
    • Verified unit tests: widgetLinks.spec.ts, widgetDataExtractor.spec.ts, and widgetSyncTrigger.spec.ts (48/48 passing).
    • Built debug APK with ./gradlew assembleDebug (BUILD SUCCESSFUL).
    • Deployed wirelessly to Pixel 9a over ADB with Success.

Session 2026-10-29: Dynamic RPG Box Style Sync for Android Widgets

What was done:

  • Native RPG Box Window Drawables (android/app/src/main/res/drawable/):
    • Created native drawables mirroring the app's .rpg-box game styles with high-fidelity gradients, bevels, and border layers:
      • widget_window_finalfantasy.xml: SNES blue gradient with bevel border.
      • widget_window_chronotrigger.xml: Slate window with warm gold border.
      • widget_window_dragonquest.xml: Classic cobalt blue with double white border.
      • widget_window_secretofmana.xml: Deep forest green with parchment border.
      • widget_window_virtualboy.xml: Pitch black with high-contrast red border.
      • widget_window_zelda.xml: Dark night teal with polished gold frame.
      • widget_window_mariorpg.xml: Espresso frame with studded gold border.
      • widget_window_phantasystar.xml: Deep cyber navy with cyan steel trim.
  • Native Java Theme Helper & Plugin Ingestion (WidgetThemeHelper.java, XpWidgetPlugin.java):
    • Added KEY_GAME_STYLE in WidgetThemeHelper and mapped all RPG styles to their respective window drawables.
    • Preserved per-widget override while falling back to the globally synced game style.
    • Ingested gameStyle in XpWidgetPlugin.syncWidgetData and saved to SharedPreferences.
  • TypeScript Sync Pipeline & Reactive Trigger (widgetCatalog.ts, widgetDataExtractor.ts, widgetSyncTrigger.ts, useHeroThemeSync.ts):
    • Added gameStyle property to WidgetSyncPayload interface.
    • Updated buildWidgetSyncPayload to accept and serialize gameStyle.
    • Updated syncAllWidgets() in widgetSyncTrigger.ts to read active RPG style from useGameStore().theme.rpg.
    • Added reactive trigger in useHeroThemeSync.ts to invoke queueWidgetSync() on theme changes.
  • Testing & Verification:
    • Added unit tests for gameStyle serialization and store extraction in widgetDataExtractor.spec.ts and widgetSyncTrigger.spec.ts.
    • Full widget test suite passed (47/47 passing).
    • Built APK with ./gradlew assembleDebug and deployed wirelessly to Pixel 9a over ADB.

Session 2026-10-29: Title Screen Chrome Clean-up (Menu Button Removal & Settings Link)

What was done:

  • Menu Corner Button Removal (src/views/LogIn/LogIn.vue, src/views/LogIn/_LogIn.scss):
    • Removed floating top-left ion-menu-toggle (.menu-corner) from start/login screen to keep splash screen art clear.
    • Cleaned up .menu-corner and legacy .menu-toggle CSS rules from _LogIn.scss.
  • Title Screen Settings Link (src/views/LogIn/LogIn.vue, src/views/LogIn/LogIn.ts, src/views/LogIn/_LogIn.scss):
    • Unhid settings action and converted it to retro text link button (.settings-link) directly beneath "Press Start".
    • Replaced the inline modal with direct navigation to the existing settings home page (/xp-settings).
    • Removed legacy InputSettings, modalController, and .settings-modal styling from the start screen.
    • Styled .settings-link with "Press Start 2P" font, gear icon with hover rotation, and synchronized fadeInUp animation.
  • Public Settings Route & Navigation (src/router/SideMenu/settings.routes.ts, src/app/SideMenu/XpSettings/components/XpSettingsHome/XpSettingsHome.vue):
    • Added meta: { requiresAuth: false } to /xp-settings and child routes so users without an active profile session can configure settings.
    • Added <xp-back-button default-href="/log-in"> to the Settings toolbar to allow returning directly to the title screen.

Session 2026-10-29: Wallet Tier Floor Invariant & Storage Self-Healing Migration

What was done:

  • Domain Invariant Enforcement (src/lib/services/gp/wallet.ts, src/lib/utils/User/stats.ts):
    • Floored nextWalletUpgrade() at DEFAULT_WALLET_LIMIT (500 GP) so the base tier is never queried as an upgrade offer, resolving soft-locks on legacy profiles.
    • Ensured Stats constructor floors stats.gp.limit at DEFAULT_WALLET_LIMIT.
  • Storage Self-Healing Ingestion (src/lib/databases/ProfileDb.ts, src/lib/store/stores/user/resources.ts):
    • Added hasOutdatedWalletLimit() and normalizeProfileWallet() in ProfileDb.
    • Updated ProfileDb.getAll() to auto-migrate legacy profiles with limit < DEFAULT_WALLET_LIMIT and persist fixes to storage.
    • Added safety floor in applyGpChange() to update outdated limits on live point adjustments.
  • Testing:
    • Added regression test cases in Wallet.spec.ts, WalletShops.spec.ts, and ProfileDbPins.spec.ts.

Session 2026-10-29: Android Widget Suite Expansion & Launcher Home Screen Previews

What was done:

  • Native Android AppWidgetProviders (11 Total Suite):
    • Expanded widget suite from 5 to 11 with 6 new providers:
      • NextQuestWidget (Slot 6): Urgent next quest countdown, reward tags, and one-tap deep link.
      • LevelGaugeWidget (Slot 7): Level progress bar, XP percentage, and remaining XP to level up.
      • PartyRosterWidget (Slot 8): Multi-hero status board showing HP/MP bars for up to 4 heroes.
      • HeroCompanionWidget (Slot 9): Hero pixel companion, class, dynamic status quote, and portal link.
      • BountyApprovalsWidget (Slot 10): Pending approvals count and overdue chores counter for Game Masters.
      • SpellbookWidget (Slot 11): Action Points (AP) gauge and tactical quick-cast ability dock.
    • Updated BaseXpWidgetProvider.java request code bit-packing (appWidgetId << 8) | ((providerSlot() & 0x1F) << 3) | (target & 0x7) to safely support up to 32 distinct widget providers.
    • Updated WidgetPayload.java with allHeroes() and firstPendingQuest() helper accessors.
    • Registered all 11 providers in XpWidgetPlugin.java and AndroidManifest.xml.
  • Home Screen Launcher Previews (Android 12+ / API 31+):
    • Added android:previewLayout to all 11 widget provider XML definitions (res/xml/widget_*_info.xml).
    • Created widget_quest_board_preview.xml providing an authentic populated preview with sample quest items in the launcher widget selector.
  • Deep Links & In-App Preview Customizer:
    • Extended widgetLinks.ts with routing for com.forthexp.doit://abilities and com.forthexp.doit://approvals.
    • Expanded XpWidgetConfigModal.vue with segment selectors, interactive mockups, and theme tokens for all 11 widgets in full compliance with Hex Color Ratchet rules (RGB tokens only).
  • Verification:
    • Clean Android compilation: ./gradlew compileDebugSources BUILD SUCCESSFUL.
    • Unit tests: widgetLinks.spec.ts (26/26 passing), HexLiteralRatchet.spec.ts (15/15 passing).

Session 2026-10-29: Mobile Asset DLC Hydration & Remote CDN Fallback

What was done:

  • In-App DLC Downloader Service (src/lib/services/dlc/assetDlcService.ts):

    • Implemented singleton service managing manifest verification, progress tracking, and bulk asset download.
    • Caches remote assets into HTML5 CacheStorage (xp-dlc-v1) under Capacitor's native origin.
    • Stores synced DLC version in @capacitor/preferences to prevent redundant downloads.
  • Service Worker Asset Interception (public/alerts-sw.js):

    • Extended Service Worker with fetch handler for /img/ and /media/ paths.
    • Intercepts requests, matches cached assets first, tries local APK, and falls back to remote CDN endpoints (R2 -> WordPress -> Cloudflare Pages) while asynchronously caching responses.
  • DLC Modal UI Component (src/components/molecules/Modals/XpDlcModal.vue):

    • Created retro RPG-styled modal offering "Download All" or "Stream Later".
    • Displays download progress percentage and file progress meter using theme tokens.
  • App Bootstrap Integration (src/app/App.vue, src/app/App.ts, src/main.ts):

    • Registered Service Worker for native Capacitor environments.
    • Triggered DLC readiness checks on startup for native platforms.
  • Asset Packaging & Cloudflare R2 Upload (scripts/upload-dlc-r2.mjs, package.json):

    • Built high-speed concurrent HTTP uploader leveraging Cloudflare R2 REST API.
    • Successfully uploaded all 888 items (manifest, assets-bundle.zip, and extracted assets) to remote R2 bucket xp-bgm under /dlc/.
  • General Settings Manual DLC Trigger (GeneralSettings.vue):

    • Added "Game Asset Pack" card to General Settings (/settings/general).
    • Displays download/ready badge and summary text, with one-tap access to open XpDlcModal for manual downloading or cache refreshing.
  • CI/CD Mobile Build Fixes (.github/workflows/build-mobile.yml):

    • Fixed Android SDK license acceptance to use runner pre-installed SDK.
    • Removed redundant chemx verification gate to prevent build blocking.
  • Native Beast Sprites Bundling (.mobileignore, dist/):

    • Bundled 214 beast sprites (~11 MB) directly in the mobile APK/IPA to ensure instant local loading without broken image icons in Bestiary, Quests, or Battle screens.
    • Preserved 60% total asset reduction (52.85 MB APK payload down from 133 MB) by keeping heavy audio (65 MB) and dungeon tiles (14 MB) in the downloadable DLC.
  • Merge Conflict Resolution (feat/kid-creations):

    • Resolved conflict between Makers settings from feat/kid-creations and Party overhaul modes from master.
    • Verified unit tests for PartySettings.spec.ts (both Makers and Party Modes) and XpDashboard.spec.ts (all 25 tests passing).

Session 2026-10-28: Hex Colour Ratchet Sweep & CI Restoration

What was done:

  • Hex Colour Ratchet Compliance (XpPowerCard.vue, _XpNotifications.scss, XpWidgetConfigModal.vue, XpFamilyCloudCard.vue, XpRebalancePrompt.vue):
    • Eliminated all raw hex colour literals in style blocks across recent UI additions, replacing them with standard RGB values, Ionic variables, and --gs-* / --xp-app-* theme tokens.
    • Resolved the ratchet violation in HexLiteralRatchet.spec.ts preventing CI failures on PR #168 and full test runs.
  • Baseline Ratchet Lockdown (tests/unit/hexLiteralBaseline.json):
    • Lowered baseline total from 1541 to 1536.
    • Dropped _MyAbilities.scss and _XpNotifications.scss from baseline after sweeping all remaining hex literals to zero.
  • Verification:
    • tests/unit/HexLiteralRatchet.spec.ts (15/15 passing cleanly).

Session 2026-10-28: Powers & Notifications UI Overhaul

What was done:

  • Phone App Skin Registration (useAppSkin.ts):
    • Added notifications: "#f05a5b" to XP_APP_ACCENTS for consistent retro/modern app branding.
  • Powers Page & Rich Spell Card Grid (XpPowerCard.vue, MyAbilities.vue, _MyAbilities.scss, powerRow.ts, MyAbilities.ts):
    • Enhanced XpPowerCard.vue into a rich spell card component with themed visual emblem tiles, icon glow effects, lock/cooldown badges, running timer indicator, high-visibility AP meters with percentage readouts, MP tags, frequency tags, and dedicated tactile Cast buttons.
    • Replaced flat list rows in MyAbilities.vue with responsive .powers-grid layout (1 column on mobile, 2+ columns on tablet/desktop).
    • Wired timerLeftOf and power state data directly into card bindings.
    • Preserved backwards compatibility for BattlePowersSheet.vue and XpPowerCard.spec.ts.
  • Notifications Feed Overhaul (XpNotifications.vue, XpNotifications.ts, _XpNotifications.scss):
    • Converted XpNotifications.vue from raw Ionic markup to the unified Phone App Kit (xp-app, xp-app-header, xp-app-section, xp-app-row, xp-app-chip, xp-app-empty).
    • Grouped notifications into clean sections ("New" vs "Earlier" or "Recent").
    • Added color-coded duotone icons per notification kind, unread indicator dot, category tag chips, and relative timestamps.
    • Added quick trailing row actions (Mark Read checkmark and Delete trash).
    • Implemented bottom bar with filter pills ("All" vs "Unread" with count badge) and bulk actions ("Mark Read" and "Clear").
  • Living Documentation (docs/App/My-Portal/My Notifications.md):
    • Updated feed and management documentation reflecting Phone App Kit integration.

What was done:

  • .mobileignore Configuration (.mobileignore):
    • Established universal mobile exclusion rules for heavy assets (audio media/**, dungeon tiles img/[*,*].*.webp, world maps img/world-map.*.webp, beast sprites img/[0-9][0-9][0-9].*.webp, and redundant Webpack Font Awesome SVGs img/fa-*.svg).
    • Leaves dist/ completely intact so web builds and Cloudflare Pages deploy 100% of all assets without disruption.
  • Mobile DLC Packaging & Pruning Pipeline (scripts/package-mobile-assets.mjs):
    • Created zero-dependency Node CLI script supporting --pack-only, --prune-only, and --dry-run.
    • Extracts excluded assets into dist-dlc/assets/, generates manifest.json with SHA-256 hashes and file sizes, and compresses into dist-dlc/assets-bundle.zip.
    • Prunes excluded assets from native project targets (android/app/src/main/assets/public/ and ios/App/App/public/), reducing native mobile asset payloads from ~132 MB down to ~40 MB (~70% reduction).
  • NPM Build Integration (package.json):
    • Added assets:pack, assets:prune, assets:analyze, cap:sync:mobile, and build:mobile scripts.
  • Continuous Integration Workflow (.github/workflows/build-mobile.yml):
    • Created GitHub Actions workflow triggered on push to master and workflow_dispatch.
    • Sets up Node 22, pnpm, JDK 17, and Android SDK.
    • Stamps build version, builds web bundle, packages DLC assets, prunes native assets, and compiles Android debug and release APKs.
    • Publishes lean APKs, assets-bundle.zip, and manifest.json as release artifacts and GitHub Releases.

Session 2026-10-28: Family Profile Management & Cloud Account Linking

What was done:

  • Non-Destructive Backup Merge UI (useBackupRestore.ts):
    • Updated confirmRestore to present a 3-way dialog when profiles already exist: "Cancel", "Merge with current data" (mode: "merge"), and "Replace everything" (mode: "replace").
    • Wired mode parameter through runRestore into backupService.restoreBackup(backup, { mode }).
    • Customized completion alert to display "Merge complete" or "Restore complete" based on execution mode.
  • Pre-Link Safety Backup Prompt (AccountSettings.vue):
    • Intercepted account linking when local profiles exist to prompt "Back up before linking?".
    • Provides one-tap "Back up & Link" that downloads an export before redirecting to WordPress authorization.
  • Cloud Family Conflict Resolution (XpFamilyConflictModal.vue & XpFamilyPhones.vue):
    • Created XpFamilyConflictModal.vue to inspect and resolve other-family account mismatches.
    • Compares cloud family ID and registered heroes against local device heroes.
    • Allows Game Masters to adopt the cloud family ID (adoptFamily), disconnect/unlink, or download a local backup.
    • Wired active "Resolve" buttons into AccountSettings.vue and XpFamilyPhones.vue banners.
  • Cloud Account & Sync Inspector Card (XpFamilyCloudCard.vue & FamilySettings.vue):
    • Implemented XpFamilyCloudCard.vue in Family Settings displaying cloud connection status, home/family device badges, and local vs. remote hero sync statuses.
    • Embedded <xp-family-cloud-card> in FamilySettings.vue for Game Masters.
  • Living Documentation (docs/XP-Settings.md):
    • Comprehensive documentation added for Family Settings, Cloud Sync Inspector, Conflict Resolution, and Merge vs Replace restores.

Session 2026-10-28: Select Profile Page & Card Padding Alignment

What was done:

  • Select Profile Page Container Alignment (SwitchProfile.vue):
    • Added xp-settings-page class and content-class="ion-padding" to <xp-rpg-page> to align with standard settings page layout and padding.
    • Added :class="{ 'full-row': users.length === 1 }" on mobile card grid column to center single-profile cards.
    • Replaced oversized desktop card class max-w-4xl with standard settings-card max-w-2xl matching settings pages.
    • Cleaned redundant py-4 utility padding from desktop list items and labels.
  • Grid Spacing & Shadow Geometry (_SwitchProfile.scss):
    • Accounted for Earthbound RPG box 16px outer box-shadow border (eb-box).
    • Replaced column padding (8px !important) with 48px grid gap (gap: 48px, padding: 16px 16px 96px 16px), yielding a uniform 16px visible gap between cards and screen edges.
    • Set margin: 16px auto; width: calc(100% - 32px); max-width: 520px; on .eb-window and .empty-window for uniform 16px margins inside ion-padding.
    • Standardized desktop .profile-item padding to 16px horizontal and 10px vertical.
  • Profile Card Padding Standardization (XpProfileCard.vue):
    • Enforced margin: 0 !important; width: 100% !important; so cards conform cleanly to grid columns.
    • Standardized ion-card-header (padding: 1rem 0.75rem 0.5rem) and ion-card-content (padding: 0 0.75rem 0.75rem).
    • Removed root padding bloat on &.is-large, delegating structured padding to header and content (1.5rem 1rem 0.5rem / 0 1rem 1rem).

Session 2026-10-28: Portrait (9:16) Splash Screens (Dark & Light)

What was done:

  • Pegasus Feather Crystal Splash Art:
    • Selected design: Hand holding the radiant Pegasus crystal shard in the center with golden celestial spiral aura.
    • 16-bit retro fantasy RPG title typography ("Do it for the XP!") centered at the top.
    • Gold pixel ribbon banner: "Family Owned & Operated / Made by family, for families".
    • Full pairs created for both Dark (midnight cosmos) and Light (daylight azure) themes.
  • Asset Deployment & Multi-Resolution Support:
    • Master source files deployed to assets/splash-dark.png and assets/splash.png.
    • Generated 26 full-bleed Android drawable density/orientation sets across ldpi, mdpi, hdpi, xhdpi, xxhdpi, and xxxhdpi (day and night).
    • Resolved aspect ratio pillarboxing via center-crop scaling for edge-to-edge rendering on all screen sizes (including custom 600x1024 tablets).
    • Built and verified live on devices (G8S1L905128401PM and b1929aa0).

Session 2026-10-27: Android Home Screen Widgets Suite (5 Gamified Widgets & In-App Customizer)

What was done:

  • Native Android Widget Infrastructure:
    • Implemented BaseXpWidgetProvider.java and WidgetThemeHelper.java supporting 5 retro RPG themes: Onett Blue (earthbound), Retro Monochrome (gameboy), Molten Ruby (lava), Hometown Royal (gold), and Obsidian Deep (dungeon).
    • Added XML drawables for retro double-line borders (widget_window_*.xml), stat progress bars (widget_progress_hp.xml, widget_progress_mp.xml), and badge chips (widget_badge_bg.xml).
  • 5 Gamified Android Home Screen Widgets:
    • HeroCardWidget.java (2x2 / 4x2): Displays Hero nickname, Level, Job Class, animated-style HP/MP bars, GP purse, and streak count. Tapping launches directly into the hero portal.
    • StreakAltarWidget.java (1x1 / 2x1): Displays streak flame counter, active XP multiplier (1.0x to 1.5x), and launch shortcut to Party.
    • GoldVaultWidget.java (2x1 / 2x2): Retro Hometown Bank kiosk showing Wallet GP and Savings balance with one-tap ATM launcher.
    • QuickDockWidget.java (4x1): Four quick-action shortcuts: + Task (com.forthexp.doit://action/add-task), Chores (com.forthexp.doit://chores), Dungeon (com.forthexp.doit://dungeon), and Party (com.forthexp.doit://party).
    • QuestBoardWidget.java & QuestWidgetRemoteViewsService.java (4x2): Scrollable RemoteViews collection widget displaying today's pending chores, due times, and rewards (+XP / +GP) with deep link taps to individual quests (com.forthexp.doit://quest/:id).
  • Capacitor Native Bridge (XpWidgetPlugin.java):
    • Registered @CapacitorPlugin(name = "XpWidget") in MainActivity.java.
    • Implemented syncWidgetData, reloadAllWidgets, and saveWidgetConfig updating SharedPreferences and notifying AppWidgetManager.
    • Registered all 5 widget receivers and remote views service in AndroidManifest.xml with deep link scheme com.forthexp.doit.
  • Web & Store State Layer:
    • Created widgetCatalog.ts: Theme configurations and sync payload interfaces.
    • Created widgetDataExtractor.ts: Pure converters extracting hero stats, quest list items, streak bonuses, and bank balances.
    • Created widgetSync.ts: Capacitor plugin wrapper with browser fallback.
    • Created widgetSyncTrigger.ts and wired automatic widget sync on userStore profile persistence flush (persistence.ts).
  • In-App Widget Preview & Customization (XpWidgetConfigModal.vue):
    • Interactive live preview modal with retro widget themes, real-time hero stats rendering, and manual sync action.
    • Integrated into Theme Settings (ThemeSettings.vue) under "Home Screen -> Android Widgets".
  • Verification:
    • Unit tests: tests/unit/widgetDataExtractor.spec.ts (5/5 passing).
    • TypeScript type check: npm run typecheck (0 errors).

Session 2026-10-13: Family Invites & Party Hub Wireup

What was done:

  • Party Invites Hub (XpShareApp.vue at /tell-a-friend):
    • Replaced legacy mock referral placeholder with active Family & Party Invites Hub.
    • Added "Invite Your Family" section with "Add Hero on this Device" (opens AddProfile.vue modal) and "Link a Hero's Phone (QR Code)" (opens XpHeroPhonesModal.vue).
    • Added direct link to Town Hall if unlinked, plus link to Family Settings.
    • Added "Invite Friends & Allies" section with real share sheet (@capacitor/share) and "Copy Invite Link" action.
  • Party Tab Action Wiring (PartyRosterTab.vue + MyParty.ts / MyParty.vue):
    • Added prominent "+ Add Hero / Invite Family" action button to the Party Roster.
    • Added per-hero phone linking quick action button (<i class="fad fa-mobile-alt"></i>) in the roster.
    • Wired Action Sheet dialog to create new profiles or generate pairing QR codes / codes for heroes on demand.
  • Family Settings Onboarding (XpFamilyPhones.vue):
    • Added graceful unlinked card when multiplayer flag is on but Town Hall is not yet connected (data-cy="family-phones-connect").
    • Added direct button to navigate to Town Hall to complete multiplayer setup.
    • Updated unit tests in XpFamilyPhones.spec.ts (22/22 passing).
  • Verification:
    • chemx test tests/unit/XpFamilyPhones.spec.ts tests/unit/partyStats.spec.ts (49/49 passing).
    • chemx typecheck clean.
    • chemx check clean (0 hazards across all modified components).

What was done:

  • Source: screenshots in tools/For the xp/ (S'moresUp chores, boss fights, reward shelf).
  • StarterWorld.ts: 3 new categories (cat-family, cat-health, cat-bosses) and new quests mapped to library beasts where one fits.
  • rewardPresets.ts: 12 new GP shop rewards (boba, pizza night, game nights, spa, Lego, bike and more).
  • AbilityPresets.ts: 3 new real-life AP powers (Car DJ, App Extension Time, YES Day).
  • StarterWorld.spec.ts: timed-quest assertion relaxed to toMatchObject (16 passed).
  • Not yet covered: remaining shelf items (consoles, gems), streak quests, dog and sibling chores.

Session 2026-10-13: Multiplayer Part 1 Swarm (MP12-MP19 & Party Tab #1334)

What was done:

  • Enabled multiplayer in production builds via .env.production (VUE_APP_MULTIPLAYER=true).
  • Party Tab Honesty Pass (#1334):
    • Replaced mock/random online dots and activities in MyParty.vue.
    • Decomposed 735-line component into MyParty.vue, MyParty.ts, _MyParty.scss, and subcomponents under src/app/Console/MyPortal/party/.
    • Implemented real daily streak counting consecutive days with approved quest logs in partyStats.ts (27/27 unit tests passing).
    • Wired latest 20 approved quest logs into activity feed (partyStats.ts).
    • Added Cypress test in tests/e2e/specs/party.spec.js.
  • MP12 (#1305): Verified family store sending, cards diffing, and single-flight flush (66/66 unit tests passing).
  • MP13 (#1306): Finished XpFamilyPhones.vue card in Settings with comprehensive unit tests for age pickers, error banners, and home transfer (22/22 unit tests passing).
  • MP14 (#1307): Implemented deviceLink.ts, HeroDeviceDb.ts, and kid-mode store state and actions (94/94 unit tests passing).
  • MP15 (#1308): Implemented XpHeroPhonesModal.vue with live QR code generation (qrcode), ABCD-EFGH formatted code, 10-minute expiry countdown, and device list (6/6 unit tests passing).
  • MP16 (#1309): Implemented /link claiming flow in LinkPhone.vue, ML Kit barcode camera scanner, and profile chooser empty state hero button (6/6 unit tests passing).
  • MP17 (#1310): Implemented Kid Mode router guards (heroPhone.guard.ts), GM lockout in gm.guard.ts, and /hero-phone view with 3D voxel model and unlinked recovery (133/133 unit tests passing across guard and view specs).
  • MP18 (#1311): Implemented server reward deduplication with eventInbox.ts, "party" receipts in QuestLogDb, and auto-download triggers in family.ts (89/89 unit tests passing).
  • Review #1331: Completed deep review of MP12 and MP18, confirming all 6 critical event stream and reward invariants hold.
  • MP19 (#1312): Created comprehensive Cypress end-to-end spec in tests/e2e/specs/family.spec.js and fixtures in tests/e2e/fixtures/family/.
  • All tasks committed and marked done on ChemX. MP20 (#1313) queued for full rehearsal.

Session 2026-10-13: Random Thief Encounter (The Thief Beast)

What was done:

  • Created dedicated thief encounter domain logic in thiefEncounter.ts:
    • Constants: THIEF_BEAST_ID = "beast-thief", THIEF_ENCOUNTER_RATE = 0.20, THIEF_POTION_STEAL_RATE = 0.40.
    • Thief enemy factory createThiefEnemy() configured with no tasks, standard beast stats, avatar 189, raccoon emoji.
    • Identification helper isPotionOrEther() recognizing potion, ether, elixir, and registered potion catalog items.
    • Safe theft calculation calculateStolenGp() stealing 10% to 25% of wallet GP (min 5, max 50 GP), safely bounded by available wallet.
    • Orchestrator stealFromHero() deducting GP and optionally consuming one potion or ether from inventory.
  • Integrated Thief encounter into battle routing and guard systems:
    • Extended BattleContext and PendingAmbush with encounter?: string in battleContext.ts and battle.ts.
    • Updated battle.guard.ts with isThiefRoll() triggering random thief encounters (query ?encounter=thief), preserving parameters across background alerts and return callbacks.
  • Integrated Thief encounter into battle pipeline and stage presentation:
    • Updated encounterLoader.ts to detect encounter === "thief" or beastIds.includes("beast-thief") and return a thief encounter (thief: true).
    • Updated BattleEnemyStage.vue to hide the chores panel for thief enemies (v-if="enemy && !enemy.isThief"), preventing "0 tasks left" displays.
    • Implemented startThiefEncounter() in BattleField.ts displaying surprise leap dialogue, applying hit feedback and sound on stolen loot, reporting GP and potion losses or empty pockets, and executing fadeout escape automatically.
  • Documentation:
    • Updated Random Encounters.md with details on the Thief Beast encounter and theft rates.
  • Verification & Quality:
    • Added unit test suite ThiefEncounter.spec.ts covering theft calculation, item detection, userStore integration, and edge cases (12/12 passing).
    • Updated encounterLoader.spec.ts (34/34 passing).

Session 2026-10-13: Dungeon Room 3D Voxel Models & Chest FAB Retirement

What was done:

  • Retired the placeholder center room FAB (ion-fab id="room-action") in TempleGrounds.vue.
  • Implemented modular 3D voxel room model organism XpDungeonRoomModel.vue:
    • Interactive 3D WebGL landmark canvas with Three.js renderer integration via useDungeonRoomScene.ts.
    • Drag-to-rotate interactivity for 3D exploration.
    • Chest lure animation (@keyframes chest-bob), golden treasure aura (drop-shadow), and hover elevation.
    • Earthbound-style title badges with action cues via <xp-landmark-badge> (e.g. "Treasure Chest", "Tap to open!").
    • Accessible keyboard control (role="button", tabindex="0", Enter/Space) and SFX triggers.
  • Built comprehensive 3D voxel geometries in dungeonRoomShapes.ts:
    • Unopened treasure chest with iron brackets, curved lid, golden ribs, lock plate, and scattered coins.
    • Open empty chest with tilted lid and hollow interior.
    • Boss/Master chest variant with crimson body, gilded dragon trim, and inset ruby.
    • Custom voxel models for all dungeon room types: Key, Healing Spring, Mana Spring, Campfire, Puzzle Stela, Teleport Circle, Merchant Stall, Save Monument, Pegasus Egg Altar, Secret Alcove, Stairs Up/Down, Temple Entrance, Exit Gate, Spike Trap, Dark Chasm, Dusty Chamber, and Cleared Victory Trophy.
  • Updated TempleGrounds.ts and _TempleGrounds.scss to center the room voxel model and support cleared room markers.
  • Verification & Quality:
    • Unit tests added: dungeonRoomVoxel.spec.ts (25 passed, 25 total).
    • TypeScript type check clean (0 errors).
    • Chemical X lint/check clean (0 violations).

Session 2026-10-13: Battle Tackle Menu Font and Icon Scaling

What was done:

  • Scaled up attack typography and icons in XpBattleTaskMenu.vue:
    • Chore attack item text (.battle-task-item): raised font size from 1.25rem to 1.5rem with line-height: 1.25 for improved mobile readability.
    • Claw attack icons (.task-icon): enlarged from 1.3rem / width: 1.6rem to 1.5rem / width: 1.8rem.
    • Sheet title and subtitle: raised title from 1.4rem to 1.55rem (icon 1.35rem) and subtitle from 0.95rem to 1.05rem.
    • Confirmation question and action buttons: increased .confirm-question to 1.15rem and .rpg-button to 1.35rem.
  • Verification & Quality:
    • Unit tests: XpBattleTaskMenu.spec.ts (18 passed, 18 total).

Session 2026-10-13: Combat Escape Bribe System & Wealth/Grudge Scaling

What was done:

  • Implemented GP bribery mechanic for fleeing combat:
    • Added pure calculation helpers in bribeMath.ts:
      • Base bribe: Math.max(5, Math.round(attack * 1.5)) scaled by beast attack.
      • Wealth surcharge: 5% of total wealth (wallet + savings).
      • Grudge scaling: 50% increase per grudge mark (1 + marks * 0.5).
      • Low bribe tier: 50% discount (Math.floor(fullCost * 0.5)).
    • Extended escape types in types.ts:
      • Added bribed, bribeTier, and bribeCost to EscapeReport.
      • Added "bribe-full" and "bribe-low" to BattleAction.
    • Added Earthbound-style flavor dialog lines in dialogLines.ts.
    • Updated engine in BattleService.ts:
      • Added getBribeQuotes and handleBribe.
      • Handled wallet GP deduction via userStore.updateUserGP.
    • Updated battle outcome logic in useBattleOutcome.ts:
      • Skipped grudge mark penalties when hero escapes with a full bribe.
    • Updated UI radial menu and action triggers:
      • BattleField.ts: Added bribe menu actions to run confirmation cluster, wired reactive GP tracking.
      • XpBattleRadialMenu.vue: Added gold full bribe and secondary low bribe buttons.
  • Verification & Quality:
    • Unit tests added: BattleBribe.spec.ts (10 passed).
    • Test suites updated: BattleOutcomeDefeat.spec.ts, XpBattleRadialMenu.spec.ts, BattleField.spec.ts.

Session 2026-10-13: Lego Monster Task, Portrait Asset, and Starter World Seeding

What was done:

  • Added Lego Monster beast portrait asset:
    • Generated and keyed out 480x480 RGBA WebP sprite saved at 294.webp.
    • Bumped TOTAL_BEAST_AVATARS to 294 in BestiaryService.ts.
    • Bumped nAvatars to 294 in AvatarSelect.vue.
    • Added lego-monster: 294 mapping in beast_numbers.json.
  • Seeded Lego Monster beast and quest in StarterWorld.ts:
    • Defined STARTER_LEGO_BEAST with id beast-lego-monster, 4-step chore checklist, earth element, avatar 294, and battle backgrounds.
    • Included STARTER_LEGO_BEAST in STARTER_BEASTS.
    • Added quest seed quest-lego ("Dismantle the Lego Monster") under cat-chamber ("The Hero's Chamber") scheduled daily in the evening.
  • Added vocabulary support:
    • Added lego and legos synonyms to librarySuggest.ts.
  • Verification & Quality:
    • Unit tests updated and passing: StarterWorld.spec.ts, beastLibrary.spec.ts, BestiaryService.spec.ts, librarySuggest.spec.ts.
    • TypeScript type check clean (npm run typecheck, 0 errors).

Session 2026-10-13: Battle Timer Bar Pulsation & Dynamic Acceleration

What was done:

  • Implemented accelerating pulsation animation for the battle attack timer bar in BattleEnemyStage.vue:
    • Added dynamic --pulse-duration calculation scaling smoothly from a steady 1.6s rhythm at full clock (100%) down to an urgent 0.3s heartbeat at zero or critical state.
    • Bound --pulse-duration CSS variable to .attack-timer container for seamless child inheritance.
    • Added continuous pulsating glow to .attack-timer-fill and synchronized outer border glow to .attack-timer-bar.
    • Updated @keyframes timer-pulse and added @keyframes timer-bar-pulse with rhythmic brightness and glow intensity.
    • Ensured reduced motion preferences cleanly disable animations across the timer bar, fill, and labels.
  • Verification & Quality:
    • Unit tests updated and passing: BattleEnemyStage.spec.ts (58 passed).
    • Existing suite passing: BattleField.spec.ts (17 passed).

Session 2026-10-13: ATM Interface Visibility & Sprite Animation Removal

What was done:

  • Removed sprite animation from ATM prompts in bankPrompts.ts:
    • Removed sprite: 'atm' from atmMenuPrompt to prevent the sunburst rays and pixel sprite from covering the retro CRT ATM display.
    • Updated amountAsk to omit sprite animations and apply 'atm' accent when invoked with 'ATM' as the speaker.
  • Updated ATM errand caller in ATMModal.vue:
    • Set speaker explicitly to 'ATM' in amountAsk calls so amount stepper dialogs do not show spinning coin rays over the kiosk.
  • Styled subtle backdrop for ATM prompts in XpRevealPrompt.vue:
    • Bound accent-${options.accent} to prompt root.
    • Added .rp.accent-atm .rp__backdrop with rgba(10, 2, 10, 0.25) to keep the CRT scanlines and account statements fully readable.
  • Verification & Quality:
    • Unit tests updated and passing: BankPrompts.spec.ts (16 passed).
    • Existing suite passing: XpRevealPrompt.spec.ts (27 passed).
    • TypeScript type check clean (npm run typecheck, 0 errors).

Session 2026-10-13: Hotels in Every World (Thematic Lodging, World Routing, Draggable Landmarks)

What was done:

  • Implemented hotelRegistry.ts (hotelRegistry.ts):
    • Defined HotelMetadata interface and registered thematic lodgings across all 10 worlds:
      • Hometown: Grand Hotel (Hotel Concierge)
      • Plains: Windward Inn (Innkeeper Zephyr)
      • Islands: Coral Cove Resort (Concierge Marina)
      • Forest: Canopy Lodge (Lodge Keeper Bramble)
      • Mountains: Highland Peak Inn (Host Boulder)
      • Desert: Mirage Oasis Hotel (Hostess Dunestar)
      • Swamps: Foggy Bayou Inn (Night Porter Moss)
      • Ice: Frostpeak Lodge (Lodge Host Ymir)
      • Clouds: Stratus Palace Hotel (Steward Nimbus)
      • Moon: Lunar Orbital Suites (Steward Astra)
    • Exported getHotelByWorld, getHotelMetadata, and getAllHotels.
    • Added hotelId to WorldMetadata and all entries in worldRegistry.ts.
  • Parameterized hotel routing and parent resolution:
    • Updated hotel route in hometown.routes.ts to /hotel/:userId?/:world?.
    • Updated parentOf.ts (parentOf.ts): regional hotel routes now resolve their parent back to the origin regional world, ensuring Back and "Leave Hotel" return players directly to where they entered.
  • Updated XpBuildingModel.vue:
    • Added isHotel detection supporting both hotel and *-hotel identifiers.
    • Automatically builds 3D hotel voxel model for all hotels.
    • Resolves badge title from getHotelByWorld(activeWorld) and badge sublabel to "Pay to rest".
    • Routes to /hotel/:userId/:world passing the active world parameter.
  • Refactored HotelHub.vue and HotelHub.ts:
    • Dynamic hotel title bound to hotelTitle.
    • Cleaned up obsolete WordPress item grid and legacy test alert configuration.
    • Dynamic clerk speaker name and hotel greeting with {hotel} support in npc.ts and hometownPrompts.ts.
    • Preserved full night rest cycle: GP deduction, full HP and MP restoration, restoreAll audio, and receipt notice.
  • Mounted draggable hotel landmarks across all 9 regional world views:
    • WorldPlains.vue (x: 48, y: 26)
    • WorldForest.vue (x: 46, y: 28)
    • WorldIslands.vue (x: 68, y: 38)
    • WorldSwamps.vue (x: 68, y: 36)
    • WorldMountains.vue (x: 28, y: 38)
    • WorldDesert.vue (x: 28, y: 38)
    • WorldClouds.vue (x: 68, y: 32)
    • WorldIce.vue (x: 24, y: 38)
    • WorldMoon.vue (x: 28, y: 34)
  • Verification & Quality:
    • Unit tests: HotelRegistry.spec.ts (8 passed), Lodging.spec.ts (21 passed), HometownPrompts.spec.ts (27 passed), parentOf.spec.ts (31 passed), DraggableSpot.spec.ts (16 passed), PegasusWorldModel.spec.ts (9 passed).
    • TypeScript type check passed cleanly (npm run typecheck, 0 errors).

Session 2026-10-13: Procedural Floor Tiles for The Old House and Custom Temples

What was done:

  • Created TempleFloor.vue providing procedural CSS floor tiles for rooms without pre-rendered WebP background art:
    • House theme varieties for The Old House:
      • Hardwood timber planks (temple-floor--wood) for living room, front hall, bedrooms, dining room, and office.
      • Checkered ceramic tile floor (temple-floor--tile) with grout for kitchen, pantry, and bathrooms.
      • Weathered outdoor wood decking (temple-floor--deck) for front porch, back deck, and yard.
      • Concrete/slate stone slabs (temple-floor--slab) for garage, basement, and storage.
    • Elemental dungeon flagstone pavers (temple-floor--dungeon) for custom and generated temples colored by element (fire, ice, water, earth, light, shadow, moon, storm, wind).
    • Perimeter vignette and radial torch lighting (temple-floor__shade) creating depth where walls meet floors.
    • Thematic room emblems: boss mystic circle, entrance welcome mat, and sanctuary glowing circles.
  • Wired TempleGrounds.vue and TempleGrounds.ts:
    • Renders <temple-floor> on walkable rooms when no pre-rendered image asset exists.
    • Updated walls for The Old House to use warm cedar/brass styling (&--home in TempleWalls.vue).
  • Enhanced custom and moving temple element/metadata resolution:
    • Updated metadataForAsync in templeRegistry.ts to query TempleDb for non-shipped temples.
    • Updated templeElementFor in RoomBeast.ts to respect record elements for custom temples and The Old House.
    • Guarded getBgImage in useTempleLayout.ts against missing temple asset folders.
  • Verification & Quality:
    • Unit tests created: TempleFloor.spec.ts (8 passed).
    • Existing suite passed: RoomBeast.spec.ts (29 passed), movingTempleReset.spec.ts, templeAudit.spec.ts (57 passed).

Session 2026-10-13: Switch Profile Empty Notice Redesign & Responsive Menu Alignment

What was done:

  • Redesigned empty profile notice in SwitchProfile.vue:
    • Replaced naked low-contrast floating text (empty-state) with authentic Earthbound CRT window (eb-window empty-window).
    • Added signature multi-layer retro pixel borders, solid #280828 backdrop blocking the animated checkerboard background, and dual-layer header ("CHOOSE A PROFILE", "FILE SELECT").
    • Added framed duotone hero icon (fad fa-users-slash), bold retro title ("No Adventurers Yet!"), and crisp high-contrast description in "StatusPlz" monospace.
    • Mounted interactive "Start New Game" file slot CTA directly inside the window body (eb-file-slot eb-new-slot), providing an immediate creation pathway on both desktop and mobile.
    • Wrapped populated profile views in <template v-else>: eliminates layout duplication on desktop where the empty text previously sat above the separate desktop card.
    • Conditioned view-toggle left FAB on users.length > 0 to keep mobile chrome clean when no profiles exist.
  • Menu Architecture Clarification:
    • Documented dual-menu responsive divergence: navigation sidebar (SideMenu.vue) auto-collapses off-canvas via ion-split-pane behind top-left hamburger on mobile, while profile list card (SwitchProfile.vue) was previously isolated behind Tailwind hidden md:block.
  • Verification & Quality:
    • TypeScript typecheck passed cleanly (npm run typecheck, 0 errors).
    • Unit tests passed: familyPrompts.spec.ts (29 passed).

Session 2026-10-13: ATM Screen Artwork & Retro Terminal Interface

What was done:

  • Redesigned ATM screen and modal artwork in ATMModal.vue:
    • Replaced generic white card and floating FontAwesome icon with a retro CRT ATM kiosk enclosure.
    • Added marquee header banner with glowing green LEDs, status indicator pulse, and Hometown National Bank branding.
    • Implemented phosphor CRT display with deep green scanlines, curved surface glare, and terminal header ("TERMINAL #402", "ACCOUNT STATEMENT").
    • Formatted cash and savings readouts in glowing monospace phosphor typography ("StatusPlz") with color-coded status glow (gold wallet, green savings, red hospital debt).
    • Added lower machine bay featuring tactile screen-side function keys, card reader with green insertion slot, cash dispenser slit, and metallic 12-key numeric pad.
  • Created dedicated retro ATM pixel sprite in revealSprites.ts:
    • Defined atm sprite (44x40) with chassis body, glowing green CRT monitor, function keys, card slot, and key bay.
    • Added 'atm' to RevealSpriteName in revealPrompt.ts.
    • Updated atmMenuPrompt in bankPrompts.ts to display sprite: 'atm' instead of generic coins.
  • Verification & Quality:
    • Unit tests passed: XpRevealPrompt.spec.ts (27 passed), StarterWorld.spec.ts (16 passed), PurchaseService.spec.ts (42 passed).

Session 2026-10-13: Basic Items in Shops (Potions, Ethers, Elixirs)

What was done:

  • Added basic in-game consumable items to catalogue presets in rewardPresets.ts:
    • Defined BASIC_CONSUMABLE_PRESETS: Health Potion (50 GP), Mana Potion (75 GP), Ether (100 GP), and Elixir (200 GP).
    • Added consumableFromPreset mapping them to Accessory with AccessoryType.Virtual and tags: ["consumable", "preset"].
    • Updated ALL_REWARD_PRESETS and presetsNotIn to include consumables in the Compendium catalogue.
  • Stocked shops across the starter world in StarterWorld.ts:
    • Hometown Market carries the complete catalogue (all basic consumables + real-life rewards).
    • Regional shops stock Health Potion and Mana Potion alongside their rotating accessories.
  • Updated purchase service & flow in PurchaseService.ts:
    • Implemented isConsumableItem: recognizes in-game consumables, potions, ethers, and elixirs.
    • Added capacity validation: verifies canCarry(hero, item) before purchase; throws PurchaseError("bag-full") if inventory and storage are full without deducting GP.
    • Added immediate fulfillment: purchases of in-game consumables add the item directly to user.inventory via userStore.addInventoryItem(userId, consumableRawItem) and log status as "fulfilled" (skipping physical GM handover queues).
  • Enhanced shop UI and dialogue copy:
    • Added shop.buy.consumableReceipt and shop.buy.bagFull in npc.ts.
    • Added consumablePurchaseReceipt and bag-full prompt handling in shopPrompts.ts.
    • Wired consumable receipt and bag-full feedback in AccessoryShop.ts.
  • Verification & Quality:
    • Unit tests: PurchaseService.spec.ts (42 passed), StarterWorld.spec.ts (16 passed), BattlePotions.spec.ts (24 passed), and BattleItems.spec.ts (23 passed).

What was done:

  • Restored rain to swamp weather preset in presets.ts:
    • Updated weatherPresets.swamp layers to include fx.rain alongside fx.fog and fx.fireflies.
    • Updated ambient audio loop to "rain".
  • Verification:
    • Unit tests: WeatherFX.spec.ts and WeatherCanvas.spec.ts (33 passed, 33 total).

Session 2026-10-13: Red Flashy Hotel Voxel Model

What was done:

  • Redesigned 3D hotel voxel model in buildingShapes.ts:
    • Upgraded from muted brown/green inn styling to a vibrant, multi-tiered grand red hotel.
    • Added charcoal/red carpet entryway foundation.
    • Multi-tier crimson, ruby, and scarlet facade blocks (#b71c1c, #c62828, #d32f2f, #e53935).
    • Flashy marquee canopy with neon yellow/gold borders (#ffd700, #ffea00, #ff1744).
    • Gold balconies and railings with glowing suite windows (#ffff8d).
    • Rooftop neon "HOTEL" marquee sign board with white glowing letter styling.
    • Crowned rooftop beacon spire with gold orb and crimson beacon light.
  • Verification & Quality:
    • Unit tests: buildingVoxel.spec.ts (38 passed, 38 total).

Session 2026-10-13: Beast Log Quest Wizard Fanfare & Enhanced Confetti

What was done:

  • Brought full-screen fanfare reveal to Beast Log Quest Wizard on quest summoning:
    • In XpQuestWizardModal.vue: embedded <xp-hero-fanfare> overlay triggered on quest creation.
    • Dynamically populates fanfare props (name, subtitle, portrait, title="A new quest joins the log!", actionText="Accept quest").
    • Added adventure BGM (nowLetsGo) playing alongside the level-up stinger burst.
    • Dismisses cleanly on backdrop click or "Accept quest" button press, emitting saved and close.
  • Enhanced XpHeroFanfare.vue and confetti engine for bigger, richer visual impact:
    • Generalized XpHeroFanfare.vue props (name, subtitle, title, actionText, sound) with defaults preserving existing hero creation flow.
    • Expanded sparkle particle count from 14 to 24 with increased reach (up to 205px) and varied sizes.
    • Enlarged rotating ray wheel from 640px to 800px and burst flash from 110px to 160px (_XpHeroFanfare.scss).
    • Added 3-wave confetti burst cascade (80 first wave, 45 second wave, 30 third wave per edge) and raised total chip cap to 480 in confetti.ts and XpConfettiBurst.vue.
  • Verification & Quality:
    • Unit tests: QuestFanfare.spec.ts (2 passed), HeroFanfareConfetti.spec.ts (10 passed).

Session 2026-10-13: NPC Clerk & RPG Dialog Space & Marker Refinement

What was done:

  • Fixed bloated vertical height and duplicate continue markers across RPG dialogs:
    • In XpTypingText.vue: replaced right-floated fad fa-caret-down fa-2x float-right mt-3 marker with inline .typing-more-marker (&#9660;, color #ffd84a, font-size 0.85em, subtle bounce animation). Eliminates layout distortion and vertical clearance blowup.
    • In XpNpcDialog.vue: refined styling with compact padding (10px 14px 12px, min-height: 48px), max-width 520px, subtle backdrop blur (rgba(10, 2, 10, 0.45), backdrop-filter: blur(2px)), safe-area bottom inset padding, and crisp header divider.
    • In GoldBank.vue: hid clerk FAB button while conversation is active (v-show="!isTalking").
    • In HospitalHub.vue, HotelHub.vue, XpAboutAp.vue, XpAboutGp.vue, and XpAboutXp.vue: removed duplicate .dialog-indicator elements and hid trigger FABs while dialogs are open. Corrected hasMoreText prop binding in HospitalHub.vue.
  • Verification & Quality:
    • Unit tests: AccessoryShopComponents.spec.ts (12 passed, 12 total).

Session 2026-10-13: Anytime Quest Ambushes & Battle Rewards

What was done:

  • Allowed open "anytime" chores (quests without an explicit clock due time) to trigger quest ambush encounters:
    • Updated questAmbush.ts pickQuestAmbush: anytime quests qualify for encounters alongside overdue quests. Overdue quests retain priority and trigger first.
    • Updated OS notification copy in ambushAlertCopy to state ${quest} is waiting. Come back and fight! instead of asserting overdue.
    • Updated questRoomPicker.ts: renamed neverAmbushes property to isAnytime, updated ANYTIME_AMBUSH_NOTE note text to "no due time: ambushes any time" with backwards-compatible NEVER_AMBUSHES_NOTE alias.
    • Updated documentation in Quest-Rooms-Spec.md (Section 5.9).
  • Verification & Quality:
    • Unit tests: questAmbush.spec.ts, BattleGuard.spec.ts, QuestRoomPicker.spec.ts, and BattleOutcomePassives.spec.ts all pass green.
    • Verified approval-required quests properly hold pending claims and delay rewards during battle victories.

Session 2026-10-13: Battle Dialog Auto-Scroll and Layout Room

What was done:

  • Battle dialog box padding and room (_BattleField.scss):
    • Adjusted box padding to 14px 20px 16px (was 5px 0 0) with min-height: 96px.
    • Added 22px right padding to .dialog-content and raised max-height to 260px to avoid text overlap with the ▼ more indicator.
    • Set .battle-zone--actions from fixed height: 176px to min-height: 176px to accommodate multi-line growth.
  • Forced auto-scroll on dialog growth (BattleDialogBox.vue):
    • Added template ref on .dialog-content.
    • Implemented scrollToBottom triggered via MutationObserver on child/text mutations and post-flush watchers on text and accumulatedLines.length.
    • Level-up message lines and typing text stay automatically scrolled to the latest entry without manual scrollbar dragging.
  • Verification: 14 of 14 unit tests in BattleField.spec.ts passing green.

Session 2026-10-13: Battle Room Tasks Counter Label

What was done:

  • Updated counter label in BattleEnemyStage.vue from ${left.value} ${left.value === 1 ? "chore" : "chores"} left to ${left.value} ${left.value === 1 ? "task" : "tasks"} left.
  • Updated test suites to reflect the "tasks left" terminology:
    • BattleEnemyStage.spec.ts
    • BattleField.spec.ts
    • battle.spec.js
    • moving-pack.spec.js
    • quest-grudge.spec.js
    • quest-rooms.spec.js
  • Verification: 71 of 71 unit tests passed green across BattleEnemyStage.spec.ts and BattleField.spec.ts.

Session 2026-10-13: In-Game App Bottom Navigation Standardization Across Sub-Apps

What was done:

  • Migrated legacy top segment tabs to unified bottom navigation dock across all in-game sub-apps:
    • Created reusable XpAppBottomNav.vue organism and AppNavTab interface (appBottomNav.ts):
      • Replicates visual styling and haptics of XpBottomNav (backdrop-filter: blur(16px), rgba(16, 12, 28, 0.75), gold active highlight #ffd700, notification badges, play$fx("select") audio feedback).
      • Globally registered <xp-app-bottom-nav> in src/main.ts.
    • Migrated 7 in-game sub-apps:
      • Goods (XpInventorySheet.vue, MyInventory.vue): Bottom dock with All, Potions, Keys, Materials, Tools tabs featuring reactive item count badges. Removed redundant legacy footer chevrons.
      • Spells (MyAbilities.vue, MyAbilities.ts): Bottom dock with All, Privileges, Spells, Unlocked, Locked tabs (POWER_TABS). Moved searchbar to header.
      • Quests (MyQuests.vue, MyQuests.ts): Bottom dock with Board and List tabs (including active todoCount badge). Moved searchbar to header.
      • Workbench (MyCrafts.vue, MyCrafts.ts): Bottom dock with All, Furniture, Accessories, Weapons, Key tabs (WORKBENCH_TABS). Compact page switcher in footer above dock; searchbar in header.
      • Storage (MyStorage.vue, MyStorage.ts): Bottom dock with All, HP, MP, Misc, Key tabs (STORAGE_TABS). Compact page switcher in footer above dock; searchbar in header.
      • Kitchen (MyFoods.vue, MyFoods.ts): Bottom dock with All, Favorites, Meals, Snacks, Desserts, Pantry tabs (FOOD_TABS). Searchbar in header. Fixed template toolbar closure.
      • Calendar (MyCalendar.vue, _MyCalendar.scss): Bottom dock with All, Morn, Noon, Eve, Night tabs (calendarTabs). Compact day navigation buttons in footer above dock; searchbar in header.
  • Verification and Quality:
    • Unit tests: XpAppBottomNav.spec.ts (5/5), QuestSchedule.spec.ts (65/65), XpInventoryModal.spec.ts (5/5), QuestList.spec.ts (23/23).
    • TypeScript typecheck passed with zero errors (pnpm run typecheck).

Session 2026-10-13: Battle Screen RPG Typography Harmonization

What was done:

  • Standardized retro RPG font families and discrete font size scale across the battle screen:
    • Battle dialogue: "Apple Kid", "StatusPlz", monospace at 1.55rem (_BattleField.scss).
    • Battle and radial prompts: Harmonized to "StatusPlz", monospace at 1.15rem with 1px letter spacing (_BattleField.scss, XpBattleRadialMenu.vue).
    • Action pills and menu buttons: Standardized to "Apple Kid", "StatusPlz", sans-serif at 1.15rem - 1.25rem (XpBattleRadialMenu.vue, BattleSheet.vue, XpBattleTaskMenu.vue).
    • Enemy stage typography:
      • Enemy nameplate: Updated to "StatusPlz", monospace at 1.2rem with uppercase styling (BattleEnemyStage.vue).
      • Chores remaining counter: Standardized to "StatusPlz", monospace at 1.15rem (BattleEnemyStage.vue).
      • Attack countdown timer: Unified caption to "StatusPlz", monospace at 0.85rem and timer digits to "StatusPlz", monospace at 1.25rem with tabular numbers (BattleEnemyStage.vue).
    • Hero status card typography:
      • Hero name: Standardized to "StatusPlz", monospace at 1.05rem (BattleHeroCard.vue).
      • Hero level: Raised from 0.72rem to 0.85rem in "StatusPlz", monospace (BattleHeroCard.vue).
      • Hero initial: Unified to 0.85rem (BattleHeroCard.vue).
      • HP / MP stat captions: Standardized to 0.85rem in "Fourside", "StatusPlz", monospace (BattleHeroCard.vue).
      • Defending badge: Unified to 0.85rem in "StatusPlz", monospace (BattleHeroCard.vue).
    • Battle modal sheets and inventory:
      • Sheet titles: Standardized to "Apple Kid", "StatusPlz", sans-serif at 1.4rem (BattleSheet.vue, XpBattleTaskMenu.vue).
      • Sheet subtitles: Unified to "StatusPlz", monospace at 0.95rem (BattleSheet.vue, BattlePotionSheet.vue, XpBattleTaskMenu.vue).
      • Item and power titles: Harmonized to "Apple Kid", "StatusPlz", sans-serif at 1.25rem (BattlePotionSheet.vue, BattlePowersSheet.vue, XpBattleTaskMenu.vue).
      • Descriptions and effects: Unified to "StatusPlz", monospace at 0.85rem (BattlePotionSheet.vue, BattlePowersSheet.vue).
      • Goods sheet and modal: Standardized segment tabs (0.85rem), tab badge counts (0.7rem), goods names (1.05rem), goods blurbs (0.85rem), MP costs (0.85rem), refusal reasons (0.85rem), quantities (0.95rem), and modal title (1.15rem) in "StatusPlz", monospace (XpInventorySheet.vue, XpInventoryModal.vue).
    • Victory card: Harmonized subtitle (1.15rem), quest line (1.15rem), work line (1.15rem), held badge (0.95rem), and footer prompt (1.15rem) (BattleVictoryCard.vue).
  • Test suite verification:
    • 146 of 146 battle unit tests passed (BattleField.spec.ts, BattleEnemyStage.spec.ts, BattleHeroCard.spec.ts, BattleVictoryCard.spec.ts, XpBattleRadialMenu.spec.ts, XpInventoryModal.spec.ts).
    • 50 of 50 battle consumable unit tests passed (BattleItems.spec.ts, BattlePotions.spec.ts).
    • Total 196 of 196 tests passing green.

Session 2026-10-13: Universal Draggable Landmark System with iOS Organize Mode

What was done:

  • Implemented iOS-style organize mode for landmark positioning and rotation decoupling:
    • Long-press (500ms) on any landmark triggers Organize Mode across all spots.
    • Active organize mode adds retro wobble animation (ios-wobble-1, ios-wobble-2, ios-wobble-3) to all landmarks.
    • In Organize Mode: dragging translates landmark across screen smoothly; canvas pointer events are intercepted to suppress 3D voxel rotation.
    • In Placed Mode: dragging directly rotates 3D voxel model in place without moving icon on screen; taps activate modals and navigation.
    • Extracted domain state to spotState.ts (isOrganizeMode, activeOrganizeSpotId, snapMode, snapCoordinate, enableOrganizeMode, disableOrganizeMode, cycleSnapMode).
    • Added floating retro Organize HUD with Done button and Snap toggle (Drop, Live, Off).
    • Implemented configurable grid snapping defaulting to Snap on Drop (2% grid increments, ~6 to 8px).
  • Implemented useDraggableSpot.ts composable:
    • Freeform dragging with pointer capture and coordinate clamping (5% to 95%).
    • Multi-touch pinch-to-scale calculation (0.5x to 2.0x) via pointer distance ratio.
    • Desktop mouse wheel zoom with transient floating percentage badge feedback.
    • Double-click and double-tap shortcut to reset scale to 1.0x.
    • User-scoped localStorage persistence schema (xp:spot:${screen}:${userId}:${spotId}).
    • Global xp:reset-spots CustomEvent listener with lifecycle cleanup.
  • Created XpDraggableSpot.vue organism wrapper:
    • Capture-phase click interceptor preventing route navigation or modal triggers during drags or pinches.
    • Dynamic isometric depth sorting (z-index: Math.round(y)).
    • Drag elevation (z-index: 300, lift scale 1.08, deep drop shadow).
    • Registered globally in main.ts as xp-draggable-spot.
  • Integrated across all game plaza and world scenes:
    • WorldMap.vue and WorldMap.ts: Replaced local drag divs with <xp-draggable-spot> and wired "Reset Map" action to triggerSpotsReset.
    • HomeTown.vue and _HomeTown.scss: Converted plaza to relative container, wrapped all 7 landmarks and old house.
    • MyHome.vue and _MyHome.scss: Converted plaza to relative container, wrapped all 6 home fixtures.
    • 9 World Regional Scenes: Wrapped all landmarks in WorldPlains, WorldForest, WorldIslands, WorldSwamps, WorldMountains, WorldDesert, WorldClouds, WorldIce, and WorldMoon.
  • Testing and verification:
    • Added unit test suite tests/unit/DraggableSpot.spec.ts (16 of 16 tests passing).
    • Verified tests/unit/WorldMapDraggable.spec.ts (10 of 10 tests passing).
    • Total 26 of 26 tests passing.
    • Verified Chemical X compliance: 100% Crystalline, 0 hazards across all modified files.
  • Mobile Touch & Drag Responsiveness Fixes:
    • Removed teleported .xp-organize-backdrop which blocked pointer hit-testing at z-index: 9990.
    • Added window pointerdown listener in spotState.ts dismissing organize mode on taps outside spots and toolbar.
    • Added isOrganizeMode check to sharedLandmarkRenderer.ts pointer events to prevent 3D rotation from capturing events during organize mode.
    • Applied touch-action: none !important;, -webkit-user-select: none;, and -webkit-touch-callout: none; across all draggable spots and children.
    • Bound pointer tracking to window during active touches in useDraggableSpot.ts with immediate drag engagement on touch down during organize mode.
  • Platform UI Sound Migration:
    • Replaced RPG fallback sounds (equip) with native platform UI sounds from uiSounds (nintendo / sony):
      • Enter organize mode: openTask (nintendo.News / sony.NavigationEnter).
      • Exit organize mode / reset: closeTask (nintendo.Home / sony.NavigationBack).
      • Landmark drop / placement: click (nintendo.Klick / sony.Navigation).
      • Snap cycling & scale reset: select (nintendo.Select / sony.Navigation).

Session 2026-10-13: Direct Battle Potions and Ethers Consumables Audit

What was done:

  • Fixed counterintuitive refusal where Potions and Ethers in the backpack displayed "Can't use that in a fight":
    • Root Cause: In BattleItems.ts, only combat relics (BATTLE_ITEMS) and containers (CONTAINERS: Bottles, Book of Spells) were recognized. Individual potions like "Health Potion", "Mana Potion", "Ether", "Elixir" were unmapped, defaulting to role: 'none' and returning refusal reason "Can't use that in a fight.".
    • Solutions implemented:
      • BattlePotions.ts:
        • Added findPotionRule(name) supporting case-insensitive and normalized name matching.
        • Expanded POTIONS registry with Hi-Potion, X-Potion, and Mega Potion.
        • Exported potionReason(rule, userId) to evaluate live eligibility based on current HP/MP and caps.
        • Updated drinkPotion(userId, entryId) to match either by id or name, and spend item safely using card.id.
      • BattleItems.ts:
        • Added 'potion' to BattleBagRole.
        • Updated battleBagRole(item) to recognize items matching findPotionRule(name).
        • Updated describeBattleItem(item, ctx): Potions display their healing effect (e.g. "Restores 50 HP", "Restores 50 MP"), 0 MP cost, and dynamic refusal reasons (e.g. "Your HP is full.", "Your MP is full.", "You are already at full strength.").
        • Updated useBattleItem(item, ctx): Potions execute directly via drinkPotion(ctx.userId, item.id || name), restoring HP/MP, playing heal audio, spending 1 item from inventory, and preserving the hero's turn.
  • Test coverage & verification:
    • Added unit test in src/app/Console/MyPortal/UserHud/MyInventory/__tests__/XpInventoryModal.spec.ts verifying Health Potion and Ether battle cards and direct consumption (5 of 5 tests passing).
    • Verified tests/unit/BattleItems.spec.ts passes (26 of 26 tests passing).
    • Verified tests/unit/BattlePotions.spec.ts passes (24 of 24 tests passing).
    • Verified src/app/Console/BattleField/__tests__/BattleField.spec.ts passes (14 of 14 tests passing).

Session 2026-10-13: Unified Goods & Inventory Organism (Battle Goods & My Goods App)

What was done:

  • Unified the backpack Goods experience across the My Goods page and the battle arena:
    • Created XpInventorySheet.vue (src/app/Console/MyPortal/UserHud/MyInventory/XpInventorySheet.vue) as an Organism:
      • 5 category tabs: All, Potions, Keys, Materials, Tools.
      • Category icons and tab counts directly from groupInventory(entries).
      • Merges items from inventoryOf(user) and props.equipment for seamless combat and general bag access.
      • Displays item icon, name, description / battle effect, and quantity badge (x{qty}).
      • In battle mode (mode="battle"): evaluates battleCard(item) to render MP costs, battle effect lines, disabled states, and "Use" triggers.
      • Strictly compliant with atomic design hierarchy (no raw DOM HTML elements).
    • Created XpInventoryModal.vue (src/app/Console/MyPortal/UserHud/MyInventory/XpInventoryModal.vue):
      • Reusable <ion-modal> organism with <xp-close-button>, red toolbar, backpack icon, and "My Goods" title.
    • Refactored MyInventory.vue and MyInventory.ts:
      • Delegated segment tabs and list rendering directly to <xp-inventory-sheet :user-id="userId" mode="view" />, eliminating duplicated code.
    • Replaced <XpEquipmentModal> with <XpInventoryModal> in BattleField.vue and BattleField.ts:
      • Replaced the dumbbell equipment modal in combat with the authentic backpack Goods modal.
  • Test coverage & verification:
    • Created unit test suite src/app/Console/MyPortal/UserHud/MyInventory/__tests__/XpInventoryModal.spec.ts (4 of 4 tests passing).
    • Verified full BattleField.spec.ts suite passes (14 of 14 tests passing).
    • Verified full XpBattleRadialMenu.spec.ts suite passes (7 of 7 tests passing).

Session 2026-10-13: Animated 3D Voxel Hero in Radial Battle FAB

What was done:

  • Mounted live 3D voxel hero (XpHeroModel.vue) inside center circular button of XpBattleRadialMenu.vue:
    • Added props heroLook?: HeroLook and animation?: HeroAnimation (defaults to "idle").
    • Conditionally renders <xp-hero-model> when heroLook is provided, with fallback to avatar image or shield icon.
    • Clipped inside 68px gold-bordered circular button with smooth overflow clipping.
  • Wired reactive combat animation states in BattleField.ts and BattleField.vue:
    • Computed heroLook = computed(() => hero.value?.look).
    • Computed heroAnimation with reactive states:
      • "idle": Default stance while choosing battle actions.
      • "hurt": Triggers on enemy strike (feedback.hitSignal) for 600ms.
      • "walk": Triggers during attack execution (finishCombatTask).
      • "victory": Triggers upon winning the battle (victoryCard).
  • Test coverage & verification:
    • Updated src/app/Console/BattleField/__tests__/XpBattleRadialMenu.spec.ts (7 of 7 tests passing).
    • Verified full BattleField.spec.ts suite passes (14 of 14 tests passing).

Session 2026-10-12: Modern Battle Radial FAB Menu Organism

What was done:

  • Implemented XpBattleRadialMenu.vue (src/app/Console/BattleField/components/XpBattleRadialMenu.vue) as an Organism:
    • 5-node tactile radial cluster:
      • Top: Tackle / Attack (ion-button color="success") with class weapon icon.
      • Start (Left): Powers (ion-button color="tertiary") and Defend (ion-button color="warning").
      • End (Right): Goods (ion-button color="danger") and Run Away (ion-button color="dark").
      • Center: Circular Hero Avatar button with gold border, pulsing on active turn and acting as Attack shortcut on tap.
    • Run confirmation mode: Dynamically switches to "Keep fighting" (cancel) and "Run" (confirm).
    • Contextual combat prompt: Displays menuPrompt ("Do its chores to win!", "Run away?") above the radial cluster.
  • Integrated into BattleField.vue and BattleField.ts:
    • Conditioned on gameStore.fabStyle:
      • fabStyle === 'modern': Displays <XpBattleRadialMenu> when showMenu is active.
      • fabStyle === 'retro': Preserves classic XpRpgMenu inside BattleDialogBox.
    • Computed reactive properties isModern, isRetro, and heroAvatar via appConfig.$getUserAvatar.
  • Test coverage & verification:
    • Created unit test suite in src/app/Console/BattleField/__tests__/XpBattleRadialMenu.spec.ts (6 of 6 tests passing).
    • Verified full BattleField.spec.ts suite passes (14 of 14 tests passing).

Session 2026-10-12: Unhandled Autoplay Promise Rejection Fix

What was done:

  • Fixed uncaught runtime error overlay on /xp-intro:
    • src/views/XpIntro/XpIntro.vue: Replaced raw .options.play() in beforeMount() with play$fx("options"), which checks user interaction permissions and catches rejections safely.
    • src/components/organisms/IntroSplash/XpIntroSplash.vue: Routed playSound() through play$fx(sound) and guarded direct audio playback promises with .catch(...).
    • src/app/App.ts: Guarded this.bgm.audio.play() in playAudio() with a .catch(...) handler.
    • src/main.ts: Added global unhandledrejection handler to suppress browser autoplay NotAllowedError rejections from popping webpack-dev-server overlays.
    • src/main.ts: Expanded user interaction listeners to include keydown and touchstart alongside click.
  • Verification:
    • Verified tests/unit/AudioSilentStart.spec.ts passes (5/5).

Session 2026-10-12: Silent Start Audio Mute Enforcement

What was done:

  • Fixed audio playback during silent start in XpAudioPermissionModal:
    • continueSilently cancels pending route music delays via cancelPendingRouteMusic().
    • Immediately stops all active and loaded music tracks with audioEngine.stopAllMusic(0).
    • Disables BGM in useAudioStore (audioStore.bgm.is_on = false) and pauses store audio.
    • Clears pendingMusicId and sets audioPermissionGranted = true.
  • Hardened AudioEngine against playing audio while muted:
    • playMusic short-circuits and prevents track playback if this.state.muted is true.
    • Added cancellation handle _musicFadeAnimationId to cancel running fade-in animations on mute, stop, and stop-all.
    • Guarded fadeIn animation steps to stop immediately if engine is muted or track is paused.
    • stopAllMusic with zero fade time forcefully pauses and zeroes volume for all registered tracks.
    • mute() cancels pending fade animations and zeroes volume across all music tracks in cache.
    • Guarded initializeAudioContext against missing AudioContext constructor in non-browser environments.
  • Hardened routeMusic:
    • Exported cancelPendingRouteMusic() to abort stale delayed starts.
    • playRouteMusic halts and stops music immediately when engine.state.muted is true.
    • Delayed route start checks both audioStore.bgm.is_on and !engine.state.muted.
  • Updated App.ts:
    • clickSound uses play$fx('select') instead of directly triggering raw audio elements.
  • Added test coverage:
    • tests/unit/AudioSilentStart.spec.ts verifies silent start, muted play prevention, and store synchronization.

Session 2026-10-12: Onboarding Flow Architecture and Owner Decisions

Decisions resolved (Tasks #1103 to #1112):

  • Sequential Unlocks (Task #1104, Q5):
    • Sequence: Bed Basilisk ambush (XP) -> Gold Bank account creation (GP) -> First real chore quest (Profile tab) -> Larger wallet upgrade (Shop) -> Damage taken (Hospital HP / Hotel MP) -> Pegasus egg quest & flight (Overworld unlocks, prologue completes).
  • Guide Persona (Task #1105, Q6):
    • Town Crier acts as single overarching narrative guide, with individual hub NPCs (Bank Manager, Shopkeeper, Nurse) teaching local mechanics.
  • Parent Experience (Task #1106, Q7):
    • Parent plays the identical ambush-first prologue as a hero, augmented by contextual coaching lines across the Game Master console.
  • Existing Heroes (Task #1107, Q8):
    • All existing heroes start fresh on the prologue upon next launch.
  • Ambush Battle Mechanics (Task #1108, Q9):
    • Standard battle rules apply to the Bed Basilisk ambush; defeat routes the hero to the Hospital, teaching HP and healing mechanics early.
  • Device Support Target (Task #1109, Q10):
    • Includes "Join a family" in v1 to import a parent backup file via QR code or file share on separate child devices.
  • Parent Chore Pool (Task #1110, Q11):
    • Parents select chores from existing age bands, supplemented by chores assigned directly to them or household maintenance tasks.
  • Wizard Entry Point (Task #1111, Q12):
    • "Start a new family" and "Restore a backup" buttons mounted on the Press Start screen; intro slideshow acts as page 1 of the setup wizard.
  • Unlock Pacing (Task #1112, Q13):
    • Pure progress gating with zero artificial delays; features unlock immediately upon clearing prerequisite tasks and story beats.
  • Coordination Status:
    • Recorded all answers on board tasks #1104 through #1112; notified @fable via DM #1339 to begin authoring the technical specification.

Session 2026-10-12: Battle Transition Sound and Battle BGM Sequencing

What was done:

  • Battle Transition Sound Before Animation:
    • Added sound: "enterBattle" to { effect: "swirl", direction: "in" } in sceneTransitions.ts.
    • Added an 800 ms pause before cover(plan) in transition.guard.ts for swirl transitions when reduced motion is disabled, allowing the encounter sting to ring out before the swirl covers the screen.
    • Registered enterBattle and startBattle sound effect bindings across chronoTrigger and finalFantasy RPG themes in src/assets/fx/index.ts.
  • Battle Music Trigger Directly After Intro Animation:
    • Removed decoupled BATTLE_BGM_ROUTES handling and useBattleStore dependency from bgm.guard.ts, eliminating the arbitrary 4.2-second wait timeout.
    • Updated BattleField.ts startIntro callback to trigger audio.startBossBgm() for bosses and audio.startBattleBgm() for standard encounters right when the enemy arrives on stage.
    • Removed duplicate audio.startBossBgm() call from beginBattle.
  • Test Verification:
    • Updated tests/unit/sceneTransitions.spec.ts asserting sound: "enterBattle" on the battle swirl transition plan.
    • Added unit test in tests/unit/BattleAudio.spec.ts asserting startBattleBgm() immediately dispatches the battle BGM slot.

Session 2026-10-12: World Map 3x3 Biome Layout Realignment

What was done:

  • Realigned World Map plaza layout from 4 rows to a 3x3 grid aligning directly with world-map.webp illustration landmarks:
    • Top row (North): Islands, Mountains, Clouds shifted upward (padding-top reduced, margin-top: auto removed) to land directly over their background art features.
    • Middle row (Equator): Forests, Plains (centered between Forests and Tundras), and Tundras. Removed empty center clearing.
    • Bottom row (South): Swamps, Sands, and The Moon (Stars).
  • Updated WorldMap.vue and _WorldMap.scss to use uniform 100px sizing and justify-content: space-between across both axes.
  • Lifted middle and bottom rows higher: increased bottom padding to 180px and added equator bottom margin to place middle row directly over the forest and canyon trail, and bottom row directly over the swamp, dunes, and galaxy stars.

Session 2026-10-12: Retro-Modern RPG Shopfront Redesign

What was done:

  • Replaced cluttered shop layout in AccessoryShop.vue with an authentic retro-modern RPG shopfront matching Earthbound and glassmorphism standards.
  • Created ShopClerkStage.vue (src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopClerkStage.vue):
    • Dedicated upper scenic viewport (250px) framing authentic pixel art shopkeeper background (wrecked-ship.webp, pegasus-ranch.webp, etc.) without obscuring cards.
    • Earthbound-style dialog window with clerk nameplate, greeting, charisma discount badge, and closed sign.
  • Created ShopWalletWare.vue (src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopWalletWare.vue):
    • Featured wallet capacity upgrade card positioned at the top of the shelf with gold accents, live status cues, and instant upgrade modal prompt.
  • Created ShopItemCard.vue (src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopItemCard.vue):
    • 2-column responsive grid card with glassmorphism backdrop, centered item photo/icon, clean Apple Kid typography, and embedded price tag (with shortfall indicator when out of budget).
    • Eliminated broken margin: 2em, border-radius: 0 0 65px 65px, and overflow -20px badge positioning.
  • Created ShopItemModal.vue (src/app/Console/MyPortal/HomeTown/AccessoryShop/components/ShopItemModal.vue):
    • Single reusable inspection and purchase modal with item artwork, description, 3-column wallet economics breakdown, and tactile Buy/Cancel actions.
  • Header and Controls Refactor:
    • Added interactive Gold/Purse HUD pill to header toolbar with coin icon and wallet amount routing to ATM.
    • Eliminated 110px footer toolbar in favor of compact shelf filter chips ("All Items", "Can Afford", "Can't Afford") and inline search.
    • Increased ITEMS_PER_PAGE from 4 to 8.
    • Mapped missing pond-of-life.webp background.
  • Verification:
    • Added unit test suite in tests/unit/AccessoryShopComponents.spec.ts (10 of 10 tests passing).
    • Verified tests/unit/shopHours.spec.ts and tests/unit/PurchaseService.spec.ts passing (64 of 64 tests).
    • Full TypeScript typecheck clean (0 errors).

What was done:

  • Added custom 3D voxel palettes for all 9 sacred Pegasi in src/components/organisms/BuildingModel/voxel/buildingShapes.ts, matching PEGASUS_LOOK:
    • Ventus (Clouds): Silver-white coat (#f1f2f6), storm slate mane and wings (#2f3542)
    • Ignis (Mountains): Crimson coat (#ff4757), radiant gold mane and wings (#f1c40f)
    • Sol (Desert): Sun orange coat (#ffa502), sunset coral mane and wings (#ff6b81)
    • Aura (Plains): Spring green coat (#badc58), pure white mane and wings (#ffffff)
    • Terra (Forest): Emerald coat (#2ed573), dark forest bark slate mane and wings (#2f3542)
    • Glacie (Ice): Crystalline cyan coat (#00d2d3), glacier violet-blue mane and wings (#5352ed)
    • Aqua (Islands): Ocean cobalt coat (#3742fa), seafoam mint mane and wings (#7bed9f)
    • Venenum (Swamps): Shadow purple coat (#8e44ad), acid poison lime mane and wings (#badc58)
    • Umbra (Moon): Midnight navy coat (#130f40), radiant star white mane and wings (#ffffff)
  • Added locked dormant palette (#94a3b8, #64748b, #cbd5e1, #a1a1aa) for unfreed Pegasi.
  • Updated XpBuildingModel.vue with world prop and reactive unlock detection against user.stats?.pegasi:
    • When unlocked: displays the sacred Pegasus name (e.g., "Aura", "Ignis") and "Fly to World Map" with vibrant full-color 3D voxel model.
    • When locked: displays "Travel World" with asleep cue, applies .is-locked (45% opacity, 60% grayscale), and builds dormant voxel geometry.
    • Switches 3D mesh reactively via sceneBuildingId.
  • Updated all 9 world views (WorldPlains.vue, WorldClouds.vue, WorldDesert.vue, WorldForest.vue, WorldIce.vue, WorldIslands.vue, WorldMoon.vue, WorldMountains.vue, WorldSwamps.vue) to pass world="<world>" without hardcoded label overrides.
  • Added comprehensive unit test suite in tests/unit/PegasusWorldModel.spec.ts (9 of 9 tests passing).
  • Fixed pegasus-ranch prefix collision in XpBuildingModel.vue and buildingShapes.ts:
    • props.buildingId.startsWith("pegasus-") was inadvertently matching pegasus-ranch, causing the Plains ranch shop to render as a duplicate Pegasus ("Aura") and navigate to the world map instead of the shop.
    • Excluded pegasus-ranch from isPegasus in XpBuildingModel.vue and getBuildingBoxes in buildingShapes.ts.
    • Pegasus Ranch now renders its 3D barn voxel model, badge title "Pegasus Ranch", cue "Tap to shop", and routes to the shop on tap.

Session 2026-10-12: Battle hero card HP MP status panel alignment

What was done:

  • Fixed header identity wrapping: added white-space: nowrap and flex-shrink: 0 on .hero-level to prevent "Lv" and level number from splitting onto two vertical lines.
  • Improved name truncation resilience: added flex: 1 1 auto and min-width: 0 to .hero-name, and increased card max-width to 192px to accommodate longer hero names cleanly.
  • Restructured stat-label for HP and MP: wrapped stacked letters in individual block spans with a dedicated column flex container (width: 16px, height: 30px, font-size: 0.82rem, line-height: 0.88), replacing fragile word-wrapping and negative letter-spacing hacks.
  • Centered rolling odometer digits: applied display: flex; align-items: center; justify-content: center with padding-bottom: 4px on .digit tiles to offset Pixel Takhisis ascender whitespace and center numbers vertically.
  • Verified test suite: all 36 unit tests in src/app/Console/BattleField/__tests__/BattleHeroCard.spec.ts passing green.

Session 2026-10-11: Temple choice reveal encounter art stage positioning

What was done:

  • Moved encounter and room art ([data-cy="choice-art"]) out of the action sheet panel (.choice-reveal__panel) and into .choice-reveal__stage in src/app/Console/TempleGrounds/components/TempleChoiceReveal.vue.
  • Rendered .choice-reveal__stage when either sprite or showArt && art is present (hasStage).
  • Centered the art in the light rays and flash above the docked sheet panel, matching the chest and door reveal layout.
  • Applied choice-land bounce animation and drop shadow to the sprite.
  • Updated tests/unit/TempleChoiceReveal.spec.ts to assert that art renders on the stage outside the sheet panel.

Session 2026-10-11: Temple creator preview layout overlap and clipboard copy fallback

What was done:

  • Fixed template branching in src/app/Admin/XpCompendium/views/XpTemples/components/tabs/XpTempleLayout.vue: changed v-if="showMazeConfig" to v-else-if="showMazeConfig" so the grid editor does not render simultaneously with the preview modal and obscure buttons.
  • Hidden floating action buttons (Save, Management Shovel, Floor Switcher) during preview and maze configuration modes (&& !showPreview && !showMazeConfig).
  • Added responsive styling for .preview-container and .code-preview with vertical scroll constraints (max-height: 52vh) so action buttons remain visible on mobile devices.
  • Created src/lib/utils/clipboard.ts with copyTextToClipboard supporting both standard Clipboard API and document.execCommand('copy') fallback for non-secure HTTP contexts.
  • Updated copyToClipboard in src/app/Admin/XpCompendium/views/XpTemples/components/XpTempleCreator/hooks/useTempleCreator.ts to use copyTextToClipboard.
  • Added unit tests in tests/unit/clipboard.spec.ts covering secure API and non-secure fallback paths.

Session 2026-10-11: Dungeon room transition footstep sound effects

  • Extracted 2-step footstep asset src/assets/audio/nintendo/earthbound/step.wav (0.55s) from steps.wav for room-to-room transitions.
  • Preserved full 4-step sequence src/assets/audio/nintendo/earthbound/steps.wav (1.22s) for stairs transitions between floors.
  • Registered step (2 steps) and steps (4 steps) across $fx themes in src/assets/fx/index.ts and src/assets/fx/earthbound.fx.ts.
  • Wired fx('step') playback on room movement in moveWithUpdate() within src/app/Console/TempleGrounds/TempleGrounds.ts.
  • Wired steps sound effect to stairs climbing (climb() in src/lib/services/temples/RoomInteractions.ts).
  • Updated unit test assertions in tests/unit/RoomInteractions.spec.ts covering stairs sound outcome.

Session 2026-10-11: Toast notification center positioning with close button

What was done:

  • Updated default toast position in src/hooks/useToast.ts (rpgToastOptions and useToast) from bottom to middle.
  • Verified dismiss buttons include closeOutline cancel action button with Dismiss aria-label for instant dismissal.
  • Updated say() message helper in src/app/Console/TempleGrounds/TempleGrounds.ts to display dungeon toasts at middle position.
  • Updated toast placement documentation and comments across src/styles/themes/earthbound.scss and CLAUDE.md.
  • Updated unit test assertions in tests/unit/useToast.spec.ts covering center default positioning and dismiss button presence.

Session 2026-10-11: Batch 3 image WebP optimization (temples, shops, battleback backgrounds)

What was done:

  • Converted 292 images across temple rooms, shops, and battleback backgrounds to WebP (quality 85, method 6) and removed original JPG/PNG files:
    • 5 shop background PNGs in src/assets/images/backgrounds/shops/ (15.28 MB -> 1.81 MB, 88.14% reduction)
    • 277 temple room background JPGs across wind-temple/, light-temple/, ice-temple/, water-temple/, earth-temple/, fire-temple/, and shadow-temple/ (39.94 MB -> 21.52 MB, 46.14% reduction)
    • 10 battleback background PNGs src/assets/images/backgrounds/battleback*.png (5.80 MB -> 369.59 KB, 93.63% reduction)
  • Total weight reduced from 61,029,875 bytes (58.20 MB) down to 23,698,178 bytes (22.60 MB), saving 37,331,697 bytes (35.60 MB, 61.17% overall reduction).
  • Updated code references:
    • src/app/Console/TempleGrounds/TempleGrounds.ts (updated getBgImage and currentBgImage require statements from .jpg to .webp)
    • src/app/Console/MyPortal/HomeTown/AccessoryShop/AccessoryShop.ts (updated shopBackgrounds require paths from .png to .webp)
    • vue.config.js (verified IgnorePlugin regex compatibility with WebP backgrounds and updated comment)
    • src/views/XpDemo/XpDemo.vue (updated commented wind temple image path to .webp)

Session 2026-10-11: Batch 4 image WebP optimization (beasts/)

What was done:

  • Converted 93 monster battle sprite PNG images in src/assets/images/beasts/ (001.png through 093.png) to WebP (quality 85, method 6, transparency preserved) and removed original PNG files.
  • Reduced beast sprites weight from 8,988,589 bytes down to 2,158,374 bytes (75.99% size reduction, saving 6,830,215 bytes / 6.51 MB).
  • Updated code references:
    • src/lib/services/battle/BestiaryService.ts (getAvatar() returns .webp)
    • src/components/molecules/AvatarSelect/AvatarSelect.vue (getAvatarImage() returns .webp)
    • src/app/Admin/XpCompendium/views/XpAchievements/XpAchievements.ts (getBeastAvatar() returns .webp)
    • src/app/Admin/XpCompendium/views/XpAchievements/XpConfigAchievement/components/XpAchievementItem.vue (beastAvatarUrl() returns .webp)
    • src/app/Admin/XpCompendium/views/XpAchievements/XpConfigAchievement/hooks/useAchievementForm.ts (beastAvatarUrl returns .webp)
    • src/app/Admin/XpCompendium/views/XpBestiary/XpBestiary.vue (getAvatar() returns .webp)
    • src/app/Admin/XpCompendium/views/XpBestiary/components/XpAddBeast.vue (getAvatar() returns .webp)
    • src/app/Admin/XpCompendium/views/XpBestiary/components/XpBeastSelectorItem.vue (avatarUrl returns .webp)
    • tests/unit/TempleChoiceReveal.spec.ts (test beast art fixtures updated to .webp)
  • Unit tests verified clean: TempleChoiceReveal.spec.ts and BestiaryService.spec.ts passing (23/23 tests).

Session 2026-10-11: Batch 2 image WebP optimization (world & hometown backgrounds)

What was done:

  • Converted 12 full-screen background JPG images in src/assets/images/backgrounds/ to WebP (quality 85, method 6) and removed original JPG files:
    • world-mountains.jpg -> world-mountains.webp
    • world-map.jpg -> world-map.webp
    • world-ice.jpg -> world-ice.webp
    • hometown.jpg -> hometown.webp
    • world-plains.jpg -> world-plains.webp
    • world-moon.jpg -> world-moon.webp
    • world-swamps.jpg -> world-swamps.webp
    • world-islands.jpg -> world-islands.webp
    • world-desert.jpg -> world-desert.webp
    • world-forest.jpg -> world-forest.webp
    • world-clouds.jpg -> world-clouds.webp
    • my-home.jpg -> my-home.webp
  • Reduced background asset weight from 34,019,040 bytes down to 3,527,872 bytes (89.63% size reduction, saving 30.49 MB).
  • Updated code references across worldRegistry.ts, XpDemo.vue, JobClassSelector.vue, AccessoryShop.ts, _MyHome.scss, _WorldMap.scss, and all individual world SCSS stylesheets.

Session 2026-10-11: Batch 1 image WebP optimization (about/ & midjourney/)

What was done:

  • Converted 21 full-resolution PNG images across src/assets/images/about/ and src/assets/images/midjourney/ to WebP (quality 85).
  • Reduced folder weight from 53.36 MB down to 5.03 MB (90.6% size reduction, saving 48.33 MB).
  • Updated code references across XpIntro.vue, LogIn.scss, XpGameOver.vue, IntroSplashDemo.vue, AccessoryShop.ts, and town hub SCSS (GoldBank, HospitalHub, HotelHub).

Session 2026-10-11: Cloudflare Pages production deployment resolved

What was done:

  • Removed unreferenced public/samples/wind-temple-0-0.png (31.4 MiB) exceeding Cloudflare's 25 MiB file size cap.
  • Created canonical production deployment on Cloudflare Pages project do-it-for-the-xp with branch master.
  • Verified live HTTP 200 response and app rendering on root URL https://do-it-for-the-xp.pages.dev.
  • Attached custom domains app.forthexp.com and app.doit.forthexp.com to the live Pages project.

Session 2026-10-11: Monster voxel framing, NPC directional facing, and authentic nameplates

What was done:

  • Voxel Sizing & Camera Framing:
    • Centered Y coordinates in src/lib/engine/voxel/spriteToVoxel.ts around y = 0 and reduced extrusion depth to 1.6 for crisp 3D pixel relief without bulky square silhouettes.
    • Adjusted camera distance to 64 and target Y to 0 in src/components/organisms/MonsterModel/XpMonsterModel.vue, eliminating viewport clipping so full creature forms fit with balanced padding.
  • NPC Movement & Directional Facing:
    • Eliminated continuous 360-degree spinning (spinSpeed: 0).
    • Added directional yaw tracking in src/components/organisms/MonsterModel/useMonsterRoam.ts: monsters face their heading when walking (+0.6 rad right, -0.6 rad left) and turn forward (0 rad) upon arrival or hover.
    • Added NPC walking hop (is-moving) and gentle breathing idle (is-idle) CSS animations.
  • Under-Enemy Nameplates & Authentic Monster Naming:
    • Moved XpLandmarkBadge beneath the creature canvas and shadow (.name-under).
    • Eliminated generic "Temple Guardian" fallback in src/app/Console/TempleGrounds/TempleGrounds.ts.
    • Added resolveMonsterInfo to extract authored monster names (titleWords(monsterType)) and element-specific names (e.g. Fire Elemental, Stone Guardian, Ice Wyrm, Dark Phantom, Radiant Guardian) with matching bestiary avatars for both the roaming voxel and combat choice reveal.
  • Room Lifecycle Keying & Actual Beast Data:
    • Bound :key="monster-${currentLevel}-${currentPosition[0]}-${currentPosition[1]}" on xp-monster-model in TempleGrounds.vue so moving rooms cleanly disposes the previous room's WebGL client and spawns the new room's monster.
    • Updated TempleGrounds.ts to query BestiaryDb for the actual beast record, supporting custom imageUrl and localImage assets rather than only avatar numbers.

Session 2026-10-11: Build, typecheck, and test suite clean verification

What was done:

  • Voxel Sprite Decoding & Test Resilience:
    • Added timeout fallback guard to sampleImagePixels in src/lib/engine/voxel/spriteToVoxel.ts to prevent unhandled promise hangs during headless/SSR execution.
    • Updated tests/unit/spriteToVoxel.spec.ts with mock image decode failure handling.
  • Router Guard Optional Chaining:
    • Added optional chaining to router.beforeResolve, router.afterEach, and router.onError in src/router/_Guards/transition.guard.ts so lightweight mock router instances in unit tests run cleanly without stub errors.
  • Jest Worktree Isolation:
    • Configured testPathIgnorePatterns and modulePathIgnorePatterns in jest.config.json to ignore <rootDir>/.claude/, preventing stale worktree spec pollution.
  • Chemx Verification:
    • chemx typecheck: Clean (0 errors).
    • chemx test: 1,863 passed, 0 failed.
    • Production build (npm run vue-build): Complete.

Session 2026-10-11: Add menu button to Compendium app bar

What was done:

  • Added ion-menu-button in the #start-actions slot of XpRpgPage within XpCompendiumDashboard.vue.
  • Wired audio feedback with play$fx('select') on menu button press, matching XpDashboard.vue.
  • Exposed play$fx directly from setup() in XpCompendiumDashboard.vue.

Session 2026-10-11: Fix withoutEmptyTimes generic constraint in TimesOfDayEditor

What was done:

  • Updated withoutEmptyTimes generic constraint in timesOfDayEditor.ts from { timesOfDay?: readonly string[] } to Record<string, any>.
  • Resolved TS2353 excess property error when passing objects without timesOfDay in unit tests and consumers.

Session 2026-10-11: Cloudflare Pages live deployment

What was done:

  • Configured Cloudflare Pages SPA redirection via public/_redirects (/* -> /index.html 200).
  • Configured immutable asset caching headers via public/_headers for CSS, JS, fonts, media, and images.
  • Created and deployed project do-it-for-the-xp directly using Wrangler CLI to Cloudflare Pages.
  • Production deployment live at https://main.do-it-for-the-xp.pages.dev and https://do-it-for-the-xp.pages.dev.

Session 2026-10-11: 3D voxel dungeon monsters and room roaming

What was done:

  • 2D Sprite to 3D Voxel Engine:
    • Created spriteToVoxel.ts (src/lib/engine/voxel/spriteToVoxel.ts) to sample transparent monster PNG sprites (001.png to 093.png) into extruded 3D voxel Box[] definitions with run-length consolidation and depth.
    • Culled hidden faces via buildMeshData and cached generated meshes in-memory by sprite source URL.
    • Added procedural fallback voxel mesh for instant display and headless resilience.
  • Voxel Monster Organism:
    • Created XpMonsterModel.vue (src/components/organisms/MonsterModel/XpMonsterModel.vue) using sharedLandmarkRenderer to share the single WebGL context without GPU overhead.
    • Added continuous 360-degree 3D voxel rotation (spinSpeed: 0.9), exposing setSpinSpeed and setYaw on LandmarkHandle.
    • Added useMonsterRoam.ts to manage wandering waypoints, walking hop bobbing, and hover pause without 2D scale flipping during 3D rotation.
    • Rendered authentic mixed-case Earthbound floating title badges (Apple Kid) above the monster.
  • Temple Grounds Encounter Integration:
    • In TempleGrounds.vue and TempleGrounds.ts, mounted <xp-monster-model> in uncleared combat rooms (monster, miniboss, boss).
    • Resolved active monster avatar dynamically via BestiaryService with fallback to 074.png (Dustbunny).
    • Hid static center action FAB in active combat rooms; tapping the 3D roaming monster directly launches the room battle action sheet.
  • Unit Testing:
    • Added tests/unit/spriteToVoxel.spec.ts asserting RGBA buffer parsing, box consolidation, depth extrusion, and placeholder fallbacks.

Session 2026-10-11: Regenerate 9:16 portrait home background asset

What was done:

  • Home Background Aspect Ratio & Bottom Nav Shelf Alignment:
    • Regenerated src/assets/images/backgrounds/my-home.jpg at 9:16 portrait aspect ratio (768x1376) to replace legacy 2:3 (1024x1536) asset.
    • Eliminated horizontal cropping on mobile viewports.
    • Removed baked-in 2D furniture (bed, table, chairs, barrels, chest), providing clean floor space for interactive 3D voxel models without visual duplication or overlap.
    • Restored and repositioned the decorative horizontal shelf beam and diamond tapestry runner to sit cleanly at the bottom dock zone (bottom 11% of the viewport).
    • Eliminated the doubled lower beam and dark panel beneath the tapestry so the bottom nav bar and XP/GP purse bar sit directly on a dedicated textured background.
    • Preserved authentic 16-bit SNES pixel art style, glowing fireplace hearth, warm candle lighting, wood paneling, and center rugs.

Session 2026-10-11: Full-bleed page background and floating frosted bottom nav dock

What was done:

  • Full-Bleed Viewport Background:
    • Positioned .portal-dock absolutely at the bottom edge in MyPortal.vue and _MyPortal.scss, allowing ion-router-outlet and page ion-content to span 100% of the viewport height.
    • Page backgrounds (my-home.webp, hometown-ground.png, world-map.webp) extend completely behind the bottom nav bar and purse bar.
    • Added frosted glass blur (backdrop-filter: blur(16px)) and semi-translucent tint to XpBottomNav.vue so the underlying room textures diffuse through the nav.
  • Plaza Layout Alignment:
    • Adjusted .my-home-plaza padding in _MyHome.scss to prevent double bottom padding, keeping all voxels aligned with the room rugs without vertical scrollbars.

Session 2026-10-11: Landmark title typography and Earthbound font update

What was done:

  • Typography Overhaul:
    • Replaced all-caps gothic font Pixel Takhisis in XpLandmarkBadge.vue with authentic Earthbound font Apple Kid (font-family: "Apple Kid", "StatusPlz", sans-serif).
    • Restored clean mixed-case readability for landmark titles across all worlds and Hometown (e.g., "The Plains", "Hero's Home", "Gold Bank").
    • Preserved arcade-style high-contrast gold fill (#ffd700) with 4-sided black drop outline and tuned font-weight: normal with letter-spacing: 0.6px.
  • Unit Test Updates:
    • Updated landmarkBadge.spec.ts to assert mixed-case title rendering and uncluttered single-line badge contract.

Session 2026-10-11: Passcode screen click sound effects and UI FX mapping

What was done:

  • UI FX Mapping:
    • Mapped click and klick in src/assets/fx/index.ts for Nintendo (nintendo.Klick), Sony (sony.Navigation), Earthbound (earthbound.click), Chrono Trigger, and Final Fantasy (chronoTrigger.cursor).
    • Registered click in src/lib/engine/audio/soundRegistry.ts (nintendo_click via Klick.wav, sony_click via Navigation.mp3).
    • Added playClickSound convenience helper in src/hooks/useAudio.ts.
  • Passcode DialPad Integration:
    • Wired play$fx("click") on digit presses (appendToCode), backspace (removeLastDigit), clear (clearCode), and toggle show/hide passcode (toggleShowPass) in src/app/SideMenu/SwitchProfile/DialPad.vue.
    • Added play$fx("yes") on passcode match, play$fx("no") on passcode mismatch, and play$fx("select") on dismiss.
    • Safe-guarded controller calls (toastController, alertController, modalController) against null/undefined in test/offline environments.
  • Verification: Created tests/unit/DialPadSound.spec.ts covering registry mappings, $fx.ui mappings, and all DialPad audio triggers; all 9 tests passing green.

Session 2026-10-11: Battle HUD typography, damage visibility, and authentic Earthbound sprites

What was done:

  • Authentic Earthbound Sprite Extraction: Sliced pixel-perfect smash.png (82x28) and you_won.png (69x8) with transparent backgrounds from original sprite sheet into src/assets/images/battle/.
  • Battle Damage & Smash Overhaul:
    • Replaced text smash popup in BattleEnemyStage.vue with authentic animated Earthbound SMAAAASH!! pixel art sprite while preserving screen-reader and DOM text contracts.
    • Increased floating damage numbers from 1.8rem to 3.2rem using Pixel Takhisis with high-contrast outlines for instant readability.
    • Enlarged chore counter label (1.2rem) and attack countdown labels (0.95rem / 1.55rem).
  • Victory Announcement Banner:
    • Rendered authentic YOU WON ! Earthbound pixel banner in BattleVictoryCard.vue with 4x crisp pixel scaling and purple drop shadow.
    • Updated battle outcome resolver in useBattleOutcome.ts to announce "YOU WON!" across all battle victories.
    • Bumped victory subtitle, quest, and work line font sizes.
  • Battle Dialog Typography: Increased BattleDialogBox text from 1.2rem to 1.55rem (Apple Kid / StatusPlz) and prompt to 1.15rem in _BattleField.scss so damage taken and action text are clearly readable.
  • Verification: Ran all 5 BattleField test suites (BattleEnemyStage, BattleVictoryCard, BattleHeroCard, BattleField, XpBattleTaskMenu); all 134 tests passed.

Session 2026-10-11: Battle number ticker font upgrade (Pixel Takhisis)

What was done:

  • Font extraction & installation: Unzipped pixel_takhisis.zip in Downloads and installed pixel-takhisis.otf into src/assets/fonts/earthbound/.
  • Global font-face declaration: Added @font-face definition for "Pixel Takhisis" in src/styles/_fonts.scss.
  • Battle odometer ticker integration: Applied "Pixel Takhisis" font family to .digit in BattleHeroCard.vue for rolling HP and MP ticker tiles.
  • Verification: Ran BattleHeroCard.spec.ts test suite; 36 of 36 unit tests passing.

Session 2026-10-11: Bottom nav MMO UI/UX overhaul and reactive area tracking

What was done:

  • Reactive Area Compass Tracking: Resolved issue where the main area tab failed to update on route changes. Replaced stale Options API reassignment with a computed compass in MyPortal.ts that reactively resolves area name, icon, and link from active route name and route path.
  • Route Name Registration: Added name: "my-party" to my-portal.routes.ts so route resolution handles party navigation consistently.
  • Dynamic Active Tab State: Wired :active="activeNavTab" from MyPortal.ts and MyPortal.vue to XpBottomNav.vue (profile, area, party), highlighting the active location or opened modal.
  • MMO Hotbar Aesthetic: Redesigned XpBottomNav.vue with translucent glassmorphic styling (backdrop-filter: blur(16px)), metallic top border accents, tactile hotbar slot frames, and glowing active states. Removed harsh dashed borders and black blocks.
  • Translucent Dock Ledges: Updated .tab-docked-xp--ledge and .footer-docked-xp to matching translucent glass backgrounds so page backgrounds remain visible behind the navigation dock.

Session 2026-10-11: ChemX audit remediation and test suite stabilization

What was done:

  • Dead vendored assets purged: Removed 18 unused FontAwesome JS files in src/assets/fonts/font-awesome/js/ (~23,000 lines, 20 MB). Icons continue loading cleanly via all.css webfonts. Reduced critical hazards from 65 to 55; token burn dropped from 4.18M to 1.03M ($117/mo); health grade upgraded to 90 (Grade A).
  • Leaked markdown artifact: Removed backtick fence from line 1 of XpTempleCreatorGrid.vue.
  • Render hack eliminated: Replaced setTimeout(..., 0) with nextTick in XpIntroSplash.vue.
  • Timer handle discipline: Added explicit lifecycle tracking and teardown for progressTimer in XpMusicPlayer.vue.
  • BattleField test suite green: Corrected Defend damage expectation in BattleField.spec.ts for Warrior job class (braceFactor: 0.25 yields 1 damage, leaving 29 HP). All 62 test suites and 1,379 tests passing green.
  • WordPress API direction: doit.forthexp.com client endpoints preserved for future backend restoration.
  • Verification gate: Typecheck 0 errors, jest 1,379 passing, ChemX critical hazards down to 52.

Session 2026-10-09/10: the battle made fabulous (supersedes the lists further down)

Where v1 stands. The hero loop (see quests → claim or fight → rewards persist → GM approval → shop) was wired yesterday and verified only in jsdom. Today the battle screen was rendered in Chrome for the first time (Cypress 8.7 headless, 390×844), which exposed a dead arena background after any resize, a one-tap-skips-everything dialog, a 277 px HUD that clipped, soft-locks after Defend/Run, invalid sound keys and a 1-minute clock no real chore can beat. All fixed.

How it was done. Two critique agents (kid-UX, engineering craft) and two bug finders (each finding verified by a skeptic) reviewed the old screen and the design contract; the contract became docs/Battle-Field-Contract-v2.md. Five Sonnet builders took board tasks #25–#29 on disjoint files (stage, checklist sheet, hero card, engine + unit tests, victory card); Fable owned the page wiring, outcome flow, dialog, feedback, docs and tests. See docs/Battle-Field-Architecture.md for the result.

Rules that changed (owner, please confirm): strike ≈ 12% of max HP (was 6–19 flat); clock = 3 minutes per remaining chore via Enemy.attackCooldown (was 1); Defend = glancing hit now + fresh clock (was a free brace that double-struck); Run Away confirms first; free fights pay AP only; quests with "requires approval" are held as pending from the arena too; every fight ends at full HP (the hospital heal is still a stub).

Verification gate: typecheck 0, lint 0 errors, jest green (5 new battle specs: stage 49, hero card, checklist, victory card, engine 51, page 4), Cypress battle walk-through renders every phase at 390×844 (screenshots under tests/e2e/screenshots/battle.spec.js/, ignored by git). Hands-on: sign in, open /battle.

Open on the board: #13 (full browser walk-through of the whole loop), #19–#24 as before.


Session 2026-10-09 (supersedes the next-steps list further down)

How work is organised now. The backlog lives in this project's chemx team board (chemx team task list --all); each task carries its full spec as a comment. Fable writes specs and reviews; Sonnet/Haiku agents claim (chemx team task claim <id> --as=@handle), implement, and close (done <id> --force, because the AST gate is red on this legacy code). Waves ran on disjoint file sets.

Gate at 2026-10-09 ~02:40: typecheck clean, lint 0 errors, 10 unit suites / 320 tests passing, lockfile frozen-install OK, production build green (195 MB).

Landed today (nothing seen in a browser yet at the time of writing): battle page spec (#1); temple return carries the floor, cleared rooms unlock and survive reload (#2); Game Master gating with GM-only toggle, PIN, masquerade clean-up, legacy "user 1" fallbacks removed (#3, #18); quest board shows Pending vs Tamed (#4); My Home routes carry the hero id (#5); asset diet part 1, 225 → 195 MB (#6); dev routes and Support dev tools gated to non-production (#7); lang="ts" on every external SFC script (#8, #17); docs cleanup (#9, #16); orphan sweep, 23 files (#10); random encounters every 2–4 min on Home Town / World Map (#11); shop loop: real purchases, purchase log, GM fulfil/refund (#12); temple progress persisted per hero (#14); backup/restore everything (#15). Fable: battle rebuild fix-ups (victory strobe, hero id on cleared rooms), "New Temple" route name.

Open on the board: #13 browser walk-through as a Cypress e2e suite (running), #19 encounters on region pages, #20 asset diet part 2, #21 remove the dead WordPress API, #22 GM-only restore + native file export, #23 persist chests/doors, #24 family-settings gating + PIN for legacy GM profiles.

Known limitations: battle BGM is remote (silent offline); Goods/Abilities are off the battle menu until items have effects; profile export/backups don't save files inside native shells (#22); chemx's reader is blind inside defineComponent bodies (elysium #939), so agents fall back to bounded raw reads.


Session 2026-10-08 (paused mid-work, resume here)

Diagnosis. A 14-agent subsystem map (journal: ~/.claude/projects/-home-xopher-www-x-do-it-for-the-xp/33038804-2dfd-48ae-b87e-77d889f71ea8/subagents/workflows/wf_c5cce08c-88c/journal.jsonl) found the core loop was never wired: a hero could see quests, but Claim wrote nothing, awarded nothing, and no approval queue existed; rewards only existed inside battles, and even those Pinia stat changes were never written to ProfileDb (lost on reload). The remote WordPress API (doit.forthexp.com) is gone (404). Production build passed but was 225 MB (165 MB images via require.context("@/assets/images/")).

Done this session (uncommitted, on disk):

  • Toolchain: pnpm migration gaps fixed (@types/webpack-env, ts-jest), ambient src/types/shims-vue.d.ts (typecheck went 242 → 0 errors), typecheck/test scripts, chemx installed (.mcp.json, .cursor/.vscode mcp.json, chemx:* scripts, .chemx/index.db), explicit .ts extensions on 33 <script src> tags (vue-jest), scaffold example.spec.ts removed, isMonsterToken accepts M01_/M01! (hydrator test green).
  • Backbone: src/lib/databases/QuestLogDb.ts (completion records), src/lib/engine/quests/QuestSchedule.ts (+11 unit tests: once/daily/weekly/custom windows), QuestEngine.getQuestBoardForUser/getOpenQuestsForUser, src/lib/services/quests/QuestCompletionService.ts (completeQuest / approveCompletion / rejectCompletion / recordBattleCompletion), userStore.persistUser() called by every stat mutator (XP/GP/HP/AP/class/pegasus/slots now persist).
  • Bug fixes: post-logout lockout (requiresAuth:false on xp-profile/xp-intro/xp-demo), stopImpersonating returns to the real GM (xp_impersonator_id), User.setName parser (nick defaults to first name), GM Bonus/Penalty now goes through store actions (was writing stats.xp.total), four world maps pushed unregistered temple ids (now earth/storm/light/ice/shadow), Leave-Temple route names, XpTemples.vue creator route, GM tab captions, notification/party settings links, capacitor.config.json no longer hardcodes a LAN dev server, window.unlockPegasus dev-only, profileStorage moved to src/lib/databases/profileStorage.ts, SplashScreen type to IntroSplash/types.ts.
  • Delegated and finished (all typecheck/lint clean, verified in jsdom only, never opened in a browser): hero side (MyQuests board with Tamed state, real MyTask Claim with approval path and live counters, MyCalendar on the board), GM side (/game-master/approvals route, real XpApprovals page with History tab, live dashboard Approvals tile), toolchain (jest now pnpm-aware with a require.context shim, BattleGround.spec modernised, 17/17 tests, lint 0 errors, chemx build green, stale XpSettingsHome.js deleted). approveCompletion/rejectCompletion got an in-flight guard after a double-pay race was measured.
  • Follow-ups the agents surfaced: QuestBoardItem should expose pending so pending claims read "Pending" not "Tamed"; /calendar, /storage, /craft-item, /cook-food routes drop :userId (MyCalendar now falls back to currentUser); MyQuests never registers Swiper (pager likely inert); MyCalendar prints raw dueByTime; ~30 .vue files need lang="ts" on <script src> before jest can mount them; chemx build --help runs a real build.

Battle rebuild (later the same day, paused mid-wiring): BattleField was rebuilt from an 1,865-line page into a thin page over battle/* (context, encounter loader, rewards) and composables/* (dialog, outcome, background, audio, ATB display) plus BattleDialogBox / BattleEnemyStage components; see docs/Battle-Field-Architecture.md. Routes are now /battle/:userId/{quest|temple|free}/... (battle-quest, battle-temple, battle-free); the old battle-field* routes are gone. Fixed: 0-XP victories, unwinnable multi-beast fights (next beast steps forward), click-gated rewards (now committed at victory), no outcome recording (quest log entry + temple room cleared), always-returning-to-hometown (returns to origin). Goods/Abilities dropped from the battle menu until items have in-battle effects; in-page dev tools removed. State: typecheck clean, lint 0 errors, tests/unit/BattleContext.spec.ts green. Two agents were still running when paused: (a) dead-scaffolding sweep (BattleGround.ts, engine/battle, hooks/battle, BattleroomDevTools, battleroom config/scripts, dev battle routes, battle-store encounter helpers, random-encounter runaway fix); (b) navigators (TempleGrounds Fight + cleared-room UX, room-editor Test Fight, MyTask "Fight!" for beast quests, new __tests__/BattleField.spec.ts). Their edits land on disk regardless; read their reports first. A vue-cli-service serve dev server is up on :8100 (pid 378139).

Both agents finished before the pause: the dead-scaffolding sweep is complete (27 files removed, battle store trimmed, random-encounter runaway fixed) and the navigators are wired (temple Fight + cleared-room check marks, room-editor Test Fight, MyTask "Fight!" on beast quests). Not done: __tests__/BattleField.spec.ts (the folder was removed with the old spec; recreate it). Two gaps found and NOT yet fixed: (1) a temple fight resumed after a hard reload returns to floor 1F and markRoomCleared is a no-op because the temple route has no level and no in-memory state (carry level on the return route, e.g. as a query, and let markRoomCleared create state); (2) lockOnEnter rooms lock all doors on entry and nothing unlocks them on victory, so a hero can be stuck after winning (clear room.locked in TempleSystem.markRoomCleared). Newly orphaned, left in place: XpFabBattleActions.vue, hooks/useDialog.ts, the cross-env devDependency, docs/App/SideMenu/GameMaster/Battleroom-Dev-Tools.md.

Next steps (in order): 1) run chemx typecheck && chemx lint && chemx test, then chemx build; 2) open the app in a browser (dev server :8100) and walk the loop end to end (nothing above was seen rendered), then commit; 3) fix the two temple gaps above and write BattleField.spec.ts; 4) remaining battle wiring: battle-field-quest must load the quest's beast (BattleField.ts ~1615-1630 TODO) and call recordBattleCompletion on victory; 3) XpDashboard.ts "New Temple" route name (xp-temple-creator → xp-temple-settings); 4) GM gating: expose the isAdult checkbox in AddProfile and guard /game-master; 5) shop purchase → GM-visible record; 6) asset diet (require.context scopes, backgrounds) before any native build; 7) delete the dead files listed in the map (LogIn copy.vue, XpFabPageShortcuts copy.vue, [AppJig], MyAchievements, ProfileCards, OldSchoolHeader, AchievementsCard, XpTabBarPage, importWindTemple.ts, dsl-test-temple.ts, BattleGround.ts after audit). See Roadmap → "v1 Completion Plan".


Project State Overview

Do It For The XP is a gamified chore management application built with Vue 3, Ionic 7, and Capacitor. The application transforms household tasks into RPG-style quests where children become "Bounty Hunters" and parents become "Game Masters."


Recent Development Focus

Random Battle Training Dummy Update (2026-10-10)

  • Random Background: Dummy encounters now dynamically randomize bg1 and bg2 across the valid earthbound background spectrum (0-325) rather than relying on static fallback defaults.
  • Random Beast Avatar: The dummy enemy now assigns a random avatar from the 73 available beast portraits (1-73) instead of rendering without an image.

World Map 3D Voxel Stages (2026-10-10)

  • All 9 Voxel Stage Models: Built voxel geometries in stageShapes.ts inspired by map icons:
    • Plains (whirling tornado vortex)
    • Forests (pine and canopy trees with mushrooms)
    • Islands (tropical palm atoll and ocean)
    • Swamps (mossy skull totem)
    • Mountains (twin snow-capped volcanic peaks)
    • Sands (desert saguaro cactus with arms)
    • Clouds (thundercloud with electric lightning bolt)
    • Tundras (arctic snow igloo with arched entryway)
    • The Moon (cosmic crescent with glowing celestial star)
  • Organism Component: Created XpStageModel organism with 30 FPS idle throttling, 60 FPS drag rotation, pixelRatio: 1, tab visibility pause, <xp-landmark-badge> atom integration, and route navigation.
  • World Map Plaza Layout: Arranged in WorldMap.vue with 4-row layout leaving the center 140px clearing for the navigation FAB and safe top clearance below HUD bars.
  • Unit Tested: Full Jest suite in stageVoxel.spec.ts covering box counts, positions, normals, colors, indices, and fallback handling.

Interface Polish (In Progress)

Refining the core UI elements for a premium RPG feel.

  • ✅ Main User HUD:
    • Combined HP/MP bar and text labels for cleaner layout.
    • Improved label visibility and alignment (text below bars).
    • Grouped stat values for better readability.
    • Added animated GP Bar stacked above XP Bar.
    • Applied locale formatting to all HUD numbers (1,000 instead of 1000).
    • Menu Toggle: Implemented menuController logic for the retro menu button to sync functionality with Quick Draw.
  • ✅ Battle Task Menu Style: Adjusted "Attack" menu items and "Bash" costs to match the main RPG menu font (Apple Kid 1.5rem) and color (RPG yellow). Replaced the bolt icon with claw-marks and removed the redundant header for a cleaner, unified flow. removed background circles from icons.
  • ✅ Area FAB / Page Menu:
    • Centered menu on screen (matching User HUD aesthetic).
    • Added backdrop blur overlay with click-to-close.
    • Implemented "square-x" close button in top-right.
    • Fixed Ionic FAB visibility issues by moving menu outside ion-fab-list.
    • Synchronized Blur State: Fixed "phase-flipping" and "double-click" issues by letting Ionic handle natural toggles and forcing re-mounts on navigation via unique :key bindings.
  • ✅ User HUD Avatar:
    • Optimized avatar image registration to perfectly cover the circular FAB button.
    • Removed square green border artifacts and optimized hover scaling (1.12x).
    • Improved AP badge display with "AP %" prefix.
  • ✅ Navigation Highlighting:
    • Implemented global styles to dim non-active tabs in ion-tab-bar.
    • Non-selected tabs are grayscale (90%) and lower opacity (0.55).
    • Active tabs feature saturation boost, brightness increase, and a subtle vertical lift (translateY).
    • Added hover transitions for interactive feedback.
  • ✅ Equipment Modal:
    • Converted into a full-page Ionic card modal with presentation="card".
    • Integrated with the shared premium modal system (matching Profile Modal).
    • Added user identity (name/level) to modal header for consistency.
    • Simplified layout styles while maintaining the 7/5 grid split.
  • ✅ Modal Dismissal System:
    • Ref-Based Dismissal: Standardized all major modals (UserProfileModal, XpEquipmentModal, ItemInfoModal, ATMModal, SaveAndQuitModal) to use a local dismiss() method via a component ref.
    • Sound Logic Refinement: Resolved the "double close sound" issue by using @click.stop on close buttons to prevent event bubbling to global UI listeners.
    • Clean Event Flow: Decoupled the parent's close state from the button click, moving to the modal's native didDismiss lifecycle event to ensure single-emission logic.
  • ✅ Temple Navigation: Implemented state-based smooth scrolling, formalized /splash default routing, and tiered background strategy (parent-hosted vs child-transparent).
  • ✅ Quest Type Refactor: Replaced standard radio groups in XpConfigAchievement with iconic, dialpad-grid selection modals. Implemented generic XpTypeSelectorModal for streamlined Quest and Party type definition.
  • ✅ Quest Navigation Optimization: Refactored XpConfigAchievement to use nested routing and ion-tabs, mirroring the Temple Settings architecture for consistent GM experience. Updated child tabs (Type, Heroes, Schedule, Rewards, Config) to individual components with shared state via Provide/Inject.
  • ✅ Temple Splash Page:
    • Created a clean landing page for temple routes with a centered layout.
    • Header: Icon, title, and description centered at top.
    • Stats: 4-column responsive grid showing Rooms, Beasts, Floors, and World.
    • WeatherFX: Integrated with correct world-to-weather mapping (matching XpTemples.vue).
    • Navigation: Centered "Temple" tab in navigation bar using the temple's specific icon.
  • ✅ Quest Type Selection:
    • Replaced ion-radio-group with two clean, iconic action boxes for Quest Type and Party Type.
    • Implemented XpTypeSelectorModal: a generic, two-step selector (Grid -> Confirmation) matching the temple creator aesthetic.
    • Updated useAchievementForm hook with reactive state for modal visibility and active party type details.
  • ✅ Code Refactoring: Split XpConfigAchievement.vue into separate template (.vue), logic (.ts), and style (.scss) files for better maintainability.
  • ✅ Setup Slideshow & Dashboard Polish:
    • Dynamic Themed Backgrounds: Integrated with the global bg-slide system, applying color variations (.bg-slide-xp, .bg-slide-gp, etc.) to the ion-page for stable, high-performance background transitions.
    • Premium Glassmorphism: Implemented a modern design language using backdrop-filter: blur, subtle semi-transparent borders, and deep shadows for "floating" content cards.
    • Stat Counting Animations: Integrated vue3-autocounter into the shared XpStatBox, providing a satisfying data revealed effect when dashboards load.
    • Dashboard Grid Refinement: Updated XpDashboardGrid to support a :cols prop for explicit column control. Configured the WelcomeDashboard to a 3-column layout (3x2 for the 6 boxes) as requested by the GM.
    • Entrance Animations: Added cubic-bezier staggered entrance animations for hero cards and dashboard components to enhance the "alive" feel of the onboarding flow.
    • Custom Navigation: Replaced standard swiper arrows and bullets with themed, RPG-style indicators matching the Earthbound aesthetic.
  • ✅ Code Quality & Linting: Performed a global cleanup of ESLint errors and warnings across the codebase, including removal of unused imports, console statements, and duplicated methods in major components like BattleGround.ts, BattleState.ts, and useAchievementForm.ts.
  • ✅ Bestiary Index Fix: Resolved critical syntax and structure errors in XpBestiary.vue caused by misplaced braces and broken method blocks. Refactored clickAttachBeast to use clean async/await logic. Fixed spelling errors in DbStorageApi toast helpers.
  • ✅ Quest Index Icons:
    • Implemented LORE_COMBO_MATRIX shared constant for mapping Quest Type + Party Type to thematic icons/names.
    • Updated XpAchievementItem to display dynamic "Combo Icons" or "Beast Previews" in the avatar slot.
    • Integrated beast loading into XpAchievements.vue to ensure real-time beast avatars show in the quest index.
    • Enhanced Grid View in admin quest index to match the iconic combo logic.
    • Updated useAchievementForm summary card to reflect the new lore-based naming and iconography.
  • ✅ Beast Selection UI:
    • Removed the heavy "TARGET ACQUIRED" overlay in QuestTypeTab.vue.
    • Simplified the selection indicator by using XpBeastSelectorItem's native checkmark and border logic.
  • ✅ Beast Task List:
    • Replaced the alertController (which failed to render HTML) with a dedicated BeastTaskListModal.vue.
    • Implemented a premium glassmorphic list with staggered entrance animations for beast tasks.
  • ✅ UI Polish: Synchronized Area FAB blur, optimized Avatar presentation, standardized Ref-based modal dismissal, implemented global tab-bar highlighting, added a premium splash page for temple discovery, fixed the retro User HUD menu toggle, and matched the "Attack" task menu styles to the main RPG dialog menu (removing headers and updating icons).
  • ✅ Compendium Tab Root Navigation: Resolved a bug where clicking an active tab's subtree (e.g., editing a quest) wouldn't return to the tab's root index. Implemented handleTabClick in XpCompendium.vue to intercept clicks and force-navigate to the base tab route when already within its subtree.
  • ✅ Room Editor Toggles Fix: Resolved double-triggering bug on "It's a Trap" and Mimic toggles where clicking the switch itself failed to toggle.
  • ✅ AI Generate Card Alignment: Corrected the sizing of the AI Generate box in QuestTypeTab.vue to match other beast cards. Implemented aspect-ratio: 1/1, increased dashed border thickness, and added structural alignment spacers to ensure a perfectly uniform grid layout.

Temple Creator (Refinement Complete)

The Temple Creator tool has been consolidated and polished for a more cohesive experience.

Location: src/app/Admin/XpCompendium/views/XpTemples/

Recent Accomplishments:

  • ✅ Consolidated Editor: Removed redundant TempleFloorEditor.vue and unified all editing logic into the Layout tab (XpTempleLayout.vue).
  • ✅ Centered Grid Layout: Optimized the grid editor to be centered with the page for better focus and premium aesthetic.
  • ✅ Integrated Header: Re-enabled XpTempleCreatorHeader.vue within the layout tab for seamless grid resizing.
  • ✅ Popover Sync: Updated the quick-edit popover with full feature parity, including item/loot selection.

Current State:

  • ✅ Room type selection modal complete
  • ✅ Cardinal door system (N/E/S/W) with locks
  • ✅ Adjacent room detection for wall limiting
  • ✅ Monster room beast selector integration
  • ✅ Room navigation within editor
  • ✅ Loot room configuration complete
  • ✅ Shop room configuration complete
  • ✅ Smooth navigation return paths with auto-scroll and highlight
  • ✅ Dynamic accordion tier isolation for beast management

Key Components:

  • XpTempleLayout.vue - Unified editor and layout preview
  • components/RoomCardinalLayout.vue - Room direction/door UI
  • components/XpTempleCreatorHeader.vue - Floor controls

Battle System (Stable)

The battle system has been recently enhanced:

  • ✅ Proper player stats HP/MP calculation (level + class based)
  • ✅ Battle HUD with animated stats display
  • ✅ Integrated action menu in dialog box
  • ✅ Intro dialog messages before battle starts
  • ✅ Pinia migration complete (Vuex fully removed)

Architecture Quick Reference

State Management

All stores are Pinia-based in src/lib/store/stores/:

  • user.ts - User profiles, authentication, GP
  • game.ts - Global game state, theme, entity caching
  • battle.ts - Battle state management
  • audio.ts - Sound control
  • temple-creator.ts - Temple builder state

Engine Structure

src/lib/engine/
├── battle/           # Combat logic
├── core/dungeons/    # Temple system
└── temples/          # Pre-built temples

Component Hierarchy

components/
├── atoms/       # Basic primitives
├── molecules/   # Composed units
└── organisms/   # Complex features

Active Systems & Features

  • 3D Voxel Landmark System:
    • Unified Shared WebGL Landmark Renderer (sharedLandmarkRenderer.ts): All buildings, stages, and temples share a single offscreen WebGL context and blit onto 2D canvases, preventing mobile WebGL context exhaustion (8/16 limit) and context loss crashes (x_x canvases) during Ionic page navigation.
    • Interactive Three.js WebGL voxel models for all 9 Temples (XpTempleModel).
    • Interactive 3D voxel models for all 7 HomeTown destinations matching navigation menus 1:1: Hero's Home, Market, Hospital, Hotel, Bank, Town Hall, and The Plains (world-plains leave town gateway located at the north plaza path between Town Hall and Gold Bank).
    • Center page menu FAB retired in MyPortal.vue as 3D voxel models provide direct 1:1 tactile navigation across plazas.
    • Interactive 3D voxel models for all 9 World Land shops: Pegasus Ranch, Wrecked Ship, Hermit's Tent, Crystal Caverns, Pond of Life Oasis, Witch's Hut, Snow Shack, Cloud Market, Theia City Emporium.
    • Interactive 3D voxel models for World Travel Pegasus (pegasus) across all 8 World Region views (Mountains, Clouds, Desert, Forest, Ice, Islands, Moon, Swamps) providing 1:1 tactile navigation matching page menus.
    • Interactive 3D voxel models for Hometown return gate (home-town) on World Plains, syncing 1:1 with userActions (preserving World Map purely for the 9 world stages).
    • Interactive 3D voxel models for Home interior menu landmarks aligned with room background art: Cozy Bed (home-bed) top-left on bed, My Storage (home-storage) top-center, My Workbench (home-workbench) middle-left, My Kitchen (home-kitchen) middle-right, My Calendar (home-calendar) bottom-left on rug, and Front Door (home-door) bottom-center on entrance mat.
    • Direct camera-facing idle orientation, manual touch/drag rotation, smash-style floating titles (title-only retro pixel font with thick black outline, removing black pill boxes and sublabel clutter), and click-to-enter routing (auto-rotation and idle bobbing disabled for 0% idle GPU draw calls; renders on-demand on drag and initial load).
    • Modern iOS Minimalist Bottom Navigation (XpBottomNav.vue): Borderless, transparent tabs with frosted glass dock, 0.5px hairline top border, muted inactive states, and vibrant gold active highlighting without clunky box borders or inset shadows.
    • Bottom dock clearance (+120px) and top safe area clearance (+5.5rem) preventing HUD and hairline overlay.
    • Full unit test coverage in templeVoxel.spec.ts (9/9 passed) and buildingVoxel.spec.ts.

Immediate Next Steps

  1. Loot Room Configuration - Complete treasure chest reward selector
  2. Room Data Persistence - Ensure room edits save to temple
  3. Room Validation - Must have entrance, boss for temples
  4. Template Rooms - Pre-configured room types

Known Issues / Blockers

  • Battle dialog may show duplicate intro messages (recently fixed)
  • Wall icons occasionally show wrong icon type (recently fixed)
  • Floor editor grid size needs custom dimensions (recently fixed)
  • ✅ Navigation Crash: Fixed a TypeError: Cannot read properties of undefined (reading 'preventDefault') in WorldPlains.ts when navigating via FAB shortcuts.
  • Area FAB menu was invisible due to Ionic ion-fab-list opacity transitions (recently fixed)

Key Documentation

Doc Purpose
Roadmap Overall project direction
Architecture Technical overview
Temple-System Dungeon engine
Battle-System-Engine Combat mechanics
Player-Stats-Leveling HP/MP formulas

Quick Start for New Context

  1. Read: docs/Roadmap.md - Understand current phase
  2. Read: docs/current_context.md (this file) - Get oriented
  3. Check: Active files in XpTemples/ - Temple Creator focus
  4. Review: lib/store/stores/ - State architecture

Session 2026-10-11 (Fable + Sonnet builders on the chemx board, tasks #886–#913)

Landed on master (all local, not pushed): Powers privilege ledger Phase 1 (AP total on profile/HUD; My Powers page with Cast; per-hero cast log; Town Crier chat line + power-cast notification; AP stamped at completion); Class Codex (full-screen, from the equipment dock) and the hybrid class tree 4 → 8 → 3 (Knight/Berserker, White/Black Mage, Assassin/Ranger, Martial Artist/Mystic; Paladin/Ninja/Sage as crown classes; passives composed from existing fields); quests carry timesOfDay (calendar tabs work, N-a-day chores as one quest, timed seed, GM chips); first-grade intro copy; RPG toasts everywhere with X + swipe; dungeon dialogs as pixel reveals (riddle, shop, room actions with art), temple-cleared egg reveal, encounter reveals with beast art, chests open closed; onboarding gates (first Pegasus unlocks the overworld; whistle = fast travel); 3D look builder in profile creation + full-screen face picker; profile edit no longer wipes fields; teleports pair themselves; any door into a boss room is the Boss door; Master Room = Pegasus Egg chamber (golden egg icon), Boss Key naming, full-screen room type guide with evenly spaced dock rail options; test script runs jest directly.

Rules decided by the owner today: AP is never spent; privileges are cast with MP; the ledger is the feature, nothing enforced; controls at the bottom within thumb reach; money-valued things stay in shops.

Open: Phase 2 of the Powers spec (rolling windows, duration timer, caps); the "empty player screen" the owner wants improved (which screen is unanswered); Pegasus chest with a checklist (offered); spell skill tree spec; Class Codex "In real life" copy for crown classes; chemx verify test step times out on the full ~6 min suite; other-session work in flight (scene transitions, apiHost, sharedLandmarkRenderer typecheck errors). Spec: docs/superpowers/specs/2026-10-11-powers-privilege-ledger-design.md.

⚠️ **GitHub.com Fallback** ⚠️