diff --git a/assets/theme-v2/js/tool-display-mode.js b/assets/theme-v2/js/tool-display-mode.js
index e77b7a9df..08bada607 100644
--- a/assets/theme-v2/js/tool-display-mode.js
+++ b/assets/theme-v2/js/tool-display-mode.js
@@ -154,11 +154,6 @@
body.appendChild(navigationRow);
} catch (error) {
console.warn("Tool navigation could not be loaded.", error);
- const diagnostic = document.createElement("p");
- diagnostic.className = "status";
- diagnostic.setAttribute("role", "status");
- diagnostic.textContent = "Tool navigation is temporarily unavailable. Refresh the page or try again shortly.";
- body.appendChild(diagnostic);
}
}
diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt
index 2a3c37ce3..15213f1d6 100644
--- a/docs_build/dev/reports/codex_changed_files.txt
+++ b/docs_build/dev/reports/codex_changed_files.txt
@@ -1,54 +1,78 @@
-# Codex Changed Files - PR_26171_061-text2speech-engine-audio-feature-parity
-
-## Git Workflow
-- Starting branch: `main`.
-- Created branch: `pr/26171-061-text2speech-engine-audio-feature-parity`.
-- Initial commit: `e4541d63719ab777b0654c8fecf4b13237d31256`.
-- PR branch was merged with `origin/main` during PR conflict recovery.
-- Conflicts were limited to generated report artifacts.
-
-## Scoped Diff Stat
-```text
-...R_26171_061-engine-audio-ownership-checklist.md | 25 +
- ...R_26171_061-instruction-compliance-checklist.md | 32 +
- .../PR_26171_061-manual-validation-notes.md | 27 +
- ...R_26171_061-old-tts-feature-parity-checklist.md | 48 ++
- ..._061-text2speech-engine-audio-feature-parity.md | 71 ++
- docs_build/dev/reports/PR_26171_061-validation.md | 42 +
- docs_build/dev/reports/codex_changed_files.txt | 118 +--
- .../dev/reports/coverage_changed_js_guardrail.txt | 7 +-
- .../dev/reports/playwright_v8_coverage_report.txt | 36 +-
- src/engine/audio/TextToSpeechEngine.js | 208 ++++-
- .../tools/TextToSpeechFunctional.spec.mjs | 30 +
- toolbox/text-to-speech/index.html | 119 +--
- toolbox/text-to-speech/text2speech.js | 853 +++++++++++++++++----
- 13 files changed, 1317 insertions(+), 299 deletions(-)
-```
-
-## Changed Files
-- src/engine/audio/TextToSpeechEngine.js
-- toolbox/text-to-speech/index.html
-- toolbox/text-to-speech/text2speech.js
-- tests/playwright/tools/TextToSpeechFunctional.spec.mjs
-- docs_build/dev/reports/coverage_changed_js_guardrail.txt
-- docs_build/dev/reports/playwright_v8_coverage_report.txt
-- docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md
-- docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md
-- docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md
-- docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md
-- docs_build/dev/reports/PR_26171_061-validation.md
-- docs_build/dev/reports/PR_26171_061-manual-validation-notes.md
-- docs_build/dev/reports/codex_review.diff
-- docs_build/dev/reports/codex_changed_files.txt
+# PR_26171_042 Codex Changed Files Report
+
+## Instruction Compliance Gate
+
+- Current branch before execution: `main`
+- Required execution branch before PR branch: `main`
+- Branch validation: PASS
+- Clean repository before branch creation: PASS
+- PR owner/parity: PASS, `042` is even and Idea/Tool Display navigation scope maps to PC / Environment 1.
+- Implementation path: PASS, active Idea Board and Theme V2 files only.
+- Validation scope: PASS, targeted Idea Board, targeted Toolbox route for Idea Board, and workspace contract lane because shared Tool Display Mode behavior changed.
+- Required reports: PASS, `docs_build/dev/reports/codex_review.diff` and this report are updated.
+- ZIP requirement: PASS, `tmp/PR_26171_042-idea-board-navigation-fallback-cleanup_delta.zip` is required and produced before final delivery.
+
+## Git Workflow Fields
+
+- Created branch: `codex/pr-26171-042-idea-board-navigation-fallback-cleanup`
+- Push result: PASS, branch pushed to `origin/codex/pr-26171-042-idea-board-navigation-fallback-cleanup`.
+- PR URL: `https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/19`
+- Merge result: recorded in final Codex delivery after GitHub merge returns the merge SHA.
+- Final main commit: recorded in final Codex delivery after returning to `main` and pulling latest.
+- Conflict resolution: PASS, merged latest `origin/main` (`9df4942226b0c1a25cfc9567040fc237d90df8f9`) and resolved conflicts only in singleton generated report artifacts.
+
+## Scoped Files
+
+- `assets/theme-v2/js/tool-display-mode.js`
+- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
+- `tests/playwright/tools/ToolboxRoutePages.spec.mjs`
+- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md`
+- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md`
+- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md`
+- `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
+- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
+- `docs_build/dev/reports/codex_review.diff`
+- `docs_build/dev/reports/codex_changed_files.txt`
+
+## Requirement Evidence
+
+- PASS: Removed creator-visible Tool Display Mode navigation diagnostic fallback. `tool-display-mode.js` now logs the navigation load failure to console only and appends no status paragraph.
+- PASS: Removed visible message `Tool navigation is temporarily unavailable. Refresh the page or try again shortly.`
+- PASS: Idea Board stays usable when registry-backed navigation cannot load. Static/no-registry Playwright path expands notes and adds a note successfully.
+- PASS: Creator-facing UI does not mention server, API, local server, port, registry, snapshot, or implementation details in the navigation fallback area.
+- PASS: Navigation failure does not affect Idea Board table functionality.
+- PASS: API-backed local route validated by targeted Idea Board and Toolbox route Playwright.
+- PASS: Static/no-registry route behavior validated by targeted Idea Board Playwright with the registry snapshot returning no data.
+- PASS: Optional previous/next navigation is omitted when unavailable.
+- PASS: Idea Board lifecycle, Show filter, Create Project, Archive, chevron, and table row editing behavior were not changed.
## Validation
-- PASS: `node --check src\engine\audio\TextToSpeechEngine.js`.
-- PASS: `node --check toolbox\text-to-speech\text2speech.js`.
-- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs`.
-- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`.
-- PASS: `npm run test:workspace-v2` (legacy command name; user-facing language is Project Workspace).
-- PASS: `git diff --check`.
-- PASS: Post-conflict validation rerun after merging `origin/main` into the PR branch.
-
-## ZIP
-- Path: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip`.
+
+- PASS: `node --check assets/theme-v2/js/tool-display-mode.js`
+- PASS: `node --check toolbox/idea-board/index.js`
+- PASS: `node --check tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
+- PASS: `node --check tests/playwright/tools/ToolboxRoutePages.spec.mjs`
+- PASS: `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000`
+- PASS: `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000`
+- PASS: `npm run test:workspace-v2`
+- PASS: `git diff --check`
+- SKIP: Full samples smoke, per user instruction.
+
+## Coverage Evidence
+
+- PASS: `docs_build/dev/reports/playwright_v8_coverage_report.txt` updated.
+- PASS: `docs_build/dev/reports/coverage_changed_js_guardrail.txt` updated.
+- PASS: Changed runtime JS coverage lists `assets/theme-v2/js/tool-display-mode.js` at 64% advisory function coverage.
+
+## ZIP Contents
+
+- `assets/theme-v2/js/tool-display-mode.js`
+- `docs_build/dev/reports/codex_changed_files.txt`
+- `docs_build/dev/reports/codex_review.diff`
+- `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
+- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
+- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md`
+- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md`
+- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md`
+- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
+- `tests/playwright/tools/ToolboxRoutePages.spec.mjs`
diff --git a/docs_build/dev/reports/codex_review.diff b/docs_build/dev/reports/codex_review.diff
index 98f10d77f..19a61b590 100644
--- a/docs_build/dev/reports/codex_review.diff
+++ b/docs_build/dev/reports/codex_review.diff
@@ -1,1995 +1,465 @@
-diff --git a/docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md b/docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md
-new file mode 100644
-index 000000000..5e18e0955
---- /dev/null
-+++ b/docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md
-@@ -0,0 +1,25 @@
-+# PR_26171_061 Engine Audio Ownership Checklist
-+
-+## Engine Ownership
-+
-+- PASS: Reusable TTS voice filtering lives in `src/engine/audio/TextToSpeechEngine.js`.
-+- PASS: Reusable TTS preset shaping lives in `src/engine/audio/TextToSpeechEngine.js`.
-+- PASS: Reusable TTS queue item helpers live in `src/engine/audio/TextToSpeechEngine.js`.
-+- PASS: Existing defaults remain in `src/engine/audio/TextToSpeechDefaults.js`.
-+- PASS: Active toolbox UI consumes the engine module instead of duplicating all engine behavior locally.
-+
-+## Active Tool Ownership
-+
-+- PASS: Active tool remains under `toolbox/text-to-speech/`.
-+- PASS: Active HTML remains Theme V2 only.
-+- PASS: Active JavaScript remains external.
-+- PASS: Active tool owns DOM wiring, status display, and control event handling.
-+- PASS: Active tool does not create database behavior.
-+
-+## Boundary Checks
-+
-+- PASS: No `tools/text2speech/` path was created.
-+- PASS: Archived `old_text2speech-V2` was used as a read-only functionality sample.
-+- PASS: Archived tool files were not activated in navigation.
-+- PASS: Browser SpeechSynthesis is the implemented local provider.
-+- PASS: Planned providers remain documented but do not block browser preview.
-diff --git a/docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md b/docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md
-new file mode 100644
-index 000000000..ffb2cb288
---- /dev/null
-+++ b/docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md
-@@ -0,0 +1,32 @@
-+# PR_26171_061 Instruction Compliance Checklist
-+
-+## Pre-Work Gate
-+
-+- PASS: Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` before file changes.
-+- PASS: Read `docs_build/dev/PROJECT_MULTI_PC.txt` before file changes.
-+- PASS: Reported instruction compliance PASS/FAIL before file changes.
-+- PASS: `git branch --show-current` reported `main` before branch creation.
-+- PASS: `git checkout main` completed before branch creation.
-+- PASS: `git pull origin main` completed before branch creation.
-+- PASS: `git status` reported a clean working tree before branch creation.
-+- PASS: Created branch `pr/26171-061-text2speech-engine-audio-feature-parity` from clean latest `main`.
-+
-+## Owner And Parity
-+
-+- PASS: PR number `061` is odd.
-+- PASS: Odd parity maps to Laptop / Environment 2.
-+- PASS: Text To Speech / TTS is owned by Laptop / Environment 2.
-+- PASS: Implementation path matches active owner path: `toolbox/text-to-speech/`.
-+- PASS: Shared engine path matches approved reusable audio path: `src/engine/audio/`.
-+
-+## Hard Stop Checks
-+
-+- PASS: Instructions were present and readable.
-+- PASS: Branch workflow could be followed.
-+- PASS: Repository was clean before branching.
-+- PASS: No owner mismatch.
-+- PASS: No parity mismatch.
-+- PASS: No wrong implementation path.
-+- PASS: Scoped validation was not skipped.
-+- PASS: Required reports were created.
-+- PASS: Required repo ZIP was created.
-diff --git a/docs_build/dev/reports/PR_26171_061-manual-validation-notes.md b/docs_build/dev/reports/PR_26171_061-manual-validation-notes.md
-new file mode 100644
-index 000000000..3341b14ba
---- /dev/null
-+++ b/docs_build/dev/reports/PR_26171_061-manual-validation-notes.md
-@@ -0,0 +1,27 @@
-+# PR_26171_061 Manual Validation Notes
-+
-+## Manual Review
-+
-+- Confirmed active Text To Speech path is `toolbox/text-to-speech/`.
-+- Confirmed no `tools/text2speech/` directory was created.
-+- Confirmed old functionality sample path is `archive/v1-v2/tools/old_text2speech-V2/`.
-+- Confirmed active HTML has external scripts only.
-+- Confirmed active HTML has no inline style attributes or inline event handlers.
-+- Confirmed no database files were changed.
-+
-+## Automated Browser Coverage Used For Manual Equivalents
-+
-+- Opened active Text To Speech page through targeted Playwright validation.
-+- Verified browser voices render.
-+- Verified restored control groups render.
-+- Verified preset shaping updates pitch and volume values.
-+- Verified named sentence Add, Duplicate, and Delete.
-+- Verified output summary includes queue JSON.
-+- Verified Speak, Pause, Resume, and Stop call the browser SpeechSynthesis mock.
-+- Verified unavailable SpeechSynthesis shows actionable error.
-+
-+## Out Of Scope Manual Checks
-+
-+- No paid provider was manually exercised.
-+- No generated audio file export was manually exercised.
-+- No database behavior was manually exercised.
-diff --git a/docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md b/docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md
-new file mode 100644
-index 000000000..e09e0f974
---- /dev/null
-+++ b/docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md
-@@ -0,0 +1,48 @@
-+# PR_26171_061 Old TTS Feature Parity Checklist
-+
-+Functionality sample: `archive/v1-v2/tools/old_text2speech-V2/`
-+
-+## Controls And Options
-+
-+- PASS: Gender helper filter restored.
-+- PASS: Language filter restored.
-+- PASS: Voice dropdown restored.
-+- PASS: Voice details restored.
-+- PASS: Voice Age select restored.
-+- PASS: Character Preset select restored.
-+- PASS: SSML-like Preset select restored.
-+- PASS: Volume slider restored with visible value.
-+- PASS: Rate / Speed slider restored with visible value.
-+- PASS: Pitch slider restored with visible value.
-+- PASS: Name field restored.
-+- PASS: Text To Speak editor restored.
-+
-+## Queue And JSON
-+
-+- PASS: Named Sentences queue restored.
-+- PASS: Add named sentence restored.
-+- PASS: Duplicate named sentence restored.
-+- PASS: Delete named sentence restored.
-+- PASS: Output Summary JSON restored.
-+- PASS: Import JSON restored for standalone launch.
-+- PASS: Copy JSON restored for standalone launch.
-+- PASS: Export JSON restored for standalone launch.
-+- PASS: URL JSON source loading restored through `samplePresetPath`.
-+
-+## Playback And Status
-+
-+- PASS: Speak restored.
-+- PASS: Pause restored when browser support exists.
-+- PASS: Resume restored when browser support exists.
-+- PASS: Stop restored.
-+- PASS: Clearable status log restored.
-+- PASS: Actionable unavailable-browser error restored.
-+- PASS: No placeholder provider-blocking behavior remains for browser preview.
-+
-+## Workspace
-+
-+- PASS: Project Workspace launch detection restored.
-+- PASS: Standalone JSON actions hide during Project Workspace launch.
-+- PASS: Return to Project Workspace action restored.
-+- PASS: Project Workspace toolState loading restored.
-+- PASS: Project Workspace dirty-state writeback restored.
-diff --git a/docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md b/docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md
-new file mode 100644
-index 000000000..b2f4a44d3
---- /dev/null
-+++ b/docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md
-@@ -0,0 +1,71 @@
-+# PR_26171_061 Text To Speech Engine Audio Feature Parity
-+
-+## Summary
-+
-+Restored active Text To Speech feature parity from the archived `old_text2speech-V2` functionality sample while keeping active implementation in `toolbox/text-to-speech/` and reusable engine behavior in `src/engine/audio/`.
-+
-+## Changed Scope
-+
-+- Rebuilt reusable Text To Speech voice filtering, preset shaping, and queue-item helpers in `src/engine/audio/TextToSpeechEngine.js`.
-+- Expanded `toolbox/text-to-speech/index.html` with Theme V2 controls for the old V2 feature set.
-+- Rebuilt `toolbox/text-to-speech/text2speech.js` so the active tool consumes the engine audio module.
-+- Expanded targeted browser validation in `tests/playwright/tools/TextToSpeechFunctional.spec.mjs`.
-+- Updated Playwright V8 coverage artifacts for changed runtime JavaScript.
-+
-+## Requirement Checklist
-+
-+- PASS: Used `archive/v1-v2/tools/old_text2speech-V2/` as the required functionality sample.
-+- PASS: Reusable TTS behavior lives in `src/engine/audio/`.
-+- PASS: `toolbox/text-to-speech/` consumes `src/engine/audio/TextToSpeechEngine.js`.
-+- PASS: Restored old controls/options/features in the active tool.
-+- PASS: Browser SpeechSynthesis provider remains implemented.
-+- PASS: Planned provider adapters do not block browser preview behavior.
-+- PASS: No `tools/text2speech/` path was created.
-+- PASS: No database files were changed.
-+- PASS: Theme V2 remains the styling source.
-+- PASS: HTML uses external JavaScript only.
-+- PASS: No inline script, style, or event handler was added.
-+
-+## Restored Feature Set
-+
-+- Import JSON.
-+- Copy JSON.
-+- Export JSON.
-+- Project Workspace return action during workspace launch.
-+- Gender helper filter.
-+- Language filter.
-+- Browser voice selection.
-+- Voice details.
-+- Voice age shaping.
-+- Character presets.
-+- SSML-like presets.
-+- Volume, rate, and pitch sliders with visible values.
-+- Named sentence Name field.
-+- Add, Duplicate, and Delete named sentence actions.
-+- Text To Speak editor.
-+- Speak, Pause, Resume, and Stop playback actions.
-+- Named Sentences queue.
-+- Output Summary JSON.
-+- Clearable Status log.
-+- URL JSON preset loading through `samplePresetPath`.
-+- Project Workspace toolState loading and dirty-state writeback.
-+
-+## Validation Summary
-+
-+- PASS: `node --check src\engine\audio\TextToSpeechEngine.js`
-+- PASS: `node --check toolbox\text-to-speech\text2speech.js`
-+- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs`
-+- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`
-+- PASS: `npm run test:workspace-v2`
-+ - Note: command name is legacy; user-facing language is Project Workspace.
-+- PASS: `git diff --check`
-+- PASS: changed runtime JS coverage collected for `src/engine/audio/TextToSpeechEngine.js`.
-+- PASS: changed runtime JS coverage collected for `toolbox/text-to-speech/text2speech.js`.
-+
-+## Out Of Scope
-+
-+- No database changes.
-+- No external paid provider implementation.
-+- No generated audio file export provider.
-+- No new `tools/text2speech/` path.
-+- No archived tool activation.
-diff --git a/docs_build/dev/reports/PR_26171_061-validation.md b/docs_build/dev/reports/PR_26171_061-validation.md
-new file mode 100644
-index 000000000..bf864dc27
---- /dev/null
-+++ b/docs_build/dev/reports/PR_26171_061-validation.md
-@@ -0,0 +1,42 @@
-+# PR_26171_061 Validation Report
-+
-+## Commands Run
-+
-+- `node --check src\engine\audio\TextToSpeechEngine.js`
-+ - PASS.
-+- `node --check toolbox\text-to-speech\text2speech.js`
-+ - PASS.
-+- `node --test tests\tools\Text2SpeechShell.test.mjs`
-+ - PASS: 3 tests passed.
-+- `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`
-+ - PASS: 2 tests passed.
-+ - Covers restored controls, preset shaping, queue add/duplicate/delete, output summary, pause/resume, speak, stop, and unavailable SpeechSynthesis error handling.
-+ - PASS: rerun after merging `origin/main` into the PR branch for conflict resolution.
-+- `npm run test:workspace-v2`
-+ - PASS: 5 Project Workspace tests passed.
-+ - Note: command name is legacy; user-facing language is Project Workspace.
-+ - Note: first execution used a 120s timeout and timed out before completion; rerun with a longer timeout completed successfully.
-+ - PASS: rerun after merging `origin/main` into the PR branch for conflict resolution.
-+- `git diff --check`
-+ - PASS.
-+
-+## Coverage
-+
-+- PASS: `docs_build/dev/reports/playwright_v8_coverage_report.txt` produced changed runtime JS coverage.
-+- PASS: `docs_build/dev/reports/coverage_changed_js_guardrail.txt` reports no changed runtime JS coverage warnings.
-+- PASS: `src/engine/audio/TextToSpeechEngine.js` covered at 71%.
-+- PASS: `toolbox/text-to-speech/text2speech.js` covered at 71%.
-+
-+## Artifact Verification
-+
-+- PASS: `docs_build/dev/reports/codex_review.diff` exists.
-+- PASS: `docs_build/dev/reports/codex_changed_files.txt` exists.
-+- PASS: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip` exists.
-+- PASS: ZIP size is greater than zero.
-+- PASS: ZIP contents preserve repo-relative paths.
-+
-+## Skipped
-+
-+- Full samples validation skipped because no sample JSON or sample runtime behavior changed.
-+- Database validation skipped because no database files or runtime persistence changed.
-+- External provider validation skipped because paid/provider generation is out of scope and browser SpeechSynthesis is the implemented provider for this PR.
-diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.txt
-index bb7de5d8d..2a3c37ce3 100644
---- a/docs_build/dev/reports/codex_changed_files.txt
-+++ b/docs_build/dev/reports/codex_changed_files.txt
-@@ -1,91 +1,54 @@
--# Codex Changed Files - PR_26171_041-idea-board-production-polish
-+# Codex Changed Files - PR_26171_061-text2speech-engine-audio-feature-parity
-
- ## Git Workflow
--- Current branch: `codex/pr-26171-041-idea-board-production-polish`.
--- Expected starting branch: `main` (PASS before branch creation).
--- Created branch: `codex/pr-26171-041-idea-board-production-polish`.
--- Commit before conflict resolution: `ca626873a4cf19925229851b0da2a4ff55c2073f`.
--- Initial push result: PASS, branch pushed to `origin/codex/pr-26171-041-idea-board-production-polish`.
--- PR URL: `https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/17`.
--- Conflict resolution: merged `origin/main` at `0a364f85516aea82e38eea2f498fde5980f9adf9`; conflicts were limited to `codex_changed_files.txt` and `codex_review.diff`.
--- Conflict resolution push result: pending until after merge-validation commit.
--- Merge result: pending until after PR validation/merge.
--- Final main sync: pending until after merge and final pull.
-+- Starting branch: `main`.
-+- Created branch: `pr/26171-061-text2speech-engine-audio-feature-parity`.
-+- Initial commit: `e4541d63719ab777b0654c8fecf4b13237d31256`.
-+- PR branch was merged with `origin/main` during PR conflict recovery.
-+- Conflicts were limited to generated report artifacts.
-
--## Git Status
-+## Scoped Diff Stat
- ```text
-- M assets/theme-v2/css/tables.css
-- M assets/theme-v2/js/tool-display-mode.js
-- M docs_build/dev/reports/codex_changed_files.txt
-- M docs_build/dev/reports/codex_review.diff
-- M docs_build/dev/reports/coverage_changed_js_guardrail.txt
-- M docs_build/dev/reports/playwright_v8_coverage_report.txt
-- M src/shared/toolbox/tool-metadata-inventory.js
-- M tests/playwright/tools/IdeaBoardTableNotes.spec.mjs
-- M tests/playwright/tools/ToolboxRoutePages.spec.mjs
-- M toolbox/idea-board/index.html
-- M toolbox/idea-board/index.js
-+...R_26171_061-engine-audio-ownership-checklist.md | 25 +
-+ ...R_26171_061-instruction-compliance-checklist.md | 32 +
-+ .../PR_26171_061-manual-validation-notes.md | 27 +
-+ ...R_26171_061-old-tts-feature-parity-checklist.md | 48 ++
-+ ..._061-text2speech-engine-audio-feature-parity.md | 71 ++
-+ docs_build/dev/reports/PR_26171_061-validation.md | 42 +
-+ docs_build/dev/reports/codex_changed_files.txt | 118 +--
-+ .../dev/reports/coverage_changed_js_guardrail.txt | 7 +-
-+ .../dev/reports/playwright_v8_coverage_report.txt | 36 +-
-+ src/engine/audio/TextToSpeechEngine.js | 208 ++++-
-+ .../tools/TextToSpeechFunctional.spec.mjs | 30 +
-+ toolbox/text-to-speech/index.html | 119 +--
-+ toolbox/text-to-speech/text2speech.js | 853 +++++++++++++++++----
-+ 13 files changed, 1317 insertions(+), 299 deletions(-)
- ```
+diff --git a/assets/theme-v2/js/tool-display-mode.js b/assets/theme-v2/js/tool-display-mode.js
+index e77b7a9df..08bada607 100644
+--- a/assets/theme-v2/js/tool-display-mode.js
++++ b/assets/theme-v2/js/tool-display-mode.js
+@@ -154,11 +154,6 @@
+ body.appendChild(navigationRow);
+ } catch (error) {
+ console.warn("Tool navigation could not be loaded.", error);
+- const diagnostic = document.createElement("p");
+- diagnostic.className = "status";
+- diagnostic.setAttribute("role", "status");
+- diagnostic.textContent = "Tool navigation is temporarily unavailable. Refresh the page or try again shortly.";
+- body.appendChild(diagnostic);
+ }
+ }
--## Diff Stat
--```text
-- assets/theme-v2/css/tables.css | 70 +++++++-
-- assets/theme-v2/js/tool-display-mode.js | 2 +-
-- .../dev/reports/coverage_changed_js_guardrail.txt | 5 +-
-- .../dev/reports/playwright_v8_coverage_report.txt | 11 +-
-- src/shared/toolbox/tool-metadata-inventory.js | 6 +-
-- .../playwright/tools/IdeaBoardTableNotes.spec.mjs | 71 +++++++-
-- tests/playwright/tools/ToolboxRoutePages.spec.mjs | 26 ++-
-- toolbox/idea-board/index.html | 31 ++--
-- toolbox/idea-board/index.js | 191 ++++++++++++++++++++-
-- 9 files changed, 368 insertions(+), 45 deletions(-)
+diff --git a/docs_build/dev/reports/codex_changed_files.txt b/docs_build/dev/reports/codex_changed_files.tx
+index 2a3c37ce3..15213f1d6 100644
+--- a/docs_build/dev/reports/codex_changed_files.tx
++++ b/docs_build/dev/reports/codex_changed_files.tx
+@@ -1,54 +1,78 @@
+-# Codex Changed Files - PR_26171_061-text2speech-engine-audio-feature-parity
+-
+-## Git Workflow
+-- Starting branch: `main`.
+-- Created branch: `pr/26171-061-text2speech-engine-audio-feature-parity`.
+-- Initial commit: `e4541d63719ab777b0654c8fecf4b13237d31256`.
+-- PR branch was merged with `origin/main` during PR conflict recovery.
+-- Conflicts were limited to generated report artifacts.
+-
+-## Scoped Diff Sta
+-```tex
+-...R_26171_061-engine-audio-ownership-checklist.md | 25 +
+- ...R_26171_061-instruction-compliance-checklist.md | 32 +
+- .../PR_26171_061-manual-validation-notes.md | 27 +
+- ...R_26171_061-old-tts-feature-parity-checklist.md | 48 ++
+- ..._061-text2speech-engine-audio-feature-parity.md | 71 ++
+- docs_build/dev/reports/PR_26171_061-validation.md | 42 +
+- docs_build/dev/reports/codex_changed_files.txt | 118 +--
+- .../dev/reports/coverage_changed_js_guardrail.txt | 7 +-
+- .../dev/reports/playwright_v8_coverage_report.txt | 36 +-
+- src/engine/audio/TextToSpeechEngine.js | 208 ++++-
+- .../tools/TextToSpeechFunctional.spec.mjs | 30 +
+- toolbox/text-to-speech/index.html | 119 +--
+- toolbox/text-to-speech/text2speech.js | 853 +++++++++++++++++----
+- 13 files changed, 1317 insertions(+), 299 deletions(-)
-```
-
--## Requirement Evidence
--- PASS: Removed creator-visible Create Project from the right-side Next Steps area; no disabled `data-idea-board-create-project` panel remains.
--- PASS: Create Project is shown only in a Ready idea row's Actions column.
--- PASS: Clicking Create Project changes the idea status from Ready to Project and replaces Create Project/Delete with Open Project and Archive.
--- PASS: Project rows show Open Project and Archive and do not show Delete.
--- PASS: Added Archived status; archived rows are hidden by default.
--- PASS: Archived rows show Restore and Delete.
--- PASS: Restore returns archived ideas to their previous non-archived status, with Refining fallback in runtime.
--- PASS: Delete is guarded so Project ideas cannot be deleted unless archived first.
--- PASS: Status dropdown uses New, Exploring, Refining, Ready, Project, and Archived.
--- PASS: Added compact Show checkbox dropdown beside the visible table description line, with default statuses New, Exploring, Refining, Ready, and Project selected and Archived unselected.
--- PASS: Show dropdown supports any checkbox combination plus Select All and Clear All.
--- PASS: Updated creator-facing copy to "Capture, compare, and shape game ideas." and "Scan, compare, and update early ideas."
--- PASS: Replaced creator-visible Tool Display Mode navigation error with safe copy that does not mention server/API/local server/port/implementation details.
--- PASS: Chevron renders to the left of the Idea text, inline, same size, same color, and on the same text line; the whole Idea cell remains the expansion target.
--- PASS: Notes count remains informational only.
--- PASS: Table-first structure, inline Add Idea/Add Note, row-level Save/Cancel, status dropdown edit mode, notes indentation, and single-open accordion behavior remain covered.
-+## Changed Files
-+- src/engine/audio/TextToSpeechEngine.js
-+- toolbox/text-to-speech/index.html
-+- toolbox/text-to-speech/text2speech.js
-+- tests/playwright/tools/TextToSpeechFunctional.spec.mjs
-+- docs_build/dev/reports/coverage_changed_js_guardrail.txt
-+- docs_build/dev/reports/playwright_v8_coverage_report.txt
-+- docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md
-+- docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md
-+- docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md
-+- docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md
-+- docs_build/dev/reports/PR_26171_061-validation.md
-+- docs_build/dev/reports/PR_26171_061-manual-validation-notes.md
-+- docs_build/dev/reports/codex_review.diff
-+- docs_build/dev/reports/codex_changed_files.txt
+-## Changed Files
+-- src/engine/audio/TextToSpeechEngine.js
+-- toolbox/text-to-speech/index.html
+-- toolbox/text-to-speech/text2speech.js
+-- tests/playwright/tools/TextToSpeechFunctional.spec.mjs
+-- docs_build/dev/reports/coverage_changed_js_guardrail.tx
+-- docs_build/dev/reports/playwright_v8_coverage_report.tx
+-- docs_build/dev/reports/PR_26171_061-text2speech-engine-audio-feature-parity.md
+-- docs_build/dev/reports/PR_26171_061-instruction-compliance-checklist.md
+-- docs_build/dev/reports/PR_26171_061-old-tts-feature-parity-checklist.md
+-- docs_build/dev/reports/PR_26171_061-engine-audio-ownership-checklist.md
+-- docs_build/dev/reports/PR_26171_061-validation.md
+-- docs_build/dev/reports/PR_26171_061-manual-validation-notes.md
+-- docs_build/dev/reports/codex_review.diff
+-- docs_build/dev/reports/codex_changed_files.tx
++# PR_26171_042 Codex Changed Files Repor
++
++## Instruction Compliance Gate
++
++- Current branch before execution: `main`
++- Required execution branch before PR branch: `main`
++- Branch validation: PASS
++- Clean repository before branch creation: PASS
++- PR owner/parity: PASS, `042` is even and Idea/Tool Display navigation scope maps to PC / Environment 1.
++- Implementation path: PASS, active Idea Board and Theme V2 files only.
++- Validation scope: PASS, targeted Idea Board, targeted Toolbox route for Idea Board, and workspace contract lane because shared Tool Display Mode behavior changed.
++- Required reports: PASS, `docs_build/dev/reports/codex_review.diff` and this report are updated.
++- ZIP requirement: PASS, `tmp/PR_26171_042-idea-board-navigation-fallback-cleanup_delta.zip` is required and produced before final delivery.
++
++## Git Workflow Fields
++
++- Created branch: `codex/pr-26171-042-idea-board-navigation-fallback-cleanup`
++- Push result: PASS, branch pushed to `origin/codex/pr-26171-042-idea-board-navigation-fallback-cleanup`.
++- PR URL: `https://github.com/ToolboxAid/HTML-JavaScript-Gaming/pull/19`
++- Merge result: recorded in final Codex delivery after GitHub merge returns the merge SHA.
++- Final main commit: recorded in final Codex delivery after returning to `main` and pulling latest.
++- Conflict resolution: PASS, merged latest `origin/main` (`9df4942226b0c1a25cfc9567040fc237d90df8f9`) and resolved conflicts only in singleton generated report artifacts.
++
++## Scoped Files
++
++- `assets/theme-v2/js/tool-display-mode.js`
++- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
++- `tests/playwright/tools/ToolboxRoutePages.spec.mjs`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md`
++- `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
++- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
++- `docs_build/dev/reports/codex_review.diff`
++- `docs_build/dev/reports/codex_changed_files.txt`
++
++## Requirement Evidence
++
++- PASS: Removed creator-visible Tool Display Mode navigation diagnostic fallback. `tool-display-mode.js` now logs the navigation load failure to console only and appends no status paragraph.
++- PASS: Removed visible message `Tool navigation is temporarily unavailable. Refresh the page or try again shortly.`
++- PASS: Idea Board stays usable when registry-backed navigation cannot load. Static/no-registry Playwright path expands notes and adds a note successfully.
++- PASS: Creator-facing UI does not mention server, API, local server, port, registry, snapshot, or implementation details in the navigation fallback area.
++- PASS: Navigation failure does not affect Idea Board table functionality.
++- PASS: API-backed local route validated by targeted Idea Board and Toolbox route Playwright.
++- PASS: Static/no-registry route behavior validated by targeted Idea Board Playwright with the registry snapshot returning no data.
++- PASS: Optional previous/next navigation is omitted when unavailable.
++- PASS: Idea Board lifecycle, Show filter, Create Project, Archive, chevron, and table row editing behavior were not changed.
## Validation
--- PASS: `node --check toolbox/idea-board/index.js`.
--- PASS: `node --check assets/theme-v2/js/tool-display-mode.js`.
--- PASS: `node --check src/shared/toolbox/tool-metadata-inventory.js`.
--- PASS: `node --check tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`.
--- PASS: `node --check tests/playwright/tools/ToolboxRoutePages.spec.mjs`.
--- PASS: `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000`.
--- PASS: `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000`.
--- PASS: `npm run test:workspace-v2` (workspace-contract lane, 5 passed).
-+- PASS: `node --check src\engine\audio\TextToSpeechEngine.js`.
-+- PASS: `node --check toolbox\text-to-speech\text2speech.js`.
-+- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs`.
-+- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`.
-+- PASS: `npm run test:workspace-v2` (legacy command name; user-facing language is Project Workspace).
- - PASS: `git diff --check`.
--- PASS: Post-conflict rerun completed after merging `origin/main` at `0a364f85516aea82e38eea2f498fde5980f9adf9`.
--- PASS: Playwright V8 coverage report produced because runtime JavaScript changed.
--- WARN: Coverage report marks `src/shared/toolbox/tool-metadata-inventory.js` as not collected by browser V8 coverage; advisory only per project instructions.
--- SKIPPED: Full samples smoke was not run per request.
-+- PASS: Post-conflict validation rerun after merging `origin/main` into the PR branch.
-
- ## ZIP
--- Path: `tmp/PR_26171_041-idea-board-production-polish_delta.zip`.
--- Size: final size reported in the delivery summary after conflict-resolution ZIP refresh.
--- Contents:
-- - assets/theme-v2/css/tables.css
-- - assets/theme-v2/js/tool-display-mode.js
-- - docs_build/dev/reports/codex_changed_files.txt
-- - docs_build/dev/reports/codex_review.diff
-- - docs_build/dev/reports/coverage_changed_js_guardrail.txt
-- - docs_build/dev/reports/playwright_v8_coverage_report.txt
-- - src/shared/toolbox/tool-metadata-inventory.js
-- - tests/playwright/tools/IdeaBoardTableNotes.spec.mjs
-- - tests/playwright/tools/ToolboxRoutePages.spec.mjs
-- - toolbox/idea-board/index.html
-- - toolbox/idea-board/index.js
-+- Path: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip`.
-diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.txt
-index 66dd0cb12..807990e9f 100644
---- a/docs_build/dev/reports/coverage_changed_js_guardrail.txt
-+++ b/docs_build/dev/reports/coverage_changed_js_guardrail.txt
-@@ -6,9 +6,8 @@ Missing changed runtime JS files are WARN, not FAIL.
+-- PASS: `node --check src\engine\audio\TextToSpeechEngine.js`.
+-- PASS: `node --check toolbox\text-to-speech\text2speech.js`.
+-- PASS: `node --test tests\tools\Text2SpeechShell.test.mjs`.
+-- PASS: `npx playwright test tests/playwright/tools/TextToSpeechFunctional.spec.mjs`.
+-- PASS: `npm run test:workspace-v2` (legacy command name; user-facing language is Project Workspace).
+-- PASS: `git diff --check`.
+-- PASS: Post-conflict validation rerun after merging `origin/main` into the PR branch.
+-
+-## ZIP
+-- Path: `tmp/PR_26171_061-text2speech-engine-audio-feature-parity_delta.zip`.
++
++- PASS: `node --check assets/theme-v2/js/tool-display-mode.js`
++- PASS: `node --check toolbox/idea-board/index.js`
++- PASS: `node --check tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
++- PASS: `node --check tests/playwright/tools/ToolboxRoutePages.spec.mjs`
++- PASS: `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000`
++- PASS: `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000`
++- PASS: `npm run test:workspace-v2`
++- PASS: `git diff --check`
++- SKIP: Full samples smoke, per user instruction.
++
++## Coverage Evidence
++
++- PASS: `docs_build/dev/reports/playwright_v8_coverage_report.txt` updated.
++- PASS: `docs_build/dev/reports/coverage_changed_js_guardrail.txt` updated.
++- PASS: Changed runtime JS coverage lists `assets/theme-v2/js/tool-display-mode.js` at 64% advisory function coverage.
++
++## ZIP Contents
++
++- `assets/theme-v2/js/tool-display-mode.js`
++- `docs_build/dev/reports/codex_changed_files.txt`
++- `docs_build/dev/reports/codex_review.diff`
++- `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
++- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md`
++- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
++- `tests/playwright/tools/ToolboxRoutePages.spec.mjs`
+diff --git a/docs_build/dev/reports/coverage_changed_js_guardrail.txt b/docs_build/dev/reports/coverage_changed_js_guardrail.tx
+index 807990e9f..242796c4f 100644
+--- a/docs_build/dev/reports/coverage_changed_js_guardrail.tx
++++ b/docs_build/dev/reports/coverage_changed_js_guardrail.tx
+@@ -6,8 +6,7 @@ Missing changed runtime JS files are WARN, not FAIL.
Source: Playwright/Chromium built-in V8 coverage from the active Playwright run.
Changed runtime JS files considered:
--(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
--(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
--(74%) toolbox/idea-board/index.js - executed lines 640/640; executed functions 37/50
-+(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52
-+(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86
+-(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52
+-(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86
++(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14
Guardrail warnings:
--(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file missing from coverage; advisory only
-+(100%) none - no changed runtime JS coverage warnings
-diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.txt
-index 4a9f71ff1..dd573eabd 100644
---- a/docs_build/dev/reports/playwright_v8_coverage_report.txt
-+++ b/docs_build/dev/reports/playwright_v8_coverage_report.txt
-@@ -12,34 +12,28 @@ Note: entry percentages use function coverage when available, otherwise line cov
+ (100%) none - no changed runtime JS coverage warnings
+diff --git a/docs_build/dev/reports/playwright_v8_coverage_report.txt b/docs_build/dev/reports/playwright_v8_coverage_report.tx
+index dd573eabd..17eb943d2 100644
+--- a/docs_build/dev/reports/playwright_v8_coverage_report.tx
++++ b/docs_build/dev/reports/playwright_v8_coverage_report.tx
+@@ -12,28 +12,45 @@ Note: entry percentages use function coverage when available, otherwise line cov
Note: coverage entries are aggregated across every page/tool where coverageReporter.start(page) and coverageReporter.stop(page) ran.
Exercised tool entry points detected:
--(78%) Toolbox Index - exercised 4 runtime JS files
-+(72%) Toolbox Index - exercised 2 runtime JS files
+-(72%) Toolbox Index - exercised 2 runtime JS files
++(72%) Toolbox Index - exercised 10 runtime JS files
(0%) Tool Template V2 - not exercised by this Playwright run
--(63%) Theme V2 Shared JS - exercised 2 runtime JS files
-+(56%) Theme V2 Shared JS - exercised 2 runtime JS files
+-(56%) Theme V2 Shared JS - exercised 2 runtime JS files
++(61%) Theme V2 Shared JS - exercised 7 runtime JS files
Changed runtime JS files covered:
--(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: changed runtime JS file was not collected by Playwright V8 coverage; advisory only
--(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
--(74%) toolbox/idea-board/index.js - executed lines 640/640; executed functions 37/50
-+(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52
-+(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86
+-(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52
+-(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86
++(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14
Files with executed line/function counts where available:
--(25%) src/api/session-api-client.js - executed lines 68/68; executed functions 3/12
--(33%) src/api/toolbox-votes-api-client.js - executed lines 46/46; executed functions 2/6
--(44%) src/api/server-api-client.js - executed lines 167/167; executed functions 8/18
--(63%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 54/86
-+(36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14
-+(38%) src/api/public-config-client.js - executed lines 209/209; executed functions 10/26
-+(54%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 46/85
- (64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
--(65%) src/api/public-config-client.js - executed lines 209/209; executed functions 17/26
--(67%) src/api/game-journey-completion-api-client.js - executed lines 15/15; executed functions 2/3
--(67%) toolbox/game-workspace/game-workspace-api-client.js - executed lines 20/20; executed functions 2/3
--(74%) toolbox/idea-board/index.js - executed lines 640/640; executed functions 37/50
--(78%) toolbox/tools-page-accordions.js - executed lines 1156/1156; executed functions 87/111
--(86%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 25/29
-+(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52
-+(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86
-+(76%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 22/29
-+(100%) src/engine/audio/TextToSpeechDefaults.js - executed lines 108/108; executed functions 1/1
+-(36%) src/api/server-api-client.js - executed lines 167/167; executed functions 5/14
+-(38%) src/api/public-config-client.js - executed lines 209/209; executed functions 10/26
+-(54%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 46/85
+-(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 209/209; executed functions 9/14
+-(71%) src/engine/audio/TextToSpeechEngine.js - executed lines 412/412; executed functions 37/52
+-(71%) toolbox/text-to-speech/text2speech.js - executed lines 835/835; executed functions 61/86
+-(76%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 22/29
+-(100%) src/engine/audio/TextToSpeechDefaults.js - executed lines 108/108; executed functions 1/1
++(14%) assets/theme-v2/js/account-auth-service.js - executed lines 64/64; executed functions 1/7
++(14%) assets/theme-v2/js/admin-setup-actions.js - executed lines 55/55; executed functions 1/7
++(18%) assets/theme-v2/js/account-page-data.js - executed lines 150/150; executed functions 3/17
++(20%) assets/theme-v2/js/admin-owner-navigation.js - executed lines 58/58; executed functions 2/10
++(25%) src/api/admin-owner-navigation.js - executed lines 42/42; executed functions 1/4
++(25%) src/api/session-api-client.js - executed lines 68/68; executed functions 3/12
++(29%) src/engine/input/NormalizedInputRegistry.js - executed lines 341/341; executed functions 6/21
++(33%) src/api/admin-setup-api-client.js - executed lines 13/13; executed functions 1/3
++(33%) src/api/toolbox-votes-api-client.js - executed lines 46/46; executed functions 2/6
++(56%) toolbox/colors/colors.js - executed lines 1848/1848; executed functions 115/204
++(58%) src/api/server-api-client.js - executed lines 167/167; executed functions 11/19
++(64%) assets/theme-v2/js/tool-display-mode.js - executed lines 204/204; executed functions 9/14
++(64%) toolbox/controls/controls.js - executed lines 610/610; executed functions 36/56
++(65%) src/api/public-config-client.js - executed lines 209/209; executed functions 17/26
++(67%) src/api/game-journey-completion-api-client.js - executed lines 15/15; executed functions 2/3
++(74%) assets/theme-v2/js/gamefoundry-partials.js - executed lines 977/977; executed functions 67/90
++(75%) toolbox/game-workspace/game-workspace.js - executed lines 458/458; executed functions 33/44
++(89%) toolbox/tools-page-accordions.js - executed lines 1156/1156; executed functions 105/118
++(90%) toolbox/tool-registry-api-client.js - executed lines 155/155; executed functions 26/29
++(91%) toolbox/game-design/game-design.js - executed lines 254/254; executed functions 21/23
++(94%) assets/theme-v2/js/marketplace-page.js - executed lines 170/170; executed functions 16/17
++(100%) src/api/marketplace-api-client.js - executed lines 16/16; executed functions 3/3
++(100%) toolbox/colors/palette-api-client.js - executed lines 28/28; executed functions 4/4
++(100%) toolbox/controls/controls-api-client.js - executed lines 33/33; executed functions 5/5
++(100%) toolbox/game-design/game-design-api-client.js - executed lines 13/13; executed functions 2/2
++(100%) toolbox/game-workspace/game-workspace-api-client.js - executed lines 20/20; executed functions 3/3
Uncovered or low-coverage changed JS files:
--(0%) src/shared/toolbox/tool-metadata-inventory.js - WARNING: uncovered changed runtime JS file; advisory only
-+(100%) none - no low-coverage changed runtime JS files
+ (100%) none - no low-coverage changed runtime JS files
Changed JS files considered:
--(0%) src/shared/toolbox/tool-metadata-inventory.js - changed JS file not collected as browser runtime coverage
--(0%) tests/playwright/tools/IdeaBoardTableNotes.spec.mjs - changed JS file not collected as browser runtime coverage
--(0%) tests/playwright/tools/ToolboxRoutePages.spec.mjs - changed JS file not collected as browser runtime coverage
--(64%) assets/theme-v2/js/tool-display-mode.js - changed JS file with browser V8 coverage
--(74%) toolbox/idea-board/index.js - changed JS file with browser V8 coverage
-+(0%) tests/playwright/tools/TextToSpeechFunctional.spec.mjs - changed JS file not collected as browser runtime coverage
-+(71%) src/engine/audio/TextToSpeechEngine.js - changed JS file with browser V8 coverage
-+(71%) toolbox/text-to-speech/text2speech.js - changed JS file with browser V8 coverage
-diff --git a/src/engine/audio/TextToSpeechEngine.js b/src/engine/audio/TextToSpeechEngine.js
-index c8e1dced3..a5f3ccabd 100644
---- a/src/engine/audio/TextToSpeechEngine.js
-+++ b/src/engine/audio/TextToSpeechEngine.js
-@@ -1,7 +1,10 @@
- import {
-+ TEXT_TO_SPEECH_CHARACTER_PRESET_DEFAULTS,
- TEXT_TO_SPEECH_DEFAULTS,
- TEXT_TO_SPEECH_DISPLAY_NAME,
-- TEXT_TO_SPEECH_RANGE_DEFAULTS
-+ TEXT_TO_SPEECH_RANGE_DEFAULTS,
-+ TEXT_TO_SPEECH_SSML_LIKE_PRESET_DEFAULTS,
-+ TEXT_TO_SPEECH_VOICE_AGE_PRESET_DEFAULTS
- } from "./TextToSpeechDefaults.js";
-
- function finiteNumber(value, fallback) {
-@@ -9,8 +12,180 @@ function finiteNumber(value, fallback) {
- return Number.isFinite(number) ? number : fallback;
- }
-
--function boundedNumber(value, { fallback, max, min }) {
-- return Math.min(max, Math.max(min, finiteNumber(value, fallback)));
-+function boundedNumber(value, { fallback, max, min, value: defaultValue }) {
-+ const fallbackValue = fallback ?? defaultValue ?? min;
-+ return Math.min(max, Math.max(min, finiteNumber(value, fallbackValue)));
-+}
-+
-+function shapedNumber(value, { fallback, max, min, step }) {
-+ const boundedValue = boundedNumber(value, { fallback, max, min });
-+ const stepText = String(step || "1");
-+ const decimalPart = stepText.includes(".") ? stepText.split(".")[1] : "";
-+ const multiplier = 10 ** decimalPart.length;
-+ return Math.round(boundedValue * multiplier) / multiplier;
-+}
-+
-+function textToSpeechSlugFromName(name) {
-+ const slug = String(name || "")
-+ .trim()
-+ .toLowerCase()
-+ .replace(/[^a-z0-9]+/g, "-")
-+ .replace(/^-+|-+$/g, "");
-+ return slug || "speech-item";
-+}
-+
-+function textToSpeechVoiceGender(option) {
-+ const voiceText = `${option?.gender || ""} ${option?.name || ""} ${option?.label || ""}`;
-+ const voiceLanguage = String(option?.language || "").toLowerCase();
-+ if (/\bneutral\b|\bnon[-\s]?binary\b|\bandrogynous\b/i.test(voiceText)) return "neutral";
-+ if (voiceLanguage === "es-es" || /\bmale\b|\bman\b|\bdavid\b|\bmark\b/i.test(voiceText)) return "male";
-+ if (/\bfemale\b|\bwoman\b|\bzira\b/i.test(voiceText)) return "female";
-+ return "unknown";
-+}
-+
-+function genderFilterLabel(value) {
-+ if (value === "male-preferred") return "Male";
-+ if (value === "female-preferred") return "Female";
-+ if (value === "neutral") return "Neutral";
-+ return "Any";
-+}
-+
-+function ageFilterLabel(value) {
-+ if (value === "adult") return "Adult";
-+ if (value === "child") return "Child";
-+ if (value === "elderly") return "Elderly";
-+ if (value === "teen") return "Teen";
-+ return "Any";
-+}
-+
-+function payloadGenderValue(value) {
-+ return value === "neutral" ? "any" : value;
-+}
+-(0%) tests/playwright/tools/TextToSpeechFunctional.spec.mjs - changed JS file not collected as browser runtime coverage
+-(71%) src/engine/audio/TextToSpeechEngine.js - changed JS file with browser V8 coverage
+-(71%) toolbox/text-to-speech/text2speech.js - changed JS file with browser V8 coverage
++(0%) tests/playwright/tools/IdeaBoardTableNotes.spec.mjs - changed JS file not collected as browser runtime coverage
++(0%) tests/playwright/tools/ToolboxRoutePages.spec.mjs - changed JS file not collected as browser runtime coverage
++(64%) assets/theme-v2/js/tool-display-mode.js - changed JS file with browser V8 coverage
+diff --git a/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md
+new file mode 100644
+index 000000000..7dcde1b3e
+--- /dev/null
++++ b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md
+@@ -0,0 +1,20 @@
++# PR_26171_042-idea-board-navigation-fallback-cleanup Apply
++
++## Apply Steps
++
++1. Start from `main`.
++2. Pull latest `main`.
++3. Create `codex/pr-26171-042-idea-board-navigation-fallback-cleanup`.
++4. Implement the BUILD scope.
++5. Run requested validation.
++6. Stage scoped files only.
++7. Commit.
++8. Push branch.
++9. Create PR.
++10. Merge after validation passes.
++11. Return to `main` and pull latest.
++12. Confirm final report fields and repo-structured ZIP.
++
++## Merge Conflict Handling
++
++If conflicts occur, preserve latest `main`, preserve PR scope, resolve only touched files, rerun validation, regenerate reports and ZIP, then continue.
+diff --git a/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md
+new file mode 100644
+index 000000000..874f6dc4e
+--- /dev/null
++++ b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md
+@@ -0,0 +1,57 @@
++# PR_26171_042-idea-board-navigation-fallback-cleanup Build
++
++## Source Of Truth
++
++Use the user request for `PR_26171_042-idea-board-navigation-fallback-cleanup`, `docs_build/dev/PROJECT_INSTRUCTIONS.md`, `docs_build/dev/PROJECT_MULTI_PC.txt`, and this BUILD doc.
++
++## Singular Purpose
++
++Clean up the optional Tool Display Mode navigation fallback for Idea Board without changing Idea Board table behavior.
++
++## Exact Targets
++
++- `assets/theme-v2/js/tool-display-mode.js`
++- `toolbox/idea-board/index.js`
++- `tests/playwright/tools/IdeaBoardTableNotes.spec.mjs`
++- `tests/playwright/tools/ToolboxRoutePages.spec.mjs`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/BUILD_PR.md`
++- `docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/APPLY_PR.md`
++- `docs_build/dev/reports/coverage_changed_js_guardrail.txt`
++- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
++- `docs_build/dev/reports/codex_review.diff`
++- `docs_build/dev/reports/codex_changed_files.txt`
++
++## Implementation Requirements
++
++- Do not show creator-visible navigation diagnostics when optional Tool Display Mode navigation cannot load.
++- Remove the visible message `Tool navigation is temporarily unavailable. Refresh the page or try again shortly.`
++- Keep Idea Board usable when the navigation registry cannot load.
++- Log the navigation failure to console only.
++- Do not mention server, API, local server, port, registry, snapshot, or implementation details in creator-facing UI.
++- Do not let navigation failure affect Idea Board table functionality.
++- Validate both API-backed local route and static route without registry response.
++- In both cases, Idea Board renders, no creator-visible navigation error appears, and optional previous/next navigation is hidden or omitted when unavailable.
++- Ensure final Codex report fields are non-pending for PR URL, merge result, final main commit, created branch, and push result.
++
++## Explicit Non-Goals
++
++- Do not change Idea Board lifecycle behavior.
++- Do not change Show filter behavior.
++- Do not change Create Project behavior.
++- Do not change Archive behavior.
++- Do not change Chevron behavior.
++- Do not change table row editing behavior.
++
++## Validation
++
++- `node --check assets/theme-v2/js/tool-display-mode.js`
++- `node --check toolbox/idea-board/index.js`
++- `npx playwright test tests/playwright/tools/IdeaBoardTableNotes.spec.mjs --project=playwright --workers=1 --reporter=line --timeout=90000`
++- `npx playwright test tests/playwright/tools/ToolboxRoutePages.spec.mjs --project=playwright --workers=1 --reporter=line -g "Idea Board launches" --timeout=90000`
++- `npm run test:workspace-v2`
++- `git diff --check`
+
-+function filterTextToSpeechVoicesByGender(voiceOptions, genderFilter = "any") {
-+ if (genderFilter === "any") return voiceOptions;
-+ if (genderFilter === "male-preferred") {
-+ return voiceOptions.filter((option) => textToSpeechVoiceGender(option) === "male");
-+ }
-+ if (genderFilter === "female-preferred") {
-+ return voiceOptions.filter((option) => textToSpeechVoiceGender(option) === "female");
-+ }
-+ if (genderFilter === "neutral") {
-+ return voiceOptions.filter((option) => ["neutral", "unknown"].includes(textToSpeechVoiceGender(option)));
-+ }
-+ return voiceOptions;
-+}
++## ZIP
+
-+function optionLabelCompare(left, right) {
-+ return String(left.label).localeCompare(String(right.label), undefined, {
-+ numeric: true,
-+ sensitivity: "base"
-+ });
-+}
++Create `tmp/PR_26171_042-idea-board-navigation-fallback-cleanup_delta.zip` with repo-structured changed files only.
+diff --git a/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md
+new file mode 100644
+index 000000000..3b5d5fbfe
+--- /dev/null
++++ b/docs_build/pr/PR_26171_042-idea-board-navigation-fallback-cleanup/PLAN_PR.md
+@@ -0,0 +1,36 @@
++# PR_26171_042-idea-board-navigation-fallback-cleanup Plan
+
-+function textToSpeechLanguageOptionsFromVoices(voiceOptions) {
-+ const languageCounts = new Map();
-+ voiceOptions.forEach((option) => {
-+ const language = String(option.language || "").trim();
-+ if (language) {
-+ languageCounts.set(language, (languageCounts.get(language) || 0) + 1);
-+ }
-+ });
-+ return Array.from(languageCounts.entries())
-+ .map(([language, count]) => ({
-+ label: `${language} (${count} ${count === 1 ? "voice" : "voices"})`,
-+ value: language
-+ }))
-+ .sort(optionLabelCompare);
-+}
++## Purpose
+
-+function filterTextToSpeechVoiceOptions(voiceOptions, { gender = "any", language = "" } = {}) {
-+ const filteredByGender = filterTextToSpeechVoicesByGender(voiceOptions, gender);
-+ const matchingVoices = filteredByGender
-+ .filter((option) => !language || option.language === language)
-+ .sort(optionLabelCompare);
-+ return {
-+ filteredVoiceCount: filteredByGender.length,
-+ gender,
-+ genderLabel: genderFilterLabel(gender),
-+ language,
-+ languageOptions: textToSpeechLanguageOptionsFromVoices(filteredByGender),
-+ matchingVoices,
-+ voiceCount: voiceOptions.length
-+ };
-+}
++Fix the optional Tool Display Mode navigation fallback so Idea Board stays clean and usable when registry-backed previous/next navigation cannot load.
+
-+function shapeTextToSpeechOptions({
-+ characterPreset = TEXT_TO_SPEECH_DEFAULTS.characterPreset,
-+ pitch = TEXT_TO_SPEECH_DEFAULTS.pitch,
-+ rate = TEXT_TO_SPEECH_DEFAULTS.rate,
-+ ssmlLikePreset = TEXT_TO_SPEECH_DEFAULTS.ssmlLikePreset,
-+ voiceAge = TEXT_TO_SPEECH_DEFAULTS.voiceAge,
-+ volume = TEXT_TO_SPEECH_DEFAULTS.volume
-+} = {}, sliderOverrides = {}) {
-+ const character = TEXT_TO_SPEECH_CHARACTER_PRESET_DEFAULTS[characterPreset] || TEXT_TO_SPEECH_CHARACTER_PRESET_DEFAULTS.manual;
-+ const age = TEXT_TO_SPEECH_VOICE_AGE_PRESET_DEFAULTS[voiceAge] || TEXT_TO_SPEECH_VOICE_AGE_PRESET_DEFAULTS.any;
-+ const ssmlLike = TEXT_TO_SPEECH_SSML_LIKE_PRESET_DEFAULTS[ssmlLikePreset] || TEXT_TO_SPEECH_SSML_LIKE_PRESET_DEFAULTS.normal;
-+ return {
-+ characterPreset,
-+ pitch: sliderOverrides.pitch
-+ ? boundedNumber(pitch, TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch)
-+ : shapedNumber(Number(character.pitch) + Number(age.pitchOffset) + Number(ssmlLike.pitchOffset), TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch),
-+ rate: sliderOverrides.rate
-+ ? boundedNumber(rate, TEXT_TO_SPEECH_RANGE_DEFAULTS.rate)
-+ : shapedNumber(Number(character.rate) * Number(age.rateMultiplier) * Number(ssmlLike.rateMultiplier), TEXT_TO_SPEECH_RANGE_DEFAULTS.rate),
-+ ssmlLikePreset,
-+ voiceAge,
-+ volume: sliderOverrides.volume
-+ ? boundedNumber(volume, TEXT_TO_SPEECH_RANGE_DEFAULTS.volume)
-+ : shapedNumber(Number(character.volume) * Number(ssmlLike.volumeMultiplier), TEXT_TO_SPEECH_RANGE_DEFAULTS.volume)
-+ };
-+}
++## Scope
+
-+function uniqueTextToSpeechName(baseName, existingItems = []) {
-+ const requestedName = String(baseName || "").trim() || "New speech item";
-+ const existingNames = new Set(existingItems.map((item) => item.name));
-+ if (!existingNames.has(requestedName)) return requestedName;
-+ for (let index = 2; index < 1000; index += 1) {
-+ const candidate = `${requestedName} ${index}`;
-+ if (!existingNames.has(candidate)) return candidate;
-+ }
-+ return `${requestedName} ${Date.now().toString(36)}`;
-+}
++- Remove the creator-visible Tool Display Mode navigation fallback diagnostic.
++- Keep navigation failures logged to the browser console.
++- Preserve Idea Board lifecycle, filtering, project, archive, chevron, and row editing behavior.
++- Validate API-backed and static/no-registry Idea Board rendering.
++- Update final Codex reports with non-pending Git workflow fields.
+
-+function uniqueTextToSpeechId(baseName, existingItems = []) {
-+ const existingIds = new Set(existingItems.map((item) => item.id));
-+ const baseId = textToSpeechSlugFromName(baseName);
-+ if (!existingIds.has(baseId)) return baseId;
-+ for (let index = 2; index < 1000; index += 1) {
-+ const candidate = `${baseId}-${index}`;
-+ if (!existingIds.has(candidate)) return candidate;
-+ }
-+ return `${baseId}-${Date.now().toString(36)}`;
-+}
++## Required Validation
+
-+function createTextToSpeechQueueItem({
-+ existingItems = [],
-+ id = "",
-+ name = "",
-+ text = "",
-+ ...options
-+} = {}) {
-+ const itemName = uniqueTextToSpeechName(name, id ? [] : existingItems);
-+ return {
-+ characterPreset: options.characterPreset || TEXT_TO_SPEECH_DEFAULTS.characterPreset,
-+ gender: payloadGenderValue(options.gender || TEXT_TO_SPEECH_DEFAULTS.gender),
-+ id: id || uniqueTextToSpeechId(itemName, existingItems),
-+ language: options.language || TEXT_TO_SPEECH_DEFAULTS.language,
-+ name: itemName,
-+ pitch: boundedNumber(options.pitch, TEXT_TO_SPEECH_RANGE_DEFAULTS.pitch),
-+ rate: boundedNumber(options.rate, TEXT_TO_SPEECH_RANGE_DEFAULTS.rate),
-+ ssmlLikePreset: options.ssmlLikePreset || TEXT_TO_SPEECH_DEFAULTS.ssmlLikePreset,
-+ text: String(text || "").trim() || "New speech line.",
-+ voice: String(options.voice || ""),
-+ voiceAge: options.voiceAge || TEXT_TO_SPEECH_DEFAULTS.voiceAge,
-+ volume: boundedNumber(options.volume, TEXT_TO_SPEECH_RANGE_DEFAULTS.volume)
-+ };
++- `node --check assets/theme-v2/js/tool-display-mode.js`
++- `node --check toolbox/idea-board/index.js`
++- Targeted Idea Board Playwright.
++- Targeted Toolbox route Playwright for Idea Board.
++- `npm run test:workspace-v2`
++- Do not run full samples smoke.
++
++## Required Reports
++
++- `docs_build/dev/reports/codex_review.diff`
++- `docs_build/dev/reports/codex_changed_files.txt`
++
++## Required Delivery
++
++- Commit changes.
++- Push branch.
++- Create PR.
++- Merge after validation passes.
++- Return to main and pull latest main.
++- Produce repo-structured ZIP under `tmp/`.
+diff --git a/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs b/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs
+index 38085a4d2..1a42e53d7 100644
+--- a/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs
++++ b/tests/playwright/tools/IdeaBoardTableNotes.spec.mjs
+@@ -105,6 +105,11 @@ async function expectProductionCopy(page) {
+ );
}
- class TextToSpeechEngine {
-@@ -58,6 +233,18 @@ class TextToSpeechEngine {
- }));
- }
-
-+ filterVoiceOptions(options = {}) {
-+ return filterTextToSpeechVoiceOptions(this.voiceOptions(), options);
-+ }
-+
-+ shapeOptions(options = {}, sliderOverrides = {}) {
-+ return shapeTextToSpeechOptions(options, sliderOverrides);
-+ }
-+
-+ createQueueItem(options = {}) {
-+ return createTextToSpeechQueueItem(options);
-+ }
++async function expectNoNavigationFallbackUi(page) {
++ await expect(page.locator("body")).not.toContainText("Tool navigation is temporarily unavailable. Refresh the page or try again shortly.");
++ await expect(page.locator(".tool-display-mode")).not.toContainText(/\bserver\b|\bAPI\b|\blocal server\b|\bport\b|\bregistry\b|\bsnapshot\b/i);
++}
+
- voiceForValue(value) {
- const normalizedValue = String(value || "").trim();
- if (!normalizedValue) {
-@@ -248,5 +435,18 @@ class TextToSpeechEngine {
+ test("Idea Board uses accordion table ideas and notes", async ({ page }) => {
+ const server = await startRepoServer();
+ const previousApiUrl = process.env.GAMEFOUNDRY_API_URL;
+@@ -137,6 +142,7 @@ test("Idea Board uses accordion table ideas and notes", async ({ page }) => {
+ await page.goto(`${server.baseUrl}/toolbox/idea-board/index.html`, { waitUntil: "networkidle" });
+ await expect(page.getByRole("heading", { level: 1, name: "Idea Board" })).toBeVisible();
+ await expectProductionCopy(page);
++ await expectNoNavigationFallbackUi(page);
+ await expect(page.locator("[data-idea-board-table] > thead th[scope='col']")).toHaveText([
+ "Idea",
+ "Pitch",
+@@ -313,3 +319,55 @@ test("Idea Board uses accordion table ideas and notes", async ({ page }) => {
+ await server.close();
}
- }
-
--export { TextToSpeechEngine };
-+export {
-+ ageFilterLabel as textToSpeechAgeFilterLabel,
-+ createTextToSpeechQueueItem,
-+ filterTextToSpeechVoiceOptions,
-+ genderFilterLabel as textToSpeechGenderFilterLabel,
-+ payloadGenderValue as textToSpeechPayloadGenderValue,
-+ shapeTextToSpeechOptions,
-+ textToSpeechLanguageOptionsFromVoices,
-+ textToSpeechSlugFromName,
-+ textToSpeechVoiceGender,
-+ TextToSpeechEngine,
-+ uniqueTextToSpeechId,
-+ uniqueTextToSpeechName
-+};
- export default TextToSpeechEngine;
-diff --git a/tests/playwright/tools/TextToSpeechFunctional.spec.mjs b/tests/playwright/tools/TextToSpeechFunctional.spec.mjs
-index ccf95e3e3..17e2c0b62 100644
---- a/tests/playwright/tools/TextToSpeechFunctional.spec.mjs
-+++ b/tests/playwright/tools/TextToSpeechFunctional.spec.mjs
-@@ -66,7 +66,13 @@ async function openTextToSpeechPage(page, { speechAvailable = true } = {}) {
- getVoices() {
- return voices;
- },
-+ pause() {
-+ window.__textToSpeechCalls.push({ type: "pause" });
-+ },
- removeEventListener() {},
-+ resume() {
-+ window.__textToSpeechCalls.push({ type: "resume" });
-+ },
- speak(utterance) {
- window.__textToSpeechCalls.push({
- lang: utterance.lang,
-@@ -101,8 +107,22 @@ test("Text To Speech page loads and speaks through browser speech synthesis", as
- await expect(page.locator("[data-tts-voice-select]")).toContainText("Arcade Voice");
- await expect(page.locator("[data-tts-voice-count]")).toHaveText("2");
- await expect(page.locator("[data-tts-engine-label]")).toHaveText("Ready");
-+ await expect(page.locator("[data-tts-gender-select]")).toBeVisible();
-+ await expect(page.locator("[data-tts-language-select]")).toBeVisible();
-+ await expect(page.locator("[data-tts-age-select]")).toBeVisible();
-+ await expect(page.locator("[data-tts-character-preset-select]")).toBeVisible();
-+ await expect(page.locator("[data-tts-ssml-preset-select]")).toBeVisible();
-+ await expect(page.locator("[data-tts-import-json]")).toBeEnabled();
-+ await expect(page.locator("[data-tts-copy-json]")).toBeEnabled();
-+ await expect(page.locator("[data-tts-export-json]")).toBeEnabled();
-
- await page.locator("[data-tts-text-input]").fill("Launch the next wave.");
-+ await page.locator("[data-tts-item-name]").fill("Wave intro");
-+ await page.locator("[data-tts-character-preset-select]").selectOption("dramatic");
-+ await page.locator("[data-tts-age-select]").selectOption("teen");
-+ await page.locator("[data-tts-ssml-preset-select]").selectOption("whisper-ish");
-+ await expect(page.locator("[data-tts-pitch-value]")).toHaveText("1.1");
-+ await expect(page.locator("[data-tts-volume-value]")).toHaveText("0.6");
- await page.locator("[data-tts-voice-select]").selectOption("arcade-voice-uri");
- await page.locator("[data-tts-rate]").fill("1.4");
- await page.locator("[data-tts-pitch]").fill("0.8");
-@@ -111,6 +131,13 @@ test("Text To Speech page loads and speaks through browser speech synthesis", as
- await expect(page.locator("[data-tts-pitch-value]")).toHaveText("0.8");
- await expect(page.locator("[data-tts-volume-value]")).toHaveText("0.55");
- await expect(page.locator("[data-tts-text-count]")).toHaveText("21");
-+ await page.locator("[data-tts-add-item]").click();
-+ await expect(page.locator("[data-tts-queue-list]")).toContainText("Wave intro");
-+ await expect(page.locator("[data-tts-output-summary]")).toContainText("\"name\": \"Wave intro\"");
-+ await page.locator("[data-tts-duplicate-item]").click();
-+ await expect(page.locator("[data-tts-queue-list]")).toContainText("Wave intro 2 copy");
-+ await page.locator("[data-tts-delete-item]").click();
-+ await expect(page.locator("[data-tts-queue-list] [data-tts-queue-item]")).toHaveCount(2);
-
- await expect(page.locator("[data-tts-speak]")).toBeEnabled();
- await page.locator("[data-tts-speak]").click();
-@@ -126,10 +153,13 @@ test("Text To Speech page loads and speaks through browser speech synthesis", as
- volume: 0.55,
- }));
-
-+ await page.locator("[data-tts-pause]").click();
-+ await page.locator("[data-tts-resume]").click();
- await page.locator("[data-tts-stop]").click();
- await expect(page.locator("[data-tts-status]")).toContainText("Speech stopped");
- calls = await page.evaluate(() => window.__textToSpeechCalls);
- expect(calls.at(-1)).toEqual({ type: "cancel" });
-+ expect(calls).toEqual(expect.arrayContaining([{ type: "pause" }, { type: "resume" }]));
-
- expect(failures.failedRequests).toEqual([]);
- expect(failures.pageErrors).toEqual([]);
-diff --git a/toolbox/text-to-speech/index.html b/toolbox/text-to-speech/index.html
-index adaaff3a7..f5b29b19a 100644
---- a/toolbox/text-to-speech/index.html
-+++ b/toolbox/text-to-speech/index.html
-@@ -6,7 +6,7 @@
-
Preview spoken game text with local browser speech synthesis before deciding whether a generated audio provider is needed.
-+Create named speech lines, shape browser voices, and preview spoken game text through the shared engine audio Text To Speech module.
-Use the browser Web Speech API for immediate local preview. This does not create files, call paid providers, or fake generated audio.
--Message text remains Design-owned. Browser preview is local playback only. Future generated audio files remain Audio-owned when a real provider/export flow is added.
-+ -