{"id":"e2b1a5df-d1be-4404-be93-51ded02e3efb","entityType":"agent","slug":"clawhub-edwardwason-xhs-crafter","name":"Xhs Crafter","canonicalUrl":"https://www.xpersona.co/agent/clawhub-edwardwason-xhs-crafter","canonicalPath":"/agent/clawhub-edwardwason-xhs-crafter","generatedAt":"2026-10-10T23:47:11.155Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T20:00:07.871Z","emptyReason":null},"description":"将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/... Skill: Xhs Crafter Owner: edwardwason Summary: 将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/... Tags: article:7.5.0, card:7.5.0, editorial:7.5.0, formatter:7.5.0, image:7.5.0, latest:7.8.0, markdown:7.5.0, publishing:7.5.0, swiss:7.5.0, wechat:7.5.0, xiaohongshu:7.5.0 Version history: v7.8.0 | 2026-07-15T04","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.3K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s177q4wcvafq6fzfkhk2g3cwth83y01d:xhs-crafter","sourceUrl":"https://clawhub.ai/edwardwason/xhs-crafter","homepage":"https://clawhub.ai/edwardwason/skills/xhs-crafter","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/edwardwason/xhs-crafter","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/edwardwason/skills/xhs-crafter","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":62,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T20:00:07.871Z","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-10T20:00:07.871Z","emptyReason":null},"stars":null,"forks":null,"downloads":1273,"packageName":null,"latestVersion":"7.8.0","tractionLabel":"1.3K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T20:00:07.871Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T20:00:07.871Z","lastCrawledAt":"2026-10-10T20:00:07.871Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T20:00:07.871Z","lastVerifiedAt":null,"highlights":[{"version":"7.8.0","createdAt":"2026-07-15T04:37:27.706Z","changelog":"xhs-crafter 7.8.0 - 語义明确化：图片三选一提示增加AI生图prompt可能包含文章主题/场景描述的说明，增强数据流披露（SKILL.md）。 - 优化图片来源顺序描述，明确Unsplash直链与AI生成的优先级比对。 - 文档与工作流描述强化，用词更精准，避免外部数据流误用。 - 细化敏感内容与外部API交互的风险提醒。 - 移除 skill-card.md，整洁文档结构。","fileCount":22,"zipByteSize":90742},{"version":"7.7.0","createdAt":"2026-07-15T03:26:03.647Z","changelog":"**核心行为披露和外部能力细分，权限与数据流写法全面升级**： - 明确标注：核心流程为本地 HTML 模板填充+Puppeteer 截图，不涉及 MD→HTML 编译，也不会出局域网 - 权限声明部分全面扩写，详细逐项披露所有本地/网络/子进程/文件/环境变量权限与用途 - 图片三选一门控规则收紧：若用户给出模糊同意，默认仅走本地图片（无外部请求），需明确选择才出网 - 新增 AI 生图 API（trae-api-cn）与 Unsplash 支持，并在权限/数据流中独立披露 - 所有可选外部能力均需用户独立明确同意，不再接受“都行”“全流程”模糊用语下的批量授权 - 移除 skill-card.md，完善文档结构与数据流风险提示","fileCount":22,"zipByteSize":90998},{"version":"7.6.0","createdAt":"2026-07-15T02:55:26.368Z","changelog":"**v7.6.0 summary:** 全面移除了所有外部字体依赖，实现了图片排版流程完全本地化，并强化了外部能力授权门控。 - 移除所有 Google Fonts CDN 引用，模板全部改为系统字体栈（Noto Serif SC/Source Han Serif/PingFang/Consolas），确保无外部字体加载，网络离线下也可渲染。 - 权限与用户同意门控调整：每项外部能力（如图片API搜索、飞书云盘）必须单独逐步征得用户明确同意，禁止\"流程全走\"等模糊授权。 - 更新隐私声明，强调所有渲染和产物彻底本地完成，新版默认全流程无网络依赖（除用户主动授权图片搜索/飞书同步）。 - 移除未再使用的 skill-card.md，文档和参考手册内容同步更新为新流程规范。 - 优化输出、模板与图片处理流程","fileCount":22,"zipByteSize":88161},{"version":"7.5.0","createdAt":"2026-07-15T01:47:04.023Z","changelog":"v7.5.0: revert over-engineering image-search.js + fix workflow.md legacy reference. Deleted image-search.js (introduced 5 new Findings). Removed all references. Fixed workflow.md legacy v7 dual-channel description. Added consent gate to workflow.md delivery.","fileCount":22,"zipByteSize":86580},{"version":"7.4.0","createdAt":"2026-07-15T01:27:13.142Z","changelog":"v7.4.0: ClawHub SkillSpector audit remediation. Fixed 17 Findings (Description-Behavior Mismatch + Context-Inappropriate Capability + Missing User Warnings). Added privacy declaration, 3 consent gates, permission table, SSRF allowlist, http.server bound to 127.0.0.1.","fileCount":23,"zipByteSize":89355},{"version":"7.3.1","createdAt":"2026-06-12T10:31:19.348Z","changelog":"xhs-crafter 7.3.1 更新日志 - 新增 docs/session-handoff.md 文档，完善会话交接说明。 - 调整/增强 assets/screenshot.js 截图相关逻辑。 - 更新 CHANGELOG.md 说明文件。 - 移除 skill-card.md，精简文档内容。","fileCount":23,"zipByteSize":81043},{"version":"7.3.0","createdAt":"2026-06-11T15:55:00.198Z","changelog":"xhs-crafter 7.3.0 - 新增与完善密度、节奏与图片规则在SKILL.md中的速查表，让关键版式与图片标准一目了然。 - 内容品类数量从11增加至13类，覆盖更丰富的场景，明示特殊/超界品类前置提醒。 - 强化自动验证（validate.js）：自检项由9项扩展至12项，新增对暗色页节奏、accent面积、封面封底图片背景的自动检查。 - 补充图片使用详细规范，包括图片本地化、唯一性校验、accent色块覆盖限制等。 - SKILL.md文档结构优化，规则分层更清晰，速查表结构便于查阅与落实执行标准。","fileCount":22,"zipByteSize":75317},{"version":"7.2.0","createdAt":"2026-06-11T14:20:10.872Z","changelog":"xhs-crafter 7.2.0 更新摘要 - 自动验证流程新增2项：标题一致性和满铺图页标题颜色，`assets/validate.js` 现共9项自动检查。 - 参考品类总数增至11类，参考文档与品类映射说明同步补全。 - 精简项目文档：移除冗余（release-body.json、skill-card.md），合并或清晰化说明内容。 - 明确参考文件用途描述，对照各类风格与技术规范补充。 - 更新字号规则、版式节奏、页面密度等关键规范，使说明更直观完整。","fileCount":22,"zipByteSize":73296}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s177q4wcvafq6fzfkhk2g3cwth83y01d:xhs-crafter","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-edwardwason-xhs-crafter/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/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-10T23:47:11.151Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-edwardwason-xhs-crafter/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-10T20:00:07.871Z","emptyReason":null},"readme":"Skill: Xhs Crafter\n\nOwner: edwardwason\n\nSummary: 将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/...\n\nTags: article:7.5.0, card:7.5.0, editorial:7.5.0, formatter:7.5.0, image:7.5.0, latest:7.8.0, markdown:7.5.0, publishing:7.5.0, swiss:7.5.0, wechat:7.5.0, xiaohongshu:7.5.0\n\nVersion history:\n\nv7.8.0 | 2026-07-15T04:37:27.706Z | auto\n\nxhs-crafter 7.8.0\n\n- 語义明确化：图片三选一提示增加AI生图prompt可能包含文章主题/场景描述的说明，增强数据流披露（SKILL.md）。\n- 优化图片来源顺序描述，明确Unsplash直链与AI生成的优先级比对。\n- 文档与工作流描述强化，用词更精准，避免外部数据流误用。\n- 细化敏感内容与外部API交互的风险提醒。\n- 移除 skill-card.md，整洁文档结构。\n\nv7.7.0 | 2026-07-15T03:26:03.647Z | auto\n\n**核心行为披露和外部能力细分，权限与数据流写法全面升级**：\n\n- 明确标注：核心流程为本地 HTML 模板填充+Puppeteer 截图，不涉及 MD→HTML 编译，也不会出局域网\n- 权限声明部分全面扩写，详细逐项披露所有本地/网络/子进程/文件/环境变量权限与用途\n- 图片三选一门控规则收紧：若用户给出模糊同意，默认仅走本地图片（无外部请求），需明确选择才出网\n- 新增 AI 生图 API（trae-api-cn）与 Unsplash 支持，并在权限/数据流中独立披露\n- 所有可选外部能力均需用户独立明确同意，不再接受“都行”“全流程”模糊用语下的批量授权\n- 移除 skill-card.md，完善文档结构与数据流风险提示\n\nv7.6.0 | 2026-07-15T02:55:26.368Z | auto\n\n**v7.6.0 summary:**  \n全面移除了所有外部字体依赖，实现了图片排版流程完全本地化，并强化了外部能力授权门控。\n\n- 移除所有 Google Fonts CDN 引用，模板全部改为系统字体栈（Noto Serif SC/Source Han Serif/PingFang/Consolas），确保无外部字体加载，网络离线下也可渲染。\n- 权限与用户同意门控调整：每项外部能力（如图片API搜索、飞书云盘）必须单独逐步征得用户明确同意，禁止\"流程全走\"等模糊授权。\n- 更新隐私声明，强调所有渲染和产物彻底本地完成，新版默认全流程无网络依赖（除用户主动授权图片搜索/飞书同步）。\n- 移除未再使用的 skill-card.md，文档和参考手册内容同步更新为新流程规范。\n- 优化输出、模板与图片处理流程\n\nv7.5.0 | 2026-07-15T01:47:04.023Z | user\n\nv7.5.0: revert over-engineering image-search.js + fix workflow.md legacy reference. Deleted image-search.js (introduced 5 new Findings). Removed all references. Fixed workflow.md legacy v7 dual-channel description. Added consent gate to workflow.md delivery.\n\nv7.4.0 | 2026-07-15T01:27:13.142Z | user\n\nv7.4.0: ClawHub SkillSpector audit remediation. Fixed 17 Findings (Description-Behavior Mismatch + Context-Inappropriate Capability + Missing User Warnings). Added privacy declaration, 3 consent gates, permission table, SSRF allowlist, http.server bound to 127.0.0.1.\n\nv7.3.1 | 2026-06-12T10:31:19.348Z | auto\n\nxhs-crafter 7.3.1 更新日志\n\n- 新增 docs/session-handoff.md 文档，完善会话交接说明。\n- 调整/增强 assets/screenshot.js 截图相关逻辑。\n- 更新 CHANGELOG.md 说明文件。\n- 移除 skill-card.md，精简文档内容。\n\nv7.3.0 | 2026-06-11T15:55:00.198Z | auto\n\nxhs-crafter 7.3.0\n\n- 新增与完善密度、节奏与图片规则在SKILL.md中的速查表，让关键版式与图片标准一目了然。\n- 内容品类数量从11增加至13类，覆盖更丰富的场景，明示特殊/超界品类前置提醒。\n- 强化自动验证（validate.js）：自检项由9项扩展至12项，新增对暗色页节奏、accent面积、封面封底图片背景的自动检查。\n- 补充图片使用详细规范，包括图片本地化、唯一性校验、accent色块覆盖限制等。\n- SKILL.md文档结构优化，规则分层更清晰，速查表结构便于查阅与落实执行标准。\n\nv7.2.0 | 2026-06-11T14:20:10.872Z | auto\n\nxhs-crafter 7.2.0 更新摘要\n\n- 自动验证流程新增2项：标题一致性和满铺图页标题颜色，`assets/validate.js` 现共9项自动检查。\n- 参考品类总数增至11类，参考文档与品类映射说明同步补全。\n- 精简项目文档：移除冗余（release-body.json、skill-card.md），合并或清晰化说明内容。\n- 明确参考文件用途描述，对照各类风格与技术规范补充。\n- 更新字号规则、版式节奏、页面密度等关键规范，使说明更直观完整。\n\nv7.1.1 | 2026-06-11T12:03:12.726Z | user\n\nEmbed font size cheat sheet in SKILL.md Step 3, fix h-xl 96px to 110px, update README with 11 categories\n\nv7.1.0 | 2026-06-10T23:14:21.968Z | user\n\nType scale +15pct for mobile readability, background systems, validate.js, hero title color fix, category cookbook 11 categories, font weight iron rule\n\nv7.0.2 | 2026-06-10T14:55:11.164Z | user\n\nRemove .claude-plugin directory to fix skill vs plugin detection. All standard repo files now in place.\n\nv7.0.1 | 2026-06-10T14:12:00.425Z | user\n\nFix: add README.md, .gitattributes for UTF-8, fix repo description encoding\n\nv7.0.0 | 2026-06-10T13:58:23.927Z | user\n\nv7: Editorial/Swiss dual-mode, 10 themes, 28 layouts, rhythm system, density rules, Feishu sync\n\nArchive index:\n\nArchive v7.8.0: 22 files, 90742 bytes\n\nFiles: assets/screenshot.js (6937b), assets/template-editorial-card.html (17998b), assets/template-swiss-card.html (14289b), assets/validate.js (11444b), CHANGELOG.md (16828b), docs/session-handoff.md (11317b), README.md (14099b), references/background-systems.md (8239b), references/category-cookbook.md (14094b), references/components.md (18947b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (10025b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (5018b), skill-card.md (2494b), SKILL.md (21310b), _meta.json (130b)\n\nFile v7.8.0:SKILL.md\n\n---\nname: \"xhs-crafter\"\ndescription: \"将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/Unsplash图库API搜索（发送搜索关键词到外部API）；(2)AI生图API（发送prompt到trae-api-cn，仅限TRAE内部环境）；(3)飞书云盘上传（上传生成的PNG+txt到飞书服务器）。Invoke when用户明确说'xhs-crafter排版'、'用xhs-crafter转图片'、'公众号贴图排版'、'小红书图文卡片'。Do NOT use for原创写作、纯文字排版、视频制作、用户只提到MD文件路径但未明确要求图片排版。\"\nslug: \"xhs-crafter\"\ndisplayName: \"XHS Crafter\"\nversion: \"7.8.0\"\nsummary: \"将MD文章排版为3:4比例精美图片+压缩文字稿，用于公众号/小红书贴图发布\"\nlicense: \"MIT-0\"\n---\n\n# XHS Crafter — 文章转图片卡片\n\n## 任务\n将用户提供的MD文章内容，排版为多张3:4比例(1080×1440)的精美HTML页面，截图为PNG，压缩为≤1000字文字稿，文件夹交付。不做原创写作，不做视频，不做纯文字排版。\n\n## 隐私与数据流声明（用户须知）\n\n**本技能的数据流边界**：\n- **本地处理（默认）**：MD文本→HTML组装→PNG截图→本地文件夹交付。所有文章内容、图片素材、生成产物默认仅在本地处理，不上传任何外部服务\n- **可选外部能力（需用户明确同意）**：\n  - 图片搜索：调用Pexels/Pixabay API搜索免费图库照片（仅搜索词和图片下载，不上传文章内容）\n  - 飞书云盘同步：将生成PNG+文字稿上传到用户飞书云盘（需用户明确同意，且文章内容可能包含未发布素材）\n- **外部网络依赖**：v7.6 已移除 Google Fonts CDN 引用，模板使用系统字体回退栈（Noto Serif SC / Source Han Serif SC / Songti SC / PingFang SC / Consolas 等），完全本地渲染，无外部字体加载\n\n**用户警告**：\n- ⚠️ 如果文章包含未发布/敏感/专有内容，请谨慎使用飞书云盘同步功能——上传即意味着内容离开本地\n- ⚠️ 图片搜索会将搜索关键词发送到Pexels/Pixabay服务器，但不会发送文章原文\n- ⚠️ 飞书云盘同步需要用户已登录lark-cli，且目标文件夹由用户飞书账号持有\n\n**权限声明**（v7.7 完整披露所有行为）：\n\n| 能力类别 | 是否使用 | 说明 |\n|---------|---------|------|\n| 网络访问 | ✅ | **核心行为**：启动本地 127.0.0.1 HTTP server 加载预存 HTML 模板供 Puppeteer 截图（不出局域网）。**可选外部访问**（每项需用户独立同意）：Pexels/Pixabay/Unsplash 图库 API 搜索；trae-api-cn AI 生图 API（仅限 TRAE 内部环境）；飞书云盘上传 |\n| 文件读写 | ✅ | 读 MD 文章 + 预存 HTML 模板（assets/template-*.html）；写 output/ 目录 PNG+txt；写 `$env:TEMP` 交付文件夹；可选下载外部图片到 assets/ 目录（受 ALLOWED_HOSTS 白名单限制） |\n| 环境变量 | ✅ | `PEXELS_API_KEY`、`PIXABAY_API_KEY`（图库搜索，可选）；`CHROME_PATH`（可选，浏览器路径） |\n| subprocess | ✅ | `python -m http.server --bind 127.0.0.1`（本地回环 HTTP server，截图用）；`node assets/screenshot.js`（Puppeteer 截图）；`node assets/validate.js`（自动验证）；`curl.exe`（可选，下载外部图片）；`explorer.exe`（打开交付文件夹） |\n| 外部 API | ✅ | Pexels/Pixabay/Unsplash 图片搜索 API（可选，发送搜索关键词）；trae-api-cn.mchost.guru AI 生图 API（可选，发送 prompt，仅限 TRAE 内部环境）；飞书 lark-cli drive API（可选云盘同步，上传 PNG+txt） |\n\n> ⚠️ **核心行为说明**：本技能的核心能力是 **本地 HTML 模板填充 + Puppeteer 截图渲染**，不是 MD→HTML 编译管道。MD 内容由 AI 读取后填入预存的 HTML 模板（assets/template-editorial-card.html 或 template-swiss-card.html），然后启动本地 HTTP server 加载该 HTML 供 Puppeteer 截图为 PNG。核心流程不涉及外部网络访问。\n\n## 输出格式\n\n```\n<桌面>/<slug>公众号素材/\n├── p1-cover.png\n├── p2-xxx.png\n├── ...\n├── pN-finale.png\n└── <slug>-文字稿.txt   # ≤1000字压缩文字\n```\n\n## 工作流：5步（默认本地全自动，外部能力需用户同意）\n\n**核心原则**：用户给MD，直接出本地文件夹。Step 1-2在脑内完成（不输出长文规划），Step 3-5连续执行不等待用户确认。\n\n**外部能力同意门控**（2道，仅在触发外部网络/云盘时询问，本地渲染不询问。每道门控独立询问，不批量授权）：\n1. **图片搜索门控**（Step 1，用户无图且需背景图时）：询问是否调用Pexels/Pixabay API搜索\n2. **飞书同步门控**（Step 5，本地交付完成后）：询问是否上传到飞书云盘\n\n> ⚠️ **同意门控铁律**：每道门控必须独立询问，不得因用户说\"按流程走一遍\"、\"全流程\"、\"都行\"等模糊措辞而批量授权多个外部能力。用户必须对每个外部能力单独明确同意（\"是\"或具体指定）。\n\n### Step 1: Intake — 识别品类（脑内完成，不输出）\n从MD内容自动推断：\n- **内容品类**: 读 `references/category-cookbook.md` 路由。13个品类：商业/科技分析、职场/干货、旅行/生活方式、教程/工具、影视/读书、游戏、美食、彩妆、穿搭、家居、健身、情感、推荐。超出范围的品类（梦核/氛围感装饰风、Y2K/千禧辣妹、纯摄影展示）必须在设计前明确告知用户\n- **目标平台**: 默认小红书3:4（除非用户指定公众号）\n- **用户图片**: (a)用户指定截图文件夹路径；(b)解析MD中 `![描述](路径)` 和 `[🖼️配图建议：xxx]` 标记\n- **图片三选一门控**（仅在用户无图时触发，一次性提问不反复追问）：\n  ```\n  这篇我需要 1-2 张图。三种走法：\n  A. 你自己有照片/截图，传给我（推荐——最不\"AI感\"，完全本地处理）\n  B. 我去 Pexels/Pixabay 帮你找（⚠️ 会将搜索词发送到外部API，但不上传文章原文）\n  C. 用 AI 生成（⚠️ 会将生图prompt发送到trae-api-cn.mchost.guru生图API，prompt可能含文章主题/场景描述，仅限TRAE内部环境）\n  ```\n  推荐 A。用户必须明确选择 A/B/C 之一（如\"用B\"、\"搜图\"、\"AI生成\"）；若用户说\"都行\"/\"你看着办\"等模糊回答，默认走 A（完全本地，无外部数据流），不再追问\n- **仅在品类无法推断时才问用户**，否则直接进入Step 2\n\n### Step 2: Content Plan — 内容规划（脑内完成，不输出）\n读 `references/content-planning.md`，完成：\n- 压缩阶梯：核心论点1句 → 读者承诺 → 4-8个分论点 → 页面钩子 → 正文片段\n- 页面角色分配：7页组图至少5种不同形态\n- **页面节奏规划**：为每页标注明暗(Light/Dark)、氛围强弱(Strong/Subtle)、版式类型，读 `references/portrait-fill.md` 的\"Three-Layer Rhythm System\"\n- 封面钩子：用具体承诺而非空洞口号\n- 页数指导：600-1000字→5-7图，1000-1800字→7-9图\n- **5页及以上：封面和封底都必须有图片背景**\n\n### Step 3: Compose — 组装HTML（直接执行）\n- 拷贝种子模板：Editorial→ `assets/template-editorial-card.html`；Swiss→ `assets/template-swiss-card.html`\n- 设置 `data-theme` 或 `data-accent` 属性切换主题\n- 在 `<!-- POSTERS_HERE -->` 处添加页面\n\n**字号速查表（必须严格遵循，不得自行调整）**：\n\n| Role | Class | Size | Weight | Family | 用途 |\n|------|-------|------|--------|--------|------|\n| Display | `.h-display` | 136px | 500 | serif-zh | 封面/封底主标题 |\n| Section title | `.h-xl` | 110px | 500 | serif-zh | 内容页主标题（必须统一） |\n| Mid title | `.h-md` | 60px | 500 | serif-zh | 次级标题/数据页标题 |\n| Subtitle | `.h-sub` | 46px | 400 italic | serif-en | 英文副标题 |\n| Pull quote | `.pullquote` | 80px | 500 italic | serif-zh | 引言页大字引语 |\n| Lead | `.lead` | 34px | 400 | serif-zh | 导语/段落首句 |\n| Body | `.body` | 32px | 400 | serif-zh | 正文段落 |\n| Kicker | `.kicker` | 26px | 500 | mono | 页面顶部标签 |\n| Meta | `.meta` | 24px | 500 | mono | 页面底部注释 |\n| Label | `.label` | 24px | 500 | mono | 数据标签 |\n| Stat number | `.stat-nb` | 72px | 500 | serif-zh | 大数字 |\n| Step title | `.step-title` | 34px | 500 | serif-zh | 流程步骤标题 |\n| Step desc | `.step-desc` | 28px | 400 | serif-zh | 流程步骤描述 |\n| Ledger title | `.ledger-title` | 30px | 500 | serif-zh | 表格行标题 |\n| 辅助文字 | — | 22px | 500 | mono | stat-label/stat-unit/ledger-note/step-nb/callout-src/issue-strip |\n\n**字号铁律**：\n1. **内容页主标题必须统一用 `.h-xl` 110px**——不得混用 `.h-md`，标题太长拆行而非降级\n2. **封面/封底主标题用 `.h-display` 136px**——比内容页大24%，形成\"书挡\"层级\n3. **满铺图页标题颜色必须 `#ffffff` + `text-shadow`**——禁止 `#ece2cf`（与暖调背景太接近）\n4. **字重\"越大越轻\"**：≥110px用500，60-80px用500，32-46px用400，24-26px用500\n5. **任何文字不得低于18px**\n\n**节奏速查表（必须严格遵循）**：\n\n| 规则 | 要求 | 违反后果 |\n|------|------|---------|\n| 暗色页数量 | 5页+至少1页Midnight Ink，7页+至少1-2页 | 全light=单调 |\n| 暗色页位置 | 引言页或结尾页最佳 | 中间也行，但不可相邻 |\n| 暗色页相邻 | 禁止！2个暗色页必须隔至少1个light页 | 相邻=对比抵消 |\n| 氛围强度 | 封面/引言/封底=strong，数据/清单=subtle，正文=medium | 全同一强度=死板 |\n| 版式重复 | 禁止连续2页用同一种版式骨架 | 密集ledger后接宽松essay |\n| 首尾图框 | 5页+封面和封底都必须有图片背景 | 无图=缺\"书挡\" |\n| 连续同色 | 连续3页相同主题色=P0错误 | 第3页必须插入暗色/氛围变化 |\n\n**密度速查表（必须严格遵循）**：\n\n| 规则 | 要求 |\n|------|------|\n| 活跃构图 | ≥78%画布高度（≈1123px of 1440px） |\n| 4横带密度 | 1440px切4段(360px)，每段有内容或主动留白理由 |\n| 纯空白带 | >216px必须有设计理由（如atmospheric hero页） |\n| 最少元素 | 每页至少3种内容元素（标题+正文+数据/图/引言） |\n| 表格行高 | 不足45%画布时加左侧大数字列或转M08 Tall Ledger |\n| 重复模式 | 避免\"标题+lead+3行\"重复超过2次 |\n\n**图片规则速查（必须严格遵循）**：\n\n| 规则 | 要求 |\n|------|------|\n| 图片下载 | 必须下载到本地`assets/`，禁止引用外部URL |\n| 唯一性验证 | 下载后用`buf1.equals(buf2)`验证，相同则换源 |\n| 跨项目去重 | 下载后手动用`buf1.equals(buf2)`验证图片内容不同（文件级校验，不依赖跨项目 registry） |\n| 满铺图页 | 选图→无遮罩构图→局部色调遮罩→缩略图检查 |\n| 满铺图标题色 | 必须`#ffffff`+`text-shadow`，禁止`#ece2cf` |\n| 主体感知裁切 | 根据`object-position`确保主体完整可见 |\n| 截图展示 | 用`.frame-shot`包壳，给45-65%页面高度 |\n| 图源优先级 | 用户图>Pexels/Pixabay(API)>Unsplash(直链)>AI生成 |\n| accent面积 | Swiss≤30%，Lemon Green≤20% |\n\n- **封面/封底图片下载**：\n  1. 优先用户提供的图片（最真实，无\"AI感\"）\n  2. 用户无图时，询问是否调用 Pexels/Pixabay API 搜索（需用户同意，见 Step 1 图片三选一门控）\n  3. 用户同意后，用 `curl.exe -L -o \"assets/cover.jpg\" \"URL\"` 手动下载（URL 来自 Pexels/Pixabay API 返回）\n  4. Unsplash 直链备选：`https://images.unsplash.com/photo-{id}?w=1080&h=1440&fit=crop&auto=format&q=85`\n- **满铺图页必须遵循 `references/image-overlay.md`**：选图→无遮罩构图→局部色调遮罩→缩略图检查\n- **密度保障**：每页活跃构图≥78%画布高度，读 `references/portrait-fill.md`\n- **节奏保障**：暗色页插入、氛围强弱交替、版式不重复\n- **背景系统**：Editorial 必须使用三层背景（paper→wash→grain），禁止纯平背景。读 `references/background-systems.md`。氛围强度按页面角色分级：封面/引言/封底用 strong，数据/清单用 subtle\n- **图片必须下载到本地**（关键！Puppeteer headless无法可靠加载外部API图片）：\n  1. 用户同意后，用 `curl.exe -L -o \"assets/cover.jpg\" \"URL\"` 手动下载\n  2. HTML中用本地相对路径引用：`src=\"assets/cover.jpg\"`\n  3. 禁止直接引用外部URL（trae-api-cn.mchost.guru 仅限TRAE内部环境可用 / unsplash / pexels等），一律先下载再引用\n- **图片下载后必须验证唯一性**：\n  1. 下载多张图片后，用 `buf1.equals(buf2)` 验证图片文件内容不同\n  2. 如果两张图完全相同，换用其他图源\n  3. 禁止假设URL不同=内容不同\n- 图源优先级: 用户图 > Pexels/Pixabay(API搜索) > Unsplash(直链) > AI生成(trae-api-cn.mchost.guru text_to_image，仅限TRAE内部环境)\n- 截图用 `.frame-shot` 包壳\n\n### Step 4: Validate — 自检（自动执行，不等待）\n截图前自动检查，不通过则自动修复：\n\n**密度检查**：每页活跃构图≥78% | 每页≥3种内容元素 | 纯空白带>216px需理由\n**图片检查**：封面1秒说清主题 | 文字未压主体 | 无broken image | **多张背景图文件内容不同（buf1.equals(buf2)===false）**\n**标题一致性检查**：所有内容页主标题使用同一字号class | 不得混用.h-xl和.h-md | 封面允许更大字号\n**节奏检查**：5页+至少1暗色页 | 暗色页不相邻 | 氛围强弱交替 | 版式不重复\n**风格检查**（读 `references/style-system.md`）：\n- [ ] 全套风格统一（同一主题色+同一风格）\n- [ ] Editorial身份测试：有atmosphere层 + serif标题 + 至少一个magazine结构元素\n- [ ] Swiss身份测试：大标题字重≤300 + 无serif + 单一accent + 无卡片阴影\n- [ ] 无文字溢出/footer碰撞\n\n**自动验证**（读 `assets/validate.js`）：\n- 运行 `node assets/validate.js <项目目录>` 执行 12 项自动检查\n- R1 溢出检查 / R2 footer碰撞 / R3 Swiss粗体 / R4 最小字号 / R5 4横带密度 / R6 h-xl换行 / R7 figure margin / R8 标题一致性 / R9 满铺图页标题颜色 / R10 暗色页节奏 / R11 accent面积 / R12 封面封底图背景\n- FAIL 项必须修复后才能交付，WARN 项为建议\n\n### Step 5: Screenshot & Deliver — 截图交付（直接执行）\n- 用`assets/screenshot.js`截图（自动检测页面ID，无需手动配置）\n  - 用法：先启动`python -m http.server 8090 --bind 127.0.0.1`（绑定本地回环，不暴露局域网），然后`node assets/screenshot.js <项目目录>`\n  - puppeteer-core + 系统Chrome，deviceScaleFactor:2\n  - 等待networkidle0 + fonts.ready + 6秒（确保图片加载）\n  - Chrome路径: 自动检测`$env:LOCALAPPDATA\\ms-playwright\\chromium-*\\chrome.exe`\n- **截图大小异常检测**（关键！文件过小说明图片未渲染）：\n  - 带背景图的页面（封面/封底）PNG应 >1MB（2x分辨率下）\n  - 纯文字页面 PNG 通常 800KB-1.5MB\n  - 如果封面/封底截图 <500KB，大概率背景图未渲染，需检查图片文件是否有效\n- 文字压缩：保留原话引言+场景描述+核心数据，≤1000字\n  - **压缩模板**：标题(1句) → 场景开场(1-2句，含人物/时间/地点) → 核心论点(1-2句) → 关键原话(1-2条，用「」包裹) → 数据支撑(3-5个关键数字) → 结尾原话(1条)\n  - **必须保留**：原文中的人物原话（用「」标记）、访谈/会议场景描述、关键数据\n  - **可以删减**：过渡句、重复论述、次要细节、纯背景铺垫\n- **交付方式：本地文件夹（默认）+ 飞书云盘同步（可选，需用户同意）**\n\n  **A. 本地文件夹（默认）**\n  > ⚠️ **本地文件写入提示**：将在 `$env:TEMP` 创建 `<slug>公众号素材/` 文件夹并写入 PNG+txt 文件。截图完成后告知用户交付路径，再继续后续步骤。\n  1. 截图完成后，告知用户：`已生成 N 张 PNG + 文字稿，将保存到 $env:TEMP/<slug>公众号素材/`\n  2. 在`$env:TEMP`创建`<slug>公众号素材/`文件夹\n  3. 将PNG+txt复制到该文件夹\n  4. 用`explorer.exe`打开文件夹，用户可拖到桌面\n  5. 完成本地交付后，**询问是否上传到飞书云盘**（不主动执行）\n\n  **B. 飞书云盘同步（可选，需用户明确同意——见下方门控）**\n  > ⚠️ **数据外发提示**：上传会将文章相关PNG和文字稿传输到飞书云服务器，离开本地环境。如果文章包含未发布/敏感/专有内容，请勿启用。需要用户已登录lark-cli。\n\n  **飞书同步同意门控**（仅在本地交付完成后触发一次）：\n  ```\n  本地文件夹已交付。是否需要同步到飞书云盘？\n  - 是 → 执行下方上传步骤\n  - 否 → 结束（本地文件夹已是完整交付物）\n  ```\n\n  **用户同意后执行**：\n  1. 用`lark-cli drive +create-folder`创建`<slug>公众号素材`文件夹\n  2. cd到output目录，用`lark-cli drive +upload --file <filename> --folder-token <token>`逐个上传PNG+txt\n  3. 返回飞书云盘文件夹URL，用户手机飞书App打开即可逐张保存到相册\n  4. 注意：lark-cli要求用相对路径，必须先cd到output目录再上传\n\n## 标题一致性铁律（非协商）\n\n1. **内容页主标题统一字号**：所有内容页（P02-P08）的主标题必须使用同一个 class（Editorial 用 `.h-xl` 110px，Swiss 用 `.h-xl` 128px）\n2. **封面允许更大字号**：封面用 `.h-display`（Editorial 136px）或 `.h-hero`/`.h-statement`（Swiss）\n3. **通过拆行适配而非降级字号**：标题太长时拆为两行，太短时加副标题增加视觉重量，不得降级到 `.h-md`\n4. **不得混用不同级别标题 class**：同一套卡片中，内容页主标题不得混用 `.h-xl` 和 `.h-md`\n\n## 密度铁律（非协商）\n\n1. **活跃构图 ≥78% 画布高度**（≈1123px of 1440px）\n2. **4横带密度**：1440px切4段(360px)，每段有内容或主动留白理由\n3. **纯空白带 >216px 必须有设计理由**（如atmospheric hero页）\n4. **每页至少3种内容元素**（标题+正文+数据/图/引言）\n5. **表格/ledger行高不足45%画布时**：加左侧大数字列、加pull quote列、或转M08 Tall Ledger\n6. **避免\"标题+lead+3行\"重复超过2次**\n\n## 节奏铁律（非协商）\n\n1. **明暗节奏**：5页以上组图至少1页暗色页(Midnight Ink)，7页以上至少1-2页。暗色页不是换主题，是同一主题内的明暗对比\n2. **暗色页位置**：最佳位置是引言页(Pull Quote)或结尾页(Closing)。2个暗色页不可相邻\n3. **氛围节奏**：封面/引言/结尾用强氛围(strong grain+wash)，数据/截图/清单用弱氛围(subtle grain only)。不可所有页同一氛围强度\n4. **版式节奏**：不可连续2页用同一种版式骨架。密集ledger后接宽松essay或pull quote\n5. **首尾图框**：5页及以上组图，封面和封底都必须有图片背景（满铺图或大图区），形成\"书挡\"效果。图片必须与主题适配——封面图抓主题，封底图收情绪\n6. **连续3页相同主题=P0错误**：连续3页以上使用相同主题色（全light或全dark）视为严重错误，必须在第3页插入暗色页或氛围变化页\n\n## 必读参考文件\n\n| 文件 | 用途 |\n|------|------|\n| `references/style-system.md` | **风格系统**：Editorial vs Swiss视觉锚点+身份测试+反模式 |\n| `references/category-cookbook.md` | **品类路由表**：13个品类的风格/主题/版式/图源映射 |\n| `references/content-planning.md` | **内容规划**：压缩阶梯+页面角色+钩子模式+页数指导 |\n| `references/portrait-fill.md` | **3:4密度规则**：垂直分区+密度铁律+稀疏页修复 |\n| `references/image-overlay.md` | **文字压图**：选图→无遮罩→局部色调→缩略图检查+主体避让 |\n| `references/theme-presets.md` | 10套主题色CSS变量 |\n| `references/components.md` | 字体/字号/间距/图片容器/卡片/截图容器规范 |\n| `references/layout-recipes.md` | 28种布局模板(M01-M16+S01-S12) |\n| `references/screenshot-treatment.md` | 截图美化：设备外壳+背景材质+风格默认 |\n| `references/background-systems.md` | **背景系统**：三层架构（paper→wash→grain）+ 氛围强度分级 + 满铺图页 + Swiss极简 |\n| `references/image-sources.md` | Pexels/Unsplash图库接入 + AI生图验证规则 |\n\n## 示例\n\n**输入**: SpaceX上市分析MD → 自动推断：商业/科技分析 → Editorial × Indigo Porcelain\n\n**输出**: 7张PNG + spacex-文字稿.txt → `SpaceX公众号素材/` 文件夹\n\n**输入**: skill-forge教程MD+截图文件夹 → 自动推断：教程/工具 → Swiss × IKB Blue\n\n**输出**: 6张PNG + skillforge-文字稿.txt → `skillforge公众号素材/` 文件夹\n\nFile v7.8.0:README.md\n\n# xhs-crafter\n\n将 Markdown 文章排版为 3:4 比例的精美图片卡片 + 压缩文字稿，用于微信公众号/小红书贴图发布。\n\n[![版本](https://img.shields.io/badge/version-7.8.0-blue)](https://github.com/EdwardWason/xhs-crafter)\n[![许可证](https://img.shields.io/badge/license-MIT--0-green)](LICENSE)\n[![ClawHub](https://img.shields.io/badge/ClawHub-xhs--crafter-orange)](https://clawhub.ai/EdwardWason/xhs-crafter)\n\n## 功能\n\n- **MD → 图片卡片**：自动将 Markdown 文章拆分排版为多张 1080x1440 (3:4) HTML 页面，截图为 PNG\n- **双风格系统**：Editorial Magazine（杂志风，衬线+暖纸底）和 Swiss International（瑞士网格风，无衬线+白底）\n- **13 品类适配**：商业/科技/职场/旅行/教程/影视/游戏/美食/彩妆/穿搭/家居/健身/情感/推荐，自动路由风格+主题+版式\n- **10 套主题色**：Ink Classic / Indigo Porcelain / Forest Ink / Kraft Paper / Dune / Midnight Ink / IKB Blue / Lemon Yellow / Lemon Green / Safety Orange\n- **28 种布局模板**：M01-M16（Editorial）+ S01-S12（Swiss）\n- **三层背景架构**：paper→wash→grain，氛围强度按页面角色分级（strong/medium/subtle）\n- **三层节奏系统**：明暗交替 + 氛围强弱 + 版式多样性\n- **密度铁律**：活跃构图 >= 78% 画布高度，确保信息密度\n- **字号速查表**：15级字号体系直接嵌入SKILL.md，确保跨会话一致性\n- **自动验证**：12项validate.js检查（溢出/footer碰撞/最小字号/密度/节奏/标题一致性/accent面积等）\n- **文字压缩**：保留原话引言+场景描述，压缩至 <= 1000 字\n- **本地交付（默认）**：MD→HTML→PNG→本地文件夹，所有内容仅本地处理\n- **可选飞书云盘同步**：用户明确同意后上传（⚠️ 内容会离开本地，详见下方隐私说明）\n\n## 隐私与数据流\n\n**核心能力是本地处理**：MD文本 → HTML组装 → PNG截图 → 本地文件夹交付。文章内容、图片素材、生成产物默认仅在本地处理，不上传任何外部服务。\n\n**可选外部能力**（需用户明确同意，不主动执行）：\n- **图片搜索**：调用Pexels/Pixabay API搜索免费图库照片。⚠️ 仅搜索词和图片下载会发送到Pexels/Pixabay服务器，**不会上传文章原文**\n- **飞书云盘同步**：将生成PNG+文字稿上传到用户飞书云盘。⚠️ 上传即意味着内容离开本地，如文章包含未发布/敏感/专有内容请勿启用\n\n**外部网络依赖**：核心渲染流程完全本地（启动 127.0.0.1 HTTP server 加载预存 HTML 模板 + Puppeteer 截图，无外部网络）。可选外部能力（每项需用户独立同意）：(1)Pexels/Pixabay/Unsplash 图库 API 搜索（发送搜索关键词）；(2)trae-api-cn AI 生图 API（发送 prompt，仅限 TRAE 内部环境）；(3)飞书云盘上传。v7.6 已移除 Google Fonts CDN 引用，模板使用系统字体回退栈。\n\n## 快速开始\n\n```bash\nnpx clawhub@latest install EdwardWason/xhs-crafter\n```\n\n## 使用方法\n\n在 TRAE / Claude Code / OpenClaw 中，明确要求图片排版时触发：\n\n```\n请用 xhs-crafter 把这篇 MD 文章排版为公众号贴图：/path/to/article.md\n```\n\n5 步工作流，用户只需给 MD，直接出本地文件夹（外部能力需用户同意）：\n\n1. **Intake** — 识别内容品类（自动推断）\n2. **Content Plan** — 内容规划（压缩阶梯+页面角色+节奏规划）\n3. **Compose** — 组装 HTML（双风格+10 主题+28 布局）\n4. **Validate** — 自检（密度+图片+节奏+风格）\n5. **Screenshot & Deliver** — 截图交付（本地文件夹默认；飞书云盘需用户明确同意）\n\n## 文件结构\n\n```\nxhs-crafter/\n├── SKILL.md                              # 技能主文件（入口，含字号速查表）\n├── assets/\n│   ├── template-editorial-card.html      # Editorial 种子模板\n│   ├── template-swiss-card.html          # Swiss 种子模板\n│   ├── screenshot.js                     # Puppeteer 截图脚本\n│   └── validate.js                       # 12项自动验证脚本\n└── references/\n    ├── style-system.md                   # Editorial vs Swiss 身份测试+反模式\n    ├── category-cookbook.md              # 13 品类路由表\n    ├── content-planning.md               # 压缩阶梯+页面角色+钩子模式\n    ├── portrait-fill.md                  # 3:4 密度规则+三层节奏系统\n    ├── image-overlay.md                  # 文字压图规则\n    ├── background-systems.md             # 三层背景架构+氛围强度分级\n    ├── theme-presets.md                  # 10 套主题色 CSS 变量\n    ├── components.md                     # 字体/字号/间距规范（权威来源）\n    ├── layout-recipes.md                 # 28 种布局模板\n    ├── screenshot-treatment.md           # 截图装裱规范\n    ├── image-sources.md                  # 图库 API 接入+AI生图验证\n    └── workflow.md                       # 工作流详细参考\n```\n\n## 品类适配\n\n| 品类 | 风格 | 主题 |\n|------|------|------|\n| 商业/科技分析 | Editorial | Indigo Porcelain |\n| 职场/干货 | Swiss | IKB Blue |\n| 旅行/生活方式 | Editorial | Kraft Paper |\n| 教程/工具 | Swiss | IKB Blue |\n| 影视/读书 | Editorial | Ink Classic |\n| 游戏 | Editorial (dark) | Midnight Ink |\n| 美食 | Editorial | Kraft Paper |\n| 彩妆 | Editorial | Dune |\n| 穿搭 | Editorial | Indigo Porcelain |\n| 家居 | Editorial | Forest Ink |\n| 健身/情感/推荐 | Swiss | Safety Orange |\n\n## 文档\n\n| 文件 | 用途 |\n|------|------|\n| [SKILL.md](SKILL.md) | 技能主文件，5 步工作流+字号速查表+密度铁律+节奏铁律 |\n| [references/style-system.md](references/style-system.md) | Editorial vs Swiss 视觉锚点+身份测试 |\n| [references/components.md](references/components.md) | 字体/字号/间距规范（唯一权威来源） |\n| [references/layout-recipes.md](references/layout-recipes.md) | 28 种布局模板详细说明 |\n| [references/theme-presets.md](references/theme-presets.md) | 10 套主题色 CSS 变量定义 |\n| [references/category-cookbook.md](references/category-cookbook.md) | 13 品类风格/主题/版式映射 |\n| [references/background-systems.md](references/background-systems.md) | 三层背景架构+氛围强度分级 |\n| [references/portrait-fill.md](references/portrait-fill.md) | 3:4 密度规则+三层节奏系统 |\n| [references/image-sources.md](references/image-sources.md) | 图库接入+AI生图验证规则 |\n| [CHANGELOG.md](CHANGELOG.md) | 版本变更记录 |\n\nLicense: MIT-0\n\n---\n\n# xhs-crafter\n\nConvert Markdown articles into beautifully designed 3:4 ratio image cards + compressed text drafts for WeChat Official Account / Xiaohongshu (Little Red Book) image-post publishing.\n\n[![version](https://img.shields.io/badge/version-7.8.0-blue)](https://github.com/EdwardWason/xhs-crafter)\n[![license](https://img.shields.io/badge/license-MIT--0-green)](LICENSE)\n[![ClawHub](https://img.shields.io/badge/ClawHub-xhs--crafter-orange)](https://clawhub.ai/EdwardWason/xhs-crafter)\n\n## Features\n\n- **MD → Image Cards**: Automatically split and layout Markdown articles into multiple 1080x1440 (3:4) HTML pages, screenshot as PNG\n- **Dual Style System**: Editorial Magazine (serif + warm paper) and Swiss International (sans-serif + white + single accent)\n- **13 Category Routing**: Business/Tech/Career/Travel/Tutorial/Film/Gaming/Food/Makeup/Fashion/Home/Fitness/Emotion/Recommendation — auto-route style + theme + layout\n- **10 Theme Presets**: Ink Classic / Indigo Porcelain / Forest Ink / Kraft Paper / Dune / Midnight Ink / IKB Blue / Lemon Yellow / Lemon Green / Safety Orange\n- **28 Layout Templates**: M01-M16 (Editorial) + S01-S12 (Swiss)\n- **Three-Layer Background**: paper→wash→grain, atmosphere intensity graded by page role (strong/medium/subtle)\n- **Three-Layer Rhythm System**: Light/dark alternation + atmosphere intensity + layout diversity\n- **Density Rules**: Active composition >= 78% canvas height, ensuring information density\n- **Font Size Cheat Sheet**: 15-level type scale embedded in SKILL.md for cross-session consistency\n- **Auto Validation**: 12-rule validate.js (overflow/footer collision/min font/density/rhythm/title consistency/accent area etc.)\n- **Text Compression**: Preserve original quotes + scene descriptions, compress to <= 1000 characters\n- **Local Delivery (default)**: MD→HTML→PNG→local folder, all content processed locally only\n- **Optional Feishu cloud-drive sync**: uploaded only after explicit user consent (⚠️ content leaves local machine, see Privacy below)\n\n## Privacy & Data Flow\n\n**Core capability is local processing**: MD text → HTML assembly → PNG screenshot → local folder delivery. Article content, image assets, and generated artifacts are processed locally by default and never uploaded to any external service.\n\n**Optional external capabilities** (require explicit user consent, never auto-executed):\n- **Image search**: Calls Pexels/Pixabay API to search free stock photos. ⚠️ Only search keywords and image downloads are sent to Pexels/Pixabay servers — **article content is never uploaded**\n- **Feishu cloud-drive sync**: Uploads generated PNGs + text drafts to user's Feishu cloud drive. ⚠️ Uploading means content leaves the local machine — do not enable if the article contains unpublished/sensitive/proprietary material\n\n**External network dependencies**: Core rendering is fully local (starts 127.0.0.1 HTTP server to load pre-stored HTML template + Puppeteer screenshot, no external network). Optional external capabilities (each requires independent user consent): (1) Pexels/Pixabay/Unsplash image API search (sends search keywords); (2) trae-api-cn AI image generation API (sends prompt, TRAE internal only); (3) Feishu cloud drive upload. v7.6 removed Google Fonts CDN references, templates use system font fallback stacks.\n\n## Quick Start\n\n```bash\nnpx clawhub@latest install EdwardWason/xhs-crafter\n```\n\n## Usage\n\nIn TRAE / Claude Code / OpenClaw, trigger by explicitly requesting image layout:\n\n```\nPlease use xhs-crafter to format this MD article as WeChat image cards: /path/to/article.md\n```\n\n5-step workflow — just give MD, get local output folder (external capabilities require user consent):\n\n1. **Intake** — Identify content category (auto-inferred)\n2. **Content Plan** — Content planning (compression ladder + page roles + rhythm planning)\n3. **Compose** — Assemble HTML (dual style + 10 themes + 28 layouts)\n4. **Validate** — Self-check (density + images + rhythm + style)\n5. **Screenshot & Deliver** — Screenshot delivery (local folder by default; Feishu cloud-drive sync requires explicit user consent)\n\n## File Structure\n\n```\nxhs-crafter/\n├── SKILL.md                              # Main skill file (entry point, with font size cheat sheet)\n├── assets/\n│   ├── template-editorial-card.html      # Editorial seed template\n│   ├── template-swiss-card.html          # Swiss seed template\n│   ├── screenshot.js                     # Puppeteer screenshot script\n│   └── validate.js                       # 12-rule auto validation script\n└── references/\n    ├── style-system.md                   # Editorial vs Swiss identity test + anti-patterns\n    ├── category-cookbook.md              # 13-category routing table\n    ├── content-planning.md               # Compression ladder + page roles + hook patterns\n    ├── portrait-fill.md                  # 3:4 density rules + three-layer rhythm system\n    ├── image-overlay.md                  # Text-on-image rules\n    ├── background-systems.md             # Three-layer background + atmosphere intensity\n    ├── theme-presets.md                  # 10 theme CSS variable definitions\n    ├── components.md                     # Font/size/spacing spec (authoritative source)\n    ├── layout-recipes.md                 # 28 layout template details\n    ├── screenshot-treatment.md           # Screenshot framing spec\n    ├── image-sources.md                  # Image API integration + AI image verification\n    └── workflow.md                       # Workflow detailed reference\n```\n\n## Category Mapping\n\n| Category | Style | Theme |\n|----------|-------|-------|\n| Business/Tech Analysis | Editorial | Indigo Porcelain |\n| Career/Productivity | Swiss | IKB Blue |\n| Travel/Lifestyle | Editorial | Kraft Paper |\n| Tutorial/Tools | Swiss | IKB Blue |\n| Film/Books | Editorial | Ink Classic |\n| Gaming | Editorial (dark) | Midnight Ink |\n| Food | Editorial | Kraft Paper |\n| Makeup | Editorial | Dune |\n| Fashion | Editorial | Indigo Porcelain |\n| Home | Editorial | Forest Ink |\n| Fitness/Emotion/Recommendation | Swiss | Safety Orange |\n\n## Documentation\n\n| File | Purpose |\n|------|---------|\n| [SKILL.md](SKILL.md) | Main skill file, 5-step workflow + font size cheat sheet + density rules + rhythm rules |\n| [references/style-system.md](references/style-system.md) | Editorial vs Swiss visual anchors + identity test |\n| [references/components.md](references/components.md) | Font/size/spacing spec (authoritative source) |\n| [references/layout-recipes.md](references/layout-recipes.md) | 28 layout template details |\n| [references/theme-presets.md](references/theme-presets.md) | 10 theme CSS variable definitions |\n| [references/category-cookbook.md](references/category-cookbook.md) | 13-category style/theme/layout mapping |\n| [references/background-systems.md](references/background-systems.md) | Three-layer background + atmosphere intensity |\n| [references/portrait-fill.md](references/portrait-fill.md) | 3:4 density rules + three-layer rhythm system |\n| [references/image-sources.md](references/image-sources.md) | Image API integration + AI image verification |\n| [CHANGELOG.md](CHANGELOG.md) | Version change log |\n\nLicense: MIT-0\n\nFile v7.8.0:_meta.json\n\n{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"xhs-crafter\",\n  \"version\": \"7.8.0\",\n  \"publishedAt\": 1784090247706\n}\n\nFile v7.8.0:references/background-systems.md\n\n# Background Systems\n\n> xhs-crafter 背景系统规范——grain纹理、paper-wash水洗、WebGL流体\n> 画布基准：1080 × 1440（3:4）\n\n---\n\n## 三层背景架构\n\nEditorial Magazine 页面使用三层背景叠加，从底到顶：\n\n```\n┌─────────────────────────────────────┐\n│  Layer 3: grain（纹理）              │  z-index: 2, pointer-events: none\n│  ┌─────────────────────────────────┐│\n│  │  Layer 2: content（内容）        ││  z-index: 1\n│  │  ┌─────────────────────────────┐││\n│  │  │  Layer 1: paper-wash（水洗） │││  z-index: 0\n│  │  │  ┌─────────────────────────┐│││\n│  │  │  │  Layer 0: paper（底色）  ││││  background: var(--paper)\n│  │  │  └─────────────────────────┘│││\n│  │  └─────────────────────────────┘││\n│  └─────────────────────────────────┘│\n└─────────────────────────────────────┘\n```\n\n**禁止使用纯平背景**——Editorial 的核心美学是\"纸墨感\"，flat beige 会显得死板。\n\n---\n\n## Layer 0: Paper（底色）\n\n由 `--paper` CSS 变量控制，每个主题预设自带。\n\n```css\n.poster {\n  background: var(--paper);\n}\n```\n\n**硬规则**：\n- `--paper` 永远不是 `#FFFFFF`——纯白刺眼，印刷行业从不使用\n- `--paper` 永远不是 `#000000`——纯黑暴力，Midnight Ink 用 `#0e0d0c`\n\n---\n\n## Layer 1: Paper-Wash（水洗层）\n\n径向渐变叠加，模拟纸张的不均匀吸墨效果。\n\n### Light 主题（默认）\n\n```css\n.paper-wash {\n  position: absolute;\n  inset: 0;\n  pointer-events: none;\n  z-index: 0;\n  background:\n    radial-gradient(ellipse at 20% 80%, var(--wash-color) 0%, transparent 60%),\n    radial-gradient(ellipse at 80% 20%, var(--wash-color) 0%, transparent 50%),\n    linear-gradient(var(--wash-angle), transparent 0%, var(--wash-color) 100%);\n}\n```\n\n默认变量：\n```css\n:root {\n  --wash-color: rgba(10, 31, 61, .02);\n  --wash-angle: 160deg;\n}\n```\n\n### Midnight Ink 主题（覆盖）\n\n```css\n[data-theme=\"midnight-ink\"] .paper-wash {\n  background:\n    radial-gradient(80% 50% at 28% 16%, rgba(212, 160, 74, .12), transparent 64%),\n    radial-gradient(70% 60% at 80% 86%, rgba(60, 40, 20, .20), transparent 72%),\n    linear-gradient(180deg, rgba(236, 226, 207, .02), rgba(0, 0, 0, .32));\n}\n```\n\n**硬规则**：\n- Light 主题的 wash-color 透明度 ≤.03——若隐若现，不是渐变背景\n- Midnight Ink 的暖光斑必须偏左上角（28% 16%），模拟台灯照射\n\n---\n\n## Layer 2: Grain（纹理层）\n\n模拟纸张纤维/印刷网点的细微纹理。\n\n### Light 主题（默认）\n\n```css\n.grain {\n  position: absolute;\n  inset: 0;\n  pointer-events: none;\n  z-index: 2;\n  opacity: var(--grain-opacity);\n  mix-blend-mode: var(--grain-blend);\n  background-image:\n    radial-gradient(circle at 17% 32%, rgba(0,0,0,.15) 0%, transparent 50%),\n    radial-gradient(circle at 72% 18%, rgba(0,0,0,.10) 0%, transparent 40%),\n    radial-gradient(circle at 45% 78%, rgba(0,0,0,.12) 0%, transparent 45%),\n    radial-gradient(circle at 88% 55%, rgba(0,0,0,.08) 0%, transparent 35%);\n}\n```\n\n默认变量：\n```css\n:root {\n  --grain-opacity: .04;\n  --grain-blend: multiply;\n}\n```\n\n### Midnight Ink 主题（覆盖）\n\n```css\n[data-theme=\"midnight-ink\"] .grain {\n  opacity: .26;\n  mix-blend-mode: screen;\n  background-image:\n    radial-gradient(rgba(255, 244, 214, .10) 1px, transparent 1px);\n}\n```\n\n**硬规则**：\n- Light 主题 grain-opacity ≤.06——纹理是暗示，不是噪点\n- Midnight Ink grain-opacity .26 + screen 混合——暗色页需要更明显的纹理才不会死板\n- grain 不得降低文字可读性——如果正文变模糊，降低 opacity\n\n---\n\n## 氛围强度分级\n\n不同页面角色使用不同氛围强度：\n\n| 页面角色 | 氛围强度 | grain-opacity | paper-wash | 说明 |\n|---------|---------|---------------|------------|------|\n| 封面 | Strong | .06 | 全部3层 | 封面需要氛围感 |\n| 引言/引语 | Strong | .06 | 全部3层 | 引用页需要仪式感 |\n| 封底 | Strong | .06 | 全部3层 | 收尾需要余韵 |\n| 数据/清单 | Subtle | .02 | 仅1层 | 数据页需要清晰 |\n| 正文/essay | Medium | .04 | 2层 | 阅读页需要舒适 |\n\n**CSS 实现**：\n\n```css\n/* Strong 氛围（封面/引言/封底） */\n.poster.atmosphere-strong .grain { opacity: .06; }\n.poster.atmosphere-strong .paper-wash { opacity: 1; }\n\n/* Subtle 氛围（数据/清单） */\n.poster.atmosphere-subtle .grain { opacity: .02; }\n.poster.atmosphere-subtle .paper-wash { opacity: .3; }\n```\n\n---\n\n## 满铺图页背景\n\n封面和封底使用满铺背景图时，背景系统简化：\n\n```\n┌─────────────────────────────────────┐\n│  Layer 4: hero-content（文字内容）   │  z-index: 3\n│  ┌─────────────────────────────────┐│\n│  │  Layer 3: hero-overlay（遮罩）   ││  z-index: 1\n│  │  ┌─────────────────────────────┐││\n│  │  │  Layer 2: grain（纹理）      │││  z-index: 2\n│  │  │  ┌─────────────────────────┐│││\n│  │  │  │  Layer 1: hero-bleed    ││││  z-index: 0\n│  │  │  │  （满铺背景图）           ││││\n│  │  │  └─────────────────────────┘│││\n│  │  └─────────────────────────────┘││\n│  └─────────────────────────────────┘│\n└─────────────────────────────────────┘\n```\n\n**关键规则**：\n1. hero-overlay 使用渐变遮罩，不是纯色半透明块\n2. 遮罩方向：从上到下加深，确保底部文字可读\n3. 遮罩颜色取自主题的 ink 色——Indigo Porcelain 用深蓝遮罩，Kraft Paper 用深棕遮罩\n4. grain 仍然叠加在 overlay 之上，保持纸墨感一致性\n\n### Light 主题遮罩\n\n```css\n.hero-overlay {\n  background: linear-gradient(180deg,\n    rgba(10, 31, 61, .55) 0%,\n    rgba(10, 31, 61, .25) 40%,\n    rgba(10, 31, 61, .45) 100%\n  );\n}\n```\n\n### Midnight Ink 遮罩\n\n```css\n[data-theme=\"midnight-ink\"] .hero-overlay {\n  background: linear-gradient(180deg,\n    rgba(14, 13, 12, .50) 0%,\n    rgba(14, 13, 12, .20) 35%,\n    rgba(14, 13, 12, .60) 100%\n  );\n}\n```\n\n---\n\n## Swiss International 背景\n\nSwiss 体系不使用 grain 和 paper-wash，背景极简：\n\n```css\n/* Swiss 使用纯 paper 底色 + 可选网格点阵 */\n.poster.swiss {\n  background: var(--paper);\n}\n\n/* 可选：极细网格点阵（仅用于数据页） */\n.poster.swiss.grid-dots {\n  background-image:\n    radial-gradient(circle, var(--grey-2) 1px, transparent 1px);\n  background-size: 24px 24px;\n}\n```\n\n**硬规则**：\n- Swiss 不使用 grain 纹理\n- Swiss 不使用 paper-wash 水洗\n- Swiss 网格点阵仅用于数据页，且 opacity ≤.3\n- Swiss 封面不使用网格点阵\n\n---\n\n## 反模式\n\n| 反模式 | 问题 | 修复 |\n|-------|------|------|\n| 纯平 beige 背景 | 像网页不像杂志 | 添加 grain + paper-wash |\n| grain-opacity >.10 | 文字模糊不可读 | 降至 .04-.06 |\n| 全页渐变背景 | 像PPT不像杂志 | 用 paper-wash（透明度≤.03）代替 |\n| 遮罩用纯色半透明 | 死板无层次 | 改用渐变遮罩 |\n| Swiss 用 grain | 破坏极简感 | Swiss 不用 grain |\n| 暗色页不加 grain 覆盖 | 暗色背景死板 | Midnight Ink 必须加 screen 混合 grain |\n\nFile v7.8.0:references/category-cookbook.md\n\n# Category Cookbook\n\nPer-category cheat sheet for common content types. Each entry maps a category to style mode, theme, recipes, and image source strategy.\n\nWhen the user names a category, find the row here and start from the listed recipes instead of building from a blank file.\n\n---\n\n## 商业/科技分析 · Business & Tech Analysis\n\n**Strongest fit for our skill.**\n\n- **Recipes**: M01 (text-led cover) or M16 (image-led cover when hero image available), M04 (pull quote), M08 (pipeline), M12 (data cards), M07 (closing note)\n- **Style mode**: Editorial × Indigo Porcelain (tech/AI) or × Ink Classic (general business). Swiss × IKB Blue for pure data posts\n- **Theme**: Indigo Porcelain for tech/AI topics; Ink Classic for general business; IKB Blue for data-heavy analysis\n- **Text scheme**: Text-beside-image for feature pages. Text-on-image only for cover with qualified photo. Body pages use serif text + data cards + pull quotes\n- **Image source**: AI generated (editorial documentary style) > Unsplash (tech/office scenes) > Pexels (Chinese keyword search). Avoid stock handshake/laptop photos\n- **Content shape**: 5-7 pages. Cover (hook + 1-line deck) → opening thesis + data → 2-3 evidence pages (pipeline/ledger/quote) → closing\n- **Pitfalls**:\n  1. Generic \"industry analysis\" voice without specific numbers. Cure: every claim needs a data point\n  2. Too many data cards without narrative. Cure: alternate data pages with essay/quote pages\n  3. Cover with vague hype instead of concrete hook\n\n---\n\n## 职场/干货 · Workplace & How-to\n\n**Strong fit.** This is what Swiss-International was made for.\n\n- **Recipes**: S01 (cover), S02 (comparison), S05 (warning rows), S06 (pipeline), S07 (takeaway ledger), S09 (KPI tower), S11 (stacked ledger)\n- **Style mode**: Swiss × IKB Blue or × Safety Orange. Avoid lemon-yellow/lemon-green for serious content\n- **Theme**: IKB Blue (default), Safety Orange (warning/urgent content)\n- **Text scheme**: Text-only or text-with-diagram. Almost never text-on-photo (workplace photos read as stock)\n- **Image source**: Avoid stock business photos. Prefer diagrams, screenshots of real artifacts (Notion, Linear, Figma), or omit. Generated images rarely add value\n- **Content shape**: 5-9 pages. Cover question/claim → context KPI → 3-5 numbered insights as ledger → one comparison or pipeline diagram → takeaway\n- **Pitfalls**:\n  1. Listicle voice (\"8 个让你...\"). Cure: rewrite as numbered argument, not tips\n  2. Cheap \"advice\" energy (\"一定要\", \"千万别\"). Cure: replace with observed action verbs + a number\n  3. Stock-photo seasoning (handshake, laptop-with-coffee). Cure: omit, or use a small icon glyph\n\n---\n\n## 旅行/生活方式 · Travel & Lifestyle\n\n**Strongest fit.**\n\n- **Recipes**: M16 (image-led cover when user has great photos), M01 (text-led cover), M02 (field-note photo), M11 (marginalia essay), S11 (itinerary ledger), M07 (closing note)\n- **Style mode**: Editorial × Kraft Paper (warm-tone destinations) or × Dune (art/creative destinations) or × Forest Ink (mountain/wilderness)\n- **Theme**: Kraft Paper for warm/cultural trips; Dune for art/design destinations; Forest Ink for outdoor/nature\n- **Text scheme**: Text beside image is default. Cover can use text-on-image only when photo has quiet zone. Body pages use photo + caption pairs (field-note style)\n- **Image source**: User photos > Pexels (Chinese keyword search for domestic destinations) > Unsplash (overseas/English keywords) > Flickr CC (documentary feel)\n- **Content shape**: 5-7 pages. Cover (destination + dates) → atmosphere photo + lead → itinerary ledger → 2-3 field notes → closing quote\n- **Pitfalls**: Generic \"best places in X city\" listicle voice. Cure: keep one specific date/weather/mileage detail per page\n\n---\n\n## 教程/工具 · Tutorial & Tools\n\n**Strong fit.** Screenshot treatment is the key differentiator.\n\n- **Recipes**: S01 (cover), S06 (pipeline for steps), S08 (duo compare), S11 (stacked ledger for shortcuts), M04 (pull quote for key insight)\n- **Style mode**: Swiss × IKB Blue (default) or × Safety Orange (warning tips). Editorial × Indigo Porcelain for long-form tutorials\n- **Theme**: IKB Blue for tool tutorials; Indigo Porcelain for methodology tutorials\n- **Text scheme**: Screenshot-heavy. Use `.frame-shot` + `.device-browser` for all screenshots. Text above/below screenshots, not beside\n- **Image source**: User screenshots (mandatory for real tutorials). Use `.frame-shot` with device chrome + background texture. Never use stock UI screenshots\n- **Content shape**: 5-8 pages. Cover (tool name + what you'll learn) → context → 3-5 step pages (screenshot + 1-2 sentence instruction) → tips/shortcuts ledger → closing\n- **Pitfalls**:\n  1. Screenshots too small to read. Cure: give screenshots 45-65% page height\n  2. Full-screen dumps without focus. Cure: crop to relevant area, preserve readable UI labels\n  3. Dark screenshots on dark background. Cure: use `.frame-shot` with paper-2 background\n\n---\n\n## 影视/读书 · Film & Books\n\n**Strong fit** for reviews, scene analysis, quote cards.\n\n- **Recipes**: M01 (cover), M04 (pull quote for memorable lines), M10 (evidence feature for scene analysis), M11 (marginalia essay), S02 (comparison), S12 (matrix for weekly roundups)\n- **Style mode**: Editorial × Ink Classic or × Indigo Porcelain. Letterboxd visual vocabulary fits Editorial naturally\n- **Theme**: Ink Classic (default for reviews); Indigo Porcelain (sci-fi/tech films); Kraft Paper (literature/classics)\n- **Text scheme**: Text-beside-image for review cards (poster on left, take on right). Text-on-image only for atmospheric quote pages\n- **Image source**: Official posters/stills. Do not generate fake stills. User photos of book covers acceptable\n- **Content shape**: 5-7 pages. Cover (title + year + 1-line take) → 1-2 scene captures → director-quote/theme pullquote → verdict ledger\n- **Pitfalls**:\n  1. Fake film-festival typography (adding fake awards badges). Don't\n  2. Spoiler in title without warning. Mark `剧透` in kicker if needed\n\n---\n\n## 游戏 · Gaming\n\n**Strong fit** for journals, recaps, build lists. **Has image-rights risk.**\n\n- **Recipes**: M01 (cover with full-bleed art), M08 (boss tier ledger), S07 (takeaway ledger), S11 (chapter timeline), M15 (build before/after)\n- **Style mode**: Editorial dark (Ink Classic with paper inverted to near-black) for atmospheric games. Swiss for esports/competitive data\n- **Theme**: Midnight Ink for atmospheric games; IKB Blue for esports/data\n- **Text scheme**: Text-on-image is standard for game covers (game art is the primary draw). Use subject mapping from image-overlay.md\n- **Image source**: Pexels/Unsplash for keyword pulls, official screenshots. Always disclose copyright risk and log to SOURCES.md\n- **Content shape**: 4-6 pages. Cover (game name + playtime) → first impression → chapter ledger → memorable boss/scene → verdict\n- **Pitfalls**: Score-card seriousness (8.5/10 in giant block). Keep verdict as one short clause, not a number\n\n---\n\n## 美食 · Food\n\n**Split fit.** Recipes work. Food-photo showcase does not.\n\n- **Recipes**: M16 (image-led cover with finished-dish photo), S11 (ingredient/price ledger), M14 (cooking steps pipeline), M02 (extra dish detail)\n- **Style mode**: Editorial × Kraft Paper (cookbook feel). Swiss × Lemon Yellow/Safety Orange for \"cost-per-serving\" data posts\n- **Image source**: User photos of finished dish are best. Pexels for Chinese food scenes. Unsplash food photos read as Western stock\n- **Pitfalls**: Excited recipe voice (\"超绝!!!\"). Editorial doesn't shout — let the dish do the talking\n\n---\n\n## Capability Circle Summary\n\n**End-to-end strong** (text + structure + image all from skill):\n- 商业/科技分析 · 旅行 · 职场 · 推荐\n\n**Strong on text/structure, needs user photos for image**:\n- 影视/读书 · 游戏 · 美食(食谱) · 彩妆(教程) · 穿搭(精选/胶囊) · 家居 · 健身\n\n**Outside scope** (skill cannot reliably produce — be explicit with user before designing):\n- 美食(菜品大片摆盘) — 需要专业食物摄影，AI生图无法达到\n- 穿搭(日常OOTD全身照) — 需要真实人物实拍\n- 情感(梦核/氛围感装饰风) — 与 Editorial 和 Swiss 均冲突\n- Y2K/千禧辣妹/哥特萝莉/kawaii装饰风 — 超出两种风格体系\n- 纯摄影展示 — 图片本身就是交付物，排版无意义\n\nBe explicit with the user when their request lands in \"outside scope\". Do not promise a result the system was not designed to make.\n\n---\n\n## 彩妆 · Makeup\n\n**Split fit.** 教程方向强，大片展示方向弱。\n\n- **Recipes**: S06 (pipeline for steps), S08 (duo compare before/after), M04 (pull quote for key tip), S11 (product ledger)\n- **Style mode**: Swiss × Lemon Yellow (年轻活力) or × Safety Orange (大胆对比). Editorial × Dune for 高端品牌\n- **Theme**: Lemon Yellow for 教程/入门; Safety Orange for 对比/警示; Dune for 高端品牌\n- **Text scheme**: Text-beside-image. 步骤页用截图+简短说明，对比页用左右分栏\n- **Image source**: 用户实拍妆容步骤图（必须）. 禁止AI生成人脸\n- **Content shape**: 5-7 pages. Cover (妆容名称+效果预期) → 2-3 step pages → product ledger → before/after → tips\n- **Pitfalls**:\n  1. AI生成人脸做妆容示范 → 禁止，必须用户实拍\n  2. 色号标注不清晰 → 每个产品标注品牌+色号\n\n---\n\n## 穿搭 · Outfit\n\n**Split fit.** 胶囊衣橱/穿搭哲学方向强，日常OOTD方向弱。\n\n- **Recipes**: S11 (单品 ledger), S02 (compare 对比搭配), M11 (marginalia essay for 穿搭哲学), M07 (closing note)\n- **Style mode**: Editorial × Dune (极简穿搭) or × Kraft Paper (复古穿搭). Swiss × Lemon Yellow (年轻活力)\n- **Theme**: Dune for 极简/设计感; Kraft Paper for 复古/手作; Lemon Yellow for 年轻/潮流\n- **Text scheme**: Text-beside-image. 单品页用 ledger 列品牌+价格，搭配页用对比图\n- **Image source**: 用户实拍穿搭图（推荐）. Pexels for 平铺图/单品图. 禁止AI生成全身照\n- **Content shape**: 5-7 pages. Cover (穿搭主题+季节) → 核心理念 → 3-5 单品/搭配 → 购买清单 → closing\n- **Pitfalls**:\n  1. OOTD全身照用AI生成 → 禁止，必须用户实拍\n  2. 纯链接堆砌无搭配逻辑 → 每个单品说明为什么选它\n\n---\n\n## 家居 · Home\n\n**Strong on text/structure, needs user photos.**\n\n- **Recipes**: M02 (field-note photo for 空间展示), S11 (好物 ledger), M11 (marginalia essay for 居住哲学), S06 (pipeline for 改造步骤)\n- **Style mode**: Editorial × Kraft Paper (温暖手作) or × Dune (极简设计). Swiss × IKB Blue for 智能家居/数据\n- **Theme**: Kraft Paper for 温馨/手作; Dune for 极简/设计; IKB Blue for 智能家居\n- **Text scheme**: Text-beside-image. 空间页用大图+短文，好物页用 ledger\n- **Image source**: 用户实拍家居图（推荐）. Pexels for 家居场景. Unsplash for 极简空间\n- **Content shape**: 5-7 pages. Cover (空间类型+风格) → 理念/改造前 → 2-3 空间展示 → 好物清单 → closing\n- **Pitfalls**:\n  1. 纯产品堆砌无居住逻辑 → 每个物品说明为什么适合这个空间\n  2. 网红风过度装饰 → Editorial克制，让空间说话\n\n---\n\n## 健身 · Fitness\n\n**Strong on text/structure, needs user photos.**\n\n- **Recipes**: S06 (pipeline for 训练计划), S09 (KPI tower for 数据), S11 (动作 ledger), S02 (compare 正确vs错误)\n- **Style mode**: Swiss × Safety Orange (力量/警示) or × Lemon Green (健康/增长). Editorial × Forest Ink for 户外健身\n- **Theme**: Safety Orange for 力量训练; Lemon Green for 有氧/健康; Forest Ink for 户外\n- **Text scheme**: Text-only or text-with-diagram. 动作说明用 pipeline，数据用 KPI tower\n- **Image source**: 用户实拍训练图（推荐）. 禁止AI生成肌肉/身材图\n- **Content shape**: 5-7 pages. Cover (训练目标+周期) → 数据基线 → 3-4 训练步骤 → 饮食/恢复提示 → closing\n- **Pitfalls**:\n  1. AI生成身材图 → 禁止，用数据+文字代替\n  2. 过度承诺（\"7天练出马甲线\"） → 用真实数据说话\n\n---\n\n## 情感 · Emotion\n\n**Split fit.** 文字驱动方向强，梦核/氛围感方向弱。\n\n- **Recipes**: M04 (pull quote), M11 (marginalia essay), M07 (closing note), M01 (text-led cover)\n- **Style mode**: Editorial × Ink Classic (通用) or × Kraft Paper (温暖回忆). 避免Swiss——情感内容不适合工程感\n- **Theme**: Ink Classic for 深度思考; Kraft Paper for 温暖回忆\n- **Text scheme**: Text-only为主. 引言页用 pull quote，思考页用 marginalia essay\n- **Image source**: 用户实拍生活图（推荐）. Unsplash for 氛围图. 禁止AI生成人物情绪图\n- **Content shape**: 5-7 pages. Cover (核心感受) → 2-3 思考/引言 → 1 数据/对比 → closing quote\n- **Pitfalls**:\n  1. 梦核/氛围感装饰风 → 超出能力范围，明确告知用户\n  2. 过度鸡汤 → Editorial克制，用观察代替说教\n\n---\n\n## 推荐 · Recommended\n\n**Strong end-to-end, after specifying a subtype.**\n\n- **Recipes**: S11 (推荐清单 ledger), S02 (compare 对比), M02 (field-note for 实物展示), M07 (closing note)\n- **Style mode**: 取决于推荐类型——科技推荐用 Swiss × IKB Blue; 生活推荐用 Editorial × Kraft Paper; 设计推荐用 Editorial × Dune\n- **Theme**: 按推荐类型路由——科技→IKB Blue, 生活→Kraft Paper, 设计→Dune, 数据→Lemon Green\n- **Text scheme**: Text-beside-image. 清单页用 ledger，对比页用 compare\n- **Image source**: 用户实拍产品图（推荐）. Pexels for 产品场景. 截图 for App推荐\n- **Content shape**: 5-9 pages. Cover (推荐主题+数量) → 1-2 筛选标准 → 3-5 推荐项 → 对比/总结 → closing\n- **Pitfalls**:\n  1. 纯链接堆砌无筛选逻辑 → 每个推荐说明为什么选它\n  2. 推荐项信息不足 → 每项至少包含：名称、价格/评分、一句话推荐理由\n\nFile v7.8.0:references/components.md\n\n# Components Specification\n\n> xhs-crafter 组件规范——字体、排版、间距、容器\n> 画布基准：1080 × 1440（3:4）\n\n---\n\n## 一、Font Stacks\n\n### Editorial Magazine\n\n```css\n:root {\n  --serif-zh: \"Noto Serif SC\", \"Source Han Serif SC\", \"Songti SC\", serif;\n  --serif-en: \"Playfair Display\", \"Noto Serif SC\", serif;\n  --sans-zh:  \"Noto Sans SC\", \"Source Han Sans SC\", \"PingFang SC\", sans-serif;\n  --sans-en:  \"Inter\", \"Noto Sans SC\", sans-serif;\n  --mono:     \"IBM Plex Mono\", \"JetBrains Mono\", monospace;\n}\n```\n\n### Swiss International\n\n```css\n:root {\n  --sans:    \"Inter\", \"Noto Sans SC\", sans-serif;\n  --sans-zh: \"Noto Sans SC\", \"Source Han Sans SC\", \"PingFang SC\", sans-serif;\n  --mono:    \"IBM Plex Mono\", \"JetBrains Mono\", monospace;\n}\n```\n\n### 加载方式（系统字体回退栈，v7.6 移除 Google Fonts CDN）\n\n> v7.6 起，模板不再引用 Google Fonts CDN，改为依赖系统已安装字体。CSS `:root` 变量的字体回退栈会按顺序查找系统字体。若系统未安装指定字体，会回退到通用字体族（serif/sans-serif/monospace）。\n\n```\nEditorial 系统字体需求（推荐安装）:\n  Noto Serif SC / Source Han Serif SC / Songti SC (serif-zh)\n  Playfair Display (serif-en，可选，缺失时回退到 serif-zh)\n  Noto Sans SC / Source Han Sans SC / PingFang SC (sans-zh)\n  Inter (sans-en，可选，缺失时回退到 sans-zh)\n  IBM Plex Mono / JetBrains Mono / Consolas (mono)\n\nSwiss 系统字体需求（推荐安装）:\n  Inter / system-ui (sans)\n  Noto Sans SC / PingFang SC (sans-zh)\n  IBM Plex Mono / Consolas (mono)\n```\n\n---\n\n## 二、Type Scale\n\n### 字重铁律：\"越大越轻\"\n\n字号越大，字重越轻；字号越小，字重越重。这是印刷行业的百年传统——大标题用轻字重保持优雅，小文字用重字重保证可读。\n\n| 字号范围 | 字重 | 原因 |\n|---------|------|------|\n| ≥110px（Display/XL） | 500 | 大字号本身已有视觉重量，500足够醒目 |\n| 60-80px（MD/Pull Quote） | 500 | 中等字号需要适度加粗维持存在感 |\n| 32-46px（Lead/Body/Sub） | 400 | 阅读字号，400最舒适 |\n| 24-26px（Kicker/Meta/Label） | 500 | 小字号必须加粗才能在缩放后可读 |\n\n**反模式**：\n- 大标题用 700/900 字重 → 像PPT不像杂志\n- 正文用 300 字重 → 手机端模糊不可读\n- Swiss 大标题用 600 → 破坏极简感，Swiss 大标题必须 ≤300\n\n### Editorial Magazine（3:4 默认 1080×1440）\n\n> **权威定义**：本文档为字号/间距的唯一权威来源，模板必须与本文档保持一致。\n\n| Role | Class | Size | Weight | Tracking | Family |\n|------|-------|------|--------|----------|--------|\n| Display | `.h-display` | 136px | 500 | +.04em | serif-zh |\n| Section title | `.h-xl` | 110px | 500 | +.03em | serif-zh |\n| Mid title | `.h-md` | 60px | 500 | +.02em | serif-zh |\n| Subtitle | `.h-sub` | 46px | 400 italic | normal | serif-en |\n| Pull quote | `.pullquote` | 80px | 500 italic | normal | serif-zh |\n| Lead | `.lead` | 34px | 400 | normal | serif-zh |\n| Body | `.body` | 32px | 400 | normal | serif-zh |\n| Kicker | `.kicker` | 26px | 500 | +.22em | mono |\n| Meta | `.meta` | 24px | 500 | +.20em | mono |\n| Label | `.label` | 24px | 500 | +.20em | mono |\n| Stat number | `.stat-nb` | 72px | 500 | normal | serif-zh |\n| Step title | `.step-title` | 34px | 500 | normal | serif-zh |\n| Step desc | `.step-desc` | 28px | 400 | normal | serif-zh |\n| Ledger title | `.ledger-title` | 30px | 500 | normal | serif-zh |\n\n**CSS 示例：**\n\n```css\n.h-display {\n  font-family: var(--serif-zh);\n  font-size: 136px;\n  font-weight: 500;\n  letter-spacing: .04em;\n  line-height: 1.1;\n  color: var(--ink);\n}\n\n.h-xl {\n  font-family: var(--serif-zh);\n  font-size: 110px;\n  font-weight: 500;\n  letter-spacing: .03em;\n  line-height: 1.15;\n  color: var(--ink);\n}\n\n.h-md {\n  font-family: var(--serif-zh);\n  font-size: 60px;\n  font-weight: 500;\n  letter-spacing: .02em;\n  line-height: 1.2;\n  color: var(--ink);\n}\n\n.h-sub {\n  font-family: var(--serif-en);\n  font-size: 46px;\n  font-weight: 400;\n  font-style: italic;\n  letter-spacing: normal;\n  line-height: 1.3;\n  color: var(--muted);\n}\n\n.pullquote {\n  font-family: var(--serif-zh);\n  font-size: 80px;\n  font-weight: 500;\n  font-style: italic;\n  letter-spacing: normal;\n  line-height: 1.25;\n  color: var(--ink);\n}\n\n.lead {\n  font-family: var(--serif-zh);\n  font-size: 34px;\n  font-weight: 400;\n  letter-spacing: normal;\n  line-height: 1.7;\n  color: var(--ink);\n}\n\n.body {\n  font-family: var(--serif-zh);\n  font-size: 32px;\n  font-weight: 400;\n  letter-spacing: normal;\n  line-height: 1.8;\n  color: var(--ink);\n}\n\n.kicker {\n  font-family: var(--mono);\n  font-size: 26px;\n  font-weight: 500;\n  letter-spacing: .22em;\n  text-transform: uppercase;\n  line-height: 1.4;\n  color: var(--accent);\n}\n\n.meta {\n  font-family: var(--mono);\n  font-size: 24px;\n  font-weight: 500;\n  letter-spacing: .20em;\n  text-transform: uppercase;\n  line-height: 1.4;\n  color: var(--muted);\n}\n```\n\n### 封面/封底满铺图页标题颜色\n\n封面和封底使用满铺背景图时，标题必须使用纯白色 + text-shadow，确保与任何背景图都有足够对比度：\n\n```css\n.hero-content .h-display { color: #ffffff; text-shadow: 0 2px 16px rgba(0,0,0,.45); }\n.hero-content .h-xl { color: #ffffff; text-shadow: 0 2px 12px rgba(0,0,0,.35); }\n```\n\n**硬规则**：\n- 满铺图页标题禁止使用 `#ece2cf`（暖米色）——与暖调背景图太接近\n- 必须使用 `#ffffff`（纯白）+ `text-shadow` 确保可读性\n- text-shadow 不可省略——纯白字在亮色区域仍需阴影托底\n\n---\n\n### Swiss International（3:4 默认 1080×1440）\n\n| Role | Class | Size | Weight | Family |\n|------|-------|------|--------|--------|\n| Hero | `.h-hero` | 240px | 200 | sans |\n| Statement | `.h-statement` | 180px | 200 | sans |\n| Section title | `.h-xl` | 128px | 300 | sans |\n| Mid title | `.h-md` | 60px | 400 | sans |\n| Mega number | `.num-mega` | 216px | 200 | sans |\n| XL number | `.num-xl` | 156px | 200 | sans |\n| Lead | `.lead` | 34px | 400 | sans-zh |\n| Body | `.body` | 32px | 400 | sans-zh |\n| Category | `.t-cat` | 26px | 600 | sans |\n| Meta | `.t-meta` | 24px | 500 | mono |\n\n**CSS 示例：**\n\n```css\n.h-hero {\n  font-family: var(--sans);\n  font-size: 240px;\n  font-weight: 200;\n  line-height: .9;\n  letter-spacing: -.03em;\n  color: var(--ink);\n}\n\n.h-statement {\n  font-family: var(--sans);\n  font-size: 180px;\n  font-weight: 200;\n  line-height: .92;\n  letter-spacing: -.02em;\n  color: var(--ink);\n}\n\n.h-xl {\n  font-family: var(--sans);\n  font-size: 128px;\n  font-weight: 300;\n  line-height: 1;\n  letter-spacing: -.02em;\n  color: var(--ink);\n}\n\n.h-md {\n  font-family: var(--sans);\n  font-size: 60px;\n  font-weight: 400;\n  line-height: 1.15;\n  letter-spacing: normal;\n  color: var(--ink);\n}\n\n.num-mega {\n  font-family: var(--sans);\n  font-size: 216px;\n  font-weight: 200;\n  line-height: .9;\n  letter-spacing: -.03em;\n  color: var(--accent);\n}\n\n.num-xl {\n  font-family: var(--sans);\n  font-size: 156px;\n  font-weight: 200;\n  line-height: .9;\n  letter-spacing: -.02em;\n  color: var(--accent);\n}\n\n.lead {\n  font-family: var(--sans-zh);\n  font-size: 34px;\n  font-weight: 400;\n  line-height: 1.7;\n  letter-spacing: normal;\n  color: var(--ink);\n}\n\n.body {\n  font-family: var(--sans-zh);\n  font-size: 32px;\n  font-weight: 400;\n  line-height: 1.75;\n  letter-spacing: normal;\n  color: var(--ink);\n}\n\n.t-cat {\n  font-family: var(--sans);\n  font-size: 26px;\n  font-weight: 600;\n  letter-spacing: .12em;\n  text-transform: uppercase;\n  line-height: 1.4;\n  color: var(--accent);\n}\n\n.t-meta {\n  font-family: var(--mono);\n  font-size: 24px;\n  font-weight: 500;\n  letter-spacing: .08em;\n  text-transform: uppercase;\n  line-height: 1.4;\n  color: var(--grey-3);\n}\n```\n\n---\n\n## 三、Chinese Title Length Bands\n\n中文标题字数与字号的映射关系——字数越多，字号越小，保证标题不换行或至多换一行。\n\n### 标题一致性铁律\n\n**同一套卡片中，所有内容页主标题必须使用同一字号 class。**\n\n| 页面类型 | Editorial | Swiss | 说明 |\n|---------|-----------|-------|------|\n| 封面 (P01) | `.h-display` 136px | `.h-hero`/`.h-statement` | 允许更大字号 |\n| 内容页 (P02-P08) | `.h-xl` 110px | `.h-xl` 128px | **必须统一** |\n| 封底 (P09) | `.h-display` 136px | 视设计而定 | 与封面同级，形成\"书挡\" |\n\n**适配方法**：标题太长时拆为两行（`<br>`），太短时加副标题增加视觉重量。**不得降级到 `.h-md`**。\n\n**反模式**：不同内容页混用 `.h-xl` 和 `.h-md` → 视觉不统一，用户一眼看出不一致。\n\n### Editorial Magazine\n\n| 字数范围 | 推荐字号 | 使用 Class | 备注 |\n|----------|----------|------------|------|\n| 1–3 字 | 136px | `.h-display` | 单字 / 双字标题，最大冲击 |\n| 4–6 字 | 110px | `.h-xl` | 常规章节标题 |\n| 7–10 字 | 60px | `.h-md` | 中等长度标题 |\n| 11–16 字 | 46px | `.h-sub` | 长标题，降级为副标题尺度 |\n| 17+ 字 | 34px | `.lead` | 超长标题，按 lead 处理 |\n\n### Swiss International\n\n| 字数范围 | 推荐字号 | 使用 Class | 备注 |\n|----------|----------|------------|------|\n| 1–2 字 | 240px | `.h-hero` | 极简冲击，1–2 字 |\n| 3–4 字 | 180px | `.h-statement` | 声明式标题 |\n| 5–8 字 | 128px | `.h-xl` | 章节标题 |\n| 9–14 字 | 60px | `.h-md` | 中等标题 |\n| 15+ 字 | 32px | `.lead` | 长标题降级 |\n\n> **硬规则**：标题最多换行 2 次。如果预估会超过 2 行，必须降级到下一档字号。\n\n---\n\n## 四、Minimum Readable Sizes（Mobile-Safe）\n\n在 1080×1440 画布上，以下尺寸保证在手机端缩放后仍可读（约 360×480 逻辑像素下）。\n\n| 角色 | 最小字号 | 说明 |\n|------|----------|------|\n| Body 正文 | 24px | 绝对底线，推荐 26px |\n| Lead 导语 | 28px | 正文与标题的过渡 |\n| Caption 图注 | 20px | 辅助信息，可略小 |\n| Label 标签 | 20px | 按钮 / 标签文字 |\n| Cell title 卡片标题 | 24px | 卡片内主标题 |\n| Number annotation 数字注释 | 22px | 大数字旁的说明文字 |\n\n> **硬规则**：任何文字不得低于 18px。18px 仅用于 meta 类辅助信息，且必须使用高对比度（ink 色）。\n\n---\n\n## 五、Image Container Ratios\n\n### 可用比例\n\n| Class | 比例 | padding-bottom | 典型用途 |\n|-------|------|----------------|----------|\n| `.r-3x4` | 3:4 | 133.33% | 小红书原生比例，人像、产品 |\n| `.r-1x1` | 1:1 | 100% | 头像、图标、方形产品 |\n| `.r-4x3` | 4:3 | 75% | 横版产品、场景 |\n| `.r-3x2` | 3:2 | 66.67% | 经典横版，风景 |\n| `.r-16x9` | 16:9 | 56.25% | 视频截图、宽屏 |\n| `.r-16x10` | 16:10 | 62.5% | 笔记本屏幕截图 |\n| `.r-21x9` | 21:9 | 42.86% | 超宽屏、电影感 |\n\n**CSS 实现：**\n\n```css\n.r-3x4  { aspect-ratio: 3 / 4; }\n.r-1x1  { aspect-ratio: 1 / 1; }\n.r-4x3  { aspect-ratio: 4 / 3; }\n.r-3x2  { aspect-ratio: 3 / 2; }\n.r-16x9 { aspect-ratio: 16 / 9; }\n.r-16x10{ aspect-ratio: 16 / 10; }\n.r-21x9 { aspect-ratio: 21 / 9; }\n```\n\n### 使用指引\n\n- **小红书卡片内嵌图**：优先 `.r-3x4`（与卡片比例一致）或 `.r-4x3`（横版内容）。\n- **截图展示**：桌面用 `.r-16x10`，移动端用 `.r-3x4` 或 `.r-9x16`。\n- **产品图**：`.r-1x1` 或 `.r-3x4`。\n- **风景 / 场景**：`.r-3x2` 或 `.r-16x9`。\n- **同一卡片内**：所有图片比例必须统一，禁止混用不同比例。\n\n> **硬规则**：图片容器必须使用 aspect-ratio，禁止用固定高度。图片用 `object-fit: cover` 填充。\n\n---\n\n## 六、Spacing Tokens（Swiss）\n\nSwiss 体系使用 8px 基础网格的间距 token。\n\n| Token | 值 | 典型用途 |\n|-------|----|----------|\n| `--sp-3` | 8px | 图标与文字间距、内联元素间距 |\n| `--sp-4` | 12px | 紧凑内边距、标签内间距 |\n| `--sp-5` | 16px | 小卡片内边距、列表项间距 |\n| `--sp-6` | 24px | 标准内边距、段落间距 |\n| `--sp-7` | 32px | 区块间距、卡片内边距 |\n| `--sp-8` | 40px | 大区块间距 |\n| `--sp-9` | 48px | 章节间距 |\n| `--sp-10` | 64px | 大章节间距 |\n| `--sp-11` | 80px | 页面级间距 |\n| `--sp-12` | 120px | 重大分隔 |\n| `--sp-13` | 160px | 页面顶部 / 底部留白 |\n\n**CSS 定义：**\n\n```css\n:root {\n  --sp-3:  8px;\n  --sp-4:  12px;\n  --sp-5:  16px;\n  --sp-6:  24px;\n  --sp-7:  32px;\n  --sp-8:  40px;\n  --sp-9:  48px;\n  --sp-10: 64px;\n  --sp-11: 80px;\n  --sp-12: 120px;\n  --sp-13: 160px;\n}\n```\n\n### 使用规则\n\n1. **所有间距必须使用 token**，禁止硬编码像素值。\n2. **同一层级元素间距一致**——所有段落间距用同一个 token。\n3. **间距递增**——从内到外，token 序号递增（如卡片内 --sp-6，卡片间 --sp-8）。\n4. **Editorial 体系**同样可使用这些 token，但允许更灵活的微调（如行首缩进 2em）。\n\n---\n\n## 七、Card Fills（Swiss Only）\n\nSwiss 体系的卡片填充样式，**互斥使用**——一张卡片只能选择一种 fill。\n\n### 可用 Fill\n\n| Class | 效果 | 适用场景 |\n|-------|------|----------|\n| `.card-ink` | 背景为 ink 色，文字为 paper 色 | 强调卡片、数据高亮 |\n| `.card-accent` | 背景为 accent 色，文字为 accent-on 色 | CTA 卡片、关键指标 |\n| `.card-fill` | 背景为 grey-1 色，文字为 ink 色 | 次级信息卡片、引用块 |\n| `.card-outlined` | 无背景，1px grey-2 边框，文字为 ink 色 | 轻量卡片、列表项 |\n\n**CSS 实现：**\n\n```css\n.card-ink {\n  background: var(--ink);\n  color: var(--paper);\n  padding: var(--sp-7);\n}\n\n.card-accent {\n  background: var(--accent);\n  color: var(--accent-on);\n  padding: var(--sp-7);\n}\n\n.card-fill {\n  background: var(--grey-1);\n  color: var(--ink);\n  padding: var(--sp-7);\n}\n\n.card-outlined {\n  background: transparent;\n  border: 1px solid var(--grey-2);\n  color: var(--ink);\n  padding: var(--sp-7);\n}\n```\n\n### 硬规则\n\n1. **互斥**：一张卡片只用一种 fill，禁止组合（如 `.card-ink.card-accent`）。\n2. **card-accent 面积控制**：单张卡片内 accent 填充面积 ≤ 30%。\n3. **card-ink 内禁止使用 muted 色**——ink 背景上只有 paper 和 accent-on 可读。\n4. **card-outlined 不加 background**——透明背景是设计意图，不是遗漏。\n5. **同一组卡片 fill 必须统一**——禁止同一组内混用不同 fill。\n\n---\n\n## 八、Screenshot Containers\n\n### .frame-shot\n\n截图容器组件，支持多种参数组合。\n\n**参数：**\n\n| 参数 | 值 | 说明 |\n|------|----|------|\n| `ratio` | `3x4` / `1x1` / `4x3` / `3x2` / `16x9` / `16x10` / `21x9` | 容器比例 |\n| `corners` | `sq` / `sm` / `md` | 圆角大小：sq=0, sm=4px, md=12px |\n| `shadow` | `none` / `soft` / `ed` | 阴影：none=无, soft=柔和扩散, ed=硬边投影 |\n| `bg` | `paper` / `grid` / `dot` / `grey-1` / `ink` | 容器背景 |\n| `inset` | `none` / `sub` / `bal` | 内边距：none=0, sub=8px, bal=24px |\n\n**CSS 实现：**\n\n```css\n.frame-shot {\n  overflow: hidden;\n  position: relative;\n}\n\n/* ── corners ── */\n.frame-shot[data-corners=\"sq\"] { border-radius: 0; }\n.frame-shot[data-corners=\"sm\"] { border-radius: 4px; }\n.frame-shot[data-corners=\"md\"] { border-radius: 12px; }\n\n/* ── shadow ── */\n.frame-shot[data-shadow=\"none\"] { box-shadow: none; }\n.frame-shot[data-shadow=\"soft\"] { box-shadow: 0 8px 32px rgba(0,0,0,.12); }\n.frame-shot[data-shadow=\"ed\"]   { box-shadow: 4px 4px 0 rgba(0,0,0,.15); }\n\n/* ── bg ── */\n.frame-shot[data-bg=\"paper\"] { background: var(--paper); }\n.frame-shot[data-bg=\"grid\"]  {\n  background-image:\n    linear-gradient(var(--line) 1px, transparent 1px),\n    linear-gradient(90deg, var(--line) 1px, transparent 1px);\n  background-size: 24px 24px;\n  background-color: var(--paper);\n}\n.frame-shot[data-bg=\"dot\"]   {\n  background-image: radial-gradient(circle, var(--line) 1px, transparent 1px);\n  background-size: 16px 16px;\n  background-color: var(--paper);\n}\n.frame-shot[data-bg=\"grey-1\"]{ background: var(--grey-1); }\n.frame-shot[data-bg=\"ink\"]   { background: var(--ink); }\n\n/* ── inset ── */\n.frame-shot[data-inset=\"none\"] { padding: 0; }\n.frame-shot[data-inset=\"sub\"]  { padding: 8px; }\n.frame-shot[data-inset=\"bal\"]  { padding: 24px; }\n```\n\n---\n\n### Device Wrappers\n\n设备外壳容器，模拟浏览器或手机边框。\n\n#### .device-browser\n\n```css\n.device-browser {\n  border-radius: 12px;\n  overflow: hidden;\n  border: 1px solid var(--grey-2);\n  background: var(--paper);\n}\n\n.device-browser::before {\n  content: \"\";\n  display: block;\n  height: 40px;\n  background: var(--grey-1);\n  border-bottom: 1px solid var(--grey-2);\n  /* 三个圆点模拟浏览器控件 */\n  background-image:\n    radial-gradient(circle at 20px 20px, var(--grey-3) 4px, transparent 4px),\n    radial-gradient(circle at 40px 20px, var(--grey-3) 4px, transparent 4px),\n    radial-gradient(circle at 60px 20px, var(--grey-3) 4px, transparent 4px);\n  background-repeat: no-repeat;\n}\n```\n\n#### .device-phone\n\n```css\n.device-phone {\n  border-radius: 32px;\n  overflow: hidden;\n  border: 3px solid var(--ink);\n  background: var(--paper);\n}\n\n.device-phone::before {\n  content: \"\";\n  display: block;\n  height: 28px;\n  background: var(--ink);\n  /* 顶部刘海 */\n  clip-path: polygon(0 0, 100% 0, 100% 100%, 55% 100%, 50% 60%, 45% 100%, 0 100%);\n}\n```\n\n---\n\n### Style-Locked Defaults\n\n不同体系下截图容器的默认参数锁定：\n\n| 参数 | Swiss 默认 | Editorial 默认 |\n|------|------------|----------------|\n| `corners` | `sq` | `md` |\n| `shadow` | `ed` | `soft` |\n| `bg` | `paper` | `paper` |\n| `inset` | `none` | `sub` |\n\n**说明：**\n\n- **Swiss**：方角 + 硬边投影 = 理性、精确。\n- **Editorial**：圆角 + 柔和阴影 = 温润、纸感。\n\n> **硬规则**：除非用户明确要求，否则不修改体系默认值。如需覆盖，必须同时说明原因。\n\n---\n\n## 九、使用速查\n\n### 按体系选择组件\n\n| 需求 | Editorial | Swiss |\n|------|-----------|-------|\n| 标题字体 | serif-zh / serif-en | sans |\n| 正文字体 | serif-zh | sans-zh |\n| 辅助字体 | mono | mono |\n| 间距体系 | 灵活（可用 em） | 严格 token |\n| 卡片填充 | 无 fill 体系 | card-ink / card-accent / card-fill / card-outlined |\n| 截图圆角 | md（12px） | sq（0px） |\n| 截图阴影 | soft | ed |\n| 配色变量 | paper / paper-2 / ink / muted / line / accent / accent-soft | paper / ink / grey-1 / grey-2 / grey-3 / accent / accent-on |\n\n### 组合禁忌\n\n| 禁止 | 原因 |\n|------|------|\n| Editorial 字体 + Swiss 间距 token | 体系不匹配，视觉不协调 |\n| Swiss fill + Editorial 配色变量 | 变量名不兼容 |\n| 同一卡片混用不同 ratio 图片 | 视觉节奏断裂 |\n| card-accent + 大面积 accent-soft | 双重强调 = 无强调 |\n| .h-hero 用于超过 2 字的标题 | 字号过大，换行后失去冲击力 |\n| .num-mega 使用 ink 色 | 大数字必须用 accent 色，否则无视觉锚点 |\n\nFile v7.8.0:references/content-planning.md\n\n# Content Planning\n\n## Compression Ladder\n\nStart from the user's original text and compress in layers:\n\n1. **Core claim**: one sentence — what is this article really saying?\n2. **Viewer promise**: what the reader gets from swiping through the image set\n3. **Section map**: 4-8 ideas that become pages\n4. **Page hooks**: short, concrete, not abstract\n5. **Body fragments**: only the words needed to explain the visual\n\n**Do not put the full article on images.** The image set is a visual outline that makes the user want to read the caption/body.\n\n## Page Plan Template\n\nBefore writing any HTML, fill out this plan:\n\n```text\nTitle:\nCategory:          (→ see category-cookbook.md)\nStyle:             Editorial / Swiss\nTheme:             (→ see theme-presets.md)\nImage assets:      (user photos / search / AI generate / none)\n\n01 Cover\n- Hook:            (1-second hook line)\n- Visual:          (cover image strategy)\n- Layout:          M01 / M16 / S01\n\n02 Page\n- Point:           (core argument)\n- Copy:            (body text fragment)\n- Visual:          (data / quote / image / screenshot)\n- Layout:          M04 / M08 / S06 / ...\n\n...\n```\n\n## Page Roles — Use Variety\n\nUse varied roles instead of repeating the same card page type. A 7-page set should have at least 5 distinct shapes:\n\n| Role | Description | Typical Layout |\n|------|-------------|---------------|\n| Hook cover | 1-second stopper | M01 / M16 / S01 |\n| Problem scene | Set up the tension | M03 / S02 |\n| Misconception vs reality | Two-column contrast | S02 / M15 |\n| Checklist | Numbered items | M04 / S05 |\n| Data evidence | KPI / stats / ledger | M12 / S09 / S11 |\n| Pull quote | One big quote | M04 / M05 |\n| Step-by-step flow | Pipeline / process | M08 / M14 / S06 |\n| Screenshot evidence | Tool UI proof | S08 / frame-shot |\n| Summary / closing | \"Remember these three\" | M07 / M16 |\n\n**Avoid repeating \"title + lead + 3 rows\" more than twice in one set.**\n\n## Cover Hook Patterns\n\nUse one of these proven patterns:\n\n- \"终于有 Mac 版了\"\n- \"新手别急着买\"\n- \"这个功能真的改变用法\"\n- \"我替你踩过坑了\"\n- \"先看这 5 个点\"\n- \"不要被装备带着走\"\n- \"从此不用手动...\"\n\n**Avoid:**\n- Overlong complete article titles as cover text\n- Vague hype without a concrete object (\"重磅！\" \"速看！\")\n- Multiple unrelated claims on one cover\n\n## Copy Rules\n\n- Titles should be plain and sharp\n- Avoid abstract labels like \"背景介绍\" unless the page is actually context\n- Use verbs and consequences: \"高帮鞋会让脚更闷\" is better than \"鞋子选择\"\n- For product updates, lead with the user-facing change, then add the feature name\n- For AI/tool posts, lead with workflow change: faster capture, less manual work, cross-app automation\n\n## Image-Led Sequence\n\nWhen the user has multiple good lifestyle photos (旅行/户外/自家成菜/家居), front-load the strongest photo on page 1 and let pages 2-3 carry the text/data.\n\nPattern:\n```\nP1      M16 Image-Led Cover    ← best photo, full bleed, restrained title\nP2      S11 / M05 / M10        ← text-heavy: ledger / checklist / mini-data\nP3      M02 Field-Note Photo   ← second-best photo, in a frame, with caption\nP4-N    M02 / M11              ← more field notes or marginalia essays\nP_last  M07 / M04              ← closing note or pull quote\n```\n\n**Hard rule: never two M16 in a row.** After a full-bleed cover the eye needs to settle on text before another big image.\n\n## Page Count Guidance\n\n| Source length | Recommended pages |\n|--------------|-------------------|\n| 600-1000 Chinese characters | 5-7 images |\n| 1000-1800 Chinese characters | 7-9 images |\n| Very long source | Compress to 8-10 images, rest in caption/body |\n\nIf several pages have large empty lower areas, **merge adjacent ideas**.\n\n## Matching Visuals To Content\n\nUse visuals only when they support the point:\n\n| Visual type | When to use |\n|------------|-------------|\n| Screenshot | Proof of a product feature or UI |\n| Photo | Scene, object, person, outdoor atmosphere |\n| Generated image | Missing scene, conceptual hero, stylized illustration |\n| Diagram | Flow, cross-app chain, checklist, system relation |\n\nGenerated image prompts should be short and role-specific:\n```text\nEditorial documentary photo for a hiking gear guide, summer mountain trail,\nlightweight long-sleeve outfit, natural sunlight, clean composition, no text, no logo, 3:4.\n```\n\n## Captions And Metadata\n\nSmall recurring elements help the set feel designed:\n\n- Category row: `AI TOOL / UPDATE / 2026`\n- Issue row: `SUMMER HIKING / BEGINNER GUIDE`\n- Page number: `03 / 08`\n- Compact labels: `DO`, `DON'T`, `WHY`, `NOTE`\n\nKeep these consistent. They should support orientation, not become decoration.\n\nFile v7.8.0:references/image-overlay.md\n\n# Image Overlay & Text-on-Image Rules\n\nTwo rules that govern any poster where text sits on top of an image — full-bleed background, large photo well with title bar, or generated/AI image with text overlay.\n\n## Rule 1 — Selection first, mask only if selection fails\n\nThe default editorial-magazine answer is **no mask**. Real magazine covers (Kinfolk, Cereal, Apartamento, Monocle) almost never lay a uniform black gradient over a hero photo. They rely on **photo selection + composition** so text lands in a quiet zone naturally.\n\nApply the steps in order. Stop at the first one that passes.\n\n### Step 1 — Photo selection (the main lever)\n\nBefore picking a mask, verify the photo qualifies for full-bleed treatment. Both tests must pass:\n\n**Quiet-zone test**: at least one band of ≥30% canvas (full width × ≥30% height, or full height × ≥30% width) is low-detail / low-contrast / uniform. Examples: out-of-focus background, deep shade, fog, calm water, plain sky, blurred grass. This band is where the title will land.\n\n**Light test**: the photo carries atmospheric / restrained light — overcast, dawn fog, golden hour, forest understory, film softness, dusk silhouette. Reject high-saturation noon shots, on-camera flash, generic stock cheerfulness.\n\nIf either test fails, **the photo is wrong for M16**. Fall back to M01 (split-layout cover with photo in a frame), or shoot/source again.\n\n### Step 2 — Compose without a mask first\n\nPlace the title inside the qualified quiet zone. Run the thumbnail contrast check (Step 4). If it reads clean, ship as-is.\n\nA no-mask cover signals craft. A heavily masked cover signals \"we couldn't find the right photo.\" Try Step 2 every time before reaching for Step 3.\n\n### Step 3 — Localized, image-toned tint (fallback only)\n\nOnly when Step 2 fails the contrast check. Three rules:\n\n1. **Localized, not full-canvas.** Tint only the title region. Use `radial-gradient` centered on the title block, or a one-sided linear gradient that fades to fully transparent past the title. Never `inset: 0` over the whole image with a uniform alpha curve.\n\n2. **Image-toned, not black.** Sample a dark tone already in the photo and use it as the tint color. Forest → deep moss `#1a2818`. Dusk → tea-rose dusk `#4a2638`. Snow → cool grey-blue `#2a3438`. Pure black `#000` reads as \"annotation layer,\" not \"atmospheric depth.\"\n\n3. **Soft, not opaque.** Peak alpha 0.15-0.30 in the title region, falling to 0 outside. If you need >0.40 to read, the photo failed Step 1 — go back.\n\n```css\n/* Example: title in lower-left, image-toned soft tint */\n.hero-bleed::after {\n  content: \"\";\n  position: absolute; inset: 0;\n  background: radial-gradient(\n    60% 45% at 25% 80%,\n    rgba(26, 40, 24, 0.28) 0%,\n    rgba(26, 40, 24, 0.0) 100%);\n  pointer-events: none;\n}\n```\n\n### Step 4 — Thumbnail contrast check (always)\n\nWhether or not you applied a tint:\n- Render the PNG, downscale to 360px wide, and look\n- Title strokes must be legible without zoom\n- If title looks like it's \"fighting\" the photo → swap photo or shift title to a different quiet zone, **not** strengthen the mask\n\n### Banned\n\n- Uniform full-canvas vertical falloff (`rgba(0,0,0,.55) → .10 → .10 → .80`). That is game-key-art treatment, not editorial\n- Pure black mask color. Always image-toned\n- Flat black/white rectangle behind text\n- `mix-blend-mode: difference` for readability\n- `img { opacity: .6 }` — kills the photo's depth\n- Reaching for Step 3 before honestly attempting Step 1 with a better photo\n\n---\n\n## Rule 2 — Place text away from subject / face zones\n\nPosters in 旅行/游戏/影视/穿搭/美食 frequently use a real photo as the hero. The photo has a subject — a face, a hand, a product, a peak. Text that overlaps the subject reads as graffiti, not editorial.\n\n### Subject zone discovery\n\nBefore designing the title position on a hero photo, look at the image and observe:\n\n1. Where is the **primary subject's face / focal feature**?\n2. Where is the **edge of the subject's silhouette**?\n3. Where is the **largest open / low-detail area**?\n\nRecord the answers as a comment in the HTML next to the hero block:\n\n```html\n<!-- subject map (SpaceX cover hero):\n     rocket launch flame: 50% x 60% y, occupies ~30% of frame\n     smoke cloud: lower 40% of frame\n     safe text zone: top band (0-25% y) and upper-left corner\n-->\n```\n\n### Safe-zone placement rules\n\nGiven the subject map, place text in this order of preference:\n\n1. **Above + below** the subject (kicker top, title bottom). 90% of full-bleed covers should do this\n2. **One side** — if subject occupies one vertical column, text fills the opposite column\n3. **Diagonal corner** — only when subject is in one corner and opposite corner is genuinely empty. Rare\n\n**Never place display titles across the face.** A 88px Chinese title cutting through a person's eyes is destructive even with a mask.\n\n### Composition discipline (editorial look)\n\n- **Asymmetric placement.** Titles offset to one side / one corner read more confident than dead-centered\n- **Generous negative space.** Title should occupy ≤40% of the canvas\n- **Title in one quiet zone, only one.** Splitting the title into two zones (top + bottom) is fine; splitting into three is busy\n- **Title never overlaps the subject silhouette.** If the only safe placement requires crossing the subject's edge, switch modes\n\n### Crop guards\n\n| Subject location in raw image | Recommended `object-position` for 3:4 crop |\n|------------------------------|---------------------------------------------|\n| Face/focus in upper third | `center 25%` |\n| Face/focus in middle third | `center center` |\n| Face/focus in lower third | `center 70%` |\n| Wide landscape, no single subject | `center 35%` |\n| Vertical portrait, full body | `center top` |\n\n---\n\n## Checklist before delivery\n\nRun this for every poster that has text touching an image:\n\n- [ ] Photo passes quiet-zone test AND light test\n- [ ] Tried no-mask composition first. Tint only added if contrast check failed\n- [ ] If tinted: localized, image-toned color (not pure black), peak alpha ≤ 0.30\n- [ ] No full-canvas vertical falloff present\n- [ ] Subject map documented as a comment near the hero block\n- [ ] No display title (≥72px) overlaps a face/hand/key product feature/subject silhouette\n- [ ] Title occupies ≤40% of canvas. Asymmetric placement preferred\n- [ ] `object-position` chosen intentionally, not left at default\n- [ ] Thumbnail test passed (downscale to 360px wide; title still legible)\n\nFile v7.8.0:references/image-sources.md\n\n# Image Sources Specification\n\n> 图片来源规范：免费图库 API、选图规则与裁切指南。\n\n> ⚠️ **外部能力完整披露（v7.7 新增，用户须知）**\n>\n> 本文档涉及 **3 类外部数据流**，每类均需用户独立明确同意后才能使用（默认不启用）：\n>\n> | 外部能力 | 数据流方向 | 发送内容 | 风险等级 | 同意门控 |\n> |---------|-----------|---------|---------|---------|\n> | 图库 API 搜索（Pexels/Pixabay/Unsplash） | 出站 | 搜索关键词（中文/英文） | 中（关键词可能暗示文章主题） | Step 1 图片三选一门控，用户选 B |\n> | AI 生图 API（trae-api-cn.mchost.guru） | 出站 | 生图 prompt（可能含文章主题/场景描述） | 中高（prompt 可能泄露文章创意） | Step 1 图片三选一门控，用户选 C |\n> | 图片 CDN 下载（images.pexels.com 等） | 入站 | 无出站数据，仅下载图片文件 | 低（下载内容受 ALLOWED_HOSTS 白名单限制） | 随图库搜索/AI 生图一并授权 |\n>\n> **不会发生的数据流**：文章原文（MD 全文）**不会**被上传到任何外部服务。图库搜索只发送关键词，AI 生图只发送 prompt（由 AI 根据页面角色生成，非文章原文复制）。\n\n---\n\n## 三大免费图库\n\n### 1. Pexels\n\n| 项目 | 说明 |\n|------|------|\n| **网址** | `pexels.com/api`（脱敏，实际调用时用环境变量配置的 endpoint） |\n| **特点** | 支持中文搜索；通用/热门场景覆盖好 |\n| **API endpoint** | `api.pexels.com/v1/search`（脱敏显示，实际 URL 在运行时拼接） |\n| **认证** | 需要 API Key（环境变量 `PEXELS_API_KEY`，免费层：200 次/小时） |\n| **备用** | 浏览 `pexels.com/search/{keyword}/` |\n| **版权** | 免费商用，无需署名（但建议署名） |\n\n**API 调用方式**（实际执行时用环境变量中的 Key）：\n\n```bash\n# 用 curl.exe（非 PowerShell 别名）下载搜索结果\ncurl.exe -s -H \"Authorization: $env:PEXELS_API_KEY\" \\\n  \"https://api.pexels.com/v1/search?query=<keyword>&per_page=5\"\n```\n\n**响应关键字段**（用于提取图片 CDN URL）：\n\n```json\n{\n  \"photos\": [\n    {\n      \"id\": 12345,\n      \"width\": 4000,\n      \"height\": 6000,\n      \"src\": {\n        \"original\": \"https://images.pexels.com/photos/…\",\n        \"large2x\": \"https://images.pexels.com/photos/…?w=1600\",\n        \"large\": \"https://images.pexels.com/photos/…?w=940\"\n      },\n      \"alt\": \"workspace with laptop and coffee\"\n    }\n  ]\n}\n```\n\n---\n\n### 2. Unsplash\n\n| 项目 | 说明 |\n|------|------|\n| **网址** | `unsplash.com/developers`（脱敏显示） |\n| **特点** | 摄影质量最高，尤其擅长人物/生活方式/空间 |\n| **API endpoint** | `api.unsplash.com/search/photos`（脱敏显示） |\n| **认证** | 需要 API Key（免费层：50 次/小时） |\n| **备用** | 浏览 `unsplash.com/s/photos/{keyword}` |\n| **版权** | 免费商用，Unsplash License |\n\n**API 调用方式**：\n\n```bash\ncurl.exe -s -H \"Authorization: Client-ID <ACCESS_KEY>\" \\\n  \"https://api.unsplash.com/search/photos?query=<keyword>&per_page=5\"\n```\n\n**响应关键字段**：\n\n```json\n{\n  \"results\": [\n    {\n      \"id\": \"abc123\",\n      \"width\": 5472,\n      \"height\": 3648,\n      \"urls\": {\n        \"raw\": \"https://images.unsplash.com/photo-…\",\n        \"full\": \"https://images.unsplash.com/photo-…?w=2160\",\n        \"regular\": \"https://images.unsplash.com/photo-…?w=1080\"\n      },\n      \"alt_description\": \"minimal interior design\",\n      \"user\": { \"name\": \"Photographer Name\" }\n    }\n  ]\n}\n```\n\n---\n\n## 图片选择规则（Image Selection Rules）\n\n### 优先级排序\n\n```\n1. 用户提供的图片（最真实，最无\"AI 感\"）\n2. 免费图库搜索（匹配页面视觉角色，非泛泛装饰）\n3. AI 生成图片（仅在确实增加价值时使用，通常 1-2 页）\n```\n\n### 选图原则\n\n- **匹配视觉角色**：图片应服务于页面的视觉叙事，而非泛泛装饰\n- **风格一致**：同一组卡片内图片风格应统一（色调、构图、氛围）\n- **避免\"AI 感\"**：优先真实摄影，生成图片应自然、不夸张\n- **生成图片限制**：不嵌入标题、页码、Logo 或虚假 UI 标签\n\n### 尺寸与比例\n\n| 规则 | 要求 |\n|------|------|\n| **比例匹配** | 图片比例必须匹配布局槽位（3:4 竖版、16:9 横版等） |\n| **最小宽度** | 1600px（适配高 DPI 显示器） |\n| **推荐宽度** | 2000-4000px |\n| **格式** | 优先 JPEG（照片）、PNG（UI/截图） |\n\n---\n\n## 主体感知裁切（Subject-Aware Cropping）\n\n始终根据照片主体位置设置 `object-position` 内联样式：\n\n| 主体位置 | object-position | 典型场景 |\n|---------|-----------------|---------|\n| 主体偏上 | `center 25-35%` | 天空、建筑顶部、头部特写 |\n| 主体居中 | `center 50%`（默认） | 居中构图、正面肖像 |\n| 主体偏中下 | `center 55-65%` | 半身像、桌面物品 |\n| 主体偏下/前景 | `center 70-80%` | 地面物品、低角度拍摄 |\n\n**使用示例：**\n\n```html\n<!-- 人物半身照，主体偏中下 -->\n<img src=\"…\" style=\"object-fit:cover;object-position:center 60%\">\n\n<!-- 建筑照片，主体偏上 -->\n<img src=\"…\" style=\"object-fit:cover;object-position:center 30%\">\n\n<!-- 居中构图，默认 -->\n<img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n```\n\n### 裁切决策流程\n\n```\n1. 观察照片主体位置\n   ↓\n2. 选择对应的 object-position 范围\n   ↓\n3. 微调百分比确保主体完整可见\n   ↓\n4. 在目标比例下验证裁切效果\n```\n\n### 注意事项\n\n- `object-fit:cover` 会裁切图片以填满容器，必须配合正确的 `object-position`\n- `object-fit:contain` 保持完整但可能留白，适用于 UI 截图\n- 人像裁切时避免切到面部关键区域（眼睛、嘴巴）\n- 产品图裁切时确保产品主体完整可见\n\n---\n\n## Unsplash 直链下载（无需 API Key）\n\n当 AI 生图 API 返回相同占位图时，使用 Unsplash 直链作为备选方案。\n\n### 直链格式\n\n```\nhttps://images.unsplash.com/photo-{id}?w={width}&h={height}&fit=crop&auto=format&q={quality}\n```\n\n### 参数说明\n\n| 参数 | 推荐值 | 说明 |\n|------|--------|------|\n| `w` | 1080 | 宽度（像素） |\n| `h` | 1440 | 高度（像素，3:4比例） |\n| `fit` | crop | 裁切模式 |\n| `q` | 85 | JPEG质量（80-90） |\n\n### 常用主题图片 ID\n\n| 主题 | Photo ID | 描述 |\n|------|----------|------|\n| 深蓝科技抽象 | `1620712943543-bcc4688e7485` | 电路板/数据可视化风格 |\n| 暗夜星空 | `1534796636912-3b95b3ab5986` | 深蓝星空/宇宙 |\n| 极简办公 | `1497366216548-37526070297c` | 现代办公空间 |\n| 城市天际线 | `1477959858617-67f85cf4f1df` | 城市夜景 |\n| 自然纹理 | `1506905925346-21bda4d32df4` | 山脉/自然 |\n\n### 下载方法\n\n```javascript\n// Node.js 下载（推荐，支持重定向跟踪+域名白名单）\nconst https = require('https');\nconst fs = require('fs');\n\n// 允许的图片域名白名单（重定向目标必须在白名单内，防止SSRF）\nconst ALLOWED_HOSTS = new Set([\n  'images.pexels.com',\n  'images.unsplash.com',\n  'api.pexels.com',\n  'api.unsplash.com',\n]);\n\nfunction download(url, dest) {\n  return new Promise((resolve, reject) => {\n    const follow = (u, redirects = 0) => {\n      if (redirects > 10) return reject(new Error('Too many redirects'));\n      // 校验域名白名单（防止SSRF/重定向到内网或恶意域名）\n      const parsed = new URL(u);\n      if (!ALLOWED_HOSTS.has(parsed.hostname)) {\n        return reject(new Error(`Blocked: host ${parsed.hostname} not in allowlist`));\n      }\n      https.get(u, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {\n        if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {\n          return follow(res.headers.location, redirects + 1);\n        }\n        const file = fs.createWriteStream(dest);\n        res.pipe(file);\n        file.on('finish', () => { file.close(); resolve(fs.statSync(dest).size); });\n      }).on('error', reject);\n    };\n    follow(url);\n  });\n}\n```\n\n```bash\n# curl 下载（需用 curl.exe 而非 PowerShell 的 curl 别名）\ncurl.exe -s -L -o \"assets/cover.jpg\" \"https://images.unsplash.com/photo-1620712943543-bcc4688e7485?w=1080&h=1440&fit=crop&auto=format&q=85\"\n```\n\n---\n\n## AI 生图验证规则\n\n### 问题：AI 生图 API 可能返回相同占位图\n\n> ⚠️ **外部能力同意门控（v7.7 新增）**：AI 生图 API 会发送 prompt 到 `trae-api-cn.mchost.guru`（仅限 TRAE 内部环境）。prompt 由 AI 根据页面角色生成，可能含文章主题/场景描述。**用户必须在 Step 1 图片三选一门控中明确选择 C（AI 生成）后才能使用**，不得因用户说\"都行\"/\"你看着办\"而默认启用。\n\n> ⚠️ **环境限制**：`trae-api-cn.mchost.guru` 的 `text_to_image` API 仅限 TRAE 内部环境可用，外部环境无法访问。生产部署请优先使用 Pexels/Pixabay/Unsplash 三大免费图库。\n\n`trae-api-cn.mchost.guru`（仅限 TRAE 内部环境）的 `text_to_image` API 无论 prompt 如何不同，可能返回完全相同的占位图。两个不同的 CDN URL 不代表图片内容不同。\n\n### 验证方法\n\n```javascript\nconst fs = require('fs');\nconst b1 = fs.readFileSync('assets/cover.jpg');\nconst b2 = fs.readFileSync('assets/finale.jpg');\n\n// 必须验证：两张图文件内容不同\nif (b1.equals(b2)) {\n  console.error('ERROR: cover.jpg and finale.jpg are identical!');\n  console.error('AI image API returned same placeholder. Switch to Unsplash.');\n  // 换用 Unsplash 直链下载\n}\n```\n\n### 铁律\n\n1. **下载多张图片后必须验证唯一性**：`buf1.equals(buf2) === false`\n2. **如果两张图完全相同，立即换用 Unsplash**：不要反复重试 AI 生图 API\n3. **禁止假设 URL 不同 = 内容不同**：CDN URL 的签名和路径不同不代表图片内容不同\n4. **验证时机**：在 Step 3 Compose 组装 HTML 之前，确保所有图片文件已验证有效\n\nFile v7.8.0:references/layout-recipes.md\n\n# Layout Recipes\n\n> 3:4 (1080×1440) card layout recipes for xhs-crafter.\n> Content density rule: on 1080×1440 cards, content must cover **≥75%** of canvas height.\n\n---\n\n## Editorial Magazine × E-ink Recipes\n\n### M01 — Cover\n\n| Field | Value |\n|-------|-------|\n| **Name** | Magazine Issue Cover |\n| **Best for** | 封面页、主题开篇、系列首卡 |\n| **Structure** | 顶部 issue 行 → 大号衬线标题 2-4 行 → 大图 35-55% → 底部 issue 条 3-5 要点 |\n\n```html\n<div class=\"card frame m01-cover\">\n  <div class=\"issue-row\">Vol.03 · 2026 春</div>\n  <h1 class=\"title-serif\">如何构建<br>可持续的<br>知识体系</h1>\n  <div class=\"image-well\">\n    <img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n  </div>\n  <div class=\"issue-strip\">\n    <span>方法论</span><span>工具链</span><span>实践案例</span><span>复盘模板</span>\n  </div>\n</div>\n```\n\n---\n\n### M02 — Field Note Photo\n\n| Field | Value |\n|-------|-------|\n| **Name** | Field Note Photo |\n| **Best for** | 照片主导页、田野记录、场景展示 |\n| **Structure** | 大图 60-70% → field-note 标题 → 地点/日期元数据 |\n\n```html\n<div class=\"card frame m02-field-note\">\n  <div class=\"image-well\">\n    <img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n  </div>\n  <div class=\"field-note\">\n    <h2 class=\"title-serif\">山间工坊</h2>\n    <p class=\"meta\">📍 杭州 · 2026.04</p>\n  </div>\n</div>\n```\n\n---\n\n### M03 — Feature Essay\n\n| Field | Value |\n|-------|-------|\n| **Name** | Feature Essay |\n| **Best for** | 长文节选、深度分析、编辑式排版 |\n| **Structure** | 编辑式标题 → 窄文字列 + 宽图井交替 |\n\n```html\n<div class=\"card frame m03-essay\">\n  <header class=\"editorial-header\">\n    <span class=\"overline\">深度</span>\n    <h2 class=\"title-serif\">设计的隐秩序</h2>\n  </header>\n  <div class=\"essay-body\">\n    <div class=\"text-column\">\n      <p>好的设计不是添加，而是减去多余……</p>\n    </div>\n    <div class=\"image-well\">\n      <img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n    </div>\n  </div>\n</div>\n```\n\n---\n\n### M04 — Checklist / Numbered List\n\n| Field | Value |\n|-------|-------|\n| **Name** | Checklist / Numbered List |\n| **Best for** | 清单、步骤摘要、要点罗列 |\n| **Structure** | 编辑式标题 → 编号条目（可选图标） → 配图 |\n\n```html\n<div class=\"card frame m04-checklist\">\n  <header class=\"editorial-header\">\n    <span class=\"overline\">清单</span>\n    <h2 class=\"title-serif\">出发前检查</h2>\n  </header>\n  <ol class=\"checklist-items\">\n    <li><span class=\"nb\">01</span> 确认护照有效期</li>\n    <li><span class=\"nb\">02</span> 预订住宿</li>\n    <li><span class=\"nb\">03</span> 购买旅行保险</li>\n    <li><span class=\"nb\">04</span> 打包随身物品</li>\n  </ol>\n  <div class=\"image-well\">\n    <img src=\"…\" style=\"object-fit:cover;object-position:center 55%\">\n  </div>\n</div>\n```\n\n---\n\n### M05 — Pull Quote / Takeaway\n\n| Field | Value |\n|-------|-------|\n| **Name** | Pull Quote / Takeaway |\n| **Best for** | 金句、核心观点、关键洞察 |\n| **Structure** | 大号衬线引文 → 来源/上下文行 |\n\n```html\n<div class=\"card frame m05-pull-quote\">\n  <blockquote class=\"pull-quote\">\n    <p class=\"title-serif\">\"简洁是复杂的终极形式。\"</p>\n  </blockquote>\n  <div class=\"source-row\">\n    <span class=\"source\">— 达芬奇</span>\n    <span class=\"context\">文艺复兴笔记</span>\n  </div>\n</div>\n```\n\n---\n\n### M06 — Comparison\n\n| Field | Value |\n|-------|-------|\n| **Name** | Comparison |\n| **Best for** | 对比分析、二选一、前后对照 |\n| **Structure** | 双栏张力布局 → 简洁标签 → 视觉锚点 |\n\n```html\n<div class=\"card frame m06-comparison\">\n  <h2 class=\"title-serif\">选择</h2>\n  <div class=\"compare-columns\">\n    <div class=\"col left\">\n      <div class=\"image-well\"><img src=\"…\" style=\"object-fit:cover;object-position:center 50%\"></div>\n      <span class=\"label\">方案 A</span>\n      <p>轻量、快速</p>\n    </div>\n    <div class=\"col right\">\n      <div class=\"image-well\"><img src=\"…\" style=\"object-fit:cover;object-position:center 50%\"></div>\n      <span class=\"label\">方案 B</span>\n      <p>稳健、全面</p>\n    </div>\n  </div>\n</div>\n```\n\n---\n\n### M07 — Field Ledger\n\n| Field | Value |\n|-------|-------|\n| **Name** | Field Ledger |\n| **Best for** | 表格式信息、属性清单、规格对比 |\n| **Structure** | 编辑式标题 → 账本行（标题列 + 备注列） |\n\n```html\n<div class=\"card frame m07-ledger\">\n  <header class=\"editorial-header\">\n    <span class=\"overline\">规格</span>\n    <h2 class=\"title-serif\">材料清单</h2>\n  </header>\n  <div class=\"ledger-rows\">\n    <div class=\"row\"><span class=\"title-col\">木材</span><span class=\"note-col\">白橡木 · 2m</span></div>\n    <div class=\"row\"><span class=\"title-col\">五金</span><span class=\"note-col\">黄铜铰链 ×4</span></div>\n    <div class=\"row\"><span class=\"title-col\">涂料</span><span class=\"note-col\">哑光清漆</span></div>\n    <div class=\"row\"><span class=\"title-col\">胶水</span><span class=\"note-col\">木工白胶 500ml</span></div>\n  </div>\n</div>\n```\n\n---\n\n### M08 — Pipeline Vertical\n\n| Field | Value |\n|-------|-------|\n| **Name** | Pipeline Vertical |\n| **Best for** | 流程步骤、工作流、阶段展示 |\n| **Structure** | 垂直步骤管道 → step-nb + step-title + step-desc |\n\n```html\n<div class=\"card frame m08-pipeline\">\n  <h2 class=\"title-serif\">制作流程</h2>\n  <div class=\"pipeline-steps\">\n    <div class=\"step\">\n      <span class=\"step-nb\">01</span>\n      <div class=\"step-content\">\n        <span class=\"step-title\">选材</span>\n        <span class=\"step-desc\">挑选纹理均匀的白橡木</span>\n      </div>\n    </div>\n    <div class=\"step\">\n      <span class=\"step-nb\">02</span>\n      <div class=\"step-content\">\n        <span class=\"step-title\">切割</span>\n        <span class=\"step-desc\">按图纸精确下料</span>\n      </div>\n    </div>\n    <div class=\"step\">\n      <span class=\"step-nb\">03</span>\n      <div class=\"step-content\">\n        <span class=\"step-title\">组装</span>\n        <span class=\"step-desc\">榫卯结构拼接</span>\n      </div>\n    </div>\n    <div class=\"step\">\n      <span class=\"step-nb\">04</span>\n      <div class=\"step-content\">\n        <span class=\"step-title\">打磨</span>\n        <span class=\"step-desc\">从 80 目到 400 目逐级打磨</span>\n      </div>\n    </div>\n  </div>\n</div>\n```\n\n---\n\n### M09 — Marginalia Essay\n\n| Field | Value |\n|-------|-------|\n| **Name** | Marginalia Essay |\n| **Best for** | 学术随笔、注释式阅读、深度笔记 |\n| **Structure** | 主栏 + 旁注栏 → 衬线正文 |\n\n```html\n<div class=\"card frame m09-marginalia\">\n  <div class=\"main-column\">\n    <h2 class=\"title-serif\">论手艺的消逝</h2>\n    <p class=\"body-serif\">手艺不仅是一种技能，更是一种与材料对话的方式。当机器取代了手，我们失去的不只是效率……</p>\n  </div>\n  <aside class=\"marginalia\">\n    <p class=\"note\">手艺 (craft) 源自古英语 cræft，意为力量与技巧</p>\n    <p class=\"note\">参见 Richard Sennett《匠人》</p>\n  </aside>\n</div>\n```\n\n---\n\n### M10 — Atmosphere Thesis\n\n| Field | Value |\n|-------|-------|\n| **Name** | Atmosphere Thesis |\n| **Best for** | 氛围感宣言、品牌主张、情绪页 |\n| **Structure** | 大字陈述 + 氛围背景图 → 极少文字 |\n\n```html\n<div class=\"card frame m10-atmosphere\">\n  <div class=\"atmosphere-bg\">\n    <img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n  </div>\n  <div class=\"thesis-overlay\">\n    <h1 class=\"title-serif\">少即是多</h1>\n    <p class=\"subtitle\">Less, but better.</p>\n  </div>\n</div>\n```\n\n---\n\n### M11 — Photo Grid\n\n| Field | Value |\n|-------|-------|\n| **Name** | Photo Grid |\n| **Best for** | 多图展示、作品集、场景合集 |\n| **Structure** | 2×2 或 3×2 照片网格 + 说明文字 |\n\n```html\n<div class=\"card frame m11-photo-grid\">\n  <h2 class=\"title-serif\">空间记录</h2>\n  <div class=\"photo-grid cols-2x2\">\n    <figure><img src=\"…\" style=\"object-fit:cover;object-position:center 50%\"><figcaption>客厅</figcaption></figure>\n    <figure><img src=\"…\" style=\"object-fit:cover;object-position:center 50%\"><figcaption>书房</figcaption></figure>\n    <figure><img src=\"…\" style=\"object-fit:cover;object-position:center 50%\"><figcaption>厨房</figcaption></figure>\n    <figure><img src=\"…\" style=\"object-fit:cover;object-position:center 50%\"><figcaption>阳台</figcaption></figure>\n  </div>\n</div>\n```\n\n---\n\n### M12 — Data Cards\n\n| Field | Value |\n|-------|-------|\n| **Name** | Data Cards |\n| **Best for** | 数据展示、KPI 概览、统计摘要 |\n| **Structure** | 2×2 或 2×3 数据卡片 → 数字 + 标签 |\n\n```html\n<div class=\"card frame m12-data-cards\">\n  <h2 class=\"title-serif\">年度数据</h2>\n  <div class=\"data-grid cols-2x2\">\n    <div class=\"data-card\"><span class=\"number\">128</span><span class=\"label\">项目完成</span></div>\n    <div class=\"data-card\"><span class=\"number\">4.9</span><span class=\"label\">客户评分</span></div>\n    <div class=\"data-card\"><span class=\"number\">36</span><span class=\"label\">团队成员</span></div>\n    <div class=\"data-card\"><span class=\"number\">99%</span><span class=\"label\">按时交付</span></div>\n  </div>\n</div>\n```\n\n---\n\n### M13 — Timeline Vertical\n\n| Field | Value |\n|-------|-------|\n| **Name** | Timeline Vertical |\n| **Best for** | 时间线、发展历程、里程碑 |\n| **Structure** | 垂直时间轴 → 节点 + 日期 + 描述 |\n\n```html\n<div class=\"card frame m13-timeline\">\n  <h2 class=\"title-serif\">发展历程</h2>\n  <div class=\"timeline-nodes\">\n    <div class=\"node\">\n      <span class=\"dot\"></span>\n      <div class=\"node-content\">\n        <span class=\"date\">2023</span>\n        <span class=\"desc\">项目启动</span>\n      </div>\n    </div>\n    <div class=\"node\">\n      <span class=\"dot\"></span>\n      <div class=\"node-content\">\n        <span class=\"date\">2024</span>\n        <span class=\"desc\">首版发布</span>\n      </div>\n    </div>\n    <div class=\"node\">\n      <span class=\"dot\"></span>\n      <div class=\"node-content\">\n        <span class=\"date\">2025</span>\n        <span class=\"desc\">用户突破 10 万</span>\n      </div>\n    </div>\n    <div class=\"node\">\n      <span class=\"dot\"></span>\n      <div class=\"node-content\">\n        <span class=\"date\">2026</span>\n        <span class=\"desc\">全球化运营</span>\n      </div>\n    </div>\n  </div>\n</div>\n```\n\n---\n\n### M14 — Before / After\n\n| Field | Value |\n|-------|-------|\n| **Name** | Before / After |\n| **Best for** | 改造对比、效果展示、优化前后 |\n| **Structure** | 分割对比 → 中间分隔线 |\n\n```html\n<div class=\"card frame m14-before-after\">\n  <h2 class=\"title-serif\">改造前后</h2>\n  <div class=\"split-compare\">\n    <div class=\"half before\">\n      <img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n      <span class=\"label\">Before</span>\n    </div>\n    <div class=\"divider\"></div>\n    <div class=\"half after\">\n      <img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n      <span class=\"label\">After</span>\n    </div>\n  </div>\n</div>\n```\n\n---\n\n### M15 — Full-Bleed Image\n\n| Field | Value |\n|-------|-------|\n| **Name** | Full-Bleed Image |\n| **Best for** | 视觉冲击页、作品展示、氛围图 |\n| **Structure** | 图片覆盖 80%+ → 文字叠加安全区 |\n\n```html\n<div class=\"card frame m15-full-bleed\">\n  <div class=\"full-image\">\n    <img src=\"…\" style=\"object-fit:cover;object-position:center 50%\">\n  </div>\n  <div class=\"text-safe-zone\">\n    <h2 class=\"title-serif\">光与影</h2>\n    <p class=\"caption\">建筑摄影系列 · 第三章</p>\n  </div>\n</div>\n```\n\n---\n\n### M16 — Closing / CTA\n\n| Field | Value |\n|-------|-------|\n| **Name** | Closing / CTA |\n| **Best for** | 结尾页、行动号召、关注引导 |\n| **Structure** | 结语陈述 → CTA 按钮/链接 → 页脚 |\n\n```html\n<div class=\"card frame m16-closing\">\n  <div class=\"closing-content\">\n    <h2 class=\"title-serif\">感谢阅读</h2>\n    <p class=\"body\">如果这篇文章对你有帮助，欢迎关注获取更多内容。</p>\n    <a class=\"cta-button\" href=\"#\">关注我</a>\n  </div>\n  <footer class=\"card-footer\">\n    <span>@作者名</span>\n    <span>Vol.03 · 2026</span>\n  </footer>\n</div>\n```\n\n---\n\n## Swiss International Recipes\n\n### S01 — Index Cover\n\n| Field | Value |\n|-------|-------|\n| **Name** | Index Cover |\n| **Best for** | 索引封面、目录页、系列开篇 |\n| **Structure** | 大号无衬线标题 weight 200 → 强调元素 → 类目标签 |\n\n```html\n<div class=\"card frame s01-index\">\n  <h1 class=\"title-sans weight-200\">知识<br>管理<br>手册</h1>\n  <div class=\"accent-element\"></div>\n  <div class=\"category-labels\">\n    <span>工具</span><span>方法</span><span>实践</span>\n  </div>\n</div>\n```\n\n---\n\n### S02 — Vertical Timeline + KPI\n\n| Field | Value |\n|-------|-------|\n| **Name** | Vertical Timeline + KPI |\n| **Best for** | 时间线 + 关键指标、发展历程 + 数据 |\n| **Structure** | 时间轴节点 → KPI 数字 |\n\n```html\n<div class=\"card frame s02-timeline-kpi\">\n  <div class=\"timeline-column\">\n    <div class=\"node\"><span class=\"dot\"></span><span class=\"date\">Q1</span><span class=\"desc\">上线</span></div>\n    <div class=\"node\"><span class=\"dot\"></span><span class=\"date\">Q2</span><span class=\"desc\">增长</span></div>\n    <div class=\"node\"><span class=\"dot\"></span><span class=\"date\">Q3</span><span class=\"desc\">扩展</span></div>\n    <div class=\"node\"><span class=\"dot\"></span><span class=\"date\">Q4</span><span class=\"desc\">盈利</span></div>\n  </div>\n  <div class=\"kpi-column\">\n    <div class=\"kpi\"><span class=\"number\">10K</span><span class=\"label\">用户</span></div>\n    <div class=\"kpi\"><span class=\"number\">¥2M</span><span class=\"label\">营收</span></div>\n    <div class=\"kpi\"><span class=\"number\">98%</span><span class=\"label\">留存</span></div>\n  </div>\n</div>\n```\n\n---\n\n### S03 — Split Statement\n\n| Field | Value |\n|-------|-------|\n| **Name** | Split Statement |\n| **Best for** | 观点 + 论据、主张 + 证据 |\n| **Structure** | 左右分栏 → 陈述 + 证据 |\n\n```html\n<div class=\"card frame s03-split-statement\">\n  <div class=\"left-statement\">\n    <h2 class=\"title-sans\">设计即沟通</h2>\n    <p>每一个像素都在传递信息。</p>\n  </div>\n  <div class=\"right-evidence\">\n    <div class=\"evidence-item\"><span class=\"number\">73%</span><span class=\"label\">用户首先注意视觉</span></div>\n    <div class=\"evidence-item\"><span class=\"number\">2.6s</span><span class=\"label\">平均首屏停留</span></div>\n    <div class=\"evidence-item\"><span class=\"number\">4.2×</span><span class=\"label\">好设计提升转化</span></div>\n  </div>\n</div>\n```\n\n---\n\n### S04 — Six Cells\n\n| Field | Value |\n|-------|-------|\n| **Name** | Six Cells |\n| **Best for** | 矩阵展示、功能罗列、分类概览 |\n| **Structure** | 2×3 或 3×2 卡片填充矩阵 |\n\n```html\n<div class=\"card frame s04-six-cells\">\n  <h2 class=\"title-sans\">核心能力</h2>\n  <div class=\"cell-grid cols-2x3\">\n    <div class=\"cell\"><span class=\"icon\">📝</span><span class=\"label\">写作</span></div>\n    <div class=\"cell\"><span class=\"icon\">🎨</span><span class=\"label\">设计</span></div>\n    <div class=\"cell\"><span class=\"icon\">📊</span><span class=\"label\">数据</span></div>\n    <div class=\"cell\"><span class=\"icon\">🔧</span><span class=\"label\">工程</span></div>\n    <div class=\"cell\"><span class=\"icon\">📈</span><span class=\"label\">增长</span></div>\n    <div class=\"cell\"><span class=\"icon\">🤝</span><span class=\"label\">协作</span></div>\n  </div>\n</div>\n```\n\n---\n\n### S05 — Three Layers\n\n| Field | Value |\n|-------|-------|\n| **Name** | Three Layers |\n| **Best for** | 架构图、层级关系、系统分层 |\n| **Structure** | 三层架构图 |\n\n```html\n<div class=\"card frame s05-three-layers\">\n  <h2 class=\"title-sans\">系统架构</h2>\n  <div class=\"layers\">\n    <div class=\"layer top\"><span class=\"layer-name\">表现层</span><span class=\"layer-desc\">UI / 交互</span></div>\n    <div class=\"layer mid\"><span class=\"layer-name\">逻辑层</span><span class=\"layer-desc\">业务 / API</span></div>\n    <div class=\"layer bot\"><span class=\"layer-name\">数据层</span><span class=\"layer-desc\">存储 / 缓存</span></div>\n  </div>\n</div>\n```\n\n---\n\n### S06 — KPI Tower\n\n| Field | Value |\n|-------|-------|\n| **Name** | KPI Tower |\n| **Best for** | 关键指标展示、数据对比、仪表盘 |\n| **Structure** | 4 个 KPI 柱状条 → 不同高度 |\n\n```html\n<div class=\"card frame s06-kpi-tower\">\n  <h2 class=\"title-sans\">季度表现</h2>\n  <div class=\"tower-bars\">\n    <div class=\"bar\" style=\"height:45%\"><span class=\"number\">45%</span><span class=\"label\">Q1</span></div>\n    <div class=\"bar\" style=\"height:62%\"><span class=\"number\">62%</span><span class=\"label\">Q2</span></div>\n    <div class=\"bar\" style=\"height:78%\"><span class=\"number\">78%</span><span class=\"label\">Q3</span></div>\n    <div class=\"bar\" style=\"height:95%\"><span class=\"number\">95%</span><span class=\"label\">Q4</span></div>\n  </div>\n</div>\n```\n\n---\n\n### S07 — H-Bar Chart\n\n| Field | Value |\n|-------|-------|\n| **Name** | H-Bar Chart |\n| **Best for** | 排名、对比、水平柱状图 |\n| **Structure** | 5-10 条水平柱 → 排名展示 |\n\n```html\n<div class=\"card frame s07-hbar\">\n  <h2 class=\"title-sans\">语言流行度</h2>\n  <div class=\"hbar-rows\">\n    <div class=\"hbar-row\"><span class=\"label\">Python</span><div class=\"bar\" style=\"width:92%\"></div><span class=\"value\">92</span></div>\n    <div class=\"hbar-row\"><span class=\"label\">JavaScript</span><div class=\"bar\" style=\"width:87%\"></div><span class=\"value\">87</span></div>\n    <div class=\"hbar-row\"><span class=\"label\">TypeScript</span><div class=\"bar\" style=\"width:74%\"></div><span class=\"value\">74</span></div>\n    <div class=\"hbar-row\"><span class=\"label\">Rust</span><div class=\"bar\" style=\"width:58%\"></div><span class=\"value\">58</span></div>\n    <div class=\"hbar-row\"><span class=\"label\">Go</span><div class=\"bar\" style=\"width:51%\"></div><span class=\"value\">51</span></div>\n  </div>\n</div>\n```\n\n---\n\n### S08 — Duo Compare\n\n| Field | Value |\n|-------|-------|\n| **Name** | Duo Compare |\n| **Best for** | 前后对比、方案对比、双栏对照 |\n| **Structure** | 前后/左右对比 → 中间竖线分隔 |\n\n```html\n<div class=\"card frame s08-duo-compare\">\n  <h2 class=\"title-sans\">优化效果</h2>\n  <div class=\"duo-columns\">\n    <div class=\"duo-col before\">\n      <span class=\"label\">优化前</span>\n      <span class=\"number\">3.2s</span>\n      <span class=\"desc\">加载时间</span>\n    </div>\n    <div class=\"vertical-rule\"></div>\n    <div class=\"duo-col after\">\n      <span class=\"label\">优化后</span>\n      <span class=\"number\">0.8s</span>\n      <span class=\"desc\">加载时间</span>\n    </div>\n  </div>\n</div>\n```\n\n---\n\n### S09 — Dot Matrix Statement\n\n| Field | Value |\n|-------|-------|\n| **Name** | Dot Matrix Statement |\n| **Best for** | 宣言、主张、品牌声明 |\n| **Structure** | 大字陈述 + 点阵背景 |\n\n```html\n<div class=\"card frame s09-dot-matrix\">\n  <div class=\"dot-matrix-bg\"></div>\n  <div class=\"statement\">\n    <h1 class=\"title-sans\">做减法</h1>\n    <p>去掉一切不必要的，留下真正重要的。</p>\n  </div>\n</div>\n```\n\n---\n\n### S10 — Split Closing\n\n| Field | Value |\n|-------|-------|\n| **Name** | Split Closing |\n| **Best for** | 结尾页、分栏收束、CTA |\n| **Structure** | 分栏收尾布局 |\n\n```html\n<div class=\"card frame s10-split-closing\">\n  <div class=\"left-close\">\n    <h2 class=\"title-sans\">下期见</h2>\n    <p>每周更新，持续精进。</p>\n  </div>\n  <div class=\"right-close\">\n    <a class=\"cta-button\" href=\"#\">关注</a>\n    <a class=\"cta-link\" href=\"#\">往期回顾 →</a>\n  </div>\n</div>\n```\n\n---\n\n### S11 — Horizontal Timeline\n\n| Field | Value |\n|-------|-------|\n| **Name** | Horizontal Timeline |\n| **Best for** | 水平流程、步骤展示、阶段推进 |\n| **Structure** | 4-7 步水平流程 → 节点 + 连线 |\n\n```html\n<div class=\"card frame s11-h-timeline\">\n  <h2 class=\"title-sans\">项目阶段</h2>\n  <div class=\"h-timeline\">\n    <div class=\"step\"><span class=\"dot\"></span><span class=\"label\">调研</span></div>\n    <div class=\"connector\"></div>\n    <div class=\"step\"><span class=\"dot\"></span><span class=\"label\">设计</span></div>\n    <div class=\"connector\"></div>\n    <div class=\"step\"><span class=\"dot\"></span><span class=\"label\">开发</span></div>\n    <div class=\"connector\"></div>\n    <div class=\"step\"><span class=\"dot\"></span><span class=\"label\">测试</span></div>\n    <div class=\"connector\"></div>\n    <div class=\"step\"><span class=\"dot\"></span><span class=\"label\">发布</span></div>\n  </div>\n</div>\n```\n\n---\n\n### S12 — Manifesto + Accent Banner\n\n| Field | Value |\n|-------|-------|\n| **Name** | Manifesto + Accent Banner |\n| **Best for** | 宣言页、品牌主张、信条展示 |\n| **Structure** | 宣言文字 + 强调色横幅 |\n\n```html\n<div class=\"card frame s12-manifesto\">\n  <div class=\"manifesto-text\">\n    <p class=\"title-sans\">我们相信</p>\n    <p>好的工具应该让人更自由，而非更忙碌。</p>\n    <p>好的设计应该减少选择，而非增加焦虑。</p>\n    <p>好的产品应该安静地工作，而非喧哗地存在。</p>\n  </div>\n  <div class=\"accent-banner\">\n    <span>Less, but better.</span>\n  </div>\n</div>\n```\n\nFile v7.8.0:references/portrait-fill.md\n\n# Portrait Fill Rules\n\n3:4 social images have much more vertical space than a horizontal PPT slide. A layout that works in 16:9 often becomes a thin strip in 3:4. Solve that at the planning stage.\n\n## Vertical Zones\n\nThink of a 1080×1440 Rednote image as five zones:\n\n| Zone | Typical Height | Role |\n|------|---------------|------|\n| Header/meta | 56-90px | issue label, category, page |\n| Title/lead | 240-420px | hook and claim |\n| Evidence/body | 520-760px | image, ledger, diagram, comparison |\n| Bottom strip | 90-180px | captions, checklist, summary |\n| Footer | 52-86px | issue/page metadata |\n\nNot every page needs all five, but every page needs an intentional vertical composition.\n\n## Density Hard Rules\n\nThese are non-negotiable:\n\n1. **Active composition must cover ≥78% of page height** (≈1123px of 1440px)\n   - This includes: large type, images/screenshots, ledger rows, background atmosphere on hero pages, caption bands, marginalia columns\n   - Whitespace is good only when it is designed. Empty leftover space is not.\n\n2. **4-Band density check**: Divide 1440px canvas into 4 horizontal bands (360px each). Every band should have content or an intentional whitespace reason.\n\n3. **Pure blank band >15% (216px) must have a design reason** — e.g., atmospheric hero page with WebGL/ink background.\n\n4. **No page should have only 2 content elements** — minimum 3 (e.g., title + body + data/quote/image).\n\n## Underfilled Page Smells\n\nRevise if:\n- A table or ledger occupies less than 45% of the canvas height\n- The lower 25% of the page is empty without being an atmospheric hero page\n- Four list items are rendered as short rows with large blank space below\n- A screenshot is small even though it is the evidence\n- Body copy is centered in the middle with no top/bottom rhythm\n\n## Fixes For Thin Tables\n\nWhen a table is too short:\n1. Increase row height to 118-170px\n2. Add a left marginal column with large numbers, keywords, or category labels\n3. Add a pull quote column beside the table\n4. Add a top or bottom issue strip with 2-3 consequences\n5. Convert the table to M08 Tall Ledger\n6. If there are only 2-3 points, use M04 Pull Quote or M09 Atmospheric Thesis instead of a table\n\n## Fixes For Sparse Text\n\nIf a page has only one core sentence:\n- Use M09 Atmospheric Thesis with visible ink/wash background\n- Make the sentence the hero, not a small paragraph\n- Add one small source/context row\n- Use dark/ink page if the package needs rhythm\n\n## Fixes For Screenshot Pages\n\nIf screenshot content matters:\n- Give it 45%-65% of the page height\n- Put only one key sentence above it\n- Use a bottom caption band instead of a side paragraph\n- Crop carefully; preserve readable UI labels\n\n## Page Rhythm\n\nFor a 7-page Rednote set, use at least 5 distinct shapes:\n- Cover / feature image\n- Essay split\n- Tall ledger\n- Evidence screenshot\n- Pull quote or atmospheric thesis\n- Checklist/comparison\n- Closing note\n\n**Avoid repeating `title + lead + 3 rows` more than twice in one set.**\n\n### Three-Layer Rhythm System\n\nA set of cards that all look the same brightness and density is monotonous. Magazine editing uses three rhythm layers to keep readers engaged:\n\n#### Layer 1: Light-Dark Rhythm (Editorial only)\n\nThe most powerful rhythm tool. Insert **1-2 dark pages** in a 5+ page set to create visual punctuation.\n\n**How it works:**\n- Dark pages use Midnight Ink theme (paper/ink colors inverted) while keeping the same accent color\n- This is NOT switching themes — it's using Midnight Ink as a **rhythm tool within the same package**\n- The accent color bridges light and dark pages, maintaining visual unity\n\n**Where to place dark pages:**\n\n| Position | Best for | Why |\n|----------|---------|-----|\n| Pull Quote page (middle) | Key quote / thesis | Dark background makes the quote feel weighty and important |\n| Closing page (last) | Final takeaway | Dark ending creates a sense of conclusion, like the last page of a magazine |\n| Chapter divider | Section transition | Dark page signals \"new chapter\" like a magazine section break |\n\n**Rules:**\n- 5-6 pages: at least 1 dark page\n- 7-9 pages: at least 1-2 dark pages\n- Never place 2 dark pages adjacent (they cancel each other's contrast)\n- Dark pages must still pass the density rules — they are not permission to be empty\n- For Swiss mode: use a full-bleed image page or a solid accent-color page instead of Midnight Ink\n\n**Implementation:**\n```html\n<!-- Light page (default theme) -->\n<section class=\"poster xhs\" id=\"xhs-01\">\n  <div class=\"paper-wash\"></div>\n  <div class=\"grain\"></div>\n  ...\n</section>\n\n<!-- Dark page (Midnight Ink for rhythm) -->\n<section class=\"poster xhs\" id=\"xhs-04\" data-theme=\"midnight-ink\">\n  <div class=\"paper-wash\"></div>\n  <div class=\"grain\"></div>\n  ...\n</section>\n```\n\n#### Layer 2: Atmosphere Rhythm\n\nVary the strength of background atmosphere (grain, ink wash, WebGL) across pages.\n\n| Page type | Atmosphere strength | What to show |\n|-----------|-------------------|-------------|\n| Cover | **Strong** | Visible grain + ink wash + possible WebGL canvas |\n| Pull quote / thesis | **Strong** | Visible grain + ink wash, dark or light |\n| Closing page | **Strong** | Visible grain + ink wash |\n| Data / ledger / checklist | **Subtle** | Only faint grain, no ink wash |\n| Screenshot evidence | **Minimal** | Almost no atmosphere, let screenshot breathe |\n| Essay / body text | **Medium** | Light grain + subtle wash |\n\n**Rules:**\n- Never make all pages the same atmosphere strength\n- After a strong-atmosphere page, the next page should be subtle (eye needs rest)\n- Screenshot pages should have minimal atmosphere — background must not compete with the screenshot\n\n#### Layer 3: Layout Rhythm\n\nAlready covered above (5 distinct shapes in 7 pages). Additional rules:\n- **Never use the same layout recipe for 2 consecutive pages**\n- Alternate between text-heavy and image/data-heavy pages\n- After a dense ledger page, follow with a spacious essay or pull quote page\n\n### Rhythm Planning Template\n\nWhen creating the Content Plan (Step 2), annotate each page with its rhythm profile:\n\n```text\n01 Cover (M01) — Light / Strong atmosphere / Image-led\n02 Opening (M04) — Light / Subtle atmosphere / Text+data\n03 Expansion (M08) — Light / Medium atmosphere / Pipeline\n04 Quote (M05) — DARK / Strong atmosphere / Pull quote ← rhythm break\n05 Starship (M03) — Light / Subtle atmosphere / Essay\n06 Finale (M07) — DARK / Strong atmosphere / Closing ← dark ending\n```\n\n### Anti-Patterns\n\n- **All-light monotony**: 6 pages of identical beige paper with no dark break. Cure: insert 1 Midnight Ink pull quote page\n- **Atmosphere flatline**: every page has the same grain/wash intensity. Cure: vary atmosphere strength per the table above\n- **Layout repetition**: 3 pages in a row with \"title + body + stat cards\". Cure: swap one to a different recipe\n- **Dark pages adjacent**: two Midnight Ink pages back-to-back lose contrast impact. Cure: always separate dark pages with at least one light page\n\n## Padding Guidelines\n\nDefault padding for `.pad` container:\n\n| Element | Current | Recommended | Reason |\n|---------|---------|-------------|--------|\n| Top padding | 96px | 72px | Release 24px for content |\n| Bottom padding | 96px | 64px | Footer needs less space |\n| Left/Right padding | 80px | 64px | More horizontal space for body text |\n\nThese values give approximately 15% more canvas area for content while maintaining magazine breathing room.\n\nFile v7.8.0:references/screenshot-treatment.md\n\n# Screenshot Treatment Specification\n\n> 截图装裱规范：如何将 UI 截图和照片内容优雅地嵌入 3:4 卡片。\n\n---\n\n## 何时使用 .frame-shot vs .frame-img\n\n| 类别 | 使用 | 典型场景 |\n|------|------|---------|\n| **.frame-shot** | 应用/Web UI、代码/终端、仪表盘、IDE 截图 | 网页截图、App 界面、代码编辑器、数据面板 |\n| **.frame-img** | 摄影内容（人物、风景、产品） | 人物照、风景照、产品摄影、食物摄影 |\n\n---\n\n## 主体预处理（Subject Prep）\n\n- 裁切到前景窗口/卡片后再装裱\n- **禁止** 透视/倾斜/旋转，除非用户明确要求\n- 保持截图原始比例，不拉伸\n\n---\n\n## 解剖结构（Anatomy）\n\n```\n.frame-shot.r-{ratio}.corners-{sq|sm|md}.shadow-{none|soft|ed}.bg-{paper|grid|dot|grey-1|ink}.inset-{none|sub|bal}\n  └─ <img src=\"…\" style=\"object-fit:contain\">\n```\n\n### 参数说明\n\n| 参数 | 可选值 | 说明 |\n|------|--------|------|\n| `r-{ratio}` | `r-3-4`, `r-16-9`, `r-4-3`, `r-1-1` | 截图原始比例 |\n| `corners-{}` | `corners-sq` (0px), `corners-sm` (4px), `corners-md` (8px) | 圆角大小 |\n| `shadow-{}` | `shadow-none`, `shadow-soft`, `shadow-ed` | 阴影风格 |\n| `bg-{}` | `bg-paper`, `bg-grid`, `bg-dot`, `bg-grey-1`, `bg-ink` | 背景材质 |\n| `inset-{}` | `inset-none` (0px), `inset-sub` (12px), `inset-bal` (24px) | 内边距 |\n\n---\n\n## 设备外壳（Device Wrappers）\n\n### .device-browser — macOS 浏览器外壳\n\n模拟 macOS 浏览器窗口，包含地址栏和交通灯按钮。\n\n```html\n<div class=\"device-browser\">\n  <div class=\"browser-chrome\">\n    <div class=\"traffic-lights\">\n      <span class=\"dot red\"></span>\n      <span class=\"dot yellow\"></span>\n      <span class=\"dot green\"></span>\n    </div>\n    <div class=\"address-bar\">https://example.com</div>\n  </div>\n  <div class=\"browser-content\">\n    <img src=\"…\" style=\"object-fit:contain\">\n  </div>\n</div>\n```\n\n### .device-phone — iOS 手机外壳\n\n模拟 iOS 手机边框，包含刘海和 Home 指示条。\n\n```html\n<div class=\"device-phone\">\n  <div class=\"phone-bezel\">\n    <div class=\"notch\"></div>\n    <div class=\"phone-screen\">\n      <img src=\"…\" style=\"object-fit:contain\">\n    </div>\n    <div class=\"home-indicator\"></div>\n  </div>\n</div>\n```\n\n---\n\n## 风格锁定默认值（Style-Locked Defaults）\n\n| 参数 | Swiss 国际风格 | Editorial 杂志风格 |\n|------|---------------|-------------------|\n| **Corners** | `corners-sq` | `corners-sm` |\n| **Shadow** | `shadow-none` | `shadow-soft` |\n| **Default bg** | `bg-grey-1` | `bg-paper` |\n| **Default inset** | `inset-sub` | `inset-sub` |\n\n---\n\n## 背景材质（Background Materials）\n\n| 类名 | 效果 | 适用场景 |\n|------|------|---------|\n| `bg-paper` | 暖色纸张纹理 | Editorial 风格、温暖质感 |\n| `bg-grid` | 方格纸网格线 | Swiss 风格、技术/数据内容 |\n| `bg-dot` | 点阵图案 | Swiss 风格、宣言/声明页 |\n| `bg-grey-1` | 中性浅灰 | Swiss 风格默认、通用 |\n| `bg-ink` | 深色背景 | 浅色截图反衬、深色模式 |\n\n---\n\n## 截图清晰度规则（Screenshot Clarity Rules）\n\n1. **截图清晰度优先时**：放大截图区域，减少周围文字\n2. **禁止拉伸截图**：始终保持原始比例\n3. **UI 截图使用 `object-fit:contain`**：确保完整显示，不裁切\n4. **安全边距**：截图内容周围保留足够 padding，避免紧贴边框\n5. **高 DPI 适配**：截图源分辨率应 ≥ 2x 目标显示尺寸\n6. **文字可读性**：截图内文字必须可辨认，必要时放大截图比例\n7. **避免过度装饰**：截图本身是主角，装裱不应喧宾夺主\n\n---\n\n## 完整示例\n\n### Swiss 风格 UI 截图\n\n```html\n<div class=\"frame-shot r-16-9 corners-sq shadow-none bg-grey-1 inset-sub\">\n  <img src=\"dashboard.png\" style=\"object-fit:contain\">\n</div>\n```\n\n### Editorial 风格 App 截图 + 手机外壳\n\n```html\n<div class=\"device-phone\">\n  <div class=\"phone-bezel\">\n    <div class=\"notch\"></div>\n    <div class=\"phone-screen\">\n      <div class=\"frame-shot r-3-4 corners-sm shadow-soft bg-paper inset-sub\">\n        <img src=\"app-screen.png\" style=\"object-fit:contain\">\n      </div>\n    </div>\n    <div class=\"home-indicator\"></div>\n  </div>\n</div>\n```\n\n### 深色背景浅色截图\n\n```html\n<div class=\"frame-shot r-16-9 corners-sq shadow-none bg-ink inset-bal\">\n  <img src=\"light-theme-ui.png\" style=\"object-fit:contain\">\n</div>\n```\n\nArchive v7.7.0: 22 files, 90998 bytes\n\nFiles: assets/screenshot.js (6937b), assets/template-editorial-card.html (17998b), assets/template-swiss-card.html (14289b), assets/validate.js (11444b), CHANGELOG.md (15272b), docs/session-handoff.md (11232b), README.md (14099b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18947b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (11247b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (5035b), skill-card.md (3471b), SKILL.md (21273b), _meta.json (130b)\n\nFile v7.7.0:SKILL.md\n\n---\nname: \"xhs-crafter\"\ndescription: \"将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/Unsplash图库API搜索（发送搜索关键词到外部API）；(2)AI生图API（发送prompt到trae-api-cn，仅限TRAE内部环境）；(3)飞书云盘上传（上传生成的PNG+txt到飞书服务器）。Invoke when用户明确说'xhs-crafter排版'、'用xhs-crafter转图片'、'公众号贴图排版'、'小红书图文卡片'。Do NOT use for原创写作、纯文字排版、视频制作、用户只提到MD文件路径但未明确要求图片排版。\"\nslug: \"xhs-crafter\"\ndisplayName: \"XHS Crafter\"\nversion: \"7.7.0\"\nsummary: \"将MD文章排版为3:4比例精美图片+压缩文字稿，用于公众号/小红书贴图发布\"\nlicense: \"MIT-0\"\n---\n\n# XHS Crafter — 文章转图片卡片\n\n## 任务\n将用户提供的MD文章内容，排版为多张3:4比例(1080×1440)的精美HTML页面，截图为PNG，压缩为≤1000字文字稿，文件夹交付。不做原创写作，不做视频，不做纯文字排版。\n\n## 隐私与数据流声明（用户须知）\n\n**本技能的数据流边界**：\n- **本地处理（默认）**：MD文本→HTML组装→PNG截图→本地文件夹交付。所有文章内容、图片素材、生成产物默认仅在本地处理，不上传任何外部服务\n- **可选外部能力（需用户明确同意）**：\n  - 图片搜索：调用Pexels/Pixabay API搜索免费图库照片（仅搜索词和图片下载，不上传文章内容）\n  - 飞书云盘同步：将生成PNG+文字稿上传到用户飞书云盘（需用户明确同意，且文章内容可能包含未发布素材）\n- **外部网络依赖**：v7.6 已移除 Google Fonts CDN 引用，模板使用系统字体回退栈（Noto Serif SC / Source Han Serif SC / Songti SC / PingFang SC / Consolas 等），完全本地渲染，无外部字体加载\n\n**用户警告**：\n- ⚠️ 如果文章包含未发布/敏感/专有内容，请谨慎使用飞书云盘同步功能——上传即意味着内容离开本地\n- ⚠️ 图片搜索会将搜索关键词发送到Pexels/Pixabay服务器，但不会发送文章原文\n- ⚠️ 飞书云盘同步需要用户已登录lark-cli，且目标文件夹由用户飞书账号持有\n\n**权限声明**（v7.7 完整披露所有行为）：\n\n| 能力类别 | 是否使用 | 说明 |\n|---------|---------|------|\n| 网络访问 | ✅ | **核心行为**：启动本地 127.0.0.1 HTTP server 加载预存 HTML 模板供 Puppeteer 截图（不出局域网）。**可选外部访问**（每项需用户独立同意）：Pexels/Pixabay/Unsplash 图库 API 搜索；trae-api-cn AI 生图 API（仅限 TRAE 内部环境）；飞书云盘上传 |\n| 文件读写 | ✅ | 读 MD 文章 + 预存 HTML 模板（assets/template-*.html）；写 output/ 目录 PNG+txt；写 `$env:TEMP` 交付文件夹；可选下载外部图片到 assets/ 目录（受 ALLOWED_HOSTS 白名单限制） |\n| 环境变量 | ✅ | `PEXELS_API_KEY`、`PIXABAY_API_KEY`（图库搜索，可选）；`CHROME_PATH`（可选，浏览器路径） |\n| subprocess | ✅ | `python -m http.server --bind 127.0.0.1`（本地回环 HTTP server，截图用）；`node assets/screenshot.js`（Puppeteer 截图）；`node assets/validate.js`（自动验证）；`curl.exe`（可选，下载外部图片）；`explorer.exe`（打开交付文件夹） |\n| 外部 API | ✅ | Pexels/Pixabay/Unsplash 图片搜索 API（可选，发送搜索关键词）；trae-api-cn.mchost.guru AI 生图 API（可选，发送 prompt，仅限 TRAE 内部环境）；飞书 lark-cli drive API（可选云盘同步，上传 PNG+txt） |\n\n> ⚠️ **核心行为说明**：本技能的核心能力是 **本地 HTML 模板填充 + Puppeteer 截图渲染**，不是 MD→HTML 编译管道。MD 内容由 AI 读取后填入预存的 HTML 模板（assets/template-editorial-card.html 或 template-swiss-card.html），然后启动本地 HTTP server 加载该 HTML 供 Puppeteer 截图为 PNG。核心流程不涉及外部网络访问。\n\n## 输出格式\n\n```\n<桌面>/<slug>公众号素材/\n├── p1-cover.png\n├── p2-xxx.png\n├── ...\n├── pN-finale.png\n└── <slug>-文字稿.txt   # ≤1000字压缩文字\n```\n\n## 工作流：5步（默认本地全自动，外部能力需用户同意）\n\n**核心原则**：用户给MD，直接出本地文件夹。Step 1-2在脑内完成（不输出长文规划），Step 3-5连续执行不等待用户确认。\n\n**外部能力同意门控**（2道，仅在触发外部网络/云盘时询问，本地渲染不询问。每道门控独立询问，不批量授权）：\n1. **图片搜索门控**（Step 1，用户无图且需背景图时）：询问是否调用Pexels/Pixabay API搜索\n2. **飞书同步门控**（Step 5，本地交付完成后）：询问是否上传到飞书云盘\n\n> ⚠️ **同意门控铁律**：每道门控必须独立询问，不得因用户说\"按流程走一遍\"、\"全流程\"、\"都行\"等模糊措辞而批量授权多个外部能力。用户必须对每个外部能力单独明确同意（\"是\"或具体指定）。\n\n### Step 1: Intake — 识别品类（脑内完成，不输出）\n从MD内容自动推断：\n- **内容品类**: 读 `references/category-cookbook.md` 路由。13个品类：商业/科技分析、职场/干货、旅行/生活方式、教程/工具、影视/读书、游戏、美食、彩妆、穿搭、家居、健身、情感、推荐。超出范围的品类（梦核/氛围感装饰风、Y2K/千禧辣妹、纯摄影展示）必须在设计前明确告知用户\n- **目标平台**: 默认小红书3:4（除非用户指定公众号）\n- **用户图片**: (a)用户指定截图文件夹路径；(b)解析MD中 `![描述](路径)` 和 `[🖼️配图建议：xxx]` 标记\n- **图片三选一门控**（仅在用户无图时触发，一次性提问不反复追问）：\n  ```\n  这篇我需要 1-2 张图。三种走法：\n  A. 你自己有照片/截图，传给我（推荐——最不\"AI感\"，完全本地处理）\n  B. 我去 Pexels/Pixabay 帮你找（⚠️ 会将搜索词发送到外部API，但不上传文章原文）\n  C. 用 AI 生成（⚠️ 会将prompt发送到trae-api-cn生图API，仅限TRAE内部环境）\n  ```\n  推荐 A。用户必须明确选择 A/B/C 之一（如\"用B\"、\"搜图\"、\"AI生成\"）；若用户说\"都行\"/\"你看着办\"等模糊回答，默认走 A（完全本地，无外部数据流），不再追问\n- **仅在品类无法推断时才问用户**，否则直接进入Step 2\n\n### Step 2: Content Plan — 内容规划（脑内完成，不输出）\n读 `references/content-planning.md`，完成：\n- 压缩阶梯：核心论点1句 → 读者承诺 → 4-8个分论点 → 页面钩子 → 正文片段\n- 页面角色分配：7页组图至少5种不同形态\n- **页面节奏规划**：为每页标注明暗(Light/Dark)、氛围强弱(Strong/Subtle)、版式类型，读 `references/portrait-fill.md` 的\"Three-Layer Rhythm System\"\n- 封面钩子：用具体承诺而非空洞口号\n- 页数指导：600-1000字→5-7图，1000-1800字→7-9图\n- **5页及以上：封面和封底都必须有图片背景**\n\n### Step 3: Compose — 组装HTML（直接执行）\n- 拷贝种子模板：Editorial→ `assets/template-editorial-card.html`；Swiss→ `assets/template-swiss-card.html`\n- 设置 `data-theme` 或 `data-accent` 属性切换主题\n- 在 `<!-- POSTERS_HERE -->` 处添加页面\n\n**字号速查表（必须严格遵循，不得自行调整）**：\n\n| Role | Class | Size | Weight | Family | 用途 |\n|------|-------|------|--------|--------|------|\n| Display | `.h-display` | 136px | 500 | serif-zh | 封面/封底主标题 |\n| Section title | `.h-xl` | 110px | 500 | serif-zh | 内容页主标题（必须统一） |\n| Mid title | `.h-md` | 60px | 500 | serif-zh | 次级标题/数据页标题 |\n| Subtitle | `.h-sub` | 46px | 400 italic | serif-en | 英文副标题 |\n| Pull quote | `.pullquote` | 80px | 500 italic | serif-zh | 引言页大字引语 |\n| Lead | `.lead` | 34px | 400 | serif-zh | 导语/段落首句 |\n| Body | `.body` | 32px | 400 | serif-zh | 正文段落 |\n| Kicker | `.kicker` | 26px | 500 | mono | 页面顶部标签 |\n| Meta | `.meta` | 24px | 500 | mono | 页面底部注释 |\n| Label | `.label` | 24px | 500 | mono | 数据标签 |\n| Stat number | `.stat-nb` | 72px | 500 | serif-zh | 大数字 |\n| Step title | `.step-title` | 34px | 500 | serif-zh | 流程步骤标题 |\n| Step desc | `.step-desc` | 28px | 400 | serif-zh | 流程步骤描述 |\n| Ledger title | `.ledger-title` | 30px | 500 | serif-zh | 表格行标题 |\n| 辅助文字 | — | 22px | 500 | mono | stat-label/stat-unit/ledger-note/step-nb/callout-src/issue-strip |\n\n**字号铁律**：\n1. **内容页主标题必须统一用 `.h-xl` 110px**——不得混用 `.h-md`，标题太长拆行而非降级\n2. **封面/封底主标题用 `.h-display` 136px**——比内容页大24%，形成\"书挡\"层级\n3. **满铺图页标题颜色必须 `#ffffff` + `text-shadow`**——禁止 `#ece2cf`（与暖调背景太接近）\n4. **字重\"越大越轻\"**：≥110px用500，60-80px用500，32-46px用400，24-26px用500\n5. **任何文字不得低于18px**\n\n**节奏速查表（必须严格遵循）**：\n\n| 规则 | 要求 | 违反后果 |\n|------|------|---------|\n| 暗色页数量 | 5页+至少1页Midnight Ink，7页+至少1-2页 | 全light=单调 |\n| 暗色页位置 | 引言页或结尾页最佳 | 中间也行，但不可相邻 |\n| 暗色页相邻 | 禁止！2个暗色页必须隔至少1个light页 | 相邻=对比抵消 |\n| 氛围强度 | 封面/引言/封底=strong，数据/清单=subtle，正文=medium | 全同一强度=死板 |\n| 版式重复 | 禁止连续2页用同一种版式骨架 | 密集ledger后接宽松essay |\n| 首尾图框 | 5页+封面和封底都必须有图片背景 | 无图=缺\"书挡\" |\n| 连续同色 | 连续3页相同主题色=P0错误 | 第3页必须插入暗色/氛围变化 |\n\n**密度速查表（必须严格遵循）**：\n\n| 规则 | 要求 |\n|------|------|\n| 活跃构图 | ≥78%画布高度（≈1123px of 1440px） |\n| 4横带密度 | 1440px切4段(360px)，每段有内容或主动留白理由 |\n| 纯空白带 | >216px必须有设计理由（如atmospheric hero页） |\n| 最少元素 | 每页至少3种内容元素（标题+正文+数据/图/引言） |\n| 表格行高 | 不足45%画布时加左侧大数字列或转M08 Tall Ledger |\n| 重复模式 | 避免\"标题+lead+3行\"重复超过2次 |\n\n**图片规则速查（必须严格遵循）**：\n\n| 规则 | 要求 |\n|------|------|\n| 图片下载 | 必须下载到本地`assets/`，禁止引用外部URL |\n| 唯一性验证 | 下载后用`buf1.equals(buf2)`验证，相同则换源 |\n| 跨项目去重 | 下载后手动用`buf1.equals(buf2)`验证图片内容不同（文件级校验，不依赖跨项目 registry） |\n| 满铺图页 | 选图→无遮罩构图→局部色调遮罩→缩略图检查 |\n| 满铺图标题色 | 必须`#ffffff`+`text-shadow`，禁止`#ece2cf` |\n| 主体感知裁切 | 根据`object-position`确保主体完整可见 |\n| 截图展示 | 用`.frame-shot`包壳，给45-65%页面高度 |\n| 图源优先级 | 用户图>Pexels/Pixabay(API)>Unsplash>Wallhaven>AI生成 |\n| accent面积 | Swiss≤30%，Lemon Green≤20% |\n\n- **封面/封底图片下载**：\n  1. 优先用户提供的图片（最真实，无\"AI感\"）\n  2. 用户无图时，询问是否调用 Pexels/Pixabay API 搜索（需用户同意，见 Step 1 图片三选一门控）\n  3. 用户同意后，用 `curl.exe -L -o \"assets/cover.jpg\" \"URL\"` 手动下载（URL 来自 Pexels/Pixabay API 返回）\n  4. Unsplash 直链备选：`https://images.unsplash.com/photo-{id}?w=1080&h=1440&fit=crop&auto=format&q=85`\n- **满铺图页必须遵循 `references/image-overlay.md`**：选图→无遮罩构图→局部色调遮罩→缩略图检查\n- **密度保障**：每页活跃构图≥78%画布高度，读 `references/portrait-fill.md`\n- **节奏保障**：暗色页插入、氛围强弱交替、版式不重复\n- **背景系统**：Editorial 必须使用三层背景（paper→wash→grain），禁止纯平背景。读 `references/background-systems.md`。氛围强度按页面角色分级：封面/引言/封底用 strong，数据/清单用 subtle\n- **图片必须下载到本地**（关键！Puppeteer headless无法可靠加载外部API图片）：\n  1. 用户同意后，用 `curl.exe -L -o \"assets/cover.jpg\" \"URL\"` 手动下载\n  2. HTML中用本地相对路径引用：`src=\"assets/cover.jpg\"`\n  3. 禁止直接引用外部URL（trae-api-cn.mchost.guru 仅限TRAE内部环境可用 / unsplash / pexels等），一律先下载再引用\n- **图片下载后必须验证唯一性**：\n  1. 下载多张图片后，用 `buf1.equals(buf2)` 验证图片文件内容不同\n  2. 如果两张图完全相同，换用其他图源\n  3. 禁止假设URL不同=内容不同\n- 图源优先级: 用户图 > Pexels/Pixabay(API搜索) > Unsplash(直链) > Wallhaven > AI生成(trae-api-cn.mchost.guru text_to_image，仅限TRAE内部环境)\n- 截图用 `.frame-shot` 包壳\n\n### Step 4: Validate — 自检（自动执行，不等待）\n截图前自动检查，不通过则自动修复：\n\n**密度检查**：每页活跃构图≥78% | 每页≥3种内容元素 | 纯空白带>216px需理由\n**图片检查**：封面1秒说清主题 | 文字未压主体 | 无broken image | **多张背景图文件内容不同（buf1.equals(buf2)===false）**\n**标题一致性检查**：所有内容页主标题使用同一字号class | 不得混用.h-xl和.h-md | 封面允许更大字号\n**节奏检查**：5页+至少1暗色页 | 暗色页不相邻 | 氛围强弱交替 | 版式不重复\n**风格检查**（读 `references/style-system.md`）：\n- [ ] 全套风格统一（同一主题色+同一风格）\n- [ ] Editorial身份测试：有atmosphere层 + serif标题 + 至少一个magazine结构元素\n- [ ] Swiss身份测试：大标题字重≤300 + 无serif + 单一accent + 无卡片阴影\n- [ ] 无文字溢出/footer碰撞\n\n**自动验证**（读 `assets/validate.js`）：\n- 运行 `node assets/validate.js <项目目录>` 执行 12 项自动检查\n- R1 溢出检查 / R2 footer碰撞 / R3 Swiss粗体 / R4 最小字号 / R5 4横带密度 / R6 h-xl换行 / R7 figure margin / R8 标题一致性 / R9 满铺图页标题颜色 / R10 暗色页节奏 / R11 accent面积 / R12 封面封底图背景\n- FAIL 项必须修复后才能交付，WARN 项为建议\n\n### Step 5: Screenshot & Deliver — 截图交付（直接执行）\n- 用`assets/screenshot.js`截图（自动检测页面ID，无需手动配置）\n  - 用法：先启动`python -m http.server 8090 --bind 127.0.0.1`（绑定本地回环，不暴露局域网），然后`node assets/screenshot.js <项目目录>`\n  - puppeteer-core + 系统Chrome，deviceScaleFactor:2\n  - 等待networkidle0 + fonts.ready + 6秒（确保图片加载）\n  - Chrome路径: 自动检测`$env:LOCALAPPDATA\\ms-playwright\\chromium-*\\chrome.exe`\n- **截图大小异常检测**（关键！文件过小说明图片未渲染）：\n  - 带背景图的页面（封面/封底）PNG应 >1MB（2x分辨率下）\n  - 纯文字页面 PNG 通常 800KB-1.5MB\n  - 如果封面/封底截图 <500KB，大概率背景图未渲染，需检查图片文件是否有效\n- 文字压缩：保留原话引言+场景描述+核心数据，≤1000字\n  - **压缩模板**：标题(1句) → 场景开场(1-2句，含人物/时间/地点) → 核心论点(1-2句) → 关键原话(1-2条，用「」包裹) → 数据支撑(3-5个关键数字) → 结尾原话(1条)\n  - **必须保留**：原文中的人物原话（用「」标记）、访谈/会议场景描述、关键数据\n  - **可以删减**：过渡句、重复论述、次要细节、纯背景铺垫\n- **交付方式：本地文件夹（默认）+ 飞书云盘同步（可选，需用户同意）**\n\n  **A. 本地文件夹（默认）**\n  > ⚠️ **本地文件写入提示**：将在 `$env:TEMP` 创建 `<slug>公众号素材/` 文件夹并写入 PNG+txt 文件。截图完成后告知用户交付路径，再继续后续步骤。\n  1. 截图完成后，告知用户：`已生成 N 张 PNG + 文字稿，将保存到 $env:TEMP/<slug>公众号素材/`\n  2. 在`$env:TEMP`创建`<slug>公众号素材/`文件夹\n  3. 将PNG+txt复制到该文件夹\n  4. 用`explorer.exe`打开文件夹，用户可拖到桌面\n  5. 完成本地交付后，**询问是否上传到飞书云盘**（不主动执行）\n\n  **B. 飞书云盘同步（可选，需用户明确同意——见下方门控）**\n  > ⚠️ **数据外发提示**：上传会将文章相关PNG和文字稿传输到飞书云服务器，离开本地环境。如果文章包含未发布/敏感/专有内容，请勿启用。需要用户已登录lark-cli。\n\n  **飞书同步同意门控**（仅在本地交付完成后触发一次）：\n  ```\n  本地文件夹已交付。是否需要同步到飞书云盘？\n  - 是 → 执行下方上传步骤\n  - 否 → 结束（本地文件夹已是完整交付物）\n  ```\n\n  **用户同意后执行**：\n  1. 用`lark-cli drive +create-folder`创建`<slug>公众号素材`文件夹\n  2. cd到output目录，用`lark-cli drive +upload --file <filename> --folder-token <token>`逐个上传PNG+txt\n  3. 返回飞书云盘文件夹URL，用户手机飞书App打开即可逐张保存到相册\n  4. 注意：lark-cli要求用相对路径，必须先cd到output目录再上传\n\n## 标题一致性铁律（非协商）\n\n1. **内容页主标题统一字号**：所有内容页（P02-P08）的主标题必须使用同一个 class（Editorial 用 `.h-xl` 110px，Swiss 用 `.h-xl` 128px）\n2. **封面允许更大字号**：封面用 `.h-display`（Editorial 136px）或 `.h-hero`/`.h-statement`（Swiss）\n3. **通过拆行适配而非降级字号**：标题太长时拆为两行，太短时加副标题增加视觉重量，不得降级到 `.h-md`\n4. **不得混用不同级别标题 class**：同一套卡片中，内容页主标题不得混用 `.h-xl` 和 `.h-md`\n\n## 密度铁律（非协商）\n\n1. **活跃构图 ≥78% 画布高度**（≈1123px of 1440px）\n2. **4横带密度**：1440px切4段(360px)，每段有内容或主动留白理由\n3. **纯空白带 >216px 必须有设计理由**（如atmospheric hero页）\n4. **每页至少3种内容元素**（标题+正文+数据/图/引言）\n5. **表格/ledger行高不足45%画布时**：加左侧大数字列、加pull quote列、或转M08 Tall Ledger\n6. **避免\"标题+lead+3行\"重复超过2次**\n\n## 节奏铁律（非协商）\n\n1. **明暗节奏**：5页以上组图至少1页暗色页(Midnight Ink)，7页以上至少1-2页。暗色页不是换主题，是同一主题内的明暗对比\n2. **暗色页位置**：最佳位置是引言页(Pull Quote)或结尾页(Closing)。2个暗色页不可相邻\n3. **氛围节奏**：封面/引言/结尾用强氛围(strong grain+wash)，数据/截图/清单用弱氛围(subtle grain only)。不可所有页同一氛围强度\n4. **版式节奏**：不可连续2页用同一种版式骨架。密集ledger后接宽松essay或pull quote\n5. **首尾图框**：5页及以上组图，封面和封底都必须有图片背景（满铺图或大图区），形成\"书挡\"效果。图片必须与主题适配——封面图抓主题，封底图收情绪\n6. **连续3页相同主题=P0错误**：连续3页以上使用相同主题色（全light或全dark）视为严重错误，必须在第3页插入暗色页或氛围变化页\n\n## 必读参考文件\n\n| 文件 | 用途 |\n|------|------|\n| `references/style-system.md` | **风格系统**：Editorial vs Swiss视觉锚点+身份测试+反模式 |\n| `references/category-cookbook.md` | **品类路由表**：13个品类的风格/主题/版式/图源映射 |\n| `references/content-planning.md` | **内容规划**：压缩阶梯+页面角色+钩子模式+页数指导 |\n| `references/portrait-fill.md` | **3:4密度规则**：垂直分区+密度铁律+稀疏页修复 |\n| `references/image-overlay.md` | **文字压图**：选图→无遮罩→局部色调→缩略图检查+主体避让 |\n| `references/theme-presets.md` | 10套主题色CSS变量 |\n| `references/components.md` | 字体/字号/间距/图片容器/卡片/截图容器规范 |\n| `references/layout-recipes.md` | 28种布局模板(M01-M16+S01-S12) |\n| `references/screenshot-treatment.md` | 截图美化：设备外壳+背景材质+风格默认 |\n| `references/background-systems.md` | **背景系统**：三层架构（paper→wash→grain）+ 氛围强度分级 + 满铺图页 + Swiss极简 |\n| `references/image-sources.md` | Pexels/Unsplash/Wallhaven图库接入 + AI生图验证规则 |\n\n## 示例\n\n**输入**: SpaceX上市分析MD → 自动推断：商业/科技分析 → Editorial × Indigo Porcelain\n\n**输出**: 7张PNG + spacex-文字稿.txt → `SpaceX公众号素材/` 文件夹\n\n**输入**: skill-forge教程MD+截图文件夹 → 自动推断：教程/工具 → Swiss × IKB Blue\n\n**输出**: 6张PNG + skillforge-文字稿.txt → `skillforge公众号素材/` 文件夹\n\nFile v7.7.0:README.md\n\n# xhs-crafter\n\n将 Markdown 文章排版为 3:4 比例的精美图片卡片 + 压缩文字稿，用于微信公众号/小红书贴图发布。\n\n[![版本](https://img.shields.io/badge/version-7.7.0-blue)](https://github.com/EdwardWason/xhs-crafter)\n[![许可证](https://img.shields.io/badge/license-MIT--0-green)](LICENSE)\n[![ClawHub](https://img.shields.io/badge/ClawHub-xhs--crafter-orange)](https://clawhub.ai/EdwardWason/xhs-crafter)\n\n## 功能\n\n- **MD → 图片卡片**：自动将 Markdown 文章拆分排版为多张 1080x1440 (3:4) HTML 页面，截图为 PNG\n- **双风格系统**：Editorial Magazine（杂志风，衬线+暖纸底）和 Swiss International（瑞士网格风，无衬线+白底）\n- **13 品类适配**：商业/科技/职场/旅行/教程/影视/游戏/美食/彩妆/穿搭/家居/健身/情感/推荐，自动路由风格+主题+版式\n- **10 套主题色**：Ink Classic / Indigo Porcelain / Forest Ink / Kraft Paper / Dune / Midnight Ink / IKB Blue / Lemon Yellow / Lemon Green / Safety Orange\n- **28 种布局模板**：M01-M16（Editorial）+ S01-S12（Swiss）\n- **三层背景架构**：paper→wash→grain，氛围强度按页面角色分级（strong/medium/subtle）\n- **三层节奏系统**：明暗交替 + 氛围强弱 + 版式多样性\n- **密度铁律**：活跃构图 >= 78% 画布高度，确保信息密度\n- **字号速查表**：15级字号体系直接嵌入SKILL.md，确保跨会话一致性\n- **自动验证**：12项validate.js检查（溢出/footer碰撞/最小字号/密度/节奏/标题一致性/accent面积等）\n- **文字压缩**：保留原话引言+场景描述，压缩至 <= 1000 字\n- **本地交付（默认）**：MD→HTML→PNG→本地文件夹，所有内容仅本地处理\n- **可选飞书云盘同步**：用户明确同意后上传（⚠️ 内容会离开本地，详见下方隐私说明）\n\n## 隐私与数据流\n\n**核心能力是本地处理**：MD文本 → HTML组装 → PNG截图 → 本地文件夹交付。文章内容、图片素材、生成产物默认仅在本地处理，不上传任何外部服务。\n\n**可选外部能力**（需用户明确同意，不主动执行）：\n- **图片搜索**：调用Pexels/Pixabay API搜索免费图库照片。⚠️ 仅搜索词和图片下载会发送到Pexels/Pixabay服务器，**不会上传文章原文**\n- **飞书云盘同步**：将生成PNG+文字稿上传到用户飞书云盘。⚠️ 上传即意味着内容离开本地，如文章包含未发布/敏感/专有内容请勿启用\n\n**外部网络依赖**：核心渲染流程完全本地（启动 127.0.0.1 HTTP server 加载预存 HTML 模板 + Puppeteer 截图，无外部网络）。可选外部能力（每项需用户独立同意）：(1)Pexels/Pixabay/Unsplash 图库 API 搜索（发送搜索关键词）；(2)trae-api-cn AI 生图 API（发送 prompt，仅限 TRAE 内部环境）；(3)飞书云盘上传。v7.6 已移除 Google Fonts CDN 引用，模板使用系统字体回退栈。\n\n## 快速开始\n\n```bash\nnpx clawhub@latest install EdwardWason/xhs-crafter\n```\n\n## 使用方法\n\n在 TRAE / Claude Code / OpenClaw 中，明确要求图片排版时触发：\n\n```\n请用 xhs-crafter 把这篇 MD 文章排版为公众号贴图：/path/to/article.md\n```\n\n5 步工作流，用户只需给 MD，直接出本地文件夹（外部能力需用户同意）：\n\n1. **Intake** — 识别内容品类（自动推断）\n2. **Content Plan** — 内容规划（压缩阶梯+页面角色+节奏规划）\n3. **Compose** — 组装 HTML（双风格+10 主题+28 布局）\n4. **Validate** — 自检（密度+图片+节奏+风格）\n5. **Screenshot & Deliver** — 截图交付（本地文件夹默认；飞书云盘需用户明确同意）\n\n## 文件结构\n\n```\nxhs-crafter/\n├── SKILL.md                              # 技能主文件（入口，含字号速查表）\n├── assets/\n│   ├── template-editorial-card.html      # Editorial 种子模板\n│   ├── template-swiss-card.html          # Swiss 种子模板\n│   ├── screenshot.js                     # Puppeteer 截图脚本\n│   └── validate.js                       # 12项自动验证脚本\n└── references/\n    ├── style-system.md                   # Editorial vs Swiss 身份测试+反模式\n    ├── category-cookbook.md              # 13 品类路由表\n    ├── content-planning.md               # 压缩阶梯+页面角色+钩子模式\n    ├── portrait-fill.md                  # 3:4 密度规则+三层节奏系统\n    ├── image-overlay.md                  # 文字压图规则\n    ├── background-systems.md             # 三层背景架构+氛围强度分级\n    ├── theme-presets.md                  # 10 套主题色 CSS 变量\n    ├── components.md                     # 字体/字号/间距规范（权威来源）\n    ├── layout-recipes.md                 # 28 种布局模板\n    ├── screenshot-treatment.md           # 截图装裱规范\n    ├── image-sources.md                  # 图库 API 接入+AI生图验证\n    └── workflow.md                       # 工作流详细参考\n```\n\n## 品类适配\n\n| 品类 | 风格 | 主题 |\n|------|------|------|\n| 商业/科技分析 | Editorial | Indigo Porcelain |\n| 职场/干货 | Swiss | IKB Blue |\n| 旅行/生活方式 | Editorial | Kraft Paper |\n| 教程/工具 | Swiss | IKB Blue |\n| 影视/读书 | Editorial | Ink Classic |\n| 游戏 | Editorial (dark) | Midnight Ink |\n| 美食 | Editorial | Kraft Paper |\n| 彩妆 | Editorial | Dune |\n| 穿搭 | Editorial | Indigo Porcelain |\n| 家居 | Editorial | Forest Ink |\n| 健身/情感/推荐 | Swiss | Safety Orange |\n\n## 文档\n\n| 文件 | 用途 |\n|------|------|\n| [SKILL.md](SKILL.md) | 技能主文件，5 步工作流+字号速查表+密度铁律+节奏铁律 |\n| [references/style-system.md](references/style-system.md) | Editorial vs Swiss 视觉锚点+身份测试 |\n| [references/components.md](references/components.md) | 字体/字号/间距规范（唯一权威来源） |\n| [references/layout-recipes.md](references/layout-recipes.md) | 28 种布局模板详细说明 |\n| [references/theme-presets.md](references/theme-presets.md) | 10 套主题色 CSS 变量定义 |\n| [references/category-cookbook.md](references/category-cookbook.md) | 13 品类风格/主题/版式映射 |\n| [references/background-systems.md](references/background-systems.md) | 三层背景架构+氛围强度分级 |\n| [references/portrait-fill.md](references/portrait-fill.md) | 3:4 密度规则+三层节奏系统 |\n| [references/image-sources.md](references/image-sources.md) | 图库接入+AI生图验证规则 |\n| [CHANGELOG.md](CHANGELOG.md) | 版本变更记录 |\n\nLicense: MIT-0\n\n---\n\n# xhs-crafter\n\nConvert Markdown articles into beautifully designed 3:4 ratio image cards + compressed text drafts for WeChat Official Account / Xiaohongshu (Little Red Book) image-post publishing.\n\n[![version](https://img.shields.io/badge/version-7.7.0-blue)](https://github.com/EdwardWason/xhs-crafter)\n[![license](https://img.shields.io/badge/license-MIT--0-green)](LICENSE)\n[![ClawHub](https://img.shields.io/badge/ClawHub-xhs--crafter-orange)](https://clawhub.ai/EdwardWason/xhs-crafter)\n\n## Features\n\n- **MD → Image Cards**: Automatically split and layout Markdown articles into multiple 1080x1440 (3:4) HTML pages, screenshot as PNG\n- **Dual Style System**: Editorial Magazine (serif + warm paper) and Swiss International (sans-serif + white + single accent)\n- **13 Category Routing**: Business/Tech/Career/Travel/Tutorial/Film/Gaming/Food/Makeup/Fashion/Home/Fitness/Emotion/Recommendation — auto-route style + theme + layout\n- **10 Theme Presets**: Ink Classic / Indigo Porcelain / Forest Ink / Kraft Paper / Dune / Midnight Ink / IKB Blue / Lemon Yellow / Lemon Green / Safety Orange\n- **28 Layout Templates**: M01-M16 (Editorial) + S01-S12 (Swiss)\n- **Three-Layer Background**: paper→wash→grain, atmosphere intensity graded by page role (strong/medium/subtle)\n- **Three-Layer Rhythm System**: Light/dark alternation + atmosphere intensity + layout diversity\n- **Density Rules**: Active composition >= 78% canvas height, ensuring information density\n- **Font Size Cheat Sheet**: 15-level type scale embedded in SKILL.md for cross-session consistency\n- **Auto Validation**: 12-rule validate.js (overflow/footer collision/min font/density/rhythm/title consistency/accent area etc.)\n- **Text Compression**: Preserve original quotes + scene descriptions, compress to <= 1000 characters\n- **Local Delivery (default)**: MD→HTML→PNG→local folder, all content processed locally only\n- **Optional Feishu cloud-drive sync**: uploaded only after explicit user consent (⚠️ content leaves local machine, see Privacy below)\n\n## Privacy & Data Flow\n\n**Core capability is local processing**: MD text → HTML assembly → PNG screenshot → local folder delivery. Article content, image assets, and generated artifacts are processed locally by default and never uploaded to any external service.\n\n**Optional external capabilities** (require explicit user consent, never auto-executed):\n- **Image search**: Calls Pexels/Pixabay API to search free stock photos. ⚠️ Only search keywords and image downloads are sent to Pexels/Pixabay servers — **article content is never uploaded**\n- **Feishu cloud-drive sync**: Uploads generated PNGs + text drafts to user's Feishu cloud drive. ⚠️ Uploading means content leaves the local machine — do not enable if the article contains unpublished/sensitive/proprietary material\n\n**External network dependencies**: Core rendering is fully local (starts 127.0.0.1 HTTP server to load pre-stored HTML template + Puppeteer screenshot, no external network). Optional external capabilities (each requires independent user consent): (1) Pexels/Pixabay/Unsplash image API search (sends search keywords); (2) trae-api-cn AI image generation API (sends prompt, TRAE internal only); (3) Feishu cloud drive upload. v7.6 removed Google Fonts CDN references, templates use system font fallback stacks.\n\n## Quick Start\n\n```bash\nnpx clawhub@latest install EdwardWason/xhs-crafter\n```\n\n## Usage\n\nIn TRAE / Claude Code / OpenClaw, trigger by explicitly requesting image layout:\n\n```\nPlease use xhs-crafter to format this MD article as WeChat image cards: /path/to/article.md\n```\n\n5-step workflow — just give MD, get local output folder (external capabilities require user consent):\n\n1. **Intake** — Identify content category (auto-inferred)\n2. **Content Plan** — Content planning (compression ladder + page roles + rhythm planning)\n3. **Compose** — Assemble HTML (dual style + 10 themes + 28 layouts)\n4. **Validate** — Self-check (density + images + rhythm + style)\n5. **Screenshot & Deliver** — Screenshot delivery (local folder by default; Feishu cloud-drive sync requires explicit user consent)\n\n## File Structure\n\n```\nxhs-crafter/\n├── SKILL.md                              # Main skill file (entry point, with font size cheat sheet)\n├── assets/\n│   ├── template-editorial-card.html      # Editorial seed template\n│   ├── template-swiss-card.html          # Swiss seed template\n│   ├── screenshot.js                     # Puppeteer screenshot script\n│   └── validate.js                       # 12-rule auto validation script\n└── references/\n    ├── style-system.md                   # Editorial vs Swiss identity test + anti-patterns\n    ├── category-cookbook.md              # 13-category routing table\n    ├── content-planning.md               # Compression ladder + page roles + hook patterns\n    ├── portrait-fill.md                  # 3:4 density rules + three-layer rhythm system\n    ├── image-overlay.md                  # Text-on-image rules\n    ├── background-systems.md             # Three-layer background + atmosphere intensity\n    ├── theme-presets.md                  # 10 theme CSS variable definitions\n    ├── components.md                     # Font/size/spacing spec (authoritative source)\n    ├── layout-recipes.md                 # 28 layout template details\n    ├── screenshot-treatment.md           # Screenshot framing spec\n    ├── image-sources.md                  # Image API integration + AI image verification\n    └── workflow.md                       # Workflow detailed reference\n```\n\n## Category Mapping\n\n| Category | Style | Theme |\n|----------|-------|-------|\n| Business/Tech Analysis | Editorial | Indigo Porcelain |\n| Career/Productivity | Swiss | IKB Blue |\n| Travel/Lifestyle | Editorial | Kraft Paper |\n| Tutorial/Tools | Swiss | IKB Blue |\n| Film/Books | Editorial | Ink Classic |\n| Gaming | Editorial (dark) | Midnight Ink |\n| Food | Editorial | Kraft Paper |\n| Makeup | Editorial | Dune |\n| Fashion | Editorial | Indigo Porcelain |\n| Home | Editorial | Forest Ink |\n| Fitness/Emotion/Recommendation | Swiss | Safety Orange |\n\n## Documentation\n\n| File | Purpose |\n|------|---------|\n| [SKILL.md](SKILL.md) | Main skill file, 5-step workflow + font size cheat sheet + density rules + rhythm rules |\n| [references/style-system.md](references/style-system.md) | Editorial vs Swiss visual anchors + identity test |\n| [references/components.md](references/components.md) | Font/size/spacing spec (authoritative source) |\n| [references/layout-recipes.md](references/layout-recipes.md) | 28 layout template details |\n| [references/theme-presets.md](references/theme-presets.md) | 10 theme CSS variable definitions |\n| [references/category-cookbook.md](references/category-cookbook.md) | 13-category style/theme/layout mapping |\n| [references/background-systems.md](references/background-systems.md) | Three-layer background + atmosphere intensity |\n| [references/portrait-fill.md](references/portrait-fill.md) | 3:4 density rules + three-layer rhythm system |\n| [references/image-sources.md](references/image-sources.md) | Image API integration + AI image verification |\n| [CHANGELOG.md](CHANGELOG.md) | Version change log |\n\nLicense: MIT-0\n\nFile v7.7.0:_meta.json\n\n{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"xhs-crafter\",\n  \"version\": \"7.7.0\",\n  \"publishedAt\": 1784085963647\n}\n\nFile v7.7.0:references/background-systems.md\n\n# Background Systems\n\n> xhs-crafter 背景系统规范——grain纹理、paper-wash水洗、WebGL流体\n> 画布基准：1080 × 1440（3:4）\n\n---\n\n## 三层背景架构\n\nEditorial Magazine 页面使用三层背景叠加，从底到顶：\n\n```\n┌─────────────────────────────────────┐\n│  Layer 3: grain（纹理）              │  z-index: 2, pointer-events: none\n│  ┌─────────────────────────────────┐│\n│  │  Layer 2: content（内容）        ││  z-index: 1\n│  │  ┌─────────────────────────────┐││\n│  │  │  Layer 1: paper-wash（水洗） │││  z-index: 0\n│  │  │  ┌─────────────────────────┐│││\n│  │  │  │  Layer 0: paper（底色）  ││││  background: var(--paper)\n│  │  │  └─────────────────────────┘│││\n│  │  └─────────────────────────────┘││\n│  └─────────────────────────────────┘│\n└─────────────────────────────────────┘\n```\n\n**禁止使用纯平背景**——Editorial 的核心美学是\"纸墨感\"，flat beige 会显得死板。\n\n---\n\n## Layer 0: Paper（底色）\n\n由 `--paper` CSS 变量控制，每个主题预设自带。\n\n```css\n.poster {\n  background: var(--paper);\n}\n```\n\n**硬规则**：\n- `--paper` 永远不是 `#FFFFFF`——纯白刺眼，印刷行业从不使用\n- `--paper` 永远不是 `#000000`——纯黑暴力，Midnight Ink 用 `#0e0d0c`\n\n---\n\n## Layer 1: Paper-Wash（水洗层）\n\n径向渐变叠加，模拟纸张的不均匀吸墨效果。\n\n### Light 主题（默认）\n\n```css\n.paper-wash {\n  position: absolute;\n  inset: 0;\n  pointer-events: none;\n  z-index: 0;\n  background:\n    radial-gradient(ellipse at 20% 80%, var(--wash-color) 0%, transparent 60%),\n    radial-gradient(ellipse at 80% 20%, var(--wash-color) 0%, transparent 50%),\n    linear-gradient(var(--wash-angle), transparent 0%, var(--wash-color) 100%);\n}\n```\n\n默认变量：\n```css\n:root {\n  --wash-color: rgba(10, 31, 61, .02);\n  --wash-angle: 160deg;\n}\n```\n\n### Midnight Ink 主题（覆盖）\n\n```css\n[data-theme=\"midnight-ink\"] .paper-wash {\n  background:\n    radial-gradient(80% 50% at 28% 16%, rgba(212, 160, 74, .12), transparent 64%),\n    radial-gradient(70% 60% at 80% 86%, rgba(60, 40, 20, .20), transparent 72%),\n    linear-gradient(180deg, rgba(236, 226, 207, .02), rgba(0, 0, 0, .32));\n}\n```\n\n**硬规则**：\n- Light 主题的 wash-color 透明度 ≤.03——若隐若现，不是渐变背景\n- Midnight Ink 的暖光斑必须偏左上角（28% 16%），模拟台灯照射\n\n---\n\n## Layer 2: Grain（纹理层）\n\n模拟纸张纤维/印刷网点的细微纹理。\n\n### Light 主题（默认）\n\n```css\n.grain {\n  position: absolute;\n  inset: 0;\n  pointer-events: none;\n  z-index: 2;\n  opacity: var(--grain-opacity);\n  mix-blend-mode: var(--grain-blend);\n  background-image:\n    radial-gradient(circle at 17% 32%, rgba(0,0,0,.15) 0%, transparent 50%),\n    radial-gradient(circle at 72% 18%, rgba(0,0,0,.10) 0%, transparent 40%),\n    radial-gradient(circle at 45% 78%, rgba(0,0,0,.12) 0%, transparent 45%),\n    radial-gradient(circle at 88% 55%, rgba(0,0,0,.08) 0%, transparent 35%);\n}\n```\n\n默认变量：\n```css\n:root {\n  --grain-opacity: .04;\n  --grain-blend: multiply;\n}\n```\n\n### Midnight Ink 主题（覆盖）\n\n```css\n[data-theme=\"midnight-ink\"] .grain {\n  opacity: .26;\n  mix-blend-mode: screen;\n  background-image:\n    radial-gradient(rgba(255, 244, 214, .10) 1px, transparent 1px);\n}\n```\n\n**硬规则**：\n- Light 主题 grain-opacity ≤.06——纹理是暗示，不是噪点\n- Midnight Ink grain-opacity .26 + screen 混合——暗色页需要更明显的纹理才不会死板\n- grain 不得降低文字可读性——如果正文变模糊，降低 opacity\n\n---\n\n## 氛围强度分级\n\n不同页面角色使用不同氛围强度：\n\n| 页面角色 | 氛围强度 | grain-opacity | paper-wash | 说明 |\n|---------|---------|---------------|------------|------|\n| 封面 | Strong | .06 | 全部3层 | 封面需要氛围感 |\n| 引言/引语 | Strong | .06 | 全部3层 | 引用页需要仪式感 |\n| 封底 | Strong | .06 | 全部3层 | 收尾需要余韵 |\n| 数据/清单 | Subtle | .02 | 仅1层 | 数据页需要清晰 |\n| 正文/essay | Medium | .04 | 2层 | 阅读页需要舒适 |\n\n**CSS 实现**：\n\n```css\n/* Strong 氛围（封面/引言/封底） */\n.poster.atmosphere-strong .grain { opacity: .06; }\n.poster.atmosphere-strong .paper-wash { opacity: 1; }\n\n/* Subtle 氛围（数据/清单） */\n.poster.atmosphere-subtle .grain { opacity: .02; }\n.poster.atmosphere-subtle .paper-wash { opacity: .3; }\n```\n\n---\n\n## 满铺图页背景\n\n封面和封底使用满铺背景图时，背景系统简化：\n\n```\n┌─────────────────────────────────────┐\n│  Layer 4: hero-content（文字内容）   │  z-index: 3\n│  ┌─────────────────────────────────┐│\n│  │  Layer 3: hero-overlay（遮罩）   ││  z-index: 1\n│  │  ┌─────────────────────────────┐││\n│  │  │  Layer 2: grain（纹理）      │││  z-index: 2\n│  │  │  ┌─────────────────────────┐│││\n│  │  │  │  Layer 1: hero-bleed    ││││  z-index: 0\n│  │  │  │  （满铺背景图）           ││││\n│  │  │  └─────────────────────────┘│││\n│  │  └─────────────────────────────┘││\n│  └─────────────────────────────────┘│\n└─────────────────────────────────────┘\n```\n\n**关键规则**：\n1. hero-overlay 使用渐变遮罩，不是纯色半透明块\n2. 遮罩方向：从上到下加深，确保底部文字可读\n3. 遮罩颜色取自主题的 ink 色——Indigo Porcelain 用深蓝遮罩，Kraft Paper 用深棕遮罩\n4. grain 仍然叠加在 overlay 之上，保持纸墨感一致性\n\n### Light 主题遮罩\n\n```css\n.hero-overlay {\n  background: linear-gradient(180deg,\n    rgba(10, 31, 61, .55) 0%,\n    rgba(10, 31, 61, .25) 40%,\n    rgba(10, 31, 61, .45) 100%\n  );\n}\n```\n\n### Midnight Ink 遮罩\n\n```css\n[data-theme=\"midnight-ink\"] .hero-overlay {\n  background: linear-gradient(180deg,\n    rgba(14, 13, 12, .50) 0%,\n    rgba(14, 13, 12, .20) 35%,\n    rgba(14, 13, 12, .60) 100%\n  );\n}\n```\n\n---\n\n## Swiss International 背景\n\nSwiss 体系不使用 grain 和 paper-wash，背景极简：\n\n```css\n/* Swiss 使用纯 paper 底色 + 可选网格点阵 */\n.poster.swiss {\n  background: var(--paper);\n}\n\n/* 可选：极细网格点阵（仅用于数据页） */\n.poster.swiss.grid-dots {\n  background-image:\n    radial-gradient(circle, var(--grey-2) 1px, transparent 1px);\n  background-size: 24px 24px;\n}\n```\n\n**硬规则**：\n- Swiss 不使用 grain 纹理\n- Swiss 不使用 paper-wash 水洗\n- Swiss 网格点阵仅用于数据页，且 opacity ≤.3\n- Swiss 封面不使用网格点阵\n\n---\n\n## 反模式\n\n| 反模式 | 问题 | 修复 |\n|-------|------|------|\n| 纯平 beige 背景 | 像网页不像杂志 | 添加 grain + paper-wash |\n| grain-opacity >.10 | 文字模糊不可读 | 降至 .04-.06 |\n| 全页渐变背景 | 像PPT不像杂志 | 用 paper-wash（透明度≤.03）代替 |\n| 遮罩用纯色半透明 | 死板无层次 | 改用渐变遮罩 |\n| Swiss 用 grain | 破坏极简感 | Swiss 不用 grain |\n| 暗色页不加 grain 覆盖 | 暗色背景死板 | Midnight Ink 必须加 screen 混合 grain |\n\nFile v7.7.0:references/category-cookbook.md\n\n# Category Cookbook\n\nPer-category cheat sheet for common content types. Each entry maps a category to style mode, theme, recipes, and image source strategy.\n\nWhen the user names a category, find the row here and start from the listed recipes instead of building from a blank file.\n\n---\n\n## 商业/科技分析 · Business & Tech Analysis\n\n**Strongest fit for our skill.**\n\n- **Recipes**: M01 (text-led cover) or M16 (image-led cover when hero image available), M04 (pull quote), M08 (pipeline), M12 (data cards), M07 (closing note)\n- **Style mode**: Editorial × Indigo Porcelain (tech/AI) or × Ink Classic (general business). Swiss × IKB Blue for pure data posts\n- **Theme**: Indigo Porcelain for tech/AI topics; Ink Classic for general business; IKB Blue for data-heavy analysis\n- **Text scheme**: Text-beside-image for feature pages. Text-on-image only for cover with qualified photo. Body pages use serif text + data cards + pull quotes\n- **Image source**: AI generated (editorial documentary style) > Unsplash (tech/office scenes) > Pexels (Chinese keyword search). Avoid stock handshake/laptop photos\n- **Content shape**: 5-7 pages. Cover (hook + 1-line deck) → opening thesis + data → 2-3 evidence pages (pipeline/ledger/quote) → closing\n- **Pitfalls**:\n  1. Generic \"industry analysis\" voice without specific numbers. Cure: every claim needs a data point\n  2. Too many data cards without narrative. Cure: alternate data pages with essay/quote pages\n  3. Cover with vague hype instead of concrete hook\n\n---\n\n## 职场/干货 · Workplace & How-to\n\n**Strong fit.** This is what Swiss-International was made for.\n\n- **Recipes**: S01 (cover), S02 (comparison), S05 (warning rows), S06 (pipeline), S07 (takeaway ledger), S09 (KPI tower), S11 (stacked ledger)\n- **Style mode**: Swiss × IKB Blue or × Safety Orange. Avoid lemon-yellow/lemon-green for serious content\n- **Theme**: IKB Blue (default), Safety Orange (warning/urgent content)\n- **Text scheme**: Text-only or text-with-diagram. Almost never text-on-photo (workplace photos read as stock)\n- **Image source**: Avoid stock business photos. Prefer diagrams, screenshots of real artifacts (Notion, Linear, Figma), or omit. Generated images rarely add value\n- **Content shape**: 5-9 pages. Cover question/claim → context KPI → 3-5 numbered insights as ledger → one comparison or pipeline diagram → takeaway\n- **Pitfalls**:\n  1. Listicle voice (\"8 个让你...\"). Cure: rewrite as numbered argument, not tips\n  2. Cheap \"advice\" energy (\"一定要\", \"千万别\"). Cure: replace with observed action verbs + a number\n  3. Stock-photo seasoning (handshake, laptop-with-coffee). Cure: omit, or use a small icon glyph\n\n---\n\n## 旅行/生活方式 · Travel & Lifestyle\n\n**Strongest fit.**\n\n- **Recipes**: M16 (image-led cover when user has great photos), M01 (text-led cover), M02 (field-note photo), M11 (marginalia essay), S11 (itinerary ledger), M07 (closing note)\n- **Style mode**: Editorial × Kraft Paper (warm-tone destinations) or × Dune (art/creative destinations) or × Forest Ink (mountain/wilderness)\n- **Theme**: Kraft Paper for warm/cultural trips; Dune for art/design destinations; Forest Ink for outdoor/nature\n- **Text scheme**: Text beside image is default. Cover can use text-on-image only when photo has quiet zone. Body pages use photo + caption pairs (field-note style)\n- **Image source**: User photos > Pexels (Chinese keyword search for domestic destinations) > Unsplash (overseas/English keywords) > Flickr CC (documentary feel)\n- **Content shape**: 5-7 pages. Cover (destination + dates) → atmosphere photo + lead → itinerary ledger → 2-3 field notes → closing quote\n- **Pitfalls**: Generic \"best places in X city\" listicle voice. Cure: keep one specific date/weather/mileage detail per page\n\n---\n\n## 教程/工具 · Tutorial & Tools\n\n**Strong fit.** Screenshot treatment is the key differentiator.\n\n- **Recipes**: S01 (cover), S06 (pipeline for steps), S08 (duo compare), S11 (stacked ledger for shortcuts), M04 (pull quote for key insight)\n- **Style mode**: Swiss × IKB Blue (default) or × Safety Orange (warning tips). Editorial × Indigo Porcelain for long-form tutorials\n- **Theme**: IKB Blue for tool tutorials; Indigo Porcelain for methodology tutorials\n- **Text scheme**: Screenshot-heavy. Use `.frame-shot` + `.device-browser` for all screenshots. Text above/below screenshots, not beside\n- **Image source**: User screenshots (mandatory for real tutorials). Use `.frame-shot` with device chrome + background texture. Never use stock UI screenshots\n- **Content shape**: 5-8 pages. Cover (tool name + what you'll learn) → context → 3-5 step pages (screenshot + 1-2 sentence instruction) → tips/shortcuts ledger → closing\n- **Pitfalls**:\n  1. Screenshots too small to read. Cure: give screenshots 45-65% page height\n  2. Full-screen dumps without focus. Cure: crop to relevant area, preserve readable UI labels\n  3. Dark screenshots on dark background. Cure: use `.frame-shot` with paper-2 background\n\n---\n\n## 影视/读书 · Film & Books\n\n**Strong fit** for reviews, scene analysis, quote cards.\n\n- **Recipes**: M01 (cover), M04 (pull quote for memorable lines), M10 (evidence feature for scene analysis), M11 (marginalia essay), S02 (comparison), S12 (matrix for weekly roundups)\n- **Style mode**: Editorial × Ink Classic or × Indigo Porcelain. Letterboxd visual vocabulary fits Editorial naturally\n- **Theme**: Ink Classic (default for reviews); Indigo Porcelain (sci-fi/tech films); Kraft Paper (literature/classics)\n- **Text scheme**: Text-beside-image for review cards (poster on left, take on right). Text-on-image only for atmospheric quote pages\n- **Image source**: Official posters/stills. Do not generate fake stills. User photos of book covers acceptable\n- **Content shape**: 5-7 pages. Cover (title + year + 1-line take) → 1-2 scene captures → director-quote/theme pullquote → verdict ledger\n- **Pitfalls**:\n  1. Fake film-festival typography (adding fake awards badges). Don't\n  2. Spoiler in title without warning. Mark `剧透` in kicker if needed\n\n---\n\n## 游戏 · Gaming\n\n**Strong fit** for journals, recaps, build lists. **Has image-rights risk.**\n\n- **Recipes**: M01 (cover with full-bleed art), M08 (boss tier ledger), S07 (takeaway ledger), S11 (chapter timeline), M15 (build before/after)\n- **Style mode**: Editorial dark (Ink Classic with paper inverted to near-black) for atmospheric games. Swiss for esports/competitive data\n- **Theme**: Midnight Ink for atmospheric games; IKB Blue for esports/data\n- **Text scheme**: Text-on-image is standard for game covers (game art is the primary draw). Use subject mapping from image-overlay.md\n- **Image source**: Wallhaven for keyword pulls, official screenshots. Always disclose copyright risk and log to SOURCES.md\n- **Content shape**: 4-6 pages. Cover (game name + playtime) → first impression → chapter ledger → memorable boss/scene → verdict\n- **Pitfalls**: Score-card seriousness (8.5/10 in giant block). Keep verdict as one short clause, not a number\n\n---\n\n## 美食 · Food\n\n**Split fit.** Recipes work. Food-photo showcase does not.\n\n- **Recipe\n\nArchive v7.6.0: 22 files, 88161 bytes\n\nFiles: assets/screenshot.js (6937b), assets/template-editorial-card.html (17998b), assets/template-swiss-card.html (14289b), assets/validate.js (11444b), CHANGELOG.md (12030b), docs/session-handoff.md (11143b), README.md (13741b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18947b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (9666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (4716b), skill-card.md (2927b), SKILL.md (19879b), _meta.json (130b)\n\nArchive v7.5.0: 22 files, 86580 bytes\n\nFiles: assets/screenshot.js (6937b), assets/template-editorial-card.html (18040b), assets/template-swiss-card.html (14426b), assets/validate.js (11444b), CHANGELOG.md (9539b), docs/session-handoff.md (11068b), README.md (13587b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18455b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (9666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (4419b), skill-card.md (2891b), SKILL.md (19211b), _meta.json (130b)\n\nArchive v7.4.0: 23 files, 89355 bytes\n\nFiles: assets/image-search.js (12561b), assets/screenshot.js (6937b), assets/template-editorial-card.html (18040b), assets/template-swiss-card.html (14426b), assets/validate.js (11444b), CHANGELOG.md (7716b), docs/session-handoff.md (11084b), README.md (13587b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18455b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (9666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (3669b), skill-card.md (2691b), SKILL.md (19490b), _meta.json (130b)\n\nArchive v7.3.1: 23 files, 81043 bytes\n\nFiles: assets/screenshot.js (6914b), assets/template-editorial-card.html (18040b), assets/template-swiss-card.html (14426b), assets/validate.js (11444b), CHANGELOG.md (4676b), docs/session-handoff.md (10468b), LICENSE (906b), README.md (11081b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18455b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (8666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (3669b), skill-card.md (2650b), SKILL.md (15094b), _meta.json (130b)\n\nArchive v7.3.0: 22 files, 75317 bytes\n\nFiles: assets/screenshot.js (3997b), assets/template-editorial-card.html (18040b), assets/template-swiss-card.html (14426b), assets/validate.js (11444b), CHANGELOG.md (4235b), LICENSE (906b), README.md (11081b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18455b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (8666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (3669b), skill-card.md (2857b), SKILL.md (15094b), _meta.json (130b)\n\nArchive v7.2.0: 22 files, 73296 bytes\n\nFiles: assets/screenshot.js (3997b), assets/template-editorial-card.html (18040b), assets/template-swiss-card.html (14426b), assets/validate.js (7649b), CHANGELOG.md (3453b), LICENSE (906b), README.md (11081b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18455b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (8666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (3669b), skill-card.md (2561b), SKILL.md (13080b), _meta.json (130b)\n\nArchive v7.1.1: 23 files, 73138 bytes\n\nFiles: assets/screenshot.js (3997b), assets/template-editorial-card.html (18040b), assets/template-swiss-card.html (14426b), assets/validate.js (5235b), CHANGELOG.md (2932b), LICENSE (906b), README.md (11081b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18455b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (8666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (3669b), release-body.json (1219b), skill-card.md (2805b), SKILL.md (13028b), _meta.json (130b)\n\nArchive v7.1.0: 22 files, 70699 bytes\n\nFiles: assets/screenshot.js (3997b), assets/template-editorial-card.html (18040b), assets/template-swiss-card.html (14426b), assets/validate.js (5235b), CHANGELOG.md (2517b), LICENSE (906b), README.md (8916b), references/background-systems.md (8239b), references/category-cookbook.md (14088b), references/components.md (18455b), references/content-planning.md (4731b), references/image-overlay.md (6526b), references/image-sources.md (8666b), references/layout-recipes.md (21550b), references/portrait-fill.md (7459b), references/screenshot-treatment.md (4424b), references/style-system.md (4224b), references/theme-presets.md (8543b), references/workflow.md (3669b), skill-card.md (2474b), SKILL.md (11266b), _meta.json (130b)","readmeExcerpt":"Skill: Xhs Crafter Owner: edwardwason Summary: 将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/... Tags: article:7.5.0, card:7.5.0, editorial:7.5.0, formatter:7.5.0, image:7.5.0, latest:7.8.0, markdown:7.5.0, publishing:7.5.0, swiss:7.5.0, wechat:7.5.0, xiaohongshu:7.5.0 Version history: v7.8.0 | 2026-07-15T04","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"<桌面>/<slug>公众号素材/\n├── p1-cover.png\n├── p2-xxx.png\n├── ...\n├── pN-finale.png\n└── <slug>-文字稿.txt   # ≤1000字压缩文字"},{"language":"text","snippet":"这篇我需要 1-2 张图。三种走法：\n  A. 你自己有照片/截图，传给我（推荐——最不\"AI感\"，完全本地处理）\n  B. 我去 Pexels/Pixabay 帮你找（⚠️ 会将搜索词发送到外部API，但不上传文章原文）\n  C. 用 AI 生成（⚠️ 会将生图prompt发送到trae-api-cn.mchost.guru生图API，prompt可能含文章主题/场景描述，仅限TRAE内部环境）"},{"language":"text","snippet":"本地文件夹已交付。是否需要同步到飞书云盘？\n  - 是 → 执行下方上传步骤\n  - 否 → 结束（本地文件夹已是完整交付物）"},{"language":"bash","snippet":"npx clawhub@latest install EdwardWason/xhs-crafter"},{"language":"text","snippet":"请用 xhs-crafter 把这篇 MD 文章排版为公众号贴图：/path/to/article.md"},{"language":"text","snippet":"xhs-crafter/\n├── SKILL.md                              # 技能主文件（入口，含字号速查表）\n├── assets/\n│   ├── template-editorial-card.html      # Editorial 种子模板\n│   ├── template-swiss-card.html          # Swiss 种子模板\n│   ├── screenshot.js                     # Puppeteer 截图脚本\n│   └── validate.js                       # 12项自动验证脚本\n└── references/\n    ├── style-system.md                   # Editorial vs Swiss 身份测试+反模式\n    ├── category-cookbook.md              # 13 品类路由表\n    ├── content-planning.md               # 压缩阶梯+页面角色+钩子模式\n    ├── portrait-fill.md                  # 3:4 密度规则+三层节奏系统\n    ├── image-overlay.md                  # 文字压图规则\n    ├── background-systems.md             # 三层背景架构+氛围强度分级\n    ├── theme-presets.md                  # 10 套主题色 CSS 变量\n    ├── components.md                     # 字体/字号/间距规范（权威来源）\n    ├── layout-recipes.md                 # 28 种布局模板\n    ├── screenshot-treatment.md           # 截图装裱规范\n    ├── image-sources.md                  # 图库 API 接入+AI生图验证\n    └── workflow.md                       # 工作流详细参考"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: \"xhs-crafter\"\ndescription: \"将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/Unsplash图库API搜索（发送搜索关键词到外部API）；(2)AI生图API（发送prompt到trae-api-cn，仅限TRAE内部环境）；(3)飞书云盘上传（上传生成的PNG+txt到飞书服务器）。Invoke when用户明确说'xhs-crafter排版'、'用xhs-crafter转图片'、'公众号贴图排版'、'小红书图文卡片'。Do NOT use for原创写作、纯文字排版、视频制作、用户只提到MD文件路径但未明确要求图片排版。\"\nslug: \"xhs-crafter\"\ndisplayName: \"XHS Crafter\"\nversion: \"7.8.0\"\nsummary: \"将MD文章排版为3:4比例精美图片+压缩文字稿，用于公众号/小红书贴图发布\"\nlicense: \"MIT-0\"\n---\n\n# XHS Crafter — 文章转图片卡片\n\n## 任务\n将用户提供的MD文章内容，排版为多张3:4比例(1080×1440)的精美HTML页面，截图为PNG，压缩为≤1000字文字稿，文件夹交付。不做原创写作，不做视频，不做纯文字排版。\n\n## 隐私与数据流声明（用户须知）\n\n**本技能的数据流边界**：\n- **本地处理（默认）**：MD文本→HTML组装→PNG截图→本地文件夹交付。所有文章内容、图片素材、生成产物默认仅在本地处理，不上传任何外部服务\n- **可选外部能力（需用户明确同意）**：\n  - 图片搜索：调用Pexels/Pixabay API搜索免费图库照片（仅搜索词和图片下载，不上传文章内容）\n  - 飞书云盘同步：将生成PNG+文字稿上传到用户飞书云盘（需用户明确同意，且文章内容可能包含未发布素材）\n- **外部网络依赖**：v7.6 已移除 Google Fonts CDN 引用，模板使用系统字体回退栈（Noto Serif SC / Source Han Serif SC / Songti SC / PingFang SC / Consolas 等），完全本地渲染，无外部字体加载\n\n**用户警告**：\n- ⚠️ 如果文章包含未发布/敏感/专有内容，请谨慎使用飞书云盘同步功能——上传即意味着内容离开本地\n- ⚠️ 图片搜索会将搜索关键词发送到Pexels/Pixabay服务器，但不会发送文章原文\n- ⚠️ 飞书云盘同步需要用户已登录lark-cli，且目标文件夹由用户飞书账号持有\n\n**权限声明**（v7.7 完整披露所有行为）：\n\n| 能力类别 | 是否使用 | 说明 |\n|---------|---------|------|\n| 网络访问 | ✅ | **核心行为**：启动本地 127.0.0.1 HTTP server 加载预存 HTML 模板供 Puppeteer 截图（不出局域网）。**可选外部访问**（每项需用户独立同意）：Pexels/Pixabay/Unsplash 图库 API 搜索；trae-api-cn AI 生图 API（仅限 TRAE 内部环境）；飞书云盘上传 |\n| 文件读写 | ✅ | 读 MD 文章 + 预存 HTML 模板（assets/template-*.html）；写 output/ 目录 PNG+txt；写 `$env:TEMP` 交付文件夹；可选下载外部图片到 assets/ 目录（受 ALLOWED_HOSTS 白名单限制） |\n| 环境变量 | ✅ | `PEXELS_API_KEY`、`PIXABAY_API_KEY`（图库搜索，可选）；`CHROME_PATH`（可选，浏览器路径） |\n| subprocess | ✅ | `python -m http.server --bind 127.0.0.1`（本地回环 HTTP server，截图用）；`node assets/screenshot.js`（Puppeteer 截图）；`node assets/validate.js`（自动验证）；`curl.exe`（可选，下载外部图片）；`explorer.exe`（打开交付文件夹） |\n| 外部 API | ✅ | Pexels/Pixabay/Unsplash 图片搜索 API（可选，发送搜索关键词）；trae-api-cn.mchost.guru AI 生图 API（可选，发送 prompt，仅限 TRAE 内部环境）；飞书 lark-cli drive API（可选云盘同步，上传 PNG+txt） |\n\n> ⚠️ **核心行为说明**：本技能的核心能力是 **本地 HTML 模板填充 + Puppeteer 截图渲染**，不是 MD→HTML 编译管道。MD 内容由 AI 读取后填入预存的 HTML 模板（assets/template-editorial-card.html 或 template-swiss-card.html），然后启动本地 HTTP server 加载该 HTML 供 Puppeteer 截图为 PNG。核心流程不涉及外部网络访问。\n\n## 输出格式\n\n```\n<桌面>/<slug>公众号素材/\n├── p1-cover.png\n├── p2-xxx.png\n├── ...\n├── pN-finale.png\n└── <slug>-文字稿.txt   # ≤1000字压缩文字\n```\n\n## 工作流：5步（默认本地全自动，外部能力需用户同意）\n\n**核心原则**：用户给MD，直接出本地文件夹。Step 1-2在脑内完成（不输出长文规划），Step 3-5连续执行不等待用户确认。\n\n**外部能力同意门控**（2道，仅在触发外部网络/云盘时询问，本地渲染不询问。每道门控独立询问，不批量授权）：\n1. **图片搜索门控**（Step 1，用户无图且需背景图时）：询问是否调用Pexels/Pixabay API搜索\n2. **飞书同步门控**（Step 5，本地交付完成后）：询问是否上传到飞书云盘\n\n> ⚠️ **同意门控铁律**：每道门控必须独立询问，不得因用户说\"按流程走一遍\"、\"全流程\"、\"都行\"等模糊措辞而批量授权多个外部能力。用户必须对每个外部能力单独明确同意（\"是\"或具体指定）。\n\n### Step 1: Intake — 识别品类（脑内完成，不输出）\n从MD内容自动推断：\n- **内容品类**: 读 `references/category-cookbook.md` 路由。13个品类：商业/科技分析、职场/干货、旅行/生活方式、教程/工具、影视/读书、游戏、美食、彩妆、穿搭、家居、健身、情感、推荐。超出范围的品类（梦核/氛围感装饰风、Y2K/千禧辣妹、纯摄影展示）必须在设计前明"},{"path":"README.md","content":"# xhs-crafter\n\n将 Markdown 文章排版为 3:4 比例的精美图片卡片 + 压缩文字稿，用于微信公众号/小红书贴图发布。\n\n[![版本](https://img.shields.io/badge/version-7.8.0-blue)](https://github.com/EdwardWason/xhs-crafter)\n[![许可证](https://img.shields.io/badge/license-MIT--0-green)](LICENSE)\n[![ClawHub](https://img.shields.io/badge/ClawHub-xhs--crafter-orange)](https://clawhub.ai/EdwardWason/xhs-crafter)\n\n## 功能\n\n- **MD → 图片卡片**：自动将 Markdown 文章拆分排版为多张 1080x1440 (3:4) HTML 页面，截图为 PNG\n- **双风格系统**：Editorial Magazine（杂志风，衬线+暖纸底）和 Swiss International（瑞士网格风，无衬线+白底）\n- **13 品类适配**：商业/科技/职场/旅行/教程/影视/游戏/美食/彩妆/穿搭/家居/健身/情感/推荐，自动路由风格+主题+版式\n- **10 套主题色**：Ink Classic / Indigo Porcelain / Forest Ink / Kraft Paper / Dune / Midnight Ink / IKB Blue / Lemon Yellow / Lemon Green / Safety Orange\n- **28 种布局模板**：M01-M16（Editorial）+ S01-S12（Swiss）\n- **三层背景架构**：paper→wash→grain，氛围强度按页面角色分级（strong/medium/subtle）\n- **三层节奏系统**：明暗交替 + 氛围强弱 + 版式多样性\n- **密度铁律**：活跃构图 >= 78% 画布高度，确保信息密度\n- **字号速查表**：15级字号体系直接嵌入SKILL.md，确保跨会话一致性\n- **自动验证**：12项validate.js检查（溢出/footer碰撞/最小字号/密度/节奏/标题一致性/accent面积等）\n- **文字压缩**：保留原话引言+场景描述，压缩至 <= 1000 字\n- **本地交付（默认）**：MD→HTML→PNG→本地文件夹，所有内容仅本地处理\n- **可选飞书云盘同步**：用户明确同意后上传（⚠️ 内容会离开本地，详见下方隐私说明）\n\n## 隐私与数据流\n\n**核心能力是本地处理**：MD文本 → HTML组装 → PNG截图 → 本地文件夹交付。文章内容、图片素材、生成产物默认仅在本地处理，不上传任何外部服务。\n\n**可选外部能力**（需用户明确同意，不主动执行）：\n- **图片搜索**：调用Pexels/Pixabay API搜索免费图库照片。⚠️ 仅搜索词和图片下载会发送到Pexels/Pixabay服务器，**不会上传文章原文**\n- **飞书云盘同步**：将生成PNG+文字稿上传到用户飞书云盘。⚠️ 上传即意味着内容离开本地，如文章包含未发布/敏感/专有内容请勿启用\n\n**外部网络依赖**：核心渲染流程完全本地（启动 127.0.0.1 HTTP server 加载预存 HTML 模板 + Puppeteer 截图，无外部网络）。可选外部能力（每项需用户独立同意）：(1)Pexels/Pixabay/Unsplash 图库 API 搜索（发送搜索关键词）；(2)trae-api-cn AI 生图 API（发送 prompt，仅限 TRAE 内部环境）；(3)飞书云盘上传。v7.6 已移除 Google Fonts CDN 引用，模板使用系统字体回退栈。\n\n## 快速开始\n\n```bash\nnpx clawhub@latest install EdwardWason/xhs-crafter\n```\n\n## 使用方法\n\n在 TRAE / Claude Code / OpenClaw 中，明确要求图片排版时触发：\n\n```\n请用 xhs-crafter 把这篇 MD 文章排版为公众号贴图：/path/to/article.md\n```\n\n5 步工作流，用户只需给 MD，直接出本地文件夹（外部能力需用户同意）：\n\n1. **Intake** — 识别内容品类（自动推断）\n2. **Content Plan** — 内容规划（压缩阶梯+页面角色+节奏规划）\n3. **Compose** — 组装 HTML（双风格+10 主题+28 布局）\n4. **Validate** — 自检（密度+图片+节奏+风格）\n5. **Screenshot & Deliver** — 截图交付（本地文件夹默认；飞书云盘需用户明确同意）\n\n## 文件结构\n\n```\nxhs-crafter/\n├── SKILL.md                              # 技能主文件（入口，含字号速查表）\n├── assets/\n│   ├── template-editorial-card.html      # Editorial 种子模板\n│   ├── template-swiss-card.html          # Swiss 种子模板\n│   ├── screenshot.js                     # Puppeteer 截图脚本\n│   └── validate.js                       # 12项自动验证脚本\n└── references/\n    ├── style-system.md                   # Editorial vs Swiss 身份测试+反模式\n    ├── category-cookbook.md              # 13 品类路由表\n    ├── content-planning.md               # 压缩阶梯+页面角色+钩子模式\n    ├── portrait-fill.md                  # 3:4 密度规则+三层节奏系统\n    ├── image-overlay.md                  # 文字压图规则\n    ├── background-systems.md             # 三层背景架构+氛围强度分级\n    ├── theme-presets.md                  # 10 套主题色 CSS 变量\n    ├── components.md                     # 字体/字号/间距规范（权威来源）\n    ├── layout-recipes.md                 # 28 种布局模板\n    ├── screenshot-tr"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn75zj7vzdyvap84adxa8heyyd82f5eh\",\n  \"slug\": \"xhs-crafter\",\n  \"version\": \"7.8.0\",\n  \"publishedAt\": 1784090247706\n}"},{"path":"references/background-systems.md","content":"# Background Systems\n\n> xhs-crafter 背景系统规范——grain纹理、paper-wash水洗、WebGL流体\n> 画布基准：1080 × 1440（3:4）\n\n---\n\n## 三层背景架构\n\nEditorial Magazine 页面使用三层背景叠加，从底到顶：\n\n```\n┌─────────────────────────────────────┐\n│  Layer 3: grain（纹理）              │  z-index: 2, pointer-events: none\n│  ┌─────────────────────────────────┐│\n│  │  Layer 2: content（内容）        ││  z-index: 1\n│  │  ┌─────────────────────────────┐││\n│  │  │  Layer 1: paper-wash（水洗） │││  z-index: 0\n│  │  │  ┌─────────────────────────┐│││\n│  │  │  │  Layer 0: paper（底色）  ││││  background: var(--paper)\n│  │  │  └─────────────────────────┘│││\n│  │  └─────────────────────────────┘││\n│  └─────────────────────────────────┘│\n└─────────────────────────────────────┘\n```\n\n**禁止使用纯平背景**——Editorial 的核心美学是\"纸墨感\"，flat beige 会显得死板。\n\n---\n\n## Layer 0: Paper（底色）\n\n由 `--paper` CSS 变量控制，每个主题预设自带。\n\n```css\n.poster {\n  background: var(--paper);\n}\n```\n\n**硬规则**：\n- `--paper` 永远不是 `#FFFFFF`——纯白刺眼，印刷行业从不使用\n- `--paper` 永远不是 `#000000`——纯黑暴力，Midnight Ink 用 `#0e0d0c`\n\n---\n\n## Layer 1: Paper-Wash（水洗层）\n\n径向渐变叠加，模拟纸张的不均匀吸墨效果。\n\n### Light 主题（默认）\n\n```css\n.paper-wash {\n  position: absolute;\n  inset: 0;\n  pointer-events: none;\n  z-index: 0;\n  background:\n    radial-gradient(ellipse at 20% 80%, var(--wash-color) 0%, transparent 60%),\n    radial-gradient(ellipse at 80% 20%, var(--wash-color) 0%, transparent 50%),\n    linear-gradient(var(--wash-angle), transparent 0%, var(--wash-color) 100%);\n}\n```\n\n默认变量：\n```css\n:root {\n  --wash-color: rgba(10, 31, 61, .02);\n  --wash-angle: 160deg;\n}\n```\n\n### Midnight Ink 主题（覆盖）\n\n```css\n[data-theme=\"midnight-ink\"] .paper-wash {\n  background:\n    radial-gradient(80% 50% at 28% 16%, rgba(212, 160, 74, .12), transparent 64%),\n    radial-gradient(70% 60% at 80% 86%, rgba(60, 40, 20, .20), transparent 72%),\n    linear-gradient(180deg, rgba(236, 226, 207, .02), rgba(0, 0, 0, .32));\n}\n```\n\n**硬规则**：\n- Light 主题的 wash-color 透明度 ≤.03——若隐若现，不是渐变背景\n- Midnight Ink 的暖光斑必须偏左上角（28% 16%），模拟台灯照射\n\n---\n\n## Layer 2: Grain（纹理层）\n\n模拟纸张纤维/印刷网点的细微纹理。\n\n### Light 主题（默认）\n\n```css\n.grain {\n  position: absolute;\n  inset: 0;\n  pointer-events: none;\n  z-index: 2;\n  opacity: var(--grain-opacity);\n  mix-blend-mode: var(--grain-blend);\n  background-image:\n    radial-gradient(circle at 17% 32%, rgba(0,0,0,.15) 0%, transparent 50%),\n    radial-gradient(circle at 72% 18%, rgba(0,0,0,.10) 0%, transparent 40%),\n    radial-gradient(circle at 45% 78%, rgba(0,0,0,.12) 0%, transparent 45%),\n    radial-gradient(circle at 88% 55%, rgba(0,0,0,.08) 0%, transparent 35%);\n}\n```\n\n默认变量：\n```css\n:root {\n  --grain-opacity: .04;\n  --grain-blend: multiply;\n}\n```\n\n### Midnight Ink 主题（覆盖）\n\n```css\n[data-theme=\"midnight-ink\"] .grain {\n  opacity: .26;\n  mix-blend-mode: screen;\n  background-image:\n    radial-gradient(rgba(255, 244, 214, .10) 1px, transparent 1px);\n}\n```\n\n**硬规则**：\n- Light 主题 grain-opacity ≤.06——纹理是暗示，不是噪点\n- Midnight Ink grain-opacity .26 + screen 混合——暗色页需要更明显的纹理才不会死板\n- grain 不得降低文字可读性——如果正文变模糊，降低 opacity\n\n---\n\n## 氛围强度分级\n\n不同页面角色使用不同氛围强度：\n\n| 页面角色 | 氛围强度 | grain-opacity "},{"path":"references/category-cookbook.md","content":"# Category Cookbook\n\nPer-category cheat sheet for common content types. Each entry maps a category to style mode, theme, recipes, and image source strategy.\n\nWhen the user names a category, find the row here and start from the listed recipes instead of building from a blank file.\n\n---\n\n## 商业/科技分析 · Business & Tech Analysis\n\n**Strongest fit for our skill.**\n\n- **Recipes**: M01 (text-led cover) or M16 (image-led cover when hero image available), M04 (pull quote), M08 (pipeline), M12 (data cards), M07 (closing note)\n- **Style mode**: Editorial × Indigo Porcelain (tech/AI) or × Ink Classic (general business). Swiss × IKB Blue for pure data posts\n- **Theme**: Indigo Porcelain for tech/AI topics; Ink Classic for general business; IKB Blue for data-heavy analysis\n- **Text scheme**: Text-beside-image for feature pages. Text-on-image only for cover with qualified photo. Body pages use serif text + data cards + pull quotes\n- **Image source**: AI generated (editorial documentary style) > Unsplash (tech/office scenes) > Pexels (Chinese keyword search). Avoid stock handshake/laptop photos\n- **Content shape**: 5-7 pages. Cover (hook + 1-line deck) → opening thesis + data → 2-3 evidence pages (pipeline/ledger/quote) → closing\n- **Pitfalls**:\n  1. Generic \"industry analysis\" voice without specific numbers. Cure: every claim needs a data point\n  2. Too many data cards without narrative. Cure: alternate data pages with essay/quote pages\n  3. Cover with vague hype instead of concrete hook\n\n---\n\n## 职场/干货 · Workplace & How-to\n\n**Strong fit.** This is what Swiss-International was made for.\n\n- **Recipes**: S01 (cover), S02 (comparison), S05 (warning rows), S06 (pipeline), S07 (takeaway ledger), S09 (KPI tower), S11 (stacked ledger)\n- **Style mode**: Swiss × IKB Blue or × Safety Orange. Avoid lemon-yellow/lemon-green for serious content\n- **Theme**: IKB Blue (default), Safety Orange (warning/urgent content)\n- **Text scheme**: Text-only or text-with-diagram. Almost never text-on-photo (workplace photos read as stock)\n- **Image source**: Avoid stock business photos. Prefer diagrams, screenshots of real artifacts (Notion, Linear, Figma), or omit. Generated images rarely add value\n- **Content shape**: 5-9 pages. Cover question/claim → context KPI → 3-5 numbered insights as ledger → one comparison or pipeline diagram → takeaway\n- **Pitfalls**:\n  1. Listicle voice (\"8 个让你...\"). Cure: rewrite as numbered argument, not tips\n  2. Cheap \"advice\" energy (\"一定要\", \"千万别\"). Cure: replace with observed action verbs + a number\n  3. Stock-photo seasoning (handshake, laptop-with-coffee). Cure: omit, or use a small icon glyph\n\n---\n\n## 旅行/生活方式 · Travel & Lifestyle\n\n**Strongest fit.**\n\n- **Recipes**: M16 (image-led cover when user has great photos), M01 (text-led cover), M02 (field-note photo), M11 (marginalia essay), S11 (itinerary ledger), M07 (closing note)\n- **Style mode**: Editorial × Kraft Paper (warm-tone destinations) or × Dune (art/creative destinations) or × Forest Ink (mountain/wil"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/... Skill: Xhs Crafter Owner: edwardwason Summary: 将MD文章排版为3:4比例的精美图片+压缩文字稿，用于公众号/小红书贴图发布。核心能力是本地HTML模板填充+Puppeteer截图渲染（启动本地127.0.0.1 HTTP server加载预存HTML模板，非MD→HTML编译管道）。可选外部能力（每项需用户独立明确同意）：(1)Pexels/Pixabay/... Tags: article:7.5.0, card:7.5.0, editorial:7.5.0, formatter:7.5.0, image:7.5.0, latest:7.8.0, markdown:7.5.0, publishing:7.5.0, swiss:7.5.0, wechat:7.5.0, xiaohongshu:7.5.0 Version history: v7.8.0 | 2026-07-15T04","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1451,"uniquenessScore":48,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T20:00:07.871Z","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-10T20:00:07.871Z","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-10T23:47:11.155Z","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"}]}}}