@taloswork/ose-shared 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/package.json +3 -3
  2. package/skills/document/SKILL.md +135 -219
  3. package/skills/document/art-directions/base.css +27 -2
  4. package/skills/document/art-directions/cinematic-depth.css +3 -1
  5. package/skills/document/art-directions/collage-paper.css +5 -1
  6. package/skills/document/art-directions/editorial-cut.css +5 -1
  7. package/skills/document/art-directions/geometric-pop.css +6 -0
  8. package/skills/document/art-directions/gradient-mesh.css +5 -1
  9. package/skills/document/art-directions/illustrated-doodle.css +5 -0
  10. package/skills/document/art-directions/luxury-ornament.css +4 -1
  11. package/skills/document/art-directions/maximalist-blocks.css +6 -0
  12. package/skills/document/art-directions/technical-grid.css +4 -0
  13. package/skills/document/assets/fonts/fonts.json +2 -2
  14. package/skills/document/assets/pdf-fonts/NotoSansSC-PDF-Bold.ttf +0 -0
  15. package/skills/document/assets/pdf-fonts/NotoSansSC-PDF-Regular.ttf +0 -0
  16. package/skills/document/assets/pdf-fonts/OFL.txt +93 -0
  17. package/skills/document/assets/pdf-fonts/README.md +35 -0
  18. package/skills/document/assets/tessdata/LICENSE-Apache-2.0.txt +202 -0
  19. package/skills/document/assets/tessdata/README.md +21 -0
  20. package/skills/document/assets/tessdata/chi_sim.traineddata.gz +0 -0
  21. package/skills/document/assets/tessdata/eng.traineddata.gz +0 -0
  22. package/skills/document/bin/deck-build.cjs +12563 -83
  23. package/skills/document/bin/deck-chart.cjs +771 -0
  24. package/skills/document/bin/deck-plan.cjs +12414 -0
  25. package/skills/document/bin/deck-qa.cjs +1075 -266
  26. package/skills/document/bin/deck-scenario.cjs +1363 -0
  27. package/skills/document/bin/deck-styles.cjs +1604 -0
  28. package/skills/document/bin/doc-convert.cjs +308 -292
  29. package/skills/document/bin/doc-fill.cjs +73264 -192
  30. package/skills/document/bin/doc-gen.cjs +2491 -312
  31. package/skills/document/bin/doc-run.cjs +162 -24
  32. package/skills/document/bin/doc-scan.cjs +13 -0
  33. package/skills/document/bin/doc-text.cjs +13 -0
  34. package/skills/document/bin/doc-validate.cjs +838 -68
  35. package/skills/document/bin/doc-xml.cjs +9 -5
  36. package/skills/document/bin/docx-annotate.cjs +95 -19
  37. package/skills/document/bin/docx-defaults.cjs +9907 -0
  38. package/skills/document/bin/fontkit.cjs +1 -0
  39. package/skills/document/bin/html2pptx.cjs +36622 -31394
  40. package/skills/document/bin/ocr-worker.cjs +1 -0
  41. package/skills/document/bin/ocr.cjs +131 -40
  42. package/skills/document/bin/pdf-form.cjs +682 -177
  43. package/skills/document/bin/pdf-images.cjs +13 -0
  44. package/skills/document/bin/pdf-ops.cjs +642 -199
  45. package/skills/document/bin/pdf-render.cjs +19 -3
  46. package/skills/document/bin/pdf-tables.cjs +13 -0
  47. package/skills/document/bin/pptx-clone.cjs +3 -3
  48. package/skills/document/bin/pptx-notes.cjs +10038 -0
  49. package/skills/document/bin/pptx-slide.cjs +3 -3
  50. package/skills/document/bin/pptx-tokenize.cjs +19 -4
  51. package/skills/document/bin/template-skin.cjs +10910 -0
  52. package/skills/document/bin/xlsx-query.cjs +192 -61
  53. package/skills/document/bin-reference.md +61 -33
  54. package/skills/document/catalog.json +33 -32
  55. package/skills/document/content-pipeline.md +179 -257
  56. package/skills/document/deck-design.md +378 -638
  57. package/skills/document/generated-visuals.md +99 -0
  58. package/skills/document/layouts/MAINTAINERS.md +33 -0
  59. package/skills/document/layouts/README.md +49 -36
  60. package/skills/document/layouts/big-stat.tpl +1 -1
  61. package/skills/document/layouts/capacity.json +1 -0
  62. package/skills/document/layouts/cards-3.tpl +1 -1
  63. package/skills/document/layouts/chart-full.tpl +1 -1
  64. package/skills/document/layouts/chart-kpi.tpl +1 -1
  65. package/skills/document/layouts/comparison.tpl +1 -1
  66. package/skills/document/layouts/data-table.tpl +1 -1
  67. package/skills/document/layouts/funnel.tpl +1 -1
  68. package/skills/document/layouts/gantt.tpl +1 -1
  69. package/skills/document/layouts/hub-flow.tpl +4 -0
  70. package/skills/document/layouts/icon-row.tpl +1 -1
  71. package/skills/document/layouts/image-grid.tpl +1 -1
  72. package/skills/document/layouts/matrix-2x2.tpl +1 -1
  73. package/skills/document/layouts/mock-qa.tpl +4 -0
  74. package/skills/document/layouts/profiles.json +2 -2
  75. package/skills/document/layouts/pyramid.tpl +1 -1
  76. package/skills/document/layouts/radar.tpl +1 -1
  77. package/skills/document/layouts/ring-progress.tpl +1 -1
  78. package/skills/document/layouts/slots.json +1 -1
  79. package/skills/document/layouts/steps-vertical.tpl +1 -1
  80. package/skills/document/layouts/steps.tpl +1 -1
  81. package/skills/document/layouts/three-kpi.tpl +1 -1
  82. package/skills/document/layouts/timeline.tpl +1 -1
  83. package/skills/document/layouts/toc-panel.tpl +2 -2
  84. package/skills/document/layouts/two-kpi.tpl +2 -2
  85. package/skills/document/layouts/versus.tpl +1 -1
  86. package/skills/document/motion/README.md +3 -2
  87. package/skills/document/office.md +3 -3
  88. package/skills/document/packs/README.md +1 -1
  89. package/skills/document/packs/board-brief/backdrop.html +2 -0
  90. package/skills/document/packs/board-brief/pack.css +2 -1
  91. package/skills/document/packs/mckinsey-photo/backdrop.html +2 -0
  92. package/skills/document/packs/mckinsey-photo/pack.css +2 -1
  93. package/skills/document/packs/press-room/backdrop.html +2 -0
  94. package/skills/document/packs/press-room/pack.css +2 -1
  95. package/skills/document/packs/prismatic-3d/backdrop.html +2 -0
  96. package/skills/document/packs/prismatic-3d/pack.css +4 -1
  97. package/skills/document/pdf.md +60 -43
  98. package/skills/document/rewrite.md +257 -309
  99. package/skills/document/scenarios.json +1307 -0
  100. package/skills/document/scenarios.schema.json +104 -0
  101. package/skills/document/styles/README.md +15 -25
  102. package/skills/document/styles/_backdrops/rimlight.html +3 -2
  103. package/skills/document/styles/_contract-defaults.css +31 -2
  104. package/skills/document/styles/_samples/_groups/biz-premium.webp +0 -0
  105. package/skills/document/styles/_samples/mckinsey.webp +0 -0
  106. package/skills/document/styles/anthropic/skin.css +6 -3
  107. package/skills/document/styles/apple/skin.css +4 -3
  108. package/skills/document/styles/bistro-warm/backdrop.html +2 -0
  109. package/skills/document/styles/bistro-warm/skin.css +4 -1
  110. package/skills/document/styles/black-gold/skin.css +6 -5
  111. package/skills/document/styles/bold-clash/backdrop.html +2 -0
  112. package/skills/document/styles/bold-clash/skin.css +2 -1
  113. package/skills/document/styles/branding/skin.css +4 -4
  114. package/skills/document/styles/campus-teal/backdrop.html +2 -0
  115. package/skills/document/styles/campus-teal/skin.css +2 -1
  116. package/skills/document/styles/cinereel/skin.css +7 -3
  117. package/skills/document/styles/clinic-care/backdrop.html +2 -0
  118. package/skills/document/styles/clinic-care/skin.css +2 -1
  119. package/skills/document/styles/cool/skin.css +6 -5
  120. package/skills/document/styles/dark-glass/backdrop.html +2 -0
  121. package/skills/document/styles/dark-glass/skin.css +2 -1
  122. package/skills/document/styles/gov-brief/backdrop.html +2 -0
  123. package/skills/document/styles/gov-brief/skin.css +2 -1
  124. package/skills/document/styles/grid-tech/backdrop.html +2 -0
  125. package/skills/document/styles/grid-tech/skin.css +2 -1
  126. package/skills/document/styles/hand-drawn/skin.css +3 -3
  127. package/skills/document/styles/ivory-gold/skin.css +7 -6
  128. package/skills/document/styles/legal-slate/backdrop.html +2 -0
  129. package/skills/document/styles/legal-slate/skin.css +2 -1
  130. package/skills/document/styles/magazine-ink/skin.css +4 -3
  131. package/skills/document/styles/mckinsey/backdrop.html +7 -5
  132. package/skills/document/styles/mckinsey/skin.css +2 -1
  133. package/skills/document/styles/memphis/backdrop.html +2 -0
  134. package/skills/document/styles/memphis/skin.css +2 -1
  135. package/skills/document/styles/mono/skin.css +6 -2
  136. package/skills/document/styles/neon-cyber/backdrop.html +2 -0
  137. package/skills/document/styles/neon-cyber/skin.css +2 -1
  138. package/skills/document/styles/olive-gold/skin.css +7 -6
  139. package/skills/document/styles/organic-earth/backdrop.html +2 -0
  140. package/skills/document/styles/organic-earth/skin.css +2 -1
  141. package/skills/document/styles/pastel-saas/backdrop.html +2 -0
  142. package/skills/document/styles/pastel-saas/skin.css +2 -1
  143. package/skills/document/styles/portfolio-noir/backdrop.html +2 -0
  144. package/skills/document/styles/portfolio-noir/skin.css +2 -1
  145. package/skills/document/styles/retro-press/backdrop.html +2 -0
  146. package/skills/document/styles/retro-press/skin.css +2 -1
  147. package/skills/document/styles/sport-arena/backdrop.html +2 -0
  148. package/skills/document/styles/sport-arena/skin.css +4 -1
  149. package/skills/document/styles/swiss-grid/skin.css +10 -5
  150. package/skills/document/styles/wedding-blush/backdrop.html +2 -0
  151. package/skills/document/styles/wedding-blush/skin.css +4 -1
  152. package/skills/document/theme-system.md +85 -77
  153. package/skills/document/themes/README.md +7 -5
  154. package/skills/document/vision.md +8 -5
  155. package/skills/document/xlsx.md +15 -25
  156. package/skills/grill-me/SKILL.md +6 -0
  157. package/skills/grill-me/agents/openai.yaml +5 -0
  158. package/skills/grilling/SKILL.md +28 -0
  159. package/skills/grilling/agents/openai.yaml +3 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taloswork/ose-shared",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Talos cross-OSE shared library — skills + MCP servers auto-loaded into every OSE (P93 2026-07-27).",
5
5
  "type": "module",
6
6
  "files": [
@@ -10,6 +10,6 @@
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
13
- "_talosPublishHash": "sha256-JzD-VeYh0UJfwZYHueL8DpxlsjlDOEJGiSdOaX70yIg",
14
- "_talosPublishedAt": "2026-09-28T08:42:12.912Z"
13
+ "_talosPublishHash": "sha256-HbLb5fXPsWxwD1td2ljod1H_UVd555EmCpblxk4GZ2g",
14
+ "_talosPublishedAt": "2026-10-10T06:45:49.079Z"
15
15
  }
@@ -1,231 +1,147 @@
1
1
  ---
2
2
  name: document
3
- description: "Use for document FILES. Reading: a PDF, .docx, .pptx or .xlsx attachment to read, summarize, translate or search when its pages must be rendered (formulas, scans, figures) or a sheet computed — others arrive as extracted text. Writing: any request to create or edit a Word, PowerPoint, Excel or PDF file, or convert one (转成/导出 PDF, .docx/.pptx → PDF). ALWAYS use its scripts — doc-gen (docs), html2pptx (decks, and a deck made here to PDF), doc-convert (an existing file to PDF); never hand-write a python/ReportLab/LibreOffice/browser pipeline. Do NOT trigger for images or plain .txt/.md/.csv."
3
+ description: "Use for document FILES. Reading: a PDF, .docx, .pptx or .xlsx attachment to read, summarize, translate or search when its pages must be rendered (formulas, scans, figures) or a sheet computed — others arrive as extracted text. Writing: any request to create or edit a Word, PowerPoint, Excel or PDF file, or convert one (转成/导出 PDF, .docx/.pptx → PDF). ALWAYS use its scripts — doc-gen (docs), html2pptx (decks), doc-convert (Office files and final decks to PDF); never hand-write a python/ReportLab/LibreOffice/browser pipeline. Do NOT trigger for images or plain .txt/.md/.csv."
4
4
  license: Proprietary. LICENSE.txt has complete terms
5
5
  ---
6
6
 
7
7
  # Document Handling
8
8
 
9
- Local-first, progressive-disclosure document processing. Prefer local text
10
- extraction (cheap, cross-vendor, avoids gateway size/timeout limits); escalate
11
- to page rendering only when the content is genuinely visual, and to native
12
- document delivery only when the user explicitly opts in (PDF only).
9
+ Local-first, progressive disclosure: read the extracted text first, render pages only
10
+ when the content is genuinely visual, and write files only through this skill's scripts.
13
11
 
14
12
  ## Route (read only what you need)
15
13
 
16
- This skill is for work the submit-time delivery does NOT do: PDF page rendering,
17
- spreadsheet computation, and document generation. **Attachments arrive as file
18
- pointers** — a `<document … delivery="file">` block gives you the on-disk path
19
- (PDF/Office point at a pre-extracted `<file>.txt` sidecar). **Read that file
20
- FIRST** (ordinary file/read tool — no script needed) before answering anything
21
- about the document's content; never guess from the filename. Then reach for a
22
- script only when:
23
-
24
- - **Spreadsheet** (.xlsx) computation — "sum/average/pivot/how many/总数/统计"
25
- → read **xlsx.md**, use `bin/xlsx-query`. **Compute, do not dump** — and it is
26
- exact (don't do the arithmetic yourself).
27
- - **Formula / figure / scanned / exact layout matters** AND you can see images
28
- → read **vision.md**; `bin/pdf-render` a page, then look.
29
- - **A deck you built here, as PDF**(PPT 要 PDF / 导出 PDF / deck as PDF)→ print
30
- its `deck.html` with the same STYLE flags you rendered the .pptx with (leave out
31
- `--editable` / `--rasterize` / `--notes-doc`, which are .pptx-only):
32
- `bin/html2pptx.cjs deck.html out.pdf --style <id> [--theme-v2 …] [--backdrop …]`.
33
- One 16:9 page per slide, vector text (selectable, searchable), links clickable.
34
- Do not route it through `doc-convert` (that re-lays out the .pptx) and never
35
- assemble slide PNGs into a PDF (image pages: no text, no links). If the result
36
- reports `pages` ≠ `slides`, a slide overflows its canvas — fix it and print again.
37
- - **Convert** a .docx/.pptx/.xlsx to PDF(转成/转换/导出 PDF / convert to PDF)→
38
- `bin/doc-convert.cjs <in.docx|pptx|xlsx> <out.pdf>`. This is FAITHFUL conversion —
39
- the source's content, structure and images with neutral print styling; do not
40
- re-theme, re-typeset or "优化排版" unless the user asks. **Never** hand-roll a
41
- textutil / LibreOffice / python / headless-browser pipeline for this. xlsx/xls/
42
- ods render ONLY through a real LibreOffice (local `soffice` or the
43
- `TALOS_OFFICE_URL` sidecar) — there is no HTML/text-only fallback for
44
- spreadsheets, so if neither is available the command errors instead of
45
- degrading.
46
- - **Create or edit** a .docx/.pptx/.xlsx/.pdf (generate from scratch or fill a
47
- template) → read **rewrite.md**, use `doc-gen` / `doc-fill`. **Always** produce
48
- document files via these scripts — never hand-write a python / ReportLab /
14
+ **Attachments arrive as file pointers** — a `<document … delivery="file">` block gives
15
+ the on-disk path (PDF/Office point at a pre-extracted `<file>.txt` sidecar). **Read that
16
+ file FIRST** (ordinary read tool, no script) before answering anything about the
17
+ document's content; never guess from the filename. Then:
18
+
19
+ - **Read a docx/pptx** → the sidecar is the content; don't re-extract (**office.md**).
20
+ - **Read a PDF** whose text is garbled/missing where the answer should be, or that needs
21
+ formulas, tables, figures or a scan read → **pdf.md** (scan → text or render; looking
22
+ at a page and the OCR fallback → **vision.md**).
23
+ - **Spreadsheet** computation ("sum/average/how many/总数/统计") → **xlsx.md**,
24
+ `bin/xlsx-query`. **Compute, do not dump** — it is exact; don't do the arithmetic yourself.
25
+ - **Create, fill or edit** a .docx/.xlsx/.pdf (or edit an existing .pptx: template fill,
26
+ slide surgery, comments/tracked changes) → **rewrite.md** — its index names the one
27
+ section your task needs. PDF forms, merge/split, stamp, encrypt → **pdf.md**. **Always**
28
+ produce document files via the scripts — never hand-write a python / ReportLab /
49
29
  LibreOffice script for document output.
50
- **A length limit** (正文 1000 字以内 / under 800 words) is kept in the spec,
51
- before generating: after a PDF, `doc-gen` prints `textChars` (spaces and URLs
52
- not counted) — over the limit, shorten the spec and generate once more. Do not
53
- extract text from the output to count it.
54
- **Any deck/presentation(路演/汇报/评审/宣讲/pitch/roadshow/介绍 PPT)**:
55
- **CLARIFY FIRST — HARD GATE (applies to EVERY deck).** Before authoring, collect
56
- three brief fields: **(1) content source** (提供材料 / 联网调研 / 自由创作);
57
- **(2) scenario** (pitch / 内审 / 销售 / 讲座 / 发布会 / 培训 / 大会 — sets tone,
58
- density, required sections); **(3) slide count.** Ask only for fields the user did
59
- not already supply, in **ONE AskUserQuestion call with at most THREE questions**, and
60
- wait for the answers. If all three are already known, do not ask them again.
61
-
62
- **STYLE PICKER — ONE RESULT PER IMAGE, SCENARIO-RANKED.** After the scenario is
63
- known, read the skill directory's **current `catalog.json` from disk immediately
64
- before building the picker**. Never reuse a catalog listing from earlier conversation
65
- context and never infer pack availability by scanning `packs/`. If the current catalog
66
- cannot be read or parsed, stop and report that exact error instead of presenting stale
67
- options.
68
-
69
- Unless the user already named an entry id/name, supplied a template file, or explicitly
70
- said **"无需展示模板,直接替我选定风格"**, send one single-question image-card picker:
71
-
72
- - Rank **entries**, not groups, against the confirmed scenario and the user's requested
73
- tone. Show at most 8 recommended entries. A scenario-matching `kind === "pack"` ranks
74
- before matching skins; include at least one matching pack whenever one exists.
75
- - Every image card maps to exactly one final entry and uses
76
- `{ label: entry.kind === "pack" ? "PACK · " + entry.name_cn :
77
- (entry 属于 renderMode === "classic-v1" 的 collection ? "经典 · " + entry.name_cn : entry.name_cn),
78
- description: entry.oneliner, imagePath: <skill目录下entry.sample的绝对路径> }`.
79
- Copy `entry.oneliner` verbatim. Never use `group.sample` in this default picker.
80
- - Append `{ label: "查看全部风格", description: "一次查看全部模板" }`, then
81
- `{ label: "使用我的模板文件", description: "复用现成 PPT 的版式/风格",
82
- filePick: "file" }` as the final option.
83
-
84
- **"按场景推荐/你推荐" means rank the cards and still ask.** It does NOT waive the
85
- picker. Only the explicit no-picker wording above authorizes automatic selection.
86
- Do not waive this gate because the deck is small or quick.
87
-
88
- If the user chooses **查看全部风格**, immediately show **every current
89
- `catalog.entries` item in one single-question image-card picker** using the same label,
90
- description, and imagePath rule above. Preserve catalog order, keep `PACK ·` visible,
91
- and append the custom-template file card. Do not ask for a group, paginate, or return to
92
- any category/second-level picker; the browse-all action must expose final selectable
93
- templates directly.
94
-
95
- Samples are pre-rendered WebP files shipped with the skill: pass their absolute paths
96
- directly and do not render anything during the question. The selected `entry.id` is the
97
- stable `style` id. Resolve the selected entry against `catalog.collections` before writing
98
- the spec. Entries in a `renderMode:"classic-v1"` collection are frozen: omit
99
- `themeVersion`, `mediaStyle`, `decorRhythm`, per-slide scene controls, and every layout in
100
- `layouts/profiles.json.themeV2Layouts`; render them with `--style <id>` and never add
101
- `--theme-v2`. All other newly authored decks use Theme V2 (`"themeVersion":2`), which
102
- composes that family with its component profile, media treatment and art direction. Read
103
- **theme-system.md** before authoring. The CLIs reject Theme V2 for frozen classic entries.
104
-
105
- **Keep both calls LEAN.** The content/scenario/count questions use bare label strings,
106
- no per-option descriptions; every question stem is one short sentence. Skip chat
107
- preambles or keep one short line. Every question has the panel's implicit custom-text
108
- escape. If the user responds with a correction or question, handle it and re-ask.
109
-
110
- **Automatic choice, only when explicitly authorized:** rank by a remembered preference,
111
- an exact user-named style, scenario match, a matching pack before a matching skin, then
112
- `entry.mode` when the user asked for clean/formal/light/dark. Never hardcode a family id:
113
- `catalog.json` is the only roster; `styles/README.md` is explanatory only. Never render
114
- unstyled. After the user confirms, save the preference to memory.
115
-
116
- **Custom style (user picked 其他/自定义 in the style picker)** — clarify which route, **prefer B
117
- (derive a bespoke look)**:
118
- - **B — derive a bespoke look (PREFERRED).** From an **existing deck**: `pptx-tokenize`
119
- it to reuse its EXACT layouts/master/brand as a fillable template (rewrite.md B2),
120
- OR `pptx-theme` to extract just its palette → paint OUR `layouts/`. From a
121
- **reference image / brand color**: build a new `styles/<name>/skin.css` (sample the
122
- palette → fill the class contract; see deck-design "build a skin from a reference
123
- image"). *(A deck given here is for its STYLE — distinct from a deck given as
124
- content, which is text-only; see content-pipeline's content-source choice.)*
125
- - **A — map to the nearest of catalog 里的族** (they only described a vibe): pick the
126
- closest, render its sample, confirm.
127
- - **C — tweak an existing skin** ("刚才那个族但换绿色"): clone it, swap accent/palette or
128
- flip light↔dark.
129
- Then render a cover+content sample of the result and confirm (same image-card step as
130
- a normal pick) before authoring; save the resulting preference to memory.
131
-
132
- **Then build it — the method lives in deck-design.md.** For a substantive deck read
133
- **content-pipeline.md** first (brief → research → narrative → one outline gate), then
134
- **deck-design.md** (workflow and delivery sign-off) and **`layouts/README.md`** (the
135
- layout index and fill rules). In short: pick layouts from `layouts/profiles.json` by
136
- slide intent; fill them with `deck-build` (required for any layout with a `{{#rows}}`
137
- block — it computes the geometry; put the confirmed scenario in its spec as
138
- `"scenario"` — read decks such as 内审/报告/培训 then get no animation); render with `bin/html2pptx.cjs deck.html out.pptx
139
- --style <id>` (+ `--theme-v2` for modern entries, never for `classic-v1`) — DEFAULT
140
- hybrid: baked visuals, native editable text. `doc-gen` makes no decks and the doc-run
141
- PptxGenJS deck path is OFF. html2pptx needs a browser (the app's Chromium or bundled
142
- Playwright); without one, say so and stop — never fall back to a lesser deck.
143
- - **Generators check their own output.** `doc-gen` and `html2pptx` report
144
- validity in the step that wrote the file — `valid: false` exits 1, fix before
145
- delivering; never re-run `doc-validate` on their output. `doc-gen pdf` prints
146
- `{valid, pages, textChars, cjkChars, previews}` (a ≈72dpi PNG per page — read
147
- those, do not re-render or count characters yourself); `doc-gen docx` prints
148
- `{valid, textChars, cjkChars}`, `xlsx` `{valid}`; `html2pptx` adds `valid` and
149
- `qa` (deck-qa's findings) to its result. **After any other edit** (doc-fill /
150
- docx-annotate / pptx-clone / pptx-slide / doc-xml pack / hand-written scripts)
151
- run `bin/doc-validate.cjs <file>` yourself — exit 1 means fix it. Valid is not
152
- good-looking: **render-and-look** before delivery (see "Verify generated
153
- output" below; decks sign off with `deck-qa --final`).
154
- - **Raw XML edit** (when no targeted tool fits): `doc-xml unpack` → edit →
155
- `doc-xml pack` → `doc-validate` (see rewrite.md "Raw XML editing").
156
- - **PDF** whose inlined text is garbled/missing where the answer should be →
157
- **pdf.md**: `bin/doc-text <file.pdf>` to re-extract, or render + look.
158
- - Just reading a docx/pptx/text → read the pointed-at file/sidecar directly;
159
- don't re-extract with scripts (see **office.md**).
160
-
161
- ## Fidelity decision (default text, escalate on evidence)
162
-
163
- 1. `bin/doc-scan <file>` → cheap per-page signals (`textChars`, `imageCoverage`,
164
- `mathHint`, `tableHint`, `scanned`). Costs nothing to the context beyond the
165
- small JSON.
166
- 2. Read intent: summarize/translate → text; formulas/tables/figures/layout →
167
- visual; unsure → start with text.
168
- 3. Per page: `scanned` OR high `imageCoverage` OR (visual intent AND
169
- math/table hint) → render + look (vision.md); else `doc-text`.
170
- 4. **Self-correct (important):** if the extracted text is garbled or missing
171
- where the answer should be (symbols shredded for a formula, a table collapsed
172
- into one line, a page with almost no characters) → render THAT page and look.
173
- 5. **Vision unavailable** (text-only model): text/OCR only, and state the
174
- limitation plainly — never silently return empty for a scanned/visual page.
175
-
176
- ## Verify generated output (render-and-look — MANDATORY for delivery)
177
-
178
- Structural validation (`doc-validate`) proves the file is well-formed; it does
179
- NOT prove it *looks* right. Before delivering ANY document you generated or
180
- converted (doc-gen / doc-fill / doc-convert / doc-run / raw-XML / template fill),
181
- do a visual self-check — the same "assume there are problems" ethos as the
182
- Fidelity-decision self-correct, but pointed at your OWN output:
183
-
184
- 1. **Render the final artifact to images** and LOOK at every page (not "glance"):
185
- PDF → `bin/pdf-render.cjs <file.pdf> all`; docx/pptx → `bin/doc-convert.cjs
186
- <file> /tmp/preview.pdf` then `pdf-render` the PDF. Decks follow the fuller
187
- loop in **deck-design.md** ("Verify before delivering") — do that instead.
188
- 2. **Hunt for render-level bugs** structural checks can't see: text overflowing
189
- its box / cut off at the page edge; tables broken or collapsed; bad page
190
- breaks (heading orphaned from its body, a row split mid-cell); **tofu / □ /
191
- blank CJK** (a missing-font symptom, not a content bug); colliding
192
- headers/footers; leftover `{{tokens}}` / "lorem" / "undefined".
193
- 3. **Fix → re-render the affected pages.** One fix often creates another; repeat
194
- until a clean pass. Fix what is broken — clipped, overlapping, unreadable, tofu —
195
- not how full a page looks: unless the user asked for a page count, never
30
+ - **Convert** a .docx/.pptx/.xlsx to PDF(转成/导出 PDF)→ `bin/doc-convert.cjs <in> <out.pdf>`.
31
+ Preserve the source; do not re-theme or "优化排版" unless asked, and never hand-roll a textutil /
32
+ LibreOffice / headless-browser pipeline. PPTX and spreadsheets render ONLY through a real
33
+ LibreOffice (local `soffice` or `TALOS_OFFICE_URL`); without one the command errors.
34
+ DOCX may fall back to HTML reconstruction; report that its layout can change.
35
+ - **A deck you built here, as PDF**(PPT 要 PDF)→ `bin/doc-convert.cjs deck.pptx out.pdf`.
36
+ The final PPTX is the source of truth for content, fonts and layout. Reuse its final
37
+ QA Office PDF only if the PPTX has not changed. Never print `deck.html` or assemble
38
+ preview PNGs as the delivered PDF. No Office engine → report that PDF export is unavailable.
39
+ - **Any deck/presentation(路演/汇报/评审/宣讲/pitch/roadshow/介绍 PPT)** → the deck route below.
40
+
41
+ ## Decks
42
+
43
+ **CLARIFY FIRST — HARD GATE (applies to EVERY deck).** Before authoring, collect three
44
+ brief fields: **(1) content source** (提供材料 / 联网调研 / 自由创作); **(2) scenario**
45
+ (pitch / 内审 / 销售 / 讲座 / 发布会 / 培训 / 大会 — sets tone, density, required sections);
46
+ **(3) slide count.** Ask only for fields the user did not already supply, in **ONE
47
+ AskUserQuestion call with at most THREE questions**, and wait for the answers. If all
48
+ three are already known, do not ask them again.
49
+
50
+ **STYLE PICKER — ONE RESULT PER IMAGE, SCENARIO-RANKED.** After the scenario is
51
+ known, run `node <skill>/bin/deck-styles.cjs --scenario "<the confirmed scenario>"`: it
52
+ reads the current `catalog.json` from disk immediately and ranks the entries (a
53
+ scenario-matching pack first, at least six cards). Never rank from memory, reuse a listing
54
+ from earlier context or scan `packs/`. If it exits non-zero, stop and report that exact
55
+ error instead of presenting stale options.
56
+
57
+ Unless the user already named an entry id/name, supplied a template file, or explicitly
58
+ said **"无需展示模板,直接替我选定风格"**, send one single-question image-card picker whose
59
+ `options` are deck-styles' `options` **as printed** — never rewrite, reorder or add a card.
60
+
61
+ **"按场景推荐/你推荐" means rank the cards and still ask.** It does NOT waive the
62
+ picker. Only the explicit no-picker wording above authorizes automatic selection.
63
+ Do not waive this gate because the deck is small or quick.
64
+
65
+ **查看全部风格** opens the full gallery in the app itself — you receive the final pick, not
66
+ the click. Only if 查看全部风格 comes back as the answer, show **every current
67
+ `catalog.entries` item in one single-question image-card picker** in catalog order:
68
+ `{ label: "PACK · " + entry.name_cn` for a pack, `"经典 · " + entry.name_cn` in a
69
+ `classic-v1` collection, else `entry.name_cn`; `description: entry.oneliner, imagePath:
70
+ "document:" + entry.sample }`, then the template card. Do not ask for a group, paginate, or return to
71
+ any category/second-level picker.
72
+
73
+ The selected `entry.id` is the stable
74
+ `style` id. An entry in a `renderMode:"classic-v1"` collection of `catalog.collections`
75
+ renders V1 (no `themeVersion`, never `--theme-v2`); every other new deck uses Theme V2 —
76
+ read **theme-system.md** before authoring.
77
+
78
+ **Keep both calls LEAN:** bare label strings for the content/scenario/count questions,
79
+ one short sentence per stem, no chat preamble beyond one line. If the user answers with
80
+ a correction or question, handle it and re-ask.
81
+
82
+ **Automatic choice, only when explicitly authorized:** rank by a remembered preference,
83
+ an exact user-named style, scenario match, a matching pack before a matching skin, then
84
+ `entry.mode` when the user asked for clean/formal/light/dark. Never hardcode a family id:
85
+ `catalog.json` is the only roster. Never render unstyled. After the user confirms, save
86
+ the preference to memory.
87
+
88
+ **Custom style** (其他/自定义, 使用我的模板文件, "我之前那个风格"): routes and naming are in
89
+ **deck-design.md "Custom skins"** — prefer deriving a bespoke skin, saved as a user style
90
+ under `$TALOS_DOC_STYLES_DIR/styles/<name>/`; a 使用我的模板文件 deck is learned as a style
91
+ (`template-skin`); refilling its original pages (opt-in) → rewrite.md "Reuse an
92
+ uploaded deck". Never write inside the skill directory.
93
+
94
+ **Then build it.** Read **content-pipeline.md** for a substantive deck, then
95
+ **deck-design.md** and **`layouts/README.md`**. Assess whether generated visuals help;
96
+ if so, read **generated-visuals.md**. In short:
97
+ **plan before you fill** — `bin/deck-plan.cjs plan.json spec.json` picks layouts by
98
+ MEASURED capacity and drafts the spec, `deck-build` fills it, charts are drawn from data
99
+ (never hand-write chart SVG), and `bin/html2pptx.cjs deck.html out.pptx --style <id>`
100
+ (+ `--theme-v2` unless the entry is classic-v1) renders it. `doc-gen` and doc-run
101
+ PptxGenJS make no decks; html2pptx needs a browser — without one, say so and stop, never
102
+ fall back to a lesser deck.
103
+
104
+ ## After writing a file (MANDATORY before delivery)
105
+
106
+ 1. **Valid.** `doc-gen` and `html2pptx` check their own output in the step that wrote
107
+ it — `valid: false` exits 1, fix before delivering;
108
+ never re-run `doc-validate` on their output. `doc-gen pdf` prints `{valid, pages, textChars, cjkChars, previews}`
109
+ (≈72dpi PNGs — read those, do not re-render). Counts describe input, not visible glyphs.
110
+ `doc-gen docx` prints `{valid, textChars, cjkChars}`, `xlsx` `{valid}`. After any
111
+ other write (doc-fill, docx-annotate, pptx-*, pdf-form / pdf-ops, doc-xml pack, a
112
+ doc-run script) run `bin/doc-validate.cjs <file>` yourself — exit 1 means fix it.
113
+ 2. **Looks right — render and LOOK at every page** (valid is not good-looking): a
114
+ doc-gen PDF → its `previews`; another PDF → `bin/pdf-render.cjs <file.pdf> all 1`;
115
+ docx/pptx/xlsx → `bin/doc-convert.cjs <file> preview.pdf` (working folder), then
116
+ `pdf-render` it. Decks follow deck-design.md "Verify before delivering" instead. Hunt
117
+ for text overflowing or cut off at the page edge, collapsed tables, a row split
118
+ mid-cell, **tofu / □ / blank CJK** (a missing font, not a content bug), colliding
119
+ headers/footers, leftover `{{tokens}}` / "lorem" / "undefined".
120
+ 3. **Fix → re-render the affected pages** and look at only those — never re-read a
121
+ page you already looked at. Fix what is broken — clipped, overlapping, unreadable,
122
+ tofu — not how full a page looks: unless the user asked for a page count, never
196
123
  resize fonts, line height or margins to fill a short last page or squeeze onto
197
- fewer pages. Page breaks already keep a heading with its text and never strand
198
- a single line, so a heading near a page edge is not something to fix. Layout and styling taste gets at most
199
- TWO fix rounds: after the second, deliver and name what is still imperfect instead
200
- of regenerating again. Scale rigor to the artifact: a one-page memo = one look; a
201
- multi-page report/deck = every page, ideally a sub-agent for fresh eyes.
202
- 4. **Vision unavailable**: say so and rely on `doc-validate` + a text re-extract
203
- (`doc-text`) as a weaker proxy — never claim the layout is verified.
204
-
205
- ## Scripts (run via bash; output returns to context, the script itself does not)
206
-
207
- One line each — **read a bin's entry in `bin-reference.md` before its first use**
208
- (flags, output shape, exit codes, gotchas). Do not read, grep or open `bin/*.cjs`
209
- themselves — they are bundled builds; the answer is in `bin-reference.md`.
210
-
211
- - Read: `bin/doc-scan.cjs <file.pdf>` page signals · `bin/doc-text.cjs <file.pdf>` text layer ·
212
- `bin/pdf-render.cjs <file.pdf> <N|N-M|3,7-8|all> [scale]` pages → PNG (scale `1` ≈72dpi for layout) ·
213
- `bin/pdf-images.cjs` embedded images · `bin/pdf-tables.cjs` text-layer tables ·
214
- `bin/ocr.cjs <image> [lang]` · `bin/xlsx-query.cjs <file> --summary|--agg|--sample` exact spreadsheet compute.
215
- - Generate: `bin/doc-gen.cjs <docx|xlsx|pdf> <out> <spec.json>` (self-checks) ·
216
- `bin/doc-run.cjs <script.js>` custom script with the bundled libraries ·
217
- `bin/doc-convert.cjs <in.docx|pptx|xlsx> <out.pdf>` faithful → PDF.
218
- - Decks: `bin/deck-build.cjs <spec.json> <deck.html>` catalog slides from a compact spec ·
219
- `bin/html2pptx.cjs <deck.html> <out.pptx> --style <id> …` THE deck path (self-checks; `--preview-dir` for fast previews) ·
220
- `bin/deck-qa.cjs <deck.pptx> [--json | --final]` lint, and the one-call delivery sign-off.
221
- - Edit: `bin/doc-fill.cjs` fill `{{tokens}}` · `bin/doc-xml.cjs unpack|pack|replace|merge-runs` raw XML ·
222
- `bin/pptx-slide.cjs add|dup|remove|reorder` · `bin/pptx-clone.cjs` clone a template slide per item ·
223
- `bin/pptx-tokenize.cjs` uploaded deck → template · `bin/pptx-set-image.cjs` · `bin/pptx-theme.cjs` palette from a deck ·
224
- `bin/pptx-embed-fonts.cjs` · `bin/docx-annotate.cjs comment|suggest|accept|redline-check` ·
225
- `bin/xlsx-recalc.cjs` recompute formulas.
226
- - Validate: `bin/doc-validate.cjs <file.docx|pptx|xlsx|pdf> [--strict]` — for anything a generator did not already check.
227
- - PDF: `bin/pdf-form.cjs list|fill|overlay` · `bin/pdf-ops.cjs merge|split|rotate|watermark|stamp|encrypt|decrypt`.
228
-
229
- All scripts are Node and print a machine-readable result plus a human note. On a
230
- missing dependency or unreadable file they exit non-zero with a clear message —
231
- report that to the user, do not fabricate content.
124
+ fewer pages. Page breaks already keep a heading with its text and never strand a
125
+ single line, so a heading near a page edge is not something to fix. Layout taste gets at most
126
+ TWO fix rounds; then deliver and name what is still imperfect. A one-page memo = one
127
+ look; a long report = every page.
128
+ 4. **Vision unavailable**: say so, rely on `doc-validate` + a `doc-text` re-extract as a
129
+ weaker proxy, and never claim the layout is verified.
130
+
131
+ ## Scripts
132
+
133
+ Run them with bash; **read a bin's entry in `bin-reference.md` before its first use** —
134
+ its index at the top points at the one section your task needs (flags, output, exit
135
+ codes). Never read or grep `bin/*.cjs` themselves: they are bundled builds.
136
+
137
+ - Read: `bin/doc-scan.cjs` · `bin/doc-text.cjs` · `bin/pdf-render.cjs` · `bin/pdf-images.cjs` ·
138
+ `bin/pdf-tables.cjs` · `bin/ocr.cjs` · `bin/xlsx-query.cjs`
139
+ - Generate: `bin/doc-gen.cjs` · `bin/doc-run.cjs` · `bin/xlsx-recalc.cjs`
140
+ - Fill / edit: `bin/doc-fill.cjs` · `bin/doc-xml.cjs` · `bin/docx-annotate.cjs` · `bin/docx-defaults.cjs` · `bin/pptx-clone.cjs` ·
141
+ `bin/pptx-slide.cjs` · `bin/pptx-tokenize.cjs` · `bin/pptx-set-image.cjs` · `bin/pptx-notes.cjs` · `bin/pptx-theme.cjs` ·
142
+ `bin/pptx-embed-fonts.cjs` · `bin/pdf-form.cjs` · `bin/pdf-ops.cjs`
143
+ - Decks: `bin/deck-scenario.cjs` · `bin/deck-styles.cjs` · `bin/deck-plan.cjs` · `bin/deck-build.cjs` · `bin/deck-chart.cjs` · `bin/html2pptx.cjs` · `bin/deck-qa.cjs` · `bin/template-skin.cjs`
144
+ - Validate / convert: `bin/doc-validate.cjs <file.docx|pptx|xlsx|pdf> [--strict]` · `bin/doc-convert.cjs`
145
+
146
+ Every script prints a machine-readable result. On a missing dependency or unreadable
147
+ file it exits non-zero with a clear message — report that, never fabricate content.
@@ -1,7 +1,11 @@
1
1
  /* Theme V2 art-direction canvas. The renderer injects this decoration-only layer
2
- into .slide-backdrop; V1 never receives the markup or these rules. */
3
- .theme-art-layer,.theme-art-layer>*{position:absolute;pointer-events:none}
2
+ into .slide-backdrop; V1 never receives the markup or these rules.
3
+ Markup: .theme-art-layer > .art-slot.art-slot-{a,b,c,pattern} > .art-{a,b,c,pattern}.
4
+ Each slot is a full-bleed, untransformed box, so a canvas-space mask on it stays
5
+ put while the shape inside it is rotated, scaled or moved. */
6
+ .theme-art-layer,.theme-art-layer *{position:absolute;pointer-events:none}
4
7
  .theme-art-layer{inset:0;overflow:hidden}
8
+ .theme-art-layer .art-slot{inset:0;display:block}
5
9
  .theme-art-layer .art-shape{display:block}
6
10
 
7
11
  /* Scene controls composition; density controls intensity. These selectors only
@@ -21,3 +25,24 @@
21
25
  [data-scene-variant="b"] .theme-art-layer .art-b{opacity:.82}
22
26
  [data-scene-variant="c"] .theme-art-layer .art-a{opacity:.18}
23
27
  [data-scene-variant="c"] .theme-art-layer .art-c{opacity:.86}
28
+
29
+ /* Content safe zone. Every motif is composed for the open hero/cover canvas; on a
30
+ content layout the type, cards and charts fill x≈94–1196 · y≈128–655, so a corner
31
+ block at hero size lands on them. Each art direction therefore restates its hard
32
+ shapes for content layouts — shrunk back toward the canvas corner/edge they lean on
33
+ (`scale`/`translate` compose with a motif's own `transform`), never clipped.
34
+ The content selector is the same in every art-direction file (and in gen-skin's
35
+ signature rules); tests/unit/deck-decor-overlap.test.ts holds them to it:
36
+
37
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"])
38
+
39
+ Slides without data-layout (hand-written HTML) keep the hero composition.
40
+
41
+ Safety net: a slot listed by its art direction under the same selector gets
42
+ --decor-safe-mask, which clears the content box (x 94–1196 · y 128–654; matrix axis labels reach x≈1195) with a short feather outside it. Where
43
+ the retreat already keeps a shape out of the box the mask changes no pixel; it only
44
+ bites where a shape still reaches in. */
45
+ .theme-art-layer,.sig-layer{
46
+ --decor-safe-mask:linear-gradient(90deg,black 80px,transparent 94px,transparent calc(100% - 84px),black calc(100% - 74px)),
47
+ linear-gradient(180deg,black 112px,transparent 128px,transparent calc(100% - 66px),black calc(100% - 58px));
48
+ }
@@ -3,4 +3,6 @@
3
3
  .theme-art-layer .art-b{left:18%;top:-230px;width:260px;height:1120px;background:linear-gradient(180deg,color-mix(in srgb,var(--c3) 36%,transparent),transparent 78%);transform:rotate(-28deg);filter:blur(18px);opacity:.52}
4
4
  .theme-art-layer .art-c{right:84px;top:62px;width:210px;height:210px;border:1px solid var(--c1);border-radius:50%;box-shadow:0 0 0 28px color-mix(in srgb,var(--c1) 8%,transparent),0 0 70px color-mix(in srgb,var(--c2) 30%,transparent);opacity:.62}
5
5
  .theme-art-layer .art-pattern{inset:0;background:linear-gradient(180deg,transparent 64%,color-mix(in srgb,var(--title) 7%,transparent));opacity:.8}
6
-
6
+ /* Content layouts — the floating ring shrinks into the top-right corner; the lights and beams stay. */
7
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-c{transform-origin:calc(100% + 84px) -62px;scale:.36}
8
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-c){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
@@ -5,4 +5,8 @@
5
5
  .theme-art-layer .art-pattern{right:54px;bottom:44px;width:170px;height:120px;background:conic-gradient(from 90deg,color-mix(in srgb,var(--c1) 32%,transparent) 25%,transparent 0 50%,color-mix(in srgb,var(--c2) 28%,transparent) 0 75%,transparent 0);background-size:24px 24px;transform:rotate(3deg);opacity:.68}
6
6
  .component-grid>.component-card:nth-child(odd),.component-grid>.team-card:nth-child(odd){transform:rotate(-.45deg)}
7
7
  .component-grid>.component-card:nth-child(even),.component-grid>.team-card:nth-child(even){transform:rotate(.45deg)}
8
-
8
+ /* Content layouts — the paper scraps and the checker swatch shrink into their corners; the tape strip already sits in the top margin. */
9
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-a{transform-origin:calc(100% - 40px) 52px;scale:.52}
10
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{transform-origin:64px calc(100% - 52px);scale:.4}
11
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-pattern{transform-origin:calc(100% + 54px) calc(100% + 44px);scale:.45}
12
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-a,.art-slot-b,.art-slot-pattern){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
@@ -5,4 +5,8 @@
5
5
  .theme-art-layer .art-pattern{right:44px;bottom:34px;width:220px;height:164px;border:1px solid var(--c1);background:repeating-linear-gradient(-45deg,transparent 0 11px,color-mix(in srgb,var(--c1) 14%,transparent) 11px 13px);opacity:.58}
6
6
  [data-layout="cover"] .theme-art-layer .art-a,[data-layout="section"] .theme-art-layer .art-a{width:40%;background:var(--c1);opacity:.9}
7
7
  .component-grid>.component-card:nth-child(even),.component-grid>.proof-card:nth-child(even){background:color-mix(in srgb,var(--c2) 9%,var(--cmp-surface))}
8
-
8
+ /* Content layouts — the colour column narrows to the right margin (its gradient cap follows); the hatched plate shrinks into the bottom-right corner. */
9
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-a{width:74px}
10
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{width:74px}
11
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-pattern{transform-origin:calc(100% + 44px) calc(100% + 34px);scale:.4}
12
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-a,.art-slot-b,.art-slot-pattern){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
@@ -7,3 +7,9 @@
7
7
  .component-grid>.component-card:nth-child(4n+1),.component-grid>.feature-card:nth-child(4n+1){border-top:7px solid var(--c1)}
8
8
  .component-grid>.component-card:nth-child(4n+2),.component-grid>.feature-card:nth-child(4n+2){border-top:7px solid var(--c2)}
9
9
  .component-grid>.component-card:nth-child(4n+3),.component-grid>.feature-card:nth-child(4n+3){border-top:7px solid var(--c3)}
10
+ /* Content layouts — the colour fields and the square ring shrink into the corners they are cropped by. */
11
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-a{transform-origin:calc(100% - 80px) calc(100% - 110px);scale:.28}
12
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{transform-origin:70px calc(100% - 92px);scale:.45}
13
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-c{transform-origin:calc(100% + 260px) calc(100% + 44px);scale:.22}
14
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-a,.art-slot-b,.art-slot-c){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
15
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"])[data-layout="pitch-problem"] .theme-art-layer .art-a{transform-origin:calc(100% - 80px) 90px}
@@ -3,4 +3,8 @@
3
3
  .theme-art-layer .art-b{right:-110px;top:90px;width:380px;height:520px;border-radius:52% 0 0 52%;background:linear-gradient(150deg,color-mix(in srgb,var(--c2) 78%,transparent),color-mix(in srgb,var(--c4) 58%,transparent));opacity:.18;transform:rotate(8deg)}
4
4
  .theme-art-layer .art-c{left:58%;top:-160px;width:320px;height:320px;border:1px solid var(--c1);border-radius:50%;box-shadow:0 0 0 38px color-mix(in srgb,var(--c1) 8%,transparent),0 0 0 76px color-mix(in srgb,var(--c2) 6%,transparent);opacity:.45}
5
5
  .theme-art-layer .art-pattern{inset:0;background:linear-gradient(115deg,transparent 48%,color-mix(in srgb,var(--c1) 12%,transparent) 49%,transparent 51%);opacity:.6}
6
-
6
+ /* Content layouts — the side blob retreats to the right edge; the rings shrink onto their centre on the top edge
7
+ (outer shadow ring ends at y≈106, above pitch eyebrows/headlines at x 600–1180 · y≥123); the mesh and the light stay. */
8
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{transform-origin:calc(100% - 110px) 50%;scale:.28}
9
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-c{transform-origin:50% 50%;scale:.45}
10
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-b,.art-slot-c){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
@@ -6,3 +6,8 @@
6
6
  .component-grid>.component-card:nth-child(3n+1),.component-grid>.feature-card:nth-child(3n+1){background:color-mix(in srgb,var(--c1) 9%,var(--cmp-surface))}
7
7
  .component-grid>.component-card:nth-child(3n+2),.component-grid>.feature-card:nth-child(3n+2){background:color-mix(in srgb,var(--c2) 9%,var(--cmp-surface))}
8
8
  .component-grid>.component-card:nth-child(3n),.component-grid>.feature-card:nth-child(3n){background:color-mix(in srgb,var(--c3) 9%,var(--cmp-surface))}
9
+ /* Content layouts — the blobs and the loop shrink into their corners. */
10
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-a{transform-origin:calc(100% - 95px) 76px;scale:.55}
11
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{transform-origin:90px calc(100% - 90px);scale:.44}
12
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-c{transform-origin:calc(100% + 210px) calc(100% + 58px);scale:.3}
13
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-a,.art-slot-b,.art-slot-c){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
@@ -3,4 +3,7 @@
3
3
  .theme-art-layer .art-b{right:-150px;top:-150px;width:420px;height:420px;border:1px solid var(--c2);border-radius:50%;box-shadow:0 0 0 34px color-mix(in srgb,var(--c2) 7%,transparent),0 0 0 68px color-mix(in srgb,var(--c3) 5%,transparent);opacity:.46}
4
4
  .theme-art-layer .art-c{left:-120px;bottom:-120px;width:320px;height:320px;background:radial-gradient(circle,var(--c1) 0 2px,transparent 3px),conic-gradient(from 0deg,transparent 0 8deg,color-mix(in srgb,var(--c1) 18%,transparent) 8deg 10deg,transparent 10deg 20deg);border-radius:50%;opacity:.4}
5
5
  .theme-art-layer .art-pattern{right:50px;bottom:50px;width:180px;height:1px;background:linear-gradient(90deg,transparent,var(--c1),transparent);box-shadow:0 -8px 0 color-mix(in srgb,var(--c1) 22%,transparent),0 8px 0 color-mix(in srgb,var(--c1) 22%,transparent)}
6
-
6
+ /* Content layouts — the corner rings and the ray ornament shrink into their corners; the frame stays. */
7
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{transform-origin:calc(100% - 150px) 150px;scale:.55}
8
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-c{transform-origin:120px calc(100% - 120px);scale:.55}
9
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-b,.art-slot-c){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
@@ -7,3 +7,9 @@
7
7
  .component-grid>.component-card:nth-child(4n+2),.component-grid>.price-card:nth-child(4n+2){background:var(--c2)}
8
8
  .component-grid>.component-card:nth-child(4n+3),.component-grid>.price-card:nth-child(4n+3){background:var(--c3)}
9
9
  .component-grid>.component-card:nth-child(4n+4),.component-grid>.price-card:nth-child(4n+4){background:var(--c4)}
10
+ /* Content layouts — the top slab already lives above the title; the floor slab, the shadowed card and the stripe swatch shrink into their corners.
11
+ The swatch stops above y≈56: pitch layouts put their eyebrow at x 80 · y 64. */
12
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{transform-origin:80px calc(100% - 78px);scale:.38}
13
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-c{transform-origin:calc(100% + 36px) calc(100% + 48px);scale:.34}
14
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-pattern{transform-origin:0 0;scale:.36}
15
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-b,.art-slot-c,.art-slot-pattern){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}
@@ -4,3 +4,7 @@
4
4
  .theme-art-layer .art-c{right:76px;top:64px;width:122px;height:122px;border:1px solid var(--c1);box-shadow:26px 26px 0 color-mix(in srgb,var(--c2) 16%,transparent);opacity:.58}
5
5
  .theme-art-layer .art-pattern{left:36px;bottom:32px;width:300px;height:26px;background:repeating-linear-gradient(90deg,var(--c1) 0 2px,transparent 2px 18px);opacity:.32}
6
6
  .component-grid>.component-card,.component-grid>.metric-card{background:color-mix(in srgb,var(--slide-bg) 82%,transparent);backdrop-filter:blur(8px)}
7
+ /* Content layouts — the modular zone and the node square shrink into their corners; grid and tick rail stay. */
8
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-b{transform-origin:100% 100%;scale:.2}
9
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer .art-c{transform-origin:calc(100% + 76px) -64px;scale:.5}
10
+ .slide[data-layout]:not([data-layout^="cover"],[data-layout^="section"],[data-layout^="title"],[data-layout^="ending"],[data-layout="hero"],[data-layout="transition"]) .theme-art-layer :is(.art-slot-b,.art-slot-c){-webkit-mask-image:var(--decor-safe-mask);mask-image:var(--decor-safe-mask)}