skill-forge-hub 1.3.11 → 1.3.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.en.md +17 -0
  2. package/CHANGELOG.md +17 -0
  3. package/annual-report/resources/reference.html +1 -1
  4. package/annual-report/resources/skillforge-guide.html +1 -1
  5. package/article-to-html/resources/reference.html +1 -1
  6. package/article-to-html/resources/skillforge-guide.html +1 -1
  7. package/commit-heatmap/resources/reference.html +1 -1
  8. package/commit-heatmap/resources/skillforge-guide.html +1 -1
  9. package/daily-report/resources/reference.html +1 -1
  10. package/daily-report/resources/skillforge-guide.html +1 -1
  11. package/data-prepper/resources/skillforge-guide.html +1 -1
  12. package/decision-log/resources/skillforge-guide.html +1 -1
  13. package/deck-stage/resources/skillforge-guide.html +1 -1
  14. package/magic-deck/resources/reference.html +1 -1
  15. package/magic-deck/resources/skillforge-guide.html +1 -1
  16. package/meeting-minutes/resources/reference.html +1 -1
  17. package/meeting-minutes/resources/skillforge-guide.html +1 -1
  18. package/meta-forge/SKILL.md +3 -3
  19. package/meta-forge/resources/forge-rules.md +7 -4
  20. package/meta-forge/resources/skillforge-guide.html +1 -1
  21. package/monthly-report/resources/reference.html +1 -1
  22. package/monthly-report/resources/skillforge-guide.html +1 -1
  23. package/one-pager/SKILL.md +1 -1
  24. package/one-pager/resources/reference.html +49 -46
  25. package/one-pager/resources/skillforge-guide.html +1 -1
  26. package/package.json +1 -1
  27. package/prompt-pouch/SKILL.md +9 -2
  28. package/prompt-pouch/resources/reference.html +1 -1
  29. package/prompt-pouch/resources/skillforge-guide.html +1 -1
  30. package/quarterly-report/resources/reference.html +1 -1
  31. package/quarterly-report/resources/skillforge-guide.html +1 -1
  32. package/release-notes/resources/skillforge-guide.html +1 -1
  33. package/skill-doctor/resources/skillforge-guide.html +1 -1
  34. package/spec-doc2spec/resources/skillforge-guide.html +1 -1
  35. package/spec-spec2doc/resources/skillforge-guide.html +1 -1
  36. package/team-report-collector/resources/reference.html +1 -1
  37. package/team-report-collector/resources/skillforge-guide.html +1 -1
  38. package/template/SKILL.md +1 -1
  39. package/twin-docs/resources/skillforge-guide.html +1 -1
  40. package/weekly-report/resources/reference.html +1 -1
  41. package/weekly-report/resources/skillforge-guide.html +1 -1
package/CHANGELOG.en.md CHANGED
@@ -4,6 +4,23 @@
4
4
 
5
5
  Version history of the SkillForge npm package `skill-forge-hub` (command name `skill-forge`).
6
6
 
7
+ ## 1.3.13 (2026-11-13)
8
+
9
+ **one-pager template dock slimmer, no auto-close on pick, × close button (@15); version self-check for prompt-pouch & meta-forge**
10
+
11
+ - one-pager template dock: width tightened from 720px to 480px (fits the content instead of spanning 80% of the screen); picking a template no longer auto-folds the panel (users may click through to compare), close via the new × round button, handle reopens; stamp one-pager@14 → @15
12
+ - prompt-pouch version self-check at all touchpoints: every invocation (generate / init / maintain / retrieve / open) silently compares the page stamp against the current template (two meta lines, zero network, no data touched); the result only affects prompting, never execution — open asks proactively (with an update-point list, rebuild keeps the original pouch-id, prompts.json untouched), maintain/retrieve ends with a one-line nudge, declined once means silent for the session
13
+ - meta-forge mechanism #8 gains "tool-type product version self-check": the clarification list adds a product-type question (tool-type vs snapshot), forging tool-type skills (fixed page reopened often, accumulating data) automatically embeds the all-touchpoint self-check + per-scenario prompting; the static gate adds a matching check, and the template's rebuild section syncs the tool-type branch
14
+
15
+ ## 1.3.12 (2026-11-13)
16
+
17
+ **one-pager privilege templates get "mood response": six signature palettes now track the theme's light/dark mood (@14)**
18
+
19
+ - Fix: acid / glitch / vaporwave / inkwash / palace / landscape previously hardcoded their signature hues, so theme switching only changed the page chrome (docks / container) while the poster body stayed frozen — the reported "only the browser shell changes"
20
+ - Mood-response approach: every signature hue now uses CSS color-mix() against theme tokens — backgrounds mix var(--bg) at 22%, accents mix var(--accent) at 20%, ink text mixes var(--text) at 20%, muted text mixes var(--muted) at 25%; the signature look dominates (character preserved) while brightness/warmth subtly follow the theme (the switch is felt), covering all 25 themes with zero lookup tables
21
+ - Fade compatibility: the transient transition list across all 34 interactive-skin HTML files now also includes background — solid backgrounds (paper base, mountain layers) fade smoothly on theme switch, gradient backgrounds switch discretely per browser standard; existing color / border / shadow fades unaffected
22
+ - Template stamp one-pager@13 → @14
23
+
7
24
  ## 1.3.11 (2026-11-13)
8
25
 
9
26
  **Theme-fade full coverage: 22 install guide pages get the transition, 12 templates upgrade to Material easing**
package/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@
4
4
 
5
5
  SkillForge(技能锻造坊)npm 包 `skill-forge-hub`(命令名 `skill-forge`)版本变更记录。
6
6
 
7
+ ## 1.3.13(2026-11-13)
8
+
9
+ **one-pager 模板坞收窄适配 + 点选不收起 + × 关闭(@15);锦囊与元锻炉新增版本自检机制**
10
+
11
+ - one-pager 模板坞:宽度从 720px 收紧到 480px(内容适配不再占屏八成);点选模板不再自动收起(用户连点对比不同模板效果),改由面板右上角 × 圆钮关闭、把手可重开;版本戳 one-pager@14 → @15
12
+ - prompt-pouch 版本自检全时机:每次调用(生成/初始化/维护/取用/打开)先静默比对页面版本戳与模板当前版(两行 meta、零网络、不碰数据),结果只影响提示不影响执行;提示分场景——打开时主动询问升级(附更新点清单,回炉升级沿用原页 pouch-id、prompts.json 数据不动)、维护/取用收尾一句话轻提示、拒绝后本次会话静默
13
+ - meta-forge 机制八新增「工具型产物版本自检」:澄清清单新增产物类型一问(工具型/快照型分流),锻造工具型技能(固定页面反复打开、数据累积)自动植入全时机版本自检 + 场景分级提示;验证环静态门禁新增对应检查项,template 回炉节模板同步工具型分支
14
+
15
+ ## 1.3.12(2026-11-13)
16
+
17
+ **one-pager 特许模板「氛围响应」:六款风格固有色随主题明暗冷暖适配(@14)**
18
+
19
+ - 问题修复:acid / glitch / vaporwave / 水墨 / 宫廷 / 青绿山水六款特许模板此前硬编码风格本体色,切换主题时只有页面壳(换肤坞 / 容器)在变、海报主体纹丝不动——用户反馈「主题切换只是浏览器的壳在变化」
20
+ - 氛围响应方案:特许本色一律改为 CSS color-mix() 与主题变量按比例混合——背景色混 var(--bg) 22%、强调装饰色混 var(--accent) 20%、墨字混 var(--text) 20%、灰字混 var(--muted) 25%,本色主导(气质不丢)又随主题明暗冷暖微调(切换有感),零映射表天然覆盖全部 25 主题
21
+ - 渐变兼容:34 个交互换肤 HTML 的瞬态过渡列表统一加 background 属性——纯色背景(宣纸底 / 山峦等)切主题平滑渐变,渐变背景按浏览器标准离散切换;既有 color / border / 阴影渐变不受影响
22
+ - 版本戳 one-pager@13 → @14
23
+
7
24
  ## 1.3.11(2026-11-13)
8
25
 
9
26
  **换肤渐变全覆盖:22 份安装引导页补齐过渡,12 模板缓动升级 Material 标准曲线**
@@ -253,7 +253,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
253
253
  .header-card h1{ font-size:26px; }
254
254
  }
255
255
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
256
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
256
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
257
257
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
258
258
 
259
259
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -310,7 +310,7 @@ td.hl{font-weight:700;color:var(--ink)}
310
310
 
311
311
  .foot{text-align:center;padding:34px 0 44px;color:var(--ink-4);font-size:12.5px}
312
312
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
313
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
313
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
314
314
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
315
315
 
316
316
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -75,7 +75,7 @@ body{background:var(--bg);color:var(--text);font-family:system-ui,'Segoe UI',Rob
75
75
  footer{text-align:center;color:var(--muted);font-size:10px;margin-top:26px}
76
76
  html[data-shot] .card{animation:none!important}
77
77
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
78
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
78
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
79
79
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
80
80
 
81
81
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -407,7 +407,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
407
407
  .header-card h1{ font-size:26px; }
408
408
  }
409
409
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
410
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
410
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
411
411
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
412
412
 
413
413
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -785,7 +785,7 @@ body:hover .nav{ opacity:1; }
785
785
  }
786
786
 
787
787
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
788
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
788
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
789
789
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
790
790
 
791
791
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -210,7 +210,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
210
210
  .act-table th:nth-child(2), .act-table td:nth-child(2){ display:none; }
211
211
  }
212
212
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
213
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
213
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
214
214
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
215
215
 
216
216
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: meta-forge
3
- description: 锻造新技能的元技能(造 skill 的 skill)。按 SkillForge 工坊规范从需求出发生成完整技能包(薄入口 SKILL.md + 按阶段拆分的 resources/ + 用户配置 user-config.md),自动植入机制体系:CONFIG_VERSION 配置版本钥匙、user-config 配置抽离、reference 双轨(含 HTML 输出时)、多文件隔离(页面有 localStorage 记忆时)、零侵权脱敏离线纪律(含 HTML 输出时)、产物升级回炉(含 HTML 输出时)、preserve 保护清单(含半定制资产时)、文档同步自检纪律;技能入 SkillForge 仓库时同步登记 README 分类表、cli.js CATEGORIES 与 package.json files。当用户请求创建新技能、造一个 skill、做一个 XX 技能、把 XX 流程固化成技能,或询问 meta-forge 用法(怎么造技能/元锻炉怎么用)时使用。
3
+ description: 锻造新技能的元技能(造 skill 的 skill)。按 SkillForge 工坊规范从需求出发生成完整技能包(薄入口 SKILL.md + 按阶段拆分的 resources/ + 用户配置 user-config.md),自动植入机制体系:CONFIG_VERSION 配置版本钥匙、user-config 配置抽离、reference 双轨(含 HTML 输出时)、多文件隔离(页面有 localStorage 记忆时)、零侵权脱敏离线纪律(含 HTML 输出时)、产物升级回炉(含 HTML 输出时,工具型产物加全时机版本自检)、preserve 保护清单(含半定制资产时)、文档同步自检纪律;技能入 SkillForge 仓库时同步登记 README 分类表、cli.js CATEGORIES 与 package.json files。当用户请求创建新技能、造一个 skill、做一个 XX 技能、把 XX 流程固化成技能,或询问 meta-forge 用法(怎么造技能/元锻炉怎么用)时使用。
4
4
  allowed-tools: Bash, Read, Write
5
5
  disable-model-invocation: false
6
6
  ---
@@ -14,7 +14,7 @@ disable-model-invocation: false
14
14
  0. **读用户配置**(DIR/REGISTER/CONFIG_VERSION)→ 先 Read 同目录 `user-config.md`
15
15
  1. **需求澄清**(技能名、触发场景、产出形态、可配置项、是否含 HTML 输出、是否入仓库)→ 读 `resources/forge-rules.md` 的「一、澄清清单」
16
16
  2. **结构生成**(薄入口 + resources 拆分 + 咨询应答接线)→ 读 `resources/forge-rules.md` 的「二、结构规范」
17
- 3. **机制植入**(CONFIG_VERSION 钥匙 / user-config 抽离 / reference 双轨 / 多文件隔离 / 零侵权脱敏离线 / 产物升级回炉 / preserve 保护清单 / 自检纪律,缺一不可;含 HTML 输出加机制三、七、八,页面有 localStorage 记忆加机制六,含半定制资产加机制五)→ 读 `resources/forge-rules.md` 的「三、机制体系」
17
+ 3. **机制植入**(CONFIG_VERSION 钥匙 / user-config 抽离 / reference 双轨 / 多文件隔离 / 零侵权脱敏离线 / 产物升级回炉 / preserve 保护清单 / 自检纪律,缺一不可;含 HTML 输出加机制三、七、八,页面有 localStorage 记忆加机制六,含半定制资产加机制五,工具型产物加机制八「工具型产物版本自检」)→ 读 `resources/forge-rules.md` 的「三、机制体系」
18
18
  4. **验证环**(静态门禁 grep 逐项 + 含 HTML 时 Playwright 运行时实测:零 JS 错误 / 键带路径 / 刷新恢复 / 多文件隔离 / 自愈实测 + 交付报告附验证证据,任一未过修复重跑禁止跳过)→ 读 `resources/forge-rules.md` 的「四、验证环」
19
19
  5. **仓库登记**(技能入 SkillForge 仓库时:README 技能分类表/技能清单/目录结构 + cli.js CATEGORIES + package.json files 同步登记,登记后跑 `skill-forge ls` 与 `npm pack --dry-run` 验证)→ 读 `resources/forge-rules.md` 的「五、仓库登记」
20
20
  6. **使用咨询**(用户只问「怎么造技能」等用法、未要求创建)→ 读 `resources/usage-guide.md`,将其内容原样输出(首行标题改为「元锻炉使用指南」),不创建任何文件
@@ -42,7 +42,7 @@ disable-model-invocation: false
42
42
 
43
43
  ## 规则速览
44
44
 
45
- - 机制体系缺一不可:CONFIG_VERSION 钥匙(配置版本机制节 + user-config 配置块首行 CONFIG_VERSION: 1)、user-config 抽离(用户可改配置全部出站,SKILL.md 只引用不内嵌)、reference 双轨(含 HTML 输出的技能以 reference.html 为样式真相源)、多文件隔离(页面有 localStorage 记忆时键带路径命名空间)、零侵权脱敏离线(品牌字体零出现、禁 CDN 离线可开、示例数据零真实身份)、产物升级回炉(HTML 带模板版本戳、业务/数据格式/页面改动均 bump、旧产物可交互回炉、生成时顺扫旧版主动提示)、preserve 保护清单(半定制资产 .preserve 声明、CLI 升级永不覆盖、官方更新另存 .upstream 对照)、自检纪律(改一处 grep 全仓)
45
+ - 机制体系缺一不可:CONFIG_VERSION 钥匙(配置版本机制节 + user-config 配置块首行 CONFIG_VERSION: 1)、user-config 抽离(用户可改配置全部出站,SKILL.md 只引用不内嵌)、reference 双轨(含 HTML 输出的技能以 reference.html 为样式真相源)、多文件隔离(页面有 localStorage 记忆时键带路径命名空间)、零侵权脱敏离线(品牌字体零出现、禁 CDN 离线可开、示例数据零真实身份)、产物升级回炉(HTML 带模板版本戳、业务/数据格式/页面改动均 bump、旧产物可交互回炉、生成时顺扫旧版主动提示、工具型产物全时机版本自检+场景分级提示)、preserve 保护清单(半定制资产 .preserve 声明、CLI 升级永不覆盖、官方更新另存 .upstream 对照)、自检纪律(改一处 grep 全仓)
46
46
  - 薄入口:SKILL.md 只留 frontmatter / 生成流程 / 配置节 / 机制节 / 规则速览;重内容按阶段拆 resources/,一文件一职责
47
47
  - 新技能必须带 user-config.md(含 CONFIG_VERSION: 1)、resources/usage-guide.md(咨询应答原样输出源)与 resources/skillforge-guide.txt + skillforge-guide.html(SkillForge 使用指引双版,SKILL.md 末尾带整体咨询触发节)
48
48
  - 完整规则(澄清清单 / 结构规范 / 机制体系 / 验证环 / 仓库登记)见 `resources/forge-rules.md`
@@ -12,7 +12,8 @@
12
12
  4. **可配置项**:哪些行为用户会想改?→ 全部进 user-config.md
13
13
  5. **是否含 HTML 输出**:是 → 必须建 reference.html 双轨机制(机制三);否 → 无此要求
14
14
  6. **页面是否有 localStorage 记忆**(含 HTML 时必问:主题/偏好/用户数据等):是 → 机制六(多文件隔离)必植入
15
- 7. **归属**:入 SkillForge 仓库(需登记)还是独立技能(不登记)?
15
+ 7. **产物类型**(含 HTML 时必问):工具型——固定页面反复打开、数据累积(如提示词管理台),升级提示是体验关键;快照型/生成型——生成即归档(如日报/文章页),旧产物不再改。工具型 → 机制八「工具型产物版本自检」必植入
16
+ 8. **归属**:入 SkillForge 仓库(需登记)还是独立技能(不登记)?
16
17
 
17
18
  ## 二、结构规范(薄入口 + resources 拆分)
18
19
 
@@ -94,7 +95,8 @@
94
95
  - 用户数据类细则(IndexedDB 数据按稳定 ID 命名空间存取的技能):深升级重建必须沿用原页稳定 ID meta 值(换 ID = 数据失联,重建后原收藏/分组照旧读回);<DATA_DIR> 数据文件一概不动
95
96
  - 回炉交互:用户说「升级旧产物/回炉」→ 扫落盘目录读版本戳筛旧版(无版本戳或缺少稳定 ID meta 的产物视为 v0 最旧版,一并进清单) → 列清单(文件/旧版本/手改状态:旧 html 正文与 md 正文对比,不一致视为可能手改)→ AskUserQuestion 选全部或部分 → 逐份升级 → 报告三段式(✅ 已升级 / ⚠️ 手改保留 / 🟡 失败项原因)
96
97
  - 版本递增判定:模板业务改动(板块/段落/标题体系)、数据格式改动(字段/存储结构)、页面改动(样式/布局/交互)任一发生即模板升级,版本戳 +1 并同步 reference.html 与 SKILL.md「产物升级(回炉)」节;纯措辞润色不 bump
97
- - 主动提示:每次生成 HTML 或用户使用该技能 HTML 产出时,顺扫落盘目录读版本戳;发现低于当前模板版本的旧产物,主动告知「技能模板已升级至 vN,检测到 X 份旧版产物(vN-1),说『把我旧XX都升级成新样式』即可一键升级」,不让用户背触发语
98
+ - 主动提示(快照型/生成型产物——生成即归档,如日报/文章页):每次生成 HTML 时顺扫落盘目录读版本戳;发现低于当前模板版本的旧产物,主动告知「技能模板已升级至 vN,检测到 X 份旧版产物(vN-1),说『把我旧XX都升级成新样式』即可一键升级」,不让用户背触发语
99
+ - 工具型产物版本自检(固定页面反复打开、数据累积的技能——如提示词管理台,澄清清单确认工具型时必植入):每次调用本 skill(生成/初始化/维护/取用/打开)先静默自检——读目标页面版本戳与 reference.html 当前版比对(两行 meta、零网络、不碰数据),结果只影响「提示」不影响「执行」,版本旧也绝不拒绝或推迟本次任务。提示分场景:打开场景主动问(起服务前 AskUserQuestion:A 升级后打开(推荐)——走回炉流程、沿用原页稳定 ID meta 值、数据文件一概不动;B 直接打开旧版——本次会话不再询问;询问时附更新点清单:检索 CHANGELOG 相关条目 + 版本差区间归纳 2-5 条用户可感知变化,一句话一条);维护/取用场景照常执行、收尾报告一句轻提示(「页面还是旧版(@N,当前 @M),说『升级XX』即可换新」,不弹问不打断);用户拒绝过升级则本次会话静默。SKILL.md 执行流程第 0 步后固定写「版本自检(静默前置,全时机)」步骤
98
100
 
99
101
  ## 四、验证环(交付前全过,偏差必被发现)
100
102
 
@@ -112,8 +114,9 @@
112
114
  10. 示例数据脱敏:全文 grep 无真实项目名/人名/公司名/平台名/本机路径(/Users/具体用户名、~/SmartDeveloper 等);页脚署名 GENERATED BY AI TEAM
113
115
  11. 产物版本戳(含 HTML 的技能):reference.html 头部含 `<meta name="sf-template" content="<技能名>@N">`(N≥1);SKILL.md 含「产物升级(回炉)」节且判定含无版本戳/无稳定 ID meta 视为 v0 最旧版
114
116
  12. 版本递增与主动提示(含 HTML 的技能):SKILL.md 回炉节含版本递增判定(业务/数据格式/页面改动均 bump)与主动提示语(顺扫旧产物 + 告知触发语)
115
- 13. 入场动画兜底(含 HTML 且含滚动入场动画的技能):reference.html 含 2s 兜底强制全显代码(`.rv:not(.in)` 模式或等价),确保 headless 截图 / 打印预览内容全显
116
- 14. 执行层自愈块(含 HTML 且页面有 localStorage 记忆的技能):HTML 内嵌 JS 含 id meta 校验——非法或缺失(占位残留 / 手写变体 / 误沿用旧值)时按路径键(`sf-heal:` + location.pathname)自愈为 crypto.randomUUID() 标准 v4 并回写 meta,console.warn 显性报警
117
+ 13. 工具型产物版本自检(工具型技能):SKILL.md 执行流程含「版本自检(静默前置,全时机)」步骤(静默比对版本戳、零网络不碰数据、结果只影响提示不影响执行)+ 场景分级提示(打开主动问/维护取用一句话/拒绝会话静默)
118
+ 14. 入场动画兜底(含 HTML 且含滚动入场动画的技能):reference.html 含 2s 兜底强制全显代码(`.rv:not(.in)` 模式或等价),确保 headless 截图 / 打印预览内容全显
119
+ 15. 执行层自愈块(含 HTML 且页面有 localStorage 记忆的技能):HTML 内嵌 JS 含 id meta 校验——非法或缺失(占位残留 / 手写变体 / 误沿用旧值)时按路径键(`sf-heal:` + location.pathname)自愈为 crypto.randomUUID() 标准 v4 并回写 meta,console.warn 显性报警
117
120
 
118
121
  ### B. 运行时实测(含 HTML 的技能必做,Playwright headless channel="chrome")
119
122
 
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -251,7 +251,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
251
251
  .header-card h1{ font-size:26px; }
252
252
  }
253
253
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
254
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
254
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
255
255
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
256
256
 
257
257
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -62,7 +62,7 @@ disable-model-invocation: false
62
62
 
63
63
  ## 产物升级(回炉)
64
64
 
65
- 生成 HTML 时头部写版本戳 `<meta name="sf-template" content="one-pager@13">`(模板升级时递增 @N 并同步 reference.html 与本文档)。用户说「升级旧海报/回炉」时:顺扫海报库根目录(DIR 值)下两种形态——新子目录形态 `<slug>/poster.html` 与旧平铺形态 `poster-*.html`,读版本戳筛旧版(无版本戳或缺少 `<meta name="poster-id">` 稳定 ID 的产物视为 v0 最旧版,一并进清单)→ 列清单(文件/旧版本)→ AskUserQuestion 选全部或部分 → 逐份升级:浅升级(仅 CSS/JS 变化)对旧页替换 `<style>` 块与交互脚本、正文原样保留;深升级(DOM 结构变化)从同目录 md 底稿按当前 reference.html 重建,先备份旧版 `.bak-时间戳`,重建必须沿用原页 poster-id meta 值(换 ID = 模板/主题记忆失联)→ 报告三段式:✅ 已升级清单 / ⚠️ 手改保留说明 / 🟡 失败项原因。模板改动分级:业务改动、数据格式改动、页面改动任一发生即模板升级,版本戳 +1 并同步 reference.html 与本文档;纯措辞润色不 bump。每次生成 HTML 时顺扫落盘目录读版本戳:发现旧版产物主动告知用户「说『把我旧海报都升级成新样式』即可一键升级」。
65
+ 生成 HTML 时头部写版本戳 `<meta name="sf-template" content="one-pager@15">`(模板升级时递增 @N 并同步 reference.html 与本文档)。用户说「升级旧海报/回炉」时:顺扫海报库根目录(DIR 值)下两种形态——新子目录形态 `<slug>/poster.html` 与旧平铺形态 `poster-*.html`,读版本戳筛旧版(无版本戳或缺少 `<meta name="poster-id">` 稳定 ID 的产物视为 v0 最旧版,一并进清单)→ 列清单(文件/旧版本)→ AskUserQuestion 选全部或部分 → 逐份升级:浅升级(仅 CSS/JS 变化)对旧页替换 `<style>` 块与交互脚本、正文原样保留;深升级(DOM 结构变化)从同目录 md 底稿按当前 reference.html 重建,先备份旧版 `.bak-时间戳`,重建必须沿用原页 poster-id meta 值(换 ID = 模板/主题记忆失联)→ 报告三段式:✅ 已升级清单 / ⚠️ 手改保留说明 / 🟡 失败项原因。模板改动分级:业务改动、数据格式改动、页面改动任一发生即模板升级,版本戳 +1 并同步 reference.html 与本文档;纯措辞润色不 bump。每次生成 HTML 时顺扫落盘目录读版本戳:发现旧版产物主动告知用户「说『把我旧海报都升级成新样式』即可一键升级」。
66
66
 
67
67
  ## 规则速览
68
68
 
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <meta name="sf-template" content="one-pager@13">
6
+ <meta name="sf-template" content="one-pager@15">
7
7
  <meta name="poster-id" content="REF-POSTER-0000">
8
8
  <title>AI 改变工作 · 一页纸海报</title>
9
9
  <style>
@@ -463,10 +463,10 @@ body{background:linear-gradient(180deg,var(--bg) 12%,var(--bg2) 135%);color:var(
463
463
  .tpl-artnouveau ul.points .num{font-family:Georgia,serif;font-size:15px;font-style:italic;color:var(--accent);margin-right:8px}
464
464
  .tpl-artnouveau footer{font-size:10px;letter-spacing:3px;color:var(--muted);display:flex;gap:24px}
465
465
 
466
- /* 21. acid 酸性设计:液态金属 blob + 荧光斜切徽章(风格本体色特许:金属灰) */
466
+ /* 21. acid 酸性设计:液态金属 blob + 荧光斜切徽章(风格本体色特许:金属灰,经 color-mix 混入主题强调色) */
467
467
  .tpl-acid{display:flex;flex-direction:column;justify-content:center;width:min(82%,1100px);height:100%;padding:6vh 0;position:relative}
468
468
  .tpl-acid .liquid{position:absolute;inset:0;pointer-events:none;background:linear-gradient(115deg,transparent 42%,var(--border) 46%,transparent 52%),repeating-linear-gradient(90deg,var(--border) 0 1px,transparent 1px 90px);opacity:.8}
469
- .tpl-acid .blob{position:absolute;top:8%;right:6%;width:min(24vw,190px);height:min(24vw,190px);border-radius:58% 42% 55% 45% / 48% 55% 45% 52%;background:conic-gradient(from 210deg,rgba(180,180,170,.9),rgba(70,70,80,.9),rgba(220,220,210,.9),rgba(90,90,100,.9),rgba(180,180,170,.9));box-shadow:inset 0 0 24px rgba(0,0,0,.35);opacity:.85}
469
+ .tpl-acid .blob{position:absolute;top:8%;right:6%;width:min(24vw,190px);height:min(24vw,190px);border-radius:58% 42% 55% 45% / 48% 55% 45% 52%;background:conic-gradient(from 210deg,color-mix(in srgb,rgba(180,180,170,.9) 80%,var(--accent) 20%),color-mix(in srgb,rgba(70,70,80,.9) 80%,var(--accent) 20%),color-mix(in srgb,rgba(220,220,210,.9) 80%,var(--accent) 20%),color-mix(in srgb,rgba(90,90,100,.9) 80%,var(--accent) 20%),color-mix(in srgb,rgba(180,180,170,.9) 80%,var(--accent) 20%));box-shadow:inset 0 0 24px rgba(0,0,0,.35);opacity:.85}
470
470
  .tpl-acid .badge{font-size:12px;font-weight:900;letter-spacing:3px;color:var(--bg);background:var(--accent);padding:7px 16px;border-radius:2px;transform:skewX(-12deg);margin-bottom:3vh;align-self:flex-start}
471
471
  .tpl-acid h1{font-size:clamp(44px,5.8vw,76px);font-weight:900;line-height:1.02;letter-spacing:-1px;color:var(--text);margin-bottom:2.5vh}
472
472
  .tpl-acid .quote{font-size:15px;color:var(--muted);margin-bottom:4vh;max-width:70%;border-left:4px solid var(--accent);padding-left:16px}
@@ -476,24 +476,24 @@ body{background:linear-gradient(180deg,var(--bg) 12%,var(--bg2) 135%);color:var(
476
476
  .tpl-acid ul.points .num{color:var(--accent);font-family:ui-monospace,'SF Mono',Menlo,monospace}
477
477
  .tpl-acid footer{display:flex;justify-content:space-between;font-size:10px;letter-spacing:2px;color:var(--muted);border-top:1px dashed var(--border);padding-top:12px}
478
478
 
479
- /* 22. glitch 故障艺术:RGB 错位标题 + 阶梯裁切卡(风格本体色特许:品红/青错位影) */
479
+ /* 22. glitch 故障艺术:RGB 错位标题 + 阶梯裁切卡(风格本体色特许:品红/青错位影,经 color-mix 混入主题强调色) */
480
480
  .tpl-glitch{display:flex;flex-direction:column;justify-content:center;width:min(84%,1150px);height:100%;padding:6vh 0;position:relative}
481
- .tpl-glitch .bars{position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent 0 18px,rgba(255,0,200,.06) 18px 21px,rgba(0,255,255,.06) 21px 24px)}
481
+ .tpl-glitch .bars{position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent 0 18px,color-mix(in srgb,var(--accent) 6%,transparent) 18px 21px,color-mix(in srgb,var(--accent2) 6%,transparent) 21px 24px)}
482
482
  .tpl-glitch .badge{font-family:ui-monospace,'SF Mono',Menlo,monospace;font-size:12px;letter-spacing:3px;color:var(--accent);border:1.5px solid var(--accent);padding:5px 12px;margin-bottom:3vh;align-self:flex-start}
483
483
  .tpl-glitch h1{position:relative;font-size:clamp(44px,6vw,80px);font-weight:900;line-height:1.05;color:var(--text);margin-bottom:3vh}
484
484
  .tpl-glitch h1::before,.tpl-glitch h1::after{content:attr(data-t);position:absolute;inset:0;opacity:.7}
485
- .tpl-glitch h1::before{color:#f0f;transform:translate(-3px,2px);clip-path:inset(12% 0 58% 0)}
486
- .tpl-glitch h1::after{color:#0ff;transform:translate(3px,-2px);clip-path:inset(58% 0 12% 0)}
485
+ .tpl-glitch h1::before{color:color-mix(in srgb,#f0f 78%,var(--accent) 22%);transform:translate(-3px,2px);clip-path:inset(12% 0 58% 0)}
486
+ .tpl-glitch h1::after{color:color-mix(in srgb,#0ff 78%,var(--accent2) 22%);transform:translate(3px,-2px);clip-path:inset(58% 0 12% 0)}
487
487
  .tpl-glitch .quote{font-size:15px;color:var(--muted);margin-bottom:4vh;max-width:70%;font-family:ui-monospace,'SF Mono',Menlo,monospace}
488
488
  .tpl-glitch ul.points{list-style:none;display:grid;grid-template-columns:repeat(2,1fr);gap:14px;margin-bottom:4vh}
489
489
  .tpl-glitch ul.points li{font-size:14px;color:var(--text);background:var(--panel-solid);border:1px solid var(--border);padding:12px 14px;display:flex;gap:10px;align-items:baseline;clip-path:polygon(0 0,100% 0,100% calc(100% - 8px),calc(100% - 8px) 100%,0 100%)}
490
490
  .tpl-glitch ul.points .num{font-family:ui-monospace,'SF Mono',Menlo,monospace;color:var(--accent);font-weight:800}
491
491
  .tpl-glitch footer{display:flex;justify-content:space-between;font-size:10px;letter-spacing:2px;color:var(--muted);font-family:ui-monospace,'SF Mono',Menlo,monospace}
492
492
 
493
- /* 23. vaporwave 蒸汽波:落日渐变 + 透视网格地平线(风格本体色特许:粉紫地平线) */
493
+ /* 23. vaporwave 蒸汽波:落日渐变 + 透视网格地平线(风格本体色特许:粉紫地平线,经 color-mix 混入主题强调色) */
494
494
  .tpl-vaporwave{display:flex;flex-direction:column;justify-content:flex-end;width:min(86%,1150px);height:100%;padding:7vh 0 6vh;position:relative}
495
495
  .tpl-vaporwave .sun{position:absolute;top:12%;left:50%;transform:translateX(-50%);width:min(34vw,260px);height:min(34vw,260px);border-radius:50%;background:linear-gradient(180deg,var(--accent2),transparent 62%);opacity:.55;pointer-events:none}
496
- .tpl-vaporwave .grid{position:absolute;bottom:0;left:0;right:0;height:42%;pointer-events:none;background:linear-gradient(180deg,transparent,rgba(180,80,255,.28)),repeating-linear-gradient(90deg,rgba(255,255,255,.14) 0 1px,transparent 1px 64px),repeating-linear-gradient(0deg,rgba(255,255,255,.14) 0 1px,transparent 1px 34px);transform:perspective(340px) rotateX(58deg);transform-origin:bottom}
496
+ .tpl-vaporwave .grid{position:absolute;bottom:0;left:0;right:0;height:42%;pointer-events:none;background:linear-gradient(180deg,transparent,color-mix(in srgb,rgba(180,80,255,.28) 76%,var(--accent) 24%)),repeating-linear-gradient(90deg,rgba(255,255,255,.14) 0 1px,transparent 1px 64px),repeating-linear-gradient(0deg,rgba(255,255,255,.14) 0 1px,transparent 1px 34px);transform:perspective(340px) rotateX(58deg);transform-origin:bottom}
497
497
  .tpl-vaporwave .badge{font-size:12px;letter-spacing:5px;color:var(--bg);background:linear-gradient(90deg,var(--accent),var(--accent2));padding:7px 18px;border-radius:999px;margin-bottom:3vh;align-self:flex-start}
498
498
  .tpl-vaporwave h1{font-size:clamp(40px,5.4vw,70px);font-weight:900;line-height:1.1;letter-spacing:1px;color:var(--text);margin-bottom:2.5vh}
499
499
  .tpl-vaporwave .quote{font-size:15px;color:var(--muted);margin-bottom:4vh;max-width:64%}
@@ -571,52 +571,52 @@ body{background:linear-gradient(180deg,var(--bg) 12%,var(--bg2) 135%);color:var(
571
571
  .tpl-notice ul.points .num{color:var(--accent);font-weight:800}
572
572
  .tpl-notice footer{display:flex;flex-direction:column;align-items:flex-end;font-size:12px;color:var(--muted);gap:6px;margin-top:auto}
573
573
 
574
- /* 29. inkwash 水墨:宣纸底 + 墨色远山 + 朱印落款(风格本体色特许:宣纸米/墨黑/朱砂红) */
575
- .tpl-inkwash{display:flex;align-items:center;justify-content:center;width:100%;height:100%;position:relative;overflow:hidden;background:#f5f0e3}
576
- .tpl-inkwash .mt{position:absolute;border-radius:50%;pointer-events:none;background:#26221e}
574
+ /* 29. inkwash 水墨:宣纸底 + 墨色远山 + 朱印落款(风格本体色特许:宣纸米/墨黑/朱砂红,经 color-mix 与主题变量氛围混合) */
575
+ .tpl-inkwash{display:flex;align-items:center;justify-content:center;width:100%;height:100%;position:relative;overflow:hidden;background:color-mix(in srgb,#f5f0e3 78%,var(--bg) 22%)}
576
+ .tpl-inkwash .mt{position:absolute;border-radius:50%;pointer-events:none;background:color-mix(in srgb,#26221e 78%,var(--bg) 22%)}
577
577
  .tpl-inkwash .m1{width:76%;height:26%;left:-6%;bottom:-7%;opacity:.07}
578
578
  .tpl-inkwash .m2{width:92%;height:30%;left:14%;bottom:-13%;opacity:.13}
579
579
  .tpl-inkwash .m3{width:104%;height:34%;left:24%;bottom:-17%;opacity:.2}
580
- .tpl-inkwash .sun{position:absolute;right:15%;top:11%;width:min(15vw,110px);height:min(15vw,110px);border-radius:50%;background:#b03a2e;opacity:.92;pointer-events:none}
580
+ .tpl-inkwash .sun{position:absolute;right:15%;top:11%;width:min(15vw,110px);height:min(15vw,110px);border-radius:50%;background:color-mix(in srgb,#b03a2e 80%,var(--accent) 20%);opacity:.92;pointer-events:none}
581
581
  .tpl-inkwash .content{position:relative;display:flex;flex-direction:column;justify-content:center;width:min(82%,1060px);height:100%;padding:7vh 0}
582
- .tpl-inkwash .seal{align-self:flex-start;font-family:Georgia,'Songti SC','SimSun',serif;font-size:13px;font-weight:700;letter-spacing:2px;color:#f5f0e3;background:#b03a2e;padding:8px 12px;border-radius:4px;margin-bottom:3vh}
583
- .tpl-inkwash h1{font-family:Georgia,'Songti SC','SimSun',serif;font-size:clamp(38px,5.2vw,66px);font-weight:700;color:#26221e;line-height:1.4;margin-bottom:2.5vh}
584
- .tpl-inkwash .quote{font-size:16px;font-style:italic;color:#6b645a;margin-bottom:4vh;max-width:72%;border-left:3px solid #b03a2e;padding-left:18px;line-height:1.9}
582
+ .tpl-inkwash .seal{align-self:flex-start;font-family:Georgia,'Songti SC','SimSun',serif;font-size:13px;font-weight:700;letter-spacing:2px;color:color-mix(in srgb,#f5f0e3 78%,var(--bg) 22%);background:color-mix(in srgb,#b03a2e 80%,var(--accent) 20%);padding:8px 12px;border-radius:4px;margin-bottom:3vh}
583
+ .tpl-inkwash h1{font-family:Georgia,'Songti SC','SimSun',serif;font-size:clamp(38px,5.2vw,66px);font-weight:700;color:color-mix(in srgb,#26221e 80%,var(--text) 20%);line-height:1.4;margin-bottom:2.5vh}
584
+ .tpl-inkwash .quote{font-size:16px;font-style:italic;color:color-mix(in srgb,#6b645a 75%,var(--muted) 25%);margin-bottom:4vh;max-width:72%;border-left:3px solid color-mix(in srgb,#b03a2e 80%,var(--accent) 20%);padding-left:18px;line-height:1.9}
585
585
  .tpl-inkwash ul.points{list-style:none;display:flex;flex-direction:column;gap:14px;margin-bottom:4vh}
586
- .tpl-inkwash ul.points li{font-size:15px;color:#26221e;display:flex;gap:12px;align-items:baseline;line-height:1.8}
587
- .tpl-inkwash ul.points .num{font-family:Georgia,'Songti SC','SimSun',serif;color:#b03a2e;font-weight:700;flex:none}
588
- .tpl-inkwash footer{display:flex;justify-content:space-between;font-size:10px;letter-spacing:3px;color:#6b645a;border-top:1px solid rgba(38,34,30,.18);padding-top:14px}
586
+ .tpl-inkwash ul.points li{font-size:15px;color:color-mix(in srgb,#26221e 80%,var(--text) 20%);display:flex;gap:12px;align-items:baseline;line-height:1.8}
587
+ .tpl-inkwash ul.points .num{font-family:Georgia,'Songti SC','SimSun',serif;color:color-mix(in srgb,#b03a2e 80%,var(--accent) 20%);font-weight:700;flex:none}
588
+ .tpl-inkwash footer{display:flex;justify-content:space-between;font-size:10px;letter-spacing:3px;color:color-mix(in srgb,#6b645a 75%,var(--muted) 25%);border-top:1px solid color-mix(in srgb,rgba(38,34,30,.18) 75%,var(--border) 25%);padding-top:14px}
589
589
 
590
- /* 30. palace 红金宫廷:朱红底 + 回纹金边双线框 + 衬线金字(风格本体色特许:朱红/鎏金/米白) */
591
- .tpl-palace{display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:linear-gradient(160deg,#7a1f1f,#5e1717);padding:6vh 0}
592
- .tpl-palace .frame{position:relative;width:min(80%,1060px);height:100%;display:flex;flex-direction:column;justify-content:center;border:2px solid #d4af37;outline:1px solid #d4af37;outline-offset:5px;padding:7vh 5vw;text-align:center;background:repeating-linear-gradient(90deg,rgba(212,175,55,.08) 0 2px,transparent 2px 34px)}
590
+ /* 30. palace 红金宫廷:朱红底 + 回纹金边双线框 + 衬线金字(风格本体色特许:朱红/鎏金/米白,经 color-mix 与主题变量氛围混合) */
591
+ .tpl-palace{display:flex;align-items:center;justify-content:center;width:100%;height:100%;background:linear-gradient(160deg,color-mix(in srgb,#7a1f1f 78%,var(--bg) 22%),color-mix(in srgb,#5e1717 78%,var(--bg) 22%));padding:6vh 0}
592
+ .tpl-palace .frame{position:relative;width:min(80%,1060px);height:100%;display:flex;flex-direction:column;justify-content:center;border:2px solid color-mix(in srgb,#d4af37 80%,var(--accent) 20%);outline:1px solid color-mix(in srgb,#d4af37 80%,var(--accent) 20%);outline-offset:5px;padding:7vh 5vw;text-align:center;background:repeating-linear-gradient(90deg,rgba(212,175,55,.08) 0 2px,transparent 2px 34px)}
593
593
  .tpl-palace .frame::after{content:'';position:absolute;inset:9px;border:1px solid rgba(212,175,55,.5);pointer-events:none}
594
- .tpl-palace .badge{font-size:12px;letter-spacing:8px;color:#d4af37;margin-bottom:2.5vh}
595
- .tpl-palace h1{font-family:Georgia,'Songti SC','SimSun',serif;font-size:clamp(36px,4.8vw,62px);font-weight:700;color:#f5ead1;margin-bottom:2vh;line-height:1.4}
596
- .tpl-palace .divider{display:flex;align-items:center;gap:14px;justify-content:center;color:#d4af37;font-size:13px;margin-bottom:2.5vh}
597
- .tpl-palace .divider::before,.tpl-palace .divider::after{content:'';height:1px;width:110px;background:linear-gradient(90deg,transparent,#d4af37)}
598
- .tpl-palace .divider::after{background:linear-gradient(90deg,#d4af37,transparent)}
599
- .tpl-palace .quote{font-size:15px;font-style:italic;color:#e8cba0;margin-bottom:3.5vh;max-width:70%;margin-left:auto;margin-right:auto}
594
+ .tpl-palace .badge{font-size:12px;letter-spacing:8px;color:color-mix(in srgb,#d4af37 80%,var(--accent) 20%);margin-bottom:2.5vh}
595
+ .tpl-palace h1{font-family:Georgia,'Songti SC','SimSun',serif;font-size:clamp(36px,4.8vw,62px);font-weight:700;color:color-mix(in srgb,#f5ead1 80%,var(--text) 20%);margin-bottom:2vh;line-height:1.4}
596
+ .tpl-palace .divider{display:flex;align-items:center;gap:14px;justify-content:center;color:color-mix(in srgb,#d4af37 80%,var(--accent) 20%);font-size:13px;margin-bottom:2.5vh}
597
+ .tpl-palace .divider::before,.tpl-palace .divider::after{content:'';height:1px;width:110px;background:linear-gradient(90deg,transparent,color-mix(in srgb,#d4af37 80%,var(--accent) 20%))}
598
+ .tpl-palace .divider::after{background:linear-gradient(90deg,color-mix(in srgb,#d4af37 80%,var(--accent) 20%),transparent)}
599
+ .tpl-palace .quote{font-size:15px;font-style:italic;color:color-mix(in srgb,#e8cba0 80%,var(--text) 20%);margin-bottom:3.5vh;max-width:70%;margin-left:auto;margin-right:auto}
600
600
  .tpl-palace ul.points{list-style:none;display:flex;justify-content:center;gap:3.5vw;flex-wrap:wrap;margin-bottom:3.5vh}
601
- .tpl-palace ul.points li{font-size:14px;color:#f5ead1;display:flex;gap:8px;align-items:center;line-height:1.8}
602
- .tpl-palace ul.points .num{width:22px;height:22px;border:1px solid #d4af37;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;color:#d4af37;flex:none}
603
- .tpl-palace footer{display:flex;justify-content:center;gap:26px;font-size:10px;letter-spacing:3px;color:#d8b878}
601
+ .tpl-palace ul.points li{font-size:14px;color:color-mix(in srgb,#f5ead1 80%,var(--text) 20%);display:flex;gap:8px;align-items:center;line-height:1.8}
602
+ .tpl-palace ul.points .num{width:22px;height:22px;border:1px solid color-mix(in srgb,#d4af37 80%,var(--accent) 20%);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;color:color-mix(in srgb,#d4af37 80%,var(--accent) 20%);flex:none}
603
+ .tpl-palace footer{display:flex;justify-content:center;gap:26px;font-size:10px;letter-spacing:3px;color:color-mix(in srgb,#d8b878 75%,var(--muted) 25%)}
604
604
 
605
- /* 31. landscape 青绿山水:clip-path 层叠山峦 + 留白天际 + 题跋落款(风格本体色特许:青绿/赭石/留白) */
606
- .tpl-landscape{display:flex;align-items:center;justify-content:center;width:100%;height:100%;position:relative;overflow:hidden;background:#f4f1e8}
605
+ /* 31. landscape 青绿山水:clip-path 层叠山峦 + 留白天际 + 题跋落款(风格本体色特许:青绿/赭石/留白,经 color-mix 与主题变量氛围混合) */
606
+ .tpl-landscape{display:flex;align-items:center;justify-content:center;width:100%;height:100%;position:relative;overflow:hidden;background:color-mix(in srgb,#f4f1e8 78%,var(--bg) 22%)}
607
607
  .tpl-landscape .peak{position:absolute;left:-6%;right:-6%;pointer-events:none}
608
- .tpl-landscape .p1{bottom:36%;height:32%;background:#a8c6b4;clip-path:polygon(0 100%,8% 42%,18% 66%,30% 30%,44% 58%,56% 38%,68% 62%,80% 34%,100% 70%,100% 100%)}
609
- .tpl-landscape .p2{bottom:23%;height:32%;background:#6ea08d;clip-path:polygon(0 100%,12% 48%,26% 72%,40% 40%,58% 68%,72% 44%,86% 70%,100% 50%,100% 100%)}
610
- .tpl-landscape .p3{bottom:9%;height:30%;background:#4a8a76;clip-path:polygon(0 100%,10% 58%,30% 78%,50% 52%,70% 80%,88% 60%,100% 84%,100% 100%)}
611
- .tpl-landscape .p4{bottom:-5%;height:24%;background:#356b5a;clip-path:polygon(0 100%,18% 62%,42% 86%,64% 66%,84% 90%,100% 74%,100% 100%)}
608
+ .tpl-landscape .p1{bottom:36%;height:32%;background:color-mix(in srgb,#a8c6b4 80%,var(--accent) 20%);clip-path:polygon(0 100%,8% 42%,18% 66%,30% 30%,44% 58%,56% 38%,68% 62%,80% 34%,100% 70%,100% 100%)}
609
+ .tpl-landscape .p2{bottom:23%;height:32%;background:color-mix(in srgb,#6ea08d 80%,var(--accent) 20%);clip-path:polygon(0 100%,12% 48%,26% 72%,40% 40%,58% 68%,72% 44%,86% 70%,100% 50%,100% 100%)}
610
+ .tpl-landscape .p3{bottom:9%;height:30%;background:color-mix(in srgb,#4a8a76 80%,var(--accent) 20%);clip-path:polygon(0 100%,10% 58%,30% 78%,50% 52%,70% 80%,88% 60%,100% 84%,100% 100%)}
611
+ .tpl-landscape .p4{bottom:-5%;height:24%;background:color-mix(in srgb,#356b5a 80%,var(--accent) 20%);clip-path:polygon(0 100%,18% 62%,42% 86%,64% 66%,84% 90%,100% 74%,100% 100%)}
612
612
  .tpl-landscape .content{position:relative;display:flex;flex-direction:column;justify-content:center;width:min(82%,1060px);height:100%;padding:7vh 0}
613
- .tpl-landscape .badge{align-self:flex-start;font-family:Georgia,'Songti SC','SimSun',serif;font-size:12px;letter-spacing:6px;color:#356b5a;border:1px solid #356b5a;padding:6px 14px;margin-bottom:3vh}
614
- .tpl-landscape h1{font-family:Georgia,'Songti SC','SimSun',serif;font-size:clamp(36px,4.8vw,62px);font-weight:700;color:#26352e;line-height:1.45;margin-bottom:2vh;max-width:82%}
615
- .tpl-landscape .quote{font-size:15px;color:#5c6b62;margin-bottom:4vh;max-width:64%;line-height:1.9}
613
+ .tpl-landscape .badge{align-self:flex-start;font-family:Georgia,'Songti SC','SimSun',serif;font-size:12px;letter-spacing:6px;color:color-mix(in srgb,#356b5a 80%,var(--accent) 20%);border:1px solid color-mix(in srgb,#356b5a 80%,var(--accent) 20%);padding:6px 14px;margin-bottom:3vh}
614
+ .tpl-landscape h1{font-family:Georgia,'Songti SC','SimSun',serif;font-size:clamp(36px,4.8vw,62px);font-weight:700;color:color-mix(in srgb,#26352e 80%,var(--text) 20%);line-height:1.45;margin-bottom:2vh;max-width:82%}
615
+ .tpl-landscape .quote{font-size:15px;color:color-mix(in srgb,#5c6b62 75%,var(--muted) 25%);margin-bottom:4vh;max-width:64%;line-height:1.9}
616
616
  .tpl-landscape ul.points{list-style:none;display:flex;flex-direction:column;gap:12px;margin-bottom:3.5vh}
617
- .tpl-landscape ul.points li{font-size:14px;color:#26352e;display:flex;gap:10px;align-items:baseline}
618
- .tpl-landscape ul.points .num{font-family:Georgia,'Songti SC','SimSun',serif;color:#b06a3b;font-weight:700;flex:none}
619
- .tpl-landscape footer{display:flex;justify-content:space-between;font-size:10px;letter-spacing:3px;color:#5c6b62}
617
+ .tpl-landscape ul.points li{font-size:14px;color:color-mix(in srgb,#26352e 80%,var(--text) 20%);display:flex;gap:10px;align-items:baseline}
618
+ .tpl-landscape ul.points .num{font-family:Georgia,'Songti SC','SimSun',serif;color:color-mix(in srgb,#b06a3b 80%,var(--accent) 20%);font-weight:700;flex:none}
619
+ .tpl-landscape footer{display:flex;justify-content:space-between;font-size:10px;letter-spacing:3px;color:color-mix(in srgb,#5c6b62 75%,var(--muted) 25%)}
620
620
 
621
621
  /* 32. watermark 水印公文:斜置大字背景水印 + 居中公文正文(颜色跟随主题令牌) */
622
622
  .tpl-watermark{display:flex;align-items:center;justify-content:center;width:100%;height:100%;position:relative;overflow:hidden}
@@ -633,7 +633,7 @@ body{background:linear-gradient(180deg,var(--bg) 12%,var(--bg2) 135%);color:var(
633
633
  .tpl-watermark footer{display:flex;flex-direction:column;align-items:flex-end;font-size:12px;color:var(--muted);gap:6px;margin-top:auto}
634
634
 
635
635
  /* ▼ 用户模板 CSS 内嵌点(TPL_DIR 模板的 TPL_CSS 块插到本行之前,无用户模板则保持原样) */
636
- /* ═══ 切换坞(可折叠):模板坞(32 标签七组流派 + 用户模板)在顶部、主题坞(25 色点 5×5)在右下角;默认折叠成胶囊把手,点开选完自动收起 ═══ */
636
+ /* ═══ 切换坞(可折叠):模板坞(32 标签七组流派 + 用户模板)在顶部、主题坞(25 色点 5×5)在右下角;默认折叠成胶囊把手,点开可连续试选不收起,右上角 × 圆钮关闭 ═══ */
637
637
  .dock-tpl{position:fixed;right:18px;top:18px;display:flex;flex-direction:column;align-items:flex-end;gap:8px;z-index:1001}
638
638
  .dock-theme{position:fixed;right:18px;bottom:18px;display:flex;flex-direction:column;align-items:flex-end;gap:8px;z-index:1001}
639
639
  .dock-bar{display:flex;align-items:center;gap:8px;background:var(--panel-solid);border:1px solid var(--border);border-radius:999px;padding:7px 13px;color:var(--text);cursor:pointer;box-shadow:0 4px 18px rgba(0,0,0,.3);transition:border-color .15s ease;font-family:inherit}
@@ -644,6 +644,7 @@ body{background:linear-gradient(180deg,var(--bg) 12%,var(--bg2) 135%);color:var(
644
644
  .dock-theme.fold .bar-arrow{transform:rotate(-90deg)}
645
645
  .dock-theme .bar-arrow{transform:rotate(180deg)}
646
646
  .dock-body{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px;background:var(--panel-solid);border:1px solid var(--border);border-radius:14px;padding:8px 10px;max-width:min(720px,calc(100vw - 36px));box-shadow:0 4px 18px rgba(0,0,0,.3)}
647
+ .dock-tpl .dock-body{max-width:min(480px,calc(100vw - 36px));position:relative}
647
648
  .dock-theme .dock-body{display:grid;grid-template-columns:repeat(5,18px);gap:11px 10px;border-radius:14px;padding:12px 13px;max-width:none;position:relative}
648
649
  .th-close{position:absolute;top:-10px;right:-10px;width:22px;height:22px;border-radius:50%;border:1px solid var(--border);background:var(--panel-solid);color:var(--muted);font-size:14px;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.28);padding:0}
649
650
  .th-close:hover{color:var(--text);border-color:var(--accent)}
@@ -700,7 +701,7 @@ html[data-shot] .dock-tpl,html[data-shot] .dock-theme{display:none!important}
700
701
  .dock-body{max-width:calc(100vw - 36px)}
701
702
  }
702
703
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
703
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
704
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
704
705
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
705
706
 
706
707
  </style>
@@ -710,6 +711,7 @@ html.theming, html.theming *, html.theming *::before, html.theming *::after{ tra
710
711
  <div class="dock-tpl fold" id="tplDock">
711
712
  <button class="dock-bar" id="tplBar" type="button" title="模板切换(点击展开/收起)"><span class="bar-tpl-name">模板</span><span class="bar-arrow">▾</span></button>
712
713
  <div class="dock-body">
714
+ <button class="th-close" id="tpClose" type="button" title="关闭(点顶部「模板」标签可重新打开)" aria-label="关闭模板面板">×</button>
713
715
  <span class="tp-sep">现代主义</span>
714
716
  <button class="tp-btn on" data-tpl="classic" title="经典舞台">经典</button>
715
717
  <button class="tp-btn" data-tpl="minimal" title="极简留白">极简</button>
@@ -1259,7 +1261,6 @@ html.theming, html.theming *, html.theming *::before, html.theming *::after{ tra
1259
1261
  try { localStorage.setItem(TPL_KEY, curP); } catch(e) {}
1260
1262
  document.querySelectorAll('.tp-btn').forEach(function(x){ x.classList.toggle('on', x === b); });
1261
1263
  var bt = document.querySelector('#tplBar .bar-tpl-name'); if (bt) bt.textContent = '模板 · ' + b.textContent;
1262
- document.getElementById('tplDock').classList.add('fold');
1263
1264
  render();
1264
1265
  });
1265
1266
  });
@@ -1282,6 +1283,8 @@ html.theming, html.theming *, html.theming *::before, html.theming *::after{ tra
1282
1283
  bindBar('themeDock');
1283
1284
  var thClose = document.getElementById('thClose');
1284
1285
  if (thClose) thClose.addEventListener('click', function(){ document.getElementById('themeDock').classList.add('fold'); });
1286
+ var tpClose = document.getElementById('tpClose');
1287
+ if (tpClose) tpClose.addEventListener('click', function(){ document.getElementById('tplDock').classList.add('fold'); });
1285
1288
  var initTplBtn = document.querySelector('#tplDock .tp-btn[data-tpl="' + curP + '"]');
1286
1289
  var btEl = document.querySelector('#tplBar .bar-tpl-name');
1287
1290
  if (btEl) btEl.textContent = '模板 · ' + (initTplBtn ? initTplBtn.textContent : '自定义');
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-forge-hub",
3
- "version": "1.3.11",
3
+ "version": "1.3.13",
4
4
  "description": "SkillForge (技能锻造坊) — a curated collection of AI craft skills. Install once, then pick skills interactively: daily/weekly/monthly/quarterly/annual reports, meeting minutes, article-to-HTML, magic-deck slides, deck-stage PPTX, prompt-pouch manager, Pandoc doc converters, meta-forge.",
5
5
  "bin": {
6
6
  "skill-forge": "cli.js"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: prompt-pouch
3
- description: 锦囊(prompt-pouch)提示词管理 Skill:生成并维护一个本地 HTML 提示词管理页面(锦囊管理台), 暖棕金/深蓝科技/IDEA 黑亮/IDEA 白亮/薄荷绿五套主题(右下角换肤坞随时切换,THEME 配置可设默认),页面披四层科技氛围(网格/星点/扫描线/光带,与日报/周报/年报同源、卡片带细纹),功能为分组侧栏(带计数徽章)+ 搜索(关键词高亮)+ 卡片网格 + 四种排序(最新添加默认/最近使用/使用频率/手动, 拖拽与 ▲▼ 自动切手动)+ 分组条拖拽排序 + 标签交互(点击过滤/悬停删/快捷加)+ 导入导出 JSON 备份 + 使用统计 + 收藏星标 + {变量} 插值填充面板 + 一键复制 + 卡片「👁 详情」弹窗 (全文滚动查看 / 复制 / 修改 / 创建修改时间线);数据存 <DIR>/data/prompts.json(DATA_DIR 可配), 页面与数据严格分离,双笔协作(页面经授权目录直写,AI 代笔维护)。四类任务:①初始化——目标目录无页面时确认目录(默认用户配置 DIR) 并生成 prompt-pouch.html(样式真相源为 resources/reference.html,原样复制)与 data/prompts.json (默认示例五组:写作输出/沟通协作/规划执行/复盘成长/提问艺术,每条带 createdAt;页面另内置同款示例种子 DEFAULT_POUCH,prompts.json 读不到时兜底展示);②维护——用户说「把这段话/这段对话/这个文件/XX 加进锦囊、存成提示词、收藏这句话」或口述增删改提示词与分组、调整排序、导入导出备份、 切换收藏,读写 prompts.json(UTF-8、2 空格缩进),用户刷新页面即见;③取用——用户说「锦囊里有什么适合 XX 的」列候选推荐;日常任务(写日报/周报/复盘/邮件等)动手前先查锦囊匹配模板,有则套用执行、无则完成后轻问是否入囊。④打开——用户说「打开锦囊」时 起本地服务并按平台打开浏览器访问管理页面。 数据通过 HTTP 方式访问(file:// 直开会回退浏览器缓存快照,需提示用户起本地服务)。 当用户问「锦囊怎么用/使用说明」时输出 resources/usage-guide.md 内容,不执行任何文件操作。
3
+ description: 锦囊(prompt-pouch)提示词管理 Skill:生成并维护一个本地 HTML 提示词管理页面(锦囊管理台), 暖棕金/深蓝科技/IDEA 黑亮/IDEA 白亮/薄荷绿五套主题(右下角换肤坞随时切换,THEME 配置可设默认),页面披四层科技氛围(网格/星点/扫描线/光带,与日报/周报/年报同源、卡片带细纹),功能为分组侧栏(带计数徽章)+ 搜索(关键词高亮)+ 卡片网格 + 四种排序(最新添加默认/最近使用/使用频率/手动, 拖拽与 ▲▼ 自动切手动)+ 分组条拖拽排序 + 标签交互(点击过滤/悬停删/快捷加)+ 导入导出 JSON 备份 + 使用统计 + 收藏星标 + {变量} 插值填充面板 + 一键复制 + 卡片「👁 详情」弹窗 (全文滚动查看 / 复制 / 修改 / 创建修改时间线);数据存 <DIR>/data/prompts.json(DATA_DIR 可配), 页面与数据严格分离,双笔协作(页面经授权目录直写,AI 代笔维护)。四类任务:①初始化——目标目录无页面时确认目录(默认用户配置 DIR) 并生成 prompt-pouch.html(样式真相源为 resources/reference.html,原样复制)与 data/prompts.json (默认示例五组:写作输出/沟通协作/规划执行/复盘成长/提问艺术,每条带 createdAt;页面另内置同款示例种子 DEFAULT_POUCH,prompts.json 读不到时兜底展示);②维护——用户说「把这段话/这段对话/这个文件/XX 加进锦囊、存成提示词、收藏这句话」或口述增删改提示词与分组、调整排序、导入导出备份、 切换收藏,读写 prompts.json(UTF-8、2 空格缩进),用户刷新页面即见;③取用——用户说「锦囊里有什么适合 XX 的」列候选推荐;日常任务(写日报/周报/复盘/邮件等)动手前先查锦囊匹配模板,有则套用执行、无则完成后轻问是否入囊。④打开——用户说「打开锦囊」时 起本地服务并按平台打开浏览器访问管理页面(打开前静默自检页面版本,旧则列出更新点询问是否升级,同意走回炉升级)。 数据通过 HTTP 方式访问(file:// 直开会回退浏览器缓存快照,需提示用户起本地服务)。 当用户问「锦囊怎么用/使用说明」时输出 resources/usage-guide.md 内容,不执行任何文件操作。
4
4
  allowed-tools: ["Bash", "Read", "Write", "Edit"]
5
5
  disable-model-invocation: false
6
6
  ---
@@ -24,6 +24,9 @@ disable-model-invocation: false
24
24
  ## 执行流程
25
25
 
26
26
  0. **读用户配置**(DIR/DIR_WIN/PORT/DATA_DIR/BACKUP_DIR/INIT_DATA/CONFIRM/THEME/CONFIG_VERSION)→ 先 Read 同目录 `user-config.md`
27
+ 0.1 **版本自检(静默前置,全时机)**:目标目录存在 `prompt-pouch.html` 时,读其 `<meta name="sf-template">` 版本戳与 `resources/reference.html` 当前版比对(读两行 meta,零网络、不碰数据),结果只影响「提示」不影响「执行」:
28
+ - 版本一致 / 无页面(首次初始化)→ 静默跳过,直接进对应流程
29
+ - 版本旧 → 记下版本差(旧 @N → 当前 @M),按场景分级提示(打开见步骤 4、维护见步骤 2、取用见步骤 3);禁止因版本旧而拒绝或推迟执行本次任务
27
30
  0.5 **意图识别与确认**:
28
31
  - **明确入囊**:用户说「把这段话/这段对话/这个文件 加进锦囊、存成提示词、收藏这句话、整理进锦囊」→ 直接进入维护或批量整理流程
29
32
  - **模糊意图**:用户表达可能指向锦囊但不明确(如「保存这个」「记一下这个」)→ 先 AskUserQuestion 确认(选项:放入锦囊提示词 / 只是本次会话临时记录 / 其它),确认后执行,不擅自写文件
@@ -42,6 +45,7 @@ disable-model-invocation: false
42
45
  - **分类交互**:用户说「添加 XX」但未说分组 → 先按现有分组语义智能匹配(如内容讲周报 → 建议「写作输出 ✍️」并说明理由),匹配到则默认归入、用户可改口换组;匹配不到 → AskUserQuestion 列出全部现有分组(加「新建分组」选项)让用户选;用户指定的分组不存在 → 明确告知该分组不存在,并问是否新建(新建则补 groups 条目:id 16 位数字主键(雪花规则见 data-format.md)、name 中文、icon 一个 emoji)
43
46
  - **调优**:用户说「这条不好用,帮我改」→ 读原文 + 用户反馈 → 输出改版对照(旧 → 新)→ 用户确认后写回(updatedAt 更新到时分秒,写回前重读合并 + 先备份)
44
47
  - **效果反馈**:用户说「这条好用 / 这条用着顺手」→ 定位条目,把反馈写进可选 `notes` 字段(无则新建;一段使用心得/效果备注,页面详情弹窗「📝 使用心得」只读展示,页面表单不编辑此字段);说「这条不好用」但不想改 → 同样记入 notes 留档
48
+ - **版本轻提示**:0.1 自检发现页面旧版 → 本次维护照常执行(读写 prompts.json 与页面版本无关),收尾报告末尾附一句「锦囊页面还是旧版(@N,当前 @M),说『升级锦囊』即可换新」,不弹问、不打断;用户拒绝过升级则本次会话静默不提
45
49
  2.5 **交付前自检**(初始化与每次维护落盘后必做,硬门禁不可跳过):
46
50
  - **json 机器校验**:`python3 -c "import json;json.load(open('<DIR>/<DATA_DIR>/prompts.json',encoding='utf-8'))"`(Windows 用 py)解析通过,且 schema 自查无缺(version/groups/prompts 齐全、group 引用存在、order 连续、新增条目 createdAt 到时分秒)
47
51
  - **页面零报错验证**:Playwright headless(缺则 `pip3 install --user playwright`;用系统 Chrome,channel="chrome" 无需下载浏览器)→ 起本地服务 `cd <DIR> && python3 -m http.server <PORT>` → goto `http://localhost:<PORT>/prompt-pouch.html` → 挂 pageerror 监听(零容忍)→ 断言卡片数 `document.querySelectorAll('.card').length` 等于 prompts.json 的 prompts 条数(证明数据被正确读到;落回内置示例种子即自检失败)→ 收尾停服务
@@ -51,8 +55,11 @@ disable-model-invocation: false
51
55
  - 用户选定某条 → 直接按该模板执行任务(含 {变量} 按上下文填充)或输出正文供复制;用户不选 → 不强行套用
52
56
  - 无匹配 → 正常完成任务,完成后轻问一句「这次的写法要不要收进锦囊?下次直接复用」——用户同意则衔接维护/批量整理流程
53
57
  - **日常任务取用纪律**:用户请求写日报/周报/复盘/邮件等常见任务时,先静默快扫锦囊有无匹配模板:有 → 告知「锦囊里有现成的 XX 模板,我来套用」并执行;无 → 不打断、正常完成,完成后一句轻问是否入囊(用户说「不用查锦囊」则本次跳过)
58
+ - **版本轻提示**:0.1 自检发现页面旧版 → 取用照常执行,收尾一句话附注(同上);拒绝过则静默
54
59
  4. **打开页面**:用户说「打开锦囊 / 打开提示词页面」→
55
60
  - 目标目录无页面时先执行步骤 1(初始化)
61
+ - **打开时升级询问**:0.1 自检发现页面旧版 → 起服务前先 AskUserQuestion(选项:A 升级后打开(推荐)——走「产物升级(回炉)」流程:备份旧页 .bak-时间戳 + 换新版并沿用原页 pouch-id(收藏/分组记忆不丢)+ prompts.json 数据不动,升完照常打开;B 直接打开旧版——本次会话不再询问)。询问时附更新点清单:检索 CHANGELOG.md 中 prompt-pouch 相关条目,结合版本差区间列出 2-5 条用户可感知的变化(新功能/体验改进,一句话一条);CHANGELOG 查不到时据 reference.html 与旧页差异自行归纳
62
+ - 版本一致 → 直接起服务打开,零打扰
56
63
  - 后台起本地服务(`cd <DIR> && python3 -m http.server <PORT>`,Windows 用 `py -m http.server`;端口被占则换 PORT+1 再试)
57
64
  - 按平台打开浏览器:darwin → `open http://localhost:<PORT>/prompt-pouch.html`;win32 → `start` 同 URL;linux → `xdg-open` 同 URL
58
65
  - 打开后对话中报访问地址(http://localhost:<PORT>/prompt-pouch.html)与页面文件完整路径
@@ -78,7 +85,7 @@ disable-model-invocation: false
78
85
 
79
86
  ## 产物升级(回炉)
80
87
 
81
- 生成/初始化页面时头部写版本戳 `<meta name="sf-template" content="prompt-pouch@17">`(模板升级时递增 @N 并同步 reference.html 与本文档)。用户说「升级旧锦囊/回炉旧页面/旧锦囊换新样式」时:扫 `<DIR>` 下 `prompt-pouch.html` 读版本戳筛出旧版(无版本戳或缺少 `<meta name="pouch-id">` 稳定 ID 的产物视为 v0 最旧版,一并进清单)→ 列清单(文件/旧版本/有无用户数据)→ AskUserQuestion 选全部或部分 → 逐份升级:浅升级(仅 CSS/JS 变化)对旧页替换 `<style>` 块与交互脚本;深升级(DOM 结构变化)从 reference.html 重建,**必须沿用原页 pouch-id meta 值**(IndexedDB 用户数据按 pouch-id 命名空间存取,换 ID = 数据失联,重建后原收藏/分组照旧读回),`<DIR>/<DATA_DIR>/prompts.json` 数据文件一概不动,先备份旧页 `.bak-时间戳` → 报告三段式:✅ 已升级清单 / ⚠️ 手改保留说明 / 🟡 失败项原因。模板改动分级:业务改动(板块/段落/标题体系)、数据格式改动(字段/存储结构)、页面改动(样式/布局/交互)任一发生即模板升级,版本戳 +1 并同步 reference.html 与本文档;纯措辞润色不 bump。每次生成/初始化新锦囊时顺扫 `<DIR>` 读版本戳:发现旧版产物主动告知「技能模板已升级至 vN,检测到 X 份旧版锦囊,说『把我旧锦囊都升级成新样式』即可一键升级」,不让用户背触发语。
88
+ 生成/初始化页面时头部写版本戳 `<meta name="sf-template" content="prompt-pouch@17">`(模板升级时递增 @N 并同步 reference.html 与本文档)。用户说「升级旧锦囊/回炉旧页面/旧锦囊换新样式」时:扫 `<DIR>` 下 `prompt-pouch.html` 读版本戳筛出旧版(无版本戳或缺少 `<meta name="pouch-id">` 稳定 ID 的产物视为 v0 最旧版,一并进清单)→ 列清单(文件/旧版本/有无用户数据)→ AskUserQuestion 选全部或部分 → 逐份升级:浅升级(仅 CSS/JS 变化)对旧页替换 `<style>` 块与交互脚本;深升级(DOM 结构变化)从 reference.html 重建,**必须沿用原页 pouch-id meta 值**(IndexedDB 用户数据按 pouch-id 命名空间存取,换 ID = 数据失联,重建后原收藏/分组照旧读回),`<DIR>/<DATA_DIR>/prompts.json` 数据文件一概不动,先备份旧页 `.bak-时间戳` → 报告三段式:✅ 已升级清单 / ⚠️ 手改保留说明 / 🟡 失败项原因。模板改动分级:业务改动(板块/段落/标题体系)、数据格式改动(字段/存储结构)、页面改动(样式/布局/交互)任一发生即模板升级,版本戳 +1 并同步 reference.html 与本文档;纯措辞润色不 bump。**每次调用本 skill(生成/初始化/维护/取用/打开)都先顺扫 `<DIR>` 读版本戳**(见步骤 0.1):发现旧版产物按场景分级提示——打开场景主动询问升级(步骤 4),维护/取用场景收尾一句话轻提示(步骤 2/3),初始化生成场景直接按当前模板生成并主动告知;用户拒绝升级后本次会话不再提示,不让用户背触发语。
82
89
 
83
90
  ## ⚙️ 配置与自定义主题
84
91
 
@@ -692,7 +692,7 @@ footer.open .ht-arrow{ transform:rotate(180deg); }
692
692
  .theme-dock .th-dot[data-theme="mint"]{ background:#4ade80; }
693
693
  @media print{ .theme-dock{ display:none; } }
694
694
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
695
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
695
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
696
696
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
697
697
 
698
698
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -231,7 +231,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
231
231
  .header-card h1{ font-size:26px; }
232
232
  }
233
233
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
234
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
234
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
235
235
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
236
236
 
237
237
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -191,7 +191,7 @@ html[data-shot] .card{animation:none!important}
191
191
  @media (max-width:680px){body{padding:24px 12px}.wrap{width:100%}.row2{grid-template-columns:1fr}.header-card h1{font-size:18px}}
192
192
  @media print{.theme-dock,.btn{display:none}}
193
193
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
194
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
194
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
195
195
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
196
196
 
197
197
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
package/template/SKILL.md CHANGED
@@ -35,7 +35,7 @@ disable-model-invocation: false
35
35
 
36
36
  ## 产物升级(回炉)——仅含 HTML 输出的技能保留本节,否则删除
37
37
 
38
- 生成 HTML 时头部写版本戳 `<meta name="sf-template" content="<skill>@1">`(模板升级时递增 @N 并同步 reference.html 与本文档)。用户说「升级旧产物/回炉旧页面/旧XX换新样式」时:扫落盘目录读版本戳筛出旧版(无版本戳或缺少稳定 ID meta 的产物视为 v0 最旧版,一并进清单)→ 列清单(文件/旧版本/手改状态)→ AskUserQuestion 选全部或部分 → 逐份升级:浅升级(仅 CSS/JS 变化)对旧页替换 `<style>` 块与交互脚本、正文原样保留;深升级(DOM 结构变化)从同目录 md 底稿按当前 reference.html 重建且**沿用原页稳定 ID meta 值**(用户数据类换 ID = 数据失联),先备份旧版 `.bak-时间戳` → 报告三段式:✅ 已升级清单 / ⚠️ 手改保留说明 / 🟡 失败项原因。模板改动分级:业务改动(板块/段落/标题体系)、数据格式改动(字段/存储结构)、页面改动(样式/布局/交互)任一发生即模板升级,版本戳 +1 并同步 reference.html 与本文档;纯措辞润色不 bump。每次生成 HTML 时顺扫落盘目录读版本戳:发现旧版产物主动告知「技能模板已升级至 vN,检测到 X 份旧版产物,说『把我旧XX都升级成新样式』即可一键升级」,不让用户背触发语。
38
+ 生成 HTML 时头部写版本戳 `<meta name="sf-template" content="<skill>@1">`(模板升级时递增 @N 并同步 reference.html 与本文档)。用户说「升级旧产物/回炉旧页面/旧XX换新样式」时:扫落盘目录读版本戳筛出旧版(无版本戳或缺少稳定 ID meta 的产物视为 v0 最旧版,一并进清单)→ 列清单(文件/旧版本/手改状态)→ AskUserQuestion 选全部或部分 → 逐份升级:浅升级(仅 CSS/JS 变化)对旧页替换 `<style>` 块与交互脚本、正文原样保留;深升级(DOM 结构变化)从同目录 md 底稿按当前 reference.html 重建且**沿用原页稳定 ID meta 值**(用户数据类换 ID = 数据失联),先备份旧版 `.bak-时间戳` → 报告三段式:✅ 已升级清单 / ⚠️ 手改保留说明 / 🟡 失败项原因。模板改动分级:业务改动(板块/段落/标题体系)、数据格式改动(字段/存储结构)、页面改动(样式/布局/交互)任一发生即模板升级,版本戳 +1 并同步 reference.html 与本文档;纯措辞润色不 bump。每次生成 HTML 时顺扫落盘目录读版本戳:发现旧版产物主动告知「技能模板已升级至 vN,检测到 X 份旧版产物,说『把我旧XX都升级成新样式』即可一键升级」,不让用户背触发语。(工具型产物——固定页面反复打开、数据累积——每次调用本 skill 全时机顺扫,执行流程第 0 步后固定加「版本自检(静默前置,全时机)」步骤:静默比对版本戳、结果只影响提示不影响执行;打开场景主动问——起服务前 AskUserQuestion「A 升级后打开(推荐)/B 直接打开旧版(本次会话不再问)」附更新点清单;维护/取用场景收尾一句话轻提示;拒绝过后本会话静默)
39
39
 
40
40
  ## 文档同步自检纪律(维护者必读)
41
41
 
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>
@@ -529,7 +529,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
529
529
  .header-card h1{ font-size:26px; }
530
530
  }
531
531
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡;平时类不存在,不影响任何元素 */
532
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
532
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
533
533
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
534
534
 
535
535
  </style>
@@ -206,7 +206,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
206
206
  .header-card h1{ font-size:26px; }
207
207
  }
208
208
  /* 主题切换渐变:切换瞬间给 html 挂 .theming 类(650ms 后自动摘除),期间全页颜色属性平滑过渡(Material 标准缓动);平时类不存在,不影响任何元素 */
209
- html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
209
+ html.theming, html.theming *, html.theming *::before, html.theming *::after{ transition: background .45s cubic-bezier(.4,0,.2,1), background-color .45s cubic-bezier(.4,0,.2,1), color .45s cubic-bezier(.4,0,.2,1), border-color .45s cubic-bezier(.4,0,.2,1), box-shadow .45s cubic-bezier(.4,0,.2,1), fill .45s cubic-bezier(.4,0,.2,1), stroke .45s cubic-bezier(.4,0,.2,1) !important; }
210
210
  @media (prefers-reduced-motion: reduce){ html.theming, html.theming *{ transition: none !important; } }
211
211
 
212
212
  </style>