{"id":"7e070ba1-9cbe-4ed4-b36d-a0fb9624d760","entityType":"agent","slug":"clawhub-huiyonghkw-hekouwang-yandu-deck-skill","name":"hekouwang-yandu-deck-skill","canonicalUrl":"https://www.xpersona.co/agent/clawhub-huiyonghkw-hekouwang-yandu-deck-skill","canonicalPath":"/agent/clawhub-huiyonghkw-hekouwang-yandu-deck-skill","generatedAt":"2026-10-11T16:04:12.942Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T13:52:47.144Z","emptyReason":null},"description":"会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。 当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。 触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。 Skill: hekouwang-yandu-deck-skill Owner: huiyonghkw Summary: 会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。 当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s17639bexg8w6nymygatvtx99585dbjd:hekouwang-yandu-deck-skill","sourceUrl":"https://clawhub.ai/huiyonghkw/hekouwang-yandu-deck-skill","homepage":"https://clawhub.ai/huiyonghkw/skills/hekouwang-yandu-deck-skill","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/huiyonghkw/hekouwang-yandu-deck-skill","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/huiyonghkw/skills/hekouwang-yandu-deck-skill","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.de"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T13:52:47.144Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T13:52:47.144Z","emptyReason":null},"stars":null,"forks":null,"downloads":1054,"packageName":null,"latestVersion":"1.3.2","tractionLabel":"1.1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T13:52:47.067Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T13:52:47.144Z","lastCrawledAt":"2026-10-11T13:52:47.067Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T13:52:47.067Z","lastVerifiedAt":null,"highlights":[{"version":"1.3.2","createdAt":"2026-08-12T11:37:26.031Z","changelog":"ClawHub category: creative","fileCount":23,"zipByteSize":140214},{"version":"1.3.1","createdAt":"2026-08-12T08:02:47.889Z","changelog":"README freemium + SEO","fileCount":23,"zipByteSize":140184},{"version":"1.3.0","createdAt":"2026-08-12T07:49:32.852Z","changelog":"sync-from-harness、publish.py 追平真身、移动端文档","fileCount":23,"zipByteSize":139862},{"version":"1.2.1","createdAt":"2026-08-12T07:27:50.369Z","changelog":"v1.2.1: 首页品牌人设对齐 AI 工作流 builder","fileCount":21,"zipByteSize":134818},{"version":"1.2.0","createdAt":"2026-07-15T09:56:12.464Z","changelog":"**Skill version 1.0.3 changelog:** - Added Cloudflare Pages Functions + D1-based留言板 (comment board) support: includes backend function (`assets/functions/api/comments.js`), schema, and deployment config. - New interchangeable theme/skin (换肤) support: added reference docs and a token-flip script for deck color scheme switching. - Introduced new V6焰彩白 deck template for 国标系列. - Updated documentation: README template for deployment, references on token-flip/留言板, and clarified main engine/template usage. - Removed deprecated or outdated files (e.g., old skill card doc).","fileCount":20,"zipByteSize":133171},{"version":"1.0.2","createdAt":"2026-06-22T08:00:38.533Z","changelog":"目录结构对齐官方 anthropics/skills 约定：原先所有可移植副本都堆在 reference/（单数、且混入可执行脚本）。 现按官方分目录——scripts/publish.py、assets/templates/{deck-engine-暖黑,deck-engine-米白,home}.html、 references/系统说明.md、examples/demo.html。SKILL.md / README(中英) 的指针与结构树同步更新。 注：scripts/publish.py 与 assets/templates/home.html 落地时仍须拷进同一个 演读DECK/（publish.py 用 SELF/home.html 找首页源），文档已注明。","fileCount":12,"zipByteSize":71528},{"version":"1.0.1","createdAt":"2026-06-21T02:40:14.761Z","changelog":"- 移除全部 reference 文件及使用文档：删除了 README、系统说明、演示引擎模板、demo、发布脚本等 9 个文件。 - 清理仓库，只保留核心 SKILL.md 配置，去除可移植模板和示例内容。 - 本版本将易用性的文档和引擎样板迁出 skill 包，适合更精简的分发和依赖管理。","fileCount":3,"zipByteSize":7102},{"version":"1.0.0","createdAt":"2026-06-18T07:49:32.010Z","changelog":"Initial release of hekouwang-yandu-deck-skill: immersive article-to-keynote presentation and publishing tool. - Converts articles into \"one-screen, one-mirror\" web-based keynote decks with two built-in visual themes (warm black, off-white). - Fully self-hosts and subsets required fonts to minimize FOUT and optimize load speed; no CDN dependencies. - Automated deployment and publishing pipeline with zero third-party dependencies, optimized for Cloudflare Pages. - Includes reusable, boilerplate-free templates and animation hooks for speedy production of multiple deck episodes. - Provides portable templates, publish scripts, and detailed system documentation for easy integration into new projects.","fileCount":11,"zipByteSize":68707}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17639bexg8w6nymygatvtx99585dbjd:hekouwang-yandu-deck-skill","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T16:04:12.937Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-huiyonghkw-hekouwang-yandu-deck-skill/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-11T13:52:47.144Z","emptyReason":null},"readme":"Skill: hekouwang-yandu-deck-skill\n\nOwner: huiyonghkw\n\nSummary: 会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。 当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。 触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。\n\nTags: latest:1.3.2\n\nVersion history:\n\nv1.3.2 | 2026-08-12T11:37:26.031Z | user\n\nClawHub category: creative\n\nv1.3.1 | 2026-08-12T08:02:47.889Z | user\n\nREADME freemium + SEO\n\nv1.3.0 | 2026-08-12T07:49:32.852Z | user\n\nsync-from-harness、publish.py 追平真身、移动端文档\n\nv1.2.1 | 2026-08-12T07:27:50.369Z | user\n\nv1.2.1: 首页品牌人设对齐 AI 工作流 builder\n\nv1.2.0 | 2026-07-15T09:56:12.464Z | user\n\n**Skill version 1.0.3 changelog:**\n\n- Added Cloudflare Pages Functions + D1-based留言板 (comment board) support: includes backend function (`assets/functions/api/comments.js`), schema, and deployment config.\n- New interchangeable theme/skin (换肤) support: added reference docs and a token-flip script for deck color scheme switching.\n- Introduced new V6焰彩白 deck template for 国标系列.\n- Updated documentation: README template for deployment, references on token-flip/留言板, and clarified main engine/template usage.\n- Removed deprecated or outdated files (e.g., old skill card doc).\n\nv1.0.2 | 2026-06-22T08:00:38.533Z | user\n\n目录结构对齐官方 anthropics/skills 约定：原先所有可移植副本都堆在 reference/（单数、且混入可执行脚本）。 现按官方分目录——scripts/publish.py、assets/templates/{deck-engine-暖黑,deck-engine-米白,home}.html、 references/系统说明.md、examples/demo.html。SKILL.md / README(中英) 的指针与结构树同步更新。 注：scripts/publish.py 与 assets/templates/home.html 落地时仍须拷进同一个 演读DECK/（publish.py 用 SELF/home.html 找首页源），文档已注明。\n\nv1.0.1 | 2026-06-21T02:40:14.761Z | auto\n\n- 移除全部 reference 文件及使用文档：删除了 README、系统说明、演示引擎模板、demo、发布脚本等 9 个文件。\n- 清理仓库，只保留核心 SKILL.md 配置，去除可移植模板和示例内容。\n- 本版本将易用性的文档和引擎样板迁出 skill 包，适合更精简的分发和依赖管理。\n\nv1.0.0 | 2026-06-18T07:49:32.010Z | auto\n\nInitial release of hekouwang-yandu-deck-skill: immersive article-to-keynote presentation and publishing tool.\n\n- Converts articles into \"one-screen, one-mirror\" web-based keynote decks with two built-in visual themes (warm black, off-white).\n- Fully self-hosts and subsets required fonts to minimize FOUT and optimize load speed; no CDN dependencies.\n- Automated deployment and publishing pipeline with zero third-party dependencies, optimized for Cloudflare Pages.\n- Includes reusable, boilerplate-free templates and animation hooks for speedy production of multiple deck episodes.\n- Provides portable templates, publish scripts, and detailed system documentation for easy integration into new projects.\n\nArchive index:\n\nArchive v1.3.2: 23 files, 140214 bytes\n\nFiles: assets/functions/api/comments.js (4492b), assets/presenter/presenter-module.html (9173b), assets/templates/deck-engine-V6焰彩白.html (47106b), assets/templates/deck-engine-暖黑.html (68653b), assets/templates/deck-engine-米白.html (46608b), assets/templates/home.html (47618b), assets/templates/schema.sql (906b), assets/templates/wrangler.toml (1110b), CHANGELOG.md (8218b), examples/demo.html (29366b), LICENSE (1798b), README.en.md (5567b), README.md (6020b), references/mobile-and-comments.md (1538b), references/换肤-token-flip.md (8887b), references/留言板-D1.md (3428b), references/系统说明.md (4632b), scripts/flip-暖黑到米白.py (4047b), scripts/publish.py (47935b), scripts/sync-from-harness.sh (1248b), skill-card.md (2633b), SKILL.md (16938b), _meta.json (145b)\n\nFile v1.3.2:SKILL.md\n\n---\nname: hekouwang-yandu-deck-skill\nslug: hekouwang-yandu-deck-skill\ndisplayName: 演读 DECK 产线与发布\nsummary: Immersive keynote-style HTML deck publisher — flip pages, auto-play, Cloudflare Pages. yandu-deck / hekouwang.pages.dev.\nlicense: MIT\nhomepage: https://github.com/huiyonghkw/hekouwang-yandu-deck-skill\nversion: 1.3.2\ndescription: >\n  会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。\n  当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。\n  触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n---\n\n# 演读 DECK · 沉浸式演示产线与发布\n\n> 「演读 DECK」= 会勇禾口王的AI笔记出品的一款**沉浸式阅读产品**：介于长文和视频之间的第三种读法——一屏一镜、方向键/空格/点击翻页、能自动播放，把一个复杂主题安静完整地讲给你看。\n> 线上：**https://hekouwang.pages.dev** ｜ 与图文产线 `hekouwang-content-factory-skill` 配套（那是出文章/贴图/视频，这是把内容做成翻页演示 + 发布）。\n\n## 0. 系统在哪（先认这个）\n\n发布系统是项目里一个**自包含目录** `<项目根>/演读DECK/`：\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库 + 一个子集化 venv）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用；不做留言板可删）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/api/comments.js   # 留言板后端（Pages Functions，按目录约定生效）\n├── fonts/src/       # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700 + Anthropic Sans/Mono + Mozilla VF\n├── fonts/cache/     # 子集化产物缓存（无字体源/无 venv 时回退）\n├── tools/fenv/      # 子集化 venv(fonttools+brotli)；移动会失效，丢了重建\n├── dist/            # 构建产物 = 部署目录（可整删重生）\n└── README.md\n```\n\n> ⚠️ **上面这套是「真身」，本 skill 里的是可移植副本**。日常在项目里改的是真身；**改完跑 `bash scripts/sync-from-harness.sh <演读DECK路径>` 同步回 skill**，否则副本很快过时。\n\n本 Skill 按官方约定分目录带了**可移植副本**（新项目落地时拷过去）：\n- `assets/templates/` — `deck-engine-米白.html`（⭐默认）/ `deck-engine-V6焰彩白.html`（国标）/ `deck-engine-暖黑.html`（仅维护存量）、`home.html`（首页源）、`wrangler.toml` + `schema.sql`（留言板，**database_id 是占位符，落地填自己的**）\n- `scripts/publish.py`（发布脚本）、`scripts/sync-from-harness.sh`（真身→副本单向同步）、`assets/functions/api/comments.js`（留言板后端）\n- `references/换肤-token-flip.md`（换肤）、`references/留言板-D1.md`（留言板）、`references/mobile-and-comments.md`（移动端 safe-area / 留言板开关 / 视频交叉引用）、`references/系统说明.md`（**落地 README 模板**，拷进 `演读DECK/README.md` 给人看）、`examples/demo.html`（零依赖最小示例）\n\n> ⚠️ **落地时 `publish.py` 与 `home.html` 必须同目录**（`publish.py` 用 `SELF/home.html` 找首页源）；`functions/` 要放成 `演读DECK/functions/api/comments.js`。\n> ⚠️ 副本里 **`CF_BEACON_TOKEN` 与 `wrangler.toml` 的 database_id 都留空/占位**——落地新站时填自己的，别沿用他人的（否则流量统计报到别人面板、留言写进别人的库）。\n\n## 1. 把文章做成「演示版 deck」⭐ 核心\n\n一篇 V2 文章 → 一屏一镜的 keynote。**零依赖（纯 CSS + 原生 JS，不引 GSAP/外链，国内/CF 都快）。** 沿用源文章的视觉（默认米白，国标走 V6 焰彩白，见 第1.4节）、字体、grain/mesh/frame/幽灵章节号。\n\n### 1.1 引擎（照抄模板，别重写）\n\n样板（**默认拷米白**，选哪套见 第1.4节）：\n- `assets/templates/deck-engine-米白.html` — ⭐ **默认**，人文/方法论亮调。\n- `assets/templates/deck-engine-V6焰彩白.html` — 国标系列专属：紫主色+焰橙/粉，Mozilla 可变字体（`publish.py` 的 `MOZILLA_FILES` 已打包 Mozilla 字体、按页面含 \"Mozilla\" 注入 `PRELOAD_LINKS_V6`）。\n- `assets/templates/deck-engine-暖黑.html` — 🕰️ 仅维护存量（Harness），**新 EP 别拷**。\n**做新 EP = 拷一份对应主色的模板，`<head>` 的全部 CSS 和 `</main>` 之后的全部 `<script>` 逐字保留，只换内容 slide / 顶栏标签 / title / 片尾。** 引擎已实现：\n\n> ⚠️ 模板 `@font-face` 里的字体路径是占位符 `{{SKILL_DIR}}/assets/fonts/...`——指向兄弟 skill `hekouwang-content-factory-skill` 的字体。拷模板做 EP 时**把 `{{SKILL_DIR}}` 替换成 hekouwang-content-factory-skill 的绝对 Base directory**（本地预览/截图才有字体）。发布时 `publish.py` 会把它统一收成站内 `/fonts/`，万一漏替换也能兜底。\n\n- 全屏 `.slide`（一屏一镜），`.stage` 居中 + JS `fit()` 等比缩放防裁切；\n- 导航：←/→/空格/点击/触屏滑动/底部圆点/Home/End/F 全屏；右下「▶ 自动播放」(7s/屏，像放视频)；顶部进度条 + `NN/总数`；`#N` 深链（可分享到某屏）；`prefers-reduced-motion` 自动关动画。\n- **S 放映 / 提词器**（讲者视图：计时器 + 当前镜逐字稿 + 下一镜预览，详见 第1.6节）。模板已内置该模块，拷模板即带。\n\n### 1.2 进场动画钩子（只加 class + `--i` 递增控错峰，CSS 已定义）\n\n| 钩子 | 效果 | 用在 |\n|---|---|---|\n| `.an` / `.an.scale` | 淡入上浮 / 带放大 | 任何要进场的块；按出现顺序 `style=\"--i:0\"`、`--i:1`… |\n| `.bar` | 横向条 scaleX 从左生长 | 柱状/条形数据条（只给数据条，不给坐标轴） |\n| `.tok` | SVG 节点组逐个淡入 | 流程/关系/漏斗/桥的节点 `<g>` |\n| `.draw` | 折线/箭头描线(JS getTotalLength) | 连接线 `<line>`/`<path>` |\n| `.grow` | 弹性放大 | stat 数据卡 |\n| `[data-count]`+`data-suffix` | 纯数字 0→N 滚动 | 纯数字读数（初始文本写 `0`；**含箭头/汉字/百分号的别用**） |\n\n每个 slide `data-g=\"章节号\"` → 背景自动生成巨幅幽灵数字（封面/速览/片尾用 `data-g=\"·\"`）。\n\n### 1.3 内容映射铁律（一图一镜）\n\n源文每个 section + 每张图表都要有对应镜头。**封面屏 + 速览屏（用源文 hero 的关键数据做 readout 仪表条）打头，片尾签收卡收尾**（含私域 CTA），一篇 9 节 → 约 12–24 屏。\n**SVG 图表逐字搬运**（viewBox/坐标/配色/字体不改），只在外层 `.fig` 加 `an`、给数据条/节点/折线加动画钩子。源文的 `.fig.breakout` 破格在演示版里**去掉**（每屏已全宽居中，负 margin 会出问题）。文案可适度精简适配一屏，保意保语气、过 `hekouwang-content-factory-skill` #6.6 去 AI 味。\n\n### 1.4 主色：**米白是全站默认**，焰彩白是国标专属例外\n\n新做任何一期，**默认拷米白引擎**。只有两种情况例外，别自作主张换调：\n\n| 系列 | 主色 | 拷哪个模板 |\n|---|---|---|\n| **默认 / 首页 / 出行SaaS** | **米白** `#faf9f5` + 黏土 `#c15f3c`（编辑/人文感） | `deck-engine-米白.html` |\n| **智能体互联国标** | **V6 焰彩白** `#fbfaff` + 紫 `#7c3aed` + 焰橙/粉，Mozilla 可变字体（大厂发布感） | `deck-engine-V6焰彩白.html` |\n\n- ⚠️ **暖黑 `#161514` / V6焰彩黑 `#170a30` = 历史过渡态，不再新做**。线上尚有存量（算力账本·偷师=焰彩黑，Harness=暖黑），按计划逐步 flip 回米白；`deck-engine-暖黑.html` 仅为维护存量保留，**新 EP 不要拷它**。\n- 亮底适配铁律（米白/焰彩白）：网格线改极淡深色、卡片靠 `--shadow` 投影不靠辉光、标题黏土渐变(深→浅)、幽灵号深色 `opacity:.05`、`.grain` 用 `mix-blend-mode:multiply`。引擎 JS 主题无关、逐字一致。\n- **给存量 deck 换肤（黑→米白）→ 读 [`references/换肤-token-flip.md`](references/换肤-token-flip.md)**：脚本会截空文件、半成品会留残色，踩过的坑都在里面，别凭感觉改。\n\n### 1.5 批量做（多 EP）\n\n引擎相同、只内容不同 → 并行开多个 subagent，每个给「对应主色模板路径 + 源文章路径 + 本节规则」，要求 `<head>`CSS 与 `<script>`JS 与模板**逐字一致**，只换内容、按源文追加专属组件 CSS（滑块/时间线/对比/桥…，改用模板的 token）。产出后主控用 headless Chrome 截图核验各图表屏（`--virtual-time-budget=5000` 让动画跑完）。\n\n## 1.6 放映 / 提词器（讲 + 录 双用）⭐\n\n模块：`assets/presenter/presenter-module.html`（自包含 `<style>+<div>+<script>`，已注入三套引擎模板与 `examples/demo.html`，**拷模板即带，无需改引擎**）。\n\n- **按 `S`** 开「讲者视图」：**独立窗口**（计时器 + 当前镜逐字稿 + 下一镜预览），主屏与讲者窗靠 **BroadcastChannel 双向同步**——**主屏保持干净，可投影 / 录屏**。弹窗被拦（或无 BroadcastChannel）时自动回退为页内全屏浮层（单屏排练也能用）。\n- **真·双屏**：把 deck 在第二显示器再开一个窗口、地址后加 `?speaker=1` 即变讲者窗，免弹窗。讲者窗可**反向遥控主屏**：在讲者窗按 `←/→` 翻镜、`P` 计时、`R` 归零、`Esc/S` 关（靠向主屏引擎派发方向键事件，不改引擎）。\n- **键位**：`S` 开/关 · `P` 计时启停 · `R` 归零 · `Esc` 关 · `←/→` 翻镜（主屏与讲者窗都认）。\n- **逐字稿 = 配音 / 口播脚本**：在每张 `.slide` 里加 `<div class=\"notes\">这一镜要讲的话…</div>`（观众/录屏**永不可见**，模块强制 `display:none`）。这份 notes 同时就是该镜的口播稿——录屏时主屏放干净 deck、讲者窗当提词器照念；也可直接喂 TTS（云扬）。\n- 取数靠 `#deck .slide` 的 `.active` class（`MutationObserver` 监听），与引擎解耦；无 `.notes` 的镜回退显示标题。讲者信号用 `window.name`/`?speaker`（**不用 `#speaker`**——引擎深链 `replaceState('#N')` 会把 hash 冲掉）。\n- ⚠️ 本地 `file://` 双击时 `window.open` 可能被拦、且 BroadcastChannel 跨窗不通（opaque origin）——**用 `python3 -m http.server` 起本地服务**预览（与字体本地化要求一致）；发布到 CF Pages(https) 后正常。\n\n> 一图一镜 + 每镜一段 notes ⇒ 写完 deck 就同时有了「演示稿 + 提词器 + 口播稿」三合一。\n\n## 2. 首页 `home.html`\n\n演读 DECK 品牌落地页（**米白 `#faf9f5`**，2026-07-14 起；此前为暖黑）：masthead 品牌 + 「演读 ⟨DECK⟩」产品名、hero「把复杂的 AI，读成一场演示」、proof 三栏（第三种读法/翻页·自动播放/读完就懂）、系列卡片区（现 5 个：国标 / 算力账本 / 偷师AI大佬 / Harness工程 / 出行SaaS工程手记）、出品方 about（人设 + 禾口王=程）、订阅区（领《AI 内容流水线手册》三步）、底部内联留言板（`.talk-*`，`page='home'`）。**响应式**断点齐全（600/680/760/520）。\n- ⚠️ **系列卡是静态手写的**，不由 `MANIFEST` 生成（`write_index()` 是遗留死函数）——加系列要**手改 `home.html`** + 补 `MANIFEST`/`SERIES_META` 三处一起动。\n- 人设口径以记忆 `brand-persona-tagline` 三句为准（别自由改措辞）。**改首页改 `演读DECK/home.html`，不在 `dist/` 里改。**\n\n## 3. 字体自托管（零 CDN）⭐ 关键\n\n发布时 `publish.py` 的 `localize()` 把源 HTML 里所有 Google/loli 外链删掉、注入指向 `/fonts/` 的本地 `@font-face`；Anthropic 绝对路径也改写成 `/fonts/`。`subset_cjk()` 用 `tools/fenv` 的 `pyftsubset` 按**全站实际用字**把思源黑 4 字重（400/500/700/900，800 映射 900）+ 宋（金句衬线）子集化成小 woff2（各 ~180KB），连 Anthropic 一起打包进 `dist/fonts/`。\n\n- **首屏字重跳变(FOUT)**：每页 `<head>` 注入 4 条 `<link rel=preload>`（900/400/Anthropic Sans/Mono）让关键字体高优先级先下；`dist/_headers` 给 `/fonts/*` 设一周强缓存。这两条**必须保留**，否则首屏会「先系统字、再换思源」肉眼可见跳一下。\n- 字体源出处：思源来自 `@fontsource@5.0.0`（jsdelivr）逐字重静态 woff2；Anthropic 来自 `hekouwang-content-factory-skill/assets/fonts/`（自用/演示授权）；Mozilla Headline/Text VF 为 Mozilla 官方开源（OFL），可自由使用。\n- venv 丢了重建：`cd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli`。无 venv/字体源时 publish 回退用 `fonts/cache/`。\n\n## 4. 发布\n\n```bash\n# 从项目根运行\npython3 演读DECK/publish.py              # 构建 dist/ + 部署到 CF Pages（hekouwang）\npython3 演读DECK/publish.py --build-only # 只构建 dist/，不部署\n```\n\n- **加一期**：在 `publish.py` 的 `MANIFEST` 加一行（源 HTML 相对项目根的路径 + slug 如 `suanli/ep04` + 系列 + EP + 分类 + 标题 + 简介 + 屏数）。**加一个系列**：再补 `SERIES_META` 一条，**并手改 `home.html` 的系列卡**——首页系列卡是**静态手写**的，不由 MANIFEST 生成（`write_index()` 是遗留死函数，别指望它）。\n- **留言板**（Pages Functions + D1）随部署一起生效，**加装/排错 → 读 [`references/留言板-D1.md`](references/留言板-D1.md)**：部署得用配置式（不带 `dist` 参数）+ `cwd=SELF`，日志出现 `Uploading Functions bundle` 才算带上后端。\n- 干净 URL：演示版拷进 `dist/<slug>.html`，CF Pages 自动去 `.html`（`/suanli/ep01`）。\n- 部署用 `wrangler pages deploy dist --project-name hekouwang`；首次需 `wrangler login`（用户自己 `! wrangler login`）。\n\n## 5. 防踩坑（实测血泪）\n\n1. **`dist/` 每次构建被清空**——别在里面改任何东西；首页改 `home.html`，演示版改各 EP 源。\n2. **本地预览必须起 http 服务器**：`dist` 用站内 `/fonts/` 绝对路径，`file://` 双击打不出字体。`cd dist && python3 -m http.server 8000`。\n3. **`keynote.pages.dev` / `keynotes` 等常用名全球已被占**——CF 会自动加随机后缀(`keynote-9z0`)。本机网络有透明代理劫持 DNS、返回 198.18.0.x 假 IP，**本地 nslookup 测不出子域可用性**；唯一可靠 = `wrangler pages project create <名>` 后看 `project list` 分配的子域有没有后缀。最终用 `hekouwang`。\n4. **国内 EdgeOne 是死路**：免费自动域名一律带 token 鉴权、公网 401（ICP 备案要求），别再碰；直接 Cloudflare Pages。\n5. **移动 venv 会失效**（shebang/pyvenv.cfg 写死原路径）——换位置就重建。\n6. **本机代理会截断大文件下载(>~4MB)**：思源变量字体下不全 → 改用 @fontsource 逐字重静态 woff2(各 ~1.6MB)再子集化。\n7. 截图核验演示版给足时间（`--virtual-time-budget=5000`），让 fit/动画跑完再截。\n\n## 配套与依赖\n- **内容产线（强依赖）：`hekouwang-content-factory-skill`**——演示版的源文章 HTML、视觉规范(V1/V2/V3)、配色 token、字体方案都来自它；本 Skill 只做「内容→翻页演示+发布」这一半。**⚠️ 它是付费 Skill**（需作者授权），仓库不含其内容。只用引擎可直接拷 `assets/templates/deck-engine-*.html`（零依赖独立可用）。\n- 示例：`examples/demo.html`（自包含、零依赖、双击即看的最小动画示例）。\n- 记忆：`keynote-yanshi-site`（站点现状 + 发布链路）、`keynote-deck-engine`（引擎做法）、`brand-persona-tagline`（人设三句）。\n\nFile v1.3.2:README.md\n\n# hekouwang-yandu-deck-skill · 演读 DECK\n\n**中文** · [English](README.en.md)\n\n> GitHub: [https://github.com/huiyonghkw/hekouwang-yandu-deck-skill](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n\n会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。\n\n把一篇文章/选题做成**一屏一镜、可翻页、能自动播放**的 keynote 演示版网页（**暖黑** / **米白** 两套主色），自托管字体（思源黑/宋子集化 + Anthropic 打包、零 CDN、preload 治 FOUT），并一键发布到 Cloudflare Pages。\n\n线上样例：**https://hekouwang.pages.dev**\n\n## 30 秒验收\n\n```bash\nopen examples/demo.html                              # 零依赖最小示例\nbash scripts/sync-from-harness.sh <path/to/演读DECK>  # 真身→副本同步\npython3 scripts/publish.py --help                    # 发布脚本可用性\n```\n\n## 免费 / 付费\n\n| | 免费（本仓库） | 付费增值 |\n|---|---|---|\n| 引擎模板 | `deck-engine-米白/V6/暖黑` + `demo.html` | 定制系列视觉 / 内容产线 |\n| 发布 | `publish.py` + CF Pages 配方 | `hekouwang-content-factory` 授权 |\n| 联系 | GitHub Issue | **@huiyonghkw** |\n\n## 示例动画版本 / Demo\n\n最快的体验方式 —— 双击打开 **[`examples/demo.html`](examples/demo.html)**：一个**自包含、零依赖、系统字体**的最小示例，直接 `file://` 打开就能看引擎怎么动（翻页 / 自动播放 / 柱子生长 / 数字滚动 / 折线描线 / 卡片错峰）。\n\n| 封面（数字滚动 + 标题渐变） | 流程屏（节点淡入 + 箭头描线 + stat 弹入） |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **在线完整版（可翻页/自动播放）**：\n  - 首页：<https://hekouwang.pages.dev>\n  - 暖黑系列：<https://hekouwang.pages.dev/suanli/ep01>（`#3` 直达第 3 屏）\n  - 米白系列：<https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` 是两套**完整引擎模板**（需起本地服务器看字体：`python3 -m http.server`）。\n\n## 依赖\n\n| 依赖 | 关系 | 说明 |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **内容来源（强依赖）** | 本 Skill 是「**把内容做成翻页演示 + 发布**」的一半；**另一半（生成文章 HTML、视觉规范 V1/V2/V3、去 AI 味、合规红线）在 `hekouwang-content-factory`**。演示版的源 HTML、配色 token、字体方案都源自它。**⚠️ `hekouwang-content-factory` 是付费 Skill**（GitHub 上为 **PRIVATE 私有仓库，非授权无法 clone / 获取**；需向作者 @huiyonghkw 获取授权），本仓库不含其内容。 |\n| Python 3 + `fonttools`+`brotli` | 字体子集化 | 仅发布时需要（`tools/fenv` venv，见 `SKILL.md`）。没有则回退用 `fonts/cache/` 已切好的子集。 |\n| `wrangler`（Cloudflare） | 部署 | `publish.py` 调它发到 CF Pages；首次需 `wrangler login`。 |\n| Anthropic Sans/Mono woff2 | 拉丁/代码字体 | 来自 `hekouwang-content-factory`（自用/演示授权）。缺失则拉丁字自动回退系统字。 |\n\n> 只想用**引擎**（不要内容产线）：直接拷 `assets/templates/deck-engine-*.html` 当模板填内容即可，那部分零依赖、可独立使用。\n\n## 这是什么\n\n这是一个 [Claude Code](https://claude.com/claude-code) **Skill**，按官方 `anthropics/skills` 约定分目录组织。`SKILL.md` 是给 Agent 读的方法说明；`scripts/` `assets/` `references/` `examples/` 是可直接拷用的脚本、模板、文档与示例。\n\n```\nSKILL.md                              # 方法 + 触发词 + 防踩坑（Agent 入口）\nscripts/\n└── publish.py                       # 构建 dist/ → 部署 CF Pages（零三方依赖）\nassets/templates/\n├── deck-engine-暖黑.html             # 演示版引擎模板（数据/财经/科普暗调）\n├── deck-engine-米白.html             # 演示版引擎模板（人文/方法论亮调）\n└── home.html                        # 首页模板\nreferences/\n└── 系统说明.md                       # 系统说明文档\nexamples/\n└── demo.html                        # 零依赖最小示例（双击即看）\n```\n\n> 落地铁律：`scripts/publish.py` 与 `assets/templates/home.html` 拷进项目时必须放进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源）。\n\n## 安装\n\n把本仓库放进 `~/.claude/skills/hekouwang-yandu-deck-skill/`：\n\n```bash\ngit clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill\n```\n\n之后在 Claude Code 里说「把这篇做成演示版 / 加一期演读 / 发 hekouwang」等即会自动加载。\n\n## 核心能力\n\n- **演示版引擎**（零依赖 CSS+JS）：全屏一屏一镜、←/→/空格/点击/触屏翻页、自动播放、进场动画（卡片错峰 / 柱子生长 / SVG 描线 / 数字滚动 / 幽灵章节号）、`fit()` 自适应、`#N` 深链、`prefers-reduced-motion` 友好。\n- **两套主色**：暖黑（数据控制台）/ 米白（编辑人文），引擎 JS 主题无关。\n- **字体自托管**：思源黑 4 字重 + 宋按用字子集化（各 ~180KB），Anthropic Sans/Mono 打包，全站零外链；preload + 强缓存消除首屏字重跳变。\n- **一键发布**：`python3 publish.py`，MANIFEST 加一行即加一期，CF Pages 干净 URL。\n\n> 配套图文/视频产线见 `hekouwang-content-factory`。\n\n## License\n\n本仓库代码（演示版引擎模板、`publish.py`、`demo.html`、`home.html`、`SKILL.md` 等）以 **MIT** 开源，见 [LICENSE](LICENSE)。注意：\n\n- **`hekouwang-content-factory` 是独立的付费 Skill，其内容不在本仓库**，不受本许可覆盖。\n- 思源黑体/思源宋体（Noto Sans/Serif SC）为 SIL OFL 开源字体，本仓库**不含字体文件**，自行获取时遵循其 OFL。\n- Anthropic Sans/Mono 为专有字体，本仓库不含，使用前自行确认授权。\n\nFile v1.3.2:_meta.json\n\n{\n  \"ownerId\": \"kn73qd1gcmjr446mwcbdxef70x82vxcw\",\n  \"slug\": \"hekouwang-yandu-deck-skill\",\n  \"version\": \"1.3.2\",\n  \"publishedAt\": 1786534646031\n}\n\nFile v1.3.2:references/mobile-and-comments.md\n\n# 移动端 safe-area · 留言板开关 · 视频交叉引用\n\n## 移动端 safe-area\n\n演示引擎默认 `viewport-fit=cover`，全屏翻页时顶底栏要留 **safe-area**：\n\n```css\n.deck-toolbar {\n  padding-bottom: max(12px, env(safe-area-inset-bottom));\n  padding-left: max(16px, env(safe-area-inset-left));\n  padding-right: max(16px, env(safe-area-inset-right));\n}\n```\n\n- iOS 刘海/底条：没写 `env(safe-area-inset-*)` 时，翻页按钮和进度条会被挡。\n- 横屏演示：左右 inset 同样要留，别只照顾 bottom。\n- 验收：真机 Safari「添加到主屏幕」全屏翻 3 页，拇指区按钮必须可点。\n\n## 留言板（可选子系统）\n\n默认 **hekouwang.pages.dev 线上开着**；新站或纯静态演示可关：\n\n1. 删或移走 `演读DECK/functions/`（Pages Functions 不再挂载）\n2. `wrangler.toml` 里去掉 `[[d1_databases]]` 绑定\n3. `home.html` / 引擎模板里去掉留言入口 DOM 与 fetch 调用\n\n排错见 `references/留言板-D1.md`；**database_id 必须是自己的**，副本里是占位符。\n\n## 与 HyperFrames 视频产线\n\n- **演读 DECK** = 一屏一镜 **可翻页 HTML**，适合长文拆解、国标系列、教程跟读。\n- **HyperFrames 视频** = 同选题的 **ffmpeg 成片**（harness 内 `EP-*/video/` 或动画 Skill）。\n- 同一 EP 可两条线并存：文章母本 → 演示版 HTML（本 skill）+ 可选视频目录；**不要**在 deck 引擎里引外链视频或 `Date.now()`/`Math.random()`（与 harness `AGENTS.md` 视频红线一致）。\n\nFile v1.3.2:references/换肤-token-flip.md\n\n# 演读 DECK · 换肤 = token-flip（不是重做）\n\n给**已有 deck** 换主色时用这套。核心认知：两套主色的 `:root` **逐行结构完全一致、只有值不同**——所以换肤是一次**机械的 token 值映射**，引擎 CSS/JS 一字不动，内容一字不动。别重写、别让 subagent \"参照着做一版\"。\n\n> 当前口径见 SKILL.md 第1.4节：**米白 = 全站默认**，国标走 V6 焰彩白，**暖黑/焰彩黑是存量历史态**——本文档现在主要服务于「存量黑版 → 米白」的收敛。\n>\n> 现成脚本：**`scripts/flip-暖黑到米白.py`**（映射抽自引擎模板 · 单遍替换 · 内建未覆盖色守卫 · 先读后写）。用法 `python3 scripts/flip-暖黑到米白.py <deck.html>...`；退出码 2 = 有未覆盖色，按 第2.6节 人工判断后再跑。\n\n## 0. 动手前（这五步省过一次 9 期全毁）\n\n1. **先查 git 有没有现成的目标态**——见 第0.5节，能取回就别转换。\n2. **先 cp 备份**要改的文件。\n3. flip 脚本**必须先读后写**（见 第3节 第 1 条，这是最贵的坑）。\n4. flip 后 `stat -f%z` 查**每个文件大小非 0**。\n5. flip 后跑**全谱残留 grep**（第2节），**=0 才算过**。\n\n## 0.5 先问一句：git 里是不是躺着现成的？⭐ 省一整轮\n\n演读 DECK 的 deck HTML **都在 git 里**（只有 `演读DECK/publish.py` 被 `.gitignore` 的 `*.py` 排除）。整站换过肤，就意味着**换肤前的版本还在历史里**。要换回某个旧主色时，先查：\n\n```bash\ngit log --oneline --all -- <deck路径>                    # 哪次提交换的肤\ngit show <flip提交>^:<deck路径> | grep -oE -- '--bg:#[0-9a-f]*'   # 换肤前是什么色\ngit log --oneline <flip提交>..HEAD -- <deck路径>          # 换肤后还改过内容吗（0 = 可安全取回）\n```\n\n**换肤后 0 次提交 = 直接 `git show <flip提交>^:<路径>` 取回，精确、零转换风险**，比任何 flip 脚本都可靠。\n2026-07-15 实战：偷师 4 期换肤前本就是米白、之后 0 改动 → 直接取回，全谱残留 grep=0 一次过；而算力 5 期换肤前是**暖黑**（不是米白），取回只能拿到暖黑，仍需一轮真转换。**先查再动，别默认要写脚本。**\n\n## 0.6 ⚠️ 跨设计系统 ≠ 换肤，别硬套\n\n本文档的 flip 只适用于**同一套设计系统的明暗两极**（V6焰彩白↔V6焰彩黑、暖黑↔米白——后两者同为 V2 黏土系统）。\n\n**焰彩黑 → 米白 是跨系统**：主色紫 `#a855f7` vs 黏土 `#c15f3c`、字体 Mozilla VF vs Anthropic Sans，V6 的焰橙/焰粉在 V2 里根本没有对应色。硬套 token-flip 会出四不像。跨系统要走「先 git 取回同系统版本，再同系统 flip」，或老老实实重做。\n\n## 1. 已验证的映射\n\n### 1.1 V6 焰彩：白 ↔ 黑（两向互为精确逆运算）\n\n| 语义 | 焰彩白 | 焰彩黑 |\n|---|---|---|\n| 底 | `#fbfaff` | `#170a30` |\n| surface | `#ffffff` / `#f4eefc` / `#efe7fb` | `#241246` / `#231044` / `#2c1552` |\n| 正文字 | `#1c0b3e` | `#f3eefe` |\n| 主紫 | `#7c3aed` | `#a855f7` |\n| 次紫 | `#6d28d9` | `#c084fc` |\n| 蓝 | `#4f6ef0` | `#7c9bff` |\n| 金 | `#c8620a` / `#e07a1a` | `#ffb454` / `#f0a13a` |\n| warn | `#e0304f` | `#ff5c78` |\n| 线 | `rgba(28,11,62,…` | `rgba(255,255,255,…` |\n| 紫辉光 | `rgba(124,58,237,…` | `rgba(168,85,247,…` |\n| grain | `multiply` `.02` | `screen` `.05` |\n| body class | `class=\"light\"` | `class=\"dark\"` |\n\n**黑白通用、不翻**：焰橙 `#ff8a3d`、焰粉 `#ff4f8b`、`--ok`、`--teal`。\n**演示版与首页的 token 值不同，各写一份映射**，别共用一张表。\n\n### 1.2 暖黑 / 米白（旧两套）\n\n暖黑 `#161514` + 黏土 `#e08a5f` + 石板蓝 `#8fa6bd`；米白 `#faf9f5` + 黏土 `#c15f3c`。\n亮底适配：网格线→极淡深色、卡片靠 `--shadow` 不靠辉光、幽灵号深色 `opacity:.05`、`.grain`→`multiply`。\n\n## 2. 三条验收（缺一条都不算换完）\n\n1. **全谱残留 grep = 0**：拿**旧主色整套调色板**（不只是 `--bg`）去 grep，包括 SVG 内联色。半成品最爱漏的就是图表里的 `#e08a5f`（暖黑黏土）、`#8fa6bd`（石板蓝）。有残留 → 补一轮「旧色→新色」映射再跑。\n2. **封面截图**肉眼过一眼。\n3. **线上 curl 验 token**：跟随 308（`/suanli/ep04.html` → `/suanli/ep04`），确认 `--bg` 和 `class` 是新值。\n\n## 2.5 映射表从模板里抽，别手编；且必须**单遍同时替换** ⭐\n\n**映射的唯一真相源 = 两套引擎模板的 `:root` 逐 token 对照**（同一个引擎、两个主题，key 一一对应）。用脚本 diff 出来，别凭记忆写色号：\n\n```python\n# 剥掉 /* 注释 */ 再解析 :root，逐 key 比对 deck-engine-暖黑 vs deck-engine-米白\n```\n\n实测暖黑 33 token / 米白 26 token，其中 **20 个值不同**（`--bg/--surface*/--line*/--text*/--read/--hot*/--hl0/--cool*/--ochre*/--warn`），4 个通用不翻（`--font/--serif/--mono/--brand`）；另 `--m-*`（9 张插画）暖黑独有、**`stroke='%23000'` 单色遮罩、不含主题色**（靠 CSS 着色，不用管）；`--shadow/--shadow2` 米白独有（亮底要投影），flip 时**要补进去**。\n\n⚠️ **源集与目标集有交集 → 必须单遍替换**：`#f4f2eb` 既是源（暖黑 `--text` → `#1a1a18`）又是目标（暖黑 `--surface2` → `#f4f2eb`）。顺序 sed 会把前一条刚写出的颜色被后一条**再吃一次**，静默改错。正确做法是拼一个大 alternation 一次扫过：\n\n```python\npat = re.compile('|'.join(re.escape(k) for k in sorted(MAP, key=len, reverse=True)), re.I)\nout = pat.sub(lambda m: MAP[m.group(0).lower()], html)   # 单遍，绝不二次命中\n```\n\n## 2.6 图表内部色 ≠ 页面色：**脚本先扫「未覆盖色」并停下来** ⭐\n\ntoken 映射只管**相对页面底色**的颜色。deck 里还有大量**图表内部色**，它们的对比度是相对自己所在的色块，**翻了反而坏**：\n\n- `#19191a` 深字压在浅蓝柱 `#8fa6bd` 上 → 页面转亮底也得**留深**，翻了字就没了\n- `#e8eef3` 浅字压在深柱上 → **留浅**\n- 柱状填充（`#5e6b75`/`#a9714f`/`#8a7d70`）中间调 → 黑白底都成立，**别动**\n- 语义色（如 Harness 里 MCP 的绿 `#8fbf9f`）有含义 → **别当装饰色翻**\n- `#pmode` 讲者浮层（`#0c0d10`/`#ececf2`/`#9a9aac`…）、`.shell` 终端（`#1f1d1b`/`#0c0d10`）**刻意深底** → 不翻\n\n所以 flip 脚本**必须内建一道守卫**：转换前先扫全部目标文件，报出「映射表未覆盖、又不在保留名单」的裸色，**有就退出让人判断**，别闷头转（2026-07-15 实测：算力 EP01 干净，其余 5 期共 **15 种**各自的图表色需人工过——守卫挡住了一次静默改坏）。\n\n## 3. 血泪坑（都已解，别重踩）\n\n1. ⚠️ **原地覆盖脚本必须先读后写**——最贵的一个坑，曾把 9 期**全写空**：\n   ```python\n   # ✗ src==dst 时，open(dst,'w') 先把文件截断成空，再 read 就读到空字符串\n   open(dst,'w').write(flip(open(src).read()))\n   # ✓ 先读进内存，再开写\n   data = open(src).read()\n   open(dst,'w').write(flip(data))\n   ```\n2. **`.shell` 终端组件不翻**：`#1f1d1b` / `#0c0d10` / `rgba(0,0,0,.2)` 是**刻意的深底代码块**（米白/焰彩白母本自身就 `.shell{background:#1f1d1b}`），亮底下也该是深的。只在 `--shadow` 行里翻 `rgba(0,0,0,`，其余深底放行。\n3. **显式串先做**：`shadow` / `body 光晕` / `grain` 这类整串先替换，避免被后面的 bare-value 规则拆坏 alpha。\n4. **grep 单行 minified 会漏**：subagent 输出常是单行 HTML，`grep -c \"--bg:\"` 按行匹配会误判。用 `grep -o`，或先 `wc -c` 看是不是空文件。\n5. **半成品残留**：subagent 转版被中途停 → body SVG 内联色没转完。所以验收靠 第2节 第 1 条，不靠\"它说它做完了\"。\n6. **截图坑 → 用 `--headless=new` + `--timeout`**（2026-07-15 修正）：deck 的 `.draw` 动画让 `--virtual-time-budget` 不收敛。旧 `--headless` 会**挂死且不写盘**（`timeout` 杀进程后目录里什么都没有；\"杀了图其实已写盘\"的旧说法**实测不成立**，别信）。可靠配方——**1.5 秒出图**：\n\n   ```bash\n   \"$CHROME\" --headless=new --disable-gpu --incognito --user-data-dir=\"$TMP/prof\" \\\n     --window-size=1600,900 --hide-scrollbars \\\n     --virtual-time-budget=15000 --timeout=30000 \\\n     --screenshot=\"$TMP/cover.png\" \"file://$DECK\"\n   ```\n   `--timeout` 让 Chrome 自己到点截图退出（退出码 0），不必外部 `pkill`。字体走 content-factory 绝对路径，`file://` 即可加载。\n   ⚠️ 必带 `--incognito` + 独立 `--user-data-dir`，**别碰用户正在用的 Chrome**（见 memory `chrome-screenshot-isolated-incognito`）。\n\nFile v1.3.2:references/留言板-D1.md\n\n# 演读 DECK · 访客留言板（CF Pages Functions + D1）\n\n站点自带留言板：**Cloudflare Pages Functions + D1**，留言存在**自己的 CF 账号**里——无第三方、不用 giscus/GitHub 登录（国内读者友好）。**按页隔离**：首页 `home`，每期用 slug（`suanli/ep04`），各聊各的。\n\n## 1. 件在哪（本 skill 捆绑的落地副本）\n\n| 文件 | 作用 |\n|---|---|\n| `assets/functions/api/comments.js` | 后端：`onRequestGet`（读 `?page=` 列表）/ `onRequestPost`（校验+限频+写入） |\n| `assets/templates/wrangler.toml` | Pages 配置 + D1 绑定（`binding=DB`）。**database_id 是占位符，落地时填自己的** |\n| `assets/templates/schema.sql` | `comments` 表结构（含 `page` 列做隔离） |\n| `scripts/publish.py` → `inject_comments()` | 构建层把留言面板注入每篇 `</body>` 前 |\n\n**落地时全部拷进 `<项目根>/演读DECK/`**（`functions/` 保持 `functions/api/comments.js` 这个路径，Pages 按目录约定找）。\n\n## 2. 建库三步（新项目）\n\n```bash\ncd <项目根>/演读DECK\nwrangler d1 create <你的库名>                                  # ① 输出里拿 database_id\n#   ② 把 database_id / database_name / name 填进 wrangler.toml\nwrangler d1 execute <你的库名> --remote --file=schema.sql       # ③ 建表\n```\n\n> 改表结构：`CREATE IF NOT EXISTS` **不会 ALTER**，得先 DROP 再建。本地调试把 `--remote` 换 `--local`。\n\n## 3. 两种形态（为什么不一样）\n\n- **首页**：页面向下滚动 → 底部**内联**留言板（`.talk-*`），JS 里 `page='home'`。手写在 `home.html`。\n- **每期 deck**：全屏翻页、`body{overflow:hidden}` **不滚动** → 留言板做成**右侧把手 + 滑出面板 overlay**（`.hkwc-*`，暗色玻璃，对米白/焰彩白都压得住）。**不碰翻页引擎**（同讲者模式的思路），由 `publish.py` 的 `inject_comments()` 在构建层注入，**EP 源文件不动**。\n\n## 4. 已有防护（改的时候别拆掉）\n\n昵称 ≤24 / 正文 ≤500；`SHA256(salt|IP)` 前 32 位做限频（同 IP 20s 一条，**不存明文 IP**）；蜜罐字段 `website`（机器人填了就静默丢）；`ensureSchema` 幂等自建表；渲染端 `esc()`（`textContent`→`innerHTML`）防 XSS；`PAGE_RE` 白名单把非法 page（`../etc/passwd`）归 `home`，挡路径注入。\n\n## 5. 部署踩坑\n\n1. **配置式部署，别带目录参数**：要让 D1 绑定 + functions 随部署生效，`deploy_cloudflare()` 用 `wrangler pages deploy`（**不带 `dist` 参数**，带了会和 `pages_build_output_dir` 冲突）+ `cwd=SELF`（让它读到 `wrangler.toml`）。**部署日志出现 `Uploading Functions bundle` 才算带上了后端。**\n2. **验证线上要跟随 308**：`/suanli/ep04.html` → 308 → `/suanli/ep04`（Pages 去 `.html`）。`curl` 不加 `-L` 只看到空的 308 body，会误判成注入失败。\n3. **本机 curl 走代理**：测本地/线上接口都要 `--noproxy '*'`。\n\n## 6. 它还是「国内真人来没来」的口径\n\n留言板 D1 里的真实留言 + Web Analytics beacon 才是真人信号。**CF「帐户分析/流量概览」统计的是边缘请求数、机器人全算进去，会虚高几十倍，别拿它做决策。**beacon 的 `static.cloudflareinsights.com` 国内可能加载失败 → CN 真人会被少计，所以判断国内真人另看留言板 D1 / 公众号后台。\n\nFile v1.3.2:references/系统说明.md\n\n# 演读 DECK · 沉浸式演示发布系统\n\n> **这份是「落地 README 模板」**：新项目落地时连同 `publish.py` / `home.html` 一起拷进 `<项目根>/演读DECK/README.md`，给**人**看。\n> 给**模型**看的产线规矩在 SKILL.md（做 deck、换肤、留言板都从那儿走），别在这里堆细节。\n\n把「演示版」HTML（一屏一镜、可翻页、能自动播放的 keynote 长文）打包发布到 Cloudflare Pages。\n**线上：https://hekouwang.pages.dev** ｜ 出品：会勇禾口王的AI笔记。\n\n演示版「内容」（各 EP 的 HTML）放在项目内的选题目录里（`EP-算力账本/`、`EP-偷师AI大佬/`…），本目录只放**发布引擎 + 首页 + 字体管线 + 留言板后端**。\n\n## 目录结构\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/\n│   └── api/comments.js   # 留言板后端（Pages Functions）\n├── README.md        # 本说明\n├── fonts/\n│   ├── src/         # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700\n│   │                #        + Anthropic Sans/Mono + Mozilla Headline/Text VF\n│   └── cache/       # 子集化产物缓存（无字体源/无 venv 时回退用）\n├── tools/fenv/      # 子集化用的 Python venv（fonttools+brotli）；移动会失效，丢了就重建\n└── dist/            # ← 构建产物 = 部署到 CF Pages 的目录（可整删，重新构建即生成）\n```\n\n## 用法\n\n```bash\n# 从项目根运行\npython3 演读DECK/publish.py              # 构建 + 部署到 Cloudflare Pages\npython3 演读DECK/publish.py --build-only # 只生成 dist/，不部署\n\n# 本地离线预览（dist 用站内 /fonts/ 绝对路径，必须起服务器，不能 file://）\ncd 演读DECK/dist && python3 -m http.server 8000   # 浏览器开 http://localhost:8000/\n```\n\n**加一期**：在 `publish.py` 的 `MANIFEST` 加一行（源 HTML 路径 + slug + 系列 + 标题…），重跑即可。\n**加一个系列**：补 `SERIES_META` 一条，**并手改 `home.html` 的系列卡**（首页卡是静态手写的，不由 MANIFEST 生成）。\n\n## 它做了什么（关键设计）\n\n1. **干净 URL**：演示版拷进 `dist/<slug>.html`（如 `suanli/ep01`），CF Pages 自动去 `.html`。\n2. **字体全自托管、零 CDN**（`localize()`）：删掉源 HTML 里所有 Google/loli 外链，注入指向 `/fonts/` 的本地 `@font-face`；`FONT_ABS_RE` 把任意绝对字体路径 / 未替换的 `{{SKILL_DIR}}` 占位符统一收编成 `/fonts/`（覆盖 Anthropic + Mozilla）。\n3. **思源黑/宋按用字子集化**（`subset_cjk()`）：用 `tools/fenv` 的 `pyftsubset` 把全站实际用到的字切成小 woff2（各 ~180KB），思源黑 4 字重（400/500/700/900，800 映射 900）+ 宋（金句衬线）。Mozilla VF 是拉丁、体积小，整包打进不子集化。无 venv/字体源时回退 `fonts/cache/`。\n4. **首屏字体预加载 + 强缓存**：每页 `<head>` 注入 `<link rel=preload>`（含 Mozilla 的走 `PRELOAD_LINKS_V6`，按页面是否含 \"Mozilla\" 判定），消除「先系统字、后换思源」的字重跳变；`dist/_headers` 给 `/fonts/*` 设一周强缓存。\n5. **留言板注入**（`inject_comments()`）：构建层把右侧滑出面板注入每篇 `</body>` 前，**EP 源文件不动**。\n\n## 首次落地 / 换机器\n\n```bash\n# 子集化 venv（丢了或换机器时重建）\ncd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli\n\n# 留言板 D1（不做留言板可跳过，并删掉 wrangler.toml / schema.sql / functions/）\nwrangler d1 create <你的库名>                                # 拿 database_id 填进 wrangler.toml\nwrangler d1 execute <你的库名> --remote --file=schema.sql    # 建表\n\n# 部署前先登录\nwrangler login\n```\n\n**要填的自己的值**：`publish.py` 的 `CF_BEACON_TOKEN`（CF Web Analytics，留空则不注入）、`wrangler.toml` 的 `name` / `database_name` / `database_id`。\n\n## 字体源出处\n\n思源黑/宋来自 `@fontsource@5.0.0`（jsdelivr）逐字重静态 woff2；Anthropic Sans/Mono 来自\n`hekouwang-content-factory-skill/assets/fonts/`（自用/演示授权，见该 Skill #9.1.3）；\nMozilla Headline/Text VF 为 Mozilla 官方开源（OFL），可自由使用。\n\nFile v1.3.2:CHANGELOG.md\n\n# 更新日志 · hekouwang-yandu-deck-skill\n\n本文件记录本 Skill 的所有版本变更。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/)，\n版本号遵循 [语义化版本 SemVer](https://semver.org/lang/zh-CN/)：`MAJOR.MINOR.PATCH`。\n\n**变更分类**\n- `功能` 新增能力 · `变更` 默认/行为调整 · `优化` 既有能力打磨 · `修复` 缺陷修正 · `移除` 删除\n\n---\n\n## [1.3.2] - 2026-08-12\n\n### 变更\n- ClawHub 分类：`creative`\n\n## [1.3.1] - 2026-08-12\n\n### 优化\n- README：30 秒验收 + 免费/付费表 + @huiyonghkw CTA\n- summary 补英文 SEO 关键词（keynote deck / Cloudflare Pages）\n\n## [1.3.0] - 2026-08-12\n\n### 功能\n- **`scripts/sync-from-harness.sh`**：从 harness `演读DECK/` 单向同步 `publish.py`、`home.html`、留言板模板到 skill 副本。\n\n### 优化\n- **副本追平真身**：`publish.py` 802 行与 harness 对齐（含 Harness 工程系列 / FastMCP / 股票识字等 MANIFEST）。\n- **`references/mobile-and-comments.md`**：移动端 safe-area、留言板禁用步骤、与 HyperFrames 视频产线分工。\n\n## [1.2.1] - 2026-08-12\n\n### 变更\n- **品牌人设对齐 memory `brand-persona-tagline`**：首页 `home.html` 与 `publish.py` 内嵌 about 段，\n  「真会用 AI 的程序员」→ **「会勇禾口王 = AI 工作流 builder」**；补「会勇」谐音「会用」梗。\n- about 文案微调：强调「不靠 PPT 教人，先在自己电脑上跑通再把 Skill 交到你手上」。\n\n## [1.2.0]\n\n### 修复\n- **捆绑副本追平真身（本次最大的洞）**：skill 里的 `publish.py`（511 行）已落后项目真身（735 行）——**SKILL.md 白纸黑字写着「publish.py 已支持 Mozilla 字体打包」，而副本里 \"mozilla\" 出现 0 次**；`home.html` 也只有真身的一半（314/657）。已全量同步，并补上从未随 skill 分发的留言板子系统。承诺现在兑现得了。\n- **主色口径追平线上**：description 与 第1.4节 还写着「暖黑/米白两套主色」，实际线上已是四套并存。**推测缺件正是漂移的成因**——占大头的 V6 焰彩黑没有模板（黑版是 flip 出来的），新 EP 无黑版可拷只能退回老模板，Harness（暖黑）/ 出行SaaS（米白）就是这么来的。\n- **陈旧引用**：兄弟 skill 名补 `-skill` 后缀（真实目录是 `hekouwang-content-factory-skill`，旧名照着找会扑空）；`ROOT` 注释里的旧项目名 `Pi.dev/`；`references/系统说明.md` 里的「后续会升级成 Skill」（早就是了）。\n- **第2节 首页描述**：主色暖黑 → **米白**（2026-07-14 已改），系列卡「两个」→ **五个**，并点明系列卡是**静态手写**、不由 MANIFEST 生成（`write_index()` 是遗留死函数），加系列须三处一起动。\n\n### 功能\n- **留言板随 skill 分发**（`references/留言板-D1.md` + `assets/functions/api/comments.js` + `wrangler.toml` + `schema.sql`）：CF Pages Functions + D1，按页隔离，留言存自己的 CF 账号、无第三方。含建库三步、已有防护（限频/蜜罐/XSS/路径注入）、部署三坑（配置式部署不带 dist 参、验证跟随 308、curl 加 `--noproxy`）。\n- **换肤专题**（`references/换肤-token-flip.md`）：白↔黑 token-flip 映射表 + 三条验收 + 六个坑。含「**原地覆盖脚本先读后写**」——`open(dst,'w')` 会先把文件截断成空，曾把 9 期全写空。\n\n### 变更\n- **第1.4节 主色规矩改为「米白是全站默认，V6 焰彩白是国标专属例外」**；暖黑 / V6焰彩黑降为**存量历史态、不再新做**（存量按计划 flip 回米白）。`deck-engine-暖黑.html` 仅为维护存量保留，标注「新 EP 别拷」。故**不再补 V6焰彩黑模板**——补了等于鼓励继续新做。\n\n### 优化\n- **副本去账号化**（skill 是公开分发的）：`CF_BEACON_TOKEN` 置空（留空则不注入 beacon，降级干净）、`wrangler.toml` 的 `database_id` 改占位符。否则别人用这个 skill 建的站，流量统计报到作者面板、留言写进作者的库。\n- **删死代码**：`FONT_ABS_PREFIX` 指向一个不存在的目录（少 `-skill` 后缀），真正干活的是 `FONT_ABS_RE`。已删常量、采用 skill 版更通用的正则（同时认 `{{SKILL_DIR}}` 占位符与任意绝对路径，覆盖 Anthropic + Mozilla）。\n- **第0节 加防漂移提示**：点明「项目里的是真身、skill 里的是副本，改完记得同步回来」，并记下这次漂移作为前车之鉴。\n\n## [1.1.0]\n\n### 功能\n- **放映 / 提词器模块**（`assets/presenter/presenter-module.html`，第1.6节）：按 `S` 开「讲者视图」独立窗口——计时器 + 当前镜逐字稿 + 下一镜预览。主屏与讲者窗靠 **BroadcastChannel 双向同步**，**主屏保持干净可投影/录屏**；弹窗被拦（或无 BroadcastChannel）自动回退页内浮层。\n- **真·双屏 + 反向遥控**：第二显示器另开 deck 窗口加 `?speaker=1` 即变讲者窗（免弹窗，`window.name`/`?speaker` 识别，绕开引擎深链冲 hash）；讲者窗按 `←/→` 遥控主屏翻镜、`P/R` 控计时（向主屏引擎派发方向键事件，不改引擎）。键位 `S/P/R/Esc`。\n- 逐字稿写进每张 `.slide` 的 `<div class=\"notes\">`（观众/录屏永不可见），**同时即该镜的配音/口播脚本**，可照念或喂 TTS——「演示稿 + 提词器 + 口播稿」三合一。\n- 已注入两套引擎模板（暖黑/米白）与 `examples/demo.html`，拷模板即带，无需改引擎；靠 `.active` class（MutationObserver）与引擎解耦。无头截图验证浮层渲染通过。\n\n## [1.0.1]\n\n### 变更\n- **目录结构对齐官方 `anthropics/skills` 约定**：原先所有可移植副本都堆在 `reference/`（单数、且混入可执行脚本）。\n  现按官方分目录——`scripts/publish.py`、`assets/templates/{deck-engine-暖黑,deck-engine-米白,home}.html`、\n  `references/系统说明.md`、`examples/demo.html`。SKILL.md / README(中英) 的指针与结构树同步更新。\n  注：`scripts/publish.py` 与 `assets/templates/home.html` 落地时仍须拷进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源），文档已注明。\n\n## [1.0.0]\n\n首个有记录的版本（此前以 git 历史维护，无 CHANGELOG）。\n\n### 修复\n- **字体路径可移植化**：① `reference/publish.py` 的 `localize()` 由写死的绝对前缀\n  （硬编码家目录 + `assets/fonts/`）改为**正则 `FONT_ABS_RE`**，同时认「任意绝对路径」与未替换的\n  `{{SKILL_DIR}}` 占位符，统一收成站内 `/fonts/`；② 引擎模板 `deck-engine-{暖黑,米白}.html` 的\n  `@font-face` 硬编码字体路径改为占位符 `{{SKILL_DIR}}/assets/fonts/`，拷模板做 EP 时替换。\n  不再绑定某台机器/用户名；同时修了 content-factory 改用 `{{SKILL_DIR}}` 占位后、源 HTML 字体前缀随机器变化会替换不中导致字体失效的隐患。\n\n### 优化\n- **SKILL.md 声明 `allowed-tools`**：收敛到本 skill 真正需要的工具集，减小越权面。\n\n### 既有能力（首版基线）\n- **演示版引擎**：零依赖（纯 CSS + 原生 JS）一屏一镜 keynote，暖黑/米白两套主色；导航（方向键/空格/点击/触屏/圆点/全屏）、自动播放、进度条、深链、`prefers-reduced-motion` 自适应。模板 `reference/deck-engine-{暖黑,米白}.html`。\n- **进场动画钩子**：`.an/.bar/.tok/.draw/.grow/[data-count]` + 巨幅幽灵章节号。\n- **字体自托管（零 CDN）**：`publish.py` 删外链、注入本地 `@font-face`、`pyftsubset` 子集化思源黑 4 字重 + 宋，preload 防 FOUT，`/fonts/*` 强缓存。\n- **发布**：构建 `dist/` → `wrangler pages deploy` 到 Cloudflare Pages（hekouwang.pages.dev）；`MANIFEST`/`SERIES_META` 加期加系列。\n- **踩坑沉淀**：dist 每构建清空、本地预览须起 http、CF 子域占用 + 本机 DNS 劫持、EdgeOne 死路、venv 移动失效、代理截断 >4MB 下载。\n- 强依赖内容产线 `hekouwang-content-factory`（付费 skill，提供源文章/视觉规范/字体）；引擎可零依赖单独使用。\n\nFile v1.3.2:README.en.md\n\n# hekouwang-yandu-deck-skill · YanDu DECK\n\n**English** · [中文](README.md)\n\nA [Claude Code](https://claude.com/claude-code) **Skill** by *会勇禾口王的AI笔记* — the production + publishing pipeline for **YanDu DECK** (演读 DECK), an immersive presentation format.\n\nIt turns an article into a **one-screen-per-idea, swipeable, auto-playing** keynote web deck (in **dark** or **light** theme), self-hosts its fonts (Noto Sans/Serif SC subsetted + Anthropic bundled, zero CDN, `preload` to kill FOUT), and deploys to Cloudflare Pages with one command.\n\nLive example: **https://hekouwang.pages.dev**\n\n## Demo\n\nFastest way to feel it — double-click **[`examples/demo.html`](examples/demo.html)**: a **self-contained, zero-dependency, system-font** minimal example. Just open it via `file://` to see the engine animate (paging / auto-play / bars growing / numbers counting up / lines drawing / staggered cards).\n\n| Cover (count-up + gradient title) | Flow slide (nodes fade in + arrows draw + stat pop) |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **Full live decks (swipeable / auto-play):**\n  - Home: <https://hekouwang.pages.dev>\n  - Dark series: <https://hekouwang.pages.dev/suanli/ep01> (`#3` jumps to slide 3)\n  - Light series: <https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` are the two **full engine templates** (serve locally to load fonts: `python3 -m http.server`).\n\n## Dependencies\n\n| Dependency | Relationship | Notes |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **Content source (hard dependency)** | This Skill is the *\"turn content into a swipeable deck + publish\"* half. The other half — generating the article HTML, the visual systems (V1/V2/V3), de-AI-ifying copy, compliance — lives in `hekouwang-content-factory`. Source HTML, color tokens and the font scheme all come from it. **⚠️ `hekouwang-content-factory` is a paid Skill** (contact the author @huiyonghkw for a license); its content is **not** included in this repo. |\n| Python 3 + `fonttools` + `brotli` | Font subsetting | Only needed at publish time (the `tools/fenv` venv, see `SKILL.md`). Without it, it falls back to the pre-subsetted fonts in `fonts/cache/`. |\n| `wrangler` (Cloudflare) | Deploy | `publish.py` calls it to deploy to CF Pages; first run needs `wrangler login`. |\n| Anthropic Sans/Mono woff2 | Latin / mono fonts | From `hekouwang-content-factory` (self-use / demo license). If absent, Latin text falls back to system fonts. |\n\n> Want just the **engine** (not the content pipeline)? Copy `assets/templates/deck-engine-*.html` as a template and fill in your content — that part is zero-dependency and stands alone.\n\n## What is this\n\nA Claude Code **Skill**, organized per the official `anthropics/skills` convention. `SKILL.md` is the method doc the agent reads; `scripts/` `assets/` `references/` `examples/` hold ready-to-copy scripts, templates, docs and samples.\n\n```\nSKILL.md                              # method + triggers + gotchas (agent entry point)\nscripts/\n└── publish.py                       # build dist/ → deploy to CF Pages (no 3rd-party deps)\nassets/templates/\n├── deck-engine-暖黑.html             # deck engine template (dark — data / finance / explainer)\n├── deck-engine-米白.html             # deck engine template (light — editorial / methodology)\n└── home.html                        # homepage template\nreferences/\n└── 系统说明.md                       # system notes (zh)\nexamples/\n└── demo.html                        # self-contained zero-dep animated example\n```\n\n> Placement rule: copy `scripts/publish.py` and `assets/templates/home.html` into the **same** `演读DECK/` dir in your project (publish.py resolves the homepage via `SELF/home.html`).\n\n## Install\n\nClone into `~/.claude/skills/hekouwang-yandu-deck-skill/`:\n\n```bash\ngit clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill\n```\n\nThen in Claude Code, say things like *\"turn this into a deck / add a YanDu episode / publish to hekouwang\"* and it auto-loads.\n\n## Core features\n\n- **Deck engine** (zero-dependency CSS+JS): full-screen one-idea-per-slide; arrow keys / space / click / touch paging; auto-play; entrance animations (staggered cards / growing bars / SVG line-draw / number count-up / ghost section numbers); `fit()` auto-scaling; `#N` deep links; `prefers-reduced-motion` friendly.\n- **Two themes**: dark (data-console) / light (editorial) — the engine JS is theme-agnostic.\n- **Self-hosted fonts**: Noto Sans SC (4 weights) + Serif subsetted to the glyphs actually used (~180KB each), Anthropic Sans/Mono bundled, zero external requests; `preload` + long cache to remove the first-paint weight flash.\n- **One-command publish**: `python3 publish.py`; add one MANIFEST line per episode; clean URLs on CF Pages.\n\n> For the companion article/graphics/video pipeline, see `hekouwang-content-factory`.\n\n## License\n\nThe code in this repo (deck engine templates, `publish.py`, `demo.html`, `home.html`, `SKILL.md`, etc.) is **MIT** licensed — see [LICENSE](LICENSE). Note:\n\n- **`hekouwang-content-factory` is a separate, paid Skill; its content is not in this repo** and is not covered by this license.\n- Noto Sans SC / Noto Serif SC are SIL OFL fonts — **no font files are bundled here**; their OFL applies when you fetch them.\n- Anthropic Sans/Mono are proprietary fonts, not bundled here; confirm your own licensing before use.\n\nFile v1.3.2:skill-card.md\n\n## Description:\n\nHelps an agent turn articles or topics into immersive, swipeable YanDu DECK HTML presentations, maintain deck themes and pages, self-host fonts, configure optional comments, and publish to Cloudflare Pages.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[huiyonghkw](https://clawhub.ai/user/huiyonghkw)\n\n### License/Terms of Use:\n\nMIT\n\n## Use Case:\n\nDevelopers and content-publishing teams use this skill to convert long-form content into keynote-style web decks, update the YanDu DECK site, and deploy the result to Cloudflare Pages. It is also used to configure related theme, font, and comments workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The server security review reports a hardcoded Cloudflare analytics beacon despite documentation stating portable copies should not include author-controlled analytics.\n\nMitigation: Review before installing; remove or replace the Cloudflare analytics beacon, author CTAs, and author links before publishing under another owner.\n\nRisk: The skill can deploy a public Cloudflare Pages site and optionally write visitor comments to a D1 database.\n\nMitigation: Use only the target publisher's Cloudflare account values, replace placeholder D1 identifiers, confirm comments privacy behavior, and manually approve dependencies before publishing.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/huiyonghkw/skills/hekouwang-yandu-deck-skill)\n- [Project homepage](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n- [Live YanDu DECK site](https://hekouwang.pages.dev)\n- [Mobile safe-area and comments](references/mobile-and-comments.md)\n- [Theme token flip guide](references/换肤-token-flip.md)\n- [Cloudflare Pages Functions and D1 comments](references/留言板-D1.md)\n- [YanDu DECK system notes](references/系统说明.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with HTML, JavaScript, Python, shell command, and configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce or modify deck templates, publish scripts, Cloudflare Pages/D1 configuration, and deployment instructions.]\n\n## Skill Version(s):\n\n1.3.2 (source: frontmatter and changelog, released 2026-08-12)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.3.2:assets/templates/wrangler.toml\n\n# 演读 DECK · Cloudflare Pages 配置（落地新项目时拷进 <项目根>/演读DECK/）\n# 首页/每期留言板用到 Pages Functions（functions/）+ D1 数据库（binding=DB）。\n#\n# 落地三步（照做即可，不做留言板可整份删掉本文件）：\n#   1. wrangler d1 create <你的库名>                     → 输出里拿 database_id\n#   2. 把 database_id 填回下面（name/database_name 也换成你自己的）\n#   3. wrangler d1 execute <你的库名> --remote --file=schema.sql   → 建表\n#\n# ⚠️ database_id 不是密钥，但它绑定的是「某个具体 CF 账号下的库」——\n#    别直接用别人的，否则你的站会往别人的库里写留言。\nname = \"<your-pages-project>\"          # CF Pages 项目名，也决定 <name>.pages.dev 子域\npages_build_output_dir = \"dist\"\ncompatibility_date = \"2024-11-01\"\n\n[[d1_databases]]\nbinding = \"DB\"                         # 代码里按这个名字取（functions/api/comments.js 用 env.DB），别改\ndatabase_name = \"<your-d1-name>\"\ndatabase_id = \"<your-d1-database-id>\"  # ← wrangler d1 create 后填回\n\nFile v1.3.2:LICENSE\n\nMIT License\n\nCopyright (c) 2026 huiyonghkw (会勇禾口王的AI笔记)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n---\n\nScope / third-party notice\n\nThe MIT license above covers the code in THIS repository: the deck engine\ntemplates (reference/deck-engine-*.html), demo.html, publish.py, home.html,\nSKILL.md and docs.\n\nIt does NOT cover, and this repository does NOT include:\n\n- `hekouwang-content-factory` — a separate, PAID Claude Code Skill (the content/\n  visual-system half). Its content has its own terms; contact the author.\n- Noto Sans SC / Noto Serif SC (思源黑体/思源宋体) — SIL Open Font License (OFL).\n  No font files are bundled here; when you fetch them, their OFL applies.\n- Anthropic Sans / Anthropic Mono — proprietary fonts, not bundled here; confirm\n  your own licensing for any use.\n\nArchive v1.3.1: 23 files, 140184 bytes\n\nFiles: assets/functions/api/comments.js (4492b), assets/presenter/presenter-module.html (9173b), assets/templates/deck-engine-V6焰彩白.html (47106b), assets/templates/deck-engine-暖黑.html (68653b), assets/templates/deck-engine-米白.html (46608b), assets/templates/home.html (47618b), assets/templates/schema.sql (906b), assets/templates/wrangler.toml (1110b), CHANGELOG.md (8151b), examples/demo.html (29366b), LICENSE (1798b), README.en.md (5567b), README.md (6020b), references/mobile-and-comments.md (1538b), references/换肤-token-flip.md (8887b), references/留言板-D1.md (3428b), references/系统说明.md (4632b), scripts/flip-暖黑到米白.py (4047b), scripts/publish.py (47935b), scripts/sync-from-harness.sh (1248b), skill-card.md (2642b), SKILL.md (16938b), _meta.json (145b)\n\nFile v1.3.1:SKILL.md\n\n---\nname: hekouwang-yandu-deck-skill\nslug: hekouwang-yandu-deck-skill\ndisplayName: 演读 DECK 产线与发布\nsummary: Immersive keynote-style HTML deck publisher — flip pages, auto-play, Cloudflare Pages. yandu-deck / hekouwang.pages.dev.\nlicense: MIT\nhomepage: https://github.com/huiyonghkw/hekouwang-yandu-deck-skill\nversion: 1.3.1\ndescription: >\n  会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。\n  当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。\n  触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n---\n\n# 演读 DECK · 沉浸式演示产线与发布\n\n> 「演读 DECK」= 会勇禾口王的AI笔记出品的一款**沉浸式阅读产品**：介于长文和视频之间的第三种读法——一屏一镜、方向键/空格/点击翻页、能自动播放，把一个复杂主题安静完整地讲给你看。\n> 线上：**https://hekouwang.pages.dev** ｜ 与图文产线 `hekouwang-content-factory-skill` 配套（那是出文章/贴图/视频，这是把内容做成翻页演示 + 发布）。\n\n## 0. 系统在哪（先认这个）\n\n发布系统是项目里一个**自包含目录** `<项目根>/演读DECK/`：\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库 + 一个子集化 venv）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用；不做留言板可删）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/api/comments.js   # 留言板后端（Pages Functions，按目录约定生效）\n├── fonts/src/       # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700 + Anthropic Sans/Mono + Mozilla VF\n├── fonts/cache/     # 子集化产物缓存（无字体源/无 venv 时回退）\n├── tools/fenv/      # 子集化 venv(fonttools+brotli)；移动会失效，丢了重建\n├── dist/            # 构建产物 = 部署目录（可整删重生）\n└── README.md\n```\n\n> ⚠️ **上面这套是「真身」，本 skill 里的是可移植副本**。日常在项目里改的是真身；**改完跑 `bash scripts/sync-from-harness.sh <演读DECK路径>` 同步回 skill**，否则副本很快过时。\n\n本 Skill 按官方约定分目录带了**可移植副本**（新项目落地时拷过去）：\n- `assets/templates/` — `deck-engine-米白.html`（⭐默认）/ `deck-engine-V6焰彩白.html`（国标）/ `deck-engine-暖黑.html`（仅维护存量）、`home.html`（首页源）、`wrangler.toml` + `schema.sql`（留言板，**database_id 是占位符，落地填自己的**）\n- `scripts/publish.py`（发布脚本）、`scripts/sync-from-harness.sh`（真身→副本单向同步）、`assets/functions/api/comments.js`（留言板后端）\n- `references/换肤-token-flip.md`（换肤）、`references/留言板-D1.md`（留言板）、`references/mobile-and-comments.md`（移动端 safe-area / 留言板开关 / 视频交叉引用）、`references/系统说明.md`（**落地 README 模板**，拷进 `演读DECK/README.md` 给人看）、`examples/demo.html`（零依赖最小示例）\n\n> ⚠️ **落地时 `publish.py` 与 `home.html` 必须同目录**（`publish.py` 用 `SELF/home.html` 找首页源）；`functions/` 要放成 `演读DECK/functions/api/comments.js`。\n> ⚠️ 副本里 **`CF_BEACON_TOKEN` 与 `wrangler.toml` 的 database_id 都留空/占位**——落地新站时填自己的，别沿用他人的（否则流量统计报到别人面板、留言写进别人的库）。\n\n## 1. 把文章做成「演示版 deck」⭐ 核心\n\n一篇 V2 文章 → 一屏一镜的 keynote。**零依赖（纯 CSS + 原生 JS，不引 GSAP/外链，国内/CF 都快）。** 沿用源文章的视觉（默认米白，国标走 V6 焰彩白，见 第1.4节）、字体、grain/mesh/frame/幽灵章节号。\n\n### 1.1 引擎（照抄模板，别重写）\n\n样板（**默认拷米白**，选哪套见 第1.4节）：\n- `assets/templates/deck-engine-米白.html` — ⭐ **默认**，人文/方法论亮调。\n- `assets/templates/deck-engine-V6焰彩白.html` — 国标系列专属：紫主色+焰橙/粉，Mozilla 可变字体（`publish.py` 的 `MOZILLA_FILES` 已打包 Mozilla 字体、按页面含 \"Mozilla\" 注入 `PRELOAD_LINKS_V6`）。\n- `assets/templates/deck-engine-暖黑.html` — 🕰️ 仅维护存量（Harness），**新 EP 别拷**。\n**做新 EP = 拷一份对应主色的模板，`<head>` 的全部 CSS 和 `</main>` 之后的全部 `<script>` 逐字保留，只换内容 slide / 顶栏标签 / title / 片尾。** 引擎已实现：\n\n> ⚠️ 模板 `@font-face` 里的字体路径是占位符 `{{SKILL_DIR}}/assets/fonts/...`——指向兄弟 skill `hekouwang-content-factory-skill` 的字体。拷模板做 EP 时**把 `{{SKILL_DIR}}` 替换成 hekouwang-content-factory-skill 的绝对 Base directory**（本地预览/截图才有字体）。发布时 `publish.py` 会把它统一收成站内 `/fonts/`，万一漏替换也能兜底。\n\n- 全屏 `.slide`（一屏一镜），`.stage` 居中 + JS `fit()` 等比缩放防裁切；\n- 导航：←/→/空格/点击/触屏滑动/底部圆点/Home/End/F 全屏；右下「▶ 自动播放」(7s/屏，像放视频)；顶部进度条 + `NN/总数`；`#N` 深链（可分享到某屏）；`prefers-reduced-motion` 自动关动画。\n- **S 放映 / 提词器**（讲者视图：计时器 + 当前镜逐字稿 + 下一镜预览，详见 第1.6节）。模板已内置该模块，拷模板即带。\n\n### 1.2 进场动画钩子（只加 class + `--i` 递增控错峰，CSS 已定义）\n\n| 钩子 | 效果 | 用在 |\n|---|---|---|\n| `.an` / `.an.scale` | 淡入上浮 / 带放大 | 任何要进场的块；按出现顺序 `style=\"--i:0\"`、`--i:1`… |\n| `.bar` | 横向条 scaleX 从左生长 | 柱状/条形数据条（只给数据条，不给坐标轴） |\n| `.tok` | SVG 节点组逐个淡入 | 流程/关系/漏斗/桥的节点 `<g>` |\n| `.draw` | 折线/箭头描线(JS getTotalLength) | 连接线 `<line>`/`<path>` |\n| `.grow` | 弹性放大 | stat 数据卡 |\n| `[data-count]`+`data-suffix` | 纯数字 0→N 滚动 | 纯数字读数（初始文本写 `0`；**含箭头/汉字/百分号的别用**） |\n\n每个 slide `data-g=\"章节号\"` → 背景自动生成巨幅幽灵数字（封面/速览/片尾用 `data-g=\"·\"`）。\n\n### 1.3 内容映射铁律（一图一镜）\n\n源文每个 section + 每张图表都要有对应镜头。**封面屏 + 速览屏（用源文 hero 的关键数据做 readout 仪表条）打头，片尾签收卡收尾**（含私域 CTA），一篇 9 节 → 约 12–24 屏。\n**SVG 图表逐字搬运**（viewBox/坐标/配色/字体不改），只在外层 `.fig` 加 `an`、给数据条/节点/折线加动画钩子。源文的 `.fig.breakout` 破格在演示版里**去掉**（每屏已全宽居中，负 margin 会出问题）。文案可适度精简适配一屏，保意保语气、过 `hekouwang-content-factory-skill` #6.6 去 AI 味。\n\n### 1.4 主色：**米白是全站默认**，焰彩白是国标专属例外\n\n新做任何一期，**默认拷米白引擎**。只有两种情况例外，别自作主张换调：\n\n| 系列 | 主色 | 拷哪个模板 |\n|---|---|---|\n| **默认 / 首页 / 出行SaaS** | **米白** `#faf9f5` + 黏土 `#c15f3c`（编辑/人文感） | `deck-engine-米白.html` |\n| **智能体互联国标** | **V6 焰彩白** `#fbfaff` + 紫 `#7c3aed` + 焰橙/粉，Mozilla 可变字体（大厂发布感） | `deck-engine-V6焰彩白.html` |\n\n- ⚠️ **暖黑 `#161514` / V6焰彩黑 `#170a30` = 历史过渡态，不再新做**。线上尚有存量（算力账本·偷师=焰彩黑，Harness=暖黑），按计划逐步 flip 回米白；`deck-engine-暖黑.html` 仅为维护存量保留，**新 EP 不要拷它**。\n- 亮底适配铁律（米白/焰彩白）：网格线改极淡深色、卡片靠 `--shadow` 投影不靠辉光、标题黏土渐变(深→浅)、幽灵号深色 `opacity:.05`、`.grain` 用 `mix-blend-mode:multiply`。引擎 JS 主题无关、逐字一致。\n- **给存量 deck 换肤（黑→米白）→ 读 [`references/换肤-token-flip.md`](references/换肤-token-flip.md)**：脚本会截空文件、半成品会留残色，踩过的坑都在里面，别凭感觉改。\n\n### 1.5 批量做（多 EP）\n\n引擎相同、只内容不同 → 并行开多个 subagent，每个给「对应主色模板路径 + 源文章路径 + 本节规则」，要求 `<head>`CSS 与 `<script>`JS 与模板**逐字一致**，只换内容、按源文追加专属组件 CSS（滑块/时间线/对比/桥…，改用模板的 token）。产出后主控用 headless Chrome 截图核验各图表屏（`--virtual-time-budget=5000` 让动画跑完）。\n\n## 1.6 放映 / 提词器（讲 + 录 双用）⭐\n\n模块：`assets/presenter/presenter-module.html`（自包含 `<style>+<div>+<script>`，已注入三套引擎模板与 `examples/demo.html`，**拷模板即带，无需改引擎**）。\n\n- **按 `S`** 开「讲者视图」：**独立窗口**（计时器 + 当前镜逐字稿 + 下一镜预览），主屏与讲者窗靠 **BroadcastChannel 双向同步**——**主屏保持干净，可投影 / 录屏**。弹窗被拦（或无 BroadcastChannel）时自动回退为页内全屏浮层（单屏排练也能用）。\n- **真·双屏**：把 deck 在第二显示器再开一个窗口、地址后加 `?speaker=1` 即变讲者窗，免弹窗。讲者窗可**反向遥控主屏**：在讲者窗按 `←/→` 翻镜、`P` 计时、`R` 归零、`Esc/S` 关（靠向主屏引擎派发方向键事件，不改引擎）。\n- **键位**：`S` 开/关 · `P` 计时启停 · `R` 归零 · `Esc` 关 · `←/→` 翻镜（主屏与讲者窗都认）。\n- **逐字稿 = 配音 / 口播脚本**：在每张 `.slide` 里加 `<div class=\"notes\">这一镜要讲的话…</div>`（观众/录屏**永不可见**，模块强制 `display:none`）。这份 notes 同时就是该镜的口播稿——录屏时主屏放干净 deck、讲者窗当提词器照念；也可直接喂 TTS（云扬）。\n- 取数靠 `#deck .slide` 的 `.active` class（`MutationObserver` 监听），与引擎解耦；无 `.notes` 的镜回退显示标题。讲者信号用 `window.name`/`?speaker`（**不用 `#speaker`**——引擎深链 `replaceState('#N')` 会把 hash 冲掉）。\n- ⚠️ 本地 `file://` 双击时 `window.open` 可能被拦、且 BroadcastChannel 跨窗不通（opaque origin）——**用 `python3 -m http.server` 起本地服务**预览（与字体本地化要求一致）；发布到 CF Pages(https) 后正常。\n\n> 一图一镜 + 每镜一段 notes ⇒ 写完 deck 就同时有了「演示稿 + 提词器 + 口播稿」三合一。\n\n## 2. 首页 `home.html`\n\n演读 DECK 品牌落地页（**米白 `#faf9f5`**，2026-07-14 起；此前为暖黑）：masthead 品牌 + 「演读 ⟨DECK⟩」产品名、hero「把复杂的 AI，读成一场演示」、proof 三栏（第三种读法/翻页·自动播放/读完就懂）、系列卡片区（现 5 个：国标 / 算力账本 / 偷师AI大佬 / Harness工程 / 出行SaaS工程手记）、出品方 about（人设 + 禾口王=程）、订阅区（领《AI 内容流水线手册》三步）、底部内联留言板（`.talk-*`，`page='home'`）。**响应式**断点齐全（600/680/760/520）。\n- ⚠️ **系列卡是静态手写的**，不由 `MANIFEST` 生成（`write_index()` 是遗留死函数）——加系列要**手改 `home.html`** + 补 `MANIFEST`/`SERIES_META` 三处一起动。\n- 人设口径以记忆 `brand-persona-tagline` 三句为准（别自由改措辞）。**改首页改 `演读DECK/home.html`，不在 `dist/` 里改。**\n\n## 3. 字体自托管（零 CDN）⭐ 关键\n\n发布时 `publish.py` 的 `localize()` 把源 HTML 里所有 Google/loli 外链删掉、注入指向 `/fonts/` 的本地 `@font-face`；Anthropic 绝对路径也改写成 `/fonts/`。`subset_cjk()` 用 `tools/fenv` 的 `pyftsubset` 按**全站实际用字**把思源黑 4 字重（400/500/700/900，800 映射 900）+ 宋（金句衬线）子集化成小 woff2（各 ~180KB），连 Anthropic 一起打包进 `dist/fonts/`。\n\n- **首屏字重跳变(FOUT)**：每页 `<head>` 注入 4 条 `<link rel=preload>`（900/400/Anthropic Sans/Mono）让关键字体高优先级先下；`dist/_headers` 给 `/fonts/*` 设一周强缓存。这两条**必须保留**，否则首屏会「先系统字、再换思源」肉眼可见跳一下。\n- 字体源出处：思源来自 `@fontsource@5.0.0`（jsdelivr）逐字重静态 woff2；Anthropic 来自 `hekouwang-content-factory-skill/assets/fonts/`（自用/演示授权）；Mozilla Headline/Text VF 为 Mozilla 官方开源（OFL），可自由使用。\n- venv 丢了重建：`cd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli`。无 venv/字体源时 publish 回退用 `fonts/cache/`。\n\n## 4. 发布\n\n```bash\n# 从项目根运行\npython3 演读DECK/publish.py              # 构建 dist/ + 部署到 CF Pages（hekouwang）\npython3 演读DECK/publish.py --build-only # 只构建 dist/，不部署\n```\n\n- **加一期**：在 `publish.py` 的 `MANIFEST` 加一行（源 HTML 相对项目根的路径 + slug 如 `suanli/ep04` + 系列 + EP + 分类 + 标题 + 简介 + 屏数）。**加一个系列**：再补 `SERIES_META` 一条，**并手改 `home.html` 的系列卡**——首页系列卡是**静态手写**的，不由 MANIFEST 生成（`write_index()` 是遗留死函数，别指望它）。\n- **留言板**（Pages Functions + D1）随部署一起生效，**加装/排错 → 读 [`references/留言板-D1.md`](references/留言板-D1.md)**：部署得用配置式（不带 `dist` 参数）+ `cwd=SELF`，日志出现 `Uploading Functions bundle` 才算带上后端。\n- 干净 URL：演示版拷进 `dist/<slug>.html`，CF Pages 自动去 `.html`（`/suanli/ep01`）。\n- 部署用 `wrangler pages deploy dist --project-name hekouwang`；首次需 `wrangler login`（用户自己 `! wrangler login`）。\n\n## 5. 防踩坑（实测血泪）\n\n1. **`dist/` 每次构建被清空**——别在里面改任何东西；首页改 `home.html`，演示版改各 EP 源。\n2. **本地预览必须起 http 服务器**：`dist` 用站内 `/fonts/` 绝对路径，`file://` 双击打不出字体。`cd dist && python3 -m http.server 8000`。\n3. **`keynote.pages.dev` / `keynotes` 等常用名全球已被占**——CF 会自动加随机后缀(`keynote-9z0`)。本机网络有透明代理劫持 DNS、返回 198.18.0.x 假 IP，**本地 nslookup 测不出子域可用性**；唯一可靠 = `wrangler pages project create <名>` 后看 `project list` 分配的子域有没有后缀。最终用 `hekouwang`。\n4. **国内 EdgeOne 是死路**：免费自动域名一律带 token 鉴权、公网 401（ICP 备案要求），别再碰；直接 Cloudflare Pages。\n5. **移动 venv 会失效**（shebang/pyvenv.cfg 写死原路径）——换位置就重建。\n6. **本机代理会截断大文件下载(>~4MB)**：思源变量字体下不全 → 改用 @fontsource 逐字重静态 woff2(各 ~1.6MB)再子集化。\n7. 截图核验演示版给足时间（`--virtual-time-budget=5000`），让 fit/动画跑完再截。\n\n## 配套与依赖\n- **内容产线（强依赖）：`hekouwang-content-factory-skill`**——演示版的源文章 HTML、视觉规范(V1/V2/V3)、配色 token、字体方案都来自它；本 Skill 只做「内容→翻页演示+发布」这一半。**⚠️ 它是付费 Skill**（需作者授权），仓库不含其内容。只用引擎可直接拷 `assets/templates/deck-engine-*.html`（零依赖独立可用）。\n- 示例：`examples/demo.html`（自包含、零依赖、双击即看的最小动画示例）。\n- 记忆：`keynote-yanshi-site`（站点现状 + 发布链路）、`keynote-deck-engine`（引擎做法）、`brand-persona-tagline`（人设三句）。\n\nFile v1.3.1:README.md\n\n# hekouwang-yandu-deck-skill · 演读 DECK\n\n**中文** · [English](README.en.md)\n\n> GitHub: [https://github.com/huiyonghkw/hekouwang-yandu-deck-skill](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n\n会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。\n\n把一篇文章/选题做成**一屏一镜、可翻页、能自动播放**的 keynote 演示版网页（**暖黑** / **米白** 两套主色），自托管字体（思源黑/宋子集化 + Anthropic 打包、零 CDN、preload 治 FOUT），并一键发布到 Cloudflare Pages。\n\n线上样例：**https://hekouwang.pages.dev**\n\n## 30 秒验收\n\n```bash\nopen examples/demo.html                              # 零依赖最小示例\nbash scripts/sync-from-harness.sh <path/to/演读DECK>  # 真身→副本同步\npython3 scripts/publish.py --help                    # 发布脚本可用性\n```\n\n## 免费 / 付费\n\n| | 免费（本仓库） | 付费增值 |\n|---|---|---|\n| 引擎模板 | `deck-engine-米白/V6/暖黑` + `demo.html` | 定制系列视觉 / 内容产线 |\n| 发布 | `publish.py` + CF Pages 配方 | `hekouwang-content-factory` 授权 |\n| 联系 | GitHub Issue | **@huiyonghkw** |\n\n## 示例动画版本 / Demo\n\n最快的体验方式 —— 双击打开 **[`examples/demo.html`](examples/demo.html)**：一个**自包含、零依赖、系统字体**的最小示例，直接 `file://` 打开就能看引擎怎么动（翻页 / 自动播放 / 柱子生长 / 数字滚动 / 折线描线 / 卡片错峰）。\n\n| 封面（数字滚动 + 标题渐变） | 流程屏（节点淡入 + 箭头描线 + stat 弹入） |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **在线完整版（可翻页/自动播放）**：\n  - 首页：<https://hekouwang.pages.dev>\n  - 暖黑系列：<https://hekouwang.pages.dev/suanli/ep01>（`#3` 直达第 3 屏）\n  - 米白系列：<https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` 是两套**完整引擎模板**（需起本地服务器看字体：`python3 -m http.server`）。\n\n## 依赖\n\n| 依赖 | 关系 | 说明 |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **内容来源（强依赖）** | 本 Skill 是「**把内容做成翻页演示 + 发布**」的一半；**另一半（生成文章 HTML、视觉规范 V1/V2/V3、去 AI 味、合规红线）在 `hekouwang-content-factory`**。演示版的源 HTML、配色 token、字体方案都源自它。**⚠️ `hekouwang-content-factory` 是付费 Skill**（GitHub 上为 **PRIVATE 私有仓库，非授权无法 clone / 获取**；需向作者 @huiyonghkw 获取授权），本仓库不含其内容。 |\n| Python 3 + `fonttools`+`brotli` | 字体子集化 | 仅发布时需要（`tools/fenv` venv，见 `SKILL.md`）。没有则回退用 `fonts/cache/` 已切好的子集。 |\n| `wrangler`（Cloudflare） | 部署 | `publish.py` 调它发到 CF Pages；首次需 `wrangler login`。 |\n| Anthropic Sans/Mono woff2 | 拉丁/代码字体 | 来自 `hekouwang-content-factory`（自用/演示授权）。缺失则拉丁字自动回退系统字。 |\n\n> 只想用**引擎**（不要内容产线）：直接拷 `assets/templates/deck-engine-*.html` 当模板填内容即可，那部分零依赖、可独立使用。\n\n## 这是什么\n\n这是一个 [Claude Code](https://claude.com/claude-code) **Skill**，按官方 `anthropics/skills` 约定分目录组织。`SKILL.md` 是给 Agent 读的方法说明；`scripts/` `assets/` `references/` `examples/` 是可直接拷用的脚本、模板、文档与示例。\n\n```\nSKILL.md                              # 方法 + 触发词 + 防踩坑（Agent 入口）\nscripts/\n└── publish.py                       # 构建 dist/ → 部署 CF Pages（零三方依赖）\nassets/templates/\n├── deck-engine-暖黑.html             # 演示版引擎模板（数据/财经/科普暗调）\n├── deck-engine-米白.html             # 演示版引擎模板（人文/方法论亮调）\n└── home.html                        # 首页模板\nreferences/\n└── 系统说明.md                       # 系统说明文档\nexamples/\n└── demo.html                        # 零依赖最小示例（双击即看）\n```\n\n> 落地铁律：`scripts/publish.py` 与 `assets/templates/home.html` 拷进项目时必须放进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源）。\n\n## 安装\n\n把本仓库放进 `~/.claude/skills/hekouwang-yandu-deck-skill/`：\n\n```bash\ngit clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill\n```\n\n之后在 Claude Code 里说「把这篇做成演示版 / 加一期演读 / 发 hekouwang」等即会自动加载。\n\n## 核心能力\n\n- **演示版引擎**（零依赖 CSS+JS）：全屏一屏一镜、←/→/空格/点击/触屏翻页、自动播放、进场动画（卡片错峰 / 柱子生长 / SVG 描线 / 数字滚动 / 幽灵章节号）、`fit()` 自适应、`#N` 深链、`prefers-reduced-motion` 友好。\n- **两套主色**：暖黑（数据控制台）/ 米白（编辑人文），引擎 JS 主题无关。\n- **字体自托管**：思源黑 4 字重 + 宋按用字子集化（各 ~180KB），Anthropic Sans/Mono 打包，全站零外链；preload + 强缓存消除首屏字重跳变。\n- **一键发布**：`python3 publish.py`，MANIFEST 加一行即加一期，CF Pages 干净 URL。\n\n> 配套图文/视频产线见 `hekouwang-content-factory`。\n\n## License\n\n本仓库代码（演示版引擎模板、`publish.py`、`demo.html`、`home.html`、`SKILL.md` 等）以 **MIT** 开源，见 [LICENSE](LICENSE)。注意：\n\n- **`hekouwang-content-factory` 是独立的付费 Skill，其内容不在本仓库**，不受本许可覆盖。\n- 思源黑体/思源宋体（Noto Sans/Serif SC）为 SIL OFL 开源字体，本仓库**不含字体文件**，自行获取时遵循其 OFL。\n- Anthropic Sans/Mono 为专有字体，本仓库不含，使用前自行确认授权。\n\nFile v1.3.1:_meta.json\n\n{\n  \"ownerId\": \"kn73qd1gcmjr446mwcbdxef70x82vxcw\",\n  \"slug\": \"hekouwang-yandu-deck-skill\",\n  \"version\": \"1.3.1\",\n  \"publishedAt\": 1786521767889\n}\n\nFile v1.3.1:references/mobile-and-comments.md\n\n# 移动端 safe-area · 留言板开关 · 视频交叉引用\n\n## 移动端 safe-area\n\n演示引擎默认 `viewport-fit=cover`，全屏翻页时顶底栏要留 **safe-area**：\n\n```css\n.deck-toolbar {\n  padding-bottom: max(12px, env(safe-area-inset-bottom));\n  padding-left: max(16px, env(safe-area-inset-left));\n  padding-right: max(16px, env(safe-area-inset-right));\n}\n```\n\n- iOS 刘海/底条：没写 `env(safe-area-inset-*)` 时，翻页按钮和进度条会被挡。\n- 横屏演示：左右 inset 同样要留，别只照顾 bottom。\n- 验收：真机 Safari「添加到主屏幕」全屏翻 3 页，拇指区按钮必须可点。\n\n## 留言板（可选子系统）\n\n默认 **hekouwang.pages.dev 线上开着**；新站或纯静态演示可关：\n\n1. 删或移走 `演读DECK/functions/`（Pages Functions 不再挂载）\n2. `wrangler.toml` 里去掉 `[[d1_databases]]` 绑定\n3. `home.html` / 引擎模板里去掉留言入口 DOM 与 fetch 调用\n\n排错见 `references/留言板-D1.md`；**database_id 必须是自己的**，副本里是占位符。\n\n## 与 HyperFrames 视频产线\n\n- **演读 DECK** = 一屏一镜 **可翻页 HTML**，适合长文拆解、国标系列、教程跟读。\n- **HyperFrames 视频** = 同选题的 **ffmpeg 成片**（harness 内 `EP-*/video/` 或动画 Skill）。\n- 同一 EP 可两条线并存：文章母本 → 演示版 HTML（本 skill）+ 可选视频目录；**不要**在 deck 引擎里引外链视频或 `Date.now()`/`Math.random()`（与 harness `AGENTS.md` 视频红线一致）。\n\nFile v1.3.1:references/换肤-token-flip.md\n\n# 演读 DECK · 换肤 = token-flip（不是重做）\n\n给**已有 deck** 换主色时用这套。核心认知：两套主色的 `:root` **逐行结构完全一致、只有值不同**——所以换肤是一次**机械的 token 值映射**，引擎 CSS/JS 一字不动，内容一字不动。别重写、别让 subagent \"参照着做一版\"。\n\n> 当前口径见 SKILL.md 第1.4节：**米白 = 全站默认**，国标走 V6 焰彩白，**暖黑/焰彩黑是存量历史态**——本文档现在主要服务于「存量黑版 → 米白」的收敛。\n>\n> 现成脚本：**`scripts/flip-暖黑到米白.py`**（映射抽自引擎模板 · 单遍替换 · 内建未覆盖色守卫 · 先读后写）。用法 `python3 scripts/flip-暖黑到米白.py <deck.html>...`；退出码 2 = 有未覆盖色，按 第2.6节 人工判断后再跑。\n\n## 0. 动手前（这五步省过一次 9 期全毁）\n\n1. **先查 git 有没有现成的目标态**——见 第0.5节，能取回就别转换。\n2. **先 cp 备份**要改的文件。\n3. flip 脚本**必须先读后写**（见 第3节 第 1 条，这是最贵的坑）。\n4. flip 后 `stat -f%z` 查**每个文件大小非 0**。\n5. flip 后跑**全谱残留 grep**（第2节），**=0 才算过**。\n\n## 0.5 先问一句：git 里是不是躺着现成的？⭐ 省一整轮\n\n演读 DECK 的 deck HTML **都在 git 里**（只有 `演读DECK/publish.py` 被 `.gitignore` 的 `*.py` 排除）。整站换过肤，就意味着**换肤前的版本还在历史里**。要换回某个旧主色时，先查：\n\n```bash\ngit log --oneline --all -- <deck路径>                    # 哪次提交换的肤\ngit show <flip提交>^:<deck路径> | grep -oE -- '--bg:#[0-9a-f]*'   # 换肤前是什么色\ngit log --oneline <flip提交>..HEAD -- <deck路径>          # 换肤后还改过内容吗（0 = 可安全取回）\n```\n\n**换肤后 0 次提交 = 直接 `git show <flip提交>^:<路径>` 取回，精确、零转换风险**，比任何 flip 脚本都可靠。\n2026-07-15 实战：偷师 4 期换肤前本就是米白、之后 0 改动 → 直接取回，全谱残留 grep=0 一次过；而算力 5 期换肤前是**暖黑**（不是米白），取回只能拿到暖黑，仍需一轮真转换。**先查再动，别默认要写脚本。**\n\n## 0.6 ⚠️ 跨设计系统 ≠ 换肤，别硬套\n\n本文档的 flip 只适用于**同一套设计系统的明暗两极**（V6焰彩白↔V6焰彩黑、暖黑↔米白——后两者同为 V2 黏土系统）。\n\n**焰彩黑 → 米白 是跨系统**：主色紫 `#a855f7` vs 黏土 `#c15f3c`、字体 Mozilla VF vs Anthropic Sans，V6 的焰橙/焰粉在 V2 里根本没有对应色。硬套 token-flip 会出四不像。跨系统要走「先 git 取回同系统版本，再同系统 flip」，或老老实实重做。\n\n## 1. 已验证的映射\n\n### 1.1 V6 焰彩：白 ↔ 黑（两向互为精确逆运算）\n\n| 语义 | 焰彩白 | 焰彩黑 |\n|---|---|---|\n| 底 | `#fbfaff` | `#170a30` |\n| surface | `#ffffff` / `#f4eefc` / `#efe7fb` | `#241246` / `#231044` / `#2c1552` |\n| 正文字 | `#1c0b3e` | `#f3eefe` |\n| 主紫 | `#7c3aed` | `#a855f7` |\n| 次紫 | `#6d28d9` | `#c084fc` |\n| 蓝 | `#4f6ef0` | `#7c9bff` |\n| 金 | `#c8620a` / `#e07a1a` | `#ffb454` / `#f0a13a` |\n| warn | `#e0304f` | `#ff5c78` |\n| 线 | `rgba(28,11,62,…` | `rgba(255,255,255,…` |\n| 紫辉光 | `rgba(124,58,237,…` | `rgba(168,85,247,…` |\n| grain | `multiply` `.02` | `screen` `.05` |\n| body class | `class=\"light\"` | `class=\"dark\"` |\n\n**黑白通用、不翻**：焰橙 `#ff8a3d`、焰粉 `#ff4f8b`、`--ok`、`--teal`。\n**演示版与首页的 token 值不同，各写一份映射**，别共用一张表。\n\n### 1.2 暖黑 / 米白（旧两套）\n\n暖黑 `#161514` + 黏土 `#e08a5f` + 石板蓝 `#8fa6bd`；米白 `#faf9f5` + 黏土 `#c15f3c`。\n亮底适配：网格线→极淡深色、卡片靠 `--shadow` 不靠辉光、幽灵号深色 `opacity:.05`、`.grain`→`multiply`。\n\n## 2. 三条验收（缺一条都不算换完）\n\n1. **全谱残留 grep = 0**：拿**旧主色整套调色板**（不只是 `--bg`）去 grep，包括 SVG 内联色。半成品最爱漏的就是图表里的 `#e08a5f`（暖黑黏土）、`#8fa6bd`（石板蓝）。有残留 → 补一轮「旧色→新色」映射再跑。\n2. **封面截图**肉眼过一眼。\n3. **线上 curl 验 token**：跟随 308（`/suanli/ep04.html` → `/suanli/ep04`），确认 `--bg` 和 `class` 是新值。\n\n## 2.5 映射表从模板里抽，别手编；且必须**单遍同时替换** ⭐\n\n**映射的唯一真相源 = 两套引擎模板的 `:root` 逐 token 对照**（同一个引擎、两个主题，key 一一对应）。用脚本 diff 出来，别凭记忆写色号：\n\n```python\n# 剥掉 /* 注释 */ 再解析 :root，逐 key 比对 deck-engine-暖黑 vs deck-engine-米白\n```\n\n实测暖黑 33 token / 米白 26 token，其中 **20 个值不同**（`--bg/--surface*/--line*/--text*/--read/--hot*/--hl0/--cool*/--ochre*/--warn`），4 个通用不翻（`--font/--serif/--mono/--brand`）；另 `--m-*`（9 张插画）暖黑独有、**`stroke='%23000'` 单色遮罩、不含主题色**（靠 CSS 着色，不用管）；`--shadow/--shadow2` 米白独有（亮底要投影），flip 时**要补进去**。\n\n⚠️ **源集与目标集有交集 → 必须单遍替换**：`#f4f2eb` 既是源（暖黑 `--text` → `#1a1a18`）又是目标（暖黑 `--surface2` → `#f4f2eb`）。顺序 sed 会把前一条刚写出的颜色被后一条**再吃一次**，静默改错。正确做法是拼一个大 alternation 一次扫过：\n\n```python\npat = re.compile('|'.join(re.escape(k) for k in sorted(MAP, key=len, reverse=True)), re.I)\nout = pat.sub(lambda m: MAP[m.group(0).lower()], html)   # 单遍，绝不二次命中\n```\n\n## 2.6 图表内部色 ≠ 页面色：**脚本先扫「未覆盖色」并停下来** ⭐\n\ntoken 映射只管**相对页面底色**的颜色。deck 里还有大量**图表内部色**，它们的对比度是相对自己所在的色块，**翻了反而坏**：\n\n- `#19191a` 深字压在浅蓝柱 `#8fa6bd` 上 → 页面转亮底也得**留深**，翻了字就没了\n- `#e8eef3` 浅字压在深柱上 → **留浅**\n- 柱状填充（`#5e6b75`/`#a9714f`/`#8a7d70`）中间调 → 黑白底都成立，**别动**\n- 语义色（如 Harness 里 MCP 的绿 `#8fbf9f`）有含义 → **别当装饰色翻**\n- `#pmode` 讲者浮层（`#0c0d10`/`#ececf2`/`#9a9aac`…）、`.shell` 终端（`#1f1d1b`/`#0c0d10`）**刻意深底** → 不翻\n\n所以 flip 脚本**必须内建一道守卫**：转换前先扫全部目标文件，报出「映射表未覆盖、又不在保留名单」的裸色，**有就退出让人判断**，别闷头转（2026-07-15 实测：算力 EP01 干净，其余 5 期共 **15 种**各自的图表色需人工过——守卫挡住了一次静默改坏）。\n\n## 3. 血泪坑（都已解，别重踩）\n\n1. ⚠️ **原地覆盖脚本必须先读后写**——最贵的一个坑，曾把 9 期**全写空**：\n   ```python\n   # ✗ src==dst 时，open(dst,'w') 先把文件截断成空，再 read 就读到空字符串\n   open(dst,'w').write(flip(open(src).read()))\n   # ✓ 先读进内存，再开写\n   data = open(src).read()\n   open(dst,'w').write(flip(data))\n   ```\n2. **`.shell` 终端组件不翻**：`#1f1d1b` / `#0c0d10` / `rgba(0,0,0,.2)` 是**刻意的深底代码块**（米白/焰彩白母本自身就 `.shell{background:#1f1d1b}`），亮底下也该是深的。只在 `--shadow` 行里翻 `rgba(0,0,0,`，其余深底放行。\n3. **显式串先做**：`shadow` / `body 光晕` / `grain` 这类整串先替换，避免被后面的 bare-value 规则拆坏 alpha。\n4. **grep 单行 minified 会漏**：subagent 输出常是单行 HTML，`grep -c \"--bg:\"` 按行匹配会误判。用 `grep -o`，或先 `wc -c` 看是不是空文件。\n5. **半成品残留**：subagent 转版被中途停 → body SVG 内联色没转完。所以验收靠 第2节 第 1 条，不靠\"它说它做完了\"。\n6. **截图坑 → 用 `--headless=new` + `--timeout`**（2026-07-15 修正）：deck 的 `.draw` 动画让 `--virtual-time-budget` 不收敛。旧 `--headless` 会**挂死且不写盘**（`timeout` 杀进程后目录里什么都没有；\"杀了图其实已写盘\"的旧说法**实测不成立**，别信）。可靠配方——**1.5 秒出图**：\n\n   ```bash\n   \"$CHROME\" --headless=new --disable-gpu --incognito --user-data-dir=\"$TMP/prof\" \\\n     --window-size=1600,900 --hide-scrollbars \\\n     --virtual-time-budget=15000 --timeout=30000 \\\n     --screenshot=\"$TMP/cover.png\" \"file://$DECK\"\n   ```\n   `--timeout` 让 Chrome 自己到点截图退出（退出码 0），不必外部 `pkill`。字体走 content-factory 绝对路径，`file://` 即可加载。\n   ⚠️ 必带 `--incognito` + 独立 `--user-data-dir`，**别碰用户正在用的 Chrome**（见 memory `chrome-screenshot-isolated-incognito`）。\n\nFile v1.3.1:references/留言板-D1.md\n\n# 演读 DECK · 访客留言板（CF Pages Functions + D1）\n\n站点自带留言板：**Cloudflare Pages Functions + D1**，留言存在**自己的 CF 账号**里——无第三方、不用 giscus/GitHub 登录（国内读者友好）。**按页隔离**：首页 `home`，每期用 slug（`suanli/ep04`），各聊各的。\n\n## 1. 件在哪（本 skill 捆绑的落地副本）\n\n| 文件 | 作用 |\n|---|---|\n| `assets/functions/api/comments.js` | 后端：`onRequestGet`（读 `?page=` 列表）/ `onRequestPost`（校验+限频+写入） |\n| `assets/templates/wrangler.toml` | Pages 配置 + D1 绑定（`binding=DB`）。**database_id 是占位符，落地时填自己的** |\n| `assets/templates/schema.sql` | `comments` 表结构（含 `page` 列做隔离） |\n| `scripts/publish.py` → `inject_comments()` | 构建层把留言面板注入每篇 `</body>` 前 |\n\n**落地时全部拷进 `<项目根>/演读DECK/`**（`functions/` 保持 `functions/api/comments.js` 这个路径，Pages 按目录约定找）。\n\n## 2. 建库三步（新项目）\n\n```bash\ncd <项目根>/演读DECK\nwrangler d1 create <你的库名>                                  # ① 输出里拿 database_id\n#   ② 把 database_id / database_name / name 填进 wrangler.toml\nwrangler d1 execute <你的库名> --remote --file=schema.sql       # ③ 建表\n```\n\n> 改表结构：`CREATE IF NOT EXISTS` **不会 ALTER**，得先 DROP 再建。本地调试把 `--remote` 换 `--local`。\n\n## 3. 两种形态（为什么不一样）\n\n- **首页**：页面向下滚动 → 底部**内联**留言板（`.talk-*`），JS 里 `page='home'`。手写在 `home.html`。\n- **每期 deck**：全屏翻页、`body{overflow:hidden}` **不滚动** → 留言板做成**右侧把手 + 滑出面板 overlay**（`.hkwc-*`，暗色玻璃，对米白/焰彩白都压得住）。**不碰翻页引擎**（同讲者模式的思路），由 `publish.py` 的 `inject_comments()` 在构建层注入，**EP 源文件不动**。\n\n## 4. 已有防护（改的时候别拆掉）\n\n昵称 ≤24 / 正文 ≤500；`SHA256(salt|IP)` 前 32 位做限频（同 IP 20s 一条，**不存明文 IP**）；蜜罐字段 `website`（机器人填了就静默丢）；`ensureSchema` 幂等自建表；渲染端 `esc()`（`textContent`→`innerHTML`）防 XSS；`PAGE_RE` 白名单把非法 page（`../etc/passwd`）归 `home`，挡路径注入。\n\n## 5. 部署踩坑\n\n1. **配置式部署，别带目录参数**：要让 D1 绑定 + functions 随部署生效，`deploy_cloudflare()` 用 `wrangler pages deploy`（**不带 `dist` 参数**，带了会和 `pages_build_output_dir` 冲突）+ `cwd=SELF`（让它读到 `wrangler.toml`）。**部署日志出现 `Uploading Functions bundle` 才算带上了后端。**\n2. **验证线上要跟随 308**：`/suanli/ep04.html` → 308 → `/suanli/ep04`（Pages 去 `.html`）。`curl` 不加 `-L` 只看到空的 308 body，会误判成注入失败。\n3. **本机 curl 走代理**：测本地/线上接口都要 `--noproxy '*'`。\n\n## 6. 它还是「国内真人来没来」的口径\n\n留言板 D1 里的真实留言 + Web Analytics beacon 才是真人信号。**CF「帐户分析/流量概览」统计的是边缘请求数、机器人全算进去，会虚高几十倍，别拿它做决策。**beacon 的 `static.cloudflareinsights.com` 国内可能加载失败 → CN 真人会被少计，所以判断国内真人另看留言板 D1 / 公众号后台。\n\nFile v1.3.1:references/系统说明.md\n\n# 演读 DECK · 沉浸式演示发布系统\n\n> **这份是「落地 README 模板」**：新项目落地时连同 `publish.py` / `home.html` 一起拷进 `<项目根>/演读DECK/README.md`，给**人**看。\n> 给**模型**看的产线规矩在 SKILL.md（做 deck、换肤、留言板都从那儿走），别在这里堆细节。\n\n把「演示版」HTML（一屏一镜、可翻页、能自动播放的 keynote 长文）打包发布到 Cloudflare Pages。\n**线上：https://hekouwang.pages.dev** ｜ 出品：会勇禾口王的AI笔记。\n\n演示版「内容」（各 EP 的 HTML）放在项目内的选题目录里（`EP-算力账本/`、`EP-偷师AI大佬/`…），本目录只放**发布引擎 + 首页 + 字体管线 + 留言板后端**。\n\n## 目录结构\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/\n│   └── api/comments.js   # 留言板后端（Pages Functions）\n├── README.md        # 本说明\n├── fonts/\n│   ├── src/         # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700\n│   │                #        + Anthropic Sans/Mono + Mozilla Headline/Text VF\n│   └── cache/       # 子集化产物缓存（无字体源/无 venv 时回退用）\n├── tools/fenv/      # 子集化用的 Python venv（fonttools+brotli）；移动会失效，丢了就重建\n└── dist/            # ← 构建产物 = 部署到 CF Pages 的目录（可整删，重新构建即生成）\n```\n\n## 用法\n\n```bash\n# 从项目根运行\npython3 演读DECK/publish.py              # 构建 + 部署到 Cloudflare Pages\npython3 演读DECK/publish.py --build-only # 只生成 dist/，不部署\n\n# 本地离线预览（dist 用站内 /fonts/ 绝对路径，必须起服务器，不能 file://）\ncd 演读DECK/dist && python3 -m http.server 8000   # 浏览器开 http://localhost:8000/\n```\n\n**加一期**：在 `publish.py` 的 `MANIFEST` 加一行（源 HTML 路径 + slug + 系列 + 标题…），重跑即可。\n**加一个系列**：补 `SERIES_META` 一条，**并手改 `home.html` 的系列卡**（首页卡是静态手写的，不由 MANIFEST 生成）。\n\n## 它做了什么（关键设计）\n\n1. **干净 URL**：演示版拷进 `dist/<slug>.html`（如 `suanli/ep01`），CF Pages 自动去 `.html`。\n2. **字体全自托管、零 CDN**（`localize()`）：删掉源 HTML 里所有 Google/loli 外链，注入指向 `/fonts/` 的本地 `@font-face`；`FONT_ABS_RE` 把任意绝对字体路径 / 未替换的 `{{SKILL_DIR}}` 占位符统一收编成 `/fonts/`（覆盖 Anthropic + Mozilla）。\n3. **思源黑/宋按用字子集化**（`subset_cjk()`）：用 `tools/fenv` 的 `pyftsubset` 把全站实际用到的字切成小 woff2（各 ~180KB），思源黑 4 字重（400/500/700/900，800 映射 900）+ 宋（金句衬线）。Mozilla VF 是拉丁、体积小，整包打进不子集化。无 venv/字体源时回退 `fonts/cache/`。\n4. **首屏字体预加载 + 强缓存**：每页 `<head>` 注入 `<link rel=preload>`（含 Mozilla 的走 `PRELOAD_LINKS_V6`，按页面是否含 \"Mozilla\" 判定），消除「先系统字、后换思源」的字重跳变；`dist/_headers` 给 `/fonts/*` 设一周强缓存。\n5. **留言板注入**（`inject_comments()`）：构建层把右侧滑出面板注入每篇 `</body>` 前，**EP 源文件不动**。\n\n## 首次落地 / 换机器\n\n```bash\n# 子集化 venv（丢了或换机器时重建）\ncd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli\n\n# 留言板 D1（不做留言板可跳过，并删掉 wrangler.toml / schema.sql / functions/）\nwrangler d1 create <你的库名>                                # 拿 database_id 填进 wrangler.toml\nwrangler d1 execute <你的库名> --remote --file=schema.sql    # 建表\n\n# 部署前先登录\nwrangler login\n```\n\n**要填的自己的值**：`publish.py` 的 `CF_BEACON_TOKEN`（CF Web Analytics，留空则不注入）、`wrangler.toml` 的 `name` / `database_name` / `database_id`。\n\n## 字体源出处\n\n思源黑/宋来自 `@fontsource@5.0.0`（jsdelivr）逐字重静态 woff2；Anthropic Sans/Mono 来自\n`hekouwang-content-factory-skill/assets/fonts/`（自用/演示授权，见该 Skill #9.1.3）；\nMozilla Headline/Text VF 为 Mozilla 官方开源（OFL），可自由使用。\n\nFile v1.3.1:CHANGELOG.md\n\n# 更新日志 · hekouwang-yandu-deck-skill\n\n本文件记录本 Skill 的所有版本变更。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/)，\n版本号遵循 [语义化版本 SemVer](https://semver.org/lang/zh-CN/)：`MAJOR.MINOR.PATCH`。\n\n**变更分类**\n- `功能` 新增能力 · `变更` 默认/行为调整 · `优化` 既有能力打磨 · `修复` 缺陷修正 · `移除` 删除\n\n---\n\n## [1.3.1] - 2026-08-12\n\n### 优化\n- README：30 秒验收 + 免费/付费表 + @huiyonghkw CTA\n- summary 补英文 SEO 关键词（keynote deck / Cloudflare Pages）\n\n## [1.3.0] - 2026-08-12\n\n### 功能\n- **`scripts/sync-from-harness.sh`**：从 harness `演读DECK/` 单向同步 `publish.py`、`home.html`、留言板模板到 skill 副本。\n\n### 优化\n- **副本追平真身**：`publish.py` 802 行与 harness 对齐（含 Harness 工程系列 / FastMCP / 股票识字等 MANIFEST）。\n- **`references/mobile-and-comments.md`**：移动端 safe-area、留言板禁用步骤、与 HyperFrames 视频产线分工。\n\n## [1.2.1] - 2026-08-12\n\n### 变更\n- **品牌人设对齐 memory `brand-persona-tagline`**：首页 `home.html` 与 `publish.py` 内嵌 about 段，\n  「真会用 AI 的程序员」→ **「会勇禾口王 = AI 工作流 builder」**；补「会勇」谐音「会用」梗。\n- about 文案微调：强调「不靠 PPT 教人，先在自己电脑上跑通再把 Skill 交到你手上」。\n\n## [1.2.0]\n\n### 修复\n- **捆绑副本追平真身（本次最大的洞）**：skill 里的 `publish.py`（511 行）已落后项目真身（735 行）——**SKILL.md 白纸黑字写着「publish.py 已支持 Mozilla 字体打包」，而副本里 \"mozilla\" 出现 0 次**；`home.html` 也只有真身的一半（314/657）。已全量同步，并补上从未随 skill 分发的留言板子系统。承诺现在兑现得了。\n- **主色口径追平线上**：description 与 第1.4节 还写着「暖黑/米白两套主色」，实际线上已是四套并存。**推测缺件正是漂移的成因**——占大头的 V6 焰彩黑没有模板（黑版是 flip 出来的），新 EP 无黑版可拷只能退回老模板，Harness（暖黑）/ 出行SaaS（米白）就是这么来的。\n- **陈旧引用**：兄弟 skill 名补 `-skill` 后缀（真实目录是 `hekouwang-content-factory-skill`，旧名照着找会扑空）；`ROOT` 注释里的旧项目名 `Pi.dev/`；`references/系统说明.md` 里的「后续会升级成 Skill」（早就是了）。\n- **第2节 首页描述**：主色暖黑 → **米白**（2026-07-14 已改），系列卡「两个」→ **五个**，并点明系列卡是**静态手写**、不由 MANIFEST 生成（`write_index()` 是遗留死函数），加系列须三处一起动。\n\n### 功能\n- **留言板随 skill 分发**（`references/留言板-D1.md` + `assets/functions/api/comments.js` + `wrangler.toml` + `schema.sql`）：CF Pages Functions + D1，按页隔离，留言存自己的 CF 账号、无第三方。含建库三步、已有防护（限频/蜜罐/XSS/路径注入）、部署三坑（配置式部署不带 dist 参、验证跟随 308、curl 加 `--noproxy`）。\n- **换肤专题**（`references/换肤-token-flip.md`）：白↔黑 token-flip 映射表 + 三条验收 + 六个坑。含「**原地覆盖脚本先读后写**」——`open(dst,'w')` 会先把文件截断成空，曾把 9 期全写空。\n\n### 变更\n- **第1.4节 主色规矩改为「米白是全站默认，V6 焰彩白是国标专属例外」**；暖黑 / V6焰彩黑降为**存量历史态、不再新做**（存量按计划 flip 回米白）。`deck-engine-暖黑.html` 仅为维护存量保留，标注「新 EP 别拷」。故**不再补 V6焰彩黑模板**——补了等于鼓励继续新做。\n\n### 优化\n- **副本去账号化**（skill 是公开分发的）：`CF_BEACON_TOKEN` 置空（留空则不注入 beacon，降级干净）、`wrangler.toml` 的 `database_id` 改占位符。否则别人用这个 skill 建的站，流量统计报到作者面板、留言写进作者的库。\n- **删死代码**：`FONT_ABS_PREFIX` 指向一个不存在的目录（少 `-skill` 后缀），真正干活的是 `FONT_ABS_RE`。已删常量、采用 skill 版更通用的正则（同时认 `{{SKILL_DIR}}` 占位符与任意绝对路径，覆盖 Anthropic + Mozilla）。\n- **第0节 加防漂移提示**：点明「项目里的是真身、skill 里的是副本，改完记得同步回来」，并记下这次漂移作为前车之鉴。\n\n## [1.1.0]\n\n### 功能\n- **放映 / 提词器模块**（`assets/presenter/presenter-module.html`，第1.6节）：按 `S` 开「讲者视图」独立窗口——计时器 + 当前镜逐字稿 + 下一镜预览。主屏与讲者窗靠 **BroadcastChannel 双向同步**，**主屏保持干净可投影/录屏**；弹窗被拦（或无 BroadcastChannel）自动回退页内浮层。\n- **真·双屏 + 反向遥控**：第二显示器另开 deck 窗口加 `?speaker=1` 即变讲者窗（免弹窗，`window.name`/`?speaker` 识别，绕开引擎深链冲 hash）；讲者窗按 `←/→` 遥控主屏翻镜、`P/R` 控计时（向主屏引擎派发方向键事件，不改引擎）。键位 `S/P/R/Esc`。\n- 逐字稿写进每张 `.slide` 的 `<div class=\"notes\">`（观众/录屏永不可见），**同时即该镜的配音/口播脚本**，可照念或喂 TTS——「演示稿 + 提词器 + 口播稿」三合一。\n- 已注入两套引擎模板（暖黑/米白）与 `examples/demo.html`，拷模板即带，无需改引擎；靠 `.active` class（MutationObserver）与引擎解耦。无头截图验证浮层渲染通过。\n\n## [1.0.1]\n\n### 变更\n- **目录结构对齐官方 `anthropics/skills` 约定**：原先所有可移植副本都堆在 `reference/`（单数、且混入可执行脚本）。\n  现按官方分目录——`scripts/publish.py`、`assets/templates/{deck-engine-暖黑,deck-engine-米白,home}.html`、\n  `references/系统说明.md`、`examples/demo.html`。SKILL.md / README(中英) 的指针与结构树同步更新。\n  注：`scripts/publish.py` 与 `assets/templates/home.html` 落地时仍须拷进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源），文档已注明。\n\n## [1.0.0]\n\n首个有记录的版本（此前以 git 历史维护，无 CHANGELOG）。\n\n### 修复\n- **字体路径可移植化**：① `reference/publish.py` 的 `localize()` 由写死的绝对前缀\n  （硬编码家目录 + `assets/fonts/`）改为**正则 `FONT_ABS_RE`**，同时认「任意绝对路径」与未替换的\n  `{{SKILL_DIR}}` 占位符，统一收成站内 `/fonts/`；② 引擎模板 `deck-engine-{暖黑,米白}.html` 的\n  `@font-face` 硬编码字体路径改为占位符 `{{SKILL_DIR}}/assets/fonts/`，拷模板做 EP 时替换。\n  不再绑定某台机器/用户名；同时修了 content-factory 改用 `{{SKILL_DIR}}` 占位后、源 HTML 字体前缀随机器变化会替换不中导致字体失效的隐患。\n\n### 优化\n- **SKILL.md 声明 `allowed-tools`**：收敛到本 skill 真正需要的工具集，减小越权面。\n\n### 既有能力（首版基线）\n- **演示版引擎**：零依赖（纯 CSS + 原生 JS）一屏一镜 keynote，暖黑/米白两套主色；导航（方向键/空格/点击/触屏/圆点/全屏）、自动播放、进度条、深链、`prefers-reduced-motion` 自适应。模板 `reference/deck-engine-{暖黑,米白}.html`。\n- **进场动画钩子**：`.an/.bar/.tok/.draw/.grow/[data-count]` + 巨幅幽灵章节号。\n- **字体自托管（零 CDN）**：`publish.py` 删外链、注入本地 `@font-face`、`pyftsubset` 子集化思源黑 4 字重 + 宋，preload 防 FOUT，`/fonts/*` 强缓存。\n- **发布**：构建 `dist/` → `wrangler pages deploy` 到 Cloudflare Pages（hekouwang.pages.dev）；`MANIFEST`/`SERIES_META` 加期加系列。\n- **踩坑沉淀**：dist 每构建清空、本地预览须起 http、CF 子域占用 + 本机 DNS 劫持、EdgeOne 死路、venv 移动失效、代理截断 >4MB 下载。\n- 强依赖内容产线 `hekouwang-content-factory`（付费 skill，提供源文章/视觉规范/字体）；引擎可零依赖单独使用。\n\nFile v1.3.1:README.en.md\n\n# hekouwang-yandu-deck-skill · YanDu DECK\n\n**English** · [中文](README.md)\n\nA [Claude Code](https://claude.com/claude-code) **Skill** by *会勇禾口王的AI笔记* — the production + publishing pipeline for **YanDu DECK** (演读 DECK), an immersive presentation format.\n\nIt turns an article into a **one-screen-per-idea, swipeable, auto-playing** keynote web deck (in **dark** or **light** theme), self-hosts its fonts (Noto Sans/Serif SC subsetted + Anthropic bundled, zero CDN, `preload` to kill FOUT), and deploys to Cloudflare Pages with one command.\n\nLive example: **https://hekouwang.pages.dev**\n\n## Demo\n\nFastest way to feel it — double-click **[`examples/demo.html`](examples/demo.html)**: a **self-contained, zero-dependency, system-font** minimal example. Just open it via `file://` to see the engine animate (paging / auto-play / bars growing / numbers counting up / lines drawing / staggered cards).\n\n| Cover (count-up + gradient title) | Flow slide (nodes fade in + arrows draw + stat pop) |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **Full live decks (swipeable / auto-play):**\n  - Home: <https://hekouwang.pages.dev>\n  - Dark series: <https://hekouwang.pages.dev/suanli/ep01> (`#3` jumps to slide 3)\n  - Light series: <https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` are the two **full engine templates** (serve locally to load fonts: `python3 -m http.server`).\n\n## Dependencies\n\n| Dependency | Relationship | Notes |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **Content source (hard dependency)** | This Skill is the *\"turn content into a swipeable deck + publish\"* half. The other half — generating the article HTML, the visual systems (V1/V2/V3), de-AI-ifying copy, compliance — lives in `hekouwang-content-factory`. Source HTML, color tokens and the font scheme all come from it. **⚠️ `hekouwang-content-factory` is a paid Skill** (contact the author @huiyonghkw for a license); its content is **not** included in this repo. |\n| Python 3 + `fonttools` + `brotli` | Font subsetting | Only needed at publish time (the `tools/fenv` venv, see `SKILL.md`). Without it, it falls back to the pre-subsetted fonts in `fonts/cache/`. |\n| `wrangler` (Cloudflare) | Deploy | `publish.py` calls it to deploy to CF Pages; first run needs `wrangler login`. |\n| Anthropic Sans/Mono woff2 | Latin / mono fonts | From `hekouwang-content-factory` (self-use / demo license). If absent, Latin text falls back to system fonts. |\n\n> Want just the **engine** (not the content pipeline)? Copy `assets/templates/deck-engine-*.html` as a template and fill in your content — that part is zero-dependency and stands alone.\n\n## What is this\n\nA Claude Code **Skill**, organized per the official `anthropics/skills` convention. `SKILL.md` is the method doc the agent reads; `scripts/` `assets/` `references/` `examples/` hold ready-to-copy scripts, templates, docs and samples.\n\n```\nSKILL.md                              # method + triggers + gotchas (agent entry point)\nscripts/\n└── publish.py                       # build dist/ → deploy to CF Pages (no 3rd-party deps)\nassets/templates/\n├── deck-engine-暖黑.html             # deck engine template (dark — data / finance / explainer)\n├── deck-engine-米白.html             # deck engine template (light — editorial / methodology)\n└── home.html                        # homepage template\nreferences/\n└── 系统说明.md                       # system notes (zh)\nexamples/\n└── demo.html                        # self-contained zero-dep animated example\n```\n\n> Placement rule: copy `scripts/publish.py` and `assets/templates/home.html` into the **same** `演读DECK/` dir in your project (publish.py resolves the homepage via `SELF/home.html`).\n\n## Install\n\nClone into `~/.claude/skills/hekouwang-yandu-deck-skill/`:\n\n```bash\ngit clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill\n```\n\nThen in Claude Code, say things like *\"turn this into a deck / add a YanDu episode / publish to hekouwang\"* and it auto-loads.\n\n## Core features\n\n- **Deck engine** (zero-dependency CSS+JS): full-screen one-idea-per-slide; arrow keys / space / click / touch paging; auto-play; entrance animations (staggered cards / growing bars / SVG line-draw / number count-up / ghost section numbers); `fit()` auto-scaling; `#N` deep links; `prefers-reduced-motion` friendly.\n- **Two themes**: dark (data-console) / light (editorial) — the engine JS is theme-agnostic.\n- **Self-hosted fonts**: Noto Sans SC (4 weights) + Serif subsetted to the glyphs actually used (~180KB each), Anthropic Sans/Mono bundled, zero external requests; `preload` + long cache to remove the first-paint weight flash.\n- **One-command publish**: `python3 publish.py`; add one MANIFEST line per episode; clean URLs on CF Pages.\n\n> For the companion article/graphics/video pipeline, see `hekouwang-content-factory`.\n\n## License\n\nThe code in this repo (deck engine templates, `publish.py`, `demo.html`, `home.html`, `SKILL.md`, etc.) is **MIT** licensed — see [LICENSE](LICENSE). Note:\n\n- **`hekouwang-content-factory` is a separate, paid Skill; its content is not in this repo** and is not covered by this license.\n- Noto Sans SC / Noto Serif SC are SIL OFL fonts — **no font files are bundled here**; their OFL applies when you fetch them.\n- Anthropic Sans/Mono are proprietary fonts, not bundled here; confirm your own licensing before use.\n\nFile v1.3.1:skill-card.md\n\n## Description:\n\nCreates immersive, swipeable, auto-playing HTML keynote-style decks from article content and supports publishing them to Cloudflare Pages.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[huiyonghkw](https://clawhub.ai/user/huiyonghkw)\n\n### License/Terms of Use:\n\nMIT\n\n## Use Case:\n\nDevelopers and content creators use this skill to convert article content into one-screen-per-idea HTML deck pages, manage deck themes and site assets, add homepage or comment-board pieces, and build or deploy the result to Cloudflare Pages.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The publishing workflow can deploy live Cloudflare Pages sites.\n\nMitigation: Run the build-only path first and verify the target Cloudflare project before any deployment.\n\nRisk: The included publishing script may install global tooling.\n\nMitigation: Review scripts/publish.py before execution and install Wrangler through an approved local process.\n\nRisk: A hard-coded Cloudflare analytics token may route analytics to the wrong account.\n\nMitigation: Replace or remove the Cloudflare Web Analytics beacon token before publishing.\n\nRisk: Cloudflare D1 settings can point to another database if placeholders are not replaced.\n\nMitigation: Confirm wrangler.toml and D1 database bindings are set to the user's own Cloudflare account.\n\n## Reference(s):\n\n- [ClawHub Skill Page](https://clawhub.ai/huiyonghkw/skills/hekouwang-yandu-deck-skill)\n- [Project Homepage](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n- [Live YanDu DECK Site](https://hekouwang.pages.dev)\n- [README.en.md](README.en.md)\n- [Mobile and Comments Notes](references/mobile-and-comments.md)\n- [Token Flip Theme Guide](references/换肤-token-flip.md)\n- [Cloudflare D1 Comment Board Guide](references/留言板-D1.md)\n- [System Notes](references/系统说明.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with HTML, JavaScript, Python, shell commands, and configuration file edits]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May generate or modify HTML deck pages, templates, Cloudflare Pages configuration, D1 schema, and publishing scripts.]\n\n## Skill Version(s):\n\n1.3.1 (source: frontmatter, CHANGELOG, release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.3.1:assets/templates/wrangler.toml\n\n# 演读 DECK · Cloudflare Pages 配置（落地新项目时拷进 <项目根>/演读DECK/）\n# 首页/每期留言板用到 Pages Functions（functions/）+ D1 数据库（binding=DB）。\n#\n# 落地三步（照做即可，不做留言板可整份删掉本文件）：\n#   1. wrangler d1 create <你的库名>                     → 输出里拿 database_id\n#   2. 把 database_id 填回下面（name/database_name 也换成你自己的）\n#   3. wrangler d1 execute <你的库名> --remote --file=schema.sql   → 建表\n#\n# ⚠️ database_id 不是密钥，但它绑定的是「某个具体 CF 账号下的库」——\n#    别直接用别人的，否则你的站会往别人的库里写留言。\nname = \"<your-pages-project>\"          # CF Pages 项目名，也决定 <name>.pages.dev 子域\npages_build_output_dir = \"dist\"\ncompatibility_date = \"2024-11-01\"\n\n[[d1_databases]]\nbinding = \"DB\"                         # 代码里按这个名字取（functions/api/comments.js 用 env.DB），别改\ndatabase_name = \"<your-d1-name>\"\ndatabase_id = \"<your-d1-database-id>\"  # ← wrangler d1 create 后填回\n\nFile v1.3.1:LICENSE\n\nMIT License\n\nCopyright (c) 2026 huiyonghkw (会勇禾口王的AI笔记)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n---\n\nScope / third-party notice\n\nThe MIT license above covers the code in THIS repository: the deck engine\ntemplates (reference/deck-engine-*.html), demo.html, publish.py, home.html,\nSKILL.md and docs.\n\nIt does NOT cover, and this repository does NOT include:\n\n- `hekouwang-content-factory` — a separate, PAID Claude Code Skill (the content/\n  visual-system half). Its content has its own terms; contact the author.\n- Noto Sans SC / Noto Serif SC (思源黑体/思源宋体) — SIL Open Font License (OFL).\n  No font files are bundled here; when you fetch them, their OFL applies.\n- Anthropic Sans / Anthropic Mono — proprietary fonts, not bundled here; confirm\n  your own licensing for any use.\n\nArchive v1.3.0: 23 files, 139862 bytes\n\nFiles: assets/functions/api/comments.js (4492b), assets/presenter/presenter-module.html (9173b), assets/templates/deck-engine-V6焰彩白.html (47106b), assets/templates/deck-engine-暖黑.html (68653b), assets/templates/deck-engine-米白.html (46608b), assets/templates/home.html (47618b), assets/templates/schema.sql (906b), assets/templates/wrangler.toml (1110b), CHANGELOG.md (7982b), examples/demo.html (29366b), LICENSE (1798b), README.en.md (5567b), README.md (5453b), references/mobile-and-comments.md (1538b), references/换肤-token-flip.md (8887b), references/留言板-D1.md (3428b), references/系统说明.md (4632b), scripts/flip-暖黑到米白.py (4047b), scripts/publish.py (47935b), scripts/sync-from-harness.sh (1248b), skill-card.md (2781b), SKILL.md (17028b), _meta.json (145b)\n\nFile v1.3.0:SKILL.md\n\n---\nname: hekouwang-yandu-deck-skill\nslug: hekouwang-yandu-deck-skill\ndisplayName: 演读 DECK 产线与发布\nsummary: 把文章做成一屏一镜、可翻页、可自动播放的 keynote 演示网页，并发布到 Cloudflare Pages（hekouwang.pages.dev）。含米白/V6焰彩引擎、提词器、留言板与换肤 token-flip。\nlicense: MIT\nhomepage: https://github.com/huiyonghkw/hekouwang-yandu-deck-skill\nversion: 1.3.0\ndescription: >\n  会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。\n  当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。\n  触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n---\n\n# 演读 DECK · 沉浸式演示产线与发布\n\n> 「演读 DECK」= 会勇禾口王的AI笔记出品的一款**沉浸式阅读产品**：介于长文和视频之间的第三种读法——一屏一镜、方向键/空格/点击翻页、能自动播放，把一个复杂主题安静完整地讲给你看。\n> 线上：**https://hekouwang.pages.dev** ｜ 与图文产线 `hekouwang-content-factory-skill` 配套（那是出文章/贴图/视频，这是把内容做成翻页演示 + 发布）。\n\n## 0. 系统在哪（先认这个）\n\n发布系统是项目里一个**自包含目录** `<项目根>/演读DECK/`：\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库 + 一个子集化 venv）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用；不做留言板可删）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/api/comments.js   # 留言板后端（Pages Functions，按目录约定生效）\n├── fonts/src/       # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700 + Anthropic Sans/Mono + Mozilla VF\n├── fonts/cache/     # 子集化产物缓存（无字体源/无 venv 时回退）\n├── tools/fenv/      # 子集化 venv(fonttools+brotli)；移动会失效，丢了重建\n├── dist/            # 构建产物 = 部署目录（可整删重生）\n└── README.md\n```\n\n> ⚠️ **上面这套是「真身」，本 skill 里的是可移植副本**。日常在项目里改的是真身；**改完跑 `bash scripts/sync-from-harness.sh <演读DECK路径>` 同步回 skill**，否则副本很快过时。\n\n本 Skill 按官方约定分目录带了**可移植副本**（新项目落地时拷过去）：\n- `assets/templates/` — `deck-engine-米白.html`（⭐默认）/ `deck-engine-V6焰彩白.html`（国标）/ `deck-engine-暖黑.html`（仅维护存量）、`home.html`（首页源）、`wrangler.toml` + `schema.sql`（留言板，**database_id 是占位符，落地填自己的**）\n- `scripts/publish.py`（发布脚本）、`scripts/sync-from-harness.sh`（真身→副本单向同步）、`assets/functions/api/comments.js`（留言板后端）\n- `references/换肤-token-flip.md`（换肤）、`references/留言板-D1.md`（留言板）、`references/mobile-and-comments.md`（移动端 safe-area / 留言板开关 / 视频交叉引用）、`references/系统说明.md`（**落地 README 模板**，拷进 `演读DECK/README.md` 给人看）、`examples/demo.html`（零依赖最小示例）\n\n> ⚠️ **落地时 `publish.py` 与 `home.html` 必须同目录**（`publish.py` 用 `SELF/home.html` 找首页源）；`functions/` 要放成 `演读DECK/functions/api/comments.js`。\n> ⚠️ 副本里 **`CF_BEACON_TOKEN` 与 `wrangler.toml` 的 database_id 都留空/占位**——落地新站时填自己的，别沿用他人的（否则流量统计报到别人面板、留言写进别人的库）。\n\n## 1. 把文章做成「演示版 deck」⭐ 核心\n\n一篇 V2 文章 → 一屏一镜的 keynote。**零依赖（纯 CSS + 原生 JS，不引 GSAP/外链，国内/CF 都快）。** 沿用源文章的视觉（默认米白，国标走 V6 焰彩白，见 第1.4节）、字体、grain/mesh/frame/幽灵章节号。\n\n### 1.1 引擎（照抄模板，别重写）\n\n样板（**默认拷米白**，选哪套见 第1.4节）：\n- `assets/templates/deck-engine-米白.html` — ⭐ **默认**，人文/方法论亮调。\n- `assets/templates/deck-engine-V6焰彩白.html` — 国标系列专属：紫主色+焰橙/粉，Mozilla 可变字体（`publish.py` 的 `MOZILLA_FILES` 已打包 Mozilla 字体、按页面含 \"Mozilla\" 注入 `PRELOAD_LINKS_V6`）。\n- `assets/templates/deck-engine-暖黑.html` — 🕰️ 仅维护存量（Harness），**新 EP 别拷**。\n**做新 EP = 拷一份对应主色的模板，`<head>` 的全部 CSS 和 `</main>` 之后的全部 `<script>` 逐字保留，只换内容 slide / 顶栏标签 / title / 片尾。** 引擎已实现：\n\n> ⚠️ 模板 `@font-face` 里的字体路径是占位符 `{{SKILL_DIR}}/assets/fonts/...`——指向兄弟 skill `hekouwang-content-factory-skill` 的字体。拷模板做 EP 时**把 `{{SKILL_DIR}}` 替换成 hekouwang-content-factory-skill 的绝对 Base directory**（本地预览/截图才有字体）。发布时 `publish.py` 会把它统一收成站内 `/fonts/`，万一漏替换也能兜底。\n\n- 全屏 `.slide`（一屏一镜），`.stage` 居中 + JS `fit()` 等比缩放防裁切；\n- 导航：←/→/空格/点击/触屏滑动/底部圆点/Home/End/F 全屏；右下「▶ 自动播放」(7s/屏，像放视频)；顶部进度条 + `NN/总数`；`#N` 深链（可分享到某屏）；`prefers-reduced-motion` 自动关动画。\n- **S 放映 / 提词器**（讲者视图：计时器 + 当前镜逐字稿 + 下一镜预览，详见 第1.6节）。模板已内置该模块，拷模板即带。\n\n### 1.2 进场动画钩子（只加 class + `--i` 递增控错峰，CSS 已定义）\n\n| 钩子 | 效果 | 用在 |\n|---|---|---|\n| `.an` / `.an.scale` | 淡入上浮 / 带放大 | 任何要进场的块；按出现顺序 `style=\"--i:0\"`、`--i:1`… |\n| `.bar` | 横向条 scaleX 从左生长 | 柱状/条形数据条（只给数据条，不给坐标轴） |\n| `.tok` | SVG 节点组逐个淡入 | 流程/关系/漏斗/桥的节点 `<g>` |\n| `.draw` | 折线/箭头描线(JS getTotalLength) | 连接线 `<line>`/`<path>` |\n| `.grow` | 弹性放大 | stat 数据卡 |\n| `[data-count]`+`data-suffix` | 纯数字 0→N 滚动 | 纯数字读数（初始文本写 `0`；**含箭头/汉字/百分号的别用**） |\n\n每个 slide `data-g=\"章节号\"` → 背景自动生成巨幅幽灵数字（封面/速览/片尾用 `data-g=\"·\"`）。\n\n### 1.3 内容映射铁律（一图一镜）\n\n源文每个 section + 每张图表都要有对应镜头。**封面屏 + 速览屏（用源文 hero 的关键数据做 readout 仪表条）打头，片尾签收卡收尾**（含私域 CTA），一篇 9 节 → 约 12–24 屏。\n**SVG 图表逐字搬运**（viewBox/坐标/配色/字体不改），只在外层 `.fig` 加 `an`、给数据条/节点/折线加动画钩子。源文的 `.fig.breakout` 破格在演示版里**去掉**（每屏已全宽居中，负 margin 会出问题）。文案可适度精简适配一屏，保意保语气、过 `hekouwang-content-factory-skill` #6.6 去 AI 味。\n\n### 1.4 主色：**米白是全站默认**，焰彩白是国标专属例外\n\n新做任何一期，**默认拷米白引擎**。只有两种情况例外，别自作主张换调：\n\n| 系列 | 主色 | 拷哪个模板 |\n|---|---|---|\n| **默认 / 首页 / 出行SaaS** | **米白** `#faf9f5` + 黏土 `#c15f3c`（编辑/人文感） | `deck-engine-米白.html` |\n| **智能体互联国标** | **V6 焰彩白** `#fbfaff` + 紫 `#7c3aed` + 焰橙/粉，Mozilla 可变字体（大厂发布感） | `deck-engine-V6焰彩白.html` |\n\n- ⚠️ **暖黑 `#161514` / V6焰彩黑 `#170a30` = 历史过渡态，不再新做**。线上尚有存量（算力账本·偷师=焰彩黑，Harness=暖黑），按计划逐步 flip 回米白；`deck-engine-暖黑.html` 仅为维护存量保留，**新 EP 不要拷它**。\n- 亮底适配铁律（米白/焰彩白）：网格线改极淡深色、卡片靠 `--shadow` 投影不靠辉光、标题黏土渐变(深→浅)、幽灵号深色 `opacity:.05`、`.grain` 用 `mix-blend-mode:multiply`。引擎 JS 主题无关、逐字一致。\n- **给存量 deck 换肤（黑→米白）→ 读 [`references/换肤-token-flip.md`](references/换肤-token-flip.md)**：脚本会截空文件、半成品会留残色，踩过的坑都在里面，别凭感觉改。\n\n### 1.5 批量做（多 EP）\n\n引擎相同、只内容不同 → 并行开多个 subagent，每个给「对应主色模板路径 + 源文章路径 + 本节规则」，要求 `<head>`CSS 与 `<script>`JS 与模板**逐字一致**，只换内容、按源文追加专属组件 CSS（滑块/时间线/对比/桥…，改用模板的 token）。产出后主控用 headless Chrome 截图核验各图表屏（`--virtual-time-budget=5000` 让动画跑完）。\n\n## 1.6 放映 / 提词器（讲 + 录 双用）⭐\n\n模块：`assets/presenter/presenter-module.html`（自包含 `<style>+<div>+<script>`，已注入三套引擎模板与 `examples/demo.html`，**拷模板即带，无需改引擎**）。\n\n- **按 `S`** 开「讲者视图」：**独立窗口**（计时器 + 当前镜逐字稿 + 下一镜预览），主屏与讲者窗靠 **BroadcastChannel 双向同步**——**主屏保持干净，可投影 / 录屏**。弹窗被拦（或无 BroadcastChannel）时自动回退为页内全屏浮层（单屏排练也能用）。\n- **真·双屏**：把 deck 在第二显示器再开一个窗口、地址后加 `?speaker=1` 即变讲者窗，免弹窗。讲者窗可**反向遥控主屏**：在讲者窗按 `←/→` 翻镜、`P` 计时、`R` 归零、`Esc/S` 关（靠向主屏引擎派发方向键事件，不改引擎）。\n- **键位**：`S` 开/关 · `P` 计时启停 · `R` 归零 · `Esc` 关 · `←/→` 翻镜（主屏与讲者窗都认）。\n- **逐字稿 = 配音 / 口播脚本**：在每张 `.slide` 里加 `<div class=\"notes\">这一镜要讲的话…</div>`（观众/录屏**永不可见**，模块强制 `display:none`）。这份 notes 同时就是该镜的口播稿——录屏时主屏放干净 deck、讲者窗当提词器照念；也可直接喂 TTS（云扬）。\n- 取数靠 `#deck .slide` 的 `.active` class（`MutationObserver` 监听），与引擎解耦；无 `.notes` 的镜回退显示标题。讲者信号用 `window.name`/`?speaker`（**不用 `#speaker`**——引擎深链 `replaceState('#N')` 会把 hash 冲掉）。\n- ⚠️ 本地 `file://` 双击时 `window.open` 可能被拦、且 BroadcastChannel 跨窗不通（opaque origin）——**用 `python3 -m http.server` 起本地服务**预览（与字体本地化要求一致）；发布到 CF Pages(https) 后正常。\n\n> 一图一镜 + 每镜一段 notes ⇒ 写完 deck 就同时有了「演示稿 + 提词器 + 口播稿」三合一。\n\n## 2. 首页 `home.html`\n\n演读 DECK 品牌落地页（**米白 `#faf9f5`**，2026-07-14 起；此前为暖黑）：masthead 品牌 + 「演读 ⟨DECK⟩」产品名、hero「把复杂的 AI，读成一场演示」、proof 三栏（第三种读法/翻页·自动播放/读完就懂）、系列卡片区（现 5 个：国标 / 算力账本 / 偷师AI大佬 / Harness工程 / 出行SaaS工程手记）、出品方 about（人设 + 禾口王=程）、订阅区（领《AI 内容流水线手册》三步）、底部内联留言板（`.talk-*`，`page='home'`）。**响应式**断点齐全（600/680/760/520）。\n- ⚠️ **系列卡是静态手写的**，不由 `MANIFEST` 生成（`write_index()` 是遗留死函数）——加系列要**手改 `home.html`** + 补 `MANIFEST`/`SERIES_META` 三处一起动。\n- 人设口径以记忆 `brand-persona-tagline` 三句为准（别自由改措辞）。**改首页改 `演读DECK/home.html`，不在 `dist/` 里改。**\n\n## 3. 字体自托管（零 CDN）⭐ 关键\n\n发布时 `publish.py` 的 `localize()` 把源 HTML 里所有 Google/loli 外链删掉、注入指向 `/fonts/` 的本地 `@font-face`；Anthropic 绝对路径也改写成 `/fonts/`。`subset_cjk()` 用 `tools/fenv` 的 `pyftsubset` 按**全站实际用字**把思源黑 4 字重（400/500/700/900，800 映射 900）+ 宋（金句衬线）子集化成小 woff2（各 ~180KB），连 Anthropic 一起打包进 `dist/fonts/`。\n\n- **首屏字重跳变(FOUT)**：每页 `<head>` 注入 4 条 `<link rel=preload>`（900/400/Anthropic Sans/Mono）让关键字体高优先级先下；`dist/_headers` 给 `/fonts/*` 设一周强缓存。这两条**必须保留**，否则首屏会「先系统字、再换思源」肉眼可见跳一下。\n- 字体源出处：思源来自 `@fontsource@5.0.0`（jsdelivr）逐字重静态 woff2；Anthropic 来自 `hekouwang-content-factory-skill/assets/fonts/`（自用/演示授权）；Mozilla Headline/Text VF 为 Mozilla 官方开源（OFL），可自由使用。\n- venv 丢了重建：`cd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli`。无 venv/字体源时 publish 回退用 `fonts/cache/`。\n\n## 4. 发布\n\n```bash\n# 从项目根运行\npython3 演读DECK/publish.py              # 构建 dist/ + 部署到 CF Pages（hekouwang）\npython3 演读DECK/publish.py --build-only # 只构建 dist/，不部署\n```\n\n- **加一期**：在 `publish.py` 的 `MANIFEST` 加一行（源 HTML 相对项目根的路径 + slug 如 `suanli/ep04` + 系列 + EP + 分类 + 标题 + 简介 + 屏数）。**加一个系列**：再补 `SERIES_META` 一条，**并手改 `home.html` 的系列卡**——首页系列卡是**静态手写**的，不由 MANIFEST 生成（`write_index()` 是遗留死函数，别指望它）。\n- **留言板**（Pages Functions + D1）随部署一起生效，**加装/排错 → 读 [`references/留言板-D1.md`](references/留言板-D1.md)**：部署得用配置式（不带 `dist` 参数）+ `cwd=SELF`，日志出现 `Uploading Functions bundle` 才算带上后端。\n- 干净 URL：演示版拷进 `dist/<slug>.html`，CF Pages 自动去 `.html`（`/suanli/ep01`）。\n- 部署用 `wrangler pages deploy dist --project-name hekouwang`；首次需 `wrangler login`（用户自己 `! wrangler login`）。\n\n## 5. 防踩坑（实测血泪）\n\n1. **`dist/` 每次构建被清空**——别在里面改任何东西；首页改 `home.html`，演示版改各 EP 源。\n2. **本地预览必须起 http 服务器**：`dist` 用站内 `/fonts/` 绝对路径，`file://` 双击打不出字体。`cd dist && python3 -m http.server 8000`。\n3. **`keynote.pages.dev` / `keynotes` 等常用名全球已被占**——CF 会自动加随机后缀(`keynote-9z0`)。本机网络有透明代理劫持 DNS、返回 198.18.0.x 假 IP，**本地 nslookup 测不出子域可用性**；唯一可靠 = `wrangler pages project create <名>` 后看 `project list` 分配的子域有没有后缀。最终用 `hekouwang`。\n4. **国内 EdgeOne 是死路**：免费自动域名一律带 token 鉴权、公网 401（ICP 备案要求），别再碰；直接 Cloudflare Pages。\n5. **移动 venv 会失效**（shebang/pyvenv.cfg 写死原路径）——换位置就重建。\n6. **本机代理会截断大文件下载(>~4MB)**：思源变量字体下不全 → 改用 @fontsource 逐字重静态 woff2(各 ~1.6MB)再子集化。\n7. 截图核验演示版给足时间（`--virtual-time-budget=5000`），让 fit/动画跑完再截。\n\n## 配套与依赖\n- **内容产线（强依赖）：`hekouwang-content-factory-skill`**——演示版的源文章 HTML、视觉规范(V1/V2/V3)、配色 token、字体方案都来自它；本 Skill 只做「内容→翻页演示+发布」这一半。**⚠️ 它是付费 Skill**（需作者授权），仓库不含其内容。只用引擎可直接拷 `assets/templates/deck-engine-*.html`（零依赖独立可用）。\n- 示例：`examples/demo.html`（自包含、零依赖、双击即看的最小动画示例）。\n- 记忆：`keynote-yanshi-site`（站点现状 + 发布链路）、`keynote-deck-engine`（引擎做法）、`brand-persona-tagline`（人设三句）。\n\nFile v1.3.0:README.md\n\n# hekouwang-yandu-deck-skill · 演读 DECK\n\n**中文** · [English](README.en.md)\n\n> GitHub: [https://github.com/huiyonghkw/hekouwang-yandu-deck-skill](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n\n会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。\n\n把一篇文章/选题做成**一屏一镜、可翻页、能自动播放**的 keynote 演示版网页（**暖黑** / **米白** 两套主色），自托管字体（思源黑/宋子集化 + Anthropic 打包、零 CDN、preload 治 FOUT），并一键发布到 Cloudflare Pages。\n\n线上样例：**https://hekouwang.pages.dev**\n\n## 示例动画版本 / Demo\n\n最快的体验方式 —— 双击打开 **[`examples/demo.html`](examples/demo.html)**：一个**自包含、零依赖、系统字体**的最小示例，直接 `file://` 打开就能看引擎怎么动（翻页 / 自动播放 / 柱子生长 / 数字滚动 / 折线描线 / 卡片错峰）。\n\n| 封面（数字滚动 + 标题渐变） | 流程屏（节点淡入 + 箭头描线 + stat 弹入） |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **在线完整版（可翻页/自动播放）**：\n  - 首页：<https://hekouwang.pages.dev>\n  - 暖黑系列：<https://hekouwang.pages.dev/suanli/ep01>（`#3` 直达第 3 屏）\n  - 米白系列：<https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` 是两套**完整引擎模板**（需起本地服务器看字体：`python3 -m http.server`）。\n\n## 依赖\n\n| 依赖 | 关系 | 说明 |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **内容来源（强依赖）** | 本 Skill 是「**把内容做成翻页演示 + 发布**」的一半；**另一半（生成文章 HTML、视觉规范 V1/V2/V3、去 AI 味、合规红线）在 `hekouwang-content-factory`**。演示版的源 HTML、配色 token、字体方案都源自它。**⚠️ `hekouwang-content-factory` 是付费 Skill**（GitHub 上为 **PRIVATE 私有仓库，非授权无法 clone / 获取**；需向作者 @huiyonghkw 获取授权），本仓库不含其内容。 |\n| Python 3 + `fonttools`+`brotli` | 字体子集化 | 仅发布时需要（`tools/fenv` venv，见 `SKILL.md`）。没有则回退用 `fonts/cache/` 已切好的子集。 |\n| `wrangler`（Cloudflare） | 部署 | `publish.py` 调它发到 CF Pages；首次需 `wrangler login`。 |\n| Anthropic Sans/Mono woff2 | 拉丁/代码字体 | 来自 `hekouwang-content-factory`（自用/演示授权）。缺失则拉丁字自动回退系统字。 |\n\n> 只想用**引擎**（不要内容产线）：直接拷 `assets/templates/deck-engine-*.html` 当模板填内容即可，那部分零依赖、可独立使用。\n\n## 这是什么\n\n这是一个 [Claude Code](https://claude.com/claude-code) **Skill**，按官方 `anthropics/skills` 约定分目录组织。`SKILL.md` 是给 Agent 读的方法说明；`scripts/` `assets/` `references/` `examples/` 是可直接拷用的脚本、模板、文档与示例。\n\n```\nSKILL.md                              # 方法 + 触发词 + 防踩坑（Agent 入口）\nscripts/\n└── publish.py                       # 构建 dist/ → 部署 CF Pages（零三方依赖）\nassets/templates/\n├── deck-engine-暖黑.html             # 演示版引擎模板（数据/财经/科普暗调）\n├── deck-engine-米白.html             # 演示版引擎模板（人文/方法论亮调）\n└── home.html                        # 首页模板\nreferences/\n└── 系统说明.md                       # 系统说明文档\nexamples/\n└── demo.html                        # 零依赖最小示例（双击即看）\n```\n\n> 落地铁律：`scripts/publish.py` 与 `assets/templates/home.html` 拷进项目时必须放进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源）。\n\n## 安装\n\n把本仓库放进 `~/.claude/skills/hekouwang-yandu-deck-skill/`：\n\n```bash\ngit clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill\n```\n\n之后在 Claude Code 里说「把这篇做成演示版 / 加一期演读 / 发 hekouwang」等即会自动加载。\n\n## 核心能力\n\n- **演示版引擎**（零依赖 CSS+JS）：全屏一屏一镜、←/→/空格/点击/触屏翻页、自动播放、进场动画（卡片错峰 / 柱子生长 / SVG 描线 / 数字滚动 / 幽灵章节号）、`fit()` 自适应、`#N` 深链、`prefers-reduced-motion` 友好。\n- **两套主色**：暖黑（数据控制台）/ 米白（编辑人文），引擎 JS 主题无关。\n- **字体自托管**：思源黑 4 字重 + 宋按用字子集化（各 ~180KB），Anthropic Sans/Mono 打包，全站零外链；preload + 强缓存消除首屏字重跳变。\n- **一键发布**：`python3 publish.py`，MANIFEST 加一行即加一期，CF Pages 干净 URL。\n\n> 配套图文/视频产线见 `hekouwang-content-factory`。\n\n## License\n\n本仓库代码（演示版引擎模板、`publish.py`、`demo.html`、`home.html`、`SKILL.md` 等）以 **MIT** 开源，见 [LICENSE](LICENSE)。注意：\n\n- **`hekouwang-content-factory` 是独立的付费 Skill，其内容不在本仓库**，不受本许可覆盖。\n- 思源黑体/思源宋体（Noto Sans/Serif SC）为 SIL OFL 开源字体，本仓库**不含字体文件**，自行获取时遵循其 OFL。\n- Anthropic Sans/Mono 为专有字体，本仓库不含，使用前自行确认授权。\n\nFile v1.3.0:_meta.json\n\n{\n  \"ownerId\": \"kn73qd1gcmjr446mwcbdxef70x82vxcw\",\n  \"slug\": \"hekouwang-yandu-deck-skill\",\n  \"version\": \"1.3.0\",\n  \"publishedAt\": 1786520972852\n}\n\nFile v1.3.0:references/mobile-and-comments.md\n\n# 移动端 safe-area · 留言板开关 · 视频交叉引用\n\n## 移动端 safe-area\n\n演示引擎默认 `viewport-fit=cover`，全屏翻页时顶底栏要留 **safe-area**：\n\n```css\n.deck-toolbar {\n  padding-bottom: max(12px, env(safe-area-inset-bottom));\n  padding-left: max(16px, env(safe-area-inset-left));\n  padding-right: max(16px, env(safe-area-inset-right));\n}\n```\n\n- iOS 刘海/底条：没写 `env(safe-area-inset-*)` 时，翻页按钮和进度条会被挡。\n- 横屏演示：左右 inset 同样要留，别只照顾 bottom。\n- 验收：真机 Safari「添加到主屏幕」全屏翻 3 页，拇指区按钮必须可点。\n\n## 留言板（可选子系统）\n\n默认 **hekouwang.pages.dev 线上开着**；新站或纯静态演示可关：\n\n1. 删或移走 `演读DECK/functions/`（Pages Functions 不再挂载）\n2. `wrangler.toml` 里去掉 `[[d1_databases]]` 绑定\n3. `home.html` / 引擎模板里去掉留言入口 DOM 与 fetch 调用\n\n排错见 `references/留言板-D1.md`；**database_id 必须是自己的**，副本里是占位符。\n\n## 与 HyperFrames 视频产线\n\n- **演读 DECK** = 一屏一镜 **可翻页 HTML**，适合长文拆解、国标系列、教程跟读。\n- **HyperFrames 视频** = 同选题的 **ffmpeg 成片**（harness 内 `EP-*/video/` 或动画 Skill）。\n- 同一 EP 可两条线并存：文章母本 → 演示版 HTML（本 skill）+ 可选视频目录；**不要**在 deck 引擎里引外链视频或 `Date.now()`/`Math.random()`（与 harness `AGENTS.md` 视频红线一致）。\n\nFile v1.3.0:references/换肤-token-flip.md\n\n# 演读 DECK · 换肤 = token-flip（不是重做）\n\n给**已有 deck** 换主色时用这套。核心认知：两套主色的 `:root` **逐行结构完全一致、只有值不同**——所以换肤是一次**机械的 token 值映射**，引擎 CSS/JS 一字不动，内容一字不动。别重写、别让 subagent \"参照着做一版\"。\n\n> 当前口径见 SKILL.md 第1.4节：**米白 = 全站默认**，国标走 V6 焰彩白，**暖黑/焰彩黑是存量历史态**——本文档现在主要服务于「存量黑版 → 米白」的收敛。\n>\n> 现成脚本：**`scripts/flip-暖黑到米白.py`**（映射抽自引擎模板 · 单遍替换 · 内建未覆盖色守卫 · 先读后写）。用法 `python3 scripts/flip-暖黑到米白.py <deck.html>...`；退出码 2 = 有未覆盖色，按 第2.6节 人工判断后再跑。\n\n## 0. 动手前（这五步省过一次 9 期全毁）\n\n1. **先查 git 有没有现成的目标态**——见 第0.5节，能取回就别转换。\n2. **先 cp 备份**要改的文件。\n3. flip 脚本**必须先读后写**（见 第3节 第 1 条，这是最贵的坑）。\n4. flip 后 `stat -f%z` 查**每个文件大小非 0**。\n5. flip 后跑**全谱残留 grep**（第2节），**=0 才算过**。\n\n## 0.5 先问一句：git 里是不是躺着现成的？⭐ 省一整轮\n\n演读 DECK 的 deck HTML **都在 git 里**（只有 `演读DECK/publish.py` 被 `.gitignore` 的 `*.py` 排除）。整站换过肤，就意味着**换肤前的版本还在历史里**。要换回某个旧主色时，先查：\n\n```bash\ngit log --oneline --all -- <deck路径>                    # 哪次提交换的肤\ngit show <flip提交>^:<deck路径> | grep -oE -- '--bg:#[0-9a-f]*'   # 换肤前是什么色\ngit log --oneline <flip提交>..HEAD -- <deck路径>          # 换肤后还改过内容吗（0 = 可安全取回）\n```\n\n**换肤后 0 次提交 = 直接 `git show <flip提交>^:<路径>` 取回，精确、零转换风险**，比任何 flip 脚本都可靠。\n2026-07-15 实战：偷师 4 期换肤前本就是米白、之后 0 改动 → 直接取回，全谱残留 grep=0 一次过；而算力 5 期换肤前是**暖黑**（不是米白），取回只能拿到暖黑，仍需一轮真转换。**先查再动，别默认要写脚本。**\n\n## 0.6 ⚠️ 跨设计系统 ≠ 换肤，别硬套\n\n本文档的 flip 只适用于**同一套设计系统的明暗两极**（V6焰彩白↔V6焰彩黑、暖黑↔米白——后两者同为 V2 黏土系统）。\n\n**焰彩黑 → 米白 是跨系统**：主色紫 `#a855f7` vs 黏土 `#c15f3c`、字体 Mozilla VF vs Anthropic Sans，V6 的焰橙/焰粉在 V2 里根本没有对应色。硬套 token-flip 会出四不像。跨系统要走「先 git 取回同系统版本，再同系统 flip」，或老老实实重做。\n\n## 1. 已验证的映射\n\n### 1.1 V6 焰彩：白 ↔ 黑（两向互为精确逆运算）\n\n| 语义 | 焰彩白 | 焰彩黑 |\n|---|---|---|\n| 底 | `#fbfaff` | `#170a30` |\n| surface | `#ffffff` / `#f4eefc` / `#efe7fb` | `#241246` / `#231044` / `#2c1552` |\n| 正文字 | `#1c0b3e` | `#f3eefe` |\n| 主紫 | `#7c3aed` | `#a855f7` |\n| 次紫 | `#6d28d9` | `#c084fc` |\n| 蓝 | `#4f6ef0` | `#7c9bff` |\n| 金 | `#c8620a` / `#e07a1a` | `#ffb454` / `#f0a13a` |\n| warn | `#e0304f` | `#ff5c78` |\n| 线 | `rgba(28,11,62,…` | `rgba(255,255,255,…` |\n| 紫辉光 | `rgba(124,58,237,…` | `rgba(168,85,247,…` |\n| grain | `multiply` `.02` | `screen` `.05` |\n| body class | `class=\"light\"` | `class=\"dark\"` |\n\n**黑白通用、不翻**：焰橙 `#ff8a3d`、焰粉 `#ff4f8b`、`--ok`、`--teal`。\n**演示版与首页的 token 值不同，各写一份映射**，别共用一张表。\n\n### 1.2 暖黑 / 米白（旧两套）\n\n暖黑 `#161514` + 黏土 `#e08a5f` + 石板蓝 `#8fa6bd`；米白 `#faf9f5` + 黏土 `#c15f3c`。\n亮底适配：网格线→极淡深色、卡片靠 `--shadow` 不靠辉光、幽灵号深色 `opacity:.05`、`.grain`→`multiply`。\n\n## 2. 三条验收（缺一条都不算换完）\n\n1. **全谱残留 grep = 0**：拿**旧主色整套调色板**（不只是 `--bg`）去 grep，包括 SVG 内联色。半成品最爱漏的就是图表里的 `#e08a5f`（暖黑黏土）、`#8fa6bd`（石板蓝）。有残留 → 补一轮「旧色→新色」映射再跑。\n2. **封面截图**肉眼过一眼。\n3. **线上 curl 验 token**：跟随 308（`/suanli/ep04.html` → `/suanli/ep04`），确认 `--bg` 和 `class` 是新值。\n\n## 2.5 映射表从模板里抽，别手编；且必须**单遍同时替换** ⭐\n\n**映射的唯一真相源 = 两套引擎模板的 `:root` 逐 token 对照**（同一个引擎、两个主题，key 一一对应）。用脚本 diff 出来，别凭记忆写色号：\n\n```python\n# 剥掉 /* 注释 */ 再解析 :root，逐 key 比对 deck-engine-暖黑 vs deck-engine-米白\n```\n\n实测暖黑 33 token / 米白 26 token，其中 **20 个值不同**（`--bg/--surface*/--line*/--text*/--read/--hot*/--hl0/--cool*/--ochre*/--warn`），4 个通用不翻（`--font/--serif/--mono/--brand`）；另 `--m-*`（9 张插画）暖黑独有、**`stroke='%23000'` 单色遮罩、不含主题色**（靠 CSS 着色，不用管）；`--shadow/--shadow2` 米白独有（亮底要投影），flip 时**要补进去**。\n\n⚠️ **源集与目标集有交集 → 必须单遍替换**：`#f4f2eb` 既是源（暖黑 `--text` → `#1a1a18`）又是目标（暖黑 `--surface2` → `#f4f2eb`）。顺序 sed 会把前一条刚写出的颜色被后一条**再吃一次**，静默改错。正确做法是拼一个大 alternation 一次扫过：\n\n```python\npat = re.compile('|'.join(re.escape(k) for k in sorted(MAP, key=len, reverse=True)), re.I)\nout = pat.sub(lambda m: MAP[m.group(0).lower()], html)   # 单遍，绝不二次命中\n```\n\n## 2.6 图表内部色 ≠ 页面色：**脚本先扫「未覆盖色」并停下来** ⭐\n\ntoken 映射只管**相对页面底色**的颜色。deck 里还有大量**图表内部色**，它们的对比度是相对自己所在的色块，**翻了反而坏**：\n\n- `#19191a` 深字压在浅蓝柱 `#8fa6bd` 上 → 页面转亮底也得**留深**，翻了字就没了\n- `#e8eef3` 浅字压在深柱上 → **留浅**\n- 柱状填充（`#5e6b75`/`#a9714f`/`#8a7d70`）中间调 → 黑白底都成立，**别动**\n- 语义色（如 Harness 里 MCP 的绿 `#8fbf9f`）有含义 → **别当装饰色翻**\n- `#pmode` 讲者浮层（`#0c0d10`/`#ececf2`/`#9a9aac`…）、`.shell` 终端（`#1f1d1b`/`#0c0d10`）**刻意深底** → 不翻\n\n所以 flip 脚本**必须内建一道守卫**：转换前先扫全部目标文件，报出「映射表未覆盖、又不在保留名单」的裸色，**有就退出让人判断**，别闷头转（2026-07-15 实测：算力 EP01 干净，其余 5 期共 **15 种**各自的图表色需人工过——守卫挡住了一次静默改坏）。\n\n## 3. 血泪坑（都已解，别重踩）\n\n1. ⚠️ **原地覆盖脚本必须先读后写**——最贵的一个坑，曾把 9 期**全写空**：\n   ```python\n   # ✗ src==dst 时，open(dst,'w') 先把文件截断成空，再 read 就读到空字符串\n   open(dst,'w').write(flip(open(src).read()))\n   # ✓ 先读进内存，再开写\n   data = open(src).read()\n   open(dst,'w').write(flip(data))\n   ```\n2. **`.shell` 终端组件不翻**：`#1f1d1b` / `#0c0d10` / `rgba(0,0,0,.2)` 是**刻意的深底代码块**（米白/焰彩白母本自身就 `.shell{background:#1f1d1b}`），亮底下也该是深的。只在 `--shadow` 行里翻 `rgba(0,0,0,`，其余深底放行。\n3. **显式串先做**：`shadow` / `body 光晕` / `grain` 这类整串先替换，避免被后面的 bare-value 规则拆坏 alpha。\n4. **grep 单行 minified 会漏**：subagent 输出常是单行 HTML，`grep -c \"--bg:\"` 按行匹配会误判。用 `grep -o`，或先 `wc -c` 看是不是空文件。\n5. **半成品残留**：subagent 转版被中途停 → body SVG 内联色没转完。所以验收靠 第2节 第 1 条，不靠\"它说它做完了\"。\n6. **截图坑 → 用 `--headless=new` + `--timeout`**（2026-07-15 修正）：deck 的 `.draw` 动画让 `--virtual-time-budget` 不收敛。旧 `--headless` 会**挂死且不写盘**（`timeout` 杀进程后目录里什么都没有；\"杀了图其实已写盘\"的旧说法**实测不成立**，别信）。可靠配方——**1.5 秒出图**：\n\n   ```bash\n   \"$CHROME\" --headless=new --disable-gpu --incognito --user-data-dir=\"$TMP/prof\" \\\n     --window-size=1600,900 --hide-scrollbars \\\n     --virtual-time-budget=15000 --timeout=30000 \\\n     --screenshot=\"$TMP/cover.png\" \"file://$DECK\"\n   ```\n   `--timeout` 让 Chrome 自己到点截图退出（退出码 0），不必外部 `pkill`。字体走 content-factory 绝对路径，`file://` 即可加载。\n   ⚠️ 必带 `--incognito` + 独立 `--user-data-dir`，**别碰用户正在用的 Chrome**（见 memory `chrome-screenshot-isolated-incognito`）。\n\nFile v1.3.0:references/留言板-D1.md\n\n# 演读 DECK · 访客留言板（CF Pages Functions + D1）\n\n站点自带留言板：**Cloudflare Pages Functions + D1**，留言存在**自己的 CF 账号**里——无第三方、不用 giscus/GitHub 登录（国内读者友好）。**按页隔离**：首页 `home`，每期用 slug（`suanli/ep04`），各聊各的。\n\n## 1. 件在哪（本 skill 捆绑的落地副本）\n\n| 文件 | 作用 |\n|---|---|\n| `assets/functions/api/comments.js` | 后端：`onRequestGet`（读 `?page=` 列表）/ `onRequestPost`（校验+限频+写入） |\n| `assets/templates/wrangler.toml` | Pages 配置 + D1 绑定（`binding=DB`）。**database_id 是占位符，落地时填自己的** |\n| `assets/templates/schema.sql` | `comments` 表结构（含 `page` 列做隔离） |\n| `scripts/publish.py` → `inject_comments()` | 构建层把留言面板注入每篇 `</body>` 前 |\n\n**落地时全部拷进 `<项目根>/演读DECK/`**（`functions/` 保持 `functions/api/comments.js` 这个路径，Pages 按目录约定找）。\n\n## 2. 建库三步（新项目）\n\n```bash\ncd <项目根>/演读DECK\nwrangler d1 create <你的库名>                                  # ① 输出里拿 database_id\n#   ② 把 database_id / database_name / name 填进 wrangler.toml\nwrangler d1 execute <你的库名> --remote --file=schema.sql       # ③ 建表\n```\n\n> 改表结构：`CREATE IF NOT EXISTS` **不会 ALTER**，得先 DROP 再建。本地调试把 `--remote` 换 `--local`。\n\n## 3. 两种形态（为什么不一样）\n\n- **首页**：页面向下滚动 → 底部**内联**留言板（`.talk-*`），JS 里 `page='home'`。手写在 `home.html`。\n- **每期 deck**：全屏翻页、`body{overflow:hidden}` **不滚动** → 留言板做成**右侧把手 + 滑出面板 overlay**（`.hkwc-*`，暗色玻璃，对米白/焰彩白都压得住）。**不碰翻页引擎**（同讲者模式的思路），由 `publish.py` 的 `inject_comments()` 在构建层注入，**EP 源文件不动**。\n\n## 4. 已有防护（改的时候别拆掉）\n\n昵称 ≤24 / 正文 ≤500；`SHA256(salt|IP)` 前 32 位做限频（同 IP 20s 一条，**不存明文 IP**）；蜜罐字段 `website`（机器人填了就静默丢）；`ensureSchema` 幂等自建表；渲染端 `esc()`（`textContent`→`innerHTML`）防 XSS；`PAGE_RE` 白名单把非法 page（`../etc/passwd`）归 `home`，挡路径注入。\n\n## 5. 部署踩坑\n\n1. **配置式部署，别带目录参数**：要让 D1 绑定 + functions 随部署生效，`deploy_cloudflare()` 用 `wrangler pages deploy`（**不带 `dist` 参数**，带了会和 `pages_build_output_dir` 冲突）+ `cwd=SELF`（让它读到 `wrangler.toml`）。**部署日志出现 `Uploading Functions bundle` 才算带上了后端。**\n2. **验证线上要跟随 308**：`/suanli/ep04.html` → 308 → `/suanli/ep04`（Pages 去 `.html`）。`curl` 不加 `-L` 只看到空的 308 body，会误判成注入失败。\n3. **本机 curl 走代理**：测本地/线上接口都要 `--noproxy '*'`。\n\n## 6. 它还是「国内真人来没来」的口径\n\n留言板 D1 里的真实留言 + Web Analytics beacon 才是真人信号。**CF「帐户分析/流量概览」统计的是边缘请求数、机器人全算进去，会虚高几十倍，别拿它做决策。**beacon 的 `static.cloudflareinsights.com` 国内可能加载失败 → CN 真人会被少计，所以判断国内真人另看留言板 D1 / 公众号后台。\n\nFile v1.3.0:references/系统说明.md\n\n# 演读 DECK · 沉浸式演示发布系统\n\n> **这份是「落地 README 模板」**：新项目落地时连同 `publish.py` / `home.html` 一起拷进 `<项目根>/演读DECK/README.md`，给**人**看。\n> 给**模型**看的产线规矩在 SKILL.md（做 deck、换肤、留言板都从那儿走），别在这里堆细节。\n\n把「演示版」HTML（一屏一镜、可翻页、能自动播放的 keynote 长文）打包发布到 Cloudflare Pages。\n**线上：https://hekouwang.pages.dev** ｜ 出品：会勇禾口王的AI笔记。\n\n演示版「内容」（各 EP 的 HTML）放在项目内的选题目录里（`EP-算力账本/`、`EP-偷师AI大佬/`…），本目录只放**发布引擎 + 首页 + 字体管线 + 留言板后端**。\n\n## 目录结构\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/\n│   └── api/comments.js   # 留言板后端（Pages Functions）\n├── README.md        # 本说明\n├── fonts/\n│   ├── src/         # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700\n│   │                #        + Anthropic Sans/Mono + Mozilla Headline/Text VF\n│   └── cache/       # 子集化产物缓存（无字体源/无 venv 时回退用）\n├── tools/fenv/      # 子集化用的 Python venv（fonttools+brotli）；移动会失效，丢了就重建\n└── dist/            # ← 构建产物 = 部署到 CF Pages 的目录（可整删，重新构建即生成）\n```\n\n## 用法\n\n```bash\n# 从项目根运行\npython3 演读DECK/publish.py              # 构建 + 部署到 Cloudflare Pages\npython3 演读DECK/publish.py --build-only # 只生成 dist/，不部署\n\n# 本地离线预览（dist 用站内 /fonts/ 绝对路径，必须起服务器，不能 file://）\ncd 演读DECK/dist && python3 -m http.server 8000   # 浏览器开 http://localhost:8000/\n```\n\n**加一期**：在 `publish.py` 的 `MANIFEST` 加一行（源 HTML 路径 + slug + 系列 + 标题…），重跑即可。\n**加一个系列**：补 `SERIES_META` 一条，**并手改 `home.html` 的系列卡**（首页卡是静态手写的，不由 MANIFEST 生成）。\n\n## 它做了什么（关键设计）\n\n1. **干净 URL**：演示版拷进 `dist/<slug>.html`（如 `suanli/ep01`），CF Pages 自动去 `.html`。\n2. **字体全自托管、零 CDN**（`localize()`）：删掉源 HTML 里所有 Google/loli 外链，注入指向 `/fonts/` 的本地 `@font-face`；`FONT_ABS_RE` 把任意绝对字体路径 / 未替换的 `{{SKILL_DIR}}` 占位符统一收编成 `/fonts/`（覆盖 Anthropic + Mozilla）。\n3. **思源黑/宋按用字子集化**（`subset_cjk()`）：用 `tools/fenv` 的 `pyftsubset` 把全站实际用到的字切成小 woff2（各 ~180KB），思源黑 4 字重（400/500/700/900，800 映射 900）+ 宋（金句衬线）。Mozilla VF 是拉丁、体积小，整包打进不子集化。无 venv/字体源时回退 `fonts/cache/`。\n4. **首屏字体预加载 + 强缓存**：每页 `<head>` 注入 `<link rel=preload>`（含 Mozilla 的走 `PRELOAD_LINKS_V6`，按页面是否含 \"Mozilla\" 判定），消除「先系统字、后换思源」的字重跳变；`dist/_headers` 给 `/fonts/*` 设一周强缓存。\n5. **留言板注入**（`inject_comments()`）：构建层把右侧滑出面板注入每篇 `</body>` 前，**EP 源文件不动**。\n\n## 首次落地 / 换机器\n\n```bash\n# 子集化 venv（丢了或换机器时重建）\ncd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli\n\n# 留言板 D1（不做留言板可跳过，并删掉 wrangler.toml / schema.sql / functions/）\nwrangler d1 create <你的库名>                                # 拿 database_id 填进 wrangler.toml\nwrangler d1 execute <你的库名> --remote --file=schema.sql    # 建表\n\n# 部署前先登录\nwrangler login\n```\n\n**要填的自己的值**：`publish.py` 的 `CF_BEACON_TOKEN`（CF Web Analytics，留空则不注入）、`wrangler.toml` 的 `name` / `database_name` / `database_id`。\n\n## 字体源出处\n\n思源黑/宋来自 `@fontsource@5.0.0`（jsdelivr）逐字重静态 woff2；Anthropic Sans/Mono 来自\n`hekouwang-content-factory-skill/assets/fonts/`（自用/演示授权，见该 Skill #9.1.3）；\nMozilla Headline/Text VF 为 Mozilla 官方开源（OFL），可自由使用。\n\nFile v1.3.0:CHANGELOG.md\n\n# 更新日志 · hekouwang-yandu-deck-skill\n\n本文件记录本 Skill 的所有版本变更。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/)，\n版本号遵循 [语义化版本 SemVer](https://semver.org/lang/zh-CN/)：`MAJOR.MINOR.PATCH`。\n\n**变更分类**\n- `功能` 新增能力 · `变更` 默认/行为调整 · `优化` 既有能力打磨 · `修复` 缺陷修正 · `移除` 删除\n\n---\n\n## [1.3.0] - 2026-08-12\n\n### 功能\n- **`scripts/sync-from-harness.sh`**：从 harness `演读DECK/` 单向同步 `publish.py`、`home.html`、留言板模板到 skill 副本。\n\n### 优化\n- **副本追平真身**：`publish.py` 802 行与 harness 对齐（含 Harness 工程系列 / FastMCP / 股票识字等 MANIFEST）。\n- **`references/mobile-and-comments.md`**：移动端 safe-area、留言板禁用步骤、与 HyperFrames 视频产线分工。\n\n## [1.2.1] - 2026-08-12\n\n### 变更\n- **品牌人设对齐 memory `brand-persona-tagline`**：首页 `home.html` 与 `publish.py` 内嵌 about 段，\n  「真会用 AI 的程序员」→ **「会勇禾口王 = AI 工作流 builder」**；补「会勇」谐音「会用」梗。\n- about 文案微调：强调「不靠 PPT 教人，先在自己电脑上跑通再把 Skill 交到你手上」。\n\n## [1.2.0]\n\n### 修复\n- **捆绑副本追平真身（本次最大的洞）**：skill 里的 `publish.py`（511 行）已落后项目真身（735 行）——**SKILL.md 白纸黑字写着「publish.py 已支持 Mozilla 字体打包」，而副本里 \"mozilla\" 出现 0 次**；`home.html` 也只有真身的一半（314/657）。已全量同步，并补上从未随 skill 分发的留言板子系统。承诺现在兑现得了。\n- **主色口径追平线上**：description 与 第1.4节 还写着「暖黑/米白两套主色」，实际线上已是四套并存。**推测缺件正是漂移的成因**——占大头的 V6 焰彩黑没有模板（黑版是 flip 出来的），新 EP 无黑版可拷只能退回老模板，Harness（暖黑）/ 出行SaaS（米白）就是这么来的。\n- **陈旧引用**：兄弟 skill 名补 `-skill` 后缀（真实目录是 `hekouwang-content-factory-skill`，旧名照着找会扑空）；`ROOT` 注释里的旧项目名 `Pi.dev/`；`references/系统说明.md` 里的「后续会升级成 Skill」（早就是了）。\n- **第2节 首页描述**：主色暖黑 → **米白**（2026-07-14 已改），系列卡「两个」→ **五个**，并点明系列卡是**静态手写**、不由 MANIFEST 生成（`write_index()` 是遗留死函数），加系列须三处一起动。\n\n### 功能\n- **留言板随 skill 分发**（`references/留言板-D1.md` + `assets/functions/api/comments.js` + `wrangler.toml` + `schema.sql`）：CF Pages Functions + D1，按页隔离，留言存自己的 CF 账号、无第三方。含建库三步、已有防护（限频/蜜罐/XSS/路径注入）、部署三坑（配置式部署不带 dist 参、验证跟随 308、curl 加 `--noproxy`）。\n- **换肤专题**（`references/换肤-token-flip.md`）：白↔黑 token-flip 映射表 + 三条验收 + 六个坑。含「**原地覆盖脚本先读后写**」——`open(dst,'w')` 会先把文件截断成空，曾把 9 期全写空。\n\n### 变更\n- **第1.4节 主色规矩改为「米白是全站默认，V6 焰彩白是国标专属例外」**；暖黑 / V6焰彩黑降为**存量历史态、不再新做**（存量按计划 flip 回米白）。`deck-engine-暖黑.html` 仅为维护存量保留，标注「新 EP 别拷」。故**不再补 V6焰彩黑模板**——补了等于鼓励继续新做。\n\n### 优化\n- **副本去账号化**（skill 是公开分发的）：`CF_BEACON_TOKEN` 置空（留空则不注入 beacon，降级干净）、`wrangler.toml` 的 `database_id` 改占位符。否则别人用这个 skill 建的站，流量统计报到作者面板、留言写进作者的库。\n- **删死代码**：`FONT_ABS_PREFIX` 指向一个不存在的目录（少 `-skill` 后缀），真正干活的是 `FONT_ABS_RE`。已删常量、采用 skill 版更通用的正则（同时认 `{{SKILL_DIR}}` 占位符与任意绝对路径，覆盖 Anthropic + Mozilla）。\n- **第0节 加防漂移提示**：点明「项目里的是真身、skill 里的是副本，改完记得同步回来」，并记下这次漂移作为前车之鉴。\n\n## [1.1.0]\n\n### 功能\n- **放映 / 提词器模块**（`assets/presenter/presenter-module.html`，第1.6节）：按 `S` 开「讲者视图」独立窗口——计时器 + 当前镜逐字稿 + 下一镜预览。主屏与讲者窗靠 **BroadcastChannel 双向同步**，**主屏保持干净可投影/录屏**；弹窗被拦（或无 BroadcastChannel）自动回退页内浮层。\n- **真·双屏 + 反向遥控**：第二显示器另开 deck 窗口加 `?speaker=1` 即变讲者窗（免弹窗，`window.name`/`?speaker` 识别，绕开引擎深链冲 hash）；讲者窗按 `←/→` 遥控主屏翻镜、`P/R` 控计时（向主屏引擎派发方向键事件，不改引擎）。键位 `S/P/R/Esc`。\n- 逐字稿写进每张 `.slide` 的 `<div class=\"notes\">`（观众/录屏永不可见），**同时即该镜的配音/口播脚本**，可照念或喂 TTS——「演示稿 + 提词器 + 口播稿」三合一。\n- 已注入两套引擎模板（暖黑/米白）与 `examples/demo.html`，拷模板即带，无需改引擎；靠 `.active` class（MutationObserver）与引擎解耦。无头截图验证浮层渲染通过。\n\n## [1.0.1]\n\n### 变更\n- **目录结构对齐官方 `anthropics/skills` 约定**：原先所有可移植副本都堆在 `reference/`（单数、且混入可执行脚本）。\n  现按官方分目录——`scripts/publish.py`、`assets/templates/{deck-engine-暖黑,deck-engine-米白,home}.html`、\n  `references/系统说明.md`、`examples/demo.html`。SKILL.md / README(中英) 的指针与结构树同步更新。\n  注：`scripts/publish.py` 与 `assets/templates/home.html` 落地时仍须拷进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源），文档已注明。\n\n## [1.0.0]\n\n首个有记录的版本（此前以 git 历史维护，无 CHANGELOG）。\n\n### 修复\n- **字体路径可移植化**：① `reference/publish.py` 的 `localize()` 由写死的绝对前缀\n  （硬编码家目录 + `assets/fonts/`）改为**正则 `FONT_ABS_RE`**，同时认「任意绝对路径」与未替换的\n  `{{SKILL_DIR}}` 占位符，统一收成站内 `/fonts/`；② 引擎模板 `deck-engine-{暖黑,米白}.html` 的\n  `@font-face` 硬编码字体路径改为占位符 `{{SKILL_DIR}}/assets/fonts/`，拷模板做 EP 时替换。\n  不再绑定某台机器/用户名；同时修了 content-factory 改用 `{{SKILL_DIR}}` 占位后、源 HTML 字体前缀随机器变化会替换不中导致字体失效的隐患。\n\n### 优化\n- **SKILL.md 声明 `allowed-tools`**：收敛到本 skill 真正需要的工具集，减小越权面。\n\n### 既有能力（首版基线）\n- **演示版引擎**：零依赖（纯 CSS + 原生 JS）一屏一镜 keynote，暖黑/米白两套主色；导航（方向键/空格/点击/触屏/圆点/全屏）、自动播放、进度条、深链、`prefers-reduced-motion` 自适应。模板 `reference/deck-engine-{暖黑,米白}.html`。\n- **进场动画钩子**：`.an/.bar/.tok/.draw/.grow/[data-count]` + 巨幅幽灵章节号。\n- **字体自托管（零 CDN）**：`publish.py` 删外链、注入本地 `@font-face`、`pyftsubset` 子集化思源黑 4 字重 + 宋，preload 防 FOUT，`/fonts/*` 强缓存。\n- **发布**：构建 `dist/` → `wrangler pages deploy` 到 Cloudflare Pages（hekouwang.pages.dev）；`MANIFEST`/`SERIES_META` 加期加系列。\n- **踩坑沉淀**：dist 每构建清空、本地预览须起 http、CF 子域占用 + 本机 DNS 劫持、EdgeOne 死路、venv 移动失效、代理截断 >4MB 下载。\n- 强依赖内容产线 `hekouwang-content-factory`（付费 skill，提供源文章/视觉规范/字体）；引擎可零依赖单独使用。\n\nFile v1.3.0:README.en.md\n\n# hekouwang-yandu-deck-skill · YanDu DECK\n\n**English** · [中文](README.md)\n\nA [Claude Code](https://claude.com/claude-code) **Skill** by *会勇禾口王的AI笔记* — the production + publishing pipeline for **YanDu DECK** (演读 DECK), an immersive presentation format.\n\nIt turns an article into a **one-screen-per-idea, swipeable, auto-playing** keynote web deck (in **dark** or **light** theme), self-hosts its fonts (Noto Sans/Serif SC subsetted + Anthropic bundled, zero CDN, `preload` to kill FOUT), and deploys to Cloudflare Pages with one command.\n\nLive example: **https://hekouwang.pages.dev**\n\n## Demo\n\nFastest way to feel it — double-click **[`examples/demo.html`](examples/demo.html)**: a **self-contained, zero-dependency, system-font** minimal example. Just open it via `file://` to see the engine animate (paging / auto-play / bars growing / numbers counting up / lines drawing / staggered cards).\n\n| Cover (count-up + gradient title) | Flow slide (nodes fade in + arrows draw + stat pop) |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **Full live decks (swipeable / auto-play):**\n  - Home: <https://hekouwang.pages.dev>\n  - Dark series: <https://hekouwang.pages.dev/suanli/ep01> (`#3` jumps to slide 3)\n  - Light series: <https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` are the two **full engine templates** (serve locally to load fonts: `python3 -m http.server`).\n\n## Dependencies\n\n| Dependency | Relationship | Notes |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **Content source (hard dependency)** | This Skill is the *\"turn content into a swipeable deck + publish\"* half. The other half — generating the article HTML, the visual systems (V1/V2/V3), de-AI-ifying copy, compliance — lives in `hekouwang-content-factory`. Source HTML, color tokens and the font scheme all come from it. **⚠️ `hekouwang-content-factory` is a paid Skill** (contact the author @huiyonghkw for a license); its content is **not** included in this repo. |\n| Python 3 + `fonttools` + `brotli` | Font subsetting | Only needed at publish time (the `tools/fenv` venv, see `SKILL.md`). Without it, it falls back to the pre-subsetted fonts in `fonts/cache/`. |\n| `wrangler` (Cloudflare) | Deploy | `publish.py` calls it to deploy to CF Pages; first run needs `wrangler login`. |\n| Anthropic Sans/Mono woff2 | Latin / mono fonts | From `hekouwang-content-factory` (self-use / demo license). If absent, Latin text falls back to system fonts. |\n\n> Want just the **engine** (not the content pipeline)? Copy `assets/templates/deck-engine-*.html` as a template and fill in your content — that part is zero-dependency and stands alone.\n\n## What is this\n\nA Claude Code **Skill**, organized per the official `anthropics/skills` convention. `SKILL.md` is the method doc the agent reads; `scripts/` `assets/` `references/` `examples/` hold ready-to-copy scripts, templates, docs and samples.\n\n```\nSKILL.md                              # method + triggers + gotchas (agent entry point)\nscripts/\n└── publish.py                       # build dist/ → deploy to CF Pages (no 3rd-party deps)\nassets/templates/\n├── deck-engine-暖黑.html             # deck engine template (dark — data / finance / explainer)\n├── deck-engine-米白.html             # deck engine template (light — editorial / methodology)\n└── home.html                        # homepage template\nreferences/\n└── 系统说明.md                       # system notes (zh)\nexamples/\n└── demo.html                        # self-contained zero-dep animated example\n```\n\n> Placement rule: copy `scripts/publish.py` and `assets/templates/home.html` into the **same** `演读DECK/` dir in your project (publish.py resolves the homepage via `SELF/home.html`).\n\n## Install\n\nClone into `~/.claude/skills/hekouwang-yandu-deck-skill/`:\n\n```bash\ngit clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill\n```\n\nThen in Claude Code, say things like *\"turn this into a deck / add a YanDu episode / publish to hekouwang\"* and it auto-loads.\n\n## Core features\n\n- **Deck engine** (zero-dependency CSS+JS): full-screen one-idea-per-slide; arrow keys / space / click / touch paging; auto-play; entrance animations (staggered cards / growing bars / SVG line-draw / number count-up / ghost section numbers); `fit()` auto-scaling; `#N` deep links; `prefers-reduced-motion` friendly.\n- **Two themes**: dark (data-console) / light (editorial) — the engine JS is theme-agnostic.\n- **Self-hosted fonts**: Noto Sans SC (4 weights) + Serif subsetted to the glyphs actually used (~180KB each), Anthropic Sans/Mono bundled, zero external requests; `preload` + long cache to remove the first-paint weight flash.\n- **One-command publish**: `python3 publish.py`; add one MANIFEST line per episode; clean URLs on CF Pages.\n\n> For the companion article/graphics/video pipeline, see `hekouwang-content-factory`.\n\n## License\n\nThe code in this repo (deck engine templates, `publish.py`, `demo.html`, `home.html`, `SKILL.md`, etc.) is **MIT** licensed — see [LICENSE](LICENSE). Note:\n\n- **`hekouwang-content-factory` is a separate, paid Skill; its content is not in this repo** and is not covered by this license.\n- Noto Sans SC / Noto Serif SC are SIL OFL fonts — **no font files are bundled here**; their OFL applies when you fetch them.\n- Anthropic Sans/Mono are proprietary fonts, not bundled here; confirm your own licensing before use.\n\nFile v1.3.0:skill-card.md\n\n## Description:\n\nhekouwang-yandu-deck-skill helps an agent turn articles into swipeable, auto-playing keynote-style web decks, manage deck themes and comments, and publish the resulting site to Cloudflare Pages.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[huiyonghkw](https://clawhub.ai/user/huiyonghkw)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and content producers use this skill to convert article content into full-screen presentation decks, maintain deck templates and themes, add a Cloudflare D1-backed comments feature, and publish the resulting site to Cloudflare Pages.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Publishing behavior can deploy generated content to Cloudflare Pages.\n\nMitigation: Run the publishing script with --build-only first, inspect the generated site, and deploy only after confirming the target Cloudflare project.\n\nRisk: Analytics and D1 configuration may point to the wrong Cloudflare account or database if copied without review.\n\nMitigation: Replace or remove the Cloudflare Web Analytics beacon and verify wrangler.toml uses the user's own Pages project and D1 database before deployment.\n\nRisk: The publish script can attempt a global Wrangler installation when Wrangler is missing.\n\nMitigation: Install Wrangler explicitly in the user's preferred environment before running the publish workflow.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/huiyonghkw/skills/hekouwang-yandu-deck-skill)\n- [Publisher profile](https://clawhub.ai/user/huiyonghkw)\n- [Project homepage](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n- [README.en.md](README.en.md)\n- [mobile-and-comments.md](references/mobile-and-comments.md)\n- [换肤-token-flip.md](references/换肤-token-flip.md)\n- [留言板-D1.md](references/留言板-D1.md)\n- [系统说明.md](references/系统说明.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with code snippets, shell commands, HTML templates, JavaScript, Python, shell scripts, and configuration files]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Produces agent-facing implementation guidance and ready-to-copy deck publishing assets; generated site output depends on the user's source content and Cloudflare configuration.]\n\n## Skill Version(s):\n\n1.3.0 (source: server release metadata, SKILL.md frontmatter, CHANGELOG)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.3.0:assets/templates/wrangler.toml\n\n# 演读 DECK · Cloudflare Pages 配置（落地新项目时拷进 <项目根>/演读DECK/）\n# 首页/每期留言板用到 Pages Functions（functions/）+ D1 数据库（binding=DB）。\n#\n# 落地三步（照做即可，不做留言板可整份删掉本文件）：\n#   1. wrangler d1 create <你的库名>                     → 输出里拿 database_id\n#   2. 把 database_id 填回下面（name/database_name 也换成你自己的）\n#   3. wrangler d1 execute <你的库名> --remote --file=schema.sql   → 建表\n#\n# ⚠️ database_id 不是密钥，但它绑定的是「某个具体 CF 账号下的库」——\n#    别直接用别人的，否则你的站会往别人的库里写留言。\nname = \"<your-pages-project>\"          # CF Pages 项目名，也决定 <name>.pages.dev 子域\npages_build_output_dir = \"dist\"\ncompatibility_date = \"2024-11-01\"\n\n[[d1_databases]]\nbinding = \"DB\"                         # 代码里按这个名字取（functions/api/comments.js 用 env.DB），别改\ndatabase_name = \"<your-d1-name>\"\ndatabase_id = \"<your-d1-database-id>\"  # ← wrangler d1 create 后填回\n\nFile v1.3.0:LICENSE\n\nMIT License\n\nCopyright (c) 2026 huiyonghkw (会勇禾口王的AI笔记)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n---\n\nScope / third-party notice\n\nThe MIT license above covers the code in THIS repository: the deck engine\ntemplates (reference/deck-engine-*.html), demo.html, publish.py, home.html,\nSKILL.md and docs.\n\nIt does NOT cover, and this repository does NOT include:\n\n- `hekouwang-content-factory` — a separate, PAID Claude Code Skill (the content/\n  visual-system half). Its content has its own terms; contact the author.\n- Noto Sans SC / Noto Serif SC (思源黑体/思源宋体) — SIL Open Font License (OFL).\n  No font files are bundled here; when you fetch them, their OFL applies.\n- Anthropic Sans / Anthropic Mono — proprietary fonts, not bundled here; confirm\n  your own licensing for any use.\n\nArchive v1.2.1: 21 files, 134818 bytes\n\nFiles: assets/functions/api/comments.js (4492b), assets/presenter/presenter-module.html (9173b), assets/templates/deck-engine-V6焰彩白.html (47106b), assets/templates/deck-engine-暖黑.html (68653b), assets/templates/deck-engine-米白.html (46608b), assets/templates/home.html (43088b), assets/templates/schema.sql (906b), assets/templates/wrangler.toml (1110b), CHANGELOG.md (7527b), examples/demo.html (29366b), LICENSE (1798b), README.en.md (5567b), README.md (5453b), references/换肤-token-flip.md (8887b), references/留言板-D1.md (3428b), references/系统说明.md (4632b), scripts/flip-暖黑到米白.py (4047b), scripts/publish.py (44320b), skill-card.md (2727b), SKILL.md (16521b), _meta.json (145b)\n\nFile v1.2.1:SKILL.md\n\n---\nname: hekouwang-yandu-deck-skill\nversion: 1.2.1\ndescription: >\n  会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。\n  当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。\n  触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n---\n\n# 演读 DECK · 沉浸式演示产线与发布\n\n> 「演读 DECK」= 会勇禾口王的AI笔记出品的一款**沉浸式阅读产品**：介于长文和视频之间的第三种读法——一屏一镜、方向键/空格/点击翻页、能自动播放，把一个复杂主题安静完整地讲给你看。\n> 线上：**https://hekouwang.pages.dev** ｜ 与图文产线 `hekouwang-content-factory-skill` 配套（那是出文章/贴图/视频，这是把内容做成翻页演示 + 发布）。\n\n## 0. 系统在哪（先认这个）\n\n发布系统是项目里一个**自包含目录** `<项目根>/演读DECK/`：\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库 + 一个子集化 venv）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用；不做留言板可删）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/api/comments.js   # 留言板后端（Pages Functions，按目录约定生效）\n├── fonts/src/       # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700 + Anthropic Sans/Mono + Mozilla VF\n├── fonts/cache/     # 子集化产物缓存（无字体源/无 venv 时回退）\n├── tools/fenv/      # 子集化 venv(fonttools+brotli)；移动会失效，丢了重建\n├── dist/            # 构建产物 = 部署目录（可整删重生）\n└── README.md\n```\n\n> ⚠️ **上面这套是「真身」，本 skill 里的是可移植副本**。日常在项目里改的是真身；**改完记得同步回 skill**，否则副本很快过时（历史上漂移过一次：skill 版落后到没有 Mozilla 字体、没有留言板）。\n\n本 Skill 按官方约定分目录带了**可移植副本**（新项目落地时拷过去）：\n- `assets/templates/` — `deck-engine-米白.html`（⭐默认）/ `deck-engine-V6焰彩白.html`（国标）/ `deck-engine-暖黑.html`（仅维护存量）、`home.html`（首页源）、`wrangler.toml` + `schema.sql`（留言板，**database_id 是占位符，落地填自己的**）\n- `scripts/publish.py`（发布脚本）、`assets/functions/api/comments.js`（留言板后端）\n- `references/换肤-token-flip.md`（换肤）、`references/留言板-D1.md`（留言板）、`references/系统说明.md`（**落地 README 模板**，拷进 `演读DECK/README.md` 给人看）、`examples/demo.html`（零依赖最小示例）\n\n> ⚠️ **落地时 `publish.py` 与 `home.html` 必须同目录**（`publish.py` 用 `SELF/home.html` 找首页源）；`functions/` 要放成 `演读DECK/functions/api/comments.js`。\n> ⚠️ 副本里 **`CF_BEACON_TOKEN` 与 `wrangler.toml` 的 database_id 都留空/占位**——落地新站时填自己的，别沿用他人的（否则流量统计报到别人面板、留言写进别人的库）。\n\n## 1. 把文章做成「演示版 deck」⭐ 核心\n\n一篇 V2 文章 → 一屏一镜的 keynote。**零依赖（纯 CSS + 原生 JS，不引 GSAP/外链，国内/CF 都快）。** 沿用源文章的视觉（默认米白，国标走 V6 焰彩白，见 第1.4节）、字体、grain/mesh/frame/幽灵章节号。\n\n### 1.1 引擎（照抄模板，别重写）\n\n样板（**默认拷米白**，选哪套见 第1.4节）：\n- `assets/templates/deck-engine-米白.html` — ⭐ **默认**，人文/方法论亮调。\n- `assets/templates/deck-engine-V6焰彩白.html` — 国标系列专属：紫主色+焰橙/粉，Mozilla 可变字体（`publish.py` 的 `MOZILLA_FILES` 已打包 Mozilla 字体、按页面含 \"Mozilla\" 注入 `PRELOAD_LINKS_V6`）。\n- `assets/templates/deck-engine-暖黑.html` — 🕰️ 仅维护存量（Harness），**新 EP 别拷**。\n**做新 EP = 拷一份对应主色的模板，`<head>` 的全部 CSS 和 `</main>` 之后的全部 `<script>` 逐字保留，只换内容 slide / 顶栏标签 / title / 片尾。** 引擎已实现：\n\n> ⚠️ 模板 `@font-face` 里的字体路径是占位符 `{{SKILL_DIR}}/assets/fonts/...`——指向兄弟 skill `hekouwang-content-factory-skill` 的字体。拷模板做 EP 时**把 `{{SKILL_DIR}}` 替换成 hekouwang-content-factory-skill 的绝对 Base directory**（本地预览/截图才有字体）。发布时 `publish.py` 会把它统一收成站内 `/fonts/`，万一漏替换也能兜底。\n\n- 全屏 `.slide`（一屏一镜），`.stage` 居中 + JS `fit()` 等比缩放防裁切；\n- 导航：←/→/空格/点击/触屏滑动/底部圆点/Home/End/F 全屏；右下「▶ 自动播放」(7s/屏，像放视频)；顶部进度条 + `NN/总数`；`#N` 深链（可分享到某屏）；`prefers-reduced-motion` 自动关动画。\n- **S 放映 / 提词器**（讲者视图：计时器 + 当前镜逐字稿 + 下一镜预览，详见 第1.6节）。模板已内置该模块，拷模板即带。\n\n### 1.2 进场动画钩子（只加 class + `--i` 递增控错峰，CSS 已定义）\n\n| 钩子 | 效果 | 用在 |\n|---|---|---|\n| `.an` / `.an.scale` | 淡入上浮 / 带放大 | 任何要进场的块；按出现顺序 `style=\"--i:0\"`、`--i:1`… |\n| `.bar` | 横向条 scaleX 从左生长 | 柱状/条形数据条（只给数据条，不给坐标轴） |\n| `.tok` | SVG 节点组逐个淡入 | 流程/关系/漏斗/桥的节点 `<g>` |\n| `.draw` | 折线/箭头描线(JS getTotalLength) | 连接线 `<line>`/`<path>` |\n| `.grow` | 弹性放大 | stat 数据卡 |\n| `[data-count]`+`data-suffix` | 纯数字 0→N 滚动 | 纯数字读数（初始文本写 `0`；**含箭头/汉字/百分号的别用**） |\n\n每个 slide `data-g=\"章节号\"` → 背景自动生成巨幅幽灵数字（封面/速览/片尾用 `data-g=\"·\"`）。\n\n### 1.3 内容映射铁律（一图一镜）\n\n源文每个 section + 每张图表都要有对应镜头。**封面屏 + 速览屏（用源文 hero 的关键数据做 readout 仪表条）打头，片尾签收卡收尾**（含私域 CTA），一篇 9 节 → 约 12–24 屏。\n**SVG 图表逐字搬运**（viewBox/坐标/配色/字体不改），只在外层 `.fig` 加 `an`、给数据条/节点/折线加动画钩子。源文的 `.fig.breakout` 破格在演示版里**去掉**（每屏已全宽居中，负 margin 会出问题）。文案可适度精简适配一屏，保意保语气、过 `hekouwang-content-factory-skill` #6.6 去 AI 味。\n\n### 1.4 主色：**米白是全站默认**，焰彩白是国标专属例外\n\n新做任何一期，**默认拷米白引擎**。只有两种情况例外，别自作主张换调：\n\n| 系列 | 主色 | 拷哪个模板 |\n|---|---|---|\n| **默认 / 首页 / 出行SaaS** | **米白** `#faf9f5` + 黏土 `#c15f3c`（编辑/人文感） | `deck-engine-米白.html` |\n| **智能体互联国标** | **V6 焰彩白** `#fbfaff` + 紫 `#7c3aed` + 焰橙/粉，Mozilla 可变字体（大厂发布感） | `deck-engine-V6焰彩白.html` |\n\n- ⚠️ **暖黑 `#161514` / V6焰彩黑 `#170a30` = 历史过渡态，不再新做**。线上尚有存量（算力账本·偷师=焰彩黑，Harness=暖黑），按计划逐步 flip 回米白；`deck-engine-暖黑.html` 仅为维护存量保留，**新 EP 不要拷它**。\n- 亮底适配铁律（米白/焰彩白）：网格线改极淡深色、卡片靠 `--shadow` 投影不靠辉光、标题黏土渐变(深→浅)、幽灵号深色 `opacity:.05`、`.grain` 用 `mix-blend-mode:multiply`。引擎 JS 主题无关、逐字一致。\n- **给存量 deck 换肤（黑→米白）→ 读 [`references/换肤-token-flip.md`](references/换肤-token-flip.md)**：脚本会截空文件、半成品会留残色，踩过的坑都在里面，别凭感觉改。\n\n### 1.5 批量做（多 EP）\n\n引擎相同、只内容不同 → 并行开多个 subagent，每个给「对应主色模板路径 + 源文章路径 + 本节规则」，要求 `<head>`CSS 与 `<script>`JS 与模板**逐字一致**，只换内容、按源文追加专属组件 CSS（滑块/时间线/对比/桥…，改用模板的 token）。产出后主控用 headless Chrome 截图核验各图表屏（`--virtual-time-budget=5000` 让动画跑完）。\n\n## 1.6 放映 / 提词器（讲 + 录 双用）⭐\n\n模块：`assets/presenter/presenter-module.html`（自包含 `<style>+<div>+<script>`，已注入三套引擎模板与 `examples/demo.html`，**拷模板即带，无需改引擎**）。\n\n- **按 `S`** 开「讲者视图」：**独立窗口**（计时器 + 当前镜逐字稿 + 下一镜预览），主屏与讲者窗靠 **BroadcastChannel 双向同步**——**主屏保持干净，可投影 / 录屏**。弹窗被拦（或无 BroadcastChannel）时自动回退为页内全屏浮层（单屏排练也能用）。\n- **真·双屏**：把 deck 在第二显示器再开一个窗口、地址后加 `?speaker=1` 即变讲者窗，免弹窗。讲者窗可**反向遥控主屏**：在讲者窗按 `←/→` 翻镜、`P` 计时、`R` 归零、`Esc/S` 关（靠向主屏引擎派发方向键事件，不改引擎）。\n- **键位**：`S` 开/关 · `P` 计时启停 · `R` 归零 · `Esc` 关 · `←/→` 翻镜（主屏与讲者窗都认）。\n- **逐字稿 = 配音 / 口播脚本**：在每张 `.slide` 里加 `<div class=\"notes\">这一镜要讲的话…</div>`（观众/录屏**永不可见**，模块强制 `display:none`）。这份 notes 同时就是该镜的口播稿——录屏时主屏放干净 deck、讲者窗当提词器照念；也可直接喂 TTS（云扬）。\n- 取数靠 `#deck .slide` 的 `.active` class（`MutationObserver` 监听），与引擎解耦；无 `.notes` 的镜回退显示标题。讲者信号用 `window.name`/`?speaker`（**不用 `#speaker`**——引擎深链 `replaceState('#N')` 会把 hash 冲掉）。\n- ⚠️ 本地 `file://` 双击时 `window.open` 可能被拦、且 BroadcastChannel 跨窗不通（opaque origin）——**用 `python3 -m http.server` 起本地服务**预览（与字体本地化要求一致）；发布到 CF Pages(https) 后正常。\n\n> 一图一镜 + 每镜一段 notes ⇒ 写完 deck 就同时有了「演示稿 + 提词器 + 口播稿」三合一。\n\n## 2. 首页 `home.html`\n\n演读 DECK 品牌落地页（**米白 `#faf9f5`**，2026-07-14 起；此前为暖黑）：masthead 品牌 + 「演读 ⟨DECK⟩」产品名、hero「把复杂的 AI，读成一场演示」、proof 三栏（第三种读法/翻页·自动播放/读完就懂）、系列卡片区（现 5 个：国标 / 算力账本 / 偷师AI大佬 / Harness工程 / 出行SaaS工程手记）、出品方 about（人设 + 禾口王=程）、订阅区（领《AI 内容流水线手册》三步）、底部内联留言板（`.talk-*`，`page='home'`）。**响应式**断点齐全（600/680/760/520）。\n- ⚠️ **系列卡是静态手写的**，不由 `MANIFEST` 生成（`write_index()` 是遗留死函数）——加系列要**手改 `home.html`** + 补 `MANIFEST`/`SERIES_META` 三处一起动。\n- 人设口径以记忆 `brand-persona-tagline` 三句为准（别自由改措辞）。**改首页改 `演读DECK/home.html`，不在 `dist/` 里改。**\n\n## 3. 字体自托管（零 CDN）⭐ 关键\n\n发布时 `publish.py` 的 `localize()` 把源 HTML 里所有 Google/loli 外链删掉、注入指向 `/fonts/` 的本地 `@font-face`；Anthropic 绝对路径也改写成 `/fonts/`。`subset_cjk()` 用 `tools/fenv` 的 `pyftsubset` 按**全站实际用字**把思源黑 4 字重（400/500/700/900，800 映射 900）+ 宋（金句衬线）子集化成小 woff2（各 ~180KB），连 Anthropic 一起打包进 `dist/fonts/`。\n\n- **首屏字重跳变(FOUT)**：每页 `<head>` 注入 4 条 `<link rel=preload>`（900/400/Anthropic Sans/Mono）让关键字体高优先级先下；`dist/_headers` 给 `/fonts/*` 设一周强缓存。这两条**必须保留**，否则首屏会「先系统字、再换思源」肉眼可见跳一下。\n- 字体源出处：思源来自 `@fontsource@5.0.0`（jsdelivr）逐字重静态 woff2；Anthropic 来自 `hekouwang-content-factory-skill/assets/fonts/`（自用/演示授权）；Mozilla Headline/Text VF 为 Mozilla 官方开源（OFL），可自由使用。\n- venv 丢了重建：`cd 演读DECK && python3 -m venv tools/fenv && tools/fenv/bin/pip install fonttools brotli`。无 venv/字体源时 publish 回退用 `fonts/cache/`。\n\n## 4. 发布\n\n```bash\n# 从项目根运行\npython3 演读DECK/publish.py              # 构建 dist/ + 部署到 CF Pages（hekouwang）\npython3 演读DECK/publish.py --build-only # 只构建 dist/，不部署\n```\n\n- **加一期**：在 `publish.py` 的 `MANIFEST` 加一行（源 HTML 相对项目根的路径 + slug 如 `suanli/ep04` + 系列 + EP + 分类 + 标题 + 简介 + 屏数）。**加一个系列**：再补 `SERIES_META` 一条，**并手改 `home.html` 的系列卡**——首页系列卡是**静态手写**的，不由 MANIFEST 生成（`write_index()` 是遗留死函数，别指望它）。\n- **留言板**（Pages Functions + D1）随部署一起生效，**加装/排错 → 读 [`references/留言板-D1.md`](references/留言板-D1.md)**：部署得用配置式（不带 `dist` 参数）+ `cwd=SELF`，日志出现 `Uploading Functions bundle` 才算带上后端。\n- 干净 URL：演示版拷进 `dist/<slug>.html`，CF Pages 自动去 `.html`（`/suanli/ep01`）。\n- 部署用 `wrangler pages deploy dist --project-name hekouwang`；首次需 `wrangler login`（用户自己 `! wrangler login`）。\n\n## 5. 防踩坑（实测血泪）\n\n1. **`dist/` 每次构建被清空**——别在里面改任何东西；首页改 `home.html`，演示版改各 EP 源。\n2. **本地预览必须起 http 服务器**：`dist` 用站内 `/fonts/` 绝对路径，`file://` 双击打不出字体。`cd dist && python3 -m http.server 8000`。\n3. **`keynote.pages.dev` / `keynotes` 等常用名全球已被占**——CF 会自动加随机后缀(`keynote-9z0`)。本机网络有透明代理劫持 DNS、返回 198.18.0.x 假 IP，**本地 nslookup 测不出子域可用性**；唯一可靠 = `wrangler pages project create <名>` 后看 `project list` 分配的子域有没有后缀。最终用 `hekouwang`。\n4. **国内 EdgeOne 是死路**：免费自动域名一律带 token 鉴权、公网 401（ICP 备案要求），别再碰；直接 Cloudflare Pages。\n5. **移动 venv 会失效**（shebang/pyvenv.cfg 写死原路径）——换位置就重建。\n6. **本机代理会截断大文件下载(>~4MB)**：思源变量字体下不全 → 改用 @fontsource 逐字重静态 woff2(各 ~1.6MB)再子集化。\n7. 截图核验演示版给足时间（`--virtual-time-budget=5000`），让 fit/动画跑完再截。\n\n## 配套与依赖\n- **内容产线（强依赖）：`hekouwang-content-factory-skill`**——演示版的源文章 HTML、视觉规范(V1/V2/V3)、配色 token、字体方案都来自它；本 Skill 只做「内容→翻页演示+发布」这一半。**⚠️ 它是付费 Skill**（需作者授权），仓库不含其内容。只用引擎可直接拷 `assets/templates/deck-engine-*.html`（零依赖独立可用）。\n- 示例：`examples/demo.html`（自包含、零依赖、双击即看的最小动画示例）。\n- 记忆：`keynote-yanshi-site`（站点现状 + 发布链路）、`keynote-deck-engine`（引擎做法）、`brand-persona-tagline`（人设三句）。\n\nFile v1.2.1:README.md\n\n# hekouwang-yandu-deck-skill · 演读 DECK\n\n**中文** · [English](README.en.md)\n\n> GitHub: [https://github.com/huiyonghkw/hekouwang-yandu-deck-skill](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n\n会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。\n\n把一篇文章/选题做成**一屏一镜、可翻页、能自动播放**的 keynote 演示版网页（**暖黑** / **米白** 两套主色），自托管字体（思源黑/宋子集化 + Anthropic 打包、零 CDN、preload 治 FOUT），并一键发布到 Cloudflare Pages。\n\n线上样例：**https://hekouwang.pages.dev**\n\n## 示例动画版本 / Demo\n\n最快的体验方式 —— 双击打开 **[`examples/demo.html`](examples/demo.html)**：一个**自包含、零依赖、系统字体**的最小示例，直接 `file://` 打开就能看引擎怎么动（翻页 / 自动播放 / 柱子生长 / 数字滚动 / 折线描线 / 卡片错峰）。\n\n| 封面（数字滚动 + 标题渐变） | 流程屏（节点淡入 + 箭头描线 + stat 弹入） |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **在线完整版（可翻页/自动播放）**：\n  - 首页：<https://hekouwang.pages.dev>\n  - 暖黑系列：<https://hekouwang.pages.dev/suanli/ep01>（`#3` 直达第 3 屏）\n  - 米白系列：<https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` 是两套**完整引擎模板**（需起本地服务器看字体：`python3 -m http.server`）。\n\n## 依赖\n\n| 依赖 | 关系 | 说明 |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **内容来源（强依赖）** | 本 Skill 是「**把内容做成翻页演示 + 发布**」的一半；**另一半（生成文章 HTML、视觉规范 V1/V2/V3、去 AI 味、合规红线）在 `hekouwang-content-factory`**。演示版的源 HTML、配色 token、字体方案都源自它。**⚠️ `hekouwang-content-factory` 是付费 Skill**（GitHub 上为 **PRIVATE 私有仓库，非授权无法 clone / 获取**；需向作者 @huiyonghkw 获取授权），本仓库不含其内容。 |\n| Python 3 + `fonttools`+`brotli` | 字体子集化 | 仅发布时需要（`tools/fenv` venv，见 `SKILL.md`）。没有则回退用 `fonts/cache/` 已切好的子集。 |\n| `wrangler`（Cloudflare） | 部署 | `publish.py` 调它发到 CF Pages；首次需 `wrangler login`。 |\n| Anthropic Sans/Mono woff2 | 拉丁/代码字体 | 来自 `hekouwang-content-factory`（自用/演示授权）。缺失则拉丁字自动回退系统字。 |\n\n> 只想用**引擎**（不要内容产线）：直接拷 `assets/templates/deck-engine-*.html` 当模板填内容即可，那部分零依赖、可独立使用。\n\n## 这是什么\n\n这是一个 [Claude Code](https://claude.com/claude-code) **Skill**，按官方 `anthropics/skills` 约定分目录组织。`SKILL.md` 是给 Agent 读的方法说明；`scripts/` `assets/` `references/` `examples/` 是可直接拷用的脚本、模板、文档与示例。\n\n```\nSKILL.md                              # 方法 + 触发词 + 防踩坑（Agent 入口）\nscripts/\n└── publish.py                       # 构建 dist/ → 部署 CF Pages（零三方依赖）\nassets/templates/\n├── deck-engine-暖黑.html             # 演示版引擎模板（数据/财经/科普暗调）\n├── deck-engine-米白.html             # 演示版引擎模板（人文/方法论亮调）\n└── home.html                        # 首页模板\nreferences/\n└── 系统说明.md                       # 系统说明文档\nexamples/\n└── demo.html                        # 零依赖最小示例（双击即看）\n```\n\n> 落地铁律：`scripts/publish.py` 与 `assets/templates/home.html` 拷进项目时必须放进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源）。\n\n## 安装\n\n把本仓库放进 `~/.claude/skills/hekouwang-yandu-deck-skill/`：\n\n```bash\ngit clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill\n```\n\n之后在 Claude Code 里说「把这篇做成演示版 / 加一期演读 / 发 hekouwang」等即会自动加载。\n\n## 核心能力\n\n- **演示版引擎**（零依赖 CSS+JS）：全屏一屏一镜、←/→/空格/点击/触屏翻页、自动播放、进场动画（卡片错峰 / 柱子生长 / SVG 描线 / 数字滚动 / 幽灵章节号）、`fit()` 自适应、`#N` 深链、`prefers-reduced-motion` 友好。\n- **两套主色**：暖黑（数据控制台）/ 米白（编辑人文），引擎 JS 主题无关。\n- **字体自托管**：思源黑 4 字重 + 宋按用字子集化（各 ~180KB），Anthropic Sans/Mono 打包，全站零外链；preload + 强缓存消除首屏字重跳变。\n- **一键发布**：`python3 publish.py`，MANIFEST 加一行即加一期，CF Pages 干净 URL。\n\n> 配套图文/视频产线见 `hekouwang-content-factory`。\n\n## License\n\n本仓库代码（演示版引擎模板、`publish.py`、`demo.html`、`home.html`、`SKILL.md` 等）以 **MIT** 开源，见 [LICENSE](LICENSE)。注意：\n\n- **`hekouwang-content-factory` 是独立的付费 Skill，其内容不在本仓库**，不受本许可覆盖。\n- 思源黑体/思源宋体（Noto Sans/Serif SC）为 SIL OFL 开源字体，本仓库**不含字体文件**，自行获取时遵循其 OFL。\n- Anthropic Sans/Mono 为专有字体，本仓库不含，使用前自行确认授权。\n\nFile v1.2.1:_meta.json\n\n{\n  \"ownerId\": \"kn73qd1gcmjr446mwcbdxef70x82vxcw\",\n  \"slug\": \"hekouwang-yandu-deck-skill\",\n  \"version\": \"1.2.1\",\n  \"publishedAt\": 1786519670369\n}\n\nFile v1.2.1:references/换肤-token-flip.md\n\n# 演读 DECK · 换肤 = token-flip（不是重做）\n\n给**已有 deck** 换主色时用这套。核心认知：两套主色的 `:root` **逐行结构完全一致、只有值不同**——所以换肤是一次**机械的 token 值映射**，引擎 CSS/JS 一字不动，内容一字不动。别重写、别让 subagent \"参照着做一版\"。\n\n> 当前口径见 SKILL.md 第1.4节：**米白 = 全站默认**，国标走 V6 焰彩白，**暖黑/焰彩黑是存量历史态**——本文档现在主要服务于「存量黑版 → 米白」的收敛。\n>\n> 现成脚本：**`scripts/flip-暖黑到米白.py`**（映射抽自引擎模板 · 单遍替换 · 内建未覆盖色守卫 · 先读后写）。用法 `python3 scripts/flip-暖黑到米白.py <deck.html>...`；退出码 2 = 有未覆盖色，按 第2.6节 人工判断后再跑。\n\n## 0. 动手前（这五步省过一次 9 期全毁）\n\n1. **先查 git 有没有现成的目标态**——见 第0.5节，能取回就别转换。\n2. **先 cp 备份**要改的文件。\n3. flip 脚本**必须先读后写**（见 第3节 第 1 条，这是最贵的坑）。\n4. flip 后 `stat -f%z` 查**每个文件大小非 0**。\n5. flip 后跑**全谱残留 grep**（第2节），**=0 才算过**。\n\n## 0.5 先问一句：git 里是不是躺着现成的？⭐ 省一整轮\n\n演读 DECK 的 deck HTML **都在 git 里**（只有 `演读DECK/publish.py` 被 `.gitignore` 的 `*.py` 排除）。整站换过肤，就意味着**换肤前的版本还在历史里**。要换回某个旧主色时，先查：\n\n```bash\ngit log --oneline --all -- <deck路径>                    # 哪次提交换的肤\ngit show <flip提交>^:<deck路径> | grep -oE -- '--bg:#[0-9a-f]*'   # 换肤前是什么色\ngit log --oneline <flip提交>..HEAD -- <deck路径>          # 换肤后还改过内容吗（0 = 可安全取回）\n```\n\n**换肤后 0 次提交 = 直接 `git show <flip提交>^:<路径>` 取回，精确、零转换风险**，比任何 flip 脚本都可靠。\n2026-07-15 实战：偷师 4 期换肤前本就是米白、之后 0 改动 → 直接取回，全谱残留 grep=0 一次过；而算力 5 期换肤前是**暖黑**（不是米白），取回只能拿到暖黑，仍需一轮真转换。**先查再动，别默认要写脚本。**\n\n## 0.6 ⚠️ 跨设计系统 ≠ 换肤，别硬套\n\n本文档的 flip 只适用于**同一套设计系统的明暗两极**（V6焰彩白↔V6焰彩黑、暖黑↔米白——后两者同为 V2 黏土系统）。\n\n**焰彩黑 → 米白 是跨系统**：主色紫 `#a855f7` vs 黏土 `#c15f3c`、字体 Mozilla VF vs Anthropic Sans，V6 的焰橙/焰粉在 V2 里根本没有对应色。硬套 token-flip 会出四不像。跨系统要走「先 git 取回同系统版本，再同系统 flip」，或老老实实重做。\n\n## 1. 已验证的映射\n\n### 1.1 V6 焰彩：白 ↔ 黑（两向互为精确逆运算）\n\n| 语义 | 焰彩白 | 焰彩黑 |\n|---|---|---|\n| 底 | `#fbfaff` | `#170a30` |\n| surface | `#ffffff` / `#f4eefc` / `#efe7fb` | `#241246` / `#231044` / `#2c1552` |\n| 正文字 | `#1c0b3e` | `#f3eefe` |\n| 主紫 | `#7c3aed` | `#a855f7` |\n| 次紫 | `#6d28d9` | `#c084fc` |\n| 蓝 | `#4f6ef0` | `#7c9bff` |\n| 金 | `#c8620a` / `#e07a1a` | `#ffb454` / `#f0a13a` |\n| warn | `#e0304f` | `#ff5c78` |\n| 线 | `rgba(28,11,62,…` | `rgba(255,255,255,…` |\n| 紫辉光 | `rgba(124,58,237,…` | `rgba(168,85,247,…` |\n| grain | `multiply` `.02` | `screen` `.05` |\n| body class | `class=\"light\"` | `class=\"dark\"` |\n\n**黑白通用、不翻**：焰橙 `#ff8a3d`、焰粉 `#ff4f8b`、`--ok`、`--teal`。\n**演示版与首页的 token 值不同，各写一份映射**，别共用一张表。\n\n### 1.2 暖黑 / 米白（旧两套）\n\n暖黑 `#161514` + 黏土 `#e08a5f` + 石板蓝 `#8fa6bd`；米白 `#faf9f5` + 黏土 `#c15f3c`。\n亮底适配：网格线→极淡深色、卡片靠 `--shadow` 不靠辉光、幽灵号深色 `opacity:.05`、`.grain`→`multiply`。\n\n## 2. 三条验收（缺一条都不算换完）\n\n1. **全谱残留 grep = 0**：拿**旧主色整套调色板**（不只是 `--bg`）去 grep，包括 SVG 内联色。半成品最爱漏的就是图表里的 `#e08a5f`（暖黑黏土）、`#8fa6bd`（石板蓝）。有残留 → 补一轮「旧色→新色」映射再跑。\n2. **封面截图**肉眼过一眼。\n3. **线上 curl 验 token**：跟随 308（`/suanli/ep04.html` → `/suanli/ep04`），确认 `--bg` 和 `class` 是新值。\n\n## 2.5 映射表从模板里抽，别手编；且必须**单遍同时替换** ⭐\n\n**映射的唯一真相源 = 两套引擎模板的 `:root` 逐 token 对照**（同一个引擎、两个主题，key 一一对应）。用脚本 diff 出来，别凭记忆写色号：\n\n```python\n# 剥掉 /* 注释 */ 再解析 :root，逐 key 比对 deck-engine-暖黑 vs deck-engine-米白\n```\n\n实测暖黑 33 token / 米白 26 token，其中 **20 个值不同**（`--bg/--surface*/--line*/--text*/--read/--hot*/--hl0/--cool*/--ochre*/--warn`），4 个通用不翻（`--font/--serif/--mono/--brand`）；另 `--m-*`（9 张插画）暖黑独有、**`stroke='%23000'` 单色遮罩、不含主题色**（靠 CSS 着色，不用管）；`--shadow/--shadow2` 米白独有（亮底要投影），flip 时**要补进去**。\n\n⚠️ **源集与目标集有交集 → 必须单遍替换**：`#f4f2eb` 既是源（暖黑 `--text` → `#1a1a18`）又是目标（暖黑 `--surface2` → `#f4f2eb`）。顺序 sed 会把前一条刚写出的颜色被后一条**再吃一次**，静默改错。正确做法是拼一个大 alternation 一次扫过：\n\n```python\npat = re.compile('|'.join(re.escape(k) for k in sorted(MAP, key=len, reverse=True)), re.I)\nout = pat.sub(lambda m: MAP[m.group(0).lower()], html)   # 单遍，绝不二次命中\n```\n\n## 2.6 图表内部色 ≠ 页面色：**脚本先扫「未覆盖色」并停下来** ⭐\n\ntoken 映射只管**相对页面底色**的颜色。deck 里还有大量**图表内部色**，它们的对比度是相对自己所在的色块，**翻了反而坏**：\n\n- `#19191a` 深字压在浅蓝柱 `#8fa6bd` 上 → 页面转亮底也得**留深**，翻了字就没了\n- `#e8eef3` 浅字压在深柱上 → **留浅**\n- 柱状填充（`#5e6b75`/`#a9714f`/`#8a7d70`）中间调 → 黑白底都成立，**别动**\n- 语义色（如 Harness 里 MCP 的绿 `#8fbf9f`）有含义 → **别当装饰色翻**\n- `#pmode` 讲者浮层（`#0c0d10`/`#ececf2`/`#9a9aac`…）、`.shell` 终端（`#1f1d1b`/`#0c0d10`）**刻意深底** → 不翻\n\n所以 flip 脚本**必须内建一道守卫**：转换前先扫全部目标文件，报出「映射表未覆盖、又不在保留名单」的裸色，**有就退出让人判断**，别闷头转（2026-07-15 实测：算力 EP01 干净，其余 5 期共 **15 种**各自的图表色需人工过——守卫挡住了一次静默改坏）。\n\n## 3. 血泪坑（都已解，别重踩）\n\n1. ⚠️ **原地覆盖脚本必须先读后写**——最贵的一个坑，曾把 9 期**全写空**：\n   ```python\n   # ✗ src==dst 时，open(dst,'w') 先把文件截断成空，再 read 就读到空字符串\n   open(dst,'w').write(flip(open(src).read()))\n   # ✓ 先读进内存，再开写\n   data = open(src).read()\n   open(dst,'w').write(flip(data))\n   ```\n2. **`.shell` 终端组件不翻**：`#1f1d1b` / `#0c0d10` / `rgba(0,0,0,.2)` 是**刻意的深底代码块**（米白/焰彩白母本自身就 `.shell{background:#1f1d1b}`），亮底下也该是深的。只在 `--shadow` 行里翻 `rgba(0,0,0,`，其余深底放行。\n3. **显式串先做**：`shadow` / `body 光晕` / `grain` 这类整串先替换，避免被后面的 bare-value 规则拆坏 alpha。\n4. **grep 单行 minified 会漏**：subagent 输出常是单行 HTML，`grep -c \"--bg:\"` 按行匹配会误判。用 `grep -o`，或先 `wc -c` 看是不是空文件。\n5. **半成品残留**：subagent 转版被中途停 → body SVG 内联色没转完。所以验收靠 第2节 第 1 条，不靠\"它说它做完了\"。\n6. **截图坑 → 用 `--headless=new` + `--timeout`**（2026-07-15 修正）：deck 的 `.draw` 动画让 `--virtual-time-budget` 不收敛。旧 `--headless` 会**挂死且不写盘**（`timeout` 杀进程后目录里什么都没有；\"杀了图其实已写盘\"的旧说法**实测不成立**，别信）。可靠配方——**1.5 秒出图**：\n\n   ```bash\n   \"$CHROME\" --headless=new --disable-gpu --incognito --user-data-dir=\"$TMP/prof\" \\\n     --window-size=1600,900 --hide-scrollbars \\\n     --virtual-time-budget=15000 --timeout=30000 \\\n     --screenshot=\"$TMP/cover.png\" \"file://$DECK\"\n   ```\n   `--timeout` 让 Chrome 自己到点截图退出（退出码 0），不必外部 `pkill`。字体走 content-factory 绝对路径，`file://` 即可加载。\n   ⚠️ 必带 `--incognito` + 独立 `--user-data-dir`，**别碰用户正在用的 Chrome**（见 memory `chrome-screenshot-isolated-incognito`）。\n\nFile v1.2.1:references/留言板-D1.md\n\n# 演读 DECK · 访客留言板（CF Pages Functions + D1）\n\n站点自带留言板：**Cloudflare Pages Functions + D1**，留言存在**自己的 CF 账号**里——无第三方、不用 giscus/GitHub 登录（国内读者友好）。**按页隔离**：首页 `home`，每期用 slug（`suanli/ep04`），各聊各的。\n\n## 1. 件在哪（本 skill 捆绑的落地副本）\n\n| 文件 | 作用 |\n|---|---|\n| `assets/functions/api/comments.js` | 后端：`onRequestGet`（读 `?page=` 列表）/ `onRequestPost`（校验+限频+写入） |\n| `assets/templates/wran\n\nArchive v1.2.0: 20 files, 133171 bytes\n\nFiles: assets/functions/api/comments.js (4492b), assets/presenter/presenter-module.html (9173b), assets/templates/deck-engine-V6焰彩白.html (47082b), assets/templates/deck-engine-暖黑.html (68593b), assets/templates/deck-engine-米白.html (46584b), assets/templates/home.html (43050b), assets/templates/schema.sql (906b), assets/templates/wrangler.toml (1110b), CHANGELOG.md (7114b), examples/demo.html (29366b), README.en.md (5567b), README.md (5453b), references/换肤-token-flip.md (8863b), references/留言板-D1.md (3428b), references/系统说明.md (4632b), scripts/flip-暖黑到米白.py (4047b), scripts/publish.py (44275b), skill-card.md (2613b), SKILL.md (16509b), _meta.json (145b)\n\nArchive v1.0.2: 12 files, 71528 bytes\n\nFiles: assets/templates/deck-engine-暖黑.html (59418b), assets/templates/deck-engine-米白.html (37409b), assets/templates/home.html (22075b), CHANGELOG.md (2951b), examples/demo.html (20191b), README.en.md (5567b), README.md (5453b), references/系统说明.md (3125b), scripts/publish.py (28006b), skill-card.md (2465b), SKILL.md (11035b), _meta.json (145b)\n\nArchive v1.0.1: 3 files, 7102 bytes\n\nFiles: skill-card.md (2319b), SKILL.md (10129b), _meta.json (145b)\n\nArchive v1.0.0: 11 files, 68707 bytes\n\nFiles: README.en.md (5180b), README.md (4760b), reference/deck-engine-暖黑.html (59508b), reference/deck-engine-米白.html (37499b), reference/demo.html (20191b), reference/home.html (22075b), reference/publish.py (27661b), reference/系统说明.md (3125b), skill-card.md (3042b), SKILL.md (10129b), _meta.json (145b)","readmeExcerpt":"Skill: hekouwang-yandu-deck-skill Owner: huiyonghkw Summary: 会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。 当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库 + 一个子集化 venv）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用；不做留言板可删）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/api/comments.js   # 留言板后端（Pages Functions，按目录约定生效）\n├── fonts/src/       # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700 + Anthropic Sans/Mono + Mozilla VF\n├── fonts/cache/     # 子集化产物缓存（无字体源/无 venv 时回退）\n├── tools/fenv/      # 子集化 venv(fonttools+brotli)；移动会失效，丢了重建\n├── dist/            # 构建产物 = 部署目录（可整删重生）\n└── README.md"},{"language":"bash","snippet":"# 从项目根运行\npython3 演读DECK/publish.py              # 构建 dist/ + 部署到 CF Pages（hekouwang）\npython3 演读DECK/publish.py --build-only # 只构建 dist/，不部署"},{"language":"bash","snippet":"open examples/demo.html                              # 零依赖最小示例\nbash scripts/sync-from-harness.sh <path/to/演读DECK>  # 真身→副本同步\npython3 scripts/publish.py --help                    # 发布脚本可用性"},{"language":"text","snippet":"SKILL.md                              # 方法 + 触发词 + 防踩坑（Agent 入口）\nscripts/\n└── publish.py                       # 构建 dist/ → 部署 CF Pages（零三方依赖）\nassets/templates/\n├── deck-engine-暖黑.html             # 演示版引擎模板（数据/财经/科普暗调）\n├── deck-engine-米白.html             # 演示版引擎模板（人文/方法论亮调）\n└── home.html                        # 首页模板\nreferences/\n└── 系统说明.md                       # 系统说明文档\nexamples/\n└── demo.html                        # 零依赖最小示例（双击即看）"},{"language":"bash","snippet":"git clone git@github.com:huiyonghkw/hekouwang-yandu-deck-skill.git ~/.claude/skills/hekouwang-yandu-deck-skill"},{"language":"css","snippet":".deck-toolbar {\n  padding-bottom: max(12px, env(safe-area-inset-bottom));\n  padding-left: max(16px, env(safe-area-inset-left));\n  padding-right: max(16px, env(safe-area-inset-right));\n}"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: hekouwang-yandu-deck-skill\nslug: hekouwang-yandu-deck-skill\ndisplayName: 演读 DECK 产线与发布\nsummary: Immersive keynote-style HTML deck publisher — flip pages, auto-play, Cloudflare Pages. yandu-deck / hekouwang.pages.dev.\nlicense: MIT\nhomepage: https://github.com/huiyonghkw/hekouwang-yandu-deck-skill\nversion: 1.3.2\ndescription: >\n  会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。\n  当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。\n  触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - Edit\n  - Glob\n  - Grep\n  - AskUserQuestion\n---\n\n# 演读 DECK · 沉浸式演示产线与发布\n\n> 「演读 DECK」= 会勇禾口王的AI笔记出品的一款**沉浸式阅读产品**：介于长文和视频之间的第三种读法——一屏一镜、方向键/空格/点击翻页、能自动播放，把一个复杂主题安静完整地讲给你看。\n> 线上：**https://hekouwang.pages.dev** ｜ 与图文产线 `hekouwang-content-factory-skill` 配套（那是出文章/贴图/视频，这是把内容做成翻页演示 + 发布）。\n\n## 0. 系统在哪（先认这个）\n\n发布系统是项目里一个**自包含目录** `<项目根>/演读DECK/`：\n\n```\n演读DECK/\n├── publish.py       # 发布脚本：构建 dist/ → 部署 CF Pages（零三方依赖，仅标准库 + 一个子集化 venv）\n├── home.html        # 首页源（改首页改这个；dist/ 每次构建会清空，别在里面改）\n├── wrangler.toml    # CF Pages 配置 + D1 绑定（留言板用；不做留言板可删）\n├── schema.sql       # 留言板 D1 表结构\n├── functions/api/comments.js   # 留言板后端（Pages Functions，按目录约定生效）\n├── fonts/src/       # 字体源：思源黑 NotoSansSC-{400,500,700,900}.woff2 + 宋 -700 + Anthropic Sans/Mono + Mozilla VF\n├── fonts/cache/     # 子集化产物缓存（无字体源/无 venv 时回退）\n├── tools/fenv/      # 子集化 venv(fonttools+brotli)；移动会失效，丢了重建\n├── dist/            # 构建产物 = 部署目录（可整删重生）\n└── README.md\n```\n\n> ⚠️ **上面这套是「真身」，本 skill 里的是可移植副本**。日常在项目里改的是真身；**改完跑 `bash scripts/sync-from-harness.sh <演读DECK路径>` 同步回 skill**，否则副本很快过时。\n\n本 Skill 按官方约定分目录带了**可移植副本**（新项目落地时拷过去）：\n- `assets/templates/` — `deck-engine-米白.html`（⭐默认）/ `deck-engine-V6焰彩白.html`（国标）/ `deck-engine-暖黑.html`（仅维护存量）、`home.html`（首页源）、`wrangler.toml` + `schema.sql`（留言板，**database_id 是占位符，落地填自己的**）\n- `scripts/publish.py`（发布脚本）、`scripts/sync-from-harness.sh`（真身→副本单向同步）、`assets/functions/api/comments.js`（留言板后端）\n- `references/换肤-token-flip.md`（换肤）、`references/留言板-D1.md`（留言板）、`references/mobile-and-comments.md`（移动端 safe-area / 留言板开关 / 视频交叉引用）、`references/系统说明.md`（**落地 README 模板**，拷进 `演读DECK/README.md` 给人看）、`examples/demo.html`（零依赖最小示例）\n\n> ⚠️ **落地时 `publish.py` 与 `home.html` 必须同目录**（`publish.py` 用 `SELF/home.html` 找首页源）；`functions/` 要放成 `演读DECK/functions/api/comments.js`。\n> ⚠️ 副本里 **`CF_BEACON_TOKEN` 与 `wrangler.toml` 的 database_id 都留空/占位**——落地新站时填自己的，别沿用他人的（否则流量统计报到别人面板、留言写进别人的库）。\n\n## 1. 把文章做成「演示版 deck」⭐ 核心\n\n一篇 V2 文章 → 一屏一镜的 keynote。**零依赖（纯 CSS + 原生 JS，不引 GSAP/外链，国内/CF 都快）。** 沿用源文章的视觉（默认米白，国标走 V6 焰彩白，见 第1.4节）、字体、grain/mesh/frame/幽灵章节号。\n\n### 1.1 引擎（照抄模板，别重写）\n\n样板（**默认拷米白**，选哪套见 第1.4节"},{"path":"README.md","content":"# hekouwang-yandu-deck-skill · 演读 DECK\n\n**中文** · [English](README.en.md)\n\n> GitHub: [https://github.com/huiyonghkw/hekouwang-yandu-deck-skill](https://github.com/huiyonghkw/hekouwang-yandu-deck-skill)\n\n会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。\n\n把一篇文章/选题做成**一屏一镜、可翻页、能自动播放**的 keynote 演示版网页（**暖黑** / **米白** 两套主色），自托管字体（思源黑/宋子集化 + Anthropic 打包、零 CDN、preload 治 FOUT），并一键发布到 Cloudflare Pages。\n\n线上样例：**https://hekouwang.pages.dev**\n\n## 30 秒验收\n\n```bash\nopen examples/demo.html                              # 零依赖最小示例\nbash scripts/sync-from-harness.sh <path/to/演读DECK>  # 真身→副本同步\npython3 scripts/publish.py --help                    # 发布脚本可用性\n```\n\n## 免费 / 付费\n\n| | 免费（本仓库） | 付费增值 |\n|---|---|---|\n| 引擎模板 | `deck-engine-米白/V6/暖黑` + `demo.html` | 定制系列视觉 / 内容产线 |\n| 发布 | `publish.py` + CF Pages 配方 | `hekouwang-content-factory` 授权 |\n| 联系 | GitHub Issue | **@huiyonghkw** |\n\n## 示例动画版本 / Demo\n\n最快的体验方式 —— 双击打开 **[`examples/demo.html`](examples/demo.html)**：一个**自包含、零依赖、系统字体**的最小示例，直接 `file://` 打开就能看引擎怎么动（翻页 / 自动播放 / 柱子生长 / 数字滚动 / 折线描线 / 卡片错峰）。\n\n| 封面（数字滚动 + 标题渐变） | 流程屏（节点淡入 + 箭头描线 + stat 弹入） |\n|---|---|\n| ![cover](docs/demo-cover.png) | ![flow](docs/demo-flow.png) |\n\n- **在线完整版（可翻页/自动播放）**：\n  - 首页：<https://hekouwang.pages.dev>\n  - 暖黑系列：<https://hekouwang.pages.dev/suanli/ep01>（`#3` 直达第 3 屏）\n  - 米白系列：<https://hekouwang.pages.dev/toushi/ep01>\n- `assets/templates/deck-engine-暖黑.html` / `deck-engine-米白.html` 是两套**完整引擎模板**（需起本地服务器看字体：`python3 -m http.server`）。\n\n## 依赖\n\n| 依赖 | 关系 | 说明 |\n|---|---|---|\n| **`hekouwang-content-factory`** ⭐ | **内容来源（强依赖）** | 本 Skill 是「**把内容做成翻页演示 + 发布**」的一半；**另一半（生成文章 HTML、视觉规范 V1/V2/V3、去 AI 味、合规红线）在 `hekouwang-content-factory`**。演示版的源 HTML、配色 token、字体方案都源自它。**⚠️ `hekouwang-content-factory` 是付费 Skill**（GitHub 上为 **PRIVATE 私有仓库，非授权无法 clone / 获取**；需向作者 @huiyonghkw 获取授权），本仓库不含其内容。 |\n| Python 3 + `fonttools`+`brotli` | 字体子集化 | 仅发布时需要（`tools/fenv` venv，见 `SKILL.md`）。没有则回退用 `fonts/cache/` 已切好的子集。 |\n| `wrangler`（Cloudflare） | 部署 | `publish.py` 调它发到 CF Pages；首次需 `wrangler login`。 |\n| Anthropic Sans/Mono woff2 | 拉丁/代码字体 | 来自 `hekouwang-content-factory`（自用/演示授权）。缺失则拉丁字自动回退系统字。 |\n\n> 只想用**引擎**（不要内容产线）：直接拷 `assets/templates/deck-engine-*.html` 当模板填内容即可，那部分零依赖、可独立使用。\n\n## 这是什么\n\n这是一个 [Claude Code](https://claude.com/claude-code) **Skill**，按官方 `anthropics/skills` 约定分目录组织。`SKILL.md` 是给 Agent 读的方法说明；`scripts/` `assets/` `references/` `examples/` 是可直接拷用的脚本、模板、文档与示例。\n\n```\nSKILL.md                              # 方法 + 触发词 + 防踩坑（Agent 入口）\nscripts/\n└── publish.py                       # 构建 dist/ → 部署 CF Pages（零三方依赖）\nassets/templates/\n├── deck-engine-暖黑.html             # 演示版引擎模板（数据/财经/科普暗调）\n├── deck-engine-米白.html             # 演示版引擎模板（人文/方法论亮调）\n└── home.html                        # 首页模板\nreferences/\n└── 系统说明.md                       # 系统说明文档\nexamples/\n└── demo.html                        # 零依赖最小示例（双击即看）\n```\n\n> 落地铁律：`scripts/publish.py` 与 `assets/templates/home.html` 拷进项目时必须放进同一个 `演读DECK/`（publish.py 用 `SELF/home.html` 找首页源）。\n\n## 安装\n\n把本仓库放进 `~/.claude/skills/hekouwang-yandu-deck-skill"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn73qd1gcmjr446mwcbdxef70x82vxcw\",\n  \"slug\": \"hekouwang-yandu-deck-skill\",\n  \"version\": \"1.3.2\",\n  \"publishedAt\": 1786534646031\n}"},{"path":"references/mobile-and-comments.md","content":"# 移动端 safe-area · 留言板开关 · 视频交叉引用\n\n## 移动端 safe-area\n\n演示引擎默认 `viewport-fit=cover`，全屏翻页时顶底栏要留 **safe-area**：\n\n```css\n.deck-toolbar {\n  padding-bottom: max(12px, env(safe-area-inset-bottom));\n  padding-left: max(16px, env(safe-area-inset-left));\n  padding-right: max(16px, env(safe-area-inset-right));\n}\n```\n\n- iOS 刘海/底条：没写 `env(safe-area-inset-*)` 时，翻页按钮和进度条会被挡。\n- 横屏演示：左右 inset 同样要留，别只照顾 bottom。\n- 验收：真机 Safari「添加到主屏幕」全屏翻 3 页，拇指区按钮必须可点。\n\n## 留言板（可选子系统）\n\n默认 **hekouwang.pages.dev 线上开着**；新站或纯静态演示可关：\n\n1. 删或移走 `演读DECK/functions/`（Pages Functions 不再挂载）\n2. `wrangler.toml` 里去掉 `[[d1_databases]]` 绑定\n3. `home.html` / 引擎模板里去掉留言入口 DOM 与 fetch 调用\n\n排错见 `references/留言板-D1.md`；**database_id 必须是自己的**，副本里是占位符。\n\n## 与 HyperFrames 视频产线\n\n- **演读 DECK** = 一屏一镜 **可翻页 HTML**，适合长文拆解、国标系列、教程跟读。\n- **HyperFrames 视频** = 同选题的 **ffmpeg 成片**（harness 内 `EP-*/video/` 或动画 Skill）。\n- 同一 EP 可两条线并存：文章母本 → 演示版 HTML（本 skill）+ 可选视频目录；**不要**在 deck 引擎里引外链视频或 `Date.now()`/`Math.random()`（与 harness `AGENTS.md` 视频红线一致）。"},{"path":"references/换肤-token-flip.md","content":"# 演读 DECK · 换肤 = token-flip（不是重做）\n\n给**已有 deck** 换主色时用这套。核心认知：两套主色的 `:root` **逐行结构完全一致、只有值不同**——所以换肤是一次**机械的 token 值映射**，引擎 CSS/JS 一字不动，内容一字不动。别重写、别让 subagent \"参照着做一版\"。\n\n> 当前口径见 SKILL.md 第1.4节：**米白 = 全站默认**，国标走 V6 焰彩白，**暖黑/焰彩黑是存量历史态**——本文档现在主要服务于「存量黑版 → 米白」的收敛。\n>\n> 现成脚本：**`scripts/flip-暖黑到米白.py`**（映射抽自引擎模板 · 单遍替换 · 内建未覆盖色守卫 · 先读后写）。用法 `python3 scripts/flip-暖黑到米白.py <deck.html>...`；退出码 2 = 有未覆盖色，按 第2.6节 人工判断后再跑。\n\n## 0. 动手前（这五步省过一次 9 期全毁）\n\n1. **先查 git 有没有现成的目标态**——见 第0.5节，能取回就别转换。\n2. **先 cp 备份**要改的文件。\n3. flip 脚本**必须先读后写**（见 第3节 第 1 条，这是最贵的坑）。\n4. flip 后 `stat -f%z` 查**每个文件大小非 0**。\n5. flip 后跑**全谱残留 grep**（第2节），**=0 才算过**。\n\n## 0.5 先问一句：git 里是不是躺着现成的？⭐ 省一整轮\n\n演读 DECK 的 deck HTML **都在 git 里**（只有 `演读DECK/publish.py` 被 `.gitignore` 的 `*.py` 排除）。整站换过肤，就意味着**换肤前的版本还在历史里**。要换回某个旧主色时，先查：\n\n```bash\ngit log --oneline --all -- <deck路径>                    # 哪次提交换的肤\ngit show <flip提交>^:<deck路径> | grep -oE -- '--bg:#[0-9a-f]*'   # 换肤前是什么色\ngit log --oneline <flip提交>..HEAD -- <deck路径>          # 换肤后还改过内容吗（0 = 可安全取回）\n```\n\n**换肤后 0 次提交 = 直接 `git show <flip提交>^:<路径>` 取回，精确、零转换风险**，比任何 flip 脚本都可靠。\n2026-07-15 实战：偷师 4 期换肤前本就是米白、之后 0 改动 → 直接取回，全谱残留 grep=0 一次过；而算力 5 期换肤前是**暖黑**（不是米白），取回只能拿到暖黑，仍需一轮真转换。**先查再动，别默认要写脚本。**\n\n## 0.6 ⚠️ 跨设计系统 ≠ 换肤，别硬套\n\n本文档的 flip 只适用于**同一套设计系统的明暗两极**（V6焰彩白↔V6焰彩黑、暖黑↔米白——后两者同为 V2 黏土系统）。\n\n**焰彩黑 → 米白 是跨系统**：主色紫 `#a855f7` vs 黏土 `#c15f3c`、字体 Mozilla VF vs Anthropic Sans，V6 的焰橙/焰粉在 V2 里根本没有对应色。硬套 token-flip 会出四不像。跨系统要走「先 git 取回同系统版本，再同系统 flip」，或老老实实重做。\n\n## 1. 已验证的映射\n\n### 1.1 V6 焰彩：白 ↔ 黑（两向互为精确逆运算）\n\n| 语义 | 焰彩白 | 焰彩黑 |\n|---|---|---|\n| 底 | `#fbfaff` | `#170a30` |\n| surface | `#ffffff` / `#f4eefc` / `#efe7fb` | `#241246` / `#231044` / `#2c1552` |\n| 正文字 | `#1c0b3e` | `#f3eefe` |\n| 主紫 | `#7c3aed` | `#a855f7` |\n| 次紫 | `#6d28d9` | `#c084fc` |\n| 蓝 | `#4f6ef0` | `#7c9bff` |\n| 金 | `#c8620a` / `#e07a1a` | `#ffb454` / `#f0a13a` |\n| warn | `#e0304f` | `#ff5c78` |\n| 线 | `rgba(28,11,62,…` | `rgba(255,255,255,…` |\n| 紫辉光 | `rgba(124,58,237,…` | `rgba(168,85,247,…` |\n| grain | `multiply` `.02` | `screen` `.05` |\n| body class | `class=\"light\"` | `class=\"dark\"` |\n\n**黑白通用、不翻**：焰橙 `#ff8a3d`、焰粉 `#ff4f8b`、`--ok`、`--teal`。\n**演示版与首页的 token 值不同，各写一份映射**，别共用一张表。\n\n### 1.2 暖黑 / 米白（旧两套）\n\n暖黑 `#161514` + 黏土 `#e08a5f` + 石板蓝 `#8fa6bd`；米白 `#faf9f5` + 黏土 `#c15f3c`。\n亮底适配：网格线→极淡深色、卡片靠 `--shadow` 不靠辉光、幽灵号深色 `opacity:.05`、`.grain`→`multiply`。\n\n## 2. 三条验收（缺一条都不算换完）\n\n1. **全谱残留 grep = 0**：拿**旧主色整套调色板**（不只是 `--bg`）去 grep，包括 SVG 内联色。半成品最爱漏的就是图表里的 `#e08a5f`（暖黑黏土）、`#8fa6bd`（石板蓝）。有残留 → 补一轮「旧色→新色」映射再跑。\n2. **封面截图**肉眼过一眼。\n3. **线上 curl 验 token**：跟随 308（`/suanli/ep04.html` → `/suanli/ep04`），确认 `--bg` 和 `class` 是新值。\n\n## 2.5 映射表从模板里抽，别手编；且必须**单遍同时替换** ⭐\n\n**映射的唯一真相源 = 两套引擎模板的 `:root` 逐 token 对照**（同一个引擎、两个主题，key 一一对应）。用脚本 diff 出来，别凭记忆写色号：\n\n```python\n# 剥掉 /* 注释 */ 再解析 :root，逐 key 比对 deck-engine-暖黑 vs deck-engine-米白\n```\n\n实测暖黑 33 token / 米白 26 token，其中 **20 个值不同**（`--bg/--surface*/--line*/--text*/--read/--hot*/--hl0/--cool*/--ochre*/--warn`），4 个通用不翻（`--font/--serif/--mono/--brand`）；另 `--m-*`（9 张插画）暖黑独有、**`stroke='%23000'` "}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。 当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言板（Cloudflare Pages Functions + D1）加装/排错 时使用。 触发词：演读DECK / 演读 deck / 演示版 / 翻页演示 / keynote 网页 / 沉浸式阅读 / 发布到 hekouwang / 加一期演示 / 演示版引擎 / deck换肤 / 焰彩deck / V6焰彩白 / token-flip / deck留言板。 Skill: hekouwang-yandu-deck-skill Owner: huiyonghkw Summary: 会勇禾口王的AI笔记 ·「演读 DECK」沉浸式演示产线与发布 Skill。把一篇文章/选题做成「一屏一镜、可翻页、能自动播放」的 keynote 演示版网页（默认米白引擎，国标系列走 V6 焰彩白；暖黑/焰彩黑为存量历史态），并自托管字体、发布到 Cloudflare Pages（hekouwang.pages.dev）。 当需要：① 把某篇文章/某期内容做成「演示版 / 演读 DECK / 翻页演示 / keynote 网页 / 沉浸式阅读页」；② 给「演读 DECK」站加一期演示、加一个系列、改首页；③ 给某个系列换主色/换肤（白↔黑 token-flip、切 V6 焰彩）；④ 发布/更新 hekouwang.pages.dev；⑤ 自托管字体、解决首屏字重跳变(FOUT)、子集化思源字体；⑥ 站点留言","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1217,"uniquenessScore":49,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T13:52:47.144Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T13:52:47.144Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T16:04:12.942Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}