diff --git a/docs/current-state.md b/docs/current-state.md
index 8bd802f..e87f9e5 100644
--- a/docs/current-state.md
+++ b/docs/current-state.md
@@ -10,7 +10,7 @@
- 旧生产基线:`demo/main.py`、`demo/fall_detection_gui.py`、`demo/detect_fall.py`、`demo/best.pt`。
- V1 代码:`v1/` 目录存在但尚无实现。
- V2 代码:`v2/` 目录存在但尚无实现。
-- 非代码设计工件:`docs/ui/silver-pose-ui-ux-spec.md` 已建立,定义客户演示的正常、确认摔倒和连接异常三种 UI 状态;等待用户审阅后才生成 HTML 原型,不改变 Phase 1 任务顺序。
+- 非代码设计工件:docs/ui/silver-pose-ui-ux-spec.md、docs/ui/2026-07-20-html-prototype-plan.md 与 docs/ui/silver-pose-v1-prototype.html 已建立。HTML 可离线演示正常、确认摔倒和连接异常三种 UI 状态;其中画面、事件和时间均为模拟数据,不连接真实摄像头、模型或网络,也不改变 Phase 1 任务顺序。
- 测试:暂无 pytest 测试;`python -m compileall -q demo` 已通过。
- 模型:`demo/best.pt` 可加载为 YOLO Pose,类别 `person`,`kpt_shape=[17, 3]`;与 `D:\PythonP\fall_detection\best.pt` 哈希一致。
- 当前标准启动:`./init.ps1`。
diff --git a/docs/ui/2026-07-20-html-prototype-plan.md b/docs/ui/2026-07-20-html-prototype-plan.md
new file mode 100644
index 0000000..9eb7b5a
--- /dev/null
+++ b/docs/ui/2026-07-20-html-prototype-plan.md
@@ -0,0 +1,101 @@
+# Silver Pose HTML UI Prototype Implementation Plan
+
+> **For agentic workers:** REQUIRED SKILL: Use `executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Create one offline HTML prototype that lets a customer switch between normal monitoring, confirmed-fall, and connection-error views without accessing a camera or model.
+
+**Architecture:** One self-contained HTML document holds semantic layout, CSS tokens, inline SVG scene, and a small state controller. The controller changes visible copy, status semantics, scene treatment, event evidence, and an idempotent demonstration dialog; it does not fetch data, access files, or claim to perform inference.
+
+**Tech Stack:** HTML5, CSS custom properties, inline SVG, vanilla JavaScript, Node.js 22 static syntax checks.
+
+---
+
+## File structure
+
+| Path | Responsibility |
+| --- | --- |
+| `docs/ui/silver-pose-v1-prototype.html` | Offline, interactive customer-demo prototype. |
+| `docs/ui/silver-pose-ui-ux-spec.md` | Approved interaction and accessibility source for the artifact. |
+| `docs/current-state.md` | Records that the HTML prototype exists and remains a non-production design artifact. |
+| `progress.md` | Appends exact validation evidence and handoff state. |
+
+### Task 1: Create and verify the standalone prototype
+
+**Files:**
+
+- Create: `docs/ui/silver-pose-v1-prototype.html`
+- Modify: `docs/current-state.md`
+- Modify: `progress.md`
+
+- [ ] **Step 1: Confirm the artifact does not pre-exist**
+
+Run:
+
+```powershell
+if (Test-Path -LiteralPath docs/ui/silver-pose-v1-prototype.html) {
+ throw 'Prototype already exists; inspect it before overwriting.'
+}
+throw 'Expected initial failure: prototype file is missing.'
+```
+
+Expected: the command fails with `Expected initial failure: prototype file is missing.`.
+
+- [ ] **Step 2: Implement one semantic, offline page**
+
+Create the document with these state-controller names and controls:
+
+```html
+
+
+
+
+ NORMAL
+
+
+
+```
+
+Implement `setDemoState(nextState)` in the only inline script. It must set `app.dataset.state`, update every switch button's `aria-pressed`, open `fall-dialog` only on the first entry to `confirmed`, reset that one-shot marker when leaving `confirmed`, and close the dialog on Escape. The complete page also needs CSS tokens from the approved specification; title/source/status area; visible text and icons in addition to color; a 16:9 inline SVG scene with person `P-017`; current event evidence; recent-event rows; reflow at 1008 px, 640 px and 600 px; `aria-live="polite"` announcements; and the text “演示数据,未连接真实摄像头或模型”.
+
+- [ ] **Step 3: Run static syntax and structure validation**
+
+Run:
+
+```powershell
+node -e "const fs=require('fs'); const html=fs.readFileSync('docs/ui/silver-pose-v1-prototype.html','utf8'); const required=['data-state-target=\"normal\"','data-state-target=\"confirmed\"','data-state-target=\"offline\"','id=\"fall-dialog\"','id=\"acknowledge-button\"','aria-live=\"polite\"','@media (max-width: 640px)','@media (max-width: 1007px)']; for (const token of required) if (!html.includes(token)) throw new Error('missing '+token); const scripts=[...html.matchAll(/
+