@topmindspace/tms-skills 0.1.17 → 0.1.19

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 (49) hide show
  1. package/CHANGELOG.md +84 -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 +4 -4
  8. package/top-ppt-html/assets/examples/2026-09-09-architecture-graphite-dark.html +144 -58
  9. package/top-ppt-html/assets/examples/2026-09-09-presentation-business-blue.html +144 -58
  10. package/top-ppt-html/assets/examples/2026-09-09-research-mckinsey.html +144 -58
  11. package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.html +214 -211
  12. package/top-ppt-html/assets/examples/2026-09-26-topmind-tms-skills-showcase.model.json +33 -39
  13. package/top-ppt-html/assets/pptx-export.js +120 -46
  14. package/top-ppt-html/assets/style-gallery.html +21 -4
  15. package/top-ppt-html/assets/templates/architecture.html +158 -61
  16. package/top-ppt-html/assets/templates/engine.css +23 -11
  17. package/top-ppt-html/assets/templates/presentation.html +158 -63
  18. package/top-ppt-html/assets/templates/research.html +164 -69
  19. package/top-ppt-html/package-lock.json +2 -2
  20. package/top-ppt-html/package.json +1 -1
  21. package/top-ppt-html/references/chart-decision-tree.md +26 -25
  22. package/top-ppt-html/references/components-atoms.md +5 -4
  23. package/top-ppt-html/references/content-rules.md +17 -9
  24. package/top-ppt-html/references/failure-modes.md +31 -3
  25. package/top-ppt-html/references/high-fidelity.md +14 -1
  26. package/top-ppt-html/references/icons.md +2 -2
  27. package/top-ppt-html/references/layout-grammar.md +3 -1
  28. package/top-ppt-html/references/layouts-combo.md +1 -1
  29. package/top-ppt-html/references/layouts-research.md +1 -1
  30. package/top-ppt-html/references/modes.md +1 -1
  31. package/top-ppt-html/references/page-type-matrix.md +10 -6
  32. package/top-ppt-html/references/pptx-export.md +5 -5
  33. package/top-ppt-html/references/tech-design.md +2 -0
  34. package/top-ppt-html/scripts/build_icon_assets.js +92 -0
  35. package/top-ppt-html/scripts/build_pptx.js +226 -71
  36. package/top-ppt-html/scripts/cross_verify.py +84 -1
  37. package/top-ppt-html/scripts/extract_model.py +26 -1
  38. package/top-ppt-html/scripts/icon_lib.js +53 -0
  39. package/top-ppt-html/scripts/icon_raster.js +86 -0
  40. package/top-ppt-html/scripts/layout-constants.json +45 -2
  41. package/top-ppt-html/scripts/lib_layout_regions.js +9 -4
  42. package/top-ppt-html/scripts/model-schema.json +8 -3
  43. package/top-ppt-html/scripts/package_skill.py +1 -0
  44. package/top-ppt-html/scripts/render_from_model.py +254 -37
  45. package/top-ppt-html/scripts/scaffold_report.py +47 -24
  46. package/top-ppt-html/scripts/sync_runtime.py +21 -4
  47. package/top-ppt-html/scripts/test_feedback_gates.py +73 -0
  48. package/top-ppt-html/scripts/validate_pptx.py +162 -3
  49. package/top-ppt-html/scripts/validate_report.py +24 -0
@@ -330,7 +330,13 @@ border-color:color-mix(in srgb,var(--accent-on) 20%,transparent);color:var(--acc
330
330
  rows-2 / rows-3:等高行分区(纵向节奏,替代等高卡片堆叠) */
331
331
  .g-211{grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr)}
332
332
  .g-121{grid-template-columns:minmax(0,1fr) minmax(0,2fr) minmax(0,1fr)}
333
- .g-quad{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(0,1fr);align-items:stretch}
333
+ .g-quad{grid-template-columns:repeat(2,minmax(0,1fr));grid-auto-rows:minmax(min-content,1fr);align-items:stretch}
334
+ .g-half{grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);align-items:stretch}
335
+ @media (max-width:1180px){.g-half{grid-template-columns:1fr}}
336
+ .g-2--equal,.g-3--equal,.g-4--equal{grid-auto-rows:minmax(min-content,1fr);align-items:stretch}
337
+ .grid.g-2>.card,.grid.g-3>.card,.grid.g-4>.card,
338
+ .grid.g-quad>.card,.grid.g-half>.card,.grid.g-2--equal>.card,
339
+ .grid.g-3--equal>.card,.grid.g-4--equal>.card{align-self:stretch}
334
340
  .g-aside{grid-template-columns:minmax(0,1fr) minmax(200px,.36fr);align-items:start}
335
341
  .g-aside__side{position:sticky;top:calc(var(--bar-h) + 16px)}
336
342
  .g-mosaic{grid-template-columns:repeat(3,minmax(0,1fr));
@@ -346,7 +352,7 @@ grid-template-areas:"main main main" "s1 s2 s3"}
346
352
  .kv--2col{grid-template-columns:auto minmax(0,1fr) auto minmax(0,1fr)}
347
353
  /* ── 拼贴栅格 g-bento(Bento / 马赛克):4 列基准 + 跨列/跨行工具类 ──
348
354
  .sp-2/.sp-3/.sp-4 跨列(span),.rw-2 跨行;窄屏自动降列并收敛 span。 */
349
- .g-bento{grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:minmax(118px,auto)}
355
+ .g-bento{grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:minmax(min-content,1fr)}
350
356
  .sp-2{grid-column:span 2}.sp-3{grid-column:span 3}.sp-4{grid-column:span 4}
351
357
  .rw-2{grid-row:span 2}
352
358
  @media (max-width:1180px){.g-bento{grid-template-columns:repeat(2,minmax(0,1fr))}
@@ -381,19 +387,21 @@ background:color-mix(in srgb,var(--bg) 86%,transparent);
381
387
  backdrop-filter:saturate(160%) blur(14px);-webkit-backdrop-filter:saturate(160%) blur(14px);
382
388
  border-bottom:1px solid var(--border-soft);
383
389
  transition:height var(--dur-medium) var(--ease-standard)}
384
- .bar__in{height:100%;display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4)}
385
- .brand{display:flex;align-items:center;gap:var(--sp-3);min-width:0}
390
+ .bar__in{height:100%;display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);overflow:hidden}
391
+ .brand{display:flex;align-items:center;gap:var(--sp-3);min-width:0;flex:1 1 auto;overflow:hidden}
386
392
  .brand__mark{width:34px;height:34px;flex:none;border-radius:10px;background:var(--accent);
387
393
  color:var(--accent-on);display:grid;place-items:center;font-size:13px;font-weight:700}
394
+ .brand__txt{min-width:0;overflow:hidden;flex:1 1 auto}
388
395
  .brand__title{font-size:var(--fs-sm);font-weight:600;color:var(--text);white-space:nowrap;
389
- overflow:hidden;text-overflow:ellipsis}
396
+ overflow:hidden;text-overflow:ellipsis;max-width:100%}
390
397
  .brand__sub{font-size:var(--fs-xs);color:var(--text-3);white-space:nowrap;overflow:hidden;
391
- text-overflow:ellipsis}
392
- .nav{display:flex;align-items:center;gap:var(--sp-1)}
398
+ text-overflow:ellipsis;max-width:100%}
399
+ .nav{display:flex;align-items:center;gap:var(--sp-1);flex:0 1 auto;min-width:0;overflow:hidden}
393
400
  .nav a{padding:8px 14px;border-radius:var(--r-full);color:var(--text-2);text-decoration:none;
394
401
  font-size:var(--fs-sm);font-weight:500;white-space:nowrap;transition:background-color var(--dur-short),color var(--dur-short)}
395
402
  .nav a:hover{background:var(--surface-2);color:var(--text)}
396
403
  @media (max-width:1180px){.nav{display:none}}
404
+ @media (max-width:1360px){.brand__sub{display:none}}
397
405
  .iconbtn{width:40px;height:40px;flex:none;display:grid;place-items:center;
398
406
  border:1px solid var(--border);border-radius:var(--r-full);background:transparent;
399
407
  color:var(--text-2);cursor:pointer;transition:background-color var(--dur-short),color var(--dur-short)}
@@ -448,12 +456,15 @@ transition:background-color var(--dur-short),box-shadow var(--dur-short),transfo
448
456
  .btn--ghost{background:transparent;color:var(--text);border-color:var(--border)}
449
457
  .btn--onDark{background:var(--surface);color:var(--text)}
450
458
  .card{background:var(--surface);border:1px solid var(--border-soft);border-radius:var(--r-lg);
451
- padding:clamp(20px,2vw,30px);transition:border-color var(--dur-short),box-shadow var(--dur-short),background-color var(--dur-medium)}
459
+ padding:clamp(20px,2vw,30px);transition:border-color var(--dur-short),box-shadow var(--dur-short),background-color var(--dur-medium);
460
+ display:flex;flex-direction:column;min-width:0}
452
461
  .card:hover{border-color:var(--border);box-shadow:var(--shadow-1)}
453
462
  .card--flat{background:var(--surface-1);border-color:transparent}
454
463
  .card--flat:hover{background:var(--surface-2)}
455
464
  .card--accent{background:var(--accent-soft);border-color:transparent}
456
- .card__hd{display:flex;align-items:center;gap:var(--sp-3);margin-bottom:var(--sp-3)}
465
+ .card__hd{display:flex;align-items:center;gap:var(--sp-3);margin-bottom:var(--sp-3);flex:none}
466
+ .card>.ul,.card>.t-body,.card>.t-sm{flex:1 1 auto}
467
+ .card>.so-what,.card>.tbd-legend,.card>.flagbar{flex:none;margin-top:auto}
457
468
  .card__ico{width:34px;height:34px;flex:none;border-radius:10px;background:var(--accent-soft);
458
469
  color:var(--accent-text);display:grid;place-items:center;font-size:15px;font-weight:600}
459
470
  .card__ico svg{width:18px;height:18px}
@@ -815,8 +826,9 @@ color:var(--accent);font-variant-numeric:tabular-nums;line-height:1;min-width:2.
815
826
  .agenda__a:hover .agenda__go{color:var(--accent);transform:translateX(4px)}
816
827
  .agenda__go svg{width:20px;height:20px;display:block}
817
828
  @media (min-width:900px){
818
- .agenda--2col{display:grid;grid-template-columns:1fr 1fr;column-gap:clamp(20px,3vw,48px)}
819
- .agenda--2col .agenda__i{border-top:1px solid var(--border-soft)}}
829
+ /* R4:列优先(先左列后右列),与 PPTX Agenda 列填充一致——grid 行优先会打乱阅读顺序 */
830
+ .agenda--2col{display:block;column-count:2;column-gap:clamp(20px,3vw,48px)}
831
+ .agenda--2col .agenda__i{break-inside:avoid;border-top:1px solid var(--border-soft)}}
820
832
  /* ── 页码指示(翻页导航) ── */
821
833
  .pager{position:fixed;right:clamp(10px,1.6vw,26px);top:50%;transform:translateY(-50%);
822
834
  z-index:60;display:flex;flex-direction:column;align-items:center;gap:10px}
@@ -900,7 +912,6 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
900
912
  <nav class="nav">
901
913
  <a href="#s1">章节一</a>
902
914
  <a href="#s2">章节二</a>
903
- <a href="#refs">参考资料</a>
904
915
  </nav>
905
916
  <div class="toolsbar">
906
917
  <div class="seld" id="styleSel">
@@ -958,7 +969,7 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
958
969
  <section class="band band--fit" id="cover">
959
970
  <div class="wrap">
960
971
  <div class="shead rv">
961
- <div class="t-eyebrow">产品介绍 · 2026-09-26 · v0.1.17</div>
972
+ <div class="t-eyebrow">产品介绍 · 2026-09-26 · v0.1.19</div>
962
973
  <h1 class="t-display shead__title">TopMind × tms-skills</h1>
963
974
  <p class="t-lead shead__desc">HTML + PPT 双交付 · 为正式商务演示而生</p>
964
975
  </div>
@@ -969,22 +980,22 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
969
980
  <div class="wrap">
970
981
  <div class="shead rv"><div class="t-eyebrow">目录</div>
971
982
  <h2 class="t-h1 shead__title">报告大纲</h2></div>
972
- <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>
983
+ <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">为什么是我们</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">top-ppt-html</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">三模式</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">图表工艺</span><div class="agenda__d">05 · 图表工艺</div></span></a></li> <li class="agenda__i"><a class="agenda__a" href="#s7"><span class="agenda__n">06</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">07</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="#s11"><span class="agenda__n">08</span><span><span class="agenda__t">Header 工具栏</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">09</span><span><span class="agenda__t">Fast Mode</span><div class="agenda__d">09 · Fast Mode</div></span></a></li></ol>
973
984
  </div>
974
985
  </section>
975
986
 
976
- <section class="band" id="s1" data-skel="P4" data-page-type="points">
987
+ <section class="band" id="s1" data-skel="P5" data-page-type="cards">
977
988
  <div class="wrap">
978
989
  <div class="shead rv">
979
990
  <div class="t-eyebrow">01 · 为什么是我们</div>
980
991
  <h2 class="t-h1 shead__title">市面 PPT 技能很多,为何还要 top-ppt-html</h2>
981
992
  </div>
982
- <div class="grid g-3 rv a-start">
983
- <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>
993
+ <div class="grid g-3--equal rv">
994
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="增长"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 7l-8.5 8.5-5-5L2 17"/><path d="M16 7h6v6"/></svg></div><h3 class="t-h3">正式商务演示</h3></div>
984
995
  <ul class="ul"><li><strong>不是花哨 gadget。</strong>为演示报告与上台汇报而生——直观、大气、可编辑</li><li><strong>一屏一主张。</strong>标题即行动句,少装饰堆砌</li></ul></div>
985
- <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="4" width="18" height="14" rx="2"/><path d="M3 10h18"/><path d="M8 20h8"/></svg></div><h3 class="t-h3">HTML + PPT 双交付</h3></div>
996
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="下降"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 17l-8.5-8.5-5 5L2 7"/><path d="M16 17h6v-6"/></svg></div><h3 class="t-h3">HTML + PPT 双交付</h3></div>
986
997
  <ul class="ul"><li><strong>HTML 日常上台。</strong>单文件可翻页,等同幻灯片</li><li><strong>PPTX 按需导出。</strong>版式保真、可继续编辑</li></ul></div>
987
- <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">MD3 式克制</h3></div>
998
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="数据"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg></div><h3 class="t-h3">MD3 式克制</h3></div>
988
999
  <ul class="ul"><li><strong>密度合适。</strong>文字/图形/形状/颜色克制</li><li><strong>无 AI chrome。</strong>结论条 tonal 满铺,禁左侧装饰轨</li></ul></div>
989
1000
  </div>
990
1001
  <div class="sowhat rv"><span class="sowhat__v">产出即上台:同源模型保证 HTML 与 PPTX 一致,图表带数据可核对。</span></div>
@@ -997,16 +1008,16 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
997
1008
  <div class="t-eyebrow">02 · tms-skills</div>
998
1009
  <h2 class="t-h1 shead__title">tms-skills:整仓可安装的智能体技能</h2>
999
1010
  </div>
1000
- <div class="grid g-3 rv a-start">
1001
- <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>
1011
+ <div class="grid g-3--equal rv">
1012
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="增长"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 7l-8.5 8.5-5-5L2 17"/><path d="M16 7h6v6"/></svg></div><h3 class="t-h3">Monorepo</h3></div>
1002
1013
  <ul class="ul"><li><strong>一仓多技能。</strong>根目录技能包 + 统一安装器</li><li><strong>同 tag 发版。</strong>安装器与技能整仓对齐</li></ul></div>
1003
- <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>
1014
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="下降"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 17l-8.5-8.5-5 5L2 7"/><path d="M16 17h6v-6"/></svg></div><h3 class="t-h3">双通道安装</h3></div>
1004
1015
  <ul class="ul"><li><strong>npm 钉版本。</strong>npx @topmindspace/tms-skills</li><li><strong>GitHub 跟 HEAD。</strong>日常可 clone / 直装</li></ul></div>
1005
- <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>
1016
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="数据"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg></div><h3 class="t-h3">当前主技能</h3></div>
1006
1017
  <ul class="ul"><li><strong>top-ppt-html。</strong>正式场合演示文稿</li><li><strong>HTML + PPTX。</strong>同源模型 · 双交付</li></ul></div>
1007
1018
  </div>
1008
- <div class="footnote">包名 @topmindspace/tms-skills · 当前线 0.1.17(latest)</div>
1009
- <div class="sowhat rv"><span class="sowhat__v">安装器与技能同仓同 tag——装一次,版本线对齐。</span></div>
1019
+ <div class="sowhat rv"><span class="sowhat__v">安装器与技能同仓同 tag——装一次,版本线对齐。</span></div>
1020
+ <div class="footnote">包名 @topmindspace/tms-skills · 当前线 0.1.19(latest)</div>
1010
1021
  </div>
1011
1022
  </section>
1012
1023
 
@@ -1017,23 +1028,12 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1017
1028
  <h2 class="t-h1 shead__title">双交付:HTML 即演示,PPTX 可继续编</h2>
1018
1029
  </div>
1019
1030
  <div class="grid g-side rv a-start">
1020
- <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>
1031
+ <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>
1021
1032
  <div class="fig"><div class="fig__cap">工艺关注点(产品强调 · 示意权重)</div>
1022
1033
  <svg class="chart" data-chart="bar" viewBox="0 0 560 220">
1023
- <line x1="46" y1="170" x2="540" y2="170" class="s-bds" stroke-width="1"/>
1024
- <rect data-anim="grow" x="92.0" y="58.0" width="56.1" height="112.0" rx="6" class="f-s3"><title>版式 32</title></rect>
1025
- <text data-anim="fade" x="120.0" y="192" text-anchor="middle" class="f-txt3" font-size="11">版式</text>
1026
- <text data-anim="fade" x="120.0" y="50.0" text-anchor="middle" class="f-txt2" font-size="12" font-weight="600">32</text>
1027
- <rect data-anim="grow" x="211.9" y="72.0" width="56.1" height="98.0" rx="6" class="f-s3"><title>排版 28</title></rect>
1028
- <text data-anim="fade" x="240.0" y="192" text-anchor="middle" class="f-txt3" font-size="11">排版</text>
1029
- <text data-anim="fade" x="240.0" y="64.0" text-anchor="middle" class="f-txt2" font-size="12" font-weight="600">28</text>
1030
- <rect data-anim="grow" x="331.9" y="107.0" width="56.1" height="63.0" rx="6" class="f-acc"><title>色彩 18</title></rect>
1031
- <text data-anim="fade" x="360.0" y="192" text-anchor="middle" class="f-txt3" font-size="11">色彩</text>
1032
- <text data-anim="fade" x="360.0" y="99.0" text-anchor="middle" class="f-txt2" font-size="12" font-weight="600">18</text>
1033
- <rect data-anim="grow" x="451.9" y="93.0" width="56.1" height="77.0" rx="6" class="f-acc"><title>内容 22</title></rect>
1034
- <text data-anim="fade" x="480.0" y="192" text-anchor="middle" class="f-txt3" font-size="11">内容</text>
1035
- <text data-anim="fade" x="480.0" y="85.0" text-anchor="middle" class="f-txt2" font-size="12" font-weight="600">22</text>
1036
- </svg>
1034
+ <!-- 数据以 REPORT_MODEL.chart 为准;复杂图形用 extract_snippet --chart bar -->
1035
+ <text x="280" y="110" text-anchor="middle" class="f-txt3" font-size="12">bar · 见模型数据</text>
1036
+ </svg>
1037
1037
  </div>
1038
1038
  </div>
1039
1039
  <div class="sowhat rv"><span class="sowhat__v">工艺在结构与密度,不在 gadget——正式场合演讲/汇报才是主场。</span></div>
@@ -1046,16 +1046,16 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1046
1046
  <div class="t-eyebrow">04 · 三模式</div>
1047
1047
  <h2 class="t-h1 shead__title">模式先定后写:A 演示 · B 研究 · C 架构</h2>
1048
1048
  </div>
1049
- <div class="grid g-3 rv a-start">
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"><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>
1049
+ <div class="grid g-3--equal rv">
1050
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="增长"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 7l-8.5 8.5-5-5L2 17"/><path d="M16 7h6v6"/></svg></div><h3 class="t-h3">A · 演示</h3></div>
1051
1051
  <ul class="ul"><li><strong>每屏一主张。</strong>标题即行动句,非话题标签</li><li><strong>大气留白。</strong>证据充分但不堆咨询 dump</li></ul></div>
1052
- <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>
1052
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="下降"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 17l-8.5-8.5-5 5L2 7"/><path d="M16 17h6v-6"/></svg></div><h3 class="t-h3">B · 研究</h3></div>
1053
1053
  <ul class="ul"><li><strong>咨询密排。</strong>Exhibit · 来源 · 结论条</li><li><strong>结论可核对。</strong>数字与口径双向对齐</li></ul></div>
1054
- <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>
1054
+ <div class="card"><div class="card__hd"><div class="card__ico" data-icon="数据"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v14c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 12c0 1.66 4.03 3 9 3s9-1.34 9-3"/></svg></div><h3 class="t-h3">C · 架构</h3></div>
1055
1055
  <ul class="ul"><li><strong>图为王。</strong>拓扑 / 泳道 / 分层</li><li><strong>少字多结构。</strong>一图说清关系</li></ul></div>
1056
1056
  </div>
1057
- <div class="footnote">意图线索:路演/汇报/演讲 → A;调研/对标 → B;拓扑/方案图 → C</div>
1058
1057
  <div class="sowhat rv"><span class="sowhat__v">先定模式再写页——A/B/C 契约决定密度、图表与结论条用法。</span></div>
1058
+ <div class="footnote">意图线索:路演/汇报/演讲 → A;调研/对标 → B;拓扑/方案图 → C</div>
1059
1059
  </div>
1060
1060
  </section>
1061
1061
 
@@ -1068,15 +1068,9 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1068
1068
  <div class="grid g-side rv a-start">
1069
1069
  <div class="fig" style="text-align:center"><div class="fig__cap">构成占比</div>
1070
1070
  <svg class="chart" data-chart="donut" viewBox="0 0 560 220">
1071
- <g transform="translate(210,40)">
1072
- <circle cx="70" cy="70" r="54" class="f-none s-bds" stroke-width="15"/>
1073
- <circle data-sweep data-circ="339.3" data-p="0.4000" cx="70" cy="70" r="54" class="f-none s-acc" stroke-width="15" stroke-dasharray="135.7 203.6" stroke-linecap="butt" transform="rotate(-90.0 70 70)"><title>可翻页 HTML 40%</title></circle>
1074
- <circle data-sweep data-circ="339.3" data-p="0.3500" cx="70" cy="70" r="54" class="f-none s-txt2" stroke-width="15" stroke-dasharray="118.8 220.5" stroke-linecap="butt" transform="rotate(54.0 70 70)"><title>保真 PPTX 35%</title></circle>
1075
- <circle data-sweep data-circ="339.3" data-p="0.2500" cx="70" cy="70" r="54" class="f-none s-txt3" stroke-width="15" stroke-dasharray="84.8 254.5" stroke-linecap="butt" transform="rotate(180.0 70 70)"><title>质检交付说明 25%</title></circle>
1076
- <text x="70" y="68" text-anchor="middle" class="f-txt" font-size="22" font-weight="600" data-count="40" data-suffix="%">40%</text>
1077
- <text x="70" y="88" text-anchor="middle" class="f-txt3" font-size="11">同源模型</text>
1078
- </g>
1079
- </svg>
1071
+ <!-- 数据以 REPORT_MODEL.chart 为准;复杂图形用 extract_snippet --chart donut -->
1072
+ <text x="280" y="110" text-anchor="middle" class="f-txt3" font-size="12">donut · 见模型数据</text>
1073
+ </svg>
1080
1074
  </div>
1081
1075
  <div class="stack gap-4"><h3 class="t-h3">构成明细</h3>
1082
1076
  <ul class="ul"> <li><strong>可翻页 HTML。</strong>40(40%)</li> <li><strong>保真 PPTX。</strong>35(35%)</li> <li><strong>质检交付说明。</strong>25(25%)</li></ul>
@@ -1095,21 +1089,9 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1095
1089
  <div class="grid g-side rv a-start">
1096
1090
  <div class="fig"><div class="fig__cap">0.1.x 能力累进:定位与样张随版本加厚</div>
1097
1091
  <svg class="chart" data-chart="line" viewBox="0 0 560 220">
1098
- <line x1="46" y1="180" x2="540" y2="180" class="s-bds" stroke-width="1"/>
1099
- <line x1="46" y1="130" x2="540" y2="130" class="s-bds" stroke-width="1" stroke-dasharray="3 5"/>
1100
- <line x1="46" y1="80" x2="540" y2="80" class="s-bds" stroke-width="1" stroke-dasharray="3 5"/>
1101
- <path data-draw d="M60.0,100.0 L175.0,80.0 L290.0,70.0 L405.0,60.0 L520.0,50.0" class="f-none s-acc" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
1102
- <circle cx="60.0" cy="100.0" r="4" class="f-acc"><title>0.1.7 · 8项</title></circle>
1103
- <text x="60.0" y="200" text-anchor="middle" class="f-txt3" font-size="11">0.1.7</text>
1104
- <circle cx="175.0" cy="80.0" r="4" class="f-acc"><title>0.1.8 · 10项</title></circle>
1105
- <text x="175.0" y="200" text-anchor="middle" class="f-txt3" font-size="11">0.1.8</text>
1106
- <circle cx="290.0" cy="70.0" r="4" class="f-acc"><title>0.1.9 · 11项</title></circle>
1107
- <text x="290.0" y="200" text-anchor="middle" class="f-txt3" font-size="11">0.1.9</text>
1108
- <circle cx="405.0" cy="60.0" r="4" class="f-acc"><title>0.1.10 · 12项</title></circle>
1109
- <text x="405.0" y="200" text-anchor="middle" class="f-txt3" font-size="11">0.1.10</text>
1110
- <circle cx="520.0" cy="50.0" r="4" class="f-acc"><title>0.1.11 · 13项</title></circle>
1111
- <text x="520.0" y="200" text-anchor="middle" class="f-txt3" font-size="11">0.1.11</text>
1112
- </svg>
1092
+ <!-- 数据以 REPORT_MODEL.chart 为准;复杂图形用 extract_snippet --chart line -->
1093
+ <text x="280" y="110" text-anchor="middle" class="f-txt3" font-size="12">line · 见模型数据</text>
1094
+ </svg>
1113
1095
  </div>
1114
1096
  <div class="stack gap-4"><h3 class="t-h3">怎么读这张图</h3>
1115
1097
  <ul class="ul"><li><strong>真实版本线。</strong>对应 CHANGELOG 已合并能力,非虚构增速</li><li><strong>本版强化。</strong>差异化定位 · 双交付叙事 · README 总览精简</li></ul>
@@ -1142,9 +1124,9 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1142
1124
  <h2 class="t-h1 shead__title">散装出稿止步,strict 0/0 才算交付</h2>
1143
1125
  </div>
1144
1126
  <div class="grid g-half g-2 rv a-start">
1145
- <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>
1127
+ <div class="card"><h3 class="t-h3">散装路径 · 风险</h3>
1146
1128
  <ul class="ul"><li><strong>手改 HTML。</strong>模型与正文双写,一改就漂</li><li><strong>无严格校验。</strong>截断、同型图、半空卡易漏</li><li><strong>口头交付。</strong>缺七要素,验收靠感觉</li></ul></div>
1147
- <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>
1129
+ <div class="card" style="background:var(--accent-soft);border-color:transparent"><h3 class="t-h3" style="color:var(--accent)">门禁路径 · 目标</h3>
1148
1130
  <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>
1149
1131
  </div>
1150
1132
  <div class="sowhat rv"><span class="sowhat__v">反截断、图表多样性、runtime SHA——门禁是交付的一部分。</span></div>
@@ -1160,33 +1142,12 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1160
1142
  <div class="grid g-side rv a-start">
1161
1143
  <div class="fig"><div class="fig__cap">从想法到上台:工艺链路如何把主张垫实</div>
1162
1144
  <svg class="chart" data-chart="waterfall" viewBox="0 0 560 220">
1163
- <line x1="40" y1="190" x2="540" y2="190" class="s-bds" stroke-width="1"/>
1164
- <rect data-anim="grow" x="68.4" y="159.1" width="44.9" height="30.9" rx="5" class="f-s3"/>
1165
- <text x="90.8" y="151.1" text-anchor="middle" class="f-txt2" font-size="12" font-weight="600">20pt</text>
1166
- <text x="90.8" y="206" text-anchor="middle" class="f-txt3" font-size="11">意图</text>
1167
- <rect data-anim="grow" x="150.0" y="135.9" width="44.9" height="23.2" rx="5" class="f-acc"/>
1168
- <text x="172.5" y="127.9" text-anchor="middle" class="f-acc" font-size="12" font-weight="600">+15pt</text>
1169
- <text x="172.5" y="206" text-anchor="middle" class="f-txt3" font-size="11">模式</text>
1170
- <line x1="131.7" y1="159.1" x2="150.0" y2="159.1" class="s-bds" stroke-width="1" stroke-dasharray="3 3"/>
1171
- <rect data-anim="grow" x="231.7" y="97.2" width="44.9" height="38.6" rx="5" class="f-acc"/>
1172
- <text x="254.2" y="89.2" text-anchor="middle" class="f-acc" font-size="12" font-weight="600">+25pt</text>
1173
- <text x="254.2" y="206" text-anchor="middle" class="f-txt3" font-size="11">模型</text>
1174
- <line x1="213.3" y1="135.9" x2="231.7" y2="135.9" class="s-bds" stroke-width="1" stroke-dasharray="3 3"/>
1175
- <rect data-anim="grow" x="313.4" y="74.1" width="44.9" height="23.2" rx="5" class="f-acc"/>
1176
- <text x="335.8" y="66.1" text-anchor="middle" class="f-acc" font-size="12" font-weight="600">+15pt</text>
1177
- <text x="335.8" y="206" text-anchor="middle" class="f-txt3" font-size="11">图表</text>
1178
- <line x1="295.0" y1="97.2" x2="313.4" y2="97.2" class="s-bds" stroke-width="1" stroke-dasharray="3 3"/>
1179
- <rect data-anim="grow" x="395.0" y="50.9" width="44.9" height="23.2" rx="5" class="f-acc"/>
1180
- <text x="417.5" y="42.9" text-anchor="middle" class="f-acc" font-size="12" font-weight="600">+15pt</text>
1181
- <text x="417.5" y="206" text-anchor="middle" class="f-txt3" font-size="11">门禁</text>
1182
- <line x1="376.7" y1="74.1" x2="395.0" y2="74.1" class="s-bds" stroke-width="1" stroke-dasharray="3 3"/>
1183
- <rect data-anim="grow" x="476.7" y="50.9" width="44.9" height="139.1" rx="5" class="f-acc"/>
1184
- <text x="499.2" y="42.9" text-anchor="middle" class="f-txt2" font-size="12" font-weight="600">90pt</text>
1185
- <text x="499.2" y="206" text-anchor="middle" class="f-txt3" font-size="11">上台</text>
1186
- </svg>
1145
+ <!-- 数据以 REPORT_MODEL.chart 为准;复杂图形用 extract_snippet --chart waterfall -->
1146
+ <text x="280" y="110" text-anchor="middle" class="f-txt3" font-size="12">waterfall · 见模型数据</text>
1147
+ </svg>
1187
1148
  </div>
1188
1149
  <div class="stack gap-4"><h3 class="t-h3">怎么读这张图</h3>
1189
- <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>
1150
+ <ul class="ul"><li><strong>意图定模式。</strong>路演→A · 调研→B · 拓扑→C</li><li><strong>门禁收口。</strong>strict 0/0 前不算交付</li></ul>
1190
1151
  </div>
1191
1152
  </div>
1192
1153
  <div class="sowhat rv"><span class="sowhat__v">上台交付 = 模式契约 + 模型单写 + 多样图表 + 门禁收口。</span></div>
@@ -1200,30 +1161,12 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1200
1161
  <h2 class="t-h1 shead__title">核图优先:排名对比用横向条,一眼分出轻重</h2>
1201
1162
  </div>
1202
1163
  <div class="grid g-side rv a-start">
1203
- <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>
1164
+ <div class="stack gap-4"><ul class="ul"><li><strong>产品已交付能力。</strong>五项均为当前线真实能力,不是预测</li><li><strong>图表选型。</strong>谁大谁小 → hbar;趋势 → line;占比 → donut</li></ul></div>
1204
1165
  <div class="fig"><div class="fig__cap">能力就绪(当前发布线)</div>
1205
1166
  <svg class="chart" data-chart="hbar" viewBox="0 0 560 220">
1206
- <text x="0" y="30.0" class="f-txt2" font-size="12">strict 0/0</text>
1207
- <rect x="130" y="20.0" width="340" height="15" rx="7.5" class="f-s2"/>
1208
- <rect data-anim="grow" x="130" y="20.0" width="340.0" height="15" rx="7.5" class="f-acc"><title>strict 0/0 100%</title></rect>
1209
- <text x="482" y="32.0" class="f-txt" font-size="12" font-weight="600">100%</text>
1210
- <text x="0" y="66.0" class="f-txt2" font-size="12">三模式契约</text>
1211
- <rect x="130" y="56.0" width="340" height="15" rx="7.5" class="f-s2"/>
1212
- <rect data-anim="grow" x="130" y="56.0" width="340.0" height="15" rx="7.5" class="f-acc"><title>三模式契约 100%</title></rect>
1213
- <text x="482" y="68.0" class="f-txt" font-size="12" font-weight="600">100%</text>
1214
- <text x="0" y="102.0" class="f-txt2" font-size="12">九风格皮肤</text>
1215
- <rect x="130" y="92.0" width="340" height="15" rx="7.5" class="f-s2"/>
1216
- <rect data-anim="grow" x="130" y="92.0" width="340.0" height="15" rx="7.5" class="f-acc"><title>九风格皮肤 100%</title></rect>
1217
- <text x="482" y="104.0" class="f-txt" font-size="12" font-weight="600">100%</text>
1218
- <text x="0" y="138.0" class="f-txt2" font-size="12">双通道交付</text>
1219
- <rect x="130" y="128.0" width="340" height="15" rx="7.5" class="f-s2"/>
1220
- <rect data-anim="grow" x="130" y="128.0" width="340.0" height="15" rx="7.5" class="f-acc"><title>双通道交付 100%</title></rect>
1221
- <text x="482" y="140.0" class="f-txt" font-size="12" font-weight="600">100%</text>
1222
- <text x="0" y="174.0" class="f-txt2" font-size="12">Fast Mode</text>
1223
- <rect x="130" y="164.0" width="340" height="15" rx="7.5" class="f-s2"/>
1224
- <rect data-anim="grow" x="130" y="164.0" width="340.0" height="15" rx="7.5" class="f-acc"><title>Fast Mode 100%</title></rect>
1225
- <text x="482" y="176.0" class="f-txt" font-size="12" font-weight="600">100%</text>
1226
- </svg>
1167
+ <!-- 数据以 REPORT_MODEL.chart 为准;复杂图形用 extract_snippet --chart hbar -->
1168
+ <text x="280" y="110" text-anchor="middle" class="f-txt3" font-size="12">hbar · 见模型数据</text>
1169
+ </svg>
1227
1170
  </div>
1228
1171
  </div>
1229
1172
  <div class="sowhat rv"><span class="sowhat__v">说服力来自可核对的能力清单与图表多样性,而非单张柱图凑数。</span></div>
@@ -1267,14 +1210,6 @@ background:var(--surface-2);border-radius:6px;padding:2px 7px;color:var(--text)}
1267
1210
  </div>
1268
1211
  </div>
1269
1212
  </section>
1270
-
1271
- <section class="band band--flow" id="refs">
1272
- <div class="wrap">
1273
- <div class="shead rv"><div class="t-eyebrow">附录</div>
1274
- <h2 class="t-h1 shead__title">参考资料</h2></div>
1275
- <ol class="refs"><li>(无外部引用)</li></ol>
1276
- </div>
1277
- </section>
1278
1213
  <!-- __TOPPPT_CONTENT_END__ -->
1279
1214
 
1280
1215
  <!-- ══ 页码指示(翻页导航) ══ -->
@@ -1888,66 +1823,51 @@ window.REPORT_MODEL = {
1888
1823
  "theme": "light",
1889
1824
  "title": "TopMind × tms-skills",
1890
1825
  "subtitle": "HTML + PPT 双交付 · 为正式商务演示而生",
1891
- "meta": "产品介绍 · 2026-09-26 · v0.1.17",
1826
+ "meta": "产品介绍 · 2026-09-26 · v0.1.19",
1892
1827
  "agenda": [
1893
1828
  [
1894
1829
  "01",
1895
- "市面 PPT 技能很多,为何还要 top-ppt-html",
1830
+ "为什么是我们",
1896
1831
  "01 · 为什么是我们"
1897
1832
  ],
1898
1833
  [
1899
1834
  "02",
1900
- "tms-skills:整仓可安装的智能体技能",
1835
+ "tms-skills",
1901
1836
  "02 · tms-skills"
1902
1837
  ],
1903
1838
  [
1904
1839
  "03",
1905
- "双交付:HTML 即演示,PPTX 可继续编",
1840
+ "top-ppt-html",
1906
1841
  "03 · top-ppt-html"
1907
1842
  ],
1908
1843
  [
1909
1844
  "04",
1910
- "模式先定后写:A 演示 · B 研究 · C 架构",
1845
+ "三模式",
1911
1846
  "04 · 三模式"
1912
1847
  ],
1913
1848
  [
1914
1849
  "05",
1915
- "交付面三件套:演示 HTML · 可编辑 PPTX · 门禁说明",
1850
+ "图表工艺",
1916
1851
  "05 · 图表工艺"
1917
1852
  ],
1918
1853
  [
1919
1854
  "06",
1920
- "0.1.x 能力累进:定位与样张随版本加厚",
1921
- "05 · 图表工艺"
1922
- ],
1923
- [
1924
- "07",
1925
- "九风格开场即可见,亮暗主题一键贯穿",
1855
+ "风格主题",
1926
1856
  "06 · 风格主题"
1927
1857
  ],
1928
1858
  [
1929
- "08",
1930
- "散装出稿止步,strict 0/0 才算交付",
1931
- "07 · 质量门禁"
1932
- ],
1933
- [
1934
- "09",
1935
- "从想法到上台:工艺链路如何把主张垫实",
1859
+ "07",
1860
+ "质量门禁",
1936
1861
  "07 · 质量门禁"
1937
1862
  ],
1938
1863
  [
1939
- "10",
1940
- "核图优先:排名对比用横向条,一眼分出轻重",
1941
- "05 · 图表工艺"
1942
- ],
1943
- [
1944
- "11",
1945
- "打开 HTML 即演示:顶栏快捷操作一览",
1864
+ "08",
1865
+ "Header 工具栏",
1946
1866
  "08 · Header 工具栏"
1947
1867
  ],
1948
1868
  [
1949
- "12",
1950
- "Fast Mode:跳过问询,不跳过工艺",
1869
+ "09",
1870
+ "Fast Mode",
1951
1871
  "09 · Fast Mode"
1952
1872
  ]
1953
1873
  ],
@@ -1970,7 +1890,8 @@ window.REPORT_MODEL = {
1970
1890
  "一屏一主张",
1971
1891
  "标题即行动句,少装饰堆砌"
1972
1892
  ]
1973
- ]
1893
+ ],
1894
+ "icon": "增长"
1974
1895
  },
1975
1896
  {
1976
1897
  "title": "HTML + PPT 双交付",
@@ -1983,7 +1904,8 @@ window.REPORT_MODEL = {
1983
1904
  "PPTX 按需导出",
1984
1905
  "版式保真、可继续编辑"
1985
1906
  ]
1986
- ]
1907
+ ],
1908
+ "icon": "下降"
1987
1909
  },
1988
1910
  {
1989
1911
  "title": "MD3 式克制",
@@ -1996,7 +1918,8 @@ window.REPORT_MODEL = {
1996
1918
  "无 AI chrome",
1997
1919
  "结论条 tonal 满铺,禁左侧装饰轨"
1998
1920
  ]
1999
- ]
1921
+ ],
1922
+ "icon": "数据"
2000
1923
  }
2001
1924
  ],
2002
1925
  "soWhat": "产出即上台:同源模型保证 HTML 与 PPTX 一致,图表带数据可核对。"
@@ -2019,7 +1942,8 @@ window.REPORT_MODEL = {
2019
1942
  "同 tag 发版",
2020
1943
  "安装器与技能整仓对齐"
2021
1944
  ]
2022
- ]
1945
+ ],
1946
+ "icon": "增长"
2023
1947
  },
2024
1948
  {
2025
1949
  "title": "双通道安装",
@@ -2032,7 +1956,8 @@ window.REPORT_MODEL = {
2032
1956
  "GitHub 跟 HEAD",
2033
1957
  "日常可 clone / 直装"
2034
1958
  ]
2035
- ]
1959
+ ],
1960
+ "icon": "下降"
2036
1961
  },
2037
1962
  {
2038
1963
  "title": "当前主技能",
@@ -2045,10 +1970,11 @@ window.REPORT_MODEL = {
2045
1970
  "HTML + PPTX",
2046
1971
  "同源模型 · 双交付"
2047
1972
  ]
2048
- ]
1973
+ ],
1974
+ "icon": "数据"
2049
1975
  }
2050
1976
  ],
2051
- "footnote": "包名 @topmindspace/tms-skills · 当前线 0.1.17(latest)",
1977
+ "footnote": "包名 @topmindspace/tms-skills · 当前线 0.1.19(latest)",
2052
1978
  "soWhat": "安装器与技能同仓同 tag——装一次,版本线对齐。"
2053
1979
  },
2054
1980
  {
@@ -2111,7 +2037,8 @@ window.REPORT_MODEL = {
2111
2037
  "大气留白",
2112
2038
  "证据充分但不堆咨询 dump"
2113
2039
  ]
2114
- ]
2040
+ ],
2041
+ "icon": "增长"
2115
2042
  },
2116
2043
  {
2117
2044
  "title": "B · 研究",
@@ -2124,7 +2051,8 @@ window.REPORT_MODEL = {
2124
2051
  "结论可核对",
2125
2052
  "数字与口径双向对齐"
2126
2053
  ]
2127
- ]
2054
+ ],
2055
+ "icon": "下降"
2128
2056
  },
2129
2057
  {
2130
2058
  "title": "C · 架构",
@@ -2137,7 +2065,8 @@ window.REPORT_MODEL = {
2137
2065
  "少字多结构",
2138
2066
  "一图说清关系"
2139
2067
  ]
2140
- ]
2068
+ ],
2069
+ "icon": "数据"
2141
2070
  }
2142
2071
  ],
2143
2072
  "footnote": "意图线索:路演/汇报/演讲 → A;调研/对标 → B;拓扑/方案图 → C",
@@ -2443,7 +2372,7 @@ window.REPORT_MODEL = {
2443
2372
 
2444
2373
  /* __TOPPPT_RUNTIME_START__ */
2445
2374
  /* ══ PPTX 导出运行时(assets/pptx-export.js 的内联副本 · 由 scripts/sync_runtime.py 注入,禁止手改) ══ */
2446
- /* __TOPPPT_RUNTIME_SHA__:57dbfb4f2b594c45 */
2375
+ /* __TOPPPT_RUNTIME_SHA__:af6e25f25fd2e116 */
2447
2376
  /* ═══════════════════════════════════════════════════════════════════════════
2448
2377
  * TopPPT HTML· 浏览器端 PPTX 预览运行时
2449
2378
  * 零依赖、随报告单文件分发;OOXML 序列化器(仅供预览,页面不导出文件)。
@@ -2567,7 +2496,8 @@ function regionOf(pageType, slotId, opts) {
2567
2496
  if (type === 'bar' && slot === 'primary') {
2568
2497
  var by = P.chartY || 2.95;
2569
2498
  var bb = opts.bottom != null ? opts.bottom : bottomDefault;
2570
- return { x: MX + (P.chartX || 0), y: by, w: CW - (P.chartW || 0), h: Math.max(1.2, bb - by) };
2499
+ /* chartX/chartW 历史误用已纠正:与 donut/table/hbar/exhibit 同口径,图表盒对齐版心 (MX, CW) */
2500
+ return { x: MX, y: by, w: CW, h: Math.max(1.2, bb - by) };
2571
2501
  }
2572
2502
  if (type === 'bar' && slot === 'hbar') {
2573
2503
  var y0 = P.hbarY0 || 2.6;
@@ -2602,6 +2532,15 @@ function regionOf(pageType, slotId, opts) {
2602
2532
  return { x: MX, y: P.heroY || 2.9, w: CW * (P.heroW || 0.52), h: P.heroH || 1.6,
2603
2533
  dividerX: P.dividerX, metricY0: P.metricY0, metricRowH: P.metricRowH };
2604
2534
  }
2535
+ /* R3:kpi 支撑指标列——落在 dividerX 右侧(默认全宽返回会压住 hero) */
2536
+ if (type === 'kpi' && slot === 'metrics') {
2537
+ var dxK = P.dividerX != null ? P.dividerX : 0.56;
2538
+ return {
2539
+ x: MX + CW * dxK + 0.35, y: P.metricY0 || 2.95,
2540
+ w: CW * (1 - dxK) - 0.5,
2541
+ h: Math.max(0.6, bottomDefault - (P.metricY0 || 2.95)),
2542
+ };
2543
+ }
2605
2544
  if (type === 'comparison' && (slot === 'left' || slot === 'primary' || slot === 'right')) {
2606
2545
  var cg = P.panelGap || 0.4, pw = (CW - cg) / 2;
2607
2546
  if (slot === 'right') return { x: MX + pw + cg, y: P.panelY || 2.55, w: pw, h: P.panelH || 3.4 };
@@ -2634,15 +2573,22 @@ function regionOf(pageType, slotId, opts) {
2634
2573
  }
2635
2574
  if (type === 'image' && slot === 'primary') {
2636
2575
  var iy2 = Math.max(P.y || 2.3, opts.top || 0);
2637
- return { x: MX, y: iy2, w: CW, h: Math.max(1.2, Math.min(P.h || 4.2, (opts.bottom != null ? opts.bottom : bottomDefault) - iy2)) };
2576
+ /* R2:有图注时图片不得越过 contentBottomWithNote(图注落注释带,属 annotation self) */
2577
+ var iBottom = (opts.bottom != null) ? opts.bottom
2578
+ : (opts.caption ? (L.contentBottomWithNote || 6.4) : bottomDefault);
2579
+ return { x: MX, y: iy2, w: CW, h: Math.max(1.2, Math.min(P.h || 4.2, iBottom - iy2)) };
2638
2580
  }
2639
2581
  if ((type === 'halftable') && (slot === 'left' || slot === 'primary')) {
2640
2582
  var rs = PT.research || {};
2641
- return { x: MX, y: topDefault, w: CW * (rs.halfTableW || 0.52), h: Math.max(1, bottomDefault - topDefault) };
2583
+ var ht = opts.top != null ? opts.top : topDefault;
2584
+ var hb = opts.bottom != null ? opts.bottom : bottomDefault;
2585
+ return { x: MX, y: ht, w: CW * (rs.halfTableW || 0.52), h: Math.max(1, hb - ht) };
2642
2586
  }
2643
2587
  if ((type === 'halftable') && (slot === 'right' || slot === 'secondary')) {
2644
2588
  var rs2 = PT.research || {};
2645
- return { x: MX + CW * (rs2.halfChartX || 0.57), y: topDefault, w: CW * (rs2.halfChartW || 0.43), h: Math.max(1, bottomDefault - topDefault) };
2589
+ var ht2 = opts.top != null ? opts.top : topDefault;
2590
+ var hb2 = opts.bottom != null ? opts.bottom : bottomDefault;
2591
+ return { x: MX + CW * (rs2.halfChartX || 0.57), y: ht2, w: CW * (rs2.halfChartW || 0.43), h: Math.max(1, hb2 - ht2) };
2646
2592
  }
2647
2593
  if (type === 'matrix' && slot === 'primary') {
2648
2594
  var rm = PT.research || {};
@@ -2663,7 +2609,7 @@ function regionOf(pageType, slotId, opts) {
2663
2609
  /* __TOPPPT_SCHEMA_START__ */
2664
2610
  /* ── 由 scripts/sync_runtime.py 从 scripts/model-schema.json 注入 · 禁止手改 ── */
2665
2611
  /* DSL schema 单源:浏览器端 validateModel 与 scripts/extract_model.py 消费同一份定义 */
2666
- var MODEL_SCHEMA = {"version":"0.1","modes":["presentation","research","architecture"],"model":{"required":["title","sections:array","closing.title","closing.points:array"],"optional":["mode","style","theme","subtitle","meta","agenda:array"],"agendaMin":{"presentation":3,"research":3,"architecture":0},"sectionsMin":1,"sectionsRecommended":3,"agendaComfortMax":16},"commonSectionFields":["eyebrow","title","lead","soWhat","footnote","flags","image","exhibitNo","layoutPreset"],"flagsHint":"flags = 待核实/待二次修改条目字符串数组(如 '2027 增速 xx%(口径未定)');渲染为 accent 强调色标注行,提示用户核对。","imageHint":"image = 素材图片/配图占位对象。三选一必填:src(用户图,data: 内联或相对路径,零外链铁律禁 http(s))|items(多图版式:grid/compare/wall,元素 {src?, alt?, caption?, placeholder?})|placeholder:true(无图时出配图占位,原生形状渲染、pictures 不增)。其余可选:layout(full/half/bleed/grid/compare/wall,见 layout-constants.json imageSpec.layouts)、fit(cover 默认 / contain)、caption、alt、hint、ratio。","imageLayoutHint":"layout 与 HTML 版式对应:full=版心全宽图|half=左图右注(points 为右栏注解)|bleed=通栏出血|grid=多图网格(items 2/3/4/6 张)|compare=双图 A/B 对比(items 2 张)|wall=Logo 墙(items 3–12 张小图)。占位符标签文本由双引擎按 imageSpec 拼同一串,保证 A/B 通道逐页文本一致。","chartTypes":["bar","hbar","stack","stackline","line","dualline","area","donut","multidonut","pie","radar","scatter","bubble","waterfall","gauge","pareto","funnel","gantt","vsbar","progress","sparkline","slope","dumbbell","lollipop","dotplot","bulletchart","waffle","radialbar","rose","candlestick"],"chartTypesHint":"chart.type 可取值 = 本表(30 类:16 原生 + 14 形状还原)。其余 6 类复杂信息图(sankey/treemap/boxplot/network/marimekko/streamgraph)是**专属页型**而非 chart.type——它们要按列/段/节点等结构化载荷表达,故走 sections[].type。不变量:charts.registry.types == chartTypes ∪ 上述 6 类页型(sync_runtime.py 校验)。","chartDataTable":{"enum":["notes","inline","appendix","off"],"default":"notes","rule":"非原生图表(registry.pptx=shape)的 dataTable 不得为 off;缺失时按 registry 默认值补齐。"},"pageTypes":{"points":{"label":"要点列表页","modes":["presentation","research","architecture"],"required":["points:array"],"optional":["metrics:array"]},"metrics":{"label":"指标带页(4–6 个核心数字)","modes":["presentation","research"],"required":["metrics:array"]},"kpi":{"label":"大数指标页(hero 大数字 + 支撑指标行)","modes":["presentation","research"],"required":["hero:array"],"optional":["metrics:array"]},"table":{"label":"对比表页","modes":["presentation","research","architecture"],"required":["table.head:array","table.rows:array"],"optional":["table.colW:array"]},"timeline":{"label":"时间线 / 路线页","modes":["presentation","research"],"required":["phases:array"]},"steps":{"label":"步骤条页(N 步横排 + 箭头,可分组)","modes":["presentation","research","architecture"],"required":["steps:array"],"optional":["groups:array","note"]},"bar":{"label":"图表页(chart.type 见 chartTypes;native 通道走原生数据图表,shape 通道走高保真形状还原 + 数据表)","modes":["presentation","research"],"required":["chart.labels:array","chart.values:array"],"optional":["chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.start:array","chart.target:array","chart.dataTable","note"]},"donut":{"label":"环形图页(原生 pie 楔形 + 图例)","modes":["presentation","research"],"required":["chart.labels:array","chart.values:array"],"optional":["chart.unit","chart.centerLabel","chart.colors:array","chart.dataTable","note"]},"heatmap":{"label":"热力矩阵页(行 × 列 + 强度色阶)","modes":["presentation","research"],"required":["rowHeads:array","colHeads:array","cells:array"],"optional":["unit","scaleLabel:array","note"]},"bullet":{"label":"达成对比页(实际 vs 目标条)","modes":["presentation","research"],"required":["items:array"],"optional":["unit","max","note"]},"pyramid":{"label":"金字塔页(层级递进,顶层最窄)","modes":["presentation","research","architecture"],"required":["levels:array"],"optional":["note"]},"image":{"label":"素材图片页(full/half/bleed/grid/compare/wall,效果与位置锁定;支持配图占位)","modes":["presentation","research","architecture"],"required":["anyof:image.src:str|image.items:array|image.placeholder"],"optional":["image.caption","image.alt","image.layout","image.fit","image.ratio","image.hint","points:array","note"]},"cards":{"label":"卡片网格页(cards 元素须为 {title, points:[[k,v]…]},不接受元组)","modes":["presentation","research"],"required":["cards:array"],"optional":["columns"]},"split":{"label":"双区组合页(left / right 各可为 要点|图表|表格|图片:type = points(默认)| table | image | 图表类型名;图表/表格字段直接挂在对应侧)","modes":["presentation","research"],"required":["anyof:left.points:array|left.type:str"],"optional":["left.cap","left.image","left.labels:array","left.values:array","left.series:array","left.points:array","left.max","left.unit","left.colors:array","left.dataTable","left.head:array","left.rows:array","left.colW:array","right.type","right.cap","right.image","right.labels:array","right.values:array","right.series:array","right.points:array","right.max","right.unit","right.colors:array","right.dataTable","right.head:array","right.rows:array","right.colW:array"]},"comparison":{"label":"对比页(左右双栏 + 可选结论条)","modes":["presentation","research"],"required":["left.title","left.points:array","right.title","right.points:array"],"optional":["verdict"]},"quote":{"label":"引用 / 金句页(深色全幅)","modes":["presentation","research"],"required":["quote","author"],"optional":["context"]},"diagram":{"label":"分层架构页(architecture 模式走全幅几何)","modes":["presentation","research","architecture"],"required":["layers:array"],"optional":["legend:array"]},"exhibit":{"label":"Exhibit 编号图表页(research R2)","modes":["research"],"required":["chart.labels:array","chart.values:array"],"optional":["exhibitNo","chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.dataTable","note"]},"twocol":{"label":"双栏论证页(research R1)","modes":["research"],"required":["paragraphs:array"]},"threecol":{"label":"三栏证据页(research R6)","modes":["research"],"required":["paragraphs:array"]},"halftable":{"label":"半表半图页(research R7)","modes":["research"],"required":["table.head:array","table.rows:array","chart.labels:array","chart.values:array"],"optional":["table.colW:array","chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.dataTable","note"]},"matrix":{"label":"矩阵图页(research R8)","modes":["research"],"required":["rowHeads:array","colHeads:array","cells:array"]},"lane":{"label":"泳道页(architecture A2)","modes":["architecture"],"required":["lanes:array"]},"sankey":{"label":"桑基图页(节点-流带,流向与流量)","modes":["research","architecture"],"required":["flows:array"],"optional":["unit","chart.dataTable","note"]},"treemap":{"label":"树图页(面积编码的层级构成)","modes":["research","architecture"],"required":["items:array"],"optional":["unit","chart.dataTable","note"]},"boxplot":{"label":"箱线图页(分布对比:min/q1/median/q3/max)","modes":["research","architecture"],"required":["groups:array"],"optional":["unit","chart.dataTable","note"]},"network":{"label":"关系网络页(节点-边拓扑)","modes":["research","architecture"],"required":["nodes:array","edges:array"],"optional":["chart.dataTable","note"]},"marimekko":{"label":"马赛克图页(列宽 × 列高双重编码)","modes":["research","architecture"],"required":["cols:array","cells:array"],"optional":["unit","chart.dataTable","note"]},"streamgraph":{"label":"流带图页(时间上的构成演变)","modes":["research","architecture"],"required":["series:array"],"optional":["labels:array","chart.dataTable","note"]}}};
2612
+ var MODEL_SCHEMA = {"version":"0.1","modes":["presentation","research","architecture"],"model":{"required":["title","sections:array","closing.title","closing.points:array"],"optional":["mode","style","theme","subtitle","meta","agenda:array"],"agendaMin":{"presentation":3,"research":3,"architecture":0},"agendaMax":7,"agendaMaxWithRefs":8,"agendaHint":"agenda 条目 = 章(篇/section),3–7 条;每章可含多页(sections[] 按页建模)。禁止把逐页标题当大纲。sections[].eyebrow 的 `NN ·` 前缀 = 章键,须与某条 agenda 对应;跳转锚点 = 该章第一页。含「参考资料」条目时 +1 仍 ≤8。","sectionsMin":1,"sectionsRecommended":3,"agendaComfortMax":8},"commonSectionFields":["eyebrow","title","lead","soWhat","footnote","flags","image","exhibitNo","layoutPreset"],"mutualExclusionHint":"verdict 与 soWhat 互斥:二者共用 annotation 结论条槽位,同页双填必叠印。comparison 页填 verdict 时不要再填 soWhat(渲染器已自动二选一,但模型侧应只给一个)。","flagsHint":"flags = 待核实/待二次修改条目字符串数组(如 '2027 增速 xx%(口径未定)');渲染为 accent 强调色标注行,提示用户核对。","imageHint":"image = 素材图片/配图占位对象。三选一必填:src(用户图,data: 内联或相对路径,零外链铁律禁 http(s))|items(多图版式:grid/compare/wall,元素 {src?, alt?, caption?, placeholder?})|placeholder:true(无图时出配图占位,原生形状渲染、pictures 不增)。其余可选:layout(full/half/bleed/grid/compare/wall,见 layout-constants.json imageSpec.layouts)、fit(cover 默认 / contain)、caption、alt、hint、ratio。","imageLayoutHint":"layout 与 HTML 版式对应:full=版心全宽图|half=左图右注(points 为右栏注解)|bleed=通栏出血|grid=多图网格(items 2/3/4/6 张)|compare=双图 A/B 对比(items 2 张)|wall=Logo 墙(items 3–12 张小图)。占位符标签文本由双引擎按 imageSpec 拼同一串,保证 A/B 通道逐页文本一致。","chartTypes":["bar","hbar","stack","stackline","line","dualline","area","donut","multidonut","pie","radar","scatter","bubble","waterfall","gauge","pareto","funnel","gantt","vsbar","progress","sparkline","slope","dumbbell","lollipop","dotplot","bulletchart","waffle","radialbar","rose","candlestick"],"chartTypesHint":"chart.type 可取值 = 本表(30 类:16 原生 + 14 形状还原)。其余 6 类复杂信息图(sankey/treemap/boxplot/network/marimekko/streamgraph)是**专属页型**而非 chart.type——它们要按列/段/节点等结构化载荷表达,故走 sections[].type。不变量:charts.registry.types == chartTypes ∪ 上述 6 类页型(sync_runtime.py 校验)。","chartDataTable":{"enum":["notes","inline","appendix","off"],"default":"notes","rule":"非原生图表(registry.pptx=shape)的 dataTable 不得为 off;缺失时按 registry 默认值补齐。"},"pageTypes":{"points":{"label":"要点列表页","modes":["presentation","research","architecture"],"required":["points:array"],"optional":["metrics:array"]},"metrics":{"label":"指标带页(4–6 个核心数字)","modes":["presentation","research"],"required":["metrics:array"]},"kpi":{"label":"大数指标页(hero 大数字 + 支撑指标行)","modes":["presentation","research"],"required":["hero:array"],"optional":["metrics:array"]},"table":{"label":"对比表页","modes":["presentation","research","architecture"],"required":["table.head:array","table.rows:array"],"optional":["table.colW:array"]},"timeline":{"label":"时间线 / 路线页","modes":["presentation","research"],"required":["phases:array"]},"steps":{"label":"步骤条页(N 步横排 + 箭头,可分组)","modes":["presentation","research","architecture"],"required":["steps:array"],"optional":["groups:array","note"]},"bar":{"label":"图表页(chart.type 见 chartTypes;native 通道走原生数据图表,shape 通道走高保真形状还原 + 数据表)","modes":["presentation","research"],"required":["chart.labels:array","chart.values:array"],"optional":["chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.start:array","chart.target:array","chart.dataTable","note"]},"donut":{"label":"环形图页(原生 pie 楔形 + 图例)","modes":["presentation","research"],"required":["chart.labels:array","chart.values:array"],"optional":["chart.unit","chart.centerLabel","chart.colors:array","chart.dataTable","note"]},"heatmap":{"label":"热力矩阵页(行 × 列 + 强度色阶)","modes":["presentation","research"],"required":["rowHeads:array","colHeads:array","cells:array"],"optional":["unit","scaleLabel:array","note"]},"bullet":{"label":"达成对比页(实际 vs 目标条)","modes":["presentation","research"],"required":["items:array"],"optional":["unit","max","note"]},"pyramid":{"label":"金字塔页(层级递进,顶层最窄)","modes":["presentation","research","architecture"],"required":["levels:array"],"optional":["note"]},"image":{"label":"素材图片页(full/half/bleed/grid/compare/wall,效果与位置锁定;支持配图占位)","modes":["presentation","research","architecture"],"required":["anyof:image.src:str|image.items:array|image.placeholder"],"optional":["image.caption","image.alt","image.layout","image.fit","image.ratio","image.hint","points:array","note"]},"cards":{"label":"卡片网格页(cards 元素须为 {title, points:[[k,v]…], icon?},不接受元组)","modes":["presentation","research"],"required":["cards:array"],"optional":["columns"],"cardItemHint":"cards[] 元素:{title:str, points:[[k,v]…]|[{t,d}…]|[str…], icon?:str}。icon = 语义图标名(icon_lib.js 键:增长/下降/数据/图表/趋势/占比/表格/效率/成果/安全/权限/检查/风险/团队/流程/计划/智能/洞察/工具/清单),HTML 与 PPTX 同名真导出;缺省按标题语义自动挑选。"},"split":{"label":"双区组合页(left / right 各可为 要点|图表|表格|图片:type = points(默认)| table | image | 图表类型名;图表/表格字段直接挂在对应侧)","modes":["presentation","research"],"required":["anyof:left.points:array|left.type:str"],"optional":["left.cap","left.image","left.labels:array","left.values:array","left.series:array","left.points:array","left.max","left.unit","left.colors:array","left.dataTable","left.head:array","left.rows:array","left.colW:array","right.type","right.cap","right.image","right.labels:array","right.values:array","right.series:array","right.points:array","right.max","right.unit","right.colors:array","right.dataTable","right.head:array","right.rows:array","right.colW:array"]},"comparison":{"label":"对比页(左右双栏 + 可选结论条)","modes":["presentation","research"],"required":["left.title","left.points:array","right.title","right.points:array"],"optional":["verdict"]},"quote":{"label":"引用 / 金句页(深色全幅)","modes":["presentation","research"],"required":["quote","author"],"optional":["context"]},"diagram":{"label":"分层架构页(architecture 模式走全幅几何)","modes":["presentation","research","architecture"],"required":["layers:array"],"optional":["legend:array"]},"exhibit":{"label":"Exhibit 编号图表页(research R2)","modes":["research"],"required":["chart.labels:array","chart.values:array"],"optional":["exhibitNo","chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.dataTable","note"]},"twocol":{"label":"双栏论证页(research R1)","modes":["research"],"required":["paragraphs:array"]},"threecol":{"label":"三栏证据页(research R6)","modes":["research"],"required":["paragraphs:array"]},"halftable":{"label":"半表半图页(research R7)","modes":["research"],"required":["table.head:array","table.rows:array","chart.labels:array","chart.values:array"],"optional":["table.colW:array","chart.type","chart.series:array","chart.points:array","chart.max","chart.unit","chart.colors:array","chart.dataTable","note"]},"matrix":{"label":"矩阵图页(research R8)","modes":["research"],"required":["rowHeads:array","colHeads:array","cells:array"]},"lane":{"label":"泳道页(architecture A2)","modes":["architecture"],"required":["lanes:array"]},"sankey":{"label":"桑基图页(节点-流带,流向与流量)","modes":["research","architecture"],"required":["flows:array"],"optional":["unit","chart.dataTable","note"]},"treemap":{"label":"树图页(面积编码的层级构成)","modes":["research","architecture"],"required":["items:array"],"optional":["unit","chart.dataTable","note"]},"boxplot":{"label":"箱线图页(分布对比:min/q1/median/q3/max)","modes":["research","architecture"],"required":["groups:array"],"optional":["unit","chart.dataTable","note"]},"network":{"label":"关系网络页(节点-边拓扑)","modes":["research","architecture"],"required":["nodes:array","edges:array"],"optional":["chart.dataTable","note"]},"marimekko":{"label":"马赛克图页(列宽 × 列高双重编码)","modes":["research","architecture"],"required":["cols:array","cells:array"],"optional":["unit","chart.dataTable","note"]},"streamgraph":{"label":"流带图页(时间上的构成演变)","modes":["research","architecture"],"required":["series:array"],"optional":["labels:array","chart.dataTable","note"]}}};
2667
2613
  /* __TOPPPT_SCHEMA_END__ */
2668
2614
 
2669
2615
  var _mode = 'presentation'; /* 当前模式(slidesOf 里按 model.mode 设置) */
@@ -2954,6 +2900,15 @@ function footnoteLine(sh, text, S) {
2954
2900
  sh.push(txSp(R.x, R.y, R.w, R.h,
2955
2901
  [[{ t: text, sz: 9.5, col: S.faint, font: S.font }]]));
2956
2902
  }
2903
+ /* R2:sec.note 与 sec.footnote 共用注释带末行(footnoteY=6.72)。
2904
+ note.y=6.55 会压进 so-what 带(6.05–6.67)——同页二者必须合并为一行。 */
2905
+ function noteOrFootnote(sh, sec, S) {
2906
+ var parts = [];
2907
+ if (sec && sec.note) parts.push(String(sec.note));
2908
+ if (sec && sec.footnote) parts.push(String(sec.footnote));
2909
+ if (!parts.length) return;
2910
+ footnoteLine(sh, parts.join(' · '), S);
2911
+ }
2957
2912
  /* 待核实清单条(accent 强调色标注 · 与 build_pptx.js / HTML .flagbar 同源) */
2958
2913
  function flagBar(sh, items, S, yTop) {
2959
2914
  var F = PT.flagbar || { hdH: 0.26, rowH: 0.24, maxRows: 3, gap: 0.12 };
@@ -3142,7 +3097,9 @@ function vbarShapes(sh, ec, S, x, y, w, h, dcols) {
3142
3097
  : [{ name: '数值', values: ec.values || [] }];
3143
3098
  var nb = Math.max(1, labels.length);
3144
3099
  var ns = Math.max(1, series.length);
3145
- var baseY = y + h, plotW = w, step = plotW / nb;
3100
+ /* R2:类目标签带必须含在 h 内(原 baseY+0.08 画在图区外,会压进 so-what/来源行) */
3101
+ var labelH = 0.36;
3102
+ var baseY = y + Math.max(0.6, h - labelH), plotW = w, step = plotW / nb;
3146
3103
  var cluster = Math.min(1.1, step * (ns > 1 ? 0.78 : 0.55));
3147
3104
  var bw = cluster / ns;
3148
3105
  var all = [];
@@ -3151,26 +3108,27 @@ function vbarShapes(sh, ec, S, x, y, w, h, dcols) {
3151
3108
  });
3152
3109
  var vmax = ec.max || Math.max.apply(null, all.concat([1]));
3153
3110
  var top = all.length ? Math.max.apply(null, all) : 0;
3111
+ var plotH = Math.max(0.35, baseY - y);
3154
3112
  sh.push(shape('rect', x, baseY, plotW, 0.02, S.line));
3155
3113
  series.forEach(function (se, si) {
3156
3114
  var vals = se.values || [];
3157
3115
  var col = dcols ? dcols[si % 5] : (si === 0 ? S.accent : S.faint);
3158
3116
  vals.forEach(function (v, i) {
3159
3117
  var num = Number(v) || 0;
3160
- var hh = Math.max(0.05, num / vmax * (h - 0.5));
3118
+ var hh = Math.max(0.05, num / vmax * (plotH - 0.35));
3161
3119
  var bx = x + i * step + (step - cluster) / 2 + si * bw;
3162
3120
  var hot = ns === 1 && num === top;
3163
3121
  sh.push(shape('roundRect', bx, baseY - hh, Math.max(0.04, bw * 0.92), hh,
3164
3122
  hot ? (dcols ? dcols[i % 5] : S.accent) : col, { adj: 6000 }));
3165
3123
  if (ns === 1) {
3166
- sh.push(txSp(bx - 0.3, baseY - hh - 0.4, bw + 0.6, 0.32,
3124
+ sh.push(txSp(bx - 0.3, baseY - hh - 0.36, bw + 0.6, 0.30,
3167
3125
  [[{ t: valText(num, ec.unit), sz: 12.5, b: 1, col: hot ? S.accent : S.body, font: S.font }]], { align: 'ctr' }));
3168
3126
  }
3169
3127
  });
3170
3128
  });
3171
3129
  labels.forEach(function (lb, i) {
3172
3130
  var lx = x + i * step;
3173
- sh.push(txSp(lx, baseY + 0.08, step, 0.32,
3131
+ sh.push(txSp(lx, baseY + 0.06, step, labelH - 0.08,
3174
3132
  [[{ t: lb, sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
3175
3133
  });
3176
3134
  /* Multi-series legend along top of plot (keeps category labels; avoids blank chart). */
@@ -3193,7 +3151,10 @@ function lineShapes(sh, ec, S, x, y, w, h, dcols) {
3193
3151
  var all = [];
3194
3152
  series.forEach(function (se) { (se.values || []).forEach(function (v) { all.push(Number(v) || 0); }); });
3195
3153
  var vmax = ec.max || Math.max.apply(null, all.concat([1]));
3196
- var plotH = h - 0.5, baseY = y + h;
3154
+ /* R2:类目标签带含在 h 内,禁画到图区外压 so-what */
3155
+ var labelH = 0.36;
3156
+ var baseY = y + Math.max(0.6, h - labelH);
3157
+ var plotH = Math.max(0.35, baseY - y - 0.2);
3197
3158
  sh.push(shape('rect', x, baseY, w, 0.02, S.line));
3198
3159
  var stepX = n > 1 ? w / (n - 1) : 0;
3199
3160
  series.forEach(function (se, si) {
@@ -3213,7 +3174,7 @@ function lineShapes(sh, ec, S, x, y, w, h, dcols) {
3213
3174
  });
3214
3175
  labels.forEach(function (lb, i) {
3215
3176
  var px = x + (n > 1 ? i * stepX : w / 2);
3216
- sh.push(txSp(px - 0.5, baseY + 0.08, 1.0, 0.32,
3177
+ sh.push(txSp(px - 0.5, baseY + 0.06, 1.0, labelH - 0.08,
3217
3178
  [[{ t: lb, sz: 10.5, col: S.faint, font: S.font }]], { align: 'ctr' }));
3218
3179
  });
3219
3180
  }
@@ -3665,25 +3626,44 @@ function slidesOf(model, S) {
3665
3626
  c.push(txSp(MX, CV.subtitleY, CW - 1, CV.subtitleH, [[{ t: model.subtitle || '', sz: 18, col: S.soft, font: S.font }]]));
3666
3627
  slides.push(c);
3667
3628
 
3668
- /* Agenda(>8 条自动双列,行高自适应防溢出;architecture 极简形态可省略 agenda) */
3629
+ /* Agenda(>8 条自动双列;>12 条自动分页;长标题截断+全称入 notes;列优先与 HTML 一致) */
3669
3630
  var items = model.agenda || [];
3670
3631
  if (items.length) {
3671
- var ag = [];
3672
- head(ag, 'AGENDA', '报告大纲');
3673
- var colN = items.length > 8 ? 2 : 1;
3674
- var perCol = Math.ceil(items.length / colN) || 1;
3675
- var rowH = Math.min(1.05, (CONTENT_BOTTOM - CONTENT_TOP - 0.25) / Math.max(1, perCol));
3676
- var numSz = rowH >= 0.85 ? 30 : (rowH >= 0.65 ? 22 : 18);
3677
- var tSz = rowH >= 0.85 ? 16 : 14, dSz = rowH >= 0.85 ? 12 : 11;
3678
- items.forEach(function (it, i) {
3679
- var col = Math.floor(i / perCol), row = i % perCol;
3680
- var x = MX + col * (CW / colN), y = CONTENT_TOP + row * rowH;
3681
- ag.push(txSp(x, y, 0.9, Math.min(0.9, rowH), [[{ t: it[0], sz: numSz, b: 1, col: S.accent, font: S.font }]]));
3682
- ag.push(txSp(x + 1.0, y + 0.03, CW / colN - 1.1, Math.min(0.95, rowH),
3683
- [[{ t: it[1], sz: tSz, b: 1, col: S.ink, font: S.font }],
3684
- [{ t: it[2] || '', sz: dSz, col: S.body, font: S.font }]], { lineSpacing: tSz + 5 }));
3632
+ var ROWS_PER_PAGE = 12;
3633
+ var agPages = [];
3634
+ for (var ai = 0; ai < items.length; ai += ROWS_PER_PAGE) agPages.push(items.slice(ai, ai + ROWS_PER_PAGE));
3635
+ agPages.forEach(function (pageItems, pi) {
3636
+ var ag = [];
3637
+ var sub = agPages.length > 1 ? '(' + (pi + 1) + '/' + agPages.length + ')' : '';
3638
+ head(ag, 'AGENDA', '报告大纲' + sub);
3639
+ var colN = pageItems.length > 8 ? 2 : 1;
3640
+ var perCol = Math.ceil(pageItems.length / colN) || 1;
3641
+ var rowH = Math.min(1.05, (CONTENT_BOTTOM - CONTENT_TOP - 0.25) / Math.max(1, perCol));
3642
+ var numSz = rowH >= 0.85 ? 30 : (rowH >= 0.65 ? 22 : 18);
3643
+ var tSz = rowH >= 0.85 ? 16 : 14, dSz = rowH >= 0.85 ? 12 : 11;
3644
+ var agNotes = [];
3645
+ pageItems.forEach(function (it, i) {
3646
+ var col = Math.floor(i / perCol), row = i % perCol;
3647
+ var x = MX + col * (CW / colN), y = CONTENT_TOP + row * rowH;
3648
+ var titleBoxW = CW / colN - 1.15;
3649
+ var rawTitle = String(it[1] || '');
3650
+ var titleEstW = estTextH(rawTitle, titleBoxW, tSz, 1.2);
3651
+ var maxTitleH = rowH * 0.55;
3652
+ var title = rawTitle;
3653
+ if (titleEstW > maxTitleH) {
3654
+ var maxChars = Math.max(10, Math.floor(rawTitle.length * (maxTitleH / titleEstW)));
3655
+ if (rawTitle.length > maxChars) {
3656
+ title = rawTitle.slice(0, maxChars - 1) + '…';
3657
+ agNotes.push('条目 ' + it[0] + ' 全称:' + rawTitle);
3658
+ }
3659
+ }
3660
+ ag.push(txSp(x, y, 0.9, Math.min(0.9, rowH), [[{ t: it[0], sz: numSz, b: 1, col: S.accent, font: S.font }]]));
3661
+ ag.push(txSp(x + 1.0, y + 0.03, titleBoxW, Math.min(0.95, rowH),
3662
+ [[{ t: title, sz: tSz, b: 1, col: S.ink, font: S.font }],
3663
+ [{ t: it[2] || '', sz: dSz, col: S.body, font: S.font }]], { lineSpacing: tSz + 5 }));
3664
+ });
3665
+ slides.push(ag);
3685
3666
  });
3686
- slides.push(ag);
3687
3667
  }
3688
3668
 
3689
3669
  /* 章节页 */
@@ -3769,12 +3749,13 @@ function slidesOf(model, S) {
3769
3749
  { t: p[1], sz: fz - 1, col: S.body, font: S.font }]]));
3770
3750
  });
3771
3751
  });
3752
+ /* R2:verdict 与 soWhat 共用 annotation 槽位——只画一个(verdict 优先) */
3772
3753
  if (sec.verdict) {
3773
3754
  var vR = regOf('exhibit', 'annotation') || { x: MX, y: PT.exhibit.soWhatY, w: CW, h: 0.62 };
3774
- sh.push(shape('rect', vR.x, vR.y, vR.w, vR.h, S.accent));
3755
+ sh.push(shape('rect', vR.x, vR.y, vR.w, vR.h, S.accent, { name: 'tr:soWhat' }));
3775
3756
  sh.push(txSp(vR.x + 0.22, vR.y + 0.06, vR.w - 0.44, vR.h - 0.12,
3776
3757
  [[{ t: '结论 ', sz: 11, b: 1, col: S.onAccent, font: S.font, spc: 150 },
3777
- { t: sec.verdict, sz: 12.5, b: 1, col: S.onAccent, font: S.font }]], { anchor: 'ctr' }));
3758
+ { t: sec.verdict, sz: 12.5, b: 1, col: S.onAccent, font: S.font }]], { anchor: 'ctr', name: 'tr:soWhat' }));
3778
3759
  }
3779
3760
  } else if (type === 'quote') {
3780
3761
  var Q = PT.quote;
@@ -3807,7 +3788,6 @@ function slidesOf(model, S) {
3807
3788
  } else if (type === 'donut') {
3808
3789
  var dcn = sec.chart || {};
3809
3790
  if (dcn.labels && dcn.values) donutChart(sh, dcn, S, dcn.colors || donutColors(model.style, S, model.theme), bodyBottom);
3810
- 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 }]]));
3811
3791
  } else if (type === 'heatmap') {
3812
3792
  var H = PT.heatmap;
3813
3793
  var hR = regOf('heatmap', 'primary', { bottom: bodyBottom }) || { x: MX, y: H.y, w: CW, h: bodyBottom - H.y };
@@ -3954,7 +3934,7 @@ function slidesOf(model, S) {
3954
3934
  } else if (type === 'bar') {
3955
3935
  var ch = sec.chart || {};
3956
3936
  var dcols2 = (ch.colors || dataColors(model.style, model.theme));
3957
- var botY = chartBottom(!!sec.soWhat, !!sec.footnote) - (sec.note ? 0.42 : 0.05);
3937
+ var botY = chartBottom(!!sec.soWhat, !!(sec.footnote || sec.note)) - 0.05;
3958
3938
  var isHBar = ch.type === 'hbar';
3959
3939
  var bRR = regOf('bar', isHBar ? 'hbar' : 'primary', { bottom: botY }) ||
3960
3940
  { x: isHBar ? MX : MX + PT.bar.chartX, y: isHBar ? PT.bar.hbarY0 : PT.bar.chartY,
@@ -3981,13 +3961,12 @@ function slidesOf(model, S) {
3981
3961
  } else {
3982
3962
  chartBlockShapes(sh, ch, S, bx, bRR.y, bw, Math.max(1.5, bRR.h), dcols2);
3983
3963
  }
3984
- 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 }]]));
3985
3964
  } else if (type === 'twocol' || type === 'threecol') {
3986
3965
  var ps2 = sec.paragraphs || [];
3987
3966
  var nCol = (type === 'threecol') ? 3 : 2;
3988
3967
  var gapC = (type === 'threecol') ? PT.research.col3Gap : PT.twocol.colGap;
3989
- var tcR = regOf('twocol', 'primary', { top: bodyY, bottom: bodyBottom }) ||
3990
- { x: MX, y: bodyY, w: CW, h: bodyBottom - bodyY };
3968
+ /* R3:多栏均分用版心全宽(regOf('twocol') 返回单栏宽,当总宽会压扁三栏) */
3969
+ var tcR = { x: MX, y: bodyY, w: CW, h: bodyBottom - bodyY };
3991
3970
  var gC = cols(tcR.w, nCol, gapC);
3992
3971
  var perC = Math.ceil(ps2.length / nCol);
3993
3972
  var availC = tcR.h;
@@ -4183,7 +4162,7 @@ function slidesOf(model, S) {
4183
4162
  var dStart = dgR.y;
4184
4163
  var dEnd = dgR.y + dgR.h;
4185
4164
  var nLay = Math.max(1, lys.length);
4186
- var lh2 = Math.max(0.6, Math.min(D.maxLayerH, (dEnd - dStart) / nLay - D.layerGap));
4165
+ var lh2 = Math.max(0.5, Math.min(D.maxLayerH, (dEnd - dStart) / nLay - D.layerGap));
4187
4166
  lys.forEach(function (lay, li) {
4188
4167
  var y9 = dStart + li * (lh2 + D.layerGap);
4189
4168
  var focus = lay[2] === 'focus';
@@ -4199,9 +4178,26 @@ function slidesOf(model, S) {
4199
4178
  var ntt = isRec(nd) ? nd.t : nd;
4200
4179
  var nds = isRec(nd) ? (nd.d || '') : '';
4201
4180
  sh.push(shape('roundRect', x10, y9, nw2, lh2, ndacc ? S.soft : S.surface, { adj: 4000, line: S.line }));
4202
- sh.push(txSp(x10 + 0.12, y9 + (nds ? 0.12 : lh2 / 2 - 0.2), nw2 - 0.24, 0.38,
4203
- [[{ t: ntt, sz: 12.5, b: 1, col: ndacc ? S.accent : S.ink, font: S.font }]], { anchor: nds ? 't' : 'ctr' }));
4204
- if (nds) sh.push(txSp(x10 + 0.12, y9 + lh2 - 0.5, nw2 - 0.24, 0.4, [[{ t: nds, sz: 10, col: S.faint, font: S.font }]]));
4181
+ /* R1: 注解不得「浮回」标题上。标题顶对齐,注解钳在标题下边;空间不足降级单框混排。 */
4182
+ var padXn = 0.12, padYn = 0.10;
4183
+ var innerWn = nw2 - padXn * 2;
4184
+ var titleHn = 0.32, noteHn = 0.34, gapTNn = 0.04;
4185
+ var needHn = titleHn + gapTNn + (nds ? noteHn : 0) + padYn * 2;
4186
+ if (!nds || lh2 >= needHn) {
4187
+ var tYn = y9 + padYn;
4188
+ sh.push(txSp(x10 + padXn, nds ? tYn : y9 + lh2 / 2 - 0.18, innerWn, titleHn,
4189
+ [[{ t: ntt, sz: nds ? 11 : 12.5, b: 1, col: ndacc ? S.accent : S.ink, font: S.font }]],
4190
+ { anchor: 'ctr' }));
4191
+ if (nds) {
4192
+ var nYn = Math.max(tYn + titleHn + gapTNn, y9 + lh2 - padYn - noteHn);
4193
+ sh.push(txSp(x10 + padXn, nYn, innerWn, Math.min(noteHn, y9 + lh2 - padYn - nYn),
4194
+ [[{ t: nds, sz: 10, col: S.faint, font: S.font }]], { anchor: 't' }));
4195
+ }
4196
+ } else {
4197
+ sh.push(txSp(x10 + padXn, y9 + padYn * 0.5, innerWn, lh2 - padYn,
4198
+ [[{ t: ntt, sz: 11, b: 1, col: ndacc ? S.accent : S.ink, font: S.font }],
4199
+ [{ t: nds, sz: 9, col: S.faint, font: S.font }]], { anchor: 't', lineSpacing: 12 }));
4200
+ }
4205
4201
  });
4206
4202
  if (li < lys.length - 1) {
4207
4203
  var cy2 = y9 + lh2 + D.layerGap / 2;
@@ -4211,10 +4207,14 @@ function slidesOf(model, S) {
4211
4207
  }
4212
4208
  });
4213
4209
  if (sec.legend) {
4214
- var lx2 = MX;
4215
- sec.legend.forEach(function (lg2) {
4216
- sh.push(txSp(lx2, PH - 0.62, 3.2, 0.3, [[{ t: '● ' + lg2, sz: 10, col: S.faint, font: S.font }]]));
4217
- lx2 += 2.0;
4210
+ /* R2:图例进图区底部(与 HTML .arch__legend 同源),禁用 PH-0.62 固定偏移 */
4211
+ var lgH2 = 0.28;
4212
+ var lgY2 = Math.max(dStart, bodyBottom - lgH2 - 0.02);
4213
+ var nLg2 = Math.max(1, sec.legend.length);
4214
+ var step2 = Math.min(2.4, CW / nLg2);
4215
+ sec.legend.forEach(function (lg2, li2) {
4216
+ sh.push(txSp(MX + CW - nLg2 * step2 + li2 * step2, lgY2, step2 - 0.05, lgH2,
4217
+ [[{ t: '● ' + lg2, sz: 10, col: S.faint, font: S.font }]]));
4218
4218
  });
4219
4219
  }
4220
4220
  } else if (type === 'exhibit') {
@@ -4271,8 +4271,10 @@ function slidesOf(model, S) {
4271
4271
  }
4272
4272
  }
4273
4273
  /* research 通用可选件:so-what 结论条 + 页脚来源行 + 待核实条(共用同一槽位) */
4274
- if (sec.soWhat) soWhatBar(sh, sec.soWhat, S);
4275
- if (sec.footnote) footnoteLine(sh, sec.footnote, S);
4274
+ /* R2:verdict 已占 annotation 槽位时跳过 soWhat,禁止同槽双条叠印 */
4275
+ if (sec.soWhat && !sec.verdict) soWhatBar(sh, sec.soWhat, S);
4276
+ /* R2:note 与 footnote 共用注释带末行(禁 note.y=6.55 压 so-what) */
4277
+ noteOrFootnote(sh, sec, S);
4276
4278
  if (flagH) flagBar(sh, flagItems, S, flagY);
4277
4279
  slides.push(sh);
4278
4280
  });
@@ -4442,9 +4444,10 @@ function validateModel(model) {
4442
4444
  }
4443
4445
  var agMax = (M.model && M.model.agendaComfortMax) || 16;
4444
4446
  if ((model.agenda || []).length > agMax) {
4445
- warnings.push('agenda ' + model.agenda.length + ' 条超出单页舒适上限 ' + agMax + ',建议拆分');
4447
+ warnings.push('agenda ' + model.agenda.length + ' 条超出单页舒适上限 ' + agMax + ',将自动分页');
4446
4448
  }
4447
- var pages = 1 + (hasAgenda ? 1 : 0) + secs.length + 1; /* 封面+大纲(可选)+章节+收尾 */
4449
+ var agPageCount = hasAgenda ? Math.ceil(model.agenda.length / 12) : 0;
4450
+ var pages = 1 + agPageCount + secs.length + 1; /* 封面+大纲(可多页)+章节+收尾 */
4448
4451
  return { ok: missing.length === 0, missing: missing, warnings: warnings, pages: pages };
4449
4452
  }
4450
4453