@topmindspace/tms-skills 0.1.13 → 0.1.15

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 (44) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.en.md +3 -3
  3. package/README.md +3 -3
  4. package/package.json +1 -1
  5. package/top-ppt-html/README.en.md +2 -2
  6. package/top-ppt-html/README.md +1 -1
  7. package/top-ppt-html/SKILL.md +3 -3
  8. package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +59 -20
  9. package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +64 -26
  10. package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +64 -42
  11. package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.html +85 -46
  12. package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.model.json +1 -1
  13. package/top-ppt-html/assets/pptx-export.js +40 -17
  14. package/top-ppt-html/assets/showcase/showcase-charts.png +0 -0
  15. package/top-ppt-html/assets/showcase/showcase-cover.png +0 -0
  16. package/top-ppt-html/assets/showcase/showcase-gates.png +0 -0
  17. package/top-ppt-html/assets/showcase/showcase-modes.png +0 -0
  18. package/top-ppt-html/assets/showcase/showcase-positioning.png +0 -0
  19. package/top-ppt-html/assets/showcase/showcase-split.png +0 -0
  20. package/top-ppt-html/assets/showcase/showcase-toolbar.png +0 -0
  21. package/top-ppt-html/assets/style-gallery.html +3 -3
  22. package/top-ppt-html/assets/templates/architecture.html +59 -20
  23. package/top-ppt-html/assets/templates/engine.css +17 -1
  24. package/top-ppt-html/assets/templates/presentation.html +59 -20
  25. package/top-ppt-html/assets/templates/research.html +60 -27
  26. package/top-ppt-html/assets/templates/ui.js +1 -1
  27. package/top-ppt-html/package-lock.json +2 -2
  28. package/top-ppt-html/package.json +1 -1
  29. package/top-ppt-html/references/components-atoms.md +14 -1
  30. package/top-ppt-html/references/content-rules.md +1 -1
  31. package/top-ppt-html/references/design-system.md +1 -1
  32. package/top-ppt-html/references/icons.md +19 -0
  33. package/top-ppt-html/references/layout-grammar.md +17 -0
  34. package/top-ppt-html/references/layouts-combo.md +2 -4
  35. package/top-ppt-html/references/modes.md +1 -1
  36. package/top-ppt-html/references/pptx-export.md +1 -1
  37. package/top-ppt-html/scripts/build_pptx.js +50 -22
  38. package/top-ppt-html/scripts/layout-constants.json +18 -6
  39. package/top-ppt-html/scripts/quality_gate.py +2 -2
  40. package/top-ppt-html/scripts/render_from_model.py +2 -4
  41. package/top-ppt-html/scripts/scaffold_report.py +4 -10
  42. package/top-ppt-html/scripts/test_feedback_gates.py +2 -2
  43. package/top-ppt-html/scripts/validate_pptx.py +27 -11
  44. package/top-ppt-html/scripts/validate_report.py +27 -5
@@ -261,7 +261,8 @@ section.band{scroll-snap-align:start}
261
261
  svh 兼容移动端浏览器工具栏;旧浏览器落到 100vh。 */
262
262
  .band{padding-block:var(--band-pad);min-height:var(--band-min);
263
263
  display:flex;flex-direction:column;justify-content:center}
264
- .band>.wrap{width:100%}
264
+ .band>.wrap{width:100%;min-height:0}
265
+ .band>.wrap>.grid,.band>.wrap>.stack,.band>.wrap>.fig,.band>.wrap>.cols-2,.band>.wrap>.cols-3,.band>.wrap>.exhibit{min-height:0}
265
266
  .band--top{justify-content:flex-start} /* 内容约六七成屏:贴顶 + 底部自然留白 */
266
267
  .band--fit{justify-content:center} /* 内容接近一屏:垂直居中(默认行为,保留以兼容旧报告) */
267
268
  .band--flow{min-height:0;justify-content:flex-start} /* 长内容页(附录/全量参考)显式退出固定页高 */
@@ -502,6 +503,21 @@ tbody tr:hover{background:var(--surface-1)}
502
503
  td strong{color:var(--text);font-weight:600}
503
504
  td.k{color:var(--text);font-weight:500;white-space:nowrap}
504
505
  td.num{font-variant-numeric:tabular-nums}
506
+ /* ── 结论条(MD3 tonal strip · 本页重点收口;默认不显示「So what」标签) ──
507
+ 与上方主内容呼吸间距 ≥ --sp-6;flex:none 防止被主内容挤压;一屏页不得压进注释带。 */
508
+ .band>.wrap:has(>.sowhat),.band>.wrap:has(>.note){display:flex;flex-direction:column}
509
+ .sowhat{display:flex;align-items:flex-start;gap:var(--sp-3);flex:none;
510
+ margin-top:clamp(28px,3.6vh,48px); /* ≥ --sp-6 量级,修「贴底」 */
511
+ padding:var(--sp-4) var(--sp-5);background:var(--accent-soft);border:1px solid var(--accent-soft-2);
512
+ border-left:4px solid var(--accent);border-radius:var(--r-md);max-width:100%}
513
+ .sowhat__k{display:none}
514
+ .sowhat--labeled .sowhat__k{display:inline;font-size:var(--fs-xs);font-weight:700;letter-spacing:.1em;
515
+ text-transform:uppercase;color:var(--accent-text);white-space:nowrap;flex:none;padding-top:.15em}
516
+ .sowhat__v,.sowhat>:not(.sowhat__k){font-size:var(--fs-h3);color:var(--text);font-weight:var(--fw-title);
517
+ line-height:1.55;flex:1;min-width:0}
518
+ .sowhat__v p,.sowhat__stack{margin:0}
519
+ .sowhat__stack{display:flex;flex-direction:column;gap:var(--sp-2)}
520
+
505
521
  .note{display:flex;gap:var(--sp-4);padding:clamp(20px,2vw,28px);border-radius:var(--r-lg);
506
522
  background:var(--accent-soft);border-left:3px solid var(--accent)}
507
523
  .note__ico{width:26px;height:26px;flex:none;border-radius:50%;background:var(--accent);
@@ -941,7 +957,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
941
957
  <section class="band band--fit" id="cover">
942
958
  <div class="wrap">
943
959
  <div class="shead rv">
944
- <div class="t-eyebrow">产品介绍 · 2026-09-26 · v0.1.11</div>
960
+ <div class="t-eyebrow">产品介绍 · 2026-09-26 · v0.1.15</div>
945
961
  <h1 class="t-display shead__title">TopMind × tms-skills</h1>
946
962
  <p class="t-lead shead__desc">HTML + PPT 双交付 · 为正式商务演示而生</p>
947
963
  </div>
@@ -952,7 +968,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
952
968
  <div class="wrap">
953
969
  <div class="shead rv"><div class="t-eyebrow">目录</div>
954
970
  <h2 class="t-h1 shead__title">报告大纲</h2></div>
955
- <ol class="agenda rv"> <li class="agenda__i"><a class="agenda__a" href="#s1"><span class="agenda__n">01</span><span><span class="agenda__t">市面 PPT 技能很多,为何还要 top-ppt-html</span><div class="agenda__d">01 · 为什么是我们</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s2"><span class="agenda__n">02</span><span><span class="agenda__t">tms-skills:整仓可安装的智能体技能</span><div class="agenda__d">02 · tms-skills</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s3"><span class="agenda__n">03</span><span><span class="agenda__t">双交付:HTML 即演示,PPTX 可继续编</span><div class="agenda__d">03 · top-ppt-html</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s4"><span class="agenda__n">04</span><span><span class="agenda__t">模式先定后写:A 演示 · B 研究 · C 架构</span><div class="agenda__d">04 · 三模式</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s5"><span class="agenda__n">05</span><span><span class="agenda__t">交付面三件套:演示 HTML · 可编辑 PPTX · 门禁说明</span><div class="agenda__d">05 · 图表工艺</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s6"><span class="agenda__n">06</span><span><span class="agenda__t">0.1.x 能力累进:定位与样张随版本加厚</span><div class="agenda__d">05 · 图表工艺</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s7"><span class="agenda__n">07</span><span><span class="agenda__t">九风格开场即可见,亮暗主题一键贯穿</span><div class="agenda__d">06 · 风格主题</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s8"><span class="agenda__n">08</span><span><span class="agenda__t">散装出稿止步,strict 0/0 才算交付</span><div class="agenda__d">07 · 质量门禁</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s9"><span class="agenda__n">09</span><span><span class="agenda__t">从想法到上台:工艺链路如何把主张垫实</span><div class="agenda__d">07 · 质量门禁</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s10"><span class="agenda__n">10</span><span><span class="agenda__t">核图优先:排名对比用横向条,一眼分出轻重</span><div class="agenda__d">05 · 图表工艺</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s11"><span class="agenda__n">11</span><span><span class="agenda__t">打开 HTML 即演示:顶栏快捷操作一览</span><div class="agenda__d">08 · Header 工具栏</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s12"><span class="agenda__n">12</span><span><span class="agenda__t">Fast Mode:跳过问询,不跳过工艺</span><div class="agenda__d">09 · Fast Mode</div></span></a></li></ol>
971
+ <ol class="agenda agenda--2col rv"> <li class="agenda__i"><a class="agenda__a" href="#s1"><span class="agenda__n">01</span><span><span class="agenda__t">市面 PPT 技能很多,为何还要 top-ppt-html</span><div class="agenda__d">01 · 为什么是我们</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s2"><span class="agenda__n">02</span><span><span class="agenda__t">tms-skills:整仓可安装的智能体技能</span><div class="agenda__d">02 · tms-skills</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s3"><span class="agenda__n">03</span><span><span class="agenda__t">双交付:HTML 即演示,PPTX 可继续编</span><div class="agenda__d">03 · top-ppt-html</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s4"><span class="agenda__n">04</span><span><span class="agenda__t">模式先定后写:A 演示 · B 研究 · C 架构</span><div class="agenda__d">04 · 三模式</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s5"><span class="agenda__n">05</span><span><span class="agenda__t">交付面三件套:演示 HTML · 可编辑 PPTX · 门禁说明</span><div class="agenda__d">05 · 图表工艺</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s6"><span class="agenda__n">06</span><span><span class="agenda__t">0.1.x 能力累进:定位与样张随版本加厚</span><div class="agenda__d">05 · 图表工艺</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s7"><span class="agenda__n">07</span><span><span class="agenda__t">九风格开场即可见,亮暗主题一键贯穿</span><div class="agenda__d">06 · 风格主题</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s8"><span class="agenda__n">08</span><span><span class="agenda__t">散装出稿止步,strict 0/0 才算交付</span><div class="agenda__d">07 · 质量门禁</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s9"><span class="agenda__n">09</span><span><span class="agenda__t">从想法到上台:工艺链路如何把主张垫实</span><div class="agenda__d">07 · 质量门禁</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s10"><span class="agenda__n">10</span><span><span class="agenda__t">核图优先:排名对比用横向条,一眼分出轻重</span><div class="agenda__d">05 · 图表工艺</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s11"><span class="agenda__n">11</span><span><span class="agenda__t">打开 HTML 即演示:顶栏快捷操作一览</span><div class="agenda__d">08 · Header 工具栏</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s12"><span class="agenda__n">12</span><span><span class="agenda__t">Fast Mode:跳过问询,不跳过工艺</span><div class="agenda__d">09 · Fast Mode</div></span></a></li></ol>
956
972
  </div>
957
973
  </section>
958
974
 
@@ -963,12 +979,12 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
963
979
  <h2 class="t-h1 shead__title">市面 PPT 技能很多,为何还要 top-ppt-html</h2>
964
980
  </div>
965
981
  <div class="grid g-2 rv a-start">
966
- <div class="card"><div class="card__hd"><h3 class="t-h3">要点一</h3></div>
982
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="6"/><path d="M15.5 13 17 22l-5-3-5 3 1.5-9"/></svg></div><h3 class="t-h3">要点一</h3></div>
967
983
  <ul class="ul"><li><strong>正式商务演示,不是花哨 gadget。</strong>为演示报告与上台汇报而生——直观、大气、可编辑,而非装饰堆砌</li><li><strong>HTML + PPT 双交付。</strong>日常用 HTML 等同幻灯片演示;需要时再导出高保真可编辑 PPTX</li></ul></div>
968
- <div class="card"><div class="card__hd"><h3 class="t-h3">要点二</h3></div>
984
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l8 3v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6l8-3z"/></svg></div><h3 class="t-h3">要点二</h3></div>
969
985
  <ul class="ul"><li><strong>信息密度与克制(参考 MD3)。</strong>整体空间布局合适、文字/图形/形状/颜色克制——读得清、站得住</li></ul></div>
970
986
  </div>
971
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">产出即上台:同源模型保证 HTML 与 PPTX 一致,图表带数据可核对。</span></div>
987
+ <div class="sowhat rv"><span class="sowhat__v">产出即上台:同源模型保证 HTML 与 PPTX 一致,图表带数据可核对。</span></div>
972
988
  </div>
973
989
  </section>
974
990
 
@@ -979,11 +995,11 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
979
995
  <h2 class="t-h1 shead__title">tms-skills:整仓可安装的智能体技能</h2>
980
996
  </div>
981
997
  <div class="grid g-3 rv a-start">
982
- <div class="card"><div class="card__hd"><h3 class="t-h3">Monorepo</h3></div>
998
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2l9 5-9 5-9-5 9-5z"/><path d="M3 12l9 5 9-5"/><path d="M3 17l9 5 9-5"/></svg></div><h3 class="t-h3">Monorepo</h3></div>
983
999
  <ul class="ul"><li><strong>一仓多技能。</strong>根目录技能包 + 统一安装器</li><li><strong>同 tag 发版。</strong>安装器与技能整仓对齐</li></ul></div>
984
- <div class="card"><div class="card__hd"><h3 class="t-h3">双通道安装</h3></div>
1000
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2L3 14h8l-1 8 10-12h-8l1-8z"/></svg></div><h3 class="t-h3">双通道安装</h3></div>
985
1001
  <ul class="ul"><li><strong>npm 钉版本。</strong>npx @topmindspace/tms-skills</li><li><strong>GitHub 跟 HEAD。</strong>日常可 clone / 直装</li></ul></div>
986
- <div class="card"><div class="card__hd"><h3 class="t-h3">当前主技能</h3></div>
1002
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M8 13h8M8 17h6"/></svg></div><h3 class="t-h3">当前主技能</h3></div>
987
1003
  <ul class="ul"><li><strong>top-ppt-html。</strong>正式场合演示文稿</li><li><strong>HTML + PPTX。</strong>同源模型 · 双交付</li></ul></div>
988
1004
  </div>
989
1005
  <div class="footnote">包名 @topmindspace/tms-skills · 当前线 0.1.x(latest)</div>
@@ -997,7 +1013,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
997
1013
  <h2 class="t-h1 shead__title">双交付:HTML 即演示,PPTX 可继续编</h2>
998
1014
  </div>
999
1015
  <div class="grid g-side rv a-start">
1000
- <div class="stack gap-4"><ul class="ul"><li><strong>日常 HTML 上台。</strong>单文件可翻页,等同幻灯片;亮暗与九风格顶栏即切</li><li><strong>需要时再出 PPT。</strong>版式保真可编辑 PPTX;图表数据可标注、可核对</li><li><strong>克制的商务面。</strong>参考 MD3:合适信息密度,少装饰、一屏一主张</li></ul></div>
1016
+ <div class="stack gap-4"><ul class="ul ul--ico"><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M8 13h8M8 17h6"/></svg><strong>日常 HTML 上台。</strong>单文件可翻页,等同幻灯片;亮暗与九风格顶栏即切</li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><rect x="7" y="12" width="3" height="6" rx="1"/><rect x="12" y="8" width="3" height="10" rx="1"/><rect x="17" y="4" width="3" height="14" rx="1"/></svg><strong>需要时再出 PPT。</strong>版式保真可编辑 PPTX;图表数据可标注、可核对</li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l8 3v6c0 5-3.5 8.5-8 10-4.5-1.5-8-5-8-10V6l8-3z"/></svg><strong>克制的商务面。</strong>参考 MD3:合适信息密度,少装饰、一屏一主张</li></ul></div>
1001
1017
  <div class="fig"><div class="fig__cap">工艺关注点(产品强调 · 示意权重)</div>
1002
1018
  <svg class="chart" data-chart="bar" viewBox="0 0 560 220">
1003
1019
  <line x1="46" y1="170" x2="540" y2="170" class="s-bds" stroke-width="1"/>
@@ -1016,7 +1032,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1016
1032
  </svg>
1017
1033
  </div>
1018
1034
  </div>
1019
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">工艺在结构与密度,不在 gadget——正式场合演讲/汇报才是主场。</span></div>
1035
+ <div class="sowhat rv"><span class="sowhat__v">工艺在结构与密度,不在 gadget——正式场合演讲/汇报才是主场。</span></div>
1020
1036
  </div>
1021
1037
  </section>
1022
1038
 
@@ -1027,11 +1043,11 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1027
1043
  <h2 class="t-h1 shead__title">模式先定后写:A 演示 · B 研究 · C 架构</h2>
1028
1044
  </div>
1029
1045
  <div class="grid g-3 rv a-start">
1030
- <div class="card"><div class="card__hd"><h3 class="t-h3">A · 演示</h3></div>
1046
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></svg></div><h3 class="t-h3">A · 演示</h3></div>
1031
1047
  <ul class="ul"><li><strong>每屏一主张。</strong>标题即行动句,非话题标签</li><li><strong>大气留白。</strong>证据充分但不堆咨询 dump</li></ul></div>
1032
- <div class="card"><div class="card__hd"><h3 class="t-h3">B · 研究</h3></div>
1048
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><rect x="7" y="12" width="3" height="6" rx="1"/><rect x="12" y="8" width="3" height="10" rx="1"/><rect x="17" y="4" width="3" height="14" rx="1"/></svg></div><h3 class="t-h3">B · 研究</h3></div>
1033
1049
  <ul class="ul"><li><strong>咨询密排。</strong>Exhibit · 来源 · so-what</li><li><strong>结论可核对。</strong>数字与口径双向对齐</li></ul></div>
1034
- <div class="card"><div class="card__hd"><h3 class="t-h3">C · 架构</h3></div>
1050
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M14.5 9.5l-2 5-5 2 2-5 5-2z"/></svg></div><h3 class="t-h3">C · 架构</h3></div>
1035
1051
  <ul class="ul"><li><strong>图为王。</strong>拓扑 / 泳道 / 分层</li><li><strong>少字多结构。</strong>一图说清关系</li></ul></div>
1036
1052
  </div>
1037
1053
  <div class="footnote">意图线索:路演/汇报/演讲 → A;调研/对标 → B;拓扑/方案图 → C</div>
@@ -1061,7 +1077,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1061
1077
  <ul class="ul"> <li><strong>可翻页 HTML。</strong>40(40%)</li> <li><strong>保真 PPTX。</strong>35(35%)</li> <li><strong>质检交付说明。</strong>25(25%)</li></ul>
1062
1078
  </div>
1063
1079
  </div>
1064
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">双通道不是二选一:HTML 上台演示,PPTX 可继续编辑,门禁证明可交付。</span></div>
1080
+ <div class="sowhat rv"><span class="sowhat__v">双通道不是二选一:HTML 上台演示,PPTX 可继续编辑,门禁证明可交付。</span></div>
1065
1081
  </div>
1066
1082
  </section>
1067
1083
 
@@ -1094,7 +1110,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1094
1110
  <ul class="ul"><li><strong>真实版本线。</strong>对应 CHANGELOG 已合并能力,非虚构增速</li><li><strong>本版强化。</strong>差异化定位 · 双交付叙事 · README 总览精简</li></ul>
1095
1111
  </div>
1096
1112
  </div>
1097
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">质量与叙事同步推进——版本线把门禁、样张与定位一起写清。</span></div>
1113
+ <div class="sowhat rv"><span class="sowhat__v">质量与叙事同步推进——版本线把门禁、样张与定位一起写清。</span></div>
1098
1114
  </div>
1099
1115
  </section>
1100
1116
 
@@ -1110,7 +1126,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1110
1126
  <div class="metric"><div class="metric__v t-metric">1</div><div class="metric__k">交互画廊 style-gallery</div><div class="metric__n"></div></div>
1111
1127
  <div class="metric"><div class="metric__v t-metric">3</div><div class="metric__k">主题参考图(演示·研究·架构)</div><div class="metric__n"></div></div>
1112
1128
  </div>
1113
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">Gate 0 先给参考图;标准模式跳过即不合格。</span></div>
1129
+ <div class="sowhat rv"><span class="sowhat__v">Gate 0 先给参考图;标准模式跳过即不合格。</span></div>
1114
1130
  </div>
1115
1131
  </section>
1116
1132
 
@@ -1121,12 +1137,12 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1121
1137
  <h2 class="t-h1 shead__title">散装出稿止步,strict 0/0 才算交付</h2>
1122
1138
  </div>
1123
1139
  <div class="grid g-half g-2 rv a-start">
1124
- <div class="card"><h3 class="t-h3">散装路径 · 风险</h3>
1140
+ <div class="card"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 3.9L1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z"/><path d="M12 9v4M12 17h.01"/></svg></div><h3 class="t-h3">散装路径 · 风险</h3></div>
1125
1141
  <ul class="ul"><li><strong>手改 HTML。</strong>模型与正文双写,一改就漂</li><li><strong>无严格校验。</strong>截断、同型图、半空卡易漏</li><li><strong>口头交付。</strong>缺七要素,验收靠感觉</li></ul></div>
1126
- <div class="card" style="background:var(--accent-soft);border-color:transparent"><h3 class="t-h3" style="color:var(--accent)">门禁路径 · 目标</h3>
1142
+ <div class="card" style="background:var(--accent-soft);border-color:transparent"><div class="card__hd"><div class="card__ico"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg></div><h3 class="t-h3" style="color:var(--accent)">门禁路径 · 目标</h3></div>
1127
1143
  <ul class="ul"><li><strong>模型单写。</strong>render 回填,禁手改正文</li><li><strong>HTML + PPTX。</strong>validate --strict 双侧 0/0</li><li><strong>七要素说明。</strong>quality_gate --deliver</li></ul></div>
1128
1144
  </div>
1129
- <div class="sowhat rv"><span class="sowhat__k">结论</span><span class="sowhat__v">反截断、图表多样性、runtime SHA——门禁是交付的一部分。</span></div>
1145
+ <div class="sowhat rv"><span class="sowhat__v">反截断、图表多样性、runtime SHA——门禁是交付的一部分。</span></div>
1130
1146
  </div>
1131
1147
  </section>
1132
1148
 
@@ -1165,10 +1181,10 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1165
1181
  </svg>
1166
1182
  </div>
1167
1183
  <div class="stack gap-4"><h3 class="t-h3">怎么读这张图</h3>
1168
- <ul class="ul"><li><strong>意图定模式。</strong>路演→A · 调研→B · 拓扑→C</li><li><strong>门禁收口。</strong>strict 0/0 前不算交付</li></ul>
1184
+ <ul class="ul ul--ico"><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M14.5 9.5l-2 5-5 2 2-5 5-2z"/></svg><strong>意图定模式。</strong>路演→A · 调研→B · 拓扑→C</li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg><strong>门禁收口。</strong>strict 0/0 前不算交付</li></ul>
1169
1185
  </div>
1170
1186
  </div>
1171
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">上台交付 = 模式契约 + 模型单写 + 多样图表 + 门禁收口。</span></div>
1187
+ <div class="sowhat rv"><span class="sowhat__v">上台交付 = 模式契约 + 模型单写 + 多样图表 + 门禁收口。</span></div>
1172
1188
  </div>
1173
1189
  </section>
1174
1190
 
@@ -1179,7 +1195,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1179
1195
  <h2 class="t-h1 shead__title">核图优先:排名对比用横向条,一眼分出轻重</h2>
1180
1196
  </div>
1181
1197
  <div class="grid g-side rv a-start">
1182
- <div class="stack gap-4"><ul class="ul"><li><strong>产品已交付能力。</strong>五项均为当前线真实能力,不是预测</li><li><strong>图表选型。</strong>谁大谁小 → hbar;趋势 → line;占比 → donut</li></ul></div>
1198
+ <div class="stack gap-4"><ul class="ul ul--ico"><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/></svg><strong>产品已交付能力。</strong>五项均为当前线真实能力,不是预测</li><li><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v18h18"/><rect x="7" y="12" width="3" height="6" rx="1"/><rect x="12" y="8" width="3" height="10" rx="1"/><rect x="17" y="4" width="3" height="14" rx="1"/></svg><strong>图表选型。</strong>谁大谁小 → hbar;趋势 → line;占比 → donut</li></ul></div>
1183
1199
  <div class="fig"><div class="fig__cap">能力就绪(当前发布线)</div>
1184
1200
  <svg class="chart" data-chart="hbar" viewBox="0 0 560 220">
1185
1201
  <text x="0" y="30.0" class="f-txt2" font-size="12">strict 0/0</text>
@@ -1205,7 +1221,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1205
1221
  </svg>
1206
1222
  </div>
1207
1223
  </div>
1208
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">说服力来自可核对的能力清单与图表多样性,而非单张柱图凑数。</span></div>
1224
+ <div class="sowhat rv"><span class="sowhat__v">说服力来自可核对的能力清单与图表多样性,而非单张柱图凑数。</span></div>
1209
1225
  <div class="footnote">口径:能力就绪度 = 当前发布线已具备并写入文档/门禁的能力(均为 100%)。</div>
1210
1226
  </div>
1211
1227
  </section>
@@ -1217,7 +1233,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1217
1233
  <h2 class="t-h1 shead__title">打开 HTML 即演示:顶栏快捷操作一览</h2>
1218
1234
  </div>
1219
1235
  <div class="tbl-wrap rv"><table><thead><tr><th>控件</th><th>快捷键</th><th>行为</th></tr></thead><tbody><tr><td>亮暗主题</td><td>T</td><td>浅色外发 / 深色大屏;按文件记忆;同步 REPORT_MODEL.theme</td></tr><tr><td>风格选择</td><td>9 套</td><td>九风格实时切换(纯视觉);交付前 data-style = REPORT_MODEL.style</td></tr><tr><td>预览 PPTX</td><td>P</td><td>页序列所见即所得;可复制提示词回对话走精导</td></tr><tr><td>PPT 生成指引</td><td>H</td><td>双通道说明与环境依赖;与 ? 帮助同效</td></tr><tr><td>全屏</td><td>F</td><td>沉浸演示(requestFullscreen);图标随进入/退出切换</td></tr><tr><td>收起工具栏</td><td>B</td><td>折叠为品牌标+展开迷你条;锚点自适应并按文件记忆</td></tr></tbody></table></div>
1220
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">工具栏不是装饰——演示、预览、换肤与交付指引同一顶栏完成。</span></div>
1236
+ <div class="sowhat rv"><span class="sowhat__v">工具栏不是装饰——演示、预览、换肤与交付指引同一顶栏完成。</span></div>
1221
1237
  <div class="footnote">另:方向键翻页 · Esc 关闭模态 · 风格/主题变更后须重跑校验</div>
1222
1238
  </div>
1223
1239
  </section>
@@ -1233,7 +1249,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1233
1249
  <div class="tl__i"><div class="tl__d"></div><div class="tl__l">推断</div><div class="tl__t">默认参数</div><p class="t-body">路演线索→A·business-blue;未点明→B·mckinsey</p></div>
1234
1250
  <div class="tl__i"><div class="tl__d"></div><div class="tl__l">仍须</div><div class="tl__t">质量闭环</div><p class="t-body">最小大纲 → 模型单写 → strict 0/0 → 交付说明</p></div>
1235
1251
  </div></div>
1236
- <div class="sowhat rv"><span class="sowhat__k">So what</span><span class="sowhat__v">Fast 豁免问询,但反截断与 Mode A craft 一律不降。</span></div>
1252
+ <div class="sowhat rv"><span class="sowhat__v">Fast 豁免问询,但反截断与 Mode A craft 一律不降。</span></div>
1237
1253
  </div>
1238
1254
  </section>
1239
1255
 
@@ -1599,7 +1615,7 @@ if(e.isIntersecting){e.target.classList.add('in');o.unobserve(e.target)}})},
1599
1615
  var PROMPT=[
1600
1616
  '请为这份 HTML 报告生成可编辑 PPTX 并交付:',
1601
1617
  '1) 阅读 references/pptx-export.md 与 references/modes.md(三模式独立规则);',
1602
- '2) 核对/补全 window.REPORT_MODEL 为与正文严格一致的内容(含 mode/style/theme/title/agenda/sections/closing;theme 为 light 或 dark、与页面 data-theme 一致——PPTX 按此导出亮色版或深色版;29 种页型字段与 30 类 chart.type 见 scripts/model-schema.json;research 关键图表页用 type:"exhibit" 并填 exhibitNo/soWhat/footnote);',
1618
+ '2) 核对/补全 window.REPORT_MODEL 为与正文严格一致的内容(含 mode/style/theme/title/agenda/sections/closing;theme 为 light 或 dark、与页面 data-theme 一致——PPTX 按此导出亮色版或深色版;29 种页型字段与 30 类 chart.type 见 scripts/model-schema.json;research 关键图表页用 type:"exhibit" 并填 exhibitNo/soWhat(结论条)/footnote);',
1603
1619
  '3) 运行 python scripts/validate_report.py <报告.html> 直到全 PASS(含模型一致性检查);',
1604
1620
  '4) 智能体精导并质检(0/0 才交付):python scripts/extract_model.py <报告.html> → NODE_PATH=<pptxgenjs 所在 node_modules> node scripts/build_pptx.js <报告.pptx> --model=<报告.model.json>(如需覆盖模型主题可加 --theme=light|dark) → python scripts/validate_pptx.py <报告.pptx> --strict --model=<报告.model.json>。',
1605
1621
  '报告文件:<请填写报告.html 的路径>'
@@ -1867,7 +1883,7 @@ window.REPORT_MODEL = {
1867
1883
  "theme": "light",
1868
1884
  "title": "TopMind × tms-skills",
1869
1885
  "subtitle": "HTML + PPT 双交付 · 为正式商务演示而生",
1870
- "meta": "产品介绍 · 2026-09-26 · v0.1.11",
1886
+ "meta": "产品介绍 · 2026-09-26 · v0.1.15",
1871
1887
  "agenda": [
1872
1888
  [
1873
1889
  "01",
@@ -2392,7 +2408,7 @@ window.REPORT_MODEL = {
2392
2408
 
2393
2409
  /* __TOPPPT_RUNTIME_START__ */
2394
2410
  /* ══ PPTX 导出运行时(assets/pptx-export.js 的内联副本 · 由 scripts/sync_runtime.py 注入,禁止手改) ══ */
2395
- /* __TOPPPT_RUNTIME_SHA__:77ca318e7a510e01 */
2411
+ /* __TOPPPT_RUNTIME_SHA__:f4dc2ab366ea79c4 */
2396
2412
  /* ═══════════════════════════════════════════════════════════════════════════
2397
2413
  * TopPPT HTML· 浏览器端 PPTX 预览运行时
2398
2414
  * 零依赖、随报告单文件分发;OOXML 序列化器(仅供预览,页面不导出文件)。
@@ -2473,7 +2489,7 @@ var PRESETS_DARK = {
2473
2489
  var STYLE_DATA_COLORS = {"business-blue":["1a73e8","3526bb","21a199","b77148","99983d"],"apple-mono":["1d1d1f","0071e3","0f7b6c","c2410c","7c3aed"],"mckinsey":["003a70","2826bb","21a18e","b76848","99903d"],"brand-red":["d0021b","bb6326","d634ae","40a182","438aa8"],"warm-sand":["96681f","839324","cf3b3e","4d88b2","4a47a4"],"deep-teal":["0f6b5c","2683bb","22aa3e","b74870","a85c43"],"graphite-dark":["0369a1","2637bb","1f9977","b75948","a18a40"],"indigo-violet":["5b5bd6","7432ae","4197c8","a08f4b","7ca04b"],"spectrum":["4563ef","5b26bb","269ebb","af8746","83993d"]};
2474
2490
  var STYLE_DATA_COLORS_DARK = {"business-blue":["8ab4f8","7966e0","88e7e5","d4ad91","cbce83"],"apple-mono":["f5f5f7","2997ff","2dd4bf","ff9f0a","bf5af2"],"mckinsey":["7fb2e5","6f6bdb","8ce3d8","d1a694","cbc586"],"brand-red":["ff5a66","e09e66","e788cb","91d4c2","83b4ce"],"warm-sand":["d9b36a","c2d571","df9391","97b5ce","8e89c7"],"deep-teal":["4fc3b0","7aaecd","97d8a4","c99cac","c29c8f"],"graphite-dark":["4da3ff","6c66e0","88e7dc","d4a691","cec983"],"indigo-violet":["a5a4f0","a967e0","89c3e7","d3c792","aece83"],"spectrum":["8ba0f8","9066e0","88d6e7","d4ba91","bdce83"]};
2475
2491
  var GRID = {"columns":12,"gutter":0.16,"colW":0.8644,"x":[0.6,1.6244,2.6488,3.6732,4.6976,5.722,6.7464,7.7708,8.7952,9.8196,10.844,11.8684,12.733],"y":[2.35,3.27,4.19,5.11,6.03,6.9],"safe":{"top":0.4,"bottom":0.4,"left":0.6,"right":0.6}};
2476
- var TYPO = {"levels":[{"id":"C0","name":"封面/章节幕标题","role":"coverTitle","usage":"封面主标题、章节幕标题"},{"id":"T1","name":"页码/章节徽章","role":"caption","usage":"页码徽章、章节编号"},{"id":"T2","name":"页面主标题/结论标题","role":"h1","usage":"每页顶部结论句(research 行动标题)"},{"id":"T3","name":"副标题/语境说明","role":"lead","usage":"主标题下方导语"},{"id":"T4","name":"模块标题/图表标题","role":"h2","usage":"卡片标题、图表标题、面板标题"},{"id":"T5","name":"证据编号/轻量标签","role":"micro","usage":"Exhibit 编号、状态标签"},{"id":"T6","name":"证据块标题/小节标题","role":"h2","usage":"分栏小标题、证据块标题"},{"id":"T7","name":"正文解释段落","role":"body","usage":"证据解释、管理解读正文、表格正文"},{"id":"T8","name":"结论条文字","role":"body","usage":"so-what 结论条、核心结论框"},{"id":"T9","name":"SO WHAT 标签","role":"caption","usage":"so-what 标签行"},{"id":"T10","name":"SO WHAT 正文/业务含义","role":"body","usage":"so-what 正文、行动含义、表格行动项"},{"id":"T11","name":"图表轴/图例/刻度/微标签","role":"micro","usage":"坐标轴、图例、刻度、单位(禁用于表格正文与完整短句)"},{"id":"T12","name":"图表数据标签","role":"caption","usage":"折线点值、柱形标签、百分比标注"},{"id":"T13","name":"关键 KPI 大数字","role":"h1","usage":"KPI 大数字、hero 数值"},{"id":"T14","name":"注释/口径/来源/页脚","role":"micro","usage":"footnote、来源行、页脚、小页码"}],"tableSemanticRule":{"body":["T7","T10"],"microAllowed":["T11"],"microForbiddenFor":["表格正文","行动项","风险项","解释句","建议句","长项目符号","完整短句"]}};
2492
+ var TYPO = {"levels":[{"id":"C0","name":"封面/章节幕标题","role":"coverTitle","usage":"封面主标题、章节幕标题"},{"id":"T1","name":"页码/章节徽章","role":"caption","usage":"页码徽章、章节编号"},{"id":"T2","name":"页面主标题/结论标题","role":"h1","usage":"每页顶部结论句(research 行动标题)"},{"id":"T3","name":"副标题/语境说明","role":"lead","usage":"主标题下方导语"},{"id":"T4","name":"模块标题/图表标题","role":"h2","usage":"卡片标题、图表标题、面板标题"},{"id":"T5","name":"证据编号/轻量标签","role":"micro","usage":"Exhibit 编号、状态标签"},{"id":"T6","name":"证据块标题/小节标题","role":"h2","usage":"分栏小标题、证据块标题"},{"id":"T7","name":"正文解释段落","role":"body","usage":"证据解释、管理解读正文、表格正文"},{"id":"T8","name":"结论条文字","role":"body","usage":"结论条、核心结论框"},{"id":"T9","name":"结论条标签(可选·默认隐藏)","role":"caption","usage":"结论条可选标签(默认不显示)"},{"id":"T10","name":"结论条正文/业务含义","role":"body","usage":"结论条正文、行动含义、表格行动项"},{"id":"T11","name":"图表轴/图例/刻度/微标签","role":"micro","usage":"坐标轴、图例、刻度、单位(禁用于表格正文与完整短句)"},{"id":"T12","name":"图表数据标签","role":"caption","usage":"折线点值、柱形标签、百分比标注"},{"id":"T13","name":"关键 KPI 大数字","role":"h1","usage":"KPI 大数字、hero 数值"},{"id":"T14","name":"注释/口径/来源/页脚","role":"micro","usage":"footnote、来源行、页脚、小页码"}],"tableSemanticRule":{"body":["T7","T10"],"microAllowed":["T11"],"microForbiddenFor":["表格正文","行动项","风险项","解释句","建议句","长项目符号","完整短句"]}};
2477
2493
  var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级(禁静默截断):① 重构承载(列表/卡片/表/图/组合版式)→ ② 拆页/分章(议程→主张→证据卡→明细;01a/01b;信息须完整)→ ③ 换布局形态(V1–V4/多列/卡栅格)→ ④ 有限 fontShrink(阶梯内、模式 floor 以上、最多 4 档)→ ⑤ 禁止:静默截断、砍 so-what/证据/口径、为审美稀疏删决策必需信息。单页字数预算是预警不是删字许可证。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
2478
2494
  var REG = {"bar":{"html":"svg-bars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160}},"hbar":{"html":"svg-hbars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":100}},"stack":{"html":"svg-stack","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160},"nativeOpt":{"barGrouping":"stacked"}},"stackline":{"html":"svg-stackline","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":40},"nativeOpt":{"barGrouping":"percentStacked"}},"line":{"html":"svg-line","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"dualline":{"html":"svg-dualline","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"area":{"html":"svg-area","pptx":"native","nativeType":"area","dataTable":"notes","min":{"vbHeightMin":160}},"donut":{"html":"svg-donut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"multidonut":{"html":"svg-mdonut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"pie":{"html":"svg-pie","pptx":"native","nativeType":"pie","dataTable":"notes","min":{"pxWidthMin":140}},"radar":{"html":"svg-radar","pptx":"native","nativeType":"radar","dataTable":"notes","min":{"pxWidthMin":220}},"scatter":{"html":"svg-scatter","pptx":"native","nativeType":"scatter","dataTable":"notes","min":{"vbHeightMin":180}},"bubble":{"html":"svg-bubble","pptx":"native","nativeType":"bubble","dataTable":"notes","min":{"vbHeightMin":180}},"waterfall":{"html":"svg-wf","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":170},"nativeTrick":"stacked+hiddenBase+connector"},"gauge":{"html":"svg-gauge","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":180},"nativeTrick":"doughnut+firstSliceAng+hiddenRemainder"},"pareto":{"html":"svg-pareto","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":180},"nativeTrick":"multiType+bar+line"},"gantt":{"html":"svg-gantt","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":130},"path":{"forbidPresetShapes":true}},"vsbar":{"html":"svg-vsbar","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"progress":{"html":"svg-progress","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"sparkline":{"html":"svg-spark","pptx":"shape","dataTable":"off","min":{"vbHeightMin":20},"path":{"forbidPresetShapes":true}},"funnel":{"html":"svg-funnel","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"minSamplePoints":8,"forbidPresetShapes":true}},"treemap":{"html":"svg-treemap","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":170},"path":{"forbidPresetShapes":true}},"marimekko":{"html":"svg-marimekko","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"boxplot":{"html":"svg-boxplot","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"network":{"html":"svg-network","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"forbidPresetShapes":true}},"sankey":{"html":"svg-sankey","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"minSamplePoints":16,"trackBothEdges":true,"forbidPresetShapes":true}},"streamgraph":{"html":"svg-stream","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"minSamplePoints":24,"trackBothEdges":true,"forbidPresetShapes":true}},"slope":{"html":"svg-slope","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"dumbbell":{"html":"svg-dumbbell","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"lollipop":{"html":"svg-lollipop","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"dotplot":{"html":"svg-dotplot","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":120},"path":{"forbidPresetShapes":true}},"bulletchart":{"html":"svg-bullet","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"waffle":{"html":"svg-waffle","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"radialbar":{"html":"svg-radialbar","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":200},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"rose":{"html":"svg-rose","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":180},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"candlestick":{"html":"svg-candle","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}}};
2479
2495
  var DEEP = {"triggers":["高保真","1:1","一比一","精确还原","按图还原","正式交付","不能偏移","像素级","严格对照","逐页验收"],"complexCharts":["sankey","streamgraph","treemap","marimekko","boxplot","network","rose","radialbar","candlestick","funnel"],"checks":{"anchors":true,"containerOverflow":true,"renderCompare":true,"manifest":true},"renderCompare":{"engine":"soffice","fallback":"powerpoint-com","skipIfMissing":true,"dpi":96}};
@@ -2724,7 +2740,7 @@ function fitRowH(avail, n, pref, floor) {
2724
2740
  function chartBottom(hasSoWhat, hasFootnote) {
2725
2741
  /* D8: tightest of soWhat/footnote/contentBottomWithNote — no short-circuit */
2726
2742
  var bot = CONTENT_BOTTOM;
2727
- if (hasSoWhat) bot = Math.min(bot, PT.exhibit.soWhatY - 0.12);
2743
+ if (hasSoWhat) bot = Math.min(bot, PT.exhibit.soWhatY - 0.20);
2728
2744
  if (hasFootnote) bot = Math.min(bot, PT.exhibit.footnoteY - 0.12);
2729
2745
  if (hasSoWhat || hasFootnote) bot = Math.min(bot, CONTENT_BOTTOM_NOTE);
2730
2746
  return bot;
@@ -2808,24 +2824,31 @@ function donutWedges(labels, values) {
2808
2824
  });
2809
2825
  return segs;
2810
2826
  }
2811
- function donutChart(sh, ec, S, dcols) {
2827
+ function donutChart(sh, ec, S, dcols, bottomY) {
2812
2828
  var d = PT.donut, labels = ec.labels || [], values = ec.values || [];
2813
2829
  var segs = donutWedges(labels, values);
2814
- var bx = d.centerX - d.r, by = d.centerY - d.r, bw = d.r * 2;
2830
+ var r = d.r;
2831
+ if (bottomY != null && d.centerY + r > bottomY) {
2832
+ r = Math.max(0.9, bottomY - d.centerY - 0.04);
2833
+ }
2834
+ var holeR = d.holeR * (r / d.r);
2835
+ var bx = d.centerX - r, by = d.centerY - r, bw = r * 2;
2815
2836
  segs.forEach(function (sg) {
2816
2837
  sh.push(shape('pie', bx, by, bw, bw, dcols[sg[2] % dcols.length], { av: pieAv(sg[0], sg[1]) }));
2817
2838
  });
2818
- var hb = d.holeR * 2;
2819
- sh.push(shape('ellipse', d.centerX - d.holeR, d.centerY - d.holeR, hb, hb, S.bg));
2839
+ var hb = holeR * 2;
2840
+ sh.push(shape('ellipse', d.centerX - holeR, d.centerY - holeR, hb, hb, S.bg));
2820
2841
  var total = 0; values.forEach(function (v) { total += Math.max(0, v); });
2821
2842
  var totalStr = (Math.round(total * 10) / 10) + (ec.unit || '');
2822
- sh.push(txSp(d.centerX - d.holeR, d.centerY - 0.42, hb, 0.5,
2843
+ sh.push(txSp(d.centerX - holeR, d.centerY - 0.42, hb, 0.5,
2823
2844
  [[{ t: totalStr, sz: 20, b: 1, col: S.ink, font: S.fontDisplay }]], { align: 'ctr', anchor: 'ctr' }));
2824
- sh.push(txSp(d.centerX - d.holeR, d.centerY + 0.08, hb, 0.35,
2845
+ sh.push(txSp(d.centerX - holeR, d.centerY + 0.08, hb, 0.35,
2825
2846
  [[{ t: ec.centerLabel || '合计', sz: 9.5, col: S.faint, font: S.font }]], { align: 'ctr', anchor: 'ctr' }));
2826
2847
  var n = Math.max(1, labels.length);
2827
- var rowH = Math.min(d.legendRowH, 3.4 / n);
2848
+ var maxLegH = (bottomY != null) ? Math.max(1.2, bottomY - (d.centerY - 1.7)) : 3.4;
2849
+ var rowH = Math.min(d.legendRowH, maxLegH / n, 3.4 / n);
2828
2850
  var ly0 = d.centerY - (n * rowH) / 2 + 0.1;
2851
+ if (bottomY != null) ly0 = Math.min(ly0, bottomY - n * rowH - 0.04);
2829
2852
  var sum2 = total || 1;
2830
2853
  labels.forEach(function (lb, i) {
2831
2854
  var v = values[i] || 0;
@@ -2882,14 +2905,13 @@ function table(x, y, w, colW, rows, S, opts) {
2882
2905
  function soWhatBar(sh, text, S) {
2883
2906
  var R = (typeof regionOf === 'function') ? regionOf('exhibit', 'annotation')
2884
2907
  : { x: MX, y: PT.exhibit.soWhatY, w: CW, h: 0.62 };
2885
- /* 与 B 通道同算法:长结论条有限缩字号,优先保容器不溢出 */
2886
- var bodyW = Math.max(2.5, R.w - 0.44 - 1.35);
2887
- var fzB = fitFont([String(text || '')], bodyW, R.h - 0.14, { max: 12.5, gapFactor: 0.2, maxShrinkSteps: 3 });
2908
+ /* MD3 结论条:衬底 + 左 accent 轨 + 正文(不绘制「SO WHAT」标签字样) */
2909
+ var bodyW = Math.max(2.5, R.w - 0.44);
2910
+ var fzB = fitFont([String(text || '')], bodyW, R.h - 0.14, { max: 14, gapFactor: 0.2, maxShrinkSteps: 3 });
2888
2911
  sh.push(shape('rect', R.x, R.y, R.w, R.h, S.soft));
2889
2912
  sh.push(shape('rect', R.x, R.y, 0.06, R.h, S.accent));
2890
2913
  sh.push(txSp(R.x + 0.22, R.y + 0.06, R.w - 0.44, R.h - 0.12,
2891
- [[{ t: 'SO WHAT ', sz: 11, b: 1, col: S.accent, font: S.font, spc: 150 },
2892
- { t: text, sz: fzB, col: S.ink, font: S.font }]], { anchor: 'ctr' }));
2914
+ [[{ t: String(text || ''), sz: fzB, b: 1, col: S.ink, font: S.font }]], { anchor: 'ctr' }));
2893
2915
  }
2894
2916
  function footnoteLine(sh, text, S) {
2895
2917
  var R = (typeof regionOf === 'function') ? regionOf('exhibit', 'footnote')
@@ -3749,7 +3771,7 @@ function slidesOf(model, S) {
3749
3771
  if (img.caption) sh.push(txSp(MX, capYImg + 0.04, CW, capH2, [[{ t: img.caption, sz: 10.5, col: S.faint, font: S.font }]]));
3750
3772
  } else if (type === 'donut') {
3751
3773
  var dcn = sec.chart || {};
3752
- if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme));
3774
+ if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme), bodyBottom);
3753
3775
  if (sec.note) sh.push(txSp(MX, PT.note.y, CW, PT.note.h, [[{ t: sec.note, sz: 11, col: S.faint, font: S.font }]]));
3754
3776
  } else if (type === 'heatmap') {
3755
3777
  var H = PT.heatmap;
@@ -3902,10 +3924,27 @@ function slidesOf(model, S) {
3902
3924
  var bRR = regOf('bar', isHBar ? 'hbar' : 'primary', { bottom: botY }) ||
3903
3925
  { x: isHBar ? MX : MX + PT.bar.chartX, y: isHBar ? PT.bar.hbarY0 : PT.bar.chartY,
3904
3926
  w: isHBar ? CW : CW - PT.bar.chartW, h: 3 };
3927
+ var ptsB = (sec.points || []).filter(Boolean);
3928
+ var bx = bRR.x, bw = bRR.w;
3929
+ if (ptsB.length && !isHBar) {
3930
+ var sideW = Math.min(3.6, Math.max(2.6, bRR.w * 0.30));
3931
+ bw = Math.max(3.2, bRR.w - sideW - 0.28);
3932
+ var sx = bRR.x + bw + 0.28;
3933
+ var rowHb = Math.min(0.72, (bRR.h - 0.1) / Math.max(1, ptsB.length));
3934
+ ptsB.slice(0, 6).forEach(function (p, i) {
3935
+ var k = Array.isArray(p) ? String(p[0] || '') : String((p && p.t) || '');
3936
+ var v = Array.isArray(p) ? String(p[1] || '') : String((p && p.d) || '');
3937
+ var y = bRR.y + i * rowHb;
3938
+ sh.push(shape('rect', sx, y + 0.12, 0.08, 0.08, S.accent));
3939
+ sh.push(txSp(sx + 0.2, y, sideW - 0.25, rowHb,
3940
+ [[{ t: k + (v ? ' ' : ''), sz: 12, b: 1, col: S.ink, font: S.font },
3941
+ { t: v, sz: 11, col: S.body, font: S.font }]], { anchor: 'ctr' }));
3942
+ });
3943
+ }
3905
3944
  if (isHBar) {
3906
- chartBlockShapes(sh, ch, S, bRR.x, bRR.y, bRR.w, bRR.h, dcols2);
3945
+ chartBlockShapes(sh, ch, S, bx, bRR.y, bw, bRR.h, dcols2);
3907
3946
  } else {
3908
- chartBlockShapes(sh, ch, S, bRR.x, bRR.y, bRR.w, Math.max(1.5, bRR.h), dcols2);
3947
+ chartBlockShapes(sh, ch, S, bx, bRR.y, bw, Math.max(1.5, bRR.h), dcols2);
3909
3948
  }
3910
3949
  if (sec.note) sh.push(txSp(MX, PT.note.y, CW, PT.note.h, [[{ t: sec.note, sz: 11, col: S.faint, font: S.font }]]));
3911
3950
  } else if (type === 'twocol' || type === 'threecol') {
@@ -4,7 +4,7 @@
4
4
  "theme": "light",
5
5
  "title": "TopMind × tms-skills",
6
6
  "subtitle": "HTML + PPT 双交付 · 为正式商务演示而生",
7
- "meta": "产品介绍 · 2026-09-26 · v0.1.11",
7
+ "meta": "产品介绍 · 2026-09-26 · v0.1.15",
8
8
  "agenda": [
9
9
  [
10
10
  "01",
@@ -78,7 +78,7 @@ var PRESETS_DARK = {
78
78
  var STYLE_DATA_COLORS = {"business-blue":["1a73e8","3526bb","21a199","b77148","99983d"],"apple-mono":["1d1d1f","0071e3","0f7b6c","c2410c","7c3aed"],"mckinsey":["003a70","2826bb","21a18e","b76848","99903d"],"brand-red":["d0021b","bb6326","d634ae","40a182","438aa8"],"warm-sand":["96681f","839324","cf3b3e","4d88b2","4a47a4"],"deep-teal":["0f6b5c","2683bb","22aa3e","b74870","a85c43"],"graphite-dark":["0369a1","2637bb","1f9977","b75948","a18a40"],"indigo-violet":["5b5bd6","7432ae","4197c8","a08f4b","7ca04b"],"spectrum":["4563ef","5b26bb","269ebb","af8746","83993d"]};
79
79
  var STYLE_DATA_COLORS_DARK = {"business-blue":["8ab4f8","7966e0","88e7e5","d4ad91","cbce83"],"apple-mono":["f5f5f7","2997ff","2dd4bf","ff9f0a","bf5af2"],"mckinsey":["7fb2e5","6f6bdb","8ce3d8","d1a694","cbc586"],"brand-red":["ff5a66","e09e66","e788cb","91d4c2","83b4ce"],"warm-sand":["d9b36a","c2d571","df9391","97b5ce","8e89c7"],"deep-teal":["4fc3b0","7aaecd","97d8a4","c99cac","c29c8f"],"graphite-dark":["4da3ff","6c66e0","88e7dc","d4a691","cec983"],"indigo-violet":["a5a4f0","a967e0","89c3e7","d3c792","aece83"],"spectrum":["8ba0f8","9066e0","88d6e7","d4ba91","bdce83"]};
80
80
  var GRID = {"columns":12,"gutter":0.16,"colW":0.8644,"x":[0.6,1.6244,2.6488,3.6732,4.6976,5.722,6.7464,7.7708,8.7952,9.8196,10.844,11.8684,12.733],"y":[2.35,3.27,4.19,5.11,6.03,6.9],"safe":{"top":0.4,"bottom":0.4,"left":0.6,"right":0.6}};
81
- var TYPO = {"levels":[{"id":"C0","name":"封面/章节幕标题","role":"coverTitle","usage":"封面主标题、章节幕标题"},{"id":"T1","name":"页码/章节徽章","role":"caption","usage":"页码徽章、章节编号"},{"id":"T2","name":"页面主标题/结论标题","role":"h1","usage":"每页顶部结论句(research 行动标题)"},{"id":"T3","name":"副标题/语境说明","role":"lead","usage":"主标题下方导语"},{"id":"T4","name":"模块标题/图表标题","role":"h2","usage":"卡片标题、图表标题、面板标题"},{"id":"T5","name":"证据编号/轻量标签","role":"micro","usage":"Exhibit 编号、状态标签"},{"id":"T6","name":"证据块标题/小节标题","role":"h2","usage":"分栏小标题、证据块标题"},{"id":"T7","name":"正文解释段落","role":"body","usage":"证据解释、管理解读正文、表格正文"},{"id":"T8","name":"结论条文字","role":"body","usage":"so-what 结论条、核心结论框"},{"id":"T9","name":"SO WHAT 标签","role":"caption","usage":"so-what 标签行"},{"id":"T10","name":"SO WHAT 正文/业务含义","role":"body","usage":"so-what 正文、行动含义、表格行动项"},{"id":"T11","name":"图表轴/图例/刻度/微标签","role":"micro","usage":"坐标轴、图例、刻度、单位(禁用于表格正文与完整短句)"},{"id":"T12","name":"图表数据标签","role":"caption","usage":"折线点值、柱形标签、百分比标注"},{"id":"T13","name":"关键 KPI 大数字","role":"h1","usage":"KPI 大数字、hero 数值"},{"id":"T14","name":"注释/口径/来源/页脚","role":"micro","usage":"footnote、来源行、页脚、小页码"}],"tableSemanticRule":{"body":["T7","T10"],"microAllowed":["T11"],"microForbiddenFor":["表格正文","行动项","风险项","解释句","建议句","长项目符号","完整短句"]}};
81
+ var TYPO = {"levels":[{"id":"C0","name":"封面/章节幕标题","role":"coverTitle","usage":"封面主标题、章节幕标题"},{"id":"T1","name":"页码/章节徽章","role":"caption","usage":"页码徽章、章节编号"},{"id":"T2","name":"页面主标题/结论标题","role":"h1","usage":"每页顶部结论句(research 行动标题)"},{"id":"T3","name":"副标题/语境说明","role":"lead","usage":"主标题下方导语"},{"id":"T4","name":"模块标题/图表标题","role":"h2","usage":"卡片标题、图表标题、面板标题"},{"id":"T5","name":"证据编号/轻量标签","role":"micro","usage":"Exhibit 编号、状态标签"},{"id":"T6","name":"证据块标题/小节标题","role":"h2","usage":"分栏小标题、证据块标题"},{"id":"T7","name":"正文解释段落","role":"body","usage":"证据解释、管理解读正文、表格正文"},{"id":"T8","name":"结论条文字","role":"body","usage":"结论条、核心结论框"},{"id":"T9","name":"结论条标签(可选·默认隐藏)","role":"caption","usage":"结论条可选标签(默认不显示)"},{"id":"T10","name":"结论条正文/业务含义","role":"body","usage":"结论条正文、行动含义、表格行动项"},{"id":"T11","name":"图表轴/图例/刻度/微标签","role":"micro","usage":"坐标轴、图例、刻度、单位(禁用于表格正文与完整短句)"},{"id":"T12","name":"图表数据标签","role":"caption","usage":"折线点值、柱形标签、百分比标注"},{"id":"T13","name":"关键 KPI 大数字","role":"h1","usage":"KPI 大数字、hero 数值"},{"id":"T14","name":"注释/口径/来源/页脚","role":"micro","usage":"footnote、来源行、页脚、小页码"}],"tableSemanticRule":{"body":["T7","T10"],"microAllowed":["T11"],"microForbiddenFor":["表格正文","行动项","风险项","解释句","建议句","长项目符号","完整短句"]}};
82
82
  var CONT = {"pad":{"card":0.18,"panel":0.2,"cell":0.08,"band":0.16,"soWhat":0.16,"kpi":0.18,"chart":0.1,"head":0.05,"footer":0.05,"node":0.06},"minPad":0.06,"textMetrics":{"lineFactor":1.45,"emAsciiRatio":0.52},"overflowRule":"溢出处置优先级(禁静默截断):① 重构承载(列表/卡片/表/图/组合版式)→ ② 拆页/分章(议程→主张→证据卡→明细;01a/01b;信息须完整)→ ③ 换布局形态(V1–V4/多列/卡栅格)→ ④ 有限 fontShrink(阶梯内、模式 floor 以上、最多 4 档)→ ⑤ 禁止:静默截断、砍 so-what/证据/口径、为审美稀疏删决策必需信息。单页字数预算是预警不是删字许可证。","fontShrink":{"ladder":[15,14,13.5,13,12.5,12,11.5,11,10.5,10,9.5,9,8.5],"maxShrinkSteps":4,"floorPt":{"presentation":10,"research":9,"architecture":10},"preferContentFirst":true,"warnBelow":9.5},"continuousTextRule":"语义连续的一句话 / so-what 主句 / 结论句 / 表格单元格正文不得拆成多个独立文本框(避免异常空格、断句、基线漂移);局部加粗高亮必须用同一文本框内富文本。"};
83
83
  var REG = {"bar":{"html":"svg-bars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160}},"hbar":{"html":"svg-hbars","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":100}},"stack":{"html":"svg-stack","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":160},"nativeOpt":{"barGrouping":"stacked"}},"stackline":{"html":"svg-stackline","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":40},"nativeOpt":{"barGrouping":"percentStacked"}},"line":{"html":"svg-line","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"dualline":{"html":"svg-dualline","pptx":"native","nativeType":"line","dataTable":"notes","min":{"vbHeightMin":160}},"area":{"html":"svg-area","pptx":"native","nativeType":"area","dataTable":"notes","min":{"vbHeightMin":160}},"donut":{"html":"svg-donut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"multidonut":{"html":"svg-mdonut","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":140}},"pie":{"html":"svg-pie","pptx":"native","nativeType":"pie","dataTable":"notes","min":{"pxWidthMin":140}},"radar":{"html":"svg-radar","pptx":"native","nativeType":"radar","dataTable":"notes","min":{"pxWidthMin":220}},"scatter":{"html":"svg-scatter","pptx":"native","nativeType":"scatter","dataTable":"notes","min":{"vbHeightMin":180}},"bubble":{"html":"svg-bubble","pptx":"native","nativeType":"bubble","dataTable":"notes","min":{"vbHeightMin":180}},"waterfall":{"html":"svg-wf","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":170},"nativeTrick":"stacked+hiddenBase+connector"},"gauge":{"html":"svg-gauge","pptx":"native","nativeType":"doughnut","dataTable":"notes","min":{"pxWidthMin":180},"nativeTrick":"doughnut+firstSliceAng+hiddenRemainder"},"pareto":{"html":"svg-pareto","pptx":"native","nativeType":"bar","dataTable":"notes","min":{"vbHeightMin":180},"nativeTrick":"multiType+bar+line"},"gantt":{"html":"svg-gantt","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":130},"path":{"forbidPresetShapes":true}},"vsbar":{"html":"svg-vsbar","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"progress":{"html":"svg-progress","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":100},"path":{"forbidPresetShapes":true}},"sparkline":{"html":"svg-spark","pptx":"shape","dataTable":"off","min":{"vbHeightMin":20},"path":{"forbidPresetShapes":true}},"funnel":{"html":"svg-funnel","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"minSamplePoints":8,"forbidPresetShapes":true}},"treemap":{"html":"svg-treemap","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":170},"path":{"forbidPresetShapes":true}},"marimekko":{"html":"svg-marimekko","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"boxplot":{"html":"svg-boxplot","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"network":{"html":"svg-network","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"forbidPresetShapes":true}},"sankey":{"html":"svg-sankey","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":200},"path":{"minSamplePoints":16,"trackBothEdges":true,"forbidPresetShapes":true}},"streamgraph":{"html":"svg-stream","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":160},"path":{"minSamplePoints":24,"trackBothEdges":true,"forbidPresetShapes":true}},"slope":{"html":"svg-slope","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}},"dumbbell":{"html":"svg-dumbbell","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"lollipop":{"html":"svg-lollipop","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"dotplot":{"html":"svg-dotplot","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":120},"path":{"forbidPresetShapes":true}},"bulletchart":{"html":"svg-bullet","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":140},"path":{"forbidPresetShapes":true}},"waffle":{"html":"svg-waffle","pptx":"shape","dataTable":"notes","min":{"vbHeightMin":160},"path":{"forbidPresetShapes":true}},"radialbar":{"html":"svg-radialbar","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":200},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"rose":{"html":"svg-rose","pptx":"shape","dataTable":"notes","min":{"pxWidthMin":180},"path":{"minSamplePoints":16,"forbidPresetShapes":true}},"candlestick":{"html":"svg-candle","pptx":"shape","dataTable":"appendix","min":{"vbHeightMin":180},"path":{"forbidPresetShapes":true}}};
84
84
  var DEEP = {"triggers":["高保真","1:1","一比一","精确还原","按图还原","正式交付","不能偏移","像素级","严格对照","逐页验收"],"complexCharts":["sankey","streamgraph","treemap","marimekko","boxplot","network","rose","radialbar","candlestick","funnel"],"checks":{"anchors":true,"containerOverflow":true,"renderCompare":true,"manifest":true},"renderCompare":{"engine":"soffice","fallback":"powerpoint-com","skipIfMissing":true,"dpi":96}};
@@ -329,7 +329,7 @@ function fitRowH(avail, n, pref, floor) {
329
329
  function chartBottom(hasSoWhat, hasFootnote) {
330
330
  /* D8: tightest of soWhat/footnote/contentBottomWithNote — no short-circuit */
331
331
  var bot = CONTENT_BOTTOM;
332
- if (hasSoWhat) bot = Math.min(bot, PT.exhibit.soWhatY - 0.12);
332
+ if (hasSoWhat) bot = Math.min(bot, PT.exhibit.soWhatY - 0.20);
333
333
  if (hasFootnote) bot = Math.min(bot, PT.exhibit.footnoteY - 0.12);
334
334
  if (hasSoWhat || hasFootnote) bot = Math.min(bot, CONTENT_BOTTOM_NOTE);
335
335
  return bot;
@@ -413,24 +413,31 @@ function donutWedges(labels, values) {
413
413
  });
414
414
  return segs;
415
415
  }
416
- function donutChart(sh, ec, S, dcols) {
416
+ function donutChart(sh, ec, S, dcols, bottomY) {
417
417
  var d = PT.donut, labels = ec.labels || [], values = ec.values || [];
418
418
  var segs = donutWedges(labels, values);
419
- var bx = d.centerX - d.r, by = d.centerY - d.r, bw = d.r * 2;
419
+ var r = d.r;
420
+ if (bottomY != null && d.centerY + r > bottomY) {
421
+ r = Math.max(0.9, bottomY - d.centerY - 0.04);
422
+ }
423
+ var holeR = d.holeR * (r / d.r);
424
+ var bx = d.centerX - r, by = d.centerY - r, bw = r * 2;
420
425
  segs.forEach(function (sg) {
421
426
  sh.push(shape('pie', bx, by, bw, bw, dcols[sg[2] % dcols.length], { av: pieAv(sg[0], sg[1]) }));
422
427
  });
423
- var hb = d.holeR * 2;
424
- sh.push(shape('ellipse', d.centerX - d.holeR, d.centerY - d.holeR, hb, hb, S.bg));
428
+ var hb = holeR * 2;
429
+ sh.push(shape('ellipse', d.centerX - holeR, d.centerY - holeR, hb, hb, S.bg));
425
430
  var total = 0; values.forEach(function (v) { total += Math.max(0, v); });
426
431
  var totalStr = (Math.round(total * 10) / 10) + (ec.unit || '');
427
- sh.push(txSp(d.centerX - d.holeR, d.centerY - 0.42, hb, 0.5,
432
+ sh.push(txSp(d.centerX - holeR, d.centerY - 0.42, hb, 0.5,
428
433
  [[{ t: totalStr, sz: 20, b: 1, col: S.ink, font: S.fontDisplay }]], { align: 'ctr', anchor: 'ctr' }));
429
- sh.push(txSp(d.centerX - d.holeR, d.centerY + 0.08, hb, 0.35,
434
+ sh.push(txSp(d.centerX - holeR, d.centerY + 0.08, hb, 0.35,
430
435
  [[{ t: ec.centerLabel || '合计', sz: 9.5, col: S.faint, font: S.font }]], { align: 'ctr', anchor: 'ctr' }));
431
436
  var n = Math.max(1, labels.length);
432
- var rowH = Math.min(d.legendRowH, 3.4 / n);
437
+ var maxLegH = (bottomY != null) ? Math.max(1.2, bottomY - (d.centerY - 1.7)) : 3.4;
438
+ var rowH = Math.min(d.legendRowH, maxLegH / n, 3.4 / n);
433
439
  var ly0 = d.centerY - (n * rowH) / 2 + 0.1;
440
+ if (bottomY != null) ly0 = Math.min(ly0, bottomY - n * rowH - 0.04);
434
441
  var sum2 = total || 1;
435
442
  labels.forEach(function (lb, i) {
436
443
  var v = values[i] || 0;
@@ -487,14 +494,13 @@ function table(x, y, w, colW, rows, S, opts) {
487
494
  function soWhatBar(sh, text, S) {
488
495
  var R = (typeof regionOf === 'function') ? regionOf('exhibit', 'annotation')
489
496
  : { x: MX, y: PT.exhibit.soWhatY, w: CW, h: 0.62 };
490
- /* 与 B 通道同算法:长结论条有限缩字号,优先保容器不溢出 */
491
- var bodyW = Math.max(2.5, R.w - 0.44 - 1.35);
492
- var fzB = fitFont([String(text || '')], bodyW, R.h - 0.14, { max: 12.5, gapFactor: 0.2, maxShrinkSteps: 3 });
497
+ /* MD3 结论条:衬底 + 左 accent 轨 + 正文(不绘制「SO WHAT」标签字样) */
498
+ var bodyW = Math.max(2.5, R.w - 0.44);
499
+ var fzB = fitFont([String(text || '')], bodyW, R.h - 0.14, { max: 14, gapFactor: 0.2, maxShrinkSteps: 3 });
493
500
  sh.push(shape('rect', R.x, R.y, R.w, R.h, S.soft));
494
501
  sh.push(shape('rect', R.x, R.y, 0.06, R.h, S.accent));
495
502
  sh.push(txSp(R.x + 0.22, R.y + 0.06, R.w - 0.44, R.h - 0.12,
496
- [[{ t: 'SO WHAT ', sz: 11, b: 1, col: S.accent, font: S.font, spc: 150 },
497
- { t: text, sz: fzB, col: S.ink, font: S.font }]], { anchor: 'ctr' }));
503
+ [[{ t: String(text || ''), sz: fzB, b: 1, col: S.ink, font: S.font }]], { anchor: 'ctr' }));
498
504
  }
499
505
  function footnoteLine(sh, text, S) {
500
506
  var R = (typeof regionOf === 'function') ? regionOf('exhibit', 'footnote')
@@ -1354,7 +1360,7 @@ function slidesOf(model, S) {
1354
1360
  if (img.caption) sh.push(txSp(MX, capYImg + 0.04, CW, capH2, [[{ t: img.caption, sz: 10.5, col: S.faint, font: S.font }]]));
1355
1361
  } else if (type === 'donut') {
1356
1362
  var dcn = sec.chart || {};
1357
- if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme));
1363
+ if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme), bodyBottom);
1358
1364
  if (sec.note) sh.push(txSp(MX, PT.note.y, CW, PT.note.h, [[{ t: sec.note, sz: 11, col: S.faint, font: S.font }]]));
1359
1365
  } else if (type === 'heatmap') {
1360
1366
  var H = PT.heatmap;
@@ -1507,10 +1513,27 @@ function slidesOf(model, S) {
1507
1513
  var bRR = regOf('bar', isHBar ? 'hbar' : 'primary', { bottom: botY }) ||
1508
1514
  { x: isHBar ? MX : MX + PT.bar.chartX, y: isHBar ? PT.bar.hbarY0 : PT.bar.chartY,
1509
1515
  w: isHBar ? CW : CW - PT.bar.chartW, h: 3 };
1516
+ var ptsB = (sec.points || []).filter(Boolean);
1517
+ var bx = bRR.x, bw = bRR.w;
1518
+ if (ptsB.length && !isHBar) {
1519
+ var sideW = Math.min(3.6, Math.max(2.6, bRR.w * 0.30));
1520
+ bw = Math.max(3.2, bRR.w - sideW - 0.28);
1521
+ var sx = bRR.x + bw + 0.28;
1522
+ var rowHb = Math.min(0.72, (bRR.h - 0.1) / Math.max(1, ptsB.length));
1523
+ ptsB.slice(0, 6).forEach(function (p, i) {
1524
+ var k = Array.isArray(p) ? String(p[0] || '') : String((p && p.t) || '');
1525
+ var v = Array.isArray(p) ? String(p[1] || '') : String((p && p.d) || '');
1526
+ var y = bRR.y + i * rowHb;
1527
+ sh.push(shape('rect', sx, y + 0.12, 0.08, 0.08, S.accent));
1528
+ sh.push(txSp(sx + 0.2, y, sideW - 0.25, rowHb,
1529
+ [[{ t: k + (v ? ' ' : ''), sz: 12, b: 1, col: S.ink, font: S.font },
1530
+ { t: v, sz: 11, col: S.body, font: S.font }]], { anchor: 'ctr' }));
1531
+ });
1532
+ }
1510
1533
  if (isHBar) {
1511
- chartBlockShapes(sh, ch, S, bRR.x, bRR.y, bRR.w, bRR.h, dcols2);
1534
+ chartBlockShapes(sh, ch, S, bx, bRR.y, bw, bRR.h, dcols2);
1512
1535
  } else {
1513
- chartBlockShapes(sh, ch, S, bRR.x, bRR.y, bRR.w, Math.max(1.5, bRR.h), dcols2);
1536
+ chartBlockShapes(sh, ch, S, bx, bRR.y, bw, Math.max(1.5, bRR.h), dcols2);
1514
1537
  }
1515
1538
  if (sec.note) sh.push(txSp(MX, PT.note.y, CW, PT.note.h, [[{ t: sec.note, sz: 11, col: S.faint, font: S.font }]]));
1516
1539
  } else if (type === 'twocol' || type === 'threecol') {